2011-06-20 15 views
10

Estoy trabajando en mi solución al problema Cult of the Bound Variable.¿Cómo puedo acelerar la clonación de array en C#?

Parte del problema es que implementa un intérprete para la "antigua" máquina universal. Implementé un intepreter para la máquina que describen y ahora estoy ejecutando un programa de referencia que la universidad proporcionó para probarlo.

Mi implementación de C# de este intérprete es lento!

Inicié mi programa en el generador de perfiles ANTS para ver dónde está la ralentización y puedo ver que más del 96% de mi tiempo lo ocupa la operación "Cargar programa".

ANTS Profile Results

El specification de este operador es el siguiente:

#12. Load Program. 

       The array identified by the B register is duplicated 
       and the duplicate shall replace the '0' array, 
       regardless of size. The execution finger is placed 
       to indicate the platter of this array that is 
       described by the offset given in C, where the value 
       0 denotes the first platter, 1 the second, et 
       cetera. 

       The '0' array shall be the most sublime choice for 
       loading, and shall be handled with the utmost 
       velocity. 

Aquí está mi código de este operador:

case 12: // Load Program 
    _platters[0] = (UInt32[])_platters[(int)_registers[B]].Clone(); 
    _finger = _registers[C]; 
    break; 

El código fuente de toda mi "máquina universal" el intérprete es here.

¿Qué puedo hacer para que esto sea más rápido? Hay otras implementaciones de este intérprete escritas en C que completan el punto de referencia completo significativamente más rápido.

+1

¿Puede proporcionar tipos para _platters y otros miembros? Pruebe Array.Copy, Buffer.BlockCopy o punteros. –

+0

@lukas, proporcioné un enlace a la página de github que tiene toda la clase. Pero _platters es una lista . – mmcdole

+0

Entonces, por curiosidad, ¿cuál fue la ganancia de velocidad usando la respuesta aceptada? Su pregunta sería más valiosa para otros usuarios de SO – sehe

Respuesta

6

Usted podría tratar de usar Buffer.BlockCopy, aunque me sorprendería si hace alguna diferencia masiva en este caso:

case 12: // Load Program 
    uint[] src = _platters[(int)_registers[B]]; 
    _platters[0] = new uint[src.Length]; 
    Buffer.BlockCopy(src, 0, _platters[0], 0, src.Length * 4); 
    _finger = _registers[C]; 
    break; 
0

Dependiendo de cómo son las dos matrices resultantes utilizadas, puede usar una modificación de copy-on-write:

No usará arrays directamente, sino utilizando un contenedor. Para clonar una matriz, solo crea otra envoltura. Si intenta escribir en una matriz compartida por más de un contenedor, realice la clonación real y desacople los contenedores.

0

Aparte de la cuestión que nos ocupa, la verdadera razón de sus puntos de referencia VM tan mal es que usted debe ser el manejo de 0 "con la máxima velocidad", como dice la especificación;)

Esencialmente, saltos regulares se llevan a cabo al hacer una carga de 0 a 0. Esto es extremadamente común en el código de codex. Debe evitar clonar completamente y solo actualizar el "dedo" en ese caso particular.

Cuestiones relacionadas