This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR fortran/41157 -- dtime gives inconsistent results.
- From: Steve Kargl <sgk at troutmask dot apl dot washington dot edu>
- To: fortran at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Mon, 24 Aug 2009 13:48:47 -0700
- Subject: [PATCH] Fix PR fortran/41157 -- dtime gives inconsistent results.
Here's a patch for fortran/41157. dtime is documented
to return the execution since its last invocation. For
x reasons that I don't fully understand, the current
implementation of dtime seems to skip saving the current
execution time on every other invocation.
For an unpatched gfortran, this code
program test_dtime
implicit none
integer :: i, k
real, dimension(2) :: tarray
real result, accum, x
accum = 0.e0
do k=1, 10
call loop(k, x)
call dtime(tarray, result)
print '(4F10.6)', tarray, result, x
accum = accum + tarray(1)
end do
print '(''accum ='', F10.5)', accum
end program test_dtime
subroutine loop(k, x)
integer, intent(in) :: k
real, intent(out) :: x
x = 1.
do i = 1, 10000000
x = sin(x * i + 1.)
end do
x = x / k
end subroutine loop
REMOVE:kargl[310] ./z
0.442741 0.000000 0.442741 0.927705
0.442212 0.000000 0.442212 0.463853
0.884233 0.000000 0.884233 0.309235
0.884425 0.000000 0.884425 0.231926
1.326463 0.000000 1.326463 0.185541
1.326812 0.000000 1.326812 0.154618
1.768775 0.000000 1.768775 0.132529
1.768707 0.000000 1.768707 0.115963
2.209823 0.000000 2.209823 0.103078
2.209864 0.000000 2.209864 0.092771
accum = 13.26406
The first column should be 0.44xxx. The second column is
0.00000 and the third column is the sum of the first two.
The last column is the output from the loop() to prevent
the optimizer from removing the call to loop().
While a patched gfortran now yields
REMOVE:kargl[299] ./z
0.441574 0.000000 0.441574 0.927705
0.441296 0.000000 0.441296 0.463853
0.441349 0.000000 0.441349 0.309235
0.441090 0.000000 0.441090 0.231926
0.441855 0.000000 0.441855 0.185541
0.442233 0.000000 0.442233 0.154618
0.442404 0.000000 0.442404 0.132529
0.442425 0.000000 0.442425 0.115963
0.442323 0.000000 0.442323 0.103078
0.441952 0.000000 0.441952 0.092771
accum = 4.41850
2009-08-24 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/41157
* dtime.c (dtime_sub): Fix computing time increment.
* time_1.h: Add <sys/types.h> header. Use RUSAGE_SELF macro instead
of a hardcoded 0.
OK for trunk and 4.4?
--
Steve
Index: dtime.c
===================================================================
--- dtime.c (revision 151026)
+++ dtime.c (working copy)
@@ -38,9 +38,10 @@ iexport_proto(dtime_sub);
void
dtime_sub (gfc_array_r4 *t, GFC_REAL_4 *result)
{
- static GFC_REAL_4 tu = 0.0, ts = 0.0, tt = 0.0;
GFC_REAL_4 *tp;
long user_sec, user_usec, system_sec, system_usec;
+ static long us = 0, uu = 0, ss = 0 , su = 0;
+ GFC_REAL_4 tu, ts, tt;
if (((GFC_DESCRIPTOR_EXTENT(t,0))) < 2)
runtime_error ("Insufficient number of elements in TARRAY.");
@@ -48,15 +49,19 @@ dtime_sub (gfc_array_r4 *t, GFC_REAL_4 *
__gthread_mutex_lock (&dtime_update_lock);
if (__time_1 (&user_sec, &user_usec, &system_sec, &system_usec) == 0)
{
- tu = (GFC_REAL_4)(user_sec + 1.e-6 * user_usec) - tu;
- ts = (GFC_REAL_4)(system_sec + 1.e-6 * system_usec) - ts;
+ tu = (GFC_REAL_4) ((user_sec - us) + 1.e-6 * (user_usec - uu));
+ ts = (GFC_REAL_4) ((system_sec - ss) + 1.e-6 * (system_usec - su));
tt = tu + ts;
+ us = user_sec;
+ uu = user_usec;
+ ss = system_sec;
+ su = system_usec;
}
else
{
- tu = (GFC_REAL_4)-1.0;
- ts = (GFC_REAL_4)-1.0;
- tt = (GFC_REAL_4)-1.0;
+ tu = -1;
+ ts = -1;
+ tt = -1;
}
tp = t->data;
Index: time_1.h
===================================================================
--- time_1.h (revision 151026)
+++ time_1.h (working copy)
@@ -51,6 +51,10 @@ see the files COPYING3 and COPYING.RUNTI
# endif
#endif
+#ifdef HAVE_SYS_TYPES_H
+ #include <sys/types.h>
+#endif
+
/* The most accurate way to get the CPU time is getrusage (). */
#if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
# include <sys/resource.h>
@@ -112,7 +116,7 @@ __time_1 (long *user_sec, long *user_use
{
#if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
struct rusage usage;
- getrusage (0, &usage);
+ getrusage (RUSAGE_SELF, &usage);
*user_sec = usage.ru_utime.tv_sec;
*user_usec = usage.ru_utime.tv_usec;