Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

High-performance computing in ASP.NET

Posted on 2003-03-08
7
Medium Priority
?
463 Views
Last Modified: 2012-08-13
I have an algorithm that multiplies a chain of matrices in an optimized order and one that multiplies them from the beginning to the end. I want to show the difference in running time.

What I have now is like this:

I dropped a Timer component onto my web form and gave it a name, set its interval to 1 ms.
Then:

private int ms = 0; // milliseconds

// btnTime_Click function
timer1.Start();
for(...)
{
   algorithm...
}
timer1.Stop();

// OnTimer function
ms ++;

So I figured the OnTimer function would increment the number of milliseconds every time a millisecond passed and then stop doing that when the algorithm finished. However, the result seems to remain at 0, which to me either means I'm doing it wrong or my algorithm is faster than 1 ms (which could be reasonable).

*** UPDATE ***
Now there are a few more things going on. If I create a small number of matrices (like, 4) with high dimensions (randomized between 64 and 256) ASPNET is denied access and the server application cannot be found (I guess it locks up?) The same thing happens if I create a large number of matrices (like 200) with small dimensions (between 1 and 128).

However, if I bring the numbers down to just below the threshold, the running time shown by my imprecise timer is always 0 milliseconds.

Anybody have any ideas? Are there any timers that have higher precision than milliseconds?

Thanks,
-Dan
0
Comment
Question by:SuperMario
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 44

Expert Comment

by:Arthur_Wood
ID: 8095321
a timer is NOT used in this manner.  Rather, a Timer control is closer to a metronome - in that it 'ticks' every so often.  What you want to do is to read the SYSTEM time to the nearest millisecond - which may be rther difficult) at the start of the process, let the process execute and the  read the system time at the end of the proces, and compare these tow times to get the elapsed time.


AW
0
 
LVL 1

Expert Comment

by:Pickle
ID: 8099488
Use this timer object, I use this with my Direct3D programming, it will use the highest resolution timer available on your system.

All the methods are static just use it like this:

using SixBit.Taco;

//Get time since application started
float AppTime = Timer.ApplicationTime;


//Get the absolute time in the system
float AbsTime = Timer.AbsoluteTime;

//Get the time since the last call to Timer.ElapsedTime
//The first time this is called it will be the time elapsed since the app started
//So call it once before you do a timed event, and then read the value after your timed event to see how many seconds it took eg:
Timer.ElapsedTime;
SomeMethodToMeasure();
float ElapsedTime = Timer.ElapsedTime;
//The variable ElapsedTime now holds the number of seconds that SomeMethodToMeasure() took to execute



THE CODE:
-------------------------------------------------

using System;
using System.Runtime.InteropServices;

namespace SixBit.Taco
{
      /// <summary>
      /// Enumeration for various cmds our timer can execute
      /// </summary>
      enum TimerCommand
      {
            Reset,
            Start,
            Stop,
            Advance,
            GetAbsoluteTime,
            GetApplicationTime,
            GetElapsedTime
      };

      /// <summary>
      /// Wrapper for system level timer functions
      /// </summary>
      public class Timer
      {

            [System.Security.SuppressUnmanagedCodeSecurity] // Stop stack walk security check to improve performance
            [DllImport("kernel32")]
            private static extern bool QueryPerformanceFrequency(ref long PerformanceFrequency);

            [System.Security.SuppressUnmanagedCodeSecurity] // Stop stack walk security check to improve performance
            [DllImport("kernel32")]
            private static extern bool QueryPerformanceCounter(ref long PerformanceCount);

            [System.Security.SuppressUnmanagedCodeSecurity] // Stop stack walk security check to improve performance
            [DllImport("winmm.dll")]
            public static extern int timeGetTime();

            private static bool initialized = false;
            private static bool useQPF = false;
            private static bool stopped = true;
            private static long ticksPerSecond = 0;
            private static long timeStopped = 0;
            private static long timeElapsed = 0;
            private static long timeBase = 0;
            private static double doubleTimeElapsed = 0.0;
            private static double doubleTimeBase = 0.0;
            private static double doubleTimeStop = 0.0;

            private Timer(){}

            public static void Start()
            {
                  ExecTimerCommand(TimerCommand.Start);
            }

            public static void Stop()
            {
                  ExecTimerCommand(TimerCommand.Stop);
            }

            public static void Reset()
            {
                  ExecTimerCommand(TimerCommand.Reset);
            }

            public static void Advance()
            {
                  ExecTimerCommand(TimerCommand.Advance);
            }

            /// <summary>
            /// Application time.
            /// </summary>
            public static float ApplicationTime
            {
                  get{return ExecTimerCommand(TimerCommand.GetApplicationTime);}
            }
            
