0
\$\begingroup\$

I have the following code that I managed to make thread-safe but I am not sure if I am using C++ technology optimally.

#include <iostream>
#include <omp.h>
//#include <memory>

class GenNo
{
public:

    int num;

    explicit GenNo(int num_)
    {
        num = num_;
    };

    void create(int incr)
    {
        num += incr;
    }
};

class HelpCrunch{
public:
    HelpCrunch() {

    }

    void helper(int number)
    {
        std::cout << "Seed is " << number << " for thread number: " << omp_get_thread_num() << std::endl;
    }
};

class calculate : public HelpCrunch
{
public:

    int specific_seed;
    bool first_run;

    void CrunchManyNos()
    {
        HelpCrunch solver;

        thread_local static GenNo RanNo(specific_seed);
        //std::unique_ptr<GenNo> GenNo_ptr(nullptr);
        /*
        if(first_run == true)
        {
            GenNo_ptr.reset(new GenNo(specific_seed));
            first_run = false;
        }
         solver.helper(GenNo_ptr->num);
*/
        RanNo.create(1);
        solver.helper(RanNo.num);



        //do actual things that I hope are useful.
    };
};




int main()
{

    calculate MyLargeProb;
    MyLargeProb.first_run = true;

#pragma omp parallel firstprivate(MyLargeProb)
    {
        int thread_specific_seed = omp_get_thread_num();
        MyLargeProb.specific_seed = thread_specific_seed;

        #pragma omp for
        for(int i = 0; i < 10; i++)
        {
            MyLargeProb.CrunchManyNos();
            std::cout << "Current iteration is " << i << std::endl;
        }

    }
    return 0;
}

The code that is commented out can be used as an alternative but the pointer gets destroyed after the method finishes which crashes the programme. Moreover, it was pointed out to me that I could use threadprivate for the static instance of GenNo. The use case equivalent of GenNo is a random number generator that gets seeded once per thread with a known seed and then is left alone, i.e. not reinitialised, but called upon to generate fresh random numbers in each iteration.

I know the whole structure seems a bit contrived but my hands are tied somewhat: the classes and their dependence are dictated to me by the tools I would like to use and I think this scenario is common in the scientific computing community. It compiles fine and upon manual testing appears to be thread-safe and working but again, I don't think this is particularly good style and a bit cobbled together, so I would love to hear everyone's comments. Important note: I am using gcc as my compiler and gcc for over ten years now doesn't support threadprivate class instances. Intel's compiler which can be obtained for academics and students on a trial license, does.

The following is an example of code that would not compile in GCC (even the most recent version).

#include "myclass.h"
#include <omp.h>
int main 

{
   myclass myinstance;
   #pragma omp parallel threadprivate(my_instance)

    {

      // do parallel things

     }
    return 0;
}

The error message would be my_instance declared threadprivate after first use which is a long-standing bug or rather not a bug but a missing feature, see here, for example.

\$\endgroup\$

closed as off-topic by 200_success, Sᴀᴍ Onᴇᴌᴀ, Adriano Repetti, Gerrit0, Mast Jan 13 at 9:29

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Lacks concrete context: Code Review requires concrete code from a project, with sufficient context for reviewers to understand how that code is used. Pseudocode, stub code, hypothetical code, obfuscated code, and generic best practices are outside the scope of this site." – 200_success, Sᴀᴍ Onᴇᴌᴀ, Gerrit0, Mast
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ There's so much skipped in the code that it's impossible to review. I see statements of which I doubt they could possibly work and there's no context. Please take a look at the help center. Currently, it's impossible to say you're doing it right, since there's next-to-nothing shown and what's show looks dubious at best. \$\endgroup\$ – Mast Jan 13 at 9:28
  • \$\begingroup\$ @Mast I erred on the side of giving a minimal reproducible example which is why I threw out most of it and made a model of my code rather than posting 600 lines here. But okay I shall see how I can produce a slightly more functional example. However, the code in the big implementation works fine and I am getting my numbers crunched, I just don't think I did it very well and hence was looking for someone to take a look at it. I shall have a read through the guidelines on the help center. \$\endgroup\$ – Hirek Jan 13 at 9:36
  • \$\begingroup\$ Minimum Complete Verifiable Examples are something for Stack Overflow. On Code Review, they are not acceptable. \$\endgroup\$ – Mast Jan 13 at 10:00
  • \$\begingroup\$ @aha ok that would explain it, I will have a look at the help center because it seems a bit rich of me to ask people to look at pretty extensive code. I was referred from stackoverflow to here. \$\endgroup\$ – Hirek Jan 13 at 10:02
  • \$\begingroup\$ @Mast Excluding the two header-only libraries I use, I have about 1500 lines of code. Do you not think this is too much? It is a class that inherits from an optimiser class and contains the value function as well as methods that help along the way. Then a main that uses an instance of the class to carry out the task. \$\endgroup\$ – Hirek Jan 13 at 14:23
1
\$\begingroup\$

what is the problem with just creating a range of random number generators from <random> and assign each to a thread?

Mind that using thread_local might not be a good way, as initialization of random number generators is costly. Also i do not know, how therngs would be seeded in a thread_local environement.

\$\endgroup\$
  • \$\begingroup\$ random number generator I use is based on the Mersenne Twister and is a custom-built one that delivers multivariate normal with given covariance matrix and vector of means. Assuming I were to go with your suggestion, how would I do that? Also, I am seeding manually as is the case in the model code above. \$\endgroup\$ – Hirek Jan 11 at 19:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.