使用 SSE 反转字符串
Posted
技术标签:
【中文标题】使用 SSE 反转字符串【英文标题】:Reverse a string using SSE 【发布时间】:2013-10-28 04:25:01 【问题描述】:我们如何?这个概念对我来说是新的,所以请给我一些关于它的信息。原因是有人说使用 SSE 会加快代码和运行时间。
我搜索了 SSE,即 _mm128,但不知道如何分解它们。
谢谢
【问题讨论】:
我不认为这是以下问题的重复,但您可以通过阅读 Extracting SSE shuffled 32 bit value with only SSE2 获得一些帮助。 什么版本的上交所? 【参考方案1】:如果您可以假设最低 SSSE3,那么使用_mm_shuffle_epi8
非常容易,但在您这样做之前,您应该真正确保 (a) 您当前的实现是性能瓶颈,并且 (b) 您已经完成了所有工作您可以使当前的实现尽可能快,因为这是一个如此简单的操作,对于任何体面的实现,它的性能实际上应该只受内存带宽的限制。
无论如何,这是一个简单的实现和测试工具:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tmmintrin.h> // SSSE3
void reverse(char *begin, char *end)
while (begin < end)
const char c = *begin;
*begin = *end;
*end = c;
++begin;
--end;
void vreverse(char *begin, char *end)
const __m128i vrev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
ssize_t len = end - begin + 1;
while (len >= 16)
__m128i v1 = _mm_loadu_si128((__m128i *)begin);
__m128i v2 = _mm_loadu_si128((__m128i *)(end - 15));
v1 = _mm_shuffle_epi8(v1, vrev);
v2 = _mm_shuffle_epi8(v2, vrev);
_mm_storeu_si128((__m128i *)(end - 15), v1);
_mm_storeu_si128((__m128i *)begin, v2);
begin += 16;
end -= 16;
len -= 32;
if (len > 1)
reverse(begin, end);
int main(void)
const size_t MAX_LEN = 64;
char s1[MAX_LEN + 1], s2[MAX_LEN + 1];
size_t i, len;
for (len = 0; len < MAX_LEN; ++len)
for (i = 0; i < len; ++i)
s1[i] = s2[i] = (char)('a' + rand() % 26);
s1[len] = s2[len] = '\0';
reverse(s1, s1 + len - 1);
vreverse(s2, s2 + len - 1);
if (memcmp(s1, s2, len) != 0)
printf("FAIL: len = %zu\n", len);
printf("FAIL: s1 = %s\n", s1);
printf("FAIL: s2 = %s\n", s2);
else
//printf("PASS: len = %zu\n", len);
return 0;
测试一下:
$ gcc -Wall -mssse3 -O3 vreverse.c && ./a.out
$
【讨论】:
以上是关于使用 SSE 反转字符串的主要内容,如果未能解决你的问题,请参考以下文章