当并行代码在 Visual Studio 自动化测试中运行得更快时要寻找什么?
What to look for when parallelized code runs faster in Visual Studio automated tests?
我们有一个带有 Parallel.For
循环的 C#(.NET 4.0 框架)项目,在 Visual Studio 内的自动化测试中 运行 速度非常快,但是相同的并行化代码没有t 运行 正如在独立应用程序中预期的那样,我们正在尝试找出原因。
该代码占用大量内存,但我们的工作站(Windows 7 台 PC)有足够的 RAM,因此我预计不会出现任何内存分页问题。并行循环中没有文件 I/O 或 GUI 代码。
在独立版本中,代码 运行s 在多线程和内核上,但似乎被限制为不超过总共 1 CPU 的 CPU 时间,尽管分支到多个核心。因此,如果代码按顺序使用 1 CPU 的 100%,看起来它将在 4 CPU 秒内使用总共 25%。
运行从Visual Studio内部获取代码的自动化测试没有这个限制。控制台应用程序似乎受到限制,而自动化测试却没有。
我比较了 Thread
和 ProcessThread
之间的设置,它们似乎是等效的。他们使用相同的 SynchronizationContext
(空)和 TaskScheduler
(默认)。
我也尝试用手动创建的 Thread
替换 Parallel.For
,但似乎没有任何改变。
我应该寻找什么可能导致 Visual Studio 中的自动化测试与独立应用程序之间的这种差异?
下面是一些相关的示例代码:
public void Process(string name)
{
//...
Results bestResult = null;
int best = int.MaxValue;
Object lockObject = new Object();
var parent = new Data(this.nameToPart[name]);
var myParams = new Params(this.params);
Parallel.For(0, myParams.numRunsPerLvl, (i) =>
{
var result = Processor.MultilevelProcessor(parent, myParams);
if (part.cost < bestCut)
{
lock (lockObject)
{
if (part.cost < best)
{
best = part.cost;
bestResult = result;
}
}
}
});
//...
}
也许TaskScheduler不一样?
尝试检查 System.Threading.Tasks.TaskScheduler.Current 属性(从任务上下文中)。
我终于找到了解决问题的方法。设置 App.config 文件并将 gcServer 设置为 true 解决了我们的问题。我们的应用程序的实例化非常繁重,以至于垃圾收集器正在扼杀性能。我猜 Visual Studio 在 运行 单元测试时以不同方式工作其垃圾收集器?未来我们还将努力减少 GC 的使用。
我们有一个带有 Parallel.For
循环的 C#(.NET 4.0 框架)项目,在 Visual Studio 内的自动化测试中 运行 速度非常快,但是相同的并行化代码没有t 运行 正如在独立应用程序中预期的那样,我们正在尝试找出原因。
该代码占用大量内存,但我们的工作站(Windows 7 台 PC)有足够的 RAM,因此我预计不会出现任何内存分页问题。并行循环中没有文件 I/O 或 GUI 代码。
在独立版本中,代码 运行s 在多线程和内核上,但似乎被限制为不超过总共 1 CPU 的 CPU 时间,尽管分支到多个核心。因此,如果代码按顺序使用 1 CPU 的 100%,看起来它将在 4 CPU 秒内使用总共 25%。
运行从Visual Studio内部获取代码的自动化测试没有这个限制。控制台应用程序似乎受到限制,而自动化测试却没有。
我比较了 Thread
和 ProcessThread
之间的设置,它们似乎是等效的。他们使用相同的 SynchronizationContext
(空)和 TaskScheduler
(默认)。
我也尝试用手动创建的 Thread
替换 Parallel.For
,但似乎没有任何改变。
我应该寻找什么可能导致 Visual Studio 中的自动化测试与独立应用程序之间的这种差异?
下面是一些相关的示例代码:
public void Process(string name)
{
//...
Results bestResult = null;
int best = int.MaxValue;
Object lockObject = new Object();
var parent = new Data(this.nameToPart[name]);
var myParams = new Params(this.params);
Parallel.For(0, myParams.numRunsPerLvl, (i) =>
{
var result = Processor.MultilevelProcessor(parent, myParams);
if (part.cost < bestCut)
{
lock (lockObject)
{
if (part.cost < best)
{
best = part.cost;
bestResult = result;
}
}
}
});
//...
}
也许TaskScheduler不一样? 尝试检查 System.Threading.Tasks.TaskScheduler.Current 属性(从任务上下文中)。
我终于找到了解决问题的方法。设置 App.config 文件并将 gcServer 设置为 true 解决了我们的问题。我们的应用程序的实例化非常繁重,以至于垃圾收集器正在扼杀性能。我猜 Visual Studio 在 运行 单元测试时以不同方式工作其垃圾收集器?未来我们还将努力减少 GC 的使用。