OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CodeCacheAccessor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
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 
19 
20 template <typename CompilationContext>
22  const CodeCacheKey& key) {
23  std::lock_guard<std::mutex> lock(code_cache_mutex_);
24  get_count_++;
25  auto it = code_cache_.find(key);
26  if (it != code_cache_.cend()) {
27  found_count_++;
28  VLOG(1) << name_ << ": Reuse cached compiled kernel";
29  return it->second;
30  }
31  return {};
32 }
33 
34 template <typename CompilationContext>
37  bool warn = false;
38  {
39  std::lock_guard<std::mutex> lock(code_cache_mutex_);
40  // if key is in cache, put is no-op
41  auto it = code_cache_.find(key);
42  put_count_++;
43  if (it == code_cache_.cend()) {
44  VLOG(1) << name_ << ": Add compiled kernel to code cache";
45  evict_count_ += code_cache_.put(key, value);
46  } else {
47  ignore_count_++;
48  warn = true;
49  }
50  }
51  if (warn) {
52  LOG(WARNING) << *this << ": code already in cache, ignoring.\n";
53  return false;
54  }
55  return true;
56 }
57 
58 template <typename CompilationContext>
60  const CodeCacheKey& key) {
61  std::unique_lock<std::mutex> lk(code_cache_mutex_);
62  get_count_++;
63  if (auto* cached_code = code_cache_.get(key)) {
64  if (!cached_code->get()) {
65  // Wait until the compiling thread puts code to cache. TODO:
66  // this wait also locks other unrelated get_or_wait calls on
67  // different keys. This is suboptimal as it will block also
68  // independent get_or_wait(other_key) calls. To fix this (it
69  // likely also requires using ORCJIT to enable concurrent
70  // compilations), we'll need a key specific mutex or use some
71  // other approach that would allow threads with other keys to
72  // proceed.
73  compilation_cv_.wait(lk, [=] { return cached_code->get(); });
74  // Don't ignore spurious awakenings as the support for such
75  // events has not been implemented:
76  CHECK(cached_code->get());
77  }
78  found_count_++;
79  VLOG(1) << name_ << ": Reuse a cached compiled code";
80  return cached_code;
81  }
82  // This is the first time the key is used to acquire code from
83  // cache. Put null value to cache so that other threads acquiring
84  // the same key will wait (see above) until the code is put to the
85  // cache:
86  CodeCacheVal<CompilationContext> not_a_code(nullptr);
87  evict_count_ += code_cache_.put(key, std::move(not_a_code));
88  // returning nullptr will notify caller to trigger code compilation
89  // for the given key:
90  return nullptr;
91 }
92 
93 template <typename CompilationContext>
95  const CodeCacheKey& key,
97  std::lock_guard<std::mutex> lock(code_cache_mutex_);
98  auto result = code_cache_.get(key);
99  CHECK(result); // get_or_wait has put not_a_code to code cache
100  CHECK(!result->get()); // ensure that result really contains not_a_code per get_or_wait
101  *result = std::move(value); // set actual code
102  compilation_cv_.notify_all(); // notify waiting get_or_wait(..) calls
103 }
104 
105 template <typename CompilationContext>
107  std::lock_guard<std::mutex> lock(code_cache_mutex_);
108  code_cache_.erase(key);
109  compilation_cv_.notify_all(); // notify waiting get_or_wait(..) calls
110 }
111 
112 template <typename CompilationContext>
114  std::lock_guard<std::mutex> lock(code_cache_mutex_);
115  code_cache_.clear();
116 }
117 
std::shared_ptr< CC > CodeCacheVal
Definition: CodeCache.h:26
CodeCacheVal< CompilationContext > get_value(const CodeCacheKey &key)
#define LOG(tag)
Definition: Logger.h:285
std::vector< std::string > CodeCacheKey
Definition: CodeCache.h:24
bool put(const CodeCacheKey &key, CodeCacheVal< CompilationContext > &value)
void reset(const CodeCacheKey &key, CodeCacheVal< CompilationContext > value)
#define CHECK(condition)
Definition: Logger.h:291
CodeCacheVal< CompilationContext > * get_or_wait(const CodeCacheKey &key)
#define VLOG(n)
Definition: Logger.h:388
void erase(const CodeCacheKey &key)