在并行内部处理比常规for循环慢。为什么呢?

时间:2017-02-09 21:44:10

标签: c# multithreading unmanaged-memory unmanagedresources

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

使用此课程:

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通常需要大约两倍的常规时间。根据分析器,62%-65%的执行时间花在了FreeHGlobal的ParallelFor中。只有52%-53%用于FreeHGlobal的常规用途。

我认为现代RAM系统不会产生太大的差别。有没有办法在多个进程中处理大块未管理的内存?有没有办法可以改变它以使其具有多线程?

如果我不处理每个进程中使用的RAM(糟糕的想法,但只是为了测试),Parallel For的速度是其两倍,但之后我只能打开其中的4-5个(它们是大量的应用程序崩溃之前的同时(正如您猜测的那样,RAM外部异常)。

为什么对单独的对象执行多个Dispose操作会降低速度?

如果这是唯一的选择,我可以让他们单线程,但我希望加快这一点。

谢谢。

1 个答案:

答案 0 :(得分:0)

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

您可以通过创建单个大块非托管内存并在其中运行无锁分配器来加快速度。