Moderator: Andres Valverde
What I am thinking about is, even though my engine doesn't support MP, it could spawn a dummy thread which would just loop forever in order to take away CPU time from my MP opponent.
If ponder is off engine should be at 0% CPU, because it's waiting for an input. Engine is not looping.
Uri Blass wrote:Unfortunately I do not know how to detect cpu time so I do not know how to implement that idea.
#include <time.h>
/* Actually, using integral values would be
better. Note that after really long runtime,
this will start to fail, while the alternative
with integers will still work. It would need
different structs for the Standard C clock method,
and the Windows specific method */
typedef struct {double timestamp;} CPU_TIME_INFO;
#ifdef _WIN32
#include <windows.h>
static int use_hp=0;
static int has_proc_times=0;
static HANDLE hprocess;
/* Initialize at startup */
/* See, if we have GetProcessTimes working */
void sys_init(void)
{
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
if (GetVersionEx(&osvi) != 0)
{
#if 0
printf("siz %u, major %u, minor %u, build %u, platid %u, ver %s\n",
osvi.dwOSVersionInfoSize,
osvi.dwMajorVersion,
osvi.dwMinorVersion,
osvi.dwBuildNumber,
osvi.dwPlatformId,
osvi.szCSDVersion);
#endif
if (osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
has_proc_times = 1;
}
hprocess = GetCurrentProcess();
}
#endif
#ifdef _WIN32
double cpu_time_stamp(void)
{
FILETIME ct, kt, et, ut;
if (has_proc_times && GetProcessTimes(hprocess,&ct,&et,&kt,&ut))
{
unsigned __int64 ns100 = *(unsigned __int64 *)&ut;
#if 0
/* For some reason, this does not work, while all the nasty casting
stuff does ... */
double r = ((signed __int64)((unsigned __int64)ut.dwLowDateTime
+ ((unsigned __int64)ut.dwHighDateTime)<<32))*1e-7;
my_printf(INFORMATION, "cpu %u %u, %f %I64u\n", ut.dwHighDateTime, ut.dwLowDateTime, r, ns100);
#endif
/* This cast to signed is needed, because (some verions of)
MSVC cannot cast unsigned _int64 to double. */
return (signed __int64)ns100*1e-7;
}
/* Won't really give CPU time */
return (double)clock()/CLOCKS_PER_SEC;
}
#else
/* Standard C method */
double cpu_time_stamp(void)
{
return (double)clock()/CLOCKS_PER_SEC;
}
#endif
void start_cpu_time(CPU_TIME_INFO *p)
{
p->timestamp = cpu_time_stamp();
}
double elapsed_cpu_time(CPU_TIME_INFO *p)
{
double r = cpu_time_stamp()-p->timestamp;
if (r < 0.0) /* Should never happen, of course */
r = 0;
return r;
}
/* Windows specific main (the call to Sleep) */
#include <stdio.h>
#include <math.h>
int main(void)
{
CPU_TIME_INFO cpu_t;
double ct, r;
unsigned long n;
sys_init();
start_cpu_time(&cpu_t);
printf("GetProcessTimes should %s work on this computer\n",
has_proc_times ? "" : "not");
printf("I will sleep for 10 seconds now\n");
Sleep(10000);
ct = elapsed_cpu_time(&cpu_t);
printf("I used %.g s cpu time until now\n", ct);
printf("I will do some calculation now\n", ct);
r = 0;
for (n=0; n<10000000UL; n++)
r += sin(n*1e-7);
printf("result %g\n", r);
printf("I used %g s cpu time until now\n", elapsed_cpu_time(&cpu_t));
return 0;
}
// Here is something for process times under WIN32:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winperf.h>
#include <Psapi.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <errno.h>
#ifndef ENODATA
#define ENODATA 61
#endif
#ifndef RUSAGE_SELF
#define RUSAGE_SELF 0
#endif
#ifndef RUSAGE_CHILDREN
#define RUSAGE_CHILDREN -1
#endif
#ifdef _MSC_VER
typedef __int64 longlong;
#else
typedef long long longlong;
#endif
typedef struct timeval {
long tv_sec;
long tv_usec;
} timeval;
typedef struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
long ru_maxrss; /* integral max resident set size */
long ru_ixrss; /* integral shared text memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
long ru_minflt; /* page reclaims */
long ru_majflt; /* page faults */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* messages sent */
long ru_msgrcv; /* messages received */
long ru_nsignals;/* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary context switches */
} rusage;
/* The function GetPerformanceInfo() may or may not exist (e.g. Windows 2003 has it) in Psapi.dll */
typedef BOOL(*pfnGetPerformanceInfo) (PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb);
int getrusage(int who, struct rusage * usage)
{
HANDLE process_handle;
PROCESS_MEMORY_COUNTERS pmc;
FILETIME create_time,
exit_time,
kernel_time,
user_time;
size_t page_size = 8192;
PPERFORMANCE_INFORMATION PerformanceInformation = {0};
DWORD cb = 0;
HMODULE hm;
pfnGetPerformanceInfo fnGetPerformanceInfo = 0;
hm = GetModuleHandle("Psapi.DLL");
if (hm)
fnGetPerformanceInfo = (pfnGetPerformanceInfo) GetProcAddress(hm, "GetPerformanceInfo");
if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) {
errno = EINVAL;
return -1;
}
/* Win32 systems do not have a convenient call to enumerate child
* processes that I am aware of. */
if (who == RUSAGE_CHILDREN) {
errno = ENODATA;
return -1;
}
process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
/*
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc
* /base/getprocesstimes.asp */
if (GetProcessTimes(process_handle, &create_time, &exit_time, &kernel_time, &user_time)) {
longlong u_time = (*(longlong *) & user_time);
longlong k_time = (*(longlong *) & kernel_time);
/* The units returned by GetProcessTimes are 100 nanoseconds */
usage->ru_utime.tv_sec = (long) (u_time / 10000000);
usage->ru_stime.tv_sec = (long) (k_time / 10000000);
usage->ru_utime.tv_usec = (long) (u_time % 10000000);
usage->ru_stime.tv_usec = (long) (k_time % 10000000);
} else {
/* * Probably a permissions problem */
if (hm)
FreeLibrary(hm);
CloseHandle(process_handle);
errno = EACCES;
return -1;
}
if (fnGetPerformanceInfo && fnGetPerformanceInfo(PerformanceInformation, cb)) {
/* If the call fails, we will use an estimate of 8K per page. Else: */
page_size = PerformanceInformation->PageSize;
}
if (GetProcessMemoryInfo(process_handle, &pmc, sizeof(pmc))) {
usage->ru_maxrss = (DWORD) (pmc.WorkingSetSize / page_size);
usage->ru_majflt = pmc.PageFaultCount;
} else {
/* * Probably a permissions problem */
if (hm)
FreeLibrary(hm);
CloseHandle(process_handle);
errno = EACCES;
return -1;
}
if (hm)
FreeLibrary(hm);
CloseHandle(process_handle);
return 0;
}
typedef struct tms {
FILETIME tms_utime;
FILETIME tms_stime;
FILETIME tms_cutime;
FILETIME tms_cstime;
} tms;
longlong
times(struct tms * timebuf)
{
longlong user;
longlong kernel;
longlong dummy;
if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
&kernel, &user)) {
timebuf->tms_utime = (*(longlong *) &user);
timebuf->tms_stime = (*(longlong *) &kernel);
timebuf->tms_cutime = 0;
timebuf->tms_cstime = 0;
} else {
/* That failed - e.g. Win95 fallback to clock() */
clock_t t = clock();
timebuf->tms_utime = t;
timebuf->tms_stime = 0;
timebuf->tms_cutime = 0;
timebuf->tms_cstime = 0;
}
return timebuf->tms_utime ;
}
#ifdef UNIT_TEST
#include <time.h>
int main(void)
{
size_t i;
rusage ruse;
int r;
double cps_inv = 1.0 / CLOCKS_PER_SEC;
clock_t start,
end;
start = clock();
while ((clock() - start) * cps_inv < 1.0 && i++ < 1000000000 /* clock() can wrap */ )
r = rand();
Sleep(1000); /* We want wall time to be greater than
* process time to ensure it is working OK. */
getrusage(RUSAGE_SELF, &ruse);
printf("rusage user: %ld.%ld system: %ld.%ld\n",
ruse.ru_utime.tv_sec,
ruse.ru_utime.tv_usec,
ruse.ru_stime.tv_sec,
ruse.ru_stime.tv_usec);
return 0;
}
#endif
Dann Corbit wrote:Why not just write an SMP program?
1. Remove all globals that are written to (read only is fine).
2. Remove all non-reentrant junk like strtok()
3. Remove all statics that are written to
4. For anything else, gate it.
You can use pthreads like Amy does, and it will run everywhere.
You could also use ACE or some similar toolkit.
Dann Corbit wrote:Why not just write an SMP program?
1. Remove all globals that are written to (read only is fine).
2. Remove all non-reentrant junk like strtok()
3. Remove all statics that are written to
4. For anything else, gate it.
Dieter B?r?ner wrote:Seems not much difference, to what I have shown, arguably a bit less efficient (in case, it is called often). Suffers from exactly the same things, I had mentioned in my post (nasty, in principle incorrect cast; not working correctly under W95/W98).
Sune Fischer wrote:One must solve the problem with the lockless hash.
Dan Honeycutt wrote:Hi Sune:
Having never done it I speak from ignorance. But I read Dr. Hyatts paper on lockless hash and that seemed pretty straightforeward. Am I missing something?
(Everything else you list I agree 100%)
Dan H.
Return to Programming and Technical Discussions
Users browsing this forum: No registered users and 23 guests