diff --git a/fundamentals/simd/.gitignore b/fundamentals/simd/.gitignore new file mode 100644 index 00000000..ba077a40 --- /dev/null +++ b/fundamentals/simd/.gitignore @@ -0,0 +1 @@ +bin diff --git a/fundamentals/simd/Makefile b/fundamentals/simd/Makefile new file mode 100644 index 00000000..52bb01b0 --- /dev/null +++ b/fundamentals/simd/Makefile @@ -0,0 +1,17 @@ +CXX = g++ +CXXFLAGS = -g -Wall -mavx2 -Wno-unused-variable + +SRCDIR = src +BINDIR = bin + +SOURCES := $(wildcard $(SRCDIR)/*.cpp) +TARGETS := $(patsubst $(SRCDIR)/%.cpp, %, $(SOURCES)) + +all: $(TARGETS) + +$(TARGETS): % : $(SRCDIR)/%.cpp | bindir + $(CXX) $(CXXFLAGS) -o ${BINDIR}/$@ $< + +bindir: bin +bin: + @mkdir -p $(BINDIR) diff --git a/fundamentals/simd/README.md b/fundamentals/simd/README.md new file mode 100644 index 00000000..76755f95 --- /dev/null +++ b/fundamentals/simd/README.md @@ -0,0 +1,54 @@ +## Single Instruction, Multiple Data (SIMD) + +### Introduction +TODO: + +### Machine specific options/support +If you just try to compile a program using SIMD instructions, you may get the +following error message: +```console +$ make add +gcc -g -Wall -Wno-unused-variable -o bin/add src/add.cpp +src/add.cpp: In function ‘int main()’: +src/add.cpp:11:52: warning: AVX vector return without AVX enabled changes the ABI [-Wpsabi] + 11 | __m256i a = _mm256_loadu_si256((__m256i*)array1); + | ^ +In file included from /usr/lib/gcc/x86_64-linux-gnu/11/include/immintrin.h:43, + from src/add.cpp:1: +/usr/lib/gcc/x86_64-linux-gnu/11/include/avxintrin.h:933:1: error: inlining failed in call to ‘always_inline’ ‘void _mm256_storeu_si256(__m256i_u*, __m256i)’: target specific option mismatch + 933 | _mm256_storeu_si256 (__m256i_u *__P, __m256i __A) + | ^~~~~~~~~~~~~~~~~~~ +src/add.cpp:18:24: note: called from here + 18 | _mm256_storeu_si256((__m256i*)result, c); + | ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ +In file included from /usr/lib/gcc/x86_64-linux-gnu/11/include/immintrin.h:47, + from src/add.cpp:1: +/usr/lib/gcc/x86_64-linux-gnu/11/include/avx2intrin.h:119:1: error: inlining failed in call to ‘always_inline’ ‘__m256i _mm256_add_epi32(__m256i, __m256i)’: target specific option mismatch + 119 | _mm256_add_epi32 (__m256i __A, __m256i __B) + | ^~~~~~~~~~~~~~~~ +src/add.cpp:15:33: note: called from here + 15 | __m256i c = _mm256_add_epi32(a, b); // _epi32 denotes 32-bit integer vectors + | ~~~~~~~~~~~~~~~~^~~~~~ +In file included from /usr/lib/gcc/x86_64-linux-gnu/11/include/immintrin.h:43, + from src/add.cpp:1: +/usr/lib/gcc/x86_64-linux-gnu/11/include/avxintrin.h:927:1: error: inlining failed in call to ‘always_inline’ ‘__m256i _mm256_loadu_si256(const __m256i_u*)’: target specific option mismatch + 927 | _mm256_loadu_si256 (__m256i_u const *__P) + | ^~~~~~~~~~~~~~~~~~ +src/add.cpp:12:35: note: called from here + 12 | __m256i b = _mm256_loadu_si256((__m256i*)array2); + | ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ +In file included from /usr/lib/gcc/x86_64-linux-gnu/11/include/immintrin.h:43, + from src/add.cpp:1: +/usr/lib/gcc/x86_64-linux-gnu/11/include/avxintrin.h:927:1: error: inlining failed in call to ‘always_inline’ ‘__m256i _mm256_loadu_si256(const __m256i_u*)’: target specific option mismatch + 927 | _mm256_loadu_si256 (__m256i_u const *__P) + | ^~~~~~~~~~~~~~~~~~ +src/add.cpp:11:35: note: called from here + 11 | __m256i a = _mm256_loadu_si256((__m256i*)array1); + | ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ +make: *** [Makefile:13: add] Error 1 +``` +In this case we nee to add the 'm'achine specific option `avx2` flag to the +compilation command: +```console +$ g++ -g -Wall -mavx2 -Wno-unused-variable -o bin/add src/add.cpp +``` diff --git a/fundamentals/simd/src/add.cpp b/fundamentals/simd/src/add.cpp new file mode 100644 index 00000000..8a93e345 --- /dev/null +++ b/fundamentals/simd/src/add.cpp @@ -0,0 +1,22 @@ +#include +#include + +int main() { + int array1[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + int array2[8] = {8, 7, 6, 5, 4, 3, 2, 1}; + int result[8] = {0}; + + __m256i a = _mm256_loadu_si256((__m256i*)array1); + __m256i b = _mm256_loadu_si256((__m256i*)array2); + + __m256i c = _mm256_add_epi32(a, b); // _epi32 denotes 32-bit integer vectors + + _mm256_storeu_si256((__m256i*)result, c); + + for (int i = 0; i < 8; i++) { + std::cout << "result[" << i << "] = " << result[i] << std::endl; + } + + return 0; +} +