M-HT
Very Active Member
Yes.By CPU you mean DSP, right?
I'll try to test changing priority and read rate, if it makes any difference.At least in the last version ("scaling from L1DSRAM to L1DSRAM"), the DMA priority shouldn't matter since the RAM is only accessed by the DMA, not the DSP.
If you want to try different DMA priorities, take a look at libc64_dsp/src/dma.c, around line 133. Changing the read rate (a few lines down) might also be interesting in case you worry about bus cycles.
Memory throughput may not be the bottleneck, but L1DSRAM accesses are faster than shared memory accesses. In Scale2x, the difference is 3 ms. So I think there should be bigger difference in 2xSaI.Earlier this evening I had a quick look at (one of the) 2xSAI implementations. It really contains a lot of branches so memory throughput most probably is not the bottleneck of that algorithm. The memory bandwidth used by the L1DSRAM-to-L1DSRAM version of your scaler is ~29.7 MB/sec for the reads, plus ~118.8 MB/sec for the writes (the highest write throughput for the DMA I measured so far is ~993 MB/sec (SRAM to mem. copy), resp. ~530 MB/sec (copy from RAM to SRAM via DMA, process in SRAM via DSP, then copy from SRAM back to RAM via DMA -- but this was with a very DSP-friendly, SP-looped routine)
The algorithm speed depends on the source image (due to the branches) so the times may differ for other source images.In the DSP version I tried removing the branches (only one if remained in the innermost loop), which is one of the reasons for the speed.In post #19 you said that the ARM version, which interestingly was faster than the NEON version, takes 6.6ms, so 5.17ms for the DSP version is still quite respectable, especially because of all the conditionals / branches.
Here's the innermost loop, if you're interested:
Code:
colorI = colorF;
colorE = colorJ;
colorJ = _amem4_const(src1);
src1+=2;
colorF = _packlh2(colorJ, colorE);
colorG = colorB;
colorA = colorK;
colorK = _amem4_const(src2);
src2+=2;
colorB = _packlh2(colorK, colorA);
colorH = colorD;
colorC = colorL;
colorL = _amem4_const(src3);
src3+=2;
colorD = _packlh2(colorL, colorC);
colorM = colorO;
colorO = _mem4_const(src4);
src4+=2;
colorN = _packlh2(colorO, colorM);
Mask1 = _xpnd2( ( _cmpeq2(colorA, colorD) & (~_cmpeq2(colorB, colorC)) & _cmpeq2(colorA, colorE) & _cmpeq2(colorB, colorL) ) |
( _cmpeq2(colorA, colorC) & _cmpeq2(colorA, colorF) & (~_cmpeq2(colorB, colorE)) & _cmpeq2(colorB, colorJ) ) );
Mask2 = _xpnd2( ( _cmpeq2(colorB, colorC) & (~_cmpeq2(colorA, colorD)) & _cmpeq2(colorB, colorF) & _cmpeq2(colorA, colorH) ) |
( _cmpeq2(colorB, colorE) & _cmpeq2(colorB, colorD) & (~_cmpeq2(colorA, colorF)) & _cmpeq2(colorA, colorI) ) );
product = (colorA & Mask1) | (colorB & Mask2) | (INTERPOLATE(colorA, colorB) & ~(Mask1 | Mask2));
_amem8(dst1) = _dpack2(product, colorA);
dst1+=4;
Mask1 = _xpnd2( ( _cmpeq2(colorA, colorD) & (~_cmpeq2(colorB, colorC)) & _cmpeq2(colorA, colorG) & _cmpeq2(colorC, colorO) ) |
( _cmpeq2(colorA, colorB) & _cmpeq2(colorA, colorH) & (~_cmpeq2(colorG, colorC)) & _cmpeq2(colorC, colorM) ) );
Mask2 = _xpnd2( ( _cmpeq2(colorB, colorC) & (~_cmpeq2(colorA, colorD)) & _cmpeq2(colorC, colorH) & _cmpeq2(colorA, colorF) ) |
( _cmpeq2(colorC, colorG) & _cmpeq2(colorC, colorD) & (~_cmpeq2(colorA, colorH)) & _cmpeq2(colorA, colorI) ) );
product1 = (colorA & Mask1) | (colorC & Mask2) | (INTERPOLATE(colorA, colorC) & ~(Mask1 | Mask2));
Mask1 = _xpnd2( ( _cmpeq2(colorA, colorD) & (~_cmpeq2(colorB, colorC)) ) |
( _cmpeq2(colorA, colorD) & _cmpeq2(colorB, colorC) & _cmpeq2(colorA, colorB) ) );
Mask2 = _xpnd2( ( _cmpeq2(colorB, colorC) & (~_cmpeq2(colorA, colorD)) ) |
( _cmpeq2(colorB, colorC) & _cmpeq2(colorA, colorD) & _cmpeq2(colorA, colorB) ) );
Mask3 = _xpnd2( _cmpeq2(colorA, colorD) & _cmpeq2(colorB, colorC) & (~_cmpeq2(colorA, colorB)) );
if ( Mask3 )
{
r = _xpnd2( _cmpeq2(colorA, colorG) & _cmpeq2(colorA, colorE) );
r = _sub2(r, _xpnd2( _cmpeq2(colorB, colorG) & _cmpeq2(colorB, colorE) & (~_cmpeq2(colorA, colorG)) & (~_cmpeq2(colorA, colorE)) ) );
r = _sub2(r, _xpnd2( _cmpeq2(colorB, colorK) & _cmpeq2(colorB, colorF) ) );
r = _add2(r, _xpnd2( _cmpeq2(colorA, colorK) & _cmpeq2(colorA, colorF) & (~_cmpeq2(colorB, colorK)) & (~_cmpeq2(colorB, colorF)) ) );
r = _sub2(r, _xpnd2( _cmpeq2(colorB, colorH) & _cmpeq2(colorB, colorN) ) );
r = _add2(r, _xpnd2( _cmpeq2(colorA, colorH) & _cmpeq2(colorA, colorN) & (~_cmpeq2(colorB, colorH)) & (~_cmpeq2(colorB, colorN)) ) );
r = _add2(r, _xpnd2( _cmpeq2(colorA, colorL) & _cmpeq2(colorA, colorO) ) );
r = _sub2(r, _xpnd2( _cmpeq2(colorB, colorL) & _cmpeq2(colorB, colorO) & (~_cmpeq2(colorA, colorL)) & (~_cmpeq2(colorA, colorO)) ) );
Mask1 |= _xpnd2( _cmpgt2(r, 0) ) & Mask3;
Mask2 |= _xpnd2( _cmpgt2(0, r) ) & Mask3;
}
product2 = (colorA & Mask1) | (colorB & Mask2) | (Q_INTERPOLATE(colorA, colorB, colorC, colorD) & ~(Mask1 | Mask2));
_amem8(dst2) = _dpack2(product2, product1);
dst2+=4;