uncomplicate

alan 2018-07-28T16:51:26.000084Z

@blueberry https://gitlab.com/alanmarazzi/numpy-vs-neanderthal/blob/master/README.md#summary So, a few interesting results: - The new svd! implementation is faster than the regular one, but it gets much slower (even slower than the regular one for larger matrices), and I thought this was weird

SVD 4x4
===========

Numpy:             17.5 µs +- 0.7 µs
Neanderthal:       4.23 µs +- 75.38 ns
Neanderthal (SDD): 3.8 µs +- 101.37 ns

SVD 4096x4096
===========

Numpy:             22.7 sec +- 2.8 sec
Neanderthal:       5.84 sec +- 54.56 ms
Neanderthal (SDD): 10.85 sec +- 125.02 ms
- The new ev! implementation for symmetric matrices it is ok, but it doesn't give me the same result as eigh for Numpy (as to say I need vl and/or vr anyway), moreover in this case it is faster than Numpy for small matrices, but slower or on par for larger ones:
SME 128x128 (Symmetric Matrix Eigenvalues)
===========

Numpy:       919 µs +- 12 µs
Neanderthal: 303 µs +- 4.6 µs

SME 1024x1024 (Symmetric Matrix Eigenvalues)
===========

Numpy:       92.8 ms +- 1.9 ms
Neanderthal: 139.33 ms +- 10.27 ms

SME 4096x4096 (Symmetric Matrix Eigenvalues)
===========

Numpy:       7.76 sec +- 0.03 sec
Neanderthal: 3.72 sec +- 4.62 sec
- As you can see above there's another issue with ev!: the standard deviation is larger than the mean! I've run it a few times to be sure

2018-07-28T17:51:17.000046Z

@justalanm these different algorithms have their strengths and weaknesses. they are not silver bullets. as far as i remember, sdd is faster than svd when you do want to compute u and/or vt. otherwise, it is not, but it also depend on the data as these are iterative algorithms.

2018-07-28T18:02:55.000006Z

@justalanm in both bench-svd and bench-sdd methods you are creating huge matrices and then throw them away. the point of ! methods is that you pre-create one memory object and then reuse it. the standard deviation might come from the GC (but I'm not sure, since this is something that you don't want to do anyway.) Pre-create the result matric outside of the benchmark loop in all places when you want the benefit of ! methods...

2018-07-28T18:04:10.000067Z

BTW in this case you were not even releasing those objects. so, your quick-bench loop would create many objects and then forget about them...

2018-07-28T18:09:29.000067Z

@justalanm as for the ev! et al I can see that in bench-symmetric-ev you are also creating the result matrix inside the loop (and then throw it away). pre-create it.

2018-07-28T18:16:06.000017Z

@justalanm however, the key point here is that, if you want the top speed from the ev! you should re-use a a GE-view of as the result! (let [res (view-ge a) (ev! a res)). In that case, it will overwrite a's memory with the eigenvectors. that's how underlying ev routines work. Otherwise, I have to copy a's data each time keep to the contract of not destroying the complementary region of a's underlying buffer, and that's why it can't get much faster than numpy in that case, since numpy does not care about that. it calls eigh and happily works with the whole rectangle (half of which might be another symmetric matrix!).

2018-07-28T18:20:40.000057Z

pca benchmarks are not very relevant since you still create and copy a bunch of objects that you use only one time, and thus can (and should if you want fast code) reuse.

alan 2018-07-28T18:54:53.000055Z

You're right, I realized it just a few moments ago!

alan 2018-07-28T18:58:47.000060Z

As above, but ev! will be slower anyway since I need vl, so I have to calculate vr as well (the reason why now I use the same object for both)

2018-07-28T19:00:54.000061Z

@justalanm for symmetric matrices, vl and vr are the same thing! + use (view-ge a) as a result!

alan 2018-07-28T19:03:00.000043Z

I know, that's why I'm using the same object for both

2018-07-28T19:13:42.000038Z

Why? you need two copies of the result? Just provide one.

alan 2018-07-28T19:53:02.000053Z

(ev! a w vl) doesn't work

2018-07-28T20:13:41.000005Z

@justalanm It's difficult to say anything without knowing how "doesn't work" look like, but I guess that for what you are trying to do, you should say something like (ev! a w v nil)

2018-07-28T20:15:02.000041Z

with the advice that v should actually be (view-ge a)