Tôi đang cố gắng viết một số SIMD chủ yếu cho mục đích học tập. Tôi biết Go có thể liên kết lắp ráp, nhưng tôi không thể làm cho nó hoạt động chính xác.
Đây là ví dụ tối thiểu nhất mà tôi có thể làm (phép nhân vectơ theo phần tử):
vec_amd64.s (lưu ý: tệp thực tế có một dòng khoảng trắng bên dưới RET
vì nó gây ra lỗi nếu không)
// 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)
}
}
Khi tôi cố gắng chạy, go test
tôi gặp lỗi:
# testmain
simd.TestMul: call to external function simd.mul
simd.TestMul: undefined: simd.mul
Các go env
lệnh báo cáo của tôi GOHOSTARCH
được amd64
và phiên bản Go của tôi là 1,3. Để xác nhận đó không phải là kiến trúc gây ra sự cố, tôi đã tìm thấy một gói khác sử dụng lắp ráp và đã xóa tất cả các tệp lắp ráp ngoại trừ _amd64.s
một và các thử nghiệm của nó chạy tốt.
Tôi cũng đã thử thay đổi nó thành một số nhận dạng đã xuất trong trường hợp gây ra sự kỳ lạ, nhưng không có xúc xắc. Tôi nghĩ rằng tôi đã theo dõi khá chặt chẽ mẫu trong các gói như math/big
vậy, vì vậy hy vọng đó là một cái gì đó đơn giản và rõ ràng mà tôi đang thiếu.
Tôi biết rằng Go ít nhất đang cố gắng sử dụng hợp ngữ vì nếu tôi đưa ra một lỗi cú pháp cho tệp .s, công cụ xây dựng sẽ phàn nàn về nó.
Biên tập:
Để rõ ràng, go build
sẽ biên dịch sạch sẽ, nhưng go test
gây ra lỗi xuất hiện.
go build
hoàn thành sạch sẽ,go test
không thành công.