我正在尝试加快代码速度,提高对Dask和Numba的理解,我确实尝试在我创建的一些示例中使用这两个示例,但并没有任何改进,我也不明白为什么。
我必须说我正在使用具有四核的笔记本电脑,所以改进可能不会很大,但是仍然应该在那儿。
更准确地说,是在Windows 10笔记本电脑上,使用Python 3.7并在conda环境中使用Numba和Dask。
这是我的代码:
import numpy as np
import pandas as pd
from numba import jit
import dask.dataframe as dd
data = np.random.randint(-10, 10, (10**8, 3))
df = pd.DataFrame(data=data, columns=["A", "B", "C"], index=None)
df["F"] = np.random.choice(["apple", "banana", "orange",
"pear","grape","lime","citrus","peach"],10**8)
如您所见,这是一个很大的数据帧内存明智的选择,这是我检查Dask是否代表改进的方式。在较小的数据帧(<200MB)上,这似乎根本没有改变。
ddf = dd.from_pandas(df,npartitions=12)
@jit
def remove_special_char_with_numba(x):
return x.replace('r','')
这是一个玩具示例,在该示例中,我尝试从特定列中删除字符串,与普通熊猫相比,Numba确实加快了代码的执行速度,但不支持字符串,因此我无法修改替换或使用nopython模式。 现在:
%%timeit
remove_special_char_with_numba(df["F"])
输出:
每个循环58.9 s±9.51 s(平均±标准偏差,共运行7次,每个循环1次)
接下来,我对以下内容的理解是:Dask将我的数据帧分为不同的块/分区,并且它将对每个分离的块独立应用该功能。据我所知,它具有四个核心,应该可以加快该过程。
%%timeit
ddf["F"].map_partitions(remove_special_char_with_numba).compute()
输出:
每个循环45.9 s±10.5 s(平均±标准偏差,共运行7次,每个循环1次)
现在我不想贪婪,但是进步不应该大于此吗?我做错什么了吗?
谢谢
答案 0 :(得分:0)
这个结果应该不会让您感到惊讶。显然,您正在默认线程调度程序上运行。
这意味着每个字符串操作都必须获取单个python GIL才能发生,并且无论它是否在dask控制的工作线程中都是如此。对于该操作的numba-jit版本,这仍然适用,因为您无法在非python模式下运行此函数。如果在非python模式下 ,它将释放GIL,并且全字符串支持将进入numba。
使用分布式调度程序处理多个进程可能会获得更好的加速,尽管那样会增加在进程之间发送数据的成本,因此,如何生成数据以及将所有数据带到一起这一事实很重要。 compute()
时,结果将进入主会话。