CPU与GPU在大型矩阵计算时的性能对比

最近开始学习GPU编程,在GPU这种架构下,对大型矩阵乘法以及加法所带来的计算优势还是很有潜力。最近对这种并行结构下的GPU计算很着迷。我可能面对的是一个几十万列矩阵的乘法与加法,所以希望可以把CPU下的循环结构一知道GPU架构下,做并行计算。
我先对比了在CPU和GPU下的1000×1000矩阵乘法的完成时间,结果发现,时间上的提升还是很显著的。但是,该GPU程序的核函数部分没有使用共享内存,main函数部分,采用了托管内存寄存数据的方式,而传统的数据寄存方式是申请host以及Device内存,保证数据在device以及host之间进行传输,相较于传统的数据寄存方式,减少了数据在device以及host 之间的时间以及gpu的数据访问时间。开始贴代码。

#include 
#include 
#include 
#include 

#define w 1000

struct Matrix
{
	int width;
	int height;
	float *elements;
};

__device__ float getElement(Matrix *A, int row, int col)
{
        return A->elements[row * A->width + col];
}

__device__ void setElement(Matrix *A, int row, int col, float value)
{
        A->elements[row * A->width + col] = value;
}

__global__ void matMulKernel(Matrix *A, Matrix *B, Matrix *C)
{
        float Cvalue = 0.0;
        int row = threadIdx.y + blockIdx.y * blockDim.y;
        int col = threadIdx.x + blockIdx.x * blockDim.x;
        
        for (int i = 0; i < A->width; ++i)
        {
                Cvalue += getElement(A, row, i) * getElement(B, i, col);
        }
        setElement(C, row, col, Cvalue);
}

int main()
{
	int width = w;
	int height = w;

	Matrix *A, *B, *C;

	cudaMallocManaged((void**)&A, sizeof(Matrix));
	cudaMallocManaged((void**)&B, sizeof(Matrix));
	cudaMallocManaged((void**)&C, sizeof(Matrix));

	int nBytes = width * height * sizeof(float);

	cudaMallocManaged((void**)&A->elements, nBytes);
	cudaMallocManaged((void**)&B->elements, nBytes);
	cudaMallocManaged((void**)&C->elements, nBytes);

	A->height = height;
	A->width = width;
	B->height = height;
	B->width = width;
	C->height = height;
	C->width = width;

	for (int i = 0; i < width * height; ++i)
	{
		A->elements[i] = 1.0;
		B->elements[i] = 2.0;
	}

	dim3 blockSize(32, 32);
	dim3 gridSize((width + blockSize.x - 1) / blockSize.x,
		(height + blockSize.y - 1) / blockSize.y);

	struct timeval t1,t2;
	gettimeofday(&t1,NULL);
	double timeuse;

	matMulKernel << < gridSize, blockSize >> >(A, B, C);

	cudaDeviceSynchronize();

	gettimeofday(&t2,NULL);
	timeuse = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec)/1000000.0;
	printf("Use Time:%f\n", timeuse);

	return 0;
}

该程序在GPU上面的运行时间是0.032921s

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define w 1000

struct Matrix
{
    int width;
    int height;
    float *elements;
};

void matMul(float * M, float * N, float * P, int width){
        for (int i = 0; i < width; i++){
                for (int j = 0; j < width; j++){
                        float sum = 0;
                        for (int k = 0; k < width; k++){
                                float a = M[i * width + k];
                                float b = N[k * width + j];
                                sum += a * b;
                        }
                        P[i * width + j] = sum;
                }
        }
}

int main(){
        int width = w;
        int height = w;

        float * m = (float *)malloc (width * height * sizeof (float));
        float * n = (float *)malloc (width * height * sizeof (float));
        float * p = (float *)malloc (width * height * sizeof (float));

        for (int i = 0; i < width * height; i++){
                m[i] = 1.0;
                n[i] = 2.0;
        }

        struct timeval t1,t2;
        gettimeofday(&t1,NULL);
        double timeuse;

        matMul(m, n, p, w);

        gettimeofday(&t2,NULL);
        timeuse = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec)/1000000.0;
        printf("Use Time:%f\n",timeuse);

        return 0;
}


c++程序的编译指令是g++,该程序的运行时间是6.318331s,时间上GPU提高的量级还是很可观的。

然后我又尝试把上述c++代码用nvcc编译了一下,只是头文件部分小改动了一下, c++程序的运行时间是4.311695s,时间上面也可以缩小。 只是比起GPU编程,还是有点儿小。

下一篇我决定写一篇GPU的架构分析,以及共享内存的优势。数据说话,we will see.

你可能感兴趣的:(cuda,parallel,computation,study,of,unmanned,vehicle,research)