相关疑难解决方法(0)

禁用GCC中的所有优化选项

使用GCC编译C程序的默认优化级别是-O0.根据GCC文档关闭所有优化.例如:

    gcc -O0 test.c 
Run Code Online (Sandbox Code Playgroud)

但是,要检查-O0是否真的关闭了所有优化.我执行了这个命令:

    gcc -Q -O0 --help=optimizers 
Run Code Online (Sandbox Code Playgroud)

在这里,我有点惊讶.我启用了大约50个选项.然后,我使用以下方法检查了传递给gcc的默认参数:

    gcc -v 
Run Code Online (Sandbox Code Playgroud)

我懂了:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-       
2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --      
enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --
program-suffix=-4.8 --enable-shared --enable-linker-build-id --
libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-
gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-
sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-
time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --
with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-
cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-
java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-
jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-
directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-
gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --
with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release 
--build=x86_64-linux-gnu …
Run Code Online (Sandbox Code Playgroud)

c optimization gcc performance-testing compiler-optimization

14
推荐指数
3
解决办法
6982
查看次数

当存在更高级别的语言时,为什么旧​​游戏会在汇编中编程?

我注意到大多数(如果不是全部)Nes/Atari等游戏都是在汇编中编码的,但当时存在C,COBOL和FORTRAN,我认为这样可以更容易编码吗?那么他们为什么选择这些可用的高级语言进行汇编呢?

assembly

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

在Windows上,试用版代码的运行速度比32位快32倍,而在Linux上则高于64位

我有一段代码,在Windows上运行速度比在linux上快2倍.这是我测量的时间:

g++ -Ofast -march=native -m64
    29.1123
g++ -Ofast -march=native
    29.0497
clang++ -Ofast -march=native
    28.9192
visual studio 2013 Debug 32b
    13.8802
visual studio 2013 Release 32b
    12.5569
Run Code Online (Sandbox Code Playgroud)

这似乎是一个太大的差异.

这是代码:

#include <iostream>
#include <map>
#include <chrono>
static std::size_t Count = 1000;

static std::size_t MaxNum = 50000000;

bool IsPrime(std::size_t num)
{
    for (std::size_t i = 2; i < num; i++)
    {
        if (num % i == 0)
            return false;
    }
    return true;
}

