gpt4 book ai didi

c++ - OpenMP 创建了太多线程

转载 作者:太空狗 更新时间:2023-10-29 20:36:45 25 4
gpt4 key购买 nike

我不确定为什么 OpenMP 使用这么多线程。它似乎与 Microsoft 实现无关,因为我也尝试过显示相同行为的 Intel 库。我的代码中有一些并行部分是受计算限制的,不应创建和使用比我拥有的内核更多的线程。但我观察到的是,对于 n 个启动线程,OpenMP 创建了 n*Cores 线程。对我来说,这看起来像是一个大线程泄漏。

如果我执行一个在服务器上运行的“小型”32 位应用程序,它可能会失败,因为 1000 个 OpenMP 线程需要 2 GB 的地址空间,已经没有为应用程序留下任何内存。那不应该发生。我希望最先进的线程池能够重用其线程并删除不再使用的线程。

我曾尝试使用 omp_set_num_threads(8) 将线程池大小限制为 8 个内核,但这似乎只限制了每个启动线程实例的线程数。是我做错了,还是 OpenMP 不应该以这种方式使用?

在我的 8 核机器上,我的 AsyncWorker 类中的 5 个启动线程将分配由 OpenMP 创建的 38 个线程。我希望只创建 8 个线程,并且这些线程应该在所有 5 个启动线程中重复使用。

enter image description here

#include <atomic>
#include <thread>
#include <omp.h>
#include <chrono>
#include <vector>
#include <memory>

class AsyncWorker {
private:
std::vector<std::thread> threads;

public:
AsyncWorker()
{
}

void start() // add one thread that starts an OpenMP parallel section
{
threads.push_back(std::thread(&AsyncWorker::threadFunc, this));
}

~AsyncWorker()
{
for (auto &t : threads)
{
t.join();
}
}

private:
void threadFunc()
{
std::atomic<int> counter;

auto start = std::chrono::high_resolution_clock::now();
std::chrono::milliseconds durationInMs;

while (durationInMs.count() <5000l)
{
// each instance seems to get its own thread pool.
// Why? And how can I limit the threadpool to the number of cores and when will the threads be closed?
#pragma omp parallel
{
counter++;
auto stop = std::chrono::high_resolution_clock::now();
durationInMs = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
}
}
}

};

int main() {
//omp_set_dynamic(0);
//omp_set_nested(0);
//omp_set_num_threads(8);

{
AsyncWorker foo;

foo.start(); // 1
foo.start(); // 2
foo.start(); // 3
foo.start(); // 4
foo.start(); // 5

system("pause");
}

return 0;
}

最佳答案

OpenMP 不应该以这种方式使用。混合使用 OpenMP 和其他线程方法将导致灾难,除非非常小心。即便如此,结果也是不可预测的。 OpenMP 标准有意避免定义此类互操作性,供应商可以自由地以他们认为合适的方式提供它(如果他们认为合适)。

omp_set_num_threads(8) 并不像您认为的那样。当不存在 num_threads() 子句时,它设置当前线程遇到的并行区域的线程数。此外,omp_set_nested(0) 没有(或可能)没有效果,因为您不是从 OpenMP 线程而是从 C++11 线程启动并行区域。可以通过 OMP_THREAD_LIMIT 环境变量对 OpenMP 线程总数设置全局限制,但这仅适用于 OpenMP 3.0 及更高版本,而 MSVC(永远?)停留在 OpenMP 2.0 时代。

可能的行动方案是:

  • 使用共享队列结构和在循环中旋转的 OpenMP 线程为 OpenMP 2.0 执行您自己的任务,使工作项出队
  • 用 Intel 替换 OpenMP Threading Building Blocks - 它是开源的,支持 Windows、Linux、OS X 和 Android 上的各种编译器
  • Concurrency Runtime 中的 Microsoft PPL 替换 OpenMP , 它基本上提供了 TBB 的非可移植子集

关于c++ - OpenMP 创建了太多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37391492/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com