cuda程式設計與gpu平行計算(六):圖稀疏矩陣轉為CSR結構並傳入gpu
雖然sepgraph有這部分程式碼,還是自己先試著實現一下,這樣讀起來也方便
行壓縮格式Compressed Sparse Row (CSR)
CSR需要三種資料來表達:數值、列號、行轉移。CSR不是三元組,而是整體的編碼方式。
CSR
編碼:
行優先遍歷矩陣Matrix
values陣列中儲存矩陣中非零元素。
column indices陣列儲存values陣列中對應位置非零元素的列索引。
row offsets陣列的下標表示每一行第一個非零元素的行索引,元素值為values陣列的下標,最後一個元素值為非零元素的個數。
解碼:
遍歷values陣列,對其中的元素值x(下標記為index_X)去column indices陣列中對應位置取出x在原矩陣中的列索引(記為col_index),然後在row offsets陣列查詢index_X,如果index_X在row offsets中,其在row offsets中的下標即為x在原矩陣中的行索引(記為row_index),如果index_X不在row offsets中,則使用上一個row_index值(因為編碼時是逐行編碼,且row offsets僅儲存每行的第一個非零元素,所以當前x與上一x在同一行)。
此為前言,清楚邏輯,程式碼就好辦了
#include<stdlib.h>
#include<time.h>
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
__global__ void csr(int* d_in_1,int* d_in_2,float* d_in_3){
int i = blockIdx.x * blockDim.x + threadIdx.x;
int start = d_in_1[i];
int end = d_in_1[i + 1];
for(int j = start;j < end ;j++){
printf("(%d,%d) ",i,d_in_2[j]);
}
}
//隨機生成一個圖的鄰接矩陣
void fill_random(float*data, int m, int n) {
srand((unsigned)(time(NULL))); //每次生成的隨機數不一樣
for (int i = 0; i < m*n; i++) {
data[i] = rand() % 100; //生成100以內的隨機數
if (data[i] < 80)
data[i] = 0;
}
}
void print_matrix(float*data, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int l = i + j * m;
cout << data[l] << " ";
}
cout << endl;
}
cout << endl;
}
void print_matrix(int*data, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int l = i + j * m;
cout << data[l] << " ";
}
cout << endl;
}
cout << endl;
}
void dense2csr(float*data, int*&rowPtr, int*&colInd, float*&val, int m, int n) {
rowPtr = (int*)malloc(sizeof(int)*(m + 1));
int* tcolInd = (int*)malloc(sizeof(int)*(m *n));
float* tval = (float*)malloc(sizeof(float)*(m *n));
int towtal = m * n;
int nnv = 0;
for (int i = 0; i < m; i++) {
rowPtr[i] = nnv;//記錄行偏移,其實也是前面一共已經有多少邊
for (int j = 0; j < n; j++) {
int l = i + j * m;
if (data[l] != 0) {
tcolInd[nnv] = j;//記錄列索引
tval[nnv] = data[l];//記錄邊權
nnv++;//找到一個邊,行偏移加一
}
}
}
rowPtr[m] = nnv;
colInd = (int*)malloc(sizeof(int)*(nnv));
val = (float*)malloc(sizeof(float)*(nnv));
memcpy(colInd, tcolInd, sizeof(float)*nnv);
memcpy(val, tval, sizeof(float)*nnv);
free(tcolInd);
free(tval);
}
int main() {
int m = 5;
int n = 5;
float*A = (float*)malloc(sizeof(float)*m*n);
fill_random(A, m, n);
print_matrix(A, m, n);
int*csrRowPtr;
int*csrColInd;
float*csrVal;
dense2csr(A, csrRowPtr, csrColInd, csrVal, m, n);
print_matrix(csrRowPtr, 1, m + 1);
print_matrix(csrColInd, 1, csrRowPtr[m]);
print_matrix(csrVal, 1, csrRowPtr[m]);
const int ARRAY_SIZE = m + 1;
const int ARRAY_BYTES_1 = ARRAY_SIZE * sizeof(int);
const int ARRAY_BYTES_2 = csrRowPtr[ARRAY_SIZE - 1] * sizeof(int);
const int ARRAY_BYTES_3 = csrRowPtr[ARRAY_SIZE - 1] * sizeof(float);
// 生成cpu上的csr結構
int h_in_1[m + 1];
int h_in_2[csrRowPtr[m]];
float h_in_3[csrRowPtr[m]];
for(int i = 0;i < m + 1 ; i++){
h_in_1[i] = csrRowPtr[i];
}
for(int i = 0;i < csrRowPtr[m]; i++){
h_in_2[i] = csrColInd[i];
h_in_3[i] = csrVal[i];
}
// 宣告GPU上的CSR結構
int* d_in_1;
int* d_in_2;
float* d_in_3;
// 分配空間
cudaMalloc((void**) &d_in_1,ARRAY_BYTES_1);
cudaMalloc((void**) &d_in_2,ARRAY_BYTES_2);
cudaMalloc((void**) &d_in_3,ARRAY_BYTES_3);
// 轉移全部
cudaMemcpy(d_in_1,h_in_1,ARRAY_BYTES_1,cudaMemcpyHostToDevice);
cudaMemcpy(d_in_2,h_in_2,ARRAY_BYTES_2,cudaMemcpyHostToDevice);
cudaMemcpy(d_in_3,h_in_3,ARRAY_BYTES_3,cudaMemcpyHostToDevice);
// 操作全部
csr<<<1,ARRAY_SIZE>>>(d_in_1,d_in_2,d_in_3);
// 釋放記憶體
cudaFree(d_in_1);
cudaFree(d_in_2);
cudaFree(d_in_3);
return 0;
}
執行的結果如下
先輸出一個隨機生成的帶權重有向稀疏圖,在cpu中將其壓縮為csr格式並輸出,再傳遞到gpu上,並輸出每一條邊的起點和終點。
相關文章
- cuda程式設計與gpu平行計算(四):cuda程式設計模型程式設計GPU模型
- GPU的並行運算與CUDA的簡介GPU並行
- GPU高效能程式設計CUDA實戰(二)GPU程式設計
- GPU程式設計--CPU和GPU的設計區別GPU程式設計
- 平行計算與並行程式設計課程內容介紹並行行程程式設計
- 高效能運算&CUDA | 使用numba對三維矩陣在gpu上進行運算矩陣GPU
- GPU程式設計(一):Ubuntu下的CUDA8.0環境搭建GPU程式設計Ubuntu
- GPU程式設計(四):並行規約優化GPU程式設計並行優化
- 資料結構(一)-稀疏矩陣資料結構矩陣
- 資料結構:陣列,稀疏矩陣,矩陣的壓縮。應用:矩陣的轉置,矩陣相乘資料結構陣列矩陣
- CUDA與架構矩陣概覽架構矩陣
- GPU程式設計(五):利用好sharedmemoryGPU程式設計
- 矩陣計算矩陣
- GPU精粹與Shader程式設計(四):真實感渲染GPU程式設計
- 稀疏矩陣矩陣
- GPU程式設計--OpenCL四大模型GPU程式設計大模型
- GPU程式設計(五): 利用好shared memoryGPU程式設計
- MPI矩陣向量乘法程式碼《並行程式設計導論》矩陣並行行程程式設計
- GPU精粹與Shader程式設計(三):實時輝光與透視陰影貼圖GPU程式設計
- 一些開源的 GPU 加速和平行計算庫,涵蓋了不同的程式語言和用途:GPU
- 有Cuda能力的GPU核心GPU
- GPU硬體結構GPU
- GPU精粹與Shader程式設計(一):關於基礎物理渲染GPU程式設計
- PostgreSQLGPU加速(HeteroDBpg_strom)(GPU計算,GPU-DIO-NvmeSSD,列存,GPU記憶體快取)SQLGPU記憶體快取
- 計算矩陣的秩矩陣
- GPU精粹與Shader程式設計(二):次表面散射與環境光遮蔽GPU程式設計
- Java中神經網路Triton GPU程式設計Java神經網路GPU程式設計
- 轉矩的計算?
- 稀疏矩陣之三元組壓縮儲存並且轉置矩陣
- 計算機圖形學之矩陣變換計算機矩陣
- 平行計算與Neon簡介
- 【測繪程式設計試題集】 試題02 矩陣卷積計算程式設計矩陣卷積
- CUDA 高效能平行計算入門
- 矩陣:如何使用矩陣操作進行 PageRank 計算?矩陣
- GPU程式設計(零):老黃和他的核彈們GPU程式設計
- 【scipy 基礎】--稀疏矩陣矩陣
- 平行計算π值
- cuda 加速矩陣乘法矩陣