1. C++ / Говнокод #3235

    +993

    1. 1
    2. 2
    // Randomize
    #define srand(x) srand(x + GetCurrentThreadId())

    Чтобы в разных тредах не выдавало одинаковые последовательности

    Запостил: k06a, 14 Мая 2010

    Комментарии (19) RSS

    • .
      Ответить
      • В 2008 студии без каких либо особых настроек вызов rand() из разных тредов, даёт одинаковые последовательности.
        Ответить
        • А Вы как, если не секрет, srand-то вызываете обычно в разных потоках? Или у Вас все потоки стартуют в одну и ту же секунду? Так можно ж использовать и что-то более точное, например GetSystemTime отконвертированное с помощью SystemTimeToFileTime даёт миллисекундную точность.
          Ответить
          • И в главном пробовал и в разных. Использовал GetTickCount(). Думаю он шустрее остальных. В цикле, проверяя не изменилось ли значение, до 2000-3000 раз можно пробежать по-моему.
            Ответить
            • Так в этом и вопрос: когда и как Вы дергаете srand? По-хорошему один раз на весь поток в самом начале должно вполне хватать. Мне не ясно почему srand в разных потоках вызывается в одно и то же время. По идее так быть не должно, если Вы ничего не делаете для этого специально. Или srand вызывается в начале одной функции, которую одновременно начинают выполнять несколько потоков? Так тогда в этом месте и проблема.
              Ответить
              • Пробовал запускать как перед запуском остальных тредов, так и в них самих. Все варианты в итоге дают одно и тоже. Последовательность то случайная, только одинаковая у тредов. Попробуйте, я не шучу))
                Ответить
                • Итак, я беру MS VS 2005, создаю станадртный Win32 проект Windows Application, в меню File добавляю пункт Test с ID_FILE_TEST и дописываю вот такую функцию над WndProc:
                  DWORD WINAPI MyThreadProc( LPVOID pParam )
                  {
                  	srand(GetTickCount());
                  	TCHAR buf[1024] = {0};
                  	_stprintf(buf, _T("%d %d %d"), rand(), rand(), rand());
                  	MessageBox(NULL, buf, _T("Rand"), MB_OK);
                  	return 0;
                  }


                  А также правлю обработчик WM_COMMAND в WndProc добавляя ещё один case:
                  case ID_FILE_TEST:
                  			{
                  			HANDLE hThread = CreateThread(NULL, 0, MyThreadProc, NULL, 0, NULL);
                  			CloseHandle(hThread);
                  			break;
                  			}


                  Запускаю, жму меню > File > Test и наслаждаюсь каждый раз новым набором случайных чисел. Что я делаю не так?
                  Ответить
                  • MSVS 2008. Win32 Console Application. Вот код - http://codepad.org/zmEWqx6W Закомментирована всего 1 строка. Если коммент снять - ничего не изменится. Результат запуска вот - http://img201.yfrog.com/img201/6958/jmp.png
                    Ответить
                    • Как я и ожидал, Вы явно делаете так, чтобы вся работа выполнялась одновременно в том числе, чтобы srand вызывался многократно за малое время. Очевидно, что в такой ситуации время с точностью до миллисекунд не является достаточно случайной величиной чтобы выступать в роли seed. Я не представляю, в какой практической задаче такой дизайн может быть необходим, но, конечно, если это действительно нужно, это требует нестандартного подхода. И все же даже время можно использовать как seed и в этом случае, поскольку WinApi вполне предоставляет и более высокоточные источники времени, например вот так:
                      LARGE_INTEGER counter = {0};
                      QueryPerformanceCounter(&counter);
                      srand(counter.LowPart);

                      Ваше же решение является залепой на один-единственный, причём весьма нестандартный, часный случай.

                      А по поводу
                      // Закомментировано или нет - РАЗНИЦЫ НЕТ
                      //srand(GetTickCount());

                      Вы, конечно, не совсем правы. Если закоментированно, то последовательность будет одинаковой для всех запусков, ибо по умолчанию seed=1.
                      Ответить
    • Слушай, а ты ка-ноль-шесть-а или Коба?
      Ответить
      • Читается как Коба, но это лишь ник. А что?))
        Ответить
    • Хочется плюсануть. Но не за говно, а за оригинальность последних нескольких кусков кода, выложенных k06a.
      Рвусь на части: плюсану - подтвержу, что говнокод. Но это же не говно! Как быть?
      Ответить
      • Плюсани. В моём понимании "+" для кода на данном ресурсе скорее рекомендует этот код к прочтению, чем называет его говнокодом ;)
        Ответить
      • Я выложил те куски, которые показались мне наиболее забавными. Думаю многим некоторые из них показались интересными.
        Ответить
      • А разве скрытие функции макросом не говно? Почему нельзя было сделать #define srand_threaded srand(x ... ) и не плодить магические вызовы srand-который-на-самом-деле-не-srand.
        Ответить
        • Зато код не нужно модифицировать.
          Ответить
    • нет тут говнокода. и не такие костыли в винде приходится людям делать...
      винда она на то и винда. она сама - один большой костыль.
      Ответить
      • А причём тут Винда? О_о
        Ответить
        • при том, что только под ней такой (и подобный) подход бывает необходим
          Ответить

    Добавить комментарий