GPU可以利用平行处理的方式,缩短执行时间,因此,这一次就来介绍多执行绪的程序设计方法及应用。
上一篇 介绍GPU函数的设定是透过<<<...>>>指定三个参数:
每一种GPU的数量均不相同,因此,我们先要侦测相关的数量限制,可以执行上一篇的deviceQuery.exe,预设建置的目录在【v11.2\bin\win64\Debug】。
所以,如果要在不同的卡都能执行,必须在程序中计算可设定的执行绪数量,总数量超过程序就会发生异常。共享记忆体也是一样的道理。【GTX1050 Ti】含6个处理器,我在以下的程序设定7*2048个执行绪也不会发生异常,我猜处理器有类似queue的功能,一旦执行绪超过容量限制,工作会排队等待,直到处理器有空时才被处理。
接下来,我们使用多执行绪进行向量的相加,一维阵列中的每个元素都独立计算,每个元素计算交由一个执行绪处理。
#define N 1024
__global__ void vectorAdd(int* d_a, int* d_b, int* d_c) {
// 使用第几个执行绪计算
int tid = threadIdx.x;
//printf("threadIdx = %d\n", tid);
d_c[tid] = d_a[tid] + d_b[tid];
}
int h_a[N], h_b[N], h_c[N], h2_c[N];
// 设定 a、b 的值
for (int i = 0; i < N; i++) {
h_a[i] = i; // 1,...,N
h_b[i] = i * 2; // 2,...,2xN
}
// 分配记忆体
cudaMalloc((void**)&d_a, N * sizeof(int));
// 自 CPU变数 复制到 GPU变数
cudaMemcpy(d_a, h_a, N * sizeof(int), cudaMemcpyHostToDevice);
cudaMalloc((void**)&d_b, N * sizeof(int));
cudaMemcpy(d_b, h_b, N * sizeof(int), cudaMemcpyHostToDevice);
// 分配记忆体
cudaMalloc((void**) &d_c, N * sizeof(int));
// 使用GPU进行向量相加,1 block x N threads
vectorAdd <<<1, N >>> (d_a, d_b, d_c);
// 等待所有执行绪处理完毕
cudaDeviceSynchronize();
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
vectorAdd <<<2, 1024 >>> (d_a, d_b, d_c);
vectorAdd 函数的阵列索引值要改为:
// blockIdx.x:第几个block,blockDim.x:block内的执行绪数量
int tid = threadIdx.x + blockIdx.x * blockDim.x;
在 GPU 撰写多执行绪真是方便,只要呼叫时,指定个数即可,但是,要以程序检查是否超出硬体限制条件,这部分可自deviceQuery截取相关程序码,计算应使用的区块数及执行绪数量。
平行处理要选择多区块或多执行绪呢? 使用多执行绪有两个好处:
完整程序放在 『GitHub』的VectorAdd目录。使用多个区块的改良程序放在VectorAdd_Improved目录。
>>: 为了转生而点技能-JavaScript,day15(Strict mode摘要整理
来到了第四天,我们可以进入比较复杂一点点的操作。但一样先讲结论,如果你很急着用,可以直接使用这份 A...
复习 Revershell:在受害主机启动连线 shell,连接回攻击主机(会预先监听 port)...
今天我们来看一个简单的程序: #include<stdio.h> int main(){...
CSS 三角形作法 语法 HTML <div class="box">...
虽然 iOS的 StoryBoard已经够像原形设计的流程了,但是我想还是 有必要先进行类似的原形设...