【问题标题】:High performance comparison of signed int arrays (using Intel IPP library)有符号整数数组的高性能比较(使用英特尔 IPP 库)
【发布时间】:2009-10-16 19:47:34
【问题描述】:

我们正在尝试以高性能的方式使用不等式运算 和 >= 比较两个大小相同的 signed int 值的原生数组。由于比较了许多值,true/false 结果将被存储在与输入大小相同的char 数组中,其中0x00 表示false0xff 表示true

为此,我们使用了英特尔 IPP 库。问题是我们从图像和视频处理库中找到的名为ippiCompare_* 的执行此操作的函数仅支持unsigned char (Ipp8u)、signed/unsigned short (Ipp16s/Ipp16u) 和@987654334 类型@ (Ipp32f)。不直接支持signed int(Ipp32s)

我(仅)设想了两种可能的解决方法:

  • 将数组转换为直接支持的类型之一并在更多步骤中执行比较(它将变成大小两倍的短数组或大小四倍的 char 数组)并合并中间结果。

  • 使用另一个函数直接支持来自 IPP 或另一个库的 signed int 数组,该函数在性能方面可以做相当的事情。

但可能还有其他创造性的方式......所以我请求你帮忙! :)

PS:使用英特尔 IPP 的优势在于大型阵列的性能提升:它同时使用多值处理器功能和多个内核(可能还有更多技巧)。如此简单的循环解决方案不会像 AFAIK 那样快。

PS2:ippiCompare_* doc的链接

【问题讨论】:

    标签: c++ arrays performance comparison intel-ipp


    【解决方案1】:

    您可以使用 PCMPEQD 后跟 PACKUSDW 和 PACKUSWB 进行比较。这将是一些事情

    #include <emmintrin.h>
    
    void cmp(__m128d* a, __m128d* b, v16qi* result, unsigned count) {
        for (unsigned i=0; i < count/16; ++i) {
            __m128d result0 = _mm_cmpeq_pd(a[0], b[0]);  // each line compares 4 integers
            __m128d result1 = _mm_cmpeq_pd(a[1], b[1]);
            __m128d result2 = _mm_cmpeq_pd(a[2], b[2]);
            __m128d result3 = _mm_cmpeq_pd(a[3], b[3]);
            a += 4; b+= 4;
    
            v8hi wresult0 = __builtin_ia32_packssdw(result0, result1);  //pack 2*4 integer results into 8 words
            v8hi wresult1 = __builtin_ia32_packssdw(result0, result1);
    
            *result = __builtin_ia32_packsswb(wresult0, wresult1);  //pack 2*8 word results into 16 bytes
            result++;
        }
    }
    

    需要对齐的指针,一个可被 16 整除的计数,由于懒惰/愚蠢,我省略了一些类型转换,当然可能还有很多调试。而且我没有找到 packssdw/wb 的内在函数,所以我只使用了编译器中的内置函数。

    【讨论】:

    • 我现在正在检查 MMX 操作,这似乎是完成我的意图的好方法。我只是不确定在这种情况下是否使用多核:它似乎不是“自动”完成的,对吧?
    • 没有。而且由于两个核心共享一部分资源,比如最后一级缓存和内存,内存带宽很可能成为瓶颈。对于如此简单的例程,它可能不值得付出努力。或者更糟糕的是,性能可能会因各种原因而受到影响。
    【解决方案2】:

    我认为有一个 SSE 指令可以比较整数。您是否研究过可以做到这一点的内在函数?

    【讨论】:

      【解决方案3】:

      开箱即用:您确定这是性能问题吗?除非您的数据集适合 L1 缓存,否则您的缓存填充将受到限制,并且您在比较操作上花费的实际周期(即使以最幼稚的方式完成也几乎不会 缓慢)不可能是限制性的。

      【讨论】:

      • 你是对的,对于纯内存操作,内存带宽通常是限制因素。然而,即使对于简单的内存副本,sse 指令也会胜过“幼稚”的方式或字符串操作,即使只是小幅度的。与简单的方式相比,只占用了四分之一的执行单元,因此超线程可能会从向量操作中受益匪浅。此外,如果他有流数据,他可以选择绕过缓存(非临时 mov 指令)以避免缓存污染。
      • 我也会密切关注的;谢谢你的建议。无论如何,我们将使用 IPP 和简单的标量操作在我们正在构建的每个操作的两个版本之间运行比较测试,以确保真正的性能提升。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-26
      • 1970-01-01
      相关资源
      最近更新 更多