Форум программистов, компьютерный форум, киберфорум
Наши страницы
Boost C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.95/21: Рейтинг темы: голосов - 21, средняя оценка - 4.95
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
1

Объясните нубу про распараллеливание вычислений. thread

07.01.2013, 02:42. Просмотров 3870. Ответов 17
Метки нет (Все метки)

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

без потоков
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <windows.h>
#define n 100000000
using namespace std;
int kvo = 0;
void first() 
{
   for (int i = 0; i <= n; i++)
   {
       for (int j = i; j != 0; j /= 10)
          if (j%10 == 2) 
             kvo++;
   }
}
 
int main() 
{
  int start=GetTickCount();
  first();
  cout<<kvo<<endl;
  int end=GetTickCount();
  cout<<end-start<<endl;
  getchar();
  return 0;
}
время 13759

2 потока
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <windows.h>
#define n 100000000
using namespace std;
    int kvo = 0;
void first(boost::mutex& mutex) 
{
  {
  boost::lock_guard<boost::mutex> lock(mutex);
 
   for (int i = 0; i < n/2; i++)
   {
       for (int j = i; j != 0; j /= 10)
          if (j%10 == 2) 
             kvo++;
   }
  }
}
 
void second(boost::mutex& mutex)
{
    boost::lock_guard<boost::mutex> lock(mutex);
 
    for (int i = n/2; i <= n; i++)
    {
        for (int j = i; j != 0; j /= 10)
           if (j%10 == 2) 
              kvo++;
    }
}
 
int main() 
{
  int start=GetTickCount();
  boost::mutex io_mutex;
  boost::thread my_thread(boost::bind(&first, boost::ref(io_mutex)));
  boost::thread my_thread2(boost::bind(&second, boost::ref(io_mutex)));
  my_thread.join();
  my_thread2.join();
  cout<<kvo<<endl;
  int end=GetTickCount();
  cout<<end-start<<endl;
  getchar();
  return 0;
}
время 12480
разницы почти нет, все из-за мютексов, без синхронизации все прекрасно и быстро работает...

этой строчкой
boost::lock_guard<boost::mutex> lock(mutex);
я хотел синхронизировать потоки, чтоб не было одновременного доступа к переменной, правильно я сделал?..)

сразу скажу, что 2 процессора у меня...)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.01.2013, 02:42
Ответы с готовыми решениями:

boost::thread объясните нубу
Есть код #include &lt;boost/thread/thread.hpp&gt; #include &lt;iostream&gt; #include...

Распараллеливание вычислений
Вычисляю произведение матриц несколькими потоками (количество задаётся...

Распараллеливание вычислений
Здравствуйте. Может кто сможет подсказать как мне решить следующую задачу:...

Распараллеливание вычислений
Здравствуйте! Есть симулятор клеточного автомата. &quot;Поле действий&quot; -...

Распараллеливание вычислений
Доброго времени форумчане. Может кто-нибудь подсказать по классу Parallel из...

17
Avazart
Эксперт С++
7722 / 5631 / 549
Регистрация: 10.12.2010
Сообщений: 25,400
Записей в блоге: 17
07.01.2013, 03:29 2
Полагаю что так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int kvo = 0;
const int n= 100000000; /* зачем юзать сишный #define ? */
 
void first(boost::mutex& mutex) 
{
   int kvo1= 0;
   for (int i = 0; i < n/2; i++)
   {
       for (int j = i; j != 0; j /= 10)
          if (j%10 == 2) 
             kvo1++;
   }
  boost::lock_guard<boost::mutex> lock(mutex);
  kvo+= kvo1;
}
 
void second(boost::mutex& mutex)
{
    int kvo2= 0;
    for (int i = n/2; i <= n; i++)
    {
        for (int j = i; j != 0; j /= 10)
           if (j%10 == 2) 
              kvo2++;
    }
     boost::lock_guard<boost::mutex> lock(mutex);
     kvo+= kvo2;
}
Добавлено через 1 минуту
Вывод

80000000
7 145
Добавлено через 6 минут
Цитата Сообщение от NeonLost Посмотреть сообщение
я хотел синхронизировать потоки, чтоб не было одновременного доступа к переменной, правильно я сделал?..)
Пока один поток занял переменную - другой не может к ней достучаться и тупит пока она не освободится...
А значит занимать переменную нужно только на короткое время...
1
fasked
Эксперт С++
4982 / 2561 / 241
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
07.01.2013, 04:29 3
NeonLost, я может чего не понимаю, но зачем тут вообще синхронизироваться?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <future>
#include <iostream>
 
