2008-08-06 18:36:30 +00:00
|
|
|
// This file is part of BOINC.
|
2008-03-20 03:13:30 +00:00
|
|
|
// http://boinc.berkeley.edu
|
|
|
|
// Copyright (C) 2008 University of California
|
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// BOINC is free software; you can redistribute it and/or modify it
|
|
|
|
// under the terms of the GNU Lesser General Public License
|
|
|
|
// as published by the Free Software Foundation,
|
|
|
|
// either version 3 of the License, or (at your option) any later version.
|
2008-03-20 03:13:30 +00:00
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// BOINC is distributed in the hope that it will be useful,
|
2008-03-20 03:13:30 +00:00
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
// See the GNU Lesser General Public License for more details.
|
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
2008-03-20 03:13:30 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
// Replace the following with your own code.
|
|
|
|
// WARNING: after doing this, you must prevent this file from
|
|
|
|
// being overwritten the next time you update BOINC source code.
|
|
|
|
// You can either:
|
|
|
|
// 1) write-protect this file, or
|
|
|
|
// 2) put this in a differently-named file and change the Makefile.am
|
2008-12-10 19:14:13 +00:00
|
|
|
// (and write-protect that)
|
2008-03-20 03:13:30 +00:00
|
|
|
// In either case, put your version under source-code control, e.g. SVN
|
|
|
|
|
2008-12-19 21:27:02 +00:00
|
|
|
#include "str_util.h"
|
2008-05-06 19:53:49 +00:00
|
|
|
#include "sched_config.h"
|
2008-03-27 18:25:29 +00:00
|
|
|
#include "sched_msgs.h"
|
2008-03-20 03:13:30 +00:00
|
|
|
#include "sched_plan.h"
|
|
|
|
|
2008-03-27 18:25:29 +00:00
|
|
|
// return the number of usable CPUs, taking prefs into account.
|
|
|
|
// If prefs limit apply, set bounded to true.
|
|
|
|
//
|
|
|
|
static void get_ncpus(SCHEDULER_REQUEST& sreq, int& ncpus, bool& bounded) {
|
|
|
|
ncpus = sreq.host.p_ncpus;
|
|
|
|
bounded = false;
|
|
|
|
if (sreq.global_prefs.max_ncpus_pct && sreq.global_prefs.max_ncpus_pct < 100) {
|
|
|
|
bounded = true;
|
|
|
|
ncpus = (int)((ncpus*sreq.global_prefs.max_ncpus_pct)/100.);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool app_plan(SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu) {
|
|
|
|
if (!strcmp(plan_class, "mt")) {
|
|
|
|
// the following is for an app that can use anywhere
|
|
|
|
// from 1 to 64 threads, can control this exactly,
|
|
|
|
// and whose speedup is .95N
|
2008-03-28 18:00:27 +00:00
|
|
|
// (so on a uniprocessor, we'll use a sequential app
|
|
|
|
// if one is available)
|
2008-03-27 18:25:29 +00:00
|
|
|
//
|
|
|
|
int ncpus, nthreads;
|
|
|
|
bool bounded;
|
|
|
|
|
|
|
|
get_ncpus(sreq, ncpus, bounded);
|
|
|
|
nthreads = ncpus;
|
|
|
|
if (nthreads > 64) nthreads = 64;
|
|
|
|
hu.avg_ncpus = nthreads;
|
|
|
|
hu.max_ncpus = nthreads;
|
|
|
|
sprintf(hu.cmdline, "--nthreads %d", nthreads);
|
|
|
|
hu.flops = 0.95*sreq.host.p_fpops*nthreads;
|
|
|
|
return true;
|
2008-03-28 18:00:27 +00:00
|
|
|
} else if (!strcmp(plan_class, "cuda")) {
|
2008-12-18 21:25:51 +00:00
|
|
|
if (g_wreq->no_gpus) {
|
|
|
|
if (config.debug_version_select) {
|
|
|
|
log_messages.printf(MSG_DEBUG,
|
|
|
|
"Skipping CUDA version - user prefs say no GPUS\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2008-03-28 18:00:27 +00:00
|
|
|
// the following is for an app that uses a CUDA GPU
|
|
|
|
// and some CPU also, and gets 50 GFLOPS total
|
|
|
|
//
|
|
|
|
for (unsigned int i=0; i<sreq.coprocs.coprocs.size(); i++) {
|
2008-03-31 16:19:45 +00:00
|
|
|
COPROC* cp = sreq.coprocs.coprocs[i];
|
2008-05-09 20:54:52 +00:00
|
|
|
if (!strcmp(cp->type, "CUDA")) {
|
2008-08-28 18:41:18 +00:00
|
|
|
COPROC_CUDA* cp2 = (COPROC_CUDA*) cp;
|
2008-12-17 20:53:46 +00:00
|
|
|
int v = (cp2->prop.major)*100 + cp2->prop.minor;
|
|
|
|
if (v < 101) {
|
|
|
|
log_messages.printf(MSG_DEBUG,
|
|
|
|
"CUDA version %d < 1.1\n", v
|
|
|
|
);
|
2008-08-28 18:41:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
2008-12-10 19:14:13 +00:00
|
|
|
|
2008-12-22 20:01:30 +00:00
|
|
|
if (cp2->prop.totalGlobalMem < 254*1024*1024) {
|
2008-12-19 20:55:49 +00:00
|
|
|
log_messages.printf(MSG_DEBUG,
|
2008-12-22 20:01:30 +00:00
|
|
|
"CUDA mem %d < 254MB\n", cp2->prop.totalGlobalMem
|
2008-12-19 20:55:49 +00:00
|
|
|
);
|
2008-12-15 23:35:40 +00:00
|
|
|
return false;
|
2008-12-10 19:14:13 +00:00
|
|
|
}
|
2008-05-09 20:54:52 +00:00
|
|
|
COPROC* cu = new COPROC (cp->type);
|
2008-03-31 16:19:45 +00:00
|
|
|
cu->count = 1;
|
2008-03-28 18:00:27 +00:00
|
|
|
hu.coprocs.coprocs.push_back(cu);
|
2008-12-08 19:39:19 +00:00
|
|
|
|
|
|
|
// assume we'll need 100 MFLOPS to keep the GPU fed
|
|
|
|
//
|
|
|
|
double x = 1e8/sreq.host.p_fpops;
|
2008-03-28 18:00:27 +00:00
|
|
|
if (x > 1) x = 1;
|
|
|
|
hu.avg_ncpus = x;
|
|
|
|
hu.max_ncpus = x;
|
2008-12-08 19:39:19 +00:00
|
|
|
|
|
|
|
// estimate the FLOPS we're going to get from the GPU.
|
|
|
|
// The following is based on SETI@home CUDA,
|
|
|
|
// which gets 50 GFLOPS on a Quadro FX 3700,
|
|
|
|
// which has 14 MPs and a clock rate of 1.25 MHz
|
|
|
|
//
|
|
|
|
x = (double)cp2->prop.clockRate * (double)cp2->prop.multiProcessorCount;
|
|
|
|
double y = 14.*1250000.;
|
|
|
|
if (!x) x = y;
|
|
|
|
|
|
|
|
hu.flops = 5e10 * (x/y);
|
2008-12-17 20:53:46 +00:00
|
|
|
if (config.debug_version_select) {
|
|
|
|
log_messages.printf(MSG_DEBUG,
|
2008-12-19 21:27:02 +00:00
|
|
|
"CUDA app estimated %.2f GFLOPS (clock %d count %d)\n",
|
|
|
|
hu.flops/GIGA, cp2->prop.clockRate,
|
|
|
|
cp2->prop.multiProcessorCount
|
2008-12-17 20:53:46 +00:00
|
|
|
);
|
|
|
|
}
|
2008-03-28 18:00:27 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2008-05-06 19:53:49 +00:00
|
|
|
if (config.debug_version_select) {
|
|
|
|
log_messages.printf(MSG_DEBUG,
|
|
|
|
"Host lacks CUDA coprocessor for plan class %s\n", plan_class
|
|
|
|
);
|
|
|
|
}
|
2008-03-28 18:00:27 +00:00
|
|
|
return false;
|
2008-03-27 18:25:29 +00:00
|
|
|
}
|
|
|
|
log_messages.printf(MSG_CRITICAL,
|
|
|
|
"Unknown plan class: %s\n", plan_class
|
|
|
|
);
|
2008-03-20 03:13:30 +00:00
|
|
|
return false;
|
|
|
|
}
|