专栏首页吉浦迅科技DAY53:阅读Profiler Counter Function

DAY53:阅读Profiler Counter Function

我们正带领大家开始阅读英文的《CUDA C Programming Guide》,今天是第53天,我们正在讲解CUDA C语法,希望在接下来的47天里,您可以学习到原汁原味的CUDA,同时能养成英文阅读的习惯。

B.17. Profiler Counter Function

Each multiprocessor has a set of sixteen hardware counters that an application can increment with a single instruction by calling the __prof_trigger() function.

void __prof_trigger(int counter);

increments by one per warp the per-multiprocessor hardware counter of index counter. Counters 8 to 15 are reserved and should not be used by applications.

The value of counters 0, 1, ..., 7 can be obtained via nvprof by nvprof --events prof_trigger_0x where x is 0, 1, ..., 7. All counters are reset before each kernel launch (note that when collecting counters, kernel launches are synchronous as mentioned in Concurrent Execution between Host and Device).

本文备注/经验分享:

今天只涉及一个简单的内置函数: __prof_trigger() 该函数比较简单, 但是在很多时候很有用. 我们来看一下它的主要用途和需要注意的事项(一些可能会出乎你意外的东西)。 该函数除了叫profiler counter, 也叫performance monitors, 因此故名思议, 它的主要作用是和性能评估有关. 我们都知道, 一般情况下的开发, 是在开发机器的显卡上, 通过nvprof或者nvvp来做profiling的(性能分析) 这种方式, 通过通过命令行或者图形界面的用户交互,逐步的用户发现当前代码运行后可能出现的性能问题, 然后根据profiler的报告和建议, 逐步的优化自己的代码实现.但是在实际的生产中, 这种方式有一定的问题, 主要集中在两点上: (1)开发时候的卡, 不一定是最终生产运行时候的卡.例如你可以使用GP100上开发, 最后交付后, 客户在Titan-V上运行.此时如果再要求使用图形界面的NVVP(Nvidia Visual Profiler)是不现实的, 用户也不具有现场分析能力. (2)一些代码的运行结果和实际生产环境中的数据输入有关, 而在开发机器上用的开发测试数据, 总是有限的, 无法覆盖全面情况. 这样可能一些算法在数据集A下的运行效率还可以, 但是在实际的数据集B(无法提前知道)性能一般.此时开发者可能就需要能让代码自我调优. 或者简单的, 可以体现实现多种代码路径,在不同的运行环境卡下, 实际的能多少执行不同的代码路径选择或者kernel实现选择.则此时, 应当考虑本章节说道的__prof_trigger()函数.我举个例子说, 开发的时候, 使用的是GDDR5, 256-bit的卡, 而运行的时候则可能是HBM2或者DDR4.此时一张卡原本卡计算的, 现在瓶颈变成在在访存上,或者原本卡访存的, 现在瓶颈变成了在计算上.类似这种的. 而用户则可以配合clock()或者clock64(), 来分析单个线程或者warp中,某段代码的具体串行执行时间代价,然后分别在开发的时候, 准备好不同版本的代码片段, 然后发布的时候, 分别分析每个片段大致的周期代价, 选择不同的版本来执行.有的人看到这里可能会问, 这个完全不需要使用这些函数啊?例如她可以说, "我原本就是这样做的, 通过整体的时间(kernel)进行event测时"或者她可以说, "我原本将kernel中的多个片段用clock64()之类的隔离出来了, 然后将结果保存到global memory然后取回查看",这样不都是可以吗? 请有注意本章节的该函数有特色的:主要特色在于, 代价非常低, 或者通俗的说, "Low Profiling Overhead" 你保存到显存固然可以, 但是这种方式本身, 会造成干扰(例如你的kernel也在进行访存),而本章节的__prof_trigger, 则提供了一种独立的高速性能统计方式, 基本不造成性能干扰,(和执行普通一条单精度浮点加法的代价差不多),同时可以高速的进行统计(大约每周期每SM可以统计约4次(按照warp计)), 所以这种低代价的分析函数, 基本上对实际性能的影响很少.此外, 用户固然可以进行全局分析(kernel整体, 通过event计时),但是很多时候, 这种方式无法对具体的代码中的片段进行,例如用户可能会怀疑自己的某段非常分散的代码, 访存的代码非常高昂(例如大范围近乎随机的访存),此时如果整体测时, 无法提供任何指导意义(例如用户可能夹杂在一堆计算或者其他方式的访存整体中),而通过简单的在访存前和使用后的周期计算,用户可以单独的对超过, 例如1000个周期的结果要求增加特殊的计算数器3,而超过2000个周期的访存(某些代码实际执行中很常见的, 超高延迟), 要求增加计数器值4,最后用户可以搜集这些计数器的结果,然后发现, 哈, 我90%的访存都超过了2000个周期延迟, 只有10%的小于等于1000个周期, 肯定哪里有问题啊. 我决定让代码自动切换到使用计算换取访存吧(例如用户可以提前准备好2个code path, 根据运行时刻的标志选择),或者发现, 哈, 我完全没有计算数值4的问题, 这个代码片段应当执行路径XYZ,类似这种的.这种low overhead的分析方式, 非常有用.除了这些常见的作用外, 该函数还具有一些常见的坑, 需要说明一下.(1)该函数增加的计数器值warp为单位的. 只要warp中有1个线程能增加计数器值, 那么计数器值就会增加1,这也是本章节提到的注意事项.换句通俗的话说, warp内部有1到31到线程分量(lanes), 执行的效果是一样的。所以请尽量不要warp内分支的调用此函数, 除非你知道你在做什么.(2)点则是, 该函数因为很高效, 实际上会编译成单条低代价指令(刚才说了, 如同一次单精度的加法的代价而已),而该单条低代价指令, 支持的是16-bit的立即数(Immediate, 指的是嵌入在指令中的操作数) 因此在调用该函数的时候, 你应当直接给出常数(编译时刻能确定的常数)做为参数.例如调用方式: __prof_trigger(3)来增加3号计数器.而不要写成: __prof_trigger(n)来增加第n号性能计数器(其中n是个变量, 而且无法从编译时刻确定),如果给出了后者, 会造成高昂的性能分析代价.因为刚才说过, 该低代价指令接受的立即数形式的常数,如果你给出了n(0-15, 其中用户应当使用前8个), 编译器会生成一条具有16条等效分支的路径, 和16条条件执行的profiler trigger指令, 造成巨大的代价.请尽量规避这么做.这是该函数的主要问题..

