newLISP 多进程与多核CPU

newLISP实现了Cilk API, 可以将多个同时运行的进程执行在多处理器或者多核的CPU架构上,已达到并行节省运行时间的目的。

使用spawn和sync函数可以很快的实现。下面是来自newLISP官方文档的例子:

#!/usr/bin/newlisp

; calculate primes in a range
(define (primes from to)
  (local (plist)
      (for (i from to)
          (if (= 1 (length (factor i)))
              (push i plist -1)))
      plist))

; start child processes
(set ‘start (time-of-day))

(spawn ‘p1 (primes 1 1000000))
(spawn ‘p2 (primes 1000001 2000000))
(spawn ‘p3 (primes 2000001 3000000))
(spawn ‘p4 (primes 3000001 4000000))

; wait for a maximum of 60 seconds for all tasks to finish
(sync 60000) ; returns true if all finished in time
; p1, p2, p3 and p4 now each contain a lists of primes

(println "time spawn: " (- (time-of-day) start))
(println "time simple: " (time  (primes 1 4000000)))

(println p1)
(exit)


运行结果是:

time spawn: 5068
time simple: 8614.983
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 
 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 
 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 


现在来解释一下上面的代码:

1. local

(local是一个和(let)差不多的函数,用来初始化变量,区别是(local)将变量都初始化为nil,因此plist的初始值为nil

2. spawn 函数

syntax: (spawn sym exp [true])

sym 用来保存创建的子进程ID

exp 是子进程启动后运行的表达式,这里我们传递的是函数primes构成的表达式

true 是当父子进程通过send/receive函数通信时才需要设置,一般不需要使用该参数


spawn函数会立刻返回,所以等待子进程返回需要使用sync函数。不过要注意,sync函数返回后,子进程计算结果会保存到sym中。

3. sync函数

syntax: (sync int-timeout [func-inlet])
syntax: (sync)

int-timeout 指定等待毫秒数,如上面的60000毫秒,也就是60秒。如果指定时间到达而子进程也结束,sync返回true, 如果子进程届时还没有结束,则sync返回nil.

不管子进程是否完成,sync返回后, 子进程计算结果也会保存到之前spawn返回的pid上。

func-inlet 是可以在sync返回的时候执行的函数或者lambda表达式,参数是子进程id.


4. 用sync来跟踪进度

sync接收的超时时间只是一个估值,可以通过在循环里面多次调用,并指定较短的超时时间来



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。