2013-10-28 64 views
2

如何使用SSE反轉字符串?這個概念對我來說是新的,所以請給我一些關於它的信息。原因是有人說使用SSE會加快代碼和運行時間。使用SSE反轉字符串

我已經搜索了這個_mm128的SSE,但並不知道如何分解它們。

謝謝

+0

我不認爲這是以下問題的重複,但你能得到一些幫助通過閱讀[用SSE2提取SSE混洗的32位值]開始這一工作(http://stackoverflow.com/questions/13474170/extracting-sse- shuffled-32-bit- value-with-only-sse2) 。 – Simon

+0

SSE的版本是什麼? –

回答

2

如果您可以假設最低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 
$