Структурировано ли ваше приложение таким образом, чтобы вы могли прибыльно векторизовать эту функцию, вычисляя несколько независимых значений параллельно?Это позволило бы вам использовать аппаратные векторные единицы, такие как SSE.
Также кажется, что вам лучше хранить вокруг значения 1/r
, а не r
.
Это пример явного использования инструкций SSE2 для реализации функции.ljd()
рассчитывает два значения одновременно.
static __m128d ljd(__m128d r)
{
static const __m128d two = { 2.0, 2.0 };
static const __m128d si = { Si, Si };
static const __m128d ep24 = { 24 * Ep, 24 * Ep };
__m128d temp2, temp3;
__m128d temp = _mm_div_pd(si, r);
__m128d ep24_r = _mm_div_pd(ep24, r);
temp = _mm_mul_pd(temp, temp);
temp2 = _mm_mul_pd(temp, temp);
temp2 = _mm_mul_pd(temp2, temp);
temp3 = _mm_mul_pd(temp2, temp2);
temp3 = _mm_mul_pd(temp3, two);
return _mm_mul_pd(ep24_r, _mm_sub_pd(temp2, temp3));
}
/* Requires `out` and `in` to be 16-byte aligned */
void ljd_array(double out[], const double in[], int n)
{
int i;
for (i = 0; i < n; i += 2)
{
_mm_store_pd(out + i, ljd(_mm_load_pd(in + i)));
}
}
Однако важно отметить, что последние версии GCC часто могут автоматически векторизовать такие функции, если вы выбираете правильную архитектуру.и включить оптимизацию.Если вы нацеливаетесь на 32-битный x86, попробуйте скомпилировать с -msse2 -O3
и отрегулировать так, чтобы входной и выходной массивы были выровнены по 16 байтов.с атрибутом типа __attribute__ ((aligned (16)))
, а для динамических массивов - с помощью функции posix_memalign()
.