我正在设计一系列支持SSE(SIMD)的C ++ Vector类。为方便起见,操作员已经超载。上课的例子:
class vector2 {
public:
//...code
friend const vector2 operator+ (const vector2 & lhs, const vector2 & rhs);
//...code
protected:
float x, y;
};
到目前为止,该方法使用我创建的名为PROCESSOR的类来检查CPU是否具有SSE(SIMD)功能,该类在运行时执行该程序时进行检查。方法示例:
const vector2 operator+ (const vector2 & lhs, const vector2 & rhs) {
vector2 temp;
if(PROCESSOR.SSE) {
_asm { //... The "SSE WAY"
}
} else {
// The "NORMAL WAY"
}
return temp;
}
因此,您可以看到SSE是否可用,它将运行“SSE”方式,否则将以“正常”方式运行。但是,每次调用此操作时都必须检查SSE是否可用是非常低效的。有没有办法实现方法的两个版本并只调用适当的方法?由于我的PROCESSOR类只进行了一次SSE检查,有没有办法设置我的vector类可以做同样的事情?
答案 0 :(得分:2)
为了帮助您避免代码重复,您可以创建两个向量类,一个用于SSE,另一个用于非SSE。然后,您可以模拟您的调用算法。
class vector_base { float x,y; } ;
class vector_sse : public vector_base { vector_sse operator+(...){...} };
class vector_nonsse : public vector_base { vector_nonsse operator+(...){...} };
template< typename VECTOR >
void do_somthing() {
for( /*lots*/) {
VECTOR v = ...;
VECTOR w = ...;
foo(v+w);
}
}
int main() {
if(PROCESSOR.SSE) { do_something<vector_sse>(); }
else { do_something<vector_nonsse>(); }
}
如果您可能以SSE方式使用除矢量之外的其他类(如矩阵等),则可以通过标记类型来做得更好......在这种情况下代码如下所示:
class vector_base { float x,y; } ;
struct SSE_tag;
struct NONSSE_tag;
template<typename T>
class vector;
template<>
class vector<SSE_tag> : public vector_base { vector_sse operator+(...){...} };
template<>
class vector<NONSSE_tag> : public vector_base { vector_nonsse operator+(...){...} };
template< typename TAG >
void do_somthing() {
for( /*lots*/) {
vector<TAG> v = ...;
vector<TAG> w = ...;
matrix<TAG> m = ...;
foo(v+(m*w));
}
}
int main() {
if(PROCESSOR.SSE) { do_something<SSE_tag>(); }
else { do_something<NONSSE_tag>(); }
}
答案 1 :(得分:0)
将功能拆分为两部分,一部分用于SSE,另一部分用于SSE。创建一个函数指针并使用相应的函数版本对其进行初始化。您可以创建一个调用指针的内联函数,如果这样可以使代码看起来更清晰。
不幸的是,您仍然会为函数调用支付间接费用。这是否比测试布尔标志更快只能通过基准测试来确定。
解决此问题的最佳方法是确保每次调用处理的数据量足以使开销无关紧要。