[NCNN学习笔记]-4

1、前言

继续学习NCNN。本次学习binaryop和eltwise。

2、学习内容
2.1、binaryop

binaryop是用来二元计算的op,先来看binaryop.h的中关于二元计算的定义,其中二元计算定义了如下操作。

enum OperationType
{
    Operation_ADD = 0,
    Operation_SUB = 1,
    Operation_MUL = 2,
    Operation_DIV = 3,
    Operation_MAX = 4,
    Operation_MIN = 5,
    Operation_POW = 6,
    Operation_RSUB = 7,
    Operation_RDIV = 8,
    Operation_RPOW = 9,
    Operation_ATAN2 = 10,
    Operation_RATAN2 = 11
};

在binaryop.cpp中,实际调用了二元计算函数。

template<typename Op>
static void binary_op_broadcast(const Mat& a, const Mat& b, Mat& c, const Option& opt){
    ...
}

static void binary_op_broadcast(const Mat& a, const Mat& b, Mat& c, int op_type, const Option& opt)
{
    if (op_type == BinaryOp::Operation_ADD) return binary_op_broadcast<binary_op_add>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_SUB) return binary_op_broadcast<binary_op_sub>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_MUL) return binary_op_broadcast<binary_op_mul>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_DIV) return binary_op_broadcast<binary_op_div>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_MAX) return binary_op_broadcast<binary_op_max>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_MIN) return binary_op_broadcast<binary_op_min>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_POW) return binary_op_broadcast<binary_op_pow>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_RSUB) return binary_op_broadcast<binary_op_sub>(b, a, c, opt);
    if (op_type == BinaryOp::Operation_RDIV) return binary_op_broadcast<binary_op_div>(b, a, c, opt);
    if (op_type == BinaryOp::Operation_RPOW) return binary_op_broadcast<binary_op_pow>(b, a, c, opt);
    if (op_type == BinaryOp::Operation_ATAN2) return binary_op_broadcast<binary_op_atan2>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_RATAN2) return binary_op_broadcast<binary_op_atan2>(b, a, c, opt);
}

可以看出,二元操作是通过函数模板实现的。在binaryop_arm.cpp中实现了具体的二元操作的例子。

template<typename Op>
static void binary_op_vector_no_broadcast(const float* ptr, const float* ptr1, float* outptr, int size)
{
    const Op op;

    int i = 0;
#if __ARM_NEON
    for (; i + 3 < size; i += 4)
    {
        float32x4_t _p = vld1q_f32(ptr);
        float32x4_t _b = vld1q_f32(ptr1);
        float32x4_t _outp = op(_p, _b);    // 通过op来确定最终的操作
        vst1q_f32(outptr, _outp);
        ptr += 4;
        ptr1 += 4;
        outptr += 4;
    }
#endif // __ARM_NEON
    for (; i < size; i++)
    {
        *outptr = op(*ptr, *ptr1);
        ptr += 1;
        ptr1 += 1;
        outptr += 1;
    }
}
2.2、eltwise

elwise 主要用于两个Mat类型的数据逐元素之间的操作。在eltwise.h 中定义了三种三种计算方式

enum OperationType
{
    Operation_PROD = 0,
    Operation_SUM = 1,
    Operation_MAX = 2
};

eltwise_arm.h 继承于 eltwise.h,在eltwise_arm.cpp中实现了三种操作在arm上的实现方式。

