Clear Filters
Clear Filters

Obscure error in mvncdf()

1 view (last 30 days)
Robert Kirkby
Robert Kirkby on 5 Dec 2023
Commented: Paul on 13 Dec 2023
This error is kind of reproducible but kind of not reproducible. The following is a copy paste that of the output from matlab. Essentially, for a given value of the first two inputs to mvncdf() it throws an error
mvncdf(z_gridvals(1976,:)-z_gridspacing_down(1976,:),z_gridvals(1976,:)+z_gridspacing_up(1976,:),Mew,Sigma)
Error using gpuArray/log
LOG: needs to return a complex result, but this is not supported for real input X on the GPU. Use LOG(COMPLEX(X))
instead.
Error in internal.stats.bvncdf (line 70)
log(t1.*exp(-bsq./(2*asq)) - t2.*sqrt(2*pi).*Phi(-b./a)));
Error in mvncdf (line 249)
y = y + (-1)^i * internal.stats.bvncdf(X, rho, tol/4);
That is the error, but something as minor as the next lines of code being
aaa1=z_gridvals(1976,:)-z_gridspacing_down(1976,:);
aaa2=z_gridvals(1976,:)-z_gridspacing_up(1976,:);
mvncdf(aaa1,aaa2,Mew,Sigma)
ans =
0
and suddenly the error is gone.
This is really weird, because in principle the inputs are the same in both cases.
The values of the four inputs to mvncdf() are as follows (but just putting them in this way does not cause error)
aaa1=[4.546541072119, -19.52465262]
aaa2=[4.548657475153, -17.361228432903]
Mew = [3.6604, -5.0249]
Sigma =[3.1531, -4.7301; -4.7301, 7.1776]
As an attachment there is a mat file containing z_gridvals, etc.
If I just run
clear all
load mvnerror.mat
mvncdf(z_gridvals(1976,:)-z_gridspacing_down(1976,:),z_gridvals(1976,:)+z_gridspacing_up(1976,:),Mew,Sigma)
it is enough to generate the error message described at the beginning of this post.
Side note: these are mostly gpuArrays, not sure if that is in any way relevant (so are aaa1 and aaa2 when created as above, so seems unimportant).
[Matlab Release is R2023a]

Accepted Answer

Paul
Paul on 6 Dec 2023
Walking through the debugger for this code:
%{
aaa1=[4.546541072119, -19.52465262];
aaa2=[4.548657475153, -17.361228432903];
Mew = [3.6604, -5.0249];
Sigma =[3.1531, -4.7301; -4.7301, 7.1776];
mvncdf(aaa1,aaa2,Mew,Sigma)
The line 70 in internal.stats.bvncdf is actually a continuation line. The full line is
p2 = exp(-shk/2 + ...
log(t1.*exp(-bsq./(2*asq)) - t2.*sqrt(2*pi).*Phi(-b./a)));
%}
The argument to the log function is small but negative, presumably rounding error (copied from my command window):
arglog = -2.964393875047479e-323;
The log of a negative has an imaginary component equal to pi
log(arglog)
ans = -7.4265e+02 + 3.1416e+00i
and the argument to the exp() is (again, copied from my command window)
argexp = -7.438000043200474e+02 + 3.141592653589793e+00i
argexp = -7.4380e+02 + 3.1416e+00i
Normally, I would expect the exp(argexp) to have a small imaginary component, because mathematically, exp(argexp) can be expressed as exp(real(argexp))*exp(1i*imag(argexp))
format long e
exp(real(argexp)), exp(1i*imag(argexp))
ans =
9.881312916824931e-324
ans =
-1.000000000000000e+00 + 1.224646799147353e-16i
But, presumably the product of 1e-324 and 1e-16 rounds down to zero, so we get
exp(real(argexp))*exp(1i*imag(argexp))
ans =
-9.881312916824931e-324
whicih is the same as what exp() calculates on its own
exp(argexp)
ans =
-9.881312916824931e-324
So, mvncdf doesn't suffer with complex numbers for these double inputs because the imaginary part magically disappears (which isn't to say that bvncdf shouldn't be more careful about the argument to that log, maybe there are some inputs where the imaginary component will still stick around, unless an imaginary piece is dealt with later in the code)
From the error message, it looks like that on GPU code needs to be more careful to account for the possibility of a negative input to log.
When this code is executed
%{
aaa1=z_gridvals(1976,:)-z_gridspacing_down(1976,:);
aaa2=z_gridvals(1976,:)-z_gridspacing_up(1976,:);
%}
are aaa1 and aaa2 ordinary Matlab doubles (i.e., not gpuarray)?
  10 Comments
Robert Kirkby
Robert Kirkby on 12 Dec 2023
MathWorks support said
"Upon further investigation, I found that during the computation the value slightly falls below zero and then we take the log of it, which results in the error. The only fix to this issue is to ensure that the value does not go below zero.
The workaround to this issue is to run on the CPU and avoid using GPU Arrays.
Please know that we have identified this issue, and it will be addressed in future releases."
So hopefully it will be fixed soon in a future release :)
Paul
Paul on 13 Dec 2023
That's the workaround for this particular case. But I'd still be worried that there might be some combination of inputs where, on the CPU, the result for p2 on line 69-70 does have a small imaginary part. Not sure what would happen after line 70 should that occur.

Sign in to comment.

More Answers (0)

Products


Release

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!