我正在尝试分析和优化算法,我想了解缓存对各种处理器的具体影响.对于最近的Intel x86处理器(例如Q9300),很难找到有关缓存结构的详细信息.特别是,发布处理器规范的大多数网站(包括Intel.com)都不包含对L1缓存的任何引用.这是因为L1缓存不存在还是由于某种原因被认为不重要?是否有关于消除L1缓存的文章或讨论?
[编辑]在运行各种测试和诊断程序(主要是在下面的答案中讨论的那些)后,我得出结论,我的Q9300似乎有一个32K L1数据缓存.我仍然没有找到一个明确的解释,为什么这些信息很难得到.我目前的工作理论是,L1缓存的细节现在被英特尔视为商业机密.
请解释一下之间的区别x86
,x32
和x64
?它有点令人困惑x86
,x32
因为大多数时候32位程序在x86上运行...
我对使用Sandy-Bridge和Haswell可以完成每个核心每个循环的触发器感到困惑.据我所知,对于SSE,每个核心每个周期应该为4个触发器,对于AVX/AVX2,每个核心每个周期应该有8个触发器.
这似乎在这里得到验证, 如何实现每个周期4个FLOP的理论最大值? ,这里, Sandy-Bridge CPU规范.
然而,下面的链接似乎表明,Sandy-bridge每个核心每个周期可以执行16个触发器,每个核心每个循环使用Haswell 32个触发器 http://www.extremetech.com/computing/136219-intels-haswell-is-an-前所未有-threat-to-nvidia-amd.
谁可以给我解释一下这个?
编辑:我现在明白为什么我感到困惑.我认为术语FLOP仅指单浮点(SP).我现在看到如何在每个循环中实现理论最大值4 FLOP的测试?实际上是双浮点(DP),因此它们为SSE实现4个DP FLOP /周期,为AVX实现8个DP FLOP /周期.在SP上重做这些测试会很有趣.
关于多核CPU或多处理器系统中使用的高速缓存存储器,我有几个问题.(虽然与编程没有直接关系,但是当一个人为多核处理器/多处理器系统编写软件时会产生很多反响,因此在这里问!)
在多处理器系统或多核处理器(Intel Quad Core,Core two Duo等......)中,每个cpu核心/处理器都有自己的缓存(数据和程序缓存)吗?
一个处理器/核心可以访问彼此的高速缓存,因为如果允许它们访问彼此的高速缓存,那么我认为可能存在较少的高速缓存未命中,如果特定处理器高速缓存没有一些数据但是其他一些处理器的缓存可能有它,从而避免从内存读入第一个处理器的缓存?这个假设是否有效且真实?
允许任何处理器访问其他处理器的高速缓冲存储器会有任何问题吗?
我知道 Numpy 可以使用不同的后端,如 OpenBLAS 或 MKL。我还读到 MKL 针对英特尔进行了大量优化,所以通常人们建议在 AMD 上使用 OpenBLAS,对吗?
我使用以下测试代码:
import numpy as np
def testfunc(x):
np.random.seed(x)
X = np.random.randn(2000, 4000)
np.linalg.eigh(X @ X.T)
%timeit testfunc(0)
Run Code Online (Sandbox Code Playgroud)
我已经使用不同的 CPU 测试了这段代码:
我在所有三个系统上都使用相同的 Conda 环境。根据np.show_config()
,Intel 系统为 Numpy …
我最近一直在问自己的一个真正的问题是,设计选择带来了x86是一个小端架构而不是大端架构?
我使用英特尔®架构代码分析器(IACA)发现了一些意想不到的东西(对我而言).
以下指令使用[base+index]
寻址
addps xmm1, xmmword ptr [rsi+rax*1]
Run Code Online (Sandbox Code Playgroud)
根据IACA没有微熔丝.但是,如果我用[base+offset]
这样的
addps xmm1, xmmword ptr [rsi]
Run Code Online (Sandbox Code Playgroud)
IACA报告它确实融合了.
英特尔优化参考手册的第2-11节给出了以下"可以由所有解码器处理的微融合微操作"的示例
FADD DOUBLE PTR [RDI + RSI*8]
Run Code Online (Sandbox Code Playgroud)
和Agner Fog的优化装配手册也给出了使用[base+index]
寻址的微操作融合的例子.例如,请参见第12.2节"Core2上的相同示例".那么正确的答案是什么?
我的应用程序中有一个乘法添加内核,我想提高它的性能.
我使用英特尔酷睿i7-960(3.2 GHz时钟)并已使用SSE内在函数手动实现内核,如下所示:
for(int i=0; i<iterations; i+=4) {
y1 = _mm_set_ss(output[i]);
y2 = _mm_set_ss(output[i+1]);
y3 = _mm_set_ss(output[i+2]);
y4 = _mm_set_ss(output[i+3]);
for(k=0; k<ksize; k++){
for(l=0; l<ksize; l++){
w = _mm_set_ss(weight[i+k+l]);
x1 = _mm_set_ss(input[i+k+l]);
y1 = _mm_add_ss(y1,_mm_mul_ss(w,x1));
…
x4 = _mm_set_ss(input[i+k+l+3]);
y4 = _mm_add_ss(y4,_mm_mul_ss(w,x4));
}
}
_mm_store_ss(&output[i],y1);
_mm_store_ss(&output[i+1],y2);
_mm_store_ss(&output[i+2],y3);
_mm_store_ss(&output[i+3],y4);
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用压缩的fp向量来提高性能,我已经成功完成了,但我想知道为什么单个标量代码无法满足处理器的峰值性能.
我的机器上的这个内核的性能是每个周期大约1.6个FP操作,而每个周期最大的是2个FP操作(因为FP add + FP mul可以并行执行).
如果我对研究生成的汇编代码是正确的,理想的时间表将如下所示,其中mov
指令需要3个周期,从依赖指令的加载域到FP域的切换延迟需要2个周期,FP乘以4个循环,FP添加需要3个循环.(注意,乘法 - > add的依赖性不会导致任何切换延迟,因为操作属于同一个域).
根据测量的性能(最大理论性能的约80%),每8个周期有大约3个指令的开销.
我想要:
当然,存在缓存未命中和数据错位的问题,这可能会增加移动指令的延迟,但是还有其他因素可以在这里发挥作用吗?像寄存器读取档位或什么?
我希望我的问题很明确,在此先感谢您的回复!
更新:内循环的程序集如下所示:
...
Block 21:
movssl (%rsi,%rdi,4), %xmm4
movssl (%rcx,%rdi,4), %xmm0
movssl 0x4(%rcx,%rdi,4), %xmm1 …
Run Code Online (Sandbox Code Playgroud) 在最后几天,我观察到我的新工作站的行为,我无法解释.对此问题进行一些研究,INTEL Haswell架构以及当前的Skylake Generation 可能存在一个错误.
在编写可能的错误之前,让我先概述一下使用的硬件,程序代码和问题本身.
我目前正在运行Ubuntu 15.04 64位桌面版,安装最新更新和内核.除了使用这台机器开发CUDA内核和东西,我最近测试了一个纯C程序.该程序正在对相当大的输入数据集进行改进的ART.因此代码执行一些FFT并耗费相当长的时间来完成计算.我目前无法发布/链接到任何源代码,因为这是正在进行的无法发布的研究.如果您不熟悉ART,只需简单解释它的作用.ART是一种用于重建从计算机断层摄影机接收的数据以获得用于诊断的可见图像的技术.因此,我们的代码版本重建了大小为2048x2048x512的数据集.到目前为止,没有什么特别的,也没有涉及火箭科学.经过几个小时的调试和修复错误后,代码在参考结果上进行了测试,我们可以确认代码是否正常工作.代码使用的唯一库是标准的math.h
.没有特殊的编译参数,没有额外的库可能带来额外的问题.
该代码使用一种技术来实现ART,以最小化重建数据所需的投影.因此,我们假设我们可以重建一个涉及25个投影的数据片.代码以12个内核上完全相同的输入数据启动.请注意,实现不是基于多线程,目前启动了12个程序实例.我知道这不是最好的方法,涉及正确的线程管理是强烈建议,这已经在改进列表:)
因此,当我们运行至少两个程序实例(每个实例在一个单独的数据切片上工作)时,结果是一些预测是随机的错误.为了让您了解结果,请参阅表1.请注意,输入数据始终相同.
只运行一个涉及CPU核心的代码实例,结果都是正确的.即使执行一些涉及一个CPU内核的运行,结果仍然是正确的.仅涉及至少两个或更多核心会生成结果模式,如表1所示.
好吧,花了相当长的时间来了解究竟出了什么问题.所以我们完成了整个代码,大多数问题都是以一个小的实现错误开始的.但是,嗯,没有(当然我们不能证明没有错误也不能保证它).为验证我们的代码,我们使用了两台不同的机器:
出人意料的是,这两个MACHINE1和机器2产生总是正确的结果.即使使用所有CPU核心,结果仍然是正确的.每台机器上超过50次运行甚至没有错误的结果.代码是在没有优化选项或任何特定编译器设置的每台目标机器上编译的.因此,阅读新闻导致以下发现:
因此,在Prime95和Mersenne社区的人们 似乎是第一批发现和识别这个讨厌的bug的人.引用的帖子和新闻支持怀疑,这个问题只存在于繁重的工作量下.根据我的观察,我可以确认这种行为.
intel ×10
performance ×4
x86 ×4
assembly ×3
cpu ×2
cpu-cache ×2
64-bit ×1
architecture ×1
att ×1
avx ×1
avx2 ×1
c ×1
endianness ×1
flops ×1
iaca ×1
instructions ×1
numpy ×1
processor ×1
python ×1