编辑:找到了一个很好的解决方案(-25%)valarray,如果我应该以某种方式改变问题状态,请发表评论
假设我有一个数组或任何其他具有>E6 float/double 值的容器
对于容器内的每个元素,我都想调用一个函数
例如。 sin(x) 或者更复杂的东西。
代码:C++11
代码是一个基准示例
#include <random>
#include <iostream>
#include <cmath>
#include <chrono>
#include <algorithm>
#include <valarray>
int main()
{
std::cout<<"start\n";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(-1000, 1000);
int N=100;
while(N--)
{
std::cout<<"\nN: "<<N;
{
int T=1E7,T0=T;
std::vector<float> array;
while(T--)
{
array.push_back(dis(gen));
}
auto start_time = std::chrono::high_resolution_clock::now();
while(T0--)
{
array[T0]=sin(array[T0]);
}
auto time2=std::chrono::high_resolution_clock::now()-start_time;
std::cout<<"\nno: "<<std::chrono::duration_cast<std::chrono::microseconds>(time2).count();
}
{
int T=1E7;
std::vector<float> array;
while(T--)
{
array.push_back(dis(gen));
}
auto start_time = std::chrono::high_resolution_clock::now();
for_each (array.begin(), array.end(), sin);
auto time2=std::chrono::high_resolution_clock::now()-start_time;
std::cout<<"\nit: "<<std::chrono::duration_cast<std::chrono::microseconds>(time2).count();
}
{
int T=1E7;
std::valarray<float> array(T);
while(T--)
{
array[T]=dis(gen);
}
auto start_time = std::chrono::high_resolution_clock::now();
array=sin(array);
auto time2=std::chrono::high_resolution_clock::now()-start_time;
std::cout<<"\nvalarray: "<<std::chrono::duration_cast<std::chrono::microseconds>(time2).count();
}
}
std::cout<<"\nfin\n";
return 0;
}
有没有这样的快速好方法:
sin(&array)
或
array=sin(array)
编辑:
for_each(it) seems to be 5-10% slower;
no: 1014219
it: 1060500
valarray: 742929
in microsec;
编辑 2: Sinus 是一个相当复杂的算法,问题是如果有人知道一个库可能在 boost 中优化了一些数学函数以直接与容器一起工作,而不是每次都“启动”漏洞。
最佳答案
我觉得没有神奇的代码可以让它变快或变好。尽可能简单。
我看到您可以采取两项行动。 1)将两个循环合并为一个。你可以使用任何你可以使用的循环。 2) 在 C++11 中使用类似 OpenMP 或线程的并行计算。
另一件事是,如果你可以先使用 uniform_int_distribution,如果 T 真的很大,也许你可以使用 hashmap 来存储 sin 值。
关于C++优化函数调用批处理模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31932262/