gpt4 book ai didi

c# - Parallel for 中的 Dispose 比常规 for 循环慢。为什么?

转载 作者:太空宇宙 更新时间:2023-11-03 15:08:42 24 4
gpt4 key购买 nike

我已将我的原始问题简化为此测试。

使用这个类:

public class Unmanaged : IDisposable
{
private IntPtr unmanagedResource;

public Unmanaged()
{
this.unmanagedResource = Marshal.AllocHGlobal(10 * 1024 * 1024);
}
public void DoSomethingWithThisClass()
{
Console.WriteLine($"{DateTime.Now} - {this.unmanagedResource.ToInt64()}");
}

private bool disposedValue = false; // To detect redundant calls

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
Marshal.FreeHGlobal(unmanagedResource);
disposedValue = true;
}
}

~Unmanaged() {
Dispose(false);
}

void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}

我有这两个测试:

public class UnitTest1
{
const int Runs = 100000;

[TestMethod]
public void UsingFor()
{
for (var i = 0; i <= Runs; i++)
{
using (var unman = new Unmanaged())
{
unman.DoSomethingWithThisClass();
}
}
}

[TestMethod]
public void UsingParallelFor()
{
Parallel.For(0, Runs, new ParallelOptions() { MaxDegreeOfParallelism = 10},
index => {
using (var unman = new Unmanaged())
{
unman.DoSomethingWithThisClass();
}
});
}
}

ParallelFor 通常需要大约两倍于常规 for 的时间。根据探查器,ParallelFor 的 62%-65% 的执行时间花在了 FreeHGlobal 内部。只有 52%-53% 花费在 FreeHGlobal 内部用于常规 for。

我假设对于现代 RAM 系统,这不会产生太大的差异。有没有办法在多个进程中处理大块非托管内存?有什么方法可以改变它使其成为多线程的吗?

如果我不处理每个进程中使用的 RAM(坏主意,但只是为了测试),Parallel For 的速度是原来的两倍,但我只能打开其中的大约 4-5 个(它们是大量的图像数据)在应用程序崩溃之前的同一时间(正如您所猜测的那样,内存不足异常)。

为什么对不同对象执行多个 Dispose 操作会减慢速度?

如果那是唯一的选择,我可以让它们保持单线程,但我希望加快速度。

谢谢。

最佳答案

FreeHGlobal 几乎肯定会阻塞。这意味着您的进程中一次只能有一个线程运行它。他们排队等候。这样做有开销,所以速度较慢。

您可以通过创建一个大的非托管内存块并在其中运行无锁分配器来使其更快。

关于c# - Parallel for 中的 Dispose 比常规 for 循环慢。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42147429/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com