【问题标题】:difftime returning 0 when there is clearly a difference当明显有差异时 difftime 返回 0
【发布时间】:2010-10-28 09:34:54
【问题描述】:

我有以下 C99 程序,用于测量相对于加法的简单除法运算的性能。然而,difftime 函数仍然返回 0,即使程序显然需要几秒钟来处理 runAdditionrunDivisioniterations 设置为 10 亿。

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

void runAddition(long long iterations)
{
    long long temp;
    for (long long i = 1; i <= iterations; i++)
    {
        temp = temp + i;
    }
}

void runDivision(long long iterations)
{
    long long temp;

    // Start at 1 to avoid division by 0!
    for (long long i = 1; i <= iterations; i++)
    {
        temp = temp / i;
    }
}

int main()
{
    long long iterations = 1000000000;
    time_t startTime;

    printf("How many iterations would you like to run of each operation? ");
    scanf("%d", &iterations);

    printf("Running %d additions...\n", iterations);
    startTime = time(NULL);
    runAddition(iterations);
    printf("%d additions took %f seconds\n", iterations, difftime(time(NULL), startTime));

    printf("Running %d divisions...\n", iterations);
    startTime = time(NULL);
    runDivision(iterations);
    printf("%d divisions took %f seconds\n", iterations, difftime(time(NULL), startTime));
}

【问题讨论】:

  • 最好从 0 而不是 1 开始循环计数。
  • 是的,但是你看到我的评论了吗? “从 1 开始,避免被 0 除”
  • 出于兴趣,您是否尝试将 startTime ref 传递给 time() - 即更改 startTime = time(NULL);到时间(&startTime)?不确定为什么会有所帮助,它们都是同一件事......只是好奇。

标签: c


【解决方案1】:

您的格式字符串需要int (%d) 和double (%f)。你的论点是long longdouble。您应该将第一个格式字符串设置为%lld

当将参数压入堆栈以调用 printf 时,您使用 8 个字节压入 long long,也使用 8 个字节压入 double。当函数 printf 读取格式字符串时,它首先需要 4 个字节的 int 和 8 个字节的 doubleprintf 正确获取 int,因为您是 little-endian 并且您的 long long 的前四个字节足以表示该值。然后printf 获取double,它获取long long 的最后四个字节,然后是double 的前四个字节。由于long long 的最后四个字节为零,printf 认为双精度以四个字节开始,值为 0,根据双精度的二进制表示,导致 double 的值非常小。

【讨论】:

  • 啊...我不知道使用不正确的格式说明符会影响其他说明符。这解决了问题,+1,谢谢。另外,您能否进一步解释一下或指出一些文档?
  • 要小心,因为long long 的格式说明符取决于 CRT。最好避免打印多头。
  • @ruslik:这就是 stdint.hinttypes.h 的用途。
  • @Hasturkun @codaddict,在 Microsoft Visual Studio 2008 中找不到这两个文件。查看 C++ 标准,我发现 C++ 标准 2003 (ISO/IEC 14882) 不支持 long long,但支持通过 C++ 0x 草案 (n3126)。请参阅两个文档的“整数文字”部分
  • @Sheen:是的,但问题确实是指 C99 而不是 C++,它仍然是相关的
【解决方案2】:

尝试在printf 中使用%lld 代替%d

printf("%lld additions t
         ^^^

Works fine after this change.

【讨论】:

  • @PigBen,对此感到好奇。似乎我长期以来的假设是较大的整数将被 printf() 截断是不正确的???
  • @Sheen -- 在过去不久,这从来都不是问题。所有整数类型(char、short、int、long)都将向上转换为 long。但是现在加上了long long,情况就不同了。我不确定标准到底是怎么说的,我不再使用 printf,我更喜欢 C++ 流。
【解决方案3】:

使 temp volatile 不会被优化掉。编译器可能将其视为没有副作用的部分/函数。

【讨论】:

  • 在我看来,这是最有可能发生的事情。
  • 不这么认为。 “temp = temp / i”要求您执行计算以确定 temp 的最终值。您无法对其进行优化。
  • 考虑到大量的迭代,并且函数是内联的,在大约 30 次左右的迭代中 temp 将变为 0。编辑:实际上 30 一直基于除以 2。随着i的增加,迭代次数甚至会更少。
【解决方案4】:

它计算 time1 和 time2 之间的秒差。那么也许你的时差不到 1 秒?

输出您的开始和结束时间以进行验证。

【讨论】:

  • 不,绝对超过一秒。更像是10秒。我已经通过打印 startTimetime(NULL) 验证了这一点。
  • @Jake Petroules,你能输出开始和结束时间来调试吗?
  • 是的,正如我所说,我做到了。
【解决方案5】:

time() 返回一个 time_t,其分辨率为一秒。

runDivision() 所需时间小于一秒;在多 GHz 内核上执行 10 亿次操作只需不到一秒的时间。

【讨论】:

  • 在我的机器上需要 40 秒。正如我所说,“程序显然需要几秒钟来处理”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-14
  • 1970-01-01
  • 1970-01-01
  • 2016-02-21
  • 2014-05-19
相关资源
最近更新 更多