当前位置: 首页 > news >正文

arm 内联汇编基础

一、 Arm架构寄存器体系熟悉

基于arm neon 实现的代码有 intrinsic 和inline assembly 两种实现。

1.1 通用寄存器

arm v7 有 16 个 32-bit 通用寄存器,用 r0-r15 表示。

arm v8 有 31 个 64-bit 通用寄存器,用 x0-x30 表示,和 v7 不一样的是,这 31 个寄存器也可以作为 32-bit 寄存器来用,用 w0-w30 表示,其中 wn 是 xn 的低 32 位,如下图所示:

函数前四个参数,会按顺序被放入寄存器 r0-r3(w0-w3), 剩下会采用压栈的方式保存

寄存器寄存器别名用途
r0a1第一个函数参数: Scratch 寄存器
r1a2第二个函数参数: Scratch 寄存器
r2a3第三个函数参数: Scratch 寄存器
r3a4第四个函数参数: Scratch 寄存器
r4v1寄存器变量
r5v2寄存器变量
r6v3寄存器变量
r7v4寄存器变量
r8v5寄存器变量
r9v6 rfp寄存器变量 实际的帧指针
r10sl栈接线
r11fp参数指针
r12ip临时
r13sp栈指针
r14lr连接寄存器
r15pc程序计数

1.2 向量寄存器

armv7 包含 16 个 128-bit 向量寄存器,用 q0-q15 表示,其中每个 q 寄存器又可以拆分成两个 64-bit 向量寄存器来用,用 d0-d31 来表示。

armv8 则有更多的向量寄存器,32 个 128-bit 向量寄存器,用 v0-v31 来表示。

每个 128-bit 向量寄存器可以当做:

  • 包含 2 个 64-bit 元素的向量寄存器来用,表达形式是 vn.2d;

  • 包含 4 个 32-bit 元素的向量寄存器来用,表达形式是 vn.4s;

  • 包含 8 个 16-bit 元素的向量寄存器来用,表达形式是 vn.8h;

  • 包含 16 个 8-bit 元素的向量寄存器来用,表达形式是 vn.16b;

或者每个向量寄存器也可以只用低 64-bit:

  • 1 个 64-bit 元素的向量寄存器来用,表达形式是 vn.1d;

  • 2 个 32-bit 元素的向量寄存器来用,表达形式是 vn.2s;

  • 4 个 16-bit 元素的向量寄存器来用,表达形式是 vn.4h;

  • 8 个 8-bit 元素的向量寄存器来用,表达形式是 vn.8b;

