0

我想使用 OpenMP 来并行化我的代码,但不确定我的循环如何保持其属性。

我知道内部循环产生了多少次结果,以及它有多大:

(根据宽度的均匀性,内环的行为不同,因此天花板和地板的划分)

const size_t
    bytes_per_result = <something>,
    totalloops = width/2 * iceildiv(width, 2);

所以我可以将每个结果写入文件内的已知位置。为此,我只需分配一个该大小的文件,然后将其倒回到开头:

FILE* f = fopen(<somefile>, "w");
fseek(f, totalloops * bytes_per_result - 1, SEEK_SET); //seek to before file end
fputc('\0', f); //write byte to allocate whole file
rewind(f);

然后我只是循环,并计算内部循环通过k. 在最后一个循环之后,k == totalloops.

result_t result;
size_t i, j, k;
for (i=0, k=0; i<width; i++) {
    for (j=0; j<imin(i, width-i-1); j++, k++) {
        result = do_calculation(i, j);
        fseek(f, k * bytes_per_result, SEEK_SET);
        fwrite_result(f, result);
    }
}

现在我该如何并行化呢?并行化的东西当然是do_calculation部分,而查找和写入必须一起声明#pragma omp critical。但是我怎样才能k表现得像我想要的那样?

OpenMP 只能解析简单的 for 循环,最后只有一个增量表达式,而不是两个,所以我不能k++留在那里……</p>

4

1 回答 1

0

您可以分两步完成:

  1. 并行计算结果并将结果存储在 RAM 缓冲区中
  2. 将整个缓冲区写入文件。

.

result_t buffer[MAXLEN];

#pragma omp prarellel for
for (size_t i=0; i<width; i++) {
    for (size_t j=0; j<imin(i, width-i+1); j++) {
        result_t result = do_calculation(i, j);
        size_t k=.....;
        buffer[k]=result;
    }
}

fwrite_buffer(f, buffer, total_length);

更新

由于您的结果日期很大(~10GB),您可能会花费大部分时间将数据写入磁盘。然而,多线程代码通常无法提高磁盘带宽受限任务的性能。您应该重新考虑多线程是否适合您的任务。

如果缓冲区大小有问题,您可以保留原始设计,并使用它omp critical来避免文件访问的竞争条件。

#pragma omp prarellel for schedule(dynamic,3)
for (size_t i=0; i<width; i++) {
result_t buffer[MAXLEN];
    for (size_t j=0; j<imin(i, width-i+1); j++) {
        result_t result = do_calculation(i, j);
        size_t k=ijw2k(i,j,width);
        #pragma omp critical {
            fseek(f, k * bytes_per_result, SEEK_SET);
            fwrite_buffer(f, result);
        }
    }
}

根据您的代码,计算k似乎有点复杂,但仍然可行。k只是 的一个函数i, j, width,我想这对你来说应该不是问题。

size_t ijw2k(size_t i, size_t j, size_t width) {
    size_t k;
    if (width % 2) {
        if (i<width-i+1) {
            ....
        } else {
            ....
        }
    } else {
        if (i<width-i+1) {
            ....
        } else {
            ....
        }
    }
    return k;
}
于 2013-11-06T17:36:58.513 回答