作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想在 C++ 中尽可能快地缩小图像。 This article描述了如何有效地将 32 位 rgb 图像平均降低 50%。它速度快,看起来不错。
我尝试使用 sse 内在函数修改该方法。下面的代码在启用或不启用 SSE 的情况下都有效。然而,令人惊讶的是,加速可以忽略不计。
任何人都可以找到改进 SSE 代码的方法吗?创建 vars shuffle1 和 shuffle2 的两条线似乎是候选者(使用一些巧妙的移位或类似方法)。
/*
* Calculates the average of two rgb32 pixels.
*/
inline static uint32_t avg(uint32_t a, uint32_t b)
{
return (((a^b) & 0xfefefefeUL) >> 1) + (a&b);
}
/*
* Calculates the average of four rgb32 pixels.
*/
inline static uint32_t avg(const uint32_t a[2], const uint32_t b[2])
{
return avg(avg(a[0], a[1]), avg(b[0], b[1]));
}
/*
* Calculates the average of two rows of rgb32 pixels.
*/
void average2Rows(const uint32_t* src_row1, const uint32_t* src_row2, uint32_t* dst_row, int w)
{
#if !defined(__SSE)
for (int x = w; x; --x, dst_row++, src_row1 += 2, src_row2 += 2)
* dst_row = avg(src_row1, src_row2);
#else
for (int x = w; x; x-=4, dst_row+=4, src_row1 += 8, src_row2 += 8)
{
__m128i left = _mm_avg_epu8(_mm_load_si128((__m128i const*)src_row1), _mm_load_si128((__m128i const*)src_row2));
__m128i right = _mm_avg_epu8(_mm_load_si128((__m128i const*)(src_row1+4)), _mm_load_si128((__m128i const*)(src_row2+4)));
__m128i shuffle1 = _mm_set_epi32( right.m128i_u32[2], right.m128i_u32[0], left.m128i_u32[2], left.m128i_u32[0]);
__m128i shuffle2 = _mm_set_epi32( right.m128i_u32[3], right.m128i_u32[1], left.m128i_u32[3], left.m128i_u32[1]);
_mm_store_si128((__m128i *)dst_row, _mm_avg_epu8(shuffle1, shuffle2));
}
#endif
}
最佳答案
在通用寄存器和 SSE 寄存器之间传输数据真的很慢,所以你应该避免这样的事情:
__m128i shuffle1 = _mm_set_epi32( right.m128i_u32[2], right.m128i_u32[0], left.m128i_u32[2], left.m128i_u32[0]);
__m128i shuffle2 = _mm_set_epi32( right.m128i_u32[3], right.m128i_u32[1], left.m128i_u32[3], left.m128i_u32[1]);
在相应的混洗操作的帮助下,对 SSE 寄存器中的值进行混洗。
这应该是您要查找的内容:
__m128i t0 = _mm_unpacklo_epi32( left, right ); // right.m128i_u32[1] left.m128i_u32[1] right.m128i_u32[0] left.m128i_u32[0]
__m128i t1 = _mm_unpackhi_epi32( left, right ); // right.m128i_u32[3] left.m128i_u32[3] right.m128i_u32[2] left.m128i_u32[2]
__m128i shuffle1 = _mm_unpacklo_epi32( t0, t1 ); // right.m128i_u32[2] right.m128i_u32[0] left.m128i_u32[2] left.m128i_u32[0]
__m128i shuffle2 = _mm_unpackhi_epi32( t0, t1 ); // right.m128i_u32[3] right.m128i_u32[1] left.m128i_u32[3] left.m128i_u32[1]
关于c++ - 使用 sse intrinsics 的 (A)RGB32 图像最快 50% 缩放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8052040/
我是一名优秀的程序员,十分优秀!