MATLAB中persistent变量相当于C中局部静态变量,只能在所定义的函数内部访问到,并且一旦定义一直存在。
一般的解决方案
clear var 变量名
新的问题
如下图所示,本来想着将算法每次迭代的结果先暂时存放在一个persistent变量中,最后一次运行时将数据写入到文件中。后来调试发现,即使是利用clear var命令,该变量再次被初始化的时候仍然会被初始化为上次写入的结果。
function [ ] = RecordResult( Global )
%检查静态变量是否存在,若存在且是第一次运行,则清除
if Global.evaluated <= Global.N
clear var global_result;%第一次运行时,清除上次该函数运行留下的persistent变量
end
persistent global_result;
%% 判断目录是否存在
method = func2str(Global.algorithm);
question = func2str(Global.problem);
dir_1 = sprintf('Data/%s/',question); %问题对应的第一级目录
dir_2 = sprintf('%s%d/',dir_1,Global.run); %问题对应的第二级目录,单次运行结果存放在一个文件夹里面,文件夹的名称为运行序号
%判断路径是否存在
if ~exist(dir_1,'dir')
mkdir(dir_1);
end
if ~exist(dir_2,'dir')
mkdir(dir_2);
end
%% 输出运行过程中的信息
clc;%清空命令行
fprintf('run %d\n',Global.run);
fprintf('%s with %s on %s\n',method,func2str(Global.operator),question);
fprintf('N: %d evaluation: %d\n',Global.N,Global.evaluation);
fprintf('status: (%6.2f%%), %.2fs passed...\n',Global.evaluated/Global.evaluation*100,Global.runtime);
[r,~] = size(Global.result);
result = {Global.result{r,:}}; %每个算法最后一次运行结果
global_result = [global_result;result];
%% 运行完毕后,保存实验结果到本地
if Global.evaluated >= Global.evaluation
filename = sprintf('%s%s.mat',dir_1,question); %存放汇总的运行结果(近似PF)
filename2 = sprintf('%s%s.mat',dir_2,method); %存放每个算法的所有运行结果
if exist(filename2,'file')
delete(filename2);
end
save(filename2,'global_result');
global_result = []; %清除函数内部静态变量
if exist(filename,'file')
PF = load(filename);
PF = CombineArchive(result{1,2},PF.PF,500); %设置储备集中元素的个数
else
PF = CombineArchive(result{1,2},[],500); %个体组成的PF
end
fprintf('\nnumber of Non-dominant Solutions :%d\n',size(PF.objs,1));
save(filename,'PF'); %保存结果
end
end
原因分析:本来在RecordResult函数中有一个if判断,用来判断算法是否是最后一次迭代,若是,就会将该函数内部的persistent变量global_result设置为空。然而,由于自己中途中断了整个算法的运行,导致RecordResult函数中的persistent变量global_result没有被置为空。当再次运行整个程序时,第一次进入RecordResult函数时,虽然还是会执行如下面代码来清除上次实验保留的persistent变量。
if Global.evaluated <= Global.N
clear var global_result;%仍然会恢复上次的global_result的值
end
然而,当执行完persistent global_result后,系统仍然会恢复上次中断程序执行时保留的persistent变量global_result的值,即原内存空间部分的值,该内存区域的值好像只能在关闭matlab才能彻底释放内存。
新的解决方案
为了使得程序不会受到上次没有运行完的结果的影响,在该函数的开头,判断该程序是否为第一次执行,若是,则直接清空该persistent变量中的值。
function [ ] = RecordResult( Global )
persistent global_result;
% 声明静态变量
if Global.evaluated <= Global.N
global_result = [];%第一次运行时,清除上次该函数运行留下的persistent变量
end
%% 判断目录是否存在
method = func2str(Global.algorithm);
question = func2str(Global.problem);
dir_1 = sprintf('Data/%s/',question); %问题对应的第一级目录
dir_2 = sprintf('%s%d/',dir_1,Global.run); %问题对应的第二级目录,单次运行结果存放在一个文件夹里面,文件夹的名称为运行序号
%判断路径是否存在
if ~exist(dir_1,'dir')
mkdir(dir_1);
end
if ~exist(dir_2,'dir')
mkdir(dir_2);
end
%% 输出运行过程中的信息
clc;%清空命令行
fprintf('run %d\n',Global.run);
fprintf('%s with %s on %s\n',method,func2str(Global.operator),question);
fprintf('N: %d evaluation: %d\n',Global.N,Global.evaluation);
fprintf('status: (%6.2f%%), %.2fs passed...\n',Global.evaluated/Global.evaluation*100,Global.runtime);
[r,~] = size(Global.result);
result = {Global.result{r,:}}; %每个算法最后一次运行结果
global_result = [global_result;result];
%% 运行完毕后,保存实验结果到本地
if Global.evaluated >= Global.evaluation
filename = sprintf('%s%s.mat',dir_1,question); %存放汇总的运行结果(近似PF)
filename2 = sprintf('%s%s.mat',dir_2,method); %存放每个算法的所有运行结果
if exist(filename2,'file')
delete(filename2);
end
save(filename2,'global_result');
if exist(filename,'file')
PF = load(filename);
PF = CombineArchive(result{1,2},PF.PF,500); %设置储备集中元素的个数
else
PF = CombineArchive(result{1,2},[],500); %个体组成的PF
end
fprintf('\nnumber of Non-dominant Solutions :%d\n',size(PF.objs,1));
save(filename,'PF'); %保存结果
end
end
因此,每次实验开始前切记使用global_result=[];将persistent变量设置为空。
if Global.evaluated <= Global.N
global_result = [];%第一次运行时,清除上次该函数运行留下的persistent变量
end
这样一来,只需要在开始的时候检测该函数是否为第一次执行,若是,则将该persistent变量设置为空,也就不需要每次结束之后都将该persistent变量设置为空了。
即便是中途中断程序的运行,当函数重新运行时,第一次执行仍然会将结果设置为空,问题就解决了。代码来自改进的PlatEMO
|
请发表评论