У меня есть функция, определенная Intel IPP для работы с изображением/областью изображения.
Ввод изображения является указателем на изображение, параметрами для определения размера процесса и параметров фильтра.
Функция IPP однопоточная.Обработка параллельных изображений в OpenMP - Разделение изображения
Теперь у меня есть изображение размера M x N.
Я хочу применить фильтр к нему параллельно.
Основная идея проста, разбить изображение на 4 вспомогательных изображения, которые не зависят друг от друга.
Примените фильтр к каждому вспомогательному изображению и напишите результат на дополнительный блок пустого изображения, где каждый поток записывается в отдельный набор пикселей.
Это действительно похоже на обработку 4 изображений на каждом из них.
Это программа, которую я делаю это с:
void OpenMpTest()
{
const int width = 1920;
const int height = 1080;
Ipp32f input_image[width * height];
Ipp32f output_image[width * height];
IppiSize size = { width, height };
int step = width * sizeof(Ipp32f);
/* Splitting the image */
IppiSize section_size = { width/2, height/2};
Ipp32f* input_upper_left = input_image;
Ipp32f* input_upper_right = input_image + width/2;
Ipp32f* input_lower_left = input_image + (height/2) * width;
Ipp32f* input_lower_right = input_image + (height/2) * width + width/2;
Ipp32f* output_upper_left = input_image;
Ipp32f* output_upper_right = input_image + width/2;
Ipp32f* output_lower_left = input_image + (height/2) * width;
Ipp32f* output_lower_right = input_image + (height/2) * width + width/2;
Ipp32f* input_sections[4] = { input_upper_left, input_upper_right, input_lower_left, input_lower_right };
Ipp32f* output_sections[4] = { output_upper_left, output_upper_right, output_lower_left, output_lower_right };
/* Filter Params */
Ipp32f pKernel[7] = { 1, 2, 3, 4, 3, 2, 1 };
omp_set_num_threads(4);
#pragma omp parallel for
for (int i = 0; i < 4; i++)
ippiFilterRow_32f_C1R(
input_sections[i], step,
output_sections[i], step,
section_size, pKernel, 7, 3);
}
Теперь вопросы, я не вижу никакого выигрыша по сравнению работает режим однотридовой на все изображение.
Я попытался изменить размер изображения или размер фильтра, и ничто не изменит изображение.
Больше всего я мог бы получить ничего значимого (10-20%).
Я думал, что это может иметь какое-то отношение к тому, что я не могу «обещать» каждому потоку зону, которую он получил, «Только для чтения».
Более того, чтобы сообщить, что место памяти, на которое он пишет, также принадлежит только самому себе.
Я читал об определении переменных как private и share, но я не мог найти руководство по работе с массивами и указателями.
Что было бы правильным способом справиться с указателями и вспомогательными массивами в OpenMP?
Вы работаете с границей пропускной способности и поэтому не можете масштабироваться с количеством физических ядер (если ваш фильтр намного больше). Однако я ожидал бы улучшения более чем на 10-20%. Обычно я не распараллеливаю цикл, основанный на количестве потоков. Я бы сделал это для количества пикселей или чего-то еще. –
Как я могу доказать себе, что эта проблема ограничена памятью? – Royi
Для этого вам, вероятно, нужно использовать некоторый инструмент для профилирования. Но это не то, что я делаю. Я определяю FLOPS операции и сравниваю ее с пиковыми FLOPS процессора. Я также определяю, сколько пропускной способности используется в этой операции (вы также можете рассчитать это) и сравнить это с максимальной пропускной способностью процессора. Если операция намного меньше пиковой FLOPS и связана полосой пропускания, то это ограничение полосы пропускания памяти. –