MATLAB代码并行化求助:深度学习图像数据库代码适配parfor
解决MATLAB parfor循环构建深度学习图像数据库的报错问题
问题背景
你在高性能计算服务器上用MATLAB并行构建深度学习图像数据库时,尝试替换普通for为parfor后,因imdb结构体和image_counter累加变量出现报错。原代码如下:
for i = 1:length(cur_images) X = sprintf('image Numb: %d ',i); disp(X) cur_image = load(cur_images{i,:}); cur_image=(cur_image.Image.crop); %---------------------------------------------- cur_image = imresize(cur_image, image_size); if(rgb < 1) imdb.images.data(:,:,1,image_counter) = cur_image; else imdb.images.data(:,:,1,image_counter) = cur_image(:,:,1); imdb.images.data(:,:,2,image_counter) = cur_image(:,:,2); imdb.images.data(:,:,3,image_counter) = cur_image(:,:,3); imdb.images.data(:,:,4,image_counter) = cur_image(:,:,4); imdb.images.data(:,:,5,image_counter) = cur_image(:,:,5); imdb.images.data(:,:,6,image_counter) = cur_image(:,:,6); imdb.images.data(:,:,7,image_counter) = cur_image(:,:,7); imdb.images.data(:,:,8,image_counter) = cur_image(:,:,8); imdb.images.data(:,:,9,image_counter) = cur_image(:,:,9); imdb.images.data(:,:,10,image_counter) = cur_image(:,:,10); end imdb.images.set( 1,image_counter) = set; image_counter = image_counter + 1; end
报错原因分析
image_counter的竞态条件:普通for里的累加变量在parfor中会被多个工作线程同时修改,MATLAB无法保证操作的原子性,直接禁止这种非独立的变量操作。imdb结构体的非切片访问:parfor要求对数组/结构体的访问必须是切片式(即每个迭代i对应唯一的索引位置,互不干扰),而原代码里用image_counter动态索引,属于非独立访问,不符合parfor的规则。
修改后的适配parfor的代码
% 第一步:预先分配好所有输出内存,避免动态扩容(并行场景下更高效) num_images = length(cur_images); % 提前获取单张图的尺寸,用于预分配 sample_img = load(cur_images{1}).Image.crop; sample_img = imresize(sample_img, image_size); [h, w, ch] = size(sample_img); % 预分配数据数组,指定数据类型避免类型转换开销 imdb.images.data = zeros(h, w, ch, num_images, class(sample_img)); % 预分配set标签:如果所有图属于同一set,直接赋值;如果每张图set不同,可改成数组存储后再赋值 imdb.images.set = ones(1, num_images) * set; % 第二步:用parfor循环,直接用迭代变量i作为索引,不需要手动维护counter parfor i = 1:num_images fprintf('image Numb: %d \n', i); % 用fprintf比disp更适合并行输出(减少乱序) cur_image = load(cur_images{i}); cur_image = cur_image.Image.crop; cur_image = imresize(cur_image, image_size); % 直接用i作为第四维索引,每个线程处理自己的独立切片 if rgb < 1 imdb.images.data(:,:,1,i) = cur_image; else % 用矩阵索引简化重复代码,避免写10行冗余赋值 imdb.images.data(:,:,1:size(cur_image,3),i) = cur_image; end % 如果每张图的set标签不同,取消下面注释并替换为你的逻辑 % imdb.images.set(1,i) = your_set_list(i); end
关键修改点说明
- 预分配内存:提前计算并分配
imdb.images.data和imdb.images.set的完整空间,既提升并行效率,也符合parfor对变量的访问要求。 - 移除
image_counter:直接用parfor的迭代变量i作为图像的索引,每个线程独立处理第i张图,完全避免竞态条件。 - 切片式访问:每个迭代只修改
imdb.images.data(:,:,:,i)和imdb.images.set(1,i),属于parfor允许的独立切片访问,MATLAB能安全地并行执行。 - 简化通道赋值:把原代码里10行重复的通道赋值改成矩阵索引,让代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Aadnan Farooq A
相关产品推荐
相关产品推荐

