Skip to content

Commit

Permalink
Imrpove performance of results calculation with loop unrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
janos committed Mar 28, 2024
1 parent d1ebb4d commit a68dc7d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 15 deletions.
44 changes: 31 additions & 13 deletions schulze.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,9 @@ func calculatePairwiseStrengths[C comparable](choices []C, preferences []int) []
}
}

// optimize most inner loop by loop unrolling
const step = 8

for i := uintptr(0); i < choicesCount; i++ {
icc := i * choicesCount

Expand All @@ -409,26 +412,41 @@ func calculatePairwiseStrengths[C comparable](choices []C, preferences []int) []
ji := jcc + i
jip := *(*int)(unsafe.Add(strengthsPtr, ji*intSize))

for k := uintptr(0); k < choicesCount; k++ {

ik := icc + k
m := min(
jip,
*(*int)(unsafe.Add(strengthsPtr, ik*intSize)),
)

jk := jcc + k
jkp := (*int)(unsafe.Add(strengthsPtr, jk*intSize))
if m > *jkp {
*jkp = m
}
ccMod := choicesCount % step
cc := choicesCount - ccMod
for k := uintptr(0); k < cc; k += step {
setStrengthValue(strengthsPtr, icc, jcc, k, jip)
setStrengthValue(strengthsPtr, icc, jcc, k+1, jip)
setStrengthValue(strengthsPtr, icc, jcc, k+2, jip)
setStrengthValue(strengthsPtr, icc, jcc, k+3, jip)
setStrengthValue(strengthsPtr, icc, jcc, k+4, jip)
setStrengthValue(strengthsPtr, icc, jcc, k+5, jip)
setStrengthValue(strengthsPtr, icc, jcc, k+6, jip)
setStrengthValue(strengthsPtr, icc, jcc, k+7, jip)
}
for k := uintptr(cc); k < choicesCount; k++ {
setStrengthValue(strengthsPtr, icc, jcc, k, jip)
}
}
}

return strengths
}

func setStrengthValue(strengthsPtr unsafe.Pointer, icc, jcc, k uintptr, jip int) {
ik := icc + k
m := min(
jip,
*(*int)(unsafe.Add(strengthsPtr, ik*intSize)),
)

jk := jcc + k
jkp := (*int)(unsafe.Add(strengthsPtr, jk*intSize))
if m > *jkp {
*jkp = m
}
}

func calculateResults[C comparable](choices []C, strengths []int) (results []Result[C], tie bool) {
choicesCount := len(choices)
results = make([]Result[C], 0, choicesCount)
Expand Down
4 changes: 2 additions & 2 deletions schulze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,7 @@ func BenchmarkVote(b *testing.B) {
func BenchmarkVoting_Results(b *testing.B) {
random := rand.New(rand.NewSource(time.Now().UnixNano()))

const choicesCount = 100
const choicesCount = 1000

choices := newChoices(choicesCount)

Expand Down Expand Up @@ -1169,7 +1169,7 @@ func BenchmarkVoting_Results(b *testing.B) {
func BenchmarkResults(b *testing.B) {
random := rand.New(rand.NewSource(time.Now().UnixNano()))

const choicesCount = 100
const choicesCount = 1000

choices := newChoices(choicesCount)
preferences := schulze.NewPreferences(choicesCount)
Expand Down

0 comments on commit a68dc7d

Please sign in to comment.