2017-12-10 15 views
0

I는 다음과 같이 정의 된 벡터 클래스는 다음과 같습니다운영자는

template <unsigned int SIZE> 
Vector<SIZE> operator+ (const Vector<SIZE>& vec, float c); 

template<> 
Vector<3> operator+ (const Vector<3>& vec, float c); 

template<> 
Vector<4> operator+ (const Vector<4>& vec, float c); 

template <unsigned int SIZE> 
Vector<SIZE> operator+ (const Vector<SIZE>& vec1, const Vector<SIZE>& vec2); 

template <> 
Vector<3> operator+ (const Vector<3>& vec1, const Vector<3>& vec2); 

template <> 
Vector<4> operator+ (const Vector<4>& vec1, const Vector<4>& vec2); 
:

template <unsigned int SIZE> 
class Vector : public Stringable 
{ 
    private: 

     float mData [SIZE]; 

    public: 
     Vector(); 

     ... 
}; 

내가이 (수학) 벡터에 (Vector 클래스의 외부에) 몇 가지 연산자를 선언 한

이것은 그들이 구현하는 방법입니다

template <unsigned int SIZE> 
Vector<SIZE> operator+(const Vector<SIZE>& vec1, const Vector<SIZE>& vec2) 
{ 
    Vector<SIZE> result = Vector<SIZE>(vec1); 

    int i = 0; 
    for (i = 0; (i + 4) < SIZE; i += 4) 
    { 
     __m128 lhs = _mm_set_ps(vec1[i], vec1[i+1], vec1[i+2], vec1[i+3]); 
     __m128 rhs = _mm_set_ps(vec2[i], vec2[i+1], vec2[i+2], vec2[i+3]); 
     _mm_add_ps(lhs, rhs); 
     _mm_store_ps(result.getRawData(), lhs); 
    } 

    for (; i < SIZE; i++) 
    { 
     result[i] = vec1[i] - vec2[i]; 
    } 

    return result; 
} 

template<> 
Vector<3> operator+<3>(const Vector<3>& vec1, const Vector<3>& vec2) 
{ 
    Vector<3> result = Vector<3>(vec1); 
    float tmpBuffer [4]; 

    __m128 lhs = _mm_set_ps(vec1[0], vec1[1], vec1[2], 0); 
    __m128 rhs = _mm_set_ps(vec2[0], vec2[1], vec2[2], 0); 
    _mm_add_ps(lhs, rhs); 
    _mm_store_ps(tmpBuffer, lhs); 
    mempcpy(result.getRawData(), tmpBuffer, 3 * sizeof(float)); 

    return result; 
} 

template<> 
Vector<4> operator+<4>(const Vector<4>& vec1, const Vector<4>& vec2) 
{ 
    Vector<4> result = Vector<4>(vec1); 

    __m128 lhs = _mm_set_ps(vec1[0], vec1[1], vec1[2], vec1[3]); 
    __m128 rhs = _mm_set_ps(vec2[0], vec2[1], vec2[2], vec1[3]); 
    _mm_add_ps(lhs, rhs); 
    _mm_store_ps(result.getRawData(), lhs); 

    return result; 
} 

template <unsigned int SIZE> 
Vector<SIZE> operator+(const Vector<SIZE>& vec, float c) 
{ 
    Vector<SIZE> result = Vector<SIZE>(vec); 

    int i = 0; 
    for (i = 0; (i + 4) < SIZE; i += 4) 
    { 
     __m128 lhs = _mm_set_ps(vec[i], vec[i+1], vec[i+2], vec[i+3]); 
     __m128 rhs = _mm_set1_ps(c); 
     _mm_add_ps(lhs, rhs); 
     _mm_store_ps(result.getRawData(), lhs); 
    } 

    for (; i < SIZE; i++) 
    { 
     result[i] = vec[i] + c; 
    } 

    return result; 
} 

template <> 
Vector<3> operator+<3>(const Vector<3>& vec, float c) 
{ 
    Vector<3> result = Vector<3>(vec); 
    float tmpBuffer [4]; 

    __m128 lhs = _mm_set_ps(vec[0], vec[1], vec[2], 0); 
    __m128 rhs = _mm_set1_ps(c); 
    _mm_add_ps(lhs, rhs); 
    _mm_store_ps(tmpBuffer, lhs); 
    mempcpy(result.getRawData(), tmpBuffer, 3 * sizeof(float)); 

    return result; 
} 

template <> 
Vector<4> operator+<4>(const Vector<4>& vec, float c) 
{ 
    Vector<4> result = Vector<4>(vec); 

    __m128 lhs = _mm_set_ps(vec[0], vec[1], vec[2], 0); 
    __m128 rhs = _mm_set1_ps(c); 
    _mm_add_ps(lhs, rhs); 
    _mm_store_ps(result.getRawData(), lhs); 

    return result; 
} 

위의 코드의 모든 "Vector.cpp"

현재 인텔의 SSE 내장 함수를 사용하여 '일반적인'벡터 연산에서 SIMD 연산으로 이동하는 중입니다.

크기가 3 & 4 인 벡터는 내 응용 프로그램에서 매우 일반적이므로 XMM 레지스터를보다 잘 사용할 수 있도록 템플릿 연산자를 전문으로하고 싶습니다. (볼 수 있듯이 SIMD 루프는 크기가 < 인 벡터에 대해서는 사용되지 않습니다 4).

불행하게도, 실제로이 작업을 수행하는 방법에 대한 손실에 있어요, 정말 ...

편집을 어떤 템플릿 매개 변수가 될 필요가 내가 필요한 선언/정의를 몰라 : 지금은 '다중 정의'링커 오류가 발생합니다. clang ++ 5.0을 사용하고 있습니다.

이러한 오류가 약 50 개 (50 개는 추측 일뿐입니다), 모든 전문 분야가 같습니다 선물로 ...

CMakeFiles/Space.elf.dir/src/Entities/Entity.cpp.o: In function `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, float)': 
/home/.../CLionProjects/Space/src/Maths/Vector.cpp:427: multiple definition of `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, float)' 
CMakeFiles/Space.elf.dir/src/main.cpp.o:/home/.../CLionProjects/Space/src/Maths/Vector.cpp:427: first defined here 
CMakeFiles/Space.elf.dir/src/Entities/Entity.cpp.o: In function `Maths::Vector<4u> Maths::operator+<4u>(Maths::Vector<4u> const&, Maths::Vector<4u> const&)': 
/home/.../CLionProjects/Space/src/Maths/Vector.cpp:392: multiple definition of `Maths::Vector<4u> Maths::operator+<4u>(Maths::Vector<4u> const&, Maths::Vector<4u> const&)' 
CMakeFiles/Space.elf.dir/src/main.cpp.o:/home/.../CLionProjects/Space/src/Maths/Vector.cpp:392: first defined here 
/home/.../CLionProjects/Space/src/Maths/Vector.cpp:377: multiple definition of `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, Maths::Vector<3u> const&)' 
CMakeFiles/Space.elf.dir/src/main.cpp.o:/home/.../CLionProjects/Space/src/Maths/Vector.cpp:377: first defined here 
CMakeFiles/Space.elf.dir/src/Entities/EntityManager.cpp.o: In function `Maths::Vector<3u> Maths::operator+<3u>(Maths::Vector<3u> const&, float)': 

나는 경로의 일부를 검열했지만 아이디어는 얻을 수있다.

+0

헤더가 있습니까 파일 Vector.h? 모든 템플릿 정의는 헤더에 있어야한다고 생각합니다. –

답변

0

좋아, 문제를 해결했다. 다른 클래스와 마찬가지로 정의와 선언을 구분했습니다. 그런 다음 내 구현 파일 (.cpp)의 맨 아래에서 클래스를 비롯하여 모든 연산자를 명시 적으로 인스턴스화했습니다.

(불행하게도 로딩/언 로딩의 양이 만든 SIMD 명령어는 전체 클래스를 전문으로하는 이곳의 솔루션이 될 수 있습니다. 제거되었다,하지만 다른 시간의보다 하다며 만들어 더 많은 오버 헤드가 있기 때문에 폐기)