工具/软件:Code Composer Studio
您好!
我们正在开发一个简单内核(Sobel)并在 DSP 上进行优化。 我们从 C66x Sobel 代码中获取了参考、但在处理后、我们无法获得预期结果。
有人可以帮助我在代码中找到问题吗?
谢谢
Vikase2e.ti.com/.../dsp_5F00_sobel_5F00_kernel.rar
附加项目以供参考
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:Code Composer Studio
您好!
我们正在开发一个简单内核(Sobel)并在 DSP 上进行优化。 我们从 C66x Sobel 代码中获取了参考、但在处理后、我们无法获得预期结果。
有人可以帮助我在代码中找到问题吗?
谢谢
Vikase2e.ti.com/.../dsp_5F00_sobel_5F00_kernel.rar
附加项目以供参考
大家好、Vikas、
请详细说明一下吗? 它将帮助我 更快地识别问题?
此致、
Shyam
我还附加了从该代码接收的输出.........
void eel_dsp_kernel_optimized (uint8_t * inPtr、uint8_t * outPtr、uint32_t width、uint32_t height) { uint8_t * inptr_a1[width]、* inptr_a2[width]、* inptr_a3[width];//处理数据的输入缓冲区 uint8_t buffer[width];//输出缓冲区以处理数据 uint8_t *temp1、*inptr1、*inptr2、*inptr3、*outpointer、 *指针; inpt1 =(uint8_t *) inptr_A1; inpt2 =(uint8_t *) inptr_A2; inpt3 =(uint8_t *) inptr_A3; inpointer = inPtr; outpointer = outPtr; //复制第一行 memcpy (inptr1、inpointer、width); inpointer +=宽度; //复制第二行 memcpy (inptr2、inpointer、width); inpointer +=宽度; //复制第三行 memcpy (inptr3、inpointer、width); inpointer +=宽度; //将输入的第一行直接复制到输出缓冲区,因为我们不会处理第一行 memcpy (outpointer、inptr1、width); outpointer +=宽度; int32_t x、y; int64_t mask1_8 = 0x0101010101010101; int64_t mask2_8 = 0x0202020202020202; uint32_t mask1_4 =_loll (mask1_8); uint32_t mask2_4 =_loll (mask2_8); int64_t r0、R1、R2、R01_lo、R01_hi、 r012_lo、r012_hi、r012_lo_D2、r012_hi_D2、C02_lo、 C02_hi; _x128_t r0_2、r1_2、r2_2; 对于(y = 1;y <(height -1);y++) { uint32_t x0_3210 =_mem4_const (inpt1); uint32_t x1_3210 =_mem4_const (inpt2); uint32_t x2_3210 =_mem4_const (inpt3); /*将8bpp 转换为16bpp,以便我们可以对行进行 SIMD 加法*/ int64_t x0_2 =_mpyu4ll (x0_3210、mask1_4); int64_t x1_2 =_mpyu4ll (x1_3210、mask2_4); int64_t x2_2 =_mpyu4ll (x2_3210、mask1_4); /*添加行0+1+2、逐列*/ int32_t x01 =_ADD2 ((int32_t)_loll (x0_2)、(int32_t)_loll (x1_2)); uint32_t xaxb =(uint32_t)_ADD2 (x01、(int32_t)_loll (x2_2)); 对于(x=0;x <(宽度/8);x++) { /*从3行中的每行读取8个字节。 * r0 =_mem8_const (&inpt1[(x*8)+ 2]); r1 =_mem8_const (&inpt2[(x*8)+ 2]); R2 =_mem8_const (&inpt3[(x*8)+ 2]); /*将8bpp 转换为16bpp,以便我们可以对行进行 SIMD 加法*/ R0_2 =_dmpyu4 (r0、mask1_8); r1_2 =_dmpyu4 (r1、mask2_8); R2_2 =_dmpyu4 (R2、mask1_8); /*添加行0+1、按列*/ r01_lo =_dadd2 (_lo128 (r0_2)、_lo128 (r1_2)); R01_hi =_dadd2 (_hi128 (r0_2)、_hi128 (r1_2)); /*将上一个总和添加到第2行、按列*/ r012_lo =_dadd2 (R01_lo、_lo128 (R2_2)); r012_hi =_dadd2 (R01_hi、_hi128 (R2_2)); /*使用历史记录*/将此总和左移2个像素 r012_lo_D2 =_itoll (_loll (r012_lo)、xaxb); r012_hi_d2 =_itoll (_loll (r012_hi)、_hill (r012_lo)); C02_lo =_dsub2 (r012_lo、r012_lo_D2); C02_hi =_dsub2 (r012_hi、r012_hi_D2); /*为下一次迭代保存重叠数据*/ xaxb =(uint32_t)_mVD ((int32_t)_hill (r012_hi)); /*存储8个清晰的滤波器值*/ _amem8 (&buffer[x*8]) = C02_lo; _amem8 (&buffer[(x*8)+4])= C02_hi; } memcpy (outpointer、buffer、width); outpointer +=宽度; //重新排列指针并再读取一行 TEMP1 = inttr2; inptr2 = inptr3; inptr1 = temp1; //复制第三行 memcpy (inptr3、inpointer、width); inpointer += width; } }
大家好、Vikas、
我还没有尝试过此代码、但乍一看、我在这里看到了一个潜在的问题、
_amem8(&buffer[x*8]) = c02_lo;
_amem8(&buffer[(x*8)+4]) = c02_hi;Vikas、
我看了一下 main.c、它看起来就像您用 VXLIB_sobre x_3x3_i8u_o16s.c 作为参考、对吗? 如果是这样、此代码只会生成 int16_t 格式的 X 梯度、但假设输出指针为每像素8位、则会更新输出指针、因此这是一个问题。 您的 buffer[width]数组为8位、因此对其进行16位写入将使该缓冲区溢出2倍。 您可以看到、对于8个输入像素、正在写入16个输出字节。
此外、您的参考 C 看起来像是同时生成 X 和 Y 梯度、并将它们组合成单个8位输出、而优化的代码没有这样做、因此这是另一个问题。 如果您同时需要 X 和 Y、我建议您参考 VXLIB_sobre _3x3_i8u_o16s_o16s 函数、该函数在单独的缓冲区中计算 X 和 Y 梯度。
此致、
Jesse
感谢 Shyam 花时间了解问题并提供适当的建议。
我使用_davg2和_dmin2在更少的内在函数中转换了 c 代码
//一次计算2个16位值的绝对值
abs_01 =_abs2 (_loll (C02_lo));
abs_23 =_abs2 (_hill (C02_lo));
abs_45 =_abs2 (_loll (C02_hi));
abs_67 =_abs2 (_hill (C02_hi));
//将它们打包成4组
C02_lo =_itoll (ABS_23,ABS_01 );
C02_hi =_itoll (abs_67、abs_45);
//取 x 方向和 y 方向边缘的平均值
c012_lo =_davg2 (C02_lo、c012_lo); 其中 c012_lo 是 y 方向边沿
c012_hi =_davg2 (C02_hi、c012_hi); 其中 c012 _hi 是 y 方向边缘
//使用0xff 钳制值
c012_lo =_dmin2 (c012_lo、min_value);
c012_hi =_dmin2 (c012_hi、min_value);
/*存储8个清晰的过滤值*/
_mem8 (像素[0]) = c012_lo;
_mem8 (&PIXEL [0 + 4]) = c012_hi;
对于(i=0;i<8;i++)
{
Buffer[(x*8)+ i]=像素[i];
}
现在只剩下一件事,就是将 int64_t 变量中的数据存储在 uint8_t 数组中。
谢谢
Vikas
是 Shyam、以下行将16位的结果转换为8位的结果并将结果饱和存储在8位数组中。
mem4 (& buffer[(x*8)]) = _spacku4 (_hill (c012_lo)、_loll (c012_lo));
_mem4 (& buffer[(x*8)+4]) = _spacku4 (_hill (c012_hi)、_loll (c012_hi));
感谢您的支持。
Vikas