I have about 18 million elements in an array that are initialized and ready to be used by a simple manager called ElementManager
(this number will later climb to a little more than a billion in later iterations of the program). A class, A
, which must use the elements communicates with ElementManager
that returns the next available element for consumption. That element is now in use and cannot be reused until recycled, which may happen often. Class A
is concurrent, that is, it can ask ElementManager
for an available element in several threads. The elements in this case is an object that stores three vertices to make a triangle.
Currently, the ElementManager
is using Intel TBB concurrent_bounded_queue called mAllAvailableElements
. There is also another container (a TBB concurrent_vector) that contains all elements, regardless of whether they are available for use or not, called mAllElements
. Class A
asks for the next available element, the manager tries to pop the next available element from the queue. The popped element is now in use.
Now when class A
has done what it has to do, control is handed to class B
which now has to iterate through all elements that are in use
and create meshes (to take advantage of concurrency, the array is split into several smaller arrays to create submeshes which scales with the number of available threads - the reason for this is that creating a mesh must be done serially). For this I am currently iterating over the container mAllElements
(this is also concurrent) and grabbing any element that is in use. The elements, as mentioned above, contain polygonal information to create meshes. Iteration in this case takes a long time as it has to check each element and query whether it is in use or not, because if it is not in use then it should not be part of a mesh.
Now imagine if only 1 million out of the possible 18 million elements were in use (but more than 5-6 million were recycled). Worse yet, due to constant updates to only part of the mesh (which happens concurrently) means the in use elements are fragmented throughout the mAllElements
container.
I thought about this for quite some time now and one flawed solution that I came up with was to create another queue of elements named mElementsInUse
, which is also a concurrent_queue
. I can push any element that is now in use. Problem with this approach is that since it is a queue, any element in that queue can be recycled at any time (an update in a part of the mesh) and declared not in use and since I can only pop开发者_运维知识库 the front element, this approach fails. The only other approach I can think of is to defragment the concurrent_vector mAllElements
every once in a while when no operations are taking place.
I think my approach to this problem is wrong and thus my post here. I hope I explained the problem in enough detail. It seems like a common memory management problem, but I cannot come up with any search terms to search for it.
How about using a bit vector to indicate which of your elements are in use? It's easy to partition it for parallel processing when building your full mesh, and you can use atomic operations on words in the vector and thus avoid locks.
精彩评论