测量在C中使用函数宏测量函数调用的执行时间

huangapple go评论59阅读模式
英文:

Measuring the execution time of a function call in C using a function-like macro

问题

以下是您要翻译的内容:

使用标准库函数 clock() 是在 C 中测量函数调用执行时间的几种方法之一。例如,可以如下比较两个函数(具有不同原型)的执行时间:

#include <stdio.h>
#include <time.h>

int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }

int g(int n, int a, int b) { return n < 3 ? b : g(n-1, b, a+b); }

int main(void) {
    double start, elapsed1, elapsed2;
    printf("n  f   g\n");
    for(int n = 30; n <= 40; n++) {
        start = (double) clock();
        f(n); 
        elapsed1 = (clock() - start) / CLOCKS_PER_SEC;
        start = (double) clock();
        g(n, 1, 1);
        elapsed2 = ((double) clock() - start) / CLOCKS_PER_SEC;
        printf("%d %.1f %.1f\n", n, elapsed1, elapsed2);
    }
    return 0;
}

为了使这段代码更加简洁,我们可以定义一个类似函数的宏(因为在 C 中没有“通用函数”指针):

#include <stdio.h>
#include <time.h>

double START, ELAPSED;

#define CPUTIME(FCALL) (START = (double) clock(), FCALL, ELAPSED = ((double) clock() - START) / CLOCKS_PER_SEC)

int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }

int g(int n, int a, int b) { return n < 3 ? b : g(n-1,b,a+b); }

int main(void) {
    printf("n  f   g\n");
    for(int n = 30; n <= 40; n++) 
        printf("%d %.1f %.1f\n", n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
    return 0;
}

问题: 是否有办法使变量 START 和 ELAPSED 局部于宏定义,以便宏仍然可以作为非 void “函数”调用?是否有更好的方法使代码更简洁,而不使用宏定义?

英文:

Using the standard library function clock() is one of several methods to measure the execution time of a function call in C. So, for example, the comparison of the execution times of two functions (with different prototypes) can be done as follows:

#include &lt;stdio.h&gt;
#include &lt;time.h&gt;

int f(int n) { return n &lt; 3 ? 1 : f(n-1) + f(n-2); }

int g(int n, int a, int b) { return n &lt; 3 ? b : g(n-1, b, a+b); }

int main(void) {
	double start, elapsed1, elapsed2;
	printf(&quot;n  f   g\n&quot;);
	for(int n = 30; n &lt;= 40; n++) {
        start = (double) clock();
        f(n); 
		elapsed1 = (clock() - start) / CLOCKS_PER_SEC;
        start = (double) clock();
        g(n, 1, 1);
		elapsed2 = ((double) clock() - start) / CLOCKS_PER_SEC;
		printf(&quot;%d %.1f %.1f\n&quot;, n, elapsed1, elapsed2);
	}
	return 0;
}

To make this code more concise, we could define a function-like macro (since there is no "generic function" pointer in C):

#include &lt;stdio.h&gt;
#include &lt;time.h&gt;

double START, ELAPSED;

#define CPUTIME(FCALL) (START = (double) clock(), FCALL, ELAPSED = ((double) clock() - START) / CLOCKS_PER_SEC)

int f(int n) { return n &lt; 3 ? 1 : f(n-1) + f(n-2); }

int g(int n, int a, int b) { return n &lt; 3 ? b : g(n-1,b,a+b); }

int main(void) {
    printf(&quot;n  f   g\n&quot;);
	for(int n = 30; n &lt;= 40; n++) 
		printf(&quot;%d %.1f %.1f\n&quot;, n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
	return 0;
}

Questions: Is there a way to make variables START and ELAPSED local to the macro definition so that the macro can still be called as a non-void "function"? Is there a better way to make the code more concise, without using a macro definition?

答案1

得分: 2

你可以使用非标准的 statement-expression C 扩展(至少在 clang、gcc 和 tinycc 中可用)。

#include <stdio.h>
#include <time.h>

#define CPUTIME(FCALL) ({ double START = clock(); FCALL; ((double) clock() - START) / CLOCKS_PER_SEC; })

int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }

int g(int n, int a, int b) { return n < 3 ? b : g(n-1, b, a+b); }

int main(void) {
    printf("n  f   g\n");
    for(int n = 30; n <= 40; n++) 
        printf("%d %.1f %.1f\n", n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
    return 0;
}

这是一个括号包围的块,它被评估为其中的最后一个语句所评估的结果。

我认为在标准 C 中没有通用的解决方案能够满足您的 API 约束。如果您追求标准 C 的线程安全性和/或稍微更好的代码生成,您可以使用您的原始解决方案,并在调用宏的块内(重新)声明变量。

英文:

You can use the nonstandard statement-expression C extension
(available in at least clang, gcc, and tinycc).

#include &lt;stdio.h&gt;
#include &lt;time.h&gt;

#define CPUTIME(FCALL) ({ double START = clock(); FCALL; ((double) clock() - START) / CLOCKS_PER_SEC; })

int f(int n) { return n &lt; 3 ? 1 : f(n-1) + f(n-2); }

int g(int n, int a, int b) { return n &lt; 3 ? b : g(n-1,b,a+b); }

int main(void) {
    printf(&quot;n  f   g\n&quot;);
    for(int n = 30; n &lt;= 40; n++) 
        printf(&quot;%d %.1f %.1f\n&quot;, n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
    return 0;
}

It's a parenthesized block that's evaluated to what the last statement in it evaluates to.

I don't think there's a generic solution within standard C that would satisfy your API constraints. If you're after standard-c-only threadsafety and/or slightly better codegen, you could use your original solution and (re)declare the variable(s) locally within the block that calls the macro.

答案2

得分: 1

以下是翻译好的内容:

"在不使用宏定义的情况下,有没有更简洁的方法来编写代码呢?

虽然宏定义很巧妙,但普通的函数可以减少重复,并且更容易理解:

double seconds_since(clock_t start)
{
    return (double)(clock() - start) / CLOCKS_PER_SEC;
}

int main(void) {
    clock_t start;
    double elapsed1, elapsed2;
    printf("n  f   g\n");
    for(int n = 30; n <= 40; n++) {
        start = clock();
        f(n); 
        elapsed1 = seconds_since(start);

        start = clock();
        g(n, 1, 1);
        elapsed2 = seconds_since(start);

        printf("%d %.1f %.1f\n", n, elapsed1, elapsed2);
    }
    return 0;
}
```"

<details>
<summary>英文:</summary>

&gt; Is there a better way to make the code more concise, without using a macro definition?

While the macro definition is clever, just a plain function can reduce the repetition and is simple to understand:

    double seconds_since(clock_t start)
    {
        return (double)(clock() - start) / CLOCKS_PER_SEC;
    }

    int main(void) {
        clock_t start;
        double elapsed1, elapsed2;
        printf(&quot;n  f   g\n&quot;);
        for(int n = 30; n &lt;= 40; n++) {
            start = clock();
            f(n); 
            elapsed1 = seconds_since(start);

            start = clock();
            g(n, 1, 1);
            elapsed2 = seconds_since(start);

            printf(&quot;%d %.1f %.1f\n&quot;, n, elapsed1, elapsed2);
        }
        return 0;
    }

</details>



huangapple
  • 本文由 发表于 2023年4月16日 23:06:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76028547.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定