我为Android编写了一个图像处理应用程序(https://play.google.com/store/apps/details?id=cv.cvExperiments https://play.google.com/store/apps/details?id=cv.cvExperiments)以及一些用 JNI 包装的 C++ 代码。为了在多核处理器上获得一些加速,我用 openmp“parallel for”指令注释了昂贵的循环。
问题是,在 x86 上,我在 4 核处理器上获得了从 x3 到 x5 的一些加速,但在 Android 上,激活 OpenMP(使用 -fopenmp)不会在 ARM 32 位上提供任何加速,甚至会减慢 64 位 armv8 上的代码骁龙810。
我错过了什么 ?有人能观察到 android+arm 上的加速速度可与 x86 cpu 相媲美吗?
互联网上有很多关于如何激活 OpenMP 的教程,但没有显示加速情况的基准测试。有什么指示吗?
我发现的唯一相关信息是 armv8 上 OpenMP 开销的基准,他们还注意到一些相当高的开销:https://wiki.linaro.org/WorkingGroups/Middleware/Graphics/GPGPU/Docs/OpenMPforARMv8PortAnalysis https://wiki.linaro.org/WorkingGroups/Middleware/Graphics/GPGPU/Docs/OpenMPforARMv8PortAnalysis
谢谢,
马蒂厄
Android 上的多线程问题很可能与许多 CPU 的架构有关。骁龙 810 是一款低/高架构 https://www.tomshardware.com/reviews/snapdragon-810-benchmarks,4053-2.html,有 4 个强核心和 4 个弱核心。
具体来说,810 在 big.LITTLE 异构配置中采用了四个 Cortex-A57 和四个 Cortex-A53 内核,其中所有八个内核都可供操作系统调度程序使用。
如果没有良好的工作池实现,为平衡工作负载而生成的所有额外线程最终可能会变成低性能核心,根据我的估计,在繁重的 SIMD 计算上,这些核心的速度大约是强核心的三倍(在 Samsung Exynos 9611 上测量) )。
缓解需要使用线程亲和性仅在强核心上创建额外的工作线程,或者需要根据每个核心的功能专门定制每个工作负载;这里,16 个块的工作被分为 8 个核心,即 3+3+3+3+1+1+1+1(快速核心的 CPU id 为 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,使用这种方法将原本需要 110 毫秒的任务减少到 30 毫秒,并将工作交付给 4 个更好的内核,时间减少到约 37 毫秒。
在连续工作负载(例如实时信号处理)上,将工作拆分为两倍数量的核心似乎允许 Linux 调度程序了解计算要求并将线程迁移到不同的核心,但这并不是万无一失的。 (8 个核心等于 16 个块,平均每个快速核心将执行 3 个块,每个慢速核心将执行 1 个块。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)