Obscure error in mvncdf()
2 次查看(过去 30 天)
显示 更早的评论
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]
0 个评论
采纳的回答
Paul
2023-12-6
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)
and the argument to the exp() is (again, copied from my command window)
argexp = -7.438000043200474e+02 + 3.141592653589793e+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))
But, presumably the product of 1e-324 and 1e-16 rounds down to zero, so we get
exp(real(argexp))*exp(1i*imag(argexp))
whicih is the same as what exp() calculates on its own
exp(argexp)
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 个评论
Paul
2023-12-13
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.
更多回答(0 个)
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!