aboutsummaryrefslogtreecommitdiff
path: root/src/core/NEON/kernels/arm_gemm/buffer_manager.hpp
diff options
context:
space:
mode:
authorAnthony Barbier <anthony.barbier@arm.com>2018-07-03 16:22:02 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:54:10 +0000
commit5f707736413aeac77818c42838296966f8dc6761 (patch)
treeb829ed3243ea5f3085f288836132416c78bc2e72 /src/core/NEON/kernels/arm_gemm/buffer_manager.hpp
parent7485d5a62685cb745ab50e970adb722cb71557ac (diff)
downloadComputeLibrary-5f707736413aeac77818c42838296966f8dc6761.tar.gz
COMPMID-1369: Revert accidental formatting of RSH's repo
Pulled latest fixes from David's repo: commit f43ebe932c84083332b0b1a0348241b69dda63a7 Author: David Mansell <David.Mansell@arm.com> Date: Tue Jul 3 18:09:01 2018 +0100 Whitespace tidying, fixed comment in gemv_batched imported from ACL. Change-Id: Ie37a623f44e90d88072236cb853ac55ac82d5f51 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/138530 Tested-by: Jenkins <bsgcomp@arm.com> Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com> Reviewed-by: Gian Marco Iodice <gianmarco.iodice@arm.com> Reviewed-by: David Mansell <david.mansell@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
Diffstat (limited to 'src/core/NEON/kernels/arm_gemm/buffer_manager.hpp')
-rw-r--r--src/core/NEON/kernels/arm_gemm/buffer_manager.hpp198
1 files changed, 75 insertions, 123 deletions
diff --git a/src/core/NEON/kernels/arm_gemm/buffer_manager.hpp b/src/core/NEON/kernels/arm_gemm/buffer_manager.hpp
index dd74744ebc..03f099d57b 100644
--- a/src/core/NEON/kernels/arm_gemm/buffer_manager.hpp
+++ b/src/core/NEON/kernels/arm_gemm/buffer_manager.hpp
@@ -38,36 +38,33 @@
#endif
-namespace arm_gemm
-{
+namespace arm_gemm {
+
#ifndef NO_MULTI_THREADING
-enum class BufferStatus
-{
+enum class BufferStatus {
IDLE,
POPULATING,
BUSY
};
-class Buffer
-{
+class Buffer {
private:
- const int _maxusers; // Maximum permissible threads.
- void *const _storage; // Storage for buffer content.
+ const int _maxusers; // Maximum permissible threads.
+ void * const _storage; // Storage for buffer content.
- int _numusers; // Actual number of threads (might be lower).
+ int _numusers; // Actual number of threads (might be lower).
- volatile BufferStatus _status = BufferStatus::IDLE; // Status
- std::atomic_int _users = {}; // How many users are still using the buffer.
- volatile int _index = 0; // Which block of data currently resides in the buffer.
+ volatile BufferStatus _status = BufferStatus::IDLE; // Status
+ std::atomic_int _users = { }; // How many users are still using the buffer.
+ volatile int _index = 0; // Which block of data currently resides in the buffer.
- std::mutex _lock = {};
+ std::mutex _lock = { };
#ifdef USE_SEMAPHORE
- std::condition_variable _cv = {};
+ std::condition_variable _cv = { };
#endif
template <typename T>
- void populate_buffer(T func)
- {
+ void populate_buffer(T func) {
func(_storage);
/* Now mark it as ready. */
@@ -78,17 +75,15 @@ private:
_cv.notify_all();
}
#else
- _status = BufferStatus::BUSY;
+ _status = BufferStatus::BUSY;
#endif
}
public:
Buffer(Buffer &) = delete;
- Buffer &operator=(Buffer &) = delete;
+ Buffer &operator= (Buffer &) = delete;
- Buffer(void *storage, int maxusers)
- : _maxusers(maxusers), _storage(storage), _numusers(maxusers)
- {
+ Buffer(void *storage, int maxusers) : _maxusers(maxusers), _storage(storage), _numusers(maxusers) {
_status = BufferStatus::IDLE;
}
@@ -99,38 +94,32 @@ public:
* If it's already being populated by another thread or is ready, return.
*/
template <typename T>
- void try_populate(const int index, T func)
- {
- for(;;)
- {
+ void try_populate(const int index, T func) {
+ for (;;) {
#ifdef USE_SEMAPHORE
/* If it's busy with a previous index, wait on the semaphore. */
- if((_status == BufferStatus::BUSY) && (_index != index))
- {
+ if ((_status == BufferStatus::BUSY) && (_index != index)) {
std::unique_lock<std::mutex> ul(_lock);
- if((_status == BufferStatus::BUSY) && (_index != index))
- {
+ if ((_status == BufferStatus::BUSY) && (_index != index)) {
_cv.wait(ul);
}
}
#endif
/* Return if another thread is populating it already. */
- if((_index == index) && ((_status == BufferStatus::POPULATING) || (_status == BufferStatus::BUSY)))
- {
+ if ((_index == index) &&
+ ((_status == BufferStatus::POPULATING) || (_status == BufferStatus::BUSY))) {
return;
}
- if(_status == BufferStatus::IDLE)
- {
+ if (_status == BufferStatus::IDLE) {
std::lock_guard<std::mutex> guard(_lock);
/* If the buffer is still idle, we can grab it and populate it. */
- if(_status == BufferStatus::IDLE)
- {
+ if (_status == BufferStatus::IDLE) {
_status = BufferStatus::POPULATING;
- _index = index;
- _users = _numusers;
+ _index = index;
+ _users = _numusers;
break;
}
}
@@ -141,26 +130,26 @@ public:
}
template <typename T>
- void *get(const int index, T func)
- {
+ void *get(const int index, T func) {
// Loop until we achieve something.
- for(;;)
- {
+ for (;;) {
// If the index is correct and the buffer status is busy then we can
// just return the content. No locking is needed here as the index
// cannot change (and status cannot change from BUSY) until all
// users have finished.
- if((_index == index) && (_status == BufferStatus::BUSY))
- {
+ if ((_index == index) && (_status == BufferStatus::BUSY)) {
return _storage;
}
+
+ /* If the buffer still has some previous content, or is being
+ * populated, we can wait with the semaphore. */
#ifdef USE_SEMAPHORE
- if(((_status == BufferStatus::BUSY) && (_index != index)) || (_status == BufferStatus::POPULATING))
- {
+ if (((_status == BufferStatus::BUSY) && (_index != index)) ||
+ (_status == BufferStatus::POPULATING)) {
std::unique_lock<std::mutex> ul(_lock);
- if(((_status == BufferStatus::BUSY) && (_index != index)) || (_status == BufferStatus::POPULATING))
- {
+ if (((_status == BufferStatus::BUSY) && (_index != index)) ||
+ (_status == BufferStatus::POPULATING)) {
_cv.wait(ul);
}
}
@@ -168,17 +157,15 @@ public:
// If it's idle, we need to populate it. The IDLE->POPULATING
// transition requires the lock.
- if(_status == BufferStatus::IDLE)
- {
+ if (_status == BufferStatus::IDLE) {
std::lock_guard<std::mutex> guard(_lock);
/* If it's still idle, grab it. Otherwise drop through and
* we'll do something else next time through the loop. */
- if(_status == BufferStatus::IDLE)
- {
+ if (_status == BufferStatus::IDLE) {
_status = BufferStatus::POPULATING;
- _index = index;
- _users = _numusers;
+ _index = index;
+ _users = _numusers;
break;
}
}
@@ -194,10 +181,8 @@ public:
* simply (atomically) decrement the user count, and if it's hit zero we
* flag the buffer as idle.
*/
- void release(void)
- {
- if(--_users == 0)
- {
+ void release(void) {
+ if (--_users == 0) {
#ifdef USE_SEMAPHORE
std::unique_lock<std::mutex> ul(_lock);
_status = BufferStatus::IDLE;
@@ -211,110 +196,91 @@ public:
}
/* This is called to change the number of users. */
- void set_numusers(int numusers)
- {
+ void set_numusers(int numusers) {
_numusers = std::min(numusers, _maxusers);
}
};
-class BufferManager
-{
+
+class BufferManager {
private:
/* This has to be a vector of Buffer *, because a Buffer cannot be moved
* or copied due to atomic members. */
- std::vector<Buffer *> _buffers = {};
- const int _maxthreads;
- void *const _storage;
+ std::vector<Buffer *> _buffers = { };
+ const int _maxthreads;
+ void * const _storage;
public:
BufferManager(BufferManager &) = delete;
- BufferManager &operator=(BufferManager &) = delete;
+ BufferManager & operator=(BufferManager &) = delete;
// Say how much storage is needed.
- static inline size_t get_storage_requirement(const int maxthreads, const size_t buffersize)
- {
+ static inline size_t get_storage_requirement(const int maxthreads, const size_t buffersize) {
return buffersize * ((maxthreads == 1) ? 1 : 3);
}
- BufferManager(const int maxthreads, const size_t buffersize, void *storage)
- : _maxthreads(maxthreads), _storage(storage)
- {
+ BufferManager(const int maxthreads, const size_t buffersize, void *storage) : _maxthreads(maxthreads), _storage(storage) {
const int numbuffers = (maxthreads == 1) ? 1 : 3;
/* We don't need any Buffer objects in single thread mode. */
- if(_maxthreads == 1)
- {
+ if (_maxthreads == 1) {
return;
}
/* Use intptr_t to avoid performing arithmetic on a void * */
intptr_t storage_int = reinterpret_cast<intptr_t>(_storage);
- for(int i = 0; i < numbuffers; i++)
- {
+ for (int i=0; i<numbuffers; i++) {
_buffers.push_back(new Buffer(reinterpret_cast<void *>(storage_int), _maxthreads));
storage_int += buffersize;
}
}
- ~BufferManager()
- {
- while(_buffers.size())
- {
+ ~BufferManager() {
+ while (_buffers.size()) {
delete _buffers.back();
_buffers.pop_back();
}
}
template <typename T>
- void *get(const int index, T func)
- {
+ void *get(const int index, T func) {
/* In single thread mode, we just directly call the populating
* function on the (single) buffer, otherwise forward to the
* relevant Buffer. */
- if(_maxthreads == 1)
- {
+ if (_maxthreads==1) {
func(_storage);
return _storage;
- }
- else
- {
+ } else {
return _buffers[index % _buffers.size()]->get(index, func);
}
}
template <typename T>
- void try_populate(const int index, T func)
- {
+ void try_populate(const int index, T func) {
/* No need for this in single thread mode. */
- if(_maxthreads == 1)
- {
+ if (_maxthreads==1) {
return;
}
_buffers[index % _buffers.size()]->try_populate(index, func);
}
- void release(const int index)
- {
+ void release(const int index) {
/* No need for this in single thread mode. */
- if(_maxthreads == 1)
- {
+ if (_maxthreads==1) {
return;
}
_buffers[index % _buffers.size()]->release();
}
- void set_nthreads(int threads)
- {
- if(_maxthreads == 1)
- {
+ void set_nthreads(int threads) {
+ if (_maxthreads==1) {
return;
}
- for(unsigned int i = 0; i < _buffers.size(); i++)
- {
+ for(unsigned int i=0; i<_buffers.size(); i++) {
_buffers[i]->set_numusers(threads);
}
}
@@ -329,49 +295,35 @@ public:
* All the other methods do nothing.
*/
-class BufferManager
-{
+class BufferManager {
private:
- void *const _storage;
+ void * const _storage;
public:
BufferManager(BufferManager &) = delete;
- BufferManager &operator=(BufferManager &) = delete;
+ BufferManager & operator=(BufferManager &) = delete;
- BufferManager(const int maxthreads, const size_t buffersize, void *storage)
- : _storage(storage)
- {
- }
+ BufferManager(const int maxthreads, const size_t buffersize, void *storage) : _storage(storage) { }
- ~BufferManager()
- {
- }
+ ~BufferManager() { }
// Say how much storage is needed.
- static inline size_t get_storage_requirement(const int maxthreads, const size_t buffersize)
- {
+ static inline size_t get_storage_requirement(const int maxthreads, const size_t buffersize) {
return buffersize;
}
template <typename T>
- void try_populate(const int index, T func)
- {
- }
+ void try_populate(const int index, T func) { }
- void release(const int index)
- {
- }
+ void release(const int index) { }
template <typename T>
- void *get(const int index, T func)
- {
+ void *get(const int index, T func) {
func(_storage);
return _storage;
}
- void set_nthreads(int)
- {
- }
+ void set_nthreads(int) { }
};
#endif