-
Notifications
You must be signed in to change notification settings - Fork 3
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
Reducing memory allocation using lazy evaluation #29
Comments
Thanks for the kind comment 😊 Regarding the lazy evaluation technique, while it's an interesting topic, it's difficult for me to implement and maintain due to my current workload 😖 Anyway, I really hope that interest in numerical computation and ML expands within the .NET community. |
INMO in C# any lazy evaluations will imply ether boxing of value-types, or allocations of delegates, which in both cases implies heap allocations (and impossibility to use ref structs). With the current approach all intermediate objects are structs, so they are stack-allocated by compiler which is cheap. Something like this can be achieved with code-generators, but that's another level. UPD: There's some hope https://github.com/dotnet/runtime/issues/104936 with the upcoming NET10, though. |
Here by "lazy evaluation" I do not refer to any specific current implementations like As for System.Numerics.Tensors, of course I also hope it to be good enough to use. However, AFAIK Microsoft is not particularly experienced with numerics. I am not so confident that they will make it right. In fact, I have already seen some severe criticism (indicating the whole design is problematic) on System.Numerics.Tensors and the whole System.Numerics actually. You could use a translator to read https://zhuanlan.zhihu.com/p/713157309 if you are interested. |
My point was that when constructing any deferred execution expression chain, you'll have to return something from it's building blocks to get nice syntax. You can not return ref struct as an Interface that it implements (A ref struct can't be converted to an instance of an interface it implements). Those interfaces serve different goals. |
Why just returning the raw ref struct is a problem? I can not see why we need to convert it to an interface or delegate. For example, suppose the operation is defined as: struct AddGeneric<V1, V2>: IVecExp where V1: IVecExp, V2: IVecExp {
V1 left;
V2 right;
} The expression struct AddInterface: IVecExp {
IVec left;
IVec right;
} The |
Thank you for this project! .NET world really need good numerics and linear algebra libraries nowadays.
The README indicates the impact of memory allocation on performance is already noticed, and an inplace operation is suggested.
In principle, such inplace operations do avoid memory allocations. However, it would requrie the coder to manually arrange the orders for a complex chained expression, and make the code harder to read.
The popular libraries in C++ world (e.g. Eigen3 and Blaze) use a lazy evaluation technique to handle such difficulties. For example,
var X = A.Add(B)
produces aMatAdd<Mat, Mat>
instead of aMat
,var X = A.Add(B.MultipleBy(C))
will produce aMatAdd<Mat, MatMul<Mat, Mat>>
, whereMatAdd
andMatMul
only track the operations to be performed (but not actually perform them) and are something like aref struct
that does not need heap allocation.And finally,
X.Eval()
will allocate a new matrix andX.EvalTo(M)
will use the pre-allocatedM
. Only at this point the lazy evaluation is performed, and all the intermediate temp allocation can be avoided.(This may be simplified using the upcoming Extention Everthing, e.g
var R = X.Eval()
may be just replaced byMat R = X
, but I am not sure)The text was updated successfully, but these errors were encountered: