Cuda c++ 多設備系統

 枚舉設備

int deviceCount; 
cudaGetDeviceCount(&deviceCount); 
int device; 
for (device = 0; device < deviceCount; ++device) { 
    cudaDeviceProp deviceProp; 
    cudaGetDeviceProperties(&deviceProp, device); 
    printf("Device %d has compute capability %d.%d.\n", device, deviceProp.major, 
    deviceProp.minor);
}

主機線程都可以使用 cudaSetDevice()來設置它操作的設備,默認設備爲 0 號

正確使用方式

cudaSetDevice(0); // Set device 0 as current 
cudaStream_t s0; 
cudaStreamCreate(&s0); // Create stream s0 on device 0 
MyKernel<<<100, 64, 0, s0>>>(); // Launch kernel on device 0 in s0 
cudaSetDevice(1); // Set device 1 as current 
cudaStream_t s1; 
cudaStreamCreate(&s1); // Create stream s1 on device 1 
MyKernel<<<100, 64, 0, s1>>>(); // Launch kernel on device 1 in s1 

錯誤使用方式

// This kernel launch will fail: 
MyKernel<<<100, 64, 0, s0>>>(); // Launch kernel on device 1 in s0
  1. 如果輸入事件和輸入流關聯到不同的設備,cudaEventRecord()將失敗。
  2. 如果兩個輸入事件關聯到不同的設備,cudaEventElapsedTime()將會失敗。
  3. 即使輸入事件關聯的設備並非當前設備, cudaEventSynchronize() cudaEventQuery()也會成功。
  4. 即使輸入流和輸入事件關聯到不同的設備,cudaStreamWaitEvent()也會成功。
  5. 因此 cduaStreamWaitEvent()可用於在不同的設備同步彼此。

 p2p 存儲器訪問

只要兩個設備上的 cudaDeviceCanAccessPeer()返回 true,這種 p2p 的存儲器訪問特性在它們間得到支持。

如下例所示,必須通過調用 cudaDeviceEnablePeerAccess()啓用兩個設備間的p2p 存儲器訪問支持。
 

cudaSetDevice(0); // Set device 0 as current 
float* p0; 
size_t size = 1024 * sizeof(float); 
cudaMalloc(&p0, size); // Allocate memory on device 0 
MyKernel<<<1000, 128>>>(p0); // Launch kernel on device 0 
cudaSetDevice(1); // Set device 1 as current 

//開啓P2P訪問功能
cudaDeviceEnablePeerAccess(0, 0); // Enable peer-to-peer access 
// with device 0 
// Launch kernel on device 1 
// This kernel launch can access memory on device 0 at address p0 

//設備1 可以訪問 設備0 的p0 內存
MyKernel<<<1000, 128>>>(p0);

 p2p 存儲器複製

普 通 的 存 儲 器 拷 貝 函 數 即 可 。 否 則 使 用 cudaMemcpyPeer() 、cudaMemcpyPeerAsync()、cudaMemcpy3Dpeer()或者 cudaMemcpy3DpeerAsync()

cudaSetDevice(0); // Set device 0 as current 
float* p0; 
size_t size = 1024 * sizeof(float); 
cudaMalloc(&p0, size); // Allocate memory on device 0 
cudaSetDevice(1); // Set device 1 as current 
float* p1; 
cudaMalloc(&p1, size); // Allocate memory on device 1 
cudaSetDevice(0); // Set device 0 as current 
MyKernel<<<1000, 128>>>(p0); // Launch kernel on device 0 
cudaSetDevice(1); // Set device 1 as current 
cudaMemcpyPeer(p1, 1, p0, 0, size); // Copy p0 to p1 
MyKernel<<<1000, 128>>>(p1); // Launch kernel on device 1

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章