0

I have been studying about parallel loops (C++11) and testing them with MS visual studio 2013. I am clear about them (lambdas esp.) which are pretty cool.

But my concern is that I have to call a function that performs a simple euclidean distance measure. Function by itself is clear, but I have to move the function to a class called EuclideanDistance and do the euclidean math inside the function Match(vectorA,vectorB) on two vectors which simply is some norm(...) calculation.And returns a floating point value.

Now how do I go about this inside a parallel_for/parallel_foreach loop? Do I create the class object inside the loop or keeping the class object outside the loop will cause inconsistencies? If I understood correctly about parallel loops the function over which it works is basically a clean copy for every thread launched. Does this happen in the case of class functions? My hunch is no! Unless I create an object inside the class as shown in the second code snippet.

e.g. For the sake of readability, I keep the code abbreviated.

vectorA; // Floating point array of 1024 entries.
concurrent_queue vectorQ; // each entry in the queue is a 1024 array
EuclideanDistance euclid;
parallel_for_each(begin,end,[&](auto item)
{
    auto distance = euclid.Match(vectorA,item);
});

Or this will be the right way of doing it?

parallel_for_each(begin,end,[&](auto item)
{
EuclideanDistance euclid;
    auto distance = euclid.Match(vectorA,item);
});

The whole class is nothing more than a single function.

    class EuclideanDistance
    {
public:
       float Match(vectorA,vectorB)
        {
           return norm(vectorA,vectorB); 
        }
    };

Any pitfalls would be highly appreciated!

Allanqunzi
  • 3,230
  • 1
  • 26
  • 58
Wajih
  • 793
  • 3
  • 14
  • 31
  • You don't really provide enough information here to answer your question. Does your `Match()` function modify state in the `EuclideanDistance` object? If so then you may run into problems declaring it outside your `parallel_for_each` but you would also expect different results from declaring it inside if the modifications to state impact the results of your computation. – mattnewport Aug 27 '15 at 19:50
  • @mattnewport - Oh, good point. It does not change the state in EuclideanDIstance object. The function just returns a value. I have edited the question. Thanks for pointing it out. – Wajih Aug 27 '15 at 19:58
  • You shouldn't need to move the code into a class then, why did you do that? Since your `Match()` function doesn't have any side effects it is safe to use it inside your `parallel_for_each` wherever you define the `EuclideanDistance` object. – mattnewport Aug 27 '15 at 20:01
  • Well actually I have kept the class simple. There are different kind of distances calculated, e.g. Euclidean, Manhattan, Spherical, Angular etc. That is why I had to keep it inside a class. All of them donot change the state of the object, just return floating point values. – Wajih Aug 27 '15 at 20:03
  • As long as none of the functions you call have side effects you'll be fine. – mattnewport Aug 27 '15 at 20:04
  • @Wajih If it's only a function using no class objects, why not making it `static` ? No need for an object then. – Blacktempel Aug 28 '15 at 05:33
  • @Blacktempel - That is what I am doing right now. Converting it to a static I am experimenting to see what behaviour I can get :) – Wajih Aug 28 '15 at 05:41

1 Answers1

1

You are correct that if you define your EuclideanDistance object outside the parallel_for_each lambda body, it will be shared across all the worker threads executing the parallel_for_each. This would be a problem if your Match() function had side effects affecting shared state in your EuclideanDistance object but in that case it is likely defining the object inside the lambda (which would give each execution of the loop body its own local instance) would have different results from defining it outside.

As long as any functions you call on the EuclideanDistance object have no side effects / do not modify shared state then you are fine using one object defined outside the lambda. If you were calling functions with side effects then you would need to do your own synchronization which would likely impact the performance gain of the parallel_for_each significantly.

mattnewport
  • 13,728
  • 2
  • 35
  • 39