2011-01-12 11 views
7

Actualmente estoy trabajando en una aplicación que es responsable de calcular las permutaciones aleatorias de una matriz dentada.¿Una forma extremadamente rápida de clonar los valores de una matriz dentada en una segunda matriz?

Actualmente, la mayor parte del tiempo en la aplicación se utiliza copiando la matriz en cada iteración (1 millón de iteraciones en total). En mi sistema actual, todo el proceso tarda 50 segundos en completarse, 39 de esos segundos dedicados a la clonación de la matriz.

Mi rutina gama de clonación es la siguiente:

public static int[][] CopyArray(this int[][] source) 
    { 
     int[][] destination = new int[source.Length][]; 
     // For each Row 
     for (int y = 0; y < source.Length; y++) 
     { 
      // Initialize Array 
      destination[y] = new int[source[y].Length]; 
      // For each Column 
      for (int x = 0; x < destination[y].Length; x++) 
      { 
       destination[y][x] = source[y][x]; 
      } 
     } 
     return destination; 
    } 

¿Hay alguna manera, seguros o inseguros, para lograr el mismo efecto que el anterior, mucho más rápido?

+1

¿Ha intentado utilizar matrices multidimensionales en lugar de irregulares, es decir 'static int [,]' en lugar de 'static int [] []'? –

Respuesta

17

Cualquiera de estos debería funcionar para usted. Ambos funcionan aproximadamente en la misma cantidad de tiempo y son mucho más rápidos que tu método.

// 100 passes on a int[1000][1000] set size 

// 701% faster than original (14.26%) 
static int[][] CopyArrayLinq(int[][] source) 
{ 
    return source.Select(s => s.ToArray()).ToArray(); 
} 

// 752% faster than original (13.38%) 
static int[][] CopyArrayBuiltIn(int[][] source) 
{ 
    var len = source.Length; 
    var dest = new int[len][]; 

    for (var x = 0; x < len; x++) 
    { 
     var inner = source[x]; 
     var ilen = inner.Length; 
     var newer = new int[ilen]; 
     Array.Copy(inner, newer, ilen); 
     dest[x] = newer; 
    } 

    return dest; 
} 
+0

Tal alivio para mí para encontrar esto: por cierto, parece bastante fácil extender esto a más dimensiones: fuente de devolución. Seleccione (s => s.Select (p => p.ToArray()). ToArray()). ToArray(); –

0

¿Has mirado el método C# Array.Clone?

Editar: En realidad, creo que Array.Copy podría ser más eficiente/más rápido para sus necesidades.

Hice una prueba rápida y parece que todos los cambios en el destino no afectan a la fuente:

int[] source = new int[3]{1,2,3}; 
int[] destination = new int[source.Length]; 
Array.Copy(source, destination, source.Length); 
destination[0]++; // or destination[0] = destination[0] + 1; 

resultados en:

 source = { 1 , 2 , 3 } 
destination = { 2, 2, 3 } 

es que el resultado que buscabas?

public static int[][] CopyArray(int[][] source) 
     { 
      int[][] destination = new int[source.Length][]; 
      Array.Copy(source, destination, source.Length); 
      return destination; 
     } 

básicamente lograr lo que está buscando, creo.

+3

Esto creará una referencia a la matriz original. Usando Array.Copy, y luego modificando un valor en la matriz copiada, también se modificará la matriz original. –

0

cómo serializar/deserializar la matriz, si utiliza secuencias de memoria y serialización binaria, creo que debería ser bastante rápido.

+2

La serialización es, probablemente, órdenes de magnitud más lenta que su implementación actual. –

0

Puede utilizar Array.Clone para el bucle interno:

public static int[][] CopyArray(this int[][] source) 
{ 
    int[][] destination = new int[source.Length][]; 
    // For each Row 
    for(int y = 0;y < source.Length;y++) 
    { 
     destination[y] = (int[])source[y].Clone(); 
    } 
    return destination; 
} 

Otra alternativa para el bucle interno es Buffer.BlockCopy, pero no he medido su rendimiento contra Array.Clone - tal vez es más rápido:

destination[y] = new int[source[y].Length]; 
Buffer.BlockCopy(source[y], 0, destination[y], 0, source[y].Length * 4); 

Editar: Buffer.BlockCopy toma el número de bytes para copiar para el parámetro de conteo, no el número de elementos de la matriz.

+0

Intenté su primera solución. Desafortunadamente, solo se quita un par de segundos de todo el tiempo de ejecución. Voy a probar tu segunda solución. –

+0

Su segunda opción es bastante comparativa con la primera. Solo se eliminó un segundo o dos del tiempo total en comparación con mi método original. –

0

La forma más rápida de copiar objetos es no copiarlos en absoluto. ¿Ha considerado esta opción? Si solo necesita generar permutaciones, no necesita copiar datos en cada una, simplemente cambie la matriz. Este enfoque no funcionará si necesita mantener los resultados de llamadas anteriores. En cualquier caso, revise su código para ver si no está copiando datos más veces de lo necesario.

+0

Necesito copias separadas de la matriz, ya que cada permutación necesita tener un conjunto de trabajo original. –

Cuestiones relacionadas