I'm using a time_t variable in C (openMP enviroment) to keep cpu execution time...I define a float value sum_tot_time to sum time for all cpu's...I mean sum_tot_time is the sum of cpu's time_t values. The problem is that printing the value sum_tot_time it appear as an integer or long, by the way without its decimal part!
I tried in these ways:
to printf sum_tot_time as a double being a double value
to printf sum_tot_time as float being a float value
to printf sum_tot_time as double being a time_t value
to printf sum_tot_time as float being a time_t value
The resolution of time_t is at most one second on most platforms. That is, on most platforms, time_t will be an integer (32- or 64-bit) value counting the number of seconds elapsed since midnight of Jan 1st 1970 (UTC), and can only achieve one-second resolution.
Therefore, a sum of time_t values will also only exhibit one-second resolution (no decimal part, even after converting to double.)
The above having been said, what native or OpenMP call are you using to obtain the time_t values that you are attempting to accumulate?
If using either the native *nix getrusage() call to fill out an rusage structure (provided your platform supports it) with user/kernel times, or if using gettimeofday() to get wall time, then use both the tv_sec and tv_usec fields of struct timeval to generate a double value (of millisecond-or-better resolution, typically), and use that instead of time_t in your calculations:
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
Correspondingly, you can use GetThreadTimes/GetProcessTimes for user/kernel times or _ftime for wall time on Windows platforms, then combine FILETIME::dwHighDateTime/dwLowDateTime.
I'm not sure if you have access to standard *nix system calls ( or if this is relevant to specifically to what you're doing ), but if you do you can use the timeval struct and gettimeofday. For example, to print out a timestamp with six decimal places of precision which produces a tcpdump style time stamp ( courtesy of Steven UNP )
#include "unp.h"
#include <time.h>
char *
gf_time(void)
{
struct timeval tv;
time_t t;
static char str[30];
char *ptr;
if (gettimeofday(&tv, NULL) < 0)
err_sys("gettimeofday error");
t = tv.tv_sec; /* POSIX says tv.tv_sec is time_t; some BSDs don't agree. */
ptr = ctime(&t);
strcpy(str, &ptr[11]);
/* Fri Sep 13 00:00:00 1986\n\0 */
/* 0123456789012345678901234 5 */
snprintf(str+8, sizeof(str)-8, ".%06ld", tv.tv_usec);
return(str);
}
Related
double timespec_delta2milliseconds(struct timespec *last, struct timespec *previous)
{
return (last->tv_sec - previous->tv_sec) + (last->tv_nsec - previous->tv_nsec)*pow(10,-3);
}
This function computes the difference (last - previous) and returns the result expressed in milliseconds as a double. I tried a lot of different ways but if I don't do like this i receve in output segmentation fault.
I think that this solution works but it's wrong, someone can help me ?
The timespec structure can handle fractions of a second, and the tv_nsec is the fractions, represented as nanoseconds.
That means getting the difference between two timespec structures isn't as straight-forward as you make it seem in your code.
Here's an example on how to get the difference, returned as a new timesepc structure:
struct timespec diff_timespec(const struct timespec *time1, const struct timespec *time0)
{
struct timespec diff = {
.tv_sec = time1->tv_sec - time0->tv_sec,
.tv_nsec = time1->tv_nsec - time0->tv_nsec
};
if (diff.tv_nsec < 0)
{
diff.tv_nsec += 1000000000;
diff.tv_sec--;
}
return diff;
}
You need two functions: sub_timespec(), which calculates the difference between two time spec values, and timespec_as_milliseconds(), which returns the number of milliseconds in a time spec value as an integer.
enum { NS_PER_SECOND = 1000000000 };
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec *td)
{
td->tv_nsec = t2.tv_nsec - t1.tv_nsec;
td->tv_sec = t2.tv_sec - t1.tv_sec;
if (td->tv_sec > 0 && td->tv_nsec < 0)
{
td->tv_nsec += NS_PER_SECOND;
td->tv_sec--;
}
else if (td->tv_sec < 0 && td->tv_nsec > 0)
{
td->tv_nsec -= NS_PER_SECOND;
td->tv_sec++;
}
}
int64_t timespec_as_milliseconds(struct timespec ts)
{
int64_t rv = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
return rv;
}
If you want to round the milliseconds, it gets trickier because you have to worry about carries and negative numbers and so on. You should not encounter a timespec value where the tv_sec and tv_nsec values have opposite signs (zeros aren't a problem).
In your code, adding pow(10, -3) mixes floating point arithmetic with integer arithmetic — usually not a good idea.
If you want a double value with up to 3 decimal places of fractional seconds, then you need:
double timespec_to_double_milliseconds(struct timespec ts)
{
double rv = ts.tv_sec + (ts.tv_nsec / 1000000) / 1000.0;
return rv;
}
The first division is (deliberately) integer division; the second gives a floating-point value. Again, rounding has problems with carrying and so on.
Your function then becomes:
double timespec_delta2milliseconds(struct timespec *last, struct timespec *previous)
{
struct timespec delta = sub_timespec(*last, *previous);
return timespec_to_double_milliseconds(delta);
}
You can use an extra value in the function so it is easier to print the value returned in a debugger: double rv = timespec_to_double_milliseconds(delta); return rv;.
The key idea, though, is to do separate tasks in separate functions. Taking the difference between two struct timespec values is one task; converting a struct timespec value to an appropriate double is a separate task. When you can split things into separate tasks, you should.
I often pass struct timespec values by value rather than pointer. The structure size is typically small enough that it is not a stress on the stack or registers. I return them by value too, which simplifies memory management — YMMV.
And, just in case it isn't clear, the tv_sec member of a struct timespec contains an integer number of seconds, and the tv_nsec contains the fractional part of a second expressed as a number of nanoseconds (0 to 999,999,999). It requires care in printing the tv_nsec value; you need a format such as %.9ld to print 9 digits with leading zeros, and the type is long. To print microseconds, divide the tv_nsec value by 1,000 and change 9 to 6; to print milliseconds, divide by 1,000,000 and change 9 to 3. Beware negative values!
I am trying to code a function which populates a struct tm from year, month, day, hour and minutes values.
The application deals with no time zone information, i.e., we assume that the input data time zone matches with the application and user time zone.
I have tried this:
void timeCreate(struct tm* pTm1, int year, int month, int day, int hour, int minute) {
pTm1->tm_year = year - 1900;
pTm1->tm_mon = month - 1;
pTm1->tm_mday = day;
pTm1->tm_hour = hour;
pTm1->tm_min = minute;
pTm1->tm_sec = 0;
pTm1->tm_isdst = -1;
mktime(pTm1);
}
If I don't do anything else, I get the CET time set by mktime (CET is my local timezone) and it seems that mktime changes the time and date, so it is no longer 2014/01/01 00:00 but the day before.
If I do this:
pTm1->tm_gmtoff = 0;
pTm1->tm_zone = "UTC";
Then I do not get any correction.
I have also seen the function gmtime() instead of mktime(). Which would be the "right" way of setting up this struct?
Also I get a random value for tm_wday, can that value be calculated automatically?
mktime only works with local time, and its behavior is constrained by the specification so that it cannot examine any nonstandard fields of struct tm like tm_gmtoff. And gmtime is not an analog of mktime but of localtime - it converts in the opposite direction. If you want a normalization/conversion of broken-down UTC time in struct tm format to time_t, you need to either use the nonstandard but widely available timegm function, or write it out yourself. Thankfully POSIX exactly specifies the formula:
tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
(tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
Note that if copied as written to C code, this is full of integer overflows, so some type promotions or other fixes need to be introduced to make it valid.
If you need the normalization aspect timegm also performs, but need it done portably without depending on the nonportable timegm, you can just call gmtime_r after using the above formula to invert it and get a normalized result.
Do I have to populate tm_gmtoff and tm_zone?
Which would be the "right" way of setting up this struct?
For portable code, yes.
The C spec has
"The tm structure shall contain at least the following members, in any order." (C spec) --> struct tm has at least the following 9 members:
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
And may include others like tm_gmtoff, tm_zone, tm_msec, etc.
The mktime function converts the broken-down time, expressed as local time, in the structure pointed to by timeptr into a calendar time value with the same encoding as that of the values returned by the time function. The original values of the tm_wday and tm_yday components of the structure are ignored, and the original values of the other components are not restricted to the ranges indicated above. ...
... On successful completion, the values of the tm_wday and tm_yday components of the structure are set appropriately, and the other components are set to represent the specified calendar time, but with their values forced to the ranges indicated above; the final value of tm_mday is not set until tm_mon and tm_year are determined.
C17dr § 7.27.2.3 2
Since mktime() is only specified to ignore tm_wday and tm_yday, all other members may contribute to the result. There is no C spec that limits the result to 7 of the above required members.
Good programing practice would zero out all members not explicitly initialized/assigned before calling mktime().
void timeCreate(struct tm* pTm1, int year, int month, int day, int hour, int minute) {
memset(pTm1, 0, sizeof *pTm1); // Zero all members.
pTm1->tm_year = year - 1900;
pTm1->tm_mon = month - 1;
pTm1->tm_mday = day;
pTm1->tm_hour = hour;
pTm1->tm_min = minute;
pTm1->tm_sec = 0;
pTm1->tm_isdst = -1;
mktime(pTm1);
// recommend to return the result of mktime() so caller can ID invalid timestamps.
}
If you code is used on a sub-set of platforms, it may get away without such zeroing assignments.
I can get current time using the timespec_get C11 function. Supposedly I want to retrieve the timespec value of the next milliseconds of the current time, how should I write the get_due_time function?
struct timespec get_due_time(long ms) {
struct timespec now, due;
timespec_get(&now, TIME_UTC);
...
return due;
}
struct timespec get_due_time(long ms)
{
assert(ms >= 0);
struct timespec now, due;
timespec_get(&now, TIME_UTC);
due.tv_sec = now.tv_sec + ms / 1000;
due.tv_nsec = now.tv_nsec + (ms % 1000) * 1000000;
if (due.tv_nsec >= 1000000000)
{
due.tv_nsec -= 1000000000;
due.tv_sec++;
}
return due;
}
Deal with big values of ms by adding whole seconds to the seconds part of the current time (there are 1000 milliseconds in a second). Deal with the sub-second part of the value of ms by multiplying by one million (the number of nanoseconds in a millisecond). Deal with overflow of tv_nsec by subtracting one billion (the number of nanoseconds in a second) from tv_nsec and incrementing the tv_sec part. The arithmetic is safe assuming timespec_get() returns a normalized struct timespec value (so tv_nsec is in the range 0..999,999,999.
You could simply modify now and return it instead of creating and modifying due. That's not a significant problem, though.
You could create and use names like:
enum
{
MILLISECONDS_PER_SECOND = 1000,
NANOSECONDS_PER_SECOND = 1000000000,
NANOSECONDS_PER_MILLISECOND = NANOSECONDS_PER_SECOND / MILLISECONDS_PER_SECOND
};
I'm not sure whether that's worth it.
If you need to handle negative offsets (negative values for ms), you have more work to do, dealing with negative results tv_nsec after adding a negative quantity and decrementing tv_sec if necessary.
Please, consider the following program:
#include <stdio.h>
#include <time.h>
#define N 10000
int main ()
{
time_t begin1,end1;
float diff1;
int begin2, end2, diff2;
int i;
begin1 = time (NULL);
begin2 = time (NULL);
//consuming time
for(i=0;i<N;i++){
printf("%.2f%%\n",(i/(float)N)*100);
}
end1 = time (NULL);
end2 = time (NULL);
diff1 = difftime(end1, begin1);
diff2 = end2-begin2;
printf("%f\t%d\n",diff1, diff2);
return 0;
}
We can see that the program works perfectly. It calculates the time differences in two ways. And both provide the same answer. I'm wondering why it is possible to implicit convert the result of calling time(NULL) to an integer variable in this way.
I'm wondering why it is possible to implicit convert the result of calling time(NULL) to an integer variable in this way.
No, not for portable robust code and get consistent expected results.
difftime() returns a double. Saving as a float can certainly lose range and precision. It returns the difference in seconds.
// float diff1;
double diff1 = difftime(end1, begin1);
time_t type is a scalar. Commonly that is some wide integer and commonly a signed integer. Yet it not need be. Saving as an int can lose range (not uncommon) and precision if time_t was some floating point type (rare). time_t is often scaled in seconds, but that is not required by C. Others units are possible.
// int begin2 = time (NULL);
time_t begin2 = time (NULL);
...
// int end2 = time (NULL);
time_t end2 = time (NULL);
printf("%f\n",difftime(end2, begin2));
How the casting of time_t works in C?
Detail. OP's post does not cast anything, except go (float)N. The code does assign a time_t to an int and causes a conversion. That is similar to casting though.
First, check the prototype of time():
time_t time (time_t* timer);
where you can see that the return type is time_t, which generally is implemented as a long integer.
That is not standard though, which means you can't rely on this when you have to take portability into account.
Read more in What is ultimately a time_t typedef to?
I have two date and time strings separately in variables. I need to calculate the difference between these 2 date and time values in milliseconds. How to get that in C. The solution should work across platforms(at least windows and unix).
char date1[] = {"26/11/2015"};
char time1[] = {"20:22:19"};
char date2[] = {"26/11/2015"};
char time2[] = {"20:23:19"};
First I need to save this into some time structure and then compare 2 time structures to get the difference. What is the time structure which is available in C Library to do this.
Use mktime() and difftime()
The mktime function returns the specified calendar time encoded as a value of type time_t. If the calendar time cannot be represented, the function returns the value (time_t)(-1). C11dr §7.27.2.3 4
The difftime function returns the difference expressed in seconds as a double §7.27.2.2 2
#include <time.h>
#include <stdlib.h>
#include <string.h>
time_t parse_dt(const char *mdy, const char *hms) {
struct tm tm;
memset(&tm, 0, sizeof tm);
if (3 != sscanf(mdy, "%d/%d/%d", &tm.tm_mon, &tm.tm_mday, &tm.tm_year)) return -1;
tm.tm_year -= 1900;
tm.tm_mday++;
if (3 != sscanf(hms, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec)) return -1;
tm.tm_isdst = -1; // Assume local time
return mktime(&tm);
}
int main() {
// application
char date1[] = { "26/11/2015" };
char time1[] = { "20:22:19" };
char date2[] = { "26/11/2015" };
char time2[] = { "20:23:19" };
time_t t1 = parse_dt(date1, time1);
time_t t2 = parse_dt(date2, time2);
if (t1 == -1 || t2 == -1) return 1;
printf("Time difference %.3f\n", difftime(t2, t1) * 1000.0);
return 0;
}
Output
Time difference 60000.000
from the man page for mktime()
this is the prototype for mktime()
time_t mktime(struct tm *tm);
this is the description of the function mktime()
The mktime() function takes an argument representing
broken-down time which is a representation separated into year, month,
day, and so on.
Broken-down time is stored in the structure tm which is defined in
<time.h> as follows:
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
The members of the tm structure are:
tm_sec The number of seconds after the minute, normally in the range
0 to 59, but can be up to 60 to allow for leap seconds.
tm_min The number of minutes after the hour, in the range 0 to 59.
tm_hour The number of hours past midnight, in the range 0 to 23.
tm_mday The day of the month, in the range 1 to 31.
tm_mon The number of months since January, in the range 0 to 11.
tm_year The number of years since 1900.
tm_wday The number of days since Sunday, in the range 0 to 6.
tm_yday The number of days since January 1, in the range 0 to 365.
tm_isdst A flag that indicates whether daylight saving time is in
effect at the time described. The value is positive if day‐
light saving time is in effect, zero if it is not, and nega‐
tive if the information is not available.
The mktime() function converts a broken-down time structure, expressed
as local time, to calendar time representation. The function ignores
the values supplied by the caller in the tm_wday and tm_yday fields.
The value specified in the tm_isdst field informs mktime() whether or
not daylight saving time (DST) is in effect for the time supplied in
the tm structure: a positive value means DST is in effect; zero means
that DST is not in effect; and a negative value means that mktime()
should (use timezone information and system databases to) attempt to
determine whether DST is in effect at the specified time.
The mktime() function modifies the fields of the tm structure as fol‐
lows: tm_wday and tm_yday are set to values determined from the con‐
tents of the other fields; if structure members are outside their valid
interval, they will be normalized (so that, for example, 40 October is
changed into 9 November); tm_isdst is set (regardless of its initial
value) to a positive value or to 0, respectively, to indicate whether
DST is or is not in effect at the specified time. Calling mktime()
also sets the external variable tzname with information about the cur‐
rent timezone.
If the specified broken-down time cannot be represented as calendar
time (seconds since the Epoch), mktime() returns (time_t) -1 and does
not alter the members of the broken-down time structure.
==========================================
this is from the man page for difftime()
this is the prototype:
double difftime(time_t time1, time_t time0);
This is the description:
The difftime() function returns the number of seconds elapsed between
time time1 and time time0, represented as a double. Each of the times
is specified in calendar time, which means its value is a measurement
(in seconds) relative to the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
to get the result in seconds. To get the results in milliseconds, multiply by 1000.0