出于好奇,我以 3 种方式实现了 vector3 实用程序:数组(使用 typedef)、类和结构
这是数组实现:
typedef float newVector3[3];
namespace vec3{
void add(const newVector3& first, const newVector3& second, newVector3& out_newVector3);
void subtract(const newVector3& first, const newVector3& second, newVector3& out_newVector3);
void dot(const newVector3& first, const newVector3& second, float& out_result);
void cross(const newVector3& first, const newVector3& second, newVector3& out_newVector3);
}
// implementations, nothing fancy...really
void add(const newVector3& first, const newVector3& second, newVector3& out_newVector3)
{
out_newVector3[0] = first[0] + second[0];
out_newVector3[1] = first[1] + second[1];
out_newVector3[2] = first[2] + second[2];
}
void subtract(const newVector3& first, const newVector3& second, newVector3& out_newVector3){
out_newVector3[0] = first[0] - second[0];
out_newVector3[1] = first[1] - second[1];
out_newVector3[2] = first[2] - second[2];
}
void dot(const newVector3& first, const newVector3& second, float& out_result){
out_result = first[0]*second[0] + first[1]*second[1] + first[2]*second[2];
}
void cross(const newVector3& first, const newVector3& second, newVector3& out_newVector3){
out_newVector3[0] = first[0] * second[0];
out_newVector3[1] = first[1] * second[1];
out_newVector3[2] = first[2] * second[2];
}
}
还有一个类实现:
class Vector3{
private:
float x;
float y;
float z;
public:
// constructors
Vector3(float new_x, float new_y, float new_z){
x = new_x;
y = new_y;
z = new_z;
}
Vector3(const Vector3& other){
if(&other != this){
this->x = other.x;
this->y = other.y;
this->z = other.z;
}
}
}
当然,它包含通常出现在 Vector3 类中的其他功能。
最后,一个结构实现:
struct s_vector3{
float x;
float y;
float z;
// constructors
s_vector3(float new_x, float new_y, float new_z){
x = new_x;
y = new_y;
z = new_z;
}
s_vector3(const s_vector3& other){
if(&other != this){
this->x = other.x;
this->y = other.y;
this->z = other.z;
}
}
同样,我省略了一些其他常见的 Vector3 功能。 现在,我让他们三个都创建了 9000000 个新对象,并做了 9000000 次叉积(我在其中一个完成后写入了一大块数据数据缓存,以避免缓存帮助他们)。
测试代码如下:
const int K_OPERATION_TIME = 9000000;
const size_t bigger_than_cachesize = 20 * 1024 * 1024;
void cleanCache()
{
// flush the cache
long *p = new long[bigger_than_cachesize];// 20 MB
for(int i = 0; i < bigger_than_cachesize; i++)
{
p[i] = rand();
}
}
int main(){
cleanCache();
// first, the Vector3 struct
std::clock_t start;
double duration;
start = std::clock();
for(int i = 0; i < K_OPERATION_TIME; ++i){
s_vector3 newVector3Struct = s_vector3(i,i,i);
newVector3Struct = s_vector3::cross(newVector3Struct, newVector3Struct);
}
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
printf("The struct implementation of Vector3 takes %f seconds.\n", duration);
cleanCache();
// second, the Vector3 array implementation
start = std::clock();
for(int i = 0; i < K_OPERATION_TIME; ++i){
newVector3 newVector3Array = {i, i, i};
newVector3 opResult;
vec3::cross(newVector3Array, newVector3Array, opResult);
}
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
printf("The array implementation of Vector3 takes %f seconds.\n", duration);
cleanCache();
// Third, the Vector3 class implementation
start = std::clock();
for(int i = 0; i < K_OPERATION_TIME; ++i){
Vector3 newVector3Class = Vector3(i,i,i);
newVector3Class = Vector3::cross(newVector3Class, newVector3Class);
}
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
printf("The class implementation of Vector3 takes %f seconds.\n", duration);
return 0;
}
结果令人吃惊。
struct 和 class 实现在 0.23 秒左右完成任务,
而 array 的实现只需要 0.08 秒!
如果数组确实有这样显着的性能优势,虽然它的语法会很丑陋,但它在很多情况下都值得使用。
所以我真的很想确定,这是应该发生的事情吗?谢谢!
最佳答案
简短回答:视情况而定。正如您所观察到的,如果在没有优化的情况下进行编译,则会有所不同。
当我在 (-O2 或 -O3) 上进行优化编译(所有内联函数)时,没有区别(继续阅读,它不像看起来很容易)。
Optimization Times (struct vs. array)
-O0 0.27 vs. 0.12
-O1 0.14 vs. 0.04
-O2 0.00 vs. 0.00
-O3 0.00 vs. 0.00
无法保证您的编译器可以/将会做什么优化,所以完整的答案是“这取决于您的编译器”。起初我会相信我的编译器会做正确的事情,否则我应该开始编程汇编。只有当这部分代码是一个真正的瓶颈时,才值得考虑帮助编译器。
如果使用 -O2 编译,您的代码对于两个版本都需要 0.0 秒,但这是因为优化器发现这些值根本没有被使用,所以它只是丢弃了整个代码!
让我们确保这不会发生:
#include <ctime>
#include <cstdio>
const int K_OPERATION_TIME = 1000000000;
int main(){
std::clock_t start;
double duration;
start = std::clock();
double checksum=0.0;
for(int i = 0; i < K_OPERATION_TIME; ++i){
s_vector3 newVector3Struct = s_vector3(i,i,i);
newVector3Struct = s_vector3::cross(newVector3Struct, newVector3Struct);
checksum+=newVector3Struct.x +newVector3Struct.y+newVector3Struct.z; // actually using the result of cross-product!
}
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
printf("The struct implementation of Vector3 takes %f seconds.\n", duration);
// second, the Vector3 array implementation
start = std::clock();
for(int i = 0; i < K_OPERATION_TIME; ++i){
newVector3 newVector3Array = {i, i, i};
newVector3 opResult;
vec3::cross(newVector3Array, newVector3Array, opResult);
checksum+=opResult[0] +opResult[1]+opResult[2]; // actually using the result of cross-product!
}
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
printf("The array implementation of Vector3 takes %f seconds.\n", duration);
printf("Checksum: %f\n", checksum);
}
您将看到以下变化:
1e9 次迭代,以获得有意义的时间。通过此更改,我们看到以下计时(英特尔编译器):
Optimization Times (struct vs. array)
-O0 33.2 vs. 17.1
-O1 19.1 vs. 7.8
-Os 19.2 vs. 7.9
-O2 0.7 vs. 0.7
-O3 0.7 vs. 0.7
我有点失望,-Os 有这么差的性能,但除此之外你可以看到,如果优化,结构和数组之间没有区别!
我个人很喜欢-Os,因为它会产生我能看懂的汇编,所以我们来看看,为什么这么慢。
最明显的事情,无需查看生成的程序集:s_vector3::cross 返回一个 s_vector3 对象,但我们将结果分配给一个已经存在的对象,所以如果优化器看不到旧对象不再使用,他可能无法执行 RVO。所以让替换
newVector3Struct = s_vector3::cross(newVector3Struct, newVector3Struct);
checksum+=newVector3Struct.x +newVector3Struct.y+newVector3Struct.z;
与:
s_vector3 r = s_vector3::cross(newVector3Struct, newVector3Struct);
checksum+=r.x +r.y+r.z;
现在有结果:2.14 (struct) vs. 7.9 - 这是相当大的改进!
我的收获:优化器做得很好,但如果需要,我们可以提供一点帮助。
关于c++ - 对于 C++ Vector3 实用程序类实现,数组是否比结构和类快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46417117/
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这