int main()
{
    auto start = std::chrono::steady_clock::now();
    std::map<std::size_t, bool> value; …
Run Code Online (Sandbox Code Playgroud)

c++ performance benchmarking x86 32bit-64bit

12
推荐指数
2
解决办法
931
查看次数

英特尔内在函数指南 - 延迟和吞吐量

有人可以解释英特尔内部指南中给出的延迟和吞吐量值吗?

我是否正确理解延迟是指令运行所需的时间单位,吞吐量是每个时间单位可以启动的指令数量?

如果我的定义是正确的,为什么某些指令的延迟在较新的CPU版本上更高(例如mulps)?

performance x86 sse intel intrinsics

12
推荐指数
1
解决办法
2256
查看次数

Java中的代码注入/汇编内联?

我知道Java是一种安全的语言,但是当需要矩阵计算时,我可以更快地尝试一下吗?

我在C++,Digital-Mars编译器和FASM中学习__asm {}.我想在Java中做同样的事情.如何在函数中内联汇编代码?这甚至可能吗?

像这样的东西(使用AVX支持CPU将数组的所有元素钳制到没有分支的值的矢量化循环):

JavaAsmBlock(
   # get pointers into registers somehow
   # and tell Java which registers the asm clobbers somehow
     vbroadcastss  twenty_five(%rip), %ymm0
     xor   %edx,%edx
.Lloop:                            # do {
    vmovups   (%rsi, %rdx, 4), %ymm1
    vcmpltps   %ymm1, %ymm0, %ymm2
    vblendvps  %ymm2, %ymm0, %ymm1, %ymm1  # TODO: use vminps instead
    vmovups    %ymm1, (%rdi, %rdx, 4)
    # TODO: unroll the loop a bit, and maybe handle unaligned output specially if that's common
    add         $32, %rdx
    cmp         %rcx, %rdx
    jb     .Lloop                  # } …
Run Code Online (Sandbox Code Playgroud)

java assembly inline-assembly

10
推荐指数
2
解决办法
2万
查看次数

如果我要在程序集中编写程序,那么这个HelloWorld汇编代码的哪些部分是必不可少的?

我有这个简短的你好世界计划:

#include <stdio.h>

static const char* msg = "Hello world";

int main(){
    printf("%s\n", msg);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用gcc将它编译成以下汇编代码:

    .file   "hello_world.c"
    .section    .rodata
.LC0:
    .string "Hello world"
    .data
    .align 4
    .type   msg, @object
    .size   msg, 4
msg:
    .long   .LC0
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    movl    msg, %eax
    movl    %eax, (%esp)
    call    puts
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa …
Run Code Online (Sandbox Code Playgroud)

c linux x86 assembly

10
推荐指数
1
解决办法
1149
查看次数

什么是微编码指令?

我看过很多参考微编码指令的文献.

这些是什么以及为什么使用它们?

cpu assembly cpu-architecture

10
推荐指数
1
解决办法
1560
查看次数

内联x86程序集中是否未定义整数溢出?

说我有以下C代码:

int32_t foo(int32_t x) {
    return x + 1;
}
Run Code Online (Sandbox Code Playgroud)

这是未定义的行为时x == INT_MAX.现在说我用内联汇编代替了:

int32_t foo(int32_t x) {
    asm("incl %0" : "+g"(x));
    return x;
}
Run Code Online (Sandbox Code Playgroud)

问题:内联汇编版本何时仍会调用未定义的行为x == INT_MAX?或者未定义的行为仅适用于C代码?

c x86 gcc undefined-behavior

10
推荐指数
1
解决办法
594
查看次数

128位值 - 从XMM寄存器到通用

我有几个与将XMM值移动到通用寄存器有关的问题.在SO上找到的所有问题都集中在相反的方面,即将gp寄存器中的值传递给XMM.

  1. 如何将XMM寄存器值(128位)移动到两个64位通用寄存器?

    movq RAX XMM1 ; 0th bit to 63th bit
    mov? RCX XMM1 ; 64th bit to 127th bit
    
    Run Code Online (Sandbox Code Playgroud)
  2. 同样,如何将XMM寄存器值(128位)移动到4个32位通用寄存器?

    movd EAX XMM1 ; 0th bit to 31th bit
    mov? ECX XMM1 ; 32th bit to 63th bit
    
    mov? EDX XMM1 ; 64th bit to 95th bit
    mov? ESI XMM1 ; 96th bit to 127 bit
    
    Run Code Online (Sandbox Code Playgroud)

x86 assembly sse

9
推荐指数
1
解决办法
2194
查看次数

充分利用kaby湖上的管道

(此处跟进代码复习问题,包含此循环上下文的更多详细信息.)


环境:

  • Windows 7 x64
  • VS 2017社区
  • 在Intel i7700k(kaby lake)上定位x64代码

我没有写很多汇编程序代码,当我这么做时,它要么足够短,要么足够简单,以至于我不必担心压缩它的最大数量.我的更复杂的代码通常用C编写,我让编译器的优化器担心延迟,代码对齐等.

但是在我目前的项目中,MSVC的优化器在关键路径中的代码上做得非常糟糕.所以...

我还没有找到一个好的工具,可以对x64汇编代码进行静态或运行时分析,以便消除停顿,改善延迟等等.我所拥有的只是VS分析器,它告诉我(大致)哪些指令花了最多的时间.墙上的时钟告诉我最近的变化是否使事情变得更好或更糟.

作为替代方案,我一直在通过Agner的文档进行操作,希望能从我的代码中挤出一些更多的信息.问题是,在你理解了所有这些工作之前,很难理解他的任何工作.但它的一部分是有意义的,我正在尝试应用我学到的东西.

记住这一点,这里是我最内层循环的核心(不足为奇)是VS剖析器说我花费的时间:

nottop:

vpminub ymm2, ymm2, ymm3 ; reset out of range values
vpsubb  ymm2, ymm2, ymm0 ; take a step

top:
vptest  ymm2, ymm1       ; check for out of range values
jnz nottop

; Outer loop that does some math, does a "vpsubb ymm2, ymm2, ymm0",
; and eventually jumps back to top
Run Code Online (Sandbox Code Playgroud)

是的,这几乎是一个依赖链的教科书示例:这个紧密的小循环中的每个指令都取决于前一个操作的结果.这意味着没有并行性,这意味着我没有充分利用处理器.

受Agner的"优化汇编程序"文档的启发,我想出了一种方法(希望)允许我一次做2个操作,所以我可以有一个管道更新ymm2和另一个更新(比如说)ymm8.

虽然这是一个非平凡的变化,所以在我开始撕掉所有东西之前,我想知道它是否可能有所帮助.看看Agner的kaby lake(我的目标)的"指令表",我看到:

        uops
        each
        port    Latency
pminub …
Run Code Online (Sandbox Code Playgroud)

performance assembly x86-64 micro-optimization avx2

8
推荐指数
1
解决办法
275
查看次数