Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 与默认IF相比,速记IF是否能提高效率?_C++_C_Performance_If Statement_Shorthand - Fatal编程技术网

C++ 与默认IF相比,速记IF是否能提高效率?

C++ 与默认IF相比,速记IF是否能提高效率?,c++,c,performance,if-statement,shorthand,C++,C,Performance,If Statement,Shorthand,如果我有一个包含任意长度整数的大数据文件,需要按其第二个字段进行排序: 1 3 4 5 1 4 5 7 -1 34 56 7 124 58394 1384 -1938 1948 3848089 -14850 0 1048 01840 1039 888 //consider this is a LARGE file, the data goes on for quite some time 我呼吁qsort成为我选择的武器,在我的排序功能中,如果使用速记可以显著提高数据排序所需的总体时间,那么它

如果我有一个包含任意长度整数的大数据文件,需要按其第二个字段进行排序:

1 3 4 5
1 4 5 7
-1 34 56 7
124 58394 1384 -1938
1948 3848089 -14850 0
1048 01840 1039 888
//consider this is a LARGE file, the data goes on for quite some time
我呼吁qsort成为我选择的武器,在我的排序功能中,如果使用速记可以显著提高数据排序所需的总体时间,那么它会不会提供显著的性能提升?或者速记只是用来组织代码的一种方便工具

num2 = atoi(Str);
num1 = atoi(Str2);
LoggNum = (num2 > num1) ? num2 : num1; //faster?


任何现代编译器都会在这两种情况下生成相同的代码,区别只是风格和方便而已。

这个问题没有答案。。。编译器可以自由生成它认为合适的任何代码。也就是说,只有一个特别愚蠢的编译器才能为这些情况生成明显不同的代码。你应该写任何你觉得最好的表达你的程序是如何工作的。。。对我来说,三元操作符版本更简洁易读,但是人们不习惯C和/或C++,可以发现IF/EL版本更容易理解。
如果您对这类事情感兴趣,并且希望更好地理解代码生成,那么应该学习如何调用编译器,让它生成汇编语言输出,显示程序的CPU指令。例如,GNU编译器接受一个生成汇编语言文件的
-S
标志。

唯一知道的方法是分析。但是,三元运算符允许您对对象进行初始化:

Sometype z = ( x < y) ? something : somethingElse; // copy initialization

如果分配给
SomeType
的开销很大,这可能会产生影响。

我们在VC 2010中测试了这两个语句:

为?=生成的程序集为:

 01207AE1 cmp byte ptr [ebp-101h],0
 01207AE8 jne CTestSOFDlg::OnBnClickedButton1+47h (1207AF7h)
 01207AEA push offset (1207BE5h)
 01207AEF call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207AF4 add esp,4
 01207AF7 cmp byte ptr [ebp-0F5h],0
 01207AFE jne CTestSOFDlg::OnBnClickedButton1+5Dh (1207B0Dh)
 01207B00 push offset (1207BE0h)
 01207B05 call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207B0A add esp,4
 01207B0D mov eax,dword ptr [num2]
 01207B10 cmp eax,dword ptr [num1]
 01207B13 jle CTestSOFDlg::OnBnClickedButton1+86h (1207B36h)
 01207B15 cmp byte ptr [ebp-101h],0
 01207B1C jne CTestSOFDlg::OnBnClickedButton1+7Bh (1207B2Bh)
 01207B1E push offset (1207BE5h)
 01207B23 call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207B28 add esp,4
 01207B2B mov ecx,dword ptr [num2]
 01207B2E mov dword ptr [ebp-10Ch],ecx
 01207B34 jmp CTestSOFDlg::OnBnClickedButton1+0A5h (1207B55h)
 01207B36 cmp byte ptr [ebp-0F5h],0
 01207B3D jne CTestSOFDlg::OnBnClickedButton1+9Ch (1207B4Ch)
 01207B3F push offset (1207BE0h)
 01207B44 call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207B49 add esp,4
 01207B4C mov edx,dword ptr [num1]
 01207B4F mov dword ptr [ebp-10Ch],edx
 01207B55 mov eax,dword ptr [ebp-10Ch]
 01207B5B mov dword ptr [LoggNum],eax
对于if else操作员:

 01207B5E cmp byte ptr [ebp-101h],0
 01207B65 jne CTestSOFDlg::OnBnClickedButton1+0C4h (1207B74h)
 01207B67 push offset (1207BE5h)
 01207B6C call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207B71 add esp,4
 01207B74 cmp byte ptr [ebp-0F5h],0
 01207B7B jne CTestSOFDlg::OnBnClickedButton1+0DAh (1207B8Ah)
 01207B7D push offset (1207BE0h)
 01207B82 call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207B87 add esp,4
 01207B8A mov eax,dword ptr [num2]
 01207B8D cmp eax,dword ptr [num1]
 01207B90 jle CTestSOFDlg::OnBnClickedButton1+100h (1207BB0h)
 01207B92 cmp byte ptr [ebp-101h],0
 01207B99 jne CTestSOFDlg::OnBnClickedButton1+0F8h (1207BA8h)
 01207B9B push offset (1207BE5h)
 01207BA0 call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207BA5 add esp,4
 01207BA8 mov eax,dword ptr [num2]
 01207BAB mov dword ptr [LoggNum],eax
 01207BB0 cmp byte ptr [ebp-0F5h],0
 01207BB7 jne CTestSOFDlg::OnBnClickedButton1+116h (1207BC6h)
 01207BB9 push offset (1207BE0h)
 01207BBE call @ILT+840(__RTC_UninitUse) (120134Dh)
 01207BC3 add esp,4
 01207BC6 mov eax,dword ptr [num1]
 01207BC9 mov dword ptr [LoggNum],eax
如您所见?=运算符还有两个asm命令:

01207B4C mov edx,dword ptr [num1]
01207B4F mov dword ptr [ebp-10Ch],edx
这需要更多的CPU时间


对于97000000大小的循环,如果其他形式更快的话。

这个特殊的优化在实际的代码库中让我感到痛苦,在锁定函数中从一种形式更改为另一种形式可以在宏基准测试中节省10%的执行时间

让我们在MacOS上使用gcc 4.2.1进行测试:

int global;

void
foo(int x, int y)
{
    if (x < y)
        global = x;
    else
        global = y;
}

void
bar(int x, int y)
{
    global = (x < y) ? x : y;
}
考虑到cmov指令是专门为了提高此类操作的性能而添加的(通过避免管道暂停),很明显,在这个特定的编译器中“?:”更快



编译器应该在这两种情况下生成相同的代码吗?对会吗?不,当然不是,没有一个编译器是完美的。如果您真的关心性能(在大多数情况下您不应该这样做),请测试并查看。

如果从文件中读取数据并调用atoi将占用大部分实际时间,我不会感到惊讶。当然,读取是线性的,排序是NlogN的,但是与比较+交换相比,磁盘读取和atoi的附加常数是巨大的。我在VS2010和ARM7上的嵌入式系统(LPC2478,Keil编译器)上为一个项目比较这两种方法方面有实际经验。他们显示出不同的结果。正如我记得的那样,VS“if”的速度更快!在Keil上,结果是相同的。我用
g++
尝试了一个非常简单的例子,并检查了程序集。对于
-O3
,它们是相同的。如果没有,第一个案例有一些额外的说明(不需要仔细查看它来找出原因,只需要计算)。但是,这与实际性能和实际代码没有多大关系。感谢您的回答,不知道为什么这个问题值得否决,但这回答了我的问题。谢谢三元运算符允许您根据条件以不同方式初始化新对象。VS2010是现代编译器,但它可以为此显示不同的结果。这就是您的想法。为什么不测试一下呢?GCC没有(版本4.2.1和更早版本)。具体来说,在am64上“?:”生成cmovq,而if else窗体生成跳转。这恰好是我在一个经常被调用的函数(类似于锁定函数)的大型代码库中所做的优化,其影响是在一个大规模基准测试中减少10%的执行时间。我真的看不出初始化在?:和if else之间有什么不同。您的示例将在这两种情况下生成相同的机器代码。因为这两种情况都假设“z”是一个局部变量。@Lundin否,这两种情况在语义上是不同的,编译器不能保证生成相同的代码。在C++的默认构造函数中,你不知道会发生什么。逗号运算符允许您在
中进行设置。但是,如果
中的
值是正确的<代码>如果(z=某物,x。。。当然,在你的具体例子中,
z
被设置为
something
somethingElse
,如果你点击它,它就会在
else
的情况下被覆盖。支持你的声明的大量具体数据,尽管我怀疑我的数据文件是否会达到97000000左右!这似乎是因为一个蹩脚的编译器,而不是这两个窗体之间的任何语法差异。我们也应该考虑到在3 GHz时,每个CPU的嘀嗒声大约是0.0000000033秒。我们会注意到区别吗?;-)@Bo Persson:速度取决于调用此代码的频率和环境。如果你用一个用户在一个桌面应用程序上运行这段代码,那么差别是可以忽略不计的。但是在每秒有数百万请求的服务器上,速度很重要(当然这取决于项目预算)。不,单个时钟的差异并不重要。即使每秒有一百万个请求,差异仍然只有0.003秒。我更希望在C++中使用<代码> STD::排序< /COD>而不是<代码> qSoS> <代码>。
01207B4C mov edx,dword ptr [num1]
01207B4F mov dword ptr [ebp-10Ch],edx
int global;

void
foo(int x, int y)
{
    if (x < y)
        global = x;
    else
        global = y;
}

void
bar(int x, int y)
{
    global = (x < y) ? x : y;
}
_foo:
        cmpl    %esi, %edi
        jge     L2
        movq    _global@GOTPCREL(%rip), %rax
        movl    %edi, (%rax)
        ret
L2:
        movq    _global@GOTPCREL(%rip), %rax
        movl    %esi, (%rax)
        ret

_bar:
        cmpl    %edi, %esi
        cmovle  %esi, %edi
        movq    _global@GOTPCREL(%rip), %rax
        movl    %edi, (%rax)
        ret