| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //  BufferPool.cpp
 | 
					
						
							|  |  |  | //  MNN
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //  Created by MNN on 2019/02/28.
 | 
					
						
							|  |  |  | //  Copyright © 2018, Alibaba Group Holding Limited
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | #include "backend/opencl/core/BufferPool.hpp"
 | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | namespace MNN { | 
					
						
							|  |  |  | namespace OpenCL { | 
					
						
							| 
									
										
										
										
											2024-04-19 11:58:21 +08:00
										 |  |  | cl::Buffer* BufferPool::alloc(size_t size, bool separate) { | 
					
						
							| 
									
										
										
										
											2022-05-27 23:46:44 +08:00
										 |  |  |     if (!separate) { | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |         auto iter = mFreeList.lower_bound(size); | 
					
						
							|  |  |  |         if (iter != mFreeList.end()) { | 
					
						
							|  |  |  |             auto buffer = iter->second->buffer.get(); | 
					
						
							|  |  |  |             mFreeList.erase(iter); | 
					
						
							|  |  |  |             return buffer; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-12-31 15:34:08 +08:00
										 |  |  |     std::shared_ptr<OpenCLBufferNode> node(new OpenCLBufferNode); | 
					
						
							| 
									
										
										
										
											2023-07-31 14:24:48 +08:00
										 |  |  |     cl_int ret = CL_SUCCESS; | 
					
						
							| 
									
										
										
										
											2023-12-27 17:26:44 +08:00
										 |  |  |     mTotalSize += size; | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |     node->size = size; | 
					
						
							| 
									
										
										
										
											2023-07-31 14:24:48 +08:00
										 |  |  |     node->buffer.reset(new cl::Buffer(mContext, mFlag, size, NULL, &ret)); | 
					
						
							|  |  |  |     if (nullptr == node->buffer.get() || ret != CL_SUCCESS) { | 
					
						
							| 
									
										
										
										
											2024-04-19 11:58:21 +08:00
										 |  |  |         MNN_ERROR("Alloc Buffer %lu error, code:%d \n", size, ret); | 
					
						
							| 
									
										
										
										
											2023-07-31 14:24:48 +08:00
										 |  |  |         return nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |     mAllBuffer.insert(std::make_pair(node->buffer.get(), node)); | 
					
						
							|  |  |  |     return node->buffer.get(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BufferPool::recycle(cl::Buffer* buffer, bool release) { | 
					
						
							|  |  |  |     auto iter = mAllBuffer.find(buffer); | 
					
						
							|  |  |  |     if (iter == mAllBuffer.end()) { | 
					
						
							|  |  |  |         MNN_ERROR("Error for recycle buffer\n"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (release) { | 
					
						
							|  |  |  |         mAllBuffer.erase(iter); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mFreeList.insert(std::make_pair(iter->second->size, iter->second)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BufferPool::clear() { | 
					
						
							|  |  |  |     mFreeList.clear(); | 
					
						
							|  |  |  |     mAllBuffer.clear(); | 
					
						
							| 
									
										
										
										
											2023-12-27 17:26:44 +08:00
										 |  |  |     mTotalSize = 0; | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-11-15 14:22:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-04 11:12:20 +08:00
										 |  |  | void BufferPool::releaseFreeList() { | 
					
						
							|  |  |  |     for(auto mf : mFreeList){ | 
					
						
							|  |  |  |         auto iter = mAllBuffer.find(mf.second->buffer.get()); | 
					
						
							|  |  |  |         if (iter != mAllBuffer.end()) { | 
					
						
							|  |  |  |             mAllBuffer.erase(iter); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mFreeList.clear(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-12-31 15:34:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | std::shared_ptr<OpenCLBufferNode> BufferExecutionPool::alloc(size_t size, bool separate) { | 
					
						
							|  |  |  |     if (!separate) { | 
					
						
							|  |  |  |         auto iter = mFreeList.lower_bound(size); | 
					
						
							|  |  |  |         if (iter != mFreeList.end()) { | 
					
						
							|  |  |  |             auto node = iter->second; | 
					
						
							|  |  |  |             mFreeList.erase(iter); | 
					
						
							|  |  |  |             return node; | 
					
						
							|  |  |  |         } else if(mFreeList.size() != 0){ | 
					
						
							|  |  |  |             cl_int ret = CL_SUCCESS; | 
					
						
							|  |  |  |             // Synchronize to prevent old buffer references
 | 
					
						
							|  |  |  |             mCommand.finish(); | 
					
						
							|  |  |  |             auto maxIter = mFreeList.rbegin(); | 
					
						
							|  |  |  |             auto node = maxIter->second; | 
					
						
							|  |  |  |             mTotalSize += size - node.get()->size; | 
					
						
							|  |  |  |             node.get()->size = size; | 
					
						
							|  |  |  |             node.get()->buffer.reset(new cl::Buffer(mContext, mFlag, size, NULL, &ret)); | 
					
						
							|  |  |  |             if (nullptr == node.get()->buffer.get() || ret != CL_SUCCESS) { | 
					
						
							|  |  |  |                 MNN_ERROR("Alloc Buffer %lu error, code:%d \n", size, ret); | 
					
						
							|  |  |  |                 return nullptr; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             mFreeList.erase(std::prev(mFreeList.end())); | 
					
						
							|  |  |  |             return node; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     std::shared_ptr<OpenCLBufferNode> node(new OpenCLBufferNode); | 
					
						
							|  |  |  |     cl_int ret = CL_SUCCESS; | 
					
						
							|  |  |  |     mTotalSize += size; | 
					
						
							|  |  |  |     node->size = size; | 
					
						
							|  |  |  |     node->buffer.reset(new cl::Buffer(mContext, mFlag, size, NULL, &ret)); | 
					
						
							|  |  |  |     if (nullptr == node->buffer.get() || ret != CL_SUCCESS) { | 
					
						
							|  |  |  |         MNN_ERROR("Alloc Buffer %lu error, code:%d \n", size, ret); | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mAllBuffer.insert(node); | 
					
						
							|  |  |  |     return node; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BufferExecutionPool::recycle(std::shared_ptr<OpenCLBufferNode> node, bool release) { | 
					
						
							|  |  |  |     auto iter = mAllBuffer.find(node); | 
					
						
							|  |  |  |     if (iter == mAllBuffer.end()) { | 
					
						
							|  |  |  |         MNN_ERROR("Error for recycle buffer\n"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (release) { | 
					
						
							|  |  |  |         mAllBuffer.erase(node); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mFreeList.insert(std::make_pair(node.get()->size, node)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BufferExecutionPool::clear() { | 
					
						
							|  |  |  |     mFreeList.clear(); | 
					
						
							|  |  |  |     mAllBuffer.clear(); | 
					
						
							|  |  |  |     mTotalSize = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BufferExecutionPool::releaseFreeList() { | 
					
						
							|  |  |  |     for(auto mf : mFreeList){ | 
					
						
							|  |  |  |         auto iter = mAllBuffer.find(mf.second); | 
					
						
							|  |  |  |         if (iter != mAllBuffer.end()) { | 
					
						
							|  |  |  |             mAllBuffer.erase(iter); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mFreeList.clear(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | } // namespace OpenCL
 | 
					
						
							|  |  |  | } // namespace MNN
 |