[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_NEONfor (; 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_NEONfor (; 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 blobconst 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 blobconst 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); // 0const float* ptr1 = bottom_blob1.channel(q); // 1float* 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.mzph.cn/news/772649.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

垃圾回收:垃圾回收器

目录 垃圾回收器 评估GC的性能指标 7种典型的垃圾回收器 Serial回收器&#xff1a;串行回收 ParNew回收器&#xff1a;并行回收 Parallel回收器&#xff1a;吞吐量优先 CMS回收器&#xff1a;低延迟 G1回收器&#xff1a;区域化分代式 G1回收过程1-年轻代GC G1回收过程…

自信当众讲话:从紧张到自如的转变之路

自信当众讲话&#xff1a;从紧张到自如的转变之路 在人生的舞台上&#xff0c;当众讲话是每个人都可能面对的挑战。然而&#xff0c;对于许多人来说&#xff0c;站在众人面前讲话却是一件令人紧张甚至恐惧的事情。这种紧张感往往源于对自我能力的怀疑&#xff0c;对未知的恐惧…

PyTorch----torch.nn.Linear()函数

torch.nn.Linear是PyTorch中的一个模块&#xff0c;用于在神经网络中实现完全连接层。它表示输入张量的一个线性变换通过将它与一个权矩阵相乘并加上一个偏置项。 下面是torch.nn.Linear的语法: torch.nn.Linear(in_features, out_features, biasTrue)参数&#xff1a; in_f…

neo4j使用详解(二、cypher语法基础——最全参考)

1.简介 Cypher是一种声明式图数据库查询语言&#xff0c;它具有丰富的表现力&#xff0c;能高效地查询和更新图数据。具有以下特点&#xff1a; 是一种声明性模式匹配语言遵循SQL语法的语法是非常简单且人性化、可读的格式 语法详情请看博主其他博客&#xff1a; 一、cypher插…

JS——9大陷阱

一、警惕A>X>B写法 3>2>1 返回值为false&#xff08;原因&#xff1a;3>2为true&#xff0c;会默认转成数字1&#xff0c;1>1为false&#xff09; 1<4<3 返回值为true&#xff08;原因&#xff1a;1<4为true&#xff0c;会默认转成数字1&#xff…

Leetcode第35题:搜索插入位置

代码实现 class Solution:def searchInsert(self, nums: List[int], target: int) -> int:if target in nums:return nums.index(target)index0for num in nums:if target>num:index1else:nums.insert(index,target)breakreturn index解题思路:先判断target是否在nums中…

【简单随机抽样】

文章目录 什么是简单随机抽样&#xff1f;简单随机抽样的步骤简单随机抽样的优点简单随机抽样的缺点 什么是简单随机抽样&#xff1f; 简单随机抽样是指从总体中以相同的概率随机选择一定数量的样本单元组成样本的一种方法。它要求每个样本单元被抽中的机会是均等的。每一个样…

滴滴出行高级Node.js开发工程师笔试题2024

今天参加了一个滴滴出行的Node.js岗位面试&#xff0c;一面为腾讯视频面试&#xff0c;俩个面试官。面试官比较深入问一些你过去做个的项目&#xff0c;问你解决了哪些棘手的问题。 还有就是他们比较关注性能优化&#xff0c;会问你们现在项目的峰值QPS是多少&#xff0c;如何进…

ChatGPT之道:AI与编程的完美融合

ChatGPT无限次数:点击直达 ChatGPT之道&#xff1a;AI与编程的完美融合 引言 随着人工智能技术的发展&#xff0c;AI在各个领域都展现出了惊人的应用潜力。在编程领域&#xff0c;AI的应用也是愈发广泛。其中&#xff0c;ChatGPT作为一种基于大型神经网络的自然语言生成模型&…

2024第二届经济管理、贸易与信息技术创新国际会议(ICEMITI2024)

2024第二届经济管理、贸易与信息技术创新国际会议&#xff08;ICEMITI2024&#xff09; 会议简介 2024第二届经济管理、贸易与信息技术创新国际会议&#xff08;ICEMITI2024&#xff09;将在中国郑州举行。这是一个重要的学术会议&#xff0c;旨在讨论当前经济管理、贸易和信…

[DDD] ValueObject的一种设计落地及应用

目录 前言一、ValueObject二、设计2.1 接口2.2 单一值ValueObject2.3 单一字符串ValueObject 三、实现3.1 示例3.1.1 PhoneNumber3.1.2 SocialCreditCode 四、使用4.1 异常处理4.2 Json 反/序列化4.2.1 请求体4.2.2 HTTP接口4.2.3 用例 4.3 JPA/MyBatis4.3.1 Converter或TypeHa…

vue响应式基础

声明响应式状态​ ref()​ 在组合式 API 中&#xff0c;推荐使用 ref() 函数来声明响应式状态&#xff1a; import { ref } from vueconst count ref(0) ref() 接收参数&#xff0c;并将其包裹在一个带有 .value 属性的 ref 对象中返回&#xff1a; const count ref(0)c…

202449读书笔记|《悦读诗 乐生活》——跌倒,是生活的偶然 发光,是生命的态度

202449读书笔记|《悦读诗 乐生活》——跌倒&#xff0c;是生活的偶然 发光&#xff0c;是生命的态度 第一篇 全都喜欢上第二篇 生如夏花第三篇 “希望”是带有羽毛之物第四篇 我来到这世界…… 《悦读诗 乐生活&#xff1a;小学生经典现代诗歌鉴赏集》赵迁编著&#xff0c;是小…

【JavaEE初阶系列】——多线程案例三——定时器

目录 &#x1f6a9;定时器是什么 &#x1f6a9;标准库中的定时器 &#x1f6a9;自定义定时器 &#x1f388;构造Task类 &#x1f4dd;相对时间和绝对时间 &#x1f388;构造MyTime类 &#x1f4dd;队列空和队列不为空 &#x1f4dd;wait(带参)解决消耗资源问题 &#…

多列数据表,复制插入一条有唯一索引限制的数据

假如你有一张表&#xff08;列简单列举四个&#xff0c;实际可能十好几二十好几的字段&#xff09; idnameagesex1zhangsan10男2lisi20男3wangermazi30男4xiaotaoqi40男 你想复制id4的数据&#xff0c;只把id变为6其他信息不变&#xff0c;来给自己用&#xff0c;只有主键变更…

docker配置镜像加速后容器和镜像消失

一、问题描述 根据阿里云给docker配置镜像加速器 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://gt6j98xi.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl rest…

NO9 蓝桥杯单片机串口通信之进阶版

1 回顾 串口通信的代码编写结构还是与中断一样&#xff0c;不同的是&#xff1a; 初始中断函数条件涉及到串口通信相关的寄存器和定时器1相关的寄存器&#xff08;定时器1用于产生波特率&#xff09;&#xff0c;但初始条件中的中断寄存器只考虑串口通信而不考虑定时器1。 v…

基于springboot+vue+Mysql的网上图书商城

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

多功能的RSS工具RSS Funnel

什么是 RSS Funnel &#xff1f; RSS Funnel 是一个模块化的 RSS 处理管道系统。它可以以多种方式操作 RSS/Atom 源。 例如&#xff1a; 提取完整内容从 HTML 页面生成 RSS 订阅删除不需要的元素和文本使用正则表达式进行文字编辑或替换保留或删除与关键词或模式匹配的文章突出…

微服务篇:设计一个注册中心和配置中心需要从哪些方面入手

注册中心 设计一个注册中心时&#xff0c;需要关注多个关键方面&#xff0c;以确保其稳定性、可靠性、性能和可扩展性。以下是一些重要的考虑因素&#xff1a; 服务发现机制&#xff1a;注册中心的核心功能是允许服务相互发现。这意味着当一个服务实例启动时&#xff0c;它需…