Filling array in parallel?

blov · · 594 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m trying to fill an array or slice in parallel this way:</p> <pre><code>package main import ( &#34;runtime&#34; ) const ( NGoRoutines = 4 ) var array [100000000]int func main() { c := make(chan int, NGoRoutines) runtime.GOMAXPROCS(NGoRoutines) for i := 0; i &lt; NGoRoutines; i++ { go func(id int) { for j := id; j &lt; len(array); j = j + NGoRoutines { array[j] = j } c &lt;- 1 }(i) } // wait for goroutines to finish for i := 0; i &lt; NGoRoutines; i++ { &lt;-c } } </code></pre> <p>The resulting array is as expected (0, 1, 2, 3...)</p> <p>But i&#39;m not gaining any performance over using just one goroutine. I wrote equivalent program in C and it works. So I assume that you can&#39;t access elements of one array in parallel in Go. What would be the best way to achieve this in Go?</p> <hr/>**评论:**<br/><br/>teepark: <pre><p>You might break up the array into NGoRoutine contiguous sections so they aren&#39;t all writing to the same memory pages. See if that helps.</p> <p>Also look into sync.WaitGroup, it could simplify your final wait.</p></pre>danielt0shea: <pre><p>I think the problem is the four go-routines are doing a lot of redundant work. I think you want to break the array up into NGoRoutine chunks and have each go-routine write to that section in parallel, not have them overlap. Here is a quick and dirty version that on my machine is about twice as fast as the original version:</p> <pre><code>package main import ( &#34;runtime&#34; ) const ( NGoRoutines = 4 ) var array [100000000]int func main() { c := make(chan int, NGoRoutines) runtime.GOMAXPROCS(NGoRoutines) chunk := len(array) / NGoRoutines for i := 0; i &lt; NGoRoutines; i++ { go func(start int) { end := start + chunk if end &gt; len(array) { end = len(array) } for j := start; j &lt; end; j = j + 1 { array[j] = j } c &lt;- 1 }(i * chunk) } // wait for goroutines to finish for i := 0; i &lt; NGoRoutines; i++ { &lt;-c } } </code></pre> <p>running this code gives me:</p> <pre><code>$ time ./parallel-fill real 0m0.234s user 0m0.156s sys 0m0.266s </code></pre> <p>vs the original:</p> <pre><code>$ time ./parallel-fill-orig real 0m0.431s user 0m0.377s sys 0m0.235s </code></pre> <p>Hope that helps.</p></pre>Fwippy: <pre><p>They&#39;re running in parallel and writing to the array in parallel; I think it&#39;s just that your functions are doing so little work per loop that you really don&#39;t see much gain. </p> <p>You can add a <code>time.Sleep()</code> call in there or a busy-loop to simulate a more complicated computation. This version here worked well for me in showing the difference in goroutines: <a href="https://play.golang.org/p/JogUNCX19d" rel="nofollow">https://play.golang.org/p/JogUNCX19d</a> (copy and paste; it won&#39;t be useful to run on playground).</p> <p>There&#39;s also the possibility that you&#39;re running on a CPU with only one core, if your machine is old, or a raspberry pi, or similar.</p></pre>dchapes: <pre><blockquote> <p>copy and paste</p> </blockquote> <p>FYI, you can add <code>.go</code> to the end of a play.golang.org link to get a download-able/save-able version of the source: <a href="https://play.golang.org/p/JogUNCX19d.go" rel="nofollow">https://play.golang.org/p/JogUNCX19d.go</a></p></pre>Fwippy: <pre><p>Nifty!</p></pre>Manbeardo: <pre><p>Also, older versions of go have GOMAXPROCS=1 by default.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

594 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传