Объект класса внутри или снаружи parallel_for/parallel_for_each?

Я изучал параллельные циклы (С++ 11) и тестировал их с помощью MS Visual Studio 2013. Мне они понятны (особенно лямбда-выражения), которые довольно круты.

Но меня беспокоит то, что я должен вызвать функцию, которая выполняет простую евклидову меру расстояния. Функция сама по себе понятна, но я должен переместить функцию в класс с именем EuclideanDistance и выполнить евклидовы вычисления внутри функции Match(vectorA,vectorB) для двух векторов, которые просто вычисление нормы (...). И возвращает значение с плавающей запятой.

Теперь, как мне это сделать внутри цикла parallel_for/parallel_foreach? Создаю ли я объект класса внутри цикла, или сохранение объекта класса вне цикла вызовет несоответствия? Если я правильно понял о параллельных циклах, функция, над которой он работает, в основном является чистой копией для каждого запущенного потока. Это происходит в случае функций класса? Моя догадка нет! Если я не создам объект внутри класса, как показано во втором фрагменте кода.

например Для удобочитаемости я сокращаю код.

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);
});

Или это будет правильный способ сделать это?

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

Весь класс — не что иное, как одна функция.

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

Любые подводные камни будут высоко оценены!


person Wajih    schedule 27.08.2015    source источник
comment
Вы действительно не предоставляете достаточно информации здесь, чтобы ответить на ваш вопрос. Изменяет ли ваша функция Match() состояние объекта EuclideanDistance? Если это так, вы можете столкнуться с проблемами при объявлении его за пределами вашего parallel_for_each, но вы также ожидаете других результатов от объявления его внутри, если изменения состояния повлияют на результаты ваших вычислений.   -  person mattnewport    schedule 27.08.2015
comment
@mattnewport - О, хорошее замечание. Он не изменяет состояние объекта EuclideanDIStance. Функция просто возвращает значение. Я отредактировал вопрос. Спасибо, что указали на это.   -  person Wajih    schedule 27.08.2015
comment
Тогда вам не нужно было переносить код в класс, зачем вы это сделали? Поскольку ваша функция Match() не имеет побочных эффектов, ее безопасно использовать внутри вашего parallel_for_each везде, где вы определяете объект EuclideanDistance.   -  person mattnewport    schedule 27.08.2015
comment
Ну, на самом деле я сохранил класс простым. Рассчитываются различные виды расстояний, например. Euclidean, Manhattan, Spherical, Angular и т. д. Вот почему мне пришлось держать его внутри класса. Все они не меняют состояние объекта, просто возвращают значения с плавающей запятой.   -  person Wajih    schedule 27.08.2015
comment
Пока ни одна из функций, которые вы вызываете, не имеет побочных эффектов, все будет в порядке.   -  person mattnewport    schedule 27.08.2015
comment
Опубликуйте ответ, и я приму его :)   -  person Wajih    schedule 27.08.2015
comment
@Wajih Если это всего лишь функция, не использующая объекты класса, почему бы не сделать ее static? Тогда объект не нужен.   -  person Blacktempel    schedule 28.08.2015
comment
@Blacktempel - это то, чем я сейчас занимаюсь. Преобразовывая его в статику, я экспериментирую, чтобы увидеть, какое поведение я могу получить :)   -  person Wajih    schedule 28.08.2015


Ответы (1)


Вы правы в том, что если вы определите свой объект EuclideanDistance вне тела parallel_for_each lambda, он будет общим для всех рабочих потоков, выполняющих parallel_for_each. Это было бы проблемой, если бы ваша функция Match() имела побочные эффекты, влияющие на общее состояние в вашем объекте EuclideanDistance, но в этом случае, скорее всего, определение объекта внутри лямбда (что дало бы каждому выполнению тела цикла свой собственный локальный экземпляр) имело бы разные получается из определения его снаружи.

Пока любые функции, которые вы вызываете для объекта EuclideanDistance, не имеют побочных эффектов/не изменяют общее состояние, вы можете использовать один объект, определенный вне лямбды. Если бы вы вызывали функции с побочными эффектами, вам нужно было бы выполнить собственную синхронизацию, что, вероятно, значительно повлияло бы на прирост производительности parallel_for_each.

person mattnewport    schedule 27.08.2015