【问题标题】:Measuring CUDA Allocation time测量 CUDA 分配时间
【发布时间】:2015-07-07 00:20:05
【问题描述】:

我需要测量使用new 分配普通CPU 内存和调用cudaMallocManaged 之间的时间差。我们正在使用统一内存,并试图找出将事物切换到cudaMallocManaged 的权衡。 (内核似乎运行得慢了很多,可能是由于缺少缓存或其他原因。)

无论如何,我不确定为这些分配计时的最佳方式。 boost 的process_real_cpu_clockprocess_user_cpu_clockprocess_system_cpu_clock 之一会给我最好的结果吗?还是我应该只使用 C++11 中的常规系统时间调用?或者我应该使用 cudaEvent 的东西来计时?

我认为我不应该使用 cuda 事件,因为它们用于计时 GPU 进程,并且不能准确地计时 cpu 调用(如果我错了,请纠正我。)如果我可以只在mallocManaged 一个,在计时new 调用时,最准确的比较是什么?我只是对内存分配和时间知之甚少。由于 boost 和 nvidia 的劣质文档,我阅读的所有内容似乎都让我更加困惑。

【问题讨论】:

    标签: c++ c++11 boost cuda


    【解决方案1】:

    您可以使用 CUDA 事件来测量在主机中执行的函数的时间。

    cudaEventElapsedTime 计算两个事件之间经过的时间(以毫秒为单位,分辨率约为 0.5 微秒)。

    阅读更多:http://docs.nvidia.com/cuda/cuda-runtime-api/index.html

    此外,如果您也对计时内核执行时间感兴趣,您会发现 CUDA 事件 API 会自动阻止您的代码执行并等待任何异步调用结束(如内核调用)。

    在任何情况下,您都应该使用相同的指标(始终使用 CUDA 事件、提升或您自己的时间)来确保相同的分辨率和开销。

    CUDA 工具包附带的分析器“nvprof”可能有助于理解和优化 CUDA 应用程序的性能。

    阅读更多:http://docs.nvidia.com/cuda/profiler-users-guide/index.html

    【讨论】:

    • 我不确定 cudaEvent 计时器是否正常工作,因为它报告说使用 new 制作我的数组比使用 cuMallocManaged 花费的时间长 80 倍,这似乎是错误的。 (P.S. 感谢您指出分析器。看起来它对于分配后的所有时间非常有用。)
    • 您应该添加一个显示该行为的最小示例。这可能有助于获得更好的答案。
    • 如果默认流中已经有一个(异步)内核在执行,并且我将 cudaEventRecord 添加到默认流的 FIFO 中,cudaEvent 将阻塞,直到内核在“注册”之前完成,对?换句话说,它不会捕获内核运行时发生的 CPU 执行时间,对吧?
    【解决方案2】:

    我推荐:

    auto t0 = std::chrono::high_resolution_clock::now();
    // what you want to measure
    auto t1 = std::chrono::high_resolution_clock::now();
    std::cout << std::chrono::duration<double>(t1-t0).count() << "s\n";
    

    这将输出以秒为单位的差异,表示为double

    分配算法通常会随着它们的发展而自我优化。也就是说,第一次分配通常比第二次更昂贵,因为内存缓存是在第一次分配时创建的,以期待第二次。因此,您可能希望将您正在计时的事情放在一个循环中,并对结果进行平均。

    std::chrono::high_resolution_clock 的一些实现并不那么引人注目,但随着时间的推移正在改进。您可以通过以下方式评估您的实施:

    auto t0 = std::chrono::high_resolution_clock::now();
    auto t1 = std::chrono::high_resolution_clock::now();
    std::cout << std::chrono::duration<double>(t1-t0).count() << "s\n";
    

    也就是说,您的实现能以多快的速度获得当前时间?如果它很慢,两个连续的调用将显示出很长的时间间隔。在我的系统上(在 -O3 处),此输出顺序为:

    1.2e-07s
    

    这意味着我可以对大约 1 微秒的时间进行计时。为了获得比这更精细的测量结果,我必须遍历许多操作,然后除以操作数,如果这很重要,则减去循环开销。

    如果您对std::chrono::high_resolution_clock 的实现似乎不满意,您可以构建自己的chrono 时钟along the lines of this。缺点显然是有点不便携。但是,您可以免费获得 std::chrono durationtime_point 基础架构(时间算术和单位转换)。

    【讨论】:

    • 我似乎在 9e-7 秒左右。循环通话可能会让我足够接近我想要的。我只是不确定以这种方式计时 cuda 分配是否会捕获某种实际上不应该计时的同步开销。
    猜你喜欢
    • 2012-09-30
    • 2012-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 2013-05-07
    • 2012-05-22
    相关资源
    最近更新 更多