Mac OS X의 clock_gettime 대체 기능
MacPorts를 통해 필요한 라이브러리를 설치한 후 Mac OS X에 작성한 프로그램을 컴파일할 때 다음 오류가 발생합니다.
In function 'nanotime':
error: 'CLOCK_REALTIME' undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)
인 것 같다clock_gettime
는 Mac OS X에서는 구현되지 않습니다.에폭 시간을 나노초 단위로 취득할 수 있는 대체 수단이 있습니까?불행하게도gettimeofday
단위는 마이크로초입니다.
몇 시간 동안 다양한 답변, 블로그 및 헤더를 검토한 후 현재 시간을 얻을 수 있는 휴대용 방법을 찾았습니다.
#include <time.h>
#include <sys/time.h>
#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#endif
struct timespec ts;
#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_REALTIME, &ts);
#endif
또는 다음 요지를 확인해 주십시오.https://gist.github.com/1087739
이걸로 시간을 절약할 수 있길 바랍니다.건배!
필요한 모든 것은 테크니컬 Q&A QA1398에 설명되어 있습니다. 테크니컬 Q&A QA1398: 마하 절대시간 단위, 기본적으로 필요한 기능은 다음과 같습니다.mach_absolute_time
.
다음은 마하 호출을 사용하여 모든 작업을 수행하는 이 페이지의 약간 이전 버전의 샘플 코드입니다(현재 버전은AbsoluteToNanoseconds
를 참조해 주세요).현재의 OS X(즉, x86_64의 Snow Leopard의 경우)에서는 절대 시간 값은 실제로 나노초 단위이므로 변환이 전혀 필요하지 않습니다.따라서 휴대용 코드를 잘 쓰고 있다면 변환할 수 있지만 자신을 위해 빠르고 더러운 일을 하고 있다면 신경 쓸 필요가 없습니다.
WWIW,mach_absolute_time
정말 빨라요.
uint64_t GetPIDTimeInNanoseconds(void)
{
uint64_t start;
uint64_t end;
uint64_t elapsed;
uint64_t elapsedNano;
static mach_timebase_info_data_t sTimebaseInfo;
// Start the clock.
start = mach_absolute_time();
// Call getpid. This will produce inaccurate results because
// we're only making a single system call. For more accurate
// results you should call getpid multiple times and average
// the results.
(void) getpid();
// Stop the clock.
end = mach_absolute_time();
// Calculate the duration.
elapsed = end - start;
// Convert to nanoseconds.
// If this is the first time we've run, get the timebase.
// We can use denom == 0 to indicate that sTimebaseInfo is
// uninitialised because it makes no sense to have a zero
// denominator is a fraction.
if ( sTimebaseInfo.denom == 0 ) {
(void) mach_timebase_info(&sTimebaseInfo);
}
// Do the maths. We hope that the multiplication doesn't
// overflow; the price you pay for working in fixed point.
elapsedNano = elapsed * sTimebaseInfo.numer / sTimebaseInfo.denom;
printf("multiplier %u / %u\n", sTimebaseInfo.numer, sTimebaseInfo.denom);
return elapsedNano;
}
macOS Sierra 10.12는 clock_gettime()을 지원하게 되었습니다.
#include <stdio.h>
#include <time.h>
int main() {
struct timespec res;
struct timespec time;
clock_getres(CLOCK_REALTIME, &res);
clock_gettime(CLOCK_REALTIME, &time);
printf("CLOCK_REALTIME: res.tv_sec=%lu res.tv_nsec=%lu\n", res.tv_sec, res.tv_nsec);
printf("CLOCK_REALTIME: time.tv_sec=%lu time.tv_nsec=%lu\n", time.tv_sec, time.tv_nsec);
}
nanoseconds를 제공하지만 해상도는 1000이므로 실질적으로 마이크로초로 제한됩니다.
CLOCK_REALTIME: res.tv_sec=0 res.tv_nsec=1000
CLOCK_REALTIME: time.tv_sec=1475279260 time.tv_nsec=525627000
이 기능을 사용하려면 XCode 8 이후가 필요합니다.이 기능을 사용하기 위해 컴파일된 코드는 Mac OS X(10.11 이전) 버전에서는 실행되지 않습니다.
위의 솔루션 중 어느 것도 질문에 답하지 않습니다.완벽한 Unix 시간을 제공하지 않거나 정확도가 1마이크로초입니다.jbenet에 의해 가장 인기 있는 솔루션은 저속(~6000ns)이며, 반환된 값은 나노초 단위로 계산되지 않습니다.아래는 jbenet과 Dmitri B가 제안한 2가지 솔루션에 대한 테스트와 이에 대한 저의 견해입니다.변경 없이 코드를 실행할 수 있습니다.
세 번째 솔루션은 나노초 단위로 계산되며 UNIX 절대 시간을 상당히 빠르게(~90ns) 제공합니다.도움이 된다고 생각하시는 분은, 이쪽에서 알려 주세요:-)저는 Dmitri B(코드의 솔루션 넘버1)의 것을 고집합니다.이것은 제 요구에 더 잘 맞습니다.
pthread_…timed를 만들기 위해 clock_gettime() 대신 상용 품질이 필요했습니다.이 토론이 매우 도움이 되었습니다.여러분 감사합니다.
/*
Ratings of alternatives to clock_gettime() to use with pthread timed waits:
Solution 1 "gettimeofday":
Complexity : simple
Portability : POSIX 1
timespec : easy to convert from timeval to timespec
granularity : 1000 ns,
call : 120 ns,
Rating : the best.
Solution 2 "host_get_clock_service, clock_get_time":
Complexity : simple (error handling?)
Portability : Mac specific (is it always available?)
timespec : yes (struct timespec return)
granularity : 1000 ns (don't be fooled by timespec format)
call time : 6000 ns
Rating : the worst.
Solution 3 "mach_absolute_time + gettimeofday once":
Complexity : simple..average (requires initialisation)
Portability : Mac specific. Always available
timespec : system clock can be converted to timespec without float-math
granularity : 1 ns.
call time : 90 ns unoptimised.
Rating : not bad, but do we really need nanoseconds timeout?
References:
- OS X is UNIX System 3 [U03] certified
http://www.opengroup.org/homepage-items/c987.html
- UNIX System 3 <--> POSIX 1 <--> IEEE Std 1003.1-1988
http://en.wikipedia.org/wiki/POSIX
http://www.unix.org/version3/
- gettimeofday() is mandatory on U03,
clock_..() functions are optional on U03,
clock_..() are part of POSIX Realtime extensions
http://www.unix.org/version3/inttables.pdf
- clock_gettime() is not available on MacMini OS X
(Xcode > Preferences > Downloads > Command Line Tools = Installed)
- OS X recommends to use gettimeofday to calculate values for timespec
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/pthread_cond_timedwait.3.html
- timeval holds microseconds, timespec - nanoseconds
http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
- microtime() is used by kernel to implement gettimeofday()
http://ftp.tw.freebsd.org/pub/branches/7.0-stable/src/sys/kern/kern_time.c
- mach_absolute_time() is really fast
http://www.opensource.apple.com/source/Libc/Libc-320.1.3/i386/mach/mach_absolute_time.c
- Only 9 deciaml digits have meaning when int nanoseconds converted to double seconds
Tutorial: Performance and Time post uses .12 precision for nanoseconds
http://www.macresearch.org/tutorial_performance_and_time
Example:
Three ways to prepare absolute time 1500 milliseconds in the future to use with pthread timed functions.
Output, N = 3, stock MacMini, OSX 10.7.5, 2.3GHz i5, 2GB 1333MHz DDR3:
inittime.tv_sec = 1390659993
inittime.tv_nsec = 361539000
initclock = 76672695144136
get_abs_future_time_0() : 1390659994.861599000
get_abs_future_time_0() : 1390659994.861599000
get_abs_future_time_0() : 1390659994.861599000
get_abs_future_time_1() : 1390659994.861618000
get_abs_future_time_1() : 1390659994.861634000
get_abs_future_time_1() : 1390659994.861642000
get_abs_future_time_2() : 1390659994.861643671
get_abs_future_time_2() : 1390659994.861643877
get_abs_future_time_2() : 1390659994.861643972
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h> /* gettimeofday */
#include <mach/mach_time.h> /* mach_absolute_time */
#include <mach/mach.h> /* host_get_clock_service, mach_... */
#include <mach/clock.h> /* clock_get_time */
#define BILLION 1000000000L
#define MILLION 1000000L
#define NORMALISE_TIMESPEC( ts, uint_milli ) \
do { \
ts.tv_sec += uint_milli / 1000u; \
ts.tv_nsec += (uint_milli % 1000u) * MILLION; \
ts.tv_sec += ts.tv_nsec / BILLION; \
ts.tv_nsec = ts.tv_nsec % BILLION; \
} while (0)
static mach_timebase_info_data_t timebase = { 0, 0 }; /* numer = 0, denom = 0 */
static struct timespec inittime = { 0, 0 }; /* nanoseconds since 1-Jan-1970 to init() */
static uint64_t initclock; /* ticks since boot to init() */
void init()
{
struct timeval micro; /* microseconds since 1 Jan 1970 */
if (mach_timebase_info(&timebase) != 0)
abort(); /* very unlikely error */
if (gettimeofday(µ, NULL) != 0)
abort(); /* very unlikely error */
initclock = mach_absolute_time();
inittime.tv_sec = micro.tv_sec;
inittime.tv_nsec = micro.tv_usec * 1000;
printf("\tinittime.tv_sec = %ld\n", inittime.tv_sec);
printf("\tinittime.tv_nsec = %ld\n", inittime.tv_nsec);
printf("\tinitclock = %ld\n", (long)initclock);
}
/*
* Get absolute future time for pthread timed calls
* Solution 1: microseconds granularity
*/
struct timespec get_abs_future_time_coarse(unsigned milli)
{
struct timespec future; /* ns since 1 Jan 1970 to 1500 ms in the future */
struct timeval micro = {0, 0}; /* 1 Jan 1970 */
(void) gettimeofday(µ, NULL);
future.tv_sec = micro.tv_sec;
future.tv_nsec = micro.tv_usec * 1000;
NORMALISE_TIMESPEC( future, milli );
return future;
}
/*
* Solution 2: via clock service
*/
struct timespec get_abs_future_time_served(unsigned milli)
{
struct timespec future;
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
future.tv_sec = mts.tv_sec;
future.tv_nsec = mts.tv_nsec;
NORMALISE_TIMESPEC( future, milli );
return future;
}
/*
* Solution 3: nanosecond granularity
*/
struct timespec get_abs_future_time_fine(unsigned milli)
{
struct timespec future; /* ns since 1 Jan 1970 to 1500 ms in future */
uint64_t clock; /* ticks since init */
uint64_t nano; /* nanoseconds since init */
clock = mach_absolute_time() - initclock;
nano = clock * (uint64_t)timebase.numer / (uint64_t)timebase.denom;
future = inittime;
future.tv_sec += nano / BILLION;
future.tv_nsec += nano % BILLION;
NORMALISE_TIMESPEC( future, milli );
return future;
}
#define N 3
int main()
{
int i, j;
struct timespec time[3][N];
struct timespec (*get_abs_future_time[])(unsigned milli) =
{
&get_abs_future_time_coarse,
&get_abs_future_time_served,
&get_abs_future_time_fine
};
init();
for (j = 0; j < 3; j++)
for (i = 0; i < N; i++)
time[j][i] = get_abs_future_time[j](1500); /* now() + 1500 ms */
for (j = 0; j < 3; j++)
for (i = 0; i < N; i++)
printf("get_abs_future_time_%d() : %10ld.%09ld\n",
j, time[j][i].tv_sec, time[j][i].tv_nsec);
return 0;
}
사실상 Sierra 10.12 이전 MacOS에서는 구현되지 않은 것으로 보입니다.이 블로그 엔트리를 보는 것이 좋습니다.주요 아이디어는 다음 코드 조각에 있습니다.
#include <mach/mach_time.h>
#define ORWL_NANO (+1.0E-9)
#define ORWL_GIGA UINT64_C(1000000000)
static double orwl_timebase = 0.0;
static uint64_t orwl_timestart = 0;
struct timespec orwl_gettime(void) {
// be more careful in a multithreaded environement
if (!orwl_timestart) {
mach_timebase_info_data_t tb = { 0 };
mach_timebase_info(&tb);
orwl_timebase = tb.numer;
orwl_timebase /= tb.denom;
orwl_timestart = mach_absolute_time();
}
struct timespec t;
double diff = (mach_absolute_time() - orwl_timestart) * orwl_timebase;
t.tv_sec = diff * ORWL_NANO;
t.tv_nsec = diff - (t.tv_sec * ORWL_GIGA);
return t;
}
투고 감사합니다.
다음 행을 추가할 수 있을 것 같습니다.
#ifdef __MACH__
#include <mach/mach_time.h>
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 0
int clock_gettime(int clk_id, struct timespec *t){
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
uint64_t time;
time = mach_absolute_time();
double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
t->tv_sec = seconds;
t->tv_nsec = nseconds;
return 0;
}
#else
#include <time.h>
#endif
지연 시간 및 세분화에 대한 정보를 알려 주십시오.
#if defined(__MACH__) && !defined(CLOCK_REALTIME)
#include <sys/time.h>
#define CLOCK_REALTIME 0
// clock_gettime is not implemented on older versions of OS X (< 10.12).
// If implemented, CLOCK_REALTIME will have already been defined.
int clock_gettime(int /*clk_id*/, struct timespec* t) {
struct timeval now;
int rv = gettimeofday(&now, NULL);
if (rv) return rv;
t->tv_sec = now.tv_sec;
t->tv_nsec = now.tv_usec * 1000;
return 0;
}
#endif
마리틱의이치노 #include
★★★★★★★★★★★★★★★★★」Init()
:
#include <mach/mach_time.h>
double conversion_factor;
void Init() {
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
conversion_factor = (double)timebase.numer / (double)timebase.denom;
}
사용처:
uint64_t t1, t2;
Init();
t1 = mach_absolute_time();
/* profiled code here */
t2 = mach_absolute_time();
double duration_ns = (double)(t2 - t1) * conversion_factor;
은 「」입니다.65ns +/- 2ns
(2GHz CPU).단일 실행의 "시간 진화"가 필요한 경우 이 기능을 사용하십시오. 않으면 .10000
및 (''가 있는 )gettimeofday()
(POSIX로 (POSIX)의 이 있습니다100ns +/- 0.5ns
)1us
□□□□□□□□★
clock_get_time 버전을 사용하여 host_get_clock_service 콜을 캐시했습니다.이것은 get time of day보다 훨씬 느리고 호출당 몇 마이크로초가 걸립니다.게다가 수익률도 1000단계(즉, 마이크로초 단위)입니다.
get time of day를 사용하여 tv_usec에 1000을 곱하는 것이 좋습니다.
오픈 소스 mach_absolute_time.c에 근거하여 이 행은extern mach_port_t clock_port;
단조로운 시간에 맞게 이미 초기화된 마하 포트가 있음을 나타냅니다.는 콜링에 직접 수 .mach_absolute_time
그 후 다시 로 변환합니다.struct timespec
의 콜 mach_absolute_time
퍼포먼스가 향상됩니다.
외부 코드로 작은 Github repo(PosixMachTiming)를 만들었습니다.clock_port
그리고 비슷한 실.PosixMachTiming 에뮬레이트clock_gettime
★★★★★★에CLOCK_REALTIME
★★★★★★★★★★★★★★★★★」CLOCK_MONOTONIC
이 이 됩니다.clock_nanosleep
절대 단조로운 시간을 위해.한 번 시도해 보시고 성능 비교도전해 보세요.비교 테스트를 작성하거나 다른 POSIX 클럭/함수를 에뮬레이트할 수 있습니다.
라이온까지 올라가면, 마운틴 라이온,mach_absolute_time()
는 절대시간이 아닌 나노초를 반환합니다(이것은 버스사이클의 수였습니다).
Pro Core 의 다음 는 MacBook Pro(2GHz Core i7)를 호출할 되었습니다.mach_absolute_time()
실행 중 35, 45을 반환할 입니다.10 ns('35, 45').이것은 기본적으로 2개의 콜이 mach_absolute_time에 반환되는 약1개의 호출 사이의 시간입니다.
#include <stdint.h>
#include <mach/mach_time.h>
#include <iostream>
using namespace std;
int main()
{
uint64_t now, then;
uint64_t abs;
then = mach_absolute_time(); // return nanoseconds
now = mach_absolute_time();
abs = now - then;
cout << "nanoseconds = " << abs << endl;
}
나는 다른 휴대용 해결책을 찾았다.
일부 헤더 파일(또는 소스 파일)에서 선언:
/* If compiled on DARWIN/Apple platforms. */
#ifdef DARWIN
#define CLOCK_REALTIME 0x2d4e1588
#define CLOCK_MONOTONIC 0x0
#endif /* DARWIN */
그리고 기능 구현을 추가합니다.
#ifdef DARWIN
/*
* Bellow we provide an alternative for clock_gettime,
* which is not implemented in Mac OS X.
*/
static inline int clock_gettime(int clock_id, struct timespec *ts)
{
struct timeval tv;
if (clock_id != CLOCK_REALTIME)
{
errno = EINVAL;
return -1;
}
if (gettimeofday(&tv, NULL) < 0)
{
return -1;
}
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
return 0;
}
#endif /* DARWIN */
꼭 넣어주세요.<time.h>
.
void clock_get_uptime(uint64_t *result);
void clock_get_system_microtime( uint32_t *secs,
uint32_t *microsecs);
void clock_get_system_nanotime( uint32_t *secs,
uint32_t *nanosecs);
void clock_get_calendar_microtime( uint32_t *secs,
uint32_t *microsecs);
void clock_get_calendar_nanotime( uint32_t *secs,
uint32_t *nanosecs);
MacOS의 경우 개발자 페이지 https://developer.apple.com/library/content/documentation/Darwin/Conceptual/KernelProgramming/services/services.html에서 유용한 정보를 찾을 수 있습니다.
언급URL : https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
'programing' 카테고리의 다른 글
템플릿에 있는 경우 "함수가 아니므로" 스토어의 Vue에 대한 getter에 액세스할 수 없습니다. (0) | 2022.08.14 |
---|---|
Vue의 온드래거에 상당합니다.드래그 가능(Sortable.js) (0) | 2022.08.14 |
const는 C/C++에서 어떤 최적화를 제공합니까? (0) | 2022.08.14 |
Vuex 스토어 모듈 상태 개체를 비우는 방법 (0) | 2022.08.14 |
왜 매크로가 함수가 아닌 어설트일까요? (0) | 2022.08.14 |