我为Android编写了一个图像处理应用程序(https://play.google.com/store/store/apps/details?id=cv.cvexperiments),其中一些C 代码与JNI包装。为了在多核处理器上加快加速,我用openMP"并行"指令注释了昂贵的循环。
问题是,在x86上,我在4列proc上获得了从x3到x5不等的速度,但是在Android上,激活OpenMP(带有-Opopenmp)在ARM 32BITS上没有任何速度,甚至会在ARM 32BITS上加速,甚至减慢速度的速度,甚至放慢速度。64bits armv8 snapdragon810。
我想念什么吗?是否有人可以在Android ARM上观察到与X86 CPU相当的加速度?
关于如何激活OpenMP的Internet上有很多教程,但没有显示快速的基准。有指针吗?
我发现的唯一相关信息是ARMV8上的OpenMP开销的基准,他们还注意到了一些很高的开销:https://wiki.linaro.org/workinggroups/middleware/graphics/gpgpu/docs/openmpforarmv8portanalysis
谢谢matthieu
Android上的多线程的问题很可能与许多CPU的架构有关。Snapdragon 810是一个低/高的建筑,具有4个强内核和4个弱核心。
具体来说,810在Big.Litter异质配置中使用四个Cortex-A57和四个Cortex-A53核心,其中所有八个内核都可用于OS调度程序。
。
没有好工人的池实施,所有的其他额外线程以平衡工作量的所有其他线程最终都可以达到低性能的核心,根据我的估计,这可能是较重的SIMD计算速度的速度大约是强核的慢(以强度的内核(测量)三星Exynos 9611)。
线条需要使用线程亲和力来创建其他工人,或者需要专门针对每个核心的能力量身定制每个工作负载;在这里,16个块的工作分为8个核
#pragma omp parallel num_threads(8)
{
auto tid = omp_get_thread_num();
uint8_t aff[sizeof(cpu_set_t)] = { 0x80 >> tid };
sched_setaffinity(0, 1, (cpu_set_t *)aff);
if (tid < 4) do_task(tid * 3, tid * 3 + 3);
else do_task(tid+8, tid+9);
}
使用这种方法,使用此方法最初采取110ms的任务减少到30ms,并约37ms,将工作提供给4个更好的核心。
在Continuos工作负载(例如实时信号处理)上,将工作拆分为两倍的内核数,似乎允许Linux调度程序学习计算要求并将线程迁移到不同的内核,但这不是傻瓜证明。(8个内核等于16个块,平均每个快速核心将执行3个块,每个慢速核心将执行1个块。)
在小基准(https://gist.github.com/matt-42/30b7caf73c345c28e5555b7cfd82f5540c)之后,我可以在8核ARMV8上观察到X2加速。我想结论是,如果您可以使用OpenMP在桌面CPU上获得一些加速,这并不意味着您会在ARM CPU上看到类似的加速。