3

伙计们,想象我有一个模板功能:

template <typename T> Vector<T>* Vector<T>::overwrite(const Vector<T>* copy) {
    this->_normalized = copy->_normalized;

    this->_data[0] = copy->_data[0];
    this->_data[1] = copy->_data[1];
    this->_data[2] = copy->_data[2];
    this->_data[3] = copy->_data[3];

    return this;
}

及其规格:

template <> Vector<float>* Vector<float>::overwrite(const Vector<float>* copy) {
    __m128 data = _mm_load_ps(copy->_data);

    _mm_store_ps(this->_data, data);

    return this;
}

现在我想确保处理器支持 SSE,特别是处理器具有 XMM 寄存器,可以使用 1 条指令复制 4 个浮点数。然后我想对精度有相同的功能,所以我需要 YMM 寄存器。

所以我想知道是否有办法在运行时确定 XMM 和 YMM 的可用性。

另一个更可取的选择是在预处理器工作期间以某种方式知道。即这样我就写了类似的东西:

template <typename T> Vector<T>* Vector<T>::overwrite(const Vector<T>* copy) {
    this->_normalized = copy->_normalized;

    this->_data[0] = copy->_data[0];
    this->_data[1] = copy->_data[1];
    this->_data[2] = copy->_data[2];
    this->_data[3] = copy->_data[3];

    return this;
}

#ifdef XMM_ARE_AVAILABLE
template <> Vector<float>* Vector<float>::overwrite(const Vector<float>* copy) {
    __m128 data = _mm_load_ps(copy->_data);

    _mm_store_ps(this->_data, data);

    return this;
}
#endif

#ifdef YMM_ARE_AVAILABLE
template <> Vector<double>* Vector<double>::overwrite(const Vector<double>* copy) {
    /* code that moves four doubles */

    return this;
}
#endif

谢谢!

4

1 回答 1

0

说服编译器自己对它进行矢量化比使用内部函数或 asm 编写专门的代码要好得多。麻烦的部分是指针(或引用,如果它们已被使用),Vector 参数指针和“this”。

不幸的是,C++ 不直接支持“限制”,但大多数编译器应该有某种特定于实现的属性来做到这一点。与 g++ 一起使用__restrict__,它也适用于函数类型以限制“this”:

http://gcc.gnu.org/onlinedocs/gcc/Restricted-Pointers.html

一些编译器(例如 llvm)可以将展开的循环矢量化为直线代码,如您的示例中所示。其他人将希望重新滚动循环。通常,出于自动矢量化目的,编写循环比手动展开代码更好。

此示例是自动矢量化的一个简单案例,您将拥有更多可移植代码。

于 2014-01-06T19:28:03.493 回答