计算矩阵的乘法
使用ChatGPT
辅助写作。 作为一个土狗,尝试使用CUDA计算
其中
安装CUDA
使用Windows 11的操作系统,Visual Studio作为集成开发环境。 安装CUDA的时候要注意VS的版本与CUDA的版本有一致性的要求。 例如我使用的Visual Studio Community 2022
,其中MVSC
的版本是CUDA 12.1
就不能用了,从官网重新下载了12.8的版本。
用VS2022
新建CUDA 12.8
的工程,修改kernel.cu
的内容。
初始化两个全1矩阵
size_t bytes = N * N * sizeof(int);
int* h_A = (int*)malloc(bytes);
int* h_B = (int*)malloc(bytes);
int* h_C = (int*)malloc(bytes);
std::fill(h_A, h_A + N * N, 1);
std::fill(h_B, h_B + N * N, 1);
std::fill(h_C, h_C + N * N, 0);
其中h_C为存放结果的数组。 为了方便内存管理,我们把
获取CUDA的存储空间
有点类似我们使用opengl的时候,要把主机内存的数据拷贝到显卡的内存里,再使用GPU计算,CUDA同样需要如此。
int* d_A, * d_B, * d_C;
cudaMalloc(&d_A, bytes);
cudaMalloc(&d_B, bytes);
cudaMalloc(&d_C, bytes);
cudaMemcpy(d_A, h_A, bytes, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, bytes, cudaMemcpyHostToDevice);
获取GPU的计算资源
dim3 threadsPerBlock(16, 16);
dim3 numBlocks(64, 64);
threadBlock是GPU的计算单元,每个threadBlock有一定数量的GPU线程。
每个GPU线程的计算方法
我们有
每个threadBlock有
- blockIdx
- blockDim
- threadIdx
我们已经把所有的线程映射到了C的每个元素上,根据矩阵的乘法定义:
代码如下:
__global__ void matrixMultiplication(int *c, const int *a, const int *b)
{
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
int sum = 0;
for (int i = 0; i < N; i++)
{
sum += a[row * N + i] * b[i * N + col];
}
c[row * N + col] = sum;
}
CUDA代码的调用方式如下
matrixMultiplication <<<numBlocks, threadsPerBlock >>> (d_C, d_A, d_B );
完整代码如下
#include <numeric>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <stdlib.h>
#define N 1024*8
__global__ void matrixMultiplication(int *c, const int *a, const int *b)
{
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
int sum = 0;
for (int i = 0; i < N; i++)
{
sum += a[row * N + i] * b[i * N + col];
}
c[row * N + col] = sum;
}
int genMatrix()
{
return 0;
}
int main()
{
size_t bytes = N * N * sizeof(int);
int* h_A = (int*)malloc(bytes);
int* h_B = (int*)malloc(bytes);
int* h_C = (int*)malloc(bytes);
std::fill(h_A, h_A + N * N, 1);
std::fill(h_B, h_B + N * N, 1);
std::fill(h_C, h_C + N * N, 0);
int* d_A, * d_B, * d_C;
cudaMalloc(&d_A, bytes);
cudaMalloc(&d_B, bytes);
cudaMalloc(&d_C, bytes);
cudaMemcpy(d_A, h_A, bytes, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, bytes, cudaMemcpyHostToDevice);
dim3 threadsPerBlock(16*8, 16*8);
dim3 numBlocks(64, 64);
matrixMultiplication <<<numBlocks, threadsPerBlock >>> (d_C, d_A, d_B );
cudaMemcpy(h_C, d_C, bytes, cudaMemcpyDeviceToHost);
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
free(h_A);
free(h_B);
free(h_C);
return 0;
}