Это также зависит от набора команд. Ваш процессор будет иметь несколько вычислительных блоков в режиме ожидания в любое время, и вы получите максимальную пропускную способность, если все они будут заполнены все время. Таким образом, выполнение цикла mul's так же быстро, как выполнение цикла или добавления, - но то же самое не выполняется, если выражение становится более сложным.
Например, возьмем этот цикл:
for(int j=0;j<NUMITER;j++) {
for(int i=1;i<NUMEL;i++) {
bla += 2.1 + arr1[i] + arr2[i] + arr3[i] + arr4[i] ;
}
}
для NUMITER = 10 ^ 7, NUMEL = 10 ^ 2, оба массива инициализируются маленькими положительными числами (NaN намного медленнее), это занимает 6,0 секунд при использовании удваиваний в 64-битной процедуре Если я заменю цикл на
bla += 2.1 * arr1[i] + arr2[i] + arr3[i] * arr4[i] ;
Это займет всего 1,7 секунды ... поэтому, поскольку мы "перестарались" с дополнениями, мулы были практически свободны; и сокращение дополнений помогло. Это становится более запутанным:
bla += 2.1 + arr1[i] * arr2[i] + arr3[i] * arr4[i] ;
- то же распределение mul / add, но теперь константа добавляется, а не умножается - занимает 3,7 секунды. Вероятно, ваш процессор оптимизирован для более эффективного выполнения типовых численных расчетов; так что точечный продукт, такой как суммы мул и масштабированных сумм, примерно такой же хороший, как и получается; добавление констант не так часто, так что это медленнее ...
bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; /*someval == 2.1*/
снова занимает 1,7 секунды.
bla += someval + arr1[i] + arr2[i] + arr3[i] + arr4[i] ; /*someval == 2.1*/
(аналогично начальному циклу, но без дорогостоящего добавления констант: 2,1 секунды)
bla += someval * arr1[i] * arr2[i] * arr3[i] * arr4[i] ; /*someval == 2.1*/
(в основном мулс, но одно дополнение: 1,9 секунды)
Итак, в основном; Трудно сказать, что быстрее, но если вы хотите избежать узких мест, более важно иметь разумную смесь, избегать NaN или INF, избегать добавления констант. Что бы вы ни делали, убедитесь, что вы тестируете и тестируете различные настройки компилятора, так как часто небольшие изменения могут иметь значение.
Еще несколько случаев:
bla *= someval; // someval very near 1.0; takes 2.1 seconds
bla *= arr1[i] ;// arr1[i] all very near 1.0; takes 66(!) seconds
bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; // 1.6 seconds
bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; //32-bit mode, 2.2 seconds
bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; //32-bit mode, floats 2.2 seconds
bla += someval * arr1[i]* arr2[i];// 0.9 in x64, 1.6 in x86
bla += someval * arr1[i];// 0.55 in x64, 0.8 in x86
bla += arr1[i] * arr2[i];// 0.8 in x64, 0.8 in x86, 0.95 in CLR+x64, 0.8 in CLR+x86