【问题标题】:NEON memcpy , memset and using .c with .s filesNEON memcpy、memset 和使用 .c 和 .s 文件
【发布时间】:2014-06-09 13:21:35
【问题描述】:

我正在尝试熟悉 Neon 说明。汇编和内在函数。我用的是 gcc V4.8.2 hardfp 我想使用带有 preload 的 NEON memcpy 来:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka13544.html

我也发现了这个话题: ARM memcpy and alignment 但这与官方的 ARM 页面实现略有不同。

不幸的是,我从来没有同时使用 .s 和 .c 文件,所以我需要一些帮助。我的 .c 文件如下所示:

       #include <stdlib.h>
       #include <stdio.h>
       #include <string.h>
       #include <math.h>
       #include <time.h>
       #include <stdint.h>
       #include <arm_neon.h> 

       int main()
       {

           clock_t start, end;           // timer variables
           uint32_t i,X=100;

           size_t size = 2048*32/* arbitrary */;
           size_t offset = 1;
           char* src = malloc(sizeof(char)*(size + offset));
           char* dst = malloc(sizeof(char)*(size));

           NEONCopyPLD( dst, src + offset, size );
           memcpy( dst, src + offset, size );
           return(0);
       }

且 assembly.s 文件如下:

       .global NEONCopyPLD
       NEONCopyPLD:
             PLD [r1, #0xC0]
             VLDM r1!,{d0-d7}
             VSTM r0!,{d0-d7}
             SUBS r2,r2,#0x40
             BGE NEONCopyPLD

我使用指令编译了以下程序:

arm-linux-gnueabihf-gcc -mthumb -march=armv7-a -mtune=cortex-a9 -mcpu=cortex-a9 -mfloat-abi=hard -mfpu=neon -Ofast -fprefetch-loop-数组 assembly.s asm_pr.c -o 输出

我收到以下错误:

 potentially unexpected fatal signal 11.

 CPU: 0 PID: 670 Comm: out_asm Not tainted 3.10.9-rt5+ #2
 task: bf907c00 ti: bef4a000 task.ti: bef4a000
 PC is at 0x4c90ce LR is at 0x852d
 pc : [<004c90ce>]    lr : [<0000852d>]    psr: 40030030
 sp : 7e958cb0  ip : 00000107  fp : 00000000
 r10: 76f91000  r9 : 00000000  r8 : 00000000
 r7 : 00001017  r6 : 00e85010  r5 : 00e75009  r4 : 00010001
 r3 : 000f4240  r2 : 00010000  r1 : 00e75009  r0 : 00e85010
 Flags: nZcv  IRQs on  FIQs on  Mode USER_32  ISA Thumb  Segment user
 Control: 10c5387d  Table: 4ef7404a  DAC: 00000015
 CPU: 0 PID: 670 Comm: out_asm Not tainted 3.10.9-rt5+ #2
 Backtrace:
 [<800120a4>] (dump_backtrace+0x0/0x118) from [<80012318>] (show_stack+0x20/0x24)
 [<800122f8>] (show_stack+0x0/0x24) from [<804fab0c>] (dump_stack+0x24/0x28)
 [<804faae8>] (dump_stack+0x0/0x28) from [<8000f560>] (show_regs+0x30/0x34)
 [<8000f530>] (show_regs+0x0/0x34) from [<8003349c>](get_signal_to_deliver+0x318/0x668)   
 [<80033184>] (get_signal_to_deliver+0x0/0x668) from [<80011664>] (do_signal+0x11c/0x450)
 [<80011548>] (do_signal+0x0/0x450) from [<80011b20>] (do_work_pending+0x74/0xac)
 [<80011aac>] (do_work_pending+0x0/0xac) from [<8000e500>] (work_pending+0xc/0x20)
 Segmentation fault

我的另一个问题是,我们是否可以使用 SIMD 指令(内在函数或自动向量化)来加快初始化为 0 的数组? 我注意到以下代码无法自动矢量化:

   for (i=0;i<N;i++)
        *(a++)=0;

但是这个代码块可以自动向量化:

   for (i=0;i<N;i++)
       a[i]=i;

我的最终目标是调查我是否可以拥有一个运行速度比memset() 更快的 NEON 函数。

最后我想问一些关于不可矢量化循环的问题。根据:http://gcc.gnu.org/projects/tree-ssa/vectorization.html#unvectoriz 以下代码无法自动矢量化:

           while (*p != NULL) {
              *q++ = *p++;
           }

但是,是否可以使用内在函数或程序集来开发此循环的更快版本?如果您做过类似的事情,可以在这里发布吗?

【问题讨论】:

  • NEONCopyPLD -> "NEONCopyPLD:" 注意分号。不要在同一篇文章中提出很多(三个?)问题。关于 neon 的事情是,它是一个 SIMD 单元,它应该独立于内存速度,但是大多数实际实现都为 SIMD 提供了自己的内存端口,因此 NEON 单元可能具有更快的内存访问速度。底线是,如果您是供应商,您会知道 memset 是否应该使用 NEON,但通常它不应该比普通内核慢。
  • 感谢您的评论。我改变了一些其他的东西以及插入一个半列,我能够编译。虽然我遇到了分段错误!
  • 你应该一次问一件事。打扫一下,问一件事。然后,如果您还有其他问题,请发布另一个问题或等待第一个问题,看看您是否会得到您想要的。

标签: assembly arm neon


【解决方案1】:

你永远不会从你的汇编函数返回。因此,存储在汇编函数下方的任何代码都将被执行。这迟早会导致崩溃。

退出你的函数:

mov pc, lr

这很可能会解决您的问题。您还应该检查在汇编程序函数调用期间必须保留哪些寄存器(霓虹灯 通用寄存器)。

此页面是一个有用的资源,展示了如何执行此操作的示例:http://omappedia.org/wiki/Writing_ARM_Assembly

【讨论】:

    【解决方案2】:

    您可以在 Google 上搜索“aosp bionic memcpy”。

    这不是一个完美的实现,但相当不错。

    我建议你从 memset 开始,因为 memcpy 比你想象的要复杂得多。

    分析仿生memset,尝试理解流程,并询问您是否不理解作者为什么以这种特定方式做某事。

    而且我也不明白你为什么要谈论完全无用的 IMO 自动矢量化。

    请先自己研究一下,问你是否卡住了。

    要回答这个特殊问题,需要一个由多个章节组成的完整教程,从基本的 ARM 指令开始。

    【讨论】:

    • 感谢您的回答。我会看看仿生memcpy和memset!
    【解决方案3】:

    与您的问题无关,但您显示的代码示例无法正常工作。那是因为您似乎激活了对齐陷阱,并且正在命中一个:

           [ ... ]
           size_t offset = 1;
           char* src = malloc(sizeof(char)*(size + offset));
           [ ... ]
           NEONCopyPLD( dst, src + offset, size );
    
    r7 : 00001017 r6 : 00e85010 r5 : 00e75009 r4 : 00010001
    r3:000f4240 r2:00010000 r1:00e75009 r0:00e85010
                                       ^^^^^^^^

    您正在使用带有VLDM未对齐指针(由于offset == 1src 永远不会对齐)。

    从 reg 转储中,由于您的 Neon asm 函数本身不使用 R5,因此您看到 R1 == R5 的事实让我得出结论,您在启用对齐陷阱的情况下运行,并获得 @987654327 @你第一次点击VLDM
    那是因为你没有在你的程序集中使用R5,所以C函数之前已经使用了那里的值;因此R1R5 不不同意味着R1 在采取陷阱之前没有改变,这意味着VLDM R1!,... 甚至不能执行一次

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      相关资源
      最近更新 更多