std :: thread没有按预期立即启动(c ++ 11)

Ten*_*gis 6 c++ multithreading

我的代码中包含以下代码 main.cpp

std::thread t1(&AgentsSourcesManager::Run, &sim.GetAgentSrcManager());
doSomething(); // in the main Thread
t1.join();
Run Code Online (Sandbox Code Playgroud)

我期待t1立即开始并沿主线开始.然而,这种情况并非如此.我测量我的程序的执行时间,重复这100次并制作一些图.

请参见下图中的峰值.

在此输入图像描述

现在如果我在创建之后稍等一下 t1

std::this_thread::sleep_for(std::chrono::milliseconds(100));
Run Code Online (Sandbox Code Playgroud)

我得到了更好的结果.见下图.

在此输入图像描述

(仍然有一个高峰,但很好..)

显然我的问题是:

  • 为何达到顶峰?
  • 为什么我没有直线?

编辑

好吧,根据我现在所理解的评论,可能会有一些调度程序魔术正在进行中.

这是一个有效的例子

#include <thread>
#include <chrono>
#include <iostream>
#include <pthread.h>
#include <functional>
int main() {
     float x = 0;     float y = 0;
     std::chrono::time_point<std::chrono::system_clock> start, stop;

    start= std::chrono::system_clock::now();
    auto Thread = std::thread([](){std::cout<<"Excuting  thread"<<std::endl;});
    stop = std::chrono::system_clock::now();

    for(int i = 0 ; i<10000 ; i++)
         y += x*x*x*x*x;

    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    Thread.join();

     std::chrono::duration<double> elapsed_time = stop - start;
     std::cout << "Taken time: " << std::to_string(elapsed_time.count()) << "  "<< std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译:

g++-7 -lpthread  threads.cpp -o out2.out
Run Code Online (Sandbox Code Playgroud)

对于Analysis,我使用此代码

import subprocess
import matplotlib.pyplot as plt
import numpy as np

RUNS = 1000
factor = 1000
times = []
for i in range(RUNS):
    p = subprocess.run(["./out2.out"], stdout=subprocess.PIPE)
    line = p.stdout
    times.append(float(line.split()[-1]))
    print(i, RUNS)


times = np.array(times)  * factor
plt.plot(times, "-")
plt.ylabel("time * %d" % factor)
plt.xlabel("#runs")
plt.title("mean %.3f (+- %.3f), min = %.3f, max = %.3f" %
          (np.mean(times), np.std(times), np.min(times), np.max(times)))

plt.savefig("log2.png")
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述

我想我最好问:我怎样才能减少这种延迟并告诉我的操作系统,这个线程对我来说真的很重要,应该有更高的优先级?

Com*_*sMS 3

你没有测量你认为你在这里测量的东西:

start= std::chrono::system_clock::now();
auto Thread = std::thread([](){std::cout<<"Excuting  thread"<<std::endl;});
stop = std::chrono::system_clock::now();
Run Code Online (Sandbox Code Playgroud)

时间戳仅提供了生成该线程stop所需时间的上限,并且实际上并没有告诉您该线程何时开始执行任何实际工作(为此,您需要线程内获取时间戳)。main

另外,system_clock这并不是大多数平台上进行此类测量的最佳时钟,您应该steady_clock默认使用,high_resolution_clock如果该时钟不能为您提供足够的精度,则应采用该时钟(但请注意,您将必须处理该时钟的非单调性质)那么你自己,这很容易搞乱你获得的精度)。

正如评论中已经提到的,生成一个新线程(从而也构造一个新的std::thread)是一个非常复杂且耗时的操作。如果您需要高响应能力,您要做的就是在程序启动期间生成几个线程,然后让它们等待,std::condition_variable一旦它们的工作可用,就会收到信号。这样,您可以确保在空闲的系统上,线程将很快开始处理分配给他的工作(由于操作系统调度线程的方式,在大多数系统上立即不可能,但延迟应该远远低于一毫秒)。