In CUDA C Best Practices-Leitfaden Version 5.0, Abschnitt 6.1.2 ist es, dass geschrieben:Auswirkung der Verwendung von seitenfähigem Speicher für die asynchrone Speicherkopie?
Im Gegensatz zu cudaMemcpy(), der asynchronen Transfer Version gepinnt Host-Speicher erfordert (siehe pinned Speicher) und Es enthält ein zusätzliches Argument , eine Stream-ID.
Es bedeutet die cudaMemcpyAsync
Funktion sollte fehlschlagen, wenn ich einfachen Speicher verwende.
Aber das ist nicht, was passiert ist.
Nur für Testzwecke, habe ich versucht, das folgende Programm:
Kernel:
__global__ void kernel_increment(float* src, float* dst, int n)
{
int tid = blockIdx.x * blockDim.x + threadIdx.x;
if(tid<n)
dst[tid] = src[tid] + 1.0f;
}
Main:
int main()
{
float *hPtr1, *hPtr2, *dPtr1, *dPtr2;
const int n = 1000;
size_t bytes = n * sizeof(float);
cudaStream_t str1, str2;
hPtr1 = new float[n];
hPtr2 = new float[n];
for(int i=0; i<n; i++)
hPtr1[i] = static_cast<float>(i);
cudaMalloc<float>(&dPtr1,bytes);
cudaMalloc<float>(&dPtr2,bytes);
dim3 block(16);
dim3 grid((n + block.x - 1)/block.x);
cudaStreamCreate(&str1);
cudaStreamCreate(&str2);
cudaMemcpyAsync(dPtr1,hPtr1,bytes,cudaMemcpyHostToDevice,str1);
kernel_increment<<<grid,block,0,str2>>>(dPtr1,dPtr2,n);
cudaMemcpyAsync(hPtr2,dPtr2,bytes,cudaMemcpyDeviceToHost,str1);
printf("Status: %s\n",cudaGetErrorString(cudaGetLastError()));
cudaDeviceSynchronize();
printf("Status: %s\n",cudaGetErrorString(cudaGetLastError()));
cudaStreamDestroy(str1);
cudaStreamDestroy(str2);
cudaFree(dPtr1);
cudaFree(dPtr2);
for(int i=0; i<n; i++)
std::cout<<hPtr2[i]<<std::endl;
delete[] hPtr1;
delete[] hPtr2;
return 0;
}
Das Programm gab korrekte Ausgabe. Das Array wurde erfolgreich inkrementiert.
Wie wurde cudaMemcpyAsync
ohne Seitensperre ausgeführt? Fehle ich hier etwas?
@NolwennLeGuen ... eigentlich war es von Anfang an eine Anforderung. Ich habe das auch in früheren CUDA-Guides gelesen. – sgarizvi
@NolwennLeGuen: Das ist absolut zu erwarten, kein "Black-Box-Zeug". Wenn Sie nichts konstruktives zur Diskussion hinzufügen möchten, nehmen Sie bitte nicht daran teil. – talonmies
Die Dokumentation für die Funktionszustände _Diese Funktion weist für die meisten Anwendungsfälle ein asynchrones Verhalten auf._.Wenn auslagerbarer Speicher verwendet wird, muss der Treiber den Speicher in einen nicht auslagerbaren Puffer kopieren. Wenn die Übertragungsgröße größer als der nicht auslagerbare Puffer des Treibers ist, wartet der Treiber darauf, dass der nicht auslagerbare Puffer verfügbar ist, um den Rest der Übertragung abzuschließen. –