![]() |
GemaCoreLib
The GeMA Core library
|
An implementation of the GmAppendBuffer interface based on a "per thread" growing buffer. More...
#include <gmAppendBuffer.h>
Public Member Functions | |
GmPerThreadAppendBuffer (size_t initSize, double resizeFactor=2.0, int numThreads=-1) | |
Buffer constructor. Can optionally pre allocate the buffer with initSize entries. If initSize is zero, a call to reserve() MUST be made before any append. More... | |
~GmPerThreadAppendBuffer () | |
Destructor. | |
virtual void | clear () |
virtual void | reserve (size_t bsize) |
Pre allocates buffer sizes. See basic description on the base class Should not be called if the size was given in the constructor. More... | |
virtual void | append (const T &val) |
virtual void | appendFromThread (int tid, const T &val) |
virtual size_t | size () const |
virtual T * | data () |
virtual size_t | usedMemory () const |
Protected Attributes | |
GmTLS< QVarLengthArray< T >, false > | _data |
Per thread buffers. | |
bool | _globalOnly |
Flag set to true if the user passed zero as the number of threads for the constructor. | |
int | _nt |
Number of threads considered for buffer pre-allocation & parallel memcopy. | |
T * | _dataBuffer |
The single buffer after a call to data() | |
size_t | _dataSize |
The size in _dataBuffer when _dataBuffer is not NULL. | |
An implementation of the GmAppendBuffer interface based on a "per thread" growing buffer.
This class uses a TLS strategy for providing a per thread buffer implemented by a QVarLengthArray. Tests show that an implementation with std::vector can be up to 25% slower!!! The drawback is that QVarLengthArray uses an int for control and so can overflow with a large number of appends (but that is not so bad since the global buffer size is splitted between threads). TODO: implement a variable
growing buffer with a size_t controll.
The global initial buffer size needs to be informed either in the constructor or by a call to reserve(). The requested size will be splitted equaly among the number of threads informed in the object constructor (defaulting to the maximum number of threads configured in the thread manager). If the number of threads is zero, only the "local buffer" will be pre allocated with the full requested size (the locall buffer is not allocated at all if the number of threads is greater than zero).
Calling data() will either return the internal vector if there are no threads and only the local buffer was used, or will allocate a new vector and fill it with the per thread data. In that case, thread vectors will be merged one after the other with no guaranteed ordering among the appends.
This calss is in general very efficient but can be a problem in constrained memory scenarios due to the buffer growing algorithm and by the need to allocate a new buffer to consolidate per thread data when data() is called.
OBS: This class inherits from a template parameter Base, defaulted to GmAppendBuffer, in order to make it easy for changing the base class to another one that inherits GmAppendBuffer adding additional methods, as is done in the GmSparseMatrixTripletBuffer class.
|
inline |
Buffer constructor. Can optionally pre allocate the buffer with initSize entries. If initSize is zero, a call to reserve() MUST be made before any append.
The initSize value represents the total number of expected append() calls in all threads combined. Each thread buffer will be pre-allocated with the given size divided by the number of thread buffers.
The number of threads defaults to the maximum number of threads as seen by the thread manager (when numThreads is -1), but can be given by the numThreads parameter.
Keep in mind that the given parameter does NOT affects the number of buffers in the thread local storage. This will always be equal to the maximum number of threads as seen by the thread manager. It will affect only the number of buffers that will have a pre-allocated size.
If the number of threads is 0, only the Local buffer will be preallocated (with initSize). Otherwise, the first numThread buffers will be pre-allocated (with size equal to initSize / numThreads).
|
inlinevirtual |
Pre allocates buffer sizes. See basic description on the base class Should not be called if the size was given in the constructor.
The given size will be splitted by the number of threads as explained on the class constructor description.