Skip to content

Commit e393198

Browse files
nonebackclaude
andcommitted
perf(benchmark): add concurrency scaling to topology benchmarks
- Add C10/C40/C80 variants for Concurrent benchmarks - Add C10/C40 variants for Serial and DenseLayers benchmarks - Update comments to clarify concurrency is goroutine pool size Key finding: larger concurrency can hurt performance in high-concurrency small-task scenarios due to increased lock contention and condition variable overhead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent cbd0d51 commit e393198

1 file changed

Lines changed: 53 additions & 43 deletions

File tree

benchmark/benchmark_test.go

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,46 @@ import (
99
)
1010

1111
// --- Topology scaling: measure scheduling overhead across graph shapes and sizes ---
12+
// concurrency is goroutine pool size, can be larger than NumCPU since goroutines are lightweight
1213

1314
func BenchmarkConcurrent(b *testing.B) {
15+
numCPU := runtime.NumCPU()
1416
for _, n := range []int{8, 32, 128, 512} {
15-
b.Run(fmt.Sprintf("N%d", n), func(b *testing.B) {
16-
exec := gotaskflow.NewExecutor(uint(runtime.NumCPU()))
17-
tf := gotaskflow.NewTaskFlow("concurrent")
18-
for i := 0; i < n; i++ {
19-
tf.NewTask(fmt.Sprintf("T%d", i), func() {})
20-
}
21-
b.ResetTimer()
22-
for i := 0; i < b.N; i++ {
23-
exec.Run(tf).Wait()
24-
}
25-
})
17+
for _, c := range []int{numCPU, numCPU * 4, numCPU * 8} {
18+
b.Run(fmt.Sprintf("N%d-C%d", n, c), func(b *testing.B) {
19+
exec := gotaskflow.NewExecutor(uint(c))
20+
tf := gotaskflow.NewTaskFlow("concurrent")
21+
for i := 0; i < n; i++ {
22+
tf.NewTask(fmt.Sprintf("T%d", i), func() {})
23+
}
24+
b.ResetTimer()
25+
for i := 0; i < b.N; i++ {
26+
exec.Run(tf).Wait()
27+
}
28+
})
29+
}
2630
}
2731
}
2832

2933
func BenchmarkSerial(b *testing.B) {
34+
numCPU := runtime.NumCPU()
3035
for _, n := range []int{8, 32, 128, 512} {
31-
b.Run(fmt.Sprintf("N%d", n), func(b *testing.B) {
32-
exec := gotaskflow.NewExecutor(uint(runtime.NumCPU()))
33-
tf := gotaskflow.NewTaskFlow("serial")
34-
prev := tf.NewTask("T0", func() {})
35-
for i := 1; i < n; i++ {
36-
next := tf.NewTask(fmt.Sprintf("T%d", i), func() {})
37-
prev.Precede(next)
38-
prev = next
39-
}
40-
b.ResetTimer()
41-
for i := 0; i < b.N; i++ {
42-
exec.Run(tf).Wait()
43-
}
44-
})
36+
for _, c := range []int{numCPU, numCPU * 4} {
37+
b.Run(fmt.Sprintf("N%d-C%d", n, c), func(b *testing.B) {
38+
exec := gotaskflow.NewExecutor(uint(c))
39+
tf := gotaskflow.NewTaskFlow("serial")
40+
prev := tf.NewTask("T0", func() {})
41+
for i := 1; i < n; i++ {
42+
next := tf.NewTask(fmt.Sprintf("T%d", i), func() {})
43+
prev.Precede(next)
44+
prev = next
45+
}
46+
b.ResetTimer()
47+
for i := 0; i < b.N; i++ {
48+
exec.Run(tf).Wait()
49+
}
50+
})
51+
}
4552
}
4653
}
4754

@@ -65,28 +72,31 @@ func BenchmarkDiamond(b *testing.B) {
6572
}
6673

6774
func BenchmarkDenseLayers(b *testing.B) {
75+
numCPU := runtime.NumCPU()
6876
for _, layers := range []int{4, 8} {
6977
for _, width := range []int{4, 8} {
70-
b.Run(fmt.Sprintf("L%dxW%d", layers, width), func(b *testing.B) {
71-
exec := gotaskflow.NewExecutor(uint(runtime.NumCPU()))
72-
tf := gotaskflow.NewTaskFlow("dense_layers")
73-
var curLayer, prevLayer []*gotaskflow.Task
74-
for l := 0; l < layers; l++ {
75-
for w := 0; w < width; w++ {
76-
task := tf.NewTask(fmt.Sprintf("T%d_%d", l, w), func() {})
77-
for _, p := range prevLayer {
78-
p.Precede(task)
78+
for _, c := range []int{numCPU, numCPU * 4} {
79+
b.Run(fmt.Sprintf("L%dxW%d-C%d", layers, width, c), func(b *testing.B) {
80+
exec := gotaskflow.NewExecutor(uint(c))
81+
tf := gotaskflow.NewTaskFlow("dense_layers")
82+
var curLayer, prevLayer []*gotaskflow.Task
83+
for l := 0; l < layers; l++ {
84+
for w := 0; w < width; w++ {
85+
task := tf.NewTask(fmt.Sprintf("T%d_%d", l, w), func() {})
86+
for _, p := range prevLayer {
87+
p.Precede(task)
88+
}
89+
curLayer = append(curLayer, task)
7990
}
80-
curLayer = append(curLayer, task)
91+
prevLayer = curLayer
92+
curLayer = nil
8193
}
82-
prevLayer = curLayer
83-
curLayer = nil
84-
}
85-
b.ResetTimer()
86-
for i := 0; i < b.N; i++ {
87-
exec.Run(tf).Wait()
88-
}
89-
})
94+
b.ResetTimer()
95+
for i := 0; i < b.N; i++ {
96+
exec.Run(tf).Wait()
97+
}
98+
})
99+
}
90100
}
91101
}
92102
}

0 commit comments

Comments
 (0)