Я могу использовать Устройство Вареного пудинга на массиве в C?

У меня есть цикл здесь, и я хочу заставить его работать быстрее. Я являюсь передающим в большом массиве. Я недавно услышал об Устройстве Вареного пудинга, оно может быть применено к этому для цикла? какие-либо идеи?

for (i = 0; i < dim; i++) {
    for (j = 0; j < dim; j++) {
        dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
    }
}
5
задан Lazer 28 August 2010 в 12:15
поделиться

11 ответов

Пожалуйста, пожалуйста, не используйте устройство Даффа. Тысяча программистов, занимающихся техническим обслуживанием, скажут вам спасибо. Я работал в тренинговой компании, где кто-то посчитал забавным ввести это устройство на первых десяти страницах курса программирования на языке Си. Как преподаватель, с этим было невозможно иметь дело, если только (как, очевидно, и парень, написавший этот фрагмент курса) вы не верите в "крутое" кодирование.

Нет нужды говорить, что я попросил вычеркнуть это из курса как можно скорее.

19
ответ дан 18 December 2019 в 05:28
поделиться

Если бы вы смогли это выяснить и получить выгоду, это было бы гроши и никоим образом не оправдало бы сложности.

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

Или, может быть, есть какой-то совершенно другой подход - взгляните на свою проблему целиком и попробуйте полностью отбросить свои текущие подходы и концепции и просто посмотрите, есть ли что-то, что вы не рассмотрели, потому что слишком привязаны к этой реализации.

Может ли ваша видеокарта выполнить часть этой работы?

Переосмысление проблемы на высоком уровне работает гораздо чаще, чем вы думаете.

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

Или я мог ошибиться, но есть вероятность, что просмотр в масштабе больше, чем пиксель в пиксель, может помочь вам гораздо больше, чем разворачивание циклов.

2
ответ дан 18 December 2019 в 05:28
поделиться

Я считаю, что это кандидат на устройство Даффа, в зависимости от того, что делает функция RIDX (). Но я надеюсь, вы не ожидаете, что кто-то напишет код за вас ... Кроме того, вы можете правильно отформатировать свой код, чтобы он действительно читался.

1
ответ дан 18 December 2019 в 05:28
поделиться

Педантично, нет. Устройство Даффа предназначалось для записи в аппаратный регистр (таким образом, целью копии всегда был один и тот же адрес).

Вы можете реализовать что-то очень похожее на Устройство Даффа для подобной копии, но это потребует ясности и затрат на обслуживание. Я сначала профайл, чтобы убедиться, что это проблема. Я бы также посмотрел, можете ли вы упростить индексацию, поскольку это может позволить компилятору выполнять грязную работу по развертыванию цикла.

0
ответ дан 18 December 2019 в 05:28
поделиться

Если вы его используете, убедитесь, что вы измерили его, чтобы определить, является ли улучшение реальным, значительным и необходимым с точки зрения ваших требований к производительности. Сомневаюсь, что так и будет.

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

Все время, которое вы, вероятно, сэкономите на этом (если оно есть), вы, вероятно, несколько раз потратили зря, читая ответы на этот вопрос.

0
ответ дан 18 December 2019 в 05:28
поделиться

Почему вы хотите, чтобы он работал быстрее?

Есть ли реальная проблема с производительностью?

Если да, то провели ли вы профилирование и обнаружили, что это выполняется достаточно часто и, следовательно, стоит оптимизировать?

Если так, вы можете написать его двумя способами: простым способом, который у вас есть сейчас, и с помощью устройства Даффа, или любым другим способом, который вам нравится.

На этом этапе вы проверяете производительность. Вы можете быть удивлены. Современные оптимизаторы довольно хороши, а современные процессоры действительно сложны, поэтому оптимизация на уровне исходного кода часто бывает контрпродуктивной. (Однажды я проделал это в цикле, который занимал много времени, и обнаружил, что сжатие цикла, даже при введении некоторой косвенности, улучшило производительность. Ваш пробег почти наверняка будет меняться.)

Наконец, если Устройство Даффа действительно быстрее, вам нужно решить, стоит ли улучшение производительности взять этот простой и оптимизируемый код и заменить проблему обслуживания, которая может вообще не улучшить производительность в следующей версии компилятора.

5
ответ дан 18 December 2019 в 05:28
поделиться

Число циклов инструкций для реализации оператора

dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];

намного перевесит накладные расходы на цикл, поэтому разворачивание цикла вряд ли поможет в процентном отношении.

2
ответ дан 18 December 2019 в 05:28
поделиться

Вероятно, пока dim имеет степень двойки или у вас есть быстрый модуль в вашей целевой системе. Узнал что-то новое сегодня. Я независимо обнаружил эту конструкцию 5 лет назад и поместил ее в нашу процедуру memCopy (). Кто знал :)

1
ответ дан 18 December 2019 в 05:28
поделиться

Устройство Даффа - это просто метод для разворачивания цикла. А поскольку любой цикл можно развернуть, вы можете использовать Duff's Device.

2
ответ дан 18 December 2019 в 05:28
поделиться

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

Если вы хотите, чтобы цикл работал быстро, вы должны убедиться, что все, что вычисляет RIDX, dst обращается последовательно, чтобы минимизировать количество промахов кэша. В остальном я не вижу, как можно сделать цикл быстрее.

3
ответ дан 18 December 2019 в 05:28
поделиться

Устройство Даффа может не быть оптимизированным решением в несвернутом цикле.

У меня была функция, которая посылала бит в порт, а затем тактовый импульс в другой порт. Для каждого бита функции были:

  if (bit == 1)
  {
     write to the set port.
  }
  else
  {
     write to the clear port.
  }
  write high clock bit.
  write low clock bit.

Это было помещено в цикл устройства Даффа, вместе со сдвигом битов и инкрементированием счета битов.

Я повысил эффективность цикла, используя значения полубайтов вместо битов (полубайт равен 4 битам). Оператор switch основывался на значении полубайта. Это позволило обрабатывать 4 бита без каких-либо if операторов, улучшая поток через кэш инструкций (конвейер).

Бывают случаи, когда устройство Даффа не может быть оптимальным решением, но может стать основой для более эффективного решения.

0
ответ дан 18 December 2019 в 05:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: