C 并行BW和FW算法的最佳方法
我已经实现了求解L和U三角矩阵的BW和FW算法。 我实现的算法以串行方式运行得非常快,但我不知道这是否是并行化它的最佳方法。 我认为我已经考虑到了每一个可能的数据竞争(关于alpha),对吗C 并行BW和FW算法的最佳方法,c,multithreading,performance,parallel-processing,openmp,C,Multithreading,Performance,Parallel Processing,Openmp,我已经实现了求解L和U三角矩阵的BW和FW算法。 我实现的算法以串行方式运行得非常快,但我不知道这是否是并行化它的最佳方法。 我认为我已经考虑到了每一个可能的数据竞争(关于alpha),对吗 void solveInverse (double **U, double **L, double **P, int rw, int cw) { double **inverseA = allocateMatrix(rw,cw); double* x = allocateArray(rw);
void solveInverse (double **U, double **L, double **P, int rw, int cw) {
double **inverseA = allocateMatrix(rw,cw);
double* x = allocateArray(rw);
double* y = allocateArray(rw);
double alpha;
//int i, j, t;
// Iterate along the column , so at each iteration we generate a column of the inverse matrix
for (int j = 0; j < rw; j++) {
// Lower triangular solve Ly=P
y[0] = P[0][j];
#pragma omp parallel for reduction(+:alpha)
for (int i = 1; i < rw; i++) {
alpha = 0;
for (int t = 0; t <= i-1; t++)
alpha += L[i][t] * y[t];
y[i] = P[i][j] - alpha;
}
// Upper triangular solve Ux=P
x[rw-1] = y[rw-1] / U[rw-1][rw-1];
#pragma omp parallel for reduction(+:alpha)
for (int i = rw-2; (i < rw) && (i >= 0); i--) {
alpha = 0;
for (int t = i+1; t < rw; t++)
alpha += U[i][t]*x[t];
x[i] = (y[i] - alpha) / U[i][i];
}
for (int i = 0; i < rw; i++)
inverseA[i][j] = x[i];
}
freeMemory(inverseA,rw);
free(x);
free(y);
}
void(双**U,双**L,双**P,整数rw,整数cw){
双**逆EA=分配矩阵(rw,cw);
double*x=分配通道(rw);
双*y=分配通道(rw);
双α;
//inti,j,t;
//沿着列进行迭代,因此在每次迭代中,我们生成一列逆矩阵
对于(int j=0;j
在与用户dreamcrash进行私人讨论后,我们得出了他在评论中提出的解决方案,为每个线程创建了一对向量
x
和y
,这些线程将独立工作在一个列上。在与OP讨论评论后(这些评论后来被删除),我们都得出结论:
您不需要减少alpha
变量,因为在第一个并行区域之外,它会再次初始化为零。相反,将alpha
变量设为私有
而不是每个j
迭代都有一个并行区域
。您可以提取并行区域
,以封装整个最外层循环,并使用#pragma omp for
而不是#pragma omp parallel for
。尽管如此,尽管通过这种方法我们减少了并行r的数量从rw
创建的egion
仅为1,通过此优化实现的加速应该没有那么显著,因为一个高效的OpenMP实现将使用一个线程池,其中线程在第一个并行区域
上初始化,但在下一个并行区域
上重用。因此,savi减少创建和销毁线程的开销
#pragma omp parallel
{
for (int j = 0; j < rw; j++)
{
y[0] = P[0][j];
#pragma omp for
for (int i = 1; i < rw; i++) {
double alpha = 0;
for (int t = 0; t <= i-1; t++)
alpha += L[i][t] * y[t];
y[i] = P[i][j] - alpha;
}
x[rw-1] = y[rw-1] / U[rw-1][rw-1];
#pragma omp for
for (int i = rw-2; (i < rw) && (i >= 0); i--) {
double alpha = 0;
for (int t = i+1; t < rw; t++)
alpha += U[i][t]*x[t];
x[i] = (y[i] - alpha) / U[i][i];
}
#pragma omp for
for (int i = 0; i < rw; i++)
inverseA[i][j] = x[i];
}
}
在与OP讨论评论(之后删除)后,我们都得出结论:
您不需要减少alpha
变量,因为在第一个并行区域之外,它会再次初始化为零。相反,将alpha
变量设为私有
而不是每个j
迭代都有一个并行区域
。您可以提取并行区域
,以封装整个最外层循环,并使用#pragma omp for
而不是#pragma omp parallel for
。尽管如此,尽管通过这种方法我们减少了并行r的数量从rw
创建的egion
仅为1,通过此优化实现的加速应该没有那么显著,因为一个高效的OpenMP实现将使用一个线程池,其中线程在第一个并行区域
上初始化,但在下一个并行区域
上重用。因此,savi减少创建和销毁线程的开销
#pragma omp parallel
{
for (int j = 0; j < rw; j++)
{
y[0] = P[0][j];
#pragma omp for
for (int i = 1; i < rw; i++) {
double alpha = 0;
for (int t = 0; t <= i-1; t++)
alpha += L[i][t] * y[t];
y[i] = P[i][j] - alpha;
}
x[rw-1] = y[rw-1] / U[rw-1][rw-1];
#pragma omp for
for (int i = rw-2; (i < rw) && (i >= 0); i--) {
double alpha = 0;
for (int t = i+1; t < rw; t++)
alpha += U[i][t]*x[t];
x[i] = (y[i] - alpha) / U[i][i];
}
#pragma omp for
for (int i = 0; i < rw; i++)
inverseA[i][j] = x[i];
}
}
#pragma omp parallel
{
for (int j = 0; j < rw; j++)
{
y[0] = P[0][j];
#pragma omp for
for (int i = 1; i < rw; i++) {
double alpha = 0;
for (int t = 0; t <= i-1; t++)
alpha += L[i][t] * y[t];
y[i] = P[i][j] - alpha;
}
x[rw-1] = y[rw-1] / U[rw-1][rw-1];
#pragma omp for
for (int i = rw-2; (i < rw) && (i >= 0); i--) {
double alpha = 0;
for (int t = i+1; t < rw; t++)
alpha += U[i][t]*x[t];
x[i] = (y[i] - alpha) / U[i][i];
}
#pragma omp for
for (int i = 0; i < rw; i++)
inverseA[i][j] = x[i];
}
}
#pragma omp parallel for
for (int i = 1; i < rw; i++) {
double alpha = 0;
for (int t = 0; t <= i-1; t++)
alpha += L[i][t] * y[t];
y[i] = P[i][j] - alpha;
}
#pragma omp parallel
{
double* x = allocateArray(rw);
double* y = allocateArray(rw);
#pragma omp for
for (int j = 0; j < rw; j++)
{
y[0] = P[0][j];
for (int i = 1; i < rw; i++) {
double alpha = 0;
for (int t = 0; t <= i-1; t++)
alpha += L[i][t] * y[t];
y[i] = P[i][j] - alpha;
}
x[rw-1] = y[rw-1] / U[rw-1][rw-1];
for (int i = rw-2; i >= 0; i--) {
double alpha = 0;
for (int t = i+1; t < rw; t++)
alpha += U[i][t]*x[t];
x[i] = (y[i] - alpha) / U[i][i];
}
for (int i = 0; i < rw; i++)
inverseA[i][j] = x[i];
}
free(x);
free(y);
}