If 语句在 dask 数组上

If statement over dask array

大家好,你能告诉我为什么 dask 数组上的 If 语句这么慢以及如何解决它吗?

import dask.array as da
import time

x = da.random.binomial(1, 0.5, 200, 200)
s = time.time()
if da.any(x):
    e = time.time()
    print('duration = ', e-s)

output: duration =  0.368

我看了看dask源代码。本质上,当您在 dask 数组上调用函数时,它会执行数组的 "reduction"。直觉上这是必要的,因为在幕后,dask 数组存储为单独的 "blocks",可以单独存在于内存、磁盘等中,但您需要以某种方式将它们的各个部分拉在一起以进行函数调用。

所以您注意到的时间是在执行缩减的初始开销中。请注意,如果将数组的大小增加到 2M,它所花费的时间与 200 大致相同。在 20M 时,它只需要大约 1s。

import dask.array as da
import time

# 200 case
x = da.random.binomial(1, 0.5, 200, 200)
print x.shape
s = time.time()
print "start"
if da.any(x):
    e = time.time()
    print 'duration = ', e-s

# duration =  0.362557172775


# 2M case
x = da.random.binomial(1, 0.5, 2000000, 2000000)
print x.shape
s = time.time()
print "start"
if da.any(x):
    e = time.time()
    print 'duration = ', e-s

# duration =  0.132781982422

# 20M case
x = da.random.binomial(1, 0.5, 20000000, 20000000)
print x.shape
s = time.time()
print "start"
if da.any(x):
    e = time.time()
    print 'duration = ', e-s

# duration =  1.08430886269


# 200M case
x = da.random.binomial(1, 0.5, 200000000, 200000000)
print x.shape
s = time.time()
print "start"
if da.any(x):
    e = time.time()
    print 'duration = ', e-s

# duration =  8.83682179451

默认情况下,Dask 数组是惰性的,因此在您对数组调用 .compute() 之前不会执行任何工作。

在你的例子中,当你将 dask 数组放入 if 语句时,你隐式调用了 .compute(),它将事物转换为布尔值。

x = da.random.random(...)  # this is free
y = x + x.T  # this is free
z = y.any()  # this is free

if z:  # everything above happens now, 
    ...