Нарушение доступа SSE - PullRequest
       12

Нарушение доступа SSE

3 голосов
/ 03 августа 2010

У меня есть код:

float *mu_x_ptr;
__m128 *tmp;
__m128 *mm_mu_x;

mu_x_ptr = _aligned_malloc(4*sizeof(float), 16);
mm_mu_x = (__m128*) mu_x_ptr;
for(row = 0; row < ker_size; row++) {
    tmp = (__m128*) &original[row*width + col];
    *mm_mu_x = _mm_add_ps(*tmp, *mm_mu_x);
}

Из этого я получаю:

First-chance exception at 0x00ad192e in SSIM.exe: 0xC0000005: Access violation reading location 0x00000000.
Unhandled exception at 0x00ad192e in SSIM.exe: 0xC0000005: Access violation reading location 0x00000000.
The program '[4452] SSIM.exe: Native' has exited with code -1073741819 (0xc0000005)

при запуске программы ошибка возникает в строке _mm_add_ps.

оригинал размещается с помощью _aligned_malloc (..., 16);как и в функции, поэтому не должно быть, насколько я понимаю, sse, что она не выровнена.

Интересно, кто-нибудь может понять, почему это происходит сбой, так как я могуНе понимаю, почему.

РЕДАКТИРОВАТЬ: ширина и столбец всегда кратен 4. Col - это 0 или 4, а ширина всегда кратна 4.

РЕДАКТИРОВАТЬ 2: выглядит как мой исходный массивне выровнен.Не будет:

function(float *original);
.
.
.
    orignal = _aligned_malloc(width*height*sizeof(float), 16);
    function(original);
    _aligned_free(original);
}

Убедитесь, что оригинал выровнен внутри функции?

Edit3: На самом деле это действительно странно.Когда я делаю:

float *orig;
orig = _aligned_malloc(width*height*sizeof(float), 16);
assert(isAligned(orig));

Утверждение не удается с

#define isAligned(p) (((unsigned long)(p)) & 15 == 0)

Ответы [ 2 ]

3 голосов
/ 03 августа 2010

Я думаю, вам нужно использовать

__m128 tmp = _mm_load_ps( &original[row * width + col] );

вместо

tmp = (__m128 *)&original[row * width + col];

РЕДАКТИРОВАТЬ: Если вы получаете ошибки нарушения доступа после некоторого смещения, то, возможно, ваш шаг не выравнивается. В любом случае выделите элементы __m128 (которые представляют 4 числа с плавающей запятой). Это заботится о выравнивании.

Также вы можете получить дополнительную производительность, исключив арифметику [row * width + col]. Определите свой шаг и увеличьте указатель соответственно.

1 голос
/ 03 августа 2010

tmp будет смещено, если width и col не имеют подходящих значений. В идеале оба значения width и col должны быть кратны 4.

Вы можете добавить несколько утверждений для проверки выравнивания, например,

#define IsAligned(p) ((((unsigned long)(p)) & 15) == 0)

float *mu_x_ptr;
__m128 *tmp;
__m128 *mm_mu_x;

assert(original != NULL && IsAligned(original));
mu_x_ptr = _aligned_malloc(4 * sizeof(float), 16);
assert(mu_x_ptr != NULL && IsAligned(mu_x_ptr));
mm_mu_x = (__m128 *)mu_x_ptr;
assert(IsAligned(mm_mu_x));
for (row = 0; row < ker_size; row++)
{
    tmp = (__m128 *)&original[row * width + col];
    assert(IsAligned(tmp));
    *mm_mu_x = _mm_add_ps(*tmp, *mm_mu_x);
}
...