This is a static copy of a profile report

Home

Function details for ff_az_vf_vecThis is a static copy of a profile report

Home

ff_az_vf_vec (Calls: 1, Time: 34.651 s)
Generated 18-Jun-2019 09:18:58 using performance time.
function in file C:\Users\fan\CodeDynaAsset\m_az\solve\ff_az_vf_vec.m
Copy to new window for comparing multiple runs

Parents (calling functions)
No parent
Lines where the most time was spent

Line NumberCodeCallsTotal Time% TimeTime Plot
233
mt_utility = f_util_crra(mt_c)...
159021.762 s62.8%
246
mt_utility(mt_c <= 0) = fl_...
15908.671 s25.0%
227
mt_c = f_cons(fl_z, ar_a, ar_a...
15903.056 s8.8%
252
[ar_opti_val1_z, ar_opti_idx_z...
15900.584 s1.7%
245
mt_utility = mt_utility + fl_b...
15900.344 s1.0%
All other lines  0.234 s0.7%
Totals  34.651 s100% 
Children (called functions)

Function NameFunction TypeCallsTotal Time% TimeTime Plot
...c)(((c).^(1-fl_crra)-1)./(1-fl_crra))anonymous function159019.820 s57.2%
...s>@(z,b,bprime)(f_coh(z,b)-bprime)anonymous function15901.726 s5.0%
Self time (built-ins, overhead, etc.)  13.104 s37.8%
Totals  34.651 s100% 
Code Analyzer results
Line numberMessage
320Terminate statement with semicolon to suppress output (in functions).
Coverage results
Show coverage for parent directory
Total lines in function326
Non-code lines (comments, blank lines)205
Code lines (lines that can run)121
Code lines that did run44
Code lines that did not run77
Coverage (did run/can run)36.36 %
Function listing
time 
Calls 
 line
   7 
function result_map = ff_az_vf_vec(varargin)
   8 
%% FF_AZ_VF_VEC solve infinite horizon exo shock + endo asset problem
   9 
% This program solves the infinite horizon dynamic single asset and single
  10 
% shock problem with vectorized codes.
  11 
% <https://fanwangecon.github.io/CodeDynaAsset/m_az/solve/html/ff_az_vf.html
  12 
% ff_az_vf> shows looped codes. The solution is the same.
  13 
%
  14 
% The vectorization takes advantage of implicit parallization that modern
  15 
% computers have when <https://en.wikipedia.org/wiki/SIMD same instructions
  16 
% are given for different blocks of data> With vectorization, we face a
  17 
% tradeoff between memory and speed. Suppose we have many shock points and
  18 
% many states points, if we build all states and choices into one single
  19 
% matrix and compute consumption, utility, etc over that entire matrix, that
  20 
% might be more efficient than computing consumption, utility, etc by
  21 
% subset of that matrix over a loop, but there is time required for
  22 
% generating that large input matrix, and if there are too many states, a
  23 
% computer could run out of memory.
  24 
%
  25 
% The design philosophy here is that we vectorize the endogenous states and
  26 
% choices into matrixes, but do not include the exogeous states (shocks).
  27 
% The exogenous shocks remain looped. This means we can potentially have
  28 
% multiple shock variables discretized over a large number of shock states,
  29 
% and the computer would not run into memory problems. The speed gain from
  30 
% vectoring the rest of the problem conditional on shocks is very large
  31 
% compared to the pure looped version of the problem. Even if more memory
  32 
% is available, including the exogenous states in the vectorization process
  33 
% might not be speed improving.
  34 
%
  35 
% Note one key issue is whether a programming language is
  36 
% <https://en.wikipedia.org/wiki/Row-_and_column-major_order row or column
  37 
% major> depending on which, states should be rows or columns.
  38 
%
  39 
% Another programming issue is the idea of *broadcasting* vs matrix
  40 
% algebra, both are used here. Since Matlab R2016b,
  41 
% <https://blogs.mathworks.com/loren/2016/10/24/matlab-arithmetic-expands-in-r2016b/
  42 
% matrix broadcasting> has been allowed, which means the sum of a N by 1
  43 
% and 1 by M is N by M. This is unrelated to matrix algebra. Matrix array
  44 
% broadcasting is very useful because it reduces the dimensionality of our
  45 
% model input state and choice and shock vectors, offering greater code
  46 
% clarity.
  47 
%
  48 
% @param param_map container parameter container
  49 
%
  50 
% @param support_map container support container
  51 
%
  52 
% @param armt_map container container with states, choices and shocks
  53 
% grids that are inputs for grid based solution algorithm
  54 
%
  55 
% @param func_map container container with function handles for
  56 
% consumption cash-on-hand etc.
  57 
%
  58 
% @return result_map container contains policy function matrix, value
  59 
% function matrix, iteration results, and policy function, value function
  60 
% and iteration results tables.
  61 
%
  62 
% keys included in result_map:
  63 
%
  64 
% * mt_val matrix states_n by shock_n matrix of converged value function grid
  65 
% * mt_pol_a matrix states_n by shock_n matrix of converged policy function grid
  66 
% * ar_val_diff_norm array if bl_post = true it_iter_last by 1 val function
  67 
% difference between iteration
  68 
% * ar_pol_diff_norm array if bl_post = true it_iter_last by 1 policy
  69 
% function difference between iterations
  70 
% * mt_pol_perc_change matrix if bl_post = true it_iter_last by shock_n the
  71 
% proportion of grid points at which policy function changed between
  72 
% current and last iteration for each element of shock
  73 
%
  74 
% @example
  75 
%
  76 
%    % Get Default Parameters
  77 
%    it_param_set = 2;
  78 
%    [param_map, support_map] = ffs_abz_set_default_param(it_param_set);
  79 
%    % Change Keys in param_map
  80 
%    param_map('it_a_n') = 500;
  81 
%    param_map('it_z_n') = 11;
  82 
%    param_map('fl_a_max') = 100;
  83 
%    param_map('fl_w') = 1.3;
  84 
%    % Change Keys support_map
  85 
%    support_map('bl_display') = false;
  86 
%    support_map('bl_post') = true;
  87 
%    support_map('bl_display_final') = false;
  88 
%    % Call Program with external parameters that override defaults.
  89 
%    ff_az_vf_vec(param_map, support_map);
  90 
%
  91 
% @include
  92 
%
  93 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_az/paramfunc/html/ffs_az_set_default_param.html ffs_az_set_default_param>
  94 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_az/paramfunc/html/ffs_az_get_funcgrid.html ffs_az_get_funcgrid>
  95 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_az/solvepost/html/ff_az_vf_post.html ff_az_vf_post>
  96 
%
  97 
% @seealso
  98 
%
  99 
% * save loop: <https://fanwangecon.github.io/CodeDynaAsset/m_az/solve/html/ff_az_vf.html ff_az_vf>
 100 
% * save vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_az/solve/html/ff_az_vf_vec.html ff_az_vf_vec>
 101 
% * save optimized-vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_az/solve/html/ff_az_vf_vecsv.html ff_az_vf_vecsv>
 102 
% * save + borr loop: <https://fanwangecon.github.io/CodeDynaAsset/m_abz/solve/html/ff_abz_vf.html ff_abz_vf>
 103 
% * save + borr vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_abz/solve/html/ff_abz_vf_vec.html ff_abz_vf_vec>
 104 
% * save + borr optimized-vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_abz/solve/html/ff_abz_vf_vecsv.html ff_abz_vf_vecsv>
 105 
%
 106 

 107 

 108 
%% Default
 109 
% * it_param_set = 1: quick test
 110 
% * it_param_set = 2: benchmark run
 111 
% * it_param_set = 3: benchmark profile
 112 
% * it_param_set = 4: press publish button
 113 

 114 
it_param_set = 3;
 115 
bl_input_override = true;
 116 
[param_map, support_map] = ffs_az_set_default_param(it_param_set);
 117 

 118 
% Note: param_map and support_map can be adjusted here or outside to override defaults
 119 
% param_map('it_a_n') = 750;
 120 
% param_map('it_z_n') = 15;
 121 

 122 
[armt_map, func_map] = ffs_az_get_funcgrid(param_map, support_map, bl_input_override); % 1 for override
 123 
default_params = {param_map support_map armt_map func_map};
 124 

 125 
%% Parse Parameters 1
 126 

 127 
% if varargin only has param_map and support_map,
 128 
params_len = length(varargin);
 129 
[default_params{1:params_len}] = varargin{:};
 130 
param_map = [param_map; default_params{1}];
 131 
support_map = [support_map; default_params{2}];
 132 
if params_len >= 1 && params_len <= 2
 133 
    % If override param_map, re-generate armt and func if they are not
 134 
    % provided
 135 
    bl_input_override = true;
 136 
    [armt_map, func_map] = ffs_az_get_funcgrid(param_map, support_map, bl_input_override);
 137 
else
 138 
    % Override all
 139 
    armt_map = [armt_map; default_params{3}];
 140 
    func_map = [func_map; default_params{4}];
 141 
end
 142 

 143 
% append function name
 144 
st_func_name = 'ff_az_vf_vec';
 145 
support_map('st_profile_name_main') = [st_func_name support_map('st_profile_name_main')];
 146 
support_map('st_mat_name_main') = [st_func_name support_map('st_mat_name_main')];
 147 
support_map('st_img_name_main') = [st_func_name support_map('st_img_name_main')];
 148 

 149 
%% Parse Parameters 2
 150 

 151 
% armt_map
 152 
params_group = values(armt_map, {'ar_a', 'mt_z_trans', 'ar_z'});
 153 
[ar_a, mt_z_trans, ar_z] = params_group{:};
 154 
% func_map
 155 
params_group = values(func_map, {'f_util_log', 'f_util_crra', 'f_cons', 'f_coh'});
 156 
[f_util_log, f_util_crra, f_cons, f_coh] = params_group{:};
 157 
% param_map
 158 
params_group = values(param_map, {'it_a_n', 'it_z_n', 'fl_crra', 'fl_beta', 'fl_nan_replace'});
 159 
[it_a_n, it_z_n, fl_crra, fl_beta, fl_nan_replace] = params_group{:};
 160 
params_group = values(param_map, {'it_maxiter_val', 'fl_tol_val', 'fl_tol_pol', 'it_tol_pol_nochange'});
 161 
[it_maxiter_val, fl_tol_val, fl_tol_pol, it_tol_pol_nochange] = params_group{:};
 162 

 163 
% support_map
 164 
params_group = values(support_map, {'bl_profile', 'st_profile_path', ...
 165 
    'st_profile_prefix', 'st_profile_name_main', 'st_profile_suffix',...
 166 
    'bl_time', 'bl_display', 'it_display_every', 'bl_post'});
 167 
[bl_profile, st_profile_path, ...
 168 
    st_profile_prefix, st_profile_name_main, st_profile_suffix, ...
 169 
    bl_time, bl_display, it_display_every, bl_post] = params_group{:};
 170 

 171 
%% Initialize Output Matrixes
 172 
% include mt_pol_idx which we did not have in looped code
 173 

 174 
mt_val_cur = zeros(length(ar_a),length(ar_z));
 175 
mt_val = mt_val_cur - 1;
 176 
mt_pol_a = zeros(length(ar_a),length(ar_z));
 177 
mt_pol_a_cur = mt_pol_a - 1;
 178 
mt_pol_idx = zeros(length(ar_a),length(ar_z));
 179 

 180 
%% Initialize Convergence Conditions
 181 

 182 
bl_vfi_continue = true;
 183 
it_iter = 0;
 184 
ar_val_diff_norm = zeros([it_maxiter_val, 1]);
 185 
ar_pol_diff_norm = zeros([it_maxiter_val, 1]);
 186 
mt_pol_perc_change = zeros([it_maxiter_val, it_z_n]);
 187 

 188 
%% Iterate Value Function
 189 
% Loop solution with 4 nested loops
 190 
%
 191 
% # loop 1: over exogenous states
 192 
% # loop 2: over endogenous states
 193 
% # loop 3: over choices
 194 
% # loop 4: add future utility, integration--loop over future shocks
 195 
%
 196 

 197 
% Start Profile
 198 
if (bl_profile)
 199 
    close all;
 200 
    profile off;
 201 
    profile on;
< 0.001 
      1 
 202
end 
 203 

 204 
% Start Timer
< 0.001 
      1 
 205
if (bl_time) 
< 0.001 
      1 
 206
    tic; 
< 0.001 
      1 
 207
end 
 208 

 209 
% Value Function Iteration
< 0.001 
      1 
 210
while bl_vfi_continue 
< 0.001 
    106 
 211
    it_iter = it_iter + 1; 
 212 

 213 
    %% Solve Optimization Problem Current Iteration
 214 
    % Only this segment of code differs between ff_az_vf and ff_az_vf_vec
 215 

 216 
    % loop 1: over exogenous states
 217 
    % incorporating these shocks into vectorization has high memory burden
 218 
    % but insignificant speed gains. Keeping this loop allows for large
 219 
    % number of shocks without overwhelming memory
< 0.001 
    106 
 220
    for it_z_i = 1:length(ar_z) 
 221 

 222 
        % Current Shock
< 0.001 
   1590 
 223
        fl_z = ar_z(it_z_i); 
 224 

 225 
        % Consumption: fl_z = 1 by 1, ar_a = 1 by N, ar_a' = N by 1
 226 
        % mt_c is N by N: matrix broadcasting, expand to matrix from arrays
  3.056 
   1590 
 227
        mt_c = f_cons(fl_z, ar_a, ar_a'); 
 228 

 229 
        % EVAL current utility: N by N, f_util defined earlier
  0.001 
   1590 
 230
        if (fl_crra == 1) 
 231 
            mt_utility = f_util_log(mt_c);
< 0.001 
   1590 
 232
        else 
 21.762 
   1590 
 233
            mt_utility = f_util_crra(mt_c); 
< 0.001 
   1590 
 234
        end 
 235 

 236 
        % f(z'|z), 1 by Z
  0.005 
   1590 
 237
        ar_z_trans_condi = mt_z_trans(it_z_i,:); 
 238 

 239 
        % EVAL EV((A',K'),Z'|Z) = V((A',K'),Z') x p(z'|z)', (N by Z) x (Z by 1) = N by 1
 240 
        % Note: transpose ar_z_trans_condi from 1 by Z to Z by 1
 241 
        % Note: matrix multiply not dot multiply
  0.030 
   1590 
 242
        mt_evzp_condi_z = mt_val_cur * ar_z_trans_condi'; 
 243 

 244 
        % EVAL add on future utility, N by N + N by 1, broadcast again
  0.344 
   1590 
 245
        mt_utility = mt_utility + fl_beta*mt_evzp_condi_z; 
  8.671 
   1590 
 246
        mt_utility(mt_c <= 0) = fl_nan_replace; 
 247 

 248 
        % Optimization: remember matlab is column major, rows must be
 249 
        % choices, columns must be states
 250 
        % <https://en.wikipedia.org/wiki/Row-_and_column-major_order COLUMN-MAJOR>
 251 
        % mt_utility is N by N, rows are choices, cols are states.
  0.584 
   1590 
 252
        [ar_opti_val1_z, ar_opti_idx_z] = max(mt_utility); 
  0.029 
   1590 
 253
        mt_val(:,it_z_i) = ar_opti_val1_z; 
  0.028 
   1590 
 254
        mt_pol_a(:,it_z_i) = ar_a(ar_opti_idx_z); 
  0.001 
   1590 
 255
        if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
     15 
 256
            mt_pol_idx(:,it_z_i) = ar_opti_idx_z; 
< 0.001 
     15 
 257
        end 
  0.002 
   1590 
 258
    end 
 259 

 260 
    %% Check Tolerance and Continuation
 261 

 262 
    % Difference across iterations
  0.065 
    106 
 263
    ar_val_diff_norm(it_iter) = norm(mt_val - mt_val_cur); 
  0.051 
    106 
 264
    ar_pol_diff_norm(it_iter) = norm(mt_pol_a - mt_pol_a_cur); 
  0.007 
    106 
 265
    mt_pol_perc_change(it_iter, :) = sum((mt_pol_a ~= mt_pol_a_cur))/(it_a_n); 
 266 

 267 
    % Update
  0.004 
    106 
 268
    mt_val_cur = mt_val; 
  0.003 
    106 
 269
    mt_pol_a_cur = mt_pol_a; 
 270 

 271 
    % Print Iteration Results
< 0.001 
    106 
 272
    if (bl_display && (rem(it_iter, it_display_every)==0)) 
 273 
        fprintf('VAL it_iter:%d, fl_diff:%d, fl_diff_pol:%d\n', ...
 274 
            it_iter, ar_val_diff_norm(it_iter), ar_pol_diff_norm(it_iter));
 275 
        tb_valpol_iter = array2table([mean(mt_val_cur,1); mean(mt_pol_a_cur,1); ...
 276 
            mt_val_cur(it_a_n,:); mt_pol_a_cur(it_a_n,:)]);
 277 
        tb_valpol_iter.Properties.VariableNames = strcat('z', string((1:size(mt_val_cur,2))));
 278 
        tb_valpol_iter.Properties.RowNames = {'mval', 'map', 'Hval', 'Hap'};
 279 
        disp('mval = mean(mt_val_cur,1), average value over a')
 280 
        disp('map  = mean(mt_pol_a_cur,1), average choice over a')
 281 
        disp('Hval = mt_val_cur(it_a_n,:), highest a state val')
 282 
        disp('Hap = mt_pol_a_cur(it_a_n,:), highest a state choice')
 283 
        disp(tb_valpol_iter);
 284 
    end
 285 

 286 
    % Continuation Conditions:
 287 
    % 1. if value function convergence criteria reached
 288 
    % 2. if policy function variation over iterations is less than
 289 
    % threshold
< 0.001 
    106 
 290
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 291
        bl_vfi_continue = false; 
  0.002 
    105 
 292
    elseif ((it_iter == it_maxiter_val) || ... 
    105 
 293
            (ar_val_diff_norm(it_iter) < fl_tol_val) || ... 
    105 
 294
            (sum(ar_pol_diff_norm(max(1, it_iter-it_tol_pol_nochange):it_iter)) < fl_tol_pol)) 
 295 
        % Fix to max, run again to save results if needed
< 0.001 
      1 
 296
        it_iter_last = it_iter; 
< 0.001 
      1 
 297
        it_iter = it_maxiter_val; 
< 0.001 
      1 
 298
    end 
 299 

< 0.001 
    106 
 300
end 
 301 

 302 
% End Timer
< 0.001 
      1 
 303
if (bl_time) 
< 0.001 
      1 
 304
    toc; 
< 0.001 
      1 
 305
end 
 306 

 307 
% End Profile
< 0.001 
      1 
 308
if (bl_profile) 
  0.001 
      1 
 309
    profile off 
 310 
    profile viewer
 311 
    st_file_name = [st_profile_prefix st_profile_name_main st_profile_suffix];
 312 
    profsave(profile('info'), strcat(st_profile_path, st_file_name));
 313 
end
 314 

 315 
%% Process Optimal Choices
 316 

 317 
result_map = containers.Map('KeyType','char', 'ValueType','any');
 318 
result_map('mt_val') = mt_val;
 319 
result_map('mt_pol_a') = mt_pol_a;
 320 
result_map('mt_pol_c') = f_coh(ar_z, ar_a') - mt_pol_a
 321 
result_map('ar_st_pol_names') = ['mt_pol_a', 'mt_pol_c'];
 322 
result_map('mt_pol_idx') = mt_pol_idx;
 323 

 324 
if (bl_post)
 325 
    bl_input_override = true;
 326 
    result_map('ar_val_diff_norm') = ar_val_diff_norm(1:it_iter_last);
 327 
    result_map('ar_pol_diff_norm') = ar_pol_diff_norm(1:it_iter_last);
 328 
    result_map('mt_pol_perc_change') = mt_pol_perc_change(1:it_iter_last, :);
 329 
    result_map = ff_az_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 330 
end
 331 

 332 
end

Other subfunctions in this file are not included in this listing.