            public static float AbsoluteTime
            {
                  get{return ExecTimerCommand(TimerCommand.GetAbsoluteTime);}
            }

            public static float ElapsedTime
            {
                  get{return ExecTimerCommand(TimerCommand.GetElapsedTime);}
            }

            private static float ExecTimerCommand(TimerCommand cmd)
            {
                  if (!initialized)
                  {
                        initialized = true;

                        // Use QueryPerformanceFrequency() to get frequency of timer.  If QPF is
                        // not supported, we will timeGetTime() which returns milliseconds.
                        long qwTicksPerSec = 0;
                        useQPF = QueryPerformanceFrequency(ref qwTicksPerSec);
                        if (useQPF)
                              ticksPerSecond = qwTicksPerSec;
                  }
                  if (useQPF)
                  {
                        double time;
                        double fElapsedTime;
                        long qwTime = 0;
               
                        // Get either the current time or the stop time, depending
                        // on whether we're stopped and what cmd was sent
                        if (timeStopped != 0 && cmd != TimerCommand.Start && cmd != TimerCommand.GetAbsoluteTime)
                              qwTime = timeStopped;
                        else
                              QueryPerformanceCounter(ref qwTime);

                        // Return the elapsed time
                        if (cmd == TimerCommand.GetElapsedTime)
                        {
                              fElapsedTime = (double) (qwTime - timeElapsed) / (double) ticksPerSecond;
                              timeElapsed = qwTime;
                              return (float)fElapsedTime;
                        }
            
                        // Return the current time
                        if (cmd == TimerCommand.GetApplicationTime)
                        {
                              double fAppTime = (double) (qwTime - timeBase) / (double) ticksPerSecond;
                              return (float)fAppTime;
                        }
            
                        // Reset the timer
                        if (cmd == TimerCommand.Reset)
                        {
                              timeBase        = qwTime;
                              timeElapsed = qwTime;
                              timeStopped        = 0;
                              stopped     = false;
                              return 0.0f;
                        }
            
                        // Start the timer
                        if (cmd == TimerCommand.Start)
                        {
                              if (stopped)
                                    timeBase += qwTime - timeStopped;
                              timeStopped = 0;
                              timeElapsed = qwTime;
                              stopped = false;
                              return 0.0f;
                        }
            
                        // Stop the timer
                        if (cmd == TimerCommand.Stop)
                        {
                              if (!stopped)
                              {
                                    timeStopped = qwTime;
                                    timeElapsed = qwTime;
                                    stopped = true;
                              }
                              return 0.0f;
                        }
            
                        // Advance the timer by 1/10th second
                        if (cmd == TimerCommand.Advance)
                        {
                              timeStopped += ticksPerSecond/10;
                              return 0.0f;
                        }

                        if (cmd == TimerCommand.GetAbsoluteTime)
                        {
                              time = qwTime / (double) ticksPerSecond;
                              return (float)time;
                        }

                        return -1.0f; // Invalid cmd specified
                  }
                  else
                  {
                        // Get the time using timeGetTime()
                        double time;
                        double fElapsedTime;
               
                        // Get either the current time or the stop time, depending
                        // on whether we're stopped and what cmd was sent
                        if (doubleTimeStop != 0.0 && cmd != TimerCommand.Start && cmd != TimerCommand.GetAbsoluteTime)
                              time = doubleTimeStop;
                        else
                              time = timeGetTime() * 0.001;
            
                        // Return the elapsed time
                        if (cmd == TimerCommand.GetElapsedTime)
                        {  
                              fElapsedTime = (double) (time - doubleTimeElapsed);
                              doubleTimeElapsed = time;
                              return (float) fElapsedTime;
                        }
            
                        // Return the current time
                        if (cmd == TimerCommand.GetApplicationTime)
                        {
                              return (float) (time - doubleTimeBase);
                        }
            
                        // Reset the timer
                        if (cmd == TimerCommand.Reset)
                        {
                              doubleTimeBase         = time;
                              doubleTimeElapsed  = time;
                              doubleTimeStop         = 0;
                              stopped     = false;
                              return 0.0f;
                        }
            
                        // Start the timer
                        if (cmd == TimerCommand.Start)
                        {
                              if (stopped)
                                    doubleTimeBase += time - doubleTimeStop;
                              doubleTimeStop = 0.0f;
                              doubleTimeElapsed  = time;
                              stopped = false;
                              return 0.0f;
                        }
            
                        // Stop the timer
                        if (cmd == TimerCommand.Stop)
                        {
                              if (!stopped)
                              {
                                    doubleTimeStop = time;
                                    doubleTimeElapsed  = time;
                                    stopped = true;
                              }
                              return 0.0f;
                        }
            
                        // Advance the timer by 1/10th second
                        if (cmd == TimerCommand.Advance)
                        {
                              doubleTimeStop += 0.1f;
                              return 0.0f;
                        }

                        if (cmd == TimerCommand.GetAbsoluteTime)
                        {
                              return (float) time;
                        }

                        return -1.0f; // Invalid cmd specified
                  }
            }
      }
}
0
 

