You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Dask库@delayed装饰器为何性能反而不及串行代码?

Dask @delayed性能反直觉问题解惑

问题背景

我正在学习Dask库的使用,尝试用@delayed装饰器实现并行计算,结果发现并行代码的运行时长反而远高于普通串行代码。即使增加迭代次数,结果依然一致,特此寻求解惑。

测试环境:Windows系统、4物理核8逻辑核、Python 3.11.0、Dask 2023.6.0


带Dask delayed装饰器的代码

import time
import dask
from dask import delayed

@delayed
def square(x):
    return x*x

@delayed
def double(x):
    return x*2

@delayed
def add(x, y):
    return x + y

@delayed
def sum(output):
    sum = 0
    for i in output:
        sum += i

    return sum

t1 = time.time()

# 循环调用上述函数处理每个数据
output = []
for i in range(99999):
    a = square(i)
    b = double(i)
    c = add(a, b)
    output.append(c)

total = dask.delayed(sum)(output)
print(total)

print("Elapsed time: ", time.time() - t1)

运行时长:~8.46s


普通串行代码

import time

def square(x):
    return x*x

def double(x):
    return x*2

def add(x, y):
    return x + y

def sum(output):
    sum = 0
    for i in output:
        sum += i

    return sum

t1 = time.time()

# 循环调用上述函数处理每个数据
output = []
for i in range(99999):
    a = square(i)
    b = double(i)
    c = add(a, b)
    output.append(c)

total = sum(output)
print(total)

print("Elapsed time: ", time.time() - t1)

运行时长:~0.043s


原因分析与解决建议

核心原因

  1. 任务粒度极小,调度开销远超计算成本:你定义的square、double、add都是极简单的算术运算,执行耗时可以忽略,但Dask为每个任务创建延迟对象、构建依赖关系的开销远大于计算本身。串行代码直接执行运算,无额外开销,自然更快。
  2. 未实际触发并行计算:你的Dask代码只完成了任务图的构建,没有调用total.compute()触发实际的并行执行。这段代码的耗时几乎全在构建近30万个任务的依赖图上,完全没用到Dask的并行能力。
  3. 场景不匹配:Dask的优势在于处理计算密集、任务粒度大的场景(如大数据处理、复杂模型训练),或处理超出内存的数据集,而非这种简单循环的轻量运算。

解决建议

  • 合并细粒度任务:把循环内的多个轻量运算打包成一个延迟函数,大幅减少任务数量。例如将square、double、add合并为一个process_single函数,再用@delayed装饰。
  • 调用compute()触发执行:构建完任务图后,必须调用.compute()才能让Dask调度并行计算。
  • 改用Dask Collections:如果是处理数组或表格数据,优先使用Dask Array、Dask DataFrame,它们会自动优化任务粒度和调度逻辑。

修改后的示例代码

import time
import dask
from dask import delayed

@delayed
def process_single(i):
    a = i*i
    b = i*2
    return a + b

@delayed
def sum_batch(output):
    return sum(output)

t1 = time.time()

output = [process_single(i) for i in range(99999)]
total = sum_batch(output).compute()  # 触发并行计算
print(total)

print("Elapsed time: ", time.time() - t1)

内容的提问来源于stack exchange,提问作者madmatrix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:45:05