Arm 运行长度编码-SIMD

Arm 运行长度编码-SIMD,arm,jpeg,simd,neon,run-length-encoding,Arm,Jpeg,Simd,Neon,Run Length Encoding,我试图优化运行长度编码。我正在考虑在SIMD中实现它。我花了几个小时在algo上,但进展不大。值得一试吗?我正在制作霓虹灯 谢谢 我假设您的问题是JPEG中AC块系数编码中的RLE 在JPEG中使用的RLE变体非常具体。每个8x8像素的块用DCT变换并量化。然后针对第一个DC系数和63个AC系数分离DCT输出(64个系数)。8x8块AC coefs使用之字形模式转换为线性阵列,然后进行RLE编码 ZigZag通常与RLE run相结合,因此我们有具有非线性内存访问的RLE,并且应该优化这两个功

我试图优化运行长度编码。我正在考虑在SIMD中实现它。我花了几个小时在algo上,但进展不大。值得一试吗?我正在制作霓虹灯


谢谢

我假设您的问题是JPEG中AC块系数编码中的RLE

在JPEG中使用的RLE变体非常具体。每个8x8像素的块用DCT变换并量化。然后针对第一个DC系数和63个AC系数分离DCT输出(64个系数)。8x8块AC coefs使用之字形模式转换为线性阵列,然后进行RLE编码

ZigZag通常与RLE run相结合,因此我们有具有非线性内存访问的RLE,并且应该优化这两个功能

警告!JPEG中的RLE仅用于零元素!,检查F.1.2.2.1和标准

一些实现:

有(主页是),其中一些分支是由Linaro在2010-2011年为ARM提供的

这个叉子里有:

  • “前向离散余弦变换”中量化码的10臂霓虹灯优化(整数除法替换为浮点乘法)……此优化函数现在比原始C变量快近3倍-jcdctmgr.C-Siarhei Siamashka 2010-11-10
  • 9-针对“encode_one_block”的ARM组件优化(针对“encode_one_block”的ARM组件优化。比原始C变体快近2倍)-jchuff.C-Siarhei Siamashka 2010-11-10
  • 8臂霓虹灯“rgb_ycc_convert”的优化版本-Siarhei Siamashka 2010-11-10
  • 7臂霓虹灯“ycc_rgb_convert”的优化版本-Siarhei Siamashka 2010-11-10
  • 6.“convsamp”的小臂霓虹灯优化-Siarhei Siamashka 2010-11-10
  • 5臂霓虹灯优化版“jpeg_fdct_ifast”-Siarhei Siamashka 2010-11-10
  • 4臂霓虹灯“jpeg_idct_ifast”的优化版本-Siarhei Siamashka 2010-11-10
  • 3臂霓虹灯优化版“jpeg_idct_4x4”-Siarhei Siamashka 2010-11-10
was ARM优化了
jchuff.c
文件,用于函数
encode_one_block
,该函数对块的AC和DC分量进行编码;但它是在不使用NEON的情况下完成的

/* Encode a single block's worth of coefficients */
LOCAL(boolean)   encode_one_block 
事实上,RLE并没有得到优化;但在ARM组件中的
find_last_nonzero_index
helper函数中实现了锯齿形和最后零coef检测。(它是使用生成的)或。它计划用于双重问题Cortex-A8:

* Find last nonzero coefficient and produce output in natural order,
* instructions are scheduled to make use of ARM Cortex-A8 dual-issue
* capability
这是相应的函数C代码:

LOCAL(int)
find_last_nonzero_index (JCOEFPTR block, JCOEFPTR out)
{
  int tmp, i, n = 0;
  for (i = 1; i < DCTSIZE2; i++) {
    if ((tmp = block[jpeg_natural_order[i]]) != 0)
      n = i;
    out[i] = tmp;
}
return n;
r
innerloop
宏中使用的是RLE计数器

这种带有手动编码之字形的线性RLE(用于Cortex-A8)应该比原始C版本更快,即使是Cortex-A9也是如此。多亏了Siarhei Siamashka

PS:libjpeg-turbo的当前版本在此RLE中没有arm优化:-innerloop被稍微重写为
kloop
,但RLE仍然是以非线性方式完成的;锯齿形没有从中分离出来

关于霓虹灯的几点思考

NEON有一组32个寄存器,每个寄存器的宽度为64位(D0..D31;根据Anderson@ELC 2011,),理论上,可以用于存储64个16位系数并实现ZigZag+RLE。仍在搜索实现

MPEG标准中也有类似的zig-zag+RLE,在x86和arm中也有一些SIMD实现。在SSSE3中,x86实现了;8x8 zigzag。但对于arm,只有x264实现了

PS:只为我和任何不了解Jpeg内部结构的人准备。本书中有简短易懂的Jpeg编码介绍

PPS(2013年2月18日13:30更新):为了优化RLE编码,我们可以对AC系数中间的零进行预扫描搜索,然后处理预计算的数据。我们甚至可以将其保存为半字节或某些NEON Reg中的位


更新日期:2月18日:补丁作者表示commit 9的注释不准确。与jpeg6b相比,该代码有2倍的改进,而不是与libjpeg turbo相比。他表示,unroll by 63(如libjpeg tubro)的速度与此asm解决方案几乎相同(在某些测试中,它比其他版本稍好).

请提供更多关于您的案例的详细信息。什么是压缩的,您的rle是如何编码的。可能需要添加一些示例代码(没有simd和with)?您的CPU是什么?您当前的速度是多少(MB/s)或者典型大小输入的延迟,目标是什么。我正在尝试优化JPEG压缩的运行长度编码部分。JPEG编码占用的大部分时间是这个RLE。我在ARM平台上工作。它有NEON simd引擎。是的。我在Cortex A9上工作。你的JPEG实现是什么?谢谢你的回答。我已经阅读了y优化了Neon中的DCT、Quant和zigzag模块,我想知道我是否可以为RLE部分做些什么。我在阅读开源代码时得到了一些提示。你的工作是开源的吗?你是从libjpeg还是libjpeg turbo开始的?你得到了什么提示?最后的非零函数和zigzag扫描可以在Neon中实现。但是真正的问题是,运行是否可以在neon中并行计算,以便AC大小和运行编码可以优化。但是,我觉得在neon中不可能,至少在运行部分是这样。所以,是的,我有点困在那里。你有没有关于如何以SIMD方式计算运行的提示。计算运行可以通过某种方式完成但最困难的部分是使用NEON存储零系数,而只存储非零系数的运行次数和值。Rugger,你能发布你当前的代码吗?你可以将其作为更新添加到问题中。
  for (k = 2; k <= last_nonzero_index; k += 2) {
      innerloop(k);
  }