Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关于CUDA部分和码threadIdx.x、blockDim.x和a 2的混淆_Cuda_Sum_Nvidia - Fatal编程技术网

关于CUDA部分和码threadIdx.x、blockDim.x和a 2的混淆

关于CUDA部分和码threadIdx.x、blockDim.x和a 2的混淆,cuda,sum,nvidia,Cuda,Sum,Nvidia,有人能帮我理解以下CUDA-C的部分并行和算法实现吗?我无法理解共享partialSum数组的初始填充量[第3行到第8行]。我已经追踪了几个小时了,但我不明白为什么应该从下面的代码开始:应该是2*blockIdx.x*blockDim.x代替blockIdx.x*blockDim.x 主机代码: numOutputElements = numInputElements / (BLOCK_SIZE<<1); if (numInputElements % (BLOCK_SIZE<

有人能帮我理解以下CUDA-C的部分并行和算法实现吗?我无法理解共享
partialSum
数组的初始填充量[第3行到第8行]。我已经追踪了几个小时了,但我不明白为什么应该从下面的代码开始:应该是
2*blockIdx.x*blockDim.x代替
blockIdx.x*blockDim.x

主机代码:

numOutputElements = numInputElements / (BLOCK_SIZE<<1);
 if (numInputElements % (BLOCK_SIZE<<1)) {
     numOutputElements++;
 }
#define BLOCK_SIZE 512
dim3 dimGrid(numOutputElements, 1, 1);
dim3 dimBlock(BLOCK_SIZE, 1, 1);
total<<<dimGrid, dimBlock>>>(deviceInput, deviceOutput, numInputElements);

numOutputElements=numInputElements/(块大小您只需启动一半块,每个块的工作量是原来的两倍。这样做的好处是存储部分和所需的暂存空间减少了一半(因为您只启动了一半块)

做减法(在本例中是求和)的通常方法是这样做

1    __global__ void total(float * input, float * output, int len) {
2    
3    __shared__ float partialSum[BLOCK_SIZE];
4      
5     unsigned int t = threadIdx.x;
6     unsigned int start = blockIdx.x*blockDim.x;
7     partialSum[t] = 0;
8     for (int T = start; T < len; T += blockDim.x * gridDim.x) 
9        partialSum[t] += input[T];
10    for (unsigned int stride = blockDim.x/2; stride >=1; stride >>=1)
11      {
12       __syncthreads();
13        
14       if (t < stride)
15         partialSum[t] += partialSum[t + stride];
16      }
17      output[blockIdx.x] = partialSum[0];   
18  }
1\uuuu全局\uuuuu无效总计(浮点*输入,浮点*输出,整数长度){
2.
3 uuu共享uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
4.
5无符号整数t=threadIdx.x;
6无符号int start=blockIdx.x*blockDim.x;
7 partialSum[t]=0;
8用于(int T=start;T=1;步长>>=1)
11      {
12个同步线程();
13
14如果(t<步幅)
15部分肌群[t]+=部分肌群[t+步幅];
16      }
17输出[blockIdx.x]=partialSum[0];
18  }

因此,如果你有
len=1024
,并且
BLOCK\u SIZE=256
,你可以启动任何东西你只启动一半的块,每个块做两倍的工作。这样做的好处是存储部分和所需的暂存空间减少了一半(因为你只启动了一半的块)

做减法(在本例中是求和)的通常方法是这样做

1    __global__ void total(float * input, float * output, int len) {
2    
3    __shared__ float partialSum[BLOCK_SIZE];
4      
5     unsigned int t = threadIdx.x;
6     unsigned int start = blockIdx.x*blockDim.x;
7     partialSum[t] = 0;
8     for (int T = start; T < len; T += blockDim.x * gridDim.x) 
9        partialSum[t] += input[T];
10    for (unsigned int stride = blockDim.x/2; stride >=1; stride >>=1)
11      {
12       __syncthreads();
13        
14       if (t < stride)
15         partialSum[t] += partialSum[t + stride];
16      }
17      output[blockIdx.x] = partialSum[0];   
18  }
1\uuuu全局\uuuuu无效总计(浮点*输入,浮点*输出,整数长度){
2.
3 uuu共享uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
4.
5无符号整数t=threadIdx.x;
6无符号int start=blockIdx.x*blockDim.x;
7 partialSum[t]=0;
8用于(int T=start;T=1;步长>>=1)
11      {
12个同步线程();
13
14如果(t<步幅)
15部分肌群[t]+=部分肌群[t+步幅];
16      }
17输出[blockIdx.x]=partialSum[0];
18  }

因此,如果您有
len=1024
,并且
BLOCK\u SIZE=256
,您可以启动任何程序,您可能无法计算块数

假设您有10个元素要求和,并且您选择将blocksize设置为4,并且每个块有4个线程,那么只有两个块在使用

因为根据内核代码,每个线程负责全局设备mem中的两个元素

每个线程读取的输入元素如下所示。我在代码中没有看到任何范围检查。因此我假设10个元素有足够的零填充

blockIdx.x           : 0 0 0 0  1 1 1 1  2 2 2 2  3 3 3 3
threadIdx.x          : 0 1 2 3  0 1 2 3  0 1 2 3  0 1 2 3
linear thread id     : 0 1 2 3  4 5 6 7  8 9 a b  c d e f

Idx of the element     0 1 2 3  8 9
read by the thread   : 4 5 6 7
因此,
output[0]
存储元素0~7的和,
output[1]
存储元素8~9的和。我不认为丢失了任何东西

请参阅中的内核4,了解有关为什么会出现
2*
的性能问题。
较慢的内核3和@Pavan在回答中给出的内核是类似的实现,其中每个线程只负责一个元素。

计算块时可能会遇到问题

假设您有10个元素要求和,并且您选择将blocksize设置为4,并且每个块有4个线程,那么只有两个块在使用

因为根据内核代码,每个线程负责全局设备mem中的两个元素

每个线程读取的输入元素如下所示。我在代码中没有看到任何范围检查。因此我假设10个元素有足够的零填充

blockIdx.x           : 0 0 0 0  1 1 1 1  2 2 2 2  3 3 3 3
threadIdx.x          : 0 1 2 3  0 1 2 3  0 1 2 3  0 1 2 3
linear thread id     : 0 1 2 3  4 5 6 7  8 9 a b  c d e f

Idx of the element     0 1 2 3  8 9
read by the thread   : 4 5 6 7
因此,
output[0]
存储元素0~7的和,
output[1]
存储元素8~9的和。我不认为丢失了任何东西

请参阅中的内核4,了解有关为什么会出现
2*
的性能问题。
较慢的内核3和@Pavan在回答中给出的内核是类似的实现,其中每个线程只负责一个元素。

请看第7行和第8行。每个线程将2个值读入共享内存。请参阅中的内核4,了解为什么会有
2*
我编辑了我的问题,我认为这会对您有所帮助请看第7行和第8行。每个线程在共享内存中读取2个值。请参阅中的内核4,了解为什么会有一个
2*
我编辑了我的问题,我想这会帮助你们理解我的问题!当你们说“开始”时,你们的意思是“
start
”?real谢谢你的简短回答。+1!我已经编辑了我的问题,如果你能看一下,我真的很高兴!我的查询是关于我的block2(第三个block)'s element loss!因为我认为
start=2*blockIdx.x*blockDim.x;
从那时起超过了输入长度!@sadaf2605您只启动了较少的块。在您的情况下,只有2个,而不是4个。您只按需要启动块。如果主机端代码启动了4个块,则效率低下。发布主机端代码,您可以看到bloc的数量ks正在启动。@sadaf2605所以..主机代码现在是正确的(您正在按2*块大小潜水)。因此,当len=10时,您只启动了2个块,每个块有4个线程。这里没有问题。非常感谢您的简短回答。+1!我编辑了我的问题,如果您能看一下,我将非常高兴!我的查询是关于我的block2(第3个块)的元素丢失!因为我认为
start=2*blockIdx.x*blockDim.x;