SSE Stdlib-esque图书馆?

时间:2010-10-05 10:00:08

标签: c++ c visual-c++ assembly sse

8 个答案:

答案 0 :(得分:2)

这是一篇关于如何使用SIMD指令来矢量化字符计数的文章:

http://porg.es/blog/ridiculous-utf-8-character-counting

答案 1 :(得分:1)

对于memset,memcpy等简单操作,计算量很少,SIMD优化没什么意义,因为内存带宽通常是限制因素。

答案 2 :(得分:1)

也许是libSIMDx86?

http://simdx86.sourceforge.net

答案 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的标准库版本:

http://www.danielvik.com/2010/02/fast-memcpy-in-c.html

答案 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函数,试图以良好的性能处理每个可能的场景。

相反,为特定情况编写优化版本,您可以在其中充分了解手头的问题以编写正确的代码......以及重要的地方。 memsetClearLargeBufferCacheWriteThrough之间存在语义差异。

相关问题