简体   繁体   English

如何加速C#中的数组克隆?

[英]How can I speed up array cloning in C#?

I'm working on my solution to the Cult of the Bound Variable problem. 我正在研究我对绑定变量问题的解决方案。

Part of the problem has you implement an interpreter for the "ancient" Universal Machine. 部分问题是你为“古代”通用机器实现了一个解释器。 I've implemented an intepreter for the machine they describe and now I'm running a benchmark program that the university provided to test it. 我已经为他们描述的机器实现了一个解释器,现在我正在运行一个大学提供的测试它的基准程序。

My C# implementation of this interpreter is slow ! 我的这个解释器的C#实现很

I fired up my program in the ANTS profiler to see where the slowdown is and I can see that over 96% of my time is taken up by the "Load Program" operation. 我在ANTS分析器中启动了我的程序以查看减速的位置,我可以看到超过96%的时间被“加载程序”操作占用。

ANTS简介结果

The specification of this operator is as follows: 该运算符的规范如下:

 #12. Load Program.

              The array identified by the B register is duplicated
              and the duplicate shall replace the '0' array,
              regardless of size. The execution finger is placed
              to indicate the platter of this array that is
              described by the offset given in C, where the value
              0 denotes the first platter, 1 the second, et
              cetera.

              The '0' array shall be the most sublime choice for
              loading, and shall be handled with the utmost
              velocity.

Here is my code for this operator: 这是我的运算符的代码:

case 12: // Load Program
    _platters[0] = (UInt32[])_platters[(int)_registers[B]].Clone();
    _finger = _registers[C];
    break;

The source code to my whole "Universal Machine" interpreter is here . 我的整个“通用机器”解释器的源代码就在这里

What can I do to make this faster? 我能做些什么来加快速度? There are other implementations of this interpreter written in C which complete the entire benchmark significantly faster. 这个解释器的其他实现用C语言编写,可以更快地完成整个基准测试。

根据这个MSDN线程Buffer.BlockCopy承诺要快得多。

You could try using Buffer.BlockCopy , although I'd be surprised if it makes any massive difference in this case: 您可以尝试使用Buffer.BlockCopy ,但如果在这种情况下产生任何巨大差异,我会感到惊讶:

case 12: // Load Program
    uint[] src = _platters[(int)_registers[B]];
    _platters[0] = new uint[src.Length];
    Buffer.BlockCopy(src, 0, _platters[0], 0, src.Length * 4);
    _finger = _registers[C];
    break;

使用此处描述的BlockCopy方法: http ://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/42189513-2106-4467-af9a-3b1810509cc8/

Depending on how are the two resulting arrays used, you could use a modification of copy-on-write: 根据使用的两个结果数组的方式,您可以使用copy-on-write的修改:

You won't use arrays directly, but using a wrapper. 您不会直接使用数组,而是使用包装器。 To clone an array, just create another wrapper. 要克隆数组,只需创建另一个包装器。 If you try to write to an array that is shared by more than one wrapper, you do the actual cloning and decouple the wrappers. 如果您尝试写入由多个包装器共享的数组,则执行实际克隆并将包装器分离。

Aside from the question at hand, the real reason your VM benchmarks so poorly is that you should be handling 0 "with the utmost velocity" as the spec says ;) 除了手头的问题,你的虚拟机基准测试如此糟糕的真正原因是你应该按照规范说的那样以“最大速度”处理0;)

Essentially, regular jumps are performed by doing a load from 0 to 0. This is extremely common in the codex code. 本质上,通过从0到0加载来执行常规跳转。这在codex代码中非常常见。 You should avoid cloning completely and only update the "finger" in that particular case. 你应该避免完全克隆,只更新那个特定情况下的“手指”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM