1

下面我尝试绘制使用 OpenMP 任务并行化的代码。

在 main 函数中,启动了一个并行环境,然后立即将代码包装到一个#pragma omp master部分中。在计算了预期的工作负载之后,根据这个工作负载是否低于给定的阈值,必须完成的工作要么被传递给串行函数,要么被传递给递归分割工作负载并初始化单独任务的函数。然后在指令#pragma omp task之后汇总每个单曲的结果。#pragma omp taskwait

int main() {
    #pragma omp parallel
    {
        #pragma omp master
        {
            //do some serial stuff
            
            //estimate if parallelisation is worth it.
            const int workload = estimateWorkload();
            if (workload < someBound) {
                serialFunction();
            }
            else {
                parallelFunction(workload);
            }
        }
    }
}

int parallelFunction(int workload) {
    if (workload < someBound) {
        return serialFunction();
    }
    int result1, result2;
    #pragma omp task shared(result1)
    {
        result1 = parallelFunction(workload/2);
    }    
    #pragma omp task shared(result2)
    {
        result2 = parallelFunction(workload/2);
    }
    #pragma omp taskwait
   return result1 < result2;
}

在这样的设置中,如何测量每个线程的实际计算时间?

如果我测量 CPU 时间并有k活动线程,那么我会得到k*wallTime,这是有道理的,因为线程由前导#pragma omp parallel指令初始化并始终保持活动状态。然而,这并没有给我任何关于线程实际工作花费多少时间的信息,这使得代码难以分析。

4

1 回答 1

1

Q :在这样的设置下,如何测量每个线程的实际计算时间?

一个简单的半手动代码执行时间分析的简单模拟代码

在此处输入图像描述

毋庸置疑,对于“嘈杂”的执行平台,选择CLOCK_MONOTONIC保存漂移时间更新,但不会“保存”非 CPU 核心等待状态,因为任何(如果重,则更多)“背景“-(令人不安的)-由操作系统调度的进程。

然而,对于原型设计阶段,这比安装所有“omp-native”回调
{ ompt_callback_task_create_t, ompt_callback_task_schedule_t, ompt_callback_task_dependence_t, ompt_callback_dispatch_t, ompt_callback_sync_region_t, ..., ompt_callback_thread_begin_t, ompt_callback_thread_end_t, ... }容易处理。


副作用奖励:

如果报告和后处理记录的嵌套代码执行相应的持续时间,那么简单代码允许“框架”相关调用签名和递归嵌套相关开销的隐藏成本。

