我正在尝试编写一些 SIMD,主要用于学习目的。我知道 Go 可以链接程序集,但我无法让它正常工作。
这是我能做的最简单的例子(逐元素向量乘法):
vec_amd64.s(注意:实际文件下面有一个空白行,RET否则会导致错误)
RET
// func mul(v1, v2 Vec4) Vec4 TEXT .mul(SB),4,$0-48 MOVUPS v1+0(FP), X0 MOVUPS v2+16(FP), X1 MULPS X1, X0 // also tried ret+32 since I've seen some places do that MOVUPS X0, toReturn+32(FP) RET
vec.go
package simd type Vec4 [4]float32 func (v1 Vec4) Mul(v2 Vec4) Vec4 { return Vec4{v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2], v1[3] * v2[3]} } func mul(v1, v2 Vec4) Vec4
simd_test.go
package simd import ( "testing" ) func TestMul(t *testing.T) { v1 := Vec4{1, 2, 3, 4} v2 := Vec4{5, 6, 7, 8} res := v1.Mul(v2) res2 := mul(v1, v2) // Placeholder until I get it to compile if res != res2 { t.Fatalf("Expected %v; got %v", res, res2) } }
当我尝试运行时go test出现错误:
go test
# testmain simd.TestMul: call to external function simd.mul simd.TestMul: undefined: simd.mul
该go env命令报告我GOHOSTARCH要amd64和我的围棋版本为1.3。为了确认这不是导致问题的架构,我发现了另一个使用程序集的包并删除了除_amd64.s一个之外的所有程序集文件,并且其测试运行良好。
go env
GOHOSTARCH
amd64
_amd64.s
我还尝试将其更改为导出的标识符,以防导致奇怪,但没有骰子。我想我非常密切地遵循了像 那样的包中的模板math/big,所以希望它是我遗漏的简单明了的东西。
math/big
我知道 Go 至少在尝试使用程序集,因为如果我在 .s 文件中引入语法错误,构建工具会抱怨它。
编辑:
要清楚,go build会编译干净,但go test会导致错误出现。
go build
您使用了错误的点。代替
TEXT .mul(SB),4,$0-48
写
TEXT ·mul(SB),4,$0-48
一切正常。