0

GTX690(デュアルチップ)ボードで同じカーネルを実行する必要があるコードを書いています。計算はかなり分離可能であるため、デバイス間のデータ交換は必要ありません。結果をCPUにマージするだけです。各デバイスでコードを実行する方法と、各デバイスのメモリスペースにI/Oデータスペースを提供する方法を理解しています。

両方のデバイスで実行されているカーネルが使用する定数を設定しようとすると、問題が発生します。デバイスごとにアレイを作成する必要がありますか?もしそうなら、カーネル内でどのデバイスが実行されているかを確認して、配列から適切な定数にアクセスできるようにするにはどうすればよいですか?

これが私が使っているコードです。(設定により)1つのチップのみを使用する場合は正しく機能しますnumDev = 1が、両方では機能しません。

__constant__ float d_cellSizeZ;  
std::vector<int*> d_cell;  
.................  
bool Init(int cellsN_, float size_){  
  bool res = true;
  if(cudaSuccess != cudaGetDeviceCount(&numDev))  
    return false;  
  //numDev = 1;  
  d_cl.resize(numDev);  
  for(int i = 0; i < numDev; ++i){  
    res &= (cudaSuccess == cudaSetDevice(i));  
    if(!res)  
      break;  
    res &= (cudaSuccess == cudaMalloc((void**)&d_cell[i], cellsN_*sizef(int)));  
  };  
  res &= (cudaSuccess == cudaMemcpyToSymbol(d_cellSizeZ, &size_, sizeof(float)));  
  if(!res)  
    Cleanup();  
  return res;  
}

カーネルでは、d_cellSizeZ定数を使用します。では、同じカーネルから各デバイスを適切に使用するために、どのように定数を作成する必要がありますか?

もう1つの質問は、デバイス間でデータを交換しようとすると、PCIバスを通過するのでしょうか、それともデュアルチップボードに内部パスが存在するのでしょうか。

4

1 に答える 1

2

最後のデバイスでのみ初期化d_cellSizeZするため、他のデバイスでは未定義になります。各デバイスで初期化する必要がありd_cellSizeZます。最も簡単な方法は、Gregがコメントで提案したように、ループ内で初期化することです。

for(int i = 0; i < numDev; ++i)
{  
    checkCudaErrors(cudaSetDevice(i));
    checkCudaErrors(cudaMalloc((void**)&d_cell[i], cellsN_*sizef(int)));
    checkCudaErrors(cudaMemcpyToSymbol(d_cellSizeZ, &size_, sizeof(float)));
};

d_cellSizeZシンボルの再利用に関しては少し奇妙になります。舞台裏では少し巧妙なことが行われていますが、基本的にこのcudaMemcpyToSymbol()関数は現在アクティブなデバイス上のシンボルを検索するため、毎回正しいデバイスにコピーされます。

于 2012-09-10T16:25:29.737 に答える