1

以下の問題は、nvidia の新しいドライバー リリース 331.xx で修正されており、現在ベータ ドライバーとして利用できます。

コメントありがとうございます!

OpenGL テクスチャで多くのフラグメント操作と gpgpu を実行するマルチプラットフォーム アプリケーションがあります。アプリケーションは GL/CL 相互運用機能を多用し、各テクスチャは OpenCL イメージにバインドされ、CL カーネルを使用して操作されます。

問題は、アプリケーションが Linux と Windows の両方の AMD カードで高速に動作することです。NVIDIA カードでは、Linux では高速に動作しますが、Windows 7 では非常に遅くなります。問題は enqueueAcquireGLObjects と enqueueReleaseGLObjects のようです。最小限のサンプルを作成し、単純にパフォーマンスの低下を示しました。

  1. 2 つの OpenGL テクスチャの作成 (1600x1200 ピクセル、RGBA float)
  2. 2 つの OpenCL イメージを作成し、2 つのテクスチャを共有する
  3. 繰り返し (50 回) 取得、解放、終了

結果(取得、解放、終了の平均実行時間)

  • AMD HD 6980、Linux: <0.1 ミリ秒
  • AMD HD 6980、Win7: <0.1 ミリ秒
  • NVIDIA GTX590、Linux: <0.1 ミリ秒
  • NVIDIA GTX590、Win7 : 16.0 ミリ秒

古い295.73から現在のベータドライバー326.80まで、nvidiaのいくつかの異なるドライバーを試しましたが、すべて同じ動作を示しました。

私の質問は、nvidiaドライバーが深刻に壊れているのか、それともここで何か間違ったことをしているのですか? コードは Linux で高速に実行されるため、OpenCL の nvidia サポートに関する一般的な問題にはなりません。コードは AMD+Win で高速に実行されるため、コードが Windows 用に最適化されていなくても問題ありません。たとえば、cl イメージを読み取り/書き込み専用に変更してコードを最適化することは無意味です。パフォーマンスへの影響はほぼ 30 倍になるからです。

以下に、私のテスト ケースの関連コードを示します。完全なソース コードも提供できます。

コンテキスト作成に関連するコード

{ // initialize GLEW
  glewInit();
}

{ // initialize CL Context, sharing GL Contet
  std::vector<cl::Platform> platforms;
  cl::Platform::get(&platforms);
  cl_context_properties cps[] = {
             CL_GL_CONTEXT_KHR,(cl_context_properties)wglGetCurrentContext(),
             CL_WGL_HDC_KHR,(cl_context_properties)wglGetCurrentDC(),
             CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0]()),
             0};
  std::vector<cl::Device> devices;
  platforms[0].getDevices((cl_device_type)CL_DEVICE_TYPE_GPU, &devices);
  context_ = new cl::Context(devices, cps, NULL, this);
  queue_ = new cl::CommandQueue(*context_, devices[0]);
}

テクスチャを作成し、CL イメージを共有するための関連コード

width_ = 1600;
height_ = 1200;

float *data = new float[ 1600*1200*4 ];

textures_.resize(2);
glGenTextures(2, textures_.data());

for (int i=0;i<2;i++) {
  glBindTexture(GL_TEXTURE_2D, textures_[i]);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  // "data" pointer holds random/uninitialized data, do not care in this example
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, width_,height_, 0, GL_RGBA, GL_FLOAT, data);
}

delete data;
{ // create shared CL Images
#ifdef CL_VERSION_1_2
  clImages_.push_back(cl::ImageGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[0]));
  clImages_.push_back(cl::ImageGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[1]));
#else
  clImages_.push_back(cl::Image2DGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[0]));
  clImages_.push_back(cl::Image2DGL(*context_, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, textures_[1]));
#endif
}

1 つの取得、リリース、終了サイクルに関連するコード

try {
  queue_->enqueueAcquireGLObjects( &clImages_ );
  queue_->enqueueReleaseGLObjects( &clImages_ );
  queue_->finish();
} catch (cl::Error &e) {
  std::cout << e.what() << std::endl;
}
4

1 に答える 1

1

OpenGL を使用しているため、OCL の計算後に画面に何かを表示すると仮定します。

したがって、その仮定に基づいて、最初に考えたのは、VSync が有効になっているかどうかを NVIDIA コントロール パネルで確認し、有効になっている場合は無効にして再テストすることです。

私が思い出す限り、vsync に関するデフォルトのオプションは AMD と NVIDIA で異なります。これにより、2 つの GPU の違いが説明されます。

念のため、vsync がどのようにレンダリングを遅くするかを説明する投稿を次に示します。

于 2013-08-29T11:51:34.693 に答える