Эргономичное разделение петельC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Эргономичное разделение петель

Сообщение Anonymous »

Я ищу более эргономичный способ разделения цикла в C++.

Мотивирующий пример

Представьте, что мы хотим размыть все строки изображения путем свертки каждой строки с помощью хорошо известного ядра фильтра {1, 4, 6, 4, 1. Первые и последние два пикселя каждой строки должны обрабатываться отдельно, поскольку в противном случае мы получили бы доступ к пикселям, выходящим за пределы поля. Вот диаграмма:
Изображение

К сожалению, эти граничные проверки препятствуют оптимизации компилятора, поэтому вместо написания одного цикла с граничными проверками (см. Blur_rows1 ниже для справки), нам приходится разделить цикл на три отдельных цикла (см. функцию Blur_rows2):
  • один цикл над первыми двумя пикселями,
  • один цикл над средними пикселями который выполняет большую часть работы и не требует каких-либо проверок границ, и
  • один цикл по последним двум пикселям:
// Blur row with loop splitting.
for (int x = 0; x < radius; x++) blur(dst, src, nx, ny, x, y, kernel, radius);
for (int x = radius; x < nx - radius; x++) blur(dst, src, nx, ny, x, y, kernel, radius);
for (int x = nx - radius; x < nx ; x++) blur(dst, src, nx, ny, x, y, kernel, radius);

Это делает Blur_rows2 примерно в 10 раз быстрее, чем Blur_rows1 (50 мкс против 500 мкс для изображения 512x512).

Ошибочные решения

Существует несколько способов реализации разделения цикла, каждый из которых имеет различные недостатки:
  • Реализация внутреннего -большинство тело цикла как функцию, как показано ниже. Недостатки:
    • Невозможно прочитать код сверху вниз, поскольку внутренний цикл реализован как функция где-то в другом месте (плохая локальность кода).
      < li>Безумно большие списки параметров.
    • Встраивает функцию в компилятор (например, __attribute__((always_inline)) с помощью GCC)
    • Опирается на компилятору, чтобы распознать, что граничные проверки могут быть удалены в среднем цикле.
  • Реализуйте самое внутреннее тело цикла как макрос.
    • Также страдает от недостаточной локальности кода.
    • Также приходится полагаться на оптимизацию компилятора.
      < li>Необходимо добавлять \ после каждой строки.
    • обычные недостатки макросов (ошибки компилятора становятся непонятными, код становится сложнее читать и труднее рассуждать).
  • Дополните src значениями заполнения границ, чтобы проверка границ не требовалась.
    • Повышает требования к памяти.
    • Повышает затраты на пропускную способность памяти. .
  • https://github.com/halide/Halide
    • Сложно учиться.
    • Редко компилируется.

Вопрос

Было бы неплохо, если бы компилятор поддерживал что-то вроде разделения цикла #pragma. (0, radius, nx - radius, nx) или, что еще лучше, какой-то способ сообщить компилятору, что он должен разбить цикл так, чтобы выполнялось условие if (0

Подробнее здесь: https://stackoverflow.com/questions/793 ... -splitting
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»