5

I am adding OpenMP to existing code, and am trying to parallelize the for loop below. Block is a container implemented in the code. Operators < and ++ are implemented for the Block container.

#pragma omp parallel for // code compiles without this line
for ( Block::iterator it = initValue; it < blockEnd; ++it ) {
  // LOOP BODY
}

I get the following error when the OpenMP pragma is there:

No match for 'operator-' (operand types are Block::iterator and Block::iterator)

If I take the pragma out, the code compiles fine, so I am sure my operator definitions are OK. Why does OpenMP require 'operator-' to be implemented here?

Compiler: gcc 7.2.1 OpenMP 4.0

v2v1
  • 640
  • 8
  • 18
  • in response to the close vote - how is this question not about programming with the SO scope? – v2v1 Feb 19 '18 at 18:15
  • 1
    The CV is not about scope. It is about the lack of a [mcve] (which should alos include compiler and options). – Zulan Feb 19 '18 at 18:18
  • 1
    I'm not the caster but I imagine them voting to close because we lack the definition of `Block::iterator`, but I think this is unrelated. – YSC Feb 19 '18 at 18:19
  • I can't provide the implementation for proprietary reasons – v2v1 Feb 19 '18 at 18:20
  • 1
    Ideally, as Zulan said, you should build a [mcve]. This is what the good questions on SO are made of. (good Qs are made of this) – YSC Feb 19 '18 at 18:21
  • 1
    Your question is rather easily answerable without a MCVE, but generally it is necessary for a good question. A MCVE does not mean that you provide your full proprietary code. It means you craft a special minimal code that reproduces your issue. – Zulan Feb 19 '18 at 18:24
  • If the question is answerable without a MCVE, I don't understand why adding one is necessary. – v2v1 Feb 19 '18 at 18:24
  • @xcski notice that the answer is basically _guessing_ that `Block::iterator` is missing something. It does so by interpreting the error message. But they can't verify their answer from the question alone. If it would not have been that, the answer would be wrong and OP (you) would need to call it out as wrong. – WorldSEnder Feb 19 '18 at 18:30
  • 1
    @WorldSEnder there's no *guessing* involved in the answer as the error message is particularly clear - and the actual question is why it is required. Nevertheless the question would be better with a MCVE, as it would enable an answer to demonstrate how to fix it - or even show what the compiler does with your code. – Zulan Feb 19 '18 at 22:35
  • Don't use OpenMP. Don't use OpenMP with C++. It's bad, it's not supported, see also [this post](https://stackoverflow.com/questions/13837696/can-i-safely-use-openmp-with-c11). I prefer [tbb](https://www.threadingbuildingblocks.org/), which is actually C++. – Walter Feb 19 '18 at 23:03
  • Note that in order to parallelize a `for` loop (or anything) one must be able to split the task, i.e. to split the loop domain in two or more roughly equal pieces. That's not always possible, for example when looping over a linked list. Hence you must think about parallelism before you generate your data structures. – Walter Feb 19 '18 at 23:09
  • To quote Zulan, "clearly" – v2v1 Feb 20 '18 at 00:21

2 Answers2

7

OpenMP supports iterator-loops only for RandomAccessIterators. Clearly, Block::iterator does not satisfy it, missing the corresponding operator-.

Edit: The other answer gives some hints as to how GCC use the operator-. However, the true answer remains: The OpenMP standard requires you to implement a RandomAccessIterator, with all it's required operations. Note that this goes much further. Failing to do so may result in your code working with a particular GCC version, but not with another version or compiler.

Zulan
  • 21,896
  • 6
  • 49
  • 109
3

The error message is actually quite explicit about what is missing:

No match for 'operator-' (operand types are Block::iterator and Block::iterator)

Try implementing a standalone function with a signature like:

int operator - ( Block::iterator a, Block::iterator b );

I mocked this up based on the scenario you described and found that it worked under g++-5.4.


Why does OpenMP require 'operator-' to be implemented here?

OpenMP partitions your loop into segments based on the number of threads that it will be executing. To do this, requires a little math.

For starters, how big is the total job? Answer: blockEnd-initValue.

Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173