SIMD (SSE) инструкция для деления в GCC - PullRequest
5 голосов
/ 30 сентября 2010

Я хотел бы оптимизировать следующий фрагмент, используя инструкции SSE, если это возможно:

/*
 * the data structure
 */
typedef struct v3d v3d;
struct v3d {
    double x;
    double y;
    double z;
} tmp = { 1.0, 2.0, 3.0 };

/*
 * the part that should be "optimized"
 */
tmp.x /= 4.0;
tmp.y /= 4.0;
tmp.z /= 4.0;

Возможно ли это вообще?

Ответы [ 3 ]

1 голос
/ 30 сентября 2010

Я использовал расширение SIMD под Windows, но еще не под Linux. При этом вы должны быть в состоянии воспользоваться преимуществом операции DIVPS SSE, которая разделит вектор 4-х чисел на еще один вектор 4-х чисел. Но вы используете double, поэтому вам понадобится версия SSE2 DIVPD. Я почти забыл, не забудьте собрать с -msse2 свитчем.

Я нашел страницу, на которой подробно описаны некоторые встроенные функции SSE GCC. Это выглядит старым, но должно быть хорошее начало.

http://ds9a.nl/gcc-simd/

1 голос
/ 30 сентября 2010

Свойство, которое вы ищете - _mm_div_pd. Вот рабочий пример, которого должно быть достаточно, чтобы направить вас в правильном направлении:

#include <stdio.h>

#include <emmintrin.h>

typedef struct
{
    double x;
    double y;
    double z;
} v3d;

typedef union __attribute__ ((aligned(16)))
{
    v3d a;
    __m128d v[2];
} u3d;

int main(void)
{
    const __m128d vd = _mm_set1_pd(4.0);
    u3d u = { { 1.0, 2.0, 3.0 } };

    printf("v (before) = { %g %g %g }\n", u.a.x, u.a.y, u.a.z);

    u.v[0] = _mm_div_pd(u.v[0], vd);
    u.v[1] = _mm_div_pd(u.v[1], vd);

    printf("v (after) = { %g %g %g }\n", u.a.x, u.a.y, u.a.z);

    return 0;
}
1 голос
/ 30 сентября 2010

Достаточно ли tmp.x *= 0.25;?

Обратите внимание, что для инструкций SSE (в случае, если вы хотите их использовать) важно, чтобы:

1) весь доступ к памяти имеет размер 16 байтов

2) операции выполняются в цикле

3) нет двойных преобразований int <-> float или float <->

4) по возможности избегать делений

...