首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在多线程应用程序中使用perf

在多线程应用程序中使用perf
EN

Stack Overflow用户
提问于 2022-03-05 09:32:42
回答 3查看 249关注 0票数 1

我使用串行OpenMP实现编写了一个基本的三循环矩阵乘法。对于相同大小(3200x3200),perf stat -a -e instructions,cycles显示:

串行

代码语言:javascript
复制
   265,755,992,060        instructions              #    0.71  insn per cycle
   375,319,584,656        cycles

      85.923380841 seconds time elapsed

并行(16个线程)

代码语言:javascript
复制
   264,524,937,733        instructions              #    0.30  insn per cycle
   883,342,095,910        cycles

      13.381343295 seconds time elapsed

在并行运行中,我希望循环的数量与串行运行大致相同。但事实并非如此。

有什么不同之处吗?

更新:

我用8和16个线程重新运行实验,因为处理器最多有16个线程。

代码语言:javascript
复制
Using 8 threads
Max nthread = 16
Total execution Time in seconds: 13.4407235400
MM execution Time in seconds: 13.3349801241

 Performance counter stats for 'system wide':

            906.51 Joules power/energy-pkg/
   264,995,810,457        instructions              #    0.59  insn per cycle
   449,772,039,792        cycles

      13.469242993 seconds time elapsed

代码语言:javascript
复制
Using 16 threads
Max nthread = 16
Total execution Time in seconds: 13.2618084711
MM execution Time in seconds: 13.1565077840

 Performance counter stats for 'system wide':

          1,000.39 Joules power/energy-pkg/
   264,309,881,365        instructions              #    0.30  insn per cycle
   882,881,366,456        cycles

      13.289234564 seconds time elapsed

正如你所看到的,墙上的时钟大致相同,但是16个线程的周期是8个线程的2倍。这意味着,随着更高的周期计数和较低的IPC,这是有可能保持与以前的墙上时钟与更多的线程。根据perf list的说法,这个事件是cpu-cycles OR cycles [Hardware event]。我想知道,一个核还是聚合N个核的平均周期?对此有什么评论吗?

EN

回答 3

Stack Overflow用户

发布于 2022-03-05 10:25:45

假设您的流程完全可伸缩,那么指令的数量将在所有内核之间共享,指令的总数也将相同。同样的情况也适用于循环的数量。但是,当您的过程不缩放时,指令的数量应该是相同的,但是循环的数量会增加。这通常是由于共享资源的争用导致了管道中的阻塞周期。

在并行实现中,内存层次结构没有得到有效的使用,因为并行实现会导致大量缓存丢失,在使用多个线程时可能会使L3或RAM饱和,因此内存暂停。如果使用同步多线程(也称为超线程),这也会导致这个问题,因为同一核心上的两个线程通常不会真正并行运行(内核的某些部分在线程之间共享)。

票数 3
EN

Stack Overflow用户

发布于 2022-03-05 10:24:07

不断的指令是有意义的;不管这些指令是否都运行在同一个核心上,总工作量也是一样的。

您正在使用SMT (例如超线程)吗?当相同的物理核将其时间划分为两个逻辑核时,IPC就会下降。对于某些程序扩展,SMT提高了总体吞吐量;对于缓存绑定程序(如天真的matmul),有两个线程竞争相同的L1/L2缓存伤害。

否则,如果这是16个物理内核,您可能会看到L3争用的效果,而单个线程本身并不拥有所有的L3。

无论如何,由于适当的缓存阻塞,SMT通常会损害matmul /稠密线性代数的总体吞吐量。一个物理内核可以通过一个具有良好调优代码的线程来饱和ALU工作,因此对每个内核缓存的争用只会造成伤害。(但多线程肯定会帮助整个时间,就像你的情况一样。)缓存阻塞的matmul通常是5个嵌套循环,如关于内存,每个程序员都应该知道些什么?末尾的示例所示。

阿格纳·福格(https://agner.org/optimize/)在他的微弓PDF中也提到了超线程对一些工作负载的伤害。

票数 1
EN

Stack Overflow用户

发布于 2022-03-05 14:57:20

矩阵-矩阵乘法是一个典型的运算,理论上有大量的缓存重用,因此可以运行接近峰值速度。除了标准的三循环实现之外,高效使用缓存的优化实现实际上有六个层次:三个循环中的每一个都被平铺,您需要交换循环并正确设置倾斜。这不是小事一桩。

因此,您的实现基本上不使用缓存。也许您可以从L3缓存中得到一些效果,但是,如果有足够的问题大小,肯定不是L1,也可能不是L2。换句话说:你是带宽受限的。问题是,你可能有16个核心,但你没有足够的带宽来满足所有这些。

我必须说,你的6-7的因素有点令人失望,但也许你的架构没有足够的带宽。我知道,对于顶级节点,我期望的是12,但为什么不测试一下呢?编写一个基准测试,它只对内存中的数据进行流处理。矢量-矢量加法。然后看看你能得到多少个线速度。

为了回应你在答覆中提出的几点:

  1. 加速是不错的,但你应该看看性能。Matmul可以以峰值的90+ %运行。使用MKL或任何优化的BLAS,并将其与所得到的进行比较。
  2. SIMD在加速比方面没有任何区别,只是在绝对性能上。
  3. 在那个i,j,k更新中,您没有说明哪个索引在内部循环中。无论如何,让编译器生成一个优化报告。您会发现编译器是那么聪明,并且很可能通过交换循环来实现矢量化。
  4. 在内核中,FP延迟并不像您的内核那样简单。在预取和无序执行以及诸如此类的操作之间,您实际上不必担心延迟。

真的:你的表现是带宽有限的。但是你只是在测量加速比,所以你并没有真正看到这一点,除了使用你所有的核心将饱和你的带宽和限制你的加速比。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71361046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档