为什么 printf 调用有助于缩短执行时间?

问题描述 投票:0回答:1

我正在 OpenMP 中实现稀疏矩阵多向量乘法,我注意到在预处理函数中包含一些 printf 调用,而不是并行化,从后续并行化产品中获得的 GFLOPS 增加了很多。

我尝试将我的测量方法从 clock_gettime() 更改为 omp_get_wtime(),但结果几乎相同。

为了帮助您理解我在说什么:

int main() {

    // some stuff

    // serial product computation
    clock_gettime(CLOCK_MONOTONIC, &t1);
    serial_product(a, x, k, y_s);
    clock_gettime(CLOCK_MONOTONIC, &t2);

    gflops_s = flop / ((t2.tv_sec - t1.tv_sec) * 1.e9 + (t2.tv_nsec - t1.tv_nsec));

    pre_processing(...) // in here there's a loop to do some load balancing  

    clock_gettime(CLOCK_MONOTONIC, &t1);
    openmp_spmm(a, rows_idx, num_threads, x, k, y_p);
    clock_gettime(CLOCK_MONOTONIC, &t2);

    gflops_p = flop / ((t2.tv_sec - t1.tv_sec) * 1.e9 + (t2.tv_nsec - t1.tv_nsec));

    // some other stuff
}

正如我所说,如果我不调用 printf,就像我做一些基本调试一样,在 pre_processing() 函数的循环中,gflops_p 约为 2 GFLOPS。同时,如果我使用这些与 OpenMp 无关的 printf 调用,gflops_p 会跳到 10 GFLOPS。

如果有帮助,这是预处理功能:

void pre_processing(int threads, int tot_nz, const int* irp, int tot_rows, int* rows_idx){
    int j, nz, nz_prev = 0, nz_curr, start_row = 0, r_prev, r_curr = 0;

    for (int i = 0; i < threads; i++) {
        rows_idx[i] = start_row; 

        printf("."); // why this print enormously speeds up omp product???

        nz_curr = ((i + 1) * tot_nz) / threads;
        nz = nz_curr - nz_prev;
        nz_prev = nz_curr;

        for (j = start_row; j < tot_rows; j++) {
            r_curr += irp[j + 1] - irp[j]; 

            if (r_curr < nz) { 
                r_prev = r_curr; 
            } else {
                start_row = ((r_curr - nz) < (nz - r_prev)) ? j + 1 : j;
                break;
            }
        }

        r_curr = 0;
    }
    rows_idx[threads] = tot_rows;
    printf("\n");
}

我不知道为什么会这样。也许是关于标准输出刷新或时钟周期或 CPU 利用率?

c openmp stdout sparse-matrix matrix-multiplication
1个回答
0
投票

当一个线程正在做一些 I/O 时(例如通过

printf()
),它被认为是 I/O 绑定。这使得它比 CPU 绑定线程更优先。原因是确保尽快管理 I/O 以使系统响应。例如,最好支持与运算符交互的线程,而不是让底层 CPU 绑定线程占用 CPU。

© www.soinside.com 2019 - 2024. All rights reserved.