转载自我的博客园:https://www.cnblogs.com/xiao-qi-w/p/13155406.html
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程题,居然还涉及到多线程了,而且是调用Windows接口函数写多线程。虽然学汇编的时候有所了解,但毕竟没尝试过,思来想去,写出了下面的蹩脚代码,不足之处还望各位批评指正。题目描述如下:
采用windows接口函数,编写一个计算矩阵向量相乘的并行程序,矩阵按行划分后分别散发到不同的线程中,向量被复制到各个线程中,程序执行结束时,由主线程输出结果向量。假设矩阵定义为浮点型数组A[64][64],向量定义为浮点型数组y[64],结果向量存放到浮点型数组z[64]中,所用处理器有8个计算核。
开始分析:如果把矩阵按行分配给不同线程的话,很明显每个线程应该被分配八行。由于对不同行的矩阵进行操作不会发生冲突,所以连线程的同步机制都用不到,就是简单的编写一个计算矩阵向量相乘的线程函数,然后创建多个线程执行就可以了。代码实现如下:
#include <windows.h>
#include <stdio.h>
double z[64]; //结果向量
double y[64]; //待乘向量
double A[64][64];//待乘矩阵
const int numThreads = 8;//线程数
DWORD WINAPI threadFunction(LPVOID pArg) {
int myNum = *((int *)pArg); //获取本线程所需参数
int n = myNum + 8; //设置外层循环上界
for(int i = myNum; i < n; ++i){//相乘计算的具体步骤
for(int j = 0; j < 64; ++j)
z[i] += A[i][j] * y[i];
}
return 0;
}
int main() {
HANDLE threadHandles[numThreads];//线程数组
int tNum[numThreads];//用于传给线程的参数数组
printf("请输入矩阵:\n");
for(int i = 0; i < 64; ++i)
for(int j = 0; j < 64; ++j)
scanf("%lf", &A[i][j]);
printf("请输入向量:\n");
for(int i = 0; i < 64; ++i)
scanf("%lf", &y[i]);
printf("相乘后的结果向量为: \n");
for(int i = 0; i < numThreads; ++i) {
tNum[i] = i * 8; //给传给线程的参数赋值
threadHandles[i] = CreateThread( NULL, // 安全属性
0, // 栈大小
threadFunction, // 传给线程的函数
(LPVOID)&tNum[i],// 传给线程的参数
0, // 线程创建后立即激活
NULL); // 新线程的id会被传给这个参数所在的变量
}
WaitForMultipleObjects( numThreads, // 等待的线程数
threadHandles, // 等待的线程数组
TRUE, // 等待所有信号量有效在往下执行
INFINITE); // 表示无穷等待
for(int i = 0; i < 64; ++i) //输出结果向量
printf("%.2lf ", z[i]);
return 0;
}
至此,已经解决问题了。还好题目要求不是特别难,也算是通过一段代码初步了解如何使用Windows接口函数编写多线程了。不得不说C语言确实强大,可惜我基础不扎实加上现在又忘得差不多了,写这段代码时居然想通过scanf("%f",&变量名)来输入double类型的值,迟迟得不到预期结果。我还以为是多线程惹的祸,得亏调试了一下才知道原来我连值都没有正确输进去,double类型的输入格式必须是%lf,输出的话%f和%lf均可,学到了学到了。只有犯错了才能学的更透彻啊😭