-
Notifications
You must be signed in to change notification settings - Fork 0
/
MatrixOperation.cs
165 lines (153 loc) · 5.51 KB
/
MatrixOperation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace NN_BP
{
class MatrixOperation
{
private double[,] m_leftMatrix = null;
private double[,] m_rightMatrix=null;
private double[,] m_Result=null;
public static int THREAD_NUM = 64;
private int m_threadFinishedNum = 0;
private class MultiplyParameter
{
public int r_colStart;
public int r_colEnd;
public int l_rowStart;
public int l_rowEnd;
public MultiplyParameter(int leftRowStart, int leftRowEnd, int rightColStart, int rightColEnd)
{
r_colStart = rightColStart;
r_colEnd = rightColEnd;
l_rowStart = leftRowStart;
l_rowEnd = leftRowEnd;
}
}
public MatrixOperation(double [,]left,double[,] right)
{
m_leftMatrix=left;
m_rightMatrix=right;
}
public static void SetThreadNum(int num)
{
THREAD_NUM = num;
}
private double Sigmoid(double a)
{
return 1.0 / (1 + Math.Exp(-a));
}
private void MultiplyMatrix(Object obj)
{
MultiplyParameter p=(MultiplyParameter) obj;
int lrowEnd = p.l_rowEnd;
int lrowStart = p.l_rowStart;
int rcolEnd = p.r_colEnd;
int rcolStart = p.r_colStart;
int dim = m_leftMatrix.GetLength(1);
for (int i = lrowStart; i < lrowEnd; ++i)
{
for (int j = rcolStart; j < rcolEnd; ++j)
{
double temp = 0.0;
for (int k = 0; k < dim; ++k)
{
temp += m_leftMatrix[i, k] * m_rightMatrix[k, j];
}
// m_Result[i, j] = Sigmoid(temp); //如果不需要对每一个矩阵元素进行任何操作,则把这个Sigmoid(temp)换成temp直接赋值
m_Result[i, j] = temp;
}
}
lock(this){
++m_threadFinishedNum;
}
}
public void MultiplyMatrixMultiThread()
{
Array.Clear(m_Result, 0, m_Result.Length);
int lRow = m_leftMatrix.GetLength(0);
int lCol = m_leftMatrix.GetLength(1);
int rRow = m_rightMatrix.GetLength(0);
int rCol = m_rightMatrix.GetLength(1);
double[,] R = new double[lRow, rCol];
bool splitLeftFlag = true;//按照左边的分割(当然这个得看左边矩阵的行数多,还是右边矩阵的列数多了)
if (rCol > lRow)
{
splitLeftFlag = false;
}
m_threadFinishedNum = 0;
int totalThread=0;
if (splitLeftFlag)//按行分割左边的矩阵
{
if (lRow < THREAD_NUM)
{
totalThread = lRow;
}
else
{
totalThread = THREAD_NUM;
}
int rowsPerThread = lRow / totalThread;
int rowsNotAssign = lRow % totalThread;
int row_start = 0;
int row_end=0;
for (int i = 0; i < totalThread; ++i)
{
row_end = row_start + rowsPerThread;
if (rowsNotAssign > 0)
{
++row_end;
--rowsNotAssign;
}
MultiplyParameter p = new MultiplyParameter(row_start, row_end, 0, rCol);
Thread thread = new Thread(new ParameterizedThreadStart(MultiplyMatrix));
row_start = row_end;
thread.Start(p);
}
}
else //按列分割右边的矩阵
{
if (rCol < THREAD_NUM)
{
totalThread = rCol;
}
else
{
totalThread = THREAD_NUM;
}
int colsPerThread = rCol / totalThread;
int colsNotAssign = rCol % totalThread;
int col_start = 0;
int col_end = 0;
for (int i = 0; i < totalThread; ++i)
{
col_end = col_start + colsPerThread;
if (colsNotAssign > 0)
{
++col_end;
--colsNotAssign;
}
MultiplyParameter p= new MultiplyParameter(0, lRow, col_start, col_end);
Thread thread = new Thread(new ParameterizedThreadStart(MultiplyMatrix));
col_start = col_end;
thread.Start(p);
}
}
while (m_threadFinishedNum!=totalThread)//直到所有的线程都完成了自己的操作
{
Thread.Sleep(10);
}
}
public double[,] GetResultMatrix()
{
return this.m_Result;
}
public void SetResultMatrix(ref double[,] result)
{
this.m_Result = result;
}
}
}