gpt4 book ai didi

cuda - 多GPU基本使用

转载 作者:行者123 更新时间:2023-12-03 11:37:24 24 4
gpt4 key购买 nike

例如,我如何使用两个设备来改进
以下代码的性能(向量之和)?
是否可以“同时”使用更多设备?
如果是,如何管理向量在不同设备的全局内存上的分配?

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <cuda.h>

#define NB 32
#define NT 500
#define N NB*NT

__global__ void add( double *a, double *b, double *c);

//===========================================
__global__ void add( double *a, double *b, double *c){

int tid = threadIdx.x + blockIdx.x * blockDim.x;

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

}

//============================================
//BEGIN
//===========================================
int main( void ) {

double *a, *b, *c;
double *dev_a, *dev_b, *dev_c;

// allocate the memory on the CPU
a=(double *)malloc(N*sizeof(double));
b=(double *)malloc(N*sizeof(double));
c=(double *)malloc(N*sizeof(double));

// allocate the memory on the GPU
cudaMalloc( (void**)&dev_a, N * sizeof(double) );
cudaMalloc( (void**)&dev_b, N * sizeof(double) );
cudaMalloc( (void**)&dev_c, N * sizeof(double) );

// fill the arrays 'a' and 'b' on the CPU
for (int i=0; i<N; i++) {
a[i] = (double)i;
b[i] = (double)i*2;
}

// copy the arrays 'a' and 'b' to the GPU
cudaMemcpy( dev_a, a, N * sizeof(double), cudaMemcpyHostToDevice);
cudaMemcpy( dev_b, b, N * sizeof(double), cudaMemcpyHostToDevice);

for(int i=0;i<10000;++i)
add<<<NB,NT>>>( dev_a, dev_b, dev_c );

// copy the array 'c' back from the GPU to the CPU
cudaMemcpy( c, dev_c, N * sizeof(double), cudaMemcpyDeviceToHost);

// display the results
// for (int i=0; i<N; i++) {
// printf( "%g + %g = %g\n", a[i], b[i], c[i] );
// }
printf("\nGPU done\n");

// free the memory allocated on the GPU
cudaFree( dev_a );
cudaFree( dev_b );
cudaFree( dev_c );
// free the memory allocated on the CPU
free( a );
free( b );
free( c );

return 0;
}

先感谢您。
米歇尔

最佳答案

自 CUDA 4.0 发布以来,您所询问类型的多 GPU 计算相对容易。在此之前,您需要使用多线程主机应用程序,每个 GPU 一个主机线程和某种线程间通信系统,以便在同一主机应用程序中使用多个 GPU。

现在可以对主机代码的内存分配部分执行以下操作:

double *dev_a[2], *dev_b[2], *dev_c[2];
const int Ns[2] = {N/2, N-(N/2)};

// allocate the memory on the GPUs
for(int dev=0; dev<2; dev++) {
cudaSetDevice(dev);
cudaMalloc( (void**)&dev_a[dev], Ns[dev] * sizeof(double) );
cudaMalloc( (void**)&dev_b[dev], Ns[dev] * sizeof(double) );
cudaMalloc( (void**)&dev_c[dev], Ns[dev] * sizeof(double) );
}

(免责声明:用浏览器编写,从未编译,从未测试,使用风险自负)。

这里的基本思想是你使用 cudaSetDevice在设备上执行操作时在设备之间进行选择。所以在上面的代码片段中,我假设有两个 GPU 并在每个 [(N/2) 双倍在第一个设备上和 N-(N/2) 在第二个] 上分配内存。

从主机到设备的数据传输可能非常简单:
// copy the arrays 'a' and 'b' to the GPUs
for(int dev=0,pos=0; dev<2; pos+=Ns[dev], dev++) {
cudaSetDevice(dev);
cudaMemcpy( dev_a[dev], a+pos, Ns[dev] * sizeof(double), cudaMemcpyHostToDevice);
cudaMemcpy( dev_b[dev], b+pos, Ns[dev] * sizeof(double), cudaMemcpyHostToDevice);
}

(免责声明:用浏览器编写,从未编译,从未测试,使用风险自负)。

代码的内核启动部分可能如下所示:
for(int i=0;i<10000;++i) {
for(int dev=0; dev<2; dev++) {
cudaSetDevice(dev);
add<<<NB,NT>>>( dev_a[dev], dev_b[dev], dev_c[dev], Ns[dev] );
}
}

(免责声明:用浏览器编写,从未编译,从未测试,使用风险自负)。

请注意,我在内核调用中添加了一个额外的参数,因为内核的每个实例可能会使用不同数量的要处理的数组元素来调用。我会让你来解决所需的修改。
但是,同样,基本思想是相同的:使用 cudaSetDevice选择一个给定的 GPU,然后以正常方式在其上运行内核,每个内核都有自己独特的参数。

您应该能够将这些部分放在一起以生成一个简单的多 GPU 应用程序。在最近的 CUDA 版本和硬件中,还有许多其他功能可以用于辅助多个 GPU 应用程序(例如统一寻址,点对点设施更多),但这应该足以让您入门。 CUDA SDK 中还有一个简单的多 GPU 应用程序,您可以查看更多想法。

关于cuda - 多GPU基本使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10529972/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com