Блок-схема TBB: как дождаться вывода конкретного токена?

Я пытаюсь написать адаптер для Flow Graph, который имитирует конвейерный синхронный вызов функции. Но я не понимаю, как блокировать и ждать вывода для конкретного токена. призвание wait_for_all на графике не помогает, так как мне не нужно ждать все значения. Кто-нибудь может предложить решение?

template <typename TOutput, typename TInput>
class FlowPathAdapter {
public:
TOutput operator()(const TInput& val) {
m_input->try_put(val);
TOutput result;
// What should be done here to ensure that
// m_output returns the result corresponding to this specific token?
m_output->try_get(result);
return result;
}

private:
// input and output are connected in some graph constructed outside the adapter
std::shared_ptr<tbb::flow::receiver<TInput>> m_input;
std::shared_ptr<tbb::flow::sender<TOutput>> m_output;
};

0

Решение

Класс получателя и отправителя — это «чисто виртуальные» классы (по умолчанию методы try_ * упрощают определение узлов.) Для каждого из узлов flow :: graph они переопределяются поведением, характерным для этого класса.

Если вы хотите создать узел определенного типа (или адаптер), вы должны переопределить виртуальные методы. Однако вы можете использовать function_node, чтобы делать то, что вы пытаетесь сделать с этим адаптером. Вы можете удалить вызовы try_get и try_put (которые являются частью поведения function_node.)

// notice TInput and TOutput are exchanged
template < typename TInput, typename TOutput >
class FlowPathAdapterBody {
public:
TOutput operator()(const TInput& val) {
// val has the value passed to us
TOutput result;
// computation turning val into result
return result;
}
};

tbb::flow::graph g;
// node is fully-parallel in this case
tbb::flow::function_node<int, int> fnode(g, tbb::flow::unlimited, FlowPathAdapterBody<int,int>());

// ...

Вы можете присоединить несколько предшественников к входу function_node и несколько наследников к его выходу.

По умолчанию у function_node есть буфер на входе, поэтому, даже если узел является последовательным, он всегда будет принимать входные данные. Если вы хотите отклонить входные данные, а не буферизовать их, вы можете сделать узел function_node<T,U,tbb::flow::rejecting>.

Если вам нужно более продвинутое поведение (например, возможность отправлять несколько сообщений на вход, или, необязательно, не отправлять сообщения для определенных входов, или сигнализировать о специальных условиях, проверьте значение многофункционального узла. У многофункционального узла может быть только один выход, если это все, что нужно .)

С Уважением,
Крис

0

Другие решения

Ожидания, как правило, избегают в TBB; ожидание непродуктивно.

Время выполнения задачи в TBB также не гарантируется, потому что мы зависим от ОС для планирования. То есть выполнение внеполосной сигнализации, такой как атомарная операция, не будет происходить после пересылки сообщения от узла, поэтому результат не будет готов. Вы также должны использовать queue_node или другой буферный узел для хранения результата.

Учитывая, что, если вы хотите сделать явное ожидание, вы можете сделать function_node он получает окончательный ответ, присваивает его местоположению результата и выдает сигнал о том, что результат готов. (Сигнал должен быть атомарным для обеспечения ограждения.) Ваша другая задача может вращать атомное ожидание. Или вы можете использовать условную переменную.

С Уважением,
Крис

0

По вопросам рекламы [email protected]