1 /*
2  *  Copyright 2018 NVIDIA 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 /*! \file pool_options.h
18  *  \brief \p pool_options is a type used by the pooling resource adaptors to fine-tune their behavior.
19  */
20 
21 #pragma once
22 
23 #include <cstddef>
24 
25 #include <thrust/detail/integer_math.h>
26 
27 #include <thrust/mr/detail/config.h>
28 
29 namespace thrust
30 {
31 namespace mr
32 {
33 
34 /*! \addtogroup memory_management Memory Management
35  *  \ingroup memory_management
36  *  \{
37  */
38 
39 /*! A type used for configuring pooling resource adaptors, to fine-tune their behavior and parameters.
40  */
41 struct pool_options
42 {
43     /*! The minimal number of blocks, i.e. pieces of memory handed off to the user from a pool of a given size, in a single
44      *      chunk allocated from upstream.
45      */
46     std::size_t min_blocks_per_chunk;
47     /*! The minimal number of bytes in a single chunk allocated from upstream.
48      */
49     std::size_t min_bytes_per_chunk;
50     /*! The maximal number of blocks, i.e. pieces of memory handed off to the user from a pool of a given size, in a single
51      *      chunk allocated from upstream.
52      */
53     std::size_t max_blocks_per_chunk;
54     /*! The maximal number of bytes in a single chunk allocated from upstream.
55      */
56     std::size_t max_bytes_per_chunk;
57 
58     /*! The size of blocks in the smallest pool covered by the pool resource. All allocation requests below this size will
59      *      be rounded up to this size.
60      */
61     std::size_t smallest_block_size;
62     /*! The size of blocks in the largest pool covered by the pool resource. All allocation requests above this size will
63      *      be considered oversized, allocated directly from upstream (and not from a pool), and cached only of \p cache_oversized
64      *      is true.
65      */
66     std::size_t largest_block_size;
67 
68     /*! The alignment of all blocks in internal pools of the pool resource. All allocation requests above this alignment
69      *      will be considered oversized, allocated directly from upstream (and not from a pool), and cached only of
70      *      \p cache_oversized is true.
71      */
72     std::size_t alignment;
73 
74     /*! Decides whether oversized and overaligned blocks are cached for later use, or immediately return it to the upstream
75      *      resource.
76      */
77     bool cache_oversized;
78 
79     /*! The size factor at which a cached allocation is considered too ridiculously oversized to use to fulfill an allocation
80      *      request. For instance: the user requests an allocation of size 1024 bytes. A block of size 32 * 1024 bytes is
81      *      cached. If \p cached_size_cutoff_factor is 32 or less, this block will be considered too big for that allocation
82      *      request.
83      */
84     std::size_t cached_size_cutoff_factor;
85     /*! The alignment factor at which a cached allocation is considered too ridiculously overaligned to use to fulfill an
86      *      allocation request. For instance: the user requests an allocation aligned to 32 bytes. A block aligned to 1024 bytes
87      *      is cached. If \p cached_size_cutoff_factor is 32 or less, this block will be considered too overaligned for that
88      *      allocation request.
89      */
90     std::size_t cached_alignment_cutoff_factor;
91 
92     /*! Checks if the options are self-consistent.
93      *
94      *  /returns true if the options are self-consitent, false otherwise.
95      */
validatepool_options96     bool validate() const
97     {
98         if (!detail::is_power_of_2(smallest_block_size)) return false;
99         if (!detail::is_power_of_2(largest_block_size)) return false;
100         if (!detail::is_power_of_2(alignment)) return false;
101 
102         if (max_bytes_per_chunk == 0 || max_blocks_per_chunk == 0) return false;
103         if (smallest_block_size == 0 || largest_block_size == 0) return false;
104 
105         if (min_blocks_per_chunk > max_blocks_per_chunk) return false;
106         if (min_bytes_per_chunk > max_bytes_per_chunk) return false;
107 
108         if (smallest_block_size > largest_block_size) return false;
109 
110         if (min_blocks_per_chunk * smallest_block_size > max_bytes_per_chunk) return false;
111         if (min_blocks_per_chunk * largest_block_size > max_bytes_per_chunk) return false;
112 
113         if (max_blocks_per_chunk * largest_block_size < min_bytes_per_chunk) return false;
114         if (max_blocks_per_chunk * smallest_block_size < min_bytes_per_chunk) return false;
115 
116         if (alignment > smallest_block_size) return false;
117 
118         return true;
119     }
120 };
121 
122 /*! \}
123  */
124 
125 } // end mr
126 } // end thrust
127 
128