| 1 | == Project implementation details == |
| 2 | |
| 3 | The parallel version of the decision tree inference process is based on the original |
| 4 | C4.5 (revision 8) implementation by Quinlan. |
| 5 | |
| 6 | The algorithm is written in C and the parallel version was created using OpenMP. |
| 7 | The functions the algorithm uses are divided amongst several source files each having |
| 8 | a representative name for the type of functions it contains. |
| 9 | |
| 10 | Thus we have the following structure: |
| 11 | - c4.5.c - contains main function |
| 12 | - besttree.c - functions that implement different tree forming modes: |
| 13 | - single tree in batch mode (all examples at once) |
| 14 | - window mode - get samples of increasing window size from original data; compute several trees; select the best one |
| 15 | - build.c - contains function that implement the basic structure of the tree forming algorithm |
| 16 | - discr.c - contains functions that build a tree with discrete (nominal) attributes |
| 17 | - contin.c - contains functions that build that also contains continuous (numerical) attributes |
| 18 | - info.c - contains functions that compute auxiliary information such as information gain of a certain attribute |
| 19 | - getnames.c, getdata.c - files that implement functions for reading input data from text files with a specified format. |
| 20 | |
| 21 | The Src folder also contains other files, but those are irrelevant with regard to the tree inference process. |
| 22 | |
| 23 | '''Main modifications to the serial version''' |
| 24 | |
| 25 | Our test dataset (poker-hand) is composed of discrete attributes only so the files that were modified to obtain the |
| 26 | parallel functionality are the following: |
| 27 | - c4.5.c |
| 28 | - besttree.c |
| 29 | - build.c |
| 30 | - discr.c |
| 31 | |
| 32 | Mainly, all modifications include the addition of a modified version of the existing functions. |
| 33 | The new functions, thus provide an alternative instruction flow which allows for parallelism. |
| 34 | The modifications are as follows: |
| 35 | |
| 36 | - in c4.5.c - the if statement that determines whether batch mode is being used now calls OneTree_discr instead of OneTree |
| 37 | - in besttree.c - OneTree_discr calls FormTree_discr |
| 38 | - in build.c - functionality has been added to the InitialiseTreeData function |
| 39 | |
| 40 | {{{ |
| 41 | nrThreads = omp_get_max_threads(); |
| 42 | Freq_discr = (ItemCount***) calloc (nrThreads, sizeof(ItemCount**));[[BR]] |
| 43 | ValFreq_discr = (ItemCount**) calloc (nrThreads, sizeof(ItemCount*));[[BR]] |
| 44 | UnknownRate_discr = (float**) calloc (nrThreads, sizeof(float*));[[BR]] |
| 45 | for(i = 0; i < nrThreads; i++){[[BR]] |
| 46 | Freq_discr[i] = (ItemCount **) calloc(MaxDiscrVal + 1, sizeof(ItemCount *));[[BR]] |
| 47 | ForEach(v, 0, MaxDiscrVal) {[[BR]] |
| 48 | Freq_discr[i][v] = (ItemCount *) calloc(MaxClass + 1, sizeof(ItemCount));[[BR]] |
| 49 | }[[BR]] |
| 50 | |
| 51 | ValFreq_discr[i] = (ItemCount *) calloc(MaxDiscrVal + 1, sizeof(ItemCount)); |
| 52 | UnknownRate_discr[i] = (float *) calloc(MaxAtt + 1, sizeof(float)); |
| 53 | } |
| 54 | }}} |
| 55 | |
| 56 | - auxiliary work structures are allocated for the maximal number of threads possible. |
| 57 | - thus every thread will have it's own heap allocated space to perform necessary computations |
| 58 | whithout entering any race conditions (these structures need to be private to every thread). |
| 59 | |
| 60 | - in build.c - the FormTree_discr function contains the #pragma omp parallel for construct that computes attribute gains in parllel.[[BR]] |
| 61 | The directive also has a reduction clause on two variables: AvGain, Possible. The variables are necessary to compute the average gain of the attribute.[[BR]] |
| 62 | The FormTree_discr function calls EvalAttributeDisc_discr() for every attribute in the for loop.[[BR]] |
| 63 | This method is similar to the Synchronous Tree Construction approach described in theory, where the team of threads cooperates to expand (compute the best attribute) the tree at each step. |
| 64 | |
| 65 | - in discr.c - the EvalAttributeDisc_discr function evaluates each attribute. In discr.c each function ending in _discr is our modified version of the original function. The modifications are minor and mostly only concern the number and type of parameters passed to the function. |
| 66 | |
| 67 | '''Project Results''' |
| 68 | |
| 69 | |
| 70 | As our tests show, the dataset used to test the algorithm is not that well suited to parallelization because the amount |
| 71 | of work done for attribute gain computation is not very big. |
| 72 | Tests show that in the serial version the inclusive time spent in FormTree equal 7.202 seconds. |
| 73 | |
| 74 | |
| 75 | In the parallel version (with 2 threads) the time drops to about 4.8 seconds. Yet because the algorithm uses recursive calls |
| 76 | to the FormTree function, the thread team is started at each recursive call, and the overhead caused by this + some necessary |
| 77 | thread synchronizations compensate for the gain in execution speed, such that overall, there is no clearly noticeable speedup. |