Browse Source

src/core/perfmodel: the windows implementation of fscanf cannot read NAN values, we need to define a function doing it correctly

Nathalie Furmento 11 years ago
parent
commit
b901df23be

+ 1 - 0
src/Makefile.am

@@ -167,6 +167,7 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 						\
 	core/perfmodel/perfmodel_bus.c				\
 	core/perfmodel/perfmodel.c				\
 	core/perfmodel/perfmodel_print.c			\
+	core/perfmodel/perfmodel_nan.c				\
 	core/perfmodel/regression.c				\
 	core/sched_policy.c					\
 	core/simgrid.c						\

+ 3 - 0
src/core/perfmodel/perfmodel.h

@@ -89,6 +89,9 @@ int *_starpu_get_opencl_affinity_vector(unsigned gpuid);
 void _starpu_save_bandwidth_and_latency_disk(double bandwidth_write, double bandwidth_read, 
 					    double latency_write, double latency_read, unsigned node);
 
+int _starpu_read_double(FILE *f, char *format, double *val);
+int _starpu_check_number(double val, int nan);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 4
src/core/perfmodel/perfmodel_bus.c

@@ -1000,7 +1000,7 @@ static int load_bus_latency_file_content(void)
 		_starpu_drop_comments(f);
 		for (dst = 0; dst < STARPU_MAXNODES; dst++)
 		{
-			n = fscanf(f, "%lf", &latency);
+			n = _starpu_read_double(f, "%lf", &latency);
 			if (n != 1)
 			{
 				_STARPU_DISP("Error while reading latency file <%s>. Expected a number\n", path);
@@ -1039,7 +1039,7 @@ static int load_bus_latency_file_content(void)
 				break;
 			ungetc(n, f);
 
-			n = fscanf(f, "%lf", &latency);
+			n = _starpu_read_double(f, "%lf", &latency);
 			if (n && !isnan(latency))
 			{
 				_STARPU_DISP("Too many nodes in latency file %s for this configuration (%d)\n", path, STARPU_MAXNODES);
@@ -1217,7 +1217,7 @@ static int load_bus_bandwidth_file_content(void)
 		_starpu_drop_comments(f);
 		for (dst = 0; dst < STARPU_MAXNODES; dst++)
 		{
-			n = fscanf(f, "%lf", &bandwidth);
+			n = _starpu_read_double(f, "%lf", &bandwidth);
 			if (n != 1)
 			{
 				_STARPU_DISP("Error while reading bandwidth file <%s>. Expected a number\n", path);
@@ -1256,7 +1256,7 @@ static int load_bus_bandwidth_file_content(void)
 				break;
 			ungetc(n, f);
 
-			n = fscanf(f, "%lf", &bandwidth);
+			n = _starpu_read_double(f, "%lf", &bandwidth);
 			if (n && !isnan(bandwidth))
 			{
 				_STARPU_DISP("Too many nodes in bandwidth file %s for this configuration (%d)\n", path, STARPU_MAXNODES);

+ 14 - 8
src/core/perfmodel/perfmodel_history.c

@@ -152,12 +152,14 @@ static void scan_reg_model(FILE *f, struct starpu_perfmodel_regression_model *re
 
 	_starpu_drop_comments(f);
 
-	res = fscanf(f, "%le\t%le\t%le\t%le\t%le\t%le\t%u\t%lu\t%lu\n",
-		&reg_model->sumlnx, &reg_model->sumlnx2, &reg_model->sumlny,
-		&reg_model->sumlnxlny, &reg_model->alpha, &reg_model->beta,
-		&reg_model->nsample,
-		&reg_model->minx, &reg_model->maxx);
-	STARPU_ASSERT_MSG(res == 9, "Incorrect performance model file");
+	res = fscanf(f, "%le\t%le\t%le\t%le", &reg_model->sumlnx, &reg_model->sumlnx2, &reg_model->sumlny, &reg_model->sumlnxlny);
+	STARPU_ASSERT_MSG(res == 4, "Incorrect performance model file");
+	res = _starpu_read_double(f, "\t%le", &reg_model->alpha);
+	STARPU_ASSERT_MSG(res == 1, "Incorrect performance model file");
+	res = _starpu_read_double(f, "\t%le", &reg_model->beta);
+	STARPU_ASSERT_MSG(res == 1, "Incorrect performance model file");
+	res = fscanf(f, "\t%u\t%lu\t%lu\n", &reg_model->nsample, &reg_model->minx, &reg_model->maxx);
+	STARPU_ASSERT_MSG(res == 3, "Incorrect performance model file");
 
 	/* If any of the parameters describing the linear regression model is NaN, the model is invalid */
 	unsigned invalid = (isnan(reg_model->alpha)||isnan(reg_model->beta));
@@ -169,8 +171,12 @@ static void scan_reg_model(FILE *f, struct starpu_perfmodel_regression_model *re
 
 	_starpu_drop_comments(f);
 
-	res = fscanf(f, "%le\t%le\t%le\n", &reg_model->a, &reg_model->b, &reg_model->c);
-	STARPU_ASSERT_MSG(res == 3, "Incorrect performance model file");
+	res = _starpu_read_double(f, "%le\t", &reg_model->a);
+	STARPU_ASSERT_MSG(res == 1, "Incorrect performance model file");
+	res = _starpu_read_double(f, "%le\t", &reg_model->b);
+	STARPU_ASSERT_MSG(res == 1, "Incorrect performance model file");
+	res = _starpu_read_double(f, "%le\n", &reg_model->c);
+	STARPU_ASSERT_MSG(res == 1, "Incorrect performance model file");
 
 	/* If any of the parameters describing the non-linear regression model is NaN, the model is invalid */
 	unsigned nl_invalid = (isnan(reg_model->a)||isnan(reg_model->b)||isnan(reg_model->c));

+ 78 - 0
src/core/perfmodel/perfmodel_nan.c

@@ -0,0 +1,78 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  Centre National de la Recherche Scientifique
+ *
+ * StarPU 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.
+ *
+ * StarPU 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 in COPYING.LGPL for more details.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+int _starpu_read_double(FILE *f, char *format, double *val)
+{
+#ifdef STARPU_HAVE_WINDOWS
+/** Windows cannot read NAN values, yes, it is really bad ... */
+	int x1 = getc(f);
+	int x2 = getc(f);
+	int x3 = getc(f);
+
+	if (x1 == 'n' && x2 == 'a' && x3 == 'n')
+	{
+		*val = NAN;
+		return 1;
+	}
+	else
+	{
+		ungetc(x3, f);
+		ungetc(x2, f);
+		ungetc(x1, f);
+		return fscanf(f, format, val);
+	}
+#else
+	return fscanf(f, format, val);
+#endif
+}
+
+#define STRING "booh"
+
+int _starpu_check_number(double val, int nan)
+{
+	char *filename = tmpnam(NULL);
+
+	/* write the double value in the file followed by a predefined string */
+	FILE *f = fopen(filename, "w");
+	fprintf(f, "%lf %s\n", val, STRING);
+	fclose(f);
+
+	/* read the double value and the string back from the file */
+	f = fopen(filename, "r");
+	double lat;
+	char str[10];
+	int x = _starpu_read_double(f, "%lf", &lat);
+	int y = fscanf(f, "%s", str);
+	fclose(f);
+
+	/* check that what has been read is identical to what has been written */
+	int pass;
+	pass = (x == 1) && (y == 1);
+	pass = pass && strcmp(str, STRING) == 0;
+	if (nan)
+		pass = pass && isnan(val) && isnan(lat);
+	else
+		pass = pass && lat == val;
+	return pass;
+}