相关疑难解决方法(0)

用64位替换32位循环计数器会引入疯狂的性能偏差

我一直在寻找最快的方法来处理popcount大数据.我遇到了一个很奇怪的效果:改变从循环变量unsigneduint64_t50%在我的电脑上所做的性能下降.

基准

#include <iostream>
#include <chrono>
#include <x86intrin.h>

int main(int argc, char* argv[]) {

    using namespace std;
    if (argc != 2) {
       cerr << "usage: array_size in MB" << endl;
       return -1;
    }

    uint64_t size = atol(argv[1])<<20;
    uint64_t* buffer = new uint64_t[size/8];
    char* charbuffer = reinterpret_cast<char*>(buffer);
    for (unsigned i=0; i<size; ++i)
        charbuffer[i] = rand()%256;

    uint64_t count,duration;
    chrono::time_point<chrono::system_clock> startP,endP;
    {
        startP = chrono::system_clock::now();
        count = 0;
        for( unsigned k = 0; k < …
Run Code Online (Sandbox Code Playgroud)

c++ performance x86 assembly compiler-optimization

1370
推荐指数
9
解决办法
15万
查看次数

内联汇编语言比本机C++代码慢吗?

我试图比较内联汇编语言和C++代码的性能,所以我写了一个函数,添加两个大小为2000的数组,持续100000次.这是代码:

#define TIMES 100000
void calcuC(int *x,int *y,int length)
{
    for(int i = 0; i < TIMES; i++)
    {
        for(int j = 0; j < length; j++)
            x[j] += y[j];
    }
}


void calcuAsm(int *x,int *y,int lengthOfArray)
{
    __asm
    {
        mov edi,TIMES
        start:
        mov esi,0
        mov ecx,lengthOfArray
        label:
        mov edx,x
        push edx
        mov eax,DWORD PTR [edx + esi*4]
        mov edx,y
        mov ebx,DWORD PTR [edx + esi*4]
        add eax,ebx
        pop edx
        mov [edx + esi*4],eax
        inc esi
        loop label
        dec edi …
Run Code Online (Sandbox Code Playgroud)

c c++ performance assembly

174
推荐指数
14
解决办法
5万
查看次数

在x86汇编中将寄存器设置为零的最佳方法是什么:xor,mov或?

以下所有说明都做同样的事情:设置%eax为零.哪种方式最佳(需要最少的机器周期)?

xorl   %eax, %eax
mov    $0, %eax
andl   $0, %eax
Run Code Online (Sandbox Code Playgroud)

optimization performance x86 assembly micro-optimization

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

使用xor reg,reg是否优于mov reg,0?

在x86上有两种众所周知的方法可以将整数寄存器设置为零值.

mov reg, 0
Run Code Online (Sandbox Code Playgroud)

要么

xor reg, reg
Run Code Online (Sandbox Code Playgroud)

有一种观点认为第二种变体更好,因为值0没有存储在代码中并且节省了几个字节的生成的机器代码.这绝对是好的 - 使用较少的指令缓存,这有时可以实现更快的代码执行.许多编译器生成这样的代码.

然而,在xor指令和改变相同寄存器的早期指令之间正式存在指令间依赖性.由于存在依赖性,后一条指令需要等到前者完成,这可能会减少处理器单元的负载并损害性能.

add reg, 17
;do something else with reg here
xor reg, reg
Run Code Online (Sandbox Code Playgroud)

很明显,无论初始寄存器值如何,xor的结果都将完全相同.但是处理器能够识别出这个吗?

我在VC++ 7中尝试了以下测试:

const int Count = 10 * 1000 * 1000 * 1000;
int _tmain(int argc, _TCHAR* argv[])
{
    int i;
    DWORD start = GetTickCount();
    for( i = 0; i < Count ; i++ ) {
        __asm {
            mov eax, 10
            xor eax, eax
        };
    }
    DWORD diff = GetTickCount() - start;
    start = …
Run Code Online (Sandbox Code Playgroud)

x86 assembly micro-optimization

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

x86汇编中XOR的含义是什么?

我正在进行组装,我一直在运行xor,例如:

xor     ax, ax
Run Code Online (Sandbox Code Playgroud)

它只是清除了寄存器的值吗?

assembly xor

36
推荐指数
5
解决办法
8万
查看次数

x86汇编习语

我一直试图很好地掌握x86汇编语言,并且想知道是否存在快速和短暂的等价物movl $1, %eax.就在那时,我认为语言中经常使用的习语列表可能是个好主意.

这可能包括与... xorl %eax, %eax相对movl $0, %eaxtestl %eax, %eax反对的首选使用cmpl $0, %eax.

哦,并且每个帖子发布一个例子!

x86 assembly idioms

15
推荐指数
6
解决办法
6810
查看次数

通过寄存器重命名器对寄存器进行微体系结构归零:性能与mov?

在一篇博客文章中读到,最近的X86微体系结构也能够在寄存器重命名器中处理常见的寄存器归零习语(例如将寄存器与自身对齐); 用作者的话来说:

"寄存器重命名器也知道如何执行这些指令 - 它可以将寄存器本身归零."

有人知道这在实践中是如何运作的吗?我知道有些ISA,如MIPS,包含一个在硬件中始终设置为零的架构寄存器; 这是否意味着在内部,X86微体系结构内部具有类似的"零"寄存器,以便在方便时映射到寄存器?或者我的心智模型对于这些东西如何在微体系结构上工作不太正确?

我之所以要问的原因是(从一些观察中)看来mov,在一个循环中,从一个包含零的寄存器到一个目的地,仍然比在循环内通过xor将寄存器归零要快得多.

基本上它发生的是我想根据条件将循环内的寄存器归零; 这可以通过提前分配架构寄存器来存储零(%xmm3在这种情况下),在整个循环期间不进行修改,并在其中执行以下内容来完成:

movapd  %xmm3, %xmm0
Run Code Online (Sandbox Code Playgroud)

或者用xor技巧代替:

xorpd   %xmm0, %xmm0
Run Code Online (Sandbox Code Playgroud)

(AT&T语法).

换句话说,选择是在循环之外提升常数零或在每次迭代中将其重新物化在其中.后者将实时架构寄存器的数量减少一个,并且通过处理器假设的特殊情况感知和处理xor成语,它似乎应该像前者一样快(特别是因为这些机器具有更多的物理无论如何,寄存器都比体系结构寄存器更重要,所以它应该能够在内部完成与我在程序集中所做的相同的工作,通过在内部提升常数零甚至更好,完全意识和控制自己的资源).但它似乎不是,所以我很好奇是否有任何具有CPU架构知识的人可以解释是否有一个很好的理论原因.

在这种情况下,寄存器由SSE寄存器发生,机器恰好是Ivy Bridge; 我不确定这些因素有多重要.

x86 assembly x86-64 cpu-architecture

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

x86 inc与add指令的相对性能

快速提问,事先假设

mov eax, 0
Run Code Online (Sandbox Code Playgroud)

哪个更有效率?

inc eax
inc eax
Run Code Online (Sandbox Code Playgroud)

要么

add eax, 2
Run Code Online (Sandbox Code Playgroud)

另外,如果两个incs更快,编译器(比方说,GCC)通常(即没有积极的优化标志)是否优化var += 2呢?

谢谢你的时间!

PS:不要费心回答"不要过早优化",这仅仅是学术兴趣.

optimization performance x86 assembly

9
推荐指数
3
解决办法
7671
查看次数

XOR寄存器,寄存器(汇编程序)

我们不时要分析汇编程序代码(IA32),而且我经常会遇到如下所示的指令:

xor ax, ax
Run Code Online (Sandbox Code Playgroud)

或与其他寄存器藏汉:xor dx, dx,xor al, al,...

这到底是做什么的?(ax xor ax总是给0?)

x86 assembly xor

7
推荐指数
1
解决办法
6220
查看次数

为什么添加beforefieldinit会大大提高泛型类的执行速度?

我正在研究代理和带有引用类型参数的泛型类,它非常慢.特别是对于通用方法(对于刚刚返回null的普通泛型方法,大约400毫秒对3200毫秒).我决定尝试看看如果我在C#中重写生成的类,它会如何执行,并且它表现得更好,与非泛型类代码的性能相同.

这是我写的C#类::(注意我通过命名方案改变但不是很多)::

namespace TestData
{
    public class TestClassProxy<pR> : TestClass<pR>
    {
        private InvocationHandler<Func<TestClass<pR>, object>> _0_Test;
        private InvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>> _1_Test;
        private static readonly InvocationHandler[] _proxy_handlers = new InvocationHandler[] { 
            new InvocationHandler<Func<TestClass<pR>, object>>(new Func<TestClass<pR>, object>(TestClassProxy<pR>.s_0_Test)), 
        new GenericInvocationHandler<Func<TestClass<pR>, pR, GenericToken, object>>(typeof(TestClassProxy<pR>), "s_1_Test") };



        public TestClassProxy(InvocationHandler[] handlers)
        {
            if (handlers == null)
            {
                throw new ArgumentNullException("handlers");
            }
            if (handlers.Length != 2)
            {
                throw new ArgumentException("Handlers needs to be an array of 2 parameters.", "handlers");
            }
            this._0_Test = (InvocationHandler<Func<TestClass<pR>, object>>)(handlers[0] ?? _proxy_handlers[0]);
            this._1_Test …
Run Code Online (Sandbox Code Playgroud)

c# il cil reflection.emit

6
推荐指数
1
解决办法
1421
查看次数

这个汇编代码有什么作用?(TEST,XOR,JNZ)

1.

TEST EAX,EAX
JNZ SHORT program.00407190
Run Code Online (Sandbox Code Playgroud)

2.

XOR EAX,EAX
JNZ SHORT program.00407190
Run Code Online (Sandbox Code Playgroud)

如果我错了,请纠正我.谢谢!:)

根据我的理解到目前为止:

JNZ如果不等于零则跳跃,它将跳转或不跳,取决于是否ZF设置为1.如果是1,它就不会跳跃.否则,它会跳跃.

根据我对代码#1的理解,TEST EAX,EAX将检查它是否为零.如果它不等于零(ZF为0),它将跳转到地址00407190.

对于代码#2,
XOR EAX,EAX将EAX寄存器设置为0.是否设置了任何标志?如果没有,JNZ指令如何确定跳转?

最后,人们为什么要检查是否EAX为0?请帮助我更简单详细的解释,我还是初学者.

x86 assembly reverse-engineering

5
推荐指数
1
解决办法
8062
查看次数

编译器将 printf 更改为 puts

考虑以下代码:

#include <stdio.h>

void foo() {
    printf("Hello world\n");
}

void bar() {
    printf("Hello world");
}
Run Code Online (Sandbox Code Playgroud)

这两个函数产生的程序集是:

.LC0:
        .string "Hello world"
foo():
        mov     edi, OFFSET FLAT:.LC0
        jmp     puts
bar():
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        jmp     printf

Run Code Online (Sandbox Code Playgroud)

现在我知道puts 和 printf之间的区别,但我发现这很有趣,因为 gcc 能够内省 const char* 并确定是调用 printf 还是 puts。

另一个有趣的事情是bar,编译器将返回寄存器 ( eax)清零,即使它是一个void函数。为什么它在那里而不是在里面foo

我假设编译器“内省了我的字符串”是否正确,或者对此有另一种解释?

c assembly gcc compiler-optimization

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

汇编中的XOR语句

我试图了解该程序的反汇编版本:

#include <stdio.h>

int main(){
   int i=0;
   printf("HELLO VIK");
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

gdb反汇编:

(gdb) disass main
Dump of assembler code for function main:
0x0000000100000ef0 <main+0>:    push   rbp
0x0000000100000ef1 <main+1>:    mov    rbp,rsp
0x0000000100000ef4 <main+4>:    sub    rsp,0x10
0x0000000100000ef8 <main+8>:    mov    DWORD PTR [rbp-0xc],0x0
0x0000000100000eff <main+15>:   xor    al,al
0x0000000100000f01 <main+17>:   lea    rcx,[rip+0x50]        # 0x100000f58
0x0000000100000f08 <main+24>:   mov    rdi,rcx
0x0000000100000f0b <main+27>:   call   0x100000f2c <dyld_stub_printf>
0x0000000100000f10 <main+32>:   mov    DWORD PTR [rbp-0x8],0x0
0x0000000100000f17 <main+39>:   mov    eax,DWORD PTR [rbp-0x8]
0x0000000100000f1a <main+42>:   mov    DWORD PTR [rbp-0x4],eax
0x0000000100000f1d <main+45>: …
Run Code Online (Sandbox Code Playgroud)

assembly gdb x86-64

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