【Matlab】彻底清除persistent变量

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值