【问题标题】:why is Matlab slow in for loop with large number of iterations but fast with a small number of iterations?为什么Matlab在for循环中迭代次数较多但迭代次数较少时速度较慢?
【发布时间】:2015-04-20 12:41:10
【问题描述】:

我正在运行一个函数来从 100,000 多个患者 x 射线 dicom 文件中提取一些信息。出于安全目的,这些文件存储在一个 veracrypt 加密容器中。

当我在一小部分文件样本上运行该函数时,它的执行速度非常快,但是当我在整个数据集上运行该函数时,它相比之下非常慢,从每秒几个文件到每秒 1 个文件(大约) .

我在徘徊为什么会这样?我尝试将数据存储在 ssd 和普通硬盘驱动器上,并且在使用较大的数据集时会出现同样的速度变慢。

我已经添加了下面的代码以供参考,但还没有完全评论它。这是我的论文,所以一旦我完成提取,我会这样做..

感谢您的帮助。

function [ DB, corrupted_files ] = extract_from_dcm( folder_name )
%EXTRACT_FROM_DCM Summary of this function goes here
%   Detailed explanation goes here

if nargin == 0
    folder_name = 'I:\Find and Treat\MXU Old Backup\2005';
end

Database_Check = strcat(folder_name, '\DataBase.mat');

if exist(Database_Check, 'file')

    load(Database_Check);
    entry_start = length(DB) + 1;

else

    entry_start = 1;
    [ found_dicoms ] = recursive_search( folder_name );

end

mat_file_location = strcat(folder_name, '\DataBase.mat');
excel_DB_file = strcat(folder_name, '\DataBase.xlsx');
excel_Corrupted_file = strcat(folder_name, '\Corrupted_Files.xlsx');

% the recursive search creates a struct with the path for each
% dcm file found. the list is then recursivly used to locate
% the image and extract the relevant information from it.


fprintf('---------------------------------------------\n');
fprintf('Start Patient Data Extraction\n');
tic
h = waitbar(0,'','Name','Patient Data Extraction');
entry_end = length(found_dicoms);

if entry_end == 0
    %     set(handles.info_box, 'String', 'No Dicom Files Found in this Folder or its Subfolders');
else
    %     set(handles.info_box, 'String', 'Congratulations Dicom Files have been found Look Through the Data Base using the Buttons Below....Press Save Button to save the Database. (Database Save format is EXCEL SpreadSheet and MAT file');

    for  kk = entry_start : entry_end
        progress = kk/entry_end;
        progress_percent = round(progress * 100);
        waitbar(progress,h, sprintf('%d%%   %d/%d of images processed', progress_percent, kk, entry_end));

        img_full_path = found_dicoms(kk).name;

        %         search_path = folder_name;
        %         img_full_path = strrep(img_full_path, search_path, '');

        try              %# Attempt to perform some computation
            dicom_info = dicominfo(img_full_path); %# The operation you are trying to perform goes here

            try              %# Attempt to perform some computation
                dicom_read = dicomread(dicom_info); %# The operation you are trying to perform goes here

                old = dicominfo(img_full_path);

                DB(kk).StudyDate = old.StudyDate;
                DB(kk).StudyTime = old.StudyTime;


                if isfield(old.PatientName, 'FamilyName')
                    DB(kk).Forename = old.PatientName.FamilyName;
                else
                    DB(kk).Forename = 'NA';
                end

                if isfield(old.PatientName, 'GivenName')
                    DB(kk).LastName = old.PatientName.GivenName;
                else
                    DB(kk).LastName = 'NA';
                end

                if isfield(old, 'PatientSex')
                    DB(kk).PatientSex = old.PatientSex;
                else
                    DB(kk).PatientSex = 'NA';
                end

                if isempty(old.PatientBirthDate)
                    DB(kk).PatientBirthDate = '00000000';
                else
                    DB(kk).PatientBirthDate = old.PatientBirthDate;
                end

                if strcmp(old.Manufacturer, 'Philips Medical Systems')
                    DB(kk).Van = '1';
                else
                    DB(kk).Van = '0';% section to represent organising by different vans
                end

                DB(kk).img_Path = img_full_path;

                save(mat_file_location,'DB','found_dicoms');

            catch exception  %# Catch the exception
                fprintf('read - file %d corrupt.\n',kk);
                continue       %# Pass control to the next loop iteration
            end



        catch exception  %# Catch the exception
            fprintf('info - file %d corrupt.\n',kk);
            continue       %# Pass control to the next loop iteration
        end


    end

end


[ corrupted_files, DB ] = corruption_check( DB, found_dicoms, folder_name );


toc
fprintf('End Patient Data Extraction\n');
fprintf('---------------------------------------------\n');

fprintf('---------------------------------------------\n');
fprintf('Start Saving Extracted Data \n');
tic


save(mat_file_location,'DB','corrupted_files','found_dicoms');

if isempty(DB)
    msg = sprintf('No Dicom Files Found');
    msgbox(strcat(msg));
else
    DB_table = struct2table(DB);
    writetable(DB_table, excel_DB_file);
end

close(h);

toc
fprintf('End Saving Extracted Data \n');
fprintf('---------------------------------------------\n');

end

【问题讨论】:

  • 只是在没有任何支持证据的情况下将其扔在那里:您真的应该预先分配 DB 数组,它看起来不像您这样做......你知道会有多少元素,特别是entry_end - entry_start + 1。当您执行 DB(kk) 时,Matlab 应该警告您这一点,因为这可能会导致重新分配,因为您不断更改其大小(这很慢)。确实,请运行profiler
  • 更新等待栏可能会花费您大量的执行时间。循环中的图形更新非常昂贵。试着评论一下,看看是否有帮助。更好的是,使用分析器。
  • 很酷,谢谢,我计划进行预分配,我会查看等待栏。问题是代码越大,循环越慢,我不明白为什么会这样..
  • 好吧,看看这些更改是否会删除它(可以相信,重新分配会导致它随着它变大而变慢,也许等待栏也是如此),但如果没有,你应该收集@ 987654322@ 用于每次迭代并显示性能下降,并使用分析器缩小问题范围。
  • 我进行了预分配并使用了分析器,但没有明显的区别.. 处理成千上万的图像时,每个图像的速度仍然比处理数百个图像时慢得多。我没有删除等待栏,因为我真的需要它来跟踪当前正在处理的图像。

标签: performance matlab for-loop data-extraction slowdown


【解决方案1】:

好的,谢谢大家的帮助..

我的问题是每次迭代结束时的保存,但最大的问题是我运行 dicomread 函数的行。我将保存更改为每处理 20 张图像进行一次。

我还删除了 cmets 中建议的预分配,看看它在没有 dicromread 和保存膨胀的情况下有什么不同。它比预分配慢得多。

...我只需要找到 dicomread 的解决方案(我用它来检查文件是否损坏)。

【讨论】:

  • 我愿意,但它说我必须等待 2 天才能接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-30
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多