MMX SSE를 동등한 C 코드로 변환 중입니다. 거의 변환했지만 이미지 품질이 올바르지 않거나 이미지에 약간의 노이즈가 있음을 알 수 있습니다. 나는 지난 5 일 동안 코드를 디버깅하고 있지만 왜 일어나는지 알지 못합니다. 너희들이이 문제를 조사하고 나를 도와 주면 매우 행복해 할 것이다.MMX SSE에서 C 코드로 변환 할 때 이미지 품질이 저하됩니다.
ORIGINAL SSE 코드 :
void unpack_8bit_to_16bit(__m128i *a, __m128i* b0, __m128i* b1)
{
__m128i zero = _mm_setzero_si128();
b0 = _mm_unpacklo_epi8(a, zero);
b1 = _mm_unpackhi_epi8(a, zero);
}
void convolve_cols_3x3(const unsigned char* in, int16_t* out_v, int16_t* out_h, int w, int h)
{
using namespace std;
assert(w % 16 == 0 && "width must be multiple of 16!");
const int w_chunk = w/16;
__m128i* i0 = (__m128i*)(in);
__m128i* i1 = (__m128i*)(in) + w_chunk*1;
__m128i* i2 = (__m128i*)(in) + w_chunk*2;
__m128i* result_h = (__m128i*)(out_h) + 2*w_chunk;
__m128i* result_v = (__m128i*)(out_v) + 2*w_chunk;
__m128i* end_input = (__m128i*)(in) + w_chunk*h;
for(; i2 != end_input; i0++, i1++, i2++, result_v+=2, result_h+=2)
{
*result_h = _mm_setzero_si128();
*(result_h+1) = _mm_setzero_si128();
*result_v = _mm_setzero_si128();
*(result_v+1) = _mm_setzero_si128();
__m128i ilo, ihi;
unpack_8bit_to_16bit(*i0, ihi, ilo);
*result_h = _mm_add_epi16(ihi, *result_h);
*(result_h+1) = _mm_add_epi16(ilo, *(result_h+1));
*result_v = _mm_add_epi16(*result_v, ihi);
*(result_v+1) = _mm_add_epi16(*(result_v+1), ilo);
unpack_8bit_to_16bit(*i1, ihi, ilo);
*result_v = _mm_add_epi16(*result_v, ihi);
*(result_v+1) = _mm_add_epi16(*(result_v+1), ilo);
*result_v = _mm_add_epi16(*result_v, ihi);
*(result_v+1) = _mm_add_epi16(*(result_v+1), ilo);
unpack_8bit_to_16bit(*i2, ihi, ilo);
*result_h = _mm_sub_epi16(*result_h, ihi);
*(result_h+1) = _mm_sub_epi16(*(result_h+1), ilo);
*result_v = _mm_add_epi16(*result_v, ihi);
*(result_v+1) = _mm_add_epi16(*(result_v+1), ilo);
}
}
코드가 읽을 수없는 경우 내가
void convolve_cols_3x3(const unsigned char* in, int16_t* out_v, int16_t* out_h, int w, int h)
{
using namespace std;
assert(w % 16 == 0 && "width must be multiple of 16!");
const int w_chunk = w/16;
uint8_t* i0 = (uint8_t*)(in);
uint8_t* i1 = (uint8_t*)(in) + w_chunk*1*16;
uint8_t* i2 = (uint8_t*)(in) + w_chunk*2*16;
int16_t* result_h = (int16_t*)(out_h) + 2*w_chunk*16;
int16_t* result_v = (int16_t*)(out_v) + 2*w_chunk*16;
uint8_t* end_input = (uint8_t*)(in) + w_chunk*h*16;
for(; i2 != end_input; i0+= 16, i1+= 16, i2+= 16, result_v+= 16, result_h+= 16)
{
for (int i=0; i<8;i++)
{
result_h[i] = 0;
result_h[i + 8] = 0;
result_v[i] = 0;
result_v[i + 8] = 0;
result_h[i] = (int16_t)(i0[i]) + result_h[i] ;
result_h[i + 8] = (int16_t)(i0[i + 8]) + result_h[i + 8] ;
result_v[i] = (int16_t)(i0[i]) + result_v[i] ;
result_v[i + 8] = (int16_t)(i0[i + 8]) + result_v[i + 8] ;
result_v[i] = (int16_t)(i1[i]) + result_v[i] ;
result_v[i + 8] = (int16_t)(i1[i + 8]) + result_v[i + 8] ;
result_v[i] = (int16_t)(i1[i]) + result_v[i] ;
result_v[i + 8] = (int16_t)(i1[i + 8]) + result_v[i + 8] ;
result_h[i] = result_h[i] - (int16_t)(i2[i]);
result_h[i + 8] = result_h[i + 8] - (int16_t)(i2[i + 8]);
result_v[i] = (int16_t)(i2[i]) + result_v[i] ;
result_v[i + 8] = (int16_t)(i2[i + 8]) + result_v[i + 8] ;
}
}
}
죄송합니다 아래에 주어진 변환 된 코드입니다. w
및 h
은 너비와 높이를 나타냅니다. out_h
및 out_v
은 나중에 다른 용도로 사용되는 두 개의 매개 변수입니다.
적어도 하나 SSE 코드에 버그가있는 것 같습니다 : 당신은 또한 이전에 16 비트 정수를 읽을 필요가있는 경우 최종 수정 된 코드는 다음과 같을 수 사용되기 전에. 또는'unpack_8bit_to_16bit' 줄을 실수로 삭제 했습니까? –
@paul :: ihi 및 ilo는 unpack_8bit_to_16bit (---) 함수에 대한 참조로 전달되므로 원본 sse 코드에서 초기화됩니다. 변환 된 코드에서는 함수 호출을 최소화하기 위해 i0, i1 및 i2를 직접 사용했습니다 ... – user1717323
코드를 다시 살펴보십시오. 특히이 두 줄은 :'__m128i ilo, ihi; * result_h = _mm_add_epi16 (ihi, * result_h); ' –