1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 // From Apache Impala (incubating) as of 2016-01-29. Pared down to a minimal 19 // set of functions needed for Apache Arrow / Apache parquet-cpp 20 21 #pragma once 22 23 #include <cstdint> 24 #include <string> 25 26 #include "arrow/util/visibility.h" 27 28 namespace arrow { 29 namespace internal { 30 31 /// CpuInfo is an interface to query for cpu information at runtime. The caller can 32 /// ask for the sizes of the caches and what hardware features are supported. 33 /// On Linux, this information is pulled from a couple of sys files (/proc/cpuinfo and 34 /// /sys/devices) 35 class ARROW_EXPORT CpuInfo { 36 public: 37 static constexpr int64_t SSSE3 = (1 << 1); 38 static constexpr int64_t SSE4_1 = (1 << 2); 39 static constexpr int64_t SSE4_2 = (1 << 3); 40 static constexpr int64_t POPCNT = (1 << 4); 41 static constexpr int64_t ASIMD = (1 << 5); 42 static constexpr int64_t AVX = (1 << 6); 43 static constexpr int64_t AVX2 = (1 << 7); 44 static constexpr int64_t AVX512F = (1 << 8); 45 static constexpr int64_t AVX512CD = (1 << 9); 46 static constexpr int64_t AVX512VL = (1 << 10); 47 static constexpr int64_t AVX512DQ = (1 << 11); 48 static constexpr int64_t AVX512BW = (1 << 12); 49 static constexpr int64_t BMI1 = (1 << 13); 50 static constexpr int64_t BMI2 = (1 << 14); 51 52 /// Typical AVX512 subsets consists of AVX512F,AVX512BW,AVX512VL,AVX512CD,AVX512DQ 53 static constexpr int64_t AVX512 = AVX512F | AVX512CD | AVX512VL | AVX512DQ | AVX512BW; 54 55 /// Cache enums for L1 (data), L2 and L3 56 enum CacheLevel { 57 L1_CACHE = 0, 58 L2_CACHE = 1, 59 L3_CACHE = 2, 60 }; 61 62 enum class Vendor : int { Unknown = 0, Intel, AMD }; 63 64 static CpuInfo* GetInstance(); 65 66 /// Determine if the CPU meets the minimum CPU requirements and if not, issue an error 67 /// and terminate. 68 void VerifyCpuRequirements(); 69 70 /// Returns all the flags for this cpu 71 int64_t hardware_flags(); 72 73 /// \brief Returns whether or not the given feature is enabled. 74 /// 75 /// IsSupported() is true iff IsDetected() is also true and the feature 76 /// wasn't disabled by the user (for example by setting the ARROW_USER_SIMD_LEVEL 77 /// environment variable). IsSupported(int64_t flags)78 bool IsSupported(int64_t flags) const { return (hardware_flags_ & flags) == flags; } 79 80 /// Returns whether or not the given feature is available on the CPU. IsDetected(int64_t flags)81 bool IsDetected(int64_t flags) const { 82 return (original_hardware_flags_ & flags) == flags; 83 } 84 85 /// \brief The processor supports SSE4.2 and the Arrow libraries are built 86 /// with support for it 87 bool CanUseSSE4_2() const; 88 89 /// Toggle a hardware feature on and off. It is not valid to turn on a feature 90 /// that the underlying hardware cannot support. This is useful for testing. 91 void EnableFeature(int64_t flag, bool enable); 92 93 /// Returns the size of the cache in KB at this cache level 94 int64_t CacheSize(CacheLevel level); 95 96 /// Returns the number of cpu cycles per millisecond 97 int64_t cycles_per_ms(); 98 99 /// Returns the number of cores (including hyper-threaded) on this machine. 100 int num_cores(); 101 102 /// Returns the model name of the cpu (e.g. Intel i7-2600) 103 std::string model_name(); 104 105 /// Returns the vendor of the cpu. vendor()106 Vendor vendor() const { return vendor_; } 107 HasEfficientBmi2()108 bool HasEfficientBmi2() const { 109 // BMI2 (pext, pdep) is only efficient on Intel X86 processors. 110 return vendor() == Vendor::Intel && IsSupported(BMI2); 111 } 112 113 private: 114 CpuInfo(); 115 116 enum UserSimdLevel { 117 USER_SIMD_NONE = 0, 118 USER_SIMD_SSE4_2, 119 USER_SIMD_AVX, 120 USER_SIMD_AVX2, 121 USER_SIMD_AVX512, 122 USER_SIMD_MAX, 123 }; 124 125 void Init(); 126 127 /// Inits CPU cache size variables with default values 128 void SetDefaultCacheSize(); 129 130 /// Parse the SIMD level by ARROW_USER_SIMD_LEVEL env 131 void ParseUserSimdLevel(); 132 133 int64_t hardware_flags_; 134 int64_t original_hardware_flags_; 135 int64_t cache_sizes_[L3_CACHE + 1]; 136 int64_t cycles_per_ms_; 137 int num_cores_; 138 std::string model_name_; 139 Vendor vendor_; 140 }; 141 142 } // namespace internal 143 } // namespace arrow 144