Мое предположение, это в первом случае, два различных ответвления оказываются в том же слоте предсказания ветвлений на ЦП. Если эти два ответвления предскажут отличающийся каждый раз, то когда код замедлится.
Во втором цикле добавленного кода может просто быть достаточно для перемещения одного из ответвлений к другому слоту предсказания ветвлений.
Чтобы быть уверенными, можно дать анализатору Intel VTune или инструменту AMD CodeAnalyst попытку. Эти инструменты покажут Вам, что точно продолжается в Вашем коде.
Однако имейте в виду, что по всей вероятности не стоит для оптимизации этого кода далее. При настройке кода, чтобы быть быстрее на ЦП, это может одновременно стать медленнее на другом бренде.
Править:
Если Вы хотите читать на предсказании ветвлений, дают превосходному веб-сайту Вуали Agner попытку: http://www.agner.org/optimize/
Этот PDF объясняет назначение слотов предсказания ветвлений подробно: http://www.agner.org/optimize/microarchitecture.pdf
Мое первое предположение - то, что ответвление предсказывается лучше во втором случае. Возможно, потому что вложенный, если дает любому алгоритму использование процессора больше информации для предположения от. Только из любопытства, что происходит, когда Вы удаляете строку
if (((int *)SRGBCeiling)[iSRGB] <= *((int *)pSource))
?
Как Вы синхронизируете эти стандартные программы? Интересно, имеют ли подкачка страниц или кэширование эффект на синхронизации? Возможно, что вызов первой стандартной программы загружает обоих в память, пересекает границу страницы или заставляет стек пересекаться в недопустимую страницу (порождение страницы - в), но только первая стандартная программа платит цену.
Можно хотеть для пробежки обеих функций, однажды выполняющих вызовы, которые проводят измерения для сокращения эффектов, которые могли бы иметь виртуальная память и кэширование.
Вы просто тестируете этот внутренний цикл, или Вы тестируете свой нераскрытый внешний цикл также? Если так, посмотрите на эти три строки:
if (((int *)SRGBCeiling)[iSRGB] <= *((int *)pSource))
++iSRGB;
*pDestination = (unsigned char) iSRGB;
Теперь, это похоже *pDestination
счетчик для внешнего цикла. Таким образом, иногда делая дополнительный инкремент iSRGB
значение, которое Вы получаете для пропуска некоторых повторений во внешнем цикле, таким образом, уменьшая общий объем работы код, должно сделать.
Однажды у меня была похожая ситуация. Я вытащил код из цикла, чтобы сделать его быстрее, но он стал медленнее. Сбивает с толку. Оказывается, среднее количество раз, когда цикл был меньше 1.
Урок (который, очевидно, вам не нужен) заключается в том, что изменение не ускоряет ваш код, если вы не измеряете, что он действительно работает быстрее.