Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
memcpy()导致的锯齿状CPU负载模式。cpu缓存或内存管理问题?_C_Windows_Memory Management_Heap_Cpu Cache - Fatal编程技术网

memcpy()导致的锯齿状CPU负载模式。cpu缓存或内存管理问题?

memcpy()导致的锯齿状CPU负载模式。cpu缓存或内存管理问题?,c,windows,memory-management,heap,cpu-cache,C,Windows,Memory Management,Heap,Cpu Cache,因为这听起来像是一个与ffmpeg相关的问题,我相信不是 我们有一个系统,通过使用ffmpeg的过滤器处理实况电视节目 我们从视频捕获卡捕获帧并将其复制到我们自己的数据结构中 我们复制帧信息ffmpeg的本机结构 我们运行过滤器 我们将ffmpeg的本机结构中生成的帧复制回我们自己的结构中 单个帧使用4.15 Mb动态分配的内存。 使用_aligned_malloc()分配帧缓冲区。 该服务器是一个2倍Intel Xeon E5-2697v4 Windows server 2016机箱,具有64

因为这听起来像是一个与ffmpeg相关的问题,我相信不是

我们有一个系统,通过使用ffmpeg的过滤器处理实况电视节目

  • 我们从视频捕获卡捕获帧并将其复制到我们自己的数据结构中
  • 我们复制帧信息ffmpeg的本机结构
  • 我们运行过滤器
  • 我们将ffmpeg的本机结构中生成的帧复制回我们自己的结构中
  • 单个帧使用4.15 Mb动态分配的内存。 使用_aligned_malloc()分配帧缓冲区。 该服务器是一个2倍Intel Xeon E5-2697v4 Windows server 2016机箱,具有64Gb内存

    2个NUMA节点。分配给每个节点的进程

    每个进程2个通道,每个服务器总共4个通道,每个通道每秒25帧

    所有内存分配都使用一个默认进程堆。 除了帧缓冲区外,还可以进行多种用途的动态内存分配。 每个进程使用2Gb的物理内存

    当我们运行系统时,一切正常。观察到平坦的CPU负载。 过了一段时间(通常是几个小时),我们开始在CPU负载中看到锯齿模式:

    当我们使用Intel的VTune放大器2018进行调查时,发现step2中的memcpy()在这些高CPU周期消耗了大量CPU时间

    下面是我们从VTune 2018热点分析中看到的内容

    **LOW CPU PERIOD (a total of 8,13 sec)**
    
    SleepConditionVariableCS    14,167 sec CPU time
    WaitForSingleObjectEx       14,080 sec CPU time
    memcpy                       3,443 sec CPU time with the following decomposition:
      -- get_frame(step4)         -- 2,568
      -- put_frame(step2)         -- 0,740
      -- decklink_cb(step1)       -- 0,037
    
    **HIGH CPU PERIOD (a total of 8,13 sec)**
    
    memcpy                      16,812 sec CPU time with the following decomposition:
      -- put_frame(step2)         -- 10,429
      -- get_frame(step4)         --  3,692
      -- decklink_cb(step1)       --  2,236
    SleepConditionVariableCS    14,765 sec CPU time
    WaitForSingleObjectEx       13,928 sec CPU time
    _aligned_free()              3,532 sec CPU time
    
    下面是执行步骤2中的memcpy()操作所需时间的图表。 Y轴是以毫秒为单位的时间

    下面是单个帧的总处理时间图。 Y轴是以毫秒为单位的时间。 “0”读数是由于延迟导致的帧下降,应忽略不计

    当CPU越来越高,memcpy()开始花费更长的时间时,进程的句柄数就会减少

    我们在步骤2中记录了从_aligned_malloc()返回的地址。 这是我们将4.15 Mb帧数据复制到的内存中的缓冲区位置

  • 对于低CPU周期,从_aligned_malloc()返回的地址彼此非常接近,即,从两个连续内存分配操作返回的地址之间的差异往往很小
  • 对于高CPU周期,从_aligned_malloc()返回的地址范围非常大
  • 我们在总CPU负载中看到的锯齿模式似乎是由于步骤2中的memcpy()操作造成的。 对于高CPU周期,与低CPU周期返回的缓冲区地址相比,从_aligned_malloc()返回的缓冲区地址似乎具有不好的局部性

    我们相信,当我们使用memcpy()时,操作系统开始做一些额外的事情。页面错误期间是否有其他任务?一些清洁的东西?这是缓存问题吗?不知道


    是否有人可以对这种情况的原因和解决方案发表评论?

    在实际使用堆之前,操作系统可能不会实际分配堆上的数据,这意味着在
    malloc
    调用过程中不一定会分配数据,而是在您第一次使用时分配数据。这可能就是你所看到的。如果访问代码是关键的,那么尝试直接在malloc之后“虚拟访问”数据,以将分配移动到您期望的位置。问题在于一段时间内“memcpy”时间之间的差异。按照我提供的映像的锯齿模式复制内存(当CPU增加时)需要更长的时间。顺便说一下,我们已经按照您的建议在分配后直接访问“malloced”内存。您有两个进程,每个进程固定到不同的NUMA节点?请注意,将进程或线程固定到节点并不保证仅从节点的内存中满足内存分配。我建议进行一次测试。我将尝试并更新结果。