X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttv%2Flttv%2Fsync%2Fevent_analysis_chull.c;h=154258e00effc5af9369dc13c1c036e2d999125a;hb=ab6edc6a1a55aefe52cfd9e610b5f21ee2029544;hp=1dc995b17da63a406b850cb317ce06d034837dac;hpb=8d7d16dd4f5f6ae09f556a9b0b477baaa93d468c;p=lttv.git diff --git a/lttv/lttv/sync/event_analysis_chull.c b/lttv/lttv/sync/event_analysis_chull.c index 1dc995b1..154258e0 100644 --- a/lttv/lttv/sync/event_analysis_chull.c +++ b/lttv/lttv/sync/event_analysis_chull.c @@ -1,19 +1,18 @@ /* This file is part of the Linux Trace Toolkit viewer - * Copyright (C) 2009 Benjamin Poirier + * Copyright (C) 2009, 2010 Benjamin Poirier * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation; + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or (at + * your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ #define _ISOC99_SOURCE @@ -22,10 +21,12 @@ #endif #include +#include #include #include #include #include +#include #include #include "sync_chain.h" @@ -33,24 +34,27 @@ #include "event_analysis_chull.h" -#ifndef g_info -#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) -#endif - - typedef enum { LOWER, UPPER } HullType; - typedef enum { MINIMUM, MAXIMUM } LineType; +#ifdef HAVE_LIBGLPK +struct LPAddRowInfo +{ + glp_prob* lp; + int boundType; + GArray* iArray, * jArray, * aArray; +}; +#endif + // Functions common to all analysis modules static void initAnalysisCHull(SyncState* const syncState); @@ -58,69 +62,91 @@ static void destroyAnalysisCHull(SyncState* const syncState); static void analyzeMessageCHull(SyncState* const syncState, Message* const message); -static GArray* finalizeAnalysisCHull(SyncState* const syncState); +static AllFactors* finalizeAnalysisCHull(SyncState* const syncState); static void printAnalysisStatsCHull(SyncState* const syncState); -static void writeAnalysisGraphsPlotsCHull(SyncState* const syncState, const - unsigned int i, const unsigned int j); +static void writeAnalysisTraceTraceForePlotsCHull(SyncState* const syncState, + const unsigned int i, const unsigned int j); // Functions specific to this module -static void registerAnalysisCHull() __attribute__((constructor (101))); - static void openGraphFiles(SyncState* const syncState); static void closeGraphFiles(SyncState* const syncState); static void writeGraphFiles(SyncState* const syncState); static void gfDumpHullToFile(gpointer data, gpointer userData); +AllFactors* calculateAllFactors(struct _SyncState* const syncState); +void calculateFactorsMiddle(PairFactors* const factors); +static Factors* calculateFactorsExact(GQueue* const cu, GQueue* const cl, const + LineType lineType) __attribute__((pure)); +static void calculateFactorsFallback(GQueue* const cr, GQueue* const cs, + PairFactors* const result); static void grahamScan(GQueue* const hull, Point* const newPoint, const HullType type); static int jointCmp(const Point* const p1, const Point* const p2, const Point* const p3) __attribute__((pure)); static double crossProductK(const Point const* p1, const Point const* p2, const Point const* p3, const Point const* p4) __attribute__((pure)); -static FactorsCHull** calculateAllFactors(SyncState* const syncState); -static Factors* calculateFactorsExact(GQueue* const cu, GQueue* const cl, const - LineType lineType) __attribute__((pure)); -static void calculateFactorsMiddle(FactorsCHull* factors); -static void calculateFactorsFallback(GQueue* const cr, GQueue* const cs, - FactorsCHull* const result); static double slope(const Point* const p1, const Point* const p2) __attribute__((pure)); static double intercept(const Point* const p1, const Point* const p2) __attribute__((pure)); -static GArray* reduceFactors(SyncState* const syncState, FactorsCHull** - allFactors); -static void freeAllFactors(const SyncState* const syncState, FactorsCHull** - const allFactors); static double verticalDistance(Point* p1, Point* p2, Point* const point) __attribute__((pure)); -static void floydWarshall(SyncState* const syncState, FactorsCHull** const - allFactors, double*** const distances, unsigned int*** const - predecessors); -static void getFactors(FactorsCHull** const allFactors, unsigned int** const - predecessors, unsigned int* const references, const unsigned int traceNum, - Factors* const factors); static void gfPointDestroy(gpointer data, gpointer userData); +// The next group of functions is only needed when computing synchronization +// accuracy. +#ifdef HAVE_LIBGLPK +static AllFactors* finalizeAnalysisCHullLP(SyncState* const syncState); +static void writeAnalysisTraceTimeBackPlotsCHull(SyncState* const syncState, + const unsigned int i, const unsigned int j); +static void writeAnalysisTraceTimeForePlotsCHull(SyncState* const syncState, + const unsigned int i, const unsigned int j); +static void writeAnalysisTraceTraceBackPlotsCHull(SyncState* const syncState, + const unsigned int i, const unsigned int j); + +static glp_prob* lpCreateProblem(GQueue* const lowerHull, GQueue* const + upperHull); +static void gfLPAddRow(gpointer data, gpointer user_data); +static Factors* calculateFactorsLP(glp_prob* const lp, const int direction); +static void calculateCompleteFactorsLP(glp_prob* const lp, PairFactors* + factors); +void timeCorrectionLP(glp_prob* const lp, const PairFactors* const lpFactors, + const uint64_t time, CorrectedTime* const correctedTime); + +static void gfAddAbsiscaToArray(gpointer data, gpointer user_data); +static gint gcfCompareUint64(gconstpointer a, gconstpointer b); +#else +static inline AllFactors* finalizeAnalysisCHullLP(SyncState* const syncState) +{ + return NULL; +} +#endif + + static AnalysisModule analysisModuleCHull= { .name= "chull", .initAnalysis= &initAnalysisCHull, .destroyAnalysis= &destroyAnalysisCHull, .analyzeMessage= &analyzeMessageCHull, - .analyzeExchange= NULL, - .analyzeBroadcast= NULL, .finalizeAnalysis= &finalizeAnalysisCHull, .printAnalysisStats= &printAnalysisStatsCHull, - .writeAnalysisGraphsPlots= &writeAnalysisGraphsPlotsCHull, - .writeAnalysisGraphsOptions= NULL, + .graphFunctions= { +#ifdef HAVE_LIBGLPK + .writeTraceTimeBackPlots= &writeAnalysisTraceTimeBackPlotsCHull, + .writeTraceTimeForePlots= &writeAnalysisTraceTimeForePlotsCHull, + .writeTraceTraceBackPlots= &writeAnalysisTraceTraceBackPlotsCHull, +#endif + .writeTraceTraceForePlots= &writeAnalysisTraceTraceForePlotsCHull, + } }; /* * Analysis module registering function */ -static void registerAnalysisCHull() +void registerAnalysisCHull() { g_queue_push_tail(&analysisModules, &analysisModuleCHull); } @@ -159,19 +185,19 @@ static void initAnalysisCHull(SyncState* const syncState) analysisData->hullArray[i][j]= g_queue_new(); } } +#ifdef HAVE_LIBGLPK + analysisData->lps= NULL; +#endif if (syncState->stats) { - analysisData->stats= malloc(sizeof(AnalysisStatsCHull)); - analysisData->stats->dropped= 0; - analysisData->stats->allFactors= NULL; + analysisData->stats= calloc(1, sizeof(AnalysisStatsCHull)); } if (syncState->graphsStream) { - analysisData->graphsData= malloc(sizeof(AnalysisGraphsDataCHull)); + analysisData->graphsData= calloc(1, sizeof(AnalysisGraphsDataCHull)); openGraphFiles(syncState); - analysisData->graphsData->allFactors= NULL; } } @@ -193,7 +219,7 @@ static void openGraphFiles(SyncState* const syncState) analysisData= (AnalysisDataCHull*) syncState->analysisData; - cwd= changeToGraphDir(syncState->graphsDir); + cwd= changeToGraphsDir(syncState->graphsDir); analysisData->graphsData->hullPoints= malloc(syncState->traceNb * sizeof(FILE**)); @@ -270,7 +296,7 @@ static void gfDumpHullToFile(gpointer data, gpointer userData) Point* point; point= (Point*) data; - fprintf((FILE*) userData, "%20llu %20llu\n", point->x, point->y); + fprintf((FILE*) userData, "%20" PRIu64 " %20" PRIu64 "\n", point->x, point->y); } @@ -341,33 +367,59 @@ static void destroyAnalysisCHull(SyncState* const syncState) { for (j= 0; j < syncState->traceNb; j++) { - g_queue_foreach(analysisData->hullArray[i][j], gfPointDestroy, NULL); + g_queue_foreach(analysisData->hullArray[i][j], gfPointDestroy, + NULL); + g_queue_free(analysisData->hullArray[i][j]); } free(analysisData->hullArray[i]); } free(analysisData->hullArray); - if (syncState->stats) +#ifdef HAVE_LIBGLPK + if (analysisData->lps != NULL) { - if (analysisData->stats->allFactors != NULL) + for (i= 0; i < syncState->traceNb; i++) { - freeAllFactors(syncState, analysisData->stats->allFactors); + unsigned int j; + + for (j= 0; j < i; j++) + { + // There seems to be a memory leak in glpk, valgrind reports a + // loss (reachable) even if the problem is deleted + glp_delete_prob(analysisData->lps[i][j]); + } + free(analysisData->lps[i]); } + free(analysisData->lps); + } +#endif + + if (syncState->stats) + { + freeAllFactors(analysisData->stats->allFactors, syncState->traceNb); + freeAllFactors(analysisData->stats->geoFactors, syncState->traceNb); + +#ifdef HAVE_LIBGLPK + freeAllFactors(analysisData->stats->lpFactors, syncState->traceNb); +#endif free(analysisData->stats); } if (syncState->graphsStream) { - if (analysisData->graphsData->hullPoints != NULL) + AnalysisGraphsDataCHull* graphs= analysisData->graphsData; + + if (graphs->hullPoints != NULL) { closeGraphFiles(syncState); } - if (!syncState->stats && analysisData->graphsData->allFactors != NULL) - { - freeAllFactors(syncState, analysisData->graphsData->allFactors); - } + freeAllFactors(graphs->allFactors, syncState->traceNb); + +#ifdef HAVE_LIBGLPK + freeAllFactors(graphs->lpFactors, syncState->traceNb); +#endif free(analysisData->graphsData); } @@ -400,7 +452,8 @@ static void analyzeMessageCHull(SyncState* const syncState, Message* const messa newPoint->x= message->inE->cpuTime; newPoint->y= message->outE->cpuTime; hullType= UPPER; - g_debug("Reception point hullArray[%lu][%lu] x= inE->time= %llu y= outE->time= %llu", + g_debug("Reception point hullArray[%lu][%lu] " + "x= inE->time= %" PRIu64 " y= outE->time= %" PRIu64, message->inE->traceNum, message->outE->traceNum, newPoint->x, newPoint->y); } @@ -410,7 +463,8 @@ static void analyzeMessageCHull(SyncState* const syncState, Message* const messa newPoint->x= message->outE->cpuTime; newPoint->y= message->inE->cpuTime; hullType= LOWER; - g_debug("Send point hullArray[%lu][%lu] x= inE->time= %llu y= outE->time= %llu", + g_debug("Send point hullArray[%lu][%lu] " + "x= inE->time= %" PRIu64 " y= outE->time= %" PRIu64, message->inE->traceNum, message->outE->traceNum, newPoint->x, newPoint->y); } @@ -500,13 +554,13 @@ static void grahamScan(GQueue* const hull, Point* const newPoint, const * syncState container for synchronization data. * * Returns: - * Factors[traceNb] synchronization factors for each trace + * AllFactors* synchronization factors for each trace pair, the caller is + * responsible for freeing the structure */ -static GArray* finalizeAnalysisCHull(SyncState* const syncState) +static AllFactors* finalizeAnalysisCHull(SyncState* const syncState) { AnalysisDataCHull* analysisData; - GArray* factors; - FactorsCHull** allFactors; + AllFactors* geoFactors, * lpFactors; analysisData= (AnalysisDataCHull*) syncState->analysisData; @@ -516,28 +570,50 @@ static GArray* finalizeAnalysisCHull(SyncState* const syncState) closeGraphFiles(syncState); } - allFactors= calculateAllFactors(syncState); + geoFactors= calculateAllFactors(syncState); + lpFactors= finalizeAnalysisCHullLP(syncState); - factors= reduceFactors(syncState, allFactors); - - if (syncState->stats || syncState->graphsStream) + if (syncState->stats) { - if (syncState->stats) + geoFactors->refCount++; + analysisData->stats->geoFactors= geoFactors; + + if (lpFactors != NULL) { - analysisData->stats->allFactors= allFactors; + lpFactors->refCount++; + analysisData->stats->allFactors= lpFactors; } + else + { + geoFactors->refCount++; + analysisData->stats->allFactors= geoFactors; + } + } - if (syncState->graphsStream) + if (syncState->graphsStream) + { + if (lpFactors != NULL) + { + lpFactors->refCount++; + analysisData->graphsData->allFactors= lpFactors; + } + else { - analysisData->graphsData->allFactors= allFactors; + geoFactors->refCount++; + analysisData->graphsData->allFactors= geoFactors; } } + + if (lpFactors != NULL) + { + freeAllFactors(geoFactors, syncState->traceNb); + return lpFactors; + } else { - freeAllFactors(syncState, allFactors); + freeAllFactors(lpFactors, syncState->traceNb); + return geoFactors; } - - return factors; } @@ -582,41 +658,38 @@ static void printAnalysisStatsCHull(SyncState* const syncState) { for (j= i + 1; j < syncState->traceNb; j++) { - FactorsCHull* factorsCHull; + PairFactors* factorsCHull; - factorsCHull= &analysisData->stats->allFactors[j][i]; - printf("\t\t%3d - %-3d: ", i, j); + factorsCHull= &analysisData->stats->allFactors->pairFactors[j][i]; + printf("\t\t%3d - %-3d: %s", i, j, + approxNames[factorsCHull->type]); if (factorsCHull->type == EXACT) { - printf("Exact a0= % 7g a1= 1 %c %7g\n", + printf(" a0= % 7g a1= 1 %c %7g\n", factorsCHull->approx->offset, factorsCHull->approx->drift < 0. ? '-' : '+', fabs(factorsCHull->approx->drift)); } - else if (factorsCHull->type == MIDDLE) + else if (factorsCHull->type == ACCURATE) { - printf("Middle a0= % 7g a1= 1 %c %7g accuracy %7g\n", - factorsCHull->approx->offset, factorsCHull->approx->drift - - 1. < 0. ? '-' : '+', fabs(factorsCHull->approx->drift - - 1.), factorsCHull->accuracy); - printf("\t\t a0: % 7g to % 7g (delta= %7g)\n", + printf("\n\t\t a0: % 7g to % 7g (delta= %7g)\n", factorsCHull->max->offset, factorsCHull->min->offset, factorsCHull->min->offset - factorsCHull->max->offset); printf("\t\t a1: 1 %+7g to %+7g (delta= %7g)\n", factorsCHull->min->drift - 1., factorsCHull->max->drift - 1., factorsCHull->max->drift - factorsCHull->min->drift); } - else if (factorsCHull->type == FALLBACK) + else if (factorsCHull->type == APPROXIMATE) { - printf("Fallback a0= % 7g a1= 1 %c %7g error= %7g\n", + printf(" a0= % 7g a1= 1 %c %7g error= %7g\n", factorsCHull->approx->offset, factorsCHull->approx->drift - 1. < 0. ? '-' : '+', fabs(factorsCHull->approx->drift - 1.), factorsCHull->accuracy); } else if (factorsCHull->type == INCOMPLETE) { - printf("Incomplete\n"); + printf("\n"); if (factorsCHull->min->drift != -INFINITY) { @@ -633,9 +706,9 @@ static void printAnalysisStatsCHull(SyncState* const syncState) 1.)); } } - else if (factorsCHull->type == SCREWED) + else if (factorsCHull->type == FAIL) { - printf("Screwed\n"); + printf("\n"); if (factorsCHull->min != NULL && factorsCHull->min->drift != -INFINITY) { @@ -654,7 +727,7 @@ static void printAnalysisStatsCHull(SyncState* const syncState) } else if (factorsCHull->type == ABSENT) { - printf("Absent\n"); + printf("\n"); } else { @@ -662,6 +735,47 @@ static void printAnalysisStatsCHull(SyncState* const syncState) } } } + +#ifdef HAVE_LIBGLPK + printf("\tFactor comparison:\n" + "\t\tTrace pair Factors type Differences (lp - chull)\n" + "\t\t a0 a1\n" + "\t\t Min Max Min Max\n"); + + for (i= 0; i < syncState->traceNb; i++) + { + for (j= 0; j < i; j++) + { + PairFactors* geoFactors= + &analysisData->stats->geoFactors->pairFactors[i][j]; + PairFactors* lpFactors= + &analysisData->stats->lpFactors->pairFactors[i][j]; + + printf("\t\t%3d - %-3d ", i, j); + if (lpFactors->type == geoFactors->type) + { + if (lpFactors->type == ACCURATE) + { + printf("%-13s %-10.4g %-10.4g %-10.4g %.4g\n", + approxNames[lpFactors->type], + lpFactors->min->offset - geoFactors->min->offset, + lpFactors->max->offset - geoFactors->max->offset, + lpFactors->min->drift - geoFactors->min->drift, + lpFactors->max->drift - geoFactors->max->drift); + } + else if (lpFactors->type == ABSENT) + { + printf("%s\n", approxNames[lpFactors->type]); + } + } + else + { + printf("Different! %s and %s\n", approxNames[lpFactors->type], + approxNames[geoFactors->type]); + } + } + } +#endif } @@ -701,7 +815,9 @@ static int jointCmp(const Point const* p1, const Point const* p2, const const double fuzzFactor= 0.; result= crossProductK(p1, p2, p1, p3); - g_debug("crossProductK(p1= (%llu, %llu), p2= (%llu, %llu), p1= (%llu, %llu), p3= (%llu, %llu))= %g", + g_debug("crossProductK(p1= (%" PRIu64 ", %" PRIu64 "), " + "p2= (%" PRIu64 ", %" PRIu64 "), p1= (%" PRIu64 ", %" PRIu64 "), " + "p3= (%" PRIu64 ", %" PRIu64 "))= %g", p1->x, p1->y, p2->x, p2->y, p1->x, p1->y, p3->x, p3->y, result); if (result < fuzzFactor) { @@ -738,55 +854,6 @@ static double crossProductK(const Point const* p1, const Point const* p2, } -/* - * Free a container of FactorsCHull - * - * Args: - * syncState: container for synchronization data. - * allFactors: container of Factors - */ -static void freeAllFactors(const SyncState* const syncState, FactorsCHull** - const allFactors) -{ - unsigned int i, j; - - for (i= 0; i < syncState->traceNb; i++) - { - for (j= 0; j <= i; j++) - { - FactorsCHull* factorsCHull; - - factorsCHull= &allFactors[i][j]; - if (factorsCHull->type == MIDDLE || factorsCHull->type == - INCOMPLETE || factorsCHull->type == ABSENT) - { - free(factorsCHull->min); - free(factorsCHull->max); - } - else if (factorsCHull->type == SCREWED) - { - if (factorsCHull->min != NULL) - { - free(factorsCHull->min); - } - if (factorsCHull->max != NULL) - { - free(factorsCHull->max); - } - } - - if (factorsCHull->type == EXACT || factorsCHull->type == MIDDLE || - factorsCHull->type == FALLBACK) - { - free(factorsCHull->approx); - } - } - free(allFactors[i]); - } - free(allFactors); -} - - /* * Analyze the convex hulls to determine the synchronization factors between * each pair of trace. @@ -795,28 +862,21 @@ static void freeAllFactors(const SyncState* const syncState, FactorsCHull** * syncState container for synchronization data. * * Returns: - * FactorsCHull*[TraceNum][TraceNum] array. See the documentation for the - * member allFactors of AnalysisStatsCHull. + * AllFactors*, see the documentation for the member geoFactors of + * AnalysisStatsCHull. */ -static FactorsCHull** calculateAllFactors(SyncState* const syncState) +AllFactors* calculateAllFactors(SyncState* const syncState) { unsigned int traceNumA, traceNumB; - FactorsCHull** allFactors; + AllFactors* geoFactors; AnalysisDataCHull* analysisData; analysisData= (AnalysisDataCHull*) syncState->analysisData; - // Allocate allFactors and calculate min and max - allFactors= malloc(syncState->traceNb * sizeof(FactorsCHull*)); + // Allocate geoFactors and calculate min and max + geoFactors= createAllFactors(syncState->traceNb); for (traceNumA= 0; traceNumA < syncState->traceNb; traceNumA++) { - allFactors[traceNumA]= malloc((traceNumA + 1) * sizeof(FactorsCHull)); - - allFactors[traceNumA][traceNumA].type= EXACT; - allFactors[traceNumA][traceNumA].approx= malloc(sizeof(Factors)); - allFactors[traceNumA][traceNumA].approx->drift= 1.; - allFactors[traceNumA][traceNumA].approx->offset= 0.; - for (traceNumB= 0; traceNumB < traceNumA; traceNumB++) { unsigned int i; @@ -826,8 +886,8 @@ static FactorsCHull** calculateAllFactors(SyncState* const syncState) LineType lineType; size_t factorsOffset; } loopValues[]= { - {MINIMUM, offsetof(FactorsCHull, min)}, - {MAXIMUM, offsetof(FactorsCHull, max)} + {MINIMUM, offsetof(PairFactors, min)}, + {MAXIMUM, offsetof(PairFactors, max)} }; cr= analysisData->hullArray[traceNumB][traceNumA]; @@ -835,12 +895,14 @@ static FactorsCHull** calculateAllFactors(SyncState* const syncState) for (i= 0; i < sizeof(loopValues) / sizeof(*loopValues); i++) { - g_debug("allFactors[%u][%u].%s = calculateFactorsExact(cr= hullArray[%u][%u], cs= hullArray[%u][%u], %s)", + g_debug("geoFactors[%u][%u].%s = calculateFactorsExact(cr= " + "hullArray[%u][%u], cs= hullArray[%u][%u], %s)", traceNumA, traceNumB, loopValues[i].factorsOffset == - offsetof(FactorsCHull, min) ? "min" : "max", traceNumB, + offsetof(PairFactors, min) ? "min" : "max", traceNumB, traceNumA, traceNumA, traceNumB, loopValues[i].lineType == MINIMUM ? "MINIMUM" : "MAXIMUM"); - *((Factors**) ((void*) &allFactors[traceNumA][traceNumB] + + *((Factors**) ((void*) + &geoFactors->pairFactors[traceNumA][traceNumB] + loopValues[i].factorsOffset))= calculateFactorsExact(cr, cs, loopValues[i].lineType); } @@ -852,22 +914,22 @@ static FactorsCHull** calculateAllFactors(SyncState* const syncState) { for (traceNumB= 0; traceNumB < traceNumA; traceNumB++) { - FactorsCHull* factorsCHull; + PairFactors* factorsCHull; - factorsCHull= &allFactors[traceNumA][traceNumB]; + factorsCHull= &geoFactors->pairFactors[traceNumA][traceNumB]; if (factorsCHull->min == NULL && factorsCHull->max == NULL) { - factorsCHull->type= FALLBACK; + factorsCHull->type= APPROXIMATE; calculateFactorsFallback(analysisData->hullArray[traceNumB][traceNumA], analysisData->hullArray[traceNumA][traceNumB], - &allFactors[traceNumA][traceNumB]); + &geoFactors->pairFactors[traceNumA][traceNumB]); } else if (factorsCHull->min != NULL && factorsCHull->max != NULL) { if (factorsCHull->min->drift != -INFINITY && factorsCHull->max->drift != INFINITY) { - factorsCHull->type= MIDDLE; + factorsCHull->type= ACCURATE; calculateFactorsMiddle(factorsCHull); } else if (factorsCHull->min->drift != -INFINITY || @@ -883,12 +945,12 @@ static FactorsCHull** calculateAllFactors(SyncState* const syncState) else { //g_assert_not_reached(); - factorsCHull->type= SCREWED; + factorsCHull->type= FAIL; } } } - return allFactors; + return geoFactors; } @@ -908,7 +970,7 @@ static FactorsCHull** calculateAllFactors(SyncState* const syncState) * Args: * factors: contains the min and max limits, used to store the result */ -static void calculateFactorsMiddle(FactorsCHull* factors) +void calculateFactorsMiddle(PairFactors* const factors) { double amin, amax, bmin, bmax, bhat; @@ -917,7 +979,7 @@ static void calculateFactorsMiddle(FactorsCHull* factors) bmin= factors->min->drift; bmax= factors->max->drift; - g_assert_cmpfloat(bmax, >, bmin); + g_assert_cmpfloat(bmax, >=, bmin); factors->approx= malloc(sizeof(Factors)); bhat= (bmax * bmin - 1. + sqrt(1. + pow(bmax, 2.) * pow(bmin, 2.) + @@ -1064,14 +1126,15 @@ static Factors* calculateFactorsExact(GQueue* const cu, GQueue* const cl, const p1= g_queue_peek_nth(c1, i1); p2= g_queue_peek_nth(c2, i2); - g_debug("Resulting points are: c1[i1]: x= %llu y= %llu c2[i2]: x= %llu y= %llu", - p1->x, p1->y, p2->x, p2->y); + g_debug("Resulting points are: c1[i1]: x= %" PRIu64 " y= %" PRIu64 + " c2[i2]: x= %" PRIu64 " y= %" PRIu64 "", p1->x, p1->y, p2->x, p2->y); result= malloc(sizeof(Factors)); result->drift= slope(p1, p2); result->offset= intercept(p1, p2); - g_debug("Resulting factors are: drift= %g offset= %g", result->drift, result->offset); + g_debug("Resulting factors are: drift= %g offset= %g", result->drift, + result->offset); return result; } @@ -1103,7 +1166,7 @@ static Factors* calculateFactorsExact(GQueue* const cu, GQueue* const cl, const * will be stored */ static void calculateFactorsFallback(GQueue* const cr, GQueue* const cs, - FactorsCHull* const result) + PairFactors* const result) { unsigned int i, j, k; double errorMin; @@ -1210,314 +1273,6 @@ static double intercept(const Point* const p1, const Point* const p2) } -/* - * 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 (MIDDLE and FALLBACK) 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 bondaries 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: - * syncState: container for synchronization data. - * allFactors: offset and drift between each pair of traces - * - * Returns: - * Factors[traceNb] synchronization factors for each trace - */ -static GArray* reduceFactors(SyncState* const syncState, FactorsCHull** const - allFactors) -{ - GArray* factors; - double** distances; - unsigned int** predecessors; - double* distanceSums; - unsigned int* references; - unsigned int i, j; - - // Solve the all-pairs shortest path problem using the Floyd-Warshall - // algorithm - floydWarshall(syncState, 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(syncState->traceNb * sizeof(double)); - for (i= 0; i < syncState->traceNb; i++) - { - distanceSums[i]= 0.; - for (j= 0; j < syncState->traceNb; j++) - { - distanceSums[i]+= distances[i][j]; - } - } - - references= malloc(syncState->traceNb * sizeof(unsigned int)); - for (i= 0; i < syncState->traceNb; i++) - { - references[i]= UINT_MAX; - } - for (i= 0; i < syncState->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 < syncState->traceNb; j++) - { - if (distances[i][j] != INFINITY && distanceSums[j] < - distanceSumMin) - { - reference= j; - distanceSumMin= distanceSums[j]; - } - } - for (j= 0; j < syncState->traceNb; j++) - { - if (distances[i][j] != INFINITY) - { - references[j]= reference; - } - } - } - } - - for (i= 0; i < syncState->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), - syncState->traceNb); - g_array_set_size(factors, syncState->traceNb); - for (i= 0; i < syncState->traceNb; i++) - { - getFactors(allFactors, predecessors, references, i, &g_array_index(factors, - Factors, i)); - } - - for (i= 0; i < syncState->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: - * syncState: container for synchronization data. - * 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(SyncState* const syncState, FactorsCHull** const - allFactors, double*** const distances, unsigned int*** const - predecessors) -{ - unsigned int i, j, k; - - // Setup initial conditions - *distances= malloc(syncState->traceNb * sizeof(double*)); - *predecessors= malloc(syncState->traceNb * sizeof(unsigned int*)); - for (i= 0; i < syncState->traceNb; i++) - { - (*distances)[i]= malloc(syncState->traceNb * sizeof(double)); - for (j= 0; j < syncState->traceNb; j++) - { - if (i == j) - { - g_assert(allFactors[i][j].type == EXACT); - - (*distances)[i][j]= 0.; - } - else - { - unsigned int row, col; - - if (i > j) - { - row= i; - col= j; - } - else if (i < j) - { - row= j; - col= i; - } - - if (allFactors[row][col].type == MIDDLE || - allFactors[row][col].type == FALLBACK) - { - (*distances)[i][j]= allFactors[row][col].accuracy; - } - else if (allFactors[row][col].type == INCOMPLETE || - allFactors[row][col].type == SCREWED || - allFactors[row][col].type == ABSENT) - { - (*distances)[i][j]= INFINITY; - } - else - { - g_assert_not_reached(); - } - } - } - - (*predecessors)[i]= malloc(syncState->traceNb * sizeof(unsigned int)); - for (j= 0; j < syncState->traceNb; j++) - { - if (i != j) - { - (*predecessors)[i][j]= i; - } - else - { - (*predecessors)[i][j]= UINT_MAX; - } - } - } - - // Run the iterations - for (k= 0; k < syncState->traceNb; k++) - { - for (i= 0; i < syncState->traceNb; i++) - { - for (j= 0; j < syncState->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(FactorsCHull** const allFactors, unsigned int** const - predecessors, unsigned int* const references, const unsigned int traceNum, - Factors* const factors) -{ - unsigned int reference; - - reference= references[traceNum]; - - if (reference == traceNum) - { - factors->offset= 0.; - factors->drift= 1.; - } - else - { - Factors previousVertexFactors; - - getFactors(allFactors, predecessors, references, - predecessors[reference][traceNum], &previousVertexFactors); - - // convertir de traceNum à reference - - // allFactors convertit de col à row - - if (reference > traceNum) - { - factors->offset= previousVertexFactors.drift * - allFactors[reference][traceNum].approx->offset + - previousVertexFactors.offset; - factors->drift= previousVertexFactors.drift * - allFactors[reference][traceNum].approx->drift; - } - else - { - factors->offset= previousVertexFactors.drift * (-1. * - allFactors[traceNum][reference].approx->offset / - allFactors[traceNum][reference].approx->drift) + - previousVertexFactors.offset; - factors->drift= previousVertexFactors.drift * (1. / - allFactors[traceNum][reference].approx->drift); - } - } -} - - /* * Write the analysis-specific graph lines in the gnuplot script. * @@ -1526,11 +1281,11 @@ static void getFactors(FactorsCHull** const allFactors, unsigned int** const * i: first trace number * j: second trace number, garanteed to be larger than i */ -void writeAnalysisGraphsPlotsCHull(SyncState* const syncState, const unsigned +void writeAnalysisTraceTraceForePlotsCHull(SyncState* const syncState, const unsigned int i, const unsigned int j) { AnalysisDataCHull* analysisData; - FactorsCHull* factorsCHull; + PairFactors* factorsCHull; analysisData= (AnalysisDataCHull*) syncState->analysisData; @@ -1543,7 +1298,7 @@ void writeAnalysisGraphsPlotsCHull(SyncState* const syncState, const unsigned "linecolor rgb \"#003366\" linetype 4 pointtype 10 pointsize 0.8, \\\n", i, j); - factorsCHull= &analysisData->graphsData->allFactors[j][i]; + factorsCHull= &analysisData->graphsData->allFactors->pairFactors[j][i]; if (factorsCHull->type == EXACT) { fprintf(syncState->graphsStream, @@ -1552,7 +1307,7 @@ void writeAnalysisGraphsPlotsCHull(SyncState* const syncState, const unsigned "linecolor rgb \"black\" linetype 1, \\\n", factorsCHull->approx->offset, factorsCHull->approx->drift); } - else if (factorsCHull->type == MIDDLE) + else if (factorsCHull->type == ACCURATE) { fprintf(syncState->graphsStream, "\t%.2f + %.10f * x " @@ -1567,10 +1322,10 @@ void writeAnalysisGraphsPlotsCHull(SyncState* const syncState, const unsigned fprintf(syncState->graphsStream, "\t%.2f + %.10f * x " "title \"Middle conversion\" with lines " - "linecolor rgb \"gray60\" linetype 1, \\\n", + "linecolor rgb \"black\" linetype 1, \\\n", factorsCHull->approx->offset, factorsCHull->approx->drift); } - else if (factorsCHull->type == FALLBACK) + else if (factorsCHull->type == APPROXIMATE) { fprintf(syncState->graphsStream, "\t%.2f + %.10f * x " @@ -1598,7 +1353,7 @@ void writeAnalysisGraphsPlotsCHull(SyncState* const syncState, const unsigned factorsCHull->max->offset, factorsCHull->max->drift); } } - else if (factorsCHull->type == SCREWED) + else if (factorsCHull->type == FAIL) { if (factorsCHull->min != NULL && factorsCHull->min->drift != -INFINITY) { @@ -1626,3 +1381,480 @@ void writeAnalysisGraphsPlotsCHull(SyncState* const syncState, const unsigned g_assert_not_reached(); } } + + +#ifdef HAVE_LIBGLPK +/* + * Create the linear programming problem containing the constraints defined by + * two half-hulls. The objective function and optimization directions are not + * written. + * + * Args: + * syncState: container for synchronization data + * i: first trace number + * j: second trace number, garanteed to be larger than i + * Returns: + * A new glp_prob*, this problem must be freed by the caller with + * glp_delete_prob() + */ +static glp_prob* lpCreateProblem(GQueue* const lowerHull, GQueue* const + upperHull) +{ + unsigned int it; + const int zero= 0; + const double zeroD= 0.; + glp_prob* lp= glp_create_prob(); + unsigned int hullPointNb= g_queue_get_length(lowerHull) + + g_queue_get_length(upperHull); + GArray* iArray= g_array_sized_new(FALSE, FALSE, sizeof(int), hullPointNb + + 1); + GArray* jArray= g_array_sized_new(FALSE, FALSE, sizeof(int), hullPointNb + + 1); + GArray* aArray= g_array_sized_new(FALSE, FALSE, sizeof(double), + hullPointNb + 1); + struct { + GQueue* hull; + struct LPAddRowInfo rowInfo; + } loopValues[2]= { + {lowerHull, {lp, GLP_UP, iArray, jArray, aArray}}, + {upperHull, {lp, GLP_LO, iArray, jArray, aArray}}, + }; + + // Create the LP problem + glp_term_out(GLP_OFF); + if (hullPointNb > 0) + { + glp_add_rows(lp, hullPointNb); + } + glp_add_cols(lp, 2); + + glp_set_col_name(lp, 1, "a0"); + glp_set_col_bnds(lp, 1, GLP_FR, 0., 0.); + glp_set_col_name(lp, 2, "a1"); + glp_set_col_bnds(lp, 2, GLP_LO, 0., 0.); + + // Add row constraints + g_array_append_val(iArray, zero); + g_array_append_val(jArray, zero); + g_array_append_val(aArray, zeroD); + + for (it= 0; it < sizeof(loopValues) / sizeof(*loopValues); it++) + { + g_queue_foreach(loopValues[it].hull, &gfLPAddRow, + &loopValues[it].rowInfo); + } + + g_assert_cmpuint(iArray->len, ==, jArray->len); + g_assert_cmpuint(jArray->len, ==, aArray->len); + g_assert_cmpuint(aArray->len - 1, ==, hullPointNb * 2); + + glp_load_matrix(lp, aArray->len - 1, &g_array_index(iArray, int, 0), + &g_array_index(jArray, int, 0), &g_array_index(aArray, double, 0)); + + glp_scale_prob(lp, GLP_SF_AUTO); + + g_array_free(iArray, TRUE); + g_array_free(jArray, TRUE); + g_array_free(aArray, TRUE); + + return lp; +} + + +/* + * A GFunc for g_queue_foreach(). Add constraints and bounds for one row. + * + * Args: + * data Point*, synchronization point for which to add an LP row + * (a constraint) + * user_data LPAddRowInfo* + */ +static void gfLPAddRow(gpointer data, gpointer user_data) +{ + Point* p= data; + struct LPAddRowInfo* rowInfo= user_data; + int indexes[2]; + double constraints[2]; + + indexes[0]= g_array_index(rowInfo->iArray, int, rowInfo->iArray->len - 1) + 1; + indexes[1]= indexes[0]; + + if (rowInfo->boundType == GLP_UP) + { + glp_set_row_bnds(rowInfo->lp, indexes[0], GLP_UP, 0., p->y); + } + else if (rowInfo->boundType == GLP_LO) + { + glp_set_row_bnds(rowInfo->lp, indexes[0], GLP_LO, p->y, 0.); + } + else + { + g_assert_not_reached(); + } + + g_array_append_vals(rowInfo->iArray, indexes, 2); + indexes[0]= 1; + indexes[1]= 2; + g_array_append_vals(rowInfo->jArray, indexes, 2); + constraints[0]= 1.; + constraints[1]= p->x; + g_array_append_vals(rowInfo->aArray, constraints, 2); +} + + +/* + * Calculate min or max correction factors (as possible) using an LP problem. + * + * Args: + * lp: A linear programming problem with constraints and bounds + * initialized. + * direction: The type of factors desired. Use GLP_MAX for max + * approximation factors (a1, the drift or slope is the + * largest) and GLP_MIN in the other case. + * + * Returns: + * If the calculation was successful, a new Factors struct. Otherwise, NULL. + * The calculation will fail if the hull assumptions are not respected. + */ +static Factors* calculateFactorsLP(glp_prob* const lp, const int direction) +{ + int retval, status; + Factors* factors; + + glp_set_obj_coef(lp, 1, 0.); + glp_set_obj_coef(lp, 2, 1.); + + glp_set_obj_dir(lp, direction); + retval= glp_simplex(lp, NULL); + status= glp_get_status(lp); + + if (retval == 0 && status == GLP_OPT) + { + factors= malloc(sizeof(Factors)); + factors->offset= glp_get_col_prim(lp, 1); + factors->drift= glp_get_col_prim(lp, 2); + } + else + { + factors= NULL; + } + + return factors; +} + + +/* + * Calculate min, max and approx correction factors (as possible) using an LP + * problem. + * + * Args: + * lp A linear programming problem with constraints and bounds + * initialized. + * factors Resulting factors, must be preallocated + */ +static void calculateCompleteFactorsLP(glp_prob* const lp, PairFactors* factors) +{ + factors->min= calculateFactorsLP(lp, GLP_MIN); + factors->max= calculateFactorsLP(lp, GLP_MAX); + + if (factors->min && factors->max) + { + factors->type= ACCURATE; + calculateFactorsMiddle(factors); + } + else if (factors->min || factors->max) + { + factors->type= INCOMPLETE; + } + else + { + factors->type= ABSENT; + } +} + + +/* + * A GFunc for g_queue_foreach() + * + * Args: + * data Point*, a convex hull point + * user_data GArray*, an array of convex hull point absisca values, as + * uint64_t + */ +static void gfAddAbsiscaToArray(gpointer data, gpointer user_data) +{ + Point* p= data; + GArray* a= user_data; + uint64_t v= p->x; + + g_array_append_val(a, v); +} + + +/* + * A GCompareFunc for g_array_sort() + * + * Args: + * a, b uint64_t*, absisca values + * + * Returns: + * "returns less than zero for first arg is less than second arg, zero for + * equal, greater zero if first arg is greater than second arg" + * - the great glib documentation + */ +static gint gcfCompareUint64(gconstpointer a, gconstpointer b) +{ + if (*(uint64_t*) a < *(uint64_t*) b) + { + return -1; + } + else if (*(uint64_t*) a > *(uint64_t*) b) + { + return 1; + } + else + { + return 0; + } +} + + +/* + * Compute synchronization factors using a linear programming approach. + * + * Args: + * syncState: container for synchronization data + */ +static AllFactors* finalizeAnalysisCHullLP(SyncState* const syncState) +{ + AnalysisDataCHull* analysisData= syncState->analysisData; + unsigned int i, j; + AllFactors* lpFactorsArray; + + lpFactorsArray= createAllFactors(syncState->traceNb); + + analysisData->lps= malloc(syncState->traceNb * sizeof(glp_prob**)); + for (i= 0; i < syncState->traceNb; i++) + { + analysisData->lps[i]= malloc(i * sizeof(glp_prob*)); + } + + for (i= 0; i < syncState->traceNb; i++) + { + for (j= 0; j < i; j++) + { + glp_prob* lp; + unsigned int it; + GQueue*** hullArray= analysisData->hullArray; + PairFactors* lpFactors= &lpFactorsArray->pairFactors[i][j]; + + // Create the LP problem + lp= lpCreateProblem(hullArray[i][j], hullArray[j][i]); + analysisData->lps[i][j]= lp; + + // Use the LP problem to find the correction factors for this pair of + // traces + calculateCompleteFactorsLP(lp, lpFactors); + + // If possible, compute synchronization accuracy information for + // graphs + if (syncState->graphsStream && lpFactors->type == ACCURATE) + { + int retval; + char* cwd; + char fileName[43]; + FILE* fp; + GArray* xValues; + + // Open the data file + snprintf(fileName, sizeof(fileName), + "analysis_chull_accuracy-%03u_and_%03u.data", j, i); + fileName[sizeof(fileName) - 1]= '\0'; + + cwd= changeToGraphsDir(syncState->graphsDir); + + if ((fp= fopen(fileName, "w")) == NULL) + { + g_error(strerror(errno)); + } + fprintf(fp, "#%-24s %-25s %-25s %-25s\n", "x", "middle", "min", "max"); + + retval= chdir(cwd); + if (retval == -1) + { + g_error(strerror(errno)); + } + free(cwd); + + // Build the list of absisca values for the points in the accuracy graph + xValues= g_array_sized_new(FALSE, FALSE, sizeof(uint64_t), + g_queue_get_length(hullArray[i][j]) + + g_queue_get_length(hullArray[j][i])); + + g_queue_foreach(hullArray[i][j], &gfAddAbsiscaToArray, xValues); + g_queue_foreach(hullArray[j][i], &gfAddAbsiscaToArray, xValues); + + g_array_sort(xValues, &gcfCompareUint64); + + /* For each absisca value and each optimisation direction, solve the LP + * and write a line in the data file */ + for (it= 0; it < xValues->len; it++) + { + uint64_t time; + CorrectedTime correctedTime; + + time= g_array_index(xValues, uint64_t, it); + timeCorrectionLP(lp, lpFactors, time, &correctedTime); + fprintf(fp, "%24" PRIu64 " %24" PRIu64 " %24" PRIu64 + "%24" PRIu64 "\n", time, correctedTime.time, + correctedTime.min, correctedTime.max); + } + + g_array_free(xValues, TRUE); + fclose(fp); + } + } + } + + if (syncState->stats) + { + lpFactorsArray->refCount++; + analysisData->stats->lpFactors= lpFactorsArray; + } + + if (syncState->graphsStream) + { + lpFactorsArray->refCount++; + analysisData->graphsData->lpFactors= lpFactorsArray; + } + + return lpFactorsArray; +} + + +/* + * Perform correction on one time value and calculate accuracy bounds. + * + * Args: + * lp: Linear Programming problem containing the coefficients for + * the trace pair between which to perform time correction. + * lpFactors: Correction factors for this trace pair, the factors must be + * of type ACCURATE. + * time: Time value to correct. + * correctedTime: Result of the time correction, preallocated. + */ +void timeCorrectionLP(glp_prob* const lp, const PairFactors* const lpFactors, + const uint64_t time, CorrectedTime* const correctedTime) +{ + unsigned int it; + const struct + { + int direction; + size_t offset; + } loopValues[]= { + {GLP_MIN, offsetof(CorrectedTime, min)}, + {GLP_MAX, offsetof(CorrectedTime, max)} + }; + + glp_set_obj_coef(lp, 1, 1.); + glp_set_obj_coef(lp, 2, time); + + g_assert(lpFactors->type == ACCURATE); + + correctedTime->time= lpFactors->approx->offset + lpFactors->approx->drift + * time; + + for (it= 0; it < ARRAY_SIZE(loopValues); it++) + { + int status; + int retval; + + glp_set_obj_dir(lp, loopValues[it].direction); + retval= glp_simplex(lp, NULL); + status= glp_get_status(lp); + + g_assert(retval == 0 && status == GLP_OPT); + *(uint64_t*) ((void*) correctedTime + loopValues[it].offset)= + round(glp_get_obj_val(lp)); + } +} + + +/* + * Write the analysis-specific graph lines in the gnuplot script. + * + * Args: + * syncState: container for synchronization data + * i: first trace number + * j: second trace number, garanteed to be larger than i + */ +static void writeAnalysisTraceTimeBackPlotsCHull(SyncState* const syncState, + const unsigned int i, const unsigned int j) +{ + if (((AnalysisDataCHull*) + syncState->analysisData)->graphsData->lpFactors->pairFactors[j][i].type + == ACCURATE) + { + fprintf(syncState->graphsStream, + "\t\"analysis_chull_accuracy-%1$03u_and_%2$03u.data\" " + "using 1:(($3 - $2) / clock_freq_%2$u):(($4 - $2) / clock_freq_%2$u) " + "title \"Synchronization accuracy\" " + "with filledcurves linewidth 2 linetype 1 " + "linecolor rgb \"black\" fill solid 0.25 noborder, \\\n", i, + j); + } +} + + +/* + * Write the analysis-specific graph lines in the gnuplot script. + * + * Args: + * syncState: container for synchronization data + * i: first trace number + * j: second trace number, garanteed to be larger than i + */ +static void writeAnalysisTraceTimeForePlotsCHull(SyncState* const syncState, + const unsigned int i, const unsigned int j) +{ + if (((AnalysisDataCHull*) + syncState->analysisData)->graphsData->lpFactors->pairFactors[j][i].type + == ACCURATE) + { + fprintf(syncState->graphsStream, + "\t\"analysis_chull_accuracy-%1$03u_and_%2$03u.data\" " + "using 1:(($3 - $2) / clock_freq_%2$u) notitle " + "with lines linewidth 2 linetype 1 " + "linecolor rgb \"gray60\", \\\n" + "\t\"analysis_chull_accuracy-%1$03u_and_%2$03u.data\" " + "using 1:(($4 - $2) / clock_freq_%2$u) notitle " + "with lines linewidth 2 linetype 1 " + "linecolor rgb \"gray60\", \\\n", i, j); + } +} + + +/* + * Write the analysis-specific graph lines in the gnuplot script. + * + * Args: + * syncState: container for synchronization data + * i: first trace number + * j: second trace number, garanteed to be larger than i + */ +static void writeAnalysisTraceTraceBackPlotsCHull(SyncState* const syncState, + const unsigned int i, const unsigned int j) +{ + if (((AnalysisDataCHull*) + syncState->analysisData)->graphsData->lpFactors->pairFactors[j][i].type + == ACCURATE) + { + fprintf(syncState->graphsStream, + "\t\"analysis_chull_accuracy-%1$03u_and_%2$03u.data\" " + "using 1:3:4 " + "title \"Synchronization accuracy\" " + "with filledcurves linewidth 2 linetype 1 " + "linecolor rgb \"black\" fill solid 0.25 noborder, \\\n", i, j); + } +} +#endif