What's the most efficient way to copy elements of a C# multidimensional array?

佐手、 提交于 2019-12-08 08:05:58

问题


What's the most efficient way to nest my loops when copying from one multidimensional array to another in C#? The upper and lower bounds of each array are different, so I don't think Array.Copy() will do the job for me. I currently have the following:

for (int x = lower.X; x <= upper.X; x++)
{
    for (int y = lower.Y; y <= upper.Y; y++)
    {
        for (int z = lower.Z; z <= upper.Z; z++)
        {
            copy[x, y, z] = Elements[x, y, z];
        }
    }
}

This is a relatively low-level optimization, so will the compiler take care of this for me? Is there a better way to copy elements of a multidimensional array when the destination has different upper and lower bounds?


回答1:


Array.Copy will work for you, but only to replace the innermost loop. You will have to calculate the source and destination indicies yourself, but that is certainly doable. The documentation for Array.Copy(Array, Int32, Array, Int32, Int32) explains how to do the math on indices so you can specify the source and target locations.

I highly recommend using Array.Copy everywhere it makes sense to use it, because it is crazy-fast. They do some serious assembler-foo to make it work well.

UPDATE

I am not sure how close this is to correct, because I haven't tried it, but this is something like how I think it might go:

int xLength = upper.X - lower.X + 1;
int yLength = upper.Y - lower.Y + 1;
int zLength = upper.Z - lower.Z + 1;

Array copy = Array.CreateInstance(Elements.GetType(), new { xLength, yLength, zLength }, new {lower.X, lower.Y, lower.Z});

int skippedX = lower.X - Elements.GetLowerBound(0);
int skippedY = lower.Y - Elements.GetLowerBound(1);
int skippedZ = lower.Z - Elements.GetLowerBound(2);

int sourceDim0Size = Elements.GetLength(1) * Elements.GetLength(2);
int sourceDim1Size = Elements.GetLength(2);

for (int x = 0; x < xLength; x++)
{
     for (int y = 0; y < yLength; y++)
     {
         int destinationIndex = x * yLength * zLength + y * zLength;
         int sourceIndex = (x + skippedX) * sourceDim0Size 
                           + (y + skippedY) * sourceDim1Size
                           + skippedZ;
         Array.Copy(Elements, sourceIndex, copy, 0, zLength);
     }
} 



回答2:


Use Buffer.BlockCopy(). If it won't work in one step, copy first multidimensional array into single dimension array and then copy this single dimensional array to second multidimensional array.

References:

  • http://www.dotnetperls.com/buffer-blockcopy
  • http://msdn.microsoft.com/en-us/library/system.buffer.blockcopy.aspx



回答3:


My guess is this can't get any simpler. It seems like you are doing a 3 dimensional pixel copy from one surface to another - short of hardware acceleration, I think it has to go one by one.

Well, if you have multiple cores, it might be faster to go a thread per core.

Maybe someone who know more for certin will chime in...

As a footnote, I'm curious if your example is a case where non-managed code would significantly outperform...



来源:https://stackoverflow.com/questions/5655553/whats-the-most-efficient-way-to-copy-elements-of-a-c-sharp-multidimensional-arr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!