我有代码:解决冲突 - 尝试合并GMEM访问,使用SMEM,但银行冲突
struct __declspec(align(32)) Circle
{
float x, y;
float prevX, prevY;
float speedX, speedY;
float mass;
float radius;
void init(const int _x, const int _y, const float _speedX = 0.0f, const float _speedY = 0.0f,
const float _radius = CIRCLE_RADIUS_DEFAULT,
const float _mass = CIRCLE_MASS_DEFAULT);
};
,第二个:
/*smem[threadIdx.x] = *(((float*)cOut) + threadIdx.x);
smem[threadIdx.x + blockDim.x] = *(((float*)cOut) + threadIdx.x + blockDim.x);
smem[threadIdx.x + blockDim.x * 2] = *(((float*)cOut) + threadIdx.x + blockDim.x * 2);
smem[threadIdx.x + blockDim.x * 3] = *(((float*)cOut) + threadIdx.x + blockDim.x * 3);
smem[threadIdx.x + blockDim.x * 4] = *(((float*)cOut) + threadIdx.x + blockDim.x * 4);
smem[threadIdx.x + blockDim.x * 5] = *(((float*)cOut) + threadIdx.x + blockDim.x * 5);
smem[threadIdx.x + blockDim.x * 6] = *(((float*)cOut) + threadIdx.x + blockDim.x * 6);
smem[threadIdx.x + blockDim.x * 7] = *(((float*)cOut) + threadIdx.x + blockDim.x * 7);*/
__syncthreads();
/*float x, y;
float prevX, prevY;
float speedX, speedY;
float mass;
float radius;*/
/*c.x = smem[threadIdx.x];
c.y = smem[threadIdx.x + blockDim.x]; //there must be [threadId.x * 8 + 0]
c.prevX = smem[threadIdx.x + blockDim.x * 2]; //[threadId.x * 8 + 1] and e.t.c.
c.prevY = smem[threadIdx.x + blockDim.x * 3];
c.speedX = smem[threadIdx.x + blockDim.x * 4];
c.speedY = smem[threadIdx.x + blockDim.x * 5];
c.mass = smem[threadIdx.x + blockDim.x * 6];
c.radius = smem[threadIdx.x + blockDim.x * 7];*/
c = cOut[j];
//c = *((Circle*)(smem + threadIdx * SMEM));
有2 GMEM(我的意思是全球内存)访问: 1)读取圆并检测它与它的碰撞 2)在改变它的速度和位置后写入圆 另外我还有circleConst-mass的Circle,它是由cudaMallocToSybol()分配的。它用于检查从gmem读取的主圆C(它在寄存器中)的圆的交集。
当我想到,我使用const,记忆好,它获得了我所有的性能:')(我错了)
当我读到凝聚的访问GMEM(有合并获得其他类型的?记忆?我没有找到任何有关它的信息),我想为我尝试它。如你所见,Circle-structure有8个变量,类型为float = 32位。我尝试过(在代码中评论)做这件事,但是,首先,我得到了一个错误的答案(因为我必须从不正确的地方读到,下面会提到),其次,我的表现会降低33%。为什么?我认为,这不取决于错误的领域关系。
而第二个问题,正如我在代码的评论中写到从smem到C的附近的代码所写的,我必须读另一种方式,但如果我这样做,会有很多银行冲突,所以我会获得更少的性能...... 那么,我怎样才能加载圈没有银行冲突coalasced,然后,把它写回来?
p.s大小超过4 * float的结构是否位于寄存器中?
更新: 最新的版本是:
#define CF (9) //9 because the primary struct has 8 floats, so 1 is for wasting
i = blockIdx.x * blockDim.x;
smem[threadIdx.x + blockDim.x * 0 + blockDim.x * 0/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 0);
smem[threadIdx.x + blockDim.x * 1 + blockDim.x * 1/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 1);
smem[threadIdx.x + blockDim.x * 2 + blockDim.x * 2/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 2);
smem[threadIdx.x + blockDim.x * 3 + blockDim.x * 3/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 3);
smem[threadIdx.x + blockDim.x * 4 + blockDim.x * 4/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 4);
smem[threadIdx.x + blockDim.x * 5 + blockDim.x * 5/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 5);
smem[threadIdx.x + blockDim.x * 6 + blockDim.x * 6/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 6);
smem[threadIdx.x + blockDim.x * 7 + blockDim.x * 7/(CF - 1) + threadIdx.x/(CF - 1)] = *(((float*)(cOut + i)) + threadIdx.x + blockDim.x * 7);
c.x = smem[threadIdx.x * CF + 0];
c.y = smem[threadIdx.x * CF + 1];
c.prevX = smem[threadIdx.x * CF + 2];
c.prevY = smem[threadIdx.x * CF + 3];
c.speedX = smem[threadIdx.x * CF + 4];
c.speedY = smem[threadIdx.x * CF + 5];
c.mass = smem[threadIdx.x * CF + 6];
c.radius = smem[threadIdx.x * CF + 7];
是不是正确的方式使用存取权限合并SMEM GMEM?我的意思是,我害怕BlockDim.x * 1/(CF - 1) + threadIdx.x/(CF - 1)
。 我想,我没有得到一些提升,因为它不允许gmem合并读取超过一个圆,但我不明白,如何使它合并两个圆..
是的,你清楚地了解我。 我尝试使用虚拟值,如你所说。我得到了正确的答案(正确的渲染),但我没有得到任何加速或减速。这是因为sizeof(Circle)== 32b吗? (或者我做错了吗?我会在问题中添加新版本) 我的意思是,全局内存合并访问的大小(正如我在文章中所读到的)对于float(我的情况)是64b,对于float2是128b, 256b为float3和float4? 我之前读过关于SoA vs AoS模式,但在我的项目中,我无法使用SoA重新创建它(出于某些原因)。 – Nexen