【发布时间】:2020-10-19 04:46:25
【问题描述】:
我一直在为 3D 渲染引擎使用 CPU 的方式而苦恼。大多数资源都说你拥有的线程越多,性能就越好。让我们考虑一下 4 核和 8 线程 CPU,如果 2 个线程都使用相同的资源(核心)并执行相同的渲染像素的工作,并且 CPU 正在满载最大频率工作,那么两者之间的区别是什么?在单核和单线程上进行所有计算?速度会不会下降?
【问题讨论】:
标签: multithreading performance rendering cpu
我一直在为 3D 渲染引擎使用 CPU 的方式而苦恼。大多数资源都说你拥有的线程越多,性能就越好。让我们考虑一下 4 核和 8 线程 CPU,如果 2 个线程都使用相同的资源(核心)并执行相同的渲染像素的工作,并且 CPU 正在满载最大频率工作,那么两者之间的区别是什么?在单核和单线程上进行所有计算?速度会不会下降?
【问题讨论】:
标签: multithreading performance rendering cpu
SMT/超线程提供了一个小的改进,但在大多数工作负载上它只有个位数的百分比。大部分收益来自两件事:
在高并发工作负载上减少上下文切换
至少有一个线程需要的数据在 CPU 缓存中的可能性更高。如果核心上只有一个线程,核心必须等待数据来自 RAM。如果有 2 个线程,那么第二个线程的数据有可能在缓存中,这样核心就可以在其他数据来自 RAM 时执行一些高效的操作。
【讨论】:
SMT 用于利用内核的所有 EU(执行单元)。
如果您的 CPU 可以在一个时钟内进行两次加法,但您的代码具有以下形式:
add r0, r0, r1 #r0 = r0 + r1
add r0, r0, r2
add r0, r0, r3
...
那么你不能做得比每个时钟一个加法更好,因为每条指令都需要前一条的输出。
这称为依赖链,软件通常有很多依赖链。
优秀的编译器编写可以利用更多并行性的代码,例如将上面的总和写为两个子和的总和(然后可以并行进行)。
但是编写这种代码很困难,并且极度依赖于特定的微架构(阅读:CPU 型号)。
这是一个非常简单的例子,在两个线程之间共享核心资源有其自身的好处,如果一个线程停止,另一个线程可以接管 EU,而不是让它们闲置。
那么,如果您可以节省“一些”晶体管,为什么不添加一个新的执行流程呢?那是 SMT。
正如您所注意到的,SMT 不适合非常优化的代码。如果所有的 EU 都可以被一个线程最优地利用,那么再有一个是没有用的。
但您无法判断(或只是假设)软件已针对您的 CPU 进行了最佳编译,因此值得尝试使用 SMT。
顺便说一句,当人们说“线程越多越好”时,他们通常的意思是“更多的 EU”,对于大多数软件来说,这等于“更多的线程”(因为大多数软件可以在一个线程中使用所有的 EU)但是对于一个小它等于“更多核心”的百分比。
一般来说,做一个基准测试。
碰巧我不得不编写一些破解程序,我总是通过在每个内核的线程和所有线程上固定多个实例来测试它们,看看是否有改进。
当我使用手工制作的程序集和库时,没有。
【讨论】: