多线程矩阵的乘法,禁止不加改动用于课设,仅供参考。
// 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 文件