我编写了一个用于安卓系统的图像处理应用程序(https://play.google.com/store/apps/details?id=cv.cvExperiments),其中包含一些用JNI封装的C++代码。为了在多核处理器上获得一些加速,我使用openmp "parallel for“指令注释了昂贵的循环。
问题是,在x86上,我在4核处理器上获得了从x3到x5的一些加速,但在安卓上,激活OpenMP (使用-fopenmp)在ARM 32位上没有任何加速,甚至在64位armv8 Snapdraon810上的代码速度也变慢了。
我错过了什么吗?有没有人能观察到android+arm的加速比得上x86 cpus?
在互联网上有很多关于如何激活OpenMP的教程,但没有基准测试显示加速。有什么建议吗?
我找到的唯一相关信息是armv8上的OpenMP开销基准,他们还注意到了一些相当高的开销:https://wiki.linaro.org/WorkingGroups/Middleware/Graphics/GPGPU/Docs/OpenMPforARMv8PortAnalysis
谢谢,马修
发布于 2020-10-07 19:55:09
Android上的多线程问题很可能与许多CPU的架构有关。Snapdrag810是一款low/high architecture,有4个强内核和4个弱内核。
具体地说,810在big.LITTLE异构配置中使用四个Cortex-A57和四个Cortex-A53内核,其中所有八个内核均可供操作系统调度程序使用。
如果没有良好的工作池实现,为平衡工作负载而产生的所有额外线程最终可能会导致性能低下的核心,根据我的估计,在繁重的SIMD计算上,这可能是强大核心(在Samsung Exynos 9611上测量)的大约三倍慢。
mitagation需要使用线程亲和性来仅在强核心上创建额外的工作进程,或者需要针对每个核心的能力专门定制每个工作负载;在这里,16个块的工作被拆分为8个核心作为3+3+3+3+1+1+1+1 (快速核心的CPU为4..7)。
#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);
}使用OMP,任务从最初的110ms减少到30ms,并使用这种方法减少到大约37ms,只将工作交付给4个更好的内核。
对于连续的工作负载(例如,实时信号处理),将工作划分到两倍的核心数量似乎允许linux调度器了解计算需求并将线程迁移到不同的核心,但这并不是最简单的。(8个核心等于16个块,平均每个快速核将执行3个块,每个慢核将执行1个块。)
发布于 2016-06-24 23:45:25
在一个小的基准测试(https://gist.github.com/matt-42/30b7caf73c345c28e55b7cfd82f5540c)之后,我可以观察到8核armv8上的x2加速。我认为结论是,如果您可以在使用OpenMP的桌面CPU上获得一些加速,这并不意味着您将在ARM CPU上看到类似的加速。
https://stackoverflow.com/questions/37985137
复制相似问题