strlen性能实现

这是一个多function问题:

  • 这与glibc strlen实现相比如何?
  • 有没有更好的方法来实现这一点和自动向量化。

随机填充垃圾,因为stackoverflow以某种方式比我更了解代码到汇总比率

#include  #include  #include  #include  #include  #include  /* 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的作者认为这种较短的公式更有效。 然而,它可能导致误报。 因此,他们会检查是否存在误报。

这确实是一个有趣的问题,更有效的:单阶段精确测试(您的代码)或两阶段测试,以粗略的不精确检查开始,如有必要,通过精确的第二次检查(glibc代码)。

如果您想了解它们在实际性能方面的比较 – 在​​您的平台和数据上计算时间。 别无他法。

另请注意,此实现可以在此处读取char数组的末尾:

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

因此依赖于未定义的行为。

为了回答你的第二个问题,我认为天然的基于字节的strlen实现将导致编译器更好的自动向量化,如果它是智能的并且已经启用了对向量指令集扩展(例如SSE)的支持(例如使用-msse或者适当的 – -march )。 不幸的是,它不会导致缺少这些function的基线cpus的任何矢量化,即使编译器可以生成32位或64位伪矢量化代码,如问题中引用的C代码,如果它足够聪明的话。 。