0

太字の短い説明。

次のように要約できる tbb::task があります。

class UpdateTask
: public tbb::task
{
public:
    tbb::task* execute()
    {
        // some work...

        if( can_continue() )
        {
            // make sure this is re-executed
            this->recycle_to_reexecute(); //looks like it is deprecated but it's more clear to me
                            return nullptr; // ? or this? or tbb::empty_task?

        }

        return nullptr;

    }

};

条件が満たされるまで、このタスクが終了したらすぐに再スケジュールされます。 このタスクを次のように割り当てています。

UpdateTask& updater = *new(tbb::task::allocate_root()) UpdateTask();

ただし、それが問題に関連しているかどうかはわかりません。

問題: コードを実行すると、tbb (最終リビジョン、4.1.5) から (デバッグで) アサーションが表示され、それを正しく動作させる方法が見つかりません。

ドキュメントを読み直しましたが、これの簡単な例を見つけることができず、何が間違っているのかはっきりしません。私はいくつかの実験をしました:

  • 今示したコードでは、アサーションはタスクを返す必要があることを示しています。 Assertion t_next failed on line 485 of file ...\itbb\src\tbb\custom_scheduler.h Detailed description: reexecution requires that method execute() return another task
  • 次に、これを返すと、アサーションはタスクを割り当てる必要があることを示しています。 Assertion t_next->state()==task::allocated failed on line 452 of file ...\itbb\src\tbb\custom_scheduler.h Detailed description: if task::execute() returns task, it must be marked as allo cated
  • 疑問に思って、その場で作成した (チェックするために) tbb::empty_task を返そうとしましたnew(tbb::task::allocate_child()) tbb::empty_task()。このメッセージでアサーションを取得しましたAssertion p.ref_count==0 failed on line 107 of file ...\itbb\src\tbb\custom_scheduler.h Detailed description: completion of task caused predecessor's reference count to underflow

それで、それを行う方法は?私はそれが簡単だと思いますが、それが行われる方法を見つけることができません。タスク参照カウントに関連していますか?


更新:これは私が持っているものの良い近似である完全なコードです:

#include <iostream>
#include <atomic>

#include <tbb/tbb.h>

namespace test {    class UpdateTask        : public tbb::task  {   public:

        UpdateTask()        {           std::cout << "[UpdateTask]" << std::endl;       }

        ~UpdateTask()       {           std::cout << "\n[/UpdateTask]" << std::endl;        }

        tbb::task* execute()        {           std::cout << "Tick "<< m_count <<std::endl;

            ++m_count;

            // make sure this is re-executed            this->recycle_to_reexecute();           //return new(tbb::task::allocate_continuation()) tbb::empty_task();             return nullptr;         }

    private:

        std::atomic<int> m_count;

    };


    tbb::task_list m_task_list;


    void register_update_task()     {       UpdateTask& updater =
*new(tbb::task::allocate_root()) UpdateTask();      m_task_list.push_back( updater );   }

    void run_and_wait()     {       tbb::task::spawn_root_and_wait( m_task_list );  }

    void tbb_test()     {       register_update_task();         run_and_wait();

    }

}

int main()
{

    test::tbb_test();

    std::cout << "\nEND";
    std::cin.ignore();

    return 0;
}

ここで、タスクを返す必要があるという最初の例外が発生しました。関数では、リターンをコメントされたものに置き換えると、execute()機能しているように見えますが、これには2つの問題があります。

  • execute の呼び出しが行われるたびに empty_task タスクを作成する必要がありますか???
  • execute() への最初の呼び出しの後、メイン スレッドが再開されます。これは、spawn_root_and_wait() が行うべきことではありません。すべてのタスクが終了せず、正しく再スケジュールされた後。

これも正しい方法ではないと結論付けなければなりません。

4

1 に答える 1

3

this->recycle_to_reexecute();

廃止されました。

で置き換えます:

this->increment_ref_count();
this->recycle_as_safe_continuation();

楽しみ

PS:コースの終わり(あなたの場合)は execute から NULL を返します

于 2012-08-07T15:38:44.480 に答える