如何在Apple Silicon的macOS上仅将线程绑定到性能核心?
在搭载M1/M1 Pro等非对称核心Apple芯片的macOS上,如何确保线程仅运行在性能核心?
我正在开发一款音频应用,需要绝对确保关键线程只在性能核心上运行,完全不调度到效率核心。
我已经参考过苹果的官方性能调优文档,尝试通过设置Quality of Service (QoS)类来引导线程调度到性能核心,示例代码如下:
pthread_attr_t qosAttribute; pthread_attr_init(&qosAttribute); pthread_attr_set_qos_class_np(&qosAttribute, QOS_CLASS_USER_INTERACTIVE, 0); pthread_create(&thread, &qosAttribute, f, NULL);
虽然设置最高级别的QoS有一定效果,但无法保证线程绝对不会被调度到效率核心。
我知道Linux上可以用pthread_setaffinity_np通过核心掩码绑定线程到特定核心,但macOS没有这个函数,我也找不到如何获取性能/效率核心对应掩码的相关信息。
请问有没有可行的方案能实现线程仅绑定到苹果芯片的性能核心?
解决方案:使用线程亲和性策略(THREAD_AFFINITY_POLICY)
macOS提供了thread_policy_set API来设置线程的亲和性策略,结合核心信息获取,可以精准绑定线程到性能核心。
步骤1:区分性能核心与效率核心
通过sysctlbyname获取系统核心的类型信息,苹果芯片的性能核心和效率核心可通过hw.perflevel系列sysctl节点区分,性能核心的perflevel标识通常为1,效率核心为0。示例代码片段:
#include <sys/sysctl.h> #include <mach/mach.h> uint64_t get_performance_core_mask() { uint64_t mask = 0; int num_cpus = sysconf(_SC_NPROCESSORS_ONLN); // 遍历所有核心,筛选性能核心 for (int i = 0; i < num_cpus; i++) { int perf_level; size_t len = sizeof(perf_level); char name[64]; snprintf(name, sizeof(name), "hw.perflevel%d.cpu_type", i); if (sysctlbyname(name, &perf_level, &len, NULL, 0) == 0) { if (perf_level == 1) { mask |= (1ULL << i); } } } return mask; }
步骤2:设置线程亲和性
将线程绑定到性能核心掩码上:
#include <mach/thread_policy.h> bool bind_thread_to_performance_cores(pthread_t thread) { thread_port_t mach_thread = pthread_mach_thread_np(thread); thread_affinity_policy_data_t affinity_policy; affinity_policy.affinity_tag = get_performance_core_mask(); kern_return_t ret = thread_policy_set( mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&affinity_policy, THREAD_AFFINITY_POLICY_COUNT ); return ret == KERN_SUCCESS; }
注意事项
- 该方案支持macOS 10.12及以上版本,在Apple Silicon芯片上完全兼容。
- 音频应用的实时线程建议搭配
QOS_CLASS_REALTIME使用,进一步强化调度优先级,亲和性策略是确保核心绑定的关键。 - 不同型号Apple芯片的核心
perflevel标识可能略有差异,建议在目标设备上测试验证。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

