cpu — В C ++ лучше ограничить значение, используя std :: min или ветвь if?

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

value += increment;
value = std::min(value, valueMax);

против

value += increment;

if (value > valueMax)
value = valueMax;

Я думаю, что это сводится к тому, есть ли у процессоров инструкции для принятия двух значений и получения минимума. Если это так, вызов std :: min должен привести к этой инструкции и избежать ненужной ветви. Если нет, вторая версия избегает ненужного присваивания, когда значение <= значение Макс.

Я не очень хорош в таких вещах, но я уверен, что есть хакеры из старой школы, которые бы знали об этом. Им я спрашиваю: что лучше?

14

Решение

Современные компиляторы достаточно умны, чтобы генерировать один и тот же код в обоих случаях. Например, 32-битный GCC генерирует:

addl    %esi, %edi
cmpl    %edx, %edi
movl    %edi, %eax
cmovgl  %edx, %eax

64-битный Clang:

%1 = add nsw i32 %increment, %value
%2 = icmp sgt i32 %1, %valueMax
%value = select i1 %2, i32 %valueMax, i32 %1
10

Другие решения

На VC10 на выпуске для следующего кода у нас есть следующая сборка:

int main(int argc, char *argv[])
{
int dummyValue = 0, valueMax = 3000, value = valueMax + 1;

cin >> valueMax;
cin >> value;

dummyValue = std::min(value, valueMax);

cout << dummyValue;
cin >> valueMax;
cin >> value;

if (value > valueMax)
dummyValue = valueMax;

cout << dummyValue;
return 0;
}

Сформирован:

  24:   dummyValue = std::min(value, valueMax);
00E112AF  mov         eax,dword ptr [valueMax]
00E112B2  cmp         eax,dword ptr [value]
00E112B5  lea         edx,[value]
00E112B8  lea         ecx,[valueMax]
00E112BB  cmovge      ecx,edx     // <-- this is our conditional assignment
00E112BE  mov         esi,dword ptr [ecx]

а также

if (value > valueMax)
dummyValue = valueMax
00E112ED  mov         eax,dword ptr [valueMax]
00E112F0  cmp         dword ptr [value],eax
00E112F3  mov         ecx,dword ptr ds:[0E13038h]
00E112F9  cmovg       esi,eax

Таким образом, оба случая оптимизированы либо cmovge или же cmovg инструкции.

Я бы все равно пошел с std::min потому что это показывает намерение лучше, чем if заявление. Это оптимизировано, и это более читабельно.

4

Ответ зависит от типа значения. Код может быть эффективно оптимизирован, если все операции полностью прозрачны для оптимизатора кода, что будет в случае, если значение является простым целым числом. Но ваш код также будет компилироваться, если значением является std :: string, и тогда вторая версия может быть потенциально более быстрой, поскольку присваивание является условным.

0
По вопросам рекламы [email protected]