2017-01-30 24 views
0

Привет Я пытаюсь написать код для умножения векторных скаляров, используя AVX на процессоре Sandy Bridge i7-3720QM (~2012). Код C код составлен с GNU gcc по телефону Mac OSX 10.8.Ошибка векторной размножения скалярного AVX на Mac OSX

gcc -mavx -Wa,-q -o bb5 code1.c -lm

Я получаю Segmentation fault: 11. Пожалуйста помоги.

Выход:

3.000000 6.000000 9.000000 12.000000 
Segmentation fault: 11 

Итак, похоже, что команда store не работает правильно? Благодарю. В конце концов я хочу сделать что-то вроде A = A + x*B где x - это скаляр и A и B - это вектор. Функция void matsca(const double* a, double c, double *b) будет снова и снова вызываться для работы с вектором большого размера с размером 8 с double, поскольку AVX может принимать 4 двойные элементы (256 bits). Спасибо за вашу помощь.

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <immintrin.h> 

void matsca(const double* a, double c, double *b) 
{ 
    __m256d a0 = _mm256_loadu_pd(a+0); 
    __m256d a1 = _mm256_set1_pd(c); 

    __m256d a2 = _mm256_mul_pd(a0,a1); 

    double* f = (double*)&a2; 
    printf("%f %f %f %f \n",f[0],f[1],f[2],f[3]); 

    _mm256_store_pd(b,a2); 
} 

int main() 
{ 
    double m1[11]={1,2,3,4,5,6,7,8,9,10,11}; 
    double *m3; 
    double m2=3; 
    int i; 

    matsca(&m1[0],m2,&m3[0]); 

    for (i=0; i<3; i=i+1) 
    { 
     printf("%d %f \n",i,m3[i]); 
    } 

    return 0; 
} 
+2

'm3' не инициализировано, что вы ожидали? –

+1

И после того, как вы выделили некоторую память для 'm3', вам также нужно изменить' _mm256_store_pd' на '_mm256_storeu_pd'. –

+0

отличное спасибо вам обоим. это сработало. есть ли другой способ сделать это более эффективно? – Guddu

ответ

0

Вот фиксированная/улучшенная версия оригинального matsca:

inline void matsca(const double *a, const double c, double *b) 
{ 
    __m256d a0 = _mm256_loadu_pd(a); 
    __m256d a1 = _mm256_set1_pd(c); 
    __m256d a2 = _mm256_mul_pd(a0, a1); 

#if DEBUG > 0 
    double *f = (double *)&a2; 
    printf("%f %f %f %f\n", f[0], f[1], f[2], f[3]); 
#endif 

    _mm256_storeu_pd(b, a2); 
} 

Однако для вас может рассмотреть вопрос о внесении этого более общий характер, так что он может обрабатывать любой размер вектора, например,

inline void matsca(const double *a, const double c, double *b, const size_t n) 
{ 
    const __m256d a1 = _mm256_set1_pd(c); 
    size_t i; 

    for (i = 0; i + 4 <= n; i += 4) 
    { 
     __m256d a0 = _mm256_loadu_pd(&a[i]); 
     __m256d a2 = _mm256_mul_pd(a0, a1); 
     _mm256_storeu_pd(b, &a2[i]); 
    } 
    for (; i < n; ++i) // handle any odd elements at end of vector 
    { 
     a2[i] = a1[i] * a2; 
    } 
} 

Таким образом, вы амортизировать стоимость вызова функции, инициализацию постоянного вектора и т.д.

+0

не могли бы вы объяснить, что означает добавление 'inline void' и' size_t' и почему вы объявили массивы как 'const'? жаль, что я новичок. Благодарю. – Guddu

+1

Как правило, рекомендуется вводить входные параметры const. Также size_t является естественным типом для задания (без знака) размера массива или другой структуры данных. inline - это подсказка для компилятора, чтобы устранить накладные расходы на вызовы функций для небольших критически важных функций. –