繁体   English   中英

CUDA在单个内核中多个动态分配的共享阵列

[英]CUDA multiple dynamically allocated shared arrays in single kernel

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

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);
  }  
 }

调用此函数后,由于我被零除( sh_density[i].x据我所知为0),因此得到NaN。 同样,这也是加载共享内存的正确方法吗?

内核由

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);

这是一种后续答案。

根据@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是一个好主意。

我在您先前的问题中指出您不想这样做:

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-> float3转换工作,那么其他人可以为您提供帮助。 如果您编写的简单复制器不依赖我没有的一堆代码,那么我可以尝试进一步提供帮助。 如果您这样做,很有可能自己发现问题。

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

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

cuda-memcheck ./mycode

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM