[R-pkg-devel] using portable simd instructions

Vincent Dorie vdor|e @end|ng |rom gm@||@com
Tue Mar 26 16:04:20 CET 2024


Hi Jesse,

What I've done is to use a mix of compile-time detection of compiler SIMD
support and run-time detection of SIMD hardware support. At package load,
SIMD-specific versions of functions are installed in a symbol table. It's
not perfect and it can be hard to support evolving platforms, especially
now that ARM is more prevalent. However, it does allow for distribution on
CRAN as it uses only autoconf, POSIX make, and no specific compiler.

At compile time:
1. Use a configure script to detect the platform and any SIMD instructions
supported by the compiler. This is also the time to identify the compiler
flags necessary to enable instruction sets. Unlike what the existing
autoconf macros do, you can ignore whether or not the host system supports
the instruction sets (with the exception when compiling with Solaris Studio
- it won't let you load a binary with instructions not supported by the
host, even if they cannot be executed).
2. Use makefiles to conditionally compile different versions of the
functions you want, one for each level of instruction set supported by the
compiler, using the flags detected above. They all should be in different
files with different symbols. For example: partition_sse2.c defines
partition_sse2(), partition_avx.c defines partition_avx(), etc., while
partition.c defines partition_c() - a fall-back compiled without any SIMD
instructions. Note that echoing compilations with SIMD flags will trigger a
check warning, as those units are not inherently portable. That is
addressed below.

At run time:
1. On package load, detect what instruction sets are supported by the host.
On x86 machines, this usually involves a call to cpuid.
2. For the maximum level of instruction set supported by the host, install
the relevant symbol for each function into a symbol table. Using the
example above, a header defines an external function pointer partition(),
which gets set to one of the SIMD-specific implementations.

In setting that up, I found Agner Fog's notes on CPU dispatching to be
extremely helpful. They can be found here: https://www.agner.org/optimize.
I use this strategy in the dbarts package, the code for which is here:
https://github.com/vdorie/dbarts.

Best,
Vince

On Tue, Mar 26, 2024 at 10:45 AM Dirk Eddelbuettel <edd using debian.org> wrote:

>
> On 26 March 2024 at 10:53, jesse koops wrote:
> | How can I make this portable and CRAN-acceptable?
>
> But writing (or borrowing ?) some hardware detection via either configure /
> autoconf or cmake. This is no different than other tasks decided at
> install-time.
>
> Start with 'Writing R Extensions', as always, and work your way up from
> there. And if memory serves there are already a few other packages with
> SIMD
> at CRAN so you can also try to take advantage of the search for a 'token'
> (here: 'SIMD') at the (unofficial) CRAN mirror at GitHub:
>
>    https://github.com/search?q=org%3Acran%20SIMD&type=code
>
> Hth, Dirk
>
> --
> dirk.eddelbuettel.com | @eddelbuettel | edd using debian.org
>
> ______________________________________________
> R-package-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>

	[[alternative HTML version deleted]]



More information about the R-package-devel mailing list