能跑的epoll

#include <sys/types.h> 
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <sys/epoll.h>


#define RUNTIMES 16


static int count, writes, fired;
static int *pipes;
static int num_pipes, num_active, num_writes;
static int epfd;
static struct epoll_event *events;


unsigned long long getustime(void) {
struct timeval tm;

gettimeofday(&tm, NULL);
return (unsigned long long) tm.tv_sec * 1000000ULL + (unsigned long long) tm.tv_usec;
}


void read_cb(int fd, int idx) {
int widx = idx + num_active + 1;
u_char ch;

if (read(fd, &ch, sizeof(ch)))
count++;
else
fprintf(stderr, "false read event: fd=%d idx=%d\n", fd, idx);
if (writes) {
if (widx >= num_pipes)
widx -= num_pipes;
write(pipes[2 * widx + 1], "e", 1);
writes--;
fired++;
}
}


int run_once(long *work, unsigned long long *tr) {
int i, res;
unsigned long long ts, te;

fired = 0;
for (i = 0; i < num_active; i++, fired++)
write(pipes[i * 2 + 1], "e", 1);

count = 0;
writes = num_writes;

ts = getustime();
do {
res = epoll_wait(epfd, events, num_pipes, 0);
for (i = 0; i < res; i++)
read_cb(pipes[2 * events[i].data.u32], events[i].data.u32);
} while (count != fired);
te = getustime();

*tr = te - ts;
*work = count;

return (0);
}


int main (int argc, char **argv) {
struct rlimit rl;
int i, c;
long work;
unsigned long long tr;
int *cp;
struct epoll_event ev;
extern char *optarg;

num_pipes = 100;
num_active = 1;
num_writes = num_pipes;
while ((c = getopt(argc, argv, "n:a:w:")) != -1) {
switch (c) {
case 'n':
num_pipes = atoi(optarg);
break;
case 'a':
num_active = atoi(optarg);
break;
case 'w':
num_writes = atoi(optarg);
break;
default:
fprintf(stderr, "Illegal argument \"%c\"\n", c);
exit(1);
}
}

rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
exit(1);
}

events = calloc(num_pipes, sizeof(struct epoll_event));
pipes = calloc(num_pipes * 2, sizeof(int));
if (events == NULL || pipes == NULL) {
perror("malloc");
exit(1);
}

if ((epfd = epoll_create(num_pipes)) == -1) {
perror("epoll_create");
exit(1);
}

for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
if (pipe(cp) == -1) {
perror("pipe");
exit(1);
}
fcntl(cp[0], F_SETFL, fcntl(cp[0], F_GETFL) | O_NONBLOCK);
}

for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
ev.events = EPOLLIN;
ev.data.u32 = i;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, cp[0], &ev) < 0) {
perror("epoll_ctl");
exit(1);
}
}

for (i = 0; i < RUNTIMES; i++) {
run_once(&work, &tr);
if (!work)
exit(1);
fprintf(stdout, "%lf\n", (double) tr / (double) work);
}

exit(0);
}
### Python 多进程 CPU 利用率不足的解决方案及 pyarrow.plasma 安装指南 #### 1. **Python 多进程 CPU 利用率不足的原因** Python 的多线程模型受到全局解释器锁(GIL)的影响,使得多个线程在同一时间只能有一个线程执行 Python 字节码。这导致在 I/O 密集型任务中表现较好,但在 CPU 密集型任务中性能受限。相比之下,`multiprocessing` 模块通过创建独立的进程绕过了 GIL 的限制,从而提高了 CPU 利用率[^3]。 然而,在实际使用过程中,可能会因为以下几个原因导致 CPU 利用率仍然较低: - 进程间通信开销过大。 - 数据共享机制效率低下。 - 缺乏有效的负载均衡策略。 #### 2. **提升 Python 多进程 CPU 利用率的方法** ##### 方法一:减少进程间的通信量 过多的进程间通信会显著降低程序的整体性能。可以采用以下措施来优化这一点: - 尽量让每个子进程完成更多的本地计算后再返回结果。 - 使用高效的 IPC 工具如 `queue.Queue`, `multiprocessing.Pipe()` 或者更高级别的框架如 `Ray` 和 `Dask`. ##### 方法二:利用 Apache Arrow 提供的高效数据结构 Apache Arrow 是一种列式内存格式标准,旨在加速大数据处理场景下的数据分析操作。它的 Python 实现—pyarrow—允许开发者轻松地与其他库交互,例如 Pandas 和 NumPy[^4]。 对于需要频繁交换大量表格数据的应用来说,直接基于 Arrow 表格构建分布式计算流水线往往能带来数量级上的提速效果。此外,借助于其内置的支持零拷贝序列化的特性,还可以进一步削减不必要的内存复制成本。 ##### 方法三:探索异步编程模式 虽然传统意义上的同步阻塞 IO 不适合用来解决这个问题,但是现代操作系统提供的 epoll/kqueue 等事件驱动接口却非常适合用来管理成千上万的同时连接请求。结合 asyncio 标准库以及 trio/tornado/aiohttp 等第三方扩展包一起使用的话,则可以让原本串行等待的任务变成并发执行的状态,进而有效缓解单核瓶颈问题。 #### 3. **pyarrow.plasma 模块的作用及其安装方式** Plasma 是由 Ray 开发的一套轻量级的对象存储系统,专为满足大规模机器学习训练作业期间产生的中间状态保存需求而设计。它被集成到了 PyArrow 当中作为实验性质的功能选项提供给广大社区成员试用[^4]。 要成功启用这一部分功能,请按照下列步骤依次操作即可顺利完成整个配置流程: ```bash # 步骤一:更新 setuptools 工具链至最新版本 pip install --upgrade setuptools wheel # 步骤二:下载并编译 C++ 版本的核心依赖项 git clone https://github.com/apache/arrow.git cd arrow/cpp mkdir build && cd build cmake .. make -j$(nproc) # 步骤三:切换回顶层目录重新构建 python 扩展件 cd ../python PYTHONPATH=$(pwd)/build/python:$PYTHONPATH \ ARROW_BUILD_TYPE=release \ ARROW_HOME=/path/to/local/installation \ PLASMA_STORE_SIZE=$((1 << 30)) \ pytest -v test_plasma.py # 最终一步:正式发布成果物到站点包路径下 ARROW_PLASMA_ENABLED=true pip install . ``` 注意替换 `/path/to/local/installation` 成为你自己系统的实际情况! --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值