commit cfadc8f0d61920dffc31b8d39685b498707f5f4e Author: Ano-sys Date: Tue Sep 1 22:52:15 2026 +0200 bare impressions on avx made diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f366700 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 4.4.3) +project(simd_avx_example) + +add_compile_options(-Wall -Werror -std=c++23 -march=native -O3) + +FILE(GLOB sourcefiles src/*.c*) +add_executable(simd_avx_example ${sourcefiles}) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..4ae943f --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Performance Test + +Example Project to test the performance increase of avx multiplication in contrast to standard multiplication by multiplying 16 32bit integer a fixed number of times. + +## Programstructure + +The program creates two arrays with each containing 16 integers which are dispatched to a thread in a timer environment to track the execution time. The results are then printed to stdout. + +## Benchmark by 2147483647 iterations + +| | ./program | nice -20 program | chrt -f 99 program | +| :---: | :---: | :---: | :---: | +| AVX | 9.46229s | 6.651s | 11.7455s | +| Std | 16.7001s | 13.6682s | 16.828s | diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..3ea2510 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define _ITERATIONS std::numeric_limits::max() + +typedef __m512i vec16a32; + +std::mutex cout_mutex; + +void avx_mult32(uint32_t* a1, uint32_t* a2, __m512i* out){ + vec16a32 v1 = _mm512_loadu_si512(a1); + vec16a32 v2 = _mm512_loadu_si512(a2); + *out = _mm512_mullo_epi32(v1, v2); +} + +void avx_mult_example(uint32_t* values1, uint32_t* values2, vec16a32* out){ + asm volatile( + "" + : + : "m"(values1), "m"(values2) + : "memory" + ); + + avx_mult32(values1, values2, out); + + asm volatile( + "" + : + : "v"(out) + : "memory" + ); +} + +void standard_mult_example(uint32_t* values1, uint32_t* values2, uint32_t* out){ + asm volatile( + "" + : + : "m"(values1), "m"(values2) + : "memory" + ); + + for(int i = 0; i < 16; i++) out[i] = values1[i] * values2[i]; + + asm volatile( + "" + : + : "m"(out) + : "memory" + ); +} + +class Timer{ + private: + std::chrono::time_point start; + std::chrono::time_point end; + std::string name; + + public: + Timer(std::string name, auto&& func) : name(name){ + start = std::chrono::high_resolution_clock::now(); + func(); + end = std::chrono::high_resolution_clock::now(); + } + + Timer(std::string name, auto&& func, int iterations) : name(name){ + start = std::chrono::high_resolution_clock::now(); + for(int i = 0; i < iterations; i++) func(); + end = std::chrono::high_resolution_clock::now(); + } + + long long get_duration() const { + return std::chrono::duration_cast(end - start).count(); + } + + void print_duration() const { + std::scoped_lock lock(cout_mutex); + auto duration = get_duration(); + std::cout << name << " took " << duration << "μs, "; + std::cout << duration / 1000.0 << "ms, "; + std::cout << duration / 1000000.0 << "s." << std::endl; + } +}; + +std::thread dispatch_timer(std::string name, auto&& func, int iterations){ + return std::thread( + [name = std::move(name), func = std::forward(func), iterations]() mutable { + Timer timer(name, func, iterations); + timer.print_duration(); + }); +} + +void fill_pseudorandom(uint32_t* arr, size_t size){ + for(size_t i = 0; i < size; i++) arr[i] = std::rand() % 100; +} + +int main(){ + std::srand(42); + auto array_size = 16; + + uint32_t values1[array_size]; + uint32_t values2[array_size]; + + fill_pseudorandom(values1, array_size); + fill_pseudorandom(values2, array_size); + + std::cout << "For " << _ITERATIONS << " iterations:" << std::endl; + + vec16a32 avx_result; + uint32_t standard_result[16]; + + std::thread standard_thread = dispatch_timer("Standard multiplication", [&](){ standard_mult_example(values1, values2, standard_result); }, _ITERATIONS); + std::thread avx_thread = dispatch_timer("AVX multiplication", [&](){ avx_mult_example(values1, values2, &avx_result); }, _ITERATIONS); + + avx_thread.join(); + standard_thread.join(); + + (void)avx_result; + (void)standard_result; +} \ No newline at end of file