CUDA並行規約(交錯配對)

按照前文多線程的交錯配對方式實現並行規約求和方式,實現CUDA版本的並行規約求和,由於這種方式的規約可以避免線程束的分化,因此不需要進行類似於相鄰配對那種方式的優化。

交錯與優化相鄰模式相比,計算效率提升到1.14倍,性能提高有限,這主要受限於全局內存的加載和存儲模式。

並行規約的示意圖: 


#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>
#include "math.h"
#include "stdlib.h"

//錯誤檢查的宏定義
#define CHECK(call)									\
{													\
	const cudaError_t status=call;					\
if (status!=cudaSuccess)							\
	{												\
	printf("文件:%s,函數:%s,行號:%d\n",__FILE__,		\
						__FUNCTION__,__LINE__);		\
	printf("%s", cudaGetErrorString(status));		\
	exit(1);										\
	}												\
}													\

//核函數
__global__ void Kernel(int *d_data, int *d_local_sum, int N)
{
	int tid = threadIdx.x;
	int index = blockIdx.x*blockDim.x + threadIdx.x;
	int *data = d_data + blockIdx.x*blockDim.x;

	if (index >= N) return;

	for (int strize = blockDim.x / 2; strize > 0; strize >>= 1)
	{
		if (tid < strize)
			data[tid] += data[tid + strize];

		__syncthreads();
	}


	if (tid == 0)
	{
		d_local_sum[blockIdx.x] = data[0];
	}
}

//主函數
int main()
{

	//基本參數設置
	cudaSetDevice(0);
	const int N = 16777216;
	int local_length = 1024;
	int total_sum = 0;

	dim3 grid(((N + local_length - 1) / local_length), 1);
	dim3 block(local_length, 1);

	int *h_data = nullptr;
	int *h_local_sum = nullptr;
	int *d_data = nullptr;
	int *d_local_sum = nullptr;


	//Host&Deivce內存申請及數組初始化
	h_data = (int*)malloc(N * sizeof(int));
	h_local_sum = (int*)malloc(int(grid.x) * sizeof(int));


	CHECK(cudaMalloc((void**)&d_data, N * sizeof(int)));

	CHECK(cudaMalloc((void**)&d_local_sum, int(grid.x) * sizeof(int)));


	for (int i = 0; i < N; i++)
		h_data[i] = int(10 * sin(0.02*3.14*i));//限制數組元素值,防止最終求和值超過int的範圍

	//數據拷貝至Device
	CHECK(cudaMemcpy(d_data, h_data, N * sizeof(int), cudaMemcpyHostToDevice));

	for (int i = 0; i < 200; i++)
		//執行核函數
		Kernel << <grid, block >> > (d_data, d_local_sum, N);

	//數據拷貝至Host
	CHECK(cudaMemcpy(h_local_sum, d_local_sum, int(grid.x) * sizeof(int),
		cudaMemcpyDeviceToHost));

	//同步&重置設備
	CHECK(cudaDeviceSynchronize());
	CHECK(cudaDeviceReset());


	for (int i = 0; i < int(grid.x); i++)
	{
		total_sum += h_local_sum[i];
	}

	printf("%d \n", total_sum);

	//getchar();
	return 0;

}


發佈了54 篇原創文章 · 獲贊 29 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章