我使用的是Exynos 3110处理器(1 GHz单核ARM Cortex-A8,例如在Nexus S中使用),并尝试测量特定功能的执行时间.我在Nexus S上运行了Android 4.0.3.我尝试了这个方法
[1] 如何测量ARM Cortex-A8处理器中的程序执行时间?
我加载了内核模块以允许在用户模式下读取寄存器值.我使用以下程序来测试计数器:
static inline unsigned int get_cyclecount (void)
{
unsigned int value;
// Read CCNT Register
asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
return value;
}
static inline void init_perfcounters (int do_reset, int enable_divider)
{
// in general enable all counters (including cycle counter)
int value = 1;
// peform reset:
if (do_reset)
{
value |= 2; // reset all counters to zero.
value |= 4; // reset …Run Code Online (Sandbox Code Playgroud) 在这里参考@ auselen的答案:使用ARM NEON内在函数来添加alpha和permute,看起来armcc编译器比用于NEON优化的gcc编译器要好得多.这是真的吗?我还没有真正尝试过armcc编译器.但是我使用带有-O3优化标志的gcc编译器获得了相当优化的代码.但现在我想知道armcc是否真的那么好?那么考虑到所有因素,两个编译器中哪一个更好?
有一个很大的(~100 000)浮点变量数组,并且有一个阈值(也是浮点).
问题是我必须将数组中的每个变量与阈值进行比较,但NEON标志传输需要很长时间(根据分析器约20个周期).
有没有有效的方法来比较这些值?
注意:由于舍入错误无关紧要,我尝试了以下方法:
float arr[10000];
float threshold;
....
int a = arr[20]; // e.g.
int t = threshold;
if (t > a) {....}
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,我得到以下处理器命令序列:
vldr.32 s0, [r0]
vcvt.s32.f32 s0, s0
vmov r0, s0 <--- takes 20 cycles as `vmrs APSR_nzcv, fpscr` in case of
cmp r0, r1 floating point comparison
Run Code Online (Sandbox Code Playgroud)
当转换发生在NEON时,无论我是通过描述的方式还是浮点数来比较整数.
我目前正在研发TI AM335x主板(入门套件),我想让OMAP看门狗工作......
据我所知,平台在启动时会自动启用看门狗,我认为在启动时打印出的以下消息可以确认:
[ 1.510192] OMAP Watchdog Timer Rev 0x01: initial timeout 60 sec
Run Code Online (Sandbox Code Playgroud)
如果我在这一点上没有错,如果我发出以下命令:
echo 0 > /dev/watchdog
Run Code Online (Sandbox Code Playgroud)
董事会应该在60秒内重启,不是吗?相反,60秒后没有任何反应......为什么?我错过了与此相关的内容吗?有谁能够帮我?
一般如何使用 NEON 比较指令?
这是一个案例,我想使用大于或等于指令?
目前我有一个,
int x;
...
...
...
if(x >= 0)
{
....
}
Run Code Online (Sandbox Code Playgroud)
在 NEON 中,我想以同样的方式使用 x,只是这次 x 是一个向量。
int32x4_t x;
...
...
...
if(vcgeq_s32(x, vdupq_n_s32(0))) // Whats the best way to achieve this effect?
{
....
}
Run Code Online (Sandbox Code Playgroud) 了解ARM NEON内在函数,我正在计算一个函数,我编写的函数将数组中的元素加倍.使用内在函数的版本比函数的普通C版本花费更多时间.
没有NEON:
void double_elements(unsigned int *ptr, unsigned int size)
{
unsigned int loop;
for( loop= 0; loop<size; loop++)
ptr[loop]<<=1;
return;
}
Run Code Online (Sandbox Code Playgroud)
使用NEON:
void double_elements(unsigned int *ptr, unsigned int size)
{
unsigned int i;
uint32x4_t Q0,vector128Output;
for( i=0;i<(SIZE/4);i++)
{
Q0=vld1q_u32(ptr);
Q0=vaddq_u32(Q0,Q0);
vst1q_u32(ptr,Q0);
ptr+=4;
}
return;
}
Run Code Online (Sandbox Code Playgroud)
想知道阵列和向量之间的加载/存储操作是否消耗更多时间来抵消并行添加的好处.
更新:更多信息回应伊戈尔的回复.
1.代码发布在这里:
plain.c
plain.s
neon.c
neon.s
从两个汇编列表中的部分(标签)L7,我看到霓虹灯版本有更多的汇编指令.(因此更多时间采取?)2.
我在arm-gcc上使用-mfpu = neon编译,没有其他标志或优化.对于普通版本,根本没有编译器标志.
那是一个错字,SIZE的意思是大小;两者都是一样的.
4,5.由4000个元素组成.我在函数调用之前和之后使用gettimeofday()定时.NEON = 230us,普通= 155us.
是的,我在每种情况下印刷了元素.
除此之外,没有任何进步.
我正在研究在Android上编写几个实时DSP算法,因此我决定直接在Assembly中编程ARM以尽可能地优化所有内容并使数学最大化.起初我得到的速度基准并没有多大意义,所以我开始阅读有关管道危险,双重问题的能力等等.我仍然对我得到的一些数字感到困惑,所以我将它们发布在这里,希望有人可以解释为什么我得到的东西.特别是,我很感兴趣为什么NEON需要不同的时间来运行不同数据类型的计算,即使它声称在一个周期内完成每个操作.我的发现如下.
我正在使用一个非常简单的循环进行基准测试,我运行它进行了2,000,000次迭代.这是我的功能:
hzrd_test:
@use received argument an number of iterations in a loop
mov r3 , r0
@come up with some simple values
mov r0, #1
mov r1, #2
@Initialize some NEON registers (Q0-Q11)
vmov.32 d0, r0, r1
vmov.32 d1, r0, r1
vmov.32 d2, r0, r1
...
vmov.32 d21, r0, r1
vmov.32 d22, r0, r1
vmov.32 d23, r0, r1
hzrd_loop:
@do some math
vadd.s32 q0, q0, q1
vadd.s32 q1, q0, q1
vadd.s32 q2, q0, q1
vadd.s32 q3, q0, q1
vadd.s32 …Run Code Online (Sandbox Code Playgroud) 我目前正在进行颜色转换例程,以便从YUY2转换为NV12.我有一个非常快的功能,但没有我想象的那么快,主要是由于缓存未命中.
void convert_hd(uint8_t *orig, uint8_t *result) {
uint32_t width = 1280;
uint32_t height = 720;
uint8_t *lineOdd = orig;
uint8_t *lineEven = orig + width*2;
uint8_t *resultYOdd = result;
uint8_t *resultYEven = result + width;
uint8_t *resultUV = result + height*width;
uint32_t totalLoop = height/2;
while (totalLoop-- > 0) {
uint32_t lineLoop = 1280/32; // Bytes length: width*2, read by iter 16Bytes
while(lineLoop-- > 0) {
__asm__ __volatile__(
"pld [%[lineOdd]] \n\t"
"vld4.8 {d0, d1, d2, d3}, [%[lineOdd],:128]! \n\t" // d0:Y …Run Code Online (Sandbox Code Playgroud) 我对这个有问题。我使用 ARM Cortex-A9 和 DS-5 来创建裸机固件。我修改了我的链接器文件,故意将 .data 部分 LMA 与 text 和 Rodata 部分相邻,因为它的默认运行时 VMA 位于 1MB 之外,而 .bin 图像大约为 1MB,但包含 90% 的零。所以我特意制作了 LMA != VMA 以节省空间。我还在 start.S 中添加了一个代码,它将 .data 部分从它的 lma 重新定位到 vma。
然而,在 DS-5 中加载生成的 elf 文件时,它已经将所有部分加载到它们的 VMA。结果,我的 start.S 代码应该重新定位数据,从带有垃圾内容的 LMA 复制到已经正确的 VMA,不久之后这些垃圾导致了错误。
我在 Cortex-M4 中使用过二进制不相等的 VMA 和 LMA,并使用 gdb 进行精灵调试,那里没有问题,但它是微控制器。在我当前的 arm 处理器应用程序中,我将如何在 elf 中模拟调试将数据从其 LMA 正确复制到 VMA 的场景。很可能在使用二进制格式独立启动时不会有问题,但现在我们仍在 elf 调试中,所以我必须解决这个问题。