ProcessingUnit::ProcessingUnit(const DeviceContext *context, std::size_t bitsThread) : context(context), cmdQueue(context->getCommandQueue()) { auto programContext = context->getProgramContext(); auto dlContext = programContext->getDeviceListContext(); auto &clContext = dlContext->getClContext(); auto &device = context->getDevice(); auto bitsGlobal = programContext->getBitsGlobal(); kernel = cl::Kernel(programContext->getProgram(), "des_kernel"); items = std::size_t(1) << (bitsGlobal - bitsThread); resultBits = programContext->getVectorLevel() + bitsGlobal; groupSize = std::min(items, kernel.getWorkGroupInfo<CL_KERNEL_WORK_GROUP_SIZE>(device)); groupCount = BLOCK_COUNT(groupSize, items); cdBaseBufferSize = (56 - bitsGlobal) * programContext->getVectorBytes(); resultBufferSize = (MAX_FOUND_KEYS + 1) * sizeof(cl_uint); cdBaseBuffer = cl::Buffer(clContext, CL_MEM_READ_ONLY, cdBaseBufferSize); resultBuffer = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, resultBufferSize); mappedCdBaseBuffer = cmdQueue.enqueueMapBuffer( cdBaseBuffer, true, CL_MAP_WRITE, 0, cdBaseBufferSize); mappedResultBuffer = nullptr; kernel.setArg<cl::Buffer>(0, programContext->getRefInputBuffer()); kernel.setArg<cl::Buffer>(1, programContext->getRefOutputBuffer()); kernel.setArg<cl::Buffer>(2, cdBaseBuffer); kernel.setArg<cl::Buffer>(3, resultBuffer); kernel.setArg<cl_uint> (4, static_cast<cl_uint>(bitsThread)); }
void mem_pool::pool_free( void* ptr, size_t bytes ) { if( ptr ) pool_dealloc( ptr, bytes ); if( bytes <= MEMORY_POOL_MAX ) { int i; size_t index = LIST_INDEX( bytes ); size_t blk_count = BLOCK_COUNT( index ); mempage_t *erase = NULL, *prev = NULL, *curr = pool[index].first; if( pool_lock ) pool_lock( index ); while( curr ) { if( curr->count != blk_count ) /* 判断是否是空闲页 */ { prev = curr; curr = curr->next; } else { /* 从页面缓存中退出 */ for( i = 0; i < MEMORY_POOL_BUFFER; ++i ) { if( pool[index].buffer[i] == curr ) { pool[index].buffer[i] = NULL; break; } } if( prev ) prev->next = curr->next; /* 空闲页不在链首 */ else pool[index].first = curr->next; /* 空闲页在链首 */ /* 将空闲页释放 */ erase = curr; curr = curr->next; MEMFREE( erase ); --( pool[index].useable ); } /* end if */ } /* end while */ if( pool_unlock ) pool_unlock( index ); } }
BlockPath BlockPath::Index(size_t blockIndex) { std::array<uint16_t, NODE_MAX_BLOCK_PATH> components; components.fill(0); if (blockIndex < BLOCK_COUNT(0)) { // Direct reference. components.at(0) = blockIndex; return BlockPath(1, components); } if (blockIndex < BLOCK_COUNT(1)) { // Single indirect. components.at(0) = NODE_SINGLE_INDIRECT_INDEX; components.at(1) = indirectOffset<0>(blockIndex); return BlockPath(2, components); } if (blockIndex < BLOCK_COUNT(2)) { // Double indirect. components.at(0) = NODE_DOUBLE_INDIRECT_INDEX; components.at(1) = indirectOffset<1>(blockIndex); components.at(2) = indirectOffset<0>(blockIndex); return BlockPath(3, components); } if (blockIndex < BLOCK_COUNT(3)) { // Triple indirect. components.at(0) = NODE_TRIPLE_INDIRECT_INDEX; components.at(1) = indirectOffset<2>(blockIndex); components.at(2) = indirectOffset<1>(blockIndex); components.at(3) = indirectOffset<0>(blockIndex); return BlockPath(4, components); } throw std::runtime_error("Block index exceeds triple indirect."); }
namespace FolderSync { // ------------- Configurable values. // Size of a block. constexpr size_t BLOCK_SIZE = 65536; // Size of a block ID. constexpr size_t BLOCK_ID_SIZE = 16; // Offset in a node block where size is stored. constexpr size_t NODE_SIZE_OFFSET = 0; // Offset in a node block where type is stored. constexpr size_t NODE_TYPE_OFFSET = 8; // Offset in the block where IDs are stored. constexpr size_t NODE_BLOCK_ID_OFFSET = 16; // Maximum blocks held by a block cache. constexpr size_t CACHE_MAX_BLOCKS = 8; // Number of indirects in a node's root block. constexpr size_t INDIRECT_COUNT = 3; // ------------- Calculated values. // Maximum node block path size. constexpr size_t NODE_MAX_BLOCK_PATH = INDIRECT_COUNT + 1; // Maximum references in node's root block. constexpr size_t NODE_ROOT_MAX_REFS = ((BLOCK_SIZE - NODE_BLOCK_ID_OFFSET) / BLOCK_ID_SIZE); // Maximum direct references in node's root block. constexpr size_t NODE_ROOT_MAX_DIRECT_REFS = NODE_ROOT_MAX_REFS - INDIRECT_COUNT; // Maximum references in node's indirect blocks. constexpr size_t NODE_MAX_INDIRECT_REFS = (BLOCK_SIZE / BLOCK_ID_SIZE); // Index of the single indirect in node's root block. constexpr size_t NODE_SINGLE_INDIRECT_INDEX = NODE_ROOT_MAX_DIRECT_REFS; // Index of the double indirect in node's root block. constexpr size_t NODE_DOUBLE_INDIRECT_INDEX = NODE_ROOT_MAX_DIRECT_REFS + 1; // Index of the triple indirect in node's root block. constexpr size_t NODE_TRIPLE_INDIRECT_INDEX = NODE_ROOT_MAX_DIRECT_REFS + 2; // Integer power. constexpr size_t INT_POW(size_t value, size_t power) { return power > 0 ? value * INT_POW(value, power - 1) : 1; } // Integer power sum (i.e. INT_POW_SUM(n, 2, c) = n^2 + n^1 + c). constexpr size_t INT_POW_SUM(size_t value, size_t power, size_t constant) { return power > 0 ? INT_POW(value, power) + INT_POW_SUM(value, power - 1, constant) : constant; } // Calculate blocks that can be referenced by an indirect level. constexpr size_t BLOCK_COUNT(size_t indirectLevel) { return INT_POW_SUM(NODE_MAX_INDIRECT_REFS, indirectLevel, NODE_ROOT_MAX_DIRECT_REFS); } // Maximum node size in blocks. constexpr size_t NODE_MAX_BLOCKS = BLOCK_COUNT(INDIRECT_COUNT); // Maximum node size in bytes. constexpr size_t NODE_MAX_BYTES = NODE_MAX_BLOCKS * BLOCK_SIZE; }
void* mem_pool::pool_alloc( size_t bytes ) { void* ptr = NULL; if( bytes > MEMORY_POOL_MAX ) { ptr = MEMALLOC( bytes ); } else { size_t index = LIST_INDEX( bytes ); if( pool_lock ) pool_lock( index ); if( pool[index].first && pool[index].useable > 0 ) { int i; mempage_t *prev = NULL, *curr = NULL; /* 先查找页面缓存 */ for( i = 0; i < MEMORY_POOL_BUFFER; ++i ) { if( pool[index].buffer[i] ) { ptr = pool[index].buffer[i]->free; pool[index].buffer[i]->free = pool[index].buffer[i]->free->next; --( pool[index].buffer[i]->count ); /* 如果该页已无空闲块,则将该页自页面缓存中退出 */ if( pool[index].buffer[i]->count == 0 ) { --( pool[index].useable ); pool[index].buffer[i] = NULL; } else { if( i > 0 ) { /* 如果该页不在缓存首,则将该页调整至缓存首 */ pool[index].buffer[0] = pool[index].buffer[i]; pool[index].buffer[i] = NULL; } } goto EXIT_POOL_ALLOC; } } /* end for */ /* 页面缓存为空,则遍历链中的所有内存页寻找空闲的内存块 */ curr = pool[index].first; while( curr ) { if( curr->count == 0 ) /* 该页中没有空闲块 */ { /* 进入下一页 */ prev = curr; curr = curr->next; } else /* 该页中有空闲块 */ { size_t page_count = 0; /* 统计遍历过的可用内存页 */ ptr = curr->free; curr->free = curr->free->next; --( curr->count ); if( curr->count == 0 ) --( pool[index].useable ); /* 继续遍历链表,寻找其他还有空闲块的页面,将之放入页面缓存 */ while( curr && page_count < pool[index].useable ) { if( curr->count != 0 ) { /* 页面缓存还有位置则放入页面缓存 */ if( page_count < MEMORY_POOL_BUFFER ) pool[index].buffer[page_count] = curr; ++page_count; /* 如果当前页未满并且不在链首,则将之移至链首 */ if( pool[index].first != curr ) { prev->next = curr->next; /* 保存下一页 */ curr->next = pool[index].first; pool[index].first = curr; curr = prev->next; /* 进入下一页 */ continue; } } /* 进入下一页 */ prev = curr; curr = curr->next; } goto EXIT_POOL_ALLOC; } /* end else */ } /* end while */ } /* end if pool[index].useable > 0 */ else { /* 该链下未分配内存页或无空闲块,此时需增加新的内存页 */ mempage_t* pg = NULL; size_t blk_size = BLOCK_SIZE( index ); /* 如果 page_size = 0,则计算该内存链下每个内存页需占用的字节数 */ if( 0 == pool[index].page_size ) { if( DEFAULT_PAGE_SIZE % blk_size == 0 ) pool[index].page_size = DEFAULT_PAGE_SIZE; else pool[index].page_size = (DEFAULT_PAGE_SIZE / blk_size) * blk_size; } pg = (mempage_t*)MEMALLOC( sizeof(mempage_t) + pool[index].page_size ); if( pg ) { memblk_t* curr = NULL; size_t i, blk_count = BLOCK_COUNT( index ); pg->next = pool[index].first; pool[index].first = pg; /* 将内存页中的所有内存块串联成一个链表 */ curr = (memblk_t*)((unsigned char*)pg + sizeof(mempage_t)); pg->free = curr; for( i = 1; i < blk_count; ++i ) { curr->next = (memblk_t*)((unsigned char*)curr + blk_size); curr = curr->next; } curr->next = NULL; ptr = pg->free; pg->free = pg->free->next; pg->count = blk_count - 1; ++( pool[index].useable ); pool[index].buffer[0] = pg; } } EXIT_POOL_ALLOC: if( pool_unlock ) pool_unlock( index ); } /* end else */ if( ptr ) ++pool_alloc_count; return ptr; }