#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#define ThreadSize 1000
#define BlockSize 10000
#define ArraySize 10
__global__ void incKernel(int *a)
{
int i =
(blockIdx.x*blockDim.x + threadIdx.x) % ArraySize;
a[i] = a[i] + 1;
}
int main()
{
int host_a[ArraySize];
int *dev_a = 0;
float elapsedTime;
// setup performance meter from CUDA ----------
cudaEvent_t
start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaSetDevice(0);
cudaMalloc((void**)&dev_a, ArraySize * sizeof(int));
for (int run = 0; run <
10; run++) {
cudaMemset(dev_a,
0, ArraySize * sizeof(int)); //clear
cudaEventRecord(start,
0); //keep start time
incKernel
<< <BlockSize, ThreadSize >> > (dev_a); //calculate
cudaEventRecord(stop,
0); //keep stop time
cudaEventSynchronize(stop);
//wait stop event
cudaEventElapsedTime(&elapsedTime,
start, stop);
cudaMemcpy(host_a,
dev_a, ArraySize * sizeof(int), cudaMemcpyDeviceToHost);
//Print result
printf("run {%d}: ",run);
for (int i = 0; i < ArraySize; i++) {
printf("%d ", host_a[i]);
}
printf(" t=%f\n",elapsedTime);
}
//cudaDeviceSynchronize();
getchar();
cudaFree(dev_a);
return 0;
}
|
執行結果如下:
這裡可以發現, 雖然每個陣列元速執行的程式碼都一樣, 結果卻不相同. 如果要得到正確答案, 需要用到互斥機制, 在以 CPU 計算環境中, 多由作業系統負責管理, 而在 CUDA 中, 用硬體用 atomic 運算來解決這個問題, 程式修改如下:
int atomicAdd(int* address, int val);
__global__ void incKernel(int *a)
{
int i =
(blockIdx.x*blockDim.x + threadIdx.x) % ArraySize;
//a[i] = a[i] + 1;
atomicAdd(&a[i], 1);
}
|
因為 atomic 運算屬於 architecture 指令, 如果不自行宣告 header 亦可, compiler 會自動處理, 只是編輯時會看到 Visual Studio 的警告訊息. 修改後的執行結果如下:
結果就正確了, 速度快慢則不一定, 在這個例子中是變快了
沒有留言:
張貼留言