Move generator

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Carey
Posts: 313
Joined: Wed Mar 08, 2006 8:18 pm

Re: Move generator

Post by Carey »

As Lance Perkins points out at the top of the page, gettimeofday() isn't guaranteed to have better than second accuracy either. It is basically hardware dependant and depends upon what the library writer chooses to do. The joys of non-official functions, although admittedly official ISO routines may not be much better.

There is no portable way to be sure of getting anything better than second accuracy.

You'll always either

1) Use some OS dependant function that guarantees a certain precision. (And depending on the OS & function, it may have significant overhead, and not be suitable for use for search time control.)

2) Use some common but non-standard function that often works, but may not under some platforms. So you have to check it at runtime to make sure it is working, or just assume that it will and take the small risk that it wont.

(Note, some of these routines are supposed to return -1 if they aren't available for some reason. Don't believe it. I've seen a few compiler libraries that return nothing at all. You have to check the value to see if it changes or just hope that it does work.)

Personally, I often use ftime() (with clock() as a backup). It is a very common function that both Linux & Windows is likely to have and I think it's likely they will work reasonably well. But there is no guarantee, of course. The advantage of this over some others that I've tried is that it's reasonably quick. Quick enough that it can be called many times per second during the search without having a significant overhead.


And just to throw in yet another issue, there are times when these clock routines might return a time that is slightly before that from a call right before it.

In other words:

X=timer();
Y=timer();

might occasionally have Y return a value that is a tick or two sooner than what X is.

I've seen it under Windows XP & Vista, and I've read about it happening under Linux (but haven't seen it personally since I don't use Linux.)

Just some quirk in the code that reads the timer, or something. It may not happen often, but the fact that it can happen means you might want to allow for it in your code.

I don't know the cause. I just know that I've seen it.
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: Move generator

Post by sje »

CThinker wrote:"portable"?

gettimeofday() is not portable. Its resolution is also not guaranteed.
It's been around since 4.2BSD and that's at least thirteen years ago. It's POSIX from the IEEE specification. And the resolution is guaranteed to be either one microsecond or the best available if that's larger. It's also on every Mac OS/X system, and every Linux system in recent use.

If I were stuck coding for a non-POSIX environment, I'd search the net for appropriate implementations of needed POSIX functions and port them myself, as this would be a much better approach than using non standard, overly dependent code.
Carey
Posts: 313
Joined: Wed Mar 08, 2006 8:18 pm

Re: Move generator

Post by Carey »

Dann Corbit wrote: The clock() function can return -1 for any call to clock() in a conforming implementation:

"If the processor time used is not available or its value cannot be represented, the function returns the value (clock_t)(-1)."
page: 338 section: Library §7.23.2.2 under the clock() function description.
Supposed to. But I wouldn't count on it.

You'd be better off checking the value and making sure it changes within a few thousand calls.

Sure, if it says -1, then you know it doesn't work. I just mean it's worth checking and let the program actually see what the resolution is. If it's too low then you can tell the user and abort.

Since we are concerned in a chess program with the observer's time, clock() is clearly the wrong function to use anyway. Suppose that a database
It can be very useful during testing etc. That way you can run the program for a certain length of process time even if there are other processes running in the background.

I like to have both wall clcok & process time and be able to switch between them with a command switch.
query runs, taking 50% of the CPU's time an you have ten seconds left. You might consume only 5 seconds using clock(), but the observer measures ten seconds consumed and you lose on time. Clearly, that
Yup. I pointed that out too. Although unless you are heavily loaded it's not likely to be a difference of more than a few seconds. Perhaps 10 seconds or so at most for a 3 minute search.

And you probably aren't likely to heavily load the system while running a chess program. Chess programs, like modern games, are designed to use up every cpu cycle you have and still want more.
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

gettimeofday() for Windows

Post by sje »

Code: Select all

    #include < time.h >
     
    #if defined&#40;_MSC_VER&#41; || defined&#40;_MSC_EXTENSIONS&#41;
      #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
    #else
      #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
    #endif
     
    struct timezone 
    &#123;
      int  tz_minuteswest; /* minutes W of Greenwich */
      int  tz_dsttime;     /* type of dst correction */
    &#125;;
     
    int gettimeofday&#40;struct timeval *tv, struct timezone *tz&#41;
    &#123;
      FILETIME ft;
      unsigned __int64 tmpres = 0;
      static int tzflag;
     
      if &#40;NULL != tv&#41;
      &#123;
        GetSystemTimeAsFileTime&#40;&ft&#41;;
     
        tmpres |= ft.dwHighDateTime;
        tmpres <<= 32;
        tmpres |= ft.dwLowDateTime;
     
        /*converting file time to unix epoch*/
        tmpres /= 10;  /*convert into microseconds*/
        tmpres -= DELTA_EPOCH_IN_MICROSECS; 
        tv->tv_sec = &#40;long&#41;&#40;tmpres / 1000000UL&#41;;
        tv->tv_usec = &#40;long&#41;&#40;tmpres % 1000000UL&#41;;
      &#125;
     
      if &#40;NULL != tz&#41;
      &#123;
        if (!tzflag&#41;
        &#123;
          _tzset&#40;);
          tzflag++;
        &#125;
        tz->tz_minuteswest = _timezone / 60;
        tz->tz_dsttime = _daylight;
      &#125;
     
      return 0;
    &#125;

CThinker
Posts: 388
Joined: Wed Mar 08, 2006 10:08 pm

Re: gettimeofday() for Windows

Post by CThinker »

Dann has already posted that code, and that is how this thread started.

It is too much code just to get time. Plus, it is penalizing 96% of the computers in the world.

It should just be the other way around:

Code: Select all

int ChessClock&#40;void&#41;
&#123;
#if _WIN32
     return GetTickCount&#40;); // Kernel32
#else
     // 4% of computers with dozens of different types of code
    #if _PS2
    #elif _PS3
    #elif _WII
    #elif _SYMBIAN
    #elif _ITRON
    #endif
#endif
&#125;
Dann Corbit
Posts: 12541
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: gettimeofday() for Windows

Post by Dann Corbit »

CThinker wrote:Dann has already posted that code, and that is how this thread started.

It is too much code just to get time. Plus, it is penalizing 96% of the computers in the world.

It should just be the other way around:

Code: Select all

int ChessClock&#40;void&#41;
&#123;
#if _WIN32
     return GetTickCount&#40;); // Kernel32
#else
     // 4% of computers with dozens of different types of code
    #if _PS2
    #elif _PS3
    #elif _WII
    #elif _SYMBIAN
    #elif _ITRON
    #endif
#endif
&#125;
The gettimeofday() function is useful because literally dozens of Unix - born Xboard engines use that call. So I made a port of it available to simplify porting.

If you want to do timing on Windows, there is a high resolution timer (and if you find it is not available you can use an alternative).

It is also possible to use the rtdsc instruction or things of that nature.

Timing and any other OS specific function is always going to be inherently non-portable. So it is nice to have a way that can be used across systems. I would not suggest using the provided gettimeofday() function for a new windows program. But for an existing Unix program being ported to Windows it's a slam dunk.
Carey
Posts: 313
Joined: Wed Mar 08, 2006 8:18 pm

Re: gettimeofday() for Windows

Post by Carey »

Dann Corbit wrote: The gettimeofday() function is useful because literally dozens of Unix - born Xboard engines use that call. So I made a port of it available to simplify porting.

If you want to do timing on Windows, there is a high resolution timer (and if you find it is not available you can use an alternative).
You might want to check to make sure it doesn't put too overhead into your search.

Some months back, I retried several timers and the Windows specific 'high' res timers tended to have a much higher overhead than the more generic ones.

Calling it more than a few hundred times per second in the search produced a noticable slow down in the search.

Some people like to just stick the timer check directly into their search and let it check it every pass. I don't. I prefer to set up a self adjusting node counter that tries to do it no more than a hundred times per second. Any more than that and the Windows specific timers started slowing down the search.

It is also possible to use the rtdsc instruction or things of that nature.
Not recommended unless you are doing it some sort of 'unspecified' counter. (Meaning you know it counts something but not what.)

With cpu's being able to slow themselves down when they get hot (or running on batteries), it's not really consistant enough for anything but some sort of 'unknown' timer.
Timing and any other OS specific function is always going to be inherently non-portable. So it is nice to have a way that can be used across systems. I would not suggest using the provided gettimeofday() function for a new windows program. But for an existing Unix program being ported to Windows it's a slam dunk.
Assuming gettimeofday() actually works right and has a reasonable accuracy and has tolerable overhead, I don't see anything wrong with using it. I (and probably most people) don't really care the origins of the function. It could date back to DOS or Unix or even before. As long as it works reliably and is in enough compilers and OS's, then... (shrug).

But I still say that whatever you choose, you should set up a little test at the start of the program to make sure that the timer does actually change and that the resolution appears to be of sufficient resolution for what you need.

Pretty cheap insurance for somebody else compiling it on a system you haven't tested.
Carey
Posts: 313
Joined: Wed Mar 08, 2006 8:18 pm

Re: Move generator

Post by Carey »

sje wrote:
CThinker wrote:"portable"?

gettimeofday() is not portable. Its resolution is also not guaranteed.
It's been around since 4.2BSD and that's at least thirteen years ago. It's POSIX from the IEEE specification. And the resolution is guaranteed to be either one microsecond or the best available if that's larger. It's also on every Mac OS/X system, and every Linux system in recent use.
I don't happen to have a copy of the POSIX specs. (And that it's from BSD is irrelevant. Lots of things are from back than and not done the same or done right, etc.)

Anyway, does the POSIX specs *specificially* say that the accuracy must be microsecond, or does it just say the resolution must be microsecond?

That's not the same thing.

It may appear to be microseconds but in reality the numbers only change 18.2 times per second. (PC XT style) (Yes yes, that is *extremely* unlikely.)

I've seen compilers (or rather libraries) that lie about clock()'s clock_per_sec by just multiplying everything by some number to make it look like it's changing 1000 times per second. In other words, they lie and make it appear there is a higher accuracy than there really is.


So, does POSIX specs actually require all one million microseconds to be present? Or can an implementation cheat and only provide 60 or 100 (or whatever) distinct values within those million?

This is a serious question. As I said, I don't have the POSIX specs. I did a quick look on google and I just saw some pages tlaking about it, but no actual specs.

If you can quote the actual specs, I'd appreciate it.

Thanks.

Carey
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: Move generator

Post by sje »

Some of the POSIX spec is hidden behind a pay wall at ieee.org, you might be able to find in for free somewhere.

Honestly, I don't give a damn about non-POSIX platforms. I use Linux and BSD, and never have I had a problem with gettimeofday() as the resolution has always been one millisecond or better.

And no, you don't have to call it at every node. Simply use alarm() or the interval timer on a separate thread to call it every 100 milliseconds. The overhead on any modern system is too small to be measured.
Carey
Posts: 313
Joined: Wed Mar 08, 2006 8:18 pm

Re: Move generator

Post by Carey »

sje wrote:Some of the POSIX spec is hidden behind a pay wall at ieee.org, you might be able to find in for free somewhere.
I don't see the specs anywhere, but I do see a number of comments and descriptions of gettimeofday talking about it *not* being required to actually do microseconds.

It only has to be represented as microseconds, which is very different.

It's still entirely possible for it to be no better than 1 second granulatiry. It will probably be whatever is convenient for the OS & hardware, which could be 60, 100, 1000, or whatever.

But from what I see, the specs only require it to be represented as microseconds.

Which puts it no better than clock() and its undefined CLOCKS_PER_SEC.

The only differences are clock() is process time and clock_t could be 32 bit, 64 bit or double. And gettimeofday data type is slightly better defined and it's wall-clock.

But you still don't know in advance what you will actually get on a different platform until you check.

Honestly, I don't give a damn about non-POSIX platforms. I use Linux and BSD, and never have I had a problem with gettimeofday() as the
Well, you should care. Not too many programmers want to dismiss 95% of the computers in the world.

Even among Linux (POSIX or not) implementations there's obviously variation.

Which is what Lance said.

I don't use Linux or Mac but that doesn't mean I want to deliberately write code that wont work.


This discussion has been about how to do timing portably and reliably. Obviously your interests are not the same.

(shrug) Each to their own. I'm certainly not going to loose any sleep on what you choose to do.

resolution has always been one millisecond or better.
Interesting that you even admit gettimeofday isn't always microsecond granulatiy. And that it does indeed vary.

And no, you don't have to call it at every node. Simply use alarm() or the interval timer on a separate thread to call it every 100 milliseconds.

Of course you don't have to call it at every node. I was just saying that some people do because it's simpler than writing a few extra lines of code to create a slef-adjusting node counter that keeps the GetTime() calling rate down to around 100 per second.

I personally prefer to use a self-adjusting node counter because it's more portable. No OS dependant code for setting up timers.
The overhead on any modern system is too small to be measured.
For timers & alarms, sure. Neglible overhead. But that isn't what I was talking about.



Given the choice between OS dependant code or portable code that works just as well, I prefer the portable code that has fewer chances to cause problems later.