之前在HEVC代码学习35:xEncodeCU函数中介绍过xEncodeCU函数,今天来看JEM中的xEncodeCU,其中难点在于QTBT编码结构。

HM中使用compressCtu对每个CTU进行划分并预测,然后使用encodeCtu对每个CTU进行编码。JEM中也是如此,会在xEncodeCU,迭代完成CU各种信息的编码。所以在这里,当前的CTU已经进行了划分和预测,如果要看CU的划分和预测结果就可以到这里找。

JEM中与HM主要区别:
1.JEM中使用了QTBT(四叉树加二叉树)的编码结构,因此xEncodeCU中在四叉树划分之后,增加了二叉树划分的迭代操作。
2.由于使用QTBT,划分中增加了一些尺寸的限定条件,需要得到当前块尺寸,因此xEncodeCU中输入参数中增加了当前块的宽和高。
3.增加了新增模式的flag的编码。

流程如下:
1.从CTU开始,此时深度为0,尺寸为uiCTUSize,默认为128。
2.如果当前块为2Nx2N,宽度为uiCTUSize>>uiDepth,且块尺寸大于四叉树最小尺寸uiMinQTSize(在cfg中可以设置),当前划分深度小于四叉树深度(存储在TComDataCUm_puhDepth中)时,递归对四个分块进行编码;否则即达到最大深度,不再递归调用xEncodeCU
3.四叉树达到最大深度之后,如果当前块长或块大于二叉树最小尺寸且两者都小于二叉树最大尺寸时,进行二叉树划分。通过getBTSplitModeForBTDepth获取二叉树划分模式,为1时,进行横向划分,分别对两个块递归划分;为2时,进行纵向划分,分别对两个块递归划分。
4.如果当前块长和块都小于二叉树最小尺寸时,停止划分,调用encodeXXXXX函数,对CU的预测信息进行编码,这里就不列举具体函数了。

划分示例:
这样说很模糊,我随便编了一个序列,以第一个CTU为例,说明一下这个递归过程。第一个CTU的最上角32x32 CU的划分结果为:四叉树深度为2,二叉树模式为2,划分结果如下图(点击看大图):

CU(0,0) depth=0 Width=128 Height=128:
当前进入的是第一个CTU,此时深度为0,长宽均为128,此时长宽相等,且等于uiCTUSize>>uiDepth=128(uiCTUSize默认为128)。判断是否达到最小四叉树尺寸uiMinQTSize(默认为8),当前方块尺寸为128大于uiMinQTSizepcCU->getDepth( uiAbsPartIdx )获取到的四叉树深度为2,当前深度小于2,分别对四个子块调用encodeCtu进行编码。

CU(0,0) depth=1 Width=64 Height=64:
重复刚才的判断,满足四叉树划分条件,进行四叉树划分,调用encodeCtu进行编码。

CU(0,0) depth=2 Width=32 Height=32:
重复刚才的判断,当前深度2,长宽为32,等于uiCTUSize>>uiDepth=32,大于uiMinQTSize,当前深度不小于2,不再进行四叉树划分 ,下面将进行二叉树划分。
当前块长和高为32,大于最小二叉树尺寸4,且小于等于最大二叉树尺寸32,二叉树深度为0,小于最大二叉树深度3。通过pcCU->getBTSplitModeForBTDepth获取到二叉树模式为2,进行垂直划分,分别对两个子块调用encodeCtu进行编码。

CU(0,0) depth=3 Width=16 Height=32:
重复二叉树划分的判断,获取到二叉树模式为0,结束划分。

CU(16,0) depth=3 Width=16 Height=32:
重复二叉树划分的判断,获取到二叉树模式为0,结束划分。

语言表达能力较差,大家凑合着看。

代码分析:

//递归编码CU,相比HM增加了CU尺寸
/** encode a CU block recursively* \param pcCU* \param uiAbsPartIdx      CU索引* \param uiDepth               划分深度* \returns Void*/
#if JVET_C0024_QTBT
Void TEncCu::xEncodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiWidth, UInt uiHeight, UInt uiSplitConstrain )
#else
Void TEncCu::xEncodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
#endif
{
#if JVET_C0024_BT_RMV_REDUNDANTpcCU->setSplitConstrain( uiSplitConstrain );Bool bQTreeValid = false;
#endifTComPic   *const pcPic   = pcCU->getPic();      //当前帧TComSlice *const pcSlice = pcCU->getSlice();    //当前sliceconst TComSPS   &sps =*(pcSlice->getSPS());           //SPSconst TComPPS   &pps =*(pcSlice->getPPS());       //PPS#if !JVET_C0024_QTBTconst UInt maxCUWidth  = sps.getMaxCUWidth();const UInt maxCUHeight = sps.getMaxCUHeight();Bool bBoundary = false;
#endif//CU左上角X坐标UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
#if JVET_C0024_QTBT//CU右侧X坐标const UInt uiRPelX   = uiLPelX + uiWidth  - 1;
#elseconst UInt uiRPelX   = uiLPelX + (maxCUWidth>>uiDepth)  - 1;
#endif//CU左上角Y坐标UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
#if JVET_C0024_QTBT//CU下侧Y坐标const UInt uiBPelY   = uiTPelY + uiHeight - 1;
#elseconst UInt uiBPelY   = uiTPelY + (maxCUHeight>>uiDepth) - 1;
#endif#if JVET_C0024_QTBT//当块宽度大于TU最大尺寸MAX_TU_SIZE时,强制使用四叉树划分Bool bForceQT = uiWidth > MAX_TU_SIZE;if( bForceQT )        //当强制四叉树划分时,块尺寸必须是2Nx2N{assert(uiWidth == uiHeight);}//CTU尺寸UInt uiCTUSize = pcCU->getSlice()->getSPS()->getCTUSize();
#if JVET_C0024_DELTA_QP_FIX//四叉树的宽和高UInt uiQTWidth = uiCTUSize>>uiDepth;UInt uiQTHeight = uiCTUSize>>uiDepth;//二叉树的深度const UInt uiQTBTDepth = (uiDepth<<1) + (g_aucConvertToBit[uiQTWidth]-g_aucConvertToBit[uiWidth] + g_aucConvertToBit[uiQTHeight]-g_aucConvertToBit[uiHeight]);const UInt uiMaxDQPDepthQTBT = pps.getMaxCuDQPDepth() << 1;
#endif//当前块为2Nx2N且尺寸等于uiCTUSize>>uiDepth时if (uiCTUSize>>uiDepth == uiWidth && uiWidth==uiHeight){
#endif//CU坐标小于亮度图像的宽和高if( ( uiRPelX < sps.getPicWidthInLumaSamples() ) && ( uiBPelY < sps.getPicHeightInLumaSamples() ) ){
#if JVET_C0024_QTBT//强制四叉树划分if( bForceQT ){//划分深度一定小于当前CU的深度assert(uiDepth < pcCU->getDepth( uiAbsPartIdx ) ); }else
#endif//编码划分Flagm_pcEntropyCoder->encodeSplitFlag( pcCU, uiAbsPartIdx, uiDepth );}else  //CU坐标不小于亮度图像的宽和高时,检测边缘{
#if JVET_C0024_QTBTassert(uiDepth < pcCU->getDepth( uiAbsPartIdx ) );
#elsebBoundary = true;
#endif}#if JVET_C0024_BT_RMV_REDUNDANT//四叉树是否可用bQTreeValid = true;   //获取最小四叉树尺寸UInt uiMinQTSize = sps.getMinQTSize(pcCU->getSlice()->getSliceType(), pcCU->getTextType());//如果uiCTUSize>>uiDepth小于最小四叉树尺寸,此时四叉树不可用if ((uiCTUSize>>uiDepth) <= uiMinQTSize){bQTreeValid = false;}
#endif#if JVET_C0024_QTBT//当前划分深度小于当前CU深度时if( uiDepth < pcCU->getDepth( uiAbsPartIdx ) )
#elseif( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary )
#endif{UInt uiQNumParts = ( pcPic->getNumPartitionsInCtu() >> (uiDepth<<1) )>>2;
#if JVET_C0024_DELTA_QP_FIX//使用DQP时,默认关闭if( uiQTBTDepth == uiMaxDQPDepthQTBT && pps.getUseDQP())
#elseif( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP())
#endif{setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}if( uiDepth == pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj()){setCodeChromaQpAdjFlag(true);}//递归调用,对四个分块进行编码for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts ){//当前CU的坐标uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];//在亮度范围内if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) ){
#if JVET_C0024_QTBTxEncodeCU( pcCU, uiAbsPartIdx, uiDepth+1, uiWidth>>1, uiHeight>>1 );
#elsexEncodeCU( pcCU, uiAbsPartIdx, uiDepth+1 );
#endif}
#if JVET_C0024_QTBTelse{pcCU->getPic()->addCodedAreaInCTU(uiWidth*uiHeight>>2);}
#endif}return;}#if JVET_C0024_QTBT}
#if JVET_C0024_BT_RMV_REDUNDANTBool bBTHorRmvEnable = false;Bool bBTVerRmvEnable = false;if (pcCU->getSlice()->getSliceType() != I_SLICE){bBTHorRmvEnable = true;bBTVerRmvEnable = bQTreeValid;}
#endif
#if JVET_C0024_SPS_MAX_BT_DEPTH//最大二叉树深度UInt uiMaxBTD = pcSlice->isIntra() ? (isLuma(pcCU->getTextType())?sps.getMaxBTDepthISliceL():sps.getMaxBTDepthISliceC()): sps.getMaxBTDepth();
#elseUInt uiMaxBTD = pcCU->getSlice()->isIntra() ? (isLuma(pcCU->getTextType())?MAX_BT_DEPTH:MAX_BT_DEPTH_C): MAX_BT_DEPTH_INTER;
#endif
#if JVET_C0024_SPS_MAX_BT_SIZEUInt uiMaxBTSize = pcSlice->isIntra() ? (isLuma(pcCU->getTextType())?sps.getMaxBTSizeISliceL():sps.getMaxBTSizeISliceC()): sps.getMaxBTSize();
#else//最大二叉树尺寸UInt uiMaxBTSize = isLuma(pcCU->getTextType()) ? pcCU->getSlice()->getMaxBTSize(): MAX_BT_SIZE_C;
#endif//最小二叉树尺寸UInt uiMinBTSize = pcCU->getSlice()->isIntra() ? (isLuma(pcCU->getTextType())?MIN_BT_SIZE:MIN_BT_SIZE_C): MIN_BT_SIZE_INTER;//最小二叉树深度UInt uiBTDepth = pcCU->getBTDepth(uiAbsPartIdx, uiWidth, uiHeight);//当前块符合二叉树划分的深度和尺寸条件时if ( (uiHeight>uiMinBTSize || uiWidth>uiMinBTSize) && uiWidth<=uiMaxBTSize && uiHeight<=uiMaxBTSize && uiBTDepth<uiMaxBTD) {
#if JVET_C0024_BT_RMV_REDUNDANTuiSplitConstrain = 0;
#endif//编码二叉树划分m_pcEntropyCoder->encodeBTSplitMode(pcCU, uiAbsPartIdx, uiWidth, uiHeight);//二叉树划分模式为1,横向划分if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth)==1){
#if JVET_C0024_DELTA_QP_FIXif( uiQTBTDepth == uiMaxDQPDepthQTBT && pps.getUseDQP()){setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}
#endif//对两个分块进行编码for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 2; uiPartUnitIdx++ ){if (uiPartUnitIdx==1){uiAbsPartIdx = g_auiRasterToZscan[g_auiZscanToRaster[uiAbsPartIdx] + (uiHeight>>1)/pcCU->getPic()->getMinCUHeight()*pcCU->getPic()->getNumPartInCtuWidth()];}
#if JVET_C0024_BT_RMV_REDUNDANTxEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth, uiHeight>>1, uiSplitConstrain );if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth+1) == 2 && bBTHorRmvEnable && uiPartUnitIdx==0){uiSplitConstrain = 2;}
#elsexEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth, uiHeight>>1 );
#endif}return;}//二叉树划分模式为2,纵向划分else if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth)==2){
#if JVET_C0024_DELTA_QP_FIXif( uiQTBTDepth == uiMaxDQPDepthQTBT && pps.getUseDQP()){setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}
#endiffor ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 2; uiPartUnitIdx++ ){if (uiPartUnitIdx==1){uiAbsPartIdx = g_auiRasterToZscan[g_auiZscanToRaster[uiAbsPartIdx] + (uiWidth>>1)/pcCU->getPic()->getMinCUWidth()];}
#if JVET_C0024_BT_RMV_REDUNDANTxEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth>>1, uiHeight, uiSplitConstrain );if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth+1) == 1 && bBTVerRmvEnable && uiPartUnitIdx==0){uiSplitConstrain = 1;}
#elsexEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth>>1, uiHeight );
#endif}return;}}pcCU->getPic()->addCodedAreaInCTU(uiWidth*uiHeight);UInt uiBlkX = g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ] >> MIN_CU_LOG2;UInt uiBlkY = g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ] >> MIN_CU_LOG2;pcCU->getPic()->setCodedBlkInCTU(true, uiBlkX, uiBlkY, uiWidth>> MIN_CU_LOG2, uiHeight>> MIN_CU_LOG2);#endif#if JVET_C0024_AMAX_BTif (!pcCU->getSlice()->isIntra()){g_uiBlkSize[pcCU->getSlice()->getDepth()] += uiWidth*uiHeight;g_uiNumBlk[pcCU->getSlice()->getDepth()]++;}
#endif
#if JVET_C0024_DELTA_QP_FIXif( uiQTBTDepth <= uiMaxDQPDepthQTBT && pps.getUseDQP())
#elseif( uiDepth <= pps.getMaxCuDQPDepth() && pps.getUseDQP())
#endif{setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}//编码其他flagif( uiDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj()){setCodeChromaQpAdjFlag(true);}if (pps.getTransquantBypassEnableFlag()){m_pcEntropyCoder->encodeCUTransquantBypassFlag( pcCU, uiAbsPartIdx );}if( !pcSlice->isIntra() ){m_pcEntropyCoder->encodeSkipFlag( pcCU, uiAbsPartIdx );}if( pcCU->isSkipped( uiAbsPartIdx ) ){
#if VCEG_AZ07_FRUC_MERGEm_pcEntropyCoder->encodeFRUCMgrMode( pcCU , uiAbsPartIdx , 0 );if( !pcCU->getFRUCMgrMode( uiAbsPartIdx ) )
#endif
#if COM16_C1016_AFFINE{if ( pcCU->isAffineMrgFlagCoded(uiAbsPartIdx, 0) ){m_pcEntropyCoder->encodeAffineFlag( pcCU, uiAbsPartIdx, 0 );}if ( !pcCU->isAffine(uiAbsPartIdx) ){m_pcEntropyCoder->encodeMergeIndex( pcCU, uiAbsPartIdx );}}
#elsem_pcEntropyCoder->encodeMergeIndex( pcCU, uiAbsPartIdx );
#endif
#if VCEG_AZ06_ICm_pcEntropyCoder->encodeICFlag  ( pcCU, uiAbsPartIdx );
#endif
#if !JVET_C0024_QTBTfinishCU(pcCU,uiAbsPartIdx);
#endif
#if JVET_C0024_DELTA_QP_FIXif( pps.getUseDQP() ){ pcCU->setCodedQP( pcCU->getQP(uiAbsPartIdx) );}
#endifreturn;}m_pcEntropyCoder->encodePredMode( pcCU, uiAbsPartIdx );
#if JVET_C0024_QTBTif (isLuma(pcCU->getTextType())){
#endif
#if VCEG_AZ05_INTRA_MPIm_pcEntropyCoder->encodeMPIIdx(pcCU, uiAbsPartIdx);
#endif
#if COM16_C1046_PDPC_INTRA && !JVET_G0104_PLANAR_PDPCm_pcEntropyCoder->encodePDPCIdx(pcCU, uiAbsPartIdx);
#endif
#if JVET_C0024_QTBT}
#elsem_pcEntropyCoder->encodePartSize( pcCU, uiAbsPartIdx, uiDepth );
#endif#if JVET_C0024_QTBTif (pcCU->isIntra( uiAbsPartIdx ) )
#elseif (pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N )
#endif{m_pcEntropyCoder->encodeIPCMInfo( pcCU, uiAbsPartIdx );if(pcCU->getIPCMFlag(uiAbsPartIdx)){
#if !JVET_C0024_QTBT// Encode slice finishfinishCU(pcCU,uiAbsPartIdx);
#endif
#if JVET_C0024_DELTA_QP_FIXif( pps.getUseDQP() ){ pcCU->setCodedQP( pcCU->getQP(uiAbsPartIdx) );}
#endifreturn;}}// prediction Info ( Intra : direction mode, Inter : Mv, reference idx )m_pcEntropyCoder->encodePredInfo( pcCU, uiAbsPartIdx );
#if COM16_C806_OBMCm_pcEntropyCoder->encodeOBMCFlag( pcCU, uiAbsPartIdx );
#endif
#if VCEG_AZ06_ICm_pcEntropyCoder->encodeICFlag  ( pcCU, uiAbsPartIdx );
#endif// Encode CoefficientsBool bCodeDQP = getdQPFlag();Bool codeChromaQpAdj = getCodeChromaQpAdjFlag();
#if  VCEG_AZ05_ROT_TR  || VCEG_AZ05_INTRA_MPI || COM16_C1044_NSST || COM16_C1046_PDPC_INTRAInt bNonZeroCoeff = false;
#endif
#if JVET_C0045_C0053_NO_NSST_FOR_TSInt iNonZeroCoeffNonTs;
#endifm_pcEntropyCoder->encodeCoeff( pcCU, uiAbsPartIdx, uiDepth, bCodeDQP, codeChromaQpAdj
#if VCEG_AZ05_ROT_TR  || VCEG_AZ05_INTRA_MPI || COM16_C1044_NSST || COM16_C1046_PDPC_INTRA, bNonZeroCoeff
#endif
#if JVET_C0045_C0053_NO_NSST_FOR_TS, iNonZeroCoeffNonTs
#endif);setCodeChromaQpAdjFlag( codeChromaQpAdj );setdQPFlag( bCodeDQP );
#if JVET_C0024_DELTA_QP_FIXif( pps.getUseDQP() ){ pcCU->setCodedQP( pcCU->getQP(uiAbsPartIdx) );}
#endif#if !JVET_C0024_QTBT// --- write terminating bit ---finishCU(pcCU,uiAbsPartIdx);
#endif
}

