这个问题在我的问题上继续(根据神秘的建议):
继续我的问题,当我使用压缩指令而不是标量指令时,使用内在函数的代码看起来非常相似:
for(int i=0; i<size; i+=16) {
y1 = _mm_load_ps(output[i]);
…
y4 = _mm_load_ps(output[i+12]);
for(k=0; k<ksize; k++){
for(l=0; l<ksize; l++){
w = _mm_set_ps1(weight[i+k+l]);
x1 = _mm_load_ps(input[i+k+l]);
y1 = _mm_add_ps(y1,_mm_mul_ps(w,x1));
…
x4 = _mm_load_ps(input[i+k+l+12]);
y4 = _mm_add_ps(y4,_mm_mul_ps(w,x4));
}
}
_mm_store_ps(&output[i],y1);
…
_mm_store_ps(&output[i+12],y4);
}
Run Code Online (Sandbox Code Playgroud)
这个内核的测量性能是每个周期大约5.6个FP操作,虽然我预计它将是标量版本性能的4倍,即每个周期4.1,6 = 6,4 FP操作.
考虑到权重因素的移动(感谢指出这一点),时间表如下:

看起来调度没有改变,尽管在操作之后有一条额外的指令movss将标量权重值移动到XMM寄存器然后用于shufps在整个向量中复制这个标量值.似乎权重向量已经准备好用于mulps考虑从加载到浮点域的切换延迟,因此这不应该产生任何额外的延迟.
此内核中使用的movaps(对齐,打包的移动)addps和mulps指令(使用汇编代码检查)与其标量版本具有相同的延迟和吞吐量,因此这不会产生任何额外的延迟.
有没有人知道每8个周期的额外周期花费在哪里,假设这个内核可以获得的最大性能是每个周期6.4个FP运算并且每个周期运行5.6个FP运算?
顺便说一下,这是实际装配的样子:
…
Block x:
movapsx (%rax,%rcx,4), %xmm0
movapsx 0x10(%rax,%rcx,4), %xmm1
movapsx 0x20(%rax,%rcx,4), %xmm2
movapsx 0x30(%rax,%rcx,4), %xmm3
movssl …Run Code Online (Sandbox Code Playgroud) 我尝试在我的计算机上安装英特尔MPI基准测试,我收到此错误:
fork: retry: Resource temporarily unavailable
Run Code Online (Sandbox Code Playgroud)
然后,当我跑步ls和top命令时,我再次收到此错误.
导致此错误的原因是什么?
配置我的机器:
Dell precision T7500
Scientific Linux release 6.2 (Carbon)
Run Code Online (Sandbox Code Playgroud) 根据我的阅读,它用于修复CPU中的错误而无需修改BIOS.根据我对汇编的基本知识,我知道汇编指令在内部由CPU分成微码并相应地执行.但是,在系统启动并运行时,intel会以某种方式提供访问以进行一些更新.
有人有更多的信息吗?有没有关于微码可以做些什么以及如何使用它们的文件?
编辑:我已经阅读了维基百科的文章:没有弄清楚我怎么能自己写一些,以及它会有什么用处.
双值存储更高的精度并且是浮点数的两倍,但英特尔CPU是否针对浮点数进行了优化?
也就是说,双重操作与+, - ,*和/的浮点运算一样快或快.
对于64位架构,答案是否会改变?
在谈论多线程时,线程似乎通常被视为平等——与主线程相同,但在它旁边运行。
然而,在某些新处理器上,例如Apple M1芯片和即将推出的 Intel Alder Lake系列,并非所有线程的性能都与这些芯片的性能相同,因为这些芯片具有独立的高性能内核和高效、速度较慢的内核。
这并不是说还没有诸如超线程之类的东西,但这似乎对性能有更大的影响。
有没有办法查询std::thread的属性并强制它们在 C++ 中运行的核心?
正如这个问题所示,使用g ++,我能做到g++ -S -masm=intel test.cpp.另外,对于clang,我可以这样做clang++ -S test.cpp,但-masm=intelclang(warning argument unused during compilation: -masm=intel)不支持.如何使用clang获取intel语法?
我可以理解如何编写一个使用多个进程或线程的程序:fork()一个新进程并使用IPC,或创建多个线程并使用这些通信机制.
我也理解上下文切换.也就是说,只有一次CPU,操作系统为每个进程安排时间(并且有大量的调度算法),从而我们实现了同时运行多个进程.
现在我们拥有多核处理器(或多处理器计算机),我们可以在两个独立的核心上同时运行两个进程.
我的问题是关于最后一个场景:内核如何控制进程运行的核心?哪些系统调用(在Linux,甚至是Windows中)在特定核心上安排进程?
我问的原因是:我正在为学校开展一个项目,我们将在那里探索最近的计算主题 - 我选择了多核架构.关于如何在这种环境中编程(如何监视死锁或竞争条件)似乎有很多材料,但在控制各个核心本身方面却没有太多.我希望能够编写一些演示程序并提供一些汇编指令或C代码,以实现"看,我在第二个内核上运行无限循环,查看该特定内核的 CPU利用率峰值" .
任何代码示例?还是教程?
编辑:为了澄清 - 很多人都说这是操作系统的目的,应该让操作系统处理这个问题.我完全同意!但那时我所要求的(或试图感受到)是操作系统实际上做的事情.不是调度算法,而是"一旦选择了核心,必须执行哪些指令才能让核心开始获取指令?"
我正在尝试创建一个自旋锁的哑版.浏览网页时,我在x86中遇到了一个名为"PAUSE"的汇编指令,该指令用于向处理器提供当前在此CPU上运行自旋锁的提示.英特尔手册和其他可用信息说明了这一点
在大多数情况下,处理器使用此提示来避免内存顺序违规,从而大大提高了处理器性能.因此,建议在所有自旋等待循环中放置PAUSE指令.文档还提到"等待(一些延迟)"是指令的伪实现.
上段的最后一行很直观.如果我没有成功抓住锁,我必须等待一段时间然后再抓住锁.
但是,在旋转锁定的情况下,内存顺序违规是什么意思?"内存顺序违规"是否意味着旋转锁定后指令的错误推测加载/存储?
关于堆栈溢出之前已经询问了自旋锁定问题但是内存顺序违规问题仍未得到解决(至少对于我的理解).
请阅读这篇引人入胜的文章,了解使用非规范化浮点数(浮点数非常接近0)可以获得的英特尔CPU上20x-200x减速.
SSE有一个选项可以将这些选项舍入为0,在遇到这样的浮点值时恢复性能.
C#apps如何处理这个问题?是否有启用/禁用选项_MM_FLUSH_ZERO?
LOOP(英特尔参考手动输入)递减ecx/rcx,然后如果非零则跳转.这很慢,但是英特尔不能廉价地把它变得很快吗? dec/jnz已经将宏观融合成 Sandybridge家族的一个 uop; 唯一的区别是设置标志.
loop关于各种微体系结构,来自Agner Fog的说明表:
Bulldozer-family/Ryzen:1 m-op(与宏观融合测试和分支相同,或者jecxz)
P4:4次(相同jecxz)
loope/ loopne).吞吐量= 4c(loop)或7c(loope/ne).loope/ loopne). 吞吐量=每5个循环一个,这是将循环计数器保留在内存中的瓶颈!jecxz只有2 uops,吞吐量与普通吞吐量相同jcc难道解码器不能像lea rcx, [rcx-1]/ 那样解码jrcxz吗?这将是3 uops.至少那是没有地址大小前缀的情况,否则它必须使用ecx和截断RIP,EIP如果跳转; 也许奇怪的地址大小选择控制减量的宽度解释了许多uops?
或者更好,只需将其解码为不设置标志的融合分支和分支? dec ecx …