I corrieron algunas pruebas y aquí es el código Probé:
delegate(float[] inout)
{ // My Original Code
float[][] tempbuf = new float[2][];
int length = inout.Length/2;
for (int c = 0; c < 2; c++)
{
tempbuf[c] = new float[length];
for (int i = 0, offset = c; i < tempbuf[c].Length; i++, offset += 2)
tempbuf[c][i] = inout[offset];
}
}
delegate(float[] inout)
{ // jerryjvl's recommendation: loop unrolling
float[][] tempbuf = new float[2][];
int length = inout.Length/2;
for (int c = 0; c < 2; c++)
tempbuf[c] = new float[length];
for (int ix = 0, i = 0; ix < length; ix++)
{
tempbuf[0][ix] = inout[i++];
tempbuf[1][ix] = inout[i++];
}
}
delegate(float[] inout)
{ // Unsafe Code
unsafe
{
float[][] tempbuf = new float[2][];
int length = inout.Length/2;
fixed (float* buffer = inout)
for (int c = 0; c < 2; c++)
{
tempbuf[c] = new float[length];
float* offset = buffer + c;
fixed (float* buffer2 = tempbuf[c])
{
float* p = buffer2;
for (int i = 0; i < length; i++, offset += 2)
*p++ = *offset;
}
}
}
}
delegate(float[] inout)
{ // Modifying my original code to see if the compiler is not as smart as i think it is.
float[][] tempbuf = new float[2][];
int length = inout.Length/2;
for (int c = 0; c < 2; c++)
{
float[] buf = tempbuf[c] = new float[length];
for (int i = 0, offset = c; i < buf.Length; i++, offset += 2)
buf[i] = inout[offset];
}
}
y resultados: (tamaño de buffer = 2^17, iteraciones número temporizados por prueba = 200)
Average for test #1: 0.001286 seconds +/- 0.000026
Average for test #2: 0.001193 seconds +/- 0.000025
Average for test #3: 0.000686 seconds +/- 0.000009
Average for test #4: 0.000847 seconds +/- 0.000008
Average for test #1: 0.001210 seconds +/- 0.000012
Average for test #2: 0.001048 seconds +/- 0.000012
Average for test #3: 0.000690 seconds +/- 0.000009
Average for test #4: 0.000883 seconds +/- 0.000011
Average for test #1: 0.001209 seconds +/- 0.000015
Average for test #2: 0.001060 seconds +/- 0.000013
Average for test #3: 0.000695 seconds +/- 0.000010
Average for test #4: 0.000861 seconds +/- 0.000009
I obtuve resultados similares en cada prueba. Obviamente, el código inseguro es el más rápido, pero me sorprendió ver que el CLS no podía darse cuenta de que podía soltar las comprobaciones de índice cuando se trataba de una matriz dentada. Tal vez alguien pueda pensar en más formas de optimizar mis pruebas.
Edit: He intentado desenrollar el bucle con el código inseguro y no tuvo ningún efecto. También probé la optimización del método de desenrollado del bucle:
delegate(float[] inout)
{
float[][] tempbuf = new float[2][];
int length = inout.Length/2;
float[] tempbuf0 = tempbuf[0] = new float[length];
float[] tempbuf1 = tempbuf[1] = new float[length];
for (int ix = 0, i = 0; ix < length; ix++)
{
tempbuf0[ix] = inout[i++];
tempbuf1[ix] = inout[i++];
}
}
Los resultados son también un éxito-miss comparación prueba # 4 con 1% de diferencia. La prueba n. ° 4 es mi mejor opción, hasta ahora.
Como me dijeron que jerryjvl, el problema es conseguir el CLS a no índice de comprobar la memoria intermedia de entrada, ya que la adición de un segundo control (& & desplazamiento < inout.Length) va a reducir la velocidad ...
Edición 2 : me encontré con las pruebas antes en el IDE, así que aquí están los resultados exterior:
2^17 items, repeated 200 times
******************************************
Average for test #1: 0.000533 seconds +/- 0.000017
Average for test #2: 0.000527 seconds +/- 0.000016
Average for test #3: 0.000407 seconds +/- 0.000008
Average for test #4: 0.000374 seconds +/- 0.000008
Average for test #5: 0.000424 seconds +/- 0.000009
2^17 items, repeated 200 times
******************************************
Average for test #1: 0.000547 seconds +/- 0.000016
Average for test #2: 0.000732 seconds +/- 0.000020
Average for test #3: 0.000423 seconds +/- 0.000009
Average for test #4: 0.000360 seconds +/- 0.000008
Average for test #5: 0.000406 seconds +/- 0.000008
2^18 items, repeated 200 times
******************************************
Average for test #1: 0.001295 seconds +/- 0.000036
Average for test #2: 0.001283 seconds +/- 0.000020
Average for test #3: 0.001085 seconds +/- 0.000027
Average for test #4: 0.001035 seconds +/- 0.000025
Average for test #5: 0.001130 seconds +/- 0.000025
2^18 items, repeated 200 times
******************************************
Average for test #1: 0.0seconds +/- 0.000026
Average for test #2: 0.001319 seconds +/- 0.000023
Average for test #3: 0.001309 seconds +/- 0.000025
Average for test #4: 0.001191 seconds +/- 0.000026
Average for test #5: 0.001196 seconds +/- 0.000022
Test#1 = My Original Code
Test#2 = Optimized safe loop unrolling
Test#3 = Unsafe code - loop unrolling
Test#4 = Unsafe code
Test#5 = My Optimized Code
Parece que el desenrollado del bucle no es favorable. Mi código optimizado sigue siendo mi mejor opción y con solo un 10% de diferencia en comparación con el código inseguro. Si solo pudiera decirle al compilador que (i < buf.Length) implica que (offset < inout.Length), dejará caer el cheque (en [offset]) y básicamente obtendré el rendimiento inseguro.
¿Podría proporcionar un fragmento de código de lo que está tratando de hacer? Será mucho más fácil ayudarte con una muestra concreta de lo que estás tratando de lograr. – jerryjvl