将多个函数调用折叠为单个函数?
Fold multiple function-calls to single function?
我在考虑一个简单的 SIMD class,它支持重载算术运算符 +-*/
等
在将其实现为 class 模板以支持不同类型的内部函数时,我注意到有一些可用的函数可以一次执行多个操作(_mm_fmadd_ps
用于乘法和加法)。
我现在想知道是否有一种 相对合理的 方法来仍然使用数学运算符重载
a * b + c -> madd( a , b , c )
而不是使用正常的免费功能
add( mul( a , b ) , c ) -> madd( a , b , c )
和 使用这些较新的内部函数。
所以我的问题归结为:
- 是否可以链 多个(独立的)函数调用只调用一个特定函数(一般问题,与 SIMD 无关)?
- (当代理能够做到这一点时,他们值得吗)?
- 如果没有,什么是继续 api 设计 SIMD 容器以提供正常操作并能够更新内在函数的好方法?
- 同时提供运算符重载和自由函数
- 放弃运算符重载,只依赖自由函数
- 是否允许编译器折叠内在函数以在适当的地方自动使用新内在函数? (当内在函数可用时,将
add( mul( a , b ) , c )
折叠到 madd( a , b , c )
and/or 已用于所需版本的内在函数)
像这样(您可能想要使用最大优化器设置):
#include <iostream>
template<class Intrinsic>
struct optimised
{
using type = Intrinsic;
optimised(type v)
: _v (v)
{}
operator type&() {
return _v;
}
operator const type&() const {
return _v;
}
type _v;
};
// naiive implementation of madd
double madd(double a, double b, double c) {
std::cout << "madd(" << a << ", " << b << ", " << c << ")" << std::endl;
return (a * b) + c;
}
struct mul_result
{
mul_result(const double& a, const double&b)
: _a(a), _b(b)
{}
operator double() const {
return _a * _b;
}
const double &_a, &_b;
};
double operator+(const mul_result& ab, const double& c)
{
return madd(ab._a, ab._b, c);
}
mul_result operator*(const optimised<double>& a, const optimised<double>& b)
{
return mul_result(a, b);
}
using namespace std;
int main()
{
optimised<double> a = 3, b = 7, c = 2;
auto x = a * b + c;
cout << x << endl;
return 0;
}
预期输出:
madd(3, 7, 2)
23
我在考虑一个简单的 SIMD class,它支持重载算术运算符 +-*/
等
在将其实现为 class 模板以支持不同类型的内部函数时,我注意到有一些可用的函数可以一次执行多个操作(_mm_fmadd_ps
用于乘法和加法)。
我现在想知道是否有一种 相对合理的 方法来仍然使用数学运算符重载
a * b + c -> madd( a , b , c )
而不是使用正常的免费功能
add( mul( a , b ) , c ) -> madd( a , b , c )
和 使用这些较新的内部函数。
所以我的问题归结为:
- 是否可以链 多个(独立的)函数调用只调用一个特定函数(一般问题,与 SIMD 无关)?
- (当代理能够做到这一点时,他们值得吗)?
- 如果没有,什么是继续 api 设计 SIMD 容器以提供正常操作并能够更新内在函数的好方法?
- 同时提供运算符重载和自由函数
- 放弃运算符重载,只依赖自由函数
- 是否允许编译器折叠内在函数以在适当的地方自动使用新内在函数? (当内在函数可用时,将
add( mul( a , b ) , c )
折叠到madd( a , b , c )
and/or 已用于所需版本的内在函数)
像这样(您可能想要使用最大优化器设置):
#include <iostream>
template<class Intrinsic>
struct optimised
{
using type = Intrinsic;
optimised(type v)
: _v (v)
{}
operator type&() {
return _v;
}
operator const type&() const {
return _v;
}
type _v;
};
// naiive implementation of madd
double madd(double a, double b, double c) {
std::cout << "madd(" << a << ", " << b << ", " << c << ")" << std::endl;
return (a * b) + c;
}
struct mul_result
{
mul_result(const double& a, const double&b)
: _a(a), _b(b)
{}
operator double() const {
return _a * _b;
}
const double &_a, &_b;
};
double operator+(const mul_result& ab, const double& c)
{
return madd(ab._a, ab._b, c);
}
mul_result operator*(const optimised<double>& a, const optimised<double>& b)
{
return mul_result(a, b);
}
using namespace std;
int main()
{
optimised<double> a = 3, b = 7, c = 2;
auto x = a * b + c;
cout << x << endl;
return 0;
}
预期输出:
madd(3, 7, 2)
23