parallel.go 1020 B

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package imaging
  2. import (
  3. "runtime"
  4. "sync"
  5. "sync/atomic"
  6. )
  7. var parallelizationEnabled = true
  8. // if GOMAXPROCS = 1: no goroutines used
  9. // if GOMAXPROCS > 1: spawn N=GOMAXPROCS workers in separate goroutines
  10. func parallel(dataSize int, fn func(partStart, partEnd int)) {
  11. numGoroutines := 1
  12. partSize := dataSize
  13. if parallelizationEnabled {
  14. numProcs := runtime.GOMAXPROCS(0)
  15. if numProcs > 1 {
  16. numGoroutines = numProcs
  17. partSize = dataSize / (numGoroutines * 100)
  18. if partSize < 1 {
  19. partSize = 1
  20. }
  21. }
  22. }
  23. if numGoroutines == 1 {
  24. fn(0, dataSize)
  25. } else {
  26. var wg sync.WaitGroup
  27. wg.Add(numGoroutines)
  28. idx := uint64(0)
  29. for p := 0; p < numGoroutines; p++ {
  30. go func() {
  31. defer wg.Done()
  32. for {
  33. partStart := int(atomic.AddUint64(&idx, uint64(partSize))) - partSize
  34. if partStart >= dataSize {
  35. break
  36. }
  37. partEnd := partStart + partSize
  38. if partEnd > dataSize {
  39. partEnd = dataSize
  40. }
  41. fn(partStart, partEnd)
  42. }
  43. }()
  44. }
  45. wg.Wait()
  46. }
  47. }