<div>A generic function copyFrom() will copy MAX_OFF_CTX_MOD bytes values, which MAX_OFF_CTX_MOD == 157, but SAO only need two bytes, </div><div>load function in release mode, we can get its disassembly code of memcpy:</div><div><br></div><div><div><div>void Entropy::copyFrom(const Entropy& src)</div><div>{</div><div>    X265_CHECK(src.m_valid, "invalid copy source context\n");</div><div><br></div><div>    copyState(src);</div><div>000000013F4334D0  mov         eax,dword ptr [rdx+0B0h]  </div><div>000000013F4334D6  mov         dword ptr [rcx+0B0h],eax  </div><div>000000013F4334DC  mov         eax,dword ptr [rdx+0B4h]  </div><div>000000013F4334E2  mov         dword ptr [rcx+0B4h],eax  </div><div>000000013F4334E8  mov         eax,dword ptr [rdx+0C0h]  </div><div>000000013F4334EE  mov         dword ptr [rcx+0C0h],eax  </div><div>000000013F4334F4  mov         eax,dword ptr [rdx+0B8h]  </div><div>000000013F4334FA  mov         dword ptr [rcx+0B8h],eax  </div><div>000000013F433500  mov         eax,dword ptr [rdx+0BCh]  </div><div>000000013F433506  mov         dword ptr [rcx+0BCh],eax  </div><div>000000013F43350C  mov         rax,qword ptr [rdx+0C8h]  </div><div>000000013F433513  mov         qword ptr [rcx+0C8h],rax  </div><div><br></div><div>    memcpy(m_contextState, src.m_contextState, MAX_OFF_CTX_MOD * sizeof(uint8_t));</div><div>000000013F43351A  movups      xmm0,xmmword ptr [rdx+10h]  </div><div>000000013F43351E  movups      xmmword ptr [rcx+10h],xmm0  </div><div>000000013F433522  movups      xmm1,xmmword ptr [rdx+20h]  </div><div>000000013F433526  movups      xmmword ptr [rcx+20h],xmm1  </div><div>000000013F43352A  movups      xmm0,xmmword ptr [rdx+30h]  </div><div>000000013F43352E  movups      xmmword ptr [rcx+30h],xmm0  </div><div>000000013F433532  movups      xmm1,xmmword ptr [rdx+40h]  </div><div>000000013F433536  movups      xmmword ptr [rcx+40h],xmm1  </div><div>000000013F43353A  movups      xmm0,xmmword ptr [rdx+50h]  </div><div>000000013F43353E  movups      xmmword ptr [rcx+50h],xmm0  </div><div>000000013F433542  movups      xmm1,xmmword ptr [rdx+60h]  </div><div>000000013F433546  movups      xmmword ptr [rcx+60h],xmm1  </div><div>000000013F43354A  movups      xmm0,xmmword ptr [rdx+70h]  </div><div>000000013F43354E  movups      xmmword ptr [rcx+70h],xmm0  </div><div>000000013F433552  movups      xmm1,xmmword ptr [rdx+80h]  </div><div>000000013F433559  movups      xmmword ptr [rcx+80h],xmm1  </div><div>000000013F433560  movups      xmm0,xmmword ptr [rdx+90h]  </div><div>000000013F433567  movups      xmmword ptr [rcx+90h],xmm0  </div><div>000000013F43356E  movsd       xmm1,mmword ptr [rdx+0A0h]  </div><div>000000013F433576  movsd       mmword ptr [rcx+0A0h],xmm1  </div><div>000000013F43357E  mov         eax,dword ptr [rdx+0A8h]  </div><div>000000013F433584  mov         dword ptr [rcx+0A8h],eax  </div><div>000000013F43358A  movzx       eax,byte ptr [rdx+0ACh]  </div><div>000000013F433591  mov         byte ptr [rcx+0ACh],al  </div><div>    markValid();</div><div>}</div></div><div><br></div><div>We can see that, VC++ compiler will get a lot of movups to copy data. We can also get loadSAO disassembly code:</div><div><br></div><div>void Entropy::copyFromSAO(const Entropy& src)</div><div><div>{</div><div>    X265_CHECK(src.m_valid, "invalid copy source context\n");</div><div><br></div><div>    copyState(src);</div><div>000000013F4335A0  mov         eax,dword ptr [rdx+0B0h]  </div><div>000000013F4335A6  mov         dword ptr [rcx+0B0h],eax  </div><div>000000013F4335AC  mov         eax,dword ptr [rdx+0B4h]  </div><div>000000013F4335B2  mov         dword ptr [rcx+0B4h],eax  </div><div>000000013F4335B8  mov         eax,dword ptr [rdx+0C0h]  </div><div>000000013F4335BE  mov         dword ptr [rcx+0C0h],eax  </div><div>000000013F4335C4  mov         eax,dword ptr [rdx+0B8h]  </div><div>000000013F4335CA  mov         dword ptr [rcx+0B8h],eax  </div><div>000000013F4335D0  mov         eax,dword ptr [rdx+0BCh]  </div><div>000000013F4335D6  mov         dword ptr [rcx+0BCh],eax  </div><div>000000013F4335DC  mov         rax,qword ptr [rdx+0C8h]  </div><div>000000013F4335E3  mov         qword ptr [rcx+0C8h],rax  </div><div><br></div><div>    // only copy OFF_SAO_MERGE_FLAG_CTX and OFF_SAO_TYPE_IDX_CTX, two bytes</div><div>    uint16_t* srcEntropy = (uint16_t*)(src.m_contextState + OFF_SAO_MERGE_FLAG_CTX);</div><div>    uint16_t* dstEntropy = (uint16_t*)(m_contextState + OFF_SAO_MERGE_FLAG_CTX);</div><div>    *dstEntropy = *srcEntropy;</div><div>000000013F4335EA  movzx       eax,word ptr [rdx+0A8h]  </div><div>000000013F4335F1  mov         word ptr [rcx+0A8h],ax  </div><div>    markValid();</div><div>}</div></div><div><br></div><div>We can see that only one movzx and one mov instruction as only copy two bytes.</div><div><br></div><div style="font-size: 12px;font-family: Arial Narrow;padding:2px 0 2px 0;">------------------ Original ------------------</div><div style="font-size: 12px;background:#efefef;padding:8px;"><div><b>From: </b> "Ashok Kumar Mishra";<ashok@multicorewareinc.com>;</div><div><b>Date: </b> Mon, Nov 20, 2017 05:27 PM</div><div><b>To: </b> "Development for x265"<x265-devel@videolan.org>;<wbr></div><div></div><div><b>Subject: </b> Re: [x265] [PATCH] sao: only load/save entropy state of sao whenapplying sao</div></div><div><br></div><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Nov 18, 2017 at 6:25 PM, Ximing Cheng <span dir="ltr"><<a href="mailto:chengximing1989@foxmail.com" target="_blank">chengximing1989@foxmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Ximing Cheng <<a href="mailto:ximingcheng@tencent.com" target="_blank">ximingcheng@tencent.com</a>><br>
# Date 1511009612 -28800<br>
#      Sat Nov 18 20:53:32 2017 +0800<br>
# Node ID a5b805430a4b0cb797604ab7f01765<wbr>38d93e8d9d<br>
# Parent  06979c0423504a324ea05ca3de5976<wbr>9c6d0fba0d<br>
sao: only load/save entropy state of sao when applying sao<br>
<br>
diff -r 06979c042350 -r a5b805430a4b source/encoder/entropy.cpp<br>
--- a/source/encoder/entropy.cpp        Thu Nov 16 20:23:14 2017 +0530<br>
+++ b/source/encoder/entropy.cpp        Sat Nov 18 20:53:32 2017 +0800<br>
@@ -1506,6 +1506,19 @@<br>
     markValid();<br>
 }<br>
