Single precision vs. Double precision experiment

I don’t see how this works. If you tic-toc the ValueFnIter and StationaryDist commands it is not even close. 90% of runtime for most models is the ValueFnIter, and often sub 1 or 2% is StationaryDist. Some models differ, but in my experience largely just the ones with lots of semi-exo shocks.

StationaryDist_FHorz_Iteration_nProbs_e_raw is taking its time…

Gammatranspose is a sparse double matrix with 1.2227e+12 elements (about 7.4M live entries). It takes time…

I note that sparse single has only been supported in MATLAB since 2025a. So this whole single vs. double thing is timely…

Whelp…the Gammatranspose is dominating HV2000 Model 4:

You can see here that main memory and GPU memory are both down from the above, and we get 7 iterations per 4 minutes instead of 6. I’m not surprised, given that the Gamma transpose operation was taking the time it did.

I’ll see if other models speed up…

Chen2010 sped up by 10%:

single:

Current GE prices: 
	r:   0.0335 
	Tr:   0.0802 
Current aggregate variables: 
	A:   6.0279 
	N:   2.0514 
	H:   4.1922 
	Hr:   0.2086 
	pensiontaxrevenue:   0.1959 
	pensionspend:   0.1959 
	accidentalbeqleft:   0.0811 
Current GeneralEqmEqns: 
	capitalmarkets: 0.000102 
	accidentalbequests: -0.000102 
 
Current GE prices: 
	r:   0.0335 
	Tr:   0.0802 
Current aggregate variables: 
	A:   6.0279 
	N:   2.0514 
	H:   4.1922 
	Hr:   0.2086 
	pensiontaxrevenue:   0.1959 
	pensionspend:   0.1959 
	accidentalbeqleft:   0.0811 
Current GeneralEqmEqns: 
	capitalmarkets: 0.000102 
	accidentalbequests: -0.000102 
Quantitative properties of the benchmark economy 
Targeted Variables 
Payroll tax rate is 0.107 
r is 3.35% 
K/Y is 2.134 
H/Y is 1.534 
Homeownership rate is 91.0% 
Nontargeted Variables 
Ho/(A+Ho) is 41.0% 
Gini for total wealth is 0.54 
Gini for financial wealth is NaN 
Gini for housing is 0.32 
Mean loan-to-value ratio (for borrowers) is 12.1 

ans =

    0.3314


ans =

  gpuArray single

    0.4562


ans =

    0.4830


ans =

    0.4306

Elapsed time is 622.457359 seconds.

double:

Current GE prices: 
	r:   0.0335 
	Tr:   0.0804 
Current aggregate variables: 
	A:   6.0287 
	N:   2.0514 
	H:   4.1923 
	Hr:   0.2086 
	pensiontaxrevenue:   0.1959 
	pensionspend:   0.1959 
	accidentalbeqleft:   0.0812 
Current GeneralEqmEqns: 
	capitalmarkets: 0.000121 
	accidentalbequests: 0.000098 
Quantitative properties of the benchmark economy 
Targeted Variables 
Payroll tax rate is 0.107 
r is 3.35% 
K/Y is 2.135 
H/Y is 1.534 
Homeownership rate is 91.0% 
Nontargeted Variables 
Ho/(A+Ho) is 41.0% 
Gini for total wealth is 0.54 
Gini for financial wealth is NaN 
Gini for housing is 0.32 
Mean loan-to-value ratio (for borrowers) is 12.1 

ans =

    0.3314


ans =

    0.4562


ans =

    0.4830


ans =

    0.4306

Elapsed time is 673.037687 seconds.

As for accuracy: only a few numbers differ in the 5th decimal digit.

1 Like

I found this logic in LifeCycleModel35semiz:

    % Either goes up one grid point, down one grid point, or stays
    if abs((pbeforeprime-pbefore)-pbeforespacing)<1e-4 % if (pbeforeprime-pbefore)==pbeforespacing
        probp1=probhousepricerise;
    elseif pbeforeprime==pbefore
        probp1=1-probhousepricerise-probhousepricefall;
    elseif abs((pbefore-pbeforeprime)-pbeforespacing)<1e-4 % if (pbeforeprime-pbefore)==-pbeforespacing
        probp1=probhousepricefall;
    else
        probp1=0;
    end

I discovered that this logic was not quite complete:

    % so we are between grid points
    elseif abs(pbeforeprime-pnew)==0 % in case we hit grid point exactly
        probp1=1;
    elseif abs(pbeforeprime-pnew)<pbeforespacing % If this is one of the nearest grid points
        probp1=abs(pbeforeprime-pnew)/pbeforespacing; % linear interpolation for the probability weight
    else
        probp1=0;
    end

Specifically, abs(pbeforeprime-pnew)<pbeforespacing needed to be abs(pbeforeprime-pnew)+1e-4<pbeforespacing) to ensure we really were to the left of the point, not essentially on top of it. Don’t ask me how I found it :wink:

I also 100% acknowledge that the best approximation to discretization and moments is to let them run in full precision and then cast them to single if/when appropriate. Messing with their quality upstream leads to inconsistent downstream results.