【问题标题】:Queries for cyclic proportional assignment of work to hosts对主机的循环按比例分配工作的查询
【发布时间】:2022-01-01 06:52:45
【问题描述】:

考虑以循环方式分布在N 主机上的M 工作块,其中每个主机必须获得与其速度成正比的工作量。没有比例,这被实现为:

int64_t AssignWorkToHost(const int64_t i_work) {
  return i_work % N;
}

比例是权重p[i]1.0,因此i-th 主机必须获得更多或更少p[i]*M 的工作。

M 非常大,以至于存储 M 值不适合单个主机的内存(但适合的解决方案也很有趣)。 N 可以大到 10 000。理想情况下,每个主机必须存储不超过 O(M/N) 的值,AssignWorkToHost() 的计算复杂度应该不超过 O(N)。预处理很好。该算法应该是确定性的,这意味着分布式组中的每个进程必须将相同的工作分配给主机。

【问题讨论】:

    标签: c++ algorithm partitioning distributed-computing deterministic


    【解决方案1】:

    我建议使用 priority queue 存储 (estimated processing time, worker) 对和按该顺序进行比较的自定义比较器。

    在伪代码中,assign to work 的主体如下所示:

    (estimated_time, i) = queue.pop()
    queue.push((estimated_time + worker_time[i], i))
    return i
    

    这是确定性的,需要O(N) 内存,并且每次分配都需要时间O(log(N))

    当然,您设置了worker_time[i] = 1.0/worker_speed[i],现在分配给i 的工人数量与其速度成正比。


    对于查询界面,我们可以通过重建历史中的单个点然后向前播放的简单技巧来避免重播所有历史。为此,当时(i_work-1)/total_speed 不超过 i_work-1 可以产生。此外,不少于 i_work-N 可以产生。 (为什么?每个工人都未能产生小于理论 elapsed_time / worker_speed[i] 限制的 1 的分数。因此,N 工人在 N 下的产量低于该理论限制。由于它必须是整数,因此将其置于大多数 N-1 落后。和 i_work-1 - (N-1) = i_work-N。)那时,对于每个工人,我们知道该工人生产了多少,我们知道下一个工人何时会生产另一个单位。

    这足以在那个时刻产生优先级队列。然后我们向前播放。在不超过N 的步骤中,k'th 将弹出并正确分配。

    查询版本的总运行时间为O(N log(N))。俗话说,“从所有意图和目的来看,log(N) 是一个常数。对于 Google,它是一个更大的常数。”

    (以相当复杂的代价为代价,我认为您可以使查询界面真正成为O(N)。)

    在几乎是有效 Python 的伪代码中:

    total_worker_speed = sum(1/t for t in worker_time)
    t = (i_work-1) / total_worker_speed
    total_done = 0
    todo = []
    for i in 0..count_workers:
        # At time t, this is how many are left.
        done = floor(t/worker_time[i])
        # This is how long until this worker produces the next unit
        time_left = (done+1)*worker_time[i] - t
        todo.push([time_left, i])
        total_done += done
    
    queue = heapify(todo) # turning array into priority queue is O(N)
    while total_done < iwork:
        # Get the next one.
        (estimated_time, i) = queue.pop()
        queue.push((estimated_time + worker_time[i], i))
        total_done += 1
    
    # i now has the job that produced the iwork job.
    return i
    

    【讨论】:

    • 感谢您的解决方案。但是,对于类似查询的界面,我看不到使用少于O(M) 内存的方法。请在我的问题中查看AssignWorkToHost():它允许以任意顺序查询分配给哪个主机的工作。
    • @SergeRogatch 我添加了关于如何创建查询界面的说明。但是考虑到查询接口的成本有多么昂贵,在可能的情况下,最好尽可能使用增量方法。
    • 抱歉,我仍然没有得到算法。您可以为查询功能编写(伪)代码吗?我无法避免它,因为这些工作不是按顺序分配的,对于其中一些来说,可能没有查询,等等。
    • @SergeRogatch 我添加了注释伪代码。
    猜你喜欢
    • 2013-11-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多