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ą, RET
ponieważ 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 env
Polecenie moich raportów GOHOSTARCH
być amd64
i 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.s
jednego 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 build
skompiluje się bezproblemowo, ale go test
powoduje pojawienie się błędu.
go build
zakończone czysto,go test
nie udaje się