我如何在不同的核心上运行4个线程(并行)

How can I run 4 threads each on a different core (parallelism)?

本文关键字:4个 运行 线程 并行 核心      更新时间:2023-10-16

我想并行运行(不是并发)1四个线程做完全独立的事情。我是第一次接触并行,我有几个问题。我想这样做的原因是因为性能对我来说非常重要。我在一个4核的Windows机器上工作,我在Visual Studio Community 2015中使用c++。

我是否应该尝试自己调度线程,以便每个线程在不同的核心上运行,或者我应该让操作系统调度程序去做?在我看来,我认为如果我强迫它在不同的核心上运行每个线程会更快。我该怎么做呢?

这是我到目前为止所尝试的:

#include <thread>
void t1(){//do something}
void t2(){//do something}
void t3(){//do something}
void t4(){//do something}
int main(){
   std::thread thread1(t1);
   std::thread thread2(t2);
   std::thread thread3(t3);
   std::thread thread4(t4);
   t1.join();
   t2.join();
   t3.join();
   t4.join();
}

我知道join()阻塞线程,直到它完成,但我不确定它是否并行运行线程?我的代码是并发执行线程还是并行执行线程?


1

<一口>注意:

并发性本质上是指同时执行两个任务。这可能意味着其中一个在短时间内"暂停",而另一个正在处理。

并行性要求在特定时刻至少有两个进程/任务正在被执行。

你已经完成了,不需要安排任何事情。只要有多个处理器可用,你的线程就会在可用的内核上同时运行。

如果可用的处理器少于4个,比如2个,那么线程将以交错方式运行,在任何给定时间最多运行2个。


注。你自己也很容易体验到——只需要创建4个无限循环,并在4个不同的线程中运行它们。您将看到4个cpu正在被使用。


免责声明:当然,在"底层",调度是由操作系统为您完成的。因此,您依赖于操作系统中内置的调度器的质量来实现并发性。运行c++应用程序的操作系统中内置的调度器的公平性超出了c++标准,因此无法保证。但实际上,特别是在学习编写并发应用程序时,大多数现代操作系统都会在线程调度方面提供足够的公平性。

没有标准的方法来设置给定线程的亲和性,在底层,std::thread在linux/unix上使用posix线程实现,在windows下使用windows线程实现。解决方案是使用本机api,例如在windows下,下面的代码将导致我的i7 CPU的所有8核的充分利用:

  auto fn = []() {while (true);};
  std::vector<std::thread> at;
  const int num_of_cores = 8;
  for (int n = 0; n < num_of_cores; n++) {
    at.push_back(std::thread(fn));
    // for POSIX: use pthread_setaffinity_np
    BOOL res = SetThreadAffinityMask(at.back().native_handle(), 1u << n);
    assert(res);
  }
  for (auto& t : at) t.join();

但是在注释掉SetThreadAffinityMask之后,我仍然得到相同的结果,所有的内核都被充分利用,所以Windows调度程序做得很好。

如果你想更好地控制系统核心,可以看看像OpenMP、TBB(线程构建块)、PPL这样的库。

如果您愿意,您可能希望设置应用程序关联。基本上,如果你有像i7 CPU 4核/8线程,你的应用程序会更快,如果你设置亲和一个线程每核一个线程(而不是每个线程)。

有一个命令行工具可以这样做:在Windows 7上使用start/affinity命令设置affinity

同样,亲和性可以通过任务管理器设置:http://www.windowscentral.com/assign-specific-processor-cores-apps-windows-10