c-OpenMP任务的执行时间因我放置杂注的位置而异



我正在尝试使用任务使用OpenMP(和MPI(并行化一些代码。我有以下代码:

double t_copy = 0, t_forward = 0, t_backward = 0, t_diag = 0;
void pc_ssor_poisson3d(int N, void *data,
double *restrict Ax,
double *restrict x)
{
// clocks for timing
#define COPY_CLOCK 20
#define FW_SSOR_CLOCK 21
#define DIAG_SSOR_CLOCK 22
#define BW_SSOR_CLOCK 23
pc_ssor_p3d_t *ssor_data = (pc_ssor_p3d_t *)data;
int n = ssor_data->n;
double w = ssor_data->omega;
tic(COPY_CLOCK);
#ifdef PAR_PC
parallel_copy(N, Ax, x);
#else
memcpy(Ax, x, N * sizeof(double));
#endif
t_copy += toc(COPY_CLOCK);
tic(FW_SSOR_CLOCK);
#ifdef PAR_PC
parallel_ssor_forward_sweep(n, 0, n, 0, n, 0, n, Ax, w); // --1--
#else
...

这是函数parallel_ssor_forward_sweep:

void parallel_ssor_forward_sweep(int n, int i1, int i2, int j1, int j2, int k1, int k2, double *restrict Ax, double w)
{
char *dep_matrix = (char *)malloc(sizeof(char) * (i2 - i1) / BS * (j2 - j1) / BS * (k2 - k1) / BS);
// --2--
for (int k = 0; k < (k2 - k1) / BS; k++)
{
for (int j = 0; j < (j2 - j1) / BS; j++)
{
for (int i = 0; i < (i2 - i1) / BS; i++)
{
// ssor_forward_sweep_pwrap(n, i1 + i * BS, i1 + (i + 1) * BS, j1 + j * BS, j1 + (j + 1) * BS, k1 + k * BS, k1 + (k + 1) * BS, Ax, w, dep_matrix, i, j, k);
ssor_forward_sweep_pwrap(n, i1, i2, j1, j2, k1, k2, Ax, w, dep_matrix, i, j, k);
}
}
}
free(dep_matrix);

}

函数ssor_forward_sweep_pwrap实际上创建了OpenMP任务,我将附加代码:

void ssor_forward_sweep_pwrap(int n, int i1, int i2, int j1, int j2, int k1, int k2, double *restrict Ax, double w, char *dep_matrix, int i, int j, int k)
{
#define dep_mat(i, j, k) (dep_matrix[(k * (j2 - j1) + j) * (i2 - i1) + i])
char *top_dep = k - 1 >= 0 ? &dep_mat(i, j, k - 1) : NULL;
char *left_dep = j - 1 >= 0 ? &dep_mat(i, j - 1, k) : NULL;
char *back_dep = i - 1 >= 0 ? &dep_mat(i - 1, j, k) : NULL;
char *out_dep = &dep_mat(i, j, k);
#pragma omp task depend(in                                          
: *top_dep, *left_dep, *back_dep) depend(inout 
: *out_dep)
{
ssor_forward_sweep(n, i1 + i * BS, i1 + (i + 1) * BS, j1 + j * BS, j1 + (j + 1) * BS, k1 + k * BS, k1 + (k + 1) * BS, Ax, w);
}
#undef dep_mat
}

Pragma指令:

#pragma omp parallel
#pragma omp single
{
}

现在的问题是,如果我把上面的指令放在parallel_ssor_forward_sweep调用周围,使代码并行(在代码中用注释-1-标记(,我会得到更好的时间(对于该代码部分,大约9.6/9.7秒(,而如果我把它放在用注释-2-标记的代码中的for周围,那么得到的是整个函数代码,而不是malloc(12.7/12.8秒(。

我已经为每个代码执行了3次,以确保它不是侥幸,并且使用相同数量的线程(本例中为6个(。

我在我的大学机器上运行,对于分配的资源,它不应该有任何其他程序与我的同时运行。

我认为这种行为很奇怪的原因是,在pragma omp单个区域内,我希望只有一个线程执行代码,所以我不认为在区域内外使用malloc会导致这种差异。

此外,该代码给出了相同的结果,并使用相同的输入运行。

@JohnBollinger在评论中提到的问题是由于当我按照下面的方式放置pragma时,执行#pragma omp single区域的线程可以在其他线程结束之前到达free(dep_matrix)

#ifdef PAR_PC
#pragma omp parallel
#pragma omp single
{
parallel_ssor_forward_sweep(n, 0, n, 0, n, 0, n, Ax, w);
}
#else

通过像下面这样将pragma放入parallel_ssor_forward_sweep函数中,执行#pragma omp single区域的线程必须等待该区域末尾(即在free(dep_matrix)之前(的其他线程,因此当其他线程需要矩阵时,该矩阵仍然可用。

void parallel_ssor_forward_sweep(int n, int i1, int i2, int j1, int j2, int k1, int k2, double *restrict Ax, double w)
{
char *dep_matrix = (char *)malloc(sizeof(char) * (i2 - i1) / BS * (j2 - j1) / BS * (k2 - k1) / BS);
#pragma omp parallel
#pragma omp single
{
for (int k = 0; k < (k2 - k1) / BS; k++)
{
for (int j = 0; j < (j2 - j1) / BS; j++)
{
for (int i = 0; i < (i2 - i1) / BS; i++)
{
// ssor_forward_sweep_pwrap(n, i1 + i * BS, i1 + (i + 1) * BS, j1 + j * BS, j1 + (j + 1) * BS, k1 + k * BS, k1 + (k + 1) * BS, Ax, w, dep_matrix, i, j, k);
ssor_forward_sweep_pwrap(n, i1, i2, j1, j2, k1, k2, Ax, w, dep_matrix, i, j, k);
}
}
}
}
free(dep_matrix);
}

相关内容

最新更新