这段代码:
#include <memory>
#include <time.h>
#include <chrono>
#include <thread>
#include <stdio.h>
#include <stdlib.h>
void Test( ) {
#define current_milliseconds std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now( ).time_since_epoch( ) ).count( )
int *c = ( int* )malloc( 1024 * 1024 * 1024 );
int result = 0;
auto millis = -current_milliseconds;
//clock_t timer = -clock( );
for ( int i = 0 ; i < 1024 * 1024 * 256 /* 1024 / 4 */; ++i )
result += c[ i ];
millis += current_milliseconds;
printf( "Took: %ldms (JUST PASSING BY: %d)\n", millis, result );
free( c );
#undef current_milliseconds
}
int main( ) {
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
Test( );
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
Test( );
return -1;
}
我进行了 7 次测试并给出了最后 6 次输出:
Took: 502ms (JUST PASSING BY: 0)
Took: 607ms (JUST PASSING BY: 0)
Took: 480ms (JUST PASSING BY: 0)
Took: 588ms (JUST PASSING BY: 0)
Took: 492ms (JUST PASSING BY: 0)
Took: 562ms (JUST PASSING BY: 0)
Took: 506ms (JUST PASSING BY: 0)
Took: 558ms (JUST PASSING BY: 0)
Took: 470ms (JUST PASSING BY: 0)
Took: 555ms (JUST PASSING BY: 0)
Took: 510ms (JUST PASSING BY: 0)
Took: 562ms (JUST PASSING BY: 0)
如果你的输出不同,那么尝试再次运行可执行文件(硬盘缓存未命中)或尝试扩大迭代次数和分配字节数(感受一下)。
请注意,定时器的代码范围仅在循环中,而不是分配;那么问题又来了:为什么第二次迭代更慢?有办法解决吗?
附加信息:
最佳答案
我的机器上的输出:
Took: 371ms (JUST PASSING BY: 0)
Took: 318ms (JUST PASSING BY: 0)
对于我希望大多数程序员在尝试您的程序时看到的内容来说,这比较典型。你可以做一个小的改变来获得完全不同的结果:
int *c = (int*)malloc(1024 * 1024 * 1024);
memset(c, 0, 1024 * 1024 * 1024); // <== added
// etc..
在我的机器上产生:
Took: 104ms (JUST PASSING BY: 0)
Took: 102ms (JUST PASSING BY: 0)
仅通过初始化内存内容即可实现 3 倍的加速。希望它在您的机器上重现,它应该。您需要得出的第一个结论是,您一直在对与代码成本完全不同的东西进行基准测试。现代机器上非常典型的基准风险。
这是按需分页虚拟内存操作系统的行为。像 Windows、Linux 或 OSX。您的 malloc() 调用实际上从未分配任何内存,它只是保留地址空间。只是处理器的数字,每 4096 字节的内存有一个。直到后来,当你真正解决它时,你才支付使用内存的成本。当按需分页功能发挥作用时。
这发生在您的 result += c[ i ]; 语句中。此时踏板必须与金属接触,操作系统被迫实际使内存可用。您的程序每 4096 字节生成一个页面错误。操作系统介入并将 4096 字节的 RAM 映射到虚拟内存页面。您的程序会生成 1GB/4096 = 262,144 个页面错误。您可以得出结论,您的操作系统大约需要 400 毫秒/262144 ~= 1.5 微秒来处理页面错误。我的速度大约是它的两倍。
注意 memset() 调用 隐藏 的成本,它在您开始计时代码执行之前 生成所有页面错误。从而真正衡量代码的成本并避免否则不可避免的初始化开销。
您的第一次运行需要多长时间取决于操作系统使 RAM 可用的速度。从一次尝试到下一次,实际测量可能会有很大差异,这取决于有多少其他进程映射了 RAM 页面。如果操作系统需要先找到空间并取消映射页面,将其内容保留在页面文件中,则可能需要相当长的时间。
第二次运行需要多长时间取决于如果没有足够的 RAM 页面可用于映射另一个 GB,操作系统可以多快回收 RAM 页面。我的问题不大,我有 8 GB 的 RAM,现在只使用了 5.6 个。它们需要进行零初始化,在典型的操作系统上属于低优先级任务。
所以,这里的基本结论:
关于c++ - 为什么第二次迭代大量字节时速度明显变慢?以及如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28987615/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?