繁体   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