使用cilk计算Fibonacci的正确方法是什么?

时间:2015-05-30 08:30:21

标签: c++ fibonacci cilk

虽然我正在学习cilk,但我反驳了两个相反的例子:

  1. From intel

  2. from wiki (or other examples in the net):

  3. 对立面就是这两行:

    x = spawn fib (n-1);
    y = spawn fib (n-2);
    

    第一个网站说:

      

    您不需要将cilk_spawn属性添加到第二个递归   拨打fib(),因为这会创建一个空的延续

    1. 我不明白为什么?
    2. 什么是正确的方法? (使用2个spawn命令或只使用一个?)

2 个答案:

答案 0 :(得分:3)

来自英特尔文档的代码“int x = cilk_spawn fib(n-1);”请求允许在另一个威胁中运行它,而下一行“int y = fib(n-2);”将与主程序运行相同的威胁。维基代码也要求计算fib(n-2)的新威胁,以便如果有超过三个处理器来运行主程序(fib(n)),fib(n-1)和fib(n-2) )所有的单独威胁。

如果只有两个处理器,两个代码将执行相同的操作。以下内容来自维基页面:

......处理者没有义务在其他地方分配衍生程序; 如果机器只有两个处理器第二个仍然忙于fib(1)当执行fib(2)的处理器进入程序调用时,第一个处理器将暂停fib(2)并执行fib(0)本身,就像它是唯一的处理器一样。当然,如果另一个处理器可用,那么它将被调用到服务中,并且所有三个处理器将同时执行单独的帧。

答案 1 :(得分:1)

您所指的维基百科中的示例来自MIT Cilk,它要求生成对Cilk函数的所有调用。 Cilk ++取消了这一要求,后者演变为英特尔的Cilk Plus实施。

请记住,这是被盗的延续,而不是衍生的功能。在生成函数之前执行代码的worker将执行派生函数。 cilk_spawn将继续推送到工人的双端队列,使其可供闲置工人偷窃。

考虑在Cilk Plus中完全实现fib:

int fib(int n) {
    if (n < 2)
        return n;
    int x = cilk_spawn fib(n-1);
    int y = fib(n-2);
    cilk_sync;
    return x+y;
}

如果你对第二次递归调用放置cilk_spawn,那么你就是允许空闲工作者在该调用之后窃取延续。但是这条链立即在cilk_sync结束,所以这是浪费时间。