为什么/如何在这里除法和乘法同样快?
Why/how are division and multiplication equally fast here?
我正在尝试制作一个简单的基准测试算法,以比较不同的操作。在我继续实际函数之前,我想检查一个有据可查的结果的琐碎情况:乘法与除法。
从我读过的文献来看,分裂应该会损失得相当远。当我编译并运行算法时,时间大约为 0。我添加了一个打印的累加器,以确保实际执行并重试操作。然后我改变了循环,数字,洗牌等等。所有这些都是为了防止任何可能导致"除法"的事情做浮点除法以外的任何事情。无济于事。时代还是基本相等的。
在这一点上,我看不出它能从浮点分界线中走出来,我放弃了。它赢了。但我真的很好奇为什么时间如此接近,我错过了哪些警告/错误,以及如何修复它们。
(我知道用随机数据填充向量然后洗牌是多余的,但我想确保数据被访问,而不仅仅是在循环之前初始化。
(我知道"字符串比较是邪恶的"。如果这是平等时代的原因,我很乐意加入猎巫。如果没有,请不要提及。
编译:
g++ -std=c++14 main.cc
测试:
./a.out multiply
2.42202e+09
1000000
t1 = 1.52422e+09 t2 = 1.52422e+09
difference = 0.218529
Average length of function : 2.18529e-07 seconds
./a.out divide
2.56147e+06
1000000
t1 = 1.52422e+09 t2 = 1.52422e+09
difference = 0.242061
Average length of function : 2.42061e-07 seconds
代码 :
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <random>
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
double multiply(double lhs, double rhs){
return lhs * rhs;
}
double divide(double lhs, double rhs){
return lhs / rhs;
}
int main(int argc, char *argv[]){
if (argc == 1)
return 0;
double grounder = 0; //prevent optimizations
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(1.0, 100.0);
size_t loop1 = argc > 2 ? std::stoi (argv[2]) : 1000;
size_t loop2 = argc > 3 ? std::stoi (argv[3]) : 1000;
std::vector<size_t>vecL1(loop1);
std::generate(vecL1.begin(), vecL1.end(), [generator, distribution] () mutable { return distribution(generator); });
std::vector<size_t>vecL2(loop2);
std::generate(vecL2.begin(), vecL2.end(), [generator, distribution] () mutable { return distribution(generator); });
double (*fp)(double, double);
std::string function(argv[1]);
if (function == "multiply")
fp = (*multiply);
if (function == "divide")
fp = (*divide);
std::random_shuffle(vecL1.begin(), vecL1.end());
std::random_shuffle(vecL2.begin(), vecL2.end());
double t1 = get_time();
for (auto outer = vecL1.begin(); outer != vecL1.end(); outer++)
for (auto inner = vecL2.begin(); inner != vecL2.end(); inner++)
grounder += (*fp)(*inner, *outer);
double t2 = get_time();
std::cout << grounder << 'n';
std::cout << (loop1 * loop2) << 'n';
std::cout << "t1 = " << t1 << "tt2 = " << t2
<< "ndifference = " << (t2 - t1) << 'n';
std::cout << "Average length of function : " << (t2 - t1) * 1/(loop1 * loop2) << " seconds n";
return 0;
}
你不只是在测量乘法/除法的速度。如果将代码放入 https://godbolt.org/则可以看到生成的程序集。
您正在测量调用函数的速度,然后在函数内执行乘法/除法。与函数调用的成本相比,单乘/除指令所花费的时间很小,因此会迷失在噪音中。如果你把循环移到函数内部,你可能会看到更多的不同。请注意,通过函数中的循环,编译器可能会决定对代码进行矢量化,这仍然会显示乘法和除法之间是否存在差异,但它不会测量单个 mul/div 指令的差异。
相关文章:
- 努力将整数转换为链表。不知道我在这里做错了什么
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- File.cpp.o:OpenPose 标志 CMakeFiles/.. 的多重定义/main.cpp.o:首先在这里定
- 为什么thread_local变量在这里从未初始化?
- 为什么我必须在这里使用dynamic_cast
- 在这里,当我们比较 if(vc[i]==vc1[i]) 时,它是向量数组. 实际上比较的值是多少,
- 我正在尝试使用 while 循环从字符串中删除字母,直到没有字母。我在这里做错了什么?
- 为什么 C++20 中的 [[可能]] 属性在这里引发警告?
- 我在这里正确传递参数了吗?
- 为什么gmp会在这里与"invalid next size"重新定位一起崩溃?
- 移动语义在这里如何工作?
- 如何在这里循环运行?
- 为什么枚举变量在这里是右值?
- 我的C++合并排序代码不起作用。我在这里错过了什么?
- 试图美化这个Arduino代码[初学者在这里]
- 复制交换习惯用法-我们可以在这里使用动态强制转换操作吗
- 在这里使用删除运算符是否正确,我很困惑
- 如何使用模板生成整数序列在这里工作
- 为什么/如何在这里除法和乘法同样快?