【问题标题】:Thread contention when allocating memory分配内存时的线程争用
【发布时间】:2018-10-21 19:33:40
【问题描述】:

在 C# 中,我运行了一个创建许多小对象的玩具代码(我知道最好避免这种情况 - 我只是想研究这个问题)。在创建的对象总数相同的情况下,一个线程比每个处理器一个线程运行得更快 (Parallel.For)。

原子操作包括创建一个包含 20k 个小对象的列表(实际上是一个数组)(为简单起见,此处为 long[4]):

private static void CreateList()
{
    long[][] list = new long[20000][];
    for (var i = 0; i < 20000; i++)
        list[i] = new long[4];
}

如果我在单个线程中创建 1000 个列表,它会在 1.5 秒内运行。如果我用多个线程创建 1000 个列表(每个线程负责 1000 个列表的一个子集),它会在 2 秒内运行。

在以下情况下行为基本相同:

  • 使用经典的小对象而不是长对象[4]
  • 使用真正的 List 而不是数组
  • 使用不同数量的对象

你能解释一下原因吗?内存管理器中是否有“锁”。和垃圾回收有关吗?

代码详情:

public static void Main()
{
    Benchmark(1000, CreateList);
}    

private static void Benchmark(int repeat, Action action)
{
    Console.WriteLine("Single thread");
    Benchmark(delegate ()
    {
        for (int i = 0; i < repeat; i++)
            action();
    });
    Console.WriteLine("Multi thread");
    Benchmark(delegate ()
    {
        Parallel.For(0, repeat, i => action());
    });
}

private static void Benchmark(Action action)
{
    for (int i = 0; i < 10; i++)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        action();
        sw.Stop();
        Console.WriteLine("Time : " + sw.Elapsed.TotalSeconds);
    }
}

【问题讨论】:

  • 当然内存管理本质上是单线程的。既分配又收集。否则在尝试分配相同的内存时会遇到竞争情况!
  • 除了上面所说的以外,不确定它是否也是您要问的另一件事,仅仅因为您产生多个线程并不一定意味着它会运行得更快。创建线程本身就有开销,因此对于非常短的任务,并行运行并不总是会缩短执行时间。
  • 我也同意 npinti 所说的。我喜欢说“多线程必须仔细挑选它的问题”。否则,您最终会得到更复杂(容易出错)、使用更多内存并且更慢然后是单个线程的代码。并行减速是一回事(en.wikipedia.org/wiki/Parallel_slowdown)。就像根本不能多线程的问题一样。只需尝试对斐波那契数列进行多线程处理,以便每个数字都由单独的线程创建。
  • @npitni;线程在这里不运行短任务。没有开销。用数学替换内存分配,你会看到的。
  • @BenoitSanchez:如果我用 CPU 绑定操作替换内存绑定操作,它甚至不再是类似的代码了。

标签: c# multithreading memory-management


【解决方案1】:

尽管内存管理器使用某种信号量是正常的,但具有许多内存分配的多线程应用程序在默认的 C# 垃圾收集器中工作得非常糟糕。使用适当的垃圾收集器,事情会好很多。

你应该:

  • 启用服务器 GC
  • (可能)禁用并发 GC

服务器 GC 将允许线程之间更好的并行化程度,因为内存分配是部分独立的。在这种情况下,多核机器的性能可能会发生根本性的变化。

简而言之,将其添加到项目的配置文件中:

  <runtime>
    <gcServer enabled="true"/>
    <gcConcurrent enabled="false" />
  </runtime>

您可以在Fundamentals of Garbage Collection 阅读有关服务器和工作站 GC 的详细信息。

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 2021-01-23
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    相关资源
    最近更新 更多