1.cudaMalloc來回拷貝東西的時候一定要注意內存大小的問題,不然的話可能會出問題。
2.CUDA主機函數中可以使用c的語法,可以使用printf進行調試。
3.printf有的時候可以起到__syncthreads()的作用,所以有的時候如果加了printf能用的話,很可能是忘了加同步了。
4.在改變任何所有的核函數統一用到的變量之前一定要加__syncthreads(),如下面的例子中,因爲每次i更新後所執行的操作都必須要求i爲上一次的值得時候的操作都執行完成,如果不加同步,就會造成執行順序無法控制,最終造成結果的錯誤。
for (int i = blockDim.x / 2; i >= 1; i /= 2) {
if ( threadIdx.x < i) {
c_cache[ threadIdx.x] += c_cache[ threadIdx.x + i];
__syncthreads();
}
}
5.double有的時候比較佔空間,所以,炸了的話,換float就行了。
6.對於texture一定要在覈函數(使用到它)之前定義。同時對於texture的理解,把a(texture變量)和b(全局變量)綁定了候,每次在執行核函數的時候會把b拷貝到a中,在這次核函數執行的過程中,對於b中的內容仍然可以修改,但是a中的內容是不變的。然後對於下次調用核函數的時候,a會再次把b拷貝,這次的就是上次對b修改後的內容。示例代碼
#include "cuda_runtime.h"
#include"cuda.h"
#include "device_launch_parameters.h"
#include "device_functions.h"
#include <stdio.h>
#include <iostream>
using namespace std;
#define N 10
texture<float> test;
#define mins(a,b)(a<b?a:b)
#define threadsperblock 16
const int blocknum=mins(int((N +threadsperblock)/ threadsperblock), 32);
__global__ void kernel(float *a, float *b)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
a[id] = a[id] + b[id];
b[id] = tex1Dfetch(test, id);
printf("now a[%d] %f texture[%d] %f\n", id, a[id], id, tex1Dfetch(test, id));
}
int main()
{
float a[N], b[N];
float* da, * db;
for (int i = 0; i < N; i++) {
a[i] = i;
b[i] = i *2;
}
cout << cudaMalloc((void**)&da, N * sizeof(float)) << endl;;
cout << cudaMalloc((void**)&db, N * sizeof(float)) << endl;;
for (int z = 0; z < 2; z++) {
cout << cudaMemcpy(da, a, N * sizeof(float), cudaMemcpyHostToDevice) << endl;
cout << cudaMemcpy(db, b, N * sizeof(float), cudaMemcpyHostToDevice) << endl;
cudaBindTexture(NULL, test, da, N * sizeof(float));
kernel << <blocknum, threadsperblock >> > (da, db);
cudaMemcpy(a, da, N * sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy(b, db, N * sizeof(float), cudaMemcpyDeviceToHost);
for (int i = 0; i < N; i++) {
cout << a[i] << "," << b[i] << endl;
}
cout << endl;
}
cudaFree(da);
cudaFree(db);
cudaUnbindTexture(test);
}