<br></blockquote><div>We use a generic function copyFrom() for loading and storing the context during analysis. copyFrom() use memcopy(), so it is faster.</div><div>It is not much beneficial for writing a separate function for SAO, though only two bytes are changing. </div><div>  </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+void Entropy::copyFromSAO(const Entropy& src)<br>
+{<br>
+    X265_CHECK(src.m_valid, "invalid copy source context\n");<br>
+<br>
+    copyState(src);<br>
+<br>
+    // only copy OFF_SAO_MERGE_FLAG_CTX and OFF_SAO_TYPE_IDX_CTX, two bytes<br>
+    uint16_t* srcEntropy = (uint16_t*)(src.m_contextState + OFF_SAO_MERGE_FLAG_CTX);<br>
+    uint16_t* dstEntropy = (uint16_t*)(m_contextState + OFF_SAO_MERGE_FLAG_CTX);<br>
+    *dstEntropy = *srcEntropy;<br>
+    markValid();<br>
+}<br>
+<br></blockquote><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 void Entropy::codePartSize(const CUData& cu, uint32_t absPartIdx, uint32_t depth)<br>
 {<br>
     PartSize partSize = (PartSize)cu.m_partSize[absPar<wbr>tIdx];<br>
diff -r 06979c042350 -r a5b805430a4b source/encoder/entropy.h<br>
--- a/source/encoder/entropy.h  Thu Nov 16 20:23:14 2017 +0530<br>
+++ b/source/encoder/entropy.h  Sat Nov 18 20:53:32 2017 +0800<br>
@@ -136,7 +136,9 @@<br>
<br>
     // SBAC RD<br>
     void load(const Entropy& src)            { copyFrom(src); }<br>
+    void loadSAO(const Entropy& src)         { copyFromSAO(src); }<br>
     void store(Entropy& dest) const          { dest.copyFrom(*this); }<br>
+    void storeSAO(Entropy& dest) const       { dest.copyFromSAO(*this); }<br>
     void loadContexts(const Entropy& src)    { copyContextsFrom(src); }<br>
     void loadIntraDirModeLuma(const Entropy& src);<br>
     void copyState(const Entropy& other);<br>
@@ -254,6 +256,7 @@<br>
                          bool& bCodeDQP, const uint32_t depthRange[2]);<br>
