-
Notifications
You must be signed in to change notification settings - Fork 524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor: replace numeric with mathjs #225
Conversation
@@ -368,7 +368,8 @@ | |||
self.webgazer.util.KalmanFilter.prototype.update = function(z) { | |||
|
|||
// Here, we define all the different matrix operations we will need | |||
var add = numeric.add, sub = numeric.sub, inv = numeric.inv, identity = numeric.identity; | |||
// FIXME: mathjs is not exported to worker global scope | |||
var add = mathjs.add, sub = mathjs.subtract, inv = mathjs.inv, identity = mathjs.identity; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this works since neither the numeric
nor the mathjs
variable is exported to the worker global scope. (as commented in #163 (comment))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we need to fix that separately.
solution = (ss.length === ss[0].length ? (numeric.LUsolve(numeric.LU(ss,true),bb)) : (webgazer.mat.QRDecomposition(ss,bb))); | ||
solution = ss.length === ss[0].length ? | ||
mathjs.squeeze(mathjs.lusolve(ss, bb)) : // lusolve returns a column vector, so squeeze it | ||
webgazer.mat.QRDecomposition(ss,bb); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
math.js has a qr decomposition too, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but the two functions are different: mathjs.qr(A)
only decomposes matrix A
, while mat.QRDecomposition(A, b)
solves the linear system Ax = b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The equivalent qrsolve()
function can be implemented as:
function qrsolve(A, b) {
const { Q, R } = mathjs.qr(A);
const dim1 = A[0].length;
return math.multiply(
mathjs.inv(R.slice(0, dim1)),
mathjs.transpose(Q).slice(0, dim1),
b,
);
}
However, I don't think it will be faster than the current one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WOW. Just wow. Add a comment so we don't accidentally use them in the future. We should verify the matmul and other functions in math.js are actually faster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather disappointing. Are there any other good candidates that may work better than math.js. Surely something has to be faster than numeric, maybe something that even leveraged WASM?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mat.mul()
is also faster thanmathjs.multiply()
after 1M runs:Maybe mathjs is wasting too much time constructing matrix instances 😞
Looked into the code and apparently the matrix instances are just a wrapper around associative arrays so that shouldn't slow it down. I did see that it did have serious speed issues though. It's designed to be flexible and extensible, not fast.
column vector before applying subtraction
Yeah, I found that Math.js wraps normal JS arrays. Hence why it's slow. It also doesn't do a lot of optimizations. It seems to be more focused on correctness and extensibility than speed sadly. Instead of reimplementing all these ourselves, I would like to see if there is a well-supported LinAlg library we can leverage. At the very least, we are using arrays of arrays in JS which are really slow, so anything that doesn't use those should perform faster. @idiotWu It may be overkill but how does the benchmarking for Eigen.JS look? https://github.com/BertrandBev/eigen-js |
Here is there official benchmarking: https://bertrandbev.github.io/eigen-js/#/benchmark |
Well, JS native arrays are actually fast on modern browsers. I thought TypedArray based implement would be faster, but in my tests ml-matrix (the only |
I just dropped in to say a big THANK YOU! Istvan |
@idiotWu Thanks. |
Resolves #211.
This PR replaced numeric with mathjs to fix the CSP error as mentioned in #211.
I'm not able to run the test script because files under
www/data/src/P_01/
are missing, but the demo pages seem to be working.As a side effect, the bundle size increased from 2.1M to 3.2M (both minified).