并行诊断工具(并发运行时)
Visual Studio 为调试和分析多线程应用程序提供了广泛的支持。
调试
Visual Studio 调试器包括“并行堆栈”窗口、“并行任务”窗口和“并行监视”窗口。 有关详细信息,请参阅演练:调试并行应用程序和如何:使用并行监视窗口。
分析
分析工具提供三种数据视图,用于显示有关多线程应用程序如何与自身和其他程序交互的图形、表格和数字信息。 你可以通过这些视图快速识别关注的区域,并从图形显示上的点导航到调用堆栈、调用站点和源代码。 有关详细信息,请参阅并发可视化工具。
事件跟踪
并发运行时使用 Windows 事件跟踪 (ETW) 在发生各种事件时通知检测工具(例如探查器)。 这些事件包括:计划程序的激活或停用、上下文的开始、结束、阻止、取消阻止或暂停,以及并行算法的开始或结束。
并发可视化工具等工具使用此功能;因此,你通常不必直接处理这些事件。 但是,当你开发自定义探查器或使用事件跟踪工具(例如 Windows Performance Toolkit)时,这些事件很有用。
并发运行时仅在启用了跟踪的情况下引发这些事件。 调用 concurrency::EnableTracing 函数可启用事件跟踪,调用 concurrency::DisableTracing 函数可禁用跟踪。
下表列出启用事件跟踪后运行时引发的事件:
事件 | 说明 | 值 |
---|---|---|
concurrency::ConcRT_ProviderGuid | 并发运行时的 ETW 提供程序标识符。 | f7b697a3-4db5-4d3b-be71-c4d284e6592f |
concurrency::ContextEventGuid | 标记与上下文相关的事件。 | 5727a00f-50be-4519-8256-f7699871fecb |
concurrency::PPLParallelForEventGuid | 标记调用 concurrency::parallel_for 算法的入口和出口。 | 31c8da6b-6165-4042-8b92-949e315f4d84 |
concurrency::PPLParallelForeachEventGuid | 标记调用 concurrency::parallel_for_each 算法的入口和出口。 | 5cb7d785-9d66-465d-bae1-4611061b5434 |
concurrency::PPLParallelInvokeEventGuid | 标记调用 concurrency::parallel_invoke 算法的入口和出口。 | d1b5b133-ec3d-49f4-98a3-464d1a9e4682 |
concurrency::SchedulerEventGuid | 标记与任务计划程序相关的事件。 | e2091f8a-1e0a-4731-84a2-0dd57c8a5261 |
concurrency::VirtualProcessorEventGuid | 标记与虚拟处理器相关的事件。 | 2f27805f-1676-4ecc-96fa-7eb09d44302f |
并发运行时定义(但不在当前引发)以下事件。 该运行时保留这些事件以供将来使用:
concurrency::ConcRT_EventType 枚举指定事件跟踪的可能的操作。 例如,在 parallel_for
算法的入口处,运行时引发 PPLParallelForEventGuid
事件并提供 CONCRT_EVENT_START
作为操作。 在 parallel_for
算法返回之前,运行时再次引发 PPLParallelForEventGuid
事件,并提供 CONCRT_EVENT_END
作为操作。
以下示例演示如何为 parallel_for
调用启用跟踪。 运行时不跟踪对 parallel_for
的第一次调用,因为此时尚未启用跟踪。 EnableTracing
调用使运行时能跟踪对 parallel_for
的第二次调用。
// etw.cpp
// compile with: /EHsc
#include <ppl.h>
using namespace concurrency;
int wmain()
{
// Perform some parallel work.
// Event tracing is disabled at this point.
parallel_for(0, 10000, [](int i) {
// TODO: Perform work.
});
// Enable tracing for a second call to parallel_for.
EnableTracing();
parallel_for(0, 10000, [](int i) {
// TODO: Perform work.
});
DisableTracing();
}
运行时跟踪你调用 EnableTracing
和 DisableTracing
的次数。 因此,如果多次调用 EnableTracing
,必须调用 DisableTracing
相同的次数才能禁用跟踪。