2015-04-04 2 views
-1

Я экспериментировал с приведенным ниже фрагментом кода для сравнения производительности серийного и параллельного для (как не-лямбда, так и лямбда).

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 

Теперь оптимизированный код, кажется, показывает лучшие результаты для последовательной части и время ламбы улучшилось.

Означает ли это, что производительность параллельного кода всегда должна быть проверена с помощью оптимизированного кода ?

+0

Какой компилятор и какой уровень оптимизации вы используете? Знаете ли вы, что любой достойный компилятор должен заменить вызов 'squarecalc' на no-op, поскольку вы не передаете аргумент по ссылке, а по значению? – MikeMB

+0

Квадрацикл намеренно предназначен для передачи аргументов по значению, поскольку моя главная цель заключалась в том, чтобы вычислить время, и мне наименее заинтересовано в получении квадратов. Я использую g ++ версию 4.6.3 и не применяю оптимизации – sjsam

+0

Извините, но в этом случае я не могу вам помочь. Рассуждение о выполнении неоптимизированного кода просто бессмысленно. И, как я сказал: если бы это был оптимизированный код, вы бы, вероятно, только измерили накладные расходы ('squarecalc', например, никогда не будет вызван). – MikeMB

ответ

0

Означает ли это, что производительность параллельного кода всегда должна тестироваться с оптимизированным кодом?

Любое качество кода должно быть проверено с оптимизированным кодом. Вы хотите оптимизировать свой код для быстрой работы во время отладки или когда используется ваше программное обеспечение?

Основная проблема в вашем коде заключается в том, что ваши циклы не выполняют никакой работы (squarecalc и, скорее всего, даже serial_apply_square(int* a) полностью оптимизированы), а измеренные времена слишком коротки, чтобы служить индикатором реальной жизни различные конструкции.

Смежные вопросы