int compute(int left, int right)
{
    int k = 0;
    for (int i = left; i <= right; ++i) 
        for (int j = i; j != 0; j /= 10)
           k += (j % 10 == 2);
 
    return k;
}
 
int main(int argc, char **argv)
{
    try {
        int n = 100000000;
        if (argc > 1) {
            std::cout << compute(0, n) << std::endl;
        } else {
            auto h1 = std::async(std::launch::async, compute, 0, n/2);
            auto h2 = std::async(std::launch::async, compute, n/2, n);
            std::cout << "async " << h1.get() + h2.get() << std::endl;
        }
    } catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
}
Код
$ time ./a.out 2
80000000
./a.out 2  8.54s user 0.43s system 99% cpu 8.987 total
$ time ./a.out  
async 80000000
./a.out  8.54s user 0.20s system 189% cpu 4.614 total
1
alex_x_x
бжни
2455 / 1661 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
07.01.2013, 04:53 4
Для таких задач openMP тащемто придумали
1
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
07.01.2013, 12:06  [ТС] 5
Цитата Сообщение от Avazart Посмотреть сообщение
Полагаю что так
Пока один поток занял переменную - другой не может к ней достучаться и тупит пока она не освободится...
А значит занимать переменную нужно только на короткое время...
почему тогда так не работает?..вроде он должен лочить поток, только тогда, когда идет его увеличение, разве нет?..)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <windows.h>
#define n 100000000
using namespace std;
    int kvo = 0;
void first(boost::mutex& mutex) 
{ 
   for (int i = 0; i < n/2; i++)
   {
       for (int j = i; j != 0; j /= 10)
          if (j%10 == 2) 
          {
             boost::lock_guard<boost::mutex> lock(mutex);
             kvo++;
          }
   }
}
 
void second(boost::mutex& mutex)
{ 
    for (int i = n/2; i <= n; i++)
    {
        for (int j = i; j != 0; j /= 10)
           if (j%10 == 2)
           {
              boost::lock_guard<boost::mutex> lock(mutex);
              kvo++;
           }
    }
}
 
int main() 
{
  int start=GetTickCount();
  boost::mutex io_mutex;
  boost::thread my_thread(boost::bind(&first, boost::ref(io_mutex)));
  boost::thread my_thread2(boost::bind(&second, boost::ref(io_mutex)));
  my_thread.join();
  my_thread2.join();
  cout<<kvo<<endl;
  int end=GetTickCount();
  cout<<end-start<<endl;
  getchar();
  return 0;
}
время 23151

Добавлено через 2 минуты
Цитата Сообщение от fasked Посмотреть сообщение
NeonLost, я может чего не понимаю, но зачем тут вообще синхронизироваться?
элегантное решение, спасибо...)
у меня было так без синхронизации
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <windows.h>
#define n 100000000
using namespace std;
int one = 0;
int two = 0;
void first() 
{
   for (int i = 0; i < n/2; i++)
   {
       for (int j = i; j != 0; j /= 10)
          if (j%10 == 2) 
             one++;
   }
}
 
void second()
{
    for (int i = n/2; i <= n; i++)
    {
        for (int j = i; j != 0; j /= 10)
           if (j%10 == 2) 
              two++;
    }
}
 
