C+的备选方案/建议+;虚函数多态性 我有一个程序,主要计算C++中非常大的向量的滚动平均和其他滚动统计。对于大小为N的向量,我想得到另一个大小为N的向量,元素k包含从0到k的滚动统计信息。下面我将使用滚动平均值进行说明
程序有一个对象,该对象具有基于新值和以前的统计值更新滚动统计的功能。例如:C+的备选方案/建议+;虚函数多态性 我有一个程序,主要计算C++中非常大的向量的滚动平均和其他滚动统计。对于大小为N的向量,我想得到另一个大小为N的向量,元素k包含从0到k的滚动统计信息。下面我将使用滚动平均值进行说明,c++,polymorphism,C++,Polymorphism,程序有一个对象,该对象具有基于新值和以前的统计值更新滚动统计的功能。例如: inline float update(const float x) { _n++; _mean += (x - _mean)/_n; return _mean; } 现在我想支持其他统计计算,比如滚动标准差,计划是添加一个纯虚拟类作为基类,使用纯虚拟步长函数,创建不同统计类型对应的不同子类 我的问题是:因为step函数将是函数的主要部分,并且将被执行数十亿次,所以我是否希望通过从内联函数切换到
inline float update(const float x) {
_n++;
_mean += (x - _mean)/_n;
return _mean;
}
现在我想支持其他统计计算,比如滚动标准差,计划是添加一个纯虚拟类作为基类,使用纯虚拟步长函数,创建不同统计类型对应的不同子类
我的问题是:因为step函数将是函数的主要部分,并且将被执行数十亿次,所以我是否希望通过从内联函数切换到虚拟函数来降低速度?对于我想做的事情,还有其他更有效的选择吗?或者我没有使用正确的设计模式,还有其他更好的方法吗?使用多态性通常是一个非常好的策略。这是一种经过验证和时间考验的方法,可用于构建正确且可维护的软件。vtable问题很少是影响性能的因素。一些有趣的文章和关于vtable的大量优化 还有其他一些好主意。例如,查看下面的示例。在创建处理程序对象时,您可以使用它来选择所选函数,可能是通过模板或作为ctor的参数。由于该策略在施工时选择一次,因此不会产生任何可变的惩罚 另一个相关的想法是将lambda函数与一些std::算法结合使用。自C++11以来,这种模式变得非常普遍。lambda用于代替多态性。下面是一个简单的例子,可以为您的项目提供一些想法
#include <iostream>
#include <vector>
#include <algorithm>
int main(int argc, char*argv[])
{
std::vector<size_t> input = {2,4,6};
std::vector<size_t> output;
auto const operation = std::stoi(argv[1]);
// transform the input vector to the output vector with algorithm selection
switch(operation)
{
// just copy it
case 1:
{
std::for_each(input.begin() ,input.end(), [&](size_t element){
output.push_back(element);
});
break;
}
// divide it by 2
case 2:
{
std::for_each(input.begin() ,input.end(), [&](size_t element){
output.push_back(element/2);
});
break;
}
}
for(auto const & element:output)
std::cout << element << std::endl;
}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
向量输入={2,4,6};
std::矢量输出;
自动常量操作=std::stoi(argv[1]);
//使用算法选择将输入向量转换为输出向量
开关(操作)
{
//复制它就行了
案例1:
{
std::for_each(input.begin()、input.end()、[&](size_t元素){
输出。推回(元件);
});
打破
}
//除以2
案例2:
{
std::for_each(input.begin()、input.end()、[&](size_t元素){
输出。推回(元件/2);
});
打破
}
}
用于(自动常量和元素:输出)
std::cout使用多态性通常是一种非常好的策略。它是一种经过验证和时间考验的方法,可以构建正确的和可维护的软件。vtable问题很少是性能的一个因素。一些有趣的文章和关于vtable的大量优化
还有其他一些好主意。请查看示例。在创建处理程序对象时,您可以使用它来选择所选函数,可能是通过模板或作为ctor的参数。由于策略在构造时选择一次,因此不会产生vtable惩罚
另一个相关的想法是将lambda函数与一些std::算法结合使用。自C++11以来,这种模式变得非常普遍。lambda被用来代替多态性。下面是一个简单的示例,可以为您的项目提供一些想法
#include <iostream>
#include <vector>
#include <algorithm>
int main(int argc, char*argv[])
{
std::vector<size_t> input = {2,4,6};
std::vector<size_t> output;
auto const operation = std::stoi(argv[1]);
// transform the input vector to the output vector with algorithm selection
switch(operation)
{
// just copy it
case 1:
{
std::for_each(input.begin() ,input.end(), [&](size_t element){
output.push_back(element);
});
break;
}
// divide it by 2
case 2:
{
std::for_each(input.begin() ,input.end(), [&](size_t element){
output.push_back(element/2);
});
break;
}
}
for(auto const & element:output)
std::cout << element << std::endl;
}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
向量输入={2,4,6};
std::矢量输出;
自动常量操作=std::stoi(argv[1]);
//使用算法选择将输入向量转换为输出向量
开关(操作)
{
//复制它就行了
案例1:
{
std::for_each(input.begin()、input.end()、[&](size_t元素){
输出。推回(元件);
});
打破
}
//除以2
案例2:
{
std::for_each(input.begin()、input.end()、[&](size_t元素){
输出。推回(元件/2);
});
打破
}
}
用于(自动常量和元素:输出)
据我所知,您可以使用模板,类似于
template <typename Range, typename F>
auto f(const Range& r, F&& f)
{
std::vector<std::decay_t<decltype(f(*r.begin()))>> result;
result.reserve(r.size());
for (const auto& e : v) {
result.push_back(f(e));
}
return result;
}
class MeanCalculator
{
public:
float operator()(float x) const {
n++;
mean += (x - mean) / n;
return mean;
}
private:
std::size_t n = 0;
float mean = 0.0f;
};
class VarianceCalculator
{
public:
float operator()(float x) const {
n++;
// ...
}
private:
std::size_t n = 0;
//...
};
模板
自动f(常数范围和r、f和f)
{
std::向量结果;
结果:保留(r.size());
用于(常数自动和e:v){
结果:推回(f(e));
}
返回结果;
}
类均值计算器
{
公众:
浮点运算符()(浮点x)常量{
n++;
平均值+=(x-平均值)/n;
回归均值;
}
私人:
标准:尺寸n=0;
浮动平均值=0.0f;
};
类变量计算器
{
公众:
浮点运算符()(浮点x)常量{
n++;
// ...
}
私人:
标准:尺寸n=0;
//...
};
然后
std::vector<float> numbers = /*...*/;
auto means = f(numbers, MeanCalculator{});
auto variances = f(numbers, VarianceCalculator{});
std::向量数=/*…*/;
自动平均数=f(数字,平均计算器{});
自动方差=f(数字,方差计算器{});
注意:std::transform
不能使用,因为它不能保证按顺序应用f
据我所知,您可以使用模板,类似于
template <typename Range, typename F>
auto f(const Range& r, F&& f)
{
std::vector<std::decay_t<decltype(f(*r.begin()))>> result;
result.reserve(r.size());
for (const auto& e : v) {
result.push_back(f(e));
}
return result;
}
class MeanCalculator
{
public:
float operator()(float x) const {
n++;
mean += (x - mean) / n;
return mean;
}
private:
std::size_t n = 0;
float mean = 0.0f;
};
class VarianceCalculator
{
public:
float operator()(float x) const {
n++;
// ...
}
private:
std::size_t n = 0;
//...
};
模板
自动f(常数范围和r、f和f)
{
std::向量结果;
结果:保留(r.size());
用于(常数自动和e:v){
结果:推回(f(e));
}
返回结果;
}
类均值计算器
{
公众:
浮点运算符()(浮点x)常量{
n++;
平均值+=(x-平均值)/n;
回归均值;
}
私人:
标准:尺寸n=0;
浮动平均值=0.0f;
};
类变量计算器
{
公众:
浮点运算符()(浮点x)常量{
n++;
// ...
}
私人:
标准:尺寸n=0;
//...
};
然后
std::vector<float> numbers = /*...*/;
auto means = f(numbers, MeanCalculator{});
auto variances = f(numbers, VarianceCalculator{});
std::向量数=/*…*/;
自动平均数=f(数字,平均计算器{});
自动方差=f(数字,方差计算器{});
注: