文章标题 原创 翻译 转载 文章内容 pipeline流水线模式(管道模式),我们用这个模式来计算所有质数的和。 # 什么是质数 质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。 # C++代码实现 我们先用一般的方法实现一下,后面跟Golang实现进行对比 ``` #include <iostream> #include <vector> #include <chrono> bool is_prime(int value) { int n = value / 2; for (int i = 2; i <= n; i++) { if (value % i == 0) { return false; } } return value > 1; } std::vector<int> makeNums(int min, int max) { std::vector<int> nums; nums.reserve(max - min + 1); for (int i = min; i <= max; i++) { nums.push_back(i); } return nums; } int main(int argc, char* argv[]) { auto start = std::chrono::system_clock::now(); auto nums = makeNums(1, 500000); int64_t sum = 0; for (auto n : nums) { if (is_prime(n)) { sum += n; } } auto end = std::chrono::system_clock::now(); auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); std::cout << "sum:" << sum << std::endl; std::cout << "elapsed:" << elapsed.count() << "ms" << std::endl; system("pause"); return 0; } ``` 我的windows开发机(4核),开了O2优化,跑了几次大概耗时:700~800ms # Golang pipeline实现 pipeline的好处是可以自由组合 ``` package main import ( "fmt" "math" "sync" "time" ) func chanInt(nums []int) <-chan int { out := make(chan int) go func() { for _, v := range nums { out <- v } close(out) }() return out } func chanSum(in <-chan int) <-chan int { out := make(chan int) go func() { var sum = 0 for v := range in { sum += v } out <- sum close(out) }() return out } func is_prime(value int) bool { n := int(math.Floor(float64(value) / 2)) for i := 2; i <= n; i++ { if value%i == 0 { return false } } return value > 1 } func prime(in <-chan int) <-chan int { out := make(chan int) go func() { for v := range in { if is_prime(v) { out <- v } } close(out) }() return out } type ChanIntFunc func([]int) <-chan int type PipeFunc func(<-chan int) <-chan int func pipeline(nums []int, chanInt ChanIntFunc, pipeFuncs ...PipeFunc) <-chan int { f := chanInt(nums) for _, p := range pipeFuncs { f = p(f) } return f } func makeRange(min, max int) []int { out := make([]int, 0, max-min+1) for i := min; i <= max; i++ { out = append(out, i) } return out } func main() { start := time.Now() for v := range pipeline(makeRange(1, 100000), chanInt, prime, chanSum) { fmt.Println(v) } fmt.Println(time.Now().Sub(start).Milliseconds()) } ``` 同一个环境golang跑下来大概要花2600ms,是C++的3倍多。 大家可能觉得是用了goroutine和chan的原因,其实用C++类似的方式实现耗时也是一样的: ``` start := time.Now() sum := 0 nums := makeRange(1, 100000) for i := range nums { if is_prime(nums[i]) { sum += nums[i] } } fmt.Println(sum) fmt.Println(time.Now().Sub(start).Milliseconds()) ``` # Golang 并行实现 ``` start := time.Now() nums := chanInt(makeRange(1, 100000)) const process = 5 var chans [process]<-chan int for i := range chans { chans[i] = chanSum(prime(nums)) } for n := range chanSum(merge(chans[:])) { fmt.Println(n) } fmt.Println(time.Now().Sub(start).Milliseconds()) ``` merge实现 ``` func merge(cs []<-chan int) <-chan int { var wg sync.WaitGroup out := make(chan int) wg.Add(len(cs)) for _, c := range cs { go func(c <-chan int) { for n := range c { out <- n } wg.Done() }(c) } go func() { wg.Wait() close(out) }() return out } ``` 这样跑下来耗时800多毫秒,跟C++差不多了。 # 结论 从这个例子来看golang和C++还是有一些性能差距的,当然这只是一个简单的特定例子,golang的优势不在此,对于这种密集型计算还是C/C++比较合适。 文章类别 Python Mobile Android Java Shell Life Database Bug Windows IOS Tools Boost Node.js Mac Product Tips C/C++ Golang Javascript React Qt MQ MongoDB Design Web Linux LLM ChatGPT RAG AI 提交