int main() 
{
  int start=GetTickCount();
  boost::thread my_thread(&first);
  boost::thread my_thread2(&second);
  my_thread.join();
  my_thread2.join();
  cout<<one+two<<endl;
  int end=GetTickCount();
  cout<<end-start<<endl;
  getchar();
  return 0;
}
время 7442
0
fasked
Эксперт С++
4982 / 2561 / 241
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
07.01.2013, 12:07 6
NeonLost, синхронизация потоков тоже не бесплатная. В этом случае на захват и освобождение мьютекса времени уходит больше, чем сами расчеты.
1
Jupiter
Каратель
Эксперт С++
6569 / 3990 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
07.01.2013, 12:12 7
Цитата Сообщение от NeonLost Посмотреть сообщение
почему тогда так не работает?..вроде он должен лочить поток, только тогда, когда идет его увеличение, разве нет?..)
нет, потому что
Цитата Сообщение от NeonLost Посмотреть сообщение
C++
1
2
my_thread.join();
my_thread2.join();
1
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
07.01.2013, 12:27  [ТС] 8
Цитата Сообщение от Jupiter Посмотреть сообщение
нет, потому что
а чем они мешают, они же вроде только основной поток программы тормозят, пока потоки все не закончат?..)

Добавлено через 6 минут
Цитата Сообщение от alex_x_x Посмотреть сообщение
Для таких задач openMP тащемто придумали
почитал, оказывается MCVS поддерживает и вроде, довольно просто...)
0
Jupiter
07.01.2013, 12:47
  #9

Не по теме:

Цитата Сообщение от NeonLost Посмотреть сообщение
а чем они мешают, они же вроде только основной поток программы тормозят, пока потоки все не закончат?..)
точно, недосмотрел

0
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
07.01.2013, 12:49  [ТС] 10
Цитата Сообщение от fasked Посмотреть сообщение
NeonLost, я может чего не понимаю, но зачем тут вообще синхронизироваться?
не в курсе как в бусте получить возвращаемое значение из функции?..)
0
Jupiter
Каратель
Эксперт С++
6569 / 3990 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
07.01.2013, 12:57 11
Цитата Сообщение от NeonLost Посмотреть сообщение
как в бусте получить возвращаемое значение из функции?..)
передавай его параметром по ссылке в фунцию
1
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
07.01.2013, 13:03  [ТС] 12
Цитата Сообщение от Jupiter Посмотреть сообщение
передавай его параметром по ссылке в фунцию
не понял...(
вот, я хотел вывести единичку...не получается...)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <boost/thread/thread.hpp>
#include <iostream>
#include <future>
using namespace std;
int first() 
{
   return 1;
}
 
int main() 
{
  boost::thread my_thread(&first);
  //auto h1 = my_thread();
  my_thread.join();
  //cout<<h1;
  getchar();
  return 0;
}
0
Jupiter
Каратель
Эксперт С++
6569 / 3990 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
07.01.2013, 13:05 13
Цитата Сообщение от NeonLost Посмотреть сообщение
не понял...(
в изначальном коде, ты mutex передаешь параметром по ссылке, точно так же сделай и для возврата результата
1
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
07.01.2013, 13:20  [ТС] 14
Цитата Сообщение от Jupiter Посмотреть сообщение
в изначальном коде, ты mutex передаешь параметром по ссылке, точно так же сделай и для возврата результата
все понял, спс...)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <boost/thread/thread.hpp>
#include <iostream>
#include <future>
using namespace std;
void first(int &num) 
{
   num=1;
}
 
int main() 
{
  int num;
  boost::thread my_thread(boost::bind(&first, boost::ref(num)));
  my_thread.join();
  cout<<num;
  getchar();
  return 0;
}
Добавлено через 12 минут
ну вот, благодаря всем вам, кзнал много нового...спасибо...)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <boost/thread/thread.hpp>
#include <iostream>
using namespace std;
 
const int n=100000000;
void first(int left, int right, int &count) 
{
   for (int i = left; i < right; i++)
   {
       for (int j = i; j != 0; j /= 10) if (j%10 == 2) count++;      
   }
}
 
