diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e8b319a2..e09e14fff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,7 @@ else() include(CheckCXXCompilerFlag) if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) check_cxx_compiler_flag("/arch:AVX" NCNN_COMPILER_SUPPORT_X86_AVX) + check_cxx_compiler_flag("/arch:AVX" NCNN_COMPILER_SUPPORT_X86_FMA) check_cxx_compiler_flag("/arch:AVX" NCNN_COMPILER_SUPPORT_X86_XOP) check_cxx_compiler_flag("/arch:AVX2" NCNN_COMPILER_SUPPORT_X86_AVX2) check_cxx_compiler_flag("/arch:AVX2" NCNN_COMPILER_SUPPORT_X86_AVX_VNNI) @@ -232,6 +233,7 @@ else() endif() else() check_cxx_compiler_flag("-mavx" NCNN_COMPILER_SUPPORT_X86_AVX) + check_cxx_compiler_flag("-mfma" NCNN_COMPILER_SUPPORT_X86_FMA) check_cxx_compiler_flag("-mxop" NCNN_COMPILER_SUPPORT_X86_XOP) check_cxx_compiler_flag("-mfma -mf16c -mavx2" NCNN_COMPILER_SUPPORT_X86_AVX2) check_cxx_compiler_flag("-mfma -mf16c -mavx512f -mavx512vl" NCNN_COMPILER_SUPPORT_X86_AVX512) @@ -247,6 +249,13 @@ else() if(NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NCNN_COMPILER_SUPPORT_X86_AVX) option(NCNN_AVX "optimize x86 platform with avx extension" ON) + if(NCNN_COMPILER_SUPPORT_X86_FMA) + if(NCNN_AVX) + option(NCNN_FMA "optimize x86 platform with fma extension" ON) + endif() + else() + message(WARNING "The compiler does not support fma extension. NCNN_FMA will be OFF.") + endif() if(NCNN_COMPILER_SUPPORT_X86_XOP) if(NCNN_AVX) option(NCNN_XOP "optimize x86 platform with xop extension" ON) diff --git a/cmake/ncnn_add_layer.cmake b/cmake/ncnn_add_layer.cmake index f08ec8844..0c1903c3a 100644 --- a/cmake/ncnn_add_layer.cmake +++ b/cmake/ncnn_add_layer.cmake @@ -159,82 +159,69 @@ macro(ncnn_add_layer class) set(layer_registry "${layer_registry}#if NCNN_STRING\n{\"${class}\", 0},\n#else\n{0},\n#endif\n") endif() - if(NCNN_RUNTIME_CPU AND NCNN_AVX512 AND NCNN_TARGET_ARCH STREQUAL "x86") + if(NCNN_RUNTIME_CPU AND NCNN_TARGET_ARCH STREQUAL "x86") if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) - ncnn_add_arch_opt_layer(${class} avx512 "/arch:AVX512") - else() - ncnn_add_arch_opt_layer(${class} avx512 "-mfma -mf16c -mavx512f -mavx512vl") - endif() - endif() - - if(NCNN_RUNTIME_CPU AND NCNN_AVX512VNNI AND NCNN_TARGET_ARCH STREQUAL "x86") - if(NCNN_COMPILER_SUPPORT_X86_AVX512_VNNI) - if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) - ncnn_add_arch_opt_source(${class} avx512vnni "/arch:AVX512 /D__AVX512VNNI__") - else() - ncnn_add_arch_opt_source(${class} avx512vnni "-mfma -mf16c -mavx512f -mavx512vl -mavx512vnni") + if(NCNN_AVX512) + ncnn_add_arch_opt_layer(${class} avx512 "/arch:AVX512 /D__FMA__") endif() - endif() - endif() - - if(NCNN_RUNTIME_CPU AND NCNN_AVX2 AND NCNN_TARGET_ARCH STREQUAL "x86") - if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) - ncnn_add_arch_opt_layer(${class} avx2 "/arch:AVX2") - else() - ncnn_add_arch_opt_layer(${class} avx2 "-mfma -mf16c -mavx2") - endif() - endif() - - if(NCNN_RUNTIME_CPU AND NCNN_AVXVNNI AND NCNN_TARGET_ARCH STREQUAL "x86") - if(NCNN_COMPILER_SUPPORT_X86_AVX_VNNI) - if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) - ncnn_add_arch_opt_source(${class} avxvnni "/arch:AVX2 /D__AVXVNNI__") - else() - ncnn_add_arch_opt_source(${class} avxvnni "-mfma -mf16c -mavx2 -mavxvnni") + if(NCNN_FMA) + ncnn_add_arch_opt_layer(${class} fma "/arch:AVX /D__FMA__") endif() - endif() - endif() - - if(NCNN_RUNTIME_CPU AND NCNN_AVX AND NCNN_TARGET_ARCH STREQUAL "x86") - if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) - ncnn_add_arch_opt_layer(${class} avx "/arch:AVX") - else() - ncnn_add_arch_opt_layer(${class} avx "-mavx") - endif() - endif() - - if(NCNN_RUNTIME_CPU AND NCNN_XOP AND NCNN_TARGET_ARCH STREQUAL "x86") - if(NCNN_COMPILER_SUPPORT_X86_XOP) - if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) + if(NCNN_AVX) + ncnn_add_arch_opt_layer(${class} avx "/arch:AVX") + endif() + if(NCNN_AVX512VNNI) + ncnn_add_arch_opt_source(${class} avx512vnni "/arch:AVX512 /D__FMA__ /D__AVX512VNNI__") + endif() + if(NCNN_AVXVNNI) + ncnn_add_arch_opt_source(${class} avxvnni "/arch:AVX2 /D__FMA__ /D__AVXVNNI__") + endif() + if(NCNN_AVX2) + ncnn_add_arch_opt_source(${class} avx2 "/arch:AVX2 /D__FMA__") + endif() + if(NCNN_XOP) ncnn_add_arch_opt_source(${class} xop "/arch:AVX /D__XOP__") - else() + endif() + else() + if(NCNN_AVX512) + ncnn_add_arch_opt_layer(${class} avx512 "-mavx512f -mavx512vl -mfma -mf16c") + endif() + if(NCNN_FMA) + ncnn_add_arch_opt_layer(${class} fma "-mavx -mfma") + endif() + if(NCNN_AVX) + ncnn_add_arch_opt_layer(${class} avx "-mavx") + endif() + if(NCNN_AVX512VNNI) + ncnn_add_arch_opt_source(${class} avx512vnni "-mavx512f -mavx512vl -mfma -mf16c -mavx512vnni") + endif() + if(NCNN_AVXVNNI) + ncnn_add_arch_opt_source(${class} avxvnni "-mavx2 -mfma -mf16c -mavxvnni") + endif() + if(NCNN_AVX2) + ncnn_add_arch_opt_source(${class} avx2 "-mavx2 -mfma -mf16c") + endif() + if(NCNN_XOP) ncnn_add_arch_opt_source(${class} xop "-mavx -mxop") endif() endif() endif() - if(NCNN_RUNTIME_CPU AND NCNN_ARM82 AND ((IOS AND CMAKE_OSX_ARCHITECTURES MATCHES "arm64") OR (APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "arm64") OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)"))) - if(NCNN_COMPILER_SUPPORT_ARM82_FP16) + if(NCNN_RUNTIME_CPU AND ((IOS AND CMAKE_OSX_ARCHITECTURES MATCHES "arm64") OR (APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "arm64") OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)"))) + if(NCNN_ARM82) ncnn_add_arch_opt_layer(${class} arm82 "-march=armv8.2-a+fp16") endif() - endif() - - if(NCNN_RUNTIME_CPU AND NCNN_ARM82DOT AND ((IOS AND CMAKE_OSX_ARCHITECTURES MATCHES "arm64") OR (APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "arm64") OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)"))) - if(NCNN_COMPILER_SUPPORT_ARM82_FP16_DOTPROD) + if(NCNN_ARM82DOT) ncnn_add_arch_opt_source(${class} arm82dot "-march=armv8.2-a+fp16+dotprod") endif() endif() if(NCNN_RUNTIME_CPU AND NCNN_MSA AND NCNN_TARGET_ARCH STREQUAL "mips") - if(NCNN_COMPILER_SUPPORT_MIPS_MSA) - ncnn_add_arch_opt_layer(${class} msa "-mmsa") - endif() + ncnn_add_arch_opt_layer(${class} msa "-mmsa") endif() if(NCNN_RUNTIME_CPU AND NCNN_MMI AND NCNN_TARGET_ARCH STREQUAL "mips") - if(NCNN_COMPILER_SUPPORT_LOONGSON_MMI) - ncnn_add_arch_opt_layer(${class} mmi "-mmsa -mloongson-mmi") - endif() + ncnn_add_arch_opt_layer(${class} mmi "-mmsa -mloongson-mmi") endif() if(NCNN_RUNTIME_CPU AND NCNN_RVV AND NCNN_TARGET_ARCH STREQUAL "riscv") diff --git a/cmake/ncnn_generate_avx2_source.cmake b/cmake/ncnn_generate_fma_source.cmake similarity index 60% rename from cmake/ncnn_generate_avx2_source.cmake rename to cmake/ncnn_generate_fma_source.cmake index c00792545..d15d73a0b 100644 --- a/cmake/ncnn_generate_avx2_source.cmake +++ b/cmake/ncnn_generate_fma_source.cmake @@ -7,8 +7,8 @@ file(READ ${SRC} source_data) string(TOUPPER ${CLASS} CLASS_UPPER) string(TOLOWER ${CLASS} CLASS_LOWER) -string(REGEX REPLACE "LAYER_${CLASS_UPPER}_X86_H" "LAYER_${CLASS_UPPER}_X86_AVX2_H" source_data "${source_data}") -string(REGEX REPLACE "${CLASS}_x86" "${CLASS}_x86_avx2" source_data "${source_data}") -string(REGEX REPLACE "#include \"${CLASS_LOWER}_x86.h\"" "#include \"${CLASS_LOWER}_x86_avx2.h\"" source_data "${source_data}") +string(REGEX REPLACE "LAYER_${CLASS_UPPER}_X86_H" "LAYER_${CLASS_UPPER}_X86_FMA_H" source_data "${source_data}") +string(REGEX REPLACE "${CLASS}_x86" "${CLASS}_x86_fma" source_data "${source_data}") +string(REGEX REPLACE "#include \"${CLASS_LOWER}_x86.h\"" "#include \"${CLASS_LOWER}_x86_fma.h\"" source_data "${source_data}") file(WRITE ${DST} "${source_data}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 65c2064ce..7cde1e194 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -331,29 +331,37 @@ if(NCNN_TARGET_ARCH STREQUAL "x86") if(NOT NCNN_RUNTIME_CPU AND NCNN_AVX512) if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) if(NCNN_AVX512VNNI) - target_compile_options(ncnn PRIVATE /arch:AVX512 /D__AVX512VNNI__) + target_compile_options(ncnn PRIVATE /arch:AVX512 /D__FMA__ /D__AVX512VNNI__) else() - target_compile_options(ncnn PRIVATE /arch:AVX512) + target_compile_options(ncnn PRIVATE /arch:AVX512 /D__FMA__) endif() else() if(NCNN_AVX512VNNI) - target_compile_options(ncnn PRIVATE -mfma -mf16c -mavx512f -mavx512vl -mavx512vnni) + target_compile_options(ncnn PRIVATE -mavx512f -mavx512vl -mfma -mf16c -mavx512vnni) else() - target_compile_options(ncnn PRIVATE -mfma -mf16c -mavx512f -mavx512vl) + target_compile_options(ncnn PRIVATE -mavx512f -mavx512vl -mfma -mf16c) endif() endif() - elseif(NOT NCNN_RUNTIME_CPU AND NCNN_AVX2) + elseif(NOT NCNN_RUNTIME_CPU AND NCNN_FMA) if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")) if(NCNN_AVXVNNI) - target_compile_options(ncnn PRIVATE /arch:AVX2 /D__AVXVNNI__) + target_compile_options(ncnn PRIVATE /arch:AVX2 /D__FMA__ /D__AVXVNNI__) + elseif(NCNN_AVX2) + target_compile_options(ncnn PRIVATE /arch:AVX2 /D__FMA__) + elseif(NCNN_XOP) + target_compile_options(ncnn PRIVATE /arch:AVX /D__FMA__ /D__XOP__) else() - target_compile_options(ncnn PRIVATE /arch:AVX2) + target_compile_options(ncnn PRIVATE /arch:AVX /D__FMA__) endif() else() if(NCNN_AVXVNNI) - target_compile_options(ncnn PRIVATE -mfma -mf16c -mavx2 -mavxvnni) + target_compile_options(ncnn PRIVATE -mavx2 -mfma -mf16c -mavxvnni) + elseif(NCNN_AVX2) + target_compile_options(ncnn PRIVATE -mavx2 -mfma -mf16c) + elseif(NCNN_XOP) + target_compile_options(ncnn PRIVATE -mavx -mfma -mxop) else() - target_compile_options(ncnn PRIVATE -mfma -mf16c -mavx2) + target_compile_options(ncnn PRIVATE -mavx -mfma) endif() endif() elseif(NOT NCNN_RUNTIME_CPU AND NCNN_AVX) diff --git a/src/cpu.cpp b/src/cpu.cpp index f5bbfe0e4..bd71177fd 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -512,6 +512,30 @@ static int get_cpu_support_x86_avx() return 1; } +static int get_cpu_support_x86_fma() +{ +#if !NCNN_FMA + return 0; +#endif + unsigned int cpu_info[4] = {0}; + x86_cpuid(0, cpu_info); + + int nIds = cpu_info[0]; + if (nIds < 7) + return 0; + + x86_cpuid(1, cpu_info); + // check AVX XSAVE OSXSAVE + if (!(cpu_info[2] & (1u << 28)) || !(cpu_info[2] & (1u << 26)) || !(cpu_info[2] & (1u << 27))) + return 0; + + // check XSAVE enabled by kernel + if ((x86_get_xcr0() & 6) != 6) + return 0; + + return cpu_info[2] & (1u << 12); +} + static int get_cpu_support_x86_xop() { #if !NCNN_XOP @@ -637,6 +661,7 @@ static int get_cpu_support_x86_avx512_vnni() } static int g_cpu_support_x86_avx = get_cpu_support_x86_avx(); +static int g_cpu_support_x86_fma = get_cpu_support_x86_fma(); static int g_cpu_support_x86_xop = get_cpu_support_x86_xop(); static int g_cpu_support_x86_avx2 = get_cpu_support_x86_avx2(); static int g_cpu_support_x86_avx_vnni = get_cpu_support_x86_avx_vnni(); @@ -644,6 +669,7 @@ static int g_cpu_support_x86_avx512 = get_cpu_support_x86_avx512(); static int g_cpu_support_x86_avx512_vnni = get_cpu_support_x86_avx512_vnni(); #else // defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) static const int g_cpu_support_x86_avx = 0; +static const int g_cpu_support_x86_fma = 0; static const int g_cpu_support_x86_xop = 0; static const int g_cpu_support_x86_avx2 = 0; static const int g_cpu_support_x86_avx_vnni = 0; @@ -656,6 +682,11 @@ int cpu_support_x86_avx() return g_cpu_support_x86_avx; } +int cpu_support_x86_fma() +{ + return g_cpu_support_x86_fma; +} + int cpu_support_x86_xop() { return g_cpu_support_x86_xop; diff --git a/src/cpu.h b/src/cpu.h index 979ce8522..9a0f64646 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -54,17 +54,19 @@ NCNN_EXPORT int cpu_support_arm_asimdhp(); // asimddp = aarch64 asimd dot product NCNN_EXPORT int cpu_support_arm_asimddp(); -// avx = x86_64 avx +// avx = x86 avx NCNN_EXPORT int cpu_support_x86_avx(); -// xop = x86_64 xop +// xop = x86 xop NCNN_EXPORT int cpu_support_x86_xop(); -// avx2 = x86_64 avx2 + fma + f16c +// fma = x86 fma +NCNN_EXPORT int cpu_support_x86_fma(); +// avx2 = x86 avx2 + fma + f16c NCNN_EXPORT int cpu_support_x86_avx2(); -// avx_vnni = x86_64 avx vnni +// avx_vnni = x86 avx vnni NCNN_EXPORT int cpu_support_x86_avx_vnni(); -// avx512 = x86_64 avx512f + avx512vl +// avx512 = x86 avx512f + avx512vl NCNN_EXPORT int cpu_support_x86_avx512(); -// avx512_vnni = x86_64 avx512 vnni +// avx512_vnni = x86 avx512 vnni NCNN_EXPORT int cpu_support_x86_avx512_vnni(); // msa = mips mas diff --git a/src/layer.cpp b/src/layer.cpp index 199882239..21ae073a9 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -239,13 +239,13 @@ Layer* create_layer(int index) } else #endif// NCNN_RUNTIME_CPU && NCNN_AVX512 -#if NCNN_RUNTIME_CPU && NCNN_AVX2 - if (ncnn::cpu_support_x86_avx2()) +#if NCNN_RUNTIME_CPU && NCNN_FMA + if (ncnn::cpu_support_x86_fma()) { - layer_creator = layer_registry_avx2[index].creator; + layer_creator = layer_registry_fma[index].creator; } else -#endif// NCNN_RUNTIME_CPU && NCNN_AVX2 +#endif// NCNN_RUNTIME_CPU && NCNN_FMA #if NCNN_RUNTIME_CPU && NCNN_AVX if (ncnn::cpu_support_x86_avx()) { diff --git a/src/layer/x86/convolution_3x3_pack8to1_int8.h b/src/layer/x86/convolution_3x3_pack8to1_int8.h index f7b8b42f1..e9de884c7 100644 --- a/src/layer/x86/convolution_3x3_pack8to1_int8.h +++ b/src/layer/x86/convolution_3x3_pack8to1_int8.h @@ -32,6 +32,15 @@ static void conv3x3s1_winograd42_transform_kernel_pack8to1_int8_sse(const Mat& k } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void conv3x3s1_winograd42_transform_kernel_pack8to1_int8_sse_avx2(const Mat& kernel, Mat& kernel_tm_pack8to1, int inch, int outch, const Option& opt); + conv3x3s1_winograd42_transform_kernel_pack8to1_int8_sse_avx2(kernel, kernel_tm_pack8to1, inch, outch, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { @@ -190,6 +199,15 @@ static void conv3x3s1_winograd42_pack8to1_int8_sse(const Mat& bottom_blob, Mat& } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void conv3x3s1_winograd42_pack8to1_int8_sse_avx2(const Mat& bottom_blob, Mat& top_blob, const Mat& kernel, const Option& opt); + conv3x3s1_winograd42_pack8to1_int8_sse_avx2(bottom_blob, top_blob, kernel_tm, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { diff --git a/src/layer/x86/convolution_3x3_pack8to4_int8.h b/src/layer/x86/convolution_3x3_pack8to4_int8.h index 6a9647d32..01106f9a7 100644 --- a/src/layer/x86/convolution_3x3_pack8to4_int8.h +++ b/src/layer/x86/convolution_3x3_pack8to4_int8.h @@ -32,6 +32,15 @@ static void conv3x3s1_winograd42_transform_kernel_pack8to4_int8_sse(const Mat& k } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void conv3x3s1_winograd42_transform_kernel_pack8to4_int8_sse_avx2(const Mat& kernel, Mat& kernel_tm_pack8, int inch, int outch, const Option& opt); + conv3x3s1_winograd42_transform_kernel_pack8to4_int8_sse_avx2(kernel, kernel_tm_pack8, inch, outch, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { @@ -174,6 +183,15 @@ static void conv3x3s1_winograd42_pack8to4_int8_sse(const Mat& bottom_blob, Mat& } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void conv3x3s1_winograd42_pack8to4_int8_sse_avx2(const Mat& bottom_blob, Mat& top_blob, const Mat& kernel, const Option& opt); + conv3x3s1_winograd42_pack8to4_int8_sse_avx2(bottom_blob, top_blob, kernel_tm, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { diff --git a/src/layer/x86/convolution_sgemm_int8.h b/src/layer/x86/convolution_sgemm_int8.h index a3c63f119..322ee0993 100644 --- a/src/layer/x86/convolution_sgemm_int8.h +++ b/src/layer/x86/convolution_sgemm_int8.h @@ -32,6 +32,15 @@ static void im2col_sgemm_int8_sse(const Mat& bottom_im2col, Mat& top_blob, const } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void im2col_sgemm_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + im2col_sgemm_int8_sse_avx2(bottom_im2col, top_blob, kernel, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { diff --git a/src/layer/x86/convolution_sgemm_pack1to4_int8.h b/src/layer/x86/convolution_sgemm_pack1to4_int8.h index 8e7399398..a9dd0b160 100644 --- a/src/layer/x86/convolution_sgemm_pack1to4_int8.h +++ b/src/layer/x86/convolution_sgemm_pack1to4_int8.h @@ -32,6 +32,15 @@ static void im2col_sgemm_pack1to4_int8_sse(const Mat& bottom_im2col, Mat& top_bl } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void im2col_sgemm_pack1to4_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + im2col_sgemm_pack1to4_int8_sse_avx2(bottom_im2col, top_blob, kernel, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { diff --git a/src/layer/x86/convolution_sgemm_pack8to1_int8.h b/src/layer/x86/convolution_sgemm_pack8to1_int8.h index d01e72def..5662266ad 100644 --- a/src/layer/x86/convolution_sgemm_pack8to1_int8.h +++ b/src/layer/x86/convolution_sgemm_pack8to1_int8.h @@ -32,6 +32,15 @@ static void im2col_sgemm_pack8to1_int8_sse(const Mat& bottom_im2col, Mat& top_bl } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void im2col_sgemm_pack8to1_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + im2col_sgemm_pack8to1_int8_sse_avx2(bottom_im2col, top_blob, kernel, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { diff --git a/src/layer/x86/convolution_sgemm_pack8to4_int8.h b/src/layer/x86/convolution_sgemm_pack8to4_int8.h index 42e4b952e..e6304743e 100644 --- a/src/layer/x86/convolution_sgemm_pack8to4_int8.h +++ b/src/layer/x86/convolution_sgemm_pack8to4_int8.h @@ -32,6 +32,15 @@ static void im2col_sgemm_pack8to4_int8_sse(const Mat& bottom_im2col, Mat& top_bl } #endif +#if NCNN_AVX2 && __AVX__ && !__AVX2__ + if (ncnn::cpu_support_x86_avx2()) + { + extern void im2col_sgemm_pack8to4_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + im2col_sgemm_pack8to4_int8_sse_avx2(bottom_im2col, top_blob, kernel, opt); + return; + } +#endif + #if NCNN_XOP && __SSE2__ && !__XOP__ if (ncnn::cpu_support_x86_xop()) { diff --git a/src/layer/x86/convolution_x86_avx2.cpp b/src/layer/x86/convolution_x86_avx2.cpp new file mode 100644 index 000000000..d2972a1ac --- /dev/null +++ b/src/layer/x86/convolution_x86_avx2.cpp @@ -0,0 +1,74 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "convolution_x86_avx2.h" + +#include "cpu.h" +#include "mat.h" +#include "x86_usability.h" + +namespace ncnn { + +#include "convolution_sgemm_int8.h" +#include "convolution_sgemm_pack1to4_int8.h" +#include "convolution_sgemm_pack8to1_int8.h" +#include "convolution_sgemm_pack8to4_int8.h" +#include "convolution_3x3_pack8to1_int8.h" +#include "convolution_3x3_pack8to4_int8.h" + +// pack1 +void im2col_sgemm_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt) +{ + im2col_sgemm_int8_sse(bottom_im2col, top_blob, kernel, opt); +} + +// pack1to4 +void im2col_sgemm_pack1to4_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt) +{ + im2col_sgemm_pack1to4_int8_sse(bottom_im2col, top_blob, kernel, opt); +} + +// pack8to1 +void im2col_sgemm_pack8to1_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt) +{ + im2col_sgemm_pack8to1_int8_sse(bottom_im2col, top_blob, kernel, opt); +} + +void conv3x3s1_winograd42_transform_kernel_pack8to1_int8_sse_avx2(const Mat& kernel, Mat& kernel_tm, int inch, int outch, const Option& opt) +{ + conv3x3s1_winograd42_transform_kernel_pack8to1_int8_sse(kernel, kernel_tm, inch, outch, opt); +} + +void conv3x3s1_winograd42_pack8to1_int8_sse_avx2(const Mat& bottom_blob, Mat& top_blob, const Mat& kernel, const Option& opt) +{ + conv3x3s1_winograd42_pack8to1_int8_sse(bottom_blob, top_blob, kernel, opt); +} + +// pack8to4 +void im2col_sgemm_pack8to4_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt) +{ + im2col_sgemm_pack8to4_int8_sse(bottom_im2col, top_blob, kernel, opt); +} + +void conv3x3s1_winograd42_transform_kernel_pack8to4_int8_sse_avx2(const Mat& kernel, Mat& kernel_tm, int inch, int outch, const Option& opt) +{ + conv3x3s1_winograd42_transform_kernel_pack8to4_int8_sse(kernel, kernel_tm, inch, outch, opt); +} + +void conv3x3s1_winograd42_pack8to4_int8_sse_avx2(const Mat& bottom_blob, Mat& top_blob, const Mat& kernel, const Option& opt) +{ + conv3x3s1_winograd42_pack8to4_int8_sse(bottom_blob, top_blob, kernel, opt); +} + +} // namespace ncnn diff --git a/src/layer/x86/convolution_x86_avx2.h b/src/layer/x86/convolution_x86_avx2.h new file mode 100644 index 000000000..32bae2170 --- /dev/null +++ b/src/layer/x86/convolution_x86_avx2.h @@ -0,0 +1,37 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "mat.h" + +namespace ncnn { + +// pack1 +void im2col_sgemm_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + +// pack1to4 +void im2col_sgemm_pack1to4_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + +// pack8to1 +void im2col_sgemm_pack8to1_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + +void conv3x3s1_winograd42_transform_kernel_pack8to1_int8_sse_avx2(const Mat& kernel, Mat& kernel_tm, int inch, int outch, const Option& opt); +void conv3x3s1_winograd42_pack8to1_int8_sse_avx2(const Mat& bottom_blob, Mat& top_blob, const Mat& kernel, const Option& opt); + +// pack8to4 +void im2col_sgemm_pack8to4_int8_sse_avx2(const Mat& bottom_im2col, Mat& top_blob, const Mat& kernel, const Option& opt); + +void conv3x3s1_winograd42_transform_kernel_pack8to4_int8_sse_avx2(const Mat& kernel, Mat& kernel_tm, int inch, int outch, const Option& opt); +void conv3x3s1_winograd42_pack8to4_int8_sse_avx2(const Mat& bottom_blob, Mat& top_blob, const Mat& kernel, const Option& opt); + +} // namespace ncnn diff --git a/src/layer/x86/x86_activation.h b/src/layer/x86/x86_activation.h index 6c8dce8b0..eece18451 100644 --- a/src/layer/x86/x86_activation.h +++ b/src/layer/x86/x86_activation.h @@ -131,7 +131,7 @@ static NCNN_FORCEINLINE __m256 tanh_avx(__m256 inputs) { const __m256 one = _mm256_set1_ps(1.0f); const __m256 two = _mm256_set1_ps(2.0f); -#if __AVX2__ +#if __FMA__ return _mm256_fmsub_ps(sigmoid_avx(_mm256_mul_ps(inputs, two)), two, one); #else return _mm256_sub_ps(_mm256_mul_ps(sigmoid_avx(_mm256_mul_ps(inputs, two)), two), one); diff --git a/src/layer/x86/x86_usability.h b/src/layer/x86/x86_usability.h index 635a0843f..dceebc67d 100644 --- a/src/layer/x86/x86_usability.h +++ b/src/layer/x86/x86_usability.h @@ -147,7 +147,7 @@ static NCNN_FORCEINLINE __m128i float2int8_sse(const __m128& _v0, const __m128& return _v8; } -#ifndef __AVX2__ +#ifndef __FMA__ static NCNN_FORCEINLINE __m128 _mm_comp_fmadd_ps(__m128 _a, const __m128 _b, const __m128 _c) { @@ -156,7 +156,7 @@ static NCNN_FORCEINLINE __m128 _mm_comp_fmadd_ps(__m128 _a, const __m128 _b, con #endif #if __AVX__ -#ifndef __AVX2__ +#ifndef __FMA__ static NCNN_FORCEINLINE __m256 _mm256_comp_fmadd_ps(__m256 _a, const __m256 _b, const __m256 _c) { return _mm256_add_ps(_mm256_mul_ps(_a, _b), _c); diff --git a/src/layer_registry.h.in b/src/layer_registry.h.in index e3add4f93..e7d85ad2b 100644 --- a/src/layer_registry.h.in +++ b/src/layer_registry.h.in @@ -11,11 +11,11 @@ static const layer_registry_entry layer_registry_avx512[] = { @layer_registry_avx512@ }; #endif // NCNN_RUNTIME_CPU && NCNN_AVX512 -#if NCNN_RUNTIME_CPU && NCNN_AVX2 -static const layer_registry_entry layer_registry_avx2[] = { -@layer_registry_avx2@ +#if NCNN_RUNTIME_CPU && NCNN_FMA +static const layer_registry_entry layer_registry_fma[] = { +@layer_registry_fma@ }; -#endif // NCNN_RUNTIME_CPU && NCNN_AVX2 +#endif // NCNN_RUNTIME_CPU && NCNN_FMA #if NCNN_RUNTIME_CPU && NCNN_AVX static const layer_registry_entry layer_registry_avx[] = { @layer_registry_avx@ diff --git a/src/platform.h.in b/src/platform.h.in index fc3091966..3f62069b7 100644 --- a/src/platform.h.in +++ b/src/platform.h.in @@ -32,6 +32,7 @@ #cmakedefine01 NCNN_RUNTIME_CPU #cmakedefine01 NCNN_AVX #cmakedefine01 NCNN_XOP +#cmakedefine01 NCNN_FMA #cmakedefine01 NCNN_AVX2 #cmakedefine01 NCNN_AVXVNNI #cmakedefine01 NCNN_AVX512