【ARMv8 编程】ARMv8 指令集介绍

news2024/11/25 7:23:44

ARMv8 架构中引入的最重要的变化之一是增加了 64 位指令集。该指令集补充了现有的 32 位指令集架构。这种增加提供了对 64 位宽整数寄存器和数据操作的访问,以及使用 64 位长度的内存指针的能力。新指令被称为 A64,以 AArch64 执行状态执行。ARMv8 还包括原始的 ARM 指令集,现在称为 A32,以及 Thumb(T32)指令集。A32 和 T32 都以 AArch32 状态执行,并向后兼容 ARMv7。

尽管 ARMv8-A 提供了与 32 位 ARM 体系结构的向后兼容,但 A64 指令集与旧的 ISA 是独立的,而且编码方式也不同。A64 添加了一些额外的功能,同时也删除了其他可能限制高性能实现的速度或能源效率的特性。ARMv8 架构还包括对 32 位指令集(A32 和 T32)的一些增强。但是,利用这些特性的代码与旧的 ARMv7 实现不兼容。然而,A64 指令集中的指令操作码仍然是 32 位,而不是 64 位。

一、ARMv8 指令集

新的 A64 指令集与现有的 A32 指令集类似。指令宽度为 32 位,语法类似。指令集在 ARMv8 架构中使用了通用的命名约定,因此原来的 32 位指令集状态现在被称为:

A32:在 AArch32 状态下,指令集基本上与 ARMv7 兼容,但也有差异。可以参考 ARMv8-A 架构参考手册。它还提供了一些新指令,以符合 A64 指令集引入的一些特性。
T32:Thumb 指令集(Thumb 是 ARM 体系结构中一种 16 位的指令集。Thumb 指令集可以看作是 ARM 指令压缩形式的子集,它是为减小代码量而提出,具有 16bit 的代码密度。Thumb 指令体系并不完整,只支持通用功能,必要时仍需要使用 ARM 指令,如进入异常时)最初包含在 ARM7TDMI 处理器中,最初只包含 16 位指令。16 位指令可以提供小得多的程序,但会牺牲一些性能。ARMv7 处理器,包括那些在 Cortex-A 系列中的处理器,支持 Thumb-2 技术,它扩展了 Thumb 指令集,以提供 16 位和 32 位指令的混合。这提供了与 ARM 类似的性能,同时保留了较短的代码长度。由于 Thumb-2 的体积和性能优势,编译或汇编所有 32 位代码以利用 Thumb-2 技术变得越来越普遍。

内核在处于 AArch64 状态时可以使用一个新的指令集。为了保持命名约定,并反映 64 位操作,该指令集称为:A64

A64:A64 提供了类似于 AArch32 或 ARMv7 中的 A32 和 T32 指令集的功能。ARMv8 架构在 AArch64 运行状态下使用 A64 指令集,在 AArch32 运行状态下使用 A32 指令集。A64 指令集和 A32 指令集是不兼容的,它们是两套完全不一样的指令集,它们的指令编码是不一样的。

新的 A64 指令集的设计允许以下几个改进:

  1. 一致编码方案:A32 中一些指令的添加导致了编码方案的不一致。例如,LDR 和 STR 支持半字的编码方式与主流的字节和字传输指令略有不同。这样做的结果是寻址模式略有不同。
  2. 宽范围常数:A64 指令为常量提供了一系列选项,每一个都是根据特定指令类型的要求定制的。
  • 算术指令通常接受 12 位立即数常量。
  • 逻辑指令通常接受 32 位或 64 位常量,这在其编码中有一些限制。
  • MOV 指令接受 16 位立即数,可将其移位到任何 16 位边界。
  • 地址生成指令适用于与 4KB 页面大小对齐的地址。
  • 对于位操作指令中使用的常量,有稍微复杂一些的规则。然而,位字段操作指令可以寻址源操作数或目标操作数中的任何连续位序列。

A64 提供了灵活的常量,但对它们进行编码,甚至确定特定常量是否可以在特定上下文中合法编码,都是非常重要的。

  1. 数据类型更容易:A64 自然地处理 64 位有符号和无符号数据类型,因为它提供了更简洁和有效的方式来处理 64 位整数。这对于所有提供 64 位整数的语言(如 C 或 Java)都是有利的。

  2. 长偏移量:A64 指令通常为 PC 相关分支和偏移寻址提供更长的偏移。增加的分支范围使管理节(inter-section)间跳转变得更容易。动态生成的代码通常放在堆上,因此实际上可以放在任何地方。运行时系统发现,通过增加分支范围可以更容易地管理这一点,并且需要更少的修复。对文本池(嵌入代码流中的文本数据块)的需求一直是 ARM 指令集的一个特点。这在 A64 中仍然存在。然而,更大的 PC 相对负载偏移量大大有助于文字池的管理,使得每个编译单元都可以使用一个。这消除了在长代码序列中为多个池制造位置的需要。

  3. 指针:指针在 AArch64 中是 64 位的,它允许寻址更多的虚拟内存,并为地址映射提供了更多的自由。然而,使用 64 位指针确实会产生一些成本。当使用 64 指针运行时,同一段代码通常比使用 32 位指针时使用更多的内存。每个指针都存储在内存中,需要八个字节而不是四个字节。这听起来可能微不足道,但可能会导致严重的后果。此外,与移动到 64 位相关联的内存空间的使用增加会导致缓存中命中的访问次数减少。缓存命中率的下降会降低性能。一些语言可以使用压缩指针(如 Java)来实现,以避免性能问题。

  4. 使用条件构造代替 IT 块:IT 块是 T32 的一个有用特性,它可以实现高效的序列,避免在未执行的指令周围进行短的前向分支。然而,硬件有时很难有效地处理这些问题。A64 删除这些块并用条件指令(如 CSEL、条件选择和 CINC 或条件增量)替换它们。这些条件构造更直接,更容易处理,无需特殊情况。

IT,这条指令用于根据指定的条件来执行后面相继的四条指令。IT 指令的描述为:IT{<x>{<y>{<z>}}} <firstcond>

其中,<x> 表示第二条指令的条件;<y> 表示第三条指令的条件;<z> 表示第四条指令的条件。<firstcond> 是条件操作数,表示第一条指令的条件。

<x>、<y>、<z> 的标识其实就两种符号 —— T 或 E。T 表示 Then,表示相应的指令所满足的条件与 <firstcond> 一致;E 表示 else,表示相应的指令所满足的条件与 <firstcond> 完全相反。因此,对于第一条指令而言,总是为 T 的,因此不需要在 IT 中显示给出,它直接对应于 <firstcond> 的条件。

另外,在 IT 块中不能再使用 IT 指令。即,相继的四条指令中不允许出现 IT 指令。例如:

ITETT   EQ
MOVEQ   R0, #1  ;//指令1
MOVNE   R0, #0  ;//指令2
MOVEQ   R1, #0  ;//指令3
MOVEQ   R2, #0  ;//指令4

这个例子意思是,当条件“EQ”符合时,执行指令 1、3、4 的 mov 操作,否则执行指令 2 的 mov 操作。

  1. 移动和循环行为更直观:A32 或 T32 的移位循环行为并不总是容易映射到高级语言所期望的行为。ARMv7 提供了一个桶形移位器,可以用作数据处理指令的一部分。然而,指定移位类型和移位量需要一定数量的操作码位,这可以在其他地方使用。A64 指令因此删除了很少使用的选项,而是添加了新的显式指令来执行更复杂的移位操作。
  2. 代码生成:在为常见的算术函数静态和动态生成代码时,A32 和 T32 通常需要不同的指令或指令序列。这是为了处理不同的数据类型。A64 中的这些操作更加一致,因此在不同大小的数据类型上生成简单操作的通用序列要容易得多。例如,在 T32 中,根据使用的寄存器(低寄存器或高寄存器),同一指令可以具有不同的编码。A64 指令集编码更加规则和合理。因此,A64 的汇编程序通常需要比 T32 的汇编程序更少的代码行。
  3. 固定长度指令:所有 A64 指令的长度相同,而 T32 是可变长度指令集。这使得生成的代码序列的管理和跟踪更容易,特别是影响动态代码生成器。
  4. 三个操作数映射更好:A32 通常为数据处理操作保留真正的三操作数结构。另一方面,T32 包含大量的双操作数指令格式,这使得它在生成代码时稍微不那么灵活。A64 坚持一致的三操作数语法,这进一步有助于提高指令集的规则性和同质性,以利于编译器。

二、区分 32 位和 64 位 A64 指令

A64 指令集中的大多数整数指令有两种形式,它们对 64 位通用寄存器文件中的 32 位或 64 位值进行操作。

查看指令使用的寄存器名时:

  • 如果寄存器名以 X 开头,则为 64 位值。
  • 如果寄存器名以 W 开头,则为 32 位值。

如果选择 32 位指令形式,则以下事实成立:

  • 循环右移在 31 位注入,而不是 63 位。
  • 由指令设置的条件标志从低 32 位计算。
  • 写入 W 寄存器,将 X 寄存器的位 [63:32] 设置为零。

AArch64 执行状态提供了 31 × 64 位通用寄存器,在任何时候和所有异常级别都可以访问。每个寄存器是 64 位宽的,它们通常被称为寄存器 X0~X30。

在这里插入图片描述

每个 AArch64 64 位通用寄存器(X~X30)也有 32 位(W0~W30)形式。

在这里插入图片描述

32 位 W 寄存器对应的 64 位 X 寄存器的下半部分。即 W0 映射到 X0 的下半部分,W1 映射到 X1 的下半部分。

从 W 寄存器读取时,忽略对应的 X 寄存器中较高的 32 位,并保持不变。写入 W 寄存器将 X 寄存器的高 32 位设置为零。也就是说,将 0xFFFFFFFF 写入 W0 会将 X0 设置为 0x00000000FFFFFFFF。

三、寻址

当处理器可以在单个寄存器中存储 64 位值时,在程序中访问大量内存就变得简单得多。在 32 位内核上执行的单个线程被限制访问 4GB 的地址空间。可寻址空间的很大一部分被保留给操作系统内核、库代码、外围设备等使用。因此,空间不足意味着程序在执行时可能需要将一些数据映射到内存中或映射出内存。使用更大的地址空间和 64 位指针可以避免这个问题。它还使内存映射文件等技术更有吸引力,使用起来更方便。

寻址的其他改进包括:

  1. 独占访问

一个字节、半字、字和双字的独占加载存储(load-store)。对一对双字的独占访问允许对一对指针进行原子更新,例如循环列表插入。所有排他性访问必须自然对齐,排他性对访问必须对齐到数据大小的两倍,即对 64 位值对齐为 128 位。

  1. 增加 PC 相对偏移寻址

PC 相对文字负载的偏移范围为 ±1MB。与 A32 的 PC 相对负载相比,这减少了文本池的数量,并增加了函数之间的文本数据共享。反过来,这又减少了 I-cache 和 TLB 污染。

大多数条件分支的范围为 ±1MB,预计足以满足在单个函数中发生的大多数条件分支。

无条件分支(包括分支和链接)的范围为 ±128MB,预计足以跨越大多数可执行加载模块和共享对象的静态代码段,而无需插入链接器 Veneers——贴面(贴面是一小段代码,例如,当链接器检测到分支目标超出范围时,它会自动插入这些代码。贴面成为原始分支的中间目标,然后贴面本身成为目标地址的分支)。

范围为 ±4GB 的 PC 相对加载、存储和地址生成可以只用两条指令内联执行,也就是说,不需要从字面量池加载偏移量。

  1. 未对齐的地址支持

除了独占和有序访问外,所有加载和存储都支持在访问正常内存时使用未对齐的地址。这简化了将代码移植到 A64 的过程。

  1. 批量传输

LDM、STM、PUSH 和 POP 指令在 A64 中不存在。可以使用 LDP 和 STP 指令构建批量传输。这些指令从连续的存储器位置加载并存储一对独立的寄存器。LDNP 和 STNP 指令提供了流式或非时间性提示,即数据不需要保留在缓存中。PRFM 或预取内存指令允许将预取定向到特定的高速缓存级别。

  1. 加载/存储

所有加载/存储指令现在都支持一致的寻址模式。例如,在从内存中加载和存储元素时,这使得以相同的方式处理 char、short、int 和 long long 变得容易得多。浮点寄存器和 NEON 寄存器现在支持与核心寄存器相同的寻址模式,这使得可以更容易地互换使用这两个寄存器组。

  1. 对齐检查

在 AArch64 中执行时,使用堆栈指针对指令获取和加载或存储执行额外的对齐检查,从而启用 PC 或当前 SP 的对齐检查。这种方法比强制 PC 或 SP 正确对齐更可取,因为 PC 或 SP 的未对齐通常表示软件错误,例如软件中的地址损坏。

四、C/C++ 内联汇编

asm 关键字可以将内联 GCC 语法汇编代码合并到函数中。例如:

#include <stdio.h>
int add(int i, int j)
{
    int res = 0;
    asm (
        "ADD %w[result], %w[input_i], %w[input_j]" // 使用“%w[名称]”对 w 寄存器进行操作。
                                                   // 也可以对 x 寄存器使用“%x[name]”,这是默认值。
        : [result] "=r" (res)
        : [input_i] "r" (i), [input_j] "r" (j)
    );
    return res;
}

int main(void)
{
    int a = 1;
    int b = 2;
    int c = 0;
    c = add(a,b)
    printf(“Result of %d + %d = %d\n, a, b, c);
}

asm 内联汇编语句的一般形式如下:

asm(code [: output_operand_list [: input_operand_list [: clobber_list]]]);

asm 关键字允许你在 C/C++ 代码中嵌入汇编指令。GCC 提供了两种形式的内联 asm 语句。基本 asm 语句是没有操作数的语句,而扩展 asm 语句包含一个或多个操作数。扩展形式是在函数中混合 C/C++ 和汇编语言的首选。

code 是汇编代码。在我们的例子中,这是“ADD %[result], %[input_i], %[input_j]”。

output_operand_list 是一个可选的输出操作数列表,用逗号分隔。每个操作数由方括号中的符号名称、约束字符串和括号中的 C 表达式组成。在这个例子中,只有一个输出操作数:[result] “=r” (res)。

input_operand_list 是一个可选的输入操作数列表,由逗号分隔。输入操作数的语法与输出操作数相同。在这个例子中,有两个输入操作数:[input_i] “r” (i)和[input_j] “r” (j)。

clobber_list 是一个可选的寄存器或其他值的列表。在这个例子中,这个参数被省略了。

扩展 asm —— 汇编指令与 C 表达式操作数

使用扩展 asm,可以从汇编程序读写 C 变量,并执行从汇编代码到 C 标签的跳转。扩展 asm 语法使用冒号(‘:’)在汇编程序模板之后分隔操作数参数:

asm asm-qualifiers ( AssemblerTemplate 
                 : OutputOperands 
                 [ : InputOperands
                 [ : Clobbers ] ])

asm asm-qualifiers ( AssemblerTemplate 
                      : OutputOperands
                      : InputOperands
                      : Clobbers
                      : GotoLabels)

在最后一种形式中,asm-限定符(asm-qualifiers)包含 goto(在第一种形式中,不包含)。

限定符

volatile —— 扩展 asm 语句的典型用法是操作输入值以产生输出值。然而,asm 语句也可能产生副作用。如果是这样,可能需要使用 volatile 限定符来禁用某些优化(GCC 的优化器有时会在确定不需要输出变量时丢弃 asm 语句。此外,如果优化器认为代码将始终返回相同的结果(即,在调用之间没有任何输入值改变),则优化器可以将代码移出循环)。

inline —— 如果使用 inline 限定符,那么出于内联目的,asm 语句的大小将尽可能小。

goto —— 这个限定符通知编译器,asm 语句可以执行跳转到 GotoLabels 中列出的标签之一。

参数

AssemblerTemplate —— 这是一个文本字符串,它是汇编程序代码的模板(汇编程序模板是包含汇编程序指令的文本字符串)。它是指输入、输出和 goto 参数的固定文本和标记的组合。

OutputOperands —— 由 AssemblerTemplate 中的指令修改的 C 变量列表,以逗号分隔。允许使用空列表。

InputOperands —— 由 AssemblerTemplate 中的指令读取的以逗号分隔的 C 表达式列表。允许使用空列表。

Clobbers —— 逗号分隔的寄存器列表或由 AssemblerTemplate 更改的其他值,不包括作为输出列出的那些值。允许使用空列表。

GotoLabels —— 当使用 asm 的 goto 形式时,此部分包含汇编模板中的代码可能跳转到的所有 C 标签的列表。asm 语句不能执行跳转到其他 asm 语句,只能跳转到列出的 GotoLabels。GCC 的优化器不知道其他跳跃。因此,他们在决定如何优化时无法考虑这些因素。

input + output + goto 操作数的总数限制为 30。

五、在指令集之间切换

不可能在单个应用程序中使用来自两种执行状态的代码。在 ARMv8 中,A64 和 A32 或 T32 指令集之间没有相互作用,而 A32 和 T32 指令集之间有相互作用。用 A64 编写的 ARMv8 处理器的代码不能在 ARMv7 Cortex-A 系列处理器上运行。但是,为 ARMv7-A 处理器编写的代码可以在 AArch32 执行状态下在 ARMv8 处理器上运行。这一点做安卓的不陌生,在 ARMv8 处理器上运行只包含 ARMv7-A 的 so 库是可以正常运行的。

在这里插入图片描述

参考资料:

  1. 《ARMv8-A-Programmer-Guide》
  2. https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm

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

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

相关文章

编码的基本概念

本专栏包含信息论与编码的核心知识&#xff0c;按知识点组织&#xff0c;可作为教学或学习的参考。markdown版本已归档至【Github仓库&#xff1a;information-theory】&#xff0c;需要的朋友们自取。或者公众号【AIShareLab】回复 信息论 也可获取。 文章目录信源编码分类前缀…

nginx模块介绍

新编译前&#xff0c;在对应的nginx原编译文件夹 如&#xff1a;nginx-1.23.0 下&#xff0c;要 make clean 清空以前编译的objs文件夹&#xff0c;实际上就是执行了rm objs文件夹。 很多要用到git&#xff0c;先yum install git -y echo-nginx-module 让nginx直接使用echo的…

基于SpringBoot的任务管理三种方式

文章目录前言一&#xff0c;异步任务1.1 无返回值异步任务调用1.2 有返回值异步任务调用二、定时任务2.1 背景介绍2.2 todo三、邮箱任务3.1 todo前言 开发 web 应用时&#xff0c;多数应用都具备任务调度功能&#xff0c;常见的任务包括异步任务、定时任务和邮件任务。我们以数…

springboot+vue企业固定资产管理系统java

资产管理系统可以更加直观的了解到企业资产的使用情况&#xff0c;让企业资产透明化。资产管理系统可以帮助企业标记企业所有的资产&#xff0c;这些资产包括电脑&#xff0c;桌子&#xff0c;椅子等不动资产的标识&#xff0c;以及固定资产的新增&#xff0c;修改&#xff0c;…

渗透测试 | UserInfo信息收集

0x00 免责声明 本文仅限于学习讨论与技术知识的分享&#xff0c;不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;本文作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担…

Leetcode 双指针详解

双指针 双指针顾名思义&#xff0c;就是同时使用两个指针&#xff0c;在序列、链表结构上指向的是位置&#xff0c;在树、图结构中指向的是节点&#xff0c;通过或同向移动&#xff0c;或相向移动来维护、统计信息 在数组的区间问题上&#xff0c;暴力算法的时间复杂度往往是O…

分布式项目-规格参数(13)

【今日成果】&#xff1a; //商品维护模块&#xff1b;其中值得一提的是。商品的介绍全部都做成图片的形式&#xff0c;这样有利于去维护。 商品模块中的页面在created中一开始要对会员等级进行查询操作&#xff0c;访问MemberController中的list接口。 //维护规格参数信息…

【离线数仓-9-数据仓库开发DWS层设计要点-1d/nd/td表设计】

离线数仓-9-数据仓库开发DWS层设计要点-1d/nd/td表设计离线数仓-9-数据仓库开发DWS层设计要点-1d/nd/td表设计一、DWS层设计要点二、DWS层设计分析 - 1d/nd1.DWS层设计一&#xff1a;不考虑用户维度2.DWS层设计二&#xff1a;考虑用户维度2.DWS层设计三 &#xff1a;考虑用户商…

骨骼控制(一)——动画动态节点(AnimDynamics)

文章目录一、引言二、骨骼控制三、UE蓝图中提供的骨骼控制节点——AnimDynamics动画蓝图节点1、什么是AnimDynamics动画蓝图节点①使用盒体计算惯性②使用约束来限制移动2、AnimDynamics节点的几种常用例子①单骨骼模拟②骨骼链模拟 <h2 id1>③群魔乱舞&#xff08;这是错…

YOLOv8之C2f模块——与YOLOv5的C3模块对比

一、源码对比 YOLOv8完整工程代码下载&#xff1a;ultralytics/ultralytic   C2f模块源码在ultralytics/nn/modules.py下&#xff0c;源码如下&#xff1a; class C2f(nn.Module):# CSP Bottleneck with 2 convolutionsdef __init__(self, c1, c2, n1, shortcutFalse, g1, e…

