Итак, мне дана программа на с ++, и я должен распараллелить ее с помощью TBB (сделать ее быстрее). Когда я изучал код, я подумал, что использование конвейера имело бы смысл. Проблема в том, что у меня мало опыта, и то, что я нашел в Интернете, смутило меня еще больше. Вот основная часть кода:
uint64_t cbRaw=uint64_t(w)*h*bits/8;
std::vector<uint64_t> raw(cbRaw/8);
std::vector<uint32_t> pixels(w*h);
while(1){
if(!read_blob(STDIN_FILENO, cbRaw, &raw[0]))
break; // No more images
unpack_blob(w, h, bits, &raw[0], &pixels[0]);
process(levels, w, h, bits, pixels);
//invert(levels, w, h, bits, pixels);
pack_blob(w, h, bits, &pixels[0], &raw[0]);
write_blob(STDOUT_FILENO, cbRaw, &raw[0]);
}
Он фактически читает видеофайл, распаковывает его, применяет преобразование, упаковывает его, а затем записывает его в вывод. Это кажется довольно простым, поэтому, если у вас есть какие-либо идеи или ресурсы, которые могут быть полезны, пожалуйста, поделитесь.
Спасибо заранее,
Д. Христос
На самом деле вы можете использовать tbb::parallel_pipeline
обрабатывать несколько видео «капель» параллельно.
Базовая схема представляет собой трехэтапный конвейер: входной фильтр считывает большой двоичный объект, средний фильтр обрабатывает его, а последний записывает обработанный большой двоичный объект в файл. Фильтры ввода и вывода должны быть serial_in_order
и средний фильтр может быть parallel
, Распаковка и упаковка, по-видимому, могут быть выполнены либо на средней стадии (я бы начал с этого, чтобы минимизировать объем работы на последовательных этапах), либо на входе & выходные каскады (но это может быть медленнее).
Вам также необходимо убедиться, что хранилище данных (raw
а также pixels
в вашем случае) не распределяется между одновременно обработанными BLOB-объектами. Возможно, самый простой способ — создать хранилище для каждого блоба, которое передается по конвейеру. В отличие от последовательной программы, будет невозможно использовать автоматические переменные для хранилища, которое необходимо передавать между этапами конвейера; Таким образом, вам нужно будет выделить ваше хранилище с new
во входном фильтре передайте его по ссылке (или через указатель) через конвейер, а затем delete
после того, как вся обработка сделана в выходном фильтре. Это, безусловно, необходимо для raw
место хранения. За pixels
однако вы можете продолжать использовать автоматическую переменную, если все операции, которые в ней нуждаются, то есть распаковка, обработка и упаковка результата, выполняются в теле среднего фильтра. Конечно, объявление переменной должно также перемещаться туда.
Позвольте мне набросать модификацию вашего серийного кода, чтобы сделать его более готовым к применению parallel_pipeline. Обратите внимание, что я изменился raw
быть динамически распределенным массивом, а не std::vector
; код, который вы показали, по-видимому, в любом случае не использовал его как вектор. Имейте в виду, что это всего лишь эскиз, и он может не работать как есть.
uint64_t cbRaw=uint64_t(w)*h*bits/8;
uint64_t * raw; // now a pointer to a dynamically allocated array
while(1){
{ // The input stage
raw = new uint64_t[cbRaw/8];
if(!read_blob(STDIN_FILENO, cbRaw, raw)) {
delete[] raw;
break; // No more images
}
}
{ // The second stage
std::vector<uint32_t> pixels(w*h);
unpack_blob(w, h, bits, raw, &pixels[0]);
process(levels, w, h, bits, pixels);
//invert(levels, w, h, bits, pixels);
pack_blob(w, h, bits, &pixels[0], raw);
}
{ // The output stage
write_blob(STDOUT_FILENO, cbRaw, raw);
delete[] raw;
}
}
Есть учебник на трубопроводе в документации TBB. Попробуйте сопоставить ваш код с примером там; это должно быть довольно легко сделать. Вы также можете обратиться за помощью в форум TBB.
Других решений пока нет …