CUDA之矩陣乘法
阿新 • • 發佈:2018-11-08
我們已經知道了threads/blocks在CUDA端的組織方式,接下來我們學學多維度空間下的多執行緒模型,下面以矩陣乘法為例。
1. 行優先
儲存方式
二維矩陣在記憶體中的儲存方式受到程式語言的影響,主要可以分為兩種:行優先和列優先。對於程式語言諸如C/C++/CUDA而言,資料在記憶體中的組織方式是行優先。舉例說明行優先的儲存方式,如下,
給定一個3 3大小的矩陣 , ,在行優先的記憶體模型下面,二維矩陣將逐行地順序儲存,比方說,將第一行矩陣的資料依次儲存完畢之後,接著儲存第二行矩陣的資料;在第二行矩陣資料儲存完畢之後,接著儲存第三行矩陣的資料,以此類推,直到將整個矩陣儲存完畢為止。直觀上,矩陣 在記憶體中的儲存位置如下,
位置索引
基於給定的 大小的矩陣 ,則 在記憶體中的位置索引為 ,其中, , .
2. CPU實現和分析
CPU核心演算法
根據行優先的位置索引,我們可以容易地計算矩陣的乘法如下,
for(int row = 0; row < matrix_width; row++)
{
for(int col = 0; col < matrix_width; col++)
{
int single_element = 0;
for(int k = 0; k < matrix_width; k++)
{
single_element += matrix_a_host[row * matrix_width + k] * matrix_b_host[matrix_width * k + col];
}
matrix_c_host[row * matrix_width + col] = single_element;
}
}
注:矩陣乘法需要保證第一個矩陣的列數等於第二個矩陣的行數。
演算法複雜度
基於CPU實現的矩陣乘法的演算法複雜度為 。
3. GPU實現和分析
Threads/Blocks組織方式
出於程式設計上的方便,我們採用一維的blocks組織方式,二維的threads組織方式,如下,
dim3 dimGrid(1, 1, 1);
dim3 dimBlock(3, 3, 1);
注:預設情況下threads/blocks均採用一維的組織方式。
GPU核心演算法
__global__ void matrixs_1D_multiplication(int *matrix_a_dev, int *matrix_b_dev, int *matrix_c_dev, int matrix_width)
{
int row = threadIdx.y;
int col = threadIdx.x;
if(row < matrix_width && col < matrix_width)
{
for(int k = 0; k < matrix_width; k++)
{
matrix_c_dev[row * matrix_width + col] += matrix_a_dev[row * matrix_width + k] * matrix_b_dev[k * matrix_width + col];
}
}
}
演算法複雜度
基於GPU實現的矩陣乘法的演算法複雜度為 。
4. 編譯除錯
CPU版本
編譯
nvcc matrix_mul_cpu.cu -o main
執行
./main
GPU版本
編譯
nvcc matrix_mul_gpu.cu -o main
執行
./main