Как я могу ускорить клонирование массива в C #? - PullRequest
10 голосов
/ 21 июня 2011

Я работаю над решением проблемы Cult of the Bound Variable .

Часть проблемы заключается в том, что вы реализовали интерпретатор для «древней» Универсальной Машины. Я реализовал интерпретатор для машины, которую они описывают, и теперь я запускаю тестовую программу, которую университет предоставил для ее тестирования.

Моя C # реализация этого интерпретатора медленная !

Я запустил свою программу в профилировщике ANTS, чтобы увидеть, где происходит замедление, и я вижу, что более 96% моего времени занято операцией «Загрузить программу».

ANTS Profile Results

Спецификация этого оператора выглядит следующим образом:

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

Вот мой код этого оператора:

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

Исходный код для всего моего интерпретатора "Универсальной машины" здесь .

Что я могу сделать, чтобы сделать это быстрее? Существуют другие реализации этого интерпретатора, написанные на C, которые значительно быстрее завершают весь тест.

Ответы [ 5 ]

7 голосов
/ 21 июня 2011

Buffer.BlockCopy обещает быть намного быстрее, согласно этому потоку MSDN .

6 голосов
/ 21 июня 2011

Вы можете попробовать использовать Buffer.BlockCopy, хотя я был бы удивлен, если в этом случае будет какая-то существенная разница:

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;
4 голосов
/ 21 июня 2011

Используйте метод BlockCopy, описанный здесь: http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/42189513-2106-4467-af9a-3b1810509cc8/

0 голосов
/ 17 сентября 2011

Помимо рассматриваемого вопроса, реальная причина, по которой ваши тесты виртуальной машины настолько плохи, заключается в том, что вы должны обрабатывать 0 "с максимальной скоростью", как сказано в спецификации;)

По сути, регулярные переходы выполняются при загрузке от 0 до 0. Это очень часто встречается в коде кодекса. Вам следует полностью избегать клонирования и обновлять «палец» только в этом конкретном случае.

0 голосов
/ 21 июня 2011

В зависимости от того, как используются два полученных массива, вы можете использовать модификацию копирования при записи:

Вы не будете использовать массивы напрямую, но будете использовать обертку. Чтобы клонировать массив, просто создайте другую оболочку. Если вы попытаетесь записать в массив, который используется более чем одной оболочкой, вы фактически выполните клонирование и отделите оболочки.

...