Мне было поручено взять существующее однопоточное моделирование Монте-Карло и оптимизировать его. Это консольное приложение C #, без доступа к базе данных, оно загружает данные один раз из файла csv и записывает их в конце, поэтому оно в значительной степени ограничено процессором, также использует только около 50 МБ памяти.
Я запустил его через профилировщик Jetbrains dotTrace. Из общего времени выполнения около 30% приходится на генерацию однородных случайных чисел, 24% - на преобразование однородных случайных чисел в нормально распределенные случайные числа.
Базовый алгоритм представляет собой множество вложенных циклов for с вызовами случайных чисел и умножением матриц в центре, каждая итерация возвращает значение типа double, которое добавляется в список результатов, этот список периодически сортируется и проверяется. для некоторых критериев сходимости (в контрольных точках каждые 5% от общего числа итераций), если это приемлемо, программа выходит из цикла и записывает результаты, в противном случае она продолжается до конца.
Я бы хотел, чтобы разработчики отметили:
- следует ли мне использовать новый поток v ThreadPool
- стоит ли заглянуть в библиотеку расширений Microsoft Parallels
- я должен посмотреть AForge.Net Parallel.For, http://code.google.com/p/aforge/ какие-либо другие библиотеки?
Некоторые ссылки на руководства по вышеизложенному были бы весьма кстати, поскольку я никогда не писал параллельный или многопоточный код.
- лучшие стратегии для генерации массовых нормально распределенных случайных чисел, а затем их использования. В этом состоянии приложение никогда не использует равномерные случайные числа, они всегда переводятся в нормально распределенные, а затем используются.
- хорошие быстрые библиотеки (параллельные?) для генерации случайных чисел
- Из соображений памяти, если я провожу эту параллель, сколько еще мне потребуется.
Текущее приложение занимает 2 часа на 500 000 итераций, бизнесу необходимо масштабировать его до 3 000 000 итераций и вызывать его несколько раз в день, поэтому необходима серьезная оптимизация.
Особо хотелось бы услышать мнение людей, которые использовали Microsoft Parallels Extension или AForge.Net Parallel
Это должно быть выполнено довольно быстро, поэтому бета-версия .net 4 отсутствует, хотя я знаю, что в нее встроены библиотеки параллелизма, мы можем рассмотреть возможность перехода на .net 4 позже, как только она будет выпущена. На данный момент на сервере есть .Net 2, я отправил на рассмотрение обновление до .net 3.5 SP1, которое есть в моем устройстве для разработчиков.
Спасибо
Обновить
Я только что пробовал реализацию Parallel.For, но она дает странные результаты. Однопоточный:
IRandomGenerator rnd = new MersenneTwister();
IDistribution dist = new DiscreteNormalDistribution(discreteNormalDistributionSize);
List<double> results = new List<double>();
for (int i = 0; i < CHECKPOINTS; i++)
{
results.AddRange(Oblist.Simulate(rnd, dist, n));
}
To:
Parallel.For(0, CHECKPOINTS, i =>
{
results.AddRange(Oblist.Simulate(rnd, dist, n));
});
Внутри имитации есть много вызовов rnd.nextUniform (), Я думаю, что получаю много одинаковых значений. Возможно ли это, потому что теперь это параллельное?
Также, возможно, проблемы с вызовом List AddRange не являются потокобезопасными? я вижу это
System.Threading.Collections.BlockingCollection, возможно, стоит использовать, но у него есть только метод Add без AddRange, поэтому мне пришлось бы просмотреть результаты и добавить потокобезопасным способом. Любое понимание от кого-то, кто использовал Parallel.For очень ценится. Я временно переключился на System.Random для своих вызовов, так как я получал исключение при вызове nextUniform с моей реализацией Mersenne Twister, возможно, это не было потокобезопасным определенным массивом получал индекс за пределами допустимого диапазона ....