我写了这个非常天真的NEON实现,从RGBA转换为RGB.它有效,但我想知道我还能做些什么来进一步提高性能.
我尝试使用预取大小,然后再展开循环,但性能没有太大变化.顺便说一句,在预取的尺寸方面,是否有任何经验法则?我在网上找不到任何有用的东西.此外,在"ARMv8指令集概述"中,我看到还有一个存储预取,这有用吗?
目前我正在大约1.7ms转换iPhone5s上的1280x720图像.
// unsigned int * rgba2rgb_neon(unsigned int * pDst, unsigned int * pSrc, unsigned int count);
_rgba2rgb_neon:
cmp w2, #0x7
b.gt loop
mov w0, #0
ret
loop:
prfm pldl1strm, [w1, #64]
ld4.8b {v0, v1, v2, v3}, [w1], #32
ld4.8b {v4, v5, v6, v7}, [w1], #32
prfm pldl1strm, [w1, #64]
st3.8b {v0, v1, v2}, [w0], #24
st3.8b {v4, v5, v6}, [w0], #24
subs w2, w2, #16
b.gt loop
done:
ret
Run Code Online (Sandbox Code Playgroud) 我有很多关于复数的计算(通常是一个包含一个由两个浮点组成的结构的数组来表示im和re;见下文)并希望用NEON C内在函数加速它们.如果你能给我一个如何加速这样的事情的例子,那将是非常棒的:
for(n = 0;n < 1024;n++,p++,ptemp++){ // get cir_abs, also find the biggest point (value and location).
abs_squared = (Uns32)(((Int32)(p->re)) * ((Int32)(p->re))
+ ((Int32)(p->im)) * ((Int32)(p->im)));
// ...
}
Run Code Online (Sandbox Code Playgroud)
p是这种数组:
typedef struct {
Int16 re;
Int16 im;
} Complex;
Run Code Online (Sandbox Code Playgroud)
我已经阅读了"ARM C语言扩展"的第12章,但在理解如何在此处加载和存储我的构造以进行计算时仍然存在问题.
这些说明的结果是什么?(有关如何通过运行我的代码自行回答这个问题的任何建议吗?)
STR.W R8, [R3], #4
STR.W R8, [R3], #4
STR.W R8, [R3], #4
STR.W R8, [R3], #4
STR.W R8, [R3], #4
STR.W R8, [R3], #4
STR.W R8, [R3]
Run Code Online (Sandbox Code Playgroud)
我知道每条指令都会将R3的值加载到R8中,然后将值增加4到R3,但我感到困惑的是,在这些指令结束时,R8中包含的值是多少?
是[R3 + 16]吗?或者是[R3 + 4],[R3 + 8],......,[R3 + 16]?
关于来自串行闪存设备的现代系统的启动概念,我有点迷失.在裸机上编程了大量简单的微控制器,从8位PIC到32位Power架构(总是通过重新编程正常的总线可寻址闪存),我想知道现代SoC如何从串行设备启动.我没有在网上找到太多,因为每个系统似乎都依赖于SD卡编程工具和辅助引导程序的组合,这两者都很少得到关注.
我最近开始玩ARM汇编,发现我似乎只打算将32位值移到寄存器中,但是如果我只想像在x86汇编中那样只将8位或16位移到寄存器中该怎么办。即
arm
eor r0, r0
mov r0, #128
x86
xor eax, eax
mov al, 0x80
Run Code Online (Sandbox Code Playgroud)
r0现在包含0x80,但它是一个32位寄存器,因此它将包含0x00000080
如果这是x86,我可以使用al(8位寄存器)来操纵最后一个字节,而不是eax(32位寄存器)。
tl; dr ARM汇编中是否有小的寄存器?
我在尝试运行一个调用非常简单的ARM汇编函数的C程序时遇到了一个奇怪的问题.这是我的C代码:
#include <stdio.h>
#include <stdlib.h>
extern void getNumber(int* pointer);
int main()
{
int* pointer = malloc(sizeof(int));
getNumber(pointer);
printf("%d\n", *pointer);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我的汇编代码:
.section .text
.align 4
.arm
.global getNumber
.type getNumber STT_FUNC
getNumber:
mov r1, #0
str r1, [r0]
bx lr
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.但是,如果我mov r7, #0在顶部添加一行getNumber,则程序在尝试访问时会出现段错误pointer.在用gdb检查之后,我注意到现在指针本身存储在一个非常低的地址,例如0xa.
现在,我做了一些研究,显然r7是THUMB代码的帧指针(根据这个).但是,我清楚地说明我不想.arm在汇编代码中的行中使用THUMB指令.为什么它失败了?
我正在使用arm-linux-gnueabihf-gcc编译.c和.s文件,我正在运行Arch Linux的基于Cortex-A8的板上运行该程序.
编辑:如果我使用-fomit-frame-pointer标志进行编译,程序运行正常.但是,我仍然想知道为什么使用r7作为帧指针.
编辑2:即使我使用.code 32而不是,它仍然失败.arm.
根据我对ARM处理器的理解,以下是按顺序执行的功能(1)按顺序执行指令(2)在当前指令完成之前,它将不执行下一条指令。(3)执行速度较慢。
乱序执行与乱序相反。(1)以非顺序顺序执行指令(2)即使当前指令未完成,它也会执行下一条指令。(仅当下一条指令不取决于当前指令的结果时才执行此操作)(3)更快的执行速度。
除上述功能外,还有其他功能差异吗?
我的环境:
我正在使用PetaLinux在Zynq上开发Linux应用程序.
我目前的问题是四个算术运算的处理时间(+/ - /*/div).
我clock_gettime()使用以下代码计算处理时间.
添加(+):
static void funcToBeTimed_floatAdd(void)
{
int idx;
float fval = 0.0;
for(idx=0; idx<100; idx++) {
fval = fval + 3.14;
}
}
Run Code Online (Sandbox Code Playgroud)
对于部门(/):
static void funcToBeTimed_floatDiv(void)
{
int idx;
float fval = 314159000.00;
for(idx=0; idx<100; idx++) {
fval = fval / 1.001;
}
}
Run Code Online (Sandbox Code Playgroud)
对于时间测量,使用以下代码.在procNo使用设置main(int argc, char *argv[])
static void disp_elapsed(int procNo)
{
struct timespec tp1, tp2;
long dsec, dnsec;
/***/
switch(procNo) { …Run Code Online (Sandbox Code Playgroud) 我正在将实时内核TNeoKernel移植到Cortex-M架构,所以我安装了Keil并且正在尝试构建内核.但是,我遇到了意想不到的问题:编译器似乎无法处理inline函数.这是简单的代码:
static inline int test(void)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器的输出如下:
src\appl\main.c(17): warning: #260-D: explicit type is missing ("int" assumed)
static inline int test(void)
src\appl\main.c(17): error: #65: expected a ";"
static inline int test(void)
Run Code Online (Sandbox Code Playgroud)
如果我删除inline关键字,它会编译并运行.
在ARM编译器的文档中,我找不到任何关于inline函数的信息.因此,只是为了确保:inlineARM编译器是否真的不支持该关键字?这太令人难以置信所以我决定问.
我static inline在内核的独立于平台的代码中有很多函数,那么,它支持ARM编译器的最佳方法是什么?在我的头脑中,我只有两个想法:
TN_INLINE,对于ARM编译器,它应该扩展为空;我想为裸机ARM准备GNU工具链,以便与Geany IDE一起使用.有一些像这样的教程:构建裸机的GNU ARM工具链,但我不明白几个步骤.
首先,每个使用Linux操作系统的人都隐式拥有gcc,binutils和gdb,为什么要下载其他人呢?其次所有教程告诉我用这样的东西配置gcc:*./configure --target = arm-elf.它甚至做了什么?难道它只是强迫我使用调用命令行GCC ARM-ELF-GCC,而不是海湾合作委员会或它改变我的gcc内部的一些选项?
到目前为止,我已经准备好了makefile,但我仍然不确定编译器选项.我没有更改任何gcc配置选项,我用这样的标志调用编译器:
CFLAGS = -Wall -std=c99 -march=armv7-m -mtune=cortex-m0
Run Code Online (Sandbox Code Playgroud)
我可以通过使用适当的参数调用gcc来准备工具链,还是需要在gcc配置中进行一些更改?
arm ×10
assembly ×4
c ×4
gcc ×3
linux ×3
neon ×2
architecture ×1
arm64 ×1
boot ×1
bootloader ×1
gnu ×1
iphone ×1
keil ×1
performance ×1
sequential ×1