14.14 Parallelizing a computation over a large amount of data 并行化大量数据的计算 (#630)

* Create 14.14.md

* Update 14.14.md

* Update 14.14.md
This commit is contained in:
Respawnz
2019-07-11 12:20:28 +08:00
committed by ᴊ. ᴄʜᴇɴ
parent 6d4770ecd8
commit df12677f18

44
eBook/14.14.md Normal file
View File

@@ -0,0 +1,44 @@
# 14.14 并行化大量数据的计算
假设我们需要处理一些数量巨大且互不相关的数据项,它们从一个`in`通道被传递进来,当我们处理完以后又要将它们放入另一个`out`通道就像一个工厂流水线一样。处理每个数据项也可能包含许多步骤Preprocess预处理 / StepA步骤A / StepB步骤B / ... / PostProcess后处理
一个典型的用于解决按顺序执行每个步骤的顺序流水线算法可以写成下面这样:
```go
func SerialProcessData(in <-chan *Data, out chan<- *Data) {
for data := range in {
tmpA := PreprocessData(data)
tmpB := ProcessStepA(tmpA)
tmpC := ProcessStepB(tmpB)
out <- PostProcessData(tmpC)
}
}
```
一次只执行一个步骤并且按顺序处理每个项目在第1个项目没有被`PostProcess`并放入`out`通道之前绝不会处理第2个项目。
如果你仔细想想,你很快就会发现这将会造成巨大的时间浪费。
一个更高效的计算方式是让每一个处理步骤作为一个协程独立工作。每一个步骤从上一步的输出通道中获得输入数据。这种方式仅有极少数时间会被浪费,而大部分时间所有的步骤都在一直执行中:
```go
func ParallelProcessData (in <-chan *Data, out chan<- *Data) {
// make channels:
preOut := make(chan *Data, 100)
stepAOut := make(chan *Data, 100)
stepBOut := make(chan *Data, 100)
stepCOut := make(chan *Data, 100)
// start parallel computations:
go PreprocessData(in, preOut)
go ProcessStepA(preOut,StepAOut)
go ProcessStepB(StepAOut,StepBOut)
go ProcessStepC(StepBOut,StepCOut)
go PostProcessData(StepCOut,out)
}
```
通道的缓冲区大小可以用来进一步优化整个过程。
## 链接
- [目录](directory.md)
- 上一节:[在多核心上并行计算](14.13.md)
- 下一节:[漏桶算法](14.15.md)