I'm trying to build an extension method that will allow me to subdivide a huge array into much smaller ones. My current code is the following but it still takes about 2s to generate with an array of size 512x512x512 and the size of the sub cubes set to 32x32x32
public static T[][][][] Divide<T>(this T[][][] array, int xSize, int ySize, int zSize)
{
int numberOfCubesInAxisX = array.Length / xSize;
int numberOfCubesInAxisY = array[0].Length / ySize;
int numberOfCubesInAxisZ = array[0][0].Length / zSize;
T[][][][] arrayDivided = new T[numberOfCubesInAxisX * numberOfCubesInAxisY * numberOfCubesInAxisZ][][][];
int index = 0;
while (index < arrayDivided.Length)
{
int xIndex = index / numberOfCubesInAxisZ / numberOfCubesInAxisX;
int yIndex = index / numberOfCubesInAxisZ % numberOfCubesInAxisY;
int zIndex = index % numberOfCubesInAxisZ;
arrayDivided[index] = new T[xSize][][];
for (int x = 0; x < xSize; x++)
{
arrayDivided[index][x] = new T[ySize][];
for (int y = 0; y < ySize; y++)
{
arrayDivided[index][x][y] = new T[zSize];
for (int z = 0; z < zSize; z++)
{
arrayDivided[index][x][y][z] = array[x + (xIndex * xSize)][y + (yIndex * ySize)][z + (zIndex * zSize)];
}
}
}
index++;
}
return arrayDivided;
}
If anyone have any clue on how to optimize it, i'll be glad to hear it! Thanks!
1 Answer 1
Just a quick shot regarding performance.....
The code is calculating
xIndex * xSize
xSize*ySize*zSize
times
yIndex * ySize
xSize*ySize*zSize
times
zIndex * zSize
xSize*ySize*zSize
times
while it only should be calculated once for each iteration of the while
loop.
In addition, x
only changes in the first for
loop and y
only changes in the second for
loop.
-
\$\begingroup\$ Hi, thanks for the tip, i've indeed changed the code a little bit. The result is not an astronomical gain in time but it's a small good upgrade. Thanks for the tip. \$\endgroup\$Kamigaku– Kamigaku2021年03月01日 15:18:26 +00:00Commented Mar 1, 2021 at 15:18
[,,,]
instead of[][][]
for each cube. Additionally a pair of some math andArray.Copy
calls will do the magic. AlsoBuffer.BlockCopy
is the fastest for non-generic primitive-typed solution. Potentially you can speed up this by ~100 times. \$\endgroup\$T
you can't useBuffer.BlockCopy
but canArray.Copy
. First copies array segment only as bytes thus you must know the exact item size in bytes.Array.Copy
will do it forT
fluently, a bit slower but a payment for Generic method nature. \$\endgroup\$Buffer.BlockCopy
operation. For large data set single-dimentional array is best choice. Because calculating item address likex * ySize * zSize + y * zSize + z
is always faster than go through 3 index-bound-checks. \$\endgroup\$