2011-06-20 12 views
10

Pracuję nad moim rozwiązaniem problemu Cult of the Bound Variable.Jak przyspieszyć klonowanie tablic w C#?

Częściowo problem polega na tym, że zaimplementowałeś tłumacza do "pradawnej" Uniwersalnej Maszyny. Zaimplementowałem wtyczkę do opisywanej maszyny, a teraz używam programu testowego, który uczelnia udostępniła w celu przetestowania go.

Moja implementacja C# tego interpretera to slow!

Uruchomiłem program w profilu ANTS, aby zobaczyć, gdzie znajduje się spowolnienie i widzę, że ponad 96% mojego czasu zajmuje operacja "Wczytaj program".

ANTS Profile Results

specification tego operatora jest następujący:

#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. 

Oto mój kod dla tego operatora:

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

Kod źródłowy do mojego całego "uniwersalna maszyna" tłumacz jest here.

Co mogę zrobić, aby przyspieszyć działanie? Istnieją inne implementacje tego interpretera napisane w C, które kończą cały benchmark znacznie szybciej.

+1

Czy możesz podać typy _platterów i innych członków? Wypróbuj Array.Copy, Buffer.BlockCopy lub wskaźniki. –

+0

@lukas, podałem link do strony github, która zawiera całą klasę. Ale _platters jest listą . – mmcdole

+0

Więc, z ciekawości, jaki był wzrost prędkości przy użyciu zaakceptowanej odpowiedzi? Twoje pytanie stałoby się bardziej cenne dla innych użytkowników SO. – sehe

Odpowiedz

6

Można spróbować użyć Buffer.BlockCopy, chociaż byłbym zaskoczony, gdyby to sprawia żadnych ogromną różnicę w tym przypadku:

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

zależności od tego jak są dwie używane tablice, można użyć modyfikacji kopiowania przy zapisie:

Nie będziesz używać tablic bezpośrednio, ale używając opakowania. Aby sklonować tablicę, po prostu utwórz kolejne opakowanie. Jeśli spróbujesz napisać do tablicy, która jest współużytkowana przez więcej niż jedno opakowanie, robisz faktyczne klonowanie i odkładanie owijki.

0

Abstrahując od kwestii pod ręką, prawdziwym powodem twoje odniesienia VM tak słabo, że należy być obchodzenia 0 „z najwyższą prędkością”, jak mówi spec;)

Zasadniczo regularne skoki są wykonywane przez robi obciążenie od 0 do 0. Jest to niezwykle powszechne w kodzie kodowym. Powinieneś całkowicie unikać klonowania i aktualizować tylko "palec" w tym konkretnym przypadku.