计算执行函数所需时间的问题

发布于 2024-11-25 11:03:57 字数 747 浏览 1 评论 0原文

我试图找到运行一个函数所需的时间。我这样做是这样的:

SomeFunc(input) {
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    //some operation on input          

    stopWatch.Stop();

    long timeTaken = stopWatch.ElapsedMilliseconds;
}

现在,评论中提到的“对输入的某些操作”根据 SomeFunc 的输入需要花费大量时间。

问题是,当我从 main 多次调用 SomeFunc 时,我仅第一次正确地得到 timeTaken,其余时间它被分配为 0。上述是否有问题代码?

编辑: 有一个带有多个文本字段的 UI,当单击按钮时,它会被委托给 SomeFunc。 SomeFunc 根据输入(来自文本字段)进行一些计算,并将结果显示在 UI 上。由于我签署了保密协议,因此我不被允许在“对输入进行某些操作”中共享代码。不过,我可以回答你关于我想在那里实现什么目标的问题。请帮忙。

编辑2: 因为当第一次调用该函数时,我似乎得到了奇怪的值,并且正如 @Mike Bantegui 提到的,必须进行 JIT 优化,这是我现在能想到的唯一解决方案(执行时间不为零)就是以纳秒为单位显示时间。在 C# 中如何以纳秒为单位显示时间?

I am trying to find the time taken to run a function. I am doing it this way:

SomeFunc(input) {
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    //some operation on input          

    stopWatch.Stop();

    long timeTaken = stopWatch.ElapsedMilliseconds;
}

Now the "some operation on input" as mentioned in the comments takes significant time based on the input to SomeFunc.

The problem is when I call SomeFunc multiple times from the main, I get timeTaken correctly only for the first time, and the rest of the time it is being assigned to 0. Is there a problem with the above code?

EDIT:
There is a UI with multiple text fields, and when a button is clicked, it is delegated to the SomeFunc. The SomeFunc makes some calculations based on the input (from the text fields) and displays the result on the UI. I am not allowed to share the code in "some operation on input" since I have signed an NDA. I can however answer your questions as to what I am trying to achieve there. Please help.

EDIT 2:
As it seems that I am getting weird value when the function is called the first time, and as @Mike Bantegui mentioned, there must be JIT optimization going on, the only solution I can think of now (to not get zero as execution time) is that to display the time in nano seconds. How is it possible to display the time in nano seconds in C#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心舞飞扬 2024-12-02 11:03:57

好吧,您不会在任何地方输出该数据。理想情况下,你会做类似这样的事情。

void SomeFunc(input)
{
  Do sstuff
}

main()
{
  List<long> results = new List<long>();
  Stopwatch sw = new Stopwatch();
  for(int i = 0; i < MAX_TRIES; i++)
  {
     sw.Start();
     SomeFunc(arg);
     sw.Stop();
     results.Add(sw.ElapsedMilliseconds);
     sw.Reset();
  }

  //Perform analyses and results
}

Well, you aren't outputing that data anywhere. Ideally you would do it something more like this.

void SomeFunc(input)
{
  Do sstuff
}

main()
{
  List<long> results = new List<long>();
  Stopwatch sw = new Stopwatch();
  for(int i = 0; i < MAX_TRIES; i++)
  {
     sw.Start();
     SomeFunc(arg);
     sw.Stop();
     results.Add(sw.ElapsedMilliseconds);
     sw.Reset();
  }

  //Perform analyses and results
}
菩提树下叶撕阳。 2024-12-02 11:03:57

事实上,您在第一次开始时得到的时间是错误的,而在其余时间中得到的时间是正确的。 您不能仅在第一次调用时进行中继来测量时间。然而,似乎操作太快,因此您得到了 0 结果。例如,要正确测量测试,请调用该函数 1000 次以查看平均成本时间:

Stopwatch watch = StopWatch.StartNew();
for (int index = 0; index < 1000; index++)
{
    SomeFunc(input);
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);

编辑:

如何以纳秒为单位显示时间

您可以获取watch.ElapsedTicks,然后将其转换为纳秒:(watch.ElapsedTicks / Stopwatch.Frequency) * 1000000000

In fact you are getting the wrong time at the first start and correct time to the remaining. You can't relay just on the first call to measure the time. However It seams to be that the operation is too fast and so you get the 0 results. To measure the test correctly call the function 1000 times for example to see the average cost time:

Stopwatch watch = StopWatch.StartNew();
for (int index = 0; index < 1000; index++)
{
    SomeFunc(input);
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);

Edit:

How is it possible to display the time in nano seconds

You can get watch.ElapsedTicks and then convert it to nanoseconds : (watch.ElapsedTicks / Stopwatch.Frequency) * 1000000000

