Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / mkl-dnn / src / common / utils.cpp
1 /*******************************************************************************
2 * Copyright 2018 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17 #include <string.h>
18
19 #define XBYAK64
20 #define XBYAK_NO_OP_NAMES
21
22 #include <cpu/xbyak/xbyak_util.h>
23
24 #ifdef _WIN32
25 #include <malloc.h>
26 #include <windows.h>
27 #endif
28
29 #include "mkldnn.h"
30 #include "utils.hpp"
31 #include "mkldnn_thread.hpp"
32 #include "mkldnn.h"
33
34 #if defined(MKLDNN_X86_64)
35 #include "xmmintrin.h"
36 #endif
37
38 namespace mkldnn {
39 namespace impl {
40
41 int mkldnn_getenv(char *value, const char *name, int length) {
42     int result = 0;
43     int last_idx = 0;
44     if (length > 1) {
45         int value_length = 0;
46 #ifdef _WIN32
47         value_length = GetEnvironmentVariable(name, value, length);
48         if (value_length >= length) {
49             result = -value_length;
50         } else {
51             last_idx = value_length;
52             result = value_length;
53         }
54 #else
55         char *buffer = getenv(name);
56         if (buffer != NULL) {
57             value_length = strlen(buffer);
58             if (value_length >= length) {
59                 result = -value_length;
60             } else {
61                 strncpy(value, buffer, value_length);
62                 last_idx = value_length;
63                 result = value_length;
64             }
65         }
66 #endif
67     }
68     value[last_idx] = '\0';
69     return result;
70 }
71
72 static bool dump_jit_code;
73 static bool initialized;
74
75 bool mkldnn_jit_dump() {
76     if (!initialized) {
77         const int len = 2;
78         char env_dump[len] = {0};
79         dump_jit_code =
80             mkldnn_getenv(env_dump, "MKLDNN_JIT_DUMP", len) == 1
81             && atoi(env_dump) == 1;
82         initialized = true;
83     }
84     return dump_jit_code;
85 }
86
87 FILE *mkldnn_fopen(const char *filename, const char *mode) {
88 #ifdef _WIN32
89     FILE *fp = NULL;
90     return fopen_s(&fp, filename, mode) ? NULL : fp;
91 #else
92     return fopen(filename, mode);
93 #endif
94 }
95
96 thread_local unsigned int mxcsr_save;
97
98 void set_rnd_mode(round_mode_t rnd_mode) {
99 #if defined(MKLDNN_X86_64)
100     mxcsr_save = _mm_getcsr();
101     unsigned int mxcsr = mxcsr_save & ~(3u << 13);
102     switch (rnd_mode) {
103     case round_mode::nearest: mxcsr |= (0u << 13); break;
104     case round_mode::down: mxcsr |= (1u << 13); break;
105     default: assert(!"unreachable");
106     }
107     if (mxcsr != mxcsr_save) _mm_setcsr(mxcsr);
108 #else
109     UNUSED(rnd_mode);
110 #endif
111 }
112
113 void restore_rnd_mode() {
114 #if defined(MKLDNN_X86_64)
115     _mm_setcsr(mxcsr_save);
116 #endif
117 }
118
119 void *malloc(size_t size, int alignment) {
120     void *ptr;
121
122 #ifdef _WIN32
123     ptr = _aligned_malloc(size, alignment);
124     int rc = ptr ? 0 : -1;
125 #else
126     int rc = ::posix_memalign(&ptr, alignment, size);
127 #endif
128
129     return (rc == 0) ? ptr : 0;
130 }
131
132 void free(void *p) {
133 #ifdef _WIN32
134     _aligned_free(p);
135 #else
136     ::free(p);
137 #endif
138 }
139
140 // Atomic operations
141 int32_t mkldnn_fetch_and_add(int32_t *dst, int32_t val) {
142 #ifdef _WIN32
143     return InterlockedExchangeAdd(reinterpret_cast<long*>(dst), val);
144 #else
145     return __sync_fetch_and_add(dst, val);
146 #endif
147 }
148
149 static Xbyak::util::Cpu cpu_;
150
151 unsigned int get_cache_size(int level, bool per_core) {
152     unsigned int l = level - 1;
153     // Currently, if XByak is not able to fetch the cache topology
154     // we default to 32KB of L1, 512KB of L2 and 1MB of L3 per core.
155     if (cpu_.getDataCacheLevels() == 0){
156         const int L1_cache_per_core = 32000;
157         const int L2_cache_per_core = 512000;
158         const int L3_cache_per_core = 1024000;
159         int num_cores = per_core ? 1 : mkldnn_get_max_threads();
160         switch(l){
161             case(0): return L1_cache_per_core * num_cores;
162             case(1): return L2_cache_per_core * num_cores;
163             case(2): return L3_cache_per_core * num_cores;
164             default: return 0;
165         }
166     }
167     if (l < cpu_.getDataCacheLevels()) {
168         return cpu_.getDataCacheSize(l)
169                / (per_core ? cpu_.getCoresSharingDataCache(l) : 1);
170     } else
171         return 0;
172 }
173
174 }
175 }
176
177 mkldnn_status_t mkldnn_set_jit_dump(int dump) {
178     using namespace mkldnn::impl::status;
179     if (dump < 0) return invalid_arguments;
180     mkldnn::impl::dump_jit_code = dump;
181     mkldnn::impl::initialized = true;
182     return success;
183 }
184
185 unsigned int mkldnn_get_cache_size(int level, int per_core) {
186     return mkldnn::impl::get_cache_size(level, per_core != 0);
187 }