Я экспериментировал с приведенным ниже фрагментом кода для сравнения производительности серийного и параллельного для (как не-лямбда, так и лямбда).
TBB лямбда против самоналоженного объекта тела
#include<iostream>
#include<chrono>
#include <ctime>
#include<fstream>
#include<stdlib.h>
#define MAX 10000000
#include "tbb/tbb.h"
#include "tbb/task_scheduler_init.h"
using namespace std;
using namespace tbb;
void squarecalc(int a)
{
a *= a;
}
void serial_apply_square(int* a)
{
for (int i = 0; i<MAX; i++)
squarecalc(*(a + i));
}
class apply_square
{
int* my_a;
public:
void operator()(const blocked_range<size_t>& r) const
{
int *a = my_a;
for (size_t i = r.begin(); i != r.end(); ++i)
squarecalc(a[i]);
}
apply_square(int* a) :my_a(a){}
};
void parallel_apply_square(int* a, size_t n)
{
parallel_for(blocked_range<size_t>(0, n), apply_square(a));
}
void parallel_apply_square_lambda(int* a, size_t n)
{
parallel_for(blocked_range<size_t>(0, n), [=](const blocked_range<size_t>& r)
{
for (size_t i = r.begin(); i != r.end(); ++i)
squarecalc(a[i]);
}
);
}
int main()
{
std::chrono::time_point<std::chrono::system_clock> start, end;
int i = 0;
int* a = new int[MAX];
fstream of;
of.open("newfile", ios::in);
while (i<MAX)
{
of >> a[i];
i++;
}
start = std::chrono::system_clock::now();
serial_apply_square(a);
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
cout << "\nTime for serial execution :" << elapsed_seconds.count() << endl;
start = std::chrono::system_clock::now();
parallel_apply_square(a, MAX);
end = std::chrono::system_clock::now();
elapsed_seconds = end - start;
cout << "\nTime for parallel execution [without lambda] :" << elapsed_seconds.count() << endl;
start = std::chrono::system_clock::now();
parallel_apply_square_lambda(a, MAX);
end = std::chrono::system_clock::now();
elapsed_seconds = end - start;
cout << "\nTime for parallel execution [with lambda] :" << elapsed_seconds.count() << endl;
free(a);
}
Короче он просто вычисляет квадрат 10000000 чисел в обеих последовательных и параллельных путях. Ниже приведен вывод, который я получил для нескольких исполнений объектного кода .
**1st execution**
Time for serial execution :0.043183
Time for parallel execution [without lambda] :0.035238
Time for parallel execution [with lambda] :0.036719
**2nd execution**
Time for serial execution :0.043252
Time for parallel execution [without lambda] :0.035403
Time for parallel execution [with lambda] :0.036811
**3rd execution**
Time for serial execution :0.043241
Time for parallel execution [without lambda] :0.035355
Time for parallel execution [with lambda] :0.036558
**4th execution**
Time for serial execution :0.043216
Time for parallel execution [without lambda] :0.035491
Time for parallel execution [with lambda] :0.036697
Мысли параллельных времен исполнения является меньшим, чем последовательное выполнение раз для всех случаев, я был любопытными, почему время метода лямбды выше , чем другая параллельной версии, где объект тела является самим написано ,
- Почему версия лямбда всегда принимает больше времени?
- Это из-за накладных расходов для компилятора, чтобы создать собственное тело объект?
- Если ответ на этот вопрос да, то лямбда-версия уступает самозанятой версии?
Редактировать
Ниже приведены результаты для оптимизированного кода (уровень -O2)
**1st execution**
Time for serial execution :0
Time for parallel execution [without lambda] :0.00055
Time for parallel execution [with lambda] :1e-05
**2nd execution**
Time for serial execution :0
Time for parallel execution [without lambda] :0.000583
Time for parallel execution [with lambda] :9e-06
**3rd execution**
Time for serial execution :0
Time for parallel execution [without lambda] :0.000554
Time for parallel execution [with lambda] :9e-06
Теперь оптимизированный код, кажется, показывает лучшие результаты для последовательной части и время ламбы улучшилось.
Означает ли это, что производительность параллельного кода всегда должна быть проверена с помощью оптимизированного кода ?
Какой компилятор и какой уровень оптимизации вы используете? Знаете ли вы, что любой достойный компилятор должен заменить вызов 'squarecalc' на no-op, поскольку вы не передаете аргумент по ссылке, а по значению? – MikeMB
Квадрацикл намеренно предназначен для передачи аргументов по значению, поскольку моя главная цель заключалась в том, чтобы вычислить время, и мне наименее заинтересовано в получении квадратов. Я использую g ++ версию 4.6.3 и не применяю оптимизации – sjsam
Извините, но в этом случае я не могу вам помочь. Рассуждение о выполнении неоптимизированного кода просто бессмысленно. И, как я сказал: если бы это был оптимизированный код, вы бы, вероятно, только измерили накладные расходы ('squarecalc', например, никогда не будет вызван). – MikeMB