C++11 基于mask的simd从大矢量加载矢量

C++11 基于mask的simd从大矢量加载矢量,c++11,simd,avx,avx2,C++11,Simd,Avx,Avx2,我希望这里有人能帮忙 我有一个大字节向量,从中创建一个小字节向量(基于掩码),然后用simd进行处理 目前,掩码是一个baseOffset+子掩码(字节[256])的数组,针对存储进行了优化,因为有>10^8个掩码。我创建一个maxsize子向量,然后在掩码数组中循环,将BaseOffsetBy 256乘以掩码加载中来自大向量的每一位偏移量,并将值依次放入一个较小的向量中。然后,通过多个VPMADDUBSW对较小的向量进行处理并累加。我可以改变这种结构。例如,遍历位一次,使用8K位数组缓冲区,然

我希望这里有人能帮忙

我有一个大字节向量,从中创建一个小字节向量(基于掩码),然后用simd进行处理

目前,掩码是一个baseOffset+子掩码(字节[256])的数组,针对存储进行了优化,因为有>10^8个掩码。我创建一个maxsize子向量,然后在掩码数组中循环,将BaseOffsetBy 256乘以掩码加载中来自大向量的每一位偏移量,并将值依次放入一个较小的向量中。然后,通过多个VPMADDUBSW对较小的向量进行处理并累加。我可以改变这种结构。例如,遍历位一次,使用8K位数组缓冲区,然后创建小向量

有没有更快的方法可以创建子阵列

我把应用程序中的代码拉到了一个测试程序中,但原来的程序处于不断变化的状态(移动到AVX2并从C#中提取更多代码)

#包括“stdafx.h”
#包括
#包括
#包括
#包括
#包括
#包括
//从
charn[4096]={9,5,5,5,9,5,5,5,5,5};
//W
charw[4096]={1,2,-3,5,5,5,5,5,5};
字符缓冲区[4096];
__declspec(对齐(2))
结构打包目的地{
字符块偏移量;
__int8位掩码[32];
};
__m128i总和=_mm_setzero_si128();
打包目的地打包目的地[10];
无效进程128(uuum128i u,uuum128i s)
{
__m128i计算=_mm_maddubs_epi16(u,s);//pmaddubsw
__m128i长度=_mm_cvtepi16_epi32(计算);
__m128i hiints=_mm_cvtepi16_epi32(_mm_shuffle_epi32(calc,0x4e));
总和=_mm_add_epi32(_mm_add_epi32(loint,hiint),总和);
}
无效进程数组(字符n[],字符w[],整数长度)
{
总和=_mm_setzero_si128();
int length128th=长度>>7;
对于(int i=0;iint blockOffset=packed_destinations[i]。blockOffset对现有代码进行了一些优化:

如果您的数据是稀疏的,那么在测试附加位之前,最好对每个8位掩码值添加一个附加测试,即

        int mask = packed_destinations[i].bitMask[j];
        if (mask != 0)
        {
            if (mask & 1 << 0)
                buffer[buffer_dest_index++] = n[joffset +  1<<0 ];
            if (mask & 1 << 1)
                buffer[buffer_dest_index++] = n[joffset +  1<<1];
            ...
请注意,除了将SSE指令计数从6减少到3之外,我还将
sum
作为一个参数,以避免对全局变量的依赖(避免全局变量始终是一个好主意,不仅是为了良好的软件工程,而且因为它们会抑制某些编译器优化)


查看代码的概要文件(使用一个像样的采样概要文件器,而不是通过插装)会很有趣,因为这将有助于确定任何进一步优化工作的优先级。

如果发布现有代码,可能会有所帮助。您的
process128
函数看起来已损坏-它实际上没有使用传递给它的参数?修复..我将函数拉出,以便制作avx2。process256我们可能需要知道掩码有多稀疏。如果掩码不是特别稀疏,则只需迭代大向量并根据需要从总和中屏蔽元素(使用SIMD)可能更有效。在另一个极端,如果掩码足够稀疏,那么您可能会使
创建_数组
功能更高效。这是一个稀疏矩阵..而通常的列:行数组在内存方面太昂贵,因此我使用掩码..通常使用率为5-15%,有时为25-100%。N高达64K,这是应该在L2中。缓冲区在500-3000范围内,因此压缩目的地理想情况下为2-6,但虽然掩码将集中在块中,但这并不理想,我假设压缩目的地长度为6-20。创建数组当前在c中,我希望可以在此处消除低效率。谢谢paul。未实现全局抑制选项。我还想知道现有pop向量与某种屏蔽移动到注册表之间的权衡,然后通过_mm256_shuffle_epi8移除空间。1000个字节的移动让我感到紧张,但应该是一级缓存将配置文件,但有大量代码需要重写并提供一些结构。当前代码是100%c#将繁重的操作转换为c。否绝对的性能,但速度越快,我可以使用的神经元越多,这就提高了准确性。如果我能从70%到85%,这将是一个巨大的胜利。好的-在你尝试了一些东西之后回来,用你的最新代码、基准测试和配置文件问一个新问题,我们可以看到进一步的优化可能。
        int mask = packed_destinations[i].bitMask[j];
        if (mask != 0)
        {
            if (mask & 1 << 0)
                buffer[buffer_dest_index++] = n[joffset +  1<<0 ];
            if (mask & 1 << 1)
                buffer[buffer_dest_index++] = n[joffset +  1<<1];
            ...
inline __m128i process128(const __m128i u, const __m128i s, const __m128i sum)
{
    const __m128i vk1 = _mm_set1_epi16(1);
    __m128i calc = _mm_maddubs_epi16(u, s);
    calc = _mm_madd_epi16(v, vk1);
    return _mm_add_epi32(sum, calc);
}