答案 0 :(得分:2)
这是一篇关于如何使用SIMD指令来矢量化字符计数的文章:
答案 1 :(得分:1)
对于memset,memcpy等简单操作,计算量很少,SIMD优化没什么意义,因为内存带宽通常是限制因素。
答案 2 :(得分:1)
也许是libSIMDx86?
答案 3 :(得分:1)
您可以使用Apple或OpenSolaris的libc。这些libc实现包含您要查找的内容。大约6年前我一直在寻找这些东西,我不得不痛苦地写下来。
年龄之前我记得参加过一个名为“fastcode”项目的编码比赛。他们使用Delphi做了一些非常棒的突破性优化。查看他们的结果页面。由于它是用Pascal编写的快速函数调用模型(复制参数到寄存器)转换为C样式的stdc函数调用模型(推送堆栈)可能有点尴尬。该项目长期以来没有更新,尤其是没有为SSE4.2编写代码。
Solaris -> src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/
Apple -> www.opensource.apple.com/source/Libc/Libc-594.9.1/
答案 4 :(得分:1)
老实说,我要做的就是安装英特尔C ++编译器并学习各种自动SIMD优化标志。我们通过简单地使用ICC编译来优化代码性能,我们拥有非常好的经验。
请记住,整个STL库基本上只是头文件,所以整个东西都被编译到exe / lib / dll中,因此可以根据需要进行优化。
ICC有很多选项,可让您指定(最简单的)目标SSE级别。您还可以使用它来生成具有多个代码路径的二进制文件,这样,如果您编译的最佳SSE配置不可用,它将运行一组不同的(仍然优化的)代码,这些代码配置为功能较弱的SIMD CPU
答案 5 :(得分:1)
这是C中的快速memcpy实现,可以在必要时替换memcpy的标准库版本:
答案 6 :(得分:1)
strstr很难优化,因为(a)\ 0-termination意味着你必须要读取每个字节, (b)在所有边缘案件中也必须是好的。
话虽如此,你可以使用SSE2操作将标准strstr提高10倍。 我注意到gcc 4.4现在使用这些操作用于strlen,但不是用于 其他字符串操作。 更多关于如何为strlen,strchr,strpbrk等使用SSE2寄存器的更多信息。 在mischasan.wordpress.com。请原谅我的超级简洁代码布局。
#include <emmintrin.h> // Other standard #includes you can figure out...
static inline unsigned under(unsigned x)
{ return (x - 1) & ~x; }
static inline __m128i xmfill(char b)
{ return _mm_set1_epi8(b); }
static inline __m128i xmload(void const*p)
{ return _mm_load_si128((__m128i const*)p); }
static inline unsigned xmatch(__m128i a, __m128i b)
{ return _mm_movemask_epi8(_mm_cmpeq_epi8(a, b)); }
char const *sse_strstr(char const *tgt, char const *pat)
{
unsigned len = sse_strlen(pat);
if (len == 0) return tgt;
if (len == 1) return sse_strchr(tgt,*pat);
__m128i x, zero = {};
__m128i p0 = _m_set1_epi8(pat[0]), p1 = _m_set1_epi8(pat[1]);
uint16_t pair = *(uint16_t const*)pat;
unsigned z, m, f = 15 & (uintptr_t)tgt;
char const* p;
// Initial unaligned chunk of tgt:
if (f) {
z = xmatch(x = xmload(tgt - f), zero) >> f;
m = under(z) & ((xmatch(x,p0) & (xmatch(x,p1) >> 1)) >> f);
for (; m; m &= m - 1)
if (!memcmp((p = tgt+ffs(m)-1)+2, pat+2, len-2))
return p;
if (z)
return NULL;
tgt += 16 - f;
if (*(uint16_t const*)(tgt - 1) == pair
&& !memcmp(tgt+1, pat+2, len-2))
return tgt - 1;
}
// 16-byte aligned chunks of tgt:
while (!(z = xmatch(x = xmload(tgt), zero))) {
m = xmatch(x,p0) & (xmatch(x,p1) >> 1);
for (; m; m &= m - 1)
if (!memcmp((p = tgt+ffs(m)-1)+2, pat+2, len-2))
return p;
tgt += 16;
if (*(uint16_t const*)(tgt - 1) == pair && !memcmp(tgt+1, pat+2, len-2))
return tgt - 1;
}
// Final 0..15 bytes of tgt:
m = under(z) & xmatch(x,p0) & (xmatch(x,p1) >> 1);
for (; m; m &= m - 1)
if (!memcmp((p = tgt+ffs(m)-1)+2, pat+2, len-2))
return p;
return NULL;
}
答案 7 :(得分:0)
我个人不打算尝试编写超级优化版本的libc函数,试图以良好的性能处理每个可能的场景。
相反,为特定情况编写优化版本,您可以在其中充分了解手头的问题以编写正确的代码......以及重要的地方。 memset
和ClearLargeBufferCacheWriteThrough
之间存在语义差异。