| 1275 | static std::atomic_flag g_cl_pool_lock = ATOMIC_FLAG_INIT; |
| 1276 | |
| 1277 | static cl_mem ggml_cl_pool_malloc(size_t size, size_t * actual_size) { |
| 1278 | scoped_spin_lock lock(g_cl_pool_lock); |
| 1279 | cl_int err; |
| 1280 | |
| 1281 | int best_i = -1; |
| 1282 | size_t best_size = std::numeric_limits<size_t>::max(); //smallest unused buffer that fits our needs |
| 1283 | int worst_i = -1; |
| 1284 | size_t worst_size = 0; //largest unused buffer seen so far |
| 1285 | for (int i = 0; i < MAX_CL_BUFFERS; ++i) { |
| 1286 | cl_buffer &b = g_cl_buffer_pool[i]; |
| 1287 | if (b.size > 0 && b.size >= size && b.size < best_size) |
| 1288 | { |
| 1289 | best_i = i; |
| 1290 | best_size = b.size; |
| 1291 | } |
| 1292 | if (b.size > 0 && b.size > worst_size) |
| 1293 | { |
| 1294 | worst_i = i; |
| 1295 | worst_size = b.size; |
| 1296 | } |
| 1297 | } |
| 1298 | if(best_i!=-1) //found the smallest buffer that fits our needs |
| 1299 | { |
| 1300 | cl_buffer& b = g_cl_buffer_pool[best_i]; |
| 1301 | cl_mem mem = b.mem; |
| 1302 | *actual_size = b.size; |
| 1303 | b.size = 0; |
| 1304 | return mem; |
| 1305 | } |
| 1306 | if(worst_i!=-1) //no buffer that fits our needs, resize largest one to save memory |
| 1307 | { |
| 1308 | cl_buffer& b = g_cl_buffer_pool[worst_i]; |
| 1309 | cl_mem mem = b.mem; |
| 1310 | b.size = 0; |
| 1311 | clReleaseMemObject(mem); |
| 1312 | } |
| 1313 | cl_mem mem; |
| 1314 | CL_CHECK((mem = clCreateBuffer(context, CL_MEM_READ_WRITE, size, NULL, &err), err)); |
| 1315 | *actual_size = size; |
| 1316 | return mem; |
| 1317 | } |
| 1318 | |
| 1319 | static void ggml_cl_pool_free(cl_mem mem, size_t size) { |
| 1320 | scoped_spin_lock lock(g_cl_pool_lock); |
no test coverage detected