From 324af878071351488ed185f5eaec33f5f26aacbf Mon Sep 17 00:00:00 2001 From: Megvii Engine Team Date: Sun, 26 Jul 2020 22:03:22 +0800 Subject: [PATCH] feat(dnn/arm): add cpuinfo runtime check for x86 and arm GitOrigin-RevId: c2020a344ef286c6104d78525e52eb4a1e86ab82 --- CMakeLists.txt | 9 ++ cmake/cpuinfo.cmake | 20 +++ dnn/src/CMakeLists.txt | 7 + dnn/src/common/cpuinfo_arch_vendor.cpp | 269 +++++++++++++++++++++++++++++++++ dnn/src/common/cpuinfo_arch_vendor.h | 27 ++++ dnn/test/arm_common/cpuinfo.cpp | 176 +++++++++++++++++++++ dnn/test/x86/cpuinfo.cpp | 47 ++++++ 7 files changed, 555 insertions(+) create mode 100644 cmake/cpuinfo.cmake create mode 100644 dnn/src/common/cpuinfo_arch_vendor.cpp create mode 100644 dnn/src/common/cpuinfo_arch_vendor.h create mode 100644 dnn/test/arm_common/cpuinfo.cpp create mode 100644 dnn/test/x86/cpuinfo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f4b43a77..c3dc1a20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,6 +104,15 @@ if(${MGE_ARCH} STREQUAL "AUTO") endif() endif() +if(${MGE_ARCH} STREQUAL "x86_64" OR ${MGE_ARCH} STREQUAL "i386" OR ${MGE_ARCH} STREQUAL "armv7" OR ${MGE_ARCH} STREQUAL "aarch64") + option(MGB_ENABLE_CPUINFO "Build cpuinfo library for check runtime." ON) + if(MGB_ENABLE_CPUINFO) + message("-- Enable cpuinfo runtime check.") + add_definitions(-DMGB_ENABLE_CPUINFO_CHECK) + include(cmake/cpuinfo.cmake) + endif() +endif() + if(MSVC OR WIN32) add_compile_definitions(NOMINMAX=1 _USE_MATH_DEFINES=1 WIN32=1) message("-- into windows build...") diff --git a/cmake/cpuinfo.cmake b/cmake/cpuinfo.cmake new file mode 100644 index 00000000..a6d9630b --- /dev/null +++ b/cmake/cpuinfo.cmake @@ -0,0 +1,20 @@ +if (MGE_USE_SYSTEM_LIB) + find_package(Cpuinfo) + message("Using system provided cpuinfo ${cpuinfo_VERSION}") + add_library(libcpuinfo IMPORTED GLOBAL) + set_target_properties( + libcpuinfo PROPERTIES + IMPORTED_LOCATION ${cpuinfo_LIBRARIES} + INTERFACE_INCLUDE_DIRECTORIES ${cpuinfo_INCLUDE_DIRS} + ) + return() +endif() + +SET(CPUINFO_LIBRARY_TYPE "static" CACHE STRING "Type of cpuinfo library (shared, static, or default) to build") +OPTION(CPUINFO_BUILD_TOOLS "Build command-line tools" OFF) +OPTION(CPUINFO_BUILD_UNIT_TESTS "Build cpuinfo unit tests" OFF) +OPTION(CPUINFO_BUILD_MOCK_TESTS "Build cpuinfo mock tests" OFF) +OPTION(CPUINFO_BUILD_BENCHMARKS "Build cpuinfo micro-benchmarks" OFF) +include_directories("${PROJECT_SOURCE_DIR}/third_party/cpuinfo/include") +add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/cpuinfo ${CMAKE_CURRENT_BINARY_DIR}/cpuinfo EXCLUDE_FROM_ALL) + diff --git a/dnn/src/CMakeLists.txt b/dnn/src/CMakeLists.txt index ecafe71c..aa19778a 100644 --- a/dnn/src/CMakeLists.txt +++ b/dnn/src/CMakeLists.txt @@ -51,6 +51,13 @@ add_definitions(${LIBMEGDNN_DEF}) add_library(megdnn EXCLUDE_FROM_ALL OBJECT ${SOURCES}) target_link_libraries(megdnn PUBLIC opr_param_defs) + +if(${MGE_ARCH} STREQUAL "x86_64" OR ${MGE_ARCH} STREQUAL "i386" OR ${MGE_ARCH} STREQUAL "armv7" OR ${MGE_ARCH} STREQUAL "aarch64") + if(MGB_ENABLE_CPUINFO) + target_link_libraries(megdnn PRIVATE $) + endif() +endif() + target_include_directories(megdnn PUBLIC $ diff --git a/dnn/src/common/cpuinfo_arch_vendor.cpp b/dnn/src/common/cpuinfo_arch_vendor.cpp new file mode 100644 index 00000000..f33a4599 --- /dev/null +++ b/dnn/src/common/cpuinfo_arch_vendor.cpp @@ -0,0 +1,269 @@ +/** + * \file dnn/src/common/cpuinfo_arch_vendor.cpp + * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") + * + * Copyright (c) 2014-2020 Megvii Inc. All rights reserved. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + */ + +#ifdef MGB_ENABLE_CPUINFO_CHECK + +#include "cpuinfo_arch_vendor.h" + +namespace megdnn { + +const char* vendor_to_string(enum cpuinfo_vendor vendor) { + switch (vendor) { + case cpuinfo_vendor_unknown: + return "unknown"; + case cpuinfo_vendor_intel: + return "Intel"; + case cpuinfo_vendor_amd: + return "AMD"; + case cpuinfo_vendor_huawei: + return "Huawei"; + case cpuinfo_vendor_hygon: + return "Hygon"; + case cpuinfo_vendor_arm: + return "ARM"; + case cpuinfo_vendor_qualcomm: + return "Qualcomm"; + case cpuinfo_vendor_apple: + return "Apple"; + case cpuinfo_vendor_samsung: + return "Samsung"; + case cpuinfo_vendor_nvidia: + return "Nvidia"; + case cpuinfo_vendor_mips: + return "MIPS"; + case cpuinfo_vendor_ibm: + return "IBM"; + case cpuinfo_vendor_ingenic: + return "Ingenic"; + case cpuinfo_vendor_via: + return "VIA"; + case cpuinfo_vendor_cavium: + return "Cavium"; + case cpuinfo_vendor_broadcom: + return "Broadcom"; + case cpuinfo_vendor_apm: + return "Applied Micro"; + default: + return "NULL"; + } +} + +const char* uarch_to_string(enum cpuinfo_uarch uarch) { + switch (uarch) { + case cpuinfo_uarch_unknown: + return "unknown"; + case cpuinfo_uarch_p5: + return "P5"; + case cpuinfo_uarch_quark: + return "Quark"; + case cpuinfo_uarch_p6: + return "P6"; + case cpuinfo_uarch_dothan: + return "Dothan"; + case cpuinfo_uarch_yonah: + return "Yonah"; + case cpuinfo_uarch_conroe: + return "Conroe"; + case cpuinfo_uarch_penryn: + return "Penryn"; + case cpuinfo_uarch_nehalem: + return "Nehalem"; + case cpuinfo_uarch_sandy_bridge: + return "Sandy Bridge"; + case cpuinfo_uarch_ivy_bridge: + return "Ivy Bridge"; + case cpuinfo_uarch_haswell: + return "Haswell"; + case cpuinfo_uarch_broadwell: + return "Broadwell"; + case cpuinfo_uarch_sky_lake: + return "Sky Lake"; + case cpuinfo_uarch_palm_cove: + return "Palm Cove"; + case cpuinfo_uarch_sunny_cove: + return "Sunny Cove"; + case cpuinfo_uarch_willamette: + return "Willamette"; + case cpuinfo_uarch_prescott: + return "Prescott"; + case cpuinfo_uarch_bonnell: + return "Bonnell"; + case cpuinfo_uarch_saltwell: + return "Saltwell"; + case cpuinfo_uarch_silvermont: + return "Silvermont"; + case cpuinfo_uarch_airmont: + return "Airmont"; + case cpuinfo_uarch_goldmont: + return "Goldmont"; + case cpuinfo_uarch_goldmont_plus: + return "Goldmont Plus"; + case cpuinfo_uarch_knights_ferry: + return "Knights Ferry"; + case cpuinfo_uarch_knights_corner: + return "Knights Corner"; + case cpuinfo_uarch_knights_landing: + return "Knights Landing"; + case cpuinfo_uarch_knights_hill: + return "Knights Hill"; + case cpuinfo_uarch_knights_mill: + return "Knights Mill"; + case cpuinfo_uarch_k5: + return "K5"; + case cpuinfo_uarch_k6: + return "K6"; + case cpuinfo_uarch_k7: + return "K7"; + case cpuinfo_uarch_k8: + return "K8"; + case cpuinfo_uarch_k10: + return "K10"; + case cpuinfo_uarch_bulldozer: + return "Bulldozer"; + case cpuinfo_uarch_piledriver: + return "Piledriver"; + case cpuinfo_uarch_steamroller: + return "Steamroller"; + case cpuinfo_uarch_excavator: + return "Excavator"; + case cpuinfo_uarch_zen: + return "Zen"; + case cpuinfo_uarch_zen2: + return "Zen 2"; + case cpuinfo_uarch_geode: + return "Geode"; + case cpuinfo_uarch_bobcat: + return "Bobcat"; + case cpuinfo_uarch_jaguar: + return "Jaguar"; + case cpuinfo_uarch_puma: + return "Puma"; + case cpuinfo_uarch_xscale: + return "XScale"; + case cpuinfo_uarch_arm7: + return "ARM7"; + case cpuinfo_uarch_arm9: + return "ARM9"; + case cpuinfo_uarch_arm11: + return "ARM11"; + case cpuinfo_uarch_cortex_a5: + return "Cortex-A5"; + case cpuinfo_uarch_cortex_a7: + return "Cortex-A7"; + case cpuinfo_uarch_cortex_a8: + return "Cortex-A8"; + case cpuinfo_uarch_cortex_a9: + return "Cortex-A9"; + case cpuinfo_uarch_cortex_a12: + return "Cortex-A12"; + case cpuinfo_uarch_cortex_a15: + return "Cortex-A15"; + case cpuinfo_uarch_cortex_a17: + return "Cortex-A17"; + case cpuinfo_uarch_cortex_a32: + return "Cortex-A32"; + case cpuinfo_uarch_cortex_a35: + return "Cortex-A35"; + case cpuinfo_uarch_cortex_a53: + return "Cortex-A53"; + case cpuinfo_uarch_cortex_a55r0: + return "Cortex-A55r0"; + case cpuinfo_uarch_cortex_a55: + return "Cortex-A55"; + case cpuinfo_uarch_cortex_a57: + return "Cortex-A57"; + case cpuinfo_uarch_cortex_a65: + return "Cortex-A65"; + case cpuinfo_uarch_cortex_a72: + return "Cortex-A72"; + case cpuinfo_uarch_cortex_a73: + return "Cortex-A73"; + case cpuinfo_uarch_cortex_a75: + return "Cortex-A75"; + case cpuinfo_uarch_cortex_a76: + return "Cortex-A76"; + case cpuinfo_uarch_cortex_a77: + return "Cortex-A77"; + case cpuinfo_uarch_cortex_a78: + return "Cortex-A78"; + case cpuinfo_uarch_scorpion: + return "Scorpion"; + case cpuinfo_uarch_krait: + return "Krait"; + case cpuinfo_uarch_kryo: + return "Kryo"; + case cpuinfo_uarch_falkor: + return "Falkor"; + case cpuinfo_uarch_saphira: + return "Saphira"; + case cpuinfo_uarch_denver: + return "Denver"; + case cpuinfo_uarch_denver2: + return "Denver 2"; + case cpuinfo_uarch_carmel: + return "Carmel"; + case cpuinfo_uarch_exynos_m1: + return "Exynos M1"; + case cpuinfo_uarch_exynos_m2: + return "Exynos M2"; + case cpuinfo_uarch_exynos_m3: + return "Exynos M3"; + case cpuinfo_uarch_exynos_m4: + return "Exynos M4"; + case cpuinfo_uarch_exynos_m5: + return "Exynos M5"; + case cpuinfo_uarch_swift: + return "Swift"; + case cpuinfo_uarch_cyclone: + return "Cyclone"; + case cpuinfo_uarch_typhoon: + return "Typhoon"; + case cpuinfo_uarch_twister: + return "Twister"; + case cpuinfo_uarch_hurricane: + return "Hurricane"; + case cpuinfo_uarch_monsoon: + return "Monsoon"; + case cpuinfo_uarch_mistral: + return "Mistral"; + case cpuinfo_uarch_vortex: + return "Vortex"; + case cpuinfo_uarch_tempest: + return "Tempest"; + case cpuinfo_uarch_lightning: + return "Lightning"; + case cpuinfo_uarch_thunder: + return "Thunder"; + case cpuinfo_uarch_thunderx: + return "ThunderX"; + case cpuinfo_uarch_thunderx2: + return "ThunderX2"; + case cpuinfo_uarch_pj4: + return "PJ4"; + case cpuinfo_uarch_brahma_b15: + return "Brahma B15"; + case cpuinfo_uarch_brahma_b53: + return "Brahma B53"; + case cpuinfo_uarch_xgene: + return "X-Gene"; + case cpuinfo_uarch_dhyana: + return "Dhyana"; + case cpuinfo_uarch_taishan_v110: + return "TaiShan v110"; + default: + return "NULL"; + } +} +} // namespace megdnn +#endif + +// vim: syntax=cpp.doxygen diff --git a/dnn/src/common/cpuinfo_arch_vendor.h b/dnn/src/common/cpuinfo_arch_vendor.h new file mode 100644 index 00000000..8d11b9e8 --- /dev/null +++ b/dnn/src/common/cpuinfo_arch_vendor.h @@ -0,0 +1,27 @@ +/** + * \file dnn/src/common/cpuinfo_arch_vendor.h + * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") + * + * Copyright (c) 2014-2020 Megvii Inc. All rights reserved. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + */ + +#pragma once + +#ifdef MGB_ENABLE_CPUINFO_CHECK + +#include + +namespace megdnn { + +const char* vendor_to_string(enum cpuinfo_vendor vendor); +const char* uarch_to_string(enum cpuinfo_uarch uarch); + +} // namespace megdnn +#endif + +// vim: syntax=cpp.doxygen diff --git a/dnn/test/arm_common/cpuinfo.cpp b/dnn/test/arm_common/cpuinfo.cpp new file mode 100644 index 00000000..d5c27d56 --- /dev/null +++ b/dnn/test/arm_common/cpuinfo.cpp @@ -0,0 +1,176 @@ +/** + * \file dnn/test/arm_common/cpuinfo.cpp + * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") + * + * Copyright (c) 2014-2020 Megvii Inc. All rights reserved. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + */ +#ifdef MGB_ENABLE_CPUINFO_CHECK +#include +#include +#include "gtest/gtest.h" + +namespace megdnn { +namespace test { + +TEST(ARM_RUNTIME, CPUINFO_KIRIN980) { + + ASSERT_TRUE(cpuinfo_initialize()); + + int right_soc = strcmp(cpuinfo_get_package(0)->name, "HiSilicon Kirin 980"); + + if (!right_soc) { + ASSERT_EQ(8, cpuinfo_get_processors_count()); + + ASSERT_TRUE(cpuinfo_get_processors()); + + ASSERT_TRUE(cpuinfo_has_arm_neon()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_fp16()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_fma()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_dot()); + + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_core(i), cpuinfo_get_processor(i)->core); + } + + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(cpuinfo_vendor_arm, cpuinfo_get_core(i)->vendor); + } + + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + switch (i) { + case 0: + case 1: + case 2: + case 3: + ASSERT_EQ(cpuinfo_uarch_cortex_a76, + cpuinfo_get_core(i)->uarch); + break; + case 4: + case 5: + case 6: + case 7: + ASSERT_EQ(cpuinfo_uarch_cortex_a55, + cpuinfo_get_core(i)->uarch); + break; + } + } + } else { + printf("detect soc: %s ,skip test.\n", cpuinfo_get_package(0)->name); + } +} + +TEST(ARM_RUNTIME, CPUINFO_SDM8150) { + + ASSERT_TRUE(cpuinfo_initialize()); + + int right_soc = + strcmp(cpuinfo_get_package(0)->name, "Qualcomm Snapdragon 8150"); + + if (!right_soc) { + ASSERT_EQ(8, cpuinfo_get_processors_count()); + + ASSERT_TRUE(cpuinfo_get_processors()); + + ASSERT_TRUE(cpuinfo_has_arm_neon()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_fp16()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_fma()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_dot()); + + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_core(i), cpuinfo_get_processor(i)->core); + } + + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(cpuinfo_vendor_arm, cpuinfo_get_core(i)->vendor); + } + + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + switch (i) { + case 0: + case 1: + case 2: + case 3: + ASSERT_EQ(cpuinfo_uarch_cortex_a76, + cpuinfo_get_core(i)->uarch); + break; + case 4: + case 5: + case 6: + case 7: + ASSERT_EQ(cpuinfo_uarch_cortex_a55, + cpuinfo_get_core(i)->uarch); + break; + } + } + } else { + printf("detect soc: %s ,skip test.\n", cpuinfo_get_package(0)->name); + } +} + +TEST(ARM_RUNTIME, CPUINFO_SDM660) { + + ASSERT_TRUE(cpuinfo_initialize()); + + int right_soc = + strcmp(cpuinfo_get_package(0)->name, "Qualcomm Snapdragon 660"); + + if (!right_soc) { + ASSERT_EQ(8, cpuinfo_get_processors_count()); + + ASSERT_TRUE(cpuinfo_get_processors()); + + ASSERT_TRUE(cpuinfo_has_arm_neon()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_fp16()); + + ASSERT_TRUE(cpuinfo_has_arm_neon_fma()); + + ASSERT_FALSE(cpuinfo_has_arm_neon_dot()); + + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_core(i), cpuinfo_get_processor(i)->core); + } + + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(cpuinfo_vendor_arm, cpuinfo_get_core(i)->vendor); + } + + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + switch (i) { + case 0: + case 1: + case 2: + case 3: + ASSERT_EQ(cpuinfo_uarch_cortex_a73, + cpuinfo_get_core(i)->uarch); + break; + case 4: + case 5: + case 6: + case 7: + ASSERT_EQ(cpuinfo_uarch_cortex_a53, + cpuinfo_get_core(i)->uarch); + break; + } + } + } else { + printf("detect soc: %s ,skip test.\n", cpuinfo_get_package(0)->name); + } +} + +} // namespace test +} // namespace megdnn +#endif +// vim: syntax=cpp.doxygen + diff --git a/dnn/test/x86/cpuinfo.cpp b/dnn/test/x86/cpuinfo.cpp new file mode 100644 index 00000000..2b30e75f --- /dev/null +++ b/dnn/test/x86/cpuinfo.cpp @@ -0,0 +1,47 @@ +/** + * \file dnn/test/x86/cpuinfo.cpp + * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") + * + * Copyright (c) 2014-2020 Megvii Inc. All rights reserved. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + */ +#ifdef MGB_ENABLE_CPUINFO_CHECK +#include +#include +#include "gtest/gtest.h" + +namespace megdnn { +namespace test { + +TEST(X86_RUNTIME, CPUINFO_XEON6130) { + + ASSERT_TRUE(cpuinfo_initialize()); + + int right_cpu = + strcmp(cpuinfo_get_package(0)->name, "Intel Xeon Gold 6130"); + + if (!right_cpu) { + + ASSERT_TRUE(cpuinfo_get_processors()); + + ASSERT_TRUE(cpuinfo_has_x86_avx2()); + + ASSERT_TRUE(cpuinfo_has_x86_avx512f()); + + ASSERT_TRUE(cpuinfo_has_x86_sse4_2()); + + ASSERT_TRUE(cpuinfo_has_x86_avx()); + + } else { + printf("detect cpu: %s ,skip test.\n", cpuinfo_get_package(0)->name); + } +} +} // namespace test +} // namespace megdnn +#endif +// vim: syntax=cpp.doxygen +