-1

我需要转换这个运行迭代的程序,将迭代步骤分成 4 个线程。如果迭代为 n,那么我使用 4 个线程执行它。该程序平均需要 4.7 秒才能运行。所有 4 个线程都可以访问总和,并且在更新时存在问题。对于 pi 的值,我得到 1.5 而不是 3.1457 作为答案。线程也不会减少时间。请帮我

#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;
}
4

2 回答 2

0

对 surt 的代码进行了一些修改,这是最终的优化版本

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;
    }
于 2014-09-12T17:55:07.200 回答
0

您正在遭受写入 sum 的竞争条件,因此 2 个线程可以用不同的值覆盖 sum,然后更新的值被覆盖。

这种改变应该奏效。

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;
}
于 2014-09-12T16:07:38.873 回答