gpt4 book ai didi

c - MMX SSE 到 C 代码转换时图像质量下降

转载 作者:行者123 更新时间:2023-11-30 17:57:36 25 4
gpt4 key购买 nike

我正在将 MMX SSE 转换为等效的 C 代码。我几乎已经转换了它,但我得到的图像质量不合适,或者我可以看到图像中出现了一些噪音。我正在调试过去 5 天的代码,但我没有得到任何发生这种情况的原因。如果你们调查这个问题并帮助我解决问题,我将非常非常高兴。

原始 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] ;
}
}
}

抱歉,如果代码不那么可读。 wh 表示宽度和高度。 out_hout_v 是两个参数,稍后用于其他目的。

最佳答案

这些错误似乎存在于您的指针数学和源数据的读取中。指针变量 i0、i1、i2 是 unsigned char。您的代码中类似这样的行:

 result_h[i + 8] = (int16_t)(i0[i + 8]) + result_h[i + 8] ;

应该是这样的:

result_h[i + 8] = (int16_t)(i0[i*2 + 16]) + result_h[i + 8] ;

转换为 int16_t 不会影响 i0 方括号内的偏移量。您正在使用 16 字节结构 (__m128i),但以 8 字节偏移量访问它们。您还只使用 i0 和 i1 指向的整数的低 8 位。在原始的 SSE 代码中,您正在读取 16 位整数。如果您需要在加法之前读取 16 位整数,最终更正后的代码可能如下所示:

result_h[i + 8] = *(int16_t *)(&i0[i*2 + 16]) + result_h[i + 8];

关于c - MMX SSE 到 C 代码转换时图像质量下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12711101/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com