program_cache.hpp 5.4 KB

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