liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//---------------------------------------------------------------------------//
// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://boostorg.github.com/compute for more information.
//---------------------------------------------------------------------------//
 
#ifndef BOOST_COMPUTE_UTILITY_PROGRAM_CACHE_HPP
#define BOOST_COMPUTE_UTILITY_PROGRAM_CACHE_HPP
 
#include <string>
#include <utility>
 
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp>
 
#include <boost/compute/context.hpp>
#include <boost/compute/program.hpp>
#include <boost/compute/detail/lru_cache.hpp>
#include <boost/compute/detail/global_static.hpp>
 
namespace boost {
namespace compute {
 
/// The program_cache class stores \ref program objects in a LRU cache.
///
/// This class can be used to help mitigate the overhead of OpenCL's run-time
/// kernel compilation model. Commonly used programs can be stored persistently
/// in the cache and only compiled once on their first use.
///
/// Program objects are stored and retreived based on a user-defined cache key
/// along with the options used to build the program (if any).
///
/// For example, to insert a program into the cache:
/// \code
/// cache.insert("foo", foo_program);
/// \endcode
///
/// And to retreive the program later:
/// \code
/// boost::optional<program> p = cache.get("foo");
/// if(p){
///     // program found in cache
/// }
/// \endcode
///
/// \see program
class program_cache : boost::noncopyable
{
public:
    /// Creates a new program cache with space for \p capacity number of
    /// program objects.
    program_cache(size_t capacity)
        : m_cache(capacity)
    {
    }
 
    /// Destroys the program cache.
    ~program_cache()
    {
    }
 
    /// Returns the number of program objects currently stored in the cache.
    size_t size() const
    {
        return m_cache.size();
    }
 
    /// Returns the total capacity of the cache.
    size_t capacity() const
    {
        return m_cache.capacity();
    }
 
    /// Clears the program cache.
    void clear()
    {
        m_cache.clear();
    }
 
    /// Returns the program object with \p key. Returns a null optional if no
    /// program with \p key exists in the cache.
    boost::optional<program> get(const std::string &key)
    {
        return m_cache.get(std::make_pair(key, std::string()));
    }
 
    /// Returns the program object with \p key and \p options. Returns a null
    /// optional if no program with \p key and \p options exists in the cache.
    boost::optional<program> get(const std::string &key, const std::string &options)
    {
        return m_cache.get(std::make_pair(key, options));
    }
 
    /// Inserts \p program into the cache with \p key.
    void insert(const std::string &key, const program &program)
    {
        insert(key, std::string(), program);
    }
 
    /// Inserts \p program into the cache with \p key and \p options.
    void insert(const std::string &key, const std::string &options, const program &program)
    {
        m_cache.insert(std::make_pair(key, options), program);
    }
 
    /// Loads the program with \p key from the cache if it exists. Otherwise
    /// builds a new program with \p source and \p options, stores it in the
    /// cache, and returns it.
    ///
    /// This is a convenience function to simplify the common pattern of
    /// attempting to load a program from the cache and, if not present,
    /// building the program from source and storing it in the cache.
    ///
    /// Equivalent to:
    /// \code
    /// boost::optional<program> p = get(key, options);
    /// if(!p){
    ///     p = program::create_with_source(source, context);
    ///     p->build(options);
    ///     insert(key, options, *p);
    /// }
    /// return *p;
    /// \endcode
    program get_or_build(const std::string &key,
                         const std::string &options,
                         const std::string &source,
                         const context &context)
    {
        boost::optional<program> p = get(key, options);
        if(!p){
            p = program::build_with_source(source, context, options);
 
            insert(key, options, *p);
        }
        return *p;
    }
 
    /// Returns the global program cache for \p context.
    ///
    /// This global cache is used internally by Boost.Compute to store compiled
    /// program objects used by its algorithms. All Boost.Compute programs are
    /// stored with a cache key beginning with \c "__boost". User programs
    /// should avoid using the same prefix in order to prevent collisions.
    static boost::shared_ptr<program_cache> get_global_cache(const context &context)
    {
        typedef detail::lru_cache<cl_context, boost::shared_ptr<program_cache> > cache_map;
 
        BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(cache_map, caches, (8));
 
        boost::optional<boost::shared_ptr<program_cache> > cache = caches.get(context.get());
        if(!cache){
            cache = boost::make_shared<program_cache>(64);
 
            caches.insert(context.get(), *cache);
        }
 
        return *cache;
    }
 
private:
    detail::lru_cache<std::pair<std::string, std::string>, program> m_cache;
};
 
} // end compute namespace
} // end boost namespace
 
#endif // BOOST_COMPUTE_UTILITY_PROGRAM_CACHE_HPP