【问题标题】:CUDA grid stride loop for nested for loop用于嵌套 for 循环的 CUDA 网格步幅循环
【发布时间】:2021-01-12 17:42:52
【问题描述】:

我正在使用CUDA网格跨步循环,结果看起来不错,但我不是100%理解为什么只需要对外循环进行跨步操作,而内循环没有任何变化。

__global__
void bodyForce(Body *p, float dt, int n) {
  
  int index = threadIdx.x + blockIdx.x * blockDim.x;
  int stride = blockDim.x * gridDim.x;


  for (int i = index; i < n; i += stride)
  {
    float Fx = 0.0f; float Fy = 0.0f; float Fz = 0.0f;

    for (int j = 0; j < n; j ++)
    {
      float dx = p[j].x - p[i].x;
      float dy = p[j].y - p[i].y;
      float dz = p[j].z - p[i].z;
      float distSqr = dx*dx + dy*dy + dz*dz + SOFTENING;
      float invDist = rsqrtf(distSqr);
      float invDist3 = invDist * invDist * invDist;

      Fx += dx * invDist3; Fy += dy * invDist3; Fz += dz * invDist3;
    }

    p[i].vx += dt*Fx; p[i].vy += dt*Fy; p[i].vz += dt*Fz;
  }
}

【问题讨论】:

    标签: c cuda


    【解决方案1】:

    此代码似乎直接来自 NVIDIA DLI 介绍性 CUDA C++ course 的评估练习。

    如果您正在学习本课程,那么网格步长循环就是您在将原始纯 CPU 代码转换为 GPU 加速代码的过程中编写的东西。所以代码是你选择写的任何东西。

    外部 for 循环上的 grid-stride 循环有意义的原因是因为外部 for 循环迭代完成的工作是独立的。从一个迭代到下一个迭代的计算顺序无关紧要,因此这可以轻松/简单地跨 CUDA 线程并行化,the grid-stride loop 是分配外部 for 循环工作的一种方法(在原始 CPU-仅代码)跨 CUDA 线程。

    内部 for 循环表示在迭代之间并非平凡独立的工作,因为一次迭代正在添加到前一次迭代的结果:

      Fx += dx * invDist3; Fy += dy * invDist3; Fz += dz * invDist3;
    

    因此,跨 CUDA 线程分配这项工作将不会采用与用于并行化外部 for 循环相同的琐碎/机械方法。

    当然可以,但这需要教授跨线程并行归约的概念,该课程当时尚未涉及。因此,明智的做法是不理会内部 for 循环,由单个线程处理,每个 Body

    这种认识仍然可以实现在该课程的评估练习中设定的绩效目标。

    【讨论】:

    • 那么内部for循环没有瘫痪?如果不是,我对分发的工作方式感到困惑,因为这两个 for 循环位于一个内核中,并且调用该内核以在设备上运行。
    • 我的意思是如果内部for循环没有瘫痪,设备怎么知道,因为j是从0开始而不是索引?
    • 内部循环未并行化。每个 CUDA 线程都运行该循环的一个实例。
    • 内部循环对每个 CUDA 线程执行“不同”的原因是因为它使用了 i 变量,每个 CUDA 线程都不同。
    • 不,我的意思是ii 从一个 CUDA 线程到下一个线程不同。 j 在每个线程中进行相同的迭代 (0..n-1)。
    猜你喜欢
    • 2022-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多