原子和std :: mutex的成本是否会破坏多线程RLNC编码的性能

时间:2018-05-09 11:08:23

标签: c++ multithreading performance

我正在尝试使用多线程进行随机线性网络编码(RLNC)编码以提高性能。 但是,我遇到了性能问题,我的多线程解决方案速度慢,比当前的非线程版本慢得多。我暂停了atomic访问m_completed以及std :: mutex将元素插入到m_results这会导致我的性能下降。但是,我不知道如何确认这一点。

在主线程completed()的{​​{1}} - 循环中调用函数while以获得更多信息,导致大量原子访问,但我不能找到一个没有原子或互斥锁的正确方法。你可以在下面找到代码。

所以,如果有人可以看到错误或指导我更好地做到这一点,我将非常感激。我已经花了1.5周的时间来弄清楚现在的错误,我的唯一想法是while(!encoder.completed()){}atomic

std::mutex

1 个答案:

答案 0 :(得分:1)

瓶颈可能不是对Completed()的调用。

在x86上,来自字对齐uint32_t的读取自动是原子操作,std::atomic或不是std::atomicuint32_t在x86上对std::atomic<uint32_t> m_buffered[31]; std::atomic<uint_32t>& m_completed = m_buffered[15];所做的唯一事情就是确保它是字对齐的,并且编译器不会重新排序或优化它。

紧密循环负载不是总线争用的原因。第一次读取时将出现高速缓存未命中,但后续加载将是高速缓存命中,直到通过从另一个线程写入地址使高速缓存无效。有一个警告 - 意外共享缓存行(&#34;虚假共享&#34;)。关于如何通过在原子的两侧切换到60字节未使用填充的数组来消除这种可能性的一个想法(仅使用中间的一个)。 int m_completed = 0; // no longer atomic std::condition_variable cv; // in main...(pseudocode) lock (unique) m_mutex // the m_mutex from the class while !Completed() cv.wait(m_mutex) // in thread (pseudocode) bool toSignal = false; lock guard m_mutex this->m_result.insert(std::end(this->m_result), std::begin(total_payload), std::end(total_payload)); ++m_completed; toSignal = Completed(); if toSignal cv.signalOne()

请记住,紧密循环会占用您的一个核心,除了查看其缓存之外什么都不做。这是浪费钱......;)这很可能是你问题的原因。您应该将代码更改为:

rescaleFactor

也可能是您的性能损失与互斥锁关键部分有关。这个关键部分可能比缓存未命中的时间长许多个数量级。我建议比较线程池中1个线程,2个线程和4个线程的时间。如果2个线程不比1个线程快,那么你的代码基本上是按顺序运行的。

如何衡量?当您不知道要优化什么时,分析工具很有用。我对它们没有很多经验,但我知道(至少有一些较旧的)在多线程方面会有点粗略。你也可以使用一个很好的老式计时器。如果你有合适的硬件,C ++ 11有一个high_resolution_clock可能在1微秒的分辨率。

最后,我看到了算法/标量优化的大量机会。预分配矢量而不是每次都这样做。使用指针或std :: move来避免不必要的深拷贝。预分配m_result并让线程写入特定的索引偏移量。

相关问题