Ошибка сегментации при работе с интринками SSE из-за неправильного выравнивания памяти

Я впервые работаю со встроенными функциями SSE и сталкиваюсь с ошибкой сегментации даже после обеспечения 16-байтового выравнивания памяти. Этот пост является продолжением моего предыдущего вопроса:

Как выделить 16-байтовые данные, выровненные по памяти

Вот как я объявил свой массив:

  float *V = (float*) memalign(16,dx*sizeof(float));

Когда я пытаюсь сделать это:

  __m128 v_i = _mm_load_ps(&V[i]); //It works

Но когда я делаю это :

  __m128 u1 = _mm_load_ps(&V[(i-1)]); //There is a segmentation fault

Но если я это сделаю :

  __m128 u1 = _mm_loadu_ps(&V[(i-1)]); //It works again

Однако я хочу отказаться от использования _mm_loadu_psи хочу, чтобы это работало только с использованием _mm_load_ps.

Я работаю с компилятором Intel icc.

Как решить эту проблему?

ОБНОВЛЕНИЕ:

использование обеих операций в следующем коде:

  void FDTD_base (float *V, float *U, int dx, float c0, float c1, float c2, float c3,     float c4)
    {
       int i, j, k;
                    for (i = 4; i < dx-4; i++)
                    {

                            U[i] = (c0 * (V[i]) //center
                                    + c1 * (V[(i-1)] + V[(i+1)] )
                                    + c2 * (V[(i-2)] + V[(i+2)] )
                                    + c3 * (V[(i-3)] + V[(i+3)] )
                                    + c4 * (V[(i-4)] + V[(i+4)] ));
                    }

       }

Версия SSE:

         for (i=4; i < dx-4; i+=4)
        {
            v_i = _mm_load_ps(&V[i]);
            __m128 center = _mm_mul_ps(v_i,c0_i);

            __m128 u1 = _mm_loadu_ps(&V[(i-1)]);
            u2 = _mm_loadu_ps(&V[(i+1)]);

            u3 = _mm_loadu_ps(&V[(i-2)]);
            u4 = _mm_loadu_ps(&V[(i+2)]);

            u5 = _mm_loadu_ps(&V[(i-3)]);
            u6 = _mm_loadu_ps(&V[(i+3)]);

            u7 = _mm_load_ps(&V[(i-4)]);
            u8 = _mm_load_ps(&V[(i+4)]);

            __m128 tmp1 = _mm_add_ps(u1,u2);
            __m128 tmp2 = _mm_add_ps(u3,u4);
            __m128 tmp3 = _mm_add_ps(u5,u6);
            __m128 tmp4 = _mm_add_ps(u7,u8);

            __m128 tmp5 = _mm_mul_ps(tmp1,c1_i);
            __m128 tmp6 = _mm_mul_ps(tmp2,c2_i);
            __m128 tmp7 = _mm_mul_ps(tmp3,c3_i);
            __m128 tmp8 = _mm_mul_ps(tmp4,c4_i);

            __m128 tmp9 = _mm_add_ps(tmp5,tmp6);
            __m128 tmp10 = _mm_add_ps(tmp7,tmp8);

            __m128 tmp11 = _mm_add_ps(tmp9,tmp10);
            __m128 tmp12 = _mm_add_ps(center,tmp11);

            _mm_store_ps(&U[i], tmp12);
    }

Есть ли более эффективный способ сделать это, используя только _mm_load_ps()?

6
задан Community 23 May 2017 в 12:16
поделиться