8

[更新:] 現在、複数のプロセスを生成していますが、基本的なスレッド化の問題はまだ存在しますが、かなりうまく機能しています。[/]

一連の opencl カーネルをコンパイルする c++ (g++ 4.6.1) プログラムをスレッド化しようとしています。かかる時間のほとんどは、clBuildProgram 内で費やされます。(これは遺伝的プログラミングであり、実際にコードを実行して適合性を評価する方がはるかに高速です。) これらのカーネルのコンパイルをスレッド化しようとしていますが、今のところうまくいきません。この時点では、スレッド間で共有されるデータはありません (プラットフォームとデバイスの参照が同じであることを除けば) が、一度に 1 つのスレッドしか実行されません。このコードを複数のプロセス (Linux の異なるターミナル ウィンドウで起動するだけ) として実行すると、複数のコアが使用されますが、1 つのプロセス内では使用されません。基本的な計算だけで、同じ基本的なスレッド コード (std::thread) で複数のコアを使用できるので、これは、opencl コンパイルまたは忘れていた静的データのいずれかと関係があります。:) 何か案は?私はこれをスレッドセーフにするために最善を尽くしたので、困惑しています。

AMD の SDK (opencl 1.1、2010 年 6 月 13 日頃) と 5830 または 5850 を使用して実行しています。SDK と g++ は可能な限り最新ではありません。新しい g++ を入手するために新しい Linux ディストリビューションを最後にインストールしたとき、私のコードは半分の速度で実行されていたので (少なくとも opencl コンパイルはそうでした)、元に戻りました。(そのインストールのコードをチェックしたところ、スレッドの違いはなく、半分の速度で実行されます。)また、一度に1つのスレッドしか実行しないと言ったとき、それらすべてを起動し、終了するまで2つを交互に実行します。そして、コードがプログラムを構築するまで、すべてのスレッドが実行されているように見えます。clBuildProgram でコールバック関数を使用していません。ここでうまくいかないことがたくさんあり、コードなしで言うのは難しいと思います。:)

この問題は、clBuildProgram の内部または呼び出しで発生すると確信しています。ここにかかった時間を出力しています。延期されたスレッドは、最初のコンパイルで長いコンパイル時間で戻ってきます。これらの clBuildProgram 呼び出し間で共有される唯一のデータは、各スレッドの cl_device_id が同じ値を持つデバイス ID です。

これは私がスレッドを起動する方法です:

    for (a = 0; a < num_threads; a++) {
        threads[a] = std::thread(std::ref(programs[a]));        
        threads[a].detach();
        sleep(1);    // giving the opencl init f()s time to complete
    }

これは行き詰まりの場所です(デバイスIDは同じですが、これらはすべてローカル変数が渡されます):

    clBuildProgram(program, 1, & device, options, NULL, NULL);

各スレッドが一意のコンテキストを持っているか、command_queue を持っているかに違いはないようです。私はこれが問題だと本当に思っていたので、それについて言及しました。:)

更新: fork() を使用した子プロセスの生成は、これで機能します。

4

1 に答える 1

2

そのことについて、AMD のサポート フォーラムに投稿することをお勧めします。仕様が要求するスレッドの一貫性に関する多くの失敗した OpenGL 実装を考慮すると、その意味で OpenCL ドライバーがまだ最適ではないことは驚くことではありません。プロセス ID を内部で使用して、代わりにデータを分離することができます。

マルチプロセス生成が機能している場合は、それを保持し、IPC を使用して結果を伝達することをお勧めします。シリアライゼーションを使用する興味深い方法を持つboost::ipcを使用することもできます(たとえば、boost::spiritを使用してデータ構造を反映します)。または、posix パイプまたは共有メモリを使用するか、boost::filesystem およびディレクトリ イテレータを使用して、コンパイル結果をファイルにダンプし、親プロセスからディレクトリをポーリングすることができます...

フォークされたプロセスは、一部のハンドルを継承する場合があります。そのため、名前のないパイプを使用する方法もあると思います。これにより、クライアントパイプをインスタンス化するパイプサーバーを作成する必要がなくなり、広範なプロトコルコーディングにつながる可能性があります。

于 2013-02-02T02:34:23.527 に答える