mirror of https://github.com/BOINC/boinc.git
- client: NVIDIA offers an API which tells you whether a GPU
is running a graphics application. Change the semantics of the "don't use GPU while computer in use" pref to "don't use a GPU that's running a graphics app while computer is in use". This will increase GPU utilization on multi-GPU systems. svn path=/trunk/boinc/; revision=18942
This commit is contained in:
parent
607119dcbf
commit
2039e67638
|
@ -7293,3 +7293,19 @@ David 28 Aug 2009
|
||||||
|
|
||||||
client/
|
client/
|
||||||
work_fetch.cpp
|
work_fetch.cpp
|
||||||
|
|
||||||
|
David 28 Aug 2009
|
||||||
|
- client: NVIDIA offers an API which tells you whether a GPU
|
||||||
|
is running a graphics application.
|
||||||
|
Change the semantics of the "don't use GPU while computer in use" pref
|
||||||
|
to "don't use a GPU that's running a graphics app while
|
||||||
|
computer is in use".
|
||||||
|
This will increase GPU utilization on multi-GPU systems.
|
||||||
|
|
||||||
|
client/
|
||||||
|
client_state.cpp
|
||||||
|
cpu_sched.cpp
|
||||||
|
sched/
|
||||||
|
file_deleter.cpp
|
||||||
|
lib/
|
||||||
|
coproc.cpp,h
|
||||||
|
|
|
@ -559,6 +559,13 @@ bool CLIENT_STATE::poll_slow_events() {
|
||||||
if (user_active != old_user_active) {
|
if (user_active != old_user_active) {
|
||||||
request_schedule_cpus("Idle state change");
|
request_schedule_cpus("Idle state change");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (coproc_cuda && user_active && !global_prefs.run_gpu_if_user_active) {
|
||||||
|
if (coproc_cuda->check_running_graphics_app()) {
|
||||||
|
request_schedule_cpus("GPU state change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// Mac screensaver launches client if not already running.
|
// Mac screensaver launches client if not already running.
|
||||||
// OS X quits screensaver when energy saver puts display to sleep,
|
// OS X quits screensaver when energy saver puts display to sleep,
|
||||||
|
|
|
@ -88,7 +88,12 @@ struct PROC_RESOURCES {
|
||||||
bool can_schedule(RESULT* rp) {
|
bool can_schedule(RESULT* rp) {
|
||||||
if (rp->uses_coprocs()) {
|
if (rp->uses_coprocs()) {
|
||||||
if (gstate.user_active && !gstate.global_prefs.run_gpu_if_user_active) {
|
if (gstate.user_active && !gstate.global_prefs.run_gpu_if_user_active) {
|
||||||
return false;
|
if (rp->avp->natis) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if it's NVIDIA, defer deciding because
|
||||||
|
// some GPUs may not be running user apps
|
||||||
|
//
|
||||||
}
|
}
|
||||||
if (sufficient_coprocs(
|
if (sufficient_coprocs(
|
||||||
*rp->avp, log_flags.cpu_sched_debug, "cpu_sched_debug")
|
*rp->avp, log_flags.cpu_sched_debug, "cpu_sched_debug")
|
||||||
|
@ -984,6 +989,33 @@ static inline void assign_coprocs(vector<RESULT*> jobs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enforce user pref in NVIDIA case
|
||||||
|
//
|
||||||
|
if (coproc_cuda && gstate.user_active && !gstate.global_prefs.run_gpu_if_user_active) {
|
||||||
|
job_iter = jobs.begin();
|
||||||
|
while (job_iter != jobs.end()) {
|
||||||
|
RESULT* rp = *job_iter;
|
||||||
|
if (!rp->avp->ncudas) {
|
||||||
|
job_iter++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ACTIVE_TASK* atp = gstate.lookup_active_task_by_result(rp);
|
||||||
|
bool some_gpu_busy = false;
|
||||||
|
for (i=0; i<rp->avp->ncudas; i++) {
|
||||||
|
int dev = atp->coproc_indices[i];
|
||||||
|
if (coproc_cuda->running_graphics_app[dev]) {
|
||||||
|
some_gpu_busy = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (some_gpu_busy) {
|
||||||
|
job_iter = jobs.erase(job_iter);
|
||||||
|
} else {
|
||||||
|
job_iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce the CPU schedule.
|
// Enforce the CPU schedule.
|
||||||
|
|
136
lib/coproc.cpp
136
lib/coproc.cpp
|
@ -194,6 +194,42 @@ int cuda_compare(COPROC_CUDA& c1, COPROC_CUDA& c2, bool loose) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef int (__stdcall *PCGDC)(int *count);
|
||||||
|
typedef int (__stdcall *PCGDP)(struct cudaDeviceProp *prop, int device);
|
||||||
|
typedef int (__stdcall *PCGDV)(int* version);
|
||||||
|
typedef int (__stdcall *PCGDI)(int);
|
||||||
|
typedef int (__stdcall *PCGDG)(int*, int);
|
||||||
|
typedef int (__stdcall *PCGDA)(int*, int, int);
|
||||||
|
typedef int (__stdcall *PCGDN)(char*, int, int);
|
||||||
|
typedef int (__stdcall *PCGDM)(unsigned int*, int);
|
||||||
|
typedef int (__stdcall *PCGDCC)(int*, int*, int);
|
||||||
|
|
||||||
|
PCGDC __cuDeviceGetCount = NULL;
|
||||||
|
//PCGDP __cuDeviceGetProperties = NULL;
|
||||||
|
PCGDV __cuDriverGetVersion = NULL;
|
||||||
|
PCGDI __cuInit = NULL;
|
||||||
|
PCGDG __cuDeviceGet = NULL;
|
||||||
|
PCGDA __cuDeviceGetAttribute = NULL;
|
||||||
|
PCGDN __cuDeviceGetName = NULL;
|
||||||
|
PCGDM __cuDeviceTotalMem = NULL;
|
||||||
|
PCGDCC __cuDeviceComputeCapability = NULL;
|
||||||
|
#else
|
||||||
|
void* cudalib;
|
||||||
|
int (*__cuInit)(int);
|
||||||
|
int (*__cuDeviceGetCount)(int*);
|
||||||
|
//int (*__cuDeviceGetProperties)(cudaDeviceProp*, int);
|
||||||
|
int (*__cuDriverGetVersion)(int*);
|
||||||
|
int (*__cuDeviceGet)(int*, int);
|
||||||
|
int (*__cuDeviceGetAttribute)(int*, int, int);
|
||||||
|
int (*__cuDeviceGetName)(char*, int, int);
|
||||||
|
int (*__cuDeviceTotalMem)(unsigned int*, int);
|
||||||
|
int (*__cuDeviceComputeCapability)(int*, int*, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NVIDIA interfaces are documented here:
|
||||||
|
// http://developer.download.nvidia.com/compute/cuda/2_3/toolkit/docs/online/index.html
|
||||||
|
|
||||||
void COPROC_CUDA::get(
|
void COPROC_CUDA::get(
|
||||||
COPROCS& coprocs, vector<string>& strings,
|
COPROCS& coprocs, vector<string>& strings,
|
||||||
bool use_all // if false, use only those equivalent to most capable
|
bool use_all // if false, use only those equivalent to most capable
|
||||||
|
@ -202,33 +238,11 @@ void COPROC_CUDA::get(
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
typedef int (__stdcall *PCGDC)(int *count);
|
|
||||||
typedef int (__stdcall *PCGDP)(struct cudaDeviceProp *prop, int device);
|
|
||||||
typedef int (__stdcall *PCGDV)(int* version);
|
|
||||||
typedef int (__stdcall *PCGDI)(int);
|
|
||||||
typedef int (__stdcall *PCGDG)(int*, int);
|
|
||||||
typedef int (__stdcall *PCGDA)(int*, int, int);
|
|
||||||
typedef int (__stdcall *PCGDN)(char*, int, int);
|
|
||||||
typedef int (__stdcall *PCGDM)(unsigned int*, int);
|
|
||||||
typedef int (__stdcall *PCGDCC)(int*, int*, int);
|
|
||||||
|
|
||||||
PCGDC __cuDeviceGetCount = NULL;
|
|
||||||
//PCGDP __cuDeviceGetProperties = NULL;
|
|
||||||
PCGDV __cuDriverGetVersion = NULL;
|
|
||||||
PCGDI __cuInit = NULL;
|
|
||||||
PCGDG __cuDeviceGet = NULL;
|
|
||||||
PCGDA __cuDeviceGetAttribute = NULL;
|
|
||||||
PCGDN __cuDeviceGetName = NULL;
|
|
||||||
PCGDM __cuDeviceTotalMem = NULL;
|
|
||||||
PCGDCC __cuDeviceComputeCapability = NULL;
|
|
||||||
|
|
||||||
HMODULE cudalib = LoadLibrary("nvcuda.dll");
|
HMODULE cudalib = LoadLibrary("nvcuda.dll");
|
||||||
if (!cudalib) {
|
if (!cudalib) {
|
||||||
strings.push_back("Can't load library nvcuda.dll");
|
strings.push_back("Can't load library nvcuda.dll");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
__cuDeviceGetCount = (PCGDC)GetProcAddress(cudalib, "cuDeviceGetCount");
|
__cuDeviceGetCount = (PCGDC)GetProcAddress(cudalib, "cuDeviceGetCount");
|
||||||
//__cuDeviceGetProperties = (PCGDP)GetProcAddress(cudalib, "cuDeviceGetProperties");
|
//__cuDeviceGetProperties = (PCGDP)GetProcAddress(cudalib, "cuDeviceGetProperties");
|
||||||
__cuDriverGetVersion = (PCGDV)GetProcAddress(cudalib, "cuDriverGetVersion" );
|
__cuDriverGetVersion = (PCGDV)GetProcAddress(cudalib, "cuDriverGetVersion" );
|
||||||
|
@ -255,16 +269,6 @@ void COPROC_CUDA::get(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
void* cudalib;
|
|
||||||
int (*__cuInit)(int);
|
|
||||||
int (*__cuDeviceGetCount)(int*);
|
|
||||||
//int (*__cuDeviceGetProperties)(cudaDeviceProp*, int);
|
|
||||||
int (*__cuDriverGetVersion)(int*);
|
|
||||||
int (*__cuDeviceGet)(int*, int);
|
|
||||||
int (*__cuDeviceGetAttribute)(int*, int, int);
|
|
||||||
int (*__cuDeviceGetName)(char*, int, int);
|
|
||||||
int (*__cuDeviceTotalMem)(unsigned int*, int);
|
|
||||||
int (*__cuDeviceComputeCapability)(int*, int*, int);
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
cudalib = dlopen("/usr/local/cuda/lib/libcuda.dylib", RTLD_NOW);
|
cudalib = dlopen("/usr/local/cuda/lib/libcuda.dylib", RTLD_NOW);
|
||||||
|
@ -613,6 +617,54 @@ int COPROC_CUDA::parse(FILE* fin) {
|
||||||
return ERR_XML_PARSE;
|
return ERR_XML_PARSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check whether each GPU is running a graphics app (assume yes)
|
||||||
|
// return true if there's been a change since last time
|
||||||
|
//
|
||||||
|
bool COPROC_CUDA::check_running_graphics_app() {
|
||||||
|
int retval, j;
|
||||||
|
bool change = false;
|
||||||
|
for (j=0; j<count; j++) {
|
||||||
|
bool new_val = true;
|
||||||
|
int device, kernel_timeout;
|
||||||
|
retval = (*__cuDeviceGet)(&device, j);
|
||||||
|
if (!retval) {
|
||||||
|
retval = (*__cuDeviceGetAttribute)(&kernel_timeout, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, device);
|
||||||
|
if (!retval && !kernel_timeout) {
|
||||||
|
new_val = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (new_val != running_graphics_app[j]) {
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
running_graphics_app[j] = new_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////// ATI STARTS HERE /////////////////
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef int (__stdcall *PCGDC)(CALuint *numDevices);
|
||||||
|
typedef int (__stdcall *ATTRIBS) (CALdeviceattribs *attribs, CALuint ordinal);
|
||||||
|
typedef int (__stdcall *INFO) (CALdeviceinfo *info, CALuint ordinal);
|
||||||
|
typedef int (__stdcall *VER) (CALuint *cal_major, CALuint *cal_minor, CALuint *cal_imp);
|
||||||
|
typedef int (__stdcall *PCGDI)(void);
|
||||||
|
typedef int (__stdcall *CLOSE)(void);
|
||||||
|
|
||||||
|
PCGDI __calInit = NULL;
|
||||||
|
VER __calGetVersion = NULL;
|
||||||
|
PCGDC __calDeviceGetCount = NULL;
|
||||||
|
ATTRIBS __calDeviceGetAttribs = NULL;
|
||||||
|
INFO __calDeviceGetInfo = NULL;
|
||||||
|
CLOSE __calShutdown = NULL;
|
||||||
|
#else
|
||||||
|
int (*__calInit)();
|
||||||
|
int (*__calGetVersion)(CALuint*, CALuint*, CALuint*);
|
||||||
|
int (*__calDeviceGetCount)(CALuint*);
|
||||||
|
int (*__calDeviceGetAttribs)(CALdeviceattribs*, CALuint);
|
||||||
|
int (*__calDeviceGetInfo)(CALdeviceinfo*, CALuint);
|
||||||
|
int (*__calShutdown)();
|
||||||
|
#endif
|
||||||
|
|
||||||
void COPROC_ATI::get(COPROCS& coprocs, vector<string>& strings) {
|
void COPROC_ATI::get(COPROCS& coprocs, vector<string>& strings) {
|
||||||
CALuint numDevices, cal_major, cal_minor, cal_imp;
|
CALuint numDevices, cal_major, cal_minor, cal_imp;
|
||||||
CALdevice device;
|
CALdevice device;
|
||||||
|
@ -626,20 +678,6 @@ void COPROC_ATI::get(COPROCS& coprocs, vector<string>& strings) {
|
||||||
numDevices =0;
|
numDevices =0;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
typedef int (__stdcall *PCGDC)(CALuint *numDevices);
|
|
||||||
typedef int (__stdcall *ATTRIBS) (CALdeviceattribs *attribs, CALuint ordinal);
|
|
||||||
typedef int (__stdcall *INFO) (CALdeviceinfo *info, CALuint ordinal);
|
|
||||||
typedef int (__stdcall *VER) (CALuint *cal_major, CALuint *cal_minor, CALuint *cal_imp);
|
|
||||||
typedef int (__stdcall *PCGDI)(void);
|
|
||||||
typedef int (__stdcall *CLOSE)(void);
|
|
||||||
|
|
||||||
PCGDI __calInit = NULL;
|
|
||||||
VER __calGetVersion = NULL;
|
|
||||||
PCGDC __calDeviceGetCount = NULL;
|
|
||||||
ATTRIBS __calDeviceGetAttribs = NULL;
|
|
||||||
INFO __calDeviceGetInfo = NULL;
|
|
||||||
CLOSE __calShutdown = NULL;
|
|
||||||
|
|
||||||
#if defined _M_X64
|
#if defined _M_X64
|
||||||
// TRY CAL 1.4 first driver > 9.2
|
// TRY CAL 1.4 first driver > 9.2
|
||||||
HINSTANCE callib = LoadLibrary("aticalrt64.dll");
|
HINSTANCE callib = LoadLibrary("aticalrt64.dll");
|
||||||
|
@ -665,12 +703,6 @@ void COPROC_ATI::get(COPROCS& coprocs, vector<string>& strings) {
|
||||||
__calShutdown = (CLOSE)GetProcAddress(callib, "calShutdown" );
|
__calShutdown = (CLOSE)GetProcAddress(callib, "calShutdown" );
|
||||||
#else
|
#else
|
||||||
void* callib;
|
void* callib;
|
||||||
int (*__calInit)();
|
|
||||||
int (*__calGetVersion)(CALuint*, CALuint*, CALuint*);
|
|
||||||
int (*__calDeviceGetCount)(CALuint*);
|
|
||||||
int (*__calDeviceGetAttribs)(CALdeviceattribs*, CALuint);
|
|
||||||
int (*__calDeviceGetInfo)(CALdeviceinfo*, CALuint);
|
|
||||||
int (*__calShutdown)();
|
|
||||||
|
|
||||||
callib = dlopen("libaticalrt.so", RTLD_NOW);
|
callib = dlopen("libaticalrt.so", RTLD_NOW);
|
||||||
if (!callib) {
|
if (!callib) {
|
||||||
|
|
|
@ -114,6 +114,8 @@ struct COPROC {
|
||||||
//
|
//
|
||||||
int device_nums[MAX_COPROC_INSTANCES];
|
int device_nums[MAX_COPROC_INSTANCES];
|
||||||
int device_num; // temp used in scan process
|
int device_num; // temp used in scan process
|
||||||
|
bool running_graphics_app[MAX_COPROC_INSTANCES];
|
||||||
|
// is this GPU running a graphics app (NVIDIA only)
|
||||||
|
|
||||||
#ifndef _USING_FCGI_
|
#ifndef _USING_FCGI_
|
||||||
virtual void write_xml(MIOFILE&);
|
virtual void write_xml(MIOFILE&);
|
||||||
|
@ -126,6 +128,10 @@ struct COPROC {
|
||||||
req_secs = 0;
|
req_secs = 0;
|
||||||
req_instances = 0;
|
req_instances = 0;
|
||||||
estimated_delay = 0;
|
estimated_delay = 0;
|
||||||
|
for (int i=0; i<MAX_COPROC_INSTANCES; i++) {
|
||||||
|
device_nums[i] = 0;
|
||||||
|
running_graphics_app[i] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
COPROC(const char* t){
|
COPROC(const char* t){
|
||||||
clear();
|
clear();
|
||||||
|
@ -242,6 +248,8 @@ struct COPROC_CUDA : public COPROC {
|
||||||
double x = (prop.clockRate * prop.multiProcessorCount)*5e10/(14*1.25e6);
|
double x = (prop.clockRate * prop.multiProcessorCount)*5e10/(14*1.25e6);
|
||||||
return x?x:5e10;
|
return x?x:5e10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_running_graphics_app();
|
||||||
};
|
};
|
||||||
|
|
||||||
void fake_cuda(COPROCS&, int);
|
void fake_cuda(COPROCS&, int);
|
||||||
|
|
|
@ -62,7 +62,6 @@
|
||||||
#include "sched_util.h"
|
#include "sched_util.h"
|
||||||
#include "sched_msgs.h"
|
#include "sched_msgs.h"
|
||||||
|
|
||||||
|
|
||||||
#define LOCKFILE "file_deleter.out"
|
#define LOCKFILE "file_deleter.out"
|
||||||
#define PIDFILE "file_deleter.pid"
|
#define PIDFILE "file_deleter.pid"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue