https://mzh.io/go-riscv64-fma-optimazation-notes
fused multiply–add 是什么?
融合乘加(Fused Multiply-Add,简称FMA)是一种在计算机处理器中执行浮点数运算的指令。它将乘法和加法操作结合在一起,以提高计算的效率和精度。
通常情况下,执行乘法和加法操作需要两个独立的指令。然而,使用FMA指令,这两个操作可以在单个指令中同时执行。这种融合的乘加操作可以在不丢失精度的情况下提高计算的速度,并减少了指令的数量,从而提高了处理器的性能。
FMA指令对于各种科学计算、图形处理和信号处理任务非常有用,因为这些任务通常需要大量的浮点数计算。通过将乘法和加法合并在一起,FMA能够减少计算所需的指令数目,并且可以在单个时钟周期内完成更多的计算。这使得FMA指令在高性能计算和并行处理领域中得到广泛应用。
需要注意的是,FMA指令的可用性取决于处理器的架构和型号。不是所有的处理器都支持FMA指令集,因此在编写代码时需要相应地考虑处理器的兼容性。
哪些处理器支持FMA指令集?
许多现代的处理器架构都支持FMA指令集。以下是一些常见处理器架构和型号,它们支持FMA指令集:
英特尔(Intel)处理器:
- 英特尔至强(Xeon)处理器,包括最新的英特尔至强融核(Xeon Scalable)系列。
- 英特尔酷睿(Core)处理器,包括第四代至第十一代的英特尔酷睿处理器。
- 英特尔至强酷睿(Xeon Core)处理器,如Intel Xeon E3系列。
AMD处理器:
- AMD EPYC处理器,包括第一代至第三代的EPYC系列。
- AMD Ryzen处理器,包括第一代至第三代的Ryzen系列。
- AMD Threadripper处理器,包括第一代至第三代的Threadripper系列。
ARM处理器:
- ARM Cortex-A系列,如Cortex-A57、Cortex-A72、Cortex-A73、Cortex-A75等。
- ARM Neoverse系列,如Neoverse N1、Neoverse E1等。
- Apple M1芯片。
需要注意的是,具体的处理器型号和架构可能在支持的指令集方面有所区别。因此,在编写代码时,建议查阅特定处理器的文档或参考手册,以确保了解其支持的指令集和功能。
FNMADD 是什么?在risc-v架构中
“FNMADD”是在RISC-V架构中的一个指令,它代表”Floating-Point Negative Multiply-Add”,即浮点数的负乘加操作。它用于执行浮点数运算,将一个浮点数乘以另一个浮点数的负值,然后将结果与第三个浮点数相加。
在RISC-V架构中,FNMADD指令的格式如下:
1 | FNMADD.D rd, rs1, rs2, rs3 |
其中:
FNMADD:指令助记符,表示浮点数的负乘加操作。.D:指令的后缀,表示指令操作的是双精度浮点数(64位)。rd:目标寄存器,用于存储计算结果。rs1、rs2、rs3:源操作数寄存器,用于存储参与计算的浮点数。
指令的执行过程如下:
- 将寄存器
rs1中的值乘以寄存器rs2中的值的负值。 - 将上一步计算的结果与寄存器
rs3中的值相加。 - 将最终结果存储到目标寄存器
rd中。
需要注意的是,上述指令是针对RISC-V架构中的双精度浮点数执行的,对于单精度浮点数(32位)可能会有不同的指令格式和后缀。具体的指令格式和后缀可能因为RISC-V扩展和实现的变种而有所不同,因此在编写代码时建议参考相应的RISC-V架构规范和处理器手册。
Go语言源码中,go/test/codegen/math.go有什么作用
在Go语言的源码中,go/test/codegen/math.go文件是用于测试代码生成器(codegen)的数学函数的文件。该文件包含了一些数学函数和对应的测试用例,用于验证编译器和代码生成器是否正确地处理了这些函数。
具体而言,math.go文件中包含了一些数学函数的实现,例如Abs、Sqrt、Pow等,并且为每个函数提供了相应的测试用例。这些测试用例会对函数进行输入和输出的验证,确保函数在各种情况下都能正确地计算结果。
通过在math.go文件中编写这些数学函数的实现和测试用例,开发人员可以验证编译器和代码生成器在处理数学函数时是否正确生成目标代码,并且能够产生正确的结果。这对于保证Go语言的数学函数的正确性和性能至关重要。
需要注意的是,go/test/codegen/math.go文件是Go语言源码的一部分,主要用于开发和测试编译器和代码生成器,对于一般的Go语言程序开发而言,不需要直接关注该文件的内容。
这些数学函数的测试用例是如何编写的?
在go/test/codegen/math.go文件中,数学函数的测试用例使用了Go语言的内置测试框架,通常是基于testing包进行编写的。下面是一个示例:
1 | func TestAbs(t *testing.T) { |
在上述示例中,TestAbs函数是一个测试函数,用于测试Abs函数的行为。在函数体内,我们可以定义多个测试用例,并使用断言语句检查函数的实际输出是否与预期值相等。
在每个测试用例中,我们调用被测试的数学函数(例如Abs)并将其结果与预期结果进行比较。如果结果不相等,我们使用t.Errorf函数输出错误信息。测试框架会记录这些错误,并在测试完成后报告测试结果。
通过编写多个测试用例,覆盖各种可能的输入和边界情况,可以确保数学函数在各种情况下都能产生正确的结果。这有助于验证数学函数的正确性,并提供了一种自动化测试的方式,以便在进行代码更改时进行回归测试。
下面这段代码什么意思?
1 | // [+ -](x * y [+ -] z). |
这段注释描述了一个数学表达式的结构和运算顺序。下面是对注释中的内容的解释:
[+ -]:表示一个正号或负号,用于指定后面的数值的符号。(x * y):表示数值x与数值y的乘法操作。z:表示另一个数值z。A:表示将乘法的结果与z做加法操作。S:表示符号操作,即根据前面的正号或负号对整个表达式的结果进行正负处理。N:表示最终的结果。
根据这个描述,整个表达式的运算顺序如下:
- 首先,计算
x与y的乘法,得到中间结果。 - 然后,将中间结果与
z做加法操作,得到一个新的中间结果。 - 最后,根据正号或负号的符号操作,决定最终结果的正负性。
这种运算顺序可以用于表达一些特定的数学公式或算法,具体应用场景可能需要根据实际情况进行解释和理解。请注意,这只是对注释中内容的解释,具体应用和上下文可能会有不同的含义。
为什么要放在src外面,而不在单元测试中?
将数学函数的测试用例放在go/test/codegen/math.go文件之外,而不是放在单元测试中,可能是出于一些特定的设计或组织原因。这样的设计决策可能因项目结构、测试策略或代码组织风格而有所不同。以下是一些可能的原因:
分离测试代码和被测试代码:将测试用例放在与被测试代码分离的文件中,可以使测试代码和被测试代码保持独立。这样做可以在组织项目时更好地区分测试代码和实际代码,并且可以避免测试代码在发布或部署过程中包含在最终的可执行文件中。
代码生成器测试:
go/test/codegen/math.go文件中的数学函数可能是用于测试代码生成器的功能和性能。这些函数可能包含一些特定的代码模式或结构,以便验证代码生成器在处理这些模式时是否正确生成目标代码。将这些测试用例与其他单元测试分开可以更好地组织和管理代码生成器的测试。整体测试策略:在某些项目中,可能会有不同层次和类型的测试,例如单元测试、集成测试和系统测试等。将数学函数的测试用例放在独立的文件中可能是整体测试策略的一部分,以便更好地组织和管理不同层次的测试。
需要注意的是,具体的设计决策可能因项目和团队的偏好而有所不同。最佳实践是根据项目的特定需求和约定来组织和编写测试代码。重要的是确保测试代码的可读性、可维护性和有效性,以便在开发过程中能够正确验证代码的行为和正确性。
Go在risc-v架构的进展
Go语言在RISC-V架构上的支持已经有了很大的进展。RISC-V是一种新兴的开放式指令集架构,被广泛认为是未来处理器架构的主要竞争者之一。以下是Go在RISC-V架构上的进展:
Go1.17对RISC-V的支持得到了大幅增强,其中包括支持硬件浮点运算和对RISC-V标准指令集的支持。
Go开发者社区对RISC-V的支持得到了增强,许多社区成员已经开始为RISC-V编写代码和开发相关工具。
Go在RISC-V上的性能得到了大幅提升,通过优化垃圾回收器和调整编译器选项,Go在RISC-V上的性能已经可以与其他平台相媲美。
许多RISC-V芯片厂商已经开始将Go语言作为默认的开发语言之一,例如SiFive的Freedom Studio IDE已经内置了Go语言开发环境。
总之,Go在RISC-V架构上的支持已经取得了显著的进展,这将有助于Go语言更好地适应未来处理器架构的发展趋势。
哪个版本开始支持risc-v的?
Go语言对RISC-V架构的支持始于Go1.9版本。但是在这个版本中,Go只支持RISC-V 64位的GNU/Linux操作系统。
随着Go版本的不断更新,Go对RISC-V架构的支持也在不断增强。从Go1.11版本开始,Go已经可以在RISC-V 64位的FreeBSD和NetBSD操作系统上运行。
而从Go1.17版本开始,Go支持在RISC-V标准指令集下运行,并增加了硬件浮点运算的支持,这使得Go在RISC-V架构上的支持更加完善。总之,Go语言在对RISC-V的支持方面,已经取得了显著的进展。
1.19:
1 | RISC-V |
https://dashen.feishu.cn/docx/NtVCdYpzPo7CDExfWlYcey0OnAh
https://dashen.feishu.cn/docx/doxcn3TbrP9zyPFtjUcQ7g8zNie
https://dashen.feishu.cn/docx/doxcn6agUIzfBGoBgQo2NsapPCe
https://github.com/golang/go/issues/27532
https://danielmangum.com/posts/risc-v-bytes-go-1-19-register-calling/
https://groups.google.com/g/golang-codereviews/c/qgCDki-2zEA
https://blog.davidburela.com/2020/11/21/cross-compiling-golang-for-risc-v/
https://forum.golangbridge.org/t/why-go-use-jmp-instead-j-for-risc-v/23801
debian riscv 源码编译golang及proxy使用
原文链接: https://dashen.tech/2010/03/26/Go语言在RISC-V/
版权声明: 转载请注明出处.