利用指令集加速,无一例外地要利用专用寄存器这种在 CPU 上稀少、宝贵的资源。专用寄存器用少了 CPU 的性能不能充分发挥,用多了则会产生寄存器溢出 (Register Spilling)(https://blog.csdn.net/qq_41112170/article/details/90286091) 这种对性能有明显负面影响的问题。因此,我们至少需要了解在编写 Neon 代码时,有多少个专用寄存器可供利用。

二、内联汇编

2.1 基础写法

__asm__ qualifiers ( // 汇编代码部分 
: OutputOperands //在内联汇编代码中被修改的变量列表 
: InputOperands //在内联汇编代码中用到的变量列表 
: Clobbers //在内联汇编代码中用到的寄存器列表 );

qualifiers:一般是用 volatile 修饰词 ,关键字__volatile__:也可以写“volatile”,理由同上;__volatile__是可选的,作用是禁止编译器对后面汇编指令再进行优化。一般自己写的汇编,考虑性能,已经做过优化,编译器再优化的话,可能效果反而更差,所以通常还是带上这个关键字;

括号里:是真正的汇编代码,主要有四部分组成,第一部分是具体的汇编代码,是必须的;其他三个为辅助参数,可选;各部分之间用冒号“:”分割,即使参数为空,也要加冒号;

  • OutputOperands:在内联汇编中会被修改的变量列表,变量之间用','隔开, 每个变量的格式是: [asmSymbolicName] "constraint"(cvariablename) cvariablename:表示变量原来的名字; asmSymbolicName:表示变量在内联汇编代码中的别名,一般和 cvariablename 一样,在汇编代码中就可以通过%[asmSymbolicName]去使用该变量; constraint: 一般填=r,具体解释见文档[6]

  • InputOperands:在内联汇编中用到的所有变量列表,变量之间用','隔开, 每个变量的格式是: [asmSymbolicName] "constraint"(cexpression) 和输出不一样地方是,首先要按OutputOperands列表的顺序再列一遍,但是constraint用数字代替从0开始,然后才是写其他只读变量,只读变量constraintr

  • Clobbers: 一般是"cc", "memory"开头,然后接着填内联汇编中用到的通用寄存器和向量寄存器 "cc"表示内联汇编代码修改了标志寄存器; "memory"表示汇编代码对输入和输出操作数执行内存读取或写入操作(读写参数列表之一的变量指向的内存);

  • 输入列表 ("r" (some_input)): 这表明 some_input 是一个输入操作数,它的值在汇编执行前被读取。"r" 约束表示 some_input 被存储在某个寄存器中,具体哪个寄存器由编译器决定。

  • 输出列表 ("+r" (result)): 这表明 result 是一个输出操作数,它的值在汇编执行后被写回。"+" 约束表示 result 既可以作为输入也可以作为输出,汇编代码可以读取它的初始值,并在执行过程中更新它的值。

约束说明:

  • "r":将值放入任意一个可用的寄存器中。

  • "+r":将值放入任意一个可用的寄存器中,并且该寄存器在操作后还会被写回,即它既可以作为输入也可以作为输出。

  • "+w":类似于 "+r",但表示该值在汇编代码中可能会被修改,并且修改后的值需要写回原始变量。

  • "m":表示该值应该被加载到内存地址中,通常与指针一起使用。

asm("mov %0,%1":"+r"(val1):"r"(val2):);

由上面对指令语法的描述进行分析:

  • 输出操作数为 val1,属性为 "=r"。

  • 输入操作数为 val2,属性为 "r"

  • code 部分为 mov %1,%0,

  • %0 表示输入输出列表中的第一个操作数,

  • %1 表示操作数列表中提供的第二个操作数,以此类推,这条汇编指令很明显就是将第二个操作数(val2)赋值给第一个操作数(val1),所以最后的结果为 val1 = 222. 。

    int x=10, y;
    __asm__ ("mov %[in],%[out]": [out]"=r"(y): [in]"r"(x):
    );
    

如果指定了别名的话,那在汇编模板中,引用该变量,就可以使用别名,增加可读性,

2.2 操作符含义

  • "=" 表示只写,通常用于所有输出操作数的属性

  • "+" 表示读写,只能被列为输出操作数的属性,否则编译会报错。

  • & :只能用作输出

限定符

ARM指令集含义

r

通用寄存器

f

浮点寄存器

m

内存地址

为保持寄存器,内存数据一致性,提供三个类型

类型作用
r0…r15告诉编译器汇编代码中修改了寄存器r0…r15 (v8 是x, v)
cc告诉编译器汇编代码会导致CPU状态位的改变
memory告诉编译器汇编代码会读取或修改内存中某个地址存放的值

三、样例分析

对于刚入门优化的同学,改写汇编最好先从 C++ 改写 intrinsic 开始,然后再根据 intrinsic 的代码去改写汇编,一般 intrinsic 的指令和汇编指令都能对应的上,当然高手可以直接跳过去写汇编,但是对于新手建议还是一步步来。

而且比较重要的一点是,我认为 算法上的改进更为重要,假设你 C++ 算法层面代码已经定下来了,对于性能还想有更进一步的提升,那么可以尝试去写 neon 汇编(内联或者纯汇编),但不是说汇编是万能的,这个和你的优化经验还有算法本身的复杂度有很大关系,可能你吭哧坑次改完,发现还做了负优化,因为编译器本身也会做向量化。

3.1 两个数组加权和

第一个例子是两个数组对应元素加权和,例子足够简单,方便讲解改写汇编的一些思路。 下面代码为了可读性会相应的作简.

3.1.1 c++ 实现

bool arrWeightedAvg(const float *arr1,const float arr1Weight,const float *arr2,const float arr2Weight,const int len,float *resultArr) {for (int i = 0; i < len; ++i) {resultArr[i] = arr1[i] * arr1Weight + arr2[i] * arr2Weight;}return true;
}

3.1.2 改 intrinsic

对于 intrinsic 代码是兼容 armv7 和 v8 的,所以不同架构之间迁移也方便,不需要改代码:

bool arrWeightedAvgIntrinsic(const float *arr1,const float arr1Weight,const float *arr2,const float arr2Weight,const int len,float *resultArr) {int neonLen = len >> 2;int remain = len - (neonLen << 2);// 这里向量化主要思路是循环内每次// 处理4个元素的加权和// 所以neonLen是数组长度len除4// 而剩下的尾部元素按正常处理float *resultArrPtr  = resultArr;const float *arr1Ptr = arr1;const float *arr2Ptr = arr2;// 因为一次处理4个元素// 所以权值要拷贝4份放到// 一个float32x4_t类型变量中// 也相当于是128-bit向量寄存器float32x4_t arr1Wf4 = vdupq_n_f32(arr1Weight);float32x4_t arr2Wf4 = vdupq_n_f32(arr2Weight);for (int i = 0; i < neonLen; ++i) {// 分别读4个数组元素float32x4_t arr1f4 = vld1q_f32(arr1Ptr);float32x4_t arr2f4 = vld1q_f32(arr2Ptr);// eltwise乘法arr1f4 = vmulq_f32(arr1f4, arr1Wf4);arr2f4 = vmulq_f32(arr2f4, arr2Wf4);// eltwise加法float32x4_t resultf4 = vaddq_f32(arr1f4, arr2f4);// 写结果vst1q_f32(resultArrPtr, resultf4);arr1Ptr += 4;arr2Ptr += 4;resultArrPtr += 4;}// 处理尾部元素for (; remain > 0; remain --) {*resultArrPtr = (*arr1Ptr) * arr1Weight + (*arr2Ptr) * arr2Weight;resultArrPtr ++;arr1Ptr ++;arr2Ptr ++;}return true;
}

3.1.3 arm v7 内联汇编

bool arrWeightedAvgIntrinsic(const float *arr1,const float arr1Weight,const float *arr2,const float arr2Weight,const int len,float *resultArr) {int neonLen = len >> 2;int remain = len - (neonLen << 2);// 这里向量化主要思路是循环内每次// 处理4个元素的加权和// 所以neonLen是数组长度len除4// 而剩下的尾部元素按正常处理float *resultArrPtr  = resultArr;const float *arr1Ptr = arr1;const float *arr2Ptr = arr2;// 因为一次处理4个元素// 所以权值要拷贝4份放到// 一个float32x4_t类型变量中// 也相当于是128-bit向量寄存器float32x4_t arr1Wf4 = vdupq_n_f32(arr1Weight);float32x4_t arr2Wf4 = vdupq_n_f32(arr2Weight);for (int i = 0; i < neonLen; ++i) {// 分别读4个数组元素float32x4_t arr1f4 = vld1q_f32(arr1Ptr);float32x4_t arr2f4 = vld1q_f32(arr2Ptr);// eltwise乘法arr1f4 = vmulq_f32(arr1f4, arr1Wf4);arr2f4 = vmulq_f32(arr2f4, arr2Wf4);// eltwise加法float32x4_t resultf4 = vaddq_f32(arr1f4, arr2f4);// 写结果vst1q_f32(resultArrPtr, resultf4);arr1Ptr += 4;arr2Ptr += 4;resultArrPtr += 4;}// 处理尾部元素for (; remain > 0; remain --) {*resultArrPtr = (*arr1Ptr) * arr1Weight + (*arr2Ptr) * arr2Weight;resultArrPtr ++;arr1Ptr ++;arr2Ptr ++;}return true;
}

3.1.4 armv8 内联汇编

#ifdef __aarch64__  // armv8__asm__ volatile("mov   x0, %[arr1Weight]                  \n"   // 将weight1的值移动到通用寄存器x0中。"dup   v0.4s, w0                          \n"   //w0是x0的低32位, 复制值到向量寄存器v0中,当成4*32来使用。"mov   x1, %[arr2Weight]                  \n""dup   v1.4s, w1                          \n""0:                                       \n"    //循环结束条件,小于0."prfm  pldl1keep, [%[arr1Ptr], #128]      \n"    //预读取arr1地址开始的128bit 数据,就是4个32bit的数据。"ld1      {v2.4s}, [%[arr1Ptr]], #16      \n"    // 将数据加载到v2 向量寄存器中, 并且地址自增16个字节。"prfm  pldl1keep, [%[arr2Ptr], #128]      \n""ld1      {v3.4s}, [%[arr2Ptr]], #16      \n""fmul       v4.4s, v2.4s, v0.4s           \n"    //数组1和权重相乘。保存在v4 寄存器中。"fmul       v5.4s, v3.4s, v1.4s           \n"    // 数据2和权重相乘,保存在v5 寄存器中。"fadd       v6.4s, v4.4s, v5.4s           \n"   //将寄存器v4, v5的值相加, 保存在v6寄存器中。"subs       %[neonLen], %[neonLen], #1    \n"  // 对应 neonLen--  sub指令后面加个s表示会更新条件flag"st1    {v6.4s}, [%[resultArrPtr]], #16   \n" //将寄存器v6的结果写入到目的地址resultarrptr, 地址自增16字节。(4个数,一个数四字节)"bgt        0b                            \n"  //b跳转指令, gt 判断是不是大于0条件判断, 大于0, 跳转到0的位置。:[arr1Ptr]        "+r"(arr1Ptr),[arr2Ptr]        "+r"(arr2Ptr),[resultArrPtr]   "+r"(resultArrPtr),[neonLen]        "+r"(neonLen):[arr1Weight]     "r"(arr1Weight),[arr2Weight]     "r"(arr2Weight):"cc", "memory", "x0", "x1", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7");

反编译系统的编译文件,进行汇编代码对比,学习。

./llvm-objdump -d /home/lsq/wind/wind_develop_my/wind/build_android/src/backend/cpu/CMakeFiles/Wi

ndCPU.dir/kernel/neon/matmul_quant_test.cc.o

内联汇编的目的是进行汇编指令的优化,尽可能的直接操作寄存器,利用新特性,进行代码的加速。更多的指令需要查找官方文档进行学习。

3.2 汇编指令对应的机器码生成

.inst 0x4e80a4d8 是一个汇编指令,用于在 ARM 架构中直接插入机器码。这个指令的格式是 .inst <机器码>,其中 <机器码> 是一个 32 位或 64 位的十六进制值,表示一条机器指令。

具体来说,0x4e80a4d8 是一个 32 位的机器码。为了理解这个机器码是如何编码的,我们需要查看 ARMv8 指令集的文档,特别是 NEON 指令集的文档。

3.2.1 使用 LLVM 工具

可以安装 llvm 工具链,然后运行如下命令:、

echo "smmla v16.4s, v4.16b, v0.16b" | llvm-mc -arch=aarch64 -mattr=+neon,+i8mm -show-encoding

这将会输出汇编指令对应的机器码。如果没有安装 llvm-mc 工具,可以参考以下汇编器指令来生成机器码。

3.2.2 使用 GNU 汇编器

你可以使用 arm-none-eabi-as 工具来编译汇编代码并生成机器码。下面是一个示例:

echo ".arch armv8-a; smmla v16.4s, v4.16b, v0.16b" | arm-none-eabi-as -o - -a -

3.2.3 在线工具

https://armconverter.com/

3.2.4 反编译编译产物

./llvm-objdump -d /home/lsq/wind/wind_develop_my/wind/build_android/src/backend/cpu/CMakeFiles/WindCPU.dir/kernel/neon/matmul_quant_test.cc.o 反汇编结果:

".inst 0x4e80a490 \n" // smmla v16.4s, v4.16b, v0.16b //v0_01s// *y0_0".inst 0x4e81a4b5 \n" // smmla v21.4s, v5.16b, v1.16b //v0_0hs// *y0_1".inst 0x4e82a4da \n" // smmla v26.4s, v6.16b, v2.16b //v0_1ls// *y0_2".inst 0x4e83a4ff \n" // smmla v31.4s, v7.16b, v3.16b// v0_1hs

四、附录

https://medium.com/@warmap_/%E8%BD%AC-%E5%A6%82%E4%BD%95%E5%9C%A8c%E6%88%96c-%E4%BB%A3%E7%A0%81%E4%B8%AD%E5%B5%8C%E5%85%A5arm%E6%B1%87%E7%BC%96%E4%BB%A3%E7%A0%81-a3704e164de8

http://giantpandacv.com/project/%E9%83%A8%E7%BD%B2%E4%BC%98%E5%8C%96/AI%20%E7%A7%BB%E5%8A%A8%E7%AB%AF%E7%AE%97%E6%B3%95%E4%BC%98%E5%8C%96/%E7%A7%BB%E5%8A%A8%E7%AB%AFarm%20cpu%E4%BC%98%E5%8C%96%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E7%A7%BB%E5%8A%A8%E7%AB%AFarm%20cpu%E4%BC%98%E5%8C%96%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E7%AC%AC4%E5%BC%B9--%E5%86%85%E8%81%94%E6%B1%87%E7%BC%96%E5%85%A5%E9%97%A8/

相关文章:

arm 内联汇编基础

一、 Arm架构寄存器体系熟悉 基于arm neon 实现的代码有 intrinsic 和inline assembly 两种实现。 1.1 通用寄存器 arm v7 有 16 个 32-bit 通用寄存器&#xff0c;用 r0-r15 表示。 arm v8 有 31 个 64-bit 通用寄存器&#xff0c;用 x0-x30 表示&#xff0c;和 v7 不一样…...

Java语言程序设计——篇五(1)

数组 概述数组定义实例展示实战演练 二维数组定义数组元素的使用数组初始化器实战演练&#xff1a;矩阵计算 &#x1f4ab;不规则二维数组实战演练&#xff1a;杨辉三角形 概述 ⚡️数组是相同数据类型的元素集合。各元素是有先后顺序的&#xff0c;它们在内存中按照这个先后顺…...

【香橙派开发板测试】:在黑科技Orange Pi AIpro部署YOLOv8深度学习纤维分割检测模型

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ Orange Pi AIpro开发板相关介绍1.1 &#x1f393; 核心配置1.2 ✨开发板接口详情图1.3 ⭐️开箱展示 二、2️⃣配置开发板详细教程2.1 &#x1f393; 烧录镜像系统2.2 ✨配置网络2.3 ⭐️使用SSH连接主板 三、…...

集成学习在数学建模中的应用

集成学习在数学建模中的应用 一、集成学习概述&#xff08;一&#xff09;基知&#xff08;二&#xff09;相关术语&#xff08;三&#xff09;集成学习为何能提高性能&#xff1f;&#xff08;四&#xff09;集成学习方法 二、Bagging方法&#xff08;一&#xff09;装袋&…...

WebKit 的 Web SQL 数据库:现代浏览器的本地存储解决方案

WebKit 的 Web SQL 数据库&#xff1a;现代浏览器的本地存储解决方案 随着Web应用的不断发展&#xff0c;对本地存储的需求也日益增加。WebKit作为许多现代浏览器的核心引擎&#xff0c;提供了一种强大的本地存储解决方案&#xff1a;Web SQL 数据库。本文将详细探讨Web SQL 数…...

Yolo-World网络模型结构及原理分析(三)——RepVL-PAN

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1. 网络结构2. 特征融合3. 文本引导&#xff08;Text-guided&#xff09;4. 图像池化注意力&#xff08;Image-Pooling Attention&#xff09;5. 区域文本匹配&…...

代码随想录——一和零(Leetcode474)

题目链接 0-1背包 class Solution {public int findMaxForm(String[] strs, int m, int n) {// 本题m&#xff0c;n为背包两个维度// dp[i][j]:最多右i个0和j个1的strs的最大子集大小int[][] dp new int[m 1][n 1];// 遍历strs中字符串for(String str : strs){int num0 …...

力扣题解(组合总和IV)

377. 组合总和 Ⅳ 给你一个由 不同 整数组成的数组 nums &#xff0c;和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 思路&#xff1a; 本题实质上是给一些数字&#xff0c;让他们在满足和是targ…...

Postgresql主键自增的方法

Postgresql主键自增的方法 一.方法&#xff08;一&#xff09; 使用 serial PRIMARY KEY 插入数据 二.方法&#xff08;二&#xff09; &#x1f388;边走、边悟&#x1f388;迟早会好 一.方法&#xff08;一&#xff09; 使用 serial PRIMARY KEY 建表语句如下&#xf…...

【源码阅读】Sony的go breaker熔断器源码探究

文章目录 背景源码分析总结 背景 在微服务时代&#xff0c;服务和服务之间调用、跨部门调用都是很常见的事&#xff0c;但这些调用都存在很多不确定因素&#xff0c;如核心服务A依赖的部门B服务挂掉了&#xff0c;那么A本身的功能将会受到直接的影响&#xff0c;而这些都会影响…...

LeetCode题(66,69,35,88)--《c++》

66.加一 // // Created by wxj05 on 2024/7/20. // //法一 class Solution { public:vector<int> plusOne(vector<int>& digits) {bool carry true; // 进位标志for (int i digits.size() - 1; i > 0 && carry; --i) {digits[i] 1;carry digit…...

来参与“向日葵杯”全国教育仿真技术大赛~

可点击进行了解&#xff1a;“向日葵杯”全国教育仿真技术大赛 (sunmooc.cn) 本次大赛共分为四个赛道&#xff1a;自主命题赛道、教育知识图谱设计赛道、FPGA硬件扑克牌对抗赛道、EasyAR元宇宙空间设计赛道。 参赛对象 &#xff1a; 具有正式学籍的在校研究生&#xff0c;本科…...

SQL每日一题:删除重复电子邮箱

题干 表: Person -------------------- | Column Name | Type | -------------------- | id | int | | email | varchar | -------------------- id 是该表的主键列(具有唯一值的列)。 该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。 编写解决方案 删除 所有重复…...

3、宠物商店智能合约实战(truffle智能合约项目实战)

3、宠物商店智能合约实战&#xff08;truffle智能合约项目实战&#xff09; 1-宠物商店环境搭建、运行2-webjs与宠物逻辑实现3-领养智能合约初始化4-宠物领养实现5-更新宠物领养状态 1-宠物商店环境搭建、运行 https://www.trufflesuite.com/boxes/pet-shop 这个还是不行 或者…...

数据库系列

目录 一、数据库的概念和作用 1.数据库的特点 2.数据模型 二、数据库系统 1.数据库管理系统 2.数据库的基本操作 一、数据库的概念和作用 数据库是指长期存储在计算机内&#xff0c;有组织的、可共享的数据集合。它可视为一个电子化的文件柜&#xff0c;用来存储电子文件…...

极狐GitLab如何启用和配置PlantUML?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…...

Shell 构建flutter + Android 生成Apk

具体步骤 #shell 具体实现和说明如下: echo "build_start_apk!" echo "编译此脚本的前提条件如下:" #在Android 项目的主工程下,进入主工程文件夹,创建build-android 文件夹,在其文件夹下有build-android.sh文件,此文件就是整个文章的脚本内容(…...

如何用手机压缩视频?手机压缩视频方法来了

高清视频的大文件大小常常成为分享和存储的障碍&#xff0c;尤其是在数据流量有限或存储空间紧张的情况下。幸运的是&#xff0c;无论是智能手机还是个人电脑&#xff0c;都有多种方法可以帮助我们轻松压缩视频文件&#xff0c;以适应不同的需求和情境。本文将介绍如何在手机上…...

Linux下如何安装配置Elastic Stack日志收集系统

安装和配置Elastic Stack日志收集系统&#xff0c;包括Elasticsearch、Logstash和Kibana&#xff0c;是一个相对复杂的过程。本篇文章将逐步引导您完成整个过程。 安装Java Elasticsearch、Logstash和Kibana都需要Java运行环境。首先&#xff0c;您需要在Linux系统上安装Java…...

【深入C++】map和set的使用

文章目录 C 中的容器分类1. 顺序容器2. 关联容器3. 无序容器4. 容器适配器5. 字符串容器6. 特殊容器 set1.构造函数2.迭代器3.容量相关的成员函数4.修改器类的成员函数5.容器相关操作的成员函数 multiset1.equal_range map1.初始化相关的函数2.迭代器3.容量相关的成员函数4.访问…...

跟代码执行流程,读Megatron源码(二)训练入口pretrain_gpt.py

Megatron-LM默认支持GPT、T5、BERT等多个常见模型的预训练&#xff0c;当下大模型流行&#xff0c;故以pretrain_gpt.py为例做源码的走读。 一. 启动pretrain_gpt.py pretrain_gpt.py为GPT类模型的训练入口&#xff0c;它通过命令行形式被调用&#xff0c;其精确执行路径位于M…...

MATLAB练习题——矩阵(2)

逻辑运算 a [5 0.2 0 -8 -0.7 ]&#xff0c;在进行逻辑运算时&#xff0c;a 相当于什么样的逻辑量。 相当于 a[1 1 0 1 1] 角度运算 在 sin(x)运算中&#xff0c;x 是角度还是弧度&#xff1f; 在 sin(x)运算中&#xff0c;x 是弧度&#xff0c;MATLAB 规定所有…...

arm、AArch64、x86、amd64、x86_64 的区别

arm vs AArch64 vs amd64 vs x86_64 vs x86 的区别 当涉及到 CPU 的时候&#xff0c;有许多术语&#xff1a;AArch64、x86_64、amd64、arm 等等。了解它们是什么以及它们之间的区别。 当你查看数据表或软件下载页面时是否被 ARM、AArch64、x86_64、i386 等术语混淆&#xff1f;…...

【SpringBoot】 jasypt配置文件密码加解密

目前我们对yml配置文件中的密码都是明文显示&#xff0c;显然这不安全&#xff0c;有的程序员离职了以后可能会做一些非法骚操作&#xff0c;所以我们最好要做一个加密&#xff0c;只能让领导架构师或者技术经理知道这个密码。所以这节课就需要来实现一下。 我们可以使用jasypt…...

复杂网络的任意子节点的网络最短距离

复杂网络的任意子节点的网络最短距离 题目要求介绍 本文算法测试用的数据集为空手道俱乐部&#xff0c;其中空手道俱乐部的数据集可通过这个链接进行下载•http://vlado.fmf.uni-lj.si/pub/networks/data/Ucinet/UciData.htm#zachary 摘要 本文旨在解决复杂网络中任意子节点…...

(Qt) 文件读写基础

文章目录 &#x1f5c2;️前言&#x1f4c4;ref&#x1f4c4;访问标记&#x1f5c3;️enum 标记 &#x1f5c2;️Code&#x1f4c4;demo&#x1f4c4;分点讲解&#x1f5c3;️继承体系&#x1f5c3;️打开/关闭&#x1f5c3;️写&#x1f5c3;️读 &#x1f5c2;️END&#x1f…...

全产业布局对穿戴甲品牌连锁店的意义

对于美甲行业来说&#xff0c;穿戴甲虽然不是什么新生事物&#xff0c;但也就是近两年才流行开来。面对井喷的市场需求&#xff0c;相应的从业者&#xff0c;不管是品牌连锁店&#xff0c;还是做批发、外贸&#xff0c;美甲周边、亦或是OEM的&#xff0c;大家都忙得不亦乐乎&am…...

git的一些使用技巧(git fetch 和 git pull的区别,git merge 和 git rebase的区别)

最近闲来无聊&#xff0c;虽然会使用git操作&#xff0c;但是 git fetch 和 git pull 的区别&#xff0c;git merge 和 git rebase的区别只是一知半解&#xff0c;稍微研究一下&#xff1b; git fetch 和 git pull 的区别 git fetch git fetch 是将远程仓库中的改动拉到本地…...

展厅中控系统有哪些优势呢

格芬科技的展厅中控系统具有多方面的优势&#xff0c;主要体现在以下几个方面&#xff1a; 一、高度集成与灵活控制 全终端网络可编程&#xff1a;格芬科技的展厅中控系统采用全终端网络可编程技术&#xff0c;能够实现对展厅内各种设备的集中控制和管理&#xff0c;包括电脑…...

FPGA开发在verilog中关于阻塞和非阻塞赋值的区别

一、概念 阻塞赋值&#xff1a;阻塞赋值的赋值号用“”表示&#xff0c;对应的是串行执行。 对应的电路结构往往与触发沿没有关系&#xff0c;只与输入电平的变化有关系。阻塞赋值的操作可以认为是只有一个步骤的操作&#xff0c;即计算赋值号右边的语句并更新赋值号左边的语句…...

动态特征转换的艺术:在Mojo模型中实现自定义变换的策略

动态特征转换的艺术&#xff1a;在Mojo模型中实现自定义变换的策略 在机器学习中&#xff0c;特征转换是数据预处理的关键步骤&#xff0c;它直接影响模型的性能和结果的准确性。Mojo模型&#xff0c;作为一种高效的模型部署形式&#xff0c;允许在不同环境中运行模型并进行预…...

如何让Python爬虫在遇到异常时继续运行

概述 在数据收集和数据挖掘中&#xff0c;爬虫技术是一项关键技能。然而&#xff0c;爬虫在运行过程中不可避免地会遇到各种异常情况&#xff0c;如网络超时、目标网站变化、数据格式不一致等。如果不加以处理&#xff0c;这些异常可能会导致爬虫程序中断&#xff0c;影响数据…...

手把手带你搭建Snort入侵检测系统

在当今数字化社会&#xff0c;网络安全问题日益突出。为了有效防范网络攻击&#xff0c;部署入侵检测系统&#xff08;IDS&#xff09;是必要的防护措施。Snort作为一款功能强大的开源IDS工具&#xff0c;被广泛应用于各种网络环境中。本文将手把手教您如何从零开始实现Snort入…...

小程序内嵌uniapp页面跳转回小程序指定页面方式

使用微信小程序提供的Api&#xff1a;wx.miniProgram.navigateTo 在小程序中嵌套uniapp的H5页面&#xff0c;并使用wx.miniProgram.navigateTo进行页面跳转&#xff0c;需要确保满足以下条件&#xff1a; 你的小程序必须是通过uniapp构建的&#xff0c;并且支持小程序嵌套。 你…...

基于 Three.js 的 3D 模型加载优化

作者&#xff1a;来自 vivo 互联网前端团队- Su Ning 作为一个3D的项目&#xff0c;从用户打开页面到最终模型的渲染需要经过多个流程&#xff0c;加载的时间也会比普通的H5项目要更长一些&#xff0c;从而造成大量的用户流失。为了提升首屏加载的转化率&#xff0c;需要尽可能…...

Jlink下载与适配keil ccs theia教程 用jlink代替ti自己的下载仿真器

用jlink代替ti自己的下载仿真器&#xff0c;然后你去买立创的m0g3507才19.9包赚160 安装 J-Link 软件包 J-Link 软件包 v7.88i 或更高版本支持 MSPM0。 从 Segger 网站下载安装程序 按照安装程序说明操作 安装程序将自动请求更新 IAR 或 Keil&#xff08;如果已安装&#x…...

C# 进制之间的转换(二进制,八进制,十进制,十六进制)

常用的方法是&#xff1a;Convert.ToString(byte value, int toBase)&#xff0c; 并且有多个重载方法&#xff0c; value的类型可以为short&#xff0c;int 等&#xff0c;但必须是整数且不能为负数&#xff0c; 一般默认为十进制 toBase: 返回值的基数&#xff0c;必须是 2、…...

Linux 基础开发工具 : Vim编辑器

Vim 是 Linux 和其他类 Unix 系统上广泛使用的文本编辑器之一。它基于更早的 vi 编辑器&#xff0c;但添加了许多增强功能和扩展。Vim 是“Vi IMproved”的缩写&#xff0c;意为“改进的 Vi”&#xff0c;我们常使用Vim编辑器编写c/c代码。 ps&#xff1a;该篇介绍均为最基础介…...

Delphi 11.2 配置Android SDK 环境

打开 Delphi 11 点击 Tools–Options… 然后点击 Deployment–SDK Manager–Add… 这里如果配置64位就选 Android 64-bit&#xff0c;如果配置32位就选 Android 32-bit 点击 Select an SDK version–Add New… 有警告图标的就是有问题的项&#xff0c;需要手动更新一下&#xf…...

Spring Boot 学习(10)——固基(Idea 配置 git 访问 gitee)

几转眼就过了两个月&#xff0c;其实也没有闲着&#xff0c;学也学了&#xff0c;只是繁杂事多&#xff0c;学的不如以前多&#xff0c;也没有做过笔记了。 以前做开发因条件受限&#xff0c;没有什么 git &#xff0c;也没有 gitee。现在出来混要跟上形势才行&#xff0c;学习…...

11 个接口性能优化技巧(上)【送源码】

接口性能优化对于从事后端开发的同学来说&#xff0c;肯定再熟悉不过了&#xff0c;因为它是一个跟开发语言无关的公共问题。 该问题说简单也简单&#xff0c;说复杂也复杂。 有时候&#xff0c;只需加个索引就能解决问题。 有时候&#xff0c;需要做代码重构。 有时候&…...

AIoTedge 智能边缘物联网平台

AIoTedge智能边缘物联网平台是一个创新的边云协同架构&#xff0c;它为智能设备和系统提供了强大的数据处理和智能决策能力。这个平台的核心优势在于其边云协同架构设计&#xff0c;它优化了数据处理速度&#xff0c;提高了系统的可靠性和灵活性&#xff0c;适用于多种场景&…...

深入理解CSS基础【代码审计实战指南】

文章目录 为什么需要cssCSS语法CSS的组成css注释&#xff1a; 快速入门示例&#xff1a;常用样式字体颜色和边框颜色介绍颜色示例&#xff1a;边框边框的宽度与高度 字体样式背景样式文本居中 字体颜色和边框颜色介绍颜色示例&#xff1a;边框边框的宽度与高度 字体样式背景样式…...

html改写vue日志

本人最近学了vue&#xff0c;想着练手的方法就是改写之前在公司开发的小系统前端&#xff0c;将前端的AJAXJSThymeleaf改为axiosvue。 改写html 将<html>中的<head>和<body>结构移除&#xff0c;将css部分移入<style>&#xff0c; 重新定义了全局的&…...

Transformer-Bert---散装知识点---mlm,nsp

本文记录的是笔者在了解了transformer结构后嗑bert中记录的一些散装知识点&#xff0c;有时间就会整理收录&#xff0c;希望最后能把transformer一个系列都完整的更新进去。 1.自监督学习 bert与原始的transformer不同&#xff0c;bert是使用大量无标签的数据进行预训…...

基于术语词典干预的机器翻译挑战赛笔记 Task3 #Datawhale AI 夏令营

书接上回&#xff0c;上回在这捏&#xff1a; 基于术语词典干预的机器翻译挑战赛笔记Task2 #Datawhale AI 夏令营-CSDN博客文章浏览阅读223次&#xff0c;点赞10次&#xff0c;收藏5次。基于术语词典干预的机器翻译挑战赛笔记Task2https://blog.csdn.net/qq_23311271/article/…...

定制QCustomPlot 带有ListView的QCustomPlot 全网唯一份

定制QCustomPlot 带有ListView的QCustomPlot 文章目录 定制QCustomPlot 带有ListView的QCustomPlot摘要需求描述实现关键字: Qt、 QCustomPlot、 魔改、 定制、 控件 摘要 先上效果,是你想要的,再看下面的分解,顺便点赞搜藏一下;不是直接右上角。 QCustomPlot是一款…...

Fast Planner规划算法(一)—— Fast Planner前端

本系列文章用于回顾学习记录Fast-Planner规划算法的相关内容&#xff0c;【本系列博客写于2023年9月&#xff0c;共包含四篇文章&#xff0c;现在进行补发第一篇&#xff0c;其余几篇文章将在近期补发】 一、Fast Planner前端 Fast Planner的轨迹规划部分一共分为三个模块&…...

问题记录-SpringBoot 2.7.2 整合 Swagger 报错

详细报错如下 报错背景&#xff0c;我将springboot从2.3.3升级到了2.7.2&#xff0c;报了下面的错误&#xff1a; org.springframework.context.ApplicationContextException: Failed to start bean documentationPluginsBootstrapper; nested exception is java.lang.NullPo…...

【视觉SLAM】 十四讲ch5习题

1.*寻找一个相机&#xff08;你手机或笔记本的摄像头即可&#xff09;&#xff0c;标定它的内参。你可能会用到标定板&#xff0c;或者自己打印一张标定用的棋盘格。 参考我之前写过的这篇博客&#xff1a;【OpenCV】 相机标定 calibrateCamera Code来源是《学习OpenCV3》18.…...