jjzjj

c++ - 有效地收集/分散任务

coder 2024-02-25 原文

我正在使用的 MPI 实现本身并不支持完整的多线程操作(最高级别是 MPI_THREAD_SERIALIZED,原因很复杂),所以我试图将来自多个线程的请求汇集到一个单个工作线程,然后将结果分散回多个线程。

通过使用并发队列,我可以轻松地处理收集本地请求任务,并且 MPI native 支持排队异步任务。然而,问题是让双方相互交谈:

为了将响应分散回各个线程,我需要对当前进行中的请求调用类似 MPI_Waitany 的方法,但在此期间 MPI worker 被有效阻塞,因此它无法从本地工作人员那里收集和提交任何新任务。

// mpi worker thread
std::vector<MPI_Request> requests; // in-flight requests
while(keep_running)
{
    if(queue.has_tasks_available())
    {
        MPI_Request r;
        // task only performs asynchronous MPI calls, puts result in r
        queue.pop_and_run(task, &r);
        requests.push_back(r);
    }
    int idx;
    MPI_Waitany(requests.size(), requests.data(), &idx,
                MPI_STATUS_IGNORE); // problems here! can't get any new tasks
    dispatch_mpi_result(idx); // notifies other task that it's response is ready
    // ... erase the freed MPI_Request from requests
}

类似地,如果我只是让 mpi worker 等待新任务从并发队列中可用,然后使用类似 MPI_Testany 的方式轮询 MPI 响应,那么最好的响应可能要么实际到达本地 worker 需要很长时间,最坏的情况是 mpi worker 会死锁,因为它正在等待本地任务,但所有任务都在等待 mpi 响应。

// mpi worker thread
std::vector<MPI_Request> requests; // in-flight requests
while(keep_running)
{
    queue.wait_for_available_task(); // problem here! might deadlock here if no new tasks happen to be submitted
    MPI_Request r;
    queue.pop_and_run(task, &r);
    requests.push_back(r);
    int idx;
    MPI_Testany(requests.size(), requests.data(), &idx, MPI_STATUS_IGNORE);
    dispatch_mpi_result(idx); // notifies other task that its response is ready
    // ... erase the freed MPI_Request from requests
}

我能看到的解决这两个问题的唯一解决方案是让 mpi worker 只轮询双方,但这意味着我有一个永久 Hook 的线程来处理请求:

// mpi worker thread
std::vector<MPI_Request> requests; // in-flight requests
while(keep_running)
{
    if(queue.has_tasks_available())
    {
        MPI_Request r;
        // task only performs asynchronous MPI calls, puts result in r
        queue.pop_and_run(task, &r);
        requests.push_back(r);
    }
    int idx;
    MPI_Testany(requests.size(), requests.data(), &idx, MPI_STATUS_IGNORE);
    dispatch_mpi_result(idx); // notifies other task that its response is ready
    // ... erase the freed MPI_Request from requests
}

我可以引入某种休眠功能,但这似乎是一种 hack,会降低我的吞吐量。对于这种饥饿/低效率问题,是否有其他解决方案?

最佳答案

我担心你已经接近你可以用你的最终解决方案做的最好的了,循环检查本地线程和MPI_Testany(或更好的MPI_Testsome)的新任务>).

您可以做的一件事就是为此投入整个核心。优点是,这很简单,具有低延迟并提供可预测的性能。在现代 HPC 系统上,这通常是 > 20 个内核,因此开销 < 5%。如果您的应用程序受内存限制,则开销甚至可以忽略不计。不幸的是,这会浪费="" cpu="" 周期和能源。一个小的修改是在循环中引入="">usleep。您必须调整 sleep 时间以平衡利用率和延迟。

如果你想为应用程序使用所有内核,你必须小心 MPI 线程不会从计算线程中窃取 CPU 时间。我假设你的队列实现是阻塞的,即不忙等待。这导致了计算线程在等待时可以给 CPU 时间给 MPI 线程的情况。不幸的是,发送这可能不是真的,因为工作人员可以在将任务放入队列后立即继续。

您可以做的是增加 MPI 线程的 nice 级别(降低优先级),以便它主要在计算线程等待结果时运行。您还可以在循环中使用 sched_yield 向调度程序提供一些提示。虽然两者都是在 POSIX 中定义的,但它们的语义非常弱并且强烈依赖于 actual scheduler implementation .用 sched_yield 实现繁忙的等待循环通常不是一个好主意,但您别无选择。 OpenMPI 和 MPICH 在某些情况下实现了类似的循环。

额外的 MPI 线程的影响取决于您的计算线程的紧密耦合程度。例如。如果它们经常处于障碍中,则会严重降低性能,因为仅延迟单个线程就会延迟所有线程。

最后,如果您希望实现高效,则必须针对特定系统进行测量和调整。

关于c++ - 有效地收集/分散任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37915579/

有关c++ - 有效地收集/分散任务的更多相关文章

  1. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 如何使用 RSpec::Core::RakeTask 创建 RSpec Rake 任务? - 2

    如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake

  4. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  6. python - 是否可以使用 Ruby 或 Python 禁用 anchor /引用来发出有效的 YAML? - 2

    是否可以在PyYAML或Ruby的Psych引擎中禁用创建anchor和引用(并有效地显式列出冗余数据)?也许我在网上搜索时遗漏了一些东西,但在Psych中似乎没有太多可用的选项,而且我也无法确定PyYAML是否允许这样做.基本原理是我必须序列化一些数据并将其以可读的形式传递给一个不是真正的技术同事进行手动验证。有些数据是多余的,但我需要以最明确的方式列出它们以提高可读性(anchor和引用是提高效率的好概念,但不是人类可读性)。Ruby和Python是我选择的工具,但如果有其他一些相当简单的方法来“展开”YAML文档,它可能就可以了。 最佳答案

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. ruby-on-rails - Rake 任务仅调用一次时执行两次 - 2

    我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里

  9. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  10. ruby - 帮助使用 Ruby 中的 "Whenever"gem 来执行 cron 任务 - 2

    我以前没有使用过cron,所以我不能确定我这样做是对的。我想要自动化的任务似乎没有运行。我在终端中执行了这些步骤:sudogeminstall每当切换到应用程序目录无论何时。(这创建了文件schedule.rb)我将此代码添加到schedule.rb:every10.minutesdorunner"User.vote",environment=>"development"endevery:hourdorunner"Digest.rss",:environment=>"development"end我将此代码添加到deploy.rb:after"deploy:symlink","depl

随机推荐