GPU计算的原理介绍

发布时间: 2021-11-11 来源: 容器技术爱好者博客 200 次
1.  GPU计算的优势

复杂的人工智能算法训练与计算经常涉及上亿的参数,这些参数的计算需要大量的计算能力,目前在深度学习领域,GPU计算已经成为主流,使用GPU运算的优势如下:

目前,主流的GPU具有强大的计算能力和内存带宽,如下图所示,无论性能还是内存带宽,均远大于同代的CPU。 同时,GPU的thousands of cores的并行计算能力也是一大优势。




理解 GPU 和 CPU 之间区别的一种简单方式是比较它们如何处理任务。CPU 由专为顺序串行处理而优化的几个核心组成,而 GPU 则拥有一个由数以千计的更小、更高效的核心(专为同时处理多重任务而设计)组成的大规模并行计算架构。同时CPU相当的一部分时间在执行外设的中断、进程的切换等任务,而GPU有更多的时间并行计算。

2.  GPU计算的原理

那么,CPU与GPU如何协同工作?下图展示了CPU与GPU的并存体系模式。


在需要GPU进行运算时,以NVIDIA推出的CUDA(Compute Unified Device Architecture)为例,整体的原理如下:



整体分为4步:

  • 从主机内存将需要处理的数据copy到GPU的内存

  • CPU发送数据处理执行给GPU

  • GPU执行并行数据处理

  • 将结果从GPU内存copy到主机内存

CUDA提供了对于一般性通用需求的大规模并发编程模型,使用户可以对NVIDIA GPU方便的对于 GPU进行并发性编程。如果进行编译优化会在特定操作系统里面把计算并行化分配到GPU的多个core里面,由于GPU有多个core(上千个),所以并发度大大提高,运算效率会比CPU高。下面用代码表明了如何通过GPU进行计算:

有三个数组int a[10], b[10], c[10];我们要计算a和b的向量之和存放到c中。

一般C语言:

[mw_shl_code=bash,true]for(int i=0; i<10; i++)

c = a + b;[/mw_shl_code]


CUDA编程做法:

GPU中的每个线程(核)有一个独立序号叫index,那么只要序号从0到9的线程执行c[index] = a[index] + b[index];就可以实现以上的for循环。以下为代码示例:

[mw_shl_code=bash,true]#include  

#include  



define N 10;/* 定义10个GPU运算线程 */  

define SIZE N*sizeof(int);



/* 运行在GPU端的程序 */  

__global__ void vectorADD(int* a, int* b, int* c)  

{  

     int index = threadIdx.x;//获得当前线程的序号  

     if(index < blockDim.x)  

         c[index] = a[index] + b[index];  

}  

  

int main ()  

{  

        /* 本地开辟三个数组存放我们要计算的内容 */  

        int* a = (int*) malloc (SIZE);  

        int* b = (int*) malloc (SIZE);  

        int* c = (int*) malloc (SIZE);  

        /* 初始化数组A, B和C */  

        for(int i=0; i
        {  

                h_a = i;  

                h_b = i;  

        }  

            

        /* 在GPU上分配同样大小的三个数组 */  

        int* d_a;  

        int* d_b;  

        int* d_c;  

        cudaMalloc((void**)&d_a, SIZE);  

        cudaMalloc((void**)&d_b, SIZE);  

        cudaMalloc((void**)&d_c, SIZE);  

  

        /* 把本地的数组拷贝进GPU内存 */  

        cudaMemcpy(d_a, a, SIZE, cudaMemcpyHostToDevice);  

        cudaMemcpy(d_b, b, SIZE, cudaMemcpyHostToDevice);  

     

        /* 定义一个GPU运算块 由 10个运算线程组成 */  

        dim3 DimBlock = N;  

        /* 通知GPU用10个线程执行函数vectorADD */  

        vectorADD<<<1, dimblock="">>>(d_a, d_b, d_c);  

        /* 将GPU运算完的结果复制回本地 */  

        cudaMemcpy(c, d_c, SIZE, cudaMemcpyDeviceToHost);  

         

        /* 释放GPU的内存 */  

        cudaFree(d_a);  

        cudaFree(d_b);  

        cudaFree(d_c);  

  

        /* 验证计算结果 */  

        for(int j=0; j
                printf(“%d “, c[j]);  

        printf(“\n”);  

}  [/mw_shl_code]


3.  GPU并行计算的原理

由于每台服务器有多个CPU,多个GPU,同时为了进一步提高并行机器学习效率,我们的目标是为了多台服务器(每台服务器包含多块GPU卡)采取分布式计算的形式进行,那么要完成目标,在硬件层面需要进行服务器集群的构建,同时需要在深度学习框架层面也支持分布式,下面介绍GPU计算的分布式原理,深度学习分布式原理在下一个章节介绍。

首先简单介绍下单主机内GPU并行计算的基本原理:

单GPU并行计算:



针对每次训练数据,模型内计算通过多次GPU 内核的调用完成计算。权重W值一直存在GPU内存中,直到所有训练数据计算完毕之后回传到系统内存中。多GPU并行计算之数据并行:



数据并行是指不同的GPU计算不同的训练数据,即把训练数据划分给不同的GPU进行分别计算,由于训练是逐步训练的,后一个训练数据的计算需要前一个训练数据更新的W(W通常是指模型训练变化了的数据),数据并行改变了这个计算顺序,多GPU计算需要进行W的互相通信,满足训练的特点,使训练可以收敛。数据并行如上图所示,多GPU训练不同的数据,每训练一次需要同步W,使得后面的训练始终为最新的W。该模型的缺点是当模型较大时,GPU内存无法满足存储要求,无法完成计算。 多GPU并行计算之模型并行:模型并行是指多个GPU同时计算同一个训练数据,多个GPU对模型内的数据进行划分,在一次训练数据多层计算过程中,每个GPU内核计算之后需要互相交换数据才能进行下一次的计算。


可以看出,模型并行需要更频繁的通信,增加通信压力,且实现难度较大多GPU并行计算之集群计算:
GPU集群并行模式即为多GPU并行中各种并行模式的扩展,如上图所示。节点间采用InfiniBand通信,节点间的GPU通过RMDA通信,节点内多GPU之间采用基于infiniband的通信。




Copyright © 2021  西安硕星信息技术有限公司版权所有 ICP证: 陕ICP备17013496号