【编程珠玑】读书笔记 时空开销模型

2013-07-10 20:13:03

【编程珠玑】读书笔记 时空开销模型

  分析算法的好坏,一般从两个角度进行,时间复杂度与空间复杂度,通过理论的分析,可以得到这两个参数,但能不能得到实际代码具体的运行呢?

  书中给出了空间、时间开销模型,用于分析代码的空间、时间开销,可以解决这个问题。下面给出具体的时空开销模型代码。


空间开销模型

模型写的很好,直接拿过来,完整代码见下方。

运行结果可能依系统而不同,此处给出我的环境:win7 32 位机+VS2010。

注意代码中的斜杠为续行符。

完整代码:

 1 /* Copyright (C) 1999 Lucent Technologies */
 2 /* From 'Programming Pearls' by Jon Bentley */
 3 
 4 /* spacemod.cpp -- simple model for C++ space */
 5 
 6 #include <iostream>
 7 using namespace std;
 8 
 9 #define MEASURE(T, text)                    
10 {                                            
11     cout << text << "	";                    
12     cout << sizeof(T) << "	";                
13     int lastp = 0;                            
14     for (int i = 0; i < 11; i++)            
15     {                                        
16         T *p = new T;                        
17         int thisp = (int) p;                
18         if (lastp != 0)                        
19         cout << " " << thisp - lastp;        
20         lastp = thisp;                        
21     }                                        
22     cout << "
";                            
23 }
24 
25 // Must use macros; templates give funny answers
26 
27 template <class T>
28 void measure(char *text)
29 {    
30     cout << " measure: " << text << "	";
31     cout << sizeof(T) << "
";
32 }
33 
34 struct structc { char c; };
35 struct structic { int i; char c; };
36 struct structip { int i; structip *p; };
37 struct structdc { double d; char c; };
38 struct structcd { char c; double d; };
39 struct structcdc { char c1; double d; char c2; };
40 struct structiii { int i1; int i2; int i3; };
41 struct structiic { int i1; int i2; char c; };
42 struct structc12 { char c[12]; };
43 struct structc13 { char c[13]; };
44 struct structc28 { char c[28]; };
45 struct structc29 { char c[29]; };
46 struct structc44 { char c[44]; };
47 struct structc45 { char c[45]; };
48 struct structc60 { char c[60]; };
49 struct structc61 { char c[61]; };
50 
51 int main()
52 {    
53     cout << "Raw sizeof";
54     cout << "
sizeof(char)="     << sizeof(char);    
55     cout << "  sizeof(short)="    << sizeof(short);
56     cout << "  sizeof(int)="      << sizeof(int);
57     cout << "
sizeof(float)="    << sizeof(float);
58     cout << "  sizeof(struct *)=" << sizeof(structc *);
59     cout << "  sizeof(long)="     << sizeof(long);
60     cout << "
sizeof(double)="   << sizeof(double);
61 
62     cout << "

MEASURE macro
";
63 
64     MEASURE(int, "int");
65     MEASURE(structc, "structc");
66     MEASURE(structic, "structic");
67     MEASURE(structip, "structip");
68     MEASURE(structdc, "structdc");
69     MEASURE(structcd, "structcd");
70     MEASURE(structcdc, "structcdc");
71     MEASURE(structiii, "structiii");
72     MEASURE(structiic, "structiic");
73     MEASURE(structc12, "structc12");
74     MEASURE(structc13, "structc13");
75     MEASURE(structc28, "structc28");
76     MEASURE(structc29, "structc29");
77     MEASURE(structc44, "structc44");
78     MEASURE(structc45, "structc45");
79     MEASURE(structc60, "structc60");
80     MEASURE(structc61, "structc61");
81 
82     cout << "
measure template (strange results)
";
83     // Uncomment below lines to see answers change
84     measure<int>("int");
85     measure<structc>("structc");
86     measure<structic>("structic");
87 
88     return 0;
89 }

在我的机子上,运行结果如下:

(可以看到,该运行结果与书中给出的结果不同,但是同样反映了一个问题,就是用new运算符分配空间时,会有较大的额外开销,对下面的测试该开销在40字节左右)

Raw sizeof
sizeof(char)=1  sizeof(short)=2  sizeof(int)=4
sizeof(float)=4  sizeof(struct *)=4  sizeof(long)=4
sizeof(double)=8