<br>
     void copyFrom(const Entropy& src);<br>
+    void copyFromSAO(const Entropy& src);<br>
     void copyContextsFrom(const Entropy& src);<br>
 };<br>
 }<br>
diff -r 06979c042350 -r a5b805430a4b source/encoder/sao.cpp<br>
--- a/source/encoder/sao.cpp    Thu Nov 16 20:23:14 2017 +0530<br>
+++ b/source/encoder/sao.cpp    Sat Nov 18 20:53:32 2017 +0800<br>
@@ -242,9 +242,9 @@<br>
         break;<br>
     }<br>
<br>
-    m_entropyCoder.load(initState)<wbr>;<br>
-    m_rdContexts.next.load(initSta<wbr>te);<br>
-    m_rdContexts.cur.load(initStat<wbr>e);<br>
+    m_entropyCoder.loadSAO(initSta<wbr>te);<br>
+    m_rdContexts.next.loadSAO(init<wbr>State);<br>
+    m_rdContexts.cur.loadSAO(initS<wbr>tate);<br>
<br>
     SAOParam* saoParam = frame->m_encData->m_saoParam;<br>
     if (!saoParam)<br>
@@ -1262,13 +1262,13 @@<br>
     for (int i = 0; i < planes; i++)<br>
         saoParam->ctuParam[i][addr].r<wbr>eset();<br>
     // SAO distortion calculation<br>
-    m_entropyCoder.load(m_rdContex<wbr>ts.cur);<br>
+    m_entropyCoder.loadSAO(m_rdCon<wbr>texts.cur);<br>
     m_entropyCoder.resetBits();<br>
     if (allowMerge[0])<br>
         m_entropyCoder.codeSaoMerge(<wbr>0);<br>
     if (allowMerge[1])<br>
         m_entropyCoder.codeSaoMerge(<wbr>0);<br>
-    m_entropyCoder.store(m_rdConte<wbr>xts.temp);<br>
+    m_entropyCoder.storeSAO(m_rdCo<wbr>ntexts.temp);<br>
     memset(m_offset, 0, sizeof(m_offset));<br>
     int64_t bestCost = 0;<br>
     int64_t rateDist = 0;<br>
@@ -1333,7 +1333,7 @@<br>
                 mergeDist += (estDist << 8) / lambda[!!plane];<br>
             }<br>
<br>
-            m_entropyCoder.load(m_rdContex<wbr>ts.cur);<br>
+            m_entropyCoder.loadSAO(m_rdCon<wbr>texts.cur);<br>
             m_entropyCoder.resetBits();<br>
             if (allowMerge[0])<br>
                 m_entropyCoder.codeSaoMerge(1 - mergeIdx);<br>
