EIG incorrect for large matrices when compiled into C on speedgoat target computer
4 views (last 30 days)
I have been using Matlab R2017b to create simulink files that are compiled onto a speedgoat target computer. In the simulink file, in a matlab function block, we use the function eig to find the eigenvectors and eigenvalues of a matrix A. When A is 4 by 4 or smaller, this works fine.
When A is larger than 4x4 (i.e. 5x5, 6x6), eig does not correctly return the eigenvalues of the matrix. That is, for the same matrix A, the eigenvalues generated by eig on the target computer are different than those generated on the target computer (i.e. calling eig in the workspace normally).
Is this related to the code being compiled into C/C++? Has anyone experienced this issue?
Mike Hosea on 22 Jul 2019
Bit difficult to debug from here. Is your code calling the initialize and terminate functions for the library you are generating?
As for complex eigenvectors, for Hermitian A we have been generating code that performs [V,D] = schur(A,'complex') and then zeros the off-diagonal elements of D. That is to say, code generation has been treating every problem as a complex one in EIG, which in the general case it must because complexity is immutable in the generated C code and depends on input data values. That might explain the occasional appearance of complex eigenvectors. We're planning to change this to do [V,D] = schur(A,'real') instead when A is real and symmetric. Since you know your input matrix is real and symmetric, you could just do that yourself instead of calling EIG.
Of course none of that explains incorrect results. I'm not aware of anything that would cause norm(A*V - V*D) to be larger than expected, and I'm not seeing any memory overruns or anything like that when debugging generated code that doesn't call into a LAPACK library, such as would be the case for a stand-alone target.
We do regularly find bugs in C compilers around here. It is worth generating code with different optimization levels to see what happens.
Finally, I believe we supported calling LAPACK on a stand-alone target in 17b. If you can get a LAPACK library built for your target, that might be a workaround and and also deliver performance benefits on larger problems. I'm not personally familiar with the process, but I know it is documented.
Delaney on 22 Jul 2019
Thanks for the help. What do you mean by your first question? We are not initializing/terminating the eig function as we are using it within a larger function (Simulink fcn block). We are using a Speedgoat target machine (https://www.speedgoat.com/learn-support/simulink-real-time-workflow) and I believe our driver blocks are working correctly as it isn't throwing any errors. Maybe this is an error on Speedgoat's end when the C code is compiled.
I'm aware of the default settings with 'schur' to the complex eigendecomposition. When I use schur(C,'real'), I find that I similarly get a completely wrong eigendecomposition. It's just all real instead of complex and the Dtemp matrix (of eigenvalues) has non-zero entries for non-diagonal indices. Here's an example (slightly different C matrix):
[6.9407 -32.0045 -0.9886;
57.0459 6.9407 2.4762;
0 0 6.9407];
So yeah, it seems the issue is with the 'schur' algorithm as 'qz' works fine. Because we only run this computation every 15 minutes or so within the context of a larger biomechanics data collection, it doesn't necessarily make sense for us to go to the trouble of building a LAPACK library. I understand that 'qz' algorithm is not as efficient (esp. for a real symmetric / Hermitian matrix) but it seems to be accurate so we'll stick with that solution for the time being.
Appreciate you looking into this,