2011-02-03 5 views
1

boost::threadpoolboostlinkの正式な部分ではありません)を使用してプログラムの特定の側面を並列化しようとしています。しかし、私はプログラムの停止と点検時に、htopは2つの非アクティブなスレッド(私はスレッドプールにあると思われます)と1つのスレッドが100%で実行されていることを示しています(私の主な実行スレッドと思われます)。ここでboost :: threadをboost :: bindで使用すると、無限ループでプログラムがハングします

は、関連するコードです:

namespace rt { 

class Renderer 
{ 
    public: 
    Renderer(int threads) : tp(threads) {} 

    void render(const Scene&, const Camera&, Image&) const; 

    private: 
    mutable boost::threadpool::pool tp; 
    //int tp; 

    static void render(const Scene&, const Camera&, Image&, int, int); 
    static Color trace_ray(const Ray&, const Scene&, int depth = 0); 
}; 

} // namespace rt
void 
Renderer::render(const Scene& scene, const Camera& cam, Image& image) const 
{ 
    for (int y = 0; y < image.get_height(); ++y) 
     for (int x = 0; x < image.get_width(); ++x) 
      tp.schedule(boost::bind(&Renderer::render, scene, cam, image, x, y)); 

    tp.wait(); 
} 

void 
Renderer::render(const Scene& scene, const Camera& cam, Image& image, int x, int y) 
{ 
    Color c = trace_ray(cam.spawn_ray(x + .25f, y + .25f), scene) 
      + trace_ray(cam.spawn_ray(x + .75f, y + .25f), scene) 
      + trace_ray(cam.spawn_ray(x + .25f, y + .75f), scene) 
      + trace_ray(cam.spawn_ray(x + .75f, y + .75f), scene); 

    image.set_pixel(x, y, c/4.0f); 
}

私は問題が私のboost::bind構築物である疑いがある理由は、私がvoid foobar() {}関数を作成し、boost::threadpool::pool::scheduleにそれを渡したときに、プログラムが取得していないということです無限ループに入ります。私はここで間違って何をしていますか?

+0

問題は、あなたのコードではなく、ブーストバインドまたはスレッドプールであると思いますか?ライブロックが発生するような同期の問題があるようです。 –

+0

これは可能かもしれませんが、 'boost :: threadpool'の代わりに' asio :: io_service'を使うようにコードを書き直しましたが、同じエラーが続く。しかし、私はそれがロックするかもしれない手掛かりがありません。より低い 'render'関数で見ることができるように、すべての関数はいくつかの独立した光線をトレースし、画像内に値を設定します(基本的には大きな配列です)。各スレッドは配列内の異なる要素にしかアクセスせず、書き込みのみを行うので、ライブロックを引き起こす可能性はありません。だから、おそらく 'boost :: bind'を間違って使用していると思います。 – robrene

+0

また、別のこと:スレッドプール内に1つのスレッドしかない場合、スレッドプールはまだハングします。したがって、これは並行性の問題のようには見えません。 – robrene

答えて

1

引数はboost::bindwill be copiedに与えられます。

取りバインド引数は 返された関数オブジェクトによって内部的にコピーされ、保持 です。たとえば、次のコードの :

int i = 5;

bind(f、i、_1); iの値のコピーが関数オブジェクトに格納されます。 boost :: refとboost :: crefを使用して、 コピーではなく、オブジェクトに の参照を格納させることができます。あなたのケースでは

tp.schedule(boost::bind(&Renderer::render, scene, cam, image, x, y)); 

camimagex、およびyからRendered::renderのコピーを送信します。それはあなたの意図ですか?

+0

優れた点は、少なくともシーンとおそらくカメラと画像にもboost :: refを使うべきです。 – AJG85

+0

これはそれでした!画像の参照を送信して、コピーではなく実際の画像オブジェクトにピクセルを設定し、最適化のためにシーンとカムへの参照を設定します。私は、デフォルトのコピーコンストラクタがオブジェクトのいずれかの無限ループに何らかの形で入っていたか、あるいは別の方法で失敗していると推測しています。 – robrene

+0

@robreneは幸運を助けてうれしい! –

1

代わりにboost :: thread_groupを即時スレッドプールとして使用したことはありますか?ここで使用されているwait()の実装は、あなたのスレッドが無期限に非アクティブになっている原因となる障壁を意味します。

編集:

はあなたが無限ループに入ることなく、レンダリングを呼び出すことができますか?おそらく、それは表示されていない光線を追跡したり産んだりしているのです。また、スレッドプールのwait_for_all_tasksに電話したい場合は、その実装に投稿したリンクを簡単に見てください。

+0

私はマルチスレッドを使用せずに、メインの実行スレッド上のすべてを実行するだけで元のポストに追加しておくべきです、うまく動作し、美しい画像が得られます。この問題は私のレンダリングアルゴリズムにはありません。マルチスレッドは、基本的なことが分かっていることを今私が納得させようとしているものです。 – robrene

+0

あなたの関数の実装に応じて、あなたのシーンのような共有オブジェクトへのスレッドアクセスのためにクリティカルセクションを追加する必要があるかもしれません。 – AJG85

関連する問題