@@ -1346,7 +1346,7 @@<br>
             {<br>
                 SaoMergeMode mergeMode = mergeIdx ? SAO_MERGE_UP : SAO_MERGE_LEFT;<br>
                 bestCost = mergeCost;<br>
-                m_entropyCoder.store(m_rdConte<wbr>xts.temp);<br>
+                m_entropyCoder.storeSAO(m_rdCo<wbr>ntexts.temp);<br>
                 for (int plane = 0; plane < planes; plane++)<br>
                 {<br>
                     if (saoParam->bSaoFlag[plane > 0])<br>
@@ -1368,8 +1368,8 @@<br>
             m_numNoSao[0]++;<br>
         if (chroma && saoParam->ctuParam[1][addr].ty<wbr>peIdx < 0)<br>
             m_numNoSao[1]++;<br>
-        m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
-        m_entropyCoder.store(m_rdConte<wbr>xts.cur);<br>
+        m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
+        m_entropyCoder.storeSAO(m_rdCo<wbr>ntexts.cur);<br>
     }<br>
 }<br>
<br>
@@ -1488,7 +1488,7 @@<br>
     int64_t costClasses[MAX_NUM_SAO_CLASS]<wbr>;<br>
<br>
     // RDO SAO_NA<br>
-    m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+    m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
     m_entropyCoder.resetBits();<br>
     m_entropyCoder.codeSaoType(0)<wbr>;<br>
     int64_t costPartBest = calcSaoRdoCost(0, m_entropyCoder.getNumberOfWrit<wbr>tenBits(), lambda[0]);<br>
@@ -1518,7 +1518,7 @@<br>
             estDist += distClasses[classIdx];<br>
         }<br>
<br>
-        m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+        m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
         m_entropyCoder.resetBits();<br>
         m_entropyCoder.codeSaoOffsetE<wbr>O(m_offset[0][typeIdx] + 1, typeIdx, 0);<br>
<br>
@@ -1576,7 +1576,7 @@<br>
     for (int classIdx = bestClassBO; classIdx < bestClassBO + SAO_NUM_OFFSET; classIdx++)<br>
         estDist += distClasses[classIdx];<br>
<br>
-    m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+    m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
     m_entropyCoder.resetBits();<br>
     m_entropyCoder.codeSaoOffsetB<wbr>O(m_offset[0][SAO_BO] + bestClassBO, bestClassBO, 0);<br>
<br>
@@ -1595,9 +1595,9 @@<br>
     }<br>
<br>
     rateDist = (bestDist << 8) / lambda[0];<br>
-    m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+    m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
     m_entropyCoder.codeSaoOffset(<wbr>*lclCtuParam, 0);<br>
-    m_entropyCoder.store(m_rdConte<wbr>xts.temp);<br>
+    m_entropyCoder.storeSAO(m_rdCo<wbr>ntexts.temp);<br>
<br>
     if (m_param->internalCsp == X265_CSP_I400)<br>
     {<br>
@@ -1616,7 +1616,7 @@<br>
     int32_t distClasses[MAX_NUM_SAO_CLASS]<wbr>;<br>
     int32_t bestClassBO[2] = { 0, 0 };<br>
<br>
-    m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+    m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
     m_entropyCoder.resetBits();<br>
     m_entropyCoder.codeSaoType(0)<wbr>;<br>
<br>
@@ -1651,7 +1651,7 @@<br>
             }<br>
         }<br>
<br>
-        m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+        m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
         m_entropyCoder.resetBits();<br>
<br>
         for (int compIdx = 0; compIdx < 2; compIdx++)<br>
@@ -1715,7 +1715,7 @@<br>
             estDist[compIdx - 1] += distClasses[classIdx];<br>
     }<br>
<br>
-    m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+    m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
     m_entropyCoder.resetBits();<br>
<br>
     for (int compIdx = 0; compIdx < 2; compIdx++)<br>
@@ -1740,13 +1740,13 @@<br>
     }<br>
<br>
     rateDist += (bestDist << 8) / lambda[1];<br>
-    m_entropyCoder.load(m_rdContex<wbr>ts.temp);<br>
+    m_entropyCoder.loadSAO(m_rdCon<wbr>texts.temp);<br>
<br>
     if (saoParam->bSaoFlag[1])<br>
     {<br>
         m_entropyCoder.codeSaoOffset(<wbr>*lclCtuParam[0], 1);<br>
         m_entropyCoder.codeSaoOffset(<wbr>*lclCtuParam[1], 2);<br>
-        m_entropyCoder.store(m_rdConte<wbr>xts.temp);<br>
+        m_entropyCoder.storeSAO(m_rdCo<wbr>ntexts.temp);<br>
<br>
         uint32_t rate = m_entropyCoder.getNumberOfWrit<wbr>tenBits();<br>
         bestCost = rateDist + rate;<br>
<br>
<br>
______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/l<wbr>istinfo/x265-devel</a><br>
</blockquote></div><br></div></div></div>