【发布时间】:2012-01-12 16:20:16
【问题描述】:
代码如下:
#include <iostream>
#include <time.h>
using namespace std;
#define ARR_LENGTH 1000000
#define TEST_NUM 0
typedef unsigned int uint;
uint arr[ARR_LENGTH];
uint inc_time(uint x) {
uint y = 0, tm = clock();
for (uint i = 0; i < x; i++) y++;
return clock() - tm;
}
int main() {
uint div = 0, mod = 0, tm = 0, overall = 0, inc_tm;
srand(time(NULL));
for (uint i = 0; i < ARR_LENGTH; i++) arr[i] = (uint)rand() + 2;
tm = clock();
for (uint i = 0; i < ARR_LENGTH - 1; i++)
if (arr[i] % arr[i+1] != TEST_NUM) mod++;
overall = clock() - tm;
inc_tm = inc_time(mod);
cout << "mods - " << mod << endl;
cout << "Overall time - " << overall<< endl;
cout << " wasted on increment - " << inc_tm << endl;
cout << " wasted on condition - " << overall - inc_tm << endl << endl;
tm = clock();
for (uint i = 0; i < ARR_LENGTH - 1; i++)
if (arr[i]/arr[i+1] != TEST_NUM) div++;
overall = clock()-tm;
inc_tm = inc_time(div);
cout << "divs - " << div << endl;
cout << "Overall time - " << overall << endl;
cout << " wasted on increment - " << inc_tm << endl;
cout << " wasted on condition - " << overall - inc_tm << endl << endl;
return 0;
}
如果您使用 Visual Studio,只需在 DEBUG(而非 RELEASE)模式下编译,如果您使用 GCC,则禁用死代码消除 (-fno-dce),否则某些部分代码将无法工作。
所以问题是:当您将 TEST_NUM 常量设置为非零(例如 5)时,两个条件(模数和除法)几乎同时执行,但是当您将 TEST_NUM 设置为 0 时,第二个条件执行较慢(最多 3 次!)。为什么?
这里是反汇编列表:disassembly listing image http://img213.imageshack.us/slideshow/webplayer.php?id=wp000076.jpg
如果为 0,则使用 test 指令而不是 cmp X, 0,但即使您将 cmp X, 5(如果为 5)修补到 cmp X, 0,您也会看到它不会影响模运算, 但会影响除法运算。
在更改TEST_NUM 常量时,请仔细观察操作计数和时间的变化情况。
如果有人可以,请解释一下这是怎么发生的?
谢谢。
【问题讨论】:
-
请您编辑您的问题以包含测试代码;我不想点击链接!
-
在没有优化的情况下编译时测试性能没有多大意义。
-
@OliCharlesworth 我已经包含了代码,但如果您不想制作自己的反汇编列表,您仍然需要点击链接(在我的情况下,它在纸上,抱歉)
-
@interjay 感谢您的评论。我知道我在做什么 :) 您只需要禁用死代码消除,或者您可以编写自己的 inc_time() 函数,该函数将能够准确计算增量时间。如您所见,此函数中没有更多有用的计算,并且由于“i”的值可以在编译时计算,因此删除了“死代码”。但是,如果您使用优化进行编译,您将获得相同的策略结果。
-
如果您想像尝试那样与它们进行比较,则需要将时间变量声明为 volatile。在没有优化的情况下授予并设置为调试无关紧要,无论如何它们都被视为易失性。
标签: performance architecture assembly x86 cmp