安装kibana 报错/访问不了

安装kibana 报错1&#xff0c;elasticsearch.yaml 和kibana.yaml 配置问题2&#xff0c;elasticsearch 和kibana版本不一致3&#xff0c;索引问题1&#xff0c;elasticsearch.yaml 和kibana.yaml 配置问题 我的RPM安装的&#xff0c;配置文件都在/etc/ vim /etc/elasticsearc…

【Python知识点桂电版】02组合数据类型

一、序列序列简介序列是指一种包含多项数据的数据结构&#xff0c;分为不可变序列和可变序列。可变序列可修改序列内的元素如列表&#xff0c;二不可变序列一旦建立就不能修改其中的元素&#xff0c;字符串和元组属于不可变序列。列表和元组的创建列表&#xff1a;列表名 [元素…

大学物理期末大题专题训练总结-热学大题

今天下午去找郑老师权老师等去答疑&#xff0c;老师说大题会考查得比较套路&#xff0c;计算不难。明天就要考试了&#xff0c;再把大题常见题型总结一下&#xff0c;热学这块我做完了蓝本的热学题目&#xff0c;发现了如下三种&#xff1a;有关循环过程曲线的&#xff1a;给出…

简历信息提取论文笔记Information Extraction from Resume Documents in PDF Format

标题&#xff1a;Information Extraction from Resume Documents in PDF Format下载地址&#xff1a;https://library.imaging.org/ei/articles/28/17/art00013长度&#xff1a;8页发表时间&#xff1a;2016引用量cite27先读标题、摘要、结论、然后 methods/experiment design,…

大数据NiFi(二十):实时同步MySQL数据到Hive

文章目录 实时同步MySQL数据到Hive 一、开启MySQL的binlog日志 1、登录mysql查看MySQL是否开启binlog日志 2 、开启mysql binlog日志 3、重启mysql 服务&#xff0c;重新查看binlog日志情况 二、​​​​​​​​​​​​​​配置“CaptureChangeMySQL”处理器 1、创建“…

JAVA企业级开发 1.4 Spring_采用Java配置类管理Bean

文章目录一、采用Java配置类管理Bean&#xff08;一&#xff09;打开项目&#xff08;二&#xff09;创建子包&#xff08;三&#xff09;创建杀龙任务类&#xff08;四&#xff09;创建勇敢骑士类&#xff08;五&#xff09;创建Spring配置类&#xff08;六&#xff09;创建测…

STM32单片机之温湿度检测系统(DTH11、OLED、LCD1602)

LCD1602LCD1602引脚第 1 脚: VSS 为电源地 第 2 脚: VDD 接 5V 正电源 第 3 脚: VL 为液晶显示器对比度调整端,接正电源时对比度最弱&#xff0c;接地时对比度最高&#xff0c;对比度过高时会产生“鬼影”&#xff0c;使用时可以通过一个 10K 的电位器调整对比度。 第 4 脚&…

Windows下命令执行绕过技巧总结(渗透测试专用)

一、连接符1、双引号不要求双引号闭合举例&#xff1a;"who"a"mi" //闭合的 "who"a"mi //不闭合的2、圆括号必须在两边&#xff0c;不能包括中间的字符。举例&#xff1a;((whoami))3、^符号&#xff08;转译符号&#xff09;不可以在结尾&…

Rasa 3.x 学习系列-摆脱意图:一种新的对话模式

Rasa 3.x 学习系列-摆脱意图:一种新的对话模式 在2019年的一篇文章中,Alan Nichol写道 :是时候摆脱意图了。一年后,Rasa发布了Rasa中的第一个无意图(或“端到端”)对话模型。现在,我们宣布迈出了一个重要的步伐,将LLM的强大功能带入Rasa的对话管理中。 首先,意图非常…

YOLOV5s+Shufflenetv2+VOC数据集+迁移学习

前言&#xff1a;更改YOLOV5的backbone网络为 Shufflenetv2&#xff0c;便于达到轻量化的目的 1. 试运行YOLOv5 b站推土机 2. VOC数据集处理 3. 更改轻量级网络 参考魔改yolov5 3.1 在common.py末尾加入以下代码 #添加轻量化模块Shufflenetv2 # ------------------------…