前言
本文實作一個可以將數字陣列加總的平行運算,並進行效能測試。
做法
首先,建立一個 nums()
函式,生成特定數量元素的陣列,例如一個包含 1 至 100 的陣列。
1 2 3 4 5 6 7 8 9
| func nums(amount int) []int { nums := []int{}
for i := 1; i <= amount; i++ { nums = append(nums, i) }
return nums }
|
建立一個 sum()
函式,將陣列中所有的元素加總。
1 2 3 4 5 6 7 8 9
| func sum(nums []int) int { total := 0
for _, n := range nums { total += n }
return total }
|
建立一個 chunk()
函式,將陣列拆成小塊。
1 2 3 4 5 6 7
| func chunk(nums []int, size int) (chunks [][]int) { for size < len(nums) { nums, chunks = nums[size:], append(chunks, nums[0:size:size]) }
return append(chunks, nums) }
|
建立一個 sumParallel()
函式,使用特定數量的 goroutine 來將陣列中的所有元素加總。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| func sumParallel(nums []int, concurrency int) int { ch := make(chan int) chunks := chunk(nums, len(nums)/concurrency)
for i := 0; i < concurrency; i++ { go func(i int) { ch <- sum(chunks[i]) }(i) }
total := 0
for i := 0; i < concurrency; i++ { total += <-ch }
return total }
|
在主程式中使用。
1 2 3 4 5 6 7
| func main() { nums := nums(10)
total := sumParallel(nums, 2)
log.Println(total) }
|
建立單元測試
建立測試案例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| func TestSum(t *testing.T) { nums := nums(60)
if sum(nums) != 1830 { t.Fail() } }
func TestSumParallel2(t *testing.T) { nums := nums(60)
if sumParallel(nums, 2) != 1830 { t.Fail() } }
func TestSumParallel6(t *testing.T) { nums := nums(60)
if sumParallel(nums, 6) != 1830 { t.Fail() } }
|
執行單元測試:
效能測試
建立 Benchmark 案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| func BenchmarkSum(b *testing.B) { nums := nums(600000)
for i := 0; i < b.N; i++ { sum(nums) } }
func BenchmarkSumParallel2(b *testing.B) { nums := nums(600000)
for i := 0; i < b.N; i++ { sumParallel(nums, 2) } }
func BenchmarkSumParallel4(b *testing.B) { nums := nums(600000)
for i := 0; i < b.N; i++ { sumParallel(nums, 4) } }
func BenchmarkSumParallel6(b *testing.B) { nums := nums(600000)
for i := 0; i < b.N; i++ { sumParallel(nums, 6) } }
func BenchmarkSumParallel8(b *testing.B) { nums := nums(600000)
for i := 0; i < b.N; i++ { sumParallel(nums, 8) } }
func BenchmarkSumParallel10(b *testing.B) { nums := nums(600000)
for i := 0; i < b.N; i++ { sumParallel(nums, 10) } }
|
執行效能測試:
1
| go test -v -bench=. -benchmem .
|
結果:
1 2 3 4 5 6 7 8 9 10 11 12
| BenchmarkSum BenchmarkSum-12 5222 222150 ns/op 5519 B/op 0 allocs/op BenchmarkSumParallel2 BenchmarkSumParallel2-12 9115 124736 ns/op 3340 B/op 3 allocs/op BenchmarkSumParallel4 BenchmarkSumParallel4-12 16198 73768 ns/op 2052 B/op 4 allocs/op BenchmarkSumParallel6 BenchmarkSumParallel6-12 19330 63036 ns/op 1956 B/op 5 allocs/op BenchmarkSumParallel8 BenchmarkSumParallel8-12 16623 71109 ns/op 2198 B/op 5 allocs/op BenchmarkSumParallel10 BenchmarkSumParallel10-12 17088 72463 ns/op 2536 B/op 6 allocs/op
|
程式碼