In Guida CUDA C Best Practices versione 5.0, sezione 6.1.2, è scritto che:Effetto dell'utilizzo di una memoria in grado di gestire la copia asincrona della memoria?
In contrasto con cudaMemcpy(), la versione di trasferimento asincrono richiede memoria host appuntato (consultare Memoria Appuntato), e contiene un argomento aggiuntivo , un ID di flusso.
Significa che la funzione cudaMemcpyAsync
non dovrebbe funzionare se utilizzo una memoria semplice.
Ma questo non è quello che è successo.
solo a scopo di test, ho provato il seguente programma:
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;
}
principale:
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;
}
Il programma ha dato uscita corretta. L'array è stato incrementato correttamente.
In che modo cudaMemcpyAsync
è stato eseguito senza memoria di blocco pagina? Mi manca qualcosa qui?
@NolwennLeGuen ... in realtà è stato un requisito sin dall'inizio. Ho letto questo anche nelle precedenti guide CUDA. – sgarizvi
@NolwennLeGuen: Questo è un comportamento assolutamente previsto, nessuna "roba da scatola nera" coinvolta. Se non hai nulla di costruttivo da aggiungere alla discussione, non esitare a partecipare. – talonmies
La documentazione per la funzione indica _Questa funzione mostra un comportamento asincrono per la maggior parte dei casi d'uso.Se viene utilizzata memoria paginabile, il driver deve copiare la memoria su un buffer non modificabile. Se la dimensione del trasferimento è maggiore del buffer non pagabile del driver, il driver attende che il buffer non pagabile sia disponibile per completare il resto del trasferimento. –