{"id":2309,"date":"2015-04-21T02:51:02","date_gmt":"2015-04-21T01:51:02","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=2309"},"modified":"2019-01-07T20:21:39","modified_gmt":"2019-01-07T19:21:39","slug":"passing-random-generators-around-functor","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=2309","title":{"rendered":"Passing random generators around (functor)"},"content":{"rendered":"<p>Update: Version with template instead of std::function <a href=\"http:\/\/roboblog.fatal-fury.de\/?p=3961\">C++ Guns: Passing function objects around (Update Example random generators)<\/a><\/p>\n<p>Consider the following problem: One has a parallelly callable function which needs a random generator for every thread. One wants to call the function several times and every time we want another random sequence. How can we implement this?<\/p>\n<p>Between every function call the random generator must keep its states. So the caller of the function must own the generator objects and pass them to the function. The caller is also in responsible the initialize the random generators. One can feed them with random seeds. But i think there exist a better solutions [1]<\/p>\n<p>We create an array of n random generators, initialize them with a random seed and pass them per pointer to the function. <\/p>\n<p>Inside this function we need a distribution. A simple rand() % maxrand is not good. It uses only the lower bits which may not be random. With c++11 we can bind the random generator and number distribution together. This allows us the create a nice dice() object which represent our rand(). Of course, this object can be simply pass around.<\/p>\n<p>Output:<\/p>\n<pre>Thread 0 sum 5021\r\nThread 0 sum 4966\r\nThread 3 sum 4996\r\nThread 3 sum 5014\r\nThread 1 sum 5007\r\nThread 2 sum 4970\r\nThread 1 sum 5092\r\nThread 2 sum 5002\r\nInfo sizeof std::function<int()> 16\r\n<\/pre>\n<p>Code:<\/p>\n<pre><code>\r\n\/\/ can be passed by value\r\nint function2(std::function<int()> dice) {\r\n  int sum = 0;\r\n  for(int i=0; i < 1000; i++) {\r\n    sum += dice();\r\n  }\r\n  return sum;\r\n}\r\n\r\n\/\/ pass by reference. it has state\r\nint function(std::minstd_rand& generator) {\r\n  \/\/ we need random numbers from 0 to 10\r\n  std::uniform_int_distribution<int> distribution(0,10);\r\n\r\n  \/\/ we bind the generator and distribution together to a new functor dice()\r\n  \/\/ std::bind copy its arguments by value. To change the given generator state,\r\n  \/\/ my must pass it by reference. This can be easly done with std:ref.\r\n  \/\/ Yeah C++ can be strange.\r\n  std::function<int()> dice = std::bind ( distribution, std::ref(generator) );\r\n\r\n  return function2(dice);\r\n}\r\n\r\nint main() {\r\n  omp_set_num_threads(4);\r\n\r\n  \/\/ create 4 random generatores with random seed\r\n  std::minstd_rand seedGen;\r\n  std::minstd_rand generators[omp_get_num_threads()];\r\n  for(int i=0; i < omp_get_num_threads(); i++) {\r\n    generators[i].seed(seedGen());\r\n  }\r\n\r\n#pragma omp parallel for\r\n  for(int i=0; i < 8; i++) {\r\n    const int id = omp_get_thread_num();\r\n    \/\/ pass one generator to our function\r\n    int sum = function(generators[id]);\r\n\r\n    std::cout << \"Thread \" << id << \" sum \" << sum << \"\\n\";\r\n  }\r\n\r\n  std::cout << \"Info sizeof std::function<int()> \" << sizeof(std::function<int()>) << \"\\n\";\r\n\r\n  return 0;\r\n}\r\n<\/code><\/pre>\n<p>[1] Tina\u2019s Random Number Generator Library<br \/>\n<a href=\"https:\/\/www.numbercrunch.de\/trng\/trng.pdf\">Tina\u2019s Random Number Generator Library<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update: Version with template instead of std::function C++ Guns: Passing function objects around (Update Example random generators) Consider the following problem: One has a parallelly callable function which needs a random generator for every thread. One wants to call the function several times and every time we want another random sequence. How can we implement [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[17],"class_list":["post-2309","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-cpp"],"_links":{"self":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2309","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2309"}],"version-history":[{"count":9,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2309\/revisions"}],"predecessor-version":[{"id":3992,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2309\/revisions\/3992"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2309"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2309"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2309"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}