Scheduled
100DaysOfGameDev: Day 48
Nothing much for today either. I was again playing with multi-threading and noticed a had a bug. The issue was that several cores were computing the result, however, because I had data races I would get a poor-quality picture. I didn't check the output image, that's why I didn't notice it yesterday. The idea is that even tho each core would do one sample, running on 8 cores would mean I have 8 samples per pixel when averaged. However, because random was shared it wouldn't do 8 samples, but some sequences would be corrupted and I get less than 8 samples. Here the code I finally ended up with:
static std::hash<std::thread::id> hasher;
static std::uniform_real_distribution<double> distribution(0.0, 1.0);
inline double random_double() {
static thread_local std::mt19937 generator(
static_cast<unsigned>(hasher(std::this_thread::get_id()))
);
return distribution(generator);
}
I have static thread_local
, which says that each thread has its own random number generator. Furthermore, its constructor receives the hash of the current thread_id resulting in different seeds for each seed, so sampling on different threads would actually make sense. Nevertheless, there is a case where hash id could repeat and my threads' work would be redundant. Fortunately for my use case since I use very few threads, six on Windows, 8 on Mac (4 efficiency cores, 4 performance cores), and all threads start “at the same” it is little likely that id would repeat.
On that note, I think the code I wrote that distributes the tasks to threads still looks kinda of ugly, and I can do better. For that specific purpose, I resumed reading Bjarne's book, specifically the “Threads and Tasks” section, to seek for better alternative.
In the meantime, let's enjoy more renders of balls. This time in full HD, with 80 samples per pixel. Why again balls? you may ask. Because I am too lazy to write code for loading meshes and handling a ray-to-triangle intersection, but I will do it eventually, most probably tomorrow. This time the image took 25 minutes to render, which is quite good considering the other render took me 4 hours. Note the previous render was 120x675.