Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.04.2012, 10:53   #1
hirosimarider
 
Регистрация: 23.03.2012
Сообщений: 3
По умолчанию Конгруэнтный метод

Приветствую!

Задался вопросом реализации своего ГСЧ и нашел прекрасный метод предложенный Кнутом. Также нашел его реализацию для плюсов - прирост быстродействия был такой: стандартный рандом ~5.3 сек., конгруэнтный метод ~0.2 сек. (сравнение на 10000 итерациях).

Для C# нашел также реализацию этого метода, но... не только прироста нет, но и, наоборот, работает медленнее..

Может кто-то реализовывал свои более быстрые варианты рандома??

Вот код реализации конгруэнтного метода ГСЧ:


Код:
    public class Rnd
    {
        private Int64 _seed;
        public Rnd()
        {
            _seed = Int64.Parse(DateTime.Now.Ticks.ToString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Int64 Next()
        {
            const int m = 1065353216;
            const int k = 1664525;
            const int b = 1013904223;
            Math.DivRem(k * _seed + b, m, out _seed);
            return _seed;
        }
    }
}
hirosimarider вне форума Ответить с цитированием
Старый 24.04.2012, 11:11   #2
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Int64.Parse(DateTime.Now.Ticks.ToSt ring());
А зачем ты переводишь число в строку и обратно?

Метод можно чуть оптимизировать:
Код:
        const int m = 1065353216;
        const int k = 1664525;
        const int b = 1013904223;

        public Int64 Next()
        {
            return (k * _seed + b) % m;
        }
Покажи код, где ты сравниваешь скорость рандомов.
ds.Dante вне форума Ответить с цитированием
Старый 24.04.2012, 12:33   #3
hirosimarider
 
Регистрация: 23.03.2012
Сообщений: 3
По умолчанию

Цитата:
А зачем ты переводишь число в строку и обратно?
Ну это инициализация - она не так важна))а вообще да, скопировал не глядя)) тупость вышла...))

Цитата:
return (k * _seed + b) % m;
те же яйца, только в профиль ХД
проблему это не решает, ибо целочисленное деление остается и занимает 90% всего времени выполнения функции...(((

Код:
var sw = new Stopwatch();
            sw.Start();
            testSpeedRandStandart();
            sw.Stop();
            MessageBox.Show(sw.Elapsed.ToString());
            sw.Reset();
            sw.Start();
            testSpeedRand();
            sw.Stop();
            MessageBox.Show(sw.Elapsed.ToString());
Код:
       private void testSpeedRandStandart()
        {
            var rnd = new Random();
            for (var n = 0; n < 1000000; n++)
                rnd.Next();
        }
        private void testSpeedRand()
        {
            var rnd = new Rnd();
            for (var n = 0; n < 1000000; n++)
                rnd.Next();
        }
На плюсах это выглятит так:
Код:
float getRandomFast()
{
    static unsigned long iran;
    unsigned long temp;
    float fran;
    static unsigned long jflone=0x3f800000;
    static unsigned long jflmsk=0x007fffff;
    iran=1664525L*iran+1013904223L;
    temp=jflone|(jflmsk&iran);
    fran=(*(float *)&temp)-1.F;
    return fran;
}

Последний раз редактировалось hirosimarider; 24.04.2012 в 12:47.
hirosimarider вне форума Ответить с цитированием
Старый 24.04.2012, 13:12   #4
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Может, просто стандартный рандом в плюсах такой тормозной?

Можно посмотреть, как он реализован в дотнете (исходники можно скачать NetMassDownloader-ом).
ds.Dante вне форума Ответить с цитированием
Старый 24.04.2012, 13:58   #5
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Цитата:
Сообщение от hirosimarider Посмотреть сообщение
... ибо целочисленное деление остается и занимает 90% всего времени выполнения функции...(((
Вообще-то советуют брать m = степени двойки

А код, который Вы для C++ привели отсюда взят: http://algolist.manual.ru/maths/generator/fastest.php ?
Там jflone=0x3f800000=1065353216 не то-же самое, что m в формуле конгруэнтного метода.
alexBlack вне форума Ответить с цитированием
Старый 24.04.2012, 14:37   #6
hirosimarider
 
Регистрация: 23.03.2012
Сообщений: 3
По умолчанию

Цитата:
Там jflone=0x3f800000=1065353216 не то-же самое
Ой, тут да, не кратно степени двойки.. поленился проверить))
ну.. даже заменив на 65536 вот такие результаты получаются:

С#
standart = 00:00:03.0421518
kongr = 00:00:02.6766811

C++(переписал немного, чтобы честнее было)
kongr = 0.383354
standart = 1.14874

Да, в плюсах рандом в 3 раза быстрее конечно...

Кстати, может знает кто, время выполнения участка замеряемого кода(привел выше) и время которое тратится на сам рандом, показываемое Intel Parallel Amplifier, очень сильно разнится. Т.е.:
Код:
	        rnd->getRandomFast();  	35.606ms
	        rand();                       	852.911ms
При том, что остальной код одинаков:
Код:
double timeStart;

	timeStart = omp_get_wtime();
	RandomGenerator* rnd = new RandomGenerator();
	rnd->initialize();
	for(int j = 0; j < 30000000; j++)
		rnd->getRandomFast();
	cout << "time     = " << omp_get_wtime() - timeStart << endl << endl;

	timeStart = omp_get_wtime();
	srand(time(NULL));
	for (int i = 0; i < 30000000; i++)
		rand();
	cout << "time     = " << omp_get_wtime() - timeStart << endl << endl;
Почему так??
hirosimarider вне форума Ответить с цитированием
Старый 24.04.2012, 14:48   #7
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Цитата:
Сообщение от hirosimarider Посмотреть сообщение
Ой, тут да, не кратно степени двойки.. поленился проверить))
ну.. даже заменив на 65536 вот такие результаты получаются:
Не торопитесь. Почему именно степень двойки и как это связано с mod ?
(это для C#)

Почему в коде C++ нет операции mod и как используется jflone.

Отвечать не нужно, просто разберитесь для себя. Иначе получается, что Вы сравниваете по времени два различных генератора и делаете неверный вывод о том, что в C++ быстрее.
alexBlack вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Конструктор,метод вывода на экран Display, метод для преобразования в строку toString в Delphi Чумак Татьяна Помощь студентам 6 03.04.2012 11:58
исследовать метод квадратных корней и метод Холецкого для решения СЛАУ Vит@x@ Помощь студентам 0 22.11.2011 10:47
Задача Коммивояжера. Метод Монте-Карло и метод приращений. [Паскаль] U9110 Помощь студентам 4 06.04.2011 09:48
Turbo Pascal[програмыки : текстовая\метод симпсона\метод половинного деления qsccsq Помощь студентам 7 24.12.2010 05:23
конгруэнтный генератор псевдослучайных чисел cvbcvb Помощь студентам 0 10.05.2010 00:16