MEASURE macro
int     4        48 96 48 48 48 48 48 48 48 48
structc 1        48 48 48 48 48 48 48 48 48 48
structic        8        56 56 56 19312 56 80 56 56 56 56
structip        8        56 56 56 56 56 56 56 56 56 56
structdc        16       64 64 64 64 88 64 64 64 64 64
structcd        16       64 64 64 64 64 64 64 64 64 64
structcdc       24       72 72 72 72 72 72 72 72 72 72
structiii       12       56 56 56 56 56 56 56 56 56 56
structiic       12       56 56 56 56 56 56 56 56 4504 56
structc12       12       56 56 56 56 56 56 56 56 56 56
structc13       13       64 64 64 64 64 64 64 64 64 64
structc28       28       72 72 72 72 72 72 72 72 72 72
structc29       29       80 80 80 80 80 80 80 104 80 80
structc44       44       88 88 88 88 88 88 88 88 88 88
structc45       45       96 96 96 96 96 96 96 96 96 96
structc60       60       104 104 104 104 104 104 104 104 104 104
structc61       61       112 112 112 112 112 112 112 112 112 112

measure template (strange results)
 measure: int   4
 measure: structc       1
 measure: structic      8
请按任意键继续. . .

时间开销模型

通过clock()函数进行计时,测试每个操作的平均时间,clock(),关于该函数的详细介绍,参见:http://www.cnblogs.com/youngforever/articles/3182876.html

用宏定义而不用模板的原因:???

完整代码:

  1 /* Copyright (C) 1999 Lucent Technologies */
  2 /* From 'Programming Pearls' by Jon Bentley */
  3 
  4 /* timemod.c -- Produce table of C run time costs */
  5 
  6 #include <stdio.h>
  7 #include <time.h>
  8 #include <stdlib.h>
  9 #include <math.h>
 10 
 11 #define MAXN 100000
 12 
 13 int x[MAXN];
 14 int startn = 5000;
 15 int n;
 16 
 17 /* FUNCTIONS TO BE TIMED */
 18 
 19 int intcmp(int *i, int *j)
 20 {   
 21     return *i - *j; 
 22 }
 23 
 24 #define swapmac(i, j) { t = x[i]; x[i] = x[j]; x[j] = t; }
 25 
 26 void swapfunc(int i, int j)
 27 { 
 28     int t = x[i];
 29     x[i] = x[j];
 30     x[j] = t;
 31 }
 32 
 33 #define maxmac(a, b) ((a) > (b) ? (a) : (b))
 34 
 35 int maxfunc(int a, int b)
 36 {    
 37     return a > b ? a : b; 
 38 }
 39 
 40 
 41 /* WORKHORSE */
 42 
 43 #define T(s) printf("%s (n=%d)
