gpt4 book ai didi

c# - C# 中用于索引的 Typedef,具有静态类型检查而没有运行时开销

转载 作者:太空宇宙 更新时间:2023-11-03 13:52:31 25 4
gpt4 key购买 nike

使用具有复杂索引的多维数组是很常见的情况。当所有索引都是整数时,这真的很困惑且容易出错,因为您可以轻松混淆列和行(或任何您拥有的)并且编译器无法识别问题。实际上应该有两种类型的索引:行和列,但它没有在类型级别上表示。

这是我想要的一个小例子:

var table = new int[RowsCount,ColumnsCount];
Row row = 5;
Column col = 10;
int value = table[row, col];

public void CalcSum(int[,] table, Column col)
{
int sum = 0;
for (Row r = 0; r < table.GetLength(0); r++)
{
sum += table[row, col];
}
return sum;
}

CalcSum(table, col); // OK
CalcSum(table, row); // Compile time error

总结:

  • 应该对索引进行静态检查以防止混淆(一种类型检查)
  • 重要!它们应该是运行时高效的,因为将 int 包装到包含索引的自定义对象然后再将它们解包回来对性能来说是不好的
  • 它们应该可以隐式转换为整数,以便在原生多维数组中用作索引

有什么办法可以实现吗?完美的解决方案是 typedef 之类的东西,它仅在编译成平面整数时用作编译时检查。

最佳答案

x64 抖动只会使速度降低 2 倍。它生成有趣的优化代码。使用该结构的循环如下所示:

00000040  mov         ecx,1 
00000045 nop word ptr [rax+rax+00000000h]
00000050 lea eax,[rcx-1]
s.Idx = j;
00000053 mov dword ptr [rsp+30h],eax
00000057 mov dword ptr [rsp+30h],ecx
0000005b add ecx,2
for (int j = 0; j < 100000000; j++) {
0000005e cmp ecx,5F5E101h
00000064 jl 0000000000000050

这需要一些注释,因为代码是不寻常的。首先,偏移量 45 处的奇怪 NOP 用于在循环开始时对齐指令。这使得偏移量 64 处的分支更快。 53 处的指令看起来完全没有必要。您在这里看到的是循环展开,请注意 5b 处的指令如何将循环计数器递增 2。然而,优化器不够智能,因此也看不到存储是不必要的。

最重要的是,您看不到 ADD 指令。换句话说,代码实际上并不计算“sum”的值。这是因为您在循环后的任何地方都没有使用它,优化器可以看到计算无用并将其完全删除。

它在第二个循环中做得更好:

000000af  xor         eax,eax 
000000b1 add eax,4
for (int j = 0; j < 100000000; j++) {
000000b4 cmp eax,5F5E100h
000000b9 jl 00000000000000B1

它现在完全删除了“sum”计算和“i”变量赋值。它也可以删除整个 for() 循环,但抖动优化器从未这样做过,它假定延迟是有意的。

希望信息现在已经很清楚了:避免根据人为的基准做出假设,只分析真实代码。您可以通过实际显示“sum”的值使其更真实,这样优化器就不会丢弃计算。在循环之后添加这行代码:

        Console.Write("Sum = {0} ", sum);

现在您会发现已经没有区别了。

关于c# - C# 中用于索引的 Typedef,具有静态类型检查而没有运行时开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13302545/

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