使用这个主题来了解什么是线程序列化,并确定代码中哪些部分没有并行运行。 当发生在不同线程上的工作需要按照特定的顺序执行时,就会发生线程序列化。 当特定线程的工作要求先完成另一线程的工作时,会经常发生这种情况。
从性能的角度来看,线程序列化是线程锁定的一种形式。 这种模式通常发生在单线程算法转换为多线程算法,但多线程算法的每一部分都需要等待前一部分先完成后再开始的时候。 如果在工作系统中,工作之间有很高的依赖性,则也会出现类似的效果。 这可能导致以下问题发生。
如果工作不是并行运行,且如果每次都只在一个线程上执行,那么算法实际上还是单线程的,并不会运行得更快。
增加了线程间切换的开销。
使用与 线程锁定 中相同的步骤来排除问题,重点在于线程之间或CPU核心之间所发生阶梯效应的位置。
PIX
图1显示PIX时间线中的阶梯式效果是怎样的。
图 1. PIX 计时捕获中线程时间线的阶梯模式
如果标题具有旋转等待工作的代码,或者如果它试图获取工作所需代码部分的锁,那么在旋转和获取部分的周围添加PIX事件是有用的。 添加这些事件可以帮助快速识别线程行为,在PIX中搜索这些事件可以帮助识别花了太多时间等待的时间段。 关于旋转案例的更多信息,请参阅核心利用率:旋转。
注意
选择上下文切换后,可以使用“元素详细信息”窗口(显示在“线程锁定”中)来帮助确定导致线程序列化发生的确切代码行。
Windows Performance Analyzer (WPA)
图2显示线程不并行运行时的情况。
图 2. 按“进程”、“线程”窗口划分的“时间线”,在线程不并行运行的情况下,显示出阶梯式的效果
如果标题中的工作线程在查找工作时会旋转,那么你会发现添加 Windows 事件跟踪 (ETW) 事件非常有用。 举例说明,见图3。 关于添加ETW的详细信息,请参阅CustomEventProvider示例。 要下载(Microsoft 游戏开发工具包 (GDK) 示例,请参阅 Xbox 开发人员下载)。 应该在工作线程上的旋转块和处理块周围添加事件。 WPA中按“提供商”、“任务”、“Opcode 窗口”划分的“通用事件活动”显示了每个事件的发生时间。 如果要识别过度旋转的线程,请参阅核心利用率:旋转。
图 3. 显示CustomEventProvider示例中自定义ETW事件的通用事件