Я успешно прототипировал приложение, используя потрясающую библиотеку потоковых графов TBB от Intel. Кажется, это работает довольно хорошо, но теперь мне нужно реорганизовать код в готовую к использованию версию.
Раньше я работал с некоторыми более крупными и «слишком развитыми» платформами для этого конкретного домена (работа заключается в обработке изображений, а предыдущие приложения использовали ITK / VTK). Однако для этого приложения я пытаюсь использовать более низкоуровневый и более целенаправленный подход.
В настоящее время я просто собираю весь свой график в main()
что, очевидно, не является устойчивым. Я бы хотел, чтобы конвейер работал итеративно, чтобы я мог получать выходные данные с каждого этапа и отображать их для целей отладки / анализа.
Моя идея до сих пор состоит в том, чтобы абстрагировать каждую логическую «стадию» приложения в класс, который принимает &tbb::flow::graph
в качестве аргумента конструктора и внутренне хранит ссылку на узел графа, которым он управляет. Я могу иметь класс обертки выделить дополнительный tbb::flow::broadcast_node
на выходе и асинхронный узел после этого, чтобы запустить события.
Это разумная концепция дизайна? Вообще говоря, как другие интегрировали концепции потокового графа TBB в структуру своего приложения? Примеры и документация довольно скудны для этой конкретной части библиотеки TBB.
Как и в случае с любым другим дизайном, я не думаю, что существует явно правильный или неправильный способ сделать это. Я не знаю ваш код достаточно хорошо, но разбить код на логические этапы, вероятно, хорошая идея.
Когда дело доходит до фреймворков, таких как TBB, вам необходимо принять решение о том, следует ли скрывать все аспекты фреймворка за интерфейсом. Преимущество состоит в том, что вы можете позже заменить реализацию другой реализацией (например, заменить TBB на OpenMP). С другой стороны, введение дополнительного слоя может не понадобиться во всех случаях. Особенно, если маловероятно, что вы когда-нибудь замените TBB.
Дизайн, который вы описываете в своем вопросе, состоит в том, как структурировать зависимую от фреймворка часть. Это очень сильно зависит от конкретного алгоритма, который вы реализуете. Например, если он состоит из применения отдельных преобразований к одному изображению, хорошим подходом может быть создание одного класса на шаг преобразования.
Кроме того, может иметь смысл обернуть все в функцию или класс. Если выполняемая операция принимает одно изображение в качестве входного и создает одно изображение в качестве выходного, это то, что может быть скрыто за интерфейсом, который скрывает детали реализации (в данном случае TBB).
Других решений пока нет …