cuDF返回字符串类型的apply函数执行失败问题排查
问题原因
你遇到的AttributeError: 'CPUDispatcher' object has no attribute '__closure__'及后续的ValueError: user defined function compilation failed.,核心问题是误用了CPU版本的Numba装饰器@numba.njit处理cuDF的GPU数据。numba.njit生成的是CPU调度器对象,而cuDF的apply方法需要能在GPU上执行的函数,二者不兼容。
解决方案
提供两种可行修复方式:
方式一:替换为GPU版Numba装饰器
将@numba.njit换成@numba.cuda.jit(device=True),生成能在GPU环境运行的函数:
import numba, cudf print(numba.__version__) # 0.58.1 print(cudf.__version__) # 23.08.00 @numba.cuda.jit(device=True) def f(row): st = row['str_col'] scale = row['scale'] if len(st) == 0: return 'a' + str(scale) + 'x' elif st.startswith('a'): return 'b' elif 'example' in st: return 'c' else: return 'd' df1 = cudf.DataFrame({ 'str_col': ['', 'abc', 'some_example'], 'scale': [1, 2, 3] }) df1['abc'] = df1.apply(f, axis=1) df1.head(100)
方式二:直接移除Numba装饰器
cuDF的apply方法本身可直接运行Python函数(会自动适配GPU执行),若对性能要求不高,去掉装饰器即可:
import numba, cudf print(numba.__version__) # 0.58.1 print(cudf.__version__) # 23.08.00 def f(row): st = row['str_col'] scale = row['scale'] if len(st) == 0: return 'a' + str(scale) + 'x' elif st.startswith('a'): return 'b' elif 'example' in st: return 'c' else: return 'd' df1 = cudf.DataFrame({ 'str_col': ['', 'abc', 'some_example'], 'scale': [1, 2, 3] }) df1['abc'] = df1.apply(f, axis=1) df1.head(100)
额外建议
若追求更高性能,优先用cuDF的向量化操作替代apply(比如cudf.Series.where、cudf.Series.mask等),因为逐行apply的性能远低于向量化处理。
内容的提问来源于stack exchange,提问作者SHM
相关产品推荐
相关产品推荐

