W CUDA C Best Practices Guide Version 5.0, pkt 6.1.2, jest napisane, że:Wpływ wykorzystania pamięci stronicowanej do kopiowania pamięci asynchronicznej?
W przeciwieństwie cudaMemcpy(), asynchronicznego transferu wersji wymagającej przypięte pamięć hosta (patrz podpięty Memory) oraz zawiera dodatkowy argument o nazwie ID strumienia.
Oznacza to, że funkcja cudaMemcpyAsync
powinna zakończyć się niepowodzeniem, jeśli użyję zwykłej pamięci.
Ale tak się nie stało.
Tylko dla celów testowania, próbowałem następujący program:
jądra:
__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;
}
Program dał poprawny wynik. Tablica inkrementowała się pomyślnie.
Jak wykonać cudaMemcpyAsync
bez pamięci zablokowanej strony? Czy tu czegoś brakuje?
@NolwennLeGuen ... w rzeczywistości było to wymagane od samego początku. Przeczytałem to również w poprzednich przewodnikach CUDA. – sgarizvi
@NolwennLeGuen: To jest absolutnie oczekiwane zachowanie, nie ma żadnych "czarnych skrzynek". Jeśli nie masz nic konstruktywnego do dodania do dyskusji, nie wahaj się w nim uczestniczyć. – talonmies
Dokumentacja dla funkcji stwierdza _ Ta funkcja wykazuje zachowanie asynchroniczne dla większości przypadków użycia.Jeśli używana jest pamięć stronicowana, sterownik musi skopiować pamięć do bufora, który nie jest obsługiwany. Jeśli rozmiar transferu jest większy niż niezadawalający bufor sterownika, sterownik czeka, aż dostępny bufor będzie dostępny do wykonania reszty transferu. –