【问题标题】:Cache efficiency with static member in thread线程中静态成员的缓存效率
【发布时间】:2019-04-30 13:40:46
【问题描述】:

我目前正在制作一个具有多个工作线程的应用程序,并行运行。程序的主要部分在工人之前执行,每个工人在完成任务后进入睡眠状态:

MainLoop()
{
    // ...

    SoundManager::PlaySound("sound1.mp3");  // Add a sound to be played, store the sound in a list in SoundManager
    SoundManager::PlaySound("sound2.mp3");
    SoundManager::PlaySound("sound3.mp3");

    // ...

    SoundThreadWorker.RunJob(); // Wake up thread and play every sound pushed in SoundManager

    // Running other threads

    SoundThreadWorker.WaitForFinish();  // Wait until the thread have finished its tasks, thread is put to sleep(but not closed)

    // Waiting other threads

    // ...
}

// In SoundThreadWorker class, running in a different thread from the main loop
RunJob()
{
    SoundManager::PlayAllSound();   // Play all sound stored in SoundManager
}

在这种情况下,存储所有声音的静态变量应该是安全的,因为线程运行时不会添加声音。

这种缓存效率高吗?

我在这里读到:https://www.agner.org/optimize/optimizing_cpp.pdf

"不同的线程需要单独的存储。没有函数或类 多线程使用的应该依赖静态或全局 变量。 (参见线程本地存储第 28 页)线程具有每个 他们的堆栈。如果线程共享,这可能会导致缓存争用 相同的缓存。”

我很难理解静态变量是如何存储在缓存中的,以及它们是如何被每个线程使用的。我是否在缓存中有两个 SoundManager 实例,因为线程不共享它们的堆栈?是否需要创建共享内存以避免此问题?

【问题讨论】:

  • 我们真的无法告诉您您的代码是否高效,因为您的代码中缺少足够的细节来了解实际情况。也就是说,如果所有线程都只从共享数据中读取,那你没问题。当你读写时,所有的 cpu 缓存都必须重新同步,这需要时间。

标签: c++ multithreading caching


【解决方案1】:

这段话是关于被改变的记忆,而不是关于保持不变的记忆。在线程之间共享常量很好。

当您有多个 CPU 每个更新同一个地方时,它们必须一直来回发送它们的更改。这会导致争用“拥有”一段特定的内存。

通常所有权并不明确。但是,当一个 CPU 告诉所有其他 CPU 需要使特定的缓存行无效,因为它只是在那里更改了某些内容,那么所有其他 CPU 都必须从其缓存中逐出该值。这具有 CPU 上次修改内存的效果,有效地“拥有”它所在的缓存行。

同样,这只是改变的事物的问题。

另外,我给您的内存和缓存视图也相当简单。请不要在推理特定代码段的线程安全时使用它。了解为什么多个 CPU 更新同一块内存对您的缓存不利的原因就足够了,但还不足以了解特定内存位置的哪个 CPU 版本最终被其他人使用。

如果内存位置在多个线程使用的线程的生命周期内不发生变化,则会导致该内存位置出现在多个 CPU 缓存中。但这不是问题。对于不会更改的特定内存位置存储在 CPU 之间共享的 L2 和 L3 缓存中也不是问题。

【讨论】:

    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 2013-12-10
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    相关资源
    最近更新 更多