对于平凡类型,编译器可以将算术表达式优化为具有相同结果的新表达式,该表达式需要较少的指令来计算它。例如,如果a, b是int,则表达式int c = a * a + b * a将计算为(a + b) * a,这节省了指令。有没有办法告诉编译器对自定义类型执行这种优化?例如,如果A, B是矩阵,那么计算A*A + A*B将被分解为A*(A+B)(在编译时),这在运行时节省了大约n2个操作。
a, b
int
int c = a * a + b * a
(a + b) * a
A, B
A*A + A*B
A*(A+B)
ff29svar1#
首先要注意,矩阵的A*A + A*B != (A+B)*A,甚至不接近,它是A*(A+B),这和矩阵乘法不交换不一样,也就是说,你所要求的,作为一个概念上的东西,是可行的。这不是一个完整的答案,只是一个提示。正如@JerryJeremiah正确地写的那样,你可以使用表达式模板。首先对于你的矩阵类,你返回一个未求值的上下文,而不是实现表达式求值的运算符:(这里我展示值scemantics,当然,你可以使用引用/指针来实现它)
A*A + A*B != (A+B)*A
template<typename LHS, typename RHS, char op> struct OperatorContext { static constexpr char operator = op; const LHS lhs; const RHS rhs; }; // inside Matrix { template<typename LHS, typename RHS, char op> friend auto operator+(const Matrix& lhs, OperatorContext<LHS, RHS, op>& rhs) { return OperatorContext<Matrix, OperatorContext<LHS, RHS, op>, '+'>{lhs, rhs}; } template<typename LHS, typename RHS, char op> friend auto operator+(OperatorContext<LHS, RHS, op>& lhs, const Matrix& rhs) { return OperatorContext<Matrix, OperatorContext<LHS, RHS, op>, '+'>{lhs, rhs}; } friend auto operator+(const Matrix& lhs, const Matrix& rhs) { return OperatorContext<Matrix, Matrix, '+'>{lhs, rhs}; } // similarly for other operators // } // furthermore, you need similar operators for 2 OperatorContext arguments
然后,您可以从不同的OperatorContext<>版本中实现Matrix的赋值运算符。在这里,您可以进行优化,因为您有完整的类型信息。请注意,只有在您为变量赋值之前,此操作才有效。例如:
OperatorContext<>
Matrix
// inside Matrix { Matrix& operator=(OperatorContext<OperatorContext<Matrix, Matrix, '*'>, OperatorContext<Matrix, Matrix, '*', '+'> other) { if (other.lhs.lhs == other.rhs.lhs) { // preferably compare-by-address *this = other.lhs.lhs * (other.lhs.rhs + other.rhs.rhs) } else { *this = other.lhs.lhs * other.lhs.rhs + other.rhs.lhs * other.rhs.rhs; } return *this; } // }
1条答案
按热度按时间ff29svar1#
首先要注意,矩阵的
A*A + A*B != (A+B)*A
,甚至不接近,它是A*(A+B)
,这和矩阵乘法不交换不一样,也就是说,你所要求的,作为一个概念上的东西,是可行的。这不是一个完整的答案,只是一个提示。正如@JerryJeremiah正确地写的那样,你可以使用表达式模板。首先对于你的矩阵类,你返回一个未求值的上下文,而不是实现表达式求值的运算符:(这里我展示值scemantics,当然,你可以使用引用/指针来实现它)
然后,您可以从不同的
OperatorContext<>
版本中实现Matrix
的赋值运算符。在这里,您可以进行优化,因为您有完整的类型信息。请注意,只有在您为变量赋值之前,此操作才有效。例如: