Add quick simd implementation, needs a lot more work still.

This commit is contained in:
King_DuckZ 2016-09-19 03:19:55 +02:00
parent f23f6d4583
commit e0c9b34a5d
6 changed files with 163 additions and 0 deletions

View File

@ -0,0 +1,55 @@
/*
* Copyright 2015, 2016 Michele "King_DuckZ" Santullo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef id2996A9D174804F7B88936D6C363D235B
#define id2996A9D174804F7B88936D6C363D235B
#include "vectorwrapper/vectorwrapper.hpp"
#include <type_traits>
#include <emmintrin.h>
namespace vwr {
namespace simd {
template <typename V, std::size_t=::vwr::Vec<V>::dimensions, typename=typename ::vwr::Vec<V>::scalar_type>
class Vec;
template <typename V>
class Vec<V, 3, float> : public ::vwr::Vec<V, 3> {
typedef ::vwr::Vec<V, 3> base_class;
public:
static_assert(alignof(V) % 16 == 0, "Wrapped type must be aligned to 16");
static_assert(base_class::is_interleaved_mem == 0, "Expected tightly packed vector_type");
using typename base_class::vector_type;
typedef float scalar_type;
Vec ( void ) = default;
Vec ( const Vec& ) = default;
explicit Vec ( const vector_type& parIn ) : base_class(parIn) { }
explicit Vec ( const scalar_type parX ) : base_class(parX) { }
explicit Vec ( const base_class& parIn ) : base_class(parIn) { }
template <typename V2> Vec& operator+= ( const Vec<V2, 3, scalar_type>& parOther );
template <typename V2> Vec& operator-= ( const Vec<V2, 3, scalar_type>& parOther );
template <typename V2> Vec& operator*= ( const Vec<V2, 3, scalar_type>& parOther );
template <typename V2> Vec& operator/= ( const Vec<V2, 3, scalar_type>& parOther );
};
} //namespace simd
} //namespace vwr
#include "vectorwrapper/vectorwrapper_simd.inl"
#endif

View File

@ -0,0 +1,47 @@
/*
* Copyright 2015, 2016 Michele "King_DuckZ" Santullo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace vwr {
namespace simd {
template <typename V>
template <typename V2>
auto Vec<V, 3, float>::operator+= (const Vec<V2, 3, scalar_type>& parOther) -> Vec& {
__m128 pack_this;
__m128 pack_other;
pack_this = _mm_load_ps(&this->x());
pack_other = _mm_load_ps(&parOther.x());
pack_this = _mm_add_ps(pack_this, pack_other);
_mm_store_ps(&this->x(), pack_this);
return *this;
}
template <typename V>
template <typename V2>
auto Vec<V, 3, float>::operator-= (const Vec<V2, 3, scalar_type>& parOther) -> Vec& {
__m128 pack_this;
__m128 pack_other;
pack_this = _mm_load_ps(&this->x());
pack_other = _mm_load_ps(&parOther.x());
pack_this = _mm_sub_ps(pack_this, pack_other);
_mm_store_ps(&this->x(), pack_this);
return *this;
}
} //namespace simd
} //namespace vwr

View File

@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
include(CTest)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 -std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -std=c++11")
@ -12,3 +14,4 @@ include_directories(SYSTEM
)
include_directories(../include)
add_subdirectory(unit)
add_subdirectory(speed)

18
test/speed/CMakeLists.txt Normal file
View File

@ -0,0 +1,18 @@
project(speed CXX)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mfpmath=sse -mmmx -msse -msse2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpmath=sse -mmmx -msse -msse2")
add_executable(${PROJECT_NAME}
${GTEST_MAIN_CPP}
speed.cpp
)
target_link_libraries(${PROJECT_NAME}
gtest
)
add_test(
NAME SpeedTest
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${PROJECT_NAME}
)

34
test/speed/speed.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "vectorwrapper/vectorops.hpp"
#include "vectorwrapper/vectorwrapper_simd.hpp"
#include <gtest/gtest.h>
#include <memory>
namespace vwr {
typedef std::aligned_storage<sizeof(float) * 3, 16>::type float3_storage;
template <>
struct VectorWrapperInfo<float3_storage> {
enum { dimensions = 3 };
typedef float scalar_type;
enum {
offset_x = 0,
offset_y = offset_x + sizeof(scalar_type),
offset_z = offset_y + sizeof(scalar_type)
};
};
} //namespace vwr
TEST(vwr_speed, speed) {
typedef vwr::simd::Vec<vwr::float3_storage> simd_vec3;
static_assert(sizeof(simd_vec3) >= sizeof(float) * 3, "SIMD vector too small");
simd_vec3 v1(1.0f);
simd_vec3 v2(0.5f);
v1 += v2;
EXPECT_FLOAT_EQ(1.5f, v1.x());
EXPECT_FLOAT_EQ(1.5f, v1.y());
EXPECT_FLOAT_EQ(1.5f, v1.z());
}

View File

@ -10,3 +10,9 @@ add_executable(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
gtest
)
add_test(
NAME UnitTest
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${PROJECT_NAME}
)