首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Guile方案并行表单加速

Guile方案并行表单加速
EN

Stack Overflow用户
提问于 2018-05-13 13:02:34
回答 1查看 327关注 0票数 1

我正在试验Guile方案的并行形式,我有以下代码:

代码语言:javascript
复制
(use-modules (srfi srfi-1)
             (ice-9 pretty-print)
             (ice-9 receive))

(define (busy-work limit)
  (if (> limit 0)
      (begin (sqrt (+ (expt limit limit) 1))
             (busy-work (- limit 1)))
      'done))

(define (busy-work-2 lst)
  (cond [(null? lst) 'done]
        [else
         (expt (car lst) (car lst))
         (busy-work-2 (cdr lst))]))

(define (time thunk)
  (define starting-time (current-time))
  (define res (thunk))
  (define ending-time (current-time))
  (display "elapsed time: ")
  (display (- ending-time starting-time))
  (display "s")
  (newline)
  res)


(define (partition-4 numbers)
  (define (loop numbers rc0 rc1 rc2 rc3)
    (cond [(null? numbers) (list (reverse rc0)
                                 (reverse rc1)
                                 (reverse rc2)
                                 (reverse rc3))]
          [else
           (let* ([number (car numbers)]
                  [residue (remainder number 4)])
             (cond [(= residue 0) (loop (cdr numbers)
                                        (cons number rc0)
                                        rc1
                                        rc2
                                        rc3)]
                   [(= residue 1) (loop (cdr numbers)
                                        rc0
                                        (cons number rc1)
                                        rc2
                                        rc3)]
                   [(= residue 2) (loop (cdr numbers)
                                        rc0
                                        rc1
                                        (cons number rc2)
                                        rc3)]
                   [(= residue 3) (loop (cdr numbers)
                                        rc0
                                        rc1
                                        rc2
                                        (cons number rc3))]))]))
  (loop numbers '() '() '() '()))

(或者在我在https://github.com/ZelphirKaltstahl/guile-scheme-tutorials/blob/5321470f8f3cbbdb7f64d4ed60e4b1eaf8d8f444/parallellism/utils.scm的实验存储库中)

据我所知,这两个过程busy-workbusy-work-2都是纯粹的数字处理,有数字列表,其中没有计算依赖于另一个。我知道时间测量可能不完全准确。

但是,我始终没有通过使用更多的线程(核心,正如我在CPU指示器中的核心使用中看到的)而得到预期的加速。

下面是一些例子,从这些例子中,我希望两个线程完成任务的速度是一个内核的两倍,而4个内核的速度是两个核心的两倍。好吧,至少或多或少,因为我是以某种方式划分列表的,这应该或多或少地分散工作。

使用4核和parallel

代码语言:javascript
复制
(let ([residue-classes (partition-4 (iota 30000))])
  (time
   (lambda ()
     (parallel (busy-work-2 (car residue-classes))
               (busy-work-2 (cadr residue-classes))
               (busy-work-2 (caddr residue-classes))
               (busy-work-2 (cadddr residue-classes))))))

这在我的机器上大约在10秒内完成。有时是9人,有时是10人。

使用par-map,它使用4个线程(核心)

代码语言:javascript
复制
(let ([residue-classes (partition-4 (iota 30000))])
  (time
   (lambda ()
     (par-map busy-work-2
              residue-classes))))

这在我的机器上大约在10秒内完成。有时是9人,有时是10人。就像和parallel一样。

使用带有4个线程的n-par-map (在我的机器上)

代码语言:javascript
复制
(let ([residue-classes (partition-4 (iota 30000))])
  (time
   (lambda ()
     (n-par-map (current-processor-count)
                busy-work-2
                residue-classes))))

也是10。在这里,手册(node/Parallel-Forms.html)说:

与上述不同的是,下面描述的函数以许多线程作为参数。这使得它们本质上是不可移植的,因为指定的线程数可能与当前处理器计数返回的可用CPU核数不同(参见进程)。此外,这些函数在调用线程时会创建指定数量的线程,并在完成时终止线程,这使得它们非常昂贵。 因此,应该避免这样做。

虽然我发现这个解释没有100%的意义(为什么n-par-map不使用与parallel相同的预先创建的线程,如果这些线程足够的话)?像我的机器上的4一样,我没有看到任何巨大的开销,而且我再次看到它大约在10秒内完成。我的猜测是,线程创建所需的时间太短了,与处理数字时的所有计算相比,它根本没有被注意到。

使用两个线程(核心)的n-par-map

代码语言:javascript
复制
(let ([residue-classes (partition-4 (iota 30000))])
  (time
   (lambda ()
     (n-par-map 2
                busy-work-2
                residue-classes))))

预期:可能在20多岁完成。

结果:在12s内完成。

现在,我当然在想:“在有4个核的运行中,一定有一些巨大的开销!”

问题:但是,当我做纯粹的数字处理而不依赖于任何结果时,这种开销来自哪里呢?它是否使用了一些共享内存,从而使内存访问成为瓶颈?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-16 10:15:41

您可能正在使用一台具有两个物理内核的机器,这些内核是超线程的,因此报告了4个cpus。它所显示的是这个工作负载不适合超线程。

我在一台有两个超线程物理核的机器上得到了类似的结果。然而,对于一台有4个物理核的机器,我可以得到9秒使用所有4个核,而16秒只使用2个核,这与您所期望的更接近。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50316416

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档