cuda与CPU运行效率对比

561 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

一、安装扩展

要想运行CUDA,还需要C++编译环境。

安装及配置visual studio

CUDA C在很大程度上与标准C没有区别。在GPU上执行的函数通常称为核函数

使用CUDA需要C++的编译环境,这里我们可以安装visual studio,这里给一个visual studio 2017的下载地址 www.aliyundrive.com/s/L7Kzx437C…,下载安装即可。

注意:CUDA只支持2017-2019版的visual studio,如果不是这个范围的vs会报错,如下图所示: 网上大部分教程都是安装visual studio来进行的,


下载完成后,打开安装文件,按下图所示选择安装即可:

在这里插入图片描述


安装完成后还需要将cl.exe所在目录加入到环境变量中,我们可以在vs目录下搜索cl.exe获取路径:

在这里插入图片描述


然后将该地址加入到环境变量中即可。

4)检查安装是否成功

我们可以建立一个main.cu的文件,然后加入下面的代码:

#include <stdio.h>

__global__ void hello() {
    
}

int main() {
    hello<<<1, 1>>>();
    printf("草莓桃桃酥");
    return 0;
}

然后在cmd中执行命令:nvcc main.cu -o main,会看到如下输出: 在这里插入图片描述


然后再输入命令:main.exe执行文件,看到输入输出即代表成功: 在这里插入图片描述


二、CUDA在GPU和CPU运行效率对比

说了那么多GPU的优势,不实际上手试试怎么行呢?实践出真知,不然都是口说无凭。

下面是一个分别使用CPU和CUDA调用GPU执行矩阵运算的代码,会根据我们输入的Num值来执行运算,Num=10000相当于会运算10000*10000次,也就是1亿次,我的显卡为:GTX1060,来看一下实际的运行比较吧:

#include <stdio.h>
#include <time.h>
#define Num (10000)
#define THREADS 1000

void serial_add(double *a, double *b, double *c)
{
    for(int index=0;index<Num;index++)
    {
        for(int j=0;j<Num;j++)
        {
            c[index] = a[index]*a[index] + b[index]*b[index];
        }
    }
}

__global__ void vector_add(double *a, double *b, double *c)
{
    int index = blockIdx.x * blockDim.x + threadIdx.x;
        for(int j=0;j<Num;j++)
        {
            c[index] = a[index]*a[index] + b[index]*b[index];
        }
}

int main()
{
    clock_t start,end;

    double *a, *b, *c;
    int size = Num * 8;
    //分配内存空间
    a = (double *)malloc( size );
    b = (double *)malloc( size );
    c = (double *)malloc( size );

    for( int i = 0; i < Num; i++ )
    {
        a[i] = b[i] = i;
        c[i] = 0;
    }

    start = clock();
    serial_add(a, b, c);
    end = clock();

    float time1 = ((float)(end-start))/CLOCKS_PER_SEC;
    printf("通过CPU执行消耗的时间: %f 秒\n",time1);
    //CUDA
    start = clock();
    double *d_a, *d_b, *d_c;
	

    cudaMalloc( (void **) &d_a, size );
    cudaMalloc( (void **) &d_b, size );
    cudaMalloc( (void **) &d_c, size );


    cudaMemcpy( d_a, a, size, cudaMemcpyHostToDevice );
    cudaMemcpy( d_b, b, size, cudaMemcpyHostToDevice );

    vector_add<<< (Num + (THREADS-1)) / THREADS, THREADS>>>( d_a, d_b, d_c );

    cudaMemcpy( c, d_c, size, cudaMemcpyDeviceToHost );
    //释放内存和显存
    free(a);
    free(b);
    free(c);
    cudaFree( d_a );
    cudaFree( d_b );
    cudaFree( d_c );
    end = clock();
    float time2 = ((float)(end-start))/CLOCKS_PER_SEC;
    printf("CUDA调用GPU执行消耗的时间: %f 秒",time2);
    return 0;
}

输出结果

通过CPU执行消耗的时间: 0.275000 秒
CUDA调用GPU执行消耗的时间: 0.109000

可以看到这么小的数据量就有2倍多的差距了,这时候我们增大Num的值,改为10W的话,它们之间的差距会更大:

通过CPU执行消耗的时间: 36.223000 秒
CUDA调用GPU执行消耗的时间: 0.900000

可以看到差距越来越大,当然也不排除我的测试方法是否存在问题。欢迎大家指导和指正。