- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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...
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page