在汇编程序和处理程序的研究中,有一件事把我带出来,如何完成指令:
add mem, 1
Run Code Online (Sandbox Code Playgroud)
在我的脑海中,处理器无法加载内存值并在同一指令期间处理算术运算.所以我觉得它发生在:
mov reg, mem
add reg, 1
mov mem, reg
Run Code Online (Sandbox Code Playgroud)
如果我考虑使用RISC Pipeline的处理器,我们可以观察一些停顿.对于简单的指令来说,这是令人惊讶的i++:
| Fetch | Decode | Exec | Memory | WriteB |
| Fetch | | | Decode | Exec | Memory | WriteB |
| Fetch | | | | Decode | Exec | Memory | WriteB |
Run Code Online (Sandbox Code Playgroud)
(正如我在Patterson的书" 计算机体系结构:定量方法"中所读到的,寄存器在解码 uOp,存储/加载到存储器uOp中读取,我们允许自己在存储器uOp中获取寄存器的值.)
我对吗?还是现代处理器有更具效的方法来做到这一点?
我正在尝试编译 C++ 代码时将参数传递给函数的方式。我尝试使用x64 msvc 19.35/latest编译器编译以下 C++ 代码以查看生成的程序集:
#include <cstdint>
void f(std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t);
void test()
{
f(1, 2, 3, 4);
}
Run Code Online (Sandbox Code Playgroud)
并得到这个结果:
void test(void) PROC
mov edx, 2
lea r9d, QWORD PTR [rdx+2]
lea r8d, QWORD PTR [rdx+1]
lea ecx, QWORD PTR [rdx-1]
jmp void f(unsigned int,unsigned int,unsigned int,unsigned int)
void test(void) ENDP
Run Code Online (Sandbox Code Playgroud)
我不明白的是,为什么编译器在这个例子中选择使用lea而不是简单的。mov我了解它的机制lea以及它如何在每个寄存器中产生正确的值,但我希望有更简单的东西,例如:
void test(void) PROC
mov ecx, 1
mov edx, 2
mov r8d, 3
mov r9d, 4 …Run Code Online (Sandbox Code Playgroud) 在最近的高端Intel CPU上重新排序x64(x86-64)指令可以获得多少性能提升.在非常时间紧迫的情况下值得打扰吗?
我还想知道通过改变寄存器使用/使用额外的寄存器(如果空闲)来获得收益的可能性,以便在某些奇怪的情况下允许更长距离的代码移动?
tl; dr:我有两个功能相同的C代码,我用Clang编译(事实上它的C代码并不重要;只有汇编很有意思),IACA告诉我一个应该更快,但我不明白为什么,我的基准测试显示两个代码的性能相同.
我有以下的C代码(忽略#include "iacaMarks.h",IACA_START,IACA_END现在):
ref.c:
#include "iacaMarks.h"
#include <x86intrin.h>
#define AND(a,b) _mm_and_si128(a,b)
#define OR(a,b) _mm_or_si128(a,b)
#define XOR(a,b) _mm_xor_si128(a,b)
#define NOT(a) _mm_andnot_si128(a,_mm_set1_epi32(-1))
void sbox_ref (__m128i r0,__m128i r1,__m128i r2,__m128i r3,
__m128i* r5,__m128i* r6,__m128i* r7,__m128i* r8) {
__m128i r4;
IACA_START
r3 = XOR(r3,r0);
r4 = r1;
r1 = AND(r1,r3);
r4 = XOR(r4,r2);
r1 = XOR(r1,r0);
r0 = OR(r0,r3);
r0 = XOR(r0,r4);
r4 = XOR(r4,r3);
r3 = XOR(r3,r2);
r2 = OR(r2,r1);
r2 = XOR(r2,r4);
r4 = NOT(r4); …Run Code Online (Sandbox Code Playgroud) 我很难解释英特尔性能事件报告。
\n考虑以下主要读/写内存的简单程序:
\n#include <stdint.h>\n#include <stdio.h>\n\nvolatile uint32_t a;\nvolatile uint32_t b;\n\nint main() {\n printf("&a=%p\\n&b=%p\\n", &a, &b);\n for(size_t i = 0; i < 1000000000LL; i++) {\n a ^= (uint32_t) i;\n b += (uint32_t) i;\n b ^= a;\n }\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n我用gcc -O2以下命令编译它并运行perf:
#include <stdint.h>\n#include <stdio.h>\n\nvolatile uint32_t a;\nvolatile uint32_t b;\n\nint main() {\n printf("&a=%p\\n&b=%p\\n", &a, &b);\n for(size_t i = 0; i < 1000000000LL; i++) {\n a ^= (uint32_t) i;\n b += (uint32_t) i;\n b ^= a;\n }\n …Run Code Online (Sandbox Code Playgroud) assembly ×4
x86-64 ×3
performance ×2
x86 ×2
c ×1
c++ ×1
iaca ×1
intel ×1
optimization ×1
perf ×1
risc ×1
visual-c++ ×1