Когда цикл раскручивается эффективный?

Если у вас есть только одна строка на дату, то это может быть самый быстрый подход:

SELECT g.table_name,
       SUM(CASE WHEN DATE(g.timestamp) = '2019-03-02'
                THEN g.rows 
                WHEN DATE(g.timestamp) = '2019-03-01'
                THEN -g.rows
                ELSE 0
           END) as diff
FROM dbadmin.table_growth g
WHERE g.timestamp >= '2019-03-01' AND
      g.timestamp < '2019-03-03'
GROUP BY g.table_name;

В частности, это может использовать индекс на table_growth(timestamp, table_name, rows).

12
задан andreas buykx 10 October 2008 в 11:13
поделиться

9 ответов

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

существуют пути выполнения кода, которые извлекают выгоду при разворачивании для Pentium-M вводят ЦП, но не извлекают выгоду для Core2, например. Если я разворачиваю вручную компилятор, не может больше принимать решение, и я могу закончить с меньше, чем оптимальным кодом. Например, точно противоположное я пытался достигнуть.

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

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

32
ответ дан 2 December 2019 в 02:57
поделиться

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

14
ответ дан 2 December 2019 в 02:57
поделиться

По моему опыту, раскручивание цикла и работа это взятия эффективно когда:

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

, Частичное раскручивание часто является меньшим количеством работы для 80% усиления. Таким образом вместо цикличного выполнения по всем пикселям изображения N на М (N повторения М), где N является всегда делимым 8, цикл (NM/8) времена по каждому блоку восьми пикселей. Это особенно эффективно, если Вы выполняете некоторую операцию, которая использует некоторые соседние пиксели.

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

И между прочим, для большей части (beautiful|remarkable) примера выезда раскручивания цикла устройство Вареных пудингов

7
ответ дан 2 December 2019 в 02:57
поделиться

Важная вещь рассмотреть: В производственном коде на Вашем рабочем месте будущая удобочитаемость Вашего кода явно перевешивает преимущества раскручивания цикла. Аппаратные средства являются дешевыми, время программиста не. Я только волновался бы о раскручивании цикла, если это - ЕДИНСТВЕННЫЙ способ решить доказанную проблему производительности (скажите в маломощном устройстве).

Другие мысли: характеристики компиляторов варьируются значительно, и в некоторых случаях, как Java, определение сделано на лету HotspotJVM, таким образом, там я привел бы доводы против цикла, раскручивающегося в любом случае.

4
ответ дан 2 December 2019 в 02:57
поделиться

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

0
ответ дан 2 December 2019 в 02:57
поделиться

Ручное раскручивание цикла в целом полезно только для очень большинства тривиальных циклов.

Как ориентир, библиотека стандарта C++ в g ++ разворачивает точно два цикла в целом источнике, которые реализуют функцию 'находки' с и без предиката, которые похожи:

while(first != last && !(*first == val))
  ++first;

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

, Конечно, лучший ответ должен только развернуть те циклы, где Ваш профилировщик показывает, что полезно сделать так!

0
ответ дан 2 December 2019 в 02:57
поделиться

В основном успокойтесь, полезная стоимость циклической структуры, значительная часть тела цикла. Структура большинства циклов (и примерно всех циклов, которые могут быть развернуты), состоит из (a) постепенного увеличения целого числа, (b) сравнения его к другому целому числу и (c) перехода - два из которых являются примерно самыми быстрыми инструкциями для ЦП. Следовательно, почти в любом цикле, тело взвесит структуру, приводя к незначительному усилению. Если у Вас будет даже один вызов функции в Вашем теле, то тело будет порядком величины медленнее, чем структура - Вы никогда не замечали бы это.

В значительной степени единственная вещь, которая может действительно извлечь выгоду из разворачивания, является чем-то как memcpy (), куда тело цикла просто перемещает байт от пятна до другого---, который является почему много C & компиляторы C++ автоматически встраивали и разворачивали memcpy в течение прошлого десятилетия.

1
ответ дан 2 December 2019 в 02:57
поделиться

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

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

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

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

Пример:

for(int i=0; i<256; i++)
{
    a+=(ptr + i) << 8;
    a-=(ptr + i - k) << 8;
    // And possibly some more
}

Может развернуть к:

#define UNROLL (i) \
    a+=(ptr[i]) << 8; \
    a-=(ptr[i-k]) << 8;


for(int i=0; i<32; i++)
{
    UNROLL(i);
    UNROLL(i+1);
    UNROLL(i+2);
    UNROLL(i+3);
    UNROLL(i+4);
    UNROLL(i+5);
    UNROLL(i+6);
    UNROLL(i+7);
}

На несвязанной ноте, но все еще несколько связанный, если Вы действительно хотите победить на стороне количества инструкции, удостоверяются, что все константы объединены в настолько меньше immediates насколько возможно в Вашем коде так, чтобы Вы не заканчивали со следующим блоком:

// Bad
MOV r1, 4
//  ...
ADD r2, r2, 1
//  ...
ADD r2, r2, 4

Вместо:

// Better
ADD r2, r2, 8

Обычно, серьезные компиляторы защищают Вас от такого рода вещей, но не все будет. Сохраните те '#define', 'перечисление' и 'статическая константа', удобная, не, все компиляторы оптимизируют локальные переменные 'константы'.

1
ответ дан 2 December 2019 в 02:57
поделиться

Эта оптимизация очень зависит от CPU, на котором код выполнен и должен быть сделан компилятором, но если Вы пишете такой компилятор, можно хотеть взглянуть на документ Intel Intel(R) 64 и Раздел Справочника Оптимизации Архитектуры IA-32 3.4.1.7:

  • Разворачивают маленькие циклы до издержек ответвления и учетных записей индукционной переменной (обычно) меньше 10% времени выполнения цикла.

  • Стараются не разворачивать циклы чрезмерно; это может перегрузить кэш трассировки или кэш инструкции.

  • Разворачивают циклы, которые часто выполняются и имеют предсказуемое количество повторений для сокращения количества взаимодействий к 16 или меньше. Сделайте это, если это не увеличивает размер кода так, чтобы рабочий набор больше не помещался в трассировку или кэш инструкции. Если тело цикла содержит больше чем один условный переход, то разверните так, чтобы количество повторений равнялось 16 / (# condtional ответвления).

можно также заказать твердую копию для свободного здесь .

2
ответ дан 2 December 2019 в 02:57
поделиться
Другие вопросы по тегам:

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