Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Tim
Beginner
221 Views

OpenMp 3.0 and iterators

Hi,

I have two questions about the Intel Compiler and OpenMp 3.0:

1. The OpenMp 3.0 specification support loop parallelization for random_access_iterators. This works fine for icpc 11.1 and a iterator over a std::deque (see example 1). The compiler does NOT produce any error messages, but the parallel for loop is not executed! If i compile with gcc or portland compiler it works as expected!

example 1:

#include
#include
#include
#include
#include


int main (int argc, char** argv){
//typedef std::deque containerType;
typedef std::vector containerType;

containerType myList;

char c='a';
for(int i=0; i myList.push_back(c);
c++;
}

containerType::iterator itL;
int i=0;

#pragma omp parallel for
for(itL=myList.begin(); itL < myList.end(); itL++){
std::cout<< (char)*itL << ": " << ++i << std::endl;
}

std::cout<<i< return 0

}


So is this a bug in the intel compiler? Shouldn't it produce a warning at least?

2. The second question is even more specific:

Now i wrote my own iterator class for my own container (example code below). I inheritated this iterator class from the std::iterator class to get a STL conform iterator. This works fine with GNU g++ 4.4.1, but for icpc I get an internal error:

$ icpc -openmp -o main2 main2.cc
(0): internal error: backend signals
compilation aborted for main2.cc (code 4)


code:

#include
#include
#include
#include
#include
#include
#include

#define SIZE 26

class SpecialMap;

class SpecialMapIterator: public std::iterator{

public:
SpecialMapIterator() : it_(0){}
SpecialMapIterator& operator++(){++it_; return *this;}
SpecialMapIterator& operator++(int){it_++; return *this;}
SpecialMapIterator& operator--(){--it_; return *this;}
SpecialMapIterator& operator--(int){it_--; return *this;}

typedef ptrdiff_t difference_type;

SpecialMapIterator& operator+=(difference_type rhs){
while(rhs>0){
it_++;
rhs--;
}
return *this;
}

char& operator*() {return it_->second;}
const char& operator*() const{return it_->second;}

bool operatorbool operatorbool operator!=(const SpecialMapIterator& rhs){return it_!=rhs.it_;}
bool operator==(const SpecialMapIterator& rhs){return (it_==rhs.it_);}

friend class SpecialMap;
friend difference_type operator-(SpecialMapIterator it1, SpecialMapIterator it2);

private:
SpecialMapIterator(std::map::iterator it) : it_(it){}
std::map::iterator it_;
};


class SpecialMap{
public:
typedef SpecialMapIterator iterator;
typedef SpecialMapIterator const_iterator;

iterator begin(){return SpecialMapIterator(map_.begin());}
iterator end(){return SpecialMapIterator(map_.end());}

char& operator[](const int i){ return map_;}

private:
std::map map_;
};


SpecialMapIterator::difference_type operator-(SpecialMapIterator it1, SpecialMapIterator it2){
SpecialMapIterator::difference_type count = 0;
while(it2 != it1){
++it2;
++count;
}
return count;
}

int main (int argc, char** argv){
typedef SpecialMap maptype;
maptype myMap;

char c='a';
for(int i=0; imyMap=c;
c++;
}

maptype::iterator itM;
int i = 0;

#pragma omp parallel for
for(itM=myMap.begin(); itM < myMap.end(); itM++){

#pragma omp critical
{
std::cout << *itM << ": " <<omp_get_thread_num()<< ": " <}
}
return 0;
}


The openMP specification does not really say, in which case a iterator is a "RandomAccessIterator". So is this a feature in gcc or a bug in icpc? Or is there another possibility to write my own RandomAccessIterator or wrap it somehow?

PS: I asked the same question in porland group forum: http://www.pgroup.com/userforum/viewtopic.php?t=1556 , because the second example also does not work with the portland compiler. And they said it is a bug on their side...

0 Kudos
10 Replies
JenniferJ
Moderator
221 Views

Quoting - timiem
1. The OpenMp 3.0 specification support loop parallelization for random_access_iterators. This works fine for icpc 11.1 and a iterator over a std::deque (see example 1). The compiler does NOT produce any error messages, but the parallel for loop is not executed! If i compile with gcc or portland compiler it works as expected!
Hello,
First of all thanks for your posting with a testcase.

About #1 issue, it seems a bug on Linux with "std::vector". It works with -Od though. I'll file a bug report to the compiler.

I'll check on the #2 next.

Thanks again.
Jennifer
Tim
Beginner
221 Views

Hello,
First of all thanks for your posting with a testcase.

