Go nie łączy mojego zestawu: niezdefiniowana funkcja zewnętrzna

82

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.

LinearZoetrope
źródło
go buildzakończone czysto, go testnie udaje się
LinearZoetrope
1
Jak kompilujesz? Nie odpowiedziałeś na pytanie.
fuz
1
Jakie polecenia wprowadziłeś, z którego katalogu względem plików źródłowych? Kompiluję za pomocą gonarzędzia do kompilacji. jest bardzo niejasny. To może oznaczać wszystko.
fuz
1
Istnieje różnica między dzwonieniem go builda go build foo.goitd. Może się również zdarzyć, że masz zabawne ustawienia $GOPATHitp. Im więcej piszesz o tym, co dokładnie zrobiłeś, tym łatwiej będzie Ci pomóc. Najlepszą rzeczą jest przesłanie transkrypcji sesji powłoki zamiast prozy.
fuz
12
Język Go naprawdę wydaje się mieć fetysz dla postaci z połowy kropki. Powiązane: Ukośniki i kropki w nazwach funkcji i prototypach?
Cody Grey

Odpowiedzi:

96

Używasz złej kropki. zamiast

TEXT .mul(SB),4,$0-48

pisać

TEXT ·mul(SB),4,$0-48

i wszystko działa dobrze.

fuz
źródło
11
Cóż, TO było subtelne, nie zauważyłem, że to kropka w środku. Dzięki.
LinearZoetrope
13
Jak ludzie wpisują to na amerykańskiej klawiaturze QWERTY? A może nie jest to typowy przypadek użycia, w którym można po prostu wygooglować symbol w razie potrzeby?
Seiyria
9
W ten sposób . Systemy operacyjne, które nie zasysają (tj. Nie Windows) odwzorowują nieużywane warstwy układu QWERTY, dzięki czemu można wprowadzić znaki, takie jak interpunct.
fuz
7
@FUZxxl FYI Alt-0183 (używając klawiatury numerycznej) nadal działa w systemie Windows. Nie tak przyjemny i zwykle trudny na laptopach, ale działa.
Intermernet
4
Na Linuksie (przynajmniej Ubuntu), jeśli masz włączony klucz tworzenia : <compose> ^ .=·
Izkata