diff --git a/CMakeLists.txt b/CMakeLists.txt index c36db10..b996842 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ set_property(GLOBAL PROPERTY PYTHON_EXTENSIONS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE # --- Detect SIMD -------------------------------------------------------------- include("src/scripts/cmake/FindAVX2.cmake") +include("src/scripts/cmake/FindAVX512.cmake") include("src/scripts/cmake/FindNEON.cmake") include("src/scripts/cmake/FindSSE2.cmake") include("src/scripts/cmake/CythonExtension.cmake") diff --git a/src/pyrodigal/impl/CMakeLists.txt b/src/pyrodigal/impl/CMakeLists.txt index 24afaf9..cae16b1 100644 --- a/src/pyrodigal/impl/CMakeLists.txt +++ b/src/pyrodigal/impl/CMakeLists.txt @@ -1,54 +1,33 @@ -# if(HAVE_SSE2) -# add_library(implsse sse.c sse.h template.h) -# target_include_directories(implsse PUBLIC $) -# if(SSE2_C_FLAGS AND NOT SSE2_C_FLAGS STREQUAL " ") -# target_link_options(implsse PUBLIC ${SSE2_C_FLAGS}) -# target_compile_options(implsse PUBLIC ${SSE2_C_FLAGS}) -# endif() -# endif() - -# if(HAVE_AVX2) -# add_library(implavx avx.c avx.h template.h) -# target_include_directories(implavx PUBLIC $) -# if(AVX2_C_FLAGS AND NOT AVX2_C_FLAGS STREQUAL " ") -# target_link_options(implavx PUBLIC ${AVX2_C_FLAGS}) -# target_compile_options(implavx PUBLIC ${AVX2_C_FLAGS}) -# endif() -# endif() - -# if(HAVE_NEON) -# add_library(implneon neon.c neon.h template.h) -# target_include_directories(implneon PUBLIC $) -# if(NEON_C_FLAGS AND NOT NEON_C_FLAGS STREQUAL " ") -# target_link_options(implneon PUBLIC ${NEON_C_FLAGS}) -# target_compile_options(implneon PUBLIC ${NEON_C_FLAGS}) -# endif() -# endif() - -# add_library(impl generic.c generic.h template.h) -# target_include_directories(impl PUBLIC $ ${PROJECT_SOURCE_DIR}/src/pyrodigal/prodigal) - - - cython_extension(generic LINKS prodigal EXTRA_SOURCES generic.c generic.h template.h) + if(HAVE_SSE2) cython_extension(sse2 LINKS prodigal EXTRA_SOURCES sse2.c sse2.h template.h) - string(STRIP "${SSE2_C_FLAGS}" IMPL_FLAGS) - if(IMPL_FLAGS) - target_compile_options(pyrodigal.impl.sse2 PUBLIC ${IMPL_FLAGS}) - endif() + string(REPLACE " " ";" IMPL_FLAGS ${SSE2_C_FLAGS}) + foreach(_flag IN LISTS IMPL_FLAGS) + target_compile_options(pyrodigal.impl.sse2 PUBLIC ${_flag}) + endforeach() endif() + if(HAVE_AVX2) cython_extension(avx2 LINKS prodigal EXTRA_SOURCES avx2.c avx2.h template.h) - string(STRIP "${AVX2_C_FLAGS}" IMPL_FLAGS) - if(IMPL_FLAGS) - target_compile_options(pyrodigal.impl.avx2 PUBLIC ${IMPL_FLAGS}) - endif() + string(REPLACE " " ";" IMPL_FLAGS ${AVX2_C_FLAGS}) + foreach(_flag IN LISTS IMPL_FLAGS) + target_compile_options(pyrodigal.impl.avx2 PUBLIC ${_flag}) + endforeach() endif() + +if(HAVE_AVX512) + cython_extension(avx512 LINKS prodigal EXTRA_SOURCES avx512.c avx512.h template.h) + string(REPLACE " " ";" IMPL_FLAGS ${AVX512_C_FLAGS}) + foreach(_flag IN LISTS IMPL_FLAGS) + target_compile_options(pyrodigal.impl.avx512 PUBLIC ${_flag}) + endforeach() +endif() + if(HAVE_NEON) cython_extension(neon LINKS prodigal EXTRA_SOURCES neon.c neon.h template.h) - string(STRIP "${NEON_C_FLAGS}" IMPL_FLAGS) - if(IMPL_FLAGS) - target_compile_options(pyrodigal.impl.neon PUBLIC ${IMPL_FLAGS}) - endif() + string(REPLACE " " ";" IMPL_FLAGS ${NEON_C_FLAGS}) + foreach(_flag IN LISTS IMPL_FLAGS) + target_compile_options(pyrodigal.impl.neon PUBLIC ${_flag}) + endforeach() endif() \ No newline at end of file diff --git a/src/pyrodigal/impl/avx512.c b/src/pyrodigal/impl/avx512.c deleted file mode 100644 index bbec291..0000000 --- a/src/pyrodigal/impl/avx512.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "sequence.h" -#include "avx512.h" -#include "generic.h" - -#ifdef __AVX512F__ - -#include - -#include "template.h" - -#define simd_t __m512i -#define simd_load(m) _mm512_load_si512((__m512i*) (m)) -#define simd_store(x, m) _mm512_store_si512((__m512i*) (m), x) -#define simd_set1(x) _mm512_set1_epi8(x) -#define simd_eq(x, y) _mm512_cmpeq_epi8_mask(x, y) - -#define mask_t __mmask64 -#define mask_eq(x, y) _kxnor_mask64(x, y) -#define mask_or(x, y) _kor_mask64(x, y) -#define mask_and(x, y) _kand_mask64(x, y) -#define mask_andnot(x, y) _kandn_mask64(y, x) -#define mask_convert(x) _mm512_movm_epi8(x) - -#define SIMD_LANES 64 -#define SIMD_MASK 0x3F - -void skippable_avx512( - const int8_t* restrict strands, - const uint8_t* restrict types, - const uint8_t* restrict frames, - const int min, - const int i, - uint8_t* restrict skip -) { - skippable_simd(strands, types, frames, min, i, skip); -} - -#endif diff --git a/src/pyrodigal/impl/avx512.h b/src/pyrodigal/impl/avx512.h index b33ebef..d6d278f 100644 --- a/src/pyrodigal/impl/avx512.h +++ b/src/pyrodigal/impl/avx512.h @@ -1,14 +1,39 @@ -#ifndef _PYRODIGAL_IMPL_AVX512_H -#define _PYRODIGAL_IMPL_AVX512_H +#include "sequence.h" +#include "generic.h" -#ifdef WIN32 -#define export __declspec( dllexport ) -#else -#define export extern -#endif +#ifdef __AVX512F__ +#ifdef __AVX512BW__ + +#include + +#include "template.h" -#include +#define simd_t __m512i +#define simd_load(m) _mm512_load_si512((__m512i*) (m)) +#define simd_store(x, m) _mm512_store_si512((__m512i*) (m), x) +#define simd_set1(x) _mm512_set1_epi8(x) +#define simd_eq(x, y) _mm512_cmpeq_epi8_mask(x, y) -export void skippable_avx512(const int8_t*, const uint8_t*, const uint8_t*, const int, const int, uint8_t*); +#define mask_t __mmask64 +#define mask_eq(x, y) _kxnor_mask64(x, y) +#define mask_or(x, y) _kor_mask64(x, y) +#define mask_and(x, y) _kand_mask64(x, y) +#define mask_andnot(x, y) _kandn_mask64(y, x) +#define mask_convert(x) _mm512_movm_epi8(x) +#define SIMD_LANES 64 +#define SIMD_MASK 0x3F + +void skippable_avx512( + const int8_t* restrict strands, + const uint8_t* restrict types, + const uint8_t* restrict frames, + const int min, + const int i, + uint8_t* restrict skip +) { + skippable_simd(strands, types, frames, min, i, skip); +} + +#endif #endif diff --git a/src/pyrodigal/impl/avx512.pxd b/src/pyrodigal/impl/avx512.pxd index 7f8636d..b4f4772 100644 --- a/src/pyrodigal/impl/avx512.pxd +++ b/src/pyrodigal/impl/avx512.pxd @@ -1,4 +1,7 @@ -from libc.stdint cimport int8_t, uint8_t +# coding: utf-8 +# cython: language_level=3, linetrace=True, binding=True -cdef extern from "impl/avx512.h" nogil: - void skippable_avx512(const int8_t*, const uint8_t*, const uint8_t*, const int, const int, uint8_t*) noexcept +from ..lib cimport BaseConnectionScorer + +cdef class AVX512ConnectionScorer(BaseConnectionScorer): + pass \ No newline at end of file diff --git a/src/pyrodigal/impl/avx512.pyx b/src/pyrodigal/impl/avx512.pyx new file mode 100644 index 0000000..b5be4e0 --- /dev/null +++ b/src/pyrodigal/impl/avx512.pyx @@ -0,0 +1,14 @@ +# coding: utf-8 +# cython: language_level=3, linetrace=True, binding=True + +from libc.stdint cimport int8_t, uint8_t + +from ..lib cimport BaseConnectionScorer + +cdef extern from "avx512.h" nogil: + void skippable_avx512(const int8_t*, const uint8_t*, const uint8_t*, const int, const int, uint8_t*) noexcept + +cdef class AVX512ConnectionScorer(BaseConnectionScorer): + def __cinit__(self): + self.skippable = skippable_avx512 + self.enabled = True diff --git a/src/scripts/cmake/CythonExtension.cmake b/src/scripts/cmake/CythonExtension.cmake index 0718de7..c3ffe3c 100644 --- a/src/scripts/cmake/CythonExtension.cmake +++ b/src/scripts/cmake/CythonExtension.cmake @@ -26,7 +26,7 @@ set(CYTHON_DIRECTIVES -E AVX2_BUILD_SUPPORT=$,True,False> -E NEON_BUILD_SUPPORT=$,True,False> -E MMX_BUILD_SUPPORT=False - -E AVX512_BUILD_SUPPORT=False + -E AVX512_BUILD_SUPPORT=$,True,False> -E SYS_IMPLEMENTATION_NAME=$ -E SYS_VERSION_INFO_MAJOR=${Python_VERSION_MAJOR} -E SYS_VERSION_INFO_MINOR=${Python_VERSION_MINOR} diff --git a/src/scripts/cmake/FindAVX512.cmake b/src/scripts/cmake/FindAVX512.cmake new file mode 100644 index 0000000..eeb6d18 --- /dev/null +++ b/src/scripts/cmake/FindAVX512.cmake @@ -0,0 +1,102 @@ +#.rst: +# FindAVX512 +# ---------- +# +# Finds AVX512 support +# +# This module can be used to detect AVX512 support in a C compiler. If +# the compiler supports AVX512, the flags required to compile with +# AVX512 support are returned in variables for the different languages. +# The variables may be empty if the compiler does not need a special +# flag to support AVX512. +# +# The following variables are set: +# +# :: +# +# AVX512_C_FLAGS - flags to add to the C compiler for AVX512 support +# AVX512_FOUND - true if AVX512 is detected +# +#============================================================================= + +set(_AVX512_REQUIRED_VARS) +set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) +set(CMAKE_REQUIRED_QUIET ${AVX512_FIND_QUIETLY}) + +# sample AVX512 source code to test +set(AVX512_C_TEST_SOURCE +" +#include +void parasail_memset___m256i(__m256i *b, __m256i c, size_t len) +{ + size_t i; + for (i=0; i