枚舉設備
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
- 如果輸入事件和輸入流關聯到不同的設備,cudaEventRecord()將失敗。
- 如果兩個輸入事件關聯到不同的設備,cudaEventElapsedTime()將會失敗。
- 即使輸入事件關聯的設備並非當前設備, cudaEventSynchronize() 和cudaEventQuery()也會成功。
- 即使輸入流和輸入事件關聯到不同的設備,cudaStreamWaitEvent()也會成功。
- 因此 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