From cae571c7136328a2f86ab6ecbeb1d82a01e673c3 Mon Sep 17 00:00:00 2001 From: Dmitri Smirnov Date: Tue, 8 Oct 2019 21:18:04 -0700 Subject: [PATCH] Add a test for AVX512 compilation before compiling 512 asm (#2055) --- check_512.s | 7 +++ cmake/onnxruntime_mlas.cmake | 54 +++++++++++++------ onnxruntime/core/mlas/lib/platform.cpp | 34 +++++++----- .../test/contrib_ops/layer_norm_op_test.cc | 4 +- 4 files changed, 68 insertions(+), 31 deletions(-) create mode 100644 check_512.s diff --git a/check_512.s b/check_512.s new file mode 100644 index 0000000000..2e9635b1be --- /dev/null +++ b/check_512.s @@ -0,0 +1,7 @@ +.intel_syntax noprefix +infiniteLoop: + jmp main +main: + vxorpd zmm0,zmm0,zmm0 + jmp infiniteLoop + diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake index 4c03761542..5ee3c8cf4b 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -181,26 +181,50 @@ else() set_source_files_properties(${mlas_platform_srcs_avx2} PROPERTIES COMPILE_FLAGS "-mavx2 -mfma") - set(mlas_platform_srcs_avx512f - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/DgemmKernelAvx512F.S - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/SgemmKernelAvx512F.S - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/SconvKernelAvx512F.S - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/SpoolKernelAvx512F.S - ) + # Some platforms do not support 512xx flags but still able to compile the source + # Others support the flag and refuse to compile w/o the flag. + # We have to run all 3 checks check_cxx_compiler_flag("-mavx512f" HAS_AVX512F) if(HAS_AVX512F) - set_source_files_properties(${mlas_platform_srcs_avx512f} PROPERTIES COMPILE_FLAGS "-mavx512f") + set(AVX512_NEEDED "-mavx512f") endif() - - set(mlas_platform_srcs_avx512bw - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8S8KernelAvx512BW.S - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8S8KernelAvx512Vnni.S - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8U8KernelAvx512BW.S - ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8U8KernelAvx512Vnni.S - ) check_cxx_compiler_flag("-mavx512bw" HAS_AVX512BW) if(HAS_AVX512BW) - set_source_files_properties(${mlas_platform_srcs_avx512bw} PROPERTIES COMPILE_FLAGS "-mavx512bw") + set(AVX512_NEEDED "${AVX512_NEEDED} -mavx512bw") + endif() + + set(CMAKE_REQUIRED_FLAGS ${AVX512_NEEDED}) + check_cxx_source_compiles( +"int main() { +asm(\"vpxord %zmm0,%zmm0,%zmm0\"); +return 0; +}" +AVX512_COMPILES) + + + if(AVX512_COMPILES) + set(mlas_platform_srcs_avx512f + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/DgemmKernelAvx512F.S + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/SgemmKernelAvx512F.S + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/SconvKernelAvx512F.S + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/SpoolKernelAvx512F.S + ) + if(HAS_AVX512F) + set_source_files_properties(${mlas_platform_srcs_avx512f} PROPERTIES COMPILE_FLAGS "-mavx512f") + endif() + + set(mlas_platform_srcs_avx512bw + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8S8KernelAvx512BW.S + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8S8KernelAvx512Vnni.S + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8U8KernelAvx512BW.S + ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86_64/QgemmU8U8KernelAvx512Vnni.S + ) + if(HAS_AVX512BW) + set_source_files_properties(${mlas_platform_srcs_avx512bw} PROPERTIES COMPILE_FLAGS "-mavx512bw") + endif() + else() + # Do not compile CPP support for 512xx + set_source_files_properties(${mlas_common_srcs} PROPERTIES COMPILE_FLAGS "-DMLAS_AVX512_UNSUPPORTED") endif() set(mlas_platform_srcs diff --git a/onnxruntime/core/mlas/lib/platform.cpp b/onnxruntime/core/mlas/lib/platform.cpp index 6ae9bd2e15..af0c64caa2 100644 --- a/onnxruntime/core/mlas/lib/platform.cpp +++ b/onnxruntime/core/mlas/lib/platform.cpp @@ -161,8 +161,7 @@ Return Value: this->PoolFloatKernel[MlasAveragePoolingIncludePad] = MlasPoolAverageIncludePadFloatKernelAvx; // - // Check if the processor supports AVX512F (and the operating - // system supports saving AVX512F state) or AVX2/FMA3 features. + // Check if the processor supports AVX2/FMA3 features. // unsigned Cpuid7[4]; @@ -181,6 +180,23 @@ Return Value: this->GemmU8U8CopyPackBRoutine = MlasGemmU8U8CopyPackBAvx2; this->GemmU8U8Kernel = MlasGemmU8U8KernelAvx2; + this->GemmFloatKernel = MlasGemmFloatKernelFma3; + this->GemmDoubleKernel = MlasGemmDoubleKernelFma3; + this->ConvNchwFloatKernel = MlasConvNchwFloatKernelFma3; + this->ConvNchwcFloatKernel = MlasConvNchwcFloatKernelFma3; + this->ConvDepthwiseFloatKernel = MlasConvDepthwiseFloatKernelFma3; + this->ConvPointwiseFloatKernel = MlasConvPointwiseFloatKernelFma3; + this->LogisticKernelRoutine = MlasLogisticKernelFma3; + this->TanhKernelRoutine = MlasTanhKernelFma3; + this->ErfKernelRoutine = MlasErfKernelFma3; + +#if !defined(MLAS_AVX512_UNSUPPORTED) + + // + // Check if the processor supports AVX512F features and the + // operating system supports saving AVX512F state. + // + if (((Cpuid7[1] & 0x10000) != 0) && ((xcr0 & 0xE0) == 0xE0)) { this->GemmFloatKernel = MlasGemmFloatKernelAvx512F; @@ -214,20 +230,10 @@ Return Value: this->GemmU8U8Kernel = MlasGemmU8U8KernelAvx512Vnni; } } - - } else { - - this->GemmFloatKernel = MlasGemmFloatKernelFma3; - this->GemmDoubleKernel = MlasGemmDoubleKernelFma3; - this->ConvNchwFloatKernel = MlasConvNchwFloatKernelFma3; - this->ConvNchwcFloatKernel = MlasConvNchwcFloatKernelFma3; - this->ConvDepthwiseFloatKernel = MlasConvDepthwiseFloatKernelFma3; - this->ConvPointwiseFloatKernel = MlasConvPointwiseFloatKernelFma3; } - this->LogisticKernelRoutine = MlasLogisticKernelFma3; - this->TanhKernelRoutine = MlasTanhKernelFma3; - this->ErfKernelRoutine = MlasErfKernelFma3; +#endif + } #endif diff --git a/onnxruntime/test/contrib_ops/layer_norm_op_test.cc b/onnxruntime/test/contrib_ops/layer_norm_op_test.cc index ae13642fac..da0b447b48 100644 --- a/onnxruntime/test/contrib_ops/layer_norm_op_test.cc +++ b/onnxruntime/test/contrib_ops/layer_norm_op_test.cc @@ -100,7 +100,7 @@ class LayerNormOpTester : public OpTester { // Compare CPU with original subgraph ASSERT_TRUE(cpu_fetches.size() == subgraph_fetches.size()); - for (auto i = 0; i < cpu_fetches.size(); i++) { + for (size_t i = 0; i < cpu_fetches.size(); i++) { if (cpu_fetches[i].IsTensor() && subgraph_fetches[i].IsTensor()) { VLOGS_DEFAULT(1) << "Checking tensor " << i; CheckTensor(subgraph_fetches[i].Get(), cpu_fetches[i].Get(), 1e-3, 1e-3); @@ -110,7 +110,7 @@ class LayerNormOpTester : public OpTester { // Compare GPU with original subgraph if (DefaultCudaExecutionProvider()) { ASSERT_TRUE(cuda_fetches.size() == subgraph_fetches.size()); - for (auto i = 0; i < cuda_fetches.size(); i++) { + for(size_t i = 0; i < cuda_fetches.size(); i++) { if (cuda_fetches[i].IsTensor() && subgraph_fetches[i].IsTensor()) { VLOGS_DEFAULT(1) << "Checking tensor " << i; CheckTensor(subgraph_fetches[i].Get(), cuda_fetches[i].Get(), 1e-3, 1e-3);