修改后的、开销严格的阿姆达尔定律然后停止欺骗你并开始更准确地向你展示,当这段代码开始失去与开销相关的(加上由于潜在的工作单元原子性主要-[SERIAL]任何预期真实的附加成本-[PARALLEL]部分加速(预期利用更多(那些并且只有那些否则免费的)资源)。

这始终是战争中最艰难的部分(仍需继续战斗……)


EFFICIENCY of SCHEDULING & OCCUPIED RESOURCES' of a CALL to 2-ary task-SCHEDULED fun() with hidden 1-ary RECURSION:

CALL
    42----*--------------------------------------------------------------------------------------*
     :    |                                                                                      |
     :    |                                                                                     21----*---------------------------------------*
     :    |                                                                                      :    |                                       |
     :    |                                                                                      :    |                                      10----*----------------*
     :    |                                                                                      :    |                                       :    |                |
     :    |                                                                                      :    |                                       :    |                5----*----*
     :    |                                                                                      :    |                                       :    |                :    |    |
     :    |                                                                                      :    |                                       :    |                :    |    2<
     :    |                                                                                      :    |                                       :    |                :    2<  /
     :    |                                                                                      :    |                                       :    5----*----*      5___/___/................ #taskwait  2
     :    |                                                                                      :    |                                       :    :    |    |     /
     :    |                                                                                      :    |                                       :    :    |    2<   /
     :    |                                                                                      :    |                                       :    :    2<  /    /
     :    |                                                                                      :    |                                       :    5___/___/    /
     :    |                                                                                      :    |                                      10___/____________/............................. #taskwait  5
     :    |                                                                                      :   10----*----------------*                /
     :    |                                                                                      :    :    |                |               /
     :    |                                                                                      :    :    |                5----*----*    /
     :    |                                                                                      :    :    |                :    |    |   /
     :    |                                                                                      :    :    |                :    |    2< /
     :    |                                                                                      :    :    |                :    2<  /  /
     :    |                                                                                      :    :    5----*----*      5___/___/  /
     :    |                                                                                      :    :    :    |    |     /          /     
     :    |                                                                                      :    :    :    |    2<   /          /
     :    |                                                                                      :    :    :    2<  /    /          /
     :    |                                                                                      :    :    5___/___/    /          /
     :    |                                                                                      :   10___/____________/__________/.......................................................... #taskwait 10
     :    |                                                                                     21___/
     :   21----*---------------------------------------*                                        /
     :    :    |                                       |                                       /
     :    :    |                                      10----*----------------*                /
     :    :    |                                       :    |                |               /
     :    :    |                                       :    |                5----*----*    /
     :    :    |                                       :    |                :    |    |   /
     :    :    |                                       :    |                :    |    2< /
     :    :    |                                       :    |                :    2<  /  /
     :    :    |                                       :    5----*----*      5___/___/  /
     :    :    |                                       :    :    |    |     /          /
     :    :    |                                       :    :    |    2<   /          /
     :    :    |                                       :    :    2<  /    /          /
     :    :    |                                       :    5___/___/    /          /
     :    :    |                                      10___/____________/          /
     :    :   10----*----------------*                /                           /
     :    :    :    |                |               /                           /
     :    :    :    |                5----*----*    /                           /
     :    :    :    |                :    |    |   /                           /
     :    :    :    |                :    |    2< /                           /
     :    :    :    |                :    2<  /  /                           /
     :    :    :    5----*----*      5___/___/  /                           /
     :    :    :    :    |    |     /          /                           /
     :    :    :    :    |    2<   /          /                           /
     :    :    :    :    2<  /    /          /                           /
     :    :    :    5___/___/    /          /                           /
     :    :   10___/____________/__________/                           /
     :   21___/_______________________________________________________/...................................................................................................................... #taskwait 21
    42___/
RET_/

效率

调度和占用资源的调用 2-ary task-SCHEDULEDfun()与隐藏的 1-ary RECURSION 对于任何不断增长的规模workload变得越来越重要workload < someBound * 2 ^ W,但代价是非常高的W(这会导致W * k-ary-many 次重新-{-acquired, -allocated, -released}浪费了所有k请求#pragma omp task shared(...)的处理相关资源,在整个纯[SERIAL]定义递归潜水和重铺返回的过程中。

很容易看出有多少资源会挂起等待(由于甚至是 1-ary RECURSION 公式),直到每一次深入递归的最深层次,都会冒泡回到顶层#pragma omp taskwait

为每个递归潜水级别重新分配新资源和新资源的成本通常会在开销严格的阿姆达尔定律(性能方面)上杀死你,如果没有陷入颠簸或与系统配置相关的溢出,因为破坏了真实的- 更早的系统物理资源,用于任何相当大的递归深度。

如果不使用“典型的便宜”但昂贵的(空闲/浪费)资源递归问题公式,即使使用最轻量级的一元案例,这些都是您不需要支付的成本。

看看有多少-:表示的“等待线”并行存在,除了拓扑的任一阶段中有多少-|表示的“计算线”,浪费/阻塞,但必须让所有与任务相关的资源(内存和堆栈空间只是比较明显的那些,它们在性能方面非常昂贵(只是让大部分处理时间空闲等待),或者如果超额订阅超出真实系统的配置容量,则容易由于溢出而崩溃)。

战争是你的!继续走 ...


网站合规免责声明:
-------------------------------------------- ----------------------------------
根据 StackOverflow 政策,此处发布了完整的模型代码,用于在任何情况下,Godbolt.org平台都可能无法访问,否则请随意选择和/或使用Compiler Explorer工具,这远远超出了放入模型源代码中的字符序列

选择 &执行它的乐趣永远是你的:o)

#include <time.h>

int estimateWorkload() {
    return 42; // _________________________________________________________ mock-up "workload"
}

int serial_a_bit_less_naive_factorial( int n ){
     return ( n < 3 ) ? n : n * serial_a_bit_less_naive_factorial( n - 1 );
}

int serialFunction() {
    return serial_a_bit_less_naive_factorial( 76 );
}

int parallelFunction( int workload, const int someBound ) { // __ pass both control parameters
    
    struct timespec T0, T1;
    int retFlag,
        retValue,
        result1,
        result2;
    
    retFlag = clock_gettime( CLOCK_MONOTONIC, &T0 ); // \/\/\/\/\/\/\/\/\/\ SECTION.begin

    if ( workload < someBound ) {
        retValue = serialFunction();
    }
    else { // -- [SEQ]----------------------------------------------------

        #pragma omp task shared( result1 ) // -- [PAR]|||||||||||||||||||| with (1-ary recursions)
        {
            result1 = parallelFunction( (int) workload / 2, someBound ); // (int) fused DIV
        }
        
        #pragma omp task shared( result2 ) // -- [PAR]|||||||||||||||||||| with (1-ary recursions)
        {
            result2 = parallelFunction( (int) workload / 2, someBound ); // (int) fused DIV
        }
        #pragma omp taskwait
    
        retValue = result1 < result2;
    }
    
    retFlag = clock_gettime( CLOCK_MONOTONIC, &T1 ); // \/\/\/\/\/\/\/\/\/\ SECTION.end

    // ____________________________________________________________________ MAY ADD ACCUMULATION (1-ary recursions)
    // ...
    // ____________________________________________________________________ MAY ADD ACCUMULATION (1-ary recursions)
    return retValue;
}


int main() {
    
    const int someBound = 3; // _______________________________________ a control parameter A

    #pragma omp parallel
    {
        #pragma omp master
        {
            // -- [SEQ]---------------------------------------- do some serial stuff
            
            // ------------------------------estimate if parallelisation is worth it
            const int workload = estimateWorkload();

            if ( workload < someBound ) {
                serialFunction();
            }
            else {
                parallelFunction( workload, someBound ); // -- [PAR]||||||| with (1-ary recursions)
            }
        }
    }
}
于 2020-07-06T16:37:18.600 回答