.. _fmv: Use the function multi-version patch generator ############################################## CPU architectures often gain interesting new instructions as they evolve but application developers find it difficult to take advantage of those instructions. The reluctance to lose backward-compatibility is one of the main roadblocks slowing developers from using advancements in newer computing architectures. :abbr:`FMV (Function Multi-Versioning)`, which first appeared in `GCC`_ 4.8, is a way to have multiple implementations of a function, each using a different architecture specialized instruction-set extensions. GCC 6 introduces changes to FMV to make it even easier to bring architecture- based optimizations to the application code. In this tutorial we will use FMV on general code and on :abbr:`FFT (Fast Fourier Transform)` library code. Upon completing the tutorial, you will be able to use this technology on your code and use the libraries to deploy architecture-based optimizations to your application code. Install and configure a Clear Linux host on bare metal ****************************************************** First, follow our guide to :ref:`bare-metal-install`. Once the bare metal installation and initial configuration are complete, add the `desktop-dev` bundle to the system. `desktop-dev`: contains the necessary development tools like GCC and Perl\*. To install the bundles, run the following command in the :file:`$HOME` directory: .. code-block:: bash sudo swupd bundle-add desktop-dev Detect loop vectorization candidates ************************************ Now, we need to detect the loop vectorization candidates to be cloned for multiple platforms with FMV. As an example, we will use the following simple C code: .. code-block:: c :linenos: #include #include #include #define MAX 1000000 int a[256], b[256], c[256]; void foo(){ int i,x; for (x=0; x log To generate the patch files, execute: .. code-block:: bash perl ./make-fmv-patch/make-fmv-patch.pl log . The :file:`make-fmv-patch.pl` script takes two arguments: `` and ``. Replace `` and `` with the proper values and execute: .. code-block:: bash perl make-fmv-patch.pl The command generates the following :file:`example.c.patch` patch: .. code-block:: console --- ./example.c 2017-09-27 16:05:42.279505430 +0000 +++ ./example.c~ 2017-09-27 16:19:11.691544026 +0000 @@ -5,6 +5,7 @@ int a[256], b[256], c[256]; +__attribute__((target_clones("avx2","arch=atom","default"))) void foo(){ int i,x; for (x=0; x #include #include #define MAX 1000000 int a[256], b[256], c[256]; __attribute__((target_clones("avx2","arch=atom","default"))) void foo(){ int i,x; for (x=0; x y) ? x : y; } +__attribute__((target_clones("avx2","arch=atom","default"))) static double aerror(C *a, C *b, int n) { if (n > 0) { @@ -111,6 +112,7 @@ } /* make array hermitian */ +__attribute__((target_clones("avx2","arch=atom","default"))) void mkhermitian(C *A, int rank, const bench_iodim *dim, int stride) { if (rank == 0) @@ -148,6 +150,7 @@ } /* C = A + B */ +__attribute__((target_clones("avx2","arch=atom","default"))) void aadd(C *c, C *a, C *b, int n) { int i; @@ -159,6 +162,7 @@ } /* C = A - B */ +__attribute__((target_clones("avx2","arch=atom","default"))) void asub(C *c, C *a, C *b, int n) { int i; @@ -170,6 +174,7 @@ } /* B = rotate left A (complex) */ +__attribute__((target_clones("avx2","arch=atom","default"))) void arol(C *b, C *a, int n, int nb, int na) { int i, ib, ia; @@ -192,6 +197,7 @@ } } With these patches, we can select where to apply the FMV technology making bringing architecture-based optimizations to application code even easier. **Congratulations!** You have successfully installed an FMV development environment on Clear Linux. Furthermore, you used cutting edge compiler technology to improve the performance of your application based on Intel Architecture technology and profiling of the specific execution of your application. .. _GCC: https://gcc.gnu.org .. _make-fmv-patch: https://github.com/clearlinux/make-fmv-patch