Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
38 / 38 / 22
Регистрация: 16.04.2013
Сообщений: 327
Записей в блоге: 1
1

Многопоточность и random_device

09.05.2022, 16:14. Показов 1122. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void create_obj_and_start()  
{
   myclass object= myclass();
   object.shuffling();
}
 
class myclass
{
public:
   int data[100];
   myclass(){};
   void shuffling()
   {
       random_device seed;
       mt19937 generator(seed());
       shuffle(data, data+100, generator);
   }
}
 
int main() 
{
   int thread_num = 5;
 
   std::vector<std::thread> threads;
 
   for (int i = 0; i < thread_num ; i++) 
      threads.push_back(std::thread(test));
  
 
  for (auto &th : threads) 
    th.join();
  
  return 0;
}
добрый день. будет ли random_device и mt19937 работать исправно в многопоточном режиме?
или нужно их объявлять static thread_local?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.05.2022, 16:14
Ответы с готовыми решениями:

std::random_device
Здравствуйте. Я так понимаю, Windows, в отличии от линя, не предоставляет специльное устройство...

STL random_device
Всем привет! 1. Относится ли random_device к аппаратным генераторам случайных чисел? 2....

std::random_device падает приложение
win7, gcc 4.4.7 пишет, ошибка &quot;std::runtime_error&quot; чего ему надо? Добавлено через 14 часов 17...

Многопоточность
Сделал таким способом многопоточность, но гуи все еще зависает. import paramiko import sys ...

10
6105 / 3460 / 1405
Регистрация: 07.02.2019
Сообщений: 8,790
09.05.2022, 16:27 2
Цитата Сообщение от Miwa123 Посмотреть сообщение
std::thread(test)
если в функции test вызывается функция create_obj_and_start, то все ок, т.к. работа с локальными для потока объектами.
1
38 / 38 / 22
Регистрация: 16.04.2013
Сообщений: 327
Записей в блоге: 1
09.05.2022, 16:39  [ТС] 3
ой в этой строке ошибка
threads.push_back(std::thread(test));
должно быть так
threads.push_back(std::thread(create_obj_and_start));
0
Вездепух
Эксперт CЭксперт С++
11694 / 6373 / 1723
Регистрация: 18.10.2014
Сообщений: 16,058
09.05.2022, 17:47 4
Цитата Сообщение от Miwa123 Посмотреть сообщение
будет ли random_device и mt19937 работать исправно в многопоточном режиме?
или нужно их объявлять static thread_local?
Странно поставленный вопрос. Что тут изменит thread_local?

Тут у каждого потока и так свой собственный random_device и свой собственный mt19937, то есть для этих объектов не будет никакого "многопоточного режима". С каждым таким объектом работает только один поток.

Другое дело: а нет ли у random_device некоего глобального внутреннего состояния/ресурса, которое разделяется между разными объектами random_device и к которому, соответственно, будет осуществляться конкурентный доступ из нескольких потоков, даже если у каждого потока есть свой random_device?

Но даже если есть, то тогда thread_local никак не изменит ситуации.

Насколько я помню, использовать отдельные объекты random_device в разных потоках - безопасно. Что-то я не могу найти подходящей цитаты, однако...
1
38 / 38 / 22
Регистрация: 16.04.2013
Сообщений: 327
Записей в блоге: 1
09.05.2022, 20:27  [ТС] 5
собственно эти детали меня и интересуют. спасибо за развернутый ответ
0
Вездепух
Эксперт CЭксперт С++
11694 / 6373 / 1723
Регистрация: 18.10.2014
Сообщений: 16,058
09.05.2022, 20:35 6
Лучший ответ Сообщение было отмечено Miwa123 как решение

Решение

Я бы все-таки в такой ситуации вынес std::random_sevice "за скобки". То есть использовал один-единственный std::random_sevice, с помощью которого генерировал бы seeds для каждого потока еще до запуска этих потоков и передавал бы эти seeds в потоки в качестве входных параметров.

Дело в том, что std::random_sevice формально может быть реализован в том числе как детерминированный генератор псевдо-случайных чисел. То есть каждый std::random_sevice имеет право генерировать одну и ту же псевдослучайную последовательность. Тогда в вашем текущем варианте получится, что для каждого из ваших поточных std::mt19937 вы будете получать от его локального std::random_sevice один и тот же seed.
0
38 / 38 / 22
Регистрация: 16.04.2013
Сообщений: 327
Записей в блоге: 1
09.05.2022, 22:33  [ТС] 7
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Я бы все-таки в такой ситуации вынес std::random_sevice "за скобки". То есть использовал один-единственный std::random_sevice, с помощью которого генерировал бы seeds для каждого потока еще до запуска этих потоков и передавал бы эти seeds в потоки в качестве входных параметров.

