многопоточность — ошибка преобразования примера pi в многопоточность для увеличения скорости в переполнении стека

Мне нужно преобразовать эту программу, которая выполняет итерацию, разделить шаги итерации на 4 потока. Если итерация равна n, тогда я выполняю ее, используя 4 потока. Работа программы занимает в среднем 4,7 с. Сумма доступна для всех 4 потоков, и при обновлении возникает проблема. Я получаю 1.5 в качестве ответа вместо 3.1457 для значения pi. Также многопоточность не уменьшает время. пожалуйста, помогите мне

#include "stdafx.h"#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
//std::mutex m;
long num_rects = 100000000;

struct params
{
int start;
int end;
double mid;
double height;
double width;
params(int st,int en)
{
start = st;
end = en;
width = 1.0 / (double)num_rects;
}

};

double sum = 0.0;void sub1(params param){

for (int i = param.start; i < param.end; i++)
{
param.mid = (i + 0.5)*param.width;
param.height = 4.0 / (1.0 + param.mid*param.mid);

//m.lock();
sum += param.height;
//m.unlock();
}
}int _tmain(int argc, _TCHAR* argv[])
{
int i;
double mid, height, width;
double area;

auto begin = std::chrono::high_resolution_clock::now();
params par(0, num_rects / 4);
std::thread t(sub1, par);

params par1(num_rects / 4, num_rects / 2);
std::thread t1(sub1, par1);

params par2(num_rects / 2, (num_rects *3)/ 4);
std::thread t2(sub1, par2);

params par3((num_rects * 3) / 4, num_rects );
std::thread t3(sub1, par3);

t.join();
t1.join();
t2.join();
t3.join();

/*
sub1(par);
sub1(par1);
sub1(par2);
sub1(par3);
*/width = 1.0 / (double)num_rects;
area = sum*width;
std::cout << area << std::endl;
auto end = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << "ms" << std::endl;
std::cin.get();
return 0;
}

-1

Решение

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

Это изменение должно работать.

double sub1(params param){
double sum = 0.0; // thread local

for (int i = param.start; i < param.end; i++)
{
param.mid = (i + 0.5)*param.width;
param.height = 4.0 / (1.0 + param.mid*param.mid);

sum += param.height;
}
return sum;
}

#include <future>
int SubMain() {
int i;
double mid, height, width;
double area;

auto begin = std::chrono::high_resolution_clock::now();
params par(0, num_rects / 4);
std::future<double> fut1 = std::async (sub1, par);

params par1(num_rects / 4, num_rects / 2);
std::future<double> fut2 = std::async (sub1, par1);

params par2(num_rects / 2, (num_rects *3)/ 4);
std::future<double> fut3 = std::async (sub1, par2);

params par3((num_rects * 3) / 4, num_rects );
std::future<double> fut4 = std::async (sub1, par3);

sum = fut1.get() + fut2.get() + fut3.get() + fut4.get();

width = 1.0 / (double)num_rects;
area = sum*width;
std::cout << area << std::endl;
auto end = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << "ms" << std::endl;
std::cin.get();
return 0;
}
0

Другие решения

внес некоторые изменения в код Сурта, это финальная оптимизированная версия

double sub1(params param){
double sum = 0.0; // thread local

for (int i = param.start; i < param.end; i++)
{
param.mid = (i + 0.5)*param.width;
param.height = 4.0 / (1.0 + param.mid*param.mid);

sum += param.height;
}
return sum;
}

#include <future>
#include <vector>
int SubMain() {
int i;
double mid, height, width;
double area;

auto begin = std::chrono::high_resolution_clock::now();

std::vector<std::future<double>> futures;
double k = 0;
for (int j = 0; j < 4; j++)
{

params par(num_rects *k, num_rects *(k + 0.25));
k += 0.25;
futures.push_back(std::async(sub1, par));

}

for (std::vector<std::future<double>> ::iterator it = futures.begin(); it != futures.end(); it++)
{
sum += it->get();
}

/*  params par(0, num_rects / 4);
std::future<double> fut1 = std::async(sub1, par);

params par1(num_rects / 4, num_rects / 2);
std::future<double> fut2 = std::async(sub1, par1);

params par2(num_rects / 2, (num_rects * 3) / 4);
std::future<double> fut3 = std::async(sub1, par2);

params par3((num_rects * 3) / 4, num_rects);
std::future<double> fut4 = std::async(sub1, par3);

sum = fut1.get() + fut2.get() + fut3.get() + fut4.get();*/width = 1.0 / (double)num_rects;
area = sum*width;
std::cout << area << std::endl;
auto end = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << "ms" << std::endl;
std::cin.get();
return 0;
}
0

По вопросам рекламы [email protected]