关于CUDA部分和码threadIdx.x、blockDim.x和a 2的混淆
有人能帮我理解以下CUDA-C的部分并行和算法实现吗?我无法理解共享关于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<
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;