【问题标题】:PRAM CREW algorithm for counting odd numbers用于计算奇数的 PRAM CREW 算法
【发布时间】:2018-01-17 09:40:29
【问题描述】:

所以我尝试解决以下任务:

开发一个 CREW PRAM 算法来计算整数序列 x_1,x_2,...x_n 的奇数。

n 是处理器的数量 - 复杂度应该是 O(log n) 并且 log_2 n 是自然数

到目前为止我的解决方案:

Input: A:={x_1,x_2,...,x_n} Output:=oddCount
begin 
1. global_read(A(n),a)
2. if(a mod 2 != 0) then
       oddCount += 1

问题是,由于 CREW 我不允许同时使用多个写入指令oddCount += 1 正在读取oddCount 然后写入oddCount + 1,所以会有多个写入。

我必须做这样的事情吗

Input: A:={x_1,x_2,...,x_n} Output:=oddCount
begin 
1. global_read(A(n),a)
2. if(a mod 2 != 0) then
       global_write(1, B(n))
3. if(n = A.length - 1) then
      for i = 0 to B.length do
         oddCount += B(i)

那么首先每个进程确定它是奇数还是偶数,最后一个进程计算总和?但这将如何影响复杂性,是否有更好的解决方案?

感谢 libik,我得到了这个解决方案:(n 以 0 开头)

Input: A:={x_1,x_2,...,x_n} Output:=A(0):=number off odd numbers
begin 
1. if(A(n) mod 2 != 0) then
       A(n) = 1
   else
       A(n) = 0
2. for i = 1 to log_2(n) do
       if (n*(2^i)+2^(i-1) < A.length)
           A(n*(2^i)) += A(n*(2^i) + (2^(i-1)))
end

i = 1 --> A(n * 2): 0 2 4 6 8 10 ... A(n*2 + 2^0): 1 3 5 7 ...

i = 2 --> A(n * 4): 0 4 8 12 16 ... A(n*4 + 2^1): 2 6 10 14 18 ...

i = 3 --> A(n * 8): 0 8 16 24 32 ... A(n*8 + 2^2): 4 12 20 28 36 ...

所以第一个 if 是第 1 步,for 代表 log_2(n)-1 步,所以所有的都有 log_2(n) 步。解应该在 A(0) 中。

【问题讨论】:

    标签: algorithm parallel-processing big-o complexity-theory


    【解决方案1】:

    您的解决方案是 O(n),因为循环必须遍历所有数字(这意味着您根本不使用多个处理器)

    CREW 意味着您不能写入同一个单元格(在您的示例单元格=处理器内存中),但您可以一次写入多个单元格。

    那么如何做到尽可能快呢?

    在初始化时,所有处理器都以 1 或 0 开头(有或没有奇数)

    在第一轮中,只需将邻居 x_2 与 x_1 相加,然后将 x_4 与 x_3 相加,以此类推。 它将在 O(1) 中完成,因为每隔一个处理器“p_x”并行查看“p_x+1”处理器并添加 0 或 1(是否有奇数)

    然后在处理器 p1,p3,p5,p7.... 中您有部分解决方案。让我们再做一次,但现在 p1 看起来像 p3,p5 看起来像 p7,p_x 看起来像 o_x+2

    那么您只能在处理器 p1、p5、p9 等中获得部分解决方案。

    重复这个过程。每一步处理器的数量减半,所以你需要 log_2(n) 步。


    如果这是现实生活中的示例,则通常会计算同步成本。基本上在每一步之后,所有处理器都必须自己同步,所以他们现在可以执行第二步(当您在每个处理器中运行所描述的代码时,但是您如何知道您是否已经可以从处理器 p_x 添加数字,因为您可以在 p_x 完成工作后执行)。

    您需要某种“时钟”或同步。

    在本例中,最终复杂度为log(n)*k,其中k 是同步的复杂度。

    成本取决于机器或定义。通知处理器您已完成的一种方法与此处描述的用于计算奇数的方法基本相同。然后它也会花费k=log(n),这将导致log^2(n)

    【讨论】:

    • Dubbox - 我认为处理器的“索引”不正确,而不是n 你应该有n^i,所以你得到数字“2, 4, 8, 16, 32.. 。”
    • libik - 我试图通过 if(n mod i == 0) 来实现这一点,所以在第一步中,处理器 0,2,4,6,.. 正在计算,在第二步0,3,6,9,... 等等。如果你用 n^i 做它,它可能会做同样的事情,问题是什么更有效?猜猜是你的?
    • 你不会得到正确的解决方案,最好的办法是拿起铅笔和纸画出来,想象它有n个人可以互相做笔记。第一步需要 0,2,4,6,8...,然后是 0,4,8,12,16...,然后是 0,8,16,32,64
    • 这比我想象的要复杂,但我想我找到了解决方案。 {n^i} 也会导致 0 1 4 9 16。但我认为我的编辑会做到吗?那么它仍然是 O(log_2 n) 步骤还是我必须将 1. 包含到我的 for 循环中?为什么要求 O(log n) 的任务可能是一个错字?
    • 第一步需要 O(1) 时间(无论n 有多大,所有处理器都并行执行此操作),因此它不会影响任何事情。现在解决方案是正确的,应该只采取 log_2(n) 步骤。如果您对现实生活中的解决方案感兴趣,通常还有同步计算。在 for 循环中的每个步骤之后,处理器必须通知其他人他们已经“完成”,以便可以进行下一步。同步的时间取决于具体的机器。
    猜你喜欢
    • 2014-01-26
    • 2016-09-19
    • 2011-08-24
    • 2023-03-31
    • 2012-04-29
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多