Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions simplex/axpy_archsimd_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build goexperiment.simd && amd64

package simplex

import "simd/archsimd"

// axpy computes dst[k] += factor*src[k], using SSE2 directly (no portable
// dispatch stub) via simd/archsimd's Float64x2 — part of the amd64 baseline.
func axpy(dst, src []float64, factor float64) {
fv := archsimd.BroadcastFloat64x2(factor)
n := len(dst)
k := 0
for ; k+2 <= n; k += 2 {
d := archsimd.LoadFloat64x2(dst[k : k+2])
s := archsimd.LoadFloat64x2(src[k : k+2])
s.MulAdd(fv, d).Store(dst[k : k+2])
}
for ; k < n; k++ {
dst[k] += factor * src[k]
}
}

// scale computes dst[k] /= divisor for all k, using SSE2 directly.
func scale(dst []float64, divisor float64) {
dv := archsimd.BroadcastFloat64x2(divisor)
n := len(dst)
k := 0
for ; k+2 <= n; k += 2 {
archsimd.LoadFloat64x2(dst[k : k+2]).Div(dv).Store(dst[k : k+2])
}
for ; k < n; k++ {
dst[k] /= divisor
}
}
34 changes: 34 additions & 0 deletions simplex/axpy_archsimd_arm64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build goexperiment.simd && arm64

package simplex

import "simd/archsimd"

// axpy computes dst[k] += factor*src[k], using NEON directly (no portable
// dispatch stub) via simd/archsimd's Float64x2 (128-bit, 2 lanes).
func axpy(dst, src []float64, factor float64) {
fv := archsimd.BroadcastFloat64x2(factor)
n := len(dst)
k := 0
for ; k+2 <= n; k += 2 {
d := archsimd.LoadFloat64x2(dst[k : k+2])
s := archsimd.LoadFloat64x2(src[k : k+2])
s.MulAdd(fv, d).Store(dst[k : k+2])
}
for ; k < n; k++ {
dst[k] += factor * src[k]
}
}

// scale computes dst[k] /= divisor for all k, using NEON directly.
func scale(dst []float64, divisor float64) {
dv := archsimd.BroadcastFloat64x2(divisor)
n := len(dst)
k := 0
for ; k+2 <= n; k += 2 {
archsimd.LoadFloat64x2(dst[k : k+2]).Div(dv).Store(dst[k : k+2])
}
for ; k < n; k++ {
dst[k] /= divisor
}
}
18 changes: 18 additions & 0 deletions simplex/axpy_generic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//go:build !goexperiment.simd

package simplex

// axpy computes dst[k] += factor*src[k] for all k. Scalar fallback used by
// default builds (Go 1.27+ with GOEXPERIMENT=simd gets a vectorized version).
func axpy(dst, src []float64, factor float64) {
for k := range dst {
dst[k] += factor * src[k]
}
}

// scale computes dst[k] /= divisor for all k.
func scale(dst []float64, divisor float64) {
for k := range dst {
dst[k] /= divisor
}
}
37 changes: 37 additions & 0 deletions simplex/axpy_simd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//go:build goexperiment.simd && !arm64 && !amd64

package simplex

import "simd"

// axpy computes dst[k] += factor*src[k], vectorized via the portable simd
// package. arm64 and amd64 use simd/archsimd directly (axpy_archsimd_*.go).
func axpy(dst, src []float64, factor float64) {
fv := simd.BroadcastFloat64s(factor)
width := fv.Len()
n := len(dst)
k := 0
for ; k+width <= n; k += width {
d := simd.LoadFloat64s(dst[k : k+width])
s := simd.LoadFloat64s(src[k : k+width])
s.MulAdd(fv, d).Store(dst[k : k+width])
}
for ; k < n; k++ {
dst[k] += factor * src[k]
}
}

// scale computes dst[k] /= divisor for all k, vectorized via the portable
// simd package.
func scale(dst []float64, divisor float64) {
dv := simd.BroadcastFloat64s(divisor)
width := dv.Len()
n := len(dst)
k := 0
for ; k+width <= n; k += width {
simd.LoadFloat64s(dst[k : k+width]).Div(dv).Store(dst[k : k+width])
}
for ; k < n; k++ {
dst[k] /= divisor
}
}
11 changes: 2 additions & 9 deletions simplex/simplex.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,7 @@ func duals(st *State, cost []float64, m int, dst []float64) {
if cb == 0 {
continue
}
row := st.binv[i*m : i*m+m]
for k := 0; k < m; k++ {
dst[k] += cb * row[k]
}
axpy(dst, st.binv[i*m:i*m+m], cb)
}
}

Expand Down Expand Up @@ -523,11 +520,7 @@ func (lp *LP) pivot(st *State, q int, dir float64, a []float64, t float64, leave
if i == leaveRow || a[i] == 0 {
continue
}
factor := a[i]
row := st.binv[i*m : i*m+m]
for k := 0; k < m; k++ {
row[k] -= factor * rowR[k]
}
axpy(st.binv[i*m:i*m+m], rowR, -a[i])
}
st.basicOf[leaveRow] = q
st.status[q] = basic
Expand Down