Java 如何并行化高斯消去算法?
我的任务是并行化这个算法:Java 如何并行化高斯消去算法?,java,c,multithreading,pthreads,gaussian,Java,C,Multithreading,Pthreads,Gaussian,我的任务是并行化这个算法: public long GEAlgorithmSequential() { long begin = System.nanoTime(); for (int row = 0; row < size; row++) { double value = matrix[row][row]; for (int col = row + 1; col < size; col++) { matrix
public long GEAlgorithmSequential() {
long begin = System.nanoTime();
for (int row = 0; row < size; row++) {
double value = matrix[row][row];
for (int col = row + 1; col < size; col++) {
matrix[row][col] /= value;
}
solutionVector[row] /= value;
matrix[row][row] = 1.0;
for (int innerRow = row + 1; innerRow < size; innerRow++) {
double innerValue = matrix[innerRow][row];
for (int innerCol = row + 1; innerCol < size; innerCol++) {
//System.out.printf("matrix[%d][%d] (%.2f) -= %.2f * matrix[%d][%d] (%.2f)\n", innerRow, innerCol, matrix[innerRow][innerCol], innerValue, row, innerCol, matrix[row][innerCol]);
matrix[innerRow][innerCol] -= innerValue * matrix[row][innerCol];
}
solutionVector[innerRow] -= matrix[innerRow][row] * solutionVector[row];
matrix[innerRow][row] = 0.0;
}
}
//PrintMatrix("Upper Triangular Matrix");
for (int back = size - 1; back >= 0; back--) {
answers[back] = solutionVector[back];
for (int i = back - 1; i >= 0; i--) {
solutionVector[i] -= answers[back] * matrix[i][back];
}
}
return System.nanoTime() - begin;
}
public long GEAlgorithmSequential(){
long begin=System.nanoTime();
对于(int row=0;row=0;back--){
答案[返回]=解向量[返回];
对于(int i=back-1;i>=0;i--){
解向量[i]=答案[back]*矩阵[i][back];
}
}
return System.nanoTime()-开始;
}
我理解这个算法:第一部分取一行,将行中的所有其他部分除以对角线值,得到对角线1
第二部分,两个循环,零代表对角线下的所有内容
最后一部分,在PrintMatrix调用之后,我们进行反向替换,最终答案向量位于solutionVector中
我被告知这部分是可并行的:
for (int innerRow = row + 1; innerRow < size; innerRow++) {
double innerValue = matrix[innerRow][row];
for (int innerCol = row + 1; innerCol < size; innerCol++) {
matrix[innerRow][innerCol] -= innerValue * matrix[row][innerCol];
}
solutionVector[innerRow] -= matrix[innerRow][row] * solutionVector[row];
matrix[innerRow][row] = 0.0;
}
for(int innerRow=row+1;innerRow
为了进一步解释这一部分,它将逐行进行,对整行(每列,即内部循环)执行操作
我的第一个想法是为每一行启动一个线程,因为每一行都是独立的,只依赖于我们刚刚设置为1的主“行”,我们不接触它
所以我这样做了:
for (int innerRow = row + 1; innerRow < size; innerRow++) {
threads[innerRow] = new SubMatrixThread(this, innerRow, row);
threads[innerRow].start();
}
for (int innerRow = row + 1; innerRow < size; innerRow++) {
try {
threads[innerRow].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int innerRow=row+1;innerRow
SubstryXthread是:
@Override
public void run() {
double innerValue = m.GetMatrix()[innerRow][row];
for (int innerCol = row + 1; innerCol < size; innerCol++) {
m.GetMatrix()[innerRow][innerCol] -= innerValue * m.GetMatrix()[row][innerCol];
}
m.GetSolutionVector()[innerRow] -= m.GetMatrix()[innerRow][row] * m.GetSolutionVector()[row];
m.GetMatrix()[innerRow][row] = 0.0;
}
@覆盖
公开募捐{
double innerValue=m.GetMatrix()[innerRow][row];
对于(int innerCol=row+1;innerCol
m.GetMatrix()和m.GetSolutionVector()是同步方法,它们从矩阵对象返回矩阵和向量
在完成所有这些之后,线程应用程序比顺序应用程序花费的时间要长得多。例如,在512x512矩阵上,顺序算法需要0.039秒,线程算法需要>10秒。矩阵越大,时机就越差。IE sequential 4098x4098耗时约24秒,线程化完成时间超过5分钟(之后我才停止)
更多信息:我第一次用C启动这个程序,遇到了同样的问题,线程(来自pthreads)比sequential花费的时间更长。我的代码开始变得疯狂,因为我试图弄明白这一点,所以我用Java编写了它,以使自己更轻松
我上面描述的方法为每一行启动一个线程。我还只启动了两个线程,并将内部for循环分成两部分,而不是n部分。我在那里也遇到了同样的问题
我在Windows桌面上用IntelliJ运行Java,在Linux发行版上运行C程序,这两个应用程序都有同样的问题
有人知道我遗漏了什么吗?问题很可能就在这里: m.GetMatrix()和m.GetSolutionVector()是同步方法 这意味着,对于每一个操作,您都会调用同步机制,这将导致巨大的性能损失 只要让它们成为常规方法就足够了。我没有彻底检查算法,但应该没有竞争条件,因为行是独立的
更不用说同步它们在另一个意义上是无用的:如果存在竞争条件的风险,你就不会受到保护:你得到了矩阵,但你在保护结束后更新了它的内容(你在退出这些方法后更新了矩阵,所以你不再有锁).您没有意识到创建线程和启动线程的开销非常大。使用线程池。创建一个执行器的简单方法是 您可以提交可运行实例或可调用实例 如果只想等待计算完成,而不从计算中获取返回值,可以使用Runnable:
Runnable r = ...;
Future<?> f = threadPool.submit(r);
因为Runnable没有返回值,所以忽略返回值
您还可以实现
Callable
,在计算结束时返回一个值,并在submit
调用返回的将来使用f.get()
检索该值。您使用的线程太多,无法满足您的需要。使用5
Runnable r = ...;
Future<?> f = threadPool.submit(r);
f.get();