VTM2.0中的wpp(波前并行处理)阅读

似乎vtm比较后期的版本就不支持wpp了,不知道为啥。。并行的算法vvenc实现的已经很好了,但科研需要,还是决定优化vtm的wpp算法

修改配置

首先修改CMakeLists.txt,把ENABLE_WPP_PARALLELISM打开

set( SET_ENABLE_WPP_PARALLELISM   ON CACHE BOOL "Set ENABLE_WPP_PARALLELISM as a compiler flag" )
set( ENABLE_WPP_PARALLELISM       ON CACHE BOOL "If SET_ENABLE_WPP_PARALLELISM is on, it will be set to this value" )

编码指令:

./bin/EncoderAppStatic -c ./cfg/encoder_intra_vtm.cfg -q 37 -wdt 1280 -hgt 720 -fr 60 -i ~/yuv/KristenAndSara_1280x720_60.yuv -f 32 --InputBitDepth=8 --OutputBitDepth=8 --InputChromaFormat=420 -o /dev/null -b /dev/null --NumWppThreads=5 --AltDQPCoding

代码

和wpp相关的代码搜索ENABLE_WPP_PARALLELISM就可以找到。接下来介绍几块重要的代码

  1. 分配任务
    schedule(static,1)指给每个线程轮流分配固定的一行ctu(比如有三个线程,那么第一个线程会被分配第0,3,6…行的ctu)?setWppThreadId的代码是这样的:void Scheduler::setSplitThreadId( const int tId ) {g_splitThreadId = tId == CURR_THREAD_ID ? omp_get_thread_num() : tId; },所以每个线程的g_splitThreadId就是它的线程号
#if ENABLE_WPP_PARALLELISM
  bool bUseThreads = m_pcCfg->getNumWppThreads() > 1;
  if( bUseThreads )
  {
    CHECK( startCtuTsAddr != 0 || boundingCtuTsAddr != pcPic->cs->pcv->sizeInCtus, "not intended" );

    pcPic->cs->allocateVectorsAtPicLevel();

    omp_set_num_threads( m_pcCfg->getNumWppThreads() + m_pcCfg->getNumWppExtraLines() );

    #pragma omp parallel for schedule(static,1) if(bUseThreads)
    for( int ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ctuTsAddr += widthInCtus )
    {
      // wpp thread start
      pcPic->scheduler.setWppThreadId();
#if ENABLE_SPLIT_PARALLELISM
      pcPic->scheduler.setSplitThreadId( 0 );
#endif
      encodeCtus( pcPic, bCompressEntireSlice, bFastDeltaQP, ctuTsAddr, ctuTsAddr + widthInCtus, m_pcLib );
      // wpp thread stop
    }
  }
  else
#endif
  1. 两个ctu行之间的同步
    在ctu编码前,EncSlice.cpp中有
pcPic->scheduler.wait( ctuXPosInCtus, ctuYPosInCtus );

scheduler.wait函数是这样的,在Picture.cpp中。正如wpp的定义一样,它要等上一行右上方的ctu编码完毕。这里的m_SyncObjs也是在Picture.cpp中用mutex实现的一个东西

void Scheduler::wait( const int ctuPosX, const int ctuPosY )
{
  if( m_numWppThreads == m_numWppDataInstances )
  {
    if( ctuPosY > 0 && ctuPosX+1 < m_ctuXsize)
    {
      m_SyncObjs[ctuPosY-1]->wait( ctuPosX+1, ctuPosY-1 );
    }
    return;
  }
  m_SyncObjs[ctuPosY]->wait( ctuPosX, ctuPosY );
}

那什么时候wait结束呢?EncSlice.cpp中每个ctu编码结束后,都会调用

pcPic->scheduler.setReady( ctuXPosInCtus, ctuYPosInCtus );
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值