【问题标题】:c++ Running a concurrent for loop, even possible?c ++运行并发for循环,甚至可能吗?
【发布时间】:2017-01-28 07:55:56
【问题描述】:

鉴于此 for 循环:

std::vector<std::string> V={"element1","element2","element3"};

for(int i=V.size(); i--;)
{
 std::cout<<i<<std::endl;
}

是否可以同时运行 for 循环的每个循环?那么每个 std::cout 会同时出现吗?

我有一个函数指针向量,我需要循环并同时执行,不是一个接一个。

注意:在这种情况下,std::thread、std::async 无济于事,因为我不知道向量的大小,因此必须在每个循环中创建一个线程并运行它。这个不会导致并发。

【问题讨论】:

  • 您应该进一步阐明您希望输出到 std::cout 的外观。您需要特定的输出顺序吗?
  • 总之不可能,即使你使用线程它们,它们也不会同时执行
  • 我的意思是...您可以创建线程并让它们都等待条件变量,然后在创建它们后发出条件信号,但@PavneetSingh 是对的,它们永远不会“同时”运行,而是交错执行。不过,这可能已经足够好了。也许对预期结果进行更多澄清会有所帮助。
  • 线程当然可以并发执行...
  • tbb::parallel_for 可能是您正在寻找的 (threadingbuildingblocks.org/docs/help/tbb_userguide/…)。

标签: c++ for-loop


【解决方案1】:

使用线程不会导致并发是什么意思?您是否希望所有线程立即在函数指针向量上创建线程,而不是让 for 循环遍历 V 并创建线程?我认为这是不可能的,而且很可能其他答案最终会在不同的抽象级别上做完全相同的事情。

示例代码:

#include <iostream>
#include <vector>
#include <thread>
#include <atomic>

typedef void (*func)();

std::atomic<int> atom;

void f1() { ++atom; }
void f2() { atom += 5; }
void f3() { atom -= 3; }

int main()
{
    using namespace std;

    vector<func> func_vec = { &f1, &f2, &f3 };
    vector<thread> thread_vec;

    for (func& f : func_vec)
        thread_vec.emplace_back(std::thread(f));

    for (thread& t : thread_vec)
        t.join();

    std::cout << "Atomic : " << atom;
}

可能有更好的方法来填充thread_vec(即迭代func_vec 和thread_vec,thread_vec 的大小设置为func_vec),但这对于一个例子来说很好。如果您在主线程执行结束之前不需要线程正确结束,您可以完全退出 thread_vec 并创建一个您立即分离的线程,作为另一个答案 demonstrated

【讨论】:

    【解决方案2】:

    是否可以同时运行for循环的每个循环?

    是的。 C++ 标准库提供了实现并发的低级工具。只需在每次迭代中启动一个新线程 - 并且在所有线程都启动之前不要加入。

    注意:在这种情况下,std::thread、std::async 无济于事,因为我不知道向量的大小,因此必须在每个循环中创建一个线程并运行它。这个不会导致并发。

    你错了。 std::thread(可能还有std::asnyc)很有用,在这种情况下可用于实现并发。在每个循环中创建线程不会阻止并发。使用函数指针的简单演示,因为那是您真正打算使用的:

    std::vector<void(*)()> function_pointers = get_the_stuff();
    for(auto f : function_pointers) {
        std::thread t(f);
        t.detach();
    }
    

    另一种稍微复杂一点的方法是创建一个线程向量。这使您可以等到所有人都通过加入执行。

    --

    std::thread 和朋友是用于并发的低级工具,可能值得对它们创建抽象 - 或使用第三方提供的现有抽象。

    另外,我敦促您重新考虑。你说你不知道向量的大小。当然,您的硬件提供商也不知道向量。他们怎么知道为您提供足够的 CPU 内核来并行执行所有线程?更好的方法是根据可用内核的数量使用恒定的线程池,以避免额外线程的开销。

    【讨论】:

      【解决方案3】:

      这是 OpenMP 的作品:

      #pragma omp parallel for
      for(int i = 0; i < V.size(); ++i)
      {
          std::cout<<i<<std::endl;
      }
      

      这使用固定的线程数(通常是 CPU 线程数)。如果V.size() 大于它,则不会同时调用所有任务。他们将等待可用的线程。

      如果您不能使用 OpenMP,第三方库和框架可以帮助您。

      【讨论】:

        【解决方案4】:

        您可以并行运行这些可执行文件。这与并行运行 for 循环无关。它更像是您的操作系统的一项功能。

        对于 Linux,请查看如何使用 fork()/exec()/system() 运行进程。

        对于 Windows,查看如何使用 CreatrProcess() 运行进程。

        【讨论】:

          【解决方案5】:

          如果您所说的可执行文件是指要启动的单独应用程序,那么您不需要使用线程。您只需在一个线程中一一启动可执行文件,而无需等待它们完成。您可以将他们的 PID 放入向量中。然后在单独的循环中,您等待这些过程完成,再次一个接一个。

          但如果这是您在程序中唯一需要做的事情,那么您最好考虑用 bash 编写它。

          【讨论】:

          • 那么 std::thread 是你的朋友。将要执行的每个函数包装到 std::thread 中,将它们放入向量中,然后等待它们。
          猜你喜欢
          • 2022-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-20
          • 1970-01-01
          相关资源
          最近更新 更多