doudao8283 2017-01-27 12:29
浏览 54
已采纳

如何在erlang或elixir中产生n-k光处理?

In Go I can create goroutines like this (EDITED as reported by kelu-thatsall's answer):

// test.go
package main

import (
        "fmt"
        "os"
        "strconv"
        "sync"
        "runtime"
)

func main() {
        var wg sync.WaitGroup
        if len(os.Args) < 2 {
                os.Exit(1)
        }
        k, ok := strconv.Atoi(os.Args[1])
        if ok != nil {
                os.Exit(2)
        }
        wg.Add(k * 1000)
        for z := 0; z < k*1000; z++ {
            go func(x int) {
                    defer wg.Done()
                    fmt.Println(x)
            }(z)
            if z%k == k-1 {
                // @mattn: avoid busy loop, so Go can start processing like BEAM do 
                runtime.Gosched() 
            }
        }
        wg.Wait()
}

The result in Go 1.8.0 (64-bit):

# shell    
$ go build test.go ; for k in 5 50 500 5000 50000 500000; do echo -n $k; time ./test $k > /dev/null; done

5
CPU: 0.00s      Real: 0.00s     RAM: 2080KB
50
CPU: 0.06s      Real: 0.01s     RAM: 3048KB
500
CPU: 0.61s      Real: 0.12s     RAM: 7760KB
5000
CPU: 6.02s      Real: 1.23s     RAM: 17712KB # 17 MB
50000
CPU: 62.30s     Real: 12.53s    RAM: 207720KB # 207 MB
500000
CPU: 649.47s    Real: 131.53s   RAM: 3008180KB # 3 GB

What's the equivalent code in Erlang or Elixir? (EDITED as reported by patrick-oscity's comment)

What I've tried so far is the following:

# test.exs
defmodule Recursion do
  def print_multiple_times(n) when n <= 1 do
    spawn fn -> IO.puts n end
  end

  def print_multiple_times(n) do
    spawn fn -> IO.puts n end
    print_multiple_times(n - 1)
  end
end

[x]=System.argv()
{k,_}=Integer.parse(x)
k=k*1000
Recursion.print_multiple_times(k)

The result in elixir 1.4.2 (erts-8.2.2):

# shell    
$ for k in 5 50 500 5000 50000 ; do echo -n $k; time elixir --erl "+P 90000000" test.exs $k > /dev/null; done

5
CPU: 0.53s      Real: 0.50s     RAM: 842384KB # 842 MB
50
CPU: 1.50s      Real: 0.62s     RAM: 934276KB # 934 MB
500
CPU: 11.92s     Real: 2.53s     RAM: 1675872KB # 1.6 GB
5000
CPU: 122.65s    Real: 20.20s    RAM: 4336116KB # 4.3 GB
50000
CPU: 1288.65s   Real: 209.66s   RAM: 6573560KB # 6.5 GB

But I'm not sure if the two are equivalent. Are they ?

EDIT Shortened version as mudasobwa's comment does not give correct output

# test2.exs
[x]=System.argv()
{k,_}=Integer.parse(x)
k=k*1000
1..k |> Enum.each(fn n -> spawn fn -> IO.puts n end end)

The result for k in 5 50 500 5000 50000 ; do echo -n $k; time elixir --erl "+P 90000000" test.exs $k | wc -l ; done:

5
CPU: 0.35s      Real: 0.41s     RAM: 1623344KB # 1.6 GB
2826 # does not complete, this should be 5000
50
CPU: 1.08s      Real: 0.53s     RAM: 1691060KB # 1.6 GB
35062
500
CPU: 8.69s      Real: 1.70s     RAM: 2340200KB # 2.3 GB
373193
5000        
CPU: 109.95s    Real: 18.49s    RAM: 4980500KB # 4.9 GB
4487475
50000
erl_child_setup closed
Crash dump is being written to: erl_crash.dump...Command terminated by signal 9
CPU: 891.35s    Real: 157.52s   RAM: 24361288KB # 24.3 GB

Not testing 500m for elixir because it took too long and +P 500000000 argument is bad number of processes

  • 写回答

1条回答 默认 最新

  • dongling4288 2017-01-28 09:16
    关注

    I'm sorry guys but I'm not convinced that this code in Go is really working as expected. I'm not an expert, so please correct me if I'm wrong. First of all it prints z which it seems is a current value of it in global scope (usually k*1000) https://play.golang.org/p/a4TJyjKBQh

    // test.go
    package main
    import (
      "fmt"
      "time"
    )
    
    func main() {
    
      for z:=0; z<1000; z++ {
        go func(x int) { // I'm passing z to the function with current value now
          fmt.Println(x) 
        }(z)
      }
    
      time.Sleep(1 * time.Nanosecond)
    
    }
    

    And also if I comment out Sleep the program will exit before even starting any goroutines (at least it doesn't print out the results). I would be happy to know if I'm doing something wrong, but from this simple example it seems the problem is not with Elixir, but Go code provided. Some Go gurus out there?

    I've also run some test on my local machine:

    go run test.go 500 | wc -l
    72442 # expected 500000
    go run test.go 5000 | wc -l
    76274 # expected 5000000
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)