FastSort/src/sort/phase_1_uncompress.cpp

184 lines
6.7 KiB
C++
Raw Normal View History

/*
Description: 线
Copyright : All right reserved by ICT
Author : Zhang Zhonghai
Date : 2026/05/25
*/
#include "phase_1_uncompress.h"
#include <klib/kthread.h>
#include <spdlog/spdlog.h>
#include <stdint.h>
#include <zlib.h>
#include "common_data.h"
#include "const_val.h"
#include "phase_1.h"
#include "sam_io.h"
#include "sort.h"
#include "util/profiling.h"
#include "util/yarn.h"
/* 多线程解压 */
static void mtUncompressBlock(void* data, long idx, int tid) {
PROF_T_BEG(mem_copy);
Phase1PipelineArg& p = *(Phase1PipelineArg*)data;
ReadBuffer & readData = p.readData[p.uncompressOrder % p.READ_BUF_NUM];
auto& blockArr = p.threadBlocksWrap.threadBlocks[tid];
auto& blockItem = blockArr.add();
uint8_t* block = readData.startAddrArr[idx];
size_t dlen = SINGLE_BLOCK_SIZE; // 65535
int block_length = unpackInt16(&block[16]) + 1;
uint32_t crc = le_to_u32(block + block_length - 8);
int ret = bgzfUncompress(blockItem.data, &dlen, (Bytef*)block + BLOCK_HEADER_LENGTH, block_length - BLOCK_HEADER_LENGTH, crc);
if (ret != 0) {
spdlog::error("uncompress error, block id: {}, len: {}, ret: {}", idx, block_length, ret);
exit(0);
}
blockItem.blockId = idx + p.startBlockId;
blockItem.blockLen = dlen;
blockArr.blockHeap.push({blockItem.blockId, blockArr.curIdx - 1}); // 解压完成后将block的id和在block数组里的索引加入堆中方便后续排序和合并
#if 0
// 放入全局缓冲区
// spdlog::info("top id: {}, block id: {}", blockArr.blockHeap.top().blockId, p.uncompressData.nextBlockId);
while (blockArr.blockHeap.top().blockId == p.uncompressData.nextBlockId) {
auto& top = blockArr.blockHeap.top();
// auto& topBlock = blockArr.blockArr[top.blockArrIdx];
// memcpy(p.uncompressData.dataBuf + p.uncompressData.usedBufSize, topBlock.data, topBlock.blockLen);
// p.uncompressData.startAddrArr.push_back(p.uncompressData.dataBuf + p.uncompressData.usedBufSize);
// p.uncompressData.usedBufSize += topBlock.blockLen;
// p.bamNum += topBlock.bamNum;
blockArr.blockHeap.pop();
p.uncompressData.nextBlockId += 1;
p.uncompressData.blockNum += 1;
}
#endif
PROF_T_END(tid, mem_copy);
}
// 多线程解压静态分配任务此时用idx代替tidmulti-thread uncompress bam blocks
static void mtUncompressBlockBatch(void* data, long idx, int tid) {
PROF_T_BEG(mem_copy);
Phase1PipelineArg& p = *(Phase1PipelineArg*)data;
ReadBuffer& readData = p.readData[p.uncompressOrder % p.READ_BUF_NUM];
tid = idx; // 静态分配任务此时用idx代替tid
int startIdx = START_IDX(idx, p.numThread, readData.startAddrArr.size());
int stopIdx = STOP_IDX(idx, p.numThread, readData.startAddrArr.size());
auto &blockBuf = p.threadBlocksWrap.threadBlockBuf[tid];
if (stopIdx - startIdx > blockBuf.maxLen / SINGLE_BLOCK_SIZE) {
blockBuf.reAllocMem((stopIdx - startIdx) * SINGLE_BLOCK_SIZE);
}
for (int i = startIdx; i < stopIdx; ++i) {
uint8_t* block = readData.startAddrArr[i];
size_t dlen = SINGLE_BLOCK_SIZE; // 65535
int block_length = unpackInt16(&block[16]) + 1;
uint32_t crc = le_to_u32(block + block_length - 8);
int ret = bgzfUncompress(blockBuf.data + blockBuf.curLen, &dlen, (Bytef*)block + BLOCK_HEADER_LENGTH, block_length - BLOCK_HEADER_LENGTH, crc);
if (ret != 0) {
spdlog::error("uncompress error, block id: {}, len: {}, ret: {}", idx, block_length, ret);
exit(0);
}
blockBuf.curLen += dlen;
}
PROF_T_END(tid, mem_copy);
}
static void mtMemCopy(void* data, long idx, int tid) {
Phase1PipelineArg& p = *(Phase1PipelineArg*)data;
tid = idx; // 静态分配任务此时用idx代替tid
uint64_t offset = 0;
for (int i = 0; i < tid; ++i) {
offset += p.threadBlocksWrap.threadBlockBuf[i].curLen;
}
memcpy(p.uncompressData.dataBuf + p.uncompressData.usedBufSize + offset, p.threadBlocksWrap.threadBlockBuf[tid].data,
p.threadBlocksWrap.threadBlockBuf[tid].curLen);
}
/* 将gz block进行解压并进行线程内排序 */
static void doPhase1Uncompress(Phase1PipelineArg& p, int finish = 0) {
PROF_G_BEG(uncompress);
uint64_t blockNum = p.readData[p.uncompressOrder % p.READ_BUF_NUM].startAddrArr.size();
// kt_for(p.numThread, mtUncompressBlock, &p, blockNum);
kt_for(p.numThread, mtUncompressBlockBatch, &p, p.numThread);
// 串行拷贝所有blocks
PROF_G_BEG(mem_copy);
#if 1
kt_for(p.numThread, mtMemCopy, &p, p.numThread);
#else
for (int i = 0; i < p.numThread; ++i) {
memcpy(p.uncompressData.dataBuf + p.uncompressData.usedBufSize, p.threadBlocksWrap.threadBlockBuf[i].data, p.threadBlocksWrap.threadBlockBuf[i].curLen);
// p.uncompressData.startAddrArr.push_back(p.uncompressData.dataBuf + p.uncompressData.usedBufSize);
p.uncompressData.usedBufSize += p.threadBlocksWrap.threadBlockBuf[i].curLen;
}
#endif
#if 0
for (int i = 0; i < 1; ++i) {
auto& blockArr = p.threadBlocksWrap.threadBlocks[i];
for (int j = 0; j < blockArr.curIdx; ++j) {
auto& blockItem = blockArr.blockArr[j];
memcpy(p.uncompressData.dataBuf + p.uncompressData.usedBufSize, blockItem.data, blockItem.blockLen);
p.uncompressData.startAddrArr.push_back(p.uncompressData.dataBuf + p.uncompressData.usedBufSize);
p.uncompressData.usedBufSize += blockItem.blockLen;
p.uncompressData.blockNum += 1;
}
}
#endif
PROF_G_END(mem_copy);
p.startBlockId += blockNum;
if (true) { // 缓冲区满了
spdlog::info("blocks num: {}, left: {}, uncompressed: {}", p.threadBlocksWrap.GetTotalBlockNum(), p.threadBlocksWrap.GetHeapBlockNum(),
p.uncompressData.blockNum);
p.uncompressData.Clear();
p.threadBlocksWrap.ResetBlockArr();
p.uncompressData.nextBlockId = p.startBlockId;
p.uncompressData.blockNum = 0;
}
PROF_G_END(uncompress);
}
/* phase1Uncompress step-2 解压线程 */
void* phase1Uncompress(void* data) {
Phase1PipelineArg& p = *(Phase1PipelineArg*)data;
/* 2. do the work */
while (true) {
// previous dependency
yarn::DEPENDENCY_NOT_TO_BE(p.readSig, 0);
if (p.readFinish) {
while (p.uncompressOrder < p.readOrder) {
doPhase1Uncompress(p, 1);
p.uncompressOrder += 1;
}
break;
}
doPhase1Uncompress(p);
// update status
yarn::CONSUME_SIGNAL(p.readSig);
p.uncompressOrder += 1;
}
spdlog::info("uncompress order: {}", p.uncompressOrder);
return nullptr;
}