1

函数中使用 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 达到同样的结果吗?

4

2 回答 2

1

如果您的算法具有填充队列或消耗队列的单独通道,请考虑使用 tbb::concurrent_vector。它有一个可用于填充通道的 push_back 方法和一个用于消耗通道的 at() 方法。如果线程争用消费过程中的弹出元素,请考虑使用 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,因为计数器“头”在内存系统中引入了一个争用点。

于 2013-03-05T22:32:10.110 回答
0

According to the Doxygen docs in the TBB site (TBB Doxy docs) there's no operation at in the queue. You can push and try_pop elements with a tbb::strict_ppl::concurrent_queue.

If you're using a tbb::deprecated::concurrent_queue (older versions of TBB), there are available the push_if_not_full and pop_if_present operations.

In both queues, "multiple threads may each push and pop concurrently" as stated down in the brief section.

于 2013-03-05T17:58:14.233 回答