0 c++ macros optimization preprocessor pow
对我的 C++ 代码进行分析后,发现该pow函数被大量使用。
我的一些pow函数有一个整数指数和另一个非整数指数。我只对整数指数感兴趣。
为了提高性能,我正在寻找一种定义宏的方法,如下所示:
#define pow(x,n) ({\
double product;\
if (typeid(n).name() == "i") {\
for(int i = 0; i < n-1; i++)\
product *= x;}\
else\
product = pow(x,n);\
product;\
})
Run Code Online (Sandbox Code Playgroud)
但我没有得到关于运行时间的预期收益。我认为这是由于else我的宏中我称之为经典pow函数的部分所致。
如何在预处理期间“写入”宏之前提前确定指数类型?
理想情况下,我希望仅在指数是整数时应用此宏,但似乎我的尝试不相关。
根据您的建议,我尝试了三种选择:
第一个选项:只需添加重载内联函数,其基数为integeror double:
// First option
inline int pow(int x, int n){
// using simple mechanism for repeated multiplication
int product = 1;
for(int i = 0; i < n; i++){
product *= x;
}
return product;
}
inline int pow(double x, int n){
// using simple mechanism for repeated multiplication
double product = 1;
for(int i = 0; i < n; i++){
product *= x;
}
return product;
}
Run Code Online (Sandbox Code Playgroud)
结果:运行时间 = 1 分 08 秒
my_pow第二个选项:定义一个宏,如果指数n不是整数,则通过内联函数调用:
// Second option
inline double my_pow(double x, double n){
return pow(x,n);
}
#define pow(x,n) ({\
double product = 1;\
if (typeid(n) == typeid(int)) {\
for(int i = 0; i < n; i++)\
product *= x;}\
else product = my_pow(x,n);\
product;\
})
Run Code Online (Sandbox Code Playgroud)
结果:运行时间 = 51.86 秒
第三个选项:在回答中给出的建议template<typename type_t>
template<typename type_t>
inline double pow(const double x, type_t n)
{
// This is compile time checking of types.
// Don't use the RTTI thing you are trying to do
//if constexpr (is_floating_point_v<type_t>)
if (typeid(n) != typeid(int))
{
return pow(x, n);
}
else
{
double value = 1;
for (type_t i = 0; i < n; ++i) value *= x;
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
结果:运行时间 = 52.84 秒
pow因此,最后,从这些第一个测试中,最好的选择是第二个,其中我将宏与调用函数的一般情况(整数和浮点指数)的函数结合使用。
是否有更有效的解决方案或者第二个选项是最好的?
P K*_*mer 14
如果您只需要在浮点类型之间切换,则可以使用模板而不是宏。
#include <cassert>
#include <cmath>
#include <type_traits>
namespace my_math
{
template<typename type_t>
inline double pow(const double x, type_t n)
{
// this is compile time checking of types
// don't use the rtti thing you are trying to do
if constexpr (std::is_floating_point_v<type_t>)
{
return std::pow(x, n);
}
else
{
double value = 1;
for (type_t i = 0; i < n; ++i) value *= x;
return value;
}
};
}
int main()
{
assert(my_math::pow(2, 0) == 1);
assert(my_math::pow(2.0, 1) == 2.0);
assert(my_math::pow(3.0, 2.0) == 9.0);
assert(my_math::pow(4.0f, 3.0f) == 64.0f);
return 0;
}
Run Code Online (Sandbox Code Playgroud)