CUDA内核函数中的内存访问(简单示例)

时间:2016-11-22 17:11:04

标签: cuda gpgpu

我是GPU并行计算的新手,我试图通过查看NVidia中的一些示例来学习CUDA" CUDA通过示例"书。

我在这样一个简单的例子(两个向量的点积)中没有正确理解线程如何访问和更改变量。

内核函数定义如下

__global__ void dot( float *a, float *b, float *c ) {    
  __shared__ float cache[threadsPerBlock];   
 int tid = threadIdx.x + blockIdx.x * blockDim.x;    
 int cacheIndex = threadIdx.x;
 float   temp = 0;

 while (tid < N) {
    temp += a[tid] * b[tid];
    tid += blockDim.x * gridDim.x;
  }

    // set the cache values
  cache[cacheIndex] = temp;

我不明白三件事。

  1. 此功能的执行顺序是什么?线程之间是否有任何序列?例如,第一个是来自第一个块的线程,然后来自第二个块的线程进入播放等等(这与为什么必须将线程划分为块的问题相关联。)

  2. 所有主题都有自己的&#34; temp&#34;变量与否(如果没有,为什么没有竞争条件?)

  3. 它是如何运作的? while 循环中的变量 temp 究竟是什么?数组缓存为不同的线程存储 temp 的值。求和如何继续?似乎 temp 已包含点积所需的所有总和,因为变量 tid while 循环中从0变为N-1。

1 个答案:

答案 0 :(得分:0)

尽管您提供的代码不完整,但这里有一些关于您的要求的澄清:

  1. 内核代码将由所有块中的所有线程执行。通过&#34;分割工作的方式&#34;是使线程只在一个或几个元素上工作。 例如,如果必须使用特定算法处理100个整数,则可能需要100个线程来处理每个1个元素。 在CUDA中,块和线程的数量在主机端的内核启动时定义:
  2. myKernel<<<grid, threads>>>(...);

    网格线程 dim3 ,它们定义了三维的尺寸。

    线程和块的执行没有特定的顺序。你可以在那里阅读: http://mc.stanford.edu/cgi-bin/images/3/34/Darve_cme343_cuda_3.pdf 在第6页上:&#34;没有特定的顺序来调度和执行块&#34;。

    1. 由于 temp 变量在内核中没有特定的方式定义,因此不会分发,并且每个线程都会将此值存储在寄存器中。
    2. 这相当于在CPU端完成的操作。所以,是的,这意味着每个线程都有自己的&#34; temp&#34;变量

      1. 使用对设备阵列的访问权限,在循环的每次迭代中更新 temp 变量。
      2. 同样,这相当于在CPU方面所做的事情。

        我认为你应该在进一步进入GPU编程之前检查你是否已经足够用于CPU端的C / C ++编程。意思是没有冒犯,似乎你缺少几个主要话题。 由于CUDA允许您使用C代码驱动GPU,因此困难不在于语法,而在于硬件的特性。