X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=lttv%2Flttv%2Fsync%2Fsync_chain.c;h=a34a93b12dbcfe96745db6c10a680dbcc73590de;hb=b2da0724a95cdb911c07640268b65bd9c5b92010;hp=08cc3cb33b2b8f137e993b9eb7214fa548079091;hpb=0a87ec9a018cc9731ce3b04309eaa4dcc77df6d2;p=lttv.git diff --git a/lttv/lttv/sync/sync_chain.c b/lttv/lttv/sync/sync_chain.c index 08cc3cb3..a34a93b1 100644 --- a/lttv/lttv/sync/sync_chain.c +++ b/lttv/lttv/sync/sync_chain.c @@ -15,14 +15,11 @@ * along with this program. If not, see . */ -#define _ISOC99_SOURCE - #ifdef HAVE_CONFIG_H #include #endif #include -#include #include #include #include @@ -33,16 +30,10 @@ GQueue processingModules= G_QUEUE_INIT; GQueue matchingModules= G_QUEUE_INIT; GQueue analysisModules= G_QUEUE_INIT; +GQueue reductionModules= G_QUEUE_INIT; GQueue moduleOptions= G_QUEUE_INIT; -static void floydWarshall(AllFactors* const allFactors, double*** const - distances, unsigned int*** const predecessors); -static void getFactors(AllFactors* const allFactors, unsigned int** const - predecessors, unsigned int* const references, const unsigned int traceNum, - Factors* const factors); - - /* * Call the statistics function of each module of a sync chain * @@ -55,14 +46,21 @@ void printStats(SyncState* const syncState) { syncState->processingModule->printProcessingStats(syncState); } - if (syncState->matchingModule->printMatchingStats != NULL) + if (syncState->matchingModule != NULL && + syncState->matchingModule->printMatchingStats != NULL) { syncState->matchingModule->printMatchingStats(syncState); } - if (syncState->analysisModule->printAnalysisStats != NULL) + if (syncState->analysisModule != NULL && + syncState->analysisModule->printAnalysisStats != NULL) { syncState->analysisModule->printAnalysisStats(syncState); } + if (syncState->reductionModule != NULL && + syncState->reductionModule->printReductionStats != NULL) + { + syncState->reductionModule->printReductionStats(syncState); + } } @@ -88,304 +86,6 @@ void timeDiff(struct timeval* const end, const struct timeval* const start) } -/* - * Calculate a resulting offset and drift for each trace. - * - * Traces are assembled in groups. A group is an "island" of nodes/traces that - * exchanged messages. A reference is determined for each group by using a - * shortest path search based on the accuracy of the approximation. This also - * forms a tree of the best way to relate each node's clock to the reference's - * based on the accuracy. Sometimes it may be necessary or advantageous to - * propagate the factors through intermediary clocks. Resulting factors for - * each trace are determined based on this tree. - * - * This part was not the focus of my research. The algorithm used here is - * inexact in some ways: - * 1) The reference used may not actually be the best one to use. This is - * because the accuracy is not corrected based on the drift during the - * shortest path search. - * 2) The min and max factors are not propagated and are no longer valid. - * 3) Approximations of different types (ACCURATE and APPROXIMATE) are compared - * together. The "accuracy" parameters of these have different meanings and - * are not readily comparable. - * - * Nevertheless, the result is satisfactory. You just can't tell "how much" it - * is. - * - * Two alternative (and subtly different) ways of propagating factors to - * preserve min and max boundaries have been proposed, see: - * [Duda, A., Harrus, G., Haddad, Y., and Bernard, G.: Estimating global time - * in distributed systems, Proc. 7th Int. Conf. on Distributed Computing - * Systems, Berlin, volume 18, 1987] p.304 - * - * [Jezequel, J.M., and Jard, C.: Building a global clock for observing - * computations in distributed memory parallel computers, Concurrency: - * Practice and Experience 8(1), volume 8, John Wiley & Sons, Ltd Chichester, - * 1996, 32] Section 5; which is mostly the same as - * [Jezequel, J.M.: Building a global time on parallel machines, Proceedings - * of the 3rd International Workshop on Distributed Algorithms, LNCS, volume - * 392, 136–147, 1989] Section 5 - * - * Args: - * allFactors: offset and drift between each pair of traces - * - * Returns: - * Factors[traceNb] synchronization factors for each trace - */ -GArray* reduceFactors(AllFactors* const allFactors) -{ - GArray* factors; - double** distances; - unsigned int** predecessors; - double* distanceSums; - unsigned int* references; - unsigned int i, j; - const unsigned int traceNb= allFactors->traceNb; - - // Solve the all-pairs shortest path problem using the Floyd-Warshall - // algorithm - floydWarshall(allFactors, &distances, &predecessors); - - /* Find the reference for each node - * - * First calculate, for each node, the sum of the distances to each other - * node it can reach. - * - * Then, go through each "island" of traces to find the trace that has the - * lowest distance sum. Assign this trace as the reference to each trace - * of the island. - */ - distanceSums= malloc(traceNb * sizeof(double)); - for (i= 0; i < traceNb; i++) - { - distanceSums[i]= 0.; - for (j= 0; j < traceNb; j++) - { - distanceSums[i]+= distances[i][j]; - } - } - - references= malloc(traceNb * sizeof(unsigned int)); - for (i= 0; i < traceNb; i++) - { - references[i]= UINT_MAX; - } - for (i= 0; i < traceNb; i++) - { - if (references[i] == UINT_MAX) - { - unsigned int reference; - double distanceSumMin; - - // A node is its own reference by default - reference= i; - distanceSumMin= INFINITY; - for (j= 0; j < traceNb; j++) - { - if (distances[i][j] != INFINITY && distanceSums[j] < - distanceSumMin) - { - reference= j; - distanceSumMin= distanceSums[j]; - } - } - for (j= 0; j < traceNb; j++) - { - if (distances[i][j] != INFINITY) - { - references[j]= reference; - } - } - } - } - - for (i= 0; i < traceNb; i++) - { - free(distances[i]); - } - free(distances); - free(distanceSums); - - /* For each trace, calculate the factors based on their corresponding - * tree. The tree is rooted at the reference and the shortest path to each - * other nodes are the branches. - */ - factors= g_array_sized_new(FALSE, FALSE, sizeof(Factors), - traceNb); - g_array_set_size(factors, traceNb); - for (i= 0; i < traceNb; i++) - { - getFactors(allFactors, predecessors, references, i, &g_array_index(factors, - Factors, i)); - } - - for (i= 0; i < traceNb; i++) - { - free(predecessors[i]); - } - free(predecessors); - free(references); - - return factors; -} - - -/* - * Perform an all-source shortest path search using the Floyd-Warshall - * algorithm. - * - * The algorithm is implemented accoding to the description here: - * http://web.mit.edu/urban_or_book/www/book/chapter6/6.2.2.html - * - * Args: - * allFactors: offset and drift between each pair of traces - * distances: resulting matrix of the length of the shortest path between - * two nodes. If there is no path between two nodes, the - * length is INFINITY - * predecessors: resulting matrix of each node's predecessor on the shortest - * path between two nodes - */ -static void floydWarshall(AllFactors* const allFactors, double*** const - distances, unsigned int*** const predecessors) -{ - unsigned int i, j, k; - const unsigned int traceNb= allFactors->traceNb; - PairFactors** const pairFactors= allFactors->pairFactors; - - // Setup initial conditions - *distances= malloc(traceNb * sizeof(double*)); - *predecessors= malloc(traceNb * sizeof(unsigned int*)); - for (i= 0; i < traceNb; i++) - { - (*distances)[i]= malloc(traceNb * sizeof(double)); - for (j= 0; j < traceNb; j++) - { - if (i == j) - { - g_assert(pairFactors[i][j].type == EXACT); - - (*distances)[i][j]= 0.; - } - else - { - if (pairFactors[i][j].type == ACCURATE || - pairFactors[i][j].type == APPROXIMATE) - { - (*distances)[i][j]= pairFactors[i][j].accuracy; - } - else if (pairFactors[j][i].type == ACCURATE || - pairFactors[j][i].type == APPROXIMATE) - { - (*distances)[i][j]= pairFactors[j][i].accuracy; - } - else - { - (*distances)[i][j]= INFINITY; - } - } - } - - (*predecessors)[i]= malloc(traceNb * sizeof(unsigned int)); - for (j= 0; j < traceNb; j++) - { - if (i != j) - { - (*predecessors)[i][j]= i; - } - else - { - (*predecessors)[i][j]= UINT_MAX; - } - } - } - - // Run the iterations - for (k= 0; k < traceNb; k++) - { - for (i= 0; i < traceNb; i++) - { - for (j= 0; j < traceNb; j++) - { - double distanceMin; - - distanceMin= MIN((*distances)[i][j], (*distances)[i][k] + - (*distances)[k][j]); - - if (distanceMin != (*distances)[i][j]) - { - (*predecessors)[i][j]= (*predecessors)[k][j]; - } - - (*distances)[i][j]= distanceMin; - } - } - } -} - - -/* - * Cummulate the time correction factors to convert a node's time to its - * reference's time. - * This function recursively calls itself until it reaches the reference node. - * - * Args: - * allFactors: offset and drift between each pair of traces - * predecessors: matrix of each node's predecessor on the shortest - * path between two nodes - * references: reference node for each node - * traceNum: node for which to find the factors - * factors: resulting factors - */ -static void getFactors(AllFactors* const allFactors, unsigned int** const - predecessors, unsigned int* const references, const unsigned int traceNum, - Factors* const factors) -{ - unsigned int reference; - PairFactors** const pairFactors= allFactors->pairFactors; - - reference= references[traceNum]; - - if (reference == traceNum) - { - factors->offset= 0.; - factors->drift= 1.; - } - else - { - Factors previousVertexFactors; - - getFactors(allFactors, predecessors, references, - predecessors[reference][traceNum], &previousVertexFactors); - - /* Convert the time from traceNum to reference; - * pairFactors[row][col] converts the time from col to row, invert the - * factors as necessary */ - - if (pairFactors[reference][traceNum].approx != NULL) - { - factors->offset= previousVertexFactors.drift * - pairFactors[reference][traceNum].approx->offset + - previousVertexFactors.offset; - factors->drift= previousVertexFactors.drift * - pairFactors[reference][traceNum].approx->drift; - } - else if (pairFactors[traceNum][reference].approx != NULL) - { - factors->offset= previousVertexFactors.drift * (-1. * - pairFactors[traceNum][reference].approx->offset / - pairFactors[traceNum][reference].approx->drift) + - previousVertexFactors.offset; - factors->drift= previousVertexFactors.drift * (1. / - pairFactors[traceNum][reference].approx->drift); - } - else - { - g_assert_not_reached(); - } - } -} - - /* * A GCompareFunc for g_slist_find_custom() * @@ -455,6 +155,29 @@ gint gcfCompareAnalysis(gconstpointer a, gconstpointer b) } +/* + * A GCompareFunc for g_slist_find_custom() + * + * Args: + * a: ReductionModule*, element's data + * b: char*, user data to compare against + * + * Returns: + * 0 if the reduction module a's name is b + */ +gint gcfCompareReduction(gconstpointer a, gconstpointer b) +{ + const ReductionModule* reductionModule; + const char* name; + + reductionModule= (const ReductionModule*) a; + name= (const char*) b; + + return strncmp(reductionModule->name, name, strlen(reductionModule->name) + + 1); +} + + /* * A GFunc for g_queue_foreach() * @@ -469,3 +192,19 @@ void gfAppendAnalysisName(gpointer data, gpointer user_data) g_string_append((GString*) user_data, ((AnalysisModule*) data)->name); g_string_append((GString*) user_data, ", "); } + + +/* + * A GFunc for g_queue_foreach() + * + * Concatenate reduction module names. + * + * Args: + * data: ReductionModule* + * user_data: GString*, concatenated names + */ +void gfAppendReductionName(gpointer data, gpointer user_data) +{ + g_string_append((GString*) user_data, ((ReductionModule*) data)->name); + g_string_append((GString*) user_data, ", "); +}