Дело в том, что std::random_sevice формально может быть реализован в том числе как детерминированный генератор псевдо-случайных чисел. То есть каждый std::random_sevice имеет право генерировать одну и ту же псевдослучайную последовательность. Тогда в вашем текущем варианте получится, что для каждого из ваших поточных std::mt19937 вы будете получать от его локального std::random_sevice один и тот же seed.
спасибо за комментарий. я пожалуй сделаю, именно так, как Вы и написали
создам внешний std::random_device и посею ним семя для каждого отдельного объекта потока. а зетам использую этим семена в локальном std::mt19937

Добавлено через 1 час 40 минут
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Я бы все-таки в такой ситуации вынес std::random_sevice "за скобки". То есть использовал один-единственный std::random_sevice, с помощью которого генерировал бы seeds для каждого потока еще до запуска этих потоков и передавал бы эти seeds в потоки в качестве входных параметров.

Дело в том, что std::random_sevice формально может быть реализован в том числе как детерминированный генератор псевдо-случайных чисел. То есть каждый std::random_sevice имеет право генерировать одну и ту же псевдослучайную последовательность. Тогда в вашем текущем варианте получится, что для каждого из ваших поточных std::mt19937 вы будете получать от его локального std::random_sevice один и тот же seed.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
random_device gseed;
 
mt19937& get_gen()
{
    static thread_local mt19937 generator(gseed());
    return generator;
}
int intRand(const int& min, const int& max)
{
    uniform_int_distribution<int> distribution(min, max);
    return distribution(get_gen());
}

чтобы не мучаться с изменением классов. как-то так придумал. в классе где нужно вызываю get_gen. полагаю так все будет исправно отрабатывать
0
6105 / 3460 / 1405
Регистрация: 07.02.2019
Сообщений: 8,790
09.05.2022, 22:37 8
Цитата Сообщение от Miwa123 Посмотреть сообщение
gseed()
Это не thread safe.
0
38 / 38 / 22
Регистрация: 16.04.2013
Сообщений: 327
Записей в блоге: 1
09.05.2022, 22:47  [ТС] 9
Цитата Сообщение от zayats80888 Посмотреть сообщение
Это не thread safe.
понял. значит буду генерировать семена отдельно и хранить их в объектах
0
6105 / 3460 / 1405
Регистрация: 07.02.2019
Сообщений: 8,790
09.05.2022, 22:54 10
Цитата Сообщение от Miwa123 Посмотреть сообщение
значит буду генерировать семена отдельно и хранить их в объектах
Поскольку это редкий вызов(только при первом вызове get_gen в каждом потоке), то достаточно сделать его под блокировкой мьютекса, "производительность" не пострадает.
Например
C++
1
2
3
4
5
6
7
8
9
  struct Seed {
    std::mutex m;
    std::random_device rd;
  
    auto operator()() {
      std::unique_lock lock{m};
      return rd();
    }
  } gseed;
1
38 / 38 / 22
Регистрация: 16.04.2013
Сообщений: 327
Записей в блоге: 1
10.05.2022, 05:42  [ТС] 11
Цитата Сообщение от zayats80888 Посмотреть сообщение
Поскольку это редкий вызов(только при первом вызове get_gen в каждом потоке), то достаточно сделать его под блокировкой мьютекса, "производительность" не пострадает.
Например
C++
1
2
3
4
5
6
7
8
9
  struct Seed {
    std::mutex m;
    std::random_device rd;
  
    auto operator()() {
      std::unique_lock lock{m};
      return rd();
    }
  } gseed;
блин, красивое однако решение.
а я уже полез мьютексы ставить в конструкторе объекта, который крутится в потоке и там намерено в блоке мьютекса делать первый принудительный вызов
0
10.05.2022, 05:42
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.05.2022, 05:42
Помогаю со студенческими работами здесь

Многопоточность
Всем привет,никак не могу разобраться с многопоточностью. Мне нужно в этом коде функцию...

Многопоточность
Необходимо разработать многопоточное консольное приложение: а) вводятся все данные из условия; ...

Многопоточность
Товарищи! Создаю 23 потока. вот так: ff1 = new f1(false); ff1-&gt;Priority = tpLower;...

Многопоточность
Столкнулся с проблемой, что не совсем понимаю, что такое многопоточность. С многозадачностью все...

Многопоточность
Доброго времени. Не могу сообразить как сделать: Задача: Методы класса Main вызываются из разных...

Многопоточность
У меня есть класс в нем куча функций мне нужно что б эти функции работали одновременно если так...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru