CUDA在单个内核中多个动态分配的共享数组

时间:2013-05-25 10:09:30

标签: cuda shared-memory

我有以下问题。我试图将共享数组划分为更小的数组,然后在其他设备函数中使用这些数组。在我的内核函数中,

for (int block_x = 0; block_x < blockDim.x; block_x++) {
  for (int block_y = 0; block_y < blockDim.y; block_y++) {
  //set up shared memory block
  extern __shared__ vec3f share[];
  vec3f *sh_pos = share;
  vec3f *sh_velocity = &sh_pos[blockDim.x*blockDim.y];
  vec3f *sh_density = &sh_velocity[blockDim.x*blockDim.y];
  vec3f *sh_pressure = &sh_density[blockDim.x*blockDim.y];
  //index by 2d threadidx's
  unsigned int index = (block_x * blockDim.x + threadIdx.x) + blockDim.x * gridDim.x * (block_y * blockDim.y + threadIdx.y);
  sh_pos[blockDim.x * threadIdx.x + threadIdx.y] = oldParticles[index].position();
  sh_velocity[blockDim.x * threadIdx.x + threadIdx.y] = oldParticles[index].velocity();
  sh_pressure[blockDim.x * threadIdx.x + threadIdx.y].x = oldParticles[index].pressure();
  sh_density[blockDim.x * threadIdx.x + threadIdx.y].x = oldParticles[index].density();
  __syncthreads();
  d_force_pressure(oldParticles[arr_pos],c_kernel_support);
  __syncthreads();
  }
}

据我所知,所有“sh_”数组都填充了零而不是我想要的值。我不知道我做错了什么。请注意,vec3f是float的向量,就像float3数据类型一样。另外,我不认为我可以在浮子中混合密度和压力,所以我只是将它们作为矢量并使用单个组件。然后,例如我的d_force_pressure函数是,

__device__ void d_force_pressure(particle& d_particle, float h) {
  extern __shared__ vec3f share[];
  vec3f *sh_pos = share;
  vec3f *sh_velocity = &sh_pos[blockDim.x*blockDim.y];
  vec3f *sh_density = &sh_velocity[blockDim.x*blockDim.y];
  vec3f *sh_pressure = &sh_density[blockDim.x*blockDim.y];
  for (int i = 0; i < blockDim.x * blockDim.y; i++) {
    vec3f diffPos = d_particle.position() - sh_pos[i];
    d_particle.force() += GradFuncion(diffPos,h) * -1.0 * c_particle_mass *  (d_particle.pressure()+sh_pressure[i].x)/(2.0*sh_density[i].x);
  }  
 }

在调用此函数后,我得到NaN,因为我除以零(sh_density[i].x就我所知,0)。这也是一般的,加载共享内存的正确方法吗?

内核由

调用
dim3 block(BLOCK_SIZE,BLOCK_SIZE,1);
dim3 grid((int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), (int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), 1);
int sharedMemSize = block.x*block.y*4*sizeof(vec3f);
force_kernel<<< grid,block,sharedMemSize  >>>(particle_ptrs[1],particle_ptrs[0],time_step);

2 个答案:

答案 0 :(得分:1)

这是一个后续答案。

根据@RobertCrovella的评论,我继续运行cuda-memcheck。信不信由你,这实际上没有错误。但是,当我在代码中更改常量(控制某些数组的大小)时,cuda-memcheck显示与此处发布的问题相关的错误write error。这让我重新检查了我填充共享数组的方式。

基本上需要改变的是什么
for (int block_x = 0; block_x < blockDim.x; block_x++) {
  for (int block_y = 0; block_y < blockDim.y; block_y++) {

for (int block_x = 0; block_x < gridDim.x; block_x++) {
  for (int block_y = 0; block_y < gridDim.y; block_y++) {

我相信这会为index变量提供正确的位置。我基本上了解到,无论何时使用共享内存并注意事情运行缓慢,最好使用cuda-memcheck。

答案 1 :(得分:0)

我在上一个问题中表示你不想这样做:

dim3 grid((int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), (int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), 1);

你想这样做:

dim3 grid((int)ceil(sqrt(float(max_particles)) / (float(block.x))), (int)ceil(sqrt(float(max_particles)) / (float(block.y))), 1);

x网格方向应该由线程块x维度缩放,而不是线程块x维度*线程块y维度。但是我在上一个回答中发布的代码也有这个错误,即使我在评论中指出,我忘了解决它。

此外,这个索引对我来说不合适:

sh_velocity[blockDim.x * threadIdx.x + threadIdx.y] 

我认为应该是:

sh_velocity[blockDim.x * threadIdx.y + threadIdx.x] 

你有几个例子。

您尚未发布完整的可执行文件。肯定会有比我上面提到的问题更多的问题。如果我必须通过所有的vec3f - &gt;我在上一个问题中做过的float3转换工作,好吧,其他人可以帮助你。如果你写一个简单的复制器,它不依赖于我没有的一堆代码,我可以尝试进一步提供帮助。很可能,如果你这样做,你会自己发现问题。

您是否已将cuda错误检查放入您的代码中,就像我在上一个回答中建议的那样?

您可能还想通过cuda-memcheck运行代码:

cuda-memcheck ./mycode