C ++ std :: threads是否有预热期?

有点背景-我正在运行以下设置:

  • i5 8300H(4核,8线程)
  • 32 GB RAM
  • Ubuntu 19.10
  • GCC 9.2.1,C ++ 17标准

我有一个线程管理器-本质上是一个对象,您可以将一些数据中继到该对象,为它提供一个可调用的对象,然后可以并行运行任务,并且该线程管理器可以使线程超时(如果某些任务挂起,例如我正在做的事情就是这种情况),分批给他们数据,等等。

此行为的伪代码如下:

function do_tasks(task,data,batch_size,timeout,threads,output_streams):
    assert arguments_are_valid()

    failed_tasks = []

    while(true):
        if data.size() == 0:
            break

        for thread in threads:
            if thread.running():
                stop_thread(thread)

            if thread.results.size() == 0:
                failed_tasks <- failed_tasks + thread.given_data
            else:
                data <- data + thread.given_data(data.begin() + thread.results.size(),thread.given_data.end())

            start_thread(thread,task,take_data(data,min(batch_size,data.size()))

        wait_for_threads_completed_or_timeout(threads,timeout)

    return failed_tasks

我没有使用任何异国情调的东西,这都是通过普通的std :: thread,std :: list,std :: future和std :: promise完成的。

长话短说,您为线程提供了数据。当您评估线程已完成的操作时,如果整个批处理都失败了(即,所有数据元素都没有解决),则整个批处理都将转移到fail_tasks容器中,然后再返回该容器。然后,通过运行batch_size为1的任务来解决这些失败的批次(因此,当任务超时时,确实需要手动检出),但是那部分并不重要。如果至少有一个数据元素已解析,则将未解析的部分传输回数据容器。直到所有数据元素都被解析或标记为failed_tasks为止。

现在,通常可以说我在7个线程上的100000个元素上运行它。发生的情况是,我第一次运行它,最多有2000个元素超时。第二次也类似,500-2000个元素超时。但是这是很奇怪的部分-运行几次后,我得到了预期的行为,大约2-5个任务失败了。

查看正在运行的功能,平均每个单线程它每秒可以处理10500个数据元素。它的最小运行时间不到一纳秒,而观察到的最大运行时间则是几毫秒(它将数据与正则表达式匹配,并且某些序列或多或少地充当DoS攻击,因此可能会大大降低执行速度) 。在7个线程上运行它通常可以平均每秒处理70000个数据元素,因此效率约为95%。但是,当发生前几次运行时,该速度下降到每秒55000个数据元素,效率大约为75%,性能显着下降。现在,性能并不是那么关键(我需要每秒处理20000个数据元素,一个任务2个线程就足够了),但是随着性能降低,失败的任务数量也会增加,这使我怀疑问题出在线程本身。

我已阅读:

What really is to “warm up” threads on multithreading processing?

,但是该行为似乎是由JIT解释器引起的,而C ++在编译时却没有这种行为。我知道std :: thread的开销,但怀疑它不是那么大。我在这里经历的事情与预热类似,但是我从未听说过线程具有预热期。即使当我更改数据(每次运行,使用不同的数据集)时,这种行为也是一致的,因此我怀疑没有进行任何高速缓存可以加快速度。

该实现可能是正确的,已对其进行了审核和正式测试。该代码主要是C和C ++,并且正在积极维护中,因此我怀疑这不是bug。但是我在互联网上找不到其他人遇到同样的问题,所以让我想知道我们是否还有什么遗漏。

任何人都知道为什么会发生这种预热吗?

编辑:工作是这样执行的:

for(ull i = 0; i != batch_size && future.wait_for(nanoseconds(0)) == future_status::timeout; ++i)
{
    //do stuff
}

由线程运行的函数会收到一个线程可以检查的future,然后再在下一个数据元素(此处称为future)上运行任务。

yangongshang0812 回答:C ++ std :: threads是否有预热期?

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3152742.html

大家都在问