2017-02-15 39 views
4

Я хочу создать гистограмму вертикальных градиентов в 8-битном сером изображении. Можно указать вертикальное расстояние для расчета градиента. Мне уже удалось ускорить работу другой части моего кода с помощью Intrinsics, но здесь это не работает. Код запускается без исключения, если _mm_store_si128 закомментирован. Когда он не прокомментирован, я получаю нарушение доступа.нарушение прав доступа _mm_store_si128 SSE Intrinsics

Что здесь общего не работает?

#define _mm_absdiff_epu8(a,b) _mm_adds_epu8(_mm_subs_epu8(a, b), _mm_subs_epu8(b, a)) //from opencv 
void CreateAbsDiffHistogramUnmanaged(void* source, unsigned int sourcestride, unsigned int height, unsigned int verticalDistance, unsigned int histogram[]) 
{ 
unsigned int xcount = sourcestride/16; 
__m128i absdiffData; 
unsigned char* bytes = (unsigned char*) _aligned_malloc(16, 16); 
__m128i* absdiffresult = (__m128i*) bytes; 
__m128i* sourceM = (__m128i*) source; 
__m128i* sourceVOffset = (__m128i*)source + verticalDistance * sourcestride; 

for (unsigned int y = 0; y < (height - verticalDistance); y++) 
{ 
    for (unsigned int x = 0; x < xcount; x++, ++sourceM, ++sourceVOffset) 
    { 
     absdiffData = _mm_absdiff_epu8(*sourceM, *sourceVOffset); 
     _mm_store_si128(absdiffresult, absdiffData); 
     //unroll loop 
     histogram[bytes[0]]++; 
     histogram[bytes[1]]++; 
     histogram[bytes[2]]++; 
     histogram[bytes[3]]++; 
     histogram[bytes[4]]++; 
     histogram[bytes[5]]++; 
     histogram[bytes[6]]++; 
     histogram[bytes[7]]++; 
     histogram[bytes[8]]++; 
     histogram[bytes[9]]++; 
     histogram[bytes[10]]++; 
     histogram[bytes[11]]++; 
     histogram[bytes[12]]++; 
     histogram[bytes[13]]++; 
     histogram[bytes[14]]++; 
     histogram[bytes[15]]++; 
    } 
} 
_aligned_free(bytes); 
} 

ответ

3

Ваша функция разбилась при загрузке, потому что входные данные не выровнены. Для того чтобы решить проблему, вы должны изменить ваш код:

от:

absdiffData = _mm_absdiff_epu8(*sourceM, *sourceVOffset); 

к:

absdiffData = _mm_absdiff_epu8(_mm_loadu_si128(sourceM), _mm_loadu_si128(sourceVOffset)); 

Здесь я использовал невыровненную загрузку.

P.S. Я реализовал аналогичную функцию (SimdAbsSecondDerivativeHistogram) в Simd Library. Он имеет SSE2, AVX2, NEON и Altivec реализации. Надеюсь, это вам поможет.

P.P.S. Кроме того, я бы настоятельно рекомендовал, чтобы проверить эту строку:

__m128i* sourceVOffset = (__m128i*)source + verticalDistance * sourcestride); 

возможные приводит к сбою (доступ к памяти за пределами входного массива). Возможно, вы имеете в виду:

__m128i* sourceVOffset = (__m128i*)((char*)source + verticalDistance * sourcestride); 
+0

Большое спасибо за помощь. Я пробовал ваше улучшение, но ошибка все еще существует. Кроме того, я знаю, что входные данные выровнены, потому что я выполняю другие операции с одними и теми же данными. –

+0

@JosefBauer Вы проверяете результат функции _aligned_malloc()? Потому что у меня нет никаких исключений в этом коде. – ErmIg

+0

В этой строке произошла дополнительная ошибка: '__m128i * sourceVOffset = (__m128i *) source + verticalDistance * sourcestride;' его нужно было заменить на '__m128i * sourceVOffset = (__m128i *) ((unsigned char *) source + (verticalDistance * sourcestride)); @ErmIg вы были правы, что мне пришлось переходить на __mm_loadu_si128. благодаря –

 Смежные вопросы

  • Нет связанных вопросов^_^