Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 26.05.2016
Сообщений: 32
1

Распараллеливание

09.12.2021, 22:12. Показов 958. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Помогите найти ошибку. Разный ответ при 1 и 4 потоках.
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
#include <iostream>
#include <cmath>
#include <ostream>
#include <cstdlib>
#include <Windows.h>
#include <conio.h>
#include <stdlib.h>
#include "omp.h"
#include <ctime>
#include <random>
using namespace std;
int main(){
    setlocale(0, "");
    srand(time(NULL));
    random_device rd;
    default_random_engine gener(rd());
    uniform_real_distribution<double> distr(-2, 2);
    int P;
    cout << "Количество потоков: P=  "; cin >> P;
    double x, y, z, V=0, V1=0;
    int n = 1000000;
    int num, i;
    int ch = n / (10 * P);
    float fTimeStart1 = clock() / (float)CLOCKS_PER_SEC;
#pragma omp parallel num_threads(P) private(i) reduction(+:V1){
        num = omp_get_thread_num();
 
#pragma omp for schedule(dynamic,ch)
        for (i = 0; i <= n; i++){
            x = distr(gener);
            y = distr(gener);
            z = distr(gener);
            if (x * x + y * y + z * z <= 4.0 && (x <= 0.0 || x >= 0.1) && (y <= 0.0 || y >= 0.1))
                V++;
            V1 = V / n;
        }
    }
    float fTimeStop = clock() / (float)CLOCKS_PER_SEC;
    printf("Время решения %f с.\n", fTimeStop - fTimeStart1);
    cout << "Result = " << V1;
    system("pause");
    return 0;
}
Примерно должно быть 1.82
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.12.2021, 22:12
Ответы с готовыми решениями:

Распараллеливание
Всем добрый вечер. Если кто знает подскажите,мне надо распараллелить перемножение...

распараллеливание
Скажите, кто-нибудь занимался распараллеливанием в си++? В моих попытках что-либо распараллелить...

Распараллеливание
Подскажите, что не так. Есть массив из 13 элементов, мне нужно разбить на три блока, один блок...

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

10
7790 / 6557 / 2984
Регистрация: 14.04.2014
Сообщений: 28,667
09.12.2021, 22:20 2
Почему именно это число? Ты же случайные берёшь.
0
0 / 0 / 0
Регистрация: 26.05.2016
Сообщений: 32
10.12.2021, 00:52  [ТС] 3
Число берётся с решения двойного интеграл sqrt(4-x*x-y*y)dxdy где х и у от 0 до 1
0
7790 / 6557 / 2984
Регистрация: 14.04.2014
Сообщений: 28,667
10.12.2021, 01:13 4
Может, дело в обращении к distr()? Пробовал с std::thread то же самое сделать?
0
693 / 303 / 99
Регистрация: 04.07.2014
Сообщений: 846
13.12.2021, 15:54 5
1. reduction(+:V1) и V1 = V / n, это не правильно. В цикле считаем V, по не муже делаем редукцию, и только после параллельной секции надо делить.

2. У тебя distr и gener - общие ресурсы для нескольких протоков. Так нельзя. Нужно для каждого OMP потока завести свои.

C++
1
2
3
4
5
6
7
8
9
10
11
12
#pragma omp parallel ...
{
    random_device rd;
    default_random_engine gener(rd());
    uniform_real_distribution<double> distr(-2, 2);
 
    // ...
    #pragma omp for
    for(....) {
        // ... distr(gener)
    }
}
0
0 / 0 / 0
Регистрация: 26.05.2016
Сообщений: 32
15.12.2021, 15:51  [ТС] 6
Цитата Сообщение от AlexVRud Посмотреть сообщение
Нужно для каждого OMP потока завести свои.
Не совсем понял, должно выглядеть как-то так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma omp parallel num_threads(P) private(x,y,z,i) reduction(+: V)
    {
        random_device rd;
        default_random_engine gener(rd());
        uniform_real_distribution<double> distr(-2, 2);
        num = omp_get_thread_num();
#pragma omp for schedule(dynamic,ch)
        for (i = 0; i <= n; i++)
        {
            x = distr(gener);
            y = distr(gener);
            z = distr(gener);
            if (x * x + y * y + z * z <= 4.0 && (x <= 0.0 || x >= 0.1) && (y <= 0.0 || y >= 0.1))
            V++;    
        }
        V = V / n;
    }
0
693 / 303 / 99
Регистрация: 04.07.2014
Сообщений: 846
16.12.2021, 15:21 7
Anyeple, Следующие рекомендации:
  • Используйте правильные целочисленные типы (знаковые/беззнаковые, размер, а то в параллельном программировании могут быть числа больше чем может представить int).
  • Не используйте double как счётчик (однажды будет x==x+1).
  • Объявляете типы максимально близко к их месту использования (в openMP это позволяет не писать лишний раз public/private).
  • Оформляйте задачи как функции с входными параметрами, тогда будет проще их проверять.
  • Осмысленные имена переменных помогут другим понять ваш код.


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
#include <iostream>
#include <random>
 
#include <omp.h>
 
