多处理-共享计数器显示负值

时间:2018-11-06 06:57:01

标签: python multiprocessing

我正在尝试在脚本中实现多处理计数器,但不确定结果是否有意义。

# Global shared variable 
total_bytes_written = multiprocessing.Value('i', 0)

# Worker method
def s3_put_worker(**kwargs):
    global total_bytes_written
    # local var that stores a data chunk length
    data_chunk_len = len(data_chunk)

    while not stop_event.is_set():
        # do some work
        # ...
        # The counter that sums shared_total_written variable with local var
        with total_bytes_written.get_lock():
            total_bytes_written.value += data_chunk_len

# I'm using ProcessPoolExecutor to start several Gevent thread pools that runs my worker method

现在停止脚本后,我得到了那些奇怪的结果:

2018-11-06 04:42:55,412; [s3_stress.s3_stress_runner] (MainProcess : MainThread) INFO - Total bytes written to storage: -1946157056

我怀疑我无法将多处理共享var与本地方法的var相加,但是我找不到关于该主题以及如何解决该问题的任何信息。

谢谢

1 个答案:

答案 0 :(得分:2)

您的问题似乎是由溢出引起的:Value('i', 0)是一个带符号的32位整数,最多可以计数2147483647(用于字节计数大约为2GiB)。

>>> total_bytes_written = multiprocessing.Value('i', 0)
>>> total_bytes_written.value += 2147483647  # 2GiB - 1B
>>> total_bytes_written
<Synchronized wrapper for c_int(2147483647)>
>>> total_bytes_written.value += 1
>>> total_bytes_written
<Synchronized wrapper for c_int(-2147483648)>

Value的最大data type'Q'的无符号long long(至少64位)。这可以处理范围[0, 18_446_744_073_709_551_615]或最多16EiB的字节计数。如果您关心正确的符号处理,则已签名的long long类型'q'仍可算到8EiB。

>>> total_bytes_written = multiprocessing.Value('q', 0)
>>> total_bytes_written.value += 9223372036854775807  # 8EiB - 1B
>>> total_bytes_written
<Synchronized wrapper for c_long(9223372036854775807)>