About #1 issue, it seems a bug on Linux with "std::vector". It works with -Od though. I'll file a bug report to the compiler.

Hi,

thanks for your quick support.

Sorry, but I think it does not really work. The output is correct with -O0 (what is better than before), but the loop seems not to be executed in parallel! (I checked this by printing out omp_get_thread_num() within the loop!)
JenniferJ
Moderator
221 Views

Quoting - timiem
Sorry, but I think it does not really work. The output is correct with -O0 (what is better than before), but the loop seems not to be executed in parallel! (I checked this by printing out omp_get_thread_num() within the loop!)
Yeh, you're right. I added this api to the test and saw the problem.

About #2 issue, it happens on Windows as well if changing following line. I've filed a bug report about this well.

When there's any update, I'll post here.

Jennifer
JenniferJ
Moderator
221 Views


About the #2 issue, there's a work-around for it. It's to make the operator methods non-class member. Like:

[cpp]#if 0
        bool operator<=(const SpecialMapIterator& rhs){return it_!=rhs.it_; }
        bool operator<(const SpecialMapIterator& rhs){return it_!=rhs.it_;}
        bool operator!=(const SpecialMapIterator& rhs){return it_!=rhs.it_;}
        bool operator==(const SpecialMapIterator& rhs){return (it_==rhs.it_);}
#else
      friend bool operator<=(const SpecialMapIterator& lhs,
                               const SpecialMapIterator& rhs)
            {return lhs.it_!=rhs.it_; }
      friend bool operator<(const SpecialMapIterator& lhs,
                              const SpecialMapIterator& rhs)
            {return lhs.it_!=rhs.it_;}
      friend bool operator!=(const SpecialMapIterator& lhs,
                               const SpecialMapIterator& rhs)
            {return lhs.it_!=rhs.it_;}
      friend bool operator==(const SpecialMapIterator& lhs,
                               const SpecialMapIterator& rhs)
            {return (lhs.it_==rhs.it_);}
#endif
[/cpp]

The #2 bug just got fixed. It should be in the 3rd compiler update around end of October.

Jennifer
JenniferJ
Moderator
221 Views

About issue #1 that the omp loop got optimized away, there is a work-around for it: it is to change the iterator to operator [].

The fix involves several modules, so it will take some time. Please use the work-around for now.When there is more news, I'll let you know.

Thanks,
Jennifer
shane_stainsby
Beginner
221 Views

Hi Jennifer,

just tried example #2 with Intel compiler 11.1.073 and even with your suggested update it only runs on one thread. This also seems to true if I try deque.Is there a version of the compiler available that resolves this issue?

Thanks

Shane

SergeyKostrov
Valued Contributor II
221 Views

What happens if the following is #pragma directive is used: #pragma omp parallel for num_threads( 8 ) ... Does it create 8 OpenMP threads?
TimP
Black Belt
221 Views

You could generate asm code to see if the OpenMP is implemented with an omp single, as is generally done for OpenMP 2.5 features.

I would agree, "support" for various levels of OpenMP might be expected to go beyond simply not breaking serial code.

Up to now, it's often been necessary to make multiple levels of loops, with an outer parallel for and inner STL loop, particularly for vectorizable cases.  Future OpenMP 4.0 omp simd parallel for directive would support combined vectorization and parallelization.

STL is designed to make things difficult for optimizing compilers, and each compiler team has had to implement specific machinery to handle vectorization of suitable STL operators.  Without vectorization, it's somewhat academic if you can get threaded parallelization.

jimdempseyatthecove
Black Belt
221 Views

I think iterators and parallel constructs are an oxymoron.

parallel for has the requirement to know the number of iterations in order to determine how (much) to partition the iteration space amongst threads. If the iterators are truely opaque, then the compiler could concievably make the parallel for into a parallel while. However, this may be at severe expense of performance.

Just for fun, consider a case where the iterator returns a random number: as does the List.begin() and List.end(), and itL++, and operator "less than". Although this is a "stupid" example, it is well within the scope of permissable activities for sequential "for(...".

I agree with Jennifer's suggestion to use operator[] with first obtaining the end[] number, replacing the iterator with size_t i.

Other complications with using containers in parallel is you must be careful not to alter the container disruptive to other threads. e.g. one thread causes container to resize, delete, move, etc...

Jim Dempsey

SergeyKostrov
Valued Contributor II
221 Views

>> I think iterators and parallel constructs are an oxymoron... In the past I've asked a couple of times a question 'Why do you need iterator here?' and the answers were like 'Just 'cause!' So, developers could not explain it. My point of view is that unnecessary applications of some programming techniques are "killing" performance of an application.
Reply