360 likes | 490 Views
Nested classes, namespaces נתעסק בעיקר במבנה הפנימי של המידע ששמור. Nesting Classes. Stack objects use an embedded data structure for storing data We have usually defined these classes publicly Stacks can store any type of data They should be a template
E N D
Nested classes, namespacesנתעסק בעיקר במבנה הפנימי של המידע ששמור
Nesting Classes • Stack objects use an embedded data structure for storing data • We have usually defined these classes publicly • Stacks can store any type of data • They should be a template • Data structure used for storing data must also be a template then • Embed the storage data structure as a nested class • Get templatized for free • Hides data structure • בשונה מג'אבה, שם לא הייתה גישה למחלקות פנימיות, כאן יש אפשרות, ע"י הצהרה של פרייבט ופאבליק כשם שיודגם בשקף הבא.
Nested Node Class template< typename T > class Stack { private: class Node { public:כלפי סטאק זה פומבי אבל מחוצה לו, בגלל שנואוד פרייבט – אי אפשר לראות Node(T& item) : pItem(&item), pNext(NULL) {} T* pItem; uses the template parameter from Stack Node* pNext; }; Node* pHead; … };
Using Nested Classes • Nested classes obey outer class’s access specification • If private, can’t be used outside the class • Used internally the same as if it was globally declared template< typename T> void Stack<T>::push(T& item) { Node* pNode = new Node(item); // no special syntax req’d pNode->pNext = pHead; pHead = pNode; }
Defining Nested Class Member Functions • Fully specify name of nested class functions template<typename T> void Stack<T>::Node::func( void ) { … }
Java inner classes vs. C++ nested classes • C++, nesting a class is an aid to: • name hiding • code organization • No running time relations between the nested (inner) and the outer class. • מחלקה פנימית ומחלקה החיצונית לה נראות למחשב כשתי מחלקות נפרדות, עם הגבלות על פרייבט וכדו', לזו הפנימית. זה אך ורק עוזר לארגון ולעיצוב התוכנית אבל אין לזה שום משמעות פונקציונלית • Java inner classes is an aid to: • Running time relations between the nested (inner) and the outer class (callbacks, GUI implementation). בסי פיפי זה לא ככה. נואוד, למשל, לא יכול להכיר אף טיפוס מסוג סטאק, אבל הוא כן יכול להכיר את המשתנים הפנימיים שלו
Java inner classes vs. C++ nested classes • How we achieve running time relations in C++? • Pointers to members of the outer class. • Java packages provide better mechanism for name hiding, What the equivalent in C++? בסי דיברנו על ספריות, אבל זה לא לגמרי כמו פקג'. אין שם מיוחד לוקטור ששייך לסט"ד למשל, זה פשוט וקטור. נרצה לספק מנגנון שבו כן נוכל להבחין בין שני סוגים של וקטורים שנמצאים בשתי ספריות שונות, למשל. בסיפיפי יש מנגנון כזה, שאולי חלק מכם כבר השתמשו בו בלי לדע
C++ Namespaces • A mechanism for logically grouping declarations and definitions into a common declarative region
C++ Namespaces • The contents of the namespace can be accessed by code inside or outside the namespace • Use the scope resolution operator to access elements from outside the namespace • Alternatively, the usingdeclaration allows the names of the elements to be used directly • יש שתי אפשרויות לשימוש ביוזינג: • using std::vector; • using namespace std; • מה הבעיה בשימוש הזה? שאם יש שני סוגי וקטורים, שאחד בסט"ד והשני לא, רק הזה שבסט"ד יופעל • להשתמש בזה רק בקבצים פנימיים שאנשים לא עושים להם אינקלוד
C++ Namespaces • Creating a namespace namespace smallNamespace { int count = 0; void abc(); } //end smallNamespace • Using a namespace חייבים לעשות אינקלוד כמובן usingnamespace smallNamespace; count +=1; abc();
C++ Namespaces • Items declared in the C++ Standard Library are declared in the std namespace • C++ include files for several functions are in the std namespace • To include input and output functions from the C++ library, write include <iostream> usingnamespace std;
using namespace #include <iostream> ... std::string question = “How do I prevent RSI?”; std::cout << question << std::endl; using namespace std; string answer = “Type less.”; cout << answer << endl; But, not in header files!
Namespaces vs nested classes • No run-time differences. • שניהם מנגנונים שנועדו לעזור במבנה ותו לא • We can declare the same namespace in many files (std for example) • Use nested classes for real private data (nodes, iterators) • Use namespaces for logic relations such as math libraries…
Performance We often worry about program performance • Total running time • Response time (interactive applications) • Memory usage • Disk usage • … How do we deal with performance?
Two Views “Super Optimizer” • Worries about every little piece of code • Spends extra effort to “squeeze” performance “Relaxed” • Why worry today if tomorrow’s computer is going to be twice as fast?
To Optimize or Not? Pros: • Faster more efficient programs Cons: • Hard to maintain • Complex data structure • Relies on machine/system specific features
Rules Optimization 1st Rule: Don’t! Most effort on “optimization” leads to • Introduction of bugs • Hard to maintain data structures • “Improvements” that are not helping performance 2nd Rule: Think before you jump
Writing for Performance Usually, we do not need to optimize • We do need reasonable performance Guidelines • Focus on a design without unnecessary overhead • Use simplest & cleanest algorithms and data structures • Deal with real problems not with imaginary ones
Design Levels & Performances • Computer Program (system) design can be viewed at many levels • Each level has its own impact on performance
Design Level 0: Problem Definition • “Root of all evil” – bad problem specification • Does the specification take into account factors that influence the performance • Additional input • Proper goals • Desired accuracy
Design Level 1: System Structure • Decomposition into modules • Make sure each module has the right interface • “Back of the envelope” calculations • Ensure that overall performance can be achieved • Identify possible bottlenecks
Design Level 2:Data Structures and Algorithms • Choose right algorithms & data structures • For a large value of n, the difference between O(n), O(n log n) and O(n2) can be huge • Faster computer can only result in constant time improvement 1e+10 1e+09 1e+08 1e+07 1e+06 100000 10000 1000 100 10 10 100 1000 10000 100000
Design Level 3: Code • Careful consideration of the cost of individual instructions can lead to faster code • Might depend on the particular compiler and machine architecture • Such optimizations are done in a targeted manner • Only for crucial procedures
Design Level 4: System • Choice of compiler & hardware • Can lead to 2-10 fold change in performance • Understand the use of the code optimization in the compiler
Optimization steps Code tuning on specific hardware: • Use float (32 bits) instead of double (64 bits) • 98% of CPU time in one function. Rewrote this function in assembly language System: • Buy a fancier floating point processor ($$$) Savings: • 10 fold speedup
Optimization steps • To achieve large speedup work on all levels • Many small speedup combine to a large one • Algorithm/Data structure change can lead to biggest improvement • Get it right first, then get it faster • To evaluate approximations, must have access to correct versions • 90-10 rule: Most of the time is taken by small fraction of the code • Evaluate system before rushing to tweak code
Profiling a Program • How do we find out where the program is spending its time? In Linux: • Compile program with –pg flag • Links special code in entry/exit to each function • Run program • Special code record information in file gmon.out • Analyze results • gprof <ProgramName>
How to Read a Profile - “flat profile” % cumulative self self total time seconds seconds calls ms/call ms/call name 99.57 49.16 49.16 71988 0.68 0.68 nodeAccessValue… 0.20 49.26 0.10 83519 0.00 0.00 nodeSuccessorKey… 0.10 49.31 0.05 71989 0.00 0.00 readWord (void) 0.02 49.32 0.01 83519 0.00 0.00 getSuccessorKey… 0.02 49.33 0.01 71988 0.00 0.00 dictionaryHasWord… 0.02 49.34 0.01 71988 0.00 0.68 getAccessToValue… 0.02 49.35 0.01 71988 0.00 0.58 insert… 0.02 49.36 0.01 11530 0.00 0.00 createNode… 0.02 49.37 0.01 11529 0.00 0.00 nodeInsert… 0.00 49.37 0.00 11530 0.00 0.00 insert… 0.00 49.37 0.00 1 0.00 0.00 createDictionary… 0.00 49.37 0.00 1 0.00 0.00 createTree(void) 0.00 49.37 0.00 1 0.00 7890.53 printDictionary
How to Read a Profile “Call graph” index % time self children called name <spontaneous> [1] 100.0 0.00 49.37 main [1] 0.01 41.42 71988/71988 insert(Dictionary *, char const *) [4] 0.00 7.89 1/1 printDictionary(Dictionary const *) [5] 0.05 0.00 71989/71989 readWord(void) [9] 0.00 0.00 1/1 createDictionary(void) [13] ----------------------------------------------- 0.00 7.87 11530/71988 printDictionary(Dictionary const *) [5] 0.01 41.29 60458/71988 insert(Dictionary *, char const *) [4] [2] 99.6 0.01 49.16 71988 getAccessToValue(StrBinTree const *, char const *) [2] 49.16 0.00 71988/71988 nodeAccessValue(StrBinTreeNode *, char const *) [3] ----------------------------------------------- 575798514 nodeAccessValue(StrBinTreeNode *, char const *) [3] 49.16 0.00 71988/71988 getAccessToValue(StrBinTree const *, char const *) [2] [3] 99.6 49.16 0.00 71988+575798514 nodeAccessValue(StrBinTreeNode *, char const *) [3] 575798514 nodeAccessValue(StrBinTreeNode *, char const *) [3]
How to Read a Profile 0.01 41.42 71988/71988 main [1] [4] 83.9 0.01 41.42 71988 insert(Dictionary *, char const *) [4] 0.01 41.29 60458/71988 getAccessToValue(StrBinTree const *, char const *) [2] 0.01 0.09 71988/71988 dictionaryHasWord(Dictionary const *, char const *) [7] 0.00 0.02 11530/11530 insert(StrBinTree *, char const *, int) [10] ----------------------------------------------- 0.00 7.89 1/1 main [1] [5] 16.0 0.00 7.89 1 printDictionary(Dictionary const *) [5] 0.00 7.87 11530/71988 getAccessToValue(StrBinTree const *, char const *) [2] 0.00 0.01 11531/83519 getSuccessorKey(StrBinTree const *, char const *, int *) [6] ----------------------------------------------- 0.00 0.01 11531/83519 printDictionary(Dictionary const *) [5] 0.01 0.09 71988/83519 dictionaryHasWord(Dictionary const *, char const *) [7] [6] 0.2 0.01 0.10 83519 getSuccessorKey(StrBinTree const *, char const *, int *) [6] 0.10 0.00 83519/83519 nodeSuccessorKey(StrBinTreeNode *, char const *, int *) [8] ----------------------------------------------- …
Case Study II: Code Tuning Old tricks: change double to float • Less of a difference with modern computers Rewrite loops: • Move ifs outside loops • Make end conditions clears Additional speed up of 10% Overall speedup: 6-fold (3hrs 30 minutes)
Code Tuning void f1( vector<int>& vec, int m ) { vector<int>::iterator i; int j = 0; for( i = vec.begin(); i != vec.end() - m ; i++ ) j += *i; } void f2( vector<int>& vec, int m ) { vector<int>::iterator i, e = vec.end() - m; int j = 0; for( i = vec.begin(); i != e; i++ ) j += *i; } void f3( vector<int>& vec, int m ) { int i, j = 0, n = vec.size() - m; for( i = 0; i < n ; i++ ) j += vec[i]; }
% cumulative self self total time seconds seconds calls us/call us/call name 46.88 5.48 5.48 1000000 5.48 5.48 f1 37.81 9.90 4.42 1000000 4.42 4.42 f2 14.88 11.64 1.74 1000000 1.74 1.74 f3 Code Tuning void f1( vector<int>& vec, int m ) { vector<int>::iterator i; int j = 0; for( i = vec.begin(); i != vec.end() - m ; i++ ) j += *i; } void f2( vector<int>& vec, int m ) { vector<int>::iterator i, e = vec.end() - m; int j = 0; for( i = vec.begin(); i != e; i++ ) j += *i; } void f3( vector<int>& vec, int m ) { int i, j = 0, n = vec.size() - m; for( i = 0; i < n ; i++ ) j += vec[i]; }
Code Tuning • Time consuming • Can hurt readability of code • Usually system specific • Instructions that are efficient on one machine + compiler might be inefficient on another • With the availability of “smart” optimizing compilers, this practice can be dangerous
I Feel The Need… the Need for Speed --- Summary • Identify the right level for optimization • Use better algorithms & data structures • Use compiler optimization (g++ -o…) • Tune crucial “bottleneck” code • Don’t optimize what does not matter • Don’t optimize too soon • Use tools: • Profilers • Established benchmark cases