zig中的线程设置亲和性

背景

最近写c/c++烦了,学了下rust和zig,rust的人体工程学真好,就是写起来不快乐,还是zig好,很快乐 :)

学完基础之后,分析了下将之前写的c++代码重写成zig的可能性,基本上都可以替换,主要是两个方面:

  1. 变量的生命周期,代码大量使用shared_ptr和unique_ptr,但是还好的是,生命周期基本上是已知的(shared_ptr多线程析构是不安全的,得清楚的知道变量的存活周期);
  2. NUMA:现代的系统架构都是非对称的,从一个NUMA操作另一个是有性能开销(内存、CPU)。

对第二个问题,之前使用的pthread_setaffinity_np,但是zig 0.14 的std.c.pthread_xxx没有这个函数,估计是编译的时候没有开#define _GNU_SOURCE,所以现在目的很明确,使用操作系统内部的pthread。

方法

  1. 使用@cImport (实测会有问题)
const c = @cImport({
    @cInclude("pthread.h");
});

build.zig里面增加exe.linkLibC();,顺便一提,build.zig文件可以使用zig init生成。
这里有个坑,如果在cImport里面定义_GNU_SOURCE宏,也就是@cDefine("_GNU_SOURCE", "");,实际不生效,估计是编译器内部处理顺序有问题导致。得放到build.zig里面:

exe_mod.addCMacro("_GNU_SOURCE", "");

使用这个方法写,会导致CPU_ZEROCPU_SET用不了,报错信息是说解析不了这两个宏定义,看后续编译器版本有无优化了。

  1. 将之前写的设置affinity封装到c函数中
// file: src/set_affinity.h
#pragma once
#define _GNU_SOURCE
#include <pthread.h>
void set_affinity(pthread_t thread, int cpu);

头文件定义里面只传了一个CPU,实际应该传多个,这里只是简单介绍。

#include "set_affinity.h"
void set_affinity(pthread_t thread, int cpu) {
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(cpu, &cpuset);
    pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
}

注意define要放到pthread.h的前面,也可以放到build.zig里面(见方法1)。
后面就简单了,在build.zig里面添加上这个文件就行。

exe_mod.addIncludePath(b.path("src"));
exe_mod.addCSourceFile(.{
    .file = b.path("src/set_affinity.c"),
});
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容