书接上文,我们提到了串行算法的矩阵转置
接下来我们来看一看如何用并行程序来对矩阵进行转置,想法有两个,这里先介绍第一种,块棋盘划分法。
Q:那么什么是块棋盘划分法呢?
A:yo~ yo~你看这个矩阵他又长又宽,就像这个棋盘他又大又方
(吴亦凡先生因言语激烈被踢出聊天室)
说实话这个yoyo让我想起了藤原书记。。。
没错,我们想想,这n*n的矩阵,确实是像个棋盘,那我们想到了,可以把他拆分成一个一个子块,然后子块之间先转换,然后子块内部自己再转置,这岂不是妙哉?!
那么我们一起来看看程序吧!
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "unistd.h"
int **matrix;//矩阵
int **tmp;
int T,n;//线程个数,矩阵维数
void init(){
matrix = (int **)malloc(n * sizeof(int *));
tmp = (int **)malloc(n * sizeof(int *));
for(int i=0;i<n;i++){
matrix[i] = (int *)malloc(n * sizeof(int));
tmp[i] = (int *)malloc(n * sizeof(int));
}
//如果想自己赋值,下面这个可以忽略
int cnt = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
matrix[i][j] = tmp[i][j] = cnt;
cnt++;
}
}
}
void *thread_function(void *arg){
int rank = *(int *)arg;
int u = rank / sqrt((double)T);
int v = rank % (int)sqrt((double)T);
//这里我偷了个懒,直接一起进行子块转换与内部转置
int m = sqrt((double)(n*n/T));
for(int i=u*m;i<(u+1)*m;i++){
for(int j=v*m;j<(v+1)*m;j++){
matrix[i][j] = tmp[j][i];
}
}
return NULL;
}
void free(int n){
free(matrix);
}
void print(int n){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(int argc, const char * argv[]) {
n = 10;//atoi(argv[1]);
T = 4;//atoi(argv[2]);
init();
int x[T];
pthread_t thread[T];
for(int i=0;i<T;i++){
x[i] = i;
pthread_create(&thread[i], NULL, thread_function, &x[i]);
}
for(int i=0;i<T;i++){
pthread_join(thread[i], NULL);
}
print(n);
return 0;
}
结果如下,
0 10 20 30 40 50 60 70 80 90
1 11 21 31 41 51 61 71 81 91
2 12 22 32 42 52 62 72 82 92
3 13 23 33 43 53 63 73 83 93
4 14 24 34 44 54 64 74 84 94
5 15 25 35 45 55 65 75 85 95
6 16 26 36 46 56 66 76 86 96
7 17 27 37 47 57 67 77 87 97
8 18 28 38 48 58 68 78 88 98
9 19 29 39 49 59 69 79 89 99
好了,这样我们就完成了对矩阵的转置了。
希望大家不吝赐教,共同进步。