小编典典

创建堆栈大小为默认值 50 倍的线程时有什么危险?

all

我目前正在开发一个对性能非常关键的程序,我决定探索可能有助于减少资源消耗的一条路径是增加我的工作线程的堆栈大小,以便我可以移动float[]我将要访问的大部分数据堆栈(使用stackalloc)。

我读过一个线程的默认堆栈大小是 1
MB,所以为了移动我的所有float[]s,我必须将堆栈扩展大约 50 倍(到 50 MB~)。

我知道这通常被认为是“不安全的”并且不推荐,但是在将我当前的代码与此方法进行基准测试后,我发现处理速度提高了 530%
!所以我不能在没有进一步调查的情况下简单地通过这个选项,这导致了我的问题;将堆栈增加到如此大的尺寸有什么危险(可能会出现什么问题),我应该采取哪些预防措施来最大限度地减少这种危险?

我的测试代码,

public static unsafe void TestMethod1()
{
    float* samples = stackalloc float[12500000];

    for (var ii = 0; ii < 12500000; ii++)
    {
        samples[ii] = 32768;
    }
}

public static void TestMethod2()
{
    var samples = new float[12500000];

    for (var i = 0; i < 12500000; i++)
    {
        samples[i] = 32768;
    }
}

阅读 65

收藏
2022-06-08

共1个答案

小编典典

在将测试代码与 Sam 进行比较后,我确定我们都是对的!
但是,关于不同的事情:

  • 访问内存(读取和写入)在任何位置(堆栈、全局或堆 )都 一样快。
  • 然而,分配 它在堆栈上最快,在堆上最慢。

它是这样的:stack< global< heap。(分配时间)
从技术上讲,堆栈分配并不是真正的分配,运行时只是确保堆栈的一部分(帧?)为数组保留。

不过,我强烈建议您谨慎行事。
我推荐以下内容:

  1. 当您需要经常创建永远不会 离开 函数的数组时(例如通过传递其引用),使用堆栈将是一个巨大的改进。
  2. 如果您可以回收阵列,请尽可能这样做!堆是长期对象存储的最佳场所。(污染全局内存不好;堆栈帧可能会消失)

:1.只适用于值类型;引用类型会在堆上分配,收益会降为0)

回答这个问题本身:我在任何大型堆栈测试中都没有遇到任何问题。
我相信唯一可能的问题是堆栈溢出,如果你不小心你的函数调用并且在系统运行不足的情况下创建你的线程时内存不足。

以下部分是我的初步回答。 这是错误的,测试不正确。仅供参考。


我的测试表明堆栈分配的内存和全局内存至少比在数组中使用的堆分配内存慢 15%(需要 120% 的时间)!

这是我的测试代码,这是一个示例输出:

Stack-allocated array time: 00:00:00.2224429
Globally-allocated array time: 00:00:00.2206767
Heap-allocated array time: 00:00:00.1842670
------------------------------------------
Fastest: Heap.

  |    S    |    G    |    H    |
--+---------+---------+---------+
S |    -    | 100.80 %| 120.72 %|
--+---------+---------+---------+
G |  99.21 %|    -    | 119.76 %|
--+---------+---------+---------+
H |  82.84 %|  83.50 %|    -    |
--+---------+---------+---------+
Rates are calculated by dividing the row's value to the column's.

我在 .NET 4.5.1 下使用 i7 4700 MQ 在 Windows 8.1 Pro(带有更新 1)上进行了
测试,我使用 x86 和 x64 进行了测试,结果是相同的。

编辑 :我将所有线程的堆栈大小增加到 201 MB,样本大小增加到 5000 万,并将迭代次数减少到 5。
结果 与上面相同

Stack-allocated array time: 00:00:00.4504903
Globally-allocated array time: 00:00:00.4020328
Heap-allocated array time: 00:00:00.3439016
------------------------------------------
Fastest: Heap.

  |    S    |    G    |    H    |
--+---------+---------+---------+
S |    -    | 112.05 %| 130.99 %|
--+---------+---------+---------+
G |  89.24 %|    -    | 116.90 %|
--+---------+---------+---------+
H |  76.34 %|  85.54 %|    -    |
--+---------+---------+---------+
Rates are calculated by dividing the row's value to the column's.

不过,似乎堆栈实际上 变得越来越慢

2022-06-08