int Eltwise_arm::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
{
    // first blob
    const Mat& bottom_blob = bottom_blobs[0];  
    int w = bottom_blob.w;
    int h = bottom_blob.h;
    int d = bottom_blob.d;
    int channels = bottom_blob.c;
    int elempack = bottom_blob.elempack;
    int size = w * h * d * elempack;
    // 逐元素相乘
    if (op_type == Operation_PROD)
    { 
		// second blob
        const Mat& bottom_blob1 = bottom_blobs[1];    // out = bottom_blobs[0] .* bottom_blobs[1];
        for (int q = 0; q < channels; q++){  // 每个channel计算
            const float* ptr = bottom_blob.channel(q); // 0
            const float* ptr1 = bottom_blob1.channel(q); // 1
            float* outptr = top_blob.channel(q);   // 0
            // 计算8的整数倍的数据
            for (; i + 7 < size; i += 8){}
            // 计算4的整数倍的数据
            for (; i + 3 < size; i += 4){}
        }   
        
        // out  = out .* bottom_blobs[i]
        for (size_t b = 2; b < bottom_blobs.size(); b++){
            
        }

    }
    
    // 逐元素相加
    if (op_type == Operation_SUM)
    {
        
    }
    
    // 逐元素计算最大值
    if (op_type == Operation_SUM)
    {
        
    }

}
3、总结

本次学习了NCNN中的binaryop、eltwise操作,学会了两个向量之间的操作还能用模板实现,省去了不少的代码量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/490343.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java算法第32天 | 贪心算法 part02 ● 122.买卖股票的最佳时机II ● 55. 跳跃游戏 ● 45.跳跃游戏II

122.买卖股票的最佳时机II 本题中理解利润拆分是关键点&#xff01; 不要整块的去看&#xff0c;而是把整体利润拆为每天的利润。假如第 0 天买入&#xff0c;第 3 天卖出&#xff0c;那么利润为&#xff1a;prices[3] - prices[0]。 相当于(prices[3] - prices[2]) (prices[…

[医学分割大模型系列] (3) SAM-Med3D 分割大模型详解

[医学分割大模型系列] -3- SAM-Med3D 分割大模型解析 1. 特点2. 背景3. 训练数据集3.1 数据集收集3.2 数据清洗3.3 模型微调数据集 4. 模型结构4.1 3D Image Encoder4.2 3D Prompt Encoder4.3 3D mask Decoder4.4 模型权重 5. 评估5.1 评估数据集5.2 Quantitative Evaluation5.…

李宏毅【生成式AI导论 2024】第1讲:生成式AI是什么?

什么是人工智能? 人工智慧可以说是一个目标,是一个我们想要达到的目标。它不是一个单一的技术,并没有哪一个技术叫做人工智慧,人工智慧是一个目标。 什么是生成式人工智能? 生成式人工智慧是要机器产生复杂而有结构的物件。比如说文章,文章也有一连串的文字所构成的。比…

[蓝桥杯 2023 省 A] 颜色平衡树:从零开始理解树上莫队 一颗颜色平衡树引发的惨案

十四是一名生物工程的学生&#xff0c;他已经7年没碰过信息学竞赛了&#xff0c;有一天他走在蓝桥上看见了一颗漂亮的颜色平衡树&#xff1a; ​​​​​​​[蓝桥杯 2023 省 A] 颜色平衡树 - 洛谷 十四想用暴力解决问题&#xff0c;他想枚举每个节点&#xff0c;每个节点代表…

死锁-写一个死锁的例子

死锁-写一个死锁的例子 什么是死锁死锁产生的条件如何避免死锁死锁预防死锁避免死锁检测死锁解除鸵鸟策略 手写一个死锁的例子 https://blog.51cto.com/u_16213642/8352155 什么是死锁 在两个或者多个并发进程中&#xff0c;如果每个进程持有某种资源而又等待其它进程释放它或…

代码随想录算法训练营第三十五天|860. 柠檬水找零,406. 根据身高重建队列,452. 用最少数量的箭引爆气球

860. 柠檬水找零 题目 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾…

C语言例4-8:格式字符c的使用例子

代码如下&#xff1a; //格式字符c的使用例子 #include<stdio.h> int main(void) {char c A;int i 65;printf("c%c,%5c,%d\n",c,c,c);printf("i%d,%c\n",i,i);return 0; } 结果如下&#xff1a;

22.WEB渗透测试-BurpSuite(一)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;21.WEB渗透测试-HTTP协议&#xff08;下&#xff09;-CSDN博客 工具的使用需要先搭建靶场…

