Cuda 用于预取的共享内存配置
在我的程序中,我使用共享内存来预取数据。一个2D线程块,维度为8×4(32),获得8*4*8*sizeof(float4)字节的共享内存。每个线程在一个循环中复制8个浮点4:Cuda 用于预取的共享内存配置,cuda,nvidia,Cuda,Nvidia,在我的程序中,我使用共享内存来预取数据。一个2D线程块,维度为8×4(32),获得8*4*8*sizeof(float4)字节的共享内存。每个线程在一个循环中复制8个浮点4: inline __device__ void pack(const float4 *g_src, float4 *s_dst, const unsigned int w, const unsigned int d) { uint2 indx = { blockIdx.x * blockDim.x + threadI
inline __device__ void pack(const float4 *g_src, float4 *s_dst, const unsigned int w, const unsigned int d) {
uint2 indx = { blockIdx.x * blockDim.x + threadIdx.x, blockIdx.y * blockDim.y + threadIdx.y };
uint2 sindx = { threadIdx.x, threadIdx.y };
int i;
for (i = 0; i < d; ++i) s_dst[(sindx.y * blockDim.x + sindx.x) * d + i] = g_src[(w * indx.y + indx.x) * d + i];
}
inline\uuu设备\uuuu无效包(常量浮点4*g\u src,浮点4*s\dst,常量无符号整数w,常量无符号整数d){
uint2 indx={blockIdx.x*blockDim.x+threadIdx.x,blockIdx.y*blockDim.y+threadIdx.y};
uint2 sindx={threadIdx.x,threadIdx.y};
int i;
对于(i=0;i
其中,“w”设置为全局内存缓冲区的宽度(以浮点数表示),“d”设置为8(复制的浮点数)
这样的配置和内存的进一步使用是否会导致银行冲突,或者是否会应用广播?如果线程只复制,比如说5个float4s,而不是8个,这种情况也会发生吗
MK
附言。
在预取阶段,将发生相同的主题库冲突。例如,ID为(计算为
threadIdx.x+threadIdx.y*blockDim.x
)0、4、8、。。。28访问同一银行。您可以将其视为属于同一银行的i
等于0访问su-dst[0]
和su-dst[32]
的线程(0,0)和线程(4,0)
如果在进一步使用期间发生银行冲突,则取决于您将访问的方案sdst
只有当线程同时读取相同的地址时,才会应用广播机制
发生多少银行冲突取决于d
的值。如果d mod 32==1
将不会有任何冲突
编辑:
IMHO在预取阶段避免组冲突的最佳方法,特别是在d
发生变化时,是在各翘曲之间平均分割功。假设您需要将n
值预取到共享内存,w_id
是warp的id,l_id
是warp中线程的id(从0到31)。而预取应该是这样的:
for(int i = l_id + w_id*WARP_SIZE; i < n; i += WARP_SIZE*COUNT_OF_WARPS_IN_BLOCK)
{
s_dst[i] = ...;
}
for(int i=l\u id+w\u id*扭曲大小;i
但这只能帮助避免预取期间的银行冲突。正如我已经说过的,在进一步使用过程中避免冲突取决于您将在预取阶段访问
sdst
的方案,库冲突将发生。例如,ID为(计算为threadIdx.x+threadIdx.y*blockDim.x
)0、4、8、。。。28访问同一银行。您可以将其视为属于同一银行的i
等于0访问su-dst[0]
和su-dst[32]
的线程(0,0)和线程(4,0)
如果在进一步使用期间发生银行冲突,则取决于您将访问的方案sdst
只有当线程同时读取相同的地址时,才会应用广播机制
发生多少银行冲突取决于d
的值。如果d mod 32==1
将不会有任何冲突
编辑:
IMHO在预取阶段避免组冲突的最佳方法,特别是在d
发生变化时,是在各翘曲之间平均分割功。假设您需要将n
值预取到共享内存,w_id
是warp的id,l_id
是warp中线程的id(从0到31)。而预取应该是这样的:
for(int i = l_id + w_id*WARP_SIZE; i < n; i += WARP_SIZE*COUNT_OF_WARPS_IN_BLOCK)
{
s_dst[i] = ...;
}
for(int i=l\u id+w\u id*扭曲大小;i
但这只能帮助避免预取期间的银行冲突。正如我已经说过的,在进一步使用过程中避免冲突取决于您将访问的方案
sdst
是否可以避免银行冲突?展开“for”循环会更好吗?w_id=(threadIdx.x+threadIdx.y*blockDim.x)/32,l_id=(threadIdx.x+threadIdx.y*blockDim.x)%32n
等于要预取的值的整个计数。根据这一点,寻址全局内存?您必须向由块ID确定的i
添加一些偏移量,该块ID表示全局内存中属于该块的数据的开头。类似于g\u src[BLOCK\u ID*n+i]
这样的事情可以在没有银行冲突的情况下完成吗?展开“for”循环会更好吗?w_id=(threadIdx.x+threadIdx.y*blockDim.x)/32,l_id=(threadIdx.x+threadIdx.y*blockDim.x)%32n
等于要预取的值的整个计数。根据这一点,寻址全局内存?您必须向由块ID确定的i
添加一些偏移量,该块ID表示全局内存中属于该块的数据的开头。类似于g\u src[BLOCK\u ID*n+i]