Какой самый эффективный способ скопировать элементы многомерного массива C #? - PullRequest
1 голос
/ 14 апреля 2011

Какой самый эффективный способ вложения моих циклов при копировании из одного многомерного массива в другой в C #? Верхняя и нижняя границы каждого массива различны, поэтому я не думаю, что Array.Copy() сделает эту работу за меня. В настоящее время у меня есть следующее:

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];
        }
    }
}

Это относительно низкоуровневая оптимизация, так что компилятор позаботится об этом для меня? Есть ли лучший способ скопировать элементы многомерного массива, когда конечный пункт имеет разные верхние и нижние границы?

Ответы [ 3 ]

4 голосов
/ 14 апреля 2011

Array.Copy будет работать для вас, но только для замены самого внутреннего цикла.Вам нужно будет самостоятельно рассчитать исходные и конечные показатели, но это, безусловно, выполнимо.Документация для Array.Copy(Array, Int32, Array, Int32, Int32) объясняет, как выполнять математику для индексов, чтобы вы могли указать исходное и целевое местоположение.

Я настоятельно рекомендую использовать Array.Copy везде, где имеет смысл его использоватьпотому что это безумно быстро.Они делают какой-то серьезный ассемблер, чтобы заставить его работать хорошо.

ОБНОВЛЕНИЕ

Я не уверен, насколько близко это исправить, потому что я не пробовал, но это что-то вроде того, как я думаю, что это может пойти:

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);
     }
} 
3 голосов
/ 14 апреля 2011

Используйте Buffer.BlockCopy(). Если это не сработает за один шаг, скопируйте первый многомерный массив в одномерный массив, а затем скопируйте этот одномерный массив во второй многомерный массив.

Рекомендации:

0 голосов
/ 14 апреля 2011

Я думаю, это не может быть проще.Похоже, что вы делаете 3-мерное копирование пикселей с одной поверхности на другую - если не считать аппаратного ускорения, я думаю, что оно должно идти по одному.

Ну, если у вас несколько ядер, это может быть быстреечтобы перейти к теме на ядро.

Может быть, кто-то, кто знает больше о certin, зазвонит ...

В качестве сноски, мне любопытно, если ваш пример - случай, когда неуправляемыйкод значительно превзойдет ...

...