如何在堆栈上分配数组以提高性能?

Rya*_*hel -3 c# arrays performance heap-memory stack-memory

一些最优化的函数版本,例如popcountcount consecutive zeros使用表查找来获得最终答案。

在 C 和 C++ 中,可以在堆栈上分配数组并快速访问它们。

有没有办法在 C# 中做到这一点?据我所知,stackalloc只能在函数内使用,因此数组不会持久化。

我有一个小的查找表,我希望能够尽快访问它,因此更愿意在堆栈而不是堆上分配它。

Pet*_*iho 5

我有一个小的查找表,我希望能够尽快访问它,因此更愿意在堆栈而不是堆上分配它。

这种说法令人困惑。将某些东西放在堆栈上意味着每次进入声明它的函数时都必须重新初始化它。通常的“优化”是将此类数据存储在持久位置,例如静态变量。

例如,以下popcount()汉明权重维基百科文章中的示例实现:

static uint8_t wordbits[65536] = { /* bitcounts of integers 0 through 65535, inclusive */ };
static int popcount(uint32_t i)
{
    return (wordbits[i&0xFFFF] + wordbits[i>>16]);
}
Run Code Online (Sandbox Code Playgroud)

请注意,wordbits数组是任何函数之外声明为static变量的。

C# 中的类似声明如下所示:

static readonly byte[] wordbits = { /* bitcounts of integers 0 through 65535, inclusive */  };
static int popcount(uint i)
{
    return (wordbits[i & 0xFFFF] + wordbits[i >> 16]);
}
Run Code Online (Sandbox Code Playgroud)

注意使用 C# 的readonly关键字来明确这个对象只会被初始化一次。

(显然,在这两个示例中,数组中的注释被实际值替换。或者,它们可以在运行时计算一次并保存到数组中)。

从您的问题来看,您似乎至少对堆栈、堆和数据段(即从可执行映像直接读取到内存中的特殊内存范围)感到困惑。对于性能而言,如果您正在处理经常分配的固定大小的对象,并且您不想承受通过内存管理器分配的成本,则堆栈分配很有用。

但是在堆栈上分配在实际访问数据方面没有提供任何性能优势,并且在初始化数据方面也绝对没有提供任何性能优势。事实上,在后一种情况下,它会花费更多,因为每次进入该函数时都必须对其进行初始化。

我相信以上内容应该足以解决您的担忧。但如果没有,请查看您实际尝试做的事情,并编辑您的问题,使其更加清晰。您可以查看我如何提出一个好问题,以获取有关如何以清晰、可回答的方式更好地提出问题的建议。