水牛社:宝妈副业,不仅赚钱更成长:一段充实之旅

大家好&#xff01;作为一名90后的全职宝妈&#xff0c;今天非常荣幸能够与大家分享我的互联网赚钱经验。趁着宝宝午睡的宝贵时光&#xff0c;我抓紧写下了这篇文章&#xff0c;虽时间紧凑&#xff0c;但我会力求内容清晰明了。 大约从2022年4月开始&#xff0c;我踏上了互联网…

天工AI搜索引擎

相信正在看autosar架构相关内容的人来说&#xff0c;对于autosar相关知识或者配置项的生涩知识点可谓是苦之久矣&#xff0c;这个时候一个好的搜索引擎能带来的帮助太大了&#xff0c;不管是平时百度还是看文档都需要大量的时间去检索自己真正想知道的信息&#xff0c;偶然间发…

Chromium 通过IDL方式添加扩展API,并且在普通网页也可以调用

先严格按照Chromium 通过IDL方式添加扩展API - 知乎、chromium 41 extensions 自定义 api 接口_chromium自定义扩展api-CSDN博客 里提到的方式&#xff0c;加入扩展api。然后最关键的地方来了&#xff1a; 到src\extensions\renderer\native_extension_bindings_system.cc \sr…

Springboot+vue的企业质量管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的企业质量管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

堆排序(六大排序)

前面博客已经分享过堆的知识了&#xff0c;今天我们来分享堆排序。 堆排序 堆排序(Heapsort)是指利用堆积树&#xff08;堆&#xff09;这种数据结构所设计的一种排序算法&#xff0c;它是选择排序的一种。它是通过堆来进行选择数据。 ★★★需要注意的是排升序要建大堆&#…

Django(三)-搭建第一个应用(2)

一、编写更多视图 问题详情页——展示某个投票的问题和不带结果的选项列表。问题结果页——展示某个投票的结果。投票处理器——用于响应用户为某个问题的特定选项投票的操作。 # 1.问题详情页&#xff1a;展示某个投票的问题和不带结果的选项列表 def detail(request,questi…

2024年【道路运输企业安全生产管理人员】考试及道路运输企业安全生产管理人员考试技巧

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 道路运输企业安全生产管理人员考试是安全生产模拟考试一点通总题库中生成的一套道路运输企业安全生产管理人员考试技巧&#xff0c;安全生产模拟考试一点通上道路运输企业安全生产管理人员作业手机同步练习。2024年【…

鸿蒙OS开发实例:【demo选择列表限定数量】

效果图&#xff1a; 示例代码 // 使用 DevEco Studio 3.1.1 Release 及以上版本&#xff0c;API 版本为 api 9 及以上。 // 主要功能及注意事项&#xff1a; // 该组件展示了一个乘客选择列表。列表中的每个项目包含一个复选框和对应的乘客姓名&#xff0c; // 用户点击任意一…

QT 控件有突出感,定义控件边框

QT 控件有突出感&#xff0c;定义控件边框 1.设计师页面 在flat部分选中 这个时候按钮会失去边框如下图&#xff1a; 然后在.cpp文件中写入代码&#xff1a; ui->pushButton->setStyleSheet("border: 1px solid gray;");按钮就有了新的边框&#xff1a;

2024年大模型面试准备(四):大模型面试必会的位置编码(绝对位置编码sinusoidal,旋转位置编码RoPE,以及相对位置编码ALiBi)

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…

Share-ChatGPT官网UI/文件上传/联网搜索/GPTS 一并同步

地址&#xff1a;Share-ChatGPT 文章目录 界面UI&#xff0c;GPTS&#xff0c;读论文&#xff0c;数据分析&#xff0c;写论文视频演示仓库地址 界面 支持多账号同时管理&#xff0c;合理利用资源&#xff1a; UI&#xff0c;GPTS&#xff0c;读论文&#xff0c;数据分析&a…

Redis入门到实战-第十弹

Redis实战热身Geospatial篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、消息代…