int main() 
{
  int one = 0;
  int two = 0;
  boost::thread my_thread(&first, 0, n/2, boost::ref(one));
  boost::thread my_thread2(&first, n/2, n, boost::ref(two));
  my_thread.join();
  my_thread2.join();
  cout<<one+two<<endl;
  getchar();
  return 0;
}
0
fasked
Эксперт С++
4982 / 2561 / 241
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
07.01.2013, 13:26 15
NeonLost, в boost, как ни странно, тоже есть future:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <boost/thread/thread.hpp>
#include <boost/thread/future.hpp>
#include <iostream>
 
int calculate_the_answer_to_life_the_universe_and_everything() 
{
   return 42;
}
 
int main() 
{
    boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
    boost::unique_future<int> fi = pt.get_future();
 
    boost::thread task(boost::move(pt)); // launch task on a thread
    fi.wait(); // wait for it to finish
 
    std::cout << fi.get() << std::endl;
}
2
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
07.01.2013, 16:56  [ТС] 16
еще назрел вопрос...почему на 4 ядерном компе эти 2 кода выдают одинаковую скорость?..)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <future>
#include <iostream>
#include<windows.h>
 
int compute(int left, int right)
{
    int k = 0;
    for (int i = left; i <= right; ++i) 
        for (int j = i; j != 0; j /= 10)
           k += (j % 10 == 2);
 
    return k;
}
 
int main(int argc, char **argv)
{
    int start=GetTickCount();
    int n = 100000000;
    auto h1 = std::async(std::launch::async, compute, 0, n/2);
    auto h2 = std::async(std::launch::async, compute, n/2, n);
    std::cout << "async " << h1.get() + h2.get() << std::endl;
    int end=GetTickCount();
    std::cout<<end-start<<std::endl;
    getchar();
}
и
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <future>
#include <iostream>
#include<windows.h>
 
int compute(int left, int right)
{
    int k = 0;
    for (int i = left; i <= right; ++i) 
        for (int j = i; j != 0; j /= 10)
           k += (j % 10 == 2);
 
    return k;
}
 
int main(int argc, char **argv)
{
    int start=GetTickCount();
    int n = 100000000;
    auto h1 = std::async(std::launch::async, compute, 0, 1*4/n);
    auto h2 = std::async(std::launch::async, compute, 1*4/n, 1/2*n);
    auto h3 = std::async(std::launch::async, compute, 1/2*n, 3/4*n);
    auto h4 = std::async(std::launch::async, compute, 3/4*n, n);
    std::cout << "async " << h1.get() + h2.get()+h3.get()+h4.get() << std::endl;
    int end=GetTickCount();
    std::cout<<end-start<<std::endl;
    getchar();
}
Добавлено через 5 минут
даже скажу, что 2 процесса отрабатывают быстрей...)
0
alex_x_x
бжни
2455 / 1661 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
07.01.2013, 17:30 17
NeonLost, у тебя точно 4 физических ядра? а не 2а + гипертрединг?
0
NeonLost
Пес войны
110 / 87 / 22
Регистрация: 23.02.2012
Сообщений: 653
07.01.2013, 17:43  [ТС] 18
Цитата Сообщение от alex_x_x Посмотреть сообщение
NeonLost, у тебя точно 4 физических ядра? а не 2а + гипертрединг?
ну вот здесь хз...я поверил картинке...)
0
Миниатюры
Объясните нубу про распараллеливание вычислений. thread  
07.01.2013, 17:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.01.2013, 17:43

OpenMP распараллеливание вычислений
Выручите, перепробовал уже с бубном плясать не выходит. Матрицу создаю...

Объясните нубу)
HELP народ, только учусь программировать... вот хочу научится как на...

Распараллеливание сортировки, thread pool
Здравствуйте! Значит задача в том, чтобы распараллелить шейкерную сортировку,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru