我在這裏遇到問題。我啓動兩個內核,檢查是否有某個值是預期值(memcpy到主機),如果是我停止,如果不是,我再次啓動兩個內核。CUDA內核和內存訪問(一個內核不能完全執行,下一個不會啓動)
第一內核:
__global__ void aco_step(const KPDeviceData* data)
{
int obj = threadIdx.x;
int ant = blockIdx.x;
int id = threadIdx.x + blockIdx.x * blockDim.x;
*(data->added) = 1;
while(*(data->added) == 1)
{
*(data->added) = 0;
//check if obj fits
int fits = (data->obj_weights[obj] + data->weight[ant] <= data->max_weight);
fits = fits * !(getElement(data->selections, data->selections_pitch, ant, obj));
if(obj == 0)
printf("ant %d going..\n", ant);
__syncthreads();
...
的代碼在此之後繼續。但是printf永遠不會被打印出來,只是出於調試目的,syncthreads就在那裏。
「增加」變量是共享的,但由於共享內存是PITA,並且通常會在代碼中拋出錯誤,我現在只是將其刪除。這個「添加」變量並不是最聰明的事情,但它比替代方法更快,它會檢查數組中的任何變量是否是主機上的某個值,並決定是否繼續迭代。
的getElement,根本矩陣存儲器計算與俯仰訪問正確的位置,並返回該元件有:
int* el = (int*) ((char*)mat + row * pitch) + col;
return *el;
的obj_weights陣列具有合適的尺寸,N *的sizeof(int)的。重量數組也是如此,螞蟻* sizeof(float)。所以他們不是越界。
內核之後的內核在開始時有一個printf權限,它不會被打印出來,並且在printf之後,它會在設備內存上設置一個變量,並在內核完成後將該內存複製到CPU ,而當我在CPU代碼中打印它時,這不是正確的值。所以我認爲這個內核做了一些非法的事情,第二個甚至沒有啓動。
我正在測試一些實例,當我啓動8個塊和512個線程時,它運行正常。 32個塊,512個線程,確定。但是8個塊和1024個線程,發生這種情況,內核不能工作,既沒有32塊也沒有1024線程。
我做錯了什麼?內存訪問?我是否啓動了太多線程?
編輯:嘗試刪除「添加」變量和while循環,所以它應該只執行一次。仍然沒有工作,沒有打印,即使printf正好在三個首行後面,下一個內核也不會打印任何東西。
編輯:另一件事,我使用的是GTX 570,因此根據http://en.wikipedia.org/wiki/CUDA,「每塊最大線程數」爲1024。也許我會堅持512最大或檢查我可以把這個價值多高。
好吧,我得到了syncthreads點,完全忘了它。但是關於內存寫入,如果多個線程向相同的地址寫入相同的值,則值將被更新,未知的是它將被更新多少次。採取從這裏:http://stackoverflow.com/questions/5953955/concurrent-writes-in-the-same-global-memory-location – hfingler
Upvoted,因爲我不知道內核啓動返回的錯誤,所以我很接近發現問題。這裏有錯誤捕獲代碼:http://code.google.com/p/stanford-cs193g-sp2010/wiki/TutorialWhenSomethingGoesWrong – hfingler
我不完全確定*(數據 - >添加)測試是做什麼的。但是爲了至少消除競爭條件,在while()之前插入__syncthreads()。由於__syncthreads()每塊同步,這也需要將標誌移回共享內存(不要害怕它 - 如果編程正確,共享內存沒有問題)。 – tera