【问题标题】:Why is it faster sending data as encoded string than sending it as bytes?为什么以编码字符串形式发送数据比以字节形式发送数据更快?
【发布时间】:2022-02-28 06:09:47
【问题描述】:

我正在使用 pyzmq 进行 4k HDR 图像数据的进程间传输,并注意到:

byt = np.array2string(np.random.randn(3840,2160,3)).encode()
while True:
   socket.send(byt)

比:

快得多
byt = np.random.randn(3840,2160,3).asbytes()
while True:
   socket.send(byt)

有人能解释为什么吗?我似乎无法理解它。

【问题讨论】:

    标签: numpy ipc zeromq pyzmq low-latency


    【解决方案1】:

    问:为什么更快 发送...?谁能解释一下为什么

    A :
    +1 曾问过 WHY -
    真正理解 WHY 的人是那些努力学习问题根源的人,以便真正了解核心原因,从而在下一步设计更好的系统,了解非常WHY(在模仿模仿或复制/粘贴别人时不走捷径)

    那么,让我们开始吧:

    HDR 不是 SDR,
    我们将有“大量数据” 在这里获取 - 存储 - 处理 - 发送,


    事实清单
    - 按此顺序:数据、流程、.send()、谁变得更快以及为什么

    数据:
    被定义为numpy 提供默认dtype 的 4K-HDR 大小的三重数据值数组,其中 ITU-T 建议 BT-2100 HDR色彩空间至少需要 10 位才能增加色彩动态范围

    原样代码提供numpy.random.randn( c4K, r4K, 3 ) 的默认值 dtypenp.float64。只是为了正确和合适的系统设计,HDR(扩展一个普通的 8 位 sRGB 三字节色彩空间)应该总是更喜欢基于int{10|12|16|32|...} 的存储,而不是在管道的后期扭曲任何数字图像后处理阶段。

    过程:
    实际的消息负载生成过程被定义为
    Case-A ) np.array2string( ) 后跟 .encode() 方法

    Case-B ) numpy.ndarray-native (原文如此) .asbytes()-方法

    .send()
    ZeroMQ Scalable Formal Communication Archetype 模式(未知类型)最终接收进程生成的消息有效负载,转换为(blocking-form of the).send()-method


    为什么的解决方案和如何做的提示:

    核心区别隐藏在我们试图将苹果与橙子进行比较的事实中。

    >>> len(                  np.random.randn( c4K, r4K, 3 ).tobytes() ) / 1E6
    199.0656 [MB]
    
    >>> len( np.array2string( np.random.randn( c4K, r4K, 3 ) )         ) / 1E6
    0.001493 [MB] ... Q.E.D.
    

    虽然 (sic) .asbytes()-方法会生成完整副本(包括 RAM 分配 + RAM-I/O 流量 [SPACE] + [TIME]-domains 的成本),即在 ZeroMQ 启动 .send()-method ZeroCopy 魔法之前花费一些额外的 us

    print(                        np.random.randn( c4K, r4K, 3 ).tobytes.__doc__ )
    a.tobytes(order='C')
    
       Construct Python bytes containing the raw data bytes in the array.
    
       Constructs Python bytes showing a copy of the raw contents of
       data memory. The bytes object is produced in C-order by default.
       This behavior is controlled by the ``order`` parameter.
    
       .. versionadded:: 1.9.0
    


    另一种情况,Case-A,首先扔掉 (!),还有很多 (!).. . 取决于实际的numpy matrix-UI-presentation 配置设置,甚至在将它们移动到.encode()-phase 之前,还有很多原始 4K-HDR 数据:

     >>> print( np.array2string( np.random.randn( c4K, r4K, 3 ) ) )
     [[[ 1.54482944 -0.23189048 -0.67866246]
       ...
       [ 0.13461456  1.47855833 -1.68885902]]
     
      [[-0.18963557 -1.1869201   1.34843493]
       ...
       [-0.3022641  -0.44158803  0.75750368]]
     
      [[-1.05737969  0.864752    0.36359686]
       ...
       [ 1.70240612 -0.12574642 -1.03325878]]
     
      ...
     
      [[ 0.41776933  1.73473723  0.28723299]
       ...
       [-0.47635911  0.15901325 -0.56407537]]
     
      [[-1.41571874  1.66735309  0.6259928 ]
       ...
       [-0.93164127  0.95708002  1.3470873 ]]
     
      [[ 0.16426176 -0.00317156  0.77522962]
       ...
       [ 0.32960196 -1.74369368 -0.34177759]]]
     
    

    因此,发送 less-DATA 意味着花费更少的时间来移动它们。

    提示如何:

    1. 在传递对.send()-方法的引用时,使用zmq.DONTWAIT 标志将受益于ZeroMQ 方法和整体性能

    2. 在可能的情况下,尽量重用最出色的 numpy-tooling,以尽量减少重复的 RAM 分配(我们可能会预先分配和重用已分配的变量)

    3. 尝试使用尽可能紧凑的 DATA 表示,如果以最小的延迟寻求最高性能 - 避免冗余、紧凑、CPU 缓存线的层次结构和关联性匹配格式将始终在最终性能的竞赛中获胜(使用内部numpy-storage 区域的视图,即不使用任何中介方法来读取访问实际的 4K-HDR 数据块可能有助于将整个管道移动到 ZeroCopy 到 ZeroMQ .send()-推送仅数据引用(即没有从/到 RAM 复制或移动单个数据字节,直到将其加载到线路上......)......这是我们在这里设计工作的最酷的性能结果,不是吗?)

    4. 无论如何,在所有关键部分,避免gc.disable() 阻塞流的影响,至少推迟潜在的.collect() 不会在“这里”发生

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-02
      • 2013-07-17
      • 1970-01-01
      • 1970-01-01
      • 2022-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多