相关疑难解决方法(0)

处理器可以同时进行内存和算术运算吗?

在汇编程序和处理程序的研究中,有一件事把我带出来,如何完成指令:

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 assembly cpu-architecture risc

4
推荐指数
1
解决办法
151
查看次数

使用 LEA 相对于 MOV 在从 C++ 编译的程序集中传递参数的优势

我正在尝试编译 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)

godbolt.org 上的结果

我不明白的是,为什么编译器在这个例子中选择使用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)

c++ assembly x86-64 micro-optimization visual-c++

4
推荐指数
2
解决办法
182
查看次数

x86/x64 asm中的指令重新排序 - 使用最新CPU进行性能优化

在最近的高端Intel CPU上重新排序x64(x86-64)指令可以获得多少性能提升.在非常时间紧迫的情况下值得打扰吗?

我还想知道通过改变寄存器使用/使用额外的寄存器(如果空闲)来获得收益的可能性,以便在某些奇怪的情况下允许更长距离的代码移动?

optimization x86 assembly x86-64 micro-optimization

3
推荐指数
1
解决办法
553
查看次数

两个看似相同的汇编代码之间的性能差异

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)

performance x86 intel micro-optimization iaca

3
推荐指数
1
解决办法
196
查看次数

“perf annotate”内存加载/存储时间报告不一致

我很难解释英特尔性能事件报告。

\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}\n
Run Code Online (Sandbox Code Playgroud)\n

我用gcc -O2以下命令编译它并运行perf

\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 …
Run Code Online (Sandbox Code Playgroud)

performance assembly x86-64 micro-optimization perf

2
推荐指数
1
解决办法
394
查看次数