2012-03-21 20 views
6

Mam następujące (fragment) jądra.Alokacja pamięci wewnątrz jądra CUDA

__global__ void plain(int* geneVec, float* probs, int* nComponents, float* randomNumbers,int *nGenes) 
{ 

    int xid = threadIdx.x + (blockDim.x * blockIdx.x); 

    float* currentProbs= (float*)malloc(sizeof(float)*tmp); 

     ..... 
     ..... 

    currentProbs[0] = probs[start]; 
    for (k=1;k<nComponents[0]; k++) 
    { 
     currentProbs[k] = currentProbs[k-1] + prob; 
    } 

     ... 
     ... 
     free(currentProbs); 

} 

Kiedy to statyczne (nawet te same rozmiary) to bardzo szybko, ale kiedy CurrentProbs jest dynamicznie przydzielana (jak wyżej) wydajność jest okropne.

To pytanie powiedział, że mogę robić to wewnątrz jądra: CUDA allocate memory in __device__ function

Oto powiązany pytanie: Efficiency of Malloc function in CUDA

Zastanawiałem się, czy jakieś inne metody rozwiązali ten inny niż ten proponowany w artykule? Wydaje się absurdalne, że nie można zaszczepić/uwolnić wewnątrz jądra bez tego rodzaju kary.

+0

Skąd pochodzi 'tmp' w twoim pseudo-kodzie? – talonmies

+0

Przepraszam - tmp = nComponents [0]; –

+0

Czy jest to stałe w przypadku wywołania jądra? Jeśli tak, to po co w ogóle zajmować się pamięcią dynamiczną? – talonmies

Odpowiedz

7

Myślę, że powodem wprowadzenia malloc() spowalnia kod jest to, że przydziela pamięć w pamięci globalnej. Gdy używasz tablicy o stałym rozmiarze, kompilator prawdopodobnie umieści go w pliku rejestru, który jest znacznie szybszy.

Posiadanie malloc wewnątrz jądra może oznaczać, że próbujesz wykonać zbyt wiele pracy z jednym jądrem. Jeśli każdy wątek przydziela inną ilość pamięci, to każdy wątek uruchamia inną liczbę razy w pętli for, a otrzymujesz dużo rozbieżności osnowy.

Jeśli każdy wątek w warpie wykonuje pętle tyle samo razy, po prostu przydzielaj z góry. Nawet jeśli uruchamiają inną liczbę razy, możesz użyć stałego rozmiaru. Ale zamiast tego, myślę, że powinieneś spojrzeć na to, w jaki sposób możesz zreorganizować swój kod, aby całkowicie usunąć tę pętlę z jądra.

+1

Kompilator nigdy nie przydzieli zmiennych jądra do pamięci współdzielonej, chyba że programista zdefiniuje je za pomocą kwalifikatora '__shared__'. Tylko rejestry lub pamięć lokalna. – talonmies

+0

@talonmies: Dziękuję za wyjaśnienia. Edytowałem odpowiedź. –