Приведение производительности от size_t к двойному

TL; DR: Почему умножение / приведение данных вsize_t медленно и почему это зависит от платформы?

У меня проблемы с производительностью, которые я до конца не понимаю. Контекст представляет собой устройство захвата кадров камеры, где изображение uint16_t размером 128x128 считывается и обрабатывается с частотой несколько 100 Гц.

При постобработке я генерирую гистограммуframe->histo который имеетuint32_t и имеетthismaxval = 2 ^ 16 элементов, в основном я подсчитываю все значения интенсивности. Используя эту гистограмму, я вычисляю сумму и квадратную сумму:

double sum=0, sumsquared=0;
size_t thismaxval = 1 << 16;

for(size_t i = 0; i < thismaxval; i++) {
    sum += (double)i * frame->histo[i];
    sumsquared += (double)(i * i) * frame->histo[i];
}

Профилируя код с профилем, я получил следующее (образцы, процент, код):

 58228 32.1263 :  sum += (double)i * frame->histo[i];
116760 64.4204 :  sumsquared += (double)(i * i) * frame->histo[i];

или первая строка занимает 32% процессорного времени, вторая строка 64%.

Я провел некоторый бенчмаркинг, и мне кажется, что это тип данных / кастинг, который проблематичен. Когда я изменяю код на

uint_fast64_t isum=0, isumsquared=0;

for(uint_fast32_t i = 0; i < thismaxval; i++) {
    isum += i * frame->histo[i];
    isumsquared += (i * i) * frame->histo[i];
}

работает ~ в 10 раз быстрее. Тем не менее, это снижение производительности также зависит от платформы. На рабочей станции Core i7 CPU 950 @ 3,07 ГГц код работает в 10 раз быстрее. На моем Macbook8,1, который имеет Intel Core i7 Sandy Bridge 2,7 ГГц (2620M), код всего в 2 раза быстрее.

Теперь мне интересно:

Почему оригинальный код такой медленный и легко ускоряется? Почему это сильно зависит от платформы?

Обновить

Я скомпилировал приведенный выше код с помощью

g++ -O3  -Wall cast_test.cc -o cast_test

Update2:

Я запускал оптимизированные коды через профилировщик Инструменты на Mac, какАкул) и нашел две вещи:

1) Сам цикл в некоторых случаях занимает значительное время.thismaxval имеет типsize_t.

for(size_t i = 0; i < thismaxval; i++) занимает 17% моего общего времени выполненияfor(uint_fast32_t i = 0; i < thismaxval; i++) берет 3,5%for(int i = 0; i < thismaxval; i++) не отображается в профилировщике, я предполагаю, что это меньше, чем 0,1%

2) Типы данных и данные о кастингах таковы:

sumsquared += (double)(i * i) * histo[i]; 15% (сsize_t i)sumsquared += (double)(i * i) * histo[i]; 36% (сuint_fast32_t i)isumsquared += (i * i) * histo[i]; 13% (сuint_fast32_t i, uint_fast64_t isumsquared)isumsquared += (i * i) * histo[i]; 11% (сint i, uint_fast64_t isumsquared)

Удивительно,int быстрее чемuint_fast32_t?

Update4:

Я провел еще несколько тестов с разными типами данных и разными компиляторами на одной машине. Результаты приведены ниже

Для testd 0 - 2 соответствующий код

    for(loop_t i = 0; i < thismaxval; i++)
        sumsquared += (double)(i * i) * histo[i];

сsumsquared двойной иloop_t size_t, uint_fast32_t а такжеint для тестов 0, 1 и 2.

Для тестов 3--5 код

    for(loop_t i = 0; i < thismaxval; i++)
        isumsquared += (i * i) * histo[i];

сisumsquared типаuint_fast64_t а такжеloop_t опять такиsize_t, uint_fast32_t а такжеint для тестов 3, 4 и 5.

Я использовал следующие компиляторы: gcc 4.2.1, gcc 4.4.7, gcc 4.6.3 и gcc 4.7.0. Временные параметры указаны в процентах от общего времени процессора, поэтому они показывают относительную производительность, а не абсолютную (хотя время выполнения было довольно постоянным в 21 с). Время процессора для обеих двух строк, потому что я не совсем уверен, правильно ли разделитель разделил две строки кода.

gcc:    4.2.1  4.4.7  4.6.3  4.7.0
----------------------------------
test 0: 21.85  25.15  22.05  21.85
test 1: 21.9   25.05  22     22
test 2: 26.35  25.1   21.95  19.2
test 3: 7.15   8.35   18.55  19.95
test 4: 11.1   8.45   7.35   7.1
test 5: 7.1    7.8    6.9    7.05

или

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

Также кажется, что gcc 4.6 и 4.7 не могут должным образом оптимизировать цикл 3 (size_t и uint_fast64_t).

Ответы на вопрос(2)

Ваш ответ на вопрос