Estoy tratando de escribir algo de SIMD principalmente con fines de aprendizaje. Sé que Go puede vincular el ensamblaje, pero no puedo hacer que funcione correctamente.
Este es el ejemplo más mínimo que puedo hacer (multiplicación de vectores por elementos):
vec_amd64.s (nota: el archivo real tiene una línea de espacio en blanco debajo, RET
ya que de lo contrario causa errores)
// 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)
}
}
Cuando intento ejecutar go test
me sale el error:
# testmain
simd.TestMul: call to external function simd.mul
simd.TestMul: undefined: simd.mul
El go env
comando informa que my GOHOSTARCH
to be amd64
y mi versión Go es 1.3. Para confirmar que no era la arquitectura la que causaba el problema, encontré otro paquete que usa ensamblaje y eliminé todos los archivos de ensamblaje excepto _amd64.s
uno y sus pruebas funcionaron bien.
También intenté cambiarlo a un identificador exportado en caso de que eso estuviera causando rarezas, pero sin dados. Creo que seguí bastante de cerca la plantilla en paquetes como math/big
, así que espero que sea algo simple y obvio que me falta.
Sé que Go al menos está intentando usar el ensamblaje porque si introduzco un error de sintaxis en el archivo .s, la herramienta de compilación se quejará al respecto.
Editar:
Para ser claros, go build
se compilará limpiamente, pero go test
hace que aparezca el error.
go build
terminado limpiamente,go test
falla.