【问题标题】:SFML Threads not running parallelSFML 线程未并行运行
【发布时间】:2012-09-09 19:36:34
【问题描述】:

我正在尝试学习线程和互斥锁是如何工作的,但是我现在遇到了一些困惑,我从官方 SFML 1.6 教程中获取了以下代码:

#include <SFML/System.hpp>
#include <iostream>

void ThreadFunction(void* UserData)
{
    // Print something...
    for (int i = 0; i < 10; ++i)
        std::cout << "I'm the thread number 1" << std::endl;
}

int main()
{
    // Create a thread with our function
    sf::Thread Thread(&ThreadFunction);

    // Start it !
    Thread.Launch();

    // Print something...
    for (int i = 0; i < 10; ++i)
        std::cout << "I'm the main thread" << std::endl;

    return EXIT_SUCCESS;
}

它说

因此,来自两个线程的文本将同时显示。

但是这并没有发生,它首先执行第一个线程然后执行第二个线程,它们不应该同时运行吗?我在 Windows XP SP3 上使用 Codeblocks IDE,运行 SFML 1.6。我做错了什么,还是我误解了它们的工作原理?从我的角度来看,线程应该同时执行,所以输出应该是这样的

"来自线程 1 的文本 来自线程 2 的文本 来自线程 1 的文本 等等”

【问题讨论】:

  • 尝试提高计数器...或者在每个循环中添加一个小延迟。
  • 输出比以前更令人困惑,它显示的内容与我原来的帖子相同,除了更多行,但在第二个线程的末尾,它从第一个线程添加了一行。很混乱,不过这段代码是我从官网拿的,不是我写的,反正不应该行吗?
  • 准备好输出“混乱”,因为 cout 不同步,如果多个线程同时写入它可能很难读取。

标签: c++ multithreading sfml


【解决方案1】:

...它们不应该同时运行吗?

嗯,这取决于。

如果您有两个或更多内核,它们可能同时运行。

即使您有可用的硬件,也取决于您的操作系统来决定如何安排您的线程:如果您想鼓励您的操作系统交错两个线程(您不能没有更多工作),尝试将sleepnanosleepyield 调用添加到您的循环中(确切的原语将取决于您的平台)。


如果它可以帮助您了解内核将如何以及为何做出调度决策,请注意大多数 CPU 架构将保留大量状态(分支预测表、数据和指令缓存),这些状态非常适合优化单线程执行。

因此,让给定线程尽可能长时间地在给定内核上运行通常更有效,以最大限度地减少可避免的上下文切换、缓存未命中和错误预测的数量。

现在,时间片通常用作每个单独进程的最佳吞吐量与最佳延迟或对外部事件的响应之间的一种权衡。线程可能会阻塞(通过等待外部事件,例如用户输入或设备 I/O,因为它显式与另一个线程同步,或者显式休眠或让步),在这种情况下,另一个线程将被调度,而第一个线程不能取得进展,但否则它通常会运行,直到内核在其分配的时间片结束时抢占它。

当父线程创建子线程时,我不想猜测当前内核上哪个“更热”,因此让父线程完成其时间片(除非它阻塞)是合理的默认值。

子线程可能会立即运行,但如果它不抢占父线程,那么为什么它应该立即抢占不同核心上的线程也不是很明显。毕竟,它仍然和父线程在同一个进程中,并且共享相同的内存、地址映射和其他资源:除非另一个内核完全空闲,否则调度子线程的最佳位置可能是 on与其父级相同的核心,因为父级很有可能将这些共享资源保持在缓存中。

因此,您的线程没有交错的原因可能是 在进程退出之前运行了相当一部分时间片,也没有任何阻塞 I/O 或显式产生 ( stdout 不会阻塞这么多数据,因为它很容易被缓冲)。

【讨论】:

  • 我没有多核,但我要试试 sleep 看看它的表现如何。
猜你喜欢
  • 2015-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 2023-03-09
相关资源
最近更新 更多