三五鸿雁 2024-12-02 11:03:57

作为一个简单的示例,请考虑以下(人为的)示例:

double Mean(List<double> items)
{
    double mu = 0;
    foreach (double val in items)
        mu += val;
    return mu / items.Length;
}

我们可以像这样计时:

void DoTimings(int n)
{
    Stopwatch sw = new Stopwatch();
    int time = 0;
    double dummy = 0;

    for (int i = 0; i < n; i++)
    {
        List<double> items = new List<double>();
        // populate items with random numbers, excluded for brevity

        sw.Start();
        dummy += Mean(items);
        sw.Stop();
        time += sw.ElapsedMilliseconds;
    }

    Console.WriteLine(dummy);
    Console.WriteLine(time / n);
}

如果项目列表实际上非常大,则这有效。但如果它太小,我们就必须在一次计时下进行多次运行:

void DoTimings(int n)
{
    Stopwatch sw = new Stopwatch();
    int time = 0;
    double dummy = 0;

    List<double> items = new List<double>(); // Reuse same list
    // populate items with random numbers, excluded for brevity

    sw.Start();
    for (int i = 0; i < n; i++)
    {
        dummy += Mean(items);
        time += sw.ElapsedMilliseconds;
    }
    sw.Stop();

    Console.WriteLine(dummy);
    Console.WriteLine(time / n);
}

在第二个示例中,如果列表的大小太小,那么我们只需运行以下命令即可准确地了解需要多长时间:足够大的n。但每种都有其优点和缺点。

然而,在执行其中任何一个之前,我会事先进行“热身”计算:

// Or something smaller, just enough to let the compiler JIT
double dummy = 0;
for (int i = 0; i < 10000; i++) 
    dummy += Mean(data);
Console.WriteLine(dummy);

// Now do the actual timing

这两种方法的另一种方法是执行 @Rig 在他的答案中所做的操作,并建立一个结果列表来进行统计。在第一种情况下,您只需建立每个单独时间的列表。在第二种情况下,您将建立多次运行的平均时间列表,因为计算时间可能小于秒表中最细粒度的时间。

话虽如此,我想说的是,在所有这一切中,有一个非常大的警告:计算某件事运行所需的时间很难正确完成。想要进行分析是令人钦佩的,但是您应该对 SO 进行一些研究,并看看其他人做了什么来正确地做到这一点。编写一个时间错误的例程很容易,但要正确执行却很难。

As a simple example, consider the following (contrived) example:

double Mean(List<double> items)
{
    double mu = 0;
    foreach (double val in items)
        mu += val;
    return mu / items.Length;
}

We can time it like so:

void DoTimings(int n)
{
    Stopwatch sw = new Stopwatch();
    int time = 0;
    double dummy = 0;

    for (int i = 0; i < n; i++)
    {
        List<double> items = new List<double>();
        // populate items with random numbers, excluded for brevity

        sw.Start();
        dummy += Mean(items);
        sw.Stop();
        time += sw.ElapsedMilliseconds;
    }

    Console.WriteLine(dummy);
    Console.WriteLine(time / n);
}

This works if the list of items is actually very large. But if it's too small, we'll have to do multiple runs under one timing:

void DoTimings(int n)
{
    Stopwatch sw = new Stopwatch();
    int time = 0;
    double dummy = 0;

    List<double> items = new List<double>(); // Reuse same list
    // populate items with random numbers, excluded for brevity

    sw.Start();
    for (int i = 0; i < n; i++)
    {
        dummy += Mean(items);
        time += sw.ElapsedMilliseconds;
    }
    sw.Stop();

    Console.WriteLine(dummy);
    Console.WriteLine(time / n);
}

In the second example, if the size of the list is too small, then we can accurately get an idea of how long it takes by simply running this for a large enough n. Each has it's advantages and flaws though.

However, before doing either of these I would do a "warm up" calculation before hand:

// Or something smaller, just enough to let the compiler JIT
double dummy = 0;
for (int i = 0; i < 10000; i++) 
    dummy += Mean(data);
Console.WriteLine(dummy);

// Now do the actual timing

An alternative method of both would be to do what @Rig did in his answer, and build up a list of results to do statistics on. In the first case, you'd simply build up a list of each individual time. In the second case, you would build up a list of the average timing of multiple runs, since the time for a calculation could smaller than finest grained time in your Stopwatch.

With all that said, I would say there is one very large caveat in all of this: Calculating the time it takes for something to run is very hard to do properly. It's admirable to want to do profiling, but you should do some research on SO and see what other people have done to do this properly. It's very easy to write a routine that times something badly, but very hard to do it right.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文