博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程之多核线上考试试题瞎解
阅读量:3934 次
发布时间:2019-05-23

本文共 5286 字,大约阅读时间需要 17 分钟。

匆忙的大三早已结束,时隔两月,再以此文祭奠我炸掉的多核考试

这次考试真正能写出来的也就两道题,以下简单地记录一下。

第二题

随机产生2个10*10的浮点数矩阵A和B,先将矩阵A和B作转置,然后再相乘,请用windows 多线程函数方法和openMP方式分别编写实现上述运算的C语言并行实现程序,要求显示矩阵A和B,以及最终的运算结果。

题目涉及到矩阵转置和相乘两个主要内容,在编程时,我只对矩阵相乘进行openmp和多线程并行处理。

本题中,假设 A 、 B A、B AB均为 N × N N\times N N×N矩阵,令 C = A B C=AB C=AB,则矩阵 C C C i i i行第 j j j列原始可表示为:

C i j = ∑ k = 1 N a i k b k j = a i 1 b 1 j + a i 2 b 2 j + ⋯ + a i N b N j C_{ij}=\sum_{k=1}^Na_{ik}b_{kj}=a_{i1}b_{1j}+a_{i2}b_{2j}+\cdots +a_{iN}b_{Nj} Cij=k=1Naikbkj=ai1b1j+ai2b2j++aiNbNj
所以为了计算 A A A B B B相乘结果,需要三层循环,最内层计算 C C C中单个元素的值,第二层计算 C C C中单行元素的值,最外层计算整个矩阵 C C C的值。

为了减少线程开销,我们只对最外层循环进行并行处理,即每个线程计算一行相乘的结果。完整程序如下:

#include
#include
#include
#include "omp.h"using namespace std;#define N 10 // 矩阵维数// 计算一行矩阵相乘结果的线程函数void func(const double* a, const double* b, double* result, int i){
// a:矩阵a的首地址 // b:矩阵b的首地址 // result:结果矩阵的第i行首地址 // i:待计算的行号 for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) {
result[j] += a[i * N + k] * b[k * N + j]; } }}int main(){
double a[N][N] = {
{
0} }; // 矩阵a double b[N][N] = {
{
0} }; // 矩阵b double result_omp[N][N] = {
{
0} }; // 保存openmp计算结果 double result_multithread[N][N] = {
{
0} }; // 保存多线程计算结果 // 产生随机双精度矩阵 for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
a[i][j] = (double)(rand() % 100) / 100; b[i][j] = (double)(rand() % 100) / 100; } } // 打印转置前的矩阵a、b cout << "----------------------------" << endl; cout << "转置前a" << endl; for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%5.3lf ", a[i][j]); } cout << endl; } cout << "----------------------------" << endl; cout << "转置前b" << endl; for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%5.3lf ", b[i][j]); } cout << endl; } //--------- 转置 --------- for (int i = 0; i < N; i++) {
for (int j = i; j < N; j++) {
double at = a[i][j]; double bt = b[i][j]; a[i][j] = a[j][i]; b[i][j] = b[j][i]; a[j][i] = at; b[j][i] = bt; } } // 打印转置后的矩阵a、b cout << "----------------------------" << endl; cout << "转置后a" << endl; for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%5.3lf ", a[i][j]); } cout << endl; } cout << "----------------------------" << endl; cout << "转置后b" << endl; for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%5.3lf ", b[i][j]); } cout << endl; } //--------- 矩阵相乘 --------- // OMP方法#pragma omp parallel for for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) result_omp[i][j] += a[i][k] * b[k][j]; } } // 多线程方法 double* aa = a[0]; // 指向矩阵a首地址的指针 double* bb = b[0]; // 指向矩阵b首地址的指针 thread t[N]; for (int i = 0; i < N; i++) {
// 一个线程计算一行结果,共有N个线程 t[i] = thread(func, aa, bb, result_multithread[i], i); } // 等待线程结束 for (int i = 0; i < N; i++) {
t[i].join(); } // 打印OMP计算结果 cout << "----------------------------" << endl; cout << "omp计算结果:" << endl; for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%5.3lf ", result_omp[i][j]); } cout << endl; } // 打印多线程计算结果 cout << "----------------------------" << endl; cout << "multi thread计算结果:" << endl; for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%5.3lf ", result_multithread[i][j]); } cout << endl; } return 0;}