", s, n);
 44 
 45 #define TRIALS 5
 46 
 47 //必须加续行符,因为是宏定义而不是语句
 48 
 49 #define M(op)    {                        
 50     printf(" %-22s", #op);                
 51     k = 0;                                
 52     timesum = 0;                        
 53     for (ex = 0; ex < TRIALS; ex++)        
 54     {                                    
 55         start = clock();                
 56         for (i = 1; i <= n; i++)        
 57         {                                
 58             fi = (float) i;                
 59             for (j = 1; j <= n; j++)    
 60             {                            
 61                 op;                        
 62             }                            
 63         }                                
 64         t = clock()-start;                
 65         printf("%6d", t);                
 66         timesum += t;                    
 67     }                                    
 68     nans = 1e9 * timesum / ((double)    
 69     n*n * TRIALS * CLOCKS_PER_SEC);        
 70     printf("%8.0f
", nans);            
 71 } //此处大括号后面加不加分号都可以,因为主函数在使用该宏时如M(k++); 已经加了分号,再加一个分号,只是会当做多了一个空语句而已
 72 
 73 int main()
 74 {   
 75     int i, j, k;
 76     float fi, fj, fk;
 77     int t, ex, timesum, start, globalstart;
 78     double nans;
 79 
 80     globalstart = clock();
 81 
 82     for (i = 0; i < n; i++)  //此处n并没有初始化,就使用,不会出错吗?n为全局变量,在C++中会初始化为0,所以此时n为0
 83         x[i] = rand();
 84 
 85     n = startn;
 86 
 87     printf("C Time Cost Model, n=%d
", n);
 88 
 89     T("Integer Arithmetic");
 90     M({});
 91     M(k++);
 92     M(k = i + j);
 93     M(k = i - j);
 94     M(k = i * j);
 95     M(k = i / j);
 96     M(k = i % j);
 97     M(k = i & j);
 98     M(k = i | j);
 99 
100     T("Floating Point Arithmetic");
101     M(fj=j;);
102     M(fj=j; fk = fi + fj;);
103     M(fj=j; fk = fi - fj;);
104     M(fj=j; fk = fi * fj;);
105     M(fj=j; fk = fi / fj;);
106 
107     T("Array Operations");
108     M(k = i + j);
109     M(k = x[i] + j);
110     M(k = i + x[j]);
111     M(k = x[i] + x[j]);
112 
113     T("Comparisons");
114     M(if (i < j) k++);
115     M(if (x[i] < x[j]) k++);
116 
117     T("Array Comparisons and Swaps");
118     M(k = (x[i]<x[k]) ? -1:1);
119     M(k = intcmp(x+i, x+j));
120     M(swapmac(i, j));
121     M(swapfunc(i, j));
122 
123     T("Max Function, Macro and Inline");
124     M(k = (i > j) ? i : j);
125     M(k = maxmac(i, j));
126     M(k = maxfunc(i, j));
127     n = startn / 5;
128 
129     T("Math Functions");
130     M(fk = j+fi;);
131     M(k = rand(););
132     M(fk = sqrt(j+fi));
133     M(fk = sin(j+fi));
134     M(fk = sinh(j+fi));
135     M(fk = asin(j+fi));
136     M(fk = cos(j+fi));
137     M(fk = tan(j+fi));
138 
139     n = startn / 10;
140     T("Memory Allocation");
141 
142     M(free(malloc(16)););
143     M(free(malloc(100)););
144     M(free(malloc(2000)););
145 
146     /* Possible additions: input, output, malloc */
147     printf("  Secs: %4.2f
",
148         ((double) clock()-globalstart)
149         / CLOCKS_PER_SEC);
150 
151     return 0;
152 }

  对每一种运算都利用宏定义 M(op),进行了TRIALS次测试,每次测试包含n*n次op操作,在M(op)中打印出了每次TRAIL的运行时间(下面运行结果中的2~6列),在最后给出了op操作每次执行的平均时间(下面运行结果中的最后一列)。

运行结果:

C Time Cost Model, n=5000
Integer Arithmetic (n=5000)
 {}                       204   217   228   180   174       8
 k++                      127   126   127   127   121       5
 k = i + j                139   138   132   137   135       5
 k = i - j                144   133   259   149   145       7
 k = i * j                183   162   143   149   138       6
 k = i / j                204   210   207   205   197       8
 k = i % j                221   199   189   191   191       8
 k = i & j                131   118   112   112   112       5
 k = i | j                140   138   125   117   113       5
Floating Point Arithmetic (n=5000)
 fj=j;                    123   121   117   118   120       5
 fj=j; fk = fi + fj;      151   167   153   162   149       6
 fj=j; fk = fi - fj;      155   168   171   160   165       7
 fj=j; fk = fi * fj;      158   159   168   166   156       6
 fj=j; fk = fi / fj;      352   356   354   354   355      14
Array Operations (n=5000)
 k = i + j                114   119   115   132   113       5
 k = x[i] + j             132   138   141   139   119       5
 k = i + x[j]             128   125   129   127   124       5
 k = x[i] + x[j]          145   156   145   137   145       6
Comparisons (n=5000)
 if (i < j) k++           100   112   121   122   129       5
 if (x[i] < x[j]) k++     149   161   140   144   147       6
Array Comparisons and Swaps (n=5000)
 k = (x[i]<x[k]) ? -1:1   192   197   197   191   200       8
 k = intcmp(x+i, x+j)    1245   987   896   814   766      38
 swapmac(i, j)            122   123   125   123   121       5
 swapfunc(i, j)           808   798   795   797   798      32
Max Function, Macro and Inline (n=5000)
 k = (i > j) ? i : j       90    89    90    93    90       4
 k = maxmac(i, j)          90    91    90    95    90       4
 k = maxfunc(i, j)        772   774   779   777   771      31
Math Functions (n=1000)
 fk = j+fi;                 3     2     2     3     3       3
 k = rand();               32    36    32    32    32      33
 fk = sqrt(j+fi)           80    72    72    72    71      73
 fk = sin(j+fi)            89    89    89    89    89      89
 fk = sinh(j+fi)          489   485   488   486   494     488
 fk = asin(j+fi)          130   133   139   137   137     135
 fk = cos(j+fi)           100    91    94    89    89      93
 fk = tan(j+fi)           102   100   106    98    99     101
Memory Allocation (n=500)
 free(malloc(16));        144   139   139   142   162     581
 free(malloc(100));       189   143   172   142   158     643
 free(malloc(2000));      165   178   168   175   163     679
  Secs: 38.56
请按任意键继续. . .
原文地址:https://www.cnblogs.com/youngforever/p/3182890.html