mirror of
				https://github.com/tiagovignatti/intel-gpu-tools.git
				synced 2025-11-04 03:58:27 +00:00 
			
		
		
		
	lib: Allow storing floating point values in igt_stats
We don't always have precise integers with which to store, so allow degrading to double precision floating point based on available input. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
		
							parent
							
								
									fdefdd48f6
								
							
						
					
					
						commit
						8506cdcaa5
					
				@ -31,6 +31,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define U64_MAX         ((uint64_t)~0ULL)
 | 
					#define U64_MAX         ((uint64_t)~0ULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define sorted_value(stats, i) (stats->is_float ? stats->sorted_f[i] : stats->sorted_u64[i])
 | 
				
			||||||
 | 
					#define unsorted_value(stats, i) (stats->is_float ? stats->values_f[i] : stats->values_u64[i])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * SECTION:igt_stats
 | 
					 * SECTION:igt_stats
 | 
				
			||||||
 * @short_description: Tools for statistical analysis
 | 
					 * @short_description: Tools for statistical analysis
 | 
				
			||||||
@ -84,14 +87,14 @@ static void igt_stats_ensure_capacity(igt_stats_t *stats,
 | 
				
			|||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new_capacity = get_new_capacity(new_n_values);
 | 
						new_capacity = get_new_capacity(new_n_values);
 | 
				
			||||||
	stats->values = realloc(stats->values,
 | 
						stats->values_u64 = realloc(stats->values_u64,
 | 
				
			||||||
				sizeof(*stats->values) * new_capacity);
 | 
									    sizeof(*stats->values_u64) * new_capacity);
 | 
				
			||||||
	igt_assert(stats->values);
 | 
						igt_assert(stats->values_u64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stats->capacity = new_capacity;
 | 
						stats->capacity = new_capacity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(stats->sorted);
 | 
						free(stats->sorted_u64);
 | 
				
			||||||
	stats->sorted = NULL;
 | 
						stats->sorted_u64 = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -130,6 +133,8 @@ void igt_stats_init_with_size(igt_stats_t *stats, unsigned int capacity)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	stats->min = U64_MAX;
 | 
						stats->min = U64_MAX;
 | 
				
			||||||
	stats->max = 0;
 | 
						stats->max = 0;
 | 
				
			||||||
 | 
						stats->range[0] = HUGE_VAL;
 | 
				
			||||||
 | 
						stats->range[1] = -HUGE_VAL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -140,8 +145,8 @@ void igt_stats_init_with_size(igt_stats_t *stats, unsigned int capacity)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void igt_stats_fini(igt_stats_t *stats)
 | 
					void igt_stats_fini(igt_stats_t *stats)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	free(stats->values);
 | 
						free(stats->values_u64);
 | 
				
			||||||
	free(stats->sorted);
 | 
						free(stats->sorted_u64);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -202,9 +207,14 @@ void igt_stats_set_population(igt_stats_t *stats, bool full_population)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void igt_stats_push(igt_stats_t *stats, uint64_t value)
 | 
					void igt_stats_push(igt_stats_t *stats, uint64_t value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (stats->is_float) {
 | 
				
			||||||
 | 
							igt_stats_push_float(stats, value);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	igt_stats_ensure_capacity(stats, 1);
 | 
						igt_stats_ensure_capacity(stats, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stats->values[stats->n_values++] = value;
 | 
						stats->values_u64[stats->n_values++] = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stats->mean_variance_valid = false;
 | 
						stats->mean_variance_valid = false;
 | 
				
			||||||
	stats->sorted_array_valid = false;
 | 
						stats->sorted_array_valid = false;
 | 
				
			||||||
@ -215,6 +225,38 @@ void igt_stats_push(igt_stats_t *stats, uint64_t value)
 | 
				
			|||||||
		stats->max = value;
 | 
							stats->max = value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * igt_stats_push:
 | 
				
			||||||
 | 
					 * @stats: An #igt_stats_t instance
 | 
				
			||||||
 | 
					 * @value: An floating point
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Adds a new value to the @stats dataset and converts the igt_stats from
 | 
				
			||||||
 | 
					 * an integer collection to a floating point one.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void igt_stats_push_float(igt_stats_t *stats, double value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						igt_stats_ensure_capacity(stats, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!stats->is_float) {
 | 
				
			||||||
 | 
							int n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (n = 0; n < stats->n_values; n++)
 | 
				
			||||||
 | 
								stats->values_f[n] = stats->values_u64[n];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							stats->is_float = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stats->values_f[stats->n_values++] = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stats->mean_variance_valid = false;
 | 
				
			||||||
 | 
						stats->sorted_array_valid = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (value < stats->range[0])
 | 
				
			||||||
 | 
							stats->range[0] = value;
 | 
				
			||||||
 | 
						if (value > stats->range[1])
 | 
				
			||||||
 | 
							stats->range[1] = value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * igt_stats_push_array:
 | 
					 * igt_stats_push_array:
 | 
				
			||||||
 * @stats: An #igt_stats_t instance
 | 
					 * @stats: An #igt_stats_t instance
 | 
				
			||||||
@ -242,6 +284,7 @@ void igt_stats_push_array(igt_stats_t *stats,
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
uint64_t igt_stats_get_min(igt_stats_t *stats)
 | 
					uint64_t igt_stats_get_min(igt_stats_t *stats)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						igt_assert(!stats->is_float);
 | 
				
			||||||
	return stats->min;
 | 
						return stats->min;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -253,6 +296,7 @@ uint64_t igt_stats_get_min(igt_stats_t *stats)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
uint64_t igt_stats_get_max(igt_stats_t *stats)
 | 
					uint64_t igt_stats_get_max(igt_stats_t *stats)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						igt_assert(!stats->is_float);
 | 
				
			||||||
	return stats->max;
 | 
						return stats->max;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -283,26 +327,39 @@ static int cmp_u64(const void *pa, const void *pb)
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int cmp_f(const void *pa, const void *pb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const double *a = pa, *b = pb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*a < *b)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						if (*a > *b)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void igt_stats_ensure_sorted_values(igt_stats_t *stats)
 | 
					static void igt_stats_ensure_sorted_values(igt_stats_t *stats)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (stats->sorted_array_valid)
 | 
						if (stats->sorted_array_valid)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!stats->sorted) {
 | 
						if (!stats->sorted_u64) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * igt_stats_ensure_capacity() will free ->sorted when the
 | 
							 * igt_stats_ensure_capacity() will free ->sorted when the
 | 
				
			||||||
		 * capacity increases, which also correspond to an invalidation
 | 
							 * capacity increases, which also correspond to an invalidation
 | 
				
			||||||
		 * of the sorted array. We'll then reallocate it here on
 | 
							 * of the sorted array. We'll then reallocate it here on
 | 
				
			||||||
		 * demand.
 | 
							 * demand.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		stats->sorted = calloc(stats->capacity, sizeof(*stats->values));
 | 
							stats->sorted_u64 = calloc(stats->capacity,
 | 
				
			||||||
		igt_assert(stats->sorted);
 | 
										   sizeof(*stats->values_u64));
 | 
				
			||||||
 | 
							igt_assert(stats->sorted_u64);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(stats->sorted, stats->values,
 | 
						memcpy(stats->sorted_u64, stats->values_u64,
 | 
				
			||||||
	       sizeof(*stats->values) * stats->n_values);
 | 
						       sizeof(*stats->values_u64) * stats->n_values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	qsort(stats->sorted, stats->n_values, sizeof(*stats->values), cmp_u64);
 | 
						qsort(stats->sorted_u64, stats->n_values, sizeof(*stats->values_u64),
 | 
				
			||||||
 | 
						      stats->is_float ? cmp_f : cmp_u64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stats->sorted_array_valid = true;
 | 
						stats->sorted_array_valid = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -326,7 +383,7 @@ igt_stats_get_median_internal(igt_stats_t *stats,
 | 
				
			|||||||
	if (n_values % 2 == 1) {
 | 
						if (n_values % 2 == 1) {
 | 
				
			||||||
		/* median is the value in the middle (actual datum) */
 | 
							/* median is the value in the middle (actual datum) */
 | 
				
			||||||
		mid = start + n_values / 2;
 | 
							mid = start + n_values / 2;
 | 
				
			||||||
		median = stats->sorted[mid];
 | 
							median = sorted_value(stats, mid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* the two halves contain the median value */
 | 
							/* the two halves contain the median value */
 | 
				
			||||||
		if (lower_end)
 | 
							if (lower_end)
 | 
				
			||||||
@ -342,7 +399,7 @@ igt_stats_get_median_internal(igt_stats_t *stats,
 | 
				
			|||||||
		 * values.
 | 
							 * values.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		mid = start + n_values / 2 - 1;
 | 
							mid = start + n_values / 2 - 1;
 | 
				
			||||||
		median = (stats->sorted[mid] + stats->sorted[mid + 1]) / 2.;
 | 
							median = (sorted_value(stats, mid) + sorted_value(stats, mid+1))/2.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (lower_end)
 | 
							if (lower_end)
 | 
				
			||||||
			*lower_end = mid + 1;
 | 
								*lower_end = mid + 1;
 | 
				
			||||||
@ -439,10 +496,10 @@ static void igt_stats_knuth_mean_variance(igt_stats_t *stats)
 | 
				
			|||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < stats->n_values; i++) {
 | 
						for (i = 0; i < stats->n_values; i++) {
 | 
				
			||||||
		double delta = stats->values[i] - mean;
 | 
							double delta = unsorted_value(stats, i) - mean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mean += delta / (i + 1);
 | 
							mean += delta / (i + 1);
 | 
				
			||||||
		m2 += delta * (stats->values[i] - mean);
 | 
							m2 += delta * (unsorted_value(stats, i) - mean);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stats->mean = mean;
 | 
						stats->mean = mean;
 | 
				
			||||||
@ -518,7 +575,7 @@ double igt_stats_get_iqm(igt_stats_t *stats)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	mean = 0;
 | 
						mean = 0;
 | 
				
			||||||
	for (i = 0; i <= q3 - q1; i++)
 | 
						for (i = 0; i <= q3 - q1; i++)
 | 
				
			||||||
		mean += (stats->sorted[q1 + i] - mean) / (i + 1);
 | 
							mean += (sorted_value(stats, q1 + i) - mean) / (i + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (stats->n_values % 4) {
 | 
						if (stats->n_values % 4) {
 | 
				
			||||||
		double rem = .5 * (stats->n_values % 4) / 4;
 | 
							double rem = .5 * (stats->n_values % 4) / 4;
 | 
				
			||||||
@ -526,8 +583,8 @@ double igt_stats_get_iqm(igt_stats_t *stats)
 | 
				
			|||||||
		q1 = (stats->n_values) / 4;
 | 
							q1 = (stats->n_values) / 4;
 | 
				
			||||||
		q3 = (3 * stats->n_values + 3) / 4;
 | 
							q3 = (3 * stats->n_values + 3) / 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mean += rem * (stats->sorted[q1] - mean) / i++;
 | 
							mean += rem * (sorted_value(stats, q1) - mean) / i++;
 | 
				
			||||||
		mean += rem * (stats->sorted[q3] - mean) / i++;
 | 
							mean += rem * (sorted_value(stats, q3) - mean) / i++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return mean;
 | 
						return mean;
 | 
				
			||||||
 | 
				
			|||||||
@ -34,17 +34,27 @@
 | 
				
			|||||||
 * @n_values: The number of pushed values
 | 
					 * @n_values: The number of pushed values
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
	uint64_t *values;
 | 
						union {
 | 
				
			||||||
 | 
							uint64_t *values_u64;
 | 
				
			||||||
 | 
							double *values_f;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	unsigned int n_values;
 | 
						unsigned int n_values;
 | 
				
			||||||
 | 
						unsigned int is_float : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*< private >*/
 | 
						/*< private >*/
 | 
				
			||||||
	unsigned int capacity;
 | 
						unsigned int capacity;
 | 
				
			||||||
	unsigned int is_population  : 1;
 | 
						unsigned int is_population  : 1;
 | 
				
			||||||
	unsigned int mean_variance_valid : 1;
 | 
						unsigned int mean_variance_valid : 1;
 | 
				
			||||||
	unsigned int sorted_array_valid : 1;
 | 
						unsigned int sorted_array_valid : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint64_t min, max;
 | 
						uint64_t min, max;
 | 
				
			||||||
 | 
						double range[2];
 | 
				
			||||||
	double mean, variance;
 | 
						double mean, variance;
 | 
				
			||||||
	uint64_t *sorted;
 | 
					
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							uint64_t *sorted_u64;
 | 
				
			||||||
 | 
							double *sorted_f;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
} igt_stats_t;
 | 
					} igt_stats_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void igt_stats_init(igt_stats_t *stats);
 | 
					void igt_stats_init(igt_stats_t *stats);
 | 
				
			||||||
@ -53,6 +63,7 @@ void igt_stats_fini(igt_stats_t *stats);
 | 
				
			|||||||
bool igt_stats_is_population(igt_stats_t *stats);
 | 
					bool igt_stats_is_population(igt_stats_t *stats);
 | 
				
			||||||
void igt_stats_set_population(igt_stats_t *stats, bool full_population);
 | 
					void igt_stats_set_population(igt_stats_t *stats, bool full_population);
 | 
				
			||||||
void igt_stats_push(igt_stats_t *stats, uint64_t value);
 | 
					void igt_stats_push(igt_stats_t *stats, uint64_t value);
 | 
				
			||||||
 | 
					void igt_stats_push_float(igt_stats_t *stats, double value);
 | 
				
			||||||
void igt_stats_push_array(igt_stats_t *stats,
 | 
					void igt_stats_push_array(igt_stats_t *stats,
 | 
				
			||||||
			  const uint64_t *values, unsigned int n_values);
 | 
								  const uint64_t *values, unsigned int n_values);
 | 
				
			||||||
uint64_t igt_stats_get_min(igt_stats_t *stats);
 | 
					uint64_t igt_stats_get_min(igt_stats_t *stats);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user