ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
14 ноября
910051 Топик полностью
Ксения (13.03.2019 16:57 - 17:11, просмотров: 625) ответил йцукен на Это не мой код, и он вроде бы не умножает coeffs[0] на x. Я бы шаблон написал.
Шаблон делу не поможет, т.к. после компиляции он выльется всё в тот же сишный код. Тогда как суть дела вот в чем: функции fmin(), fmax() и fma() появились потому, что в AVX/AVX2 появились новые процессорные инструкции, делающие эти операции "за один такт". Эта ситуация аналогична появлению в языке операторов +=, *= и им подобных из-за того, что у процессора были такие команды для работы с памятью. К тому же выражение a+=b+c строго не эквивалентно выражению a=a+b+c, т.к. компилятору запрещено "упростить" второе выражение до первого, поскольку он обязан выполнять сложения слева направо. В этом смысле меня огорчает, что люди забывают про сишные операторы типа +=, ошибочно полагая, что компилятор сам упростит выражения, написанные в духе Бэйсика. Вот и сейчас, с появлением fma(), появились новые возможности. Например, в реализации функции poly(): double poly( double x, int n, double *coef) // compute polynomial { if( !n) return 0; double y = coef[n]; while(--n >= 0) y = fma(y, x, coef[n]); return y; } При такой реализации цикл крутился бы с максимальной скоростью. Однако при том важном условии, если fma() реализована на языке, как прямая подстановка кода! Но если мы возьмем стороннюю библиотеку с функцией fma(), реализованной, как подпрограмма, то это выльется в то, что компилятор будет вынужден сперва залить три числа в параметры вызова (большая удача, если не на стек!), а затем вызвать функцию из библиотеки со всеми сопровождающими такой вызов потерями (запихиванием адреса возврата в стек, переход на другой адрес, а по окончании возврат по адресу из стека с приведением стека в прежнее состояние). При этом реализация poly() сразу же станет настолько неэффективной, что ее быстрее было бы считать без помощи fma(). Практический пример - вычисление функции erfcx() через полином 23-порядка:
 x           variant 1       variant 2    difference
...
 21.0       0.0268358       0.0268358   -6.9042e-016
 22.0       0.0256186       0.0256186   -3.81639e-016
 23.0       0.0245069       0.0245069   -2.18575e-016
 24.0       0.0234875       0.0234875     -1.249e-016
 25.0       0.0225496       0.0225496   -7.28584e-017
 26.0       0.0216836       0.0216836   -4.51028e-017
100000 раз в цикле: 
1) erfcx(x): 8960 ms
2) erfcx(x): 80 ms
Результат вычислений практически одинаковый, но время отличается в 100 раз.