首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何尽可能快地输出固定缓冲区?

如何尽可能快地输出固定缓冲区?
EN

Stack Overflow用户
提问于 2019-03-28 10:22:52
回答 3查看 478关注 0票数 3

样本代码:

代码语言:javascript
复制
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <pthread.h>

int
main (int argc, char **argv)
{

  unsigned char buffer[128];
  char buf[0x4000];
  setvbuf (stdout, buf, _IOFBF, 0x4000);
  fork ();
  fork ();

  pthread_t this_thread = pthread_self ();

  struct sched_param params;

  params.sched_priority = sched_get_priority_max (SCHED_RR);

  pthread_setschedparam (this_thread, SCHED_RR, &params);


  while (1)
    {
      fwrite (&buffer, 128, 1, stdout);
    }
}

该程序打开4个线程,并在标准输出上输出“缓冲区”的内容,即64位cpu上的128字节或16个长ints。

如果我跑了:

./writetest \ pv -ptebaSs 800 g >/dev/null

我的速度大约是7.5GB/s。

顺便说一句,如果我这样做的话,我的速度也是一样的:

代码语言:javascript
复制
$ mkfifo out
$ dd if=/dev/zero bs=16384 >out &
$ dd if=/dev/zero bs=16384 >out &
$ dd if=/dev/zero bs=16384 >out &
$ dd if=/dev/zero bs=16384 >out &
pv <out -ptebaSs 800G >/dev/null

有什么办法让这个更快吗?请注意。实际程序中的缓冲区没有填充零。

我的好奇心是了解一个程序(多进程或多进程)输出的数据数量

看起来有4个人不明白这个简单的问题。我甚至大胆地提出了这个问题的理由。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-03-31 10:17:12

看来linux调度程序和IO优先级在经济放缓中起了很大的作用。

此外,幽灵和其他cpu的可维护性降低也开始发挥作用。

经过进一步的优化之后,为了达到更快的速度,我不得不调整如下内容:

代码语言:javascript
复制
1) program nice level (nice -n -20)
2) program ionice level (ionice -c 1 -n 7)
3) pipe size increased 8 times.
4) disable cpu mitigations by adding "pti=off spectre_v2=off l1tf=off" in kernel command line
5) tuning the linux scheduler

echo -n -1 >/proc/sys/kernel/sched_rt_runtime_us
echo -n -1 >/proc/sys/kernel/sched_rt_period_us
echo -n -1 >/proc/sys/kernel/sched_rr_timeslice_ms
echo -n 0 >/proc/sys/kernel/sched_tunable_scaling

现在,程序输出(在同一台pc上)8.00GB/秒!

如果你有其他的想法,我们欢迎你做出贡献。

票数 5
EN

Stack Overflow用户

发布于 2019-03-28 12:35:51

首先,您需要确定您的速率限制因素。它可以是cpu/内存速度,cpu/系统调用延迟,管道实现,stdio实现。可能还有更多,但这是一个良好的开端:

  1. cpu/内存--测试你能以多快的速度记住一堆零。
  2. cpu/syscall --通过将1字节写入/dev/null来测试在系统上进行简单写入所需的时间
  3. 管道实现--您可以这样做,但是您可以尝试改变管道容量( fcntl(2) F_GETPIPE_SZ )。F_SETPIPE_SZ,如果您在linux上)。
  4. stdio实现--用写代替fwite/setbuf。我建议您的写入大小与管道容量/num-进程可能会产生一个好的结果,但您可能应该进行更广泛的研究。

尝试以上所有的多个进程,尽管您可能需要扩展memcpy进程以获得有意义的结果。

使用这些数字,您应该能够计算出您的最大吞吐量。请汇报,我相信有超过几个人是有兴趣的。

票数 1
EN

Stack Overflow用户

发布于 2019-03-28 12:42:08

你程序所做的是:

  1. 打给fwrite。它只是将数据从buffer复制到buf
  2. 一旦buf被填满,它就会调用write

为了加快速度,在步骤1和fwrite中避免复制,直接使用write syscall。例如:

代码语言:javascript
复制
char buf[0x4000];
for(;;)
    write(STDOUT_FILENO, buf, sizeof buf); // Implement error handling.

您还可能希望使buf变得更大,以尽量减少syscalls的数量(谱减轻会使syscalls更昂贵)。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55395211

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档