Я не понимаю, где у меня проблема в коде с использованием sse

Я новичок в программировании sse. Я хочу написать код, в котором я суммирую 4 последовательных числа из вектора v и записываю результат этой суммы в векторе ans. Я хочу написать оптимизированный код с помощью sse. Но когда я установил размер, равный 4, моя программа работает. Но когда я установил размер 8, моя программа не работает, и у меня появляется это сообщение об ошибке: «Исключение выброшено: нарушение прав доступа на чтение.

ans было 0x1110112.

Если есть обработчик для этого исключения, программу можно безопасно продолжить. «Я не понимаю, где у меня проблема. Я выделяю память правильно, в каком месте у меня проблема. Может кто-нибудь мне помочь, я буду действительно благодарен.

#include <iostream>
#include <immintrin.h>
#include <pmmintrin.h>
#include <vector>
#include <math.h>  
using namespace std;
arith_t = double
void init(arith_t *&v, size_t size) {
    for (int i = 0; i < size; ++i) {
        v[i] = i / 10.0;
    }
}
//accumulate with sse
void sub_func_sse(arith_t *v, size_t size, int start_idx, arith_t *ans, size_t start_idx_ans) {
    __m128d first_part = _mm_loadu_pd(v + start_idx);
    __m128d second_part = _mm_loadu_pd(v + start_idx + 2);

    __m128d sum = _mm_add_pd(first_part, second_part);
    sum = _mm_hadd_pd(sum, sum);
    _mm_store_pd(ans + start_idx_ans, sum);
}
int main() {
    const size_t size = 8;
    arith_t *v = new arith_t[size];
    arith_t *ans_sse = new arith_t[size / 4];
    init(v, size);
    init(ans_sse, size / 4);
    int num_repeat = 1;
    arith_t total_time_sse = 0;
    for (int p = 0; p < num_repeat; ++p) {
        for (int idx = 0, ans_idx = 0; idx < size; idx += 4, ans_idx++) {
            sub_func_sse(v, size, idx, ans_sse, ans_idx);
        }
    }

    for (size_t i = 0; i < size / 4; ++i) {
        cout << *(ans_sse + i) << endl;
    }
    delete[] ans_sse;
    delete[] v;
}

person NN_05    schedule 30.12.2019    source источник
comment
_mm_store_pd требует 16-байтового выравнивания, которое new не гарантирует (особенно в 32-битном режиме на компиляторах, где alignof(max_align_t) = 8)   -  person Peter Cordes    schedule 30.12.2019
comment
Как я могу это исправить? Как я могу выделить новую память с выравниванием по 16?   -  person NN_05    schedule 30.12.2019
comment
Хотя это не очень хорошее общее решение, если вам нужна выровненная память для использования в _mm_intrinsics, вы можете использовать _ mm_alloc и друзья, что и является вашим вариантом использования.   -  person Mike Vine    schedule 30.12.2019


Ответы (1)


Вы используете невыровненную память, для которой требуются специальные версии функций загрузки и сохранения. Вы правильно использовали _mm_loadu_pd, но_mm_store_pd не подходит для работы с невыровненной памятью, поэтому вам следует изменить его на _mm_storeu_pd. Также рассмотрите возможность использования выровненной памяти, что приведет к повышению производительности.

person navyblue    schedule 30.12.2019