矩阵乘法的多线程实现(C++语言)

多线程矩阵的乘法,禁止不加改动用于课设,仅供参考。

// multhread_martix_mul.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <thread>
#include "windows.h"
#include <vector>
#include <string>
#include <random>
template <typename T>
class Martix
{
    int p_size;
    std::vector<std::vector<T>> p;

public:
    int get_size() const { return p_size; }
    Martix(const int size)
    {
        std::random_device rd;  // 将用于获得随机数引擎的种子
        std::mt19937 gen(rd()); // 以 rd() 播种的标准 mersenne_twister_engine
        std::uniform_real_distribution<T> dis;//采用默认产生的随机分布范围
        p_size = size;
        p.resize(size + 1);
        for (auto &t : p)
        {
            t.resize(size + 1);
            for (auto &t2 : t)
            {
                t2=dis(gen);
            }
        }
    }
    const T &get_x_y(const int i, const int j) const
    {
        return p[i][j];
    }
    T &get_x_y(const int i, const int j)
    {
        return p[i][j];
    }
    void serial_mul(const Martix<T> &a, const Martix<T> &b)
    {
        for (int i = 1; i <= p_size; ++i)
            for (int j = 1; j <= p_size; ++j)
            {
                p[i][j] = 0;
                for (int k = 1; k <= p_size; ++k)
                    p[i][j] += a.get_x_y(i, k) * b.get_x_y(k, j);
            }
    }
    void accelerate_serial_mul(const Martix<T> &a, const Martix<T> &b)
    {
        for (int i = 1; i <= p_size; ++i)
            for (int j = 1; j <= p_size; ++j)
                p[i][j] = 0;
        for (int i = 1; i <= p_size; ++i)
            for (int k = 1; k <= p_size; ++k)
            {
                for (int j = 1; j <= p_size; ++j)
                    p[i][j] += a.get_x_y(i, k) * b.get_x_y(k, j);
            }
    }
    void line_parall_mul_block(const Martix<T> &a, const Martix<T> &b, const int star, const int end)
    {
        for (int i = star; i <= end; ++i)
            for (int j = 1; j <= p_size; ++j)
            {
                p[i][j] = 0;
                for (int k = 1; k <= p_size; ++k)
                    p[i][j] += a.get_x_y(i, k) * b.get_x_y(k, j);
            }
    }
    void line_parall_mul(const Martix<T> &a, const Martix<T> &b, cosnt int thread_num)
    {
        int cur_star, cur_end;
        int basic;
        std::vector<std::thread> thread_s;
        basic = p_size / thread_num;
        cur_end = 0;                         //线程数为1的情况
        for (int i = 1; i < thread_num; ++i) //前面几个核心是整除
        {
            cur_star = (i - 1) * basic + 1;
            cur_end = cur_star + basic - 1;
            thread_s.push_back(std::thread(&Martix::line_parall_mul_block, this, std::cref(a), std::cref(b), cur_star, cur_end));
        }
        thread_s.push_back(std::thread(&Martix::line_parall_mul_block, this, std::cref(a), std::cref(b), cur_end + 1, p_size)); //最后一个核心是余数
        for (auto &t : thread_s)
            t.join();
    }
    void accelerate_line_parall_mul_block(const Martix<T> &a, const Martix<T> &b, const int star, const int end)
    {
        for (int i = star; i <= end; ++i)
            for (int j = 1; j <= p_size; ++j)
                get_x_y(i, j) = 0;
        for (int i = star; i <= end; ++i)
            for (int k = 1; k <= p_size; ++k)
            {
                for (int j = 1; j <= p_size; ++j)
                    get_x_y(i, j) += a.get_x_y(i, k) * b.get_x_y(k, j);
            }
    }
    void accelerate_line_parall_mul(const Martix<T> &a, const Martix<T> &b, cosnt int thread_num)
    {
        int cur_star, cur_end;
        int basic;
        std::vector<std::thread> thread_s;
        basic = p_size / thread_num;
        cur_end = 0;                         //线程数为1的情况
        for (int i = 1; i < thread_num; ++i) //前面几个核心是整除
        {
            cur_star = (i - 1) * basic + 1;
            cur_end = cur_star + basic - 1;
            thread_s.push_back(std::thread(&Martix::accelerate_line_parall_mul_block, this, std::cref(a), std::cref(b), cur_star, cur_end));
        }
        thread_s.push_back(std::thread(&Martix::accelerate_line_parall_mul_block, this, std::cref(a), std::cref(b), cur_end + 1, p_size)); //最后一个核心是余数
        for (auto &t : thread_s)
            t.join();
    }
    ~Martix() {}
};
int main()
{
    struct
    {
        std::string excute_type;
        int thread_num;
        int spend_time;
    } mini;
    mini.spend_time = INT_MAX;
    mini.thread_num = 0;
    const int size = 6400;
    Martix<double> a(size);
    Martix<double> b(size);
    Martix<double> c(size);
    int star, end;
    /* int thread_num;
    double serial_time;
    double acc_serial_time; */
    std::vector<double> acc_para_time;
    std::cout << "(double)矩阵大小为:" << size << std::endl;
  /*   std::cout << "缓存不友好串行用时(ms):";
    star = clock();
    c.serial_mul(a, b);
    end = clock();
    std::cout << end - star << std::endl;
    serial_time = static_cast<double>(end - star);
    std::cout<<"系统暂停60S"<<std::endl;
    Sleep(1000);//防止上一次运算对下一次运算造成干扰,同时将资源监视器中的平均CPU使用率影响清除,同时将资源监视器中的平均CPU使用率影响清楚
    if (end - star < mini.spend_time)
    {
        mini.excute_type = "串行";
        mini.spend_time = end - star;
        mini.thread_num = 1;
    }
    std::cout << "缓存不友好并行用时(ms):" << std::endl;
    SYSTEM_INFO SysInfo;
    GetSystemInfo(&SysInfo);
    thread_num = SysInfo.dwNumberOfProcessors;
    acc_para_time.reserve(thread_num);
    for (int i = 1; i <= thread_num; ++i)
    {
        std::cout << "线程数为:" << i << "用时为:";
        star = clock();
        c.line_parall_mul(a, b, i);
        end = clock();
        std::cout << end - star << std::endl;
        if (end - star < mini.spend_time)
        {
            mini.excute_type = "缓存不友好";
            mini.spend_time = end - star;
            mini.thread_num = i;
        }
        std::cout<<"系统暂停60S"<<std::endl;
        Sleep(1000);//防止上一次运算对下一次运算造成干扰,同时将资源监视器中的平均CPU使用率影响清除
    } */
   /* std::cout << "缓存友好串行用时(ms):";
    star = clock();
    c.accelerate_serial_mul(a, b);
    end = clock();
     std::cout << end - star << std::endl;
    acc_serial_time = static_cast<double>(end - star);
    if (end - star < mini.spend_time)
    {
        mini.excute_type = "缓存友好串行";
        mini.spend_time = end - star;
        mini.thread_num = 1;
    }
     std::cout<<"系统暂停60S"<<std::endl;
    Sleep(60000);//防止上一次运算对下一次运算造成干扰,同时将资源监视器中的平均CPU使用率影响清除
    std::cout << "缓存友好并行用时(ms):" << std::endl; */
    for (int i = 1; i <= 8; ++i)
    {
        std::cout << "线程数为:" << i << "用时为:";
        star = clock();
        c.accelerate_line_parall_mul(a, b, i);
        i+=6;
        end = clock();
        std::cout << end - star << std::endl;
        acc_para_time.push_back(static_cast<double>(end - star));
        if (end - star < mini.spend_time)
        {
            mini.excute_type = "缓存友好";
            mini.spend_time = end - star;
            mini.thread_num = i;
        }
         std::cout<<"系统暂停60S"<<std::endl;
         Sleep(60000);//防止上一次运算对下一次运算造成干扰,同时将资源监视器中的平均CPU使用率影响清除
    }
   /*  std::cout << "最少用时(ms):" << mini.spend_time << std::endl;
    std::cout << "此时线程数为:" << mini.thread_num << std::endl;
    std::cout << "此时采用计算策略为:" << mini.excute_type << std::endl;
    std::cout << "串行情况下缓存不友好与友好时间之比为" << serial_time / acc_serial_time << std::endl;
    std::cout << "在不同线程数加速情况下,串行(缓存友好)与并行(缓存友好)时间之比依(线程数从小到大)为:" << std::endl;
    for (auto const t : acc_para_time)
        std::cout << acc_serial_time / t << std::endl; */
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示:
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值