【发布时间】:2024-04-23 14:25:02
【问题描述】:
编辑:找到了一个好的解决方案(-25%)valarray,如果我应该以某种方式更改问题状态,请发表评论
假设我有一个数组或任何其他具有 >E6 浮点/双精度值的容器
对于容器内的每个元素,我都想进行函数调用
例如。 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 中优化了一些数学函数以直接与容器一起工作,而不是每次都“启动”这个漏洞。
【问题讨论】:
-
基于基准,它让人相信您正在对未优化的构建进行基准测试,因为您的
std::for_each案例基本上什么都不做(gcc 甚至 eliminates the call to it),但该案例的时间仍然显示达到你的基准。这似乎是 SIMD 操作的完美候选,但如果您甚至不费心调整优化开关,编译器能够生成 SIMD 指令的机会可能会大大降低。
标签: c++ algorithm optimization boost containers