double calculate_figure_volume(uint64_t n_points, int n_threads)
{
    uint64_t k_points = 0;
    #pragma omp parallel num_threads(n_threads) reduction(+ : k_points)
    {
        std::random_device                     rd;
        std::default_random_engine             gener(rd());
        std::uniform_real_distribution<double> distr(-2.0, 2.0);
 
        #pragma omp for
        for (uint64_t i = 0; i < n_points; i++) {
            double x = distr(gener);
            double y = distr(gener);
            double z = distr(gener);
            if ((x * x + y * y + z * z <= 4.0) &&
                (x <= 0.0 || x >= 0.1) &&
                (y <= 0.0 || y >= 0.1))
                k_points++;
        }
    }
    return (4.0 * 4.0 * 4.0) * (double)k_points / (double)n_points;
}
 
int main()
{
    std::cout << "threads\tv\ttime\n";
    uint64_t n_points = 100'000'000ull;
    for (int n_threads = 1; n_threads <= 8; n_threads++) {
        double t_start = omp_get_wtime();
        double v       = calculate_figure_volume(n_points, n_threads);
        double t_end   = omp_get_wtime();
 
    std::cout << n_threads << "\t"
          << v << "\t"
          << (t_end - t_start) << "\n";
    }
    return 0;
}
0
0 / 0 / 0
Регистрация: 26.05.2016
Сообщений: 32
16.12.2021, 18:04  [ТС] 8
Цитата Сообщение от AlexVRud Посмотреть сообщение
return (4.0 * 4.0 * 4.0) * (double)k_points / (double)n_points;
Зачем вы тут умножаете на 64? Ответ должен быть схож с интегралом sqrt(4-x*x-y*y)dxdy, где х и у от 0 до 1.
Я нахожу объем фигуры х2+у2+z2=4 на квадрате [0,1]x[0,1], т.е. (x * x + y * y + z * z <= 4.0) &&(x <= 0.0 || x >= 0.1) && (y <= 0.0 || y >= 0.1).
0
693 / 303 / 99
Регистрация: 04.07.2014
Сообщений: 846
18.12.2021, 23:04 9
Цитата Сообщение от Anyeple Посмотреть сообщение
Я нахожу объем фигуры х2+у2+z2=4 на квадрате [0,1]x[0,1], т.е. (x * x + y * y + z * z <= 4.0) &&(x <= 0.0 || x >= 0.1) && (y <= 0.0 || y >= 0.1).
Совершенно не верное утверждение.

Что было у тебя в коде:

* Берутся случайные точки из куба [-2;2]x[-2;2]x[-2;2] и проверяются на условие (x * x + y * y + z * z <= 4.0) &&(x <= 0.0 || x >= 0.1) && (y <= 0.0 || y >= 0.1). Т.е. точка должна попасть в шар радиуса 2 и у неё https://www.cyberforum.ru/cgi-bin/latex.cgi?x \notin (0;0,1), https://www.cyberforum.ru/cgi-bin/latex.cgi?y \notin (0;0,1). Это явно не то, что ты ищешь.

Зачем вы тут умножаете на 64?
Это объём куба [-2;2]x[-2;2]x[-2;2]. Весь смысл в том, что пусть есть некая фигура заключённая в куб. Объём фигуры пусть будет https://www.cyberforum.ru/cgi-bin/latex.cgi?V_{fig}, а объём куба https://www.cyberforum.ru/cgi-bin/latex.cgi?V_{cube}. Выберем https://www.cyberforum.ru/cgi-bin/latex.cgi?n случайных точек из куба. И пусть https://www.cyberforum.ru/cgi-bin/latex.cgi?k из этих точек попадут в фигуру. Тогда

https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{V_{fig}}{V_{cube}} \approx \frac{k}{n}

или

https://www.cyberforum.ru/cgi-bin/latex.cgi?V_{fig} \approx V_{cube}\frac{k}{n}

Если вам надо найти Массив: Вычислить объем фигуры, ограниченной поверхностью х2+у2+z2=4 то возьмите точку из [0;1]x[0;1]x[0;2] и проверьте что она попала в шар.
0
0 / 0 / 0
Регистрация: 26.05.2016
Сообщений: 32
19.12.2021, 18:26  [ТС] 10
Цитата Сообщение от AlexVRud Посмотреть сообщение
Совершенно не верное утверждение.
т.е. то что в коде и то что в задании не как не связанно -.- Спасибо за разъяснение.
Как понял это условие (x * x + y * y + z * z <= 4.0) &&(x <= 0.0 || x >= 0.1) && (y <= 0.0 || y >= 0.1) с фигурой которую надо найти не как не связанно. На рисунке попытался изобразить верхнюю часть того что надо.
Миниатюры
Распараллеливание  
0
693 / 303 / 99
Регистрация: 04.07.2014
Сообщений: 846
19.12.2021, 20:51 11
Anyeple, А в чём проблема? Берёте область для случайных точек [0;1]x[0;1]x[0;2] и проверяете что попали в шар. Исправить код не должно быть затруднений.
0
19.12.2021, 20:51
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.12.2021, 20:51
Помогаю со студенческими работами здесь

Странное распараллеливание
Добрый вечер, коллеги. У меня следующая проблема. Преподаватель сказал распараллелить программу,...

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

Распараллеливание программы
Помогите эту последовательную программу распараллелить на параллельных 2 процесса. #include...

Распараллеливание циклов
Есть такой цикл std::list&lt;int&gt;::iterator iter; std::list&lt;int&gt;_paramsFFT; for(iter =...

Распараллеливание цикла
есть цикл for (unsigned n = 0; n &lt; threads; n++) { func (sigma, sub_noisy, sub_basic,...

Распараллеливание циклов
Доброго времени суток. Возникла необходимость распараллелить один численный алгоритм средствами...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru