【问题标题】:multi-GPU basic usage多GPU基本用法
【发布时间】:2012-05-18 18:54:25
【问题描述】:

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

#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 gpu multi-gpu


    【解决方案1】:

    自 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 在设备之间进行选择。所以在上面的 sn-p 中,我假设了两个 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 应用程序,您可以查看更多想法。

    【讨论】:

    猜你喜欢
    • 2017-11-06
    • 1970-01-01
    • 2022-06-25
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2017-06-26
    • 1970-01-01
    相关资源
    最近更新 更多