运行结果如下:

01

第三题

某停车场有100个停车位,共有3个入口,2个出口。剩余车位数量需要实时提供给各个出入口。请设计一个管理程序,要求使用多线程编程,每进入或驶出一辆车,在屏幕上输出当前空余的车位,如果没有剩余车位了,就要限制车辆进入该停车场。

这道题我感觉做复杂了,用到了C++11里的条件变量和互斥锁,设置两个条件变量,一个用于判断是否能够进入停车场,另一个用于判断是否能驶出停车场。

#include
#include
#include
#include
using namespace std;// 停车场的最大车位数量#define PAKING_SPACE_MAX 100// 入口数量#define NUM_ENTER 3// 出口数量#define NUM_GO_OUT 2// 线程中的循环次数,此时设置为100次// 这样总共驶出次数为200次,进入次数为300次,最终停车场剩余车位应该为零#define FOR_NUM 100 int parkingspace = PAKING_SPACE_MAX; // 当前停车位数量mutex m;condition_variable cv1; // 进入操作的条件变量condition_variable cv2; // 驶出操作的条件变量// 车辆进入的线程函数void t_enter(void){
// 循环进入100辆车 for (int i = 0; i < FOR_NUM; i++) {
unique_lock
mylock(m); // 剩余车位数为0,表明停车场满了 if (parkingspace <= 0) cv1.wait(mylock); // 不允许车进入,让他们在外面等 parkingspace--; cout << "进入一辆车,剩余车位:" << parkingspace << endl; // 唤醒一个在等待中的线程,表示现在有车可以出去 cv2.notify_one(); // 延时100ms this_thread::sleep_for(chrono::milliseconds(100)); }}// 车辆驶出的线程函数void t_go_out(void){
// 循环驶出100辆车 for (int i = 0; i < FOR_NUM; i++) {
unique_lock
mylock(m); // 如果剩余车位数大于或者等于最大车位数量,则说明停车场是空的 if (parkingspace >= PAKING_SPACE_MAX) cv2.wait(mylock); // 此时没有车辆,阻塞这个驶出线程 parkingspace++; cout << "驶出一辆车,剩余车位:" << parkingspace << endl; // 唤醒一个在等待中的进入线程,表明有空车位,可以进入 cv1.notify_one(); // 延时100ms this_thread::sleep_for(chrono::milliseconds(100)); }}int main(){ thread t1[NUM_ENTER]; // 模拟三个入口 thread t2[NUM_GO_OUT]; // 模拟两个出口 /* 开启三个入口线程*/ for (int i = 0; i < NUM_ENTER; i++) { t1[i] = thread(t_enter); } /* 开启两个出口线程 */ for (int i = 0; i < NUM_GO_OUT; i++) { t2[i] = thread(t_go_out); } /* 等待所有入口线程执行完毕 */ for (int i = 0; i < NUM_ENTER; i++) { t1[i].join(); } /* 等待所有出口线程执行完毕 */ for (int i = 0; i < NUM_GO_OUT; i++) { t2[i].join(); }}

结果如下:

02

转载地址:http://umvgn.baihongyu.com/

你可能感兴趣的文章
项目沟通管理
查看>>
项目风险管理
查看>>
项目采购管理
查看>>
合同管理
查看>>
配置管理
查看>>
外包管理
查看>>
需求管理
查看>>
项目管理师职业道德规范
查看>>
组织级项目管理与大型项目管理
查看>>
战略管理概述
查看>>
业务流程管理和重组
查看>>
知识管理
查看>>
项目整体绩效评估
查看>>
信息安全系统和安全体系
查看>>
信息系统安全风险识别与评估
查看>>
安全策略
查看>>
信息安全技术基础
查看>>
PKI公开密钥基础设施
查看>>
PMI权限(授权)管理基础设施
查看>>
信息安全审计系统S-Audit
查看>>