在tbb :: concurrent_queue容器中等效于std :: deque?

时间:2013-03-05 17:50:45

标签: c++ multithreading visual-studio-2010 tbb

我在函数中使用std :: deque 来访问元素而不从队列中弹出,因为我在不同的迭代中使用相同的队列。我的解决方案基于粗粒度多线程。现在我想制作细粒度的多线程解决方案。为此,我使用tbb :: concurrent_queue。但是我需要在tbb :: concurrent_queue中运行std :: deque 的等效函数吗?

修改 的 这就是我用std :: deque(粗粒度多线程)实现的方法 请记住,dq是静态队列(即在不同的迭代中多次使用)

vertext_found = true;
std::deque<T> dq;
while ( i < dq->size())
{
    EnterCriticalSection(&h);
    if( i < dq.size() ) 
    {
          v = dq.at(i);      // accessing element of queue without popping
          i++;
          vertext_found = true;
    }
    LeaveCriticalSection(&h);
    if (vertext_found && (i < dq.size()) && v != NULL)
    {
          **operation on 'v'
          vertext_found = false;
    }
}

我想用tbb :: concurrent_queue实现相同的结果?

2 个答案:

答案 0 :(得分:1)

如果您的算法具有填充队列或使用队列的单独传递,请考虑使用tbb :: concurrent_vector。它有一个可用于填充传递的push_back方法,以及用于消耗传递的at()方法。如果线程竞争消费传递中的pop元素,请考虑使用tbb :: atomic计数器为at()生成索引。

如果填充和消费之间没有这种清晰的分离,使用at()可能会产生比它解决的更多问题,即使它存在,因为它会与消费者竞争。

如果消耗传递只需要并行遍历concurrent_vector,请考虑使用tbb :: parallel_for作为循环。 tbb :: concurrent_vector有一个支持这个习语的range()方法。

void consume( tbb::concurrent_vector<T>& vec ) {
    tbb::parallel_for( vec.range(), [&]( const tbb::concurrent_vector<T>::range_type& r ) {
        for( auto i=r.begin(); i!=r.end(); ++i ) {
            T value = *i;
            ...process value...;
        }
    });
}

如果消费传递不能使用tbb:parallel_for,请考虑使用TBB原子计数器来生成索引。将计数器初始化为零并使用++递增计数器。这是一个例子:

tbb::atomic<size_t> head;
tbb::concurrent_vector<T> vec;

bool pop_one( T& result ) { // Try to grab next item from vec
    size_t i = head++;      // Fetch-and-increment must be single atomic operation
    if( i<vec.size() ) {
        result = vec[i];
        return true;
    } else {
        return false;       // Failed
    }
}

通常,此解决方案的可扩展性低于使用tbb :: parallel_for,因为计数器“head”会在内存系统中引入争用点。

答案 1 :(得分:0)

根据TBB站点中的Doxygen文档(TBB Doxy docs),队列中没有操作at。您可以pushtry_pop元素{/ 1}}。

如果您使用的是tbb::strict_ppl::concurrent_queue(早期版本的TBB),则tbb::deprecated::concurrent_queuepush_if_not_full操作可用。

在两个队列中,“多个线程可以同时推送和弹出”,如下面的简要部分所述。