regression.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2009, 2010, 2011, 2015 Université de Bordeaux
  4. * Copyright (C) 2010, 2011 CNRS
  5. *
  6. * StarPU is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * StarPU is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  16. */
  17. #include <core/perfmodel/regression.h>
  18. #define MAXREGITER 1000
  19. #define EPS 1.0e-10
  20. static double compute_b(double c, unsigned n, unsigned *x, double *y)
  21. {
  22. double b;
  23. /* X = log (x) , Y = log (y - c) */
  24. double sumxy = 0.0;
  25. double sumx = 0.0;
  26. double sumx2 = 0.0;
  27. double sumy = 0.0;
  28. unsigned i;
  29. for (i = 0; i < n; i++)
  30. {
  31. double xi = log(x[i]);
  32. double yi = log(y[i]-c);
  33. sumxy += xi*yi;
  34. sumx += xi;
  35. sumx2 += xi*xi;
  36. sumy += yi;
  37. }
  38. b = (n * sumxy - sumx * sumy) / (n*sumx2 - sumx*sumx);
  39. return b;
  40. }
  41. static double compute_a(double c, double b, unsigned n, unsigned *x, double *y)
  42. {
  43. double a;
  44. /* X = log (x) , Y = log (y - c) */
  45. double sumx = 0.0;
  46. double sumy = 0.0;
  47. unsigned i;
  48. for (i = 0; i < n; i++)
  49. {
  50. double xi = log(x[i]);
  51. double yi = log(y[i]-c);
  52. sumx += xi;
  53. sumy += yi;
  54. }
  55. a = (sumy - b*sumx) / n;
  56. return a;
  57. }
  58. /* returns r */
  59. static double test_r(double c, unsigned n, unsigned *x, double *y)
  60. {
  61. double r;
  62. // printf("test c = %e\n", c);
  63. /* X = log (x) , Y = log (y - c) */
  64. double sumxy = 0.0;
  65. double sumx = 0.0;
  66. double sumx2 = 0.0;
  67. double sumy = 0.0;
  68. double sumy2 = 0.0;
  69. unsigned i;
  70. for (i = 0; i < n; i++)
  71. {
  72. double xi = log(x[i]);
  73. double yi = log(y[i]-c);
  74. // printf("Xi = %e, Yi = %e\n", xi, yi);
  75. sumxy += xi*yi;
  76. sumx += xi;
  77. sumx2 += xi*xi;
  78. sumy += yi;
  79. sumy2 += yi*yi;
  80. }
  81. //printf("sumxy %e\n", sumxy);
  82. //printf("sumx %e\n", sumx);
  83. //printf("sumx2 %e\n", sumx2);
  84. //printf("sumy %e\n", sumy);
  85. //printf("sumy2 %e\n", sumy2);
  86. r = (n * sumxy - sumx * sumy) / sqrt( (n* sumx2 - sumx*sumx) * (n*sumy2 - sumy*sumy) );
  87. return r;
  88. }
  89. static unsigned find_list_size(struct starpu_perfmodel_history_list *list_history)
  90. {
  91. unsigned cnt = 0;
  92. struct starpu_perfmodel_history_list *ptr = list_history;
  93. while (ptr)
  94. {
  95. cnt++;
  96. ptr = ptr->next;
  97. }
  98. return cnt;
  99. }
  100. static double find_list_min(double *y, unsigned n)
  101. {
  102. double min = 1.0e30;
  103. unsigned i;
  104. for (i = 0; i < n; i++)
  105. {
  106. min = STARPU_MIN(min, y[i]);
  107. }
  108. return min;
  109. }
  110. static void dump_list(unsigned *x, double *y, struct starpu_perfmodel_history_list *list_history)
  111. {
  112. struct starpu_perfmodel_history_list *ptr = list_history;
  113. unsigned i = 0;
  114. while (ptr)
  115. {
  116. x[i] = ptr->entry->size;
  117. y[i] = ptr->entry->mean;
  118. ptr = ptr->next;
  119. i++;
  120. }
  121. }
  122. /* y = ax^b + c
  123. * return 0 if success, -1 otherwise
  124. * if success, a, b and c are modified
  125. * */
  126. int _starpu_regression_non_linear_power(struct starpu_perfmodel_history_list *ptr, double *a, double *b, double *c)
  127. {
  128. unsigned n = find_list_size(ptr);
  129. STARPU_ASSERT(n);
  130. unsigned *x = (unsigned *) malloc(n*sizeof(unsigned));
  131. STARPU_ASSERT(x);
  132. double *y = (double *) malloc(n*sizeof(double));
  133. STARPU_ASSERT(y);
  134. dump_list(x, y, ptr);
  135. double cmin = 0.0;
  136. double cmax = find_list_min(y, n);
  137. unsigned iter;
  138. double err = 100000.0;
  139. for (iter = 0; iter < MAXREGITER; iter++)
  140. {
  141. double c1, c2;
  142. double r1, r2;
  143. double radius = 0.01;
  144. c1 = cmin + (0.5-radius)*(cmax - cmin);
  145. c2 = cmin + (0.5+radius)*(cmax - cmin);
  146. r1 = test_r(c1, n, x, y);
  147. r2 = test_r(c2, n, x, y);
  148. double err1, err2;
  149. err1 = fabs(1.0 - r1);
  150. err2 = fabs(1.0 - r2);
  151. if (err1 < err2)
  152. {
  153. cmax = (cmin + cmax)/2;
  154. }
  155. else
  156. {
  157. /* 2 is better */
  158. cmin = (cmin + cmax)/2;
  159. }
  160. if (fabs(err - STARPU_MIN(err1, err2)) < EPS)
  161. break;
  162. err = STARPU_MIN(err1, err2);
  163. }
  164. *c = (cmin + cmax)/2;
  165. *b = compute_b(*c, n, x, y);
  166. *a = exp(compute_a(*c, *b, n, x, y));
  167. free(x);
  168. free(y);
  169. return 0;
  170. }