Próbuję napisać trochę SIMD głównie do celów edukacyjnych. Wiem, że Go może łączyć zestaw, ale nie mogę sprawić, by działał poprawnie.
Oto najbardziej minimalny przykład, jaki mogę zrobić (mnożenie wektorów według elementów):
vec_amd64.s (uwaga: rzeczywisty plik ma białą linię pod spacją, RETponieważ w przeciwnym razie powoduje błędy)
// 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)
}
}
Kiedy próbuję uruchomić go test, pojawia się błąd:
# testmain
simd.TestMul: call to external function simd.mul
simd.TestMul: undefined: simd.mul
go envPolecenie moich raportów GOHOSTARCHbyć amd64i moja wersja Go być 1.3. Aby potwierdzić, że to nie architektura powodująca problem, znalazłem inny pakiet, który używa asemblacji i usunąłem wszystkie pliki asemblera z wyjątkiem _amd64.sjednego i jego testy działały poprawnie.
Próbowałem też zmienić go na wyeksportowany identyfikator na wypadek, gdyby powodował dziwne zmiany, ale nie było kości. Myślę, że dość dokładnie śledziłem szablon w pakietach takich jak math/big, więc mam nadzieję, że jest to coś prostego i oczywistego, czego mi brakuje.
Wiem, że Go przynajmniej próbuje użyć asemblera, ponieważ jeśli wprowadzę błąd składni do pliku .s, narzędzie do budowania będzie na to narzekać.
Edytować:
Żeby było jasne, go buildskompiluje się bezproblemowo, ale go testpowoduje pojawienie się błędu.
go buildzakończone czysto,go testnie udaje się