Expert Comment

by:stevie_bm
ID: 8102313
The code provided by Pickle looks like a good option to use for the super-accurate timer.  

For a slightly less complex method, you could compare DateTime.Now's with the format string "HH:mm:ss.fffffff".  This string will give you [Hours]:[Minutes]:[Seconds].[Seven bit precision second fractions].  For the fractional seconds, anything over the number of 'f's included is truncated, and the hours, minutes, and seconds have leading zeros.

With regards to ASP.Net worker process "locking", when it is carrying out a particularly intensive task (such as matrix multiplication, or deep recursion), the process will quickly run to 100% (or another value, if you're using WebGardens - divide by # of processors).  When the worker process reaches this limit, it refuses further incoming requests.  I would suggest looking at multi-threading your application to solve this (put the matrix multiplication on a new thread, so that ASP.Net Worker Process can serve other requests).
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Author Comment

by:SuperMario
ID: 8103063
stevie_bm,
Thanks very much for the info on the worker process. That's exactly what I was looking for regarding the high-performance computing.

And Arthur_Wood, your initial suggestion solved my other problem.

Though it turns out that a timer is actually kind of useless here. The most important task of this application is to determine the actual _number_ of multiplications that take place and determine the optimum order in which to multiply the matrices (a classic dynamic programming problem).

So, I doubled the points and I'll ask customer service to divide them between Arthur_Wood and stevie_bm.

Thanks a lot guys, I truly appreciate your help!
0
 
LVL 3

Author Comment

by:SuperMario
ID: 8103152
Oh, by the way, stevie_bm:

Does your comment apply also to C# Windows apps? My roommate has this unnatural, and in my opinion, very weird, interest in pi (he has memorized something like 57 digits). He has been trying to use C# to calculate each number of pi in binary (up to 100 million digits) in hopes that it will lead him to the meaning of life. 10 million digits works just fine with his program, but 100 million will lock up the process. Is this due to the same thing you told me, and should he use multithreading to solve it?
0
 

Accepted Solution

by:
stevie_bm earned 400 total points
ID: 8103296
Yeah, it also applies to WinForms...  The only difference here is that your process won't be the ASP.Net worker process, but the executable of your app.

If he wants to do that, there's a good trilogy of tutorials on MSDN to make a multi-threaded pi calculator winform.  In short, he'll need two threads for a basic app - 1 to do the calculation of pi, and the other to render the UI and control the worker thread.

These might also help you get a good grasp on the issues of threading...

The tutorials I mention are here, and form (pun recognised, but not intended) a series, and I'm sure your friend would be satisfied by the program it produces:
"Safe, Simple Multithreading in Windows Forms, Part 1" By Chris Sells -
http://msdn.microsoft.com/library/en-us/dnforms/html/winforms06112002.asp

"Safe, Simple Multithreading in Windows Forms, Part 2" By Chris Sells -
http://msdn.microsoft.com/library/en-us/dnforms/html/winforms08162002.asp

"Safe, Simple Multithreading in Windows Forms, Part 3" By Chris Sells -
http://msdn.microsoft.com/library/en-us/dnforms/html/winforms01232003.asp

I hope this is helpful...  Multi-threading of apps is a really useful tool when you're doing processor/memory intensive operations, and it's interesting to learn, too...

Oh, and I hope your friend gets the help he quite obviously needs for his mental illness ;)
0
 
LVL 6

Expert Comment

by:Mindphaser
ID: 8104722
xxx

You asked to split points between Arthur_Wood and stevie_bm.

I have reduced the points on this question from 200 to 100 as indicated by your request at Community Support. Please copy the URL and create a new question in this topic area for the other Experts to whom you wish to award points. The title of the question should read "Points for", followed by the Expert's name. In the question itself, you should paste the link to the original question and perhaps a comment stating that the points are for their help with that question. Once you have created the new questions, you can go back to the original, and accept the comment from the Expert for whom you did not create a new question. The Experts will  comment in your new "Points for" question(s), which you then accept and grade to close.
If you have any questions, please don't hesitate to ask.
Thank you.

** Mindphaser - Community Support Moderator **
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Ivo
C# And Nullable Types Since 2.0 C# has Nullable(T) Generic Structure. The idea behind is to allow value type objects to have null values just like reference types have. This concerns scenarios where not all data sources have values (like a databa…
Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question