https://github.com/abetlen/simdinfo

Small C library for SIMD feature detection at runtime

https://github.com/abetlen/simdinfo

Science Score: 13.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
  • DOI references
  • Academic publication links
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (7.9%) to scientific vocabulary
Last synced: 10 months ago · JSON representation

Repository

Small C library for SIMD feature detection at runtime

Basic Info
  • Host: GitHub
  • Owner: abetlen
  • License: mit
  • Language: C
  • Default Branch: main
  • Homepage:
  • Size: 23.4 KB
Statistics
  • Stars: 4
  • Watchers: 1
  • Forks: 0
  • Open Issues: 1
  • Releases: 0
Created about 2 years ago · Last pushed about 2 years ago
Metadata Files
Readme License

README.md

simdinfo

simdinfo is a simple, header-only library for detecting SIMD support at runtime.

If you have a function that already checks for SIMD support at compile time via preprocessor directives

```c float sum(float *a, size_t size) {

if defined(AVX)

return sum_avx(a, size);

else

return sum_scalar(a, size);

endif

} ```

You can use simdinfo to replace the compile-time check with a runtime check using the same directive names

```c

include "simdinfo.h"

float sum(float *a, sizet size) { simdinfot info = simdinfo(); if (SIMDINFOSUPPORTS(info, _AVX_)) { return sumavx(a, size); } else { return sum_scalar(a, size); } } ```

Basic Example (Sum of Floats)

Let's start with a little example of a c function that sums up an array of floats.

c float sum_serial(float *data, size_t n) { float sum = 0; for (size_t i = 0; i < n; i++) { sum += data[i]; } return sum; }

This function iterates over a data array one element at a time and adds it to a running sum.

If we want to make this function faster one thing we can do is make use of specialised SIMD instructions to add up multiple elements at the same time.

The following uses x86_64 AVX simd intrinsics to load 8 floats a time into a vector and add them to a sum vector holding 8 partial sums.

```c

if defined(AVX)

include

float sumavx(float *data, sizet n) { _m256 sum = _mm256setzerops(); for (sizet i = 0; i < n; i += 8) { _m256 v = _mm256loadups(data + i); sum = _mm256addps(sum, v); } float result[8]; _mm256storeups(result, sum); float x = result[0] + result[1] + result[2] + result[3] + result[4] + result[5] + result[6] + result[7]; // handle remaining elements since n is not always divisible by 8 for (sizet i = n - n % 8; i < n; i++) { x += data[i]; } return x; }

endif

```

The above code will be compiled only if the compiler supports AVX instructions. Usually this is done by setting -march=native if you're compiling the code for the machine you're running it on.

What do you do if don't know if the machine you're running the code on supports AVX instructions? You can manually tell the compiler to include the AVX code path by setting -mavx flag and use SIMDINFO_SUPPORTS to check if the machine supports AVX instructions at runtime.

Below is a full example

```c // sum.c

include

include

include "simdinfo.h"

float sumserial(float *data, sizet n) { float sum = 0; for (size_t i = 0; i < n; i++) { sum += data[i]; } return sum; }

if defined(AVX)

include

float sumavx(float *data, sizet n) { _m256 sum = _mm256setzerops(); for (sizet i = 0; i < n; i += 8) { _m256 v = _mm256loadups(data + i); sum = _mm256addps(sum, v); } float result[8]; _mm256storeups(result, sum); float x = result[0] + result[1] + result[2] + result[3] + result[4] + result[5] + result[6] + result[7]; for (sizet i = n - n % 8; i < n; i++) { x += data[i]; } return x; }

endif

float sum(float *data, sizet n) { simdinfot info = simdinfo();

if defined(AVX)

if (SIMDINFO_SUPPORTS(info, __AVX__)) {
    return sum_avx(data, n);
}

endif

return sum_serial(data, n);

}

int main() { sizet n = 1000000; float *data = malloc(n * sizeof(float)); for (sizet i = 0; i < n; i++) { data[i] = 1.0; } float s = sum(data, n); printf("sum = %f\n", s); free(data); return 0; } ```

Then we can compile the code for a generic x86_64 machine with -mavx flags.

bash wget https://raw.githubusercontent.com/abetlen/simdinfo/main/simdinfo.h gcc \ -march=x86_64 \ -mavx \ -O2 \ -mtune=generic \ -o sum \ sum.c \ -I. ./sum

If you only want to enable dynamic dispatch on some builds you can implement a pattern like the following

```c float sum(float *data, size_t n) {

if defined(DYNAMIC_DISPATCH)

simdinfo_t info = simdinfo();

else

undef SIMDINFO_SUPPORTS

define SIMDINFO_SUPPORTS(info, feature) 1

endif

if defined(AVX)

if (SIMDINFO_SUPPORTS(info, __AVX__)) {
    return sum_avx(data, n);
}

endif

return sum_serial(data, n);

} ```

In the above code, if DYNAMIC_DISPATCH is defined, the code will use simdinfo to check if the machine supports AVX instructions. If DYNAMIC_DISPATCH is not defined, the code will always use the AVX code path if the compiler supports AVX instructions.

Related Projects

  • https://github.com/ashvardanian/SimSIMD
  • https://github.com/Mozilla-Ocho/llamafile
  • https://github.com/google/cpu_features
  • https://github.com/google/highway

Owner

  • Name: Andrei
  • Login: abetlen
  • Kind: user
  • Location: San Francisco, California

GitHub Events

Total
  • Issues event: 1
  • Watch event: 3
Last Year
  • Issues event: 1
  • Watch event: 3

Issues and Pull Requests

Last synced: 10 months ago

All Time
  • Total issues: 1
  • Total pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Total issue authors: 1
  • Total pull request authors: 0
  • Average comments per issue: 0.0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 1
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 1
  • Pull request authors: 0
  • Average comments per issue: 0.0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • byroot (1)
Pull Request Authors
Top Labels
Issue Labels
Pull Request Labels