H.266代码学习:xEncodeCU函数相关推荐

  1. H.266代码学习:decodeCtu和xDecodeCU函数

    之前 HEVC代码学习39:decodeCtu和xDecodeCU函数 中对HM中的CTU解码函数进行了学习,这里来学习一下JEM中的. 首先需要强调的是,这里只是用来解码flag.系数等,没有进行预 ...

  2. H.266代码学习:decompressCtu和xDecompressCU函数

    今天来学习一下JEM的decompressCtu和xDecompressCU函数.之前在 H.266代码学习:decodeCtu和xDecodeCU函数 学习了的学习中提到,decodeCtu和xDe ...

  3. H.266代码学习:xIntraCodingTUBlock函数

    今天来继续学习帧内编码的重要函数xIntraCodingTUBlock,上次 H.266代码学习:xRecurIntraCodingLumaQT函数 学习中提到,xIntraCodingTUBlock ...

  4. H.266代码学习:estIntraPredLumaQT函数

    之前 HEVC代码学习42:estIntraPredLumaQT函数 对HM中的estIntraPredLumaQT函数进行了学习,下面将对JEM中的该函数进行学习. estIntraPredLuma ...

  5. H.266代码学习:JEM使用方法

    之前在HEVC代码学习0:HM使用+码流分析教程中详细介绍了HM使用方法,而H.266参考代码JEM已经成型,因此这里简单介绍下JEM的使用方法. 阅读建议: JEM使用方法与HM类似,使用中改动在于 ...

  6. VVC/H.266代码阅读(VTM8.0)(三. Slice到CTU的处理 )

    本文是本系列的第三篇博客,内容是分析从Slice到CTU的处理代码. 该系列相关博客为: VVC/H.266代码阅读(VTM8.0)(一. NALU提取) VVC/H.266代码阅读(VTM8.0)( ...

  7. AV1代码学习:函数encode_frame和aom_codec_encode

    1.encode_frame函数 在编码端aomenc.c的main函数中,在进入编码过程循环后,循环读取视频的每一帧数据,然后通过encode_frame函数对每一帧进行编码. encode_fra ...

  8. H.266/VVC代码学习:帧内预测之角度预测函数(predIntraAng、xPredIntraAng)

    predIntraAng函数 VTM中,帧内预测的角度预测的入口函数为predIntraAng函数,该函数主要是用于进行传统的帧内预测(Planar.DC.角度预测),然后对Planar和DC模式使用 ...

  9. H.266/VVC-VTM代码学习27-VTM中编码器主函数逻辑

    H.266/VVC专栏传送 上一篇:H.266/VVC-VTM代码学习26-VTM中RDcost的计算与λ的设定(二) 下一篇:持续创作中- 目录 H.266/VVC专栏传送 前言 一.简介 二.代码 ...

最新文章

  1. UVA 116 Unidirectional TSP DP
  2. mysqlls_mysql基本命令
  3. flutter开发环境搭建
  4. OpenStack工作流服务Mistral简介
  5. 干货!华为AutoML助力AI开发效率提升攻略
  6. 从KDD 2018最佳论文看Airbnb实时搜索排序中的Embedding技巧
  7. SpringBoot整合 ActiveMQ、SpringBoot整合RabbitMQ、SpringBoot整合Kafka
  8. 【计算机组成原理】计算机软硬件组成
  9. IO模型(epoll)--详解-01
  10. Tomcat的虚拟目录映射常用的几种方式
  11. RHCE-PXE无人值守装机一
  12. 如何通过手机访问本地编写的html页面
  13. Python模块的导入
  14. 中英文字体对照表-参考
  15. 电脑 Google浏览器 截长屏 无任何辅助软件
  16. 互联网发展的四个阶段
  17. 众包中真值推断的随机猜测和任务难度建模
  18. Iphone 苹果手机HEIC照片格式 win10电脑打开 解决方案
  19. 聊一聊Java中的线程中断
  20. python虚拟机:pvm

热门文章

  1. 采用 NVIDIA DGX A100 系统和 Mellanox 频谱以太网交换机的 NetApp ONTAP AI NVA 设计(上)
  2. ai人工智能将替代人类_急于将AI推向极限
  3. “AI 终有可能消灭人类!”
  4. javascript---window.createPopup
  5. 【SQL】数据筛选过滤(初级)
  6. Python中time模块的用法
  7. Linux SSH免密码登录与拷贝文件(SCP)
  8. 终其一生,你不会因为优秀而被爱
  9. After Effects (AE)2021软件下载及安装教程。
  10. 浅谈 JSON stringify 方法