c++ - 在 iOS 设备上执行并发任务时如何设置合适的线程数?
问题描述
我开发了一个跨平台的 c++ 库,它在运行时产生线程。我使用并发队列来调度计算任务,因此每个线程大部分时间都会很忙。
现在的问题是如何在运行时获得适当数量的线程。由于我的任务没有 I/O 或网络操作,只有计算和堆内存分配,所以最好的策略是为每个 CPU 内核生成线程:
我的代码如下所示:
#include "concurrentqueue.h"
#include <algorithm>
#include <thread>
#include <vector>
#include <iostream>
#include <mutex>
std::mutex io_m;
struct Task {
int n;
};
void some_time_consuming_operations(Task &t) {
std::vector<int> vec;
for (int i = 0; i < t.n; ++i)
vec.push_back(1);
{
std::lock_guard<std::mutex> g(io_m);
std::cout << "thread " << std::this_thread::get_id() << " done, vec size:" << vec.size() << std::endl;
}
}
int main() {
// moodycamel's lockfree queue: https://github.com/cameron314/concurrentqueue
moodycamel::ConcurrentQueue<Task> tasks;
for (int i = 0; i < 100; ++i)
tasks.enqueue(Task{(i % 5) * 1000000 + 1000000});
// I left 2 threads for ui and other usages
std::vector<std::thread> jobs(std::max((size_t)2, (size_t)std::thread::hardware_concurrency() - 2));
std::cout << "thread num:" << jobs.size() << std::endl;
for (auto &job : jobs) {
job = std::thread([&tasks]() {
Task task;
while (tasks.try_dequeue(task))
some_time_consuming_operations(task);
});
}
for (auto &job : jobs)
job.join();
return 0;
}
但是,在我的 iOS 设备(iPhone XR、A12)上启用多线程时,测试程序比单线程模式慢 2 倍。我已经在我的 windows 机器上用 4 核 8 线程 intel CPU 对其进行了测试,它比单线程模式快 6 倍。
在我的 iPhone 上,该hardware_concurrency
函数返回6
,这正是 Apple A12 的核心编号。在我的 Windows 机器上,数字是 8。
我知道 Apple 的 A12 有 4 个称为 Tempest 的节能核心,但因为他们声称A11/A12 将同时使用所有六个核心(我在测试期间保持充电)。我不知道为什么它比单线程模式慢。
测试程序是UE4构建的游戏应用。
解决方案
四个较慢的核心比快速核心慢很多。因此,如果您在一个快速核心上执行一项需要 6 秒的任务,并在每个核心上运行一秒钟的工作,那么两个快速核心将在一秒钟后完成,而四个慢速核心可能需要 10 秒。
如果您使用 GCD,iOS 将在内核之间混洗这六个线程,因此您可以获得高达 2.4 倍的速度。如果您的线程实现不这样做,那么您正在减慢速度。
解决方案:要么使用 GCD(并获得 2.4 的加速),要么仅使用两个线程(并获得 2.0 的加速)。那是在 iPhone XR 上;您需要以某种方式找出快速核心的数量。
推荐阅读
- php - PHP如何获取文件读取下一个lLine
- machine-learning - 有没有办法将自定义测试数据传递到 XGBoost 预测模型中?
- java - 有人可以解释一下,java递归是如何工作的,特别是在下面的这个程序中?
- c# - 在 iOS 中调用 Web 服务时,Xamarin 表单 ios 出现异常
- python - 如何使用 'id' 打印所有值:
- java - 这是在 guice 中使用自定义注释的正确方法吗?
- java - Appium如何验证两个子节点是否属于同一个父节点
- python - 提高除数查找功能的性能
- javascript - 页面加载时如何在我的视图模型中执行功能
- sql - 如何找到两个表列之间的时间差?