我试图比较内联汇编语言和 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
cmp edi,0
jnz start
};
}
main() :int main() {
bool errorOccured = false;
setbuf(stdout,NULL);
int *xC,*xAsm,*yC,*yAsm;
xC = new int[2000];
xAsm = new int[2000];
yC = new int[2000];
yAsm = new int[2000];
for(int i = 0; i < 2000; i++)
{
xC[i] = 0;
xAsm[i] = 0;
yC[i] = i;
yAsm[i] = i;
}
time_t start = clock();
calcuC(xC,yC,2000);
// calcuAsm(xAsm,yAsm,2000);
// for(int i = 0; i < 2000; i++)
// {
// if(xC[i] != xAsm[i])
// {
// cout<<"xC["<<i<<"]="<<xC[i]<<" "<<"xAsm["<<i<<"]="<<xAsm[i]<<endl;
// errorOccured = true;
// break;
// }
// }
// if(errorOccured)
// cout<<"Error occurs!"<<endl;
// else
// cout<<"Works fine!"<<endl;
time_t end = clock();
// cout<<"time = "<<(float)(end - start) / CLOCKS_PER_SEC<<"\n";
cout<<"time = "<<end - start<<endl;
return 0;
}
Debug Release
---------------
732 668
733 680
659 672
667 675
684 694
Average: 677
Debug Release
-----------------
1068 168
999 166
1072 231
1002 166
1114 183
Average: 182
最佳答案
是的,大多数时候。
首先,您错误地假设低级语言(在这种情况下为汇编)将始终比高级语言(在这种情况下为 C++ 和 C)生成更快的代码。这不是真的。 C 代码总是比 Java 代码快吗?不,因为还有另一个变量:程序员。您编写代码的方式和架构细节的知识极大地影响了性能(正如您在本例中看到的那样)。
您可以 总是 生成一个示例,其中手工汇编代码优于编译代码,但 通常这是一个虚构的示例或单个例程,而不是 500.000 多行 C++ 代码的真实程序)。我认为编译器会产生更好的汇编代码 95% 倍和 有时,只有少数几次,您可能需要编写一些简短的汇编代码,highly used , performance critical例程或当您必须访问您最喜欢的高级语言未公开的功能时。你想感受一下这种复杂性吗?阅读 this awesome answer在这里。
这是为什么?
首先,因为编译器可以进行我们甚至无法想象的优化(参见 this short list )并且它们会在几秒钟内完成(当 we may need days 时)。
当您在汇编中编码时,您必须使用定义良好的调用接口(interface)来创建定义良好的函数。但是他们可以考虑whole-program optimization和 inter-procedural optimization这样的
如 register allocation , constant propagation , common subexpression elimination , instruction scheduling和其他复杂的、不明显的优化(例如 Polytope model )。在 RISC架构师在很多年前就不再担心这个了(例如,指令调度很难 tune by hand)和现代 CISC CPU 很长 pipelines也是。
对于一些复杂的微 Controller ,甚至系统库都是用 C 语言而不是汇编语言编写的,因为它们的编译器会生成更好(且易于维护)的最终代码。
编译器有时可以 automatically use some MMX/SIMDx instructions自己,如果你不使用它们,你根本无法比较(其他答案已经很好地审查了你的汇编代码)。
仅用于循环,这是一个 short list of loop optimizations什么是常用 由编译器检查(当你的 C# 程序的日程安排已经确定时,你认为你可以自己做吗?)如果你用汇编写一些东西,我认为你至少必须考虑一些 simple optimizations .数组的教科书示例是 unroll the cycle (它的大小在编译时是已知的)。这样做并再次运行您的测试。
如今,由于另一个原因需要使用汇编语言也非常罕见:plethora of different CPUs .你想支持他们吗?每个都有一个特定的 microarchitecture和一些 specific instruction sets .它们具有不同数量的功能单元,应安排组装说明以保持它们都处于忙碌状态。如果你用 C 编写,你可以使用 PGO但是在组装过程中,您将需要对该特定架构有丰富的了解(以及 为另一个架构重新思考和重做所有内容 )。对于小任务,编译器通常做得更好,而对于复杂的任务,工作通常不会得到返回(无论如何 compiler may do better)。
如果您坐下来查看您的代码,您可能会发现重新设计算法比转换为汇编会获得更多 yield (阅读此 great post here on SO),有高级优化(以及编译器),您可以在需要求助于汇编语言之前有效地应用。可能值得一提的是,经常使用内在函数可以获得您正在寻找的性能提升,并且编译器仍然能够执行其大部分优化。
综上所述,即使您可以生成快 5 到 10 倍的汇编代码,您也应该询问您的客户是否愿意 支付 一周的 您的时间 或到 买一个快 50 美元的 CPU .大多数情况下,我们大多数人根本不需要极端优化(尤其是在 LOB 应用程序中)。
关于c++ - 内联汇编语言是否比 native C++ 代码慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9601427/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下