Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将代码转换为程序集_C_Assembly_Arm_Simd_Neon - Fatal编程技术网

C 将代码转换为程序集

C 将代码转换为程序集,c,assembly,arm,simd,neon,C,Assembly,Arm,Simd,Neon,我正在把下面的代码翻译成Neon汇编。任何帮助都将不胜感激 void sum(int length, int *a, int *b, int *c, int *d, char *result) { int i; for (i = 0; i < length; i++) { int sum = (a[i] + b[i] + c[i] + d[i])/4; if (sum > threshold)

我正在把下面的代码翻译成Neon汇编。任何帮助都将不胜感激

void sum(int length, int *a, int *b, int *c, int *d, char *result)
{
   int i;

   for (i = 0; i < length; i++)
      {
          int sum = (a[i] + b[i] + c[i] + d[i])/4;
          if (sum > threshold)
             result[i] = 1;
          else
             result[i] = 0;
      }
}
void和(int-length,int*a,int*b,int*c,int*d,char*result)
{
int i;
对于(i=0;i阈值)
结果[i]=1;
其他的
结果[i]=0;
}
}

实际代码是一个图像二值化算法。上面的代码只是为了演示这个想法,而不是让简单的事情变得更复杂。

这里是一个相当简单的实现。请注意,我们将除法和阈值测试转换为仅针对
threshold*4
的测试(以消除除法):

void sum(常数int n、常数int32_t*a、常数int32_t*b、常数int32_t*c、常数int32_t*d、常数int32_t*result)
{
const int32_t threshold4=阈值*4;
const int32x4_t vthreshold4={threshold4,threshold4,threshold4};
常数uint32x4_t vk1={1,1,1,1};
int i;
对于(i=0;i
注:

  • 完全未经测试的代码-可能需要进一步的工作
  • result
    已更改为
    int32\u t*
    ——压缩为
    uint8\u t
    并不难,但它给这个初始示例增加了很多复杂性,因此我认为现在应该保持简单
  • a
    b
    c
    d
    结果都需要16字节对齐
  • n
    需要是4的倍数
  • a
    b
    c
    d
    的总和需要在32位带符号整数内
  • 阈值*4
    需要适合32位带符号整数

您不能通过编译器运行它吗?只需打开编译器上的开关以生成程序集,然后将该输出转换为Neon assembly谢谢您,Paul。因为源是灰度图像,所以我需要将uchar加载到int32x4_t值中。我正在考虑使用int32x4\u t input=vshrn\u n\u 32(source,24)//source是uint8\u t。你能告诉我你是如何压缩的吗?要压缩到8位,你需要取4 x 4 x 32位向量,使用vmovn_xxx或vpadd_xxx指令,先压缩到2 x 8 x 16位向量,然后再压缩到单个16 x 8位向量。谢谢@paul-r。实际上,我们正在从q(128位)到d(64位)寄存器进行打包,所以我认为它应该是2x32x4->2x16x4->8x8向量。我仍在努力实现这一点(我对Neon完全陌生,所以花了我很多时间)@PaulR-有什么办法可以加快这些初始化:
int32x4\u t vthreshold4={threshold4,threshold4,threshold4,threshold4}
uint32x4\u t vk1={1,1,1}
。我在关键代码路径上有一个函数,由于算法规范(BLAKE2加密散列),它必须多次执行该操作。@jww:编译器应该足够聪明,能够将这样的常量从任何封闭循环中提升出来,即使它来自内联函数-您检查过生成的代码吗?否则,您可以将初始化的常量作为参数传递到函数中。
void sum(const int n, const int32_t *a, const int32_t *b, const int32_t *c, const int32_t *d, int32_t *result)
{
   const int32_t threshold4 = threshold * 4;
   const int32x4_t vthreshold4 = { threshold4, threshold4, threshold4, threshold4 };
   const uint32x4_t vk1 = { 1, 1, 1, 1 };
   int i;

   for (i = 0; i < n; i += 4)
   {
      int32x4_t va = vld1q_s32(&a[i]);    // load values from a, b, c, d
      int32x4_t vb = vld1q_s32(&b[i]);
      int32x4_t vc = vld1q_s32(&c[i]);
      int32x4_t vd = vld1q_s32(&d[i]);

      int32x4_t vsum = vaddq_s32(va, vb); // sum values form a, b, c, d
      vsum = vaddq_s32(vsum, vc);
      vsum = vaddq_s32(vsum, vd);

      uint32x4_t vcmp = vcgtq_s32(vsum, vthreshold4);
                                          // compare with threshold * 4
      int32x4_t vresult = (int32x4_t)vandq_u32(vcmp, vk1);
                                          // convert result to 0/1
      vst1q_s32(&result[i], vresult);     // store result
   }
}