2008-09-06 12:23:56 +00:00
|
|
|
// This file is part of BOINC.
|
|
|
|
// http://boinc.berkeley.edu
|
|
|
|
// Copyright (C) 2008 University of California
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// BOINC is distributed in the hope that it will be useful,
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2009-02-26 00:23:23 +00:00
|
|
|
#ifndef _USING_FCGI_
|
|
|
|
#include "boinc_fcgi.h"
|
|
|
|
#else
|
|
|
|
#include <cstdio>
|
2009-08-15 00:00:57 +00:00
|
|
|
#endif
|
2009-02-26 00:23:23 +00:00
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
#include <cstdlib>
|
2008-09-06 12:23:56 +00:00
|
|
|
#ifdef _WIN32
|
2009-02-18 21:21:12 +00:00
|
|
|
#ifndef SIM
|
2009-02-16 23:03:03 +00:00
|
|
|
#include <nvapi.h>
|
2009-02-18 21:21:12 +00:00
|
|
|
#endif
|
2008-09-06 12:23:56 +00:00
|
|
|
#else
|
|
|
|
#ifdef __APPLE__
|
|
|
|
// Suppress obsolete warning when building for OS 10.3.9
|
|
|
|
#define DLOPEN_NO_WARN
|
|
|
|
#endif
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "error_numbers.h"
|
|
|
|
#include "filesys.h"
|
|
|
|
#include "parse.h"
|
2008-12-16 18:46:28 +00:00
|
|
|
#include "str_util.h"
|
2008-09-06 12:23:56 +00:00
|
|
|
|
|
|
|
#include "coproc.h"
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
using std::vector;
|
|
|
|
|
2009-02-26 00:23:23 +00:00
|
|
|
#ifndef _USING_FCGI_
|
|
|
|
using std::perror;
|
|
|
|
#endif
|
|
|
|
|
2008-09-06 12:23:56 +00:00
|
|
|
#ifndef _USING_FCGI_
|
|
|
|
void COPROC::write_xml(MIOFILE& f) {
|
|
|
|
f.printf(
|
|
|
|
"<coproc>\n"
|
|
|
|
" <type>%s</type>\n"
|
|
|
|
" <count>%d</count>\n"
|
|
|
|
"</coproc>\n",
|
|
|
|
type, count
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-08-24 23:16:17 +00:00
|
|
|
int COPROC_REQ::parse(MIOFILE& fin) {
|
|
|
|
char buf[1024];
|
|
|
|
strcpy(type, "");
|
|
|
|
count = 0;
|
|
|
|
while (fin.fgets(buf, sizeof(buf))) {
|
|
|
|
if (match_tag(buf, "</coproc>")) {
|
|
|
|
if (!strlen(type)) return ERR_XML_PARSE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (parse_str(buf, "<type>", type, sizeof(type))) continue;
|
|
|
|
if (parse_double(buf, "<count>", count)) continue;
|
|
|
|
}
|
|
|
|
return ERR_XML_PARSE;
|
|
|
|
}
|
|
|
|
|
2008-09-06 12:23:56 +00:00
|
|
|
int COPROC::parse(MIOFILE& fin) {
|
|
|
|
char buf[1024];
|
|
|
|
strcpy(type, "");
|
|
|
|
count = 0;
|
|
|
|
used = 0;
|
2009-01-03 06:01:17 +00:00
|
|
|
req_secs = 0;
|
2009-01-30 21:25:24 +00:00
|
|
|
estimated_delay = 0;
|
2009-01-03 06:01:17 +00:00
|
|
|
req_instances = 0;
|
2008-09-06 12:23:56 +00:00
|
|
|
while (fin.fgets(buf, sizeof(buf))) {
|
|
|
|
if (match_tag(buf, "</coproc>")) {
|
|
|
|
if (!strlen(type)) return ERR_XML_PARSE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (parse_str(buf, "<type>", type, sizeof(type))) continue;
|
|
|
|
if (parse_int(buf, "<count>", count)) continue;
|
2009-01-03 06:01:17 +00:00
|
|
|
if (parse_double(buf, "<req_secs>", req_secs)) continue;
|
2009-08-19 18:41:47 +00:00
|
|
|
if (parse_double(buf, "<req_instances>", req_instances)) continue;
|
2009-01-30 21:25:24 +00:00
|
|
|
if (parse_double(buf, "<estimated_delay>", estimated_delay)) continue;
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
|
|
|
return ERR_XML_PARSE;
|
|
|
|
}
|
|
|
|
|
2008-12-16 18:46:28 +00:00
|
|
|
void COPROCS::summary_string(char* buf, int len) {
|
|
|
|
char bigbuf[8192], buf2[1024];
|
|
|
|
|
|
|
|
strcpy(bigbuf, "");
|
|
|
|
for (unsigned int i=0; i<coprocs.size(); i++) {
|
|
|
|
COPROC* cp = coprocs[i];
|
|
|
|
if (!strcmp(cp->type, "CUDA")) {
|
|
|
|
COPROC_CUDA* cp2 = (COPROC_CUDA*) cp;
|
2008-12-23 01:28:24 +00:00
|
|
|
int mem = (int)(cp2->prop.dtotalGlobalMem/MEGA);
|
2009-02-24 00:06:45 +00:00
|
|
|
sprintf(buf2, "[CUDA|%s|%d|%dMB|%d]",
|
2009-07-29 21:21:52 +00:00
|
|
|
cp2->prop.name, cp2->count, mem, cp2->display_driver_version
|
2009-02-24 00:06:45 +00:00
|
|
|
);
|
2008-12-16 18:46:28 +00:00
|
|
|
strcat(bigbuf, buf2);
|
2009-08-15 00:00:57 +00:00
|
|
|
} else if (!strcmp(cp->type, "CAL")){
|
2009-08-17 16:50:40 +00:00
|
|
|
COPROC_ATI* cp2 =(COPROC_ATI*) cp;
|
2009-08-15 00:00:57 +00:00
|
|
|
sprintf(buf2,"[CAL|%s|%d|%dMB|%s]",
|
|
|
|
cp2->name, cp2->count, cp2->attribs.localRAM, cp2->version
|
|
|
|
);
|
|
|
|
strcat(bigbuf,buf2);
|
|
|
|
}
|
2008-12-16 18:46:28 +00:00
|
|
|
}
|
|
|
|
bigbuf[len-1] = 0;
|
|
|
|
strcpy(buf, bigbuf);
|
|
|
|
}
|
|
|
|
|
2009-09-24 17:23:33 +00:00
|
|
|
void COPROCS::get(bool use_all, vector<string>&descs, vector<string>&warnings) {
|
|
|
|
COPROC_CUDA::get(*this, use_all, descs, warnings);
|
2009-09-10 22:06:20 +00:00
|
|
|
#ifndef __APPLE__ // ATI does not yet support CAL on Macs
|
2009-09-24 17:23:33 +00:00
|
|
|
COPROC_ATI::get(*this, descs, warnings);
|
2009-09-10 22:06:20 +00:00
|
|
|
#endif
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
|
|
|
|
2009-03-06 22:21:47 +00:00
|
|
|
// used only to parse scheduler request messages
|
|
|
|
//
|
2008-09-06 12:23:56 +00:00
|
|
|
int COPROCS::parse(FILE* fin) {
|
|
|
|
char buf[1024];
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof(buf), fin)) {
|
|
|
|
if (match_tag(buf, "</coprocs>")) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (strstr(buf, "<coproc_cuda>")) {
|
|
|
|
COPROC_CUDA* cc = new COPROC_CUDA;
|
|
|
|
int retval = cc->parse(fin);
|
|
|
|
if (!retval) {
|
|
|
|
coprocs.push_back(cc);
|
|
|
|
}
|
|
|
|
}
|
2009-08-17 16:50:40 +00:00
|
|
|
if (strstr(buf, "<coproc_ati>")) {
|
|
|
|
COPROC_ATI* cc = new COPROC_ATI;
|
2009-08-15 00:00:57 +00:00
|
|
|
int retval = cc->parse(fin);
|
|
|
|
if (!retval) {
|
|
|
|
coprocs.push_back(cc);
|
|
|
|
}
|
|
|
|
}
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
|
|
|
return ERR_XML_PARSE;
|
|
|
|
}
|
|
|
|
|
2009-01-12 23:47:52 +00:00
|
|
|
COPROC* COPROCS::lookup(const char* type) {
|
2008-09-06 12:23:56 +00:00
|
|
|
for (unsigned int i=0; i<coprocs.size(); i++) {
|
|
|
|
COPROC* cp = coprocs[i];
|
|
|
|
if (!strcmp(type, cp->type)) return cp;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2009-05-04 02:22:25 +00:00
|
|
|
// return 1/-1/0 if device 1 is more/less/same capable than device 2.
|
|
|
|
// If "loose", ignore FLOPS and tolerate small memory diff
|
2009-04-21 08:11:28 +00:00
|
|
|
//
|
2009-05-04 02:22:25 +00:00
|
|
|
int cuda_compare(COPROC_CUDA& c1, COPROC_CUDA& c2, bool loose) {
|
2009-04-21 08:11:28 +00:00
|
|
|
if (c1.prop.major > c2.prop.major) return 1;
|
|
|
|
if (c1.prop.major < c2.prop.major) return -1;
|
|
|
|
if (c1.prop.minor > c2.prop.minor) return 1;
|
|
|
|
if (c1.prop.minor < c2.prop.minor) return -1;
|
2009-08-15 00:00:57 +00:00
|
|
|
if (c1.cuda_version > c2.cuda_version) return 1;
|
|
|
|
if (c1.cuda_version < c2.cuda_version) return -1;
|
2009-05-04 02:22:25 +00:00
|
|
|
if (loose) {
|
|
|
|
if (c1.prop.totalGlobalMem > 1.4*c2.prop.totalGlobalMem) return 1;
|
|
|
|
if (c1.prop.totalGlobalMem < .7* c2.prop.totalGlobalMem) return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
2009-04-22 02:09:53 +00:00
|
|
|
if (c1.prop.totalGlobalMem > c2.prop.totalGlobalMem) return 1;
|
|
|
|
if (c1.prop.totalGlobalMem < c2.prop.totalGlobalMem) return -1;
|
2009-07-29 21:35:09 +00:00
|
|
|
double s1 = c1.flops_estimate();
|
|
|
|
double s2 = c2.flops_estimate();
|
|
|
|
if (s1 > s2) return 1;
|
|
|
|
if (s1 < s2) return -1;
|
|
|
|
return 0;
|
2009-04-21 08:11:28 +00:00
|
|
|
}
|
|
|
|
|
2009-08-28 22:55:04 +00:00
|
|
|
#ifdef _WIN32
|
2009-08-28 23:02:15 +00:00
|
|
|
typedef int (__stdcall *CUDA_GDC)(int *count);
|
|
|
|
typedef int (__stdcall *CUDA_GDP)(struct cudaDeviceProp *prop, int device);
|
|
|
|
typedef int (__stdcall *CUDA_GDV)(int* version);
|
|
|
|
typedef int (__stdcall *CUDA_GDI)(int);
|
|
|
|
typedef int (__stdcall *CUDA_GDG)(int*, int);
|
|
|
|
typedef int (__stdcall *CUDA_GDA)(int*, int, int);
|
|
|
|
typedef int (__stdcall *CUDA_GDN)(char*, int, int);
|
|
|
|
typedef int (__stdcall *CUDA_GDM)(unsigned int*, int);
|
|
|
|
typedef int (__stdcall *CUDA_GDCC)(int*, int*, int);
|
|
|
|
|
|
|
|
CUDA_GDC __cuDeviceGetCount = NULL;
|
|
|
|
//CUDA_GDP __cuDeviceGetProperties = NULL;
|
|
|
|
CUDA_GDV __cuDriverGetVersion = NULL;
|
|
|
|
CUDA_GDI __cuInit = NULL;
|
|
|
|
CUDA_GDG __cuDeviceGet = NULL;
|
|
|
|
CUDA_GDA __cuDeviceGetAttribute = NULL;
|
|
|
|
CUDA_GDN __cuDeviceGetName = NULL;
|
|
|
|
CUDA_GDM __cuDeviceTotalMem = NULL;
|
|
|
|
CUDA_GDCC __cuDeviceComputeCapability = NULL;
|
2009-08-28 22:55:04 +00:00
|
|
|
#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
|
|
|
|
|
2009-04-27 23:51:46 +00:00
|
|
|
void COPROC_CUDA::get(
|
2009-09-24 17:23:33 +00:00
|
|
|
COPROCS& coprocs,
|
|
|
|
bool use_all, // if false, use only those equivalent to most capable
|
|
|
|
vector<string>& descs,
|
|
|
|
vector<string>& warnings
|
2009-04-27 23:51:46 +00:00
|
|
|
) {
|
2009-07-29 21:21:52 +00:00
|
|
|
int count, retval;
|
2009-08-24 19:08:05 +00:00
|
|
|
char buf[256];
|
2008-09-06 12:23:56 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
2009-07-29 19:24:28 +00:00
|
|
|
HMODULE cudalib = LoadLibrary("nvcuda.dll");
|
2008-09-06 12:23:56 +00:00
|
|
|
if (!cudalib) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("No NVIDIA library found");
|
2009-04-22 03:59:39 +00:00
|
|
|
return;
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
2009-08-28 23:02:15 +00:00
|
|
|
__cuDeviceGetCount = (CUDA_GDC)GetProcAddress(cudalib, "cuDeviceGetCount");
|
|
|
|
//__cuDeviceGetProperties = (CUDA_GDP)GetProcAddress(cudalib, "cuDeviceGetProperties");
|
|
|
|
__cuDriverGetVersion = (CUDA_GDV)GetProcAddress(cudalib, "cuDriverGetVersion" );
|
|
|
|
__cuInit = (CUDA_GDI)GetProcAddress(cudalib, "cuInit" );
|
|
|
|
__cuDeviceGet = (CUDA_GDG)GetProcAddress(cudalib, "cuDeviceGet" );
|
|
|
|
__cuDeviceGetAttribute = (CUDA_GDA)GetProcAddress(cudalib, "cuDeviceGetAttribute" );
|
|
|
|
__cuDeviceGetName = (CUDA_GDN)GetProcAddress(cudalib, "cuDeviceGetName" );
|
|
|
|
__cuDeviceTotalMem = (CUDA_GDM)GetProcAddress(cudalib, "cuDeviceTotalMem" );
|
|
|
|
__cuDeviceComputeCapability = (CUDA_GDCC)GetProcAddress(cudalib, "cuDeviceComputeCapability" );
|
2009-07-29 21:21:52 +00:00
|
|
|
|
2009-07-29 21:35:09 +00:00
|
|
|
#ifndef SIM
|
2009-07-29 21:21:52 +00:00
|
|
|
NvAPI_Status nvapiStatus;
|
|
|
|
NvDisplayHandle hDisplay;
|
|
|
|
NV_DISPLAY_DRIVER_VERSION Version;
|
|
|
|
memset(&Version, 0, sizeof(Version));
|
|
|
|
Version.version = NV_DISPLAY_DRIVER_VERSION_VER;
|
|
|
|
|
|
|
|
NvAPI_Initialize();
|
|
|
|
for (int i=0; ; i++) {
|
|
|
|
nvapiStatus = NvAPI_EnumNvidiaDisplayHandle(i, &hDisplay);
|
|
|
|
if (nvapiStatus != NVAPI_OK) break;
|
|
|
|
nvapiStatus = NvAPI_GetDisplayDriverVersion(hDisplay, &Version);
|
|
|
|
if (nvapiStatus == NVAPI_OK) break;
|
|
|
|
}
|
|
|
|
#endif
|
2008-09-06 12:23:56 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
2009-07-29 19:24:28 +00:00
|
|
|
cudalib = dlopen("/usr/local/cuda/lib/libcuda.dylib", RTLD_NOW);
|
2008-09-06 12:23:56 +00:00
|
|
|
#else
|
2009-07-29 19:24:28 +00:00
|
|
|
cudalib = dlopen("libcuda.so", RTLD_NOW);
|
2008-09-06 12:23:56 +00:00
|
|
|
#endif
|
|
|
|
if (!cudalib) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("No NVIDIA library found");
|
2009-04-22 03:59:39 +00:00
|
|
|
return;
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
2009-07-29 21:35:09 +00:00
|
|
|
__cuDeviceGetCount = (int(*)(int*)) dlsym(cudalib, "cuDeviceGetCount");
|
2009-08-24 21:41:48 +00:00
|
|
|
//__cuDeviceGetProperties = (int(*)(cudaDeviceProp*, int)) dlsym( cudalib, "cuDeviceGetProperties" );
|
2009-07-29 21:35:09 +00:00
|
|
|
__cuDriverGetVersion = (int(*)(int*)) dlsym( cudalib, "cuDriverGetVersion" );
|
|
|
|
__cuInit = (int(*)(int)) dlsym( cudalib, "cuInit" );
|
|
|
|
__cuDeviceGet = (int(*)(int*, int)) dlsym( cudalib, "cuDeviceGet" );
|
|
|
|
__cuDeviceGetAttribute = (int(*)(int*, int, int)) dlsym( cudalib, "cuDeviceGetAttribute" );
|
|
|
|
__cuDeviceGetName = (int(*)(char*, int, int)) dlsym( cudalib, "cuDeviceGetName" );
|
|
|
|
__cuDeviceTotalMem = (int(*)(unsigned int*, int)) dlsym( cudalib, "cuDeviceTotalMem" );
|
|
|
|
__cuDeviceComputeCapability = (int(*)(int*, int*, int)) dlsym( cudalib, "cuDeviceComputeCapability" );
|
2008-09-06 12:23:56 +00:00
|
|
|
#endif
|
|
|
|
|
2009-08-04 22:38:55 +00:00
|
|
|
if (!__cuDriverGetVersion) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("cuDriverGetVersion() missing from NVIDIA library");
|
2009-08-04 22:38:55 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-08-24 21:41:48 +00:00
|
|
|
if (!__cuInit) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("cuInit() missing from NVIDIA library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__cuDeviceGetCount) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("cuDeviceGetCount() missing from NVIDIA library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__cuDeviceGet) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("cuDeviceGet() missing from NVIDIA library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__cuDeviceGetAttribute) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("cuDeviceGetAttribute() missing from NVIDIA library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__cuDeviceTotalMem) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("cuDeviceTotalMem() missing from NVIDIA library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__cuDeviceComputeCapability) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("cuDeviceComputeCapability() missing from NVIDIA library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-29 21:35:09 +00:00
|
|
|
retval = (*__cuInit)(0);
|
2009-08-24 19:08:05 +00:00
|
|
|
if (retval) {
|
|
|
|
sprintf(buf, "cuInit() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 19:08:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-07-29 21:21:52 +00:00
|
|
|
|
|
|
|
int cuda_version;
|
2009-07-29 21:35:09 +00:00
|
|
|
retval = (*__cuDriverGetVersion)(&cuda_version);
|
2009-08-24 19:08:05 +00:00
|
|
|
if (retval) {
|
|
|
|
sprintf(buf, "cuDriverGetVersion() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 19:08:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-07-29 19:24:28 +00:00
|
|
|
|
2009-04-22 02:09:53 +00:00
|
|
|
vector<COPROC_CUDA> gpus;
|
2009-07-29 21:35:09 +00:00
|
|
|
retval = (*__cuDeviceGetCount)(&count);
|
2009-08-24 19:08:05 +00:00
|
|
|
if (retval) {
|
|
|
|
sprintf(buf, "cuDeviceGetCount() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 19:08:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-04-22 02:09:53 +00:00
|
|
|
int j;
|
|
|
|
unsigned int i;
|
|
|
|
COPROC_CUDA cc;
|
2008-12-11 21:44:22 +00:00
|
|
|
string s;
|
2009-04-22 02:09:53 +00:00
|
|
|
for (j=0; j<count; j++) {
|
2009-07-29 21:21:52 +00:00
|
|
|
memset(&cc.prop, 0, sizeof(cc.prop));
|
|
|
|
int device;
|
|
|
|
retval = (*__cuDeviceGet)(&device, j);
|
2009-08-24 19:08:05 +00:00
|
|
|
if (retval) {
|
|
|
|
sprintf(buf, "cuDeviceGet(%d) returned %d", j, retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 19:08:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-07-29 21:21:52 +00:00
|
|
|
(*__cuDeviceGetName)(cc.prop.name, 256, device);
|
2009-08-24 19:08:05 +00:00
|
|
|
if (retval) {
|
|
|
|
sprintf(buf, "cuDeviceGetName(%d) returned %d", j, retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 19:08:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-07-29 21:21:52 +00:00
|
|
|
(*__cuDeviceComputeCapability)(&cc.prop.major, &cc.prop.minor, device);
|
|
|
|
(*__cuDeviceTotalMem)(&cc.prop.totalGlobalMem, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.sharedMemPerBlock, CU_DEVICE_ATTRIBUTE_SHARED_MEMORY_PER_BLOCK, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.regsPerBlock, CU_DEVICE_ATTRIBUTE_REGISTERS_PER_BLOCK, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.warpSize, CU_DEVICE_ATTRIBUTE_WARP_SIZE, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.memPitch, CU_DEVICE_ATTRIBUTE_MAX_PITCH, device);
|
|
|
|
retval = (*__cuDeviceGetAttribute)(&cc.prop.maxThreadsPerBlock, CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK, device);
|
|
|
|
retval = (*__cuDeviceGetAttribute)(&cc.prop.maxThreadsDim[0], CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_X, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.maxThreadsDim[1], CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Y, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.maxThreadsDim[2], CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Z, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.maxGridSize[0], CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_X, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.maxGridSize[1], CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Y, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.maxGridSize[2], CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Z, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.clockRate, CU_DEVICE_ATTRIBUTE_CLOCK_RATE, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.totalConstMem, CU_DEVICE_ATTRIBUTE_TOTAL_CONSTANT_MEMORY, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.textureAlignment, CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT, device);
|
|
|
|
(*__cuDeviceGetAttribute)(&cc.prop.deviceOverlap, CU_DEVICE_ATTRIBUTE_GPU_OVERLAP, device);
|
|
|
|
retval = (*__cuDeviceGetAttribute)(&cc.prop.multiProcessorCount, CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT, device);
|
2009-07-29 21:35:09 +00:00
|
|
|
//retval = (*__cuDeviceGetProperties)(&cc.prop, device);
|
2008-12-11 21:44:22 +00:00
|
|
|
if (cc.prop.major <= 0) continue; // major == 0 means emulation
|
|
|
|
if (cc.prop.major > 100) continue; // e.g. 9999 is an error
|
2009-07-29 21:21:52 +00:00
|
|
|
#if defined(_WIN32) && !defined(SIM)
|
|
|
|
cc.display_driver_version = Version.drvVersion;
|
|
|
|
#else
|
|
|
|
cc.display_driver_version = 0;
|
|
|
|
#endif
|
|
|
|
cc.cuda_version = cuda_version;
|
2009-04-22 02:09:53 +00:00
|
|
|
cc.device_num = j;
|
|
|
|
gpus.push_back(cc);
|
|
|
|
}
|
2008-12-11 21:44:22 +00:00
|
|
|
|
2009-04-22 02:09:53 +00:00
|
|
|
if (!gpus.size()) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("No CUDA-capable NVIDIA GPUs found");
|
2009-04-22 02:09:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// identify the most capable instance
|
|
|
|
//
|
|
|
|
COPROC_CUDA best;
|
|
|
|
for (i=0; i<gpus.size(); i++) {
|
|
|
|
if (i==0) {
|
|
|
|
best = gpus[i];
|
2009-04-24 10:56:35 +00:00
|
|
|
} else if (cuda_compare(gpus[i], best, false) > 0) {
|
2009-04-22 02:09:53 +00:00
|
|
|
best = gpus[i];
|
2008-12-11 21:44:22 +00:00
|
|
|
}
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
2009-04-22 02:09:53 +00:00
|
|
|
|
|
|
|
// see which other instances are equivalent,
|
|
|
|
// and set the "count" and "device_nums" fields
|
|
|
|
//
|
|
|
|
best.count = 0;
|
|
|
|
for (i=0; i<gpus.size(); i++) {
|
2009-08-24 19:08:05 +00:00
|
|
|
char buf2[256];
|
2009-08-16 04:02:11 +00:00
|
|
|
gpus[i].description(buf);
|
2009-04-27 23:51:46 +00:00
|
|
|
if (use_all || !cuda_compare(gpus[i], best, true)) {
|
2009-04-22 02:09:53 +00:00
|
|
|
best.device_nums[best.count] = gpus[i].device_num;
|
|
|
|
best.count++;
|
2009-07-22 18:41:02 +00:00
|
|
|
sprintf(buf2, "NVIDIA GPU %d: %s", gpus[i].device_num, buf);
|
2009-04-22 02:09:53 +00:00
|
|
|
} else {
|
2009-07-22 18:41:02 +00:00
|
|
|
sprintf(buf2, "NVIDIA GPU %d (not used): %s", gpus[i].device_num, buf);
|
2009-04-22 02:09:53 +00:00
|
|
|
}
|
2009-09-24 17:23:33 +00:00
|
|
|
descs.push_back(string(buf2));
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
2009-04-22 02:09:53 +00:00
|
|
|
|
2008-12-11 21:44:22 +00:00
|
|
|
COPROC_CUDA* ccp = new COPROC_CUDA;
|
2009-04-22 02:09:53 +00:00
|
|
|
*ccp = best;
|
2008-12-11 21:44:22 +00:00
|
|
|
coprocs.coprocs.push_back(ccp);
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
|
|
|
|
2009-01-14 23:56:07 +00:00
|
|
|
void COPROC_CUDA::description(char* buf) {
|
2009-07-29 21:35:09 +00:00
|
|
|
sprintf(buf, "%s (driver version %d, CUDA version %d, compute capability %d.%d, %.0fMB, est. %.0fGFLOPS)",
|
|
|
|
prop.name, display_driver_version, cuda_version, prop.major, prop.minor, prop.totalGlobalMem/(1024.*1024.), flops_estimate()/1e9
|
|
|
|
);
|
2009-01-14 23:56:07 +00:00
|
|
|
}
|
|
|
|
|
2009-09-08 18:42:24 +00:00
|
|
|
// fake a NVIDIA GPU (for debugging)
|
2008-09-06 12:23:56 +00:00
|
|
|
//
|
|
|
|
void fake_cuda(COPROCS& coprocs, int count) {
|
|
|
|
COPROC_CUDA* cc = new COPROC_CUDA;
|
|
|
|
strcpy(cc->type, "CUDA");
|
|
|
|
cc->count = count;
|
2009-08-13 16:17:26 +00:00
|
|
|
for (int i=0; i<count; i++) {
|
|
|
|
cc->device_nums[i] = i;
|
|
|
|
}
|
|
|
|
cc->display_driver_version = 18000;
|
|
|
|
cc->cuda_version = 2020;
|
2009-09-08 18:42:24 +00:00
|
|
|
strcpy(cc->prop.name, "Fake NVIDIA GPU");
|
2009-01-10 00:48:22 +00:00
|
|
|
cc->prop.totalGlobalMem = 256*1024*1024;
|
2008-09-06 12:23:56 +00:00
|
|
|
cc->prop.sharedMemPerBlock = 100;
|
|
|
|
cc->prop.regsPerBlock = 8;
|
|
|
|
cc->prop.warpSize = 10;
|
|
|
|
cc->prop.memPitch = 10;
|
|
|
|
cc->prop.maxThreadsPerBlock = 20;
|
|
|
|
cc->prop.maxThreadsDim[0] = 2;
|
|
|
|
cc->prop.maxThreadsDim[1] = 2;
|
|
|
|
cc->prop.maxThreadsDim[2] = 2;
|
|
|
|
cc->prop.maxGridSize[0] = 10;
|
|
|
|
cc->prop.maxGridSize[1] = 10;
|
|
|
|
cc->prop.maxGridSize[2] = 10;
|
|
|
|
cc->prop.totalConstMem = 10;
|
|
|
|
cc->prop.major = 1;
|
2008-09-25 02:21:38 +00:00
|
|
|
cc->prop.minor = 2;
|
2009-01-10 00:48:22 +00:00
|
|
|
cc->prop.clockRate = 1250000;
|
2008-09-06 12:23:56 +00:00
|
|
|
cc->prop.textureAlignment = 1000;
|
2009-01-10 00:48:22 +00:00
|
|
|
cc->prop.multiProcessorCount = 14;
|
2008-09-06 12:23:56 +00:00
|
|
|
coprocs.coprocs.push_back(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _USING_FCGI_
|
|
|
|
void COPROC_CUDA::write_xml(MIOFILE& f) {
|
|
|
|
f.printf(
|
|
|
|
"<coproc_cuda>\n"
|
|
|
|
" <count>%d</count>\n"
|
|
|
|
" <name>%s</name>\n"
|
2009-01-03 06:01:17 +00:00
|
|
|
" <req_secs>%f</req_secs>\n"
|
2009-08-19 18:41:47 +00:00
|
|
|
" <req_instances>%f</req_instances>\n"
|
2009-01-30 21:25:24 +00:00
|
|
|
" <estimated_delay>%f</estimated_delay>\n"
|
2009-02-16 23:03:03 +00:00
|
|
|
" <drvVersion>%d</drvVersion>\n"
|
2009-07-29 21:21:52 +00:00
|
|
|
" <cudaVersion>%d</cudaVersion>\n"
|
2008-09-06 12:23:56 +00:00
|
|
|
" <totalGlobalMem>%u</totalGlobalMem>\n"
|
|
|
|
" <sharedMemPerBlock>%u</sharedMemPerBlock>\n"
|
|
|
|
" <regsPerBlock>%d</regsPerBlock>\n"
|
|
|
|
" <warpSize>%d</warpSize>\n"
|
|
|
|
" <memPitch>%u</memPitch>\n"
|
|
|
|
" <maxThreadsPerBlock>%d</maxThreadsPerBlock>\n"
|
|
|
|
" <maxThreadsDim>%d %d %d</maxThreadsDim>\n"
|
|
|
|
" <maxGridSize>%d %d %d</maxGridSize>\n"
|
|
|
|
" <totalConstMem>%u</totalConstMem>\n"
|
|
|
|
" <major>%d</major>\n"
|
|
|
|
" <minor>%d</minor>\n"
|
|
|
|
" <clockRate>%d</clockRate>\n"
|
|
|
|
" <textureAlignment>%u</textureAlignment>\n"
|
2008-12-08 19:12:38 +00:00
|
|
|
" <deviceOverlap>%d</deviceOverlap>\n"
|
|
|
|
" <multiProcessorCount>%d</multiProcessorCount>\n"
|
2008-09-06 12:23:56 +00:00
|
|
|
"</coproc_cuda>\n",
|
|
|
|
count,
|
2009-01-10 00:48:22 +00:00
|
|
|
prop.name,
|
2009-01-03 06:01:17 +00:00
|
|
|
req_secs,
|
|
|
|
req_instances,
|
2009-01-30 21:25:24 +00:00
|
|
|
estimated_delay,
|
2009-07-29 21:21:52 +00:00
|
|
|
display_driver_version,
|
|
|
|
cuda_version,
|
2008-09-06 12:23:56 +00:00
|
|
|
(unsigned int)prop.totalGlobalMem,
|
|
|
|
(unsigned int)prop.sharedMemPerBlock,
|
|
|
|
prop.regsPerBlock,
|
|
|
|
prop.warpSize,
|
|
|
|
(unsigned int)prop.memPitch,
|
|
|
|
prop.maxThreadsPerBlock,
|
|
|
|
prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2],
|
|
|
|
prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2],
|
|
|
|
(unsigned int)prop.totalConstMem,
|
|
|
|
prop.major,
|
|
|
|
prop.minor,
|
|
|
|
prop.clockRate,
|
2008-12-08 19:12:38 +00:00
|
|
|
(unsigned int)prop.textureAlignment,
|
|
|
|
prop.deviceOverlap,
|
|
|
|
prop.multiProcessorCount
|
2008-09-06 12:23:56 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void COPROC_CUDA::clear() {
|
|
|
|
count = 0;
|
2009-01-30 21:25:24 +00:00
|
|
|
used = 0;
|
|
|
|
req_secs = 0;
|
|
|
|
req_instances = 0;
|
|
|
|
estimated_delay = -1; // mark as absent
|
2009-07-29 21:21:52 +00:00
|
|
|
cuda_version = 0;
|
|
|
|
display_driver_version = 0;
|
2008-09-06 12:23:56 +00:00
|
|
|
strcpy(prop.name, "");
|
|
|
|
prop.totalGlobalMem = 0;
|
|
|
|
prop.sharedMemPerBlock = 0;
|
|
|
|
prop.regsPerBlock = 0;
|
|
|
|
prop.warpSize = 0;
|
|
|
|
prop.memPitch = 0;
|
|
|
|
prop.maxThreadsPerBlock = 0;
|
|
|
|
prop.maxThreadsDim[0] = 0;
|
|
|
|
prop.maxThreadsDim[1] = 0;
|
|
|
|
prop.maxThreadsDim[2] = 0;
|
|
|
|
prop.maxGridSize[0] = 0;
|
|
|
|
prop.maxGridSize[1] = 0;
|
|
|
|
prop.maxGridSize[2] = 0;
|
2008-12-19 19:33:30 +00:00
|
|
|
prop.clockRate = 0;
|
2008-09-06 12:23:56 +00:00
|
|
|
prop.totalConstMem = 0;
|
|
|
|
prop.major = 0;
|
|
|
|
prop.minor = 0;
|
|
|
|
prop.textureAlignment = 0;
|
2008-12-19 19:33:30 +00:00
|
|
|
prop.deviceOverlap = 0;
|
|
|
|
prop.multiProcessorCount = 0;
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int COPROC_CUDA::parse(FILE* fin) {
|
|
|
|
char buf[1024], buf2[256];
|
|
|
|
|
|
|
|
clear();
|
|
|
|
while (fgets(buf, sizeof(buf), fin)) {
|
2008-12-22 22:12:57 +00:00
|
|
|
if (strstr(buf, "</coproc_cuda>")) {
|
|
|
|
return 0;
|
|
|
|
}
|
2008-09-06 12:23:56 +00:00
|
|
|
if (parse_int(buf, "<count>", count)) continue;
|
2009-01-03 06:01:17 +00:00
|
|
|
if (parse_double(buf, "<req_secs>", req_secs)) continue;
|
2009-08-19 18:41:47 +00:00
|
|
|
if (parse_double(buf, "<req_instances>", req_instances)) continue;
|
2009-01-30 21:25:24 +00:00
|
|
|
if (parse_double(buf, "<estimated_delay>", estimated_delay)) continue;
|
2008-09-06 12:23:56 +00:00
|
|
|
if (parse_str(buf, "<name>", prop.name, sizeof(prop.name))) continue;
|
2009-07-29 21:21:52 +00:00
|
|
|
if (parse_int(buf, "<drvVersion>", display_driver_version)) continue;
|
|
|
|
if (parse_int(buf, "<cudaVersion>", cuda_version)) continue;
|
2008-12-22 22:12:57 +00:00
|
|
|
if (parse_double(buf, "<totalGlobalMem>", prop.dtotalGlobalMem)) continue;
|
2008-09-06 12:23:56 +00:00
|
|
|
if (parse_int(buf, "<sharedMemPerBlock>", (int&)prop.sharedMemPerBlock)) continue;
|
|
|
|
if (parse_int(buf, "<regsPerBlock>", prop.regsPerBlock)) continue;
|
|
|
|
if (parse_int(buf, "<warpSize>", prop.warpSize)) continue;
|
|
|
|
if (parse_int(buf, "<memPitch>", (int&)prop.memPitch)) continue;
|
|
|
|
if (parse_int(buf, "<maxThreadsPerBlock>", prop.maxThreadsPerBlock)) continue;
|
|
|
|
if (parse_str(buf, "<maxThreadsDim>", buf2, sizeof(buf2))) {
|
|
|
|
// can't use sscanf here (FCGI)
|
|
|
|
//
|
|
|
|
prop.maxThreadsDim[0] = atoi(buf2);
|
|
|
|
char* p = strchr(buf2, ' ');
|
|
|
|
if (p) {
|
2008-12-22 22:17:26 +00:00
|
|
|
p++;
|
2008-09-06 12:23:56 +00:00
|
|
|
prop.maxThreadsDim[1] = atoi(p);
|
|
|
|
p = strchr(p, ' ');
|
|
|
|
if (p) {
|
2008-12-22 22:17:26 +00:00
|
|
|
p++;
|
2008-09-06 12:23:56 +00:00
|
|
|
prop.maxThreadsDim[2] = atoi(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_str(buf, "<maxGridSize>", buf2, sizeof(buf2))) {
|
|
|
|
prop.maxGridSize[0] = atoi(buf2);
|
|
|
|
char* p = strchr(buf2, ' ');
|
|
|
|
if (p) {
|
2008-12-22 22:17:26 +00:00
|
|
|
p++;
|
2008-09-06 12:23:56 +00:00
|
|
|
prop.maxGridSize[1] = atoi(p);
|
|
|
|
p = strchr(p, ' ');
|
|
|
|
if (p) {
|
2008-12-22 22:17:26 +00:00
|
|
|
p++;
|
2008-09-06 12:23:56 +00:00
|
|
|
prop.maxGridSize[2] = atoi(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2008-12-19 19:33:30 +00:00
|
|
|
if (parse_int(buf, "<clockRate>", prop.clockRate)) continue;
|
2008-09-06 12:23:56 +00:00
|
|
|
if (parse_int(buf, "<totalConstMem>", (int&)prop.totalConstMem)) continue;
|
|
|
|
if (parse_int(buf, "<major>", prop.major)) continue;
|
|
|
|
if (parse_int(buf, "<minor>", prop.minor)) continue;
|
|
|
|
if (parse_int(buf, "<textureAlignment>", (int&)prop.textureAlignment)) continue;
|
2008-12-19 19:33:30 +00:00
|
|
|
if (parse_int(buf, "<deviceOverlap>", prop.deviceOverlap)) continue;
|
|
|
|
if (parse_int(buf, "<multiProcessorCount>", prop.multiProcessorCount)) continue;
|
2008-09-06 12:23:56 +00:00
|
|
|
}
|
|
|
|
return ERR_XML_PARSE;
|
|
|
|
}
|
2009-08-14 22:54:34 +00:00
|
|
|
|
2009-08-28 22:55:04 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2009-08-28 23:02:15 +00:00
|
|
|
return change;
|
2009-08-28 22:55:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////// ATI STARTS HERE /////////////////
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
2009-08-28 23:02:15 +00:00
|
|
|
typedef int (__stdcall *ATI_GDC)(CALuint *numDevices);
|
|
|
|
typedef int (__stdcall *ATI_ATTRIBS) (CALdeviceattribs *attribs, CALuint ordinal);
|
|
|
|
typedef int (__stdcall *ATI_INFO) (CALdeviceinfo *info, CALuint ordinal);
|
|
|
|
typedef int (__stdcall *ATI_VER) (CALuint *cal_major, CALuint *cal_minor, CALuint *cal_imp);
|
|
|
|
typedef int (__stdcall *ATI_GDI)(void);
|
|
|
|
typedef int (__stdcall *ATI_CLOSE)(void);
|
|
|
|
|
|
|
|
ATI_GDI __calInit = NULL;
|
|
|
|
ATI_VER __calGetVersion = NULL;
|
|
|
|
ATI_GDC __calDeviceGetCount = NULL;
|
|
|
|
ATI_ATTRIBS __calDeviceGetAttribs = NULL;
|
|
|
|
ATI_INFO __calDeviceGetInfo = NULL;
|
|
|
|
ATI_CLOSE __calShutdown = NULL;
|
2009-08-28 22:55:04 +00:00
|
|
|
#else
|
|
|
|
int (*__calInit)();
|
|
|
|
int (*__calGetVersion)(CALuint*, CALuint*, CALuint*);
|
|
|
|
int (*__calDeviceGetCount)(CALuint*);
|
|
|
|
int (*__calDeviceGetAttribs)(CALdeviceattribs*, CALuint);
|
|
|
|
int (*__calDeviceGetInfo)(CALdeviceinfo*, CALuint);
|
|
|
|
int (*__calShutdown)();
|
|
|
|
#endif
|
|
|
|
|
2009-09-24 17:23:33 +00:00
|
|
|
void COPROC_ATI::get(COPROCS& coprocs,
|
|
|
|
vector<string>& descs, vector<string>& warnings
|
|
|
|
) {
|
2009-08-15 00:00:57 +00:00
|
|
|
CALuint numDevices, cal_major, cal_minor, cal_imp;
|
|
|
|
CALdevice device;
|
|
|
|
CALdeviceinfo info;
|
|
|
|
CALdeviceattribs attribs;
|
2009-08-24 21:41:48 +00:00
|
|
|
char buf[256];
|
|
|
|
int retval;
|
2009-08-15 00:00:57 +00:00
|
|
|
|
|
|
|
attribs.struct_size = sizeof(CALdeviceattribs);
|
|
|
|
device = 0;
|
|
|
|
numDevices =0;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#if defined _M_X64
|
|
|
|
HINSTANCE callib = LoadLibrary("aticalrt64.dll");
|
|
|
|
#else
|
|
|
|
HINSTANCE callib = LoadLibrary("aticalrt.dll");
|
|
|
|
#endif
|
|
|
|
if (!callib) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("No ATI library found.");
|
2009-08-15 00:12:51 +00:00
|
|
|
return;
|
2009-08-15 00:00:57 +00:00
|
|
|
}
|
2009-08-28 23:02:15 +00:00
|
|
|
__calInit = (ATI_GDI)GetProcAddress(callib, "calInit" );
|
|
|
|
__calDeviceGetCount = (ATI_GDC)GetProcAddress(callib, "calDeviceGetCount" );
|
|
|
|
__calGetVersion = (ATI_VER)GetProcAddress(callib, "calGetVersion" );
|
|
|
|
__calDeviceGetInfo = (ATI_INFO)GetProcAddress(callib, "calDeviceGetInfo" );
|
|
|
|
__calDeviceGetAttribs =(ATI_ATTRIBS)GetProcAddress(callib, "calDeviceGetAttribs" );
|
|
|
|
__calShutdown = (ATI_CLOSE)GetProcAddress(callib, "calShutdown" );
|
2009-08-15 00:00:57 +00:00
|
|
|
#else
|
|
|
|
void* callib;
|
|
|
|
|
2009-08-24 21:41:48 +00:00
|
|
|
callib = dlopen("libaticalrt.so", RTLD_NOW);
|
2009-08-15 00:00:57 +00:00
|
|
|
if (!callib) {
|
2009-09-24 18:33:40 +00:00
|
|
|
warnings.push_back("No ATI library found");
|
2009-08-15 00:00:57 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
__calInit = (int(*)()) dlsym(callib, "calInit");
|
|
|
|
__calGetVersion = (int(*)(CALuint*, CALuint*, CALuint*)) dlsym(callib, "calGetVersion");
|
|
|
|
__calDeviceGetCount = (int(*)(CALuint*)) dlsym(callib, "calDeviceGetCount");
|
|
|
|
__calDeviceGetAttribs = (int(*)(CALdeviceattribs*, CALuint)) dlsym(callib, "calDeviceGetAttribs");
|
|
|
|
__calDeviceGetInfo = (int(*)(CALdeviceinfo*, CALuint)) dlsym(callib, "calDeviceGetInfo");
|
|
|
|
__calShutdown = (int(*)()) dlsym(callib, "calShutdown");
|
|
|
|
#endif
|
|
|
|
|
2009-08-24 21:41:48 +00:00
|
|
|
if (!__calInit) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("calInit() missing from CAL library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__calDeviceGetCount) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("calDeviceGetCount() missing from CAL library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__calGetVersion) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("calGetVersion() missing from CAL library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__calDeviceGetInfo) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("calDeviceGetInfo() missing from CAL library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!__calDeviceGetAttribs) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("calDeviceGetAttribs() missing from CAL library");
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = (*__calInit)();
|
|
|
|
if (retval != CAL_RESULT_OK) {
|
|
|
|
sprintf(buf, "calInit() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
retval = (*__calDeviceGetCount)(&numDevices);
|
|
|
|
if (retval != CAL_RESULT_OK) {
|
|
|
|
sprintf(buf, "calDeviceGetCount() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
retval = (*__calGetVersion)(&cal_major, &cal_minor, &cal_imp);
|
|
|
|
if (retval != CAL_RESULT_OK) {
|
|
|
|
sprintf(buf, "calGetVersion() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-08-15 00:00:57 +00:00
|
|
|
|
|
|
|
if (!numDevices) {
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back("No usable CAL devices found");
|
2009-08-15 00:00:57 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-08-16 04:02:11 +00:00
|
|
|
|
2009-08-17 16:50:40 +00:00
|
|
|
COPROC_ATI cc, cc2;
|
2009-08-16 04:02:11 +00:00
|
|
|
string s, gpu_name;
|
2009-08-17 16:50:40 +00:00
|
|
|
vector<COPROC_ATI> gpus;
|
2009-08-16 04:02:11 +00:00
|
|
|
for (CALuint i=0; i<numDevices; i++) {
|
2009-08-24 21:41:48 +00:00
|
|
|
retval = (*__calDeviceGetInfo)(&info, i);
|
|
|
|
if (retval != CAL_RESULT_OK) {
|
|
|
|
sprintf(buf, "calDeviceGetInfo() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
retval = (*__calDeviceGetAttribs)(&attribs, i);
|
|
|
|
if (retval != CAL_RESULT_OK) {
|
|
|
|
sprintf(buf, "calDeviceGetAttribs() returned %d", retval);
|
2009-09-24 17:23:33 +00:00
|
|
|
warnings.push_back(buf);
|
2009-08-24 21:41:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-08-15 00:00:57 +00:00
|
|
|
switch (info.target) {
|
2009-08-17 16:50:40 +00:00
|
|
|
case CAL_TARGET_600: gpu_name="RV600"; break;
|
|
|
|
case CAL_TARGET_610: gpu_name="RV610"; break;
|
|
|
|
case CAL_TARGET_630: gpu_name="RV630"; break;
|
|
|
|
case CAL_TARGET_670: gpu_name="RV670"; break;
|
|
|
|
case CAL_TARGET_710: gpu_name="R710"; break;
|
|
|
|
case CAL_TARGET_730: gpu_name="R730"; break;
|
|
|
|
case CAL_TARGET_7XX: gpu_name="R7XX"; break;
|
|
|
|
case CAL_TARGET_770: gpu_name="RV770"; break;
|
2009-08-16 04:02:11 +00:00
|
|
|
default: gpu_name="ATI unknown"; break;
|
2009-08-15 00:00:57 +00:00
|
|
|
}
|
|
|
|
cc.attribs = attribs;
|
2009-08-16 04:02:11 +00:00
|
|
|
strcpy(cc.name, gpu_name.c_str());
|
2009-08-18 20:44:12 +00:00
|
|
|
sprintf(cc.version, "%d.%d.%d", cal_major, cal_minor, cal_imp);
|
2009-08-16 04:02:11 +00:00
|
|
|
cc.device_num = i;
|
|
|
|
gpus.push_back(cc);
|
|
|
|
}
|
|
|
|
|
2009-08-17 16:50:40 +00:00
|
|
|
COPROC_ATI best;
|
2009-08-16 04:02:11 +00:00
|
|
|
for (unsigned int i=0; i<gpus.size(); i++) {
|
|
|
|
char buf[256], buf2[256];
|
2009-08-15 00:00:57 +00:00
|
|
|
if (i == 0) {
|
2009-08-16 04:02:11 +00:00
|
|
|
best = gpus[i];
|
2009-09-09 22:18:02 +00:00
|
|
|
} else if (gpus[i].flops_estimate() > best.flops_estimate()) {
|
2009-08-16 04:02:11 +00:00
|
|
|
best = gpus[i];
|
2009-08-15 00:00:57 +00:00
|
|
|
}
|
2009-08-16 04:02:11 +00:00
|
|
|
gpus[i].description(buf);
|
|
|
|
sprintf(buf2, "ATI GPU %d: %s", gpus[i].device_num, buf);
|
2009-09-24 17:23:33 +00:00
|
|
|
descs.push_back(buf2);
|
2009-08-16 04:02:11 +00:00
|
|
|
}
|
|
|
|
for (unsigned int i=0; i<gpus.size(); i++) {
|
|
|
|
best.device_nums[i] = i;
|
2009-08-15 00:00:57 +00:00
|
|
|
}
|
|
|
|
|
2009-08-17 16:50:40 +00:00
|
|
|
COPROC_ATI* ccp = new COPROC_ATI;
|
2009-08-16 04:02:11 +00:00
|
|
|
*ccp = best;
|
2009-08-17 16:50:40 +00:00
|
|
|
strcpy(ccp->type, "ATI");
|
2009-08-15 00:00:57 +00:00
|
|
|
ccp->count = numDevices;
|
|
|
|
coprocs.coprocs.push_back(ccp);
|
|
|
|
__calShutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _USING_FCGI_
|
2009-08-17 16:50:40 +00:00
|
|
|
void COPROC_ATI::write_xml(MIOFILE& f) {
|
2009-08-15 00:00:57 +00:00
|
|
|
f.printf(
|
2009-08-17 16:50:40 +00:00
|
|
|
"<coproc_ati>\n"
|
2009-08-15 00:00:57 +00:00
|
|
|
" <count>%d</count>\n"
|
|
|
|
" <name>%s</name>\n"
|
2009-08-19 18:41:47 +00:00
|
|
|
" <req_secs>%f</req_secs>\n"
|
|
|
|
" <req_instances>%f</req_instances>\n"
|
|
|
|
" <estimated_delay>%f</estimated_delay>\n"
|
2009-08-15 00:00:57 +00:00
|
|
|
" <localRAM>%d</localRAM>\n"
|
|
|
|
" <uncachedRemoteRAM>%d</uncachedRemoteRAM>\n"
|
|
|
|
" <cachedRemoteRAM>%d</cachedRemoteRAM>\n"
|
|
|
|
" <engineClock>%u</engineClock>\n"
|
|
|
|
" <memoryClock>%d</memoryClock>\n"
|
|
|
|
" <wavefrontSize>%d</wavefrontSize>\n"
|
|
|
|
" <numberOfSIMD>%d</numberOfSIMD>\n"
|
|
|
|
" <doublePrecision>%d</doublePrecision>\n"
|
|
|
|
" <pitch_alignment>%d</pitch_alignment>\n"
|
|
|
|
" <surface_alignment>%d</surface_alignment>\n"
|
|
|
|
" <CALVersion>%s</CALVersion>\n"
|
2009-08-17 16:50:40 +00:00
|
|
|
"</coproc_ati>\n",
|
2009-08-15 00:00:57 +00:00
|
|
|
count,
|
|
|
|
name,
|
2009-08-19 18:41:47 +00:00
|
|
|
req_secs,
|
|
|
|
req_instances,
|
|
|
|
estimated_delay,
|
2009-08-15 00:00:57 +00:00
|
|
|
attribs.localRAM,
|
|
|
|
attribs.uncachedRemoteRAM,
|
|
|
|
attribs.cachedRemoteRAM,
|
|
|
|
attribs.engineClock,
|
|
|
|
attribs.memoryClock,
|
|
|
|
attribs.wavefrontSize,
|
|
|
|
attribs.numberOfSIMD,
|
|
|
|
attribs.doublePrecision,
|
|
|
|
attribs.pitch_alignment,
|
|
|
|
attribs.surface_alignment,
|
|
|
|
version
|
|
|
|
);
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2009-08-17 16:50:40 +00:00
|
|
|
void COPROC_ATI::clear() {
|
2009-08-15 00:00:57 +00:00
|
|
|
count = 0;
|
2009-08-19 18:41:47 +00:00
|
|
|
used = 0;
|
|
|
|
req_secs = 0;
|
|
|
|
req_instances = 0;
|
|
|
|
estimated_delay = -1;
|
2009-08-15 00:00:57 +00:00
|
|
|
strcpy(name, "");
|
|
|
|
strcpy(version, "");
|
|
|
|
attribs.localRAM = 0;
|
|
|
|
attribs.uncachedRemoteRAM = 0;
|
|
|
|
attribs.cachedRemoteRAM = 0;
|
|
|
|
attribs.engineClock = 0;
|
|
|
|
attribs.memoryClock = 0;
|
|
|
|
attribs.wavefrontSize = 0;
|
|
|
|
attribs.numberOfSIMD = 0;
|
|
|
|
attribs.doublePrecision = CAL_FALSE;
|
|
|
|
attribs.pitch_alignment = 0;
|
|
|
|
attribs.surface_alignment = 0;
|
|
|
|
}
|
|
|
|
|
2009-08-17 16:50:40 +00:00
|
|
|
int COPROC_ATI::parse(FILE* fin) {
|
2009-08-15 00:00:57 +00:00
|
|
|
char buf[1024];
|
|
|
|
int n;
|
|
|
|
|
|
|
|
clear();
|
|
|
|
while (fgets(buf, sizeof(buf), fin)) {
|
2009-08-17 16:50:40 +00:00
|
|
|
if (strstr(buf, "</coproc_ati>")) return 0;
|
2009-08-15 00:00:57 +00:00
|
|
|
if (parse_int(buf, "<count>", count)) continue;
|
|
|
|
if (parse_str(buf, "<name>", name, sizeof(name))) continue;
|
2009-08-19 18:41:47 +00:00
|
|
|
if (parse_double(buf, "<req_secs>", req_secs)) continue;
|
|
|
|
if (parse_double(buf, "<req_instances>", req_instances)) continue;
|
|
|
|
if (parse_double(buf, "<estimated_delay>", estimated_delay)) continue;
|
|
|
|
|
2009-08-15 00:00:57 +00:00
|
|
|
if (parse_int(buf, "<localRAM>", n)) {
|
|
|
|
attribs.localRAM = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<uncachedRemoteRAM>", n)) {
|
|
|
|
attribs.uncachedRemoteRAM = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<cachedRemoteRAM>", n)) {
|
|
|
|
attribs.cachedRemoteRAM = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<engineClock>", n)) {
|
|
|
|
attribs.engineClock = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<memoryClock>", n)) {
|
|
|
|
attribs.memoryClock = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<wavefrontSize>", n)) {
|
|
|
|
attribs.wavefrontSize = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<numberOfSIMD>" , n)) {
|
|
|
|
attribs.numberOfSIMD = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<doublePrecision>", n)) {
|
|
|
|
attribs.doublePrecision = n?CAL_TRUE:CAL_FALSE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<pitch_alignment>", n)) {
|
|
|
|
attribs.pitch_alignment = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_int(buf, "<surface_alignment>", n)) {
|
|
|
|
attribs.surface_alignment = n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parse_str(buf, "<CALVersion>", version, sizeof(version))) continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
return ERR_XML_PARSE;
|
|
|
|
}
|
2009-08-16 04:02:11 +00:00
|
|
|
|
2009-08-17 16:50:40 +00:00
|
|
|
void COPROC_ATI::description(char* buf) {
|
2009-08-16 04:02:11 +00:00
|
|
|
sprintf(buf, "%s (CAL version %s, %.0fMB, %.0fGFLOPS)",
|
2009-09-09 22:18:02 +00:00
|
|
|
name, version, attribs.localRAM/1024.*1024., flops_estimate()/1.e9
|
2009-08-16 04:02:11 +00:00
|
|
|
);
|
|
|
|
}
|
2009-09-08 18:42:24 +00:00
|
|
|
|
|
|
|
void fake_ati(COPROCS& coprocs, int count) {
|
|
|
|
COPROC_ATI* cc = new COPROC_ATI;
|
|
|
|
strcpy(cc->type, "ATI");
|
|
|
|
strcpy(cc->version, "1.2.3");
|
|
|
|
cc->count = count;
|
|
|
|
cc->attribs.numberOfSIMD = 32;
|
|
|
|
cc->attribs.wavefrontSize = 32;
|
2009-09-08 19:30:06 +00:00
|
|
|
cc->attribs.engineClock = 50;
|
2009-09-08 18:42:24 +00:00
|
|
|
for (int i=0; i<count; i++) {
|
|
|
|
cc->device_nums[i] = i;
|
|
|
|
}
|
|
|
|
coprocs.coprocs.push_back(cc);
|
|
|
|
}
|