I'm working on an application where I'd like to dynamically generate code for a numerical calculation (for performance). Doing this calculation as a data driven operation is too slow. To describe my requirements, consider this class:
class Simulation
{
Dictionary<string, double> nodes;
double t, dt;
private void ProcessOneSample()
{
t += dt;
// Expensive operation that computes the state of nodes at the current t.
}
public void Process(int N, IDictionary<string, double[]> Input, IDictionary<string, double[]> Output)
{
for (int i = 0; i < N; ++i)
{
foreach (KeyValuePair<string, double[]> j in Input)
nodes[j.Key] = j.Value[i];
ProcessOneSample();
foreach (KeyValuePair<string, double[]> j in Output)
j.Value[i] = nodes[j.Key];
}
}
}
What I want to do is JIT compile a function that implements the outer loop in Process. The code that defines this function will be generated by the data that is currently used to implement ProcessOneSample. To clarify what I'm expecting, I'd expect all of the dictionary lookups to be performed once in the compilation process (i.e. the JIT compile would bind directly to the relevant object in the dictionary), so that when the compiled code is actually executed, it is as if all of the lookups had been hardcoded.
What I'm trying to figure out is what the best tools are to tackle this problem. The reason I'm asking this question is because there are so many options:
- Use Roslyn. Current stumbling block is how to bind expressions in the syntax to member variables from the host program (i.e. the values in the 'state' dictionary). Is this possible?
- Use LINQ Expressions (Expression.Compile).
- Use CodeDom. Just recently became aware of this in my google searching, and what prompted this question. I'm not too stoked on stumbling my way through a third compilation framework in .Net.
- My original plan before I knew any of these tools existed was to call native code (x86) that I JIT compiled myself. I have some experience with this, but there are a lot of unknowns here that I have not solved yet. This is also my backup option if the performance of the above options is not sufficient. I'd prefer one of the above 3 solutions because I am sure they will be much, much simpler, assuming I can get one of them to work!
Does anyone have any experience with something like this that they would be able to share?