簡體   English   中英

strlen 性能實現

[英]strlen performance implementation

這是一個多用途問題:

  • 這與glibc strlen實現相比如何?
  • 有沒有更好的方法來解決這個問題和自動矢量化。
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>

/* Todo: Document */
#define WORD_ONES_LOW   ((size_t)-1 / UCHAR_MAX)
#define WORD_ONES_HIGH  (((size_t)-1 / UCHAR_MAX) << (CHAR_BIT - 1))

/*@doc
 * @desc: see if an arch word has a zero
 * #param: w - string aligned to word size
 */
static inline bool word_has_zero(const size_t *w)
{
    return ((*w - WORD_ONES_LOW) & ~*w & WORD_ONES_HIGH);
}

/*@doc
 * @desc: see POSIX strlen()
 * @param: s - string
 */
size_t strlen(const char *s)
{
    const char *z = s;

    /* Align to word size */
    for (; ((uintptr_t)s & (sizeof(size_t) - 1)) && *s != '\0'; s++);

    if (*s != '\0') {
        const size_t *w;

        for (w = (const size_t *)s; !word_has_zero(w); w++);
        for (s = (const char *)w; *s != '\0'; s++);
    }

    return (s - z);
}

嗯,這個實現基於與您鏈接的 glibc 實現幾乎相同的技巧( 確定一個字是否具有零字節)。 他們幾乎做同樣的事情,除了在 glibc 版本中一些循環被展開並且位掩碼被明確地拼寫出來。 您發布的代碼中的ONESHIGHS正是himagic = 0x80808080Llomagic = 0x01010101L形成 glibc 版本。

我看到的唯一區別是 glibs 版本使用稍微不同的標准來檢測零字節

if ((longword - lomagic) & himagic)

不做... & ~longword HASZERO(x)HASZERO(x)宏相比,它與x做同樣的事情,但還包括~(x)成員)。 顯然 glibc 的作者認為這個較短的公式更有效。 然而,它可能導致誤報。 所以他們在if下檢查誤報。

這確實是一個有趣的問題,哪個更有效:單階段精確測試(您的代碼)或兩階段測試,首先進行粗略的不精確檢查,然后在必要時進行精確的第二次檢查(glibc 代碼)。

如果您想查看它們在實際性能方面的比較 - 在​​您的平台和數據上對它們進行計時。 沒有別的辦法。

另外,請注意,此實現可以在此處讀取字符數組的末尾:

for (w = (const void *)s; !HASZERO(*w); w++);

因此依賴於未定義的行為。

為了回答你的第二個問題,我認為基於字節的原始strlen實現將導致編譯器更好的自動向量化,如果它很聰明並且支持向量指令集擴展(例如 SSE)已經啟用(例如使用-msse或適當的- -march )。 不幸的是,即使編譯器可以生成 32 位或 64 位偽矢量化代碼,如問題中引用的 C 代碼,如果它足夠聰明,它也不會導致使用缺乏這些功能的基線 CPU 進行任何矢量化。 .

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM