3
\$\begingroup\$

I am trying to build a simple C#/.Net console application that runs three iterations (see code below). The process runs as intended, but because of how many iterations there are, it can run upwards of 15 to 20 minutes. I intend to run through a list of nodes that would require individual simulations. Therefore requiring iterations for each node. Maybe 50 nodes.

I am wondering if there is a better method to run these iterations. I have just started reviewing Parallel.For() functions, but have not tested. And I have not seen many examples of chained Parallel.For() functions.

I am thinking the code below requires better iteration coding and a bit of multi-threading to really see an improvement in speed. Any suggestions? Is there anything glaring that looks wrong?

Here is the code:

static void Sim()
{

    OE oe = new OE(); // node-path functionality

    string ftC = "x"; // first call
    double fC = 4; // fourth call
    double tTime = 252; // days remaining
    double calendar = 365; // full calendar days
    double rate = .0065; /// interest rate
    double sC = 1; // secondary call
    double tC = 3.897; // third call

    string path = @"c:\temp\output.csv"; // export

    //tC settings
    double i;
    double nIncrement = .05;
    double nMin = 2;
    double nMax = 5;

    // sC settings
    double vi;
    double nvIncrement = .005;
    double nvMin = .10;
    double nvMax = .50;

    // time settings
    double ti;
    double ntIncrement = 5;
    double ntMin = 1;
    double ntMax = tTime + 4;
    //double ntMax = 30;

    // begin basic increments
// where I think I can find improvement in code
    for (i = (tC - nMin); i < nMax + (tC + nIncrement); i += nIncrement) // tC loop
    {
        double nP = Math.Round(i, 2); 

        for (vi = (sC - nvMin); vi < (sC + nvMax) + nvIncrement; vi += nvIncrement) // sCatility loop
        {
            double nV = Math.Round(vi, 4);

            for (ti = ntMin; ti <= ntMax; ti += ntIncrement) // time loop
            {
                double nT = ti;

                double variableResult = Math.Round(oe.Solver(ftC, fC, nP, nV, nT, calendar, rate, 4), 5);

                // output code here
            }
        }

    }
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ So the first thing that comes to mind is that you could make a queue of numbers that you would plug into a oe.Solver. have a few threads (maybe about 4) work on them in parallel. When one solves the problem it fires an event that it is finished. That would put that thread back in line to get another set of numbers to calculate. Continue until you finish calculating. \$\endgroup\$ Jul 19, 2013 at 3:35
  • \$\begingroup\$ @RobertSnyder Wouldn't it be simpler to just use Parallel.For()? \$\endgroup\$
    – svick
    Jul 19, 2013 at 9:33
  • \$\begingroup\$ It looks like the slow part of your code is the call to oe.Solver(). Can't you optimize that? \$\endgroup\$
    – svick
    Jul 19, 2013 at 9:34
  • \$\begingroup\$ You should not need chained Parallel.For. You can parallelize the outermost loop only, for instance. See the example here \$\endgroup\$ Jul 19, 2013 at 11:04
  • \$\begingroup\$ @svick - It is a vendor developed dll. Im not sure how much it can be optimized from my side. \$\endgroup\$
    – JAS
    Jul 19, 2013 at 11:06

2 Answers 2

5
\$\begingroup\$

Since this is code review, I would like to point out that your variable naming scheme makes your code hard to read. Why abbreviate anything? Why not call fC as just fourthCall? etc.

\$\endgroup\$
0
\$\begingroup\$

If oe.Solver() is your slowdown, you're not going to be able to get a huge improvement, but you can get some by parallelizing all the calls to it.

Replace your loops with this version:

List<double[]> data = new List<double[]>();
for (i = (tC - nMin); i < nMax + (tC + nIncrement); i += nIncrement) // tC loop
{
    double nP = Math.Round(i, 2); 

    for (vi = (sC - nvMin); vi < (sC + nvMax) + nvIncrement; vi += nvIncrement) // sCatility loop
    {
        double nV = Math.Round(vi, 4);

        for (ti = ntMin; ti <= ntMax; ti += ntIncrement) // time loop
        {
            double nT = ti;

            //double variableResult = Math.Round(oe.Solver(ftC, fC, nP, nV, nT, calendar, rate, 4), 5);
            data.Add(new[] { fC, nP, nV, nT, calendar, rate});

        }
    }

}
Parallel.ForEach(data, x => { 
      var output = oe.Solver(fC, x[0], x[1], x[2], x[3], x[4], x[5], 4);
      // Round and display output
});

This will kick off a new solver run each time the prior one displays, up to the limits of what your computer can handle.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Using Parallel for OE's instance requires OE' thread-safe implementation, which is not guaranteed here. \$\endgroup\$
    – tia
    Jul 20, 2013 at 2:53
  • \$\begingroup\$ @tia - A valid point, but if it's not thread safe then the whole question is moot. Also, given the inputs and the fact it's called Solver, I'm making the (unsupported) assumption that it's stateless. \$\endgroup\$
    – Bobson
    Jul 22, 2013 at 13:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.