[NCNN学习笔记]-0

1、前言

经过前面对NEON基础的学习,对NEON有了一定的了解, 现在正准备逐步开始学习NCNN,关于NCNN的入门介绍可以参考如下链接。

2 、学习NCNN

下面会逐步学习NCNN中src/layer/arm 文件夹中关于NEON的代码,只提取部分关于NEON的代码进行学习。

2.1 absval_arm.cpp

先从一个简单的实现学习吧,这个文件主要是用来对数据进行取绝对值的操作。在学习之前先看一个简单的在NEON中取绝对值的例子

#include <arm_neon.h>
#include <iostream>
#include <vector>
using namespace std;
#include <arm_neon.h>
int main(){vector<float> data = {-1,-2,1,3};float32x4_t p0 = vld1q_f32(data.data());p0 = vabsq_f32(p0); vst1q_f32(data.data(), p0);for(auto d : data){cout << d << endl;   // 1,2,1,3}return 0;
}

下面是NCNN中的实现,整体也十分简单,主要是对剩余向量进行处理方式。

int AbsVal_arm::forward_inplace(Mat& bottom_top_blob, const Option& opt) const
{int w = bottom_top_blob.w;int h = bottom_top_blob.h;int d = bottom_top_blob.d;int channels = bottom_top_blob.c;int elempack = bottom_top_blob.elempack;int size = w * h * d * elempack; // 数据类型占用的寄存器个数,参考 https://github.com/Tencent/ncnn/wiki/element-packing#pragma omp parallel for num_threads(opt.num_threads)for (int q = 0; q < channels; q++){float* ptr = bottom_top_blob.channel(q);int i = 0;
#if __ARM_NEON// 将长度为16的整数倍的数据进行向量化加速for (; i + 15 < size; i += 16){float32x4_t _p0 = vld1q_f32(ptr); // 提取4个float32的值到q寄存器float32x4_t _p1 = vld1q_f32(ptr + 4);float32x4_t _p2 = vld1q_f32(ptr + 8);float32x4_t _p3 = vld1q_f32(ptr + 12);_p0 = vabsq_f32(_p0);        // 计算绝对值_p1 = vabsq_f32(_p1);_p2 = vabsq_f32(_p2);_p3 = vabsq_f32(_p3);vst1q_f32(ptr, _p0);      // 结果写回vst1q_f32(ptr + 4, _p1);vst1q_f32(ptr + 8, _p2);vst1q_f32(ptr + 12, _p3);ptr += 16;}// 处理剩余数据// 处理8的倍数长度的数据for (; i + 7 < size; i += 8){float32x4_t _p0 = vld1q_f32(ptr);float32x4_t _p1 = vld1q_f32(ptr + 4);_p0 = vabsq_f32(_p0);_p1 = vabsq_f32(_p1);vst1q_f32(ptr, _p0);vst1q_f32(ptr + 4, _p1);ptr += 8;}// 处理4的倍数长度的数据for (; i + 3 < size; i += 4){float32x4_t _p = vld1q_f32(ptr);_p = vabsq_f32(_p);vst1q_f32(ptr, _p);ptr += 4;}
#endif // __ARM_NEON// c语言实现方式for (; i < size; i++){*ptr = *ptr > 0 ? *ptr : -*ptr;ptr++;}}return 0;
}
2.2 arm_activation.h

这个文件中完成了部分激活函数在NEON上的实现,在学习这些激活函数之前,先了解一些NEON中基本的api用法吧。

  • vcleq_f32(v1,v2)逐元素比较,将v1小于v2的位置记为4294967295,反之记为0
float32x4_t _v = {-1, 2, -3, 4};
float32x4_t _zero = vdupq_n_f32(0.f);
uint32x4_t _lemask = vcleq_f32(_v, _zero);  {4294967295,0,4294967295,0}
  • vbslq_f32(mask,v1,v2) 根据mask中的元素,从v1和v2中挑选值,为4294967295选取v1中的元素,反之选取V2中的元素
float32x4_t a = {1,2,3,4};
float32x4_t b = {11,12,13,14};
uint32x4_t _lemask  = {0,0,4294967295,4294967295};
auto res = vbslq_f32(_lemask, a, b); // {11,12,3,4}
  • vnegq_f32, 取相反数
float32x4_t v1 = {1,2,4,8};
auto res = vnegq_f32(v1); // {-1,-2,-4,-8}
  • vrecpeq_f32,取倒数,损失较大,需要额外操作增加精度
float32x4_t v1 = {1,2,4,8};
auto res = vrecpeq_f32(v1);  // 0.98047 0.499023 0.249512 0.124756// vrecpsq_f32(a,b) =  2 - a * b
res = vmulq_f32(vrecpsq_f32(v1, res), res) // 0.999996 0.499998 0.249999 0.125
res = vmulq_f32(vrecpsq_f32(v1, res), res)  // 1 0.5 0.25 0.125

下面开始对arm_activation.h 的几个激活函数开始学习

static inline float32x4_t activation_ps(float32x4_t _v, int activation_type, const ncnn::Mat& activation_params){if (activation_type == 1)  // relu{	const float32x4_t _zero = vdupq_n_f32(0.f);_v = vmaxq_f32(_v, _zero);  // 将小于0的元素变成0  }else if (activation_type == 2){	const float32x4_t _zero = vdupq_n_f32(0.f);const float32x4_t _slope = vdupq_n_f32(activation_params[0]);   // 斜率const uint32x4_t _lemask = vcleq_f32(_v, _zero)float32x4_t _ps = vmulq_f32(_v, _slope);_v = vbslq_f32(_lemask, _ps, _v);  // 通过_lemask从 _ps和_v中挑选数据}    else if (activation_type == 3){const float32x4_t _min = vdupq_n_f32(activation_params[0]);const float32x4_t _max = vdupq_n_f32(activation_params[1]);_v = vmaxq_f32(_v, _min);_v = vminq_f32(_v, _max);      // 直接限制最大最小值}    else if (activation_type == 4){_v = sigmoid_ps(_v);           // sigmoid}else if (activation_type == 5)  // mish{_v = vmulq_f32(_v, tanh_ps(log_ps(vaddq_f32(exp_ps(_v), vdupq_n_f32(1.f)))));    // mish}else if (activation_type == 6)   // hardswish{const float alpha = activation_params[0];const float beta = activation_params[1];const float32x4_t _zero = vdupq_n_f32(0.f);const float32x4_t _one = vdupq_n_f32(1.f);float32x4_t _ans = vdupq_n_f32(beta); _ans = vmlaq_n_f32(_ans, _v, alpha);  // beta + (_v * alpht)_ans = vmaxq_f32(_ans, _zero);  _ans = vminq_f32(_ans, _one); _v = vmulq_f32(_ans, _v);      //  (beta + (_v * alpht)) * _v}}
3、总结

本次学习了NCNN中求绝对值以及部分激活函数在NEON上的实现,但仍存在部分问题,例如tanh_ps中的许多数值计算的部分,后面有机会再进行详细的学习。

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

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

相关文章

JS01-JavaScript基础

JavaScript基础 引入js方式 直接使用 <script>alert("Hello javascript!") </script>引入外部文件 <script src"../js/01.js"></script>数组 let name [甘雨,申鹤,钟离] console.log(name) console.log(name[0])数字类型 let a…

你开发的系统国际化了吗?

亲爱的朋友们&#xff0c;周一好&#xff0c;新的一周&#xff0c;精神满满。 在开发Spring Boot应用时&#xff0c;接口的参数校验是一个重要的环节&#xff0c;它确保了数据的完整性和准确性。而国际化处理则使得应用能够支持多种语言&#xff0c;提升了用户体验。 一、参数…

ev多域名ssl证书2000元一年送一月

多域名SSL证书是一种特殊的数字证书产品。多域名SSL证书可以同时保护多个独立的域名站点&#xff0c;这些域名站点可以是多个主域名、子域名&#xff0c;多域名SSL证书可以为它们提供传输数据加密服务以及身份认证服务。EV多域名SSL证书具有更高的安全性&#xff0c;所以一些金…

蓝桥集训之母亲的牛奶

蓝桥集训之母亲的牛奶 核心思想&#xff1a; 暴搜 bfs/dfs bfs: 将每种情况搜索一遍 #include <cstdio>#include <algorithm>#include <cstring>#include <iostream>using namespace std;const int N 21;int A,B,C;struct Node{int a,b,c;}q[N*N*…

深入了解主播美颜技术:从美颜SDK到实时美颜算法

在当今数字化时代&#xff0c;直播行业蓬勃发展&#xff0c;成为了人们日常生活中不可或缺的一部分。而在直播中&#xff0c;主播的形象对于吸引观众、提升观看体验至关重要。为了呈现更加美好的形象&#xff0c;主播们常常会借助美颜技术。从最初的美颜SDK到如今的实时美颜算法…

PS学习-对象选择抠图,覆盖

之前使用通道抠图抠大树 对象 选择 ctrlj 水平居中 选区羽化 选择加选按住shift&#xff0c;减选按住alt 单个选择按住shift是变正方形&#xff0c;或者椭圆变成圆 覆盖 想把天空都变成白色 选区羽化ctrlj 复制粘贴几个往上放 复制了十来个&#xff0c;遮住就行 首先存储为PS…

二叉搜索树题目:将有序链表转换为二叉搜索树

文章目录 题目标题和出处难度题目描述要求示例数据范围 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;将有序链表转换为二叉搜索树 出处&#xff1a;109. 将有序链表转换为二叉搜索树 难度 5 级 题目描述 要求 …

SPA单页面有哪些优缺点

单页面应用&#xff08;SPA&#xff09;作为一种现代化的Web应用程序架构&#xff0c;在当今互联网时代越来越受到开发者和用户的欢迎。它通过在加载应用程序时只加载一次页面&#xff0c;实现页面内容的动态更新&#xff0c;带来了许多优势和挑战。本文将深入探讨SPA的优点和缺…

【数据库】MySQL表的增删改查

文章目录 一、CRUD二、2. 新增&#xff08;Create&#xff09; 一、CRUD 注释&#xff1a;在SQL中可以使用“–空格描述”来表示注释说明 CRUD 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写 二、2. 新增&#xff08;Create&#xff09; …

【kaggle竞赛】从手写图像数据集中正确识别数字

1. 题目&#xff1a; 在本次比赛中&#xff0c;您的目标是从数以万计的手写图像数据集中正确识别数字。 1.1. Goal 目标✨ 本次比赛的目标是拍摄手写个位数的图像&#xff0c;并确定该数字是什么。 对于测试集中的每个标签&#xff0c;您都应该预测正确的标签。 本次比赛的…

SpringCloudLoadBalancer入门与实战系列

目录 一、什么是LoadBalancer&#xff1f; 1.1 负载均衡的分类 1.2 负载均衡策略 二、 为什么要学习 Spring Cloud Balancer &#xff1f; 三、 Spring Cloud LoadBalancer 内置的两种负载均衡策略 3.1 轮询负载均衡策略&#xff08;默认的&#xff09; 3.2 随机负载均衡…

科研学习|研究方法——案例研究方法

目录 1.案例研究的起源 2.案例研究的说服力 2.1 外界质疑 2.1.1 样本数量太小 2.1.2 选择的样本带有偏倚 2.1.3 选择的案例太少 2.1.4 无法验证 2.2 重要作用 2.2.1 激发研究 2.2.2 启发灵感 2.2.3 提供佐证 3.案例研究的内容 4.案例研究质量的评价 5.案例研究的优缺点 6.MI…

wsl or 虚拟机 安装

1.wsl2安装 WSL全称Windows Subsystem for Linux&#xff0c;是微软开发的适用于Linux的Windows子系统 如今已经有两代了&#xff1a; 所以用的多的还是wsl2。 安装前需要先去设置启用或关闭Windows功能&#xff1a; 打开适用于linux的子系统和虚拟机平台。 Microsoft Store里…

【实验01 扩展实验】C#桌面项目:简易计算器

【实验要求】 &#xff08;1&#xff09;新建一个C#桌面项目Calc&#xff0c;实现简易计算器功能&#xff0c;界面如图1所示。 &#xff08;2&#xff09;计算方式&#xff1a;通过点击对应的按钮&#xff0c;输入第1个数&#xff08;可以是整数或实数&#xff09;&#xff0c…

微服务:高并发带来的问题的容错方案

1.相关脚本&#xff08;陈天狼&#xff09; 启动nacos客户端&#xff1a; startup.cmd -m standalone 启动sentinel控制台&#xff1a; # 直接使⽤jar命令启动项⽬(控制台本身是⼀个SpringBoot项⽬) java -Dserver.port8080 -Dcsp.sentinel.dashboard.serverlocalhost:808…

【复现】【免费】基于多时间尺度滚动优化的多能源微网双层调度模型

目录 主要内容 部分代码 结果一览 1.原文结果 2.程序运行结果 下载链接 主要内容 该模型参考《Collaborative Autonomous Optimization of Interconnected Multi-Energy Systems with Two-Stage Transactive Control Framework》&#xff0c;主要解决的是一个…

03|提示工程(下):用思维链和思维树提升模型思考质量

什么是 Chain of Thought CoT这个概念来源于学术界&#xff0c;是谷歌大脑的Jason Wei等人于2022年在论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models&#xff08;自我一致性提升了语言模型中的思维链推理能力&#xff09;》中提出来的概念。它…

2024-Spring IOC 和 AOP源码分析(上篇)

**前言&#xff1a;**笔者最近面了几次大厂。。。开局Spring源码暴击 之前看过忘了写篇总结。。。 1、介绍一下Spring 核心组件&#xff1a; 常用模块&#xff1a; 常用注解&#xff1a; 2、说一下SpringIOC原理 概念&#xff1a;Spring 通过一个配置文件描述 Bean 及 B…

【Godot4自学手册】第二十六节用GPUParticles2D节点实现地宫入口的奇异光芒

我们的主人公与NPC对话完成后&#xff0c;夜晚来临&#xff0c;在城北有一处乱石岗&#xff0c;出现了奇异光芒&#xff0c;这是地宫的入口&#xff0c;但是有一妖怪把守&#xff0c;我们必须消灭妖怪后才可发现地宫入口。这一节&#xff0c;主要记录利用粒子系统GPUParticles2…

Python和R的区别是什么,Python与R的应用场景是什么?

如果你这么问&#xff0c;那么你可能正站在数据科学的起点。对于志在成为数据专业人员的你来说&#xff0c;学习编程是无疑的。我想行你早就听过Python 与R的比较之声&#xff0c;并在选择中感到困惑。在此&#xff0c;我想说&#xff0c;也算是一种安慰吧&#xff1a;对于语言…