然后需要补充的是: (1)你可以同时增加多个计数器的, 例如假设你的代码手工展开量一个整数求模计算, 根据 a % b中的数据的范围不同, 例如小于24-bit, 走快速float模拟. 或者大数据范围的走double模拟. 你分别需要统计读取操作数的代价(例如刚才说的超过1000个周期延迟的), 和, 需要走慢速double路径的代价(假设你对这两种情况分别指定了计数器3和4), 则你可能需要同时增加2个计数器, 以便进一步的降低本函数本身的代价(虽然已经很低了, 但有时候对于小代码路径, 例如只有几条到10几条路径的), 则可以考虑使用能同时增加多个性能计数器的版本, 该版本已经导出到了PTX中. 可以直接嵌入. (2)如果能现场调试和分析, 尽量现场分析, 新版本的profiler和较新的卡(Maxwell/Pascal+)所能支持的PC Sampling/Instruction Sampling功能, 非常易用(毕竟是图形化界面的), (3)在真正需要的场合, 真无法考虑2的, 能用本章节的本函数的, 果断使用. 但需要注意的是, 性能计数器的值无法直接读取回来.你可以考虑通过cupti来得到它们(请参考CUPTI手册),或者如果在Linux下的话, 可以简单的考虑通过nvprof外加grep的方式, 来直接搜集特定的性能计数器的值.(或者例如你可以单独在首次特定环境运行的时候, 通过perl脚本之类的东西, 直接正则分析nvprof的结果之类的),而如何指定nvprof来获取相关Event的值, 已经在本章节说过了. 注意其中的给出常数方式的调用(__prof_trigger(3)例如), 一定要注意.这是造成使用该函数的问题的主要来源.总之如非必要, 不要使用__prof_trigger(编译时刻无法确定的变量)的形式.除非你知道你在做什么.

有不明白的地方,请在本文后留言

或者在我们的技术论坛bbs.gpuworld.cn上发帖

本文分享自微信公众号 - 吉浦迅科技(gpusolution)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-07-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何在Jetson TX2上用Python捕获摄像头影像,并用Caffe进行推理

    本文转载自JK Jung的帖子:https://jkjung-avt.github.io/tx2-camera-caffe/ 如果有侵犯到贴主利益,请立刻跟我联...

    GPUS Lady
  • 【QQ问题汇总】基于任务的并行与基于数据的并行有什么区别吗

    问题1:基于任务的并行与基于数据的并行有什么区别吗? 答:有区别,前者往往是cpu上的当时,而后者往往是gpu上的。前者可以看成只有一个work-item的ke...

    GPUS Lady
  • 用Jetson NANO做个智能门铃应用

    使用Nvidia Jetson Nano,您可以用很少的预算构建运行gpu加速的深度学习模型的独立硬件系统。它有点像树莓派,但速度比树莓派快得多。

    GPUS Lady
  • 腾讯云发布无服务器云函数,较云主机成本低约70%

    4月26日,腾讯云宣布,正式开放国内首款FaaS(Function as a Service,函数即服务) 产品——无服务器云函数(SCF,Serverless...

    云资讯小编
  • 最美的C语言程序流体,你会做吗?

    想好好学C语言,尽量不要单一的只是看书(尤指谭浩强老师的,这是来自众多社群小伙伴的建议),多动手才是王道。

    C语言豆子
  • 每天学习一点儿算法--递归

    递归是很多算法都使用的一种编程方法。听说递归是一种十分优雅的问题解决办法,可是对于初涉递归的我,还没有形成这种独特的体会。 学习使用递归的关键在于:如何将问题分...

    爱吃西瓜的番茄酱
  • 不规则图形的碰撞检测

    public static class CheckHit { public static bool CheckCollision(FrameworkEl...

    用户1172164
  • 冠军奖金50万!2020腾讯广告算法大赛广发“英雄帖”

    由腾讯广告主办,腾讯云、腾讯大数据、腾讯招聘及腾讯高校合作等合作伙伴联袂举办的2020腾讯广告算法大赛现已启动,5月31日前皆可报名参加!

    腾讯智能钛AI开发者
  • 冠军奖金50万!2020腾讯广告算法大赛广发“英雄帖”

    由腾讯广告主办,腾讯云、腾讯大数据、腾讯招聘及腾讯高校合作等合作伙伴联袂举办的2020腾讯广告算法大赛现已启动,5月31日前皆可报名参加! 百万奖金池重磅加码...

    腾讯大数据
  • 百万奖金池+鹅厂直通车,2020腾讯广告算法大赛火热报名中!

    2020腾讯广告算法大赛已正式发布,目前大赛处于火热报名中,欢迎扫描下方二维码或点击文末阅读原文进行报名。 报名链接: https://algo.qq.com...

    腾讯大讲堂

扫码关注云+社区

领取腾讯云代金券