草庐IT

c++ - NEON 向量化无符号字节乘积和 : (a[i]-int1) * (b[i]-int2)

coder 2024-02-16 原文

我需要改进一个循环,因为它被我的应用程序调用了数千次。我想我需要用 Neon 来做,但我不知道从哪里开始。

假设/先决条件:

  • w 始终为 320(16/32 的倍数)。
  • papb 是16字节对齐的
  • mamb 为正数。

 int whileInstruction (const unsigned char *pa,const unsigned char *pb,int ma,int mb,int w)
{
    int sum=0;

    do {
        sum += ((*pa++)-ma)*((*pb++)-mb);

    } while(--w);


    return sum;
}

这种对其进行矢量化的尝试效果不佳,而且不安全(缺少破坏者),但展示了我正在尝试做的事情:

int whileInstruction (const unsigned char *pa,const unsigned char *pb,int ma,int mb,int w)
{

    asm volatile("lsr          %2, %2, #3      \n"
                 ".loop:                       \n"
                 "# load 8 elements:             \n"
                 "vld4.8      {d0-d3}, [%1]!   \n"
                 "vld4.8      {d4-d7}, [%2]!   \n"
                 "# do the operation:     \n"
                 "vaddl.u8    q7, d0, r7       \n"
                 "vaddl.u8    q8, d1, d8       \n"
                 "vmlal.u8    q7, q7, q8       \n"
                 "# Sum the vector a save in sum (this is wrong):\n"
                 "vaddl.u8    q7, d0, r7       \n"
                 "subs        %2, %2, #1       \n" // Decrement iteration count
                 "bne         .loop            \n" // Repeat unil iteration count is not zero
                 :
                 : "r"(pa), "r"(pb), "r"(w),"r"(ma),"r"(mb),"r"(sum)
                 : "r4", "r5", "r6","r7","r8","r9"
                 );

    return sum;
}

最佳答案

这是一个简单的 NEON 实现。我已经针对标量代码对此进行了测试,以确保它可以正常工作。请注意,为获得最佳性能,papb 都应为 16 字节对齐。

#include <arm_neon.h>

int whileInstruction_neon(const unsigned char *pa, const unsigned char *pb, int ma, int mb, int w)
{
    int sum = 0;

    const int32x4_t vma = { ma, ma, ma, ma };
    const int32x4_t vmb = { mb, mb, mb, mb };

    int32x4_t vsumll = { 0 };
    int32x4_t vsumlh = { 0 };
    int32x4_t vsumhl = { 0 };
    int32x4_t vsumhh = { 0 };
    int32x4_t vsum;

    int i;

    for (i = 0; i <= (w - 16); i += 16)
    {
        uint8x16_t va = vld1q_u8(pa);   // load vector from pa
        uint8x16_t vb = vld1q_u8(pb);   // load vector from pb

        // unpack va into 4 vectors

        int16x8_t val =  (int16x8_t)vmovl_u8(vget_low_u8(va));
        int16x8_t vah =  (int16x8_t)vmovl_u8(vget_high_u8(va));
        int32x4_t vall = vmovl_s16(vget_low_s16(val));
        int32x4_t valh = vmovl_s16(vget_high_s16(val));
        int32x4_t vahl = vmovl_s16(vget_low_s16(vah));
        int32x4_t vahh = vmovl_s16(vget_high_s16(vah));

        // subtract means

        vall = vsubq_s32(vall, vma);
        valh = vsubq_s32(valh, vma);
        vahl = vsubq_s32(vahl, vma);
        vahh = vsubq_s32(vahh, vma);

        // unpack vb into 4 vectors

        int16x8_t vbl =  (int16x8_t)vmovl_u8(vget_low_u8(vb));
        int16x8_t vbh =  (int16x8_t)vmovl_u8(vget_high_u8(vb));
        int32x4_t vbll = vmovl_s16(vget_low_s16(vbl));
        int32x4_t vblh = vmovl_s16(vget_high_s16(vbl));
        int32x4_t vbhl = vmovl_s16(vget_low_s16(vbh));
        int32x4_t vbhh = vmovl_s16(vget_high_s16(vbh));

        // subtract means

        vbll = vsubq_s32(vbll, vmb);
        vblh = vsubq_s32(vblh, vmb);
        vbhl = vsubq_s32(vbhl, vmb);
        vbhh = vsubq_s32(vbhh, vmb);

        // update 4 partial sum of products vectors

        vsumll = vmlaq_s32(vsumll, vall, vbll);
        vsumlh = vmlaq_s32(vsumlh, valh, vblh);
        vsumhl = vmlaq_s32(vsumhl, vahl, vbhl);
        vsumhh = vmlaq_s32(vsumhh, vahh, vbhh);

        pa += 16;
        pb += 16;
    }

    // sum 4 partial sum of product vectors

    vsum = vaddq_s32(vsumll, vsumlh);
    vsum = vaddq_s32(vsum, vsumhl);
    vsum = vaddq_s32(vsum, vsumhh);

    // do scalar horizontal sum across final vector

    sum = vgetq_lane_s32(vsum, 0);
    sum += vgetq_lane_s32(vsum, 1);
    sum += vgetq_lane_s32(vsum, 2);
    sum += vgetq_lane_s32(vsum, 3);

    // handle any residual non-multiple of 16 points

    for ( ; i < w; ++i)
    {
        sum +=  (*pa++ - ma) * (*pb++ - mb);
    }

    return sum;
}

关于c++ - NEON 向量化无符号字节乘积和 : (a[i]-int1) * (b[i]-int2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8473537/

有关c++ - NEON 向量化无符号字节乘积和 : (a[i]-int1) * (b[i]-int2)的更多相关文章

  1. ruby-on-rails - Ruby on Rails : . 常量化 : wrong constant name error? - 2

    我正在使用这个:4.times{|i|assert_not_equal("content#{i+2}".constantize,object.first_content)}我之前声明过局部变量content1content2content3content4content5我得到的错误NameError:wrongconstantnamecontent2这个错误是什么意思?我很确定我想要content2=\ 最佳答案 你必须用一个大字母来调用ruby​​常量:Content2而不是content2。Aconstantnamestart

  2. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby - 鸭子输入字符串、符号和数组的优雅方式? - 2

    这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby​​。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac

  8. ruby - 如果它是标点符号,我怎么能从字符串中删除最后一个字符,在 ruby​​ 中? - 2

    啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组

  9. ruby - 如何在 Ruby 字符串中插入项目符号字符? - 2

    我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195

  10. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

随机推荐