使用sorted()函数时触发NameError: global name '<lambda>' is not defined错误求助
解决Numba CUDA环境下
sorted()的lambda key引发的NameError问题 问题根源
- Numba CUDA不支持lambda作为sorted的key:CUDA设备端的JIT编译无法处理匿名lambda函数,导致无法识别
<lambda>这个全局名称,抛出NameError。 - 变量名错误:
bar函数中while len(images) > 1:里的images未定义,实际应该使用传入的images_list参数。 - CUDA函数的误用:
cv2.imread、cv2.VideoWriter这类主机端IO操作不能放在@jit(target_backend='cuda')装饰的函数里,CUDA设备代码无法调用主机端的OpenCV API。
解决方案
1. 用显式函数替代lambda
定义一个普通函数作为sorted()的key,确保能被Numba CUDA编译识别:
def sort_key(x): return x[0]
2. 分离主机端与CUDA设备端代码
将图像加载、视频写入这类IO操作移到主机端(非JIT装饰的函数),CUDA函数仅负责计算相似度和排序的核心逻辑。
3. 修正变量名错误
把bar函数中的while len(images) > 1:改为while len(images_list) > 1:。
修改后的完整代码
import cv2 import numpy as np from numba import jit, cuda import copy # 主机端函数:加载图像,不使用CUDA JIT def load_images(): images = [] for i in range(1,10):#3941): print(f'i:{i}') filename = "extracted/" + str(i).zfill(4) + '.png' image = cv2.imread(filename) images.append(image) print('loaded images') height, width, layers = images[0].shape return images, width, height # 显式定义排序key函数,供CUDA函数调用 def sort_key(x): return x[0] # CUDA加速的核心排序逻辑函数 @jit(target_backend='cuda') def sort_frames(images_list, where): images_new = [images_list.pop(3)]#3157)] c = 0 while len(images_list) > 1: scores = [] old_image = images_new[-1] for i in range(len(images_list)): scores.append([np.sum((images_list[i][where] - old_image[where])**2), i]) # 使用显式定义的sort_key替代lambda new = sorted(scores, key=sort_key) images_new.append(images_list.pop(new[0][1])) c += 1 print(f'where:{where} sorted images') return images_new # 主机端函数:生成视频 def create_video(images_new, width, height, where): video = cv2.VideoWriter(f'videoat{where}.avi', 0, 10, (width, height)) for image in images_new: video.write(image) print(f'where:{where} made video') cv2.destroyAllWindows() video.release() print(f'where:{where} done') # 主流程 images, width, height = load_images() sorted_images = sort_frames(copy.deepcopy(images), 50) create_video(sorted_images, width, height, 50)
额外说明
- 确保
sort_key函数定义在CUDA函数之前,且没有使用Numba装饰(因为它是一个简单的取值函数,Numba能自动处理)。 - 所有涉及OpenCV的IO操作都放在主机端函数中,避免CUDA设备代码调用主机API导致的错误。
内容的提问来源于stack exchange,提问作者Jerome Palayoor
相关产品推荐
相关产品推荐

