init
This commit is contained in:
commit
89c98adf3c
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
build
|
||||
CMakeUserPresets.json
|
||||
compile_commands.json
|
||||
.cache/
|
||||
10
CMakeLists.txt
Normal file
10
CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(vector-extension)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
add_executable(${PROJECT_NAME} src/bench.cc)
|
||||
|
||||
find_package(benchmark REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark_main)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -save-temps)
|
||||
target_compile_options(${PROJECT_NAME} PUBLIC -mavx -mavx2 -march=native -O2)
|
||||
5
conanfile.txt
Normal file
5
conanfile.txt
Normal file
@ -0,0 +1,5 @@
|
||||
[requires]
|
||||
benchmark/1.9.4
|
||||
[generators]
|
||||
CMakeDeps
|
||||
CMakeToolchain
|
||||
148
src/bench.cc
Normal file
148
src/bench.cc
Normal file
@ -0,0 +1,148 @@
|
||||
// 1.2.1: Example of SSE2 intrinsics
|
||||
// for int32_t
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <stdint.h>
|
||||
// for SSE2 intrinsics
|
||||
#include <emmintrin.h>
|
||||
// for AVX2 intrinsics
|
||||
#include <immintrin.h>
|
||||
|
||||
void vector(void)
|
||||
{
|
||||
int32_t array_a[4] = { 0, 2, 1, 2 }; // 128 bit
|
||||
int32_t array_b[4] = { 8, 5, 0, 6 };
|
||||
int32_t array_c[4];
|
||||
__m128i a, b, c;
|
||||
a = _mm_loadu_si128((__m128i*)array_a); // loading array_a into register a
|
||||
b = _mm_loadu_si128((__m128i*)array_b);
|
||||
c = _mm_add_epi32(a, b); // must be { 8,7,1,8 }
|
||||
_mm_storeu_si128((__m128i*)array_c, c);
|
||||
}
|
||||
|
||||
static void BM_calculateVector(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
vector();
|
||||
}
|
||||
|
||||
BENCHMARK(BM_calculateVector);
|
||||
|
||||
void scalar()
|
||||
{
|
||||
int32_t array_a[4] = { 0, 2, 1, 2 }; // 128 bit
|
||||
int32_t array_b[4] = { 8, 5, 0, 6 };
|
||||
int32_t array_c[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
array_c[i] = array_a[i] + array_b[i];
|
||||
}
|
||||
|
||||
static void BM_calculateScalar(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
scalar();
|
||||
}
|
||||
|
||||
BENCHMARK(BM_calculateScalar);
|
||||
|
||||
template <typename T = int, size_t size = 1024>
|
||||
std::array<T, size> generateLongArray()
|
||||
{
|
||||
std::array<T, size> arr;
|
||||
for (auto& a : arr) {
|
||||
a = rand() % 100;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
template <typename T = int, size_t size = 1024>
|
||||
std::array<T, size> with_vector(std::array<T, size>& arr, std::array<T, size>& arr2)
|
||||
{
|
||||
std::array<T, size> result;
|
||||
auto resPos = result.begin();
|
||||
for (auto it = arr.begin(), it2 = arr2.begin();
|
||||
it < arr.end() && it2 < arr.end();
|
||||
it2 += 4, it += 4) {
|
||||
__m128i a, b, c;
|
||||
a = _mm_loadu_si128((__m128i*)&(*it)); // loading array_a into register a
|
||||
b = _mm_loadu_si128((__m128i*)&(*it2));
|
||||
c = _mm_add_epi32(a, b);
|
||||
_mm_storeu_si128((__m128i*)&(*resPos), c);
|
||||
resPos += 4;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void BM_arrayVector(benchmark::State& state)
|
||||
{
|
||||
auto arr1 = generateLongArray<int, 1 << 16>();
|
||||
auto arr2 = generateLongArray<int, 1 << 16>();
|
||||
|
||||
for (auto _ : state)
|
||||
auto arr3 = with_vector(arr1, arr2);
|
||||
}
|
||||
|
||||
BENCHMARK(BM_arrayVector);
|
||||
|
||||
template <typename T = int, size_t size = 1024>
|
||||
std::array<T, size> with_scalar(std::array<T, size>& arr, std::array<T, size>& arr2)
|
||||
{
|
||||
std::array<T, size> result;
|
||||
auto resPos = result.begin();
|
||||
for (auto it = arr.begin(), it2 = arr2.begin();
|
||||
it < arr.end() && it2 < arr.end();
|
||||
++it2, ++it) {
|
||||
*resPos = *it + *it2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void BM_arrayScalar(benchmark::State& state)
|
||||
{
|
||||
auto arr1 = generateLongArray<int, 1 << 16>();
|
||||
auto arr2 = generateLongArray<int, 1 << 16>();
|
||||
|
||||
for (auto _ : state)
|
||||
auto arr3 = with_scalar(arr1, arr2);
|
||||
}
|
||||
|
||||
BENCHMARK(BM_arrayScalar);
|
||||
|
||||
template <typename T = int, size_t size = 1024>
|
||||
std::array<T, size> with_vectorAVX2(std::array<T, size>& arr, std::array<T, size>& arr2)
|
||||
{
|
||||
std::array<T, size> result;
|
||||
auto resPos = result.begin();
|
||||
__m256i a, b, c;
|
||||
for (auto it = arr.begin(), it2 = arr2.begin();
|
||||
it < arr.end() && it2 < arr.end();
|
||||
it2 += 4, it += 4) {
|
||||
a = _mm256_stream_load_si256((__m256i*)&(*it));
|
||||
b = _mm256_stream_load_si256((__m256i*)&(*it2));
|
||||
c = _mm256_add_epi64(a, b);
|
||||
_mm256_store_si256((__m256i*)&(*resPos), c);
|
||||
resPos += 4;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void BM_arrayAVX2Vector(benchmark::State& state)
|
||||
{
|
||||
auto arr1 = generateLongArray<int64_t, 1 << 16>();
|
||||
auto arr2 = generateLongArray<int64_t, 1 << 16>();
|
||||
for (auto _ : state)
|
||||
auto arr3 = with_vectorAVX2(arr1, arr2);
|
||||
}
|
||||
|
||||
static void BM_arrayScalar64(benchmark::State& state)
|
||||
{
|
||||
auto arr1 = generateLongArray<int64_t, 1 << 16>();
|
||||
auto arr2 = generateLongArray<int64_t, 1 << 16>();
|
||||
|
||||
for (auto _ : state)
|
||||
auto arr3 = with_scalar(arr1, arr2);
|
||||
}
|
||||
|
||||
BENCHMARK(BM_arrayAVX2Vector);
|
||||
BENCHMARK(BM_arrayScalar64);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
38
src/main.cc
Normal file
38
src/main.cc
Normal file
@ -0,0 +1,38 @@
|
||||
#include <array>
|
||||
#include <emmintrin.h>
|
||||
|
||||
template <typename T = int, size_t size = 1024>
|
||||
void generateLongArray(std::array<T, size>& arr)
|
||||
{
|
||||
for (int& a : arr) {
|
||||
a = rand() % 100;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T = int, size_t size = 1024>
|
||||
std::array<T, size> with_vector(std::array<T, size>& arr, std::array<T, size>& arr2)
|
||||
{
|
||||
std::array<T, size> result;
|
||||
auto resPos = result.begin();
|
||||
for (auto it = arr.begin(), it2 = arr2.begin();
|
||||
it < arr.end(), it2 < arr.end();
|
||||
++it2, ++it) {
|
||||
int32_t array_a[4] = { *it++, *it++, *it++, *it }; // 128 bit
|
||||
int32_t array_b[4] = { *it2++, *it2++, *it2++, *it2 };
|
||||
__m128i a, b, c;
|
||||
a = _mm_loadu_si128((__m128i*)array_a); // loading array_a into register a
|
||||
b = _mm_loadu_si128((__m128i*)array_b);
|
||||
c = _mm_add_epi32(a, b);
|
||||
_mm_storeu_si128((__m128i*)&(*resPos), c);
|
||||
resPos += 4;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::array<int, 1024> a;
|
||||
generateLongArray(a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user