1 /*******************************************************************************
2 * Copyright 2018 Intel Corporation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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 *******************************************************************************/
20 #define XBYAK_NO_OP_NAMES
22 #include <cpu/xbyak/xbyak_util.h>
31 #include "mkldnn_thread.hpp"
34 #if defined(MKLDNN_X86_64)
35 #include "xmmintrin.h"
41 int mkldnn_getenv(char *value, const char *name, int length) {
47 value_length = GetEnvironmentVariable(name, value, length);
48 if (value_length >= length) {
49 result = -value_length;
51 last_idx = value_length;
52 result = value_length;
55 char *buffer = getenv(name);
57 value_length = strlen(buffer);
58 if (value_length >= length) {
59 result = -value_length;
61 strncpy(value, buffer, value_length);
62 last_idx = value_length;
63 result = value_length;
68 value[last_idx] = '\0';
72 static bool dump_jit_code;
73 static bool initialized;
75 bool mkldnn_jit_dump() {
78 char env_dump[len] = {0};
80 mkldnn_getenv(env_dump, "MKLDNN_JIT_DUMP", len) == 1
81 && atoi(env_dump) == 1;
87 FILE *mkldnn_fopen(const char *filename, const char *mode) {
90 return fopen_s(&fp, filename, mode) ? NULL : fp;
92 return fopen(filename, mode);
96 thread_local unsigned int mxcsr_save;
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);
103 case round_mode::nearest: mxcsr |= (0u << 13); break;
104 case round_mode::down: mxcsr |= (1u << 13); break;
105 default: assert(!"unreachable");
107 if (mxcsr != mxcsr_save) _mm_setcsr(mxcsr);
113 void restore_rnd_mode() {
114 #if defined(MKLDNN_X86_64)
115 _mm_setcsr(mxcsr_save);
119 void *malloc(size_t size, int alignment) {
123 ptr = _aligned_malloc(size, alignment);
124 int rc = ptr ? 0 : -1;
126 int rc = ::posix_memalign(&ptr, alignment, size);
129 return (rc == 0) ? ptr : 0;
141 int32_t mkldnn_fetch_and_add(int32_t *dst, int32_t val) {
143 return InterlockedExchangeAdd(reinterpret_cast<long*>(dst), val);
145 return __sync_fetch_and_add(dst, val);
149 static Xbyak::util::Cpu cpu_;
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();
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;
167 if (l < cpu_.getDataCacheLevels()) {
168 return cpu_.getDataCacheSize(l)
169 / (per_core ? cpu_.getCoresSharingDataCache(l) : 1);
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;
185 unsigned int mkldnn_get_cache_size(int level, int per_core) {
186 return mkldnn::impl::get_cache_size(level, per_core != 0);