Loading...
You are not logged-in Login/Register





  • Posts   Search Threads
  • Griffin MyersDecember 19, 2011 10:13 AM PST   
    OpenMP firstprivate and C++ object destruction

    I'm experiencing some unexpected behavior with icpc when using C++ objects with a firstprivate vs. private clause.  When an object is private then it appears to be be both constructed and destructed as expected, but for firstprivate the object does not seem to be destructed.  g++ does not exhibit similar behavior.  My understanding is that firstprivate C++ objects should be destructed (albeit in an unpredictable order) -- so is this an icpc bug or am I misunderstanding the OpenMP spec?

    Consider the following contrived code:

    #include <iostream>
    #include <unistd.h>
    #include <omp.h>
    
    using namespace std;
    
    class foo
    {
        public:
            foo(int v=0) : _bar(v){}
            ~foo() {cout << "destructing: " << _bar << endl;}
            int Bar() {return _bar;}
    
        private:
            int _bar;
    };
    
    
    int main()
    {
        foo g(5);
        foo f(99);
    
    #pragma omp parallel for default(none) shared(std::cout) private(f) num_threads(3)
        for (int i=0; i<3; i++)
        {
            usleep(omp_get_thread_num()*1e6);
            cout << omp_get_thread_num() << ": " << f.Bar() << endl;
        }
    }
    

    • With this code, g++ and icpc produce identical results.  Here each instance of f inside the loop is instantiated with the default constructor (as each of the _bar values is seen to be the default value of 0)
    g++ produces:
    0: 0
    destructing: 0
    1: 0
    destructing: 0
    2: 0
    destructing: 0
    destructing: 99
    destructing: 5


    icpc produces:
    0: 0
    destructing: 0
    1: 0
    destructing: 0
    2: 0
    destructing: 0
    destructing: 99
    destructing: 5



    • Now change the private clause on line 24 to firstprivate.  We see that instantiation now occurs with the implicit copy constructor (as _bar is 99).  But, for the icpc case none of the private copies of f get destructed!
    g++ produces:
    0: 99
    destructing: 99
    1: 99
    destructing: 99
    2: 99
    destructing: 99
    destructing: 99
    destructing: 5

    icpc produces:
    0: 99
    1: 99
    2: 99
    destructing: 99
    destructing: 5


    Version info:
    icpc (ICC) 12.1.0 20111011
    g++44 (GCC) 4.4.4 20100726 (Red Hat 4.4.4-13)


    Sergey KostrovDecember 19, 2011 5:18 PM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    Hi Griffin,

    Did you try to declare the destructor as 'virtual'?

    class foo

    {
    public:
         ...
         virtual ~foo() { cout << "destructing: " << _bar << endl; }
         ...
    };

    I know that it sounds as a strange advice because there are No Runtime Binding in your Test-Case. Anyway, I would try.

    Best regards,
    Sergey



    Griffin MyersDecember 19, 2011 5:23 PM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    Sergey,

    I just tried re-running with a virtual destructor, but it did not change the results.

    -Griffin

    hydroxyprolinDecember 19, 2011 6:23 PM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    In my opinion this is this is a bug in icpc (verified with latest Version 12.1.2.273 Build 20111128 / Linux x86-64), skipping the destructors doesn't make any sense at all.

    As a workaround you may add 'lastprivate(f)' to 'firstprivate(f)', then all destructors are called as they should. Because without the lastprivate clause the value of f has an indeterminate value upon exit from the construct, this workaround does not affect any code after the work-sharing construct.


    Sergey KostrovDecember 20, 2011 5:04 AM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    >>...this is a bug in icpc...

    I would also check the code with commented out '#pragma openmp ...' directive and lines 25 to 29 in
    order to see that the C/C++ compiler does everything well and destructors are called.

    Another verification before claiming that "this is a bug" is a Test-Case for a Runtime Binding of C++
    objects. I had some issues with g++ version 3.4.2 in the past.

    Best regards,
    Sergey


    chris_cramerDecember 20, 2011 12:00 PM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    I'll test without the #pragma, but I've never had any issues of not having destructors called and the code does call the destructor when the variable is private.  

    FWIW, I've tested this under Windows running Visual Studio 2008 with the Intel Compiler plugin turned on and the results are the same.

    -chris


    chris_cramerDecember 20, 2011 12:06 PM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    and to confirm, compiling without the openmp #pragma results in the creation, construction and destruction of both objects for both g++ and icpc.
    -chris


    Sergey KostrovDecember 20, 2011 3:25 PM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    Here is a Test-Case for virtual destructors when a Runtime Binding is used:

    class A
    {
    public:
         A( void ){ printf( "A::A\n" ); };
         virtual ~A( void ){ printf( "A::~A\n" ); };
    };

    class V
    {
    public:
         V( void ){ printf( "V::V\n" ); };
         virtual ~V( void ){ printf( "V::~V\n" ); };
    // ~V( void ){ printf( "V::~V\n" ); };    // If it is declared as Non Virtual ~W() won't be called and
    };                                                         // "resources" won't be released

    class W : public V
    {
    public:
         W( void ){ printf( "W::W\n" ); };
         virtual ~W( void ){ printf( "W::~W\n" ); };
    // ~W( void ){ printf( "W::~W\n" ); };
    };

    void main( void )
    {
         A *pA = new A();

         printf( "\n" );

         V *pv = new V();
         delete pv;                 // pv->~V::V(); // Used ::operator delete()
         printf( "\n" );

         pv = new W();
         delete pv;                 // pv->~W::W(); // Used W::operator delete()
         printf( "\n" );

         pv = new W();
         ::delete pv;               // pv->~W::W(); // Used ::operator delete()
         printf( "\n" );

         delete pA;
    }



    chris_cramerDecember 21, 2011 3:33 AM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    Sure - and that makes perfect sense in the case you are showing.  But what does that have to do with the original question?  
    The openmp issue with not calling the destructor when firstprivate is used occurs in the simple test case that was presented which does not make use of run-time bindings, does make use of openmp, and behaves differently when compiled with g++ vs icpc.  None of these things are true for the textbook demonstration of virtual destructors above.  
    -chris


    Sergey KostrovDecember 21, 2011 5:38 AM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    >>But what does that have to do with the original question?..

         This is to verify that a C/C++ compiler produces everything right without OpenMP. Especially, such a
         fundamental thing as calling a virtual destructor.

    >>...None of these things are true for the textbook demonstration of virtual destructors...

         This is not a text-book example. I have several tests for virtual destructors in my set of Test-Cases. I
         use these Test-Cases because in our Build Environment four different C/C++ compilers are used and
         two more are coming. It allows to verify that regardless of a C/C++ compiler, or OpenMP in your case,
         there are no bugs and Test-Cases produce absolutely identical outputs.


    hydroxyprolinDecember 21, 2011 8:41 AM PST
    Rate
     
    OpenMP firstprivate and C++ object destruction

    I don't see any relevance of the test case from Sergey for this problem either. The behaviour of icpc is a violation of the OpenMP specification, so it is a bug.

    To intel staff: please create a ticket for fixing this bug ("objects created for OpenMP work-sharing constructs with 'firstprivate' clause are not destructed"), a test case is supplied with the first post by Griffin Myers.

Forum jump:  

Intel Software Network Forums Statistics

17,025 users have contributed to 48,319 threads and 172,758 posts to date.

In the past 24 hours, we have 11 new thread(s) 54 new posts(s), and 47 new user(s).

In the past 3 days, the most popular thread for everyone has been Optimalization of sine function\'s taylor expansion The most posts were made to Most likely, the issue is that The post with the most views is Optimalization of sine function\'s taylor expansion

Please welcome our newest member redfruit83


For more complete information about compiler optimizations, see our Optimization Notice.