• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/core/platform/cpu_feature_guard.h"
17 
18 #include <mutex>
19 #include <string>
20 
21 #include "tensorflow/core/platform/byte_order.h"
22 #include "tensorflow/core/platform/cpu_info.h"
23 #include "tensorflow/core/platform/logging.h"
24 
25 namespace tensorflow {
26 namespace port {
27 namespace {
28 
29 // If the CPU feature isn't present, log a fatal error.
CheckFeatureOrDie(CPUFeature feature,const string & feature_name)30 void CheckFeatureOrDie(CPUFeature feature, const string& feature_name) {
31   if (!TestCPUFeature(feature)) {
32 #ifdef __ANDROID__
33     // Some Android emulators seem to indicate they don't support SSE, so to
34     // avoid crashes when testing, switch this to a warning.
35     LOG(WARNING)
36 #else
37     LOG(FATAL)
38 #endif
39         << "The TensorFlow library was compiled to use " << feature_name
40         << " instructions, but these aren't available on your machine.";
41   }
42 }
43 
44 // Check if CPU feature is included in the TensorFlow binary.
CheckIfFeatureUnused(CPUFeature feature,const string & feature_name,string & missing_instructions)45 void CheckIfFeatureUnused(CPUFeature feature, const string& feature_name,
46                           string& missing_instructions) {
47   if (TestCPUFeature(feature)) {
48     missing_instructions.append(" ");
49     missing_instructions.append(feature_name);
50   }
51 }
52 
53 // Raises an error if the binary has been compiled for a CPU feature (like AVX)
54 // that isn't available on the current machine. It also warns of performance
55 // loss if there's a feature available that's not being used.
56 // Depending on the compiler and initialization order, a SIGILL exception may
57 // occur before this code is reached, but this at least offers a chance to give
58 // a more meaningful error message.
59 class CPUFeatureGuard {
60  public:
CPUFeatureGuard()61   CPUFeatureGuard() {
62 #ifdef __SSE__
63     CheckFeatureOrDie(CPUFeature::SSE, "SSE");
64 #endif  // __SSE__
65 #ifdef __SSE2__
66     CheckFeatureOrDie(CPUFeature::SSE2, "SSE2");
67 #endif  // __SSE2__
68 #ifdef __SSE3__
69     CheckFeatureOrDie(CPUFeature::SSE3, "SSE3");
70 #endif  // __SSE3__
71 #ifdef __SSE4_1__
72     CheckFeatureOrDie(CPUFeature::SSE4_1, "SSE4.1");
73 #endif  // __SSE4_1__
74 #ifdef __SSE4_2__
75     CheckFeatureOrDie(CPUFeature::SSE4_2, "SSE4.2");
76 #endif  // __SSE4_2__
77 #ifdef __AVX__
78     CheckFeatureOrDie(CPUFeature::AVX, "AVX");
79 #endif  // __AVX__
80 #ifdef __AVX2__
81     CheckFeatureOrDie(CPUFeature::AVX2, "AVX2");
82 #endif  // __AVX2__
83 #ifdef __AVX512F__
84     CheckFeatureOrDie(CPUFeature::AVX512F, "AVX512F");
85 #endif  // __AVX512F__
86 #ifdef __FMA__
87     CheckFeatureOrDie(CPUFeature::FMA, "FMA");
88 #endif  // __FMA__
89   }
90 };
91 
92 CPUFeatureGuard g_cpu_feature_guard_singleton;
93 
94 std::once_flag g_cpu_feature_guard_warn_once_flag;
95 
96 }  // namespace
97 
InfoAboutUnusedCPUFeatures()98 void InfoAboutUnusedCPUFeatures() {
99   std::call_once(g_cpu_feature_guard_warn_once_flag, [] {
100     string missing_instructions;
101 #if defined(_MSC_VER) && !defined(__clang__)
102 
103 #ifndef __AVX__
104     CheckIfFeatureUnused(CPUFeature::AVX, "AVX", missing_instructions);
105 #endif  // __AVX__
106 #ifndef __AVX2__
107     CheckIfFeatureUnused(CPUFeature::AVX2, "AVX2", missing_instructions);
108 #endif  // __AVX2__
109 
110 #else  // if defined(_MSC_VER) && !defined(__clang__)
111 
112 #ifndef __SSE__
113     CheckIfFeatureUnused(CPUFeature::SSE, "SSE", missing_instructions);
114 #endif  // __SSE__
115 #ifndef __SSE2__
116     CheckIfFeatureUnused(CPUFeature::SSE2, "SSE2", missing_instructions);
117 #endif  // __SSE2__
118 #ifndef __SSE3__
119     CheckIfFeatureUnused(CPUFeature::SSE3, "SSE3", missing_instructions);
120 #endif  // __SSE3__
121 #ifndef __SSE4_1__
122     CheckIfFeatureUnused(CPUFeature::SSE4_1, "SSE4.1", missing_instructions);
123 #endif  // __SSE4_1__
124 #ifndef __SSE4_2__
125     CheckIfFeatureUnused(CPUFeature::SSE4_2, "SSE4.2", missing_instructions);
126 #endif  // __SSE4_2__
127 #ifndef __AVX__
128     CheckIfFeatureUnused(CPUFeature::AVX, "AVX", missing_instructions);
129 #endif  // __AVX__
130 #ifndef __AVX2__
131     CheckIfFeatureUnused(CPUFeature::AVX2, "AVX2", missing_instructions);
132 #endif  // __AVX2__
133 #ifndef __AVX512F__
134     CheckIfFeatureUnused(CPUFeature::AVX512F, "AVX512F", missing_instructions);
135 #endif  // __AVX512F__
136 #ifndef __FMA__
137     CheckIfFeatureUnused(CPUFeature::FMA, "FMA", missing_instructions);
138 #endif  // __FMA__
139 #endif  // else of if defined(_MSC_VER) && !defined(__clang__)
140     if (!missing_instructions.empty()) {
141 #ifndef INTEL_MKL
142       LOG(INFO) << "Your CPU supports instructions that this TensorFlow "
143                 << "binary was not compiled to use:" << missing_instructions;
144 #else
145       LOG(INFO) << "This TensorFlow binary is optimized with Intel(R) MKL-DNN "
146                 << "to use the following CPU instructions in performance "
147                 << "critical operations: " << missing_instructions << std::endl
148                 << "To enable them in non-MKL-DNN operations, rebuild "
149                 << "TensorFlow with the appropriate compiler flags.";
150 #endif
151     }
152   });
153 }
154 
155 }  // namespace port
156 }  // namespace tensorflow
157