相关疑难解决方法(0)

在内存位置调用 `add` 是否比在寄存器上调用它然后移动值更快?

什么更快:

add DWORD PTR [rbp-0x4],1
Run Code Online (Sandbox Code Playgroud)

或者

 mov    eax,DWORD PTR [rbp-0x4]
 add    eax,1
 mov    DWORD PTR [rbp-0x4],eax
Run Code Online (Sandbox Code Playgroud)

我已经看到编译器生成的第二个代码,所以也许调用add寄存器要快得多?

x86 assembly x86-64 micro-optimization

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

受限是 volatile 的对立面吗?

我可以使用volatile类似以下的内容,其中的值可能会被外部函数/信号/等修改:

volatile int exit = 0;
while (!exit)
{
    /* something */
}
Run Code Online (Sandbox Code Playgroud)

并且编译器/程序集不会缓存该值。另一方面,使用restrict关键字,我可以告诉编译器一个变量没有别名/只在当前范围内被引用一次,编译器可以尝试优化它:

void update_res (int *a , int *b, int * restrict c ) {
    * a += * c;
    * b += * c;
}
Run Code Online (Sandbox Code Playgroud)

这是对两者的正确理解,它们基本上是彼此对立的吗?volatile说该变量可以在当前范围之外修改并restrict说它不能?对于使用这两个关键字的最基本示例,它将发出的汇编指令示例是什么?

c x86 assembly volatile restrict-qualifier

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

如何告诉计算机它正在添加而无需在程序集中添加 addl

我对汇编有一点了解。那么我先介绍一下代码,然后解释一下我的思路。

#This is the Assembly version.
pushq   %rbp
movq    %rsp, %rbp
movl    $2, -4(%rbp)
movl    $3, -8(%rbp)
movl    $5, %eax
popq    %rbp
ret


#This is the C version.
int twothree() {
    int a = 2;
    int b = 3;

    return 2 + 3;
}
Run Code Online (Sandbox Code Playgroud)

好吧,首先让我吃惊的是我们没有将变量 a 和 b 用作 a + b。所以它们是不必要的,我们直接将整数相加。然而,如果计算机能够理解这一点,我想那将是非常可怕的。所以,我的问题是:在没有任何 addl 或类似命令的情况下,这个汇编代码是如何工作的?我们直接将立即数(或常量)整数 5 移至 eax 注册器。

另外,快速提问。那么最后两行之后的 a 和 b 变量会发生什么情况呢?它们在堆栈中的位置(或者也许我们可以将它们用作内存位置的“注册器”称为“注册器”)现在是空闲的,因为我们使用 malloc + free。这是真的还是至少合乎逻辑?我猜 popq %rbp 是关闭堆栈的命令。

正如我所说,我不是汇编专家。所以这些想法大部分都只是思考。谢谢!

c assembly x86-64 compiler-optimization

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

为什么这段代码在 Debug 模式下运行速度比 Release 模式慢 100 倍以上?

重新发帖原因:

本来我只得到一个回复​​,只是指出标题夸大了。因此,再试一次,也许这次会有更多的人看到这个问题,因为我真的不知道还能看哪里......我会确保删除原来的问题以避免重复,并保留这个新问题。我并不是想向论坛发送垃圾邮件。

请随意在编辑时删除上面的文本,我只是想解释为什么我要重新发布 - 但这并不是问题的一部分。

所以,最初的问题是:

我的程序中有一些函数在 Visual Studio Community,2015 中的调试模式下运行速度非常慢。它们是用于“索引”3D 模型顶点的函数。

通常情况下,我准备好调试模式会慢一点,可能慢 2 -3 倍。但...

发布模式下,程序将在大约2 - 3 秒内启动并索引模型。完美的。

然而,在调试模式下,我的程序需要7 分钟以上才能真正响应、开始渲染并接受输入。它在索引一个模型时卡住了七分钟多。在此期间程序完全冻结。

相同的模型在“发布”模式下加载和索引只需不到 3。调试过程中怎么可能花费如此长的时间?

调试和发布模式都是标准的开箱即用模式。我不记得更改过其中任何一个的任何设置。

以下是在调试模式下减慢程序速度的代码:

// Main Indexer Function
void indexVBO_TBN(
std::vector<glm::vec3> &in_vertices,
std::vector<glm::vec2> &in_uvs,
std::vector<glm::vec3> &in_normals,
std::vector<glm::vec3> &in_tangents,
std::vector<glm::vec3> &in_bitangents,

std::vector<unsigned short> & out_indices,
std::vector<glm::vec3> &out_vertices,
std::vector<glm::vec2> &out_uvs,
std::vector<glm::vec3> &out_normals,
std::vector<glm::vec3> &out_tangents,
std::vector<glm::vec3> &out_bitangents){

int count = 0;

// For each input vertex
for (unsigned int i = …
Run Code Online (Sandbox Code Playgroud)

c++ debugging performance visual-studio-2015

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

可以使用虚拟内存来支持 i386 中的数据断点功能吗?

我潜伏在我的操作系统教科书中,它提到可以在数据断点上实现虚拟地址转换(用于程序调试)。我只知道调试器使用 INT 3 来暂停正在调试控制和地址寄存器中以某种方式处理的程序、局部和全局变量。但是经过一番挖掘,我只找到了有关使用调试寄存器的线性地址的信息。根本没有关于虚拟地址相关数据断点背后机制的文章或讨论。那么这究竟是如何工作的呢?

debugging x86 assembly virtual-memory virtual-address-space

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

gdb false 可以重新创建帧的寄存器吗?

我正在分析我的应用程序的核心转储,当我转到第 1 帧时,我打印了存储在 EAX 中的变量的值。Gdb 打印值,如果是真的,程序不会调用 panic(反汇编显示,它比较寄存器中的值,所以没有其他线程可以改变它)。我调用info reg了指令指针的一部分,对于帧 #0 和 #1 给了我相同的结果。是否有可能 Gdb 在帧 #1 中显示帧 #0 的寄存器 EAX 的值?

编辑:代码看起来像这样:

switch(myVar){
    case -1:
        break;
    default:
        panic();
}
Run Code Online (Sandbox Code Playgroud)

gdb 显示:

(gdb) bt
#0 panic()
#1 0x0891a3e9 in myFunc() at myFunc.c:10
(gdb) up
#1 0x0891a3e9 in myFunc() at myFunc.c:10
10    panic();
(gdb) print myVar
$1 = -1
(gdb) print &myVar
Address requested for identifier "myVar" which is in register $eax
Run Code Online (Sandbox Code Playgroud)

c x86 gdb

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

GCC 为什么一直没有运行优化?

我用 C 编写了众所周知的交换函数,并使用 gcc S 观看了汇编输出,并再次做了同样的事情,但对 O2 进行了优化

差异非常大,因为与 20 行相比,我只看到了 5 行。

我的问题是,如果优化真的有帮助,为什么不一直使用它?为什么我们非优化编译代码?

给业内人士一个额外的问题,当您在测试后发布程序的最终版本时,您是否进行了优化编译?

我正在回复您的所有评论,请阅读。

c optimization assembly gcc compiler-optimization

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

为什么添加 if(!memcmp()) 会加速循环,使随机短步跨过一个巨大的字节数组?

抱歉,我一直不明白这里的规则。我已经删除了所有重复的帖子。这是第一个相关问题。\n请不要将此帖子标记为我另一篇帖子的重复(执行次数减少 3 倍,但执行效率几乎不变。在 C 中),即使代码有些相似,他们提出了截然不同的问题。这也是我同一天发现的两个问题。类似的帖子因“误判”而被重复,然后被关闭。可能是我没有把这个问题说清楚。我真的很希望得到答案,所以我重新发布了它。希望大家能够看清问题,非常感谢!

\n

在下面的C代码中,我在第一次测试时间的循环中添加了一个“if”语句,执行时间完全相同。从理论上讲,它应该更慢。尽管分支预测可以使它们的性能几乎相同,但它实际上变得更快。这是什么原理呢?我尝试使用clang和gcc编译器分别在Mac和Linux环境中运行,并尝试了各种优化级别。为了防止缓存受到影响,我让速度较快的先执行,但有冗余代码的循环执行得更快。

\n

如果您认为我的描述不可信,请将以下代码编译到您的计算机中并运行。希望有人能为我回答这个问题\xef\xbc\x8c谢谢。

\n

C代码:

\n
#include <stdio.h>\n#include <time.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define TLen 300000000\n#define SLen 10\n\nint main(int argc, const char * argv[]) {\n    srandom((unsigned)time(NULL));\n    \n    // An array to increase the index,\n    // the range of its elements is 1-256\n    int rand_arr[128];\n    for (int i = 0; i < 128; ++i)\n        rand_arr[i] = random()%256+1;\n    \n    // A random text(very long), the range of its elements is 0-127\n    char *tex = malloc((sizeof *tex) * …
Run Code Online (Sandbox Code Playgroud)

c performance x86-64 cpu-architecture

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

编译器是否优化了所有临时对象?

有人说,在大多数情况下,编译器比人类更聪明,并且会优化很多我们无法明确执行的东西。我想知道编译器是否对此进行了优化。下面的代码有有趣的结果,但没有错误。但有一个严重的问题。

//will this move or copy construct?
#include <iostream>

class A
{
public:

    A()
    {
        std::cout << "Constructed A.\n";
    }

    ~A()
    {
        std::cout << "A destroyed.\n";
    }

};

class B
{
private:
    A m_A;

public:
    B(A someA):m_A{someA}
    {

    }
};

int main()
{
    B oneB{A()};

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此代码使用 Clang++ 13.0.1 在 Windows 10 上打印-fexceptions -O3 -Wall -g -std=c++20 -v -c

Constructed A.
A destroyed.
A destroyed.
Run Code Online (Sandbox Code Playgroud)

为什么A被销毁了两次但只被构造了一次?B即使使用常量引用构建时也会发生这种情况。这真是太荒谬了。我仍在学习 C++,从未参与过任何项目或其他任何事情。我想问一些我在网上学习时感到困惑的事情。

c++ compiler-optimization

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

为什么 int&amp; 作为函数参数使用 QWORD(8 字节)内存,而 int 参数使用 DWORD

在下面的代码中,

int firstFunction(int& refParam)
{
    std::cout << "Type of refParam is: " << typeid(refParam).name() << '\n';
    return refParam;
}

int secondFunction(int param)
{
    std::cout << "Type of param is: " << typeid(param).name() << '\n';
    return param;
}

int main()
{
    int firstVar{ 1 };
    int secondVar{ firstFunction(firstVar) };
    int thirdVar{ secondFunction(firstVar) };
}
Run Code Online (Sandbox Code Playgroud)

控制台输出是

int
int
Run Code Online (Sandbox Code Playgroud)

当我检查Godbolt 链接中的汇编代码时。

firstFunction(int&):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     rax, QWORD PTR [rbp-8]
        mov     eax, DWORD PTR [rax] …
Run Code Online (Sandbox Code Playgroud)

c++ assembly gcc reference x86-64

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