2010-05-18 19:22:34 +00:00
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2007 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/>.
2020-06-04 07:48:21 +00:00
# if defined(_WIN32)
2010-05-18 19:22:34 +00:00
# include "boinc_win.h"
# else
# ifdef _USING_FCGI_
# include "boinc_fcgi.h"
# else
# include <cstdio>
# endif
# include <cstring>
# include <cstdlib>
2013-04-11 01:20:22 +00:00
# include <cmath>
2010-05-18 19:22:34 +00:00
# endif
# ifdef _WIN32
# include "win_util.h"
2011-08-31 11:10:22 +00:00
# else
# ifdef __APPLE__
// Suppress obsolete warning when building for OS 10.3.9
# define DLOPEN_NO_WARN
# include <mach-o/dyld.h>
# endif
# include "config.h"
# include <dlfcn.h>
# include <setjmp.h>
# include <signal.h>
2010-05-18 19:22:34 +00:00
# endif
# include "error_numbers.h"
# include "filesys.h"
# include "parse.h"
2011-10-04 03:33:04 +00:00
# include "str_replace.h"
2010-10-27 22:58:16 +00:00
# include "util.h"
2010-05-18 19:22:34 +00:00
2012-08-11 05:47:18 +00:00
# include "coproc.h"
2010-05-18 19:22:34 +00:00
# ifndef _USING_FCGI_
using std : : perror ;
# endif
2011-08-09 21:44:14 +00:00
int COPROC_REQ : : parse ( XML_PARSER & xp ) {
2016-02-15 22:54:13 +00:00
safe_strcpy ( type , " " ) ;
2010-05-18 19:22:34 +00:00
count = 0 ;
2011-09-15 04:24:40 +00:00
while ( ! xp . get_tag ( ) ) {
if ( xp . match_tag ( " /coproc " ) ) {
2010-05-18 19:22:34 +00:00
if ( ! strlen ( type ) ) return ERR_XML_PARSE ;
return 0 ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_str ( " type " , type , sizeof ( type ) ) ) continue ;
if ( xp . parse_double ( " count " , count ) ) continue ;
2010-05-18 19:22:34 +00:00
}
return ERR_XML_PARSE ;
}
2012-06-18 20:41:37 +00:00
int PCI_INFO : : parse ( XML_PARSER & xp ) {
present = false ;
bus_id = device_id = domain_id = 0 ;
while ( ! xp . get_tag ( ) ) {
if ( xp . match_tag ( " /pci_info " ) ) {
return 0 ;
}
if ( xp . parse_int ( " bus_id " , bus_id ) ) continue ;
if ( xp . parse_int ( " device_id " , device_id ) ) continue ;
if ( xp . parse_int ( " domain_id " , domain_id ) ) continue ;
}
return ERR_XML_PARSE ;
}
2010-09-30 22:28:19 +00:00
# ifndef _USING_FCGI_
2011-03-31 15:34:05 +00:00
2012-06-18 20:41:37 +00:00
void PCI_INFO : : write ( MIOFILE & f ) {
f . printf (
" <pci_info> \n "
" <bus_id>%d</bus_id> \n "
" <device_id>%d</device_id> \n "
2012-06-29 22:24:07 +00:00
" <domain_id>%d</domain_id> \n "
" </pci_info> \n " ,
2012-06-18 20:41:37 +00:00
bus_id ,
device_id ,
domain_id
) ;
}
2014-07-16 11:33:26 +00:00
void COPROC : : write_xml ( MIOFILE & f , bool scheduler_rpc ) {
2011-03-31 15:34:05 +00:00
f . printf (
" <coproc> \n "
" <type>%s</type> \n "
2017-06-14 05:35:17 +00:00
" <count>%d</count> \n "
" <peak_flops>%f</peak_flops> \n " ,
type , count , peak_flops
2011-03-31 15:34:05 +00:00
) ;
2014-07-16 11:33:26 +00:00
if ( scheduler_rpc ) {
write_request ( f ) ;
}
if ( have_opencl ) {
opencl_prop . write_xml ( f , " coproc_opencl " ) ;
}
f . printf ( " </coproc> \n " ) ;
2011-03-31 15:34:05 +00:00
}
2010-09-23 20:54:49 +00:00
void COPROC : : write_request ( MIOFILE & f ) {
f . printf (
" <req_secs>%f</req_secs> \n "
" <req_instances>%f</req_instances> \n "
" <estimated_delay>%f</estimated_delay> \n " ,
req_secs ,
req_instances ,
estimated_delay
) ;
}
2014-07-26 17:25:59 +00:00
# endif
2011-03-25 03:44:09 +00:00
int COPROC : : parse ( XML_PARSER & xp ) {
2011-08-10 17:11:08 +00:00
char buf [ 256 ] ;
2016-02-15 22:54:13 +00:00
safe_strcpy ( type , " " ) ;
2011-03-25 03:44:09 +00:00
clear ( ) ;
for ( int i = 0 ; i < MAX_COPROC_INSTANCES ; i + + ) {
device_nums [ i ] = i ;
}
2011-08-10 17:11:08 +00:00
while ( ! xp . get_tag ( ) ) {
if ( ! xp . is_tag ) continue ;
if ( xp . match_tag ( " /coproc " ) ) {
2011-03-25 03:44:09 +00:00
if ( ! strlen ( type ) ) return ERR_XML_PARSE ;
2015-10-20 14:20:24 +00:00
clear_usage ( ) ;
2011-03-25 03:44:09 +00:00
return 0 ;
}
2016-10-25 18:08:16 +00:00
if ( xp . match_tag ( " coproc_opencl " ) ) {
opencl_prop . parse ( xp , " /coproc_opencl " ) ;
continue ;
}
2011-08-10 17:11:08 +00:00
if ( xp . parse_str ( " type " , type , sizeof ( type ) ) ) continue ;
if ( xp . parse_int ( " count " , count ) ) continue ;
2014-09-22 04:08:09 +00:00
if ( xp . parse_double ( " req_secs " , req_secs ) ) continue ;
if ( xp . parse_double ( " req_instances " , req_instances ) ) continue ;
2011-08-10 17:11:08 +00:00
if ( xp . parse_double ( " peak_flops " , peak_flops ) ) continue ;
if ( xp . parse_str ( " device_nums " , buf , sizeof ( buf ) ) ) {
2011-03-25 03:44:09 +00:00
int i = 0 ;
char * p = strtok ( buf , " " ) ;
while ( p & & i < MAX_COPROC_INSTANCES ) {
device_nums [ i + + ] = atoi ( p ) ;
p = strtok ( NULL , " " ) ;
}
continue ;
}
2014-12-09 04:38:56 +00:00
if ( xp . parse_bool ( " non_gpu " , non_gpu ) ) continue ;
2011-03-25 03:44:09 +00:00
}
return ERR_XML_PARSE ;
}
2016-10-28 05:57:19 +00:00
// return a string, to be stored in host.serialnum,
// describing the host's coprocessors
//
2010-05-18 19:22:34 +00:00
void COPROCS : : summary_string ( char * buf , int len ) {
2011-10-04 03:33:04 +00:00
char buf2 [ 1024 ] ;
2010-05-18 19:22:34 +00:00
2016-02-15 22:54:13 +00:00
strlcpy ( buf , " " , len ) ;
2011-03-25 03:44:09 +00:00
if ( nvidia . count ) {
2012-04-10 00:32:35 +00:00
int mem = ( int ) ( nvidia . prop . totalGlobalMem / MEGA ) ;
2013-06-26 09:24:36 +00:00
snprintf ( buf2 , sizeof ( buf2 ) ,
" [CUDA|%s|%d|%dMB|%d|%d] " ,
nvidia . prop . name , nvidia . count ,
mem , nvidia . display_driver_version ,
2013-02-20 06:24:51 +00:00
nvidia . opencl_prop . opencl_device_version_int
2010-05-18 19:22:34 +00:00
) ;
2011-10-04 03:33:04 +00:00
strlcat ( buf , buf2 , len ) ;
2010-05-18 19:22:34 +00:00
}
if ( ati . count ) {
2013-06-26 09:24:36 +00:00
snprintf ( buf2 , sizeof ( buf2 ) ,
2020-05-06 20:03:30 +00:00
" [CAL|%s|%d|%uMB|%s|%d] " ,
2013-06-26 09:24:36 +00:00
ati . name , ati . count ,
ati . attribs . localRAM , ati . version ,
2013-02-20 06:24:51 +00:00
ati . opencl_prop . opencl_device_version_int
2010-05-18 19:22:34 +00:00
) ;
2011-10-04 03:33:04 +00:00
strlcat ( buf , buf2 , len ) ;
2010-05-18 19:22:34 +00:00
}
2013-03-04 14:32:16 +00:00
if ( intel_gpu . count ) {
2013-06-26 09:24:36 +00:00
snprintf ( buf2 , sizeof ( buf2 ) ,
" [INTEL|%s|%d|%dMB|%s|%d] " ,
2012-12-12 18:54:01 +00:00
intel_gpu . name , intel_gpu . count ,
( int ) ( intel_gpu . opencl_prop . global_mem_size / MEGA ) ,
2013-02-20 06:24:51 +00:00
intel_gpu . version ,
intel_gpu . opencl_prop . opencl_device_version_int
2012-12-08 08:27:09 +00:00
) ;
strlcat ( buf , buf2 , len ) ;
}
2016-10-28 05:57:19 +00:00
// add OpenCL devices other than nvidia/amd/intel
//
2016-10-25 18:08:16 +00:00
for ( int i = 1 ; i < n_rsc ; i + + ) {
COPROC & cp = coprocs [ i ] ;
int type = coproc_type_name_to_num ( cp . type ) ;
if ( type = = PROC_TYPE_NVIDIA_GPU ) continue ;
if ( type = = PROC_TYPE_AMD_GPU ) continue ;
if ( type = = PROC_TYPE_INTEL_GPU ) continue ;
if ( ! strlen ( cp . opencl_prop . name ) ) continue ;
snprintf ( buf2 , sizeof ( buf2 ) ,
" [opencl_gpu|%s|%d|%dMB|%d] " ,
cp . type ,
cp . count ,
( int ) ( cp . opencl_prop . global_mem_size / MEGA ) ,
cp . opencl_prop . opencl_device_version_int
) ;
strlcat ( buf , buf2 , len ) ;
}
2010-05-18 19:22:34 +00:00
}
2011-08-09 21:44:14 +00:00
int COPROCS : : parse ( XML_PARSER & xp ) {
2010-05-18 19:22:34 +00:00
int retval ;
2011-06-22 11:25:06 +00:00
clear ( ) ;
2011-04-11 03:19:27 +00:00
n_rsc = 1 ;
2016-02-15 22:54:13 +00:00
safe_strcpy ( coprocs [ 0 ] . type , " CPU " ) ;
2012-01-19 09:38:35 +00:00
while ( ! xp . get_tag ( ) ) {
if ( xp . match_tag ( " /coprocs " ) ) {
2010-05-18 19:22:34 +00:00
return 0 ;
}
2012-01-19 09:38:35 +00:00
if ( xp . match_tag ( " coproc_cuda " ) ) {
2011-08-09 21:44:14 +00:00
retval = nvidia . parse ( xp ) ;
2010-05-18 19:22:34 +00:00
if ( retval ) {
2011-03-25 03:44:09 +00:00
nvidia . clear ( ) ;
2011-04-11 03:19:27 +00:00
} else {
coprocs [ n_rsc + + ] = nvidia ;
2010-05-18 19:22:34 +00:00
}
2011-04-11 03:19:27 +00:00
continue ;
2010-05-18 19:22:34 +00:00
}
2012-01-19 09:38:35 +00:00
if ( xp . match_tag ( " coproc_ati " ) ) {
2011-08-09 21:44:14 +00:00
retval = ati . parse ( xp ) ;
2010-05-18 19:22:34 +00:00
if ( retval ) {
ati . clear ( ) ;
2011-04-11 03:19:27 +00:00
} else {
coprocs [ n_rsc + + ] = ati ;
2010-05-18 19:22:34 +00:00
}
2011-04-11 03:19:27 +00:00
continue ;
2010-05-18 19:22:34 +00:00
}
2012-12-11 00:04:35 +00:00
if ( xp . match_tag ( " coproc_intel_gpu " ) ) {
2012-12-08 18:16:28 +00:00
retval = intel_gpu . parse ( xp ) ;
if ( retval ) {
intel_gpu . clear ( ) ;
} else {
coprocs [ n_rsc + + ] = intel_gpu ;
}
continue ;
}
2014-07-25 19:40:35 +00:00
if ( xp . match_tag ( " coproc " ) ) {
COPROC cp ;
retval = cp . parse ( xp ) ;
if ( ! retval ) {
coprocs [ n_rsc + + ] = cp ;
} else {
fprintf ( stderr , " failed to parse <coproc>: %d \n " , retval ) ;
}
}
2010-05-18 19:22:34 +00:00
}
return ERR_XML_PARSE ;
}
2016-09-12 02:57:08 +00:00
# ifdef _USING_FCGI_
void COPROCS : : write_xml ( MIOFILE & , bool ) {
}
# else
2012-06-18 20:41:37 +00:00
void COPROCS : : write_xml ( MIOFILE & mf , bool scheduler_rpc ) {
2010-05-18 19:22:34 +00:00
mf . printf ( " <coprocs> \n " ) ;
2014-07-16 11:33:26 +00:00
for ( int i = 1 ; i < n_rsc ; i + + ) {
2014-08-10 04:44:39 +00:00
switch ( coproc_type_name_to_num ( coprocs [ i ] . type ) ) {
case PROC_TYPE_NVIDIA_GPU :
nvidia . write_xml ( mf , scheduler_rpc ) ;
break ;
case PROC_TYPE_AMD_GPU :
ati . write_xml ( mf , scheduler_rpc ) ;
break ;
case PROC_TYPE_INTEL_GPU :
intel_gpu . write_xml ( mf , scheduler_rpc ) ;
break ;
default :
coprocs [ i ] . write_xml ( mf , scheduler_rpc ) ;
}
2014-07-16 11:33:26 +00:00
}
2010-05-18 19:22:34 +00:00
mf . printf ( " </coprocs> \n " ) ;
}
2016-09-12 06:30:01 +00:00
# endif
2010-05-18 19:22:34 +00:00
2013-06-26 09:24:36 +00:00
void COPROC_NVIDIA : : description ( char * buf , int buflen ) {
2011-10-11 18:57:49 +00:00
char vers [ 256 ] , cuda_vers [ 256 ] ;
2010-05-18 19:22:34 +00:00
if ( display_driver_version ) {
2011-10-12 00:21:04 +00:00
# ifdef __APPLE__
int maj = display_driver_version > > 16 ;
int min = ( display_driver_version > > 8 ) & 0xff ;
int rev = display_driver_version & 0xff ;
2016-02-17 23:50:28 +00:00
snprintf ( vers , sizeof ( vers ) , " %d.%d.%d " , maj , min , rev ) ;
2011-10-12 00:21:04 +00:00
# else
2011-10-11 18:57:49 +00:00
int maj = display_driver_version / 100 ;
int min = display_driver_version % 100 ;
2016-02-17 23:50:28 +00:00
snprintf ( vers , sizeof ( vers ) , " %d.%02d " , maj , min ) ;
2011-10-12 00:21:04 +00:00
# endif
2010-05-18 19:22:34 +00:00
} else {
2016-02-15 22:54:13 +00:00
safe_strcpy ( vers , " unknown " ) ;
2010-05-18 19:22:34 +00:00
}
2011-10-11 18:57:49 +00:00
if ( cuda_version ) {
2011-10-14 20:44:00 +00:00
int maj = cuda_version / 1000 ;
2013-07-03 04:57:15 +00:00
int min = ( cuda_version % 1000 ) / 10 ;
2016-02-17 23:50:28 +00:00
snprintf ( cuda_vers , sizeof ( cuda_vers ) , " %d.%d " , maj , min ) ;
2011-10-11 18:57:49 +00:00
} else {
2016-02-15 22:54:13 +00:00
safe_strcpy ( cuda_vers , " unknown " ) ;
2011-10-11 18:57:49 +00:00
}
2013-06-26 09:24:36 +00:00
snprintf ( buf , buflen ,
" %s (driver version %s, CUDA version %s, compute capability %d.%d, %.0fMB, %.0fMB available, %.0f GFLOPS peak) " ,
2011-10-11 18:57:49 +00:00
prop . name , vers , cuda_vers , prop . major , prop . minor ,
2011-09-14 22:45:26 +00:00
prop . totalGlobalMem / MEGA , available_ram / MEGA , peak_flops / 1e9
2010-05-18 19:22:34 +00:00
) ;
}
# ifndef _USING_FCGI_
2012-06-18 20:41:37 +00:00
void COPROC_NVIDIA : : write_xml ( MIOFILE & f , bool scheduler_rpc ) {
2010-05-18 19:22:34 +00:00
f . printf (
" <coproc_cuda> \n "
" <count>%d</count> \n "
2011-08-23 11:29:11 +00:00
" <name>%s</name> \n "
2011-09-14 23:30:51 +00:00
" <available_ram>%f</available_ram> \n "
2011-08-23 11:29:11 +00:00
" <have_cuda>%d</have_cuda> \n "
2011-08-23 12:45:07 +00:00
" <have_opencl>%d</have_opencl> \n " ,
count ,
prop . name ,
2011-09-14 23:30:51 +00:00
available_ram ,
2011-08-23 12:45:07 +00:00
have_cuda ? 1 : 0 ,
have_opencl ? 1 : 0
) ;
2012-06-18 20:41:37 +00:00
if ( scheduler_rpc ) {
2011-08-23 12:45:07 +00:00
write_request ( f ) ;
}
f . printf (
2011-07-07 22:21:56 +00:00
" <peak_flops>%f</peak_flops> \n "
2010-05-18 19:22:34 +00:00
" <cudaVersion>%d</cudaVersion> \n "
2011-06-22 11:25:06 +00:00
" <drvVersion>%d</drvVersion> \n "
2012-04-10 00:32:35 +00:00
" <totalGlobalMem>%f</totalGlobalMem> \n "
2012-07-05 20:24:17 +00:00
" <sharedMemPerBlock>%f</sharedMemPerBlock> \n "
2010-05-18 19:22:34 +00:00
" <regsPerBlock>%d</regsPerBlock> \n "
" <warpSize>%d</warpSize> \n "
2012-07-05 20:24:17 +00:00
" <memPitch>%f</memPitch> \n "
2010-05-18 19:22:34 +00:00
" <maxThreadsPerBlock>%d</maxThreadsPerBlock> \n "
" <maxThreadsDim>%d %d %d</maxThreadsDim> \n "
" <maxGridSize>%d %d %d</maxGridSize> \n "
2011-06-22 11:25:06 +00:00
" <clockRate>%d</clockRate> \n "
2012-07-05 20:24:17 +00:00
" <totalConstMem>%f</totalConstMem> \n "
2010-05-18 19:22:34 +00:00
" <major>%d</major> \n "
" <minor>%d</minor> \n "
2012-07-05 20:24:17 +00:00
" <textureAlignment>%f</textureAlignment> \n "
2010-05-18 19:22:34 +00:00
" <deviceOverlap>%d</deviceOverlap> \n "
2012-06-18 20:41:37 +00:00
" <multiProcessorCount>%d</multiProcessorCount> \n " ,
2011-06-22 11:25:06 +00:00
peak_flops ,
2010-05-18 19:22:34 +00:00
cuda_version ,
2011-06-22 11:25:06 +00:00
display_driver_version ,
2012-04-10 00:32:35 +00:00
prop . totalGlobalMem ,
2012-07-05 20:24:17 +00:00
prop . sharedMemPerBlock ,
2010-05-18 19:22:34 +00:00
prop . regsPerBlock ,
prop . warpSize ,
2012-07-05 20:24:17 +00:00
prop . memPitch ,
2010-05-18 19:22:34 +00:00
prop . maxThreadsPerBlock ,
prop . maxThreadsDim [ 0 ] , prop . maxThreadsDim [ 1 ] , prop . maxThreadsDim [ 2 ] ,
prop . maxGridSize [ 0 ] , prop . maxGridSize [ 1 ] , prop . maxGridSize [ 2 ] ,
2011-06-22 11:25:06 +00:00
prop . clockRate ,
2012-07-05 20:24:17 +00:00
prop . totalConstMem ,
2010-05-18 19:22:34 +00:00
prop . major ,
prop . minor ,
2012-07-05 20:24:17 +00:00
prop . textureAlignment ,
2010-05-18 19:22:34 +00:00
prop . deviceOverlap ,
2012-06-18 20:41:37 +00:00
prop . multiProcessorCount
2010-05-18 19:22:34 +00:00
) ;
2011-08-23 11:29:11 +00:00
if ( have_opencl ) {
2013-04-17 05:42:29 +00:00
opencl_prop . write_xml ( f , " coproc_opencl " ) ;
2011-08-23 11:29:11 +00:00
}
2012-06-18 20:41:37 +00:00
if ( ! scheduler_rpc ) {
for ( int i = 0 ; i < count ; i + + ) {
pci_infos [ i ] . write ( f ) ;
}
}
2011-08-23 11:29:11 +00:00
f . printf ( " </coproc_cuda> \n " ) ;
2010-05-18 19:22:34 +00:00
}
# endif
2011-03-25 03:44:09 +00:00
void COPROC_NVIDIA : : clear ( ) {
2020-02-10 20:23:11 +00:00
static const COPROC_NVIDIA x ( 0 ) ;
2019-11-05 08:16:02 +00:00
* this = x ;
2013-06-04 03:24:48 +00:00
safe_strcpy ( type , proc_type_name_xml ( PROC_TYPE_NVIDIA_GPU ) ) ;
2010-05-18 19:22:34 +00:00
estimated_delay = - 1 ; // mark as absent
cuda_version = 0 ;
display_driver_version = 0 ;
2016-02-15 22:54:13 +00:00
safe_strcpy ( prop . name , " " ) ;
2016-02-14 05:29:56 +00:00
prop . totalGlobalMem = 0.0 ;
2010-05-18 19:22:34 +00:00
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 ;
prop . clockRate = 0 ;
prop . totalConstMem = 0 ;
prop . major = 0 ;
prop . minor = 0 ;
prop . textureAlignment = 0 ;
prop . deviceOverlap = 0 ;
prop . multiProcessorCount = 0 ;
2015-11-25 21:39:24 +00:00
is_used = COPROC_USED ;
2010-05-18 19:22:34 +00:00
}
2011-08-09 21:44:14 +00:00
int COPROC_NVIDIA : : parse ( XML_PARSER & xp ) {
2011-09-15 04:24:40 +00:00
char buf2 [ 256 ] ;
2011-08-23 11:29:11 +00:00
int retval ;
2012-06-18 20:41:37 +00:00
int ipci = 0 ;
2010-05-18 19:22:34 +00:00
clear ( ) ;
2011-09-15 04:24:40 +00:00
while ( ! xp . get_tag ( ) ) {
if ( xp . match_tag ( " /coproc_cuda " ) ) {
2011-01-12 01:17:07 +00:00
if ( ! peak_flops ) {
2016-02-14 05:29:56 +00:00
set_peak_flops ( ) ;
2011-01-12 01:17:07 +00:00
}
2011-10-06 02:56:30 +00:00
if ( ! available_ram ) {
2012-04-10 00:32:35 +00:00
available_ram = prop . totalGlobalMem ;
2011-10-06 02:56:30 +00:00
}
2010-05-18 19:22:34 +00:00
return 0 ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " count " , count ) ) continue ;
if ( xp . parse_double ( " peak_flops " , peak_flops ) ) continue ;
if ( xp . parse_bool ( " have_cuda " , have_cuda ) ) continue ;
if ( xp . parse_bool ( " have_opencl " , have_opencl ) ) continue ;
if ( xp . parse_double ( " available_ram " , available_ram ) ) continue ;
if ( xp . parse_double ( " req_secs " , req_secs ) ) continue ;
if ( xp . parse_double ( " req_instances " , req_instances ) ) continue ;
if ( xp . parse_double ( " estimated_delay " , estimated_delay ) ) continue ;
if ( xp . parse_int ( " cudaVersion " , cuda_version ) ) continue ;
if ( xp . parse_int ( " drvVersion " , display_driver_version ) ) continue ;
if ( xp . parse_str ( " name " , prop . name , sizeof ( prop . name ) ) ) continue ;
2012-04-10 00:32:35 +00:00
if ( xp . parse_double ( " totalGlobalMem " , prop . totalGlobalMem ) ) continue ;
2012-07-05 20:24:17 +00:00
if ( xp . parse_double ( " sharedMemPerBlock " , prop . sharedMemPerBlock ) ) continue ;
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " regsPerBlock " , prop . regsPerBlock ) ) continue ;
if ( xp . parse_int ( " warpSize " , prop . warpSize ) ) continue ;
2012-07-05 20:24:17 +00:00
if ( xp . parse_double ( " memPitch " , prop . memPitch ) ) continue ;
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " maxThreadsPerBlock " , prop . maxThreadsPerBlock ) ) continue ;
if ( xp . parse_str ( " maxThreadsDim " , buf2 , sizeof ( buf2 ) ) ) {
2010-05-18 19:22:34 +00:00
// can't use sscanf here (FCGI)
//
prop . maxThreadsDim [ 0 ] = atoi ( buf2 ) ;
char * p = strchr ( buf2 , ' ' ) ;
if ( p ) {
p + + ;
prop . maxThreadsDim [ 1 ] = atoi ( p ) ;
p = strchr ( p , ' ' ) ;
if ( p ) {
p + + ;
prop . maxThreadsDim [ 2 ] = atoi ( p ) ;
}
}
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_str ( " maxGridSize " , buf2 , sizeof ( buf2 ) ) ) {
2010-05-18 19:22:34 +00:00
prop . maxGridSize [ 0 ] = atoi ( buf2 ) ;
char * p = strchr ( buf2 , ' ' ) ;
if ( p ) {
p + + ;
prop . maxGridSize [ 1 ] = atoi ( p ) ;
p = strchr ( p , ' ' ) ;
if ( p ) {
p + + ;
prop . maxGridSize [ 2 ] = atoi ( p ) ;
}
}
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " clockRate " , prop . clockRate ) ) continue ;
2012-07-05 20:24:17 +00:00
if ( xp . parse_double ( " totalConstMem " , prop . totalConstMem ) ) continue ;
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " major " , prop . major ) ) continue ;
if ( xp . parse_int ( " minor " , prop . minor ) ) continue ;
2012-07-05 20:24:17 +00:00
if ( xp . parse_double ( " textureAlignment " , prop . textureAlignment ) ) continue ;
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " deviceOverlap " , prop . deviceOverlap ) ) continue ;
if ( xp . parse_int ( " multiProcessorCount " , prop . multiProcessorCount ) ) continue ;
2012-06-18 20:41:37 +00:00
if ( xp . match_tag ( " pci_info " ) ) {
PCI_INFO p ;
p . parse ( xp ) ;
if ( ipci < MAX_COPROC_INSTANCES ) {
pci_infos [ ipci + + ] = p ;
}
}
2011-09-15 04:24:40 +00:00
if ( xp . match_tag ( " coproc_opencl " ) ) {
2013-04-17 05:42:29 +00:00
retval = opencl_prop . parse ( xp , " /coproc_opencl " ) ;
2011-08-23 11:29:11 +00:00
if ( retval ) return retval ;
continue ;
}
2010-05-18 19:22:34 +00:00
}
return ERR_XML_PARSE ;
}
2011-10-08 01:20:44 +00:00
2011-10-07 19:47:35 +00:00
void COPROC_NVIDIA : : set_peak_flops ( ) {
double x = 0 ;
2016-01-08 00:51:29 +00:00
int flops_per_clock = 0 , cores_per_proc = 0 ;
if ( prop . major | | opencl_prop . nv_compute_capability_major ) {
int major = prop . major ;
int minor = prop . minor ;
if ( opencl_prop . nv_compute_capability_major ) major = opencl_prop . nv_compute_capability_major ;
if ( opencl_prop . nv_compute_capability_minor ) minor = opencl_prop . nv_compute_capability_minor ;
switch ( major ) {
2011-10-07 19:47:35 +00:00
case 1 :
flops_per_clock = 3 ;
cores_per_proc = 8 ;
break ;
case 2 :
flops_per_clock = 2 ;
2016-01-08 00:51:29 +00:00
switch ( minor ) {
2011-10-07 19:47:35 +00:00
case 0 :
cores_per_proc = 32 ;
break ;
default :
cores_per_proc = 48 ;
break ;
}
2012-03-28 17:29:48 +00:00
break ;
2012-03-24 06:31:03 +00:00
case 3 :
flops_per_clock = 2 ;
2012-03-27 03:50:16 +00:00
cores_per_proc = 192 ;
2012-03-28 17:29:48 +00:00
break ;
2014-02-24 23:57:05 +00:00
case 5 :
flops_per_clock = 2 ;
cores_per_proc = 128 ;
break ;
2018-09-21 11:32:16 +00:00
case 6 :
flops_per_clock = 2 ;
switch ( minor ) {
case 0 : // special for Tesla P100 (GP100)
cores_per_proc = 64 ;
break ;
default :
cores_per_proc = 128 ;
break ;
}
break ;
case 7 : // for both cc7.0 (Titan V, Tesla V100) and cc7.5 (RTX, Tesla T4)
default :
flops_per_clock = 2 ;
cores_per_proc = 64 ;
break ;
2011-10-07 19:47:35 +00:00
}
2016-01-08 00:51:29 +00:00
}
if ( prop . clockRate ) {
2011-10-07 19:47:35 +00:00
// clock rate is scaled down by 1000
//
x = ( 1000. * prop . clockRate ) * prop . multiProcessorCount * cores_per_proc * flops_per_clock ;
2016-01-08 00:51:29 +00:00
} else if ( opencl_prop . nv_compute_capability_major ) {
// OpenCL w/ cl_nv_device_attribute_query extension
// Per: https://www.khronos.org/registry/cl/extensions/nv/cl_nv_device_attribute_query.txt
//
2016-09-01 14:36:56 +00:00
// The theoretical single-precision processing power of a Maxwell GPU in GFLOPS is computed as 2 (operations per FMA instruction per CUDA core per cycle) × number of CUDA cores × core clock speed (in GHz).
2016-01-08 00:51:29 +00:00
// Per: https://en.wikipedia.org/wiki/Maxwell_(microarchitecture)#Performance
// Per: https://en.wikipedia.org/wiki/List_of_Nvidia_graphics_processing_units
//
// clock is in MHz
//
x = opencl_prop . max_compute_units * cores_per_proc * flops_per_clock * ( opencl_prop . max_clock_frequency * 1e6 ) ;
2011-10-21 18:08:45 +00:00
} else if ( opencl_prop . max_compute_units ) {
2011-10-07 19:47:35 +00:00
// OpenCL doesn't give us compute capability.
2015-10-09 06:28:24 +00:00
// assume CC 2: cores_per_proc is 48 and flops_per_clock is 2
2011-10-07 19:47:35 +00:00
//
2015-10-09 06:28:24 +00:00
x = opencl_prop . max_compute_units * 48 * 2 * opencl_prop . max_clock_frequency * 1e6 ;
2011-10-07 19:47:35 +00:00
}
2019-02-07 21:52:35 +00:00
peak_flops = x ;
2011-10-07 19:47:35 +00:00
}
2010-05-18 19:22:34 +00:00
2012-06-06 03:47:13 +00:00
// fake a NVIDIA GPU (for debugging)
//
void COPROC_NVIDIA : : fake (
int driver_version , double ram , double avail_ram , int n
) {
2019-11-05 08:16:02 +00:00
static const COPROC_NVIDIA x ;
* this = x ;
safe_strcpy ( type , proc_type_name_xml ( PROC_TYPE_NVIDIA_GPU ) ) ;
count = n ;
for ( int i = 0 ; i < count ; i + + ) {
device_nums [ i ] = i ;
}
available_ram = avail_ram ;
display_driver_version = driver_version ;
cuda_version = 5000 ;
have_cuda = true ;
safe_strcpy ( prop . name , " Fake NVIDIA GPU " ) ;
prop . totalGlobalMem = ram ;
prop . sharedMemPerBlock = 100 ;
prop . regsPerBlock = 8 ;
prop . warpSize = 10 ;
prop . memPitch = 10 ;
prop . maxThreadsPerBlock = 20 ;
prop . maxThreadsDim [ 0 ] = 2 ;
prop . maxThreadsDim [ 1 ] = 2 ;
prop . maxThreadsDim [ 2 ] = 2 ;
prop . maxGridSize [ 0 ] = 10 ;
prop . maxGridSize [ 1 ] = 10 ;
prop . maxGridSize [ 2 ] = 10 ;
prop . totalConstMem = 10 ;
prop . major = 1 ;
prop . minor = 2 ;
prop . clockRate = 1250000 ;
prop . textureAlignment = 1000 ;
prop . multiProcessorCount = 14 ;
have_opencl = true ;
safe_strcpy ( opencl_prop . opencl_device_version , " OpenCL 3.17 " ) ;
opencl_prop . opencl_device_version_int = 317 ;
set_peak_flops ( ) ;
2012-06-06 03:47:13 +00:00
}
2010-05-18 19:22:34 +00:00
////////////////// ATI STARTS HERE /////////////////
# ifndef _USING_FCGI_
2012-06-18 20:41:37 +00:00
void COPROC_ATI : : write_xml ( MIOFILE & f , bool scheduler_rpc ) {
2010-05-18 19:22:34 +00:00
f . printf (
" <coproc_ati> \n "
2010-09-23 20:54:49 +00:00
" <count>%d</count> \n "
2011-08-23 11:29:11 +00:00
" <name>%s</name> \n "
2011-09-14 23:30:51 +00:00
" <available_ram>%f</available_ram> \n "
2011-08-23 11:29:11 +00:00
" <have_cal>%d</have_cal> \n "
" <have_opencl>%d</have_opencl> \n " ,
2010-09-23 20:54:49 +00:00
count ,
2011-08-23 11:29:11 +00:00
name ,
2011-09-14 23:30:51 +00:00
available_ram ,
2011-08-23 11:29:11 +00:00
have_cal ? 1 : 0 ,
have_opencl ? 1 : 0
2010-05-18 19:22:34 +00:00
) ;
2012-06-18 20:41:37 +00:00
if ( scheduler_rpc ) {
2010-09-23 20:54:49 +00:00
write_request ( f ) ;
}
2010-05-18 19:22:34 +00:00
f . printf (
2011-07-07 22:21:56 +00:00
" <peak_flops>%f</peak_flops> \n "
2011-06-22 11:25:06 +00:00
" <CALVersion>%s</CALVersion> \n "
2010-05-18 19:22:34 +00:00
" <target>%d</target> \n "
" <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 "
" <maxResource1DWidth>%d</maxResource1DWidth> \n "
" <maxResource2DWidth>%d</maxResource2DWidth> \n "
2011-06-22 11:25:06 +00:00
" <maxResource2DHeight>%d</maxResource2DHeight> \n " ,
peak_flops ,
version ,
2010-05-18 19:22:34 +00:00
attribs . target ,
attribs . localRAM ,
attribs . uncachedRemoteRAM ,
attribs . cachedRemoteRAM ,
attribs . engineClock ,
attribs . memoryClock ,
attribs . wavefrontSize ,
attribs . numberOfSIMD ,
attribs . doublePrecision ,
attribs . pitch_alignment ,
attribs . surface_alignment ,
info . maxResource1DWidth ,
info . maxResource2DWidth ,
2011-06-22 11:25:06 +00:00
info . maxResource2DHeight
2010-05-18 19:22:34 +00:00
) ;
if ( atirt_detected ) {
f . printf ( " <atirt_detected/> \n " ) ;
}
if ( amdrt_detected ) {
f . printf ( " <amdrt_detected/> \n " ) ;
}
2011-08-23 11:29:11 +00:00
if ( have_opencl ) {
2013-04-17 05:42:29 +00:00
opencl_prop . write_xml ( f , " coproc_opencl " ) ;
2011-08-23 11:29:11 +00:00
}
2010-05-18 19:22:34 +00:00
f . printf ( " </coproc_ati> \n " ) ;
2016-09-01 14:40:31 +00:00
}
2010-05-18 19:22:34 +00:00
# endif
void COPROC_ATI : : clear ( ) {
2020-02-10 20:23:11 +00:00
static const COPROC_ATI x ( 0 ) ;
2019-11-05 08:16:02 +00:00
* this = x ;
2013-06-04 03:24:48 +00:00
safe_strcpy ( type , proc_type_name_xml ( PROC_TYPE_AMD_GPU ) ) ;
2010-05-18 19:22:34 +00:00
estimated_delay = - 1 ;
2016-02-15 22:54:13 +00:00
safe_strcpy ( name , " " ) ;
safe_strcpy ( version , " " ) ;
2010-05-18 19:22:34 +00:00
atirt_detected = false ;
amdrt_detected = false ;
2012-01-23 21:59:12 +00:00
version_num = 0 ;
2015-11-25 21:39:24 +00:00
is_used = COPROC_USED ;
2010-05-18 19:22:34 +00:00
}
2011-08-09 21:44:14 +00:00
int COPROC_ATI : : parse ( XML_PARSER & xp ) {
2011-09-15 04:24:40 +00:00
int n , retval ;
2010-05-18 19:22:34 +00:00
clear ( ) ;
2011-09-15 04:24:40 +00:00
while ( ! xp . get_tag ( ) ) {
if ( xp . match_tag ( " /coproc_ati " ) ) {
2012-01-23 21:59:12 +00:00
if ( strlen ( version ) ) {
int major , minor , release ;
n = sscanf ( version , " %d.%d.%d " , & major , & minor , & release ) ;
if ( n = = 3 ) {
version_num = ati_version_int ( major , minor , release ) ;
}
}
2011-01-12 01:17:07 +00:00
if ( ! peak_flops ) {
2011-01-27 20:00:42 +00:00
set_peak_flops ( ) ;
2011-01-12 01:17:07 +00:00
}
2011-10-06 02:56:30 +00:00
if ( ! available_ram ) {
available_ram = attribs . localRAM * MEGA ;
}
2010-06-16 22:07:19 +00:00
return 0 ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " count " , count ) ) continue ;
if ( xp . parse_double ( " peak_flops " , peak_flops ) ) continue ;
if ( xp . parse_bool ( " have_cal " , have_cal ) ) continue ;
if ( xp . parse_bool ( " have_opencl " , have_opencl ) ) continue ;
if ( xp . parse_double ( " available_ram " , available_ram ) ) continue ;
if ( xp . parse_double ( " req_secs " , req_secs ) ) continue ;
if ( xp . parse_double ( " req_instances " , req_instances ) ) continue ;
if ( xp . parse_double ( " estimated_delay " , estimated_delay ) ) continue ;
if ( xp . parse_str ( " name " , name , sizeof ( name ) ) ) continue ;
if ( xp . parse_str ( " CALVersion " , version , sizeof ( version ) ) ) continue ;
if ( xp . parse_bool ( " amdrt_detected " , amdrt_detected ) ) continue ;
if ( xp . parse_bool ( " atirt_detected " , atirt_detected ) ) continue ;
if ( xp . parse_int ( " target " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . target = ( CALtarget ) n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " localRAM " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . localRAM = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " uncachedRemoteRAM " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . uncachedRemoteRAM = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " cachedRemoteRAM " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . cachedRemoteRAM = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " engineClock " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . engineClock = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " memoryClock " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . memoryClock = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " wavefrontSize " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . wavefrontSize = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " numberOfSIMD " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . numberOfSIMD = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " doublePrecision " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . doublePrecision = n ? CAL_TRUE : CAL_FALSE ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " pitch_alignment " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . pitch_alignment = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " surface_alignment " , n ) ) {
2010-05-18 19:22:34 +00:00
attribs . surface_alignment = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " maxResource1DWidth " , n ) ) {
2010-05-18 19:22:34 +00:00
info . maxResource1DWidth = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " maxResource2DWidth " , n ) ) {
2010-05-18 19:22:34 +00:00
info . maxResource2DWidth = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . parse_int ( " maxResource2DHeight " , n ) ) {
2010-05-18 19:22:34 +00:00
info . maxResource2DHeight = n ;
continue ;
}
2011-09-15 04:24:40 +00:00
if ( xp . match_tag ( " coproc_opencl " ) ) {
2013-04-17 05:42:29 +00:00
retval = opencl_prop . parse ( xp , " /coproc_opencl " ) ;
2011-08-23 11:29:11 +00:00
if ( retval ) return retval ;
continue ;
}
2010-05-18 19:22:34 +00:00
}
return ERR_XML_PARSE ;
}
2013-06-26 09:24:36 +00:00
void COPROC_ATI : : description ( char * buf , int buflen ) {
snprintf ( buf , buflen ,
2020-05-06 20:03:30 +00:00
" %s (CAL version %s, %uMB, %.0fMB available, %.0f GFLOPS peak) " ,
2013-06-26 09:24:36 +00:00
name , version , attribs . localRAM ,
available_ram / MEGA , peak_flops / 1.e9
2010-05-18 19:22:34 +00:00
) ;
}
2011-10-07 19:47:35 +00:00
void COPROC_ATI : : set_peak_flops ( ) {
double x = 0 ;
2011-10-21 17:44:18 +00:00
if ( attribs . numberOfSIMD ) {
2011-10-07 21:59:07 +00:00
x = attribs . numberOfSIMD * attribs . wavefrontSize * 5 * attribs . engineClock * 1.e6 ;
2011-10-07 19:47:35 +00:00
// clock is in MHz
2016-01-07 06:01:51 +00:00
} else if ( opencl_prop . amd_simd_per_compute_unit ) {
2016-01-07 16:44:35 +00:00
2016-01-07 06:01:51 +00:00
// OpenCL w/ cl_amd_device_attribute_query extension
2016-01-08 00:51:29 +00:00
// Per: https://www.khronos.org/registry/cl/extensions/amd/cl_amd_device_attribute_query.txt
2016-01-07 06:01:51 +00:00
//
// Single precision performance is calculated as two times the number of shaders multiplied by the base core clock speed.
2016-01-08 00:51:29 +00:00
// Per: https://en.wikipedia.org/wiki/List_of_AMD_graphics_processing_units
2016-01-07 06:01:51 +00:00
//
// clock is in MHz
2016-01-07 16:44:35 +00:00
x = opencl_prop . max_compute_units *
opencl_prop . amd_simd_per_compute_unit *
opencl_prop . amd_simd_width *
opencl_prop . amd_simd_instruction_width *
2 *
( opencl_prop . max_clock_frequency * 1.e6 ) ;
2011-10-21 17:44:18 +00:00
} else if ( opencl_prop . max_compute_units ) {
2011-10-07 19:47:35 +00:00
// OpenCL gives us only:
// - max_compute_units
// (which I'll assume is the same as attribs.numberOfSIMD)
// - max_clock_frequency (which I'll assume is the same as engineClock)
// It doesn't give wavefrontSize, which can be 16/32/64.
// So let's be conservative and use 16
//
2011-10-08 06:33:39 +00:00
x = opencl_prop . max_compute_units * 16 * 5 * opencl_prop . max_clock_frequency * 1e6 ;
2011-10-07 19:47:35 +00:00
}
2019-02-07 21:52:35 +00:00
peak_flops = x ;
2011-10-07 19:47:35 +00:00
}
2012-06-06 03:47:13 +00:00
void COPROC_ATI : : fake ( double ram , double avail_ram , int n ) {
2019-11-05 08:16:02 +00:00
clear ( ) ;
2013-06-04 03:24:48 +00:00
safe_strcpy ( type , proc_type_name_xml ( PROC_TYPE_AMD_GPU ) ) ;
safe_strcpy ( version , " 1.4.3 " ) ;
safe_strcpy ( name , " foobar " ) ;
2012-06-06 03:47:13 +00:00
count = n ;
available_ram = avail_ram ;
2012-07-22 03:45:47 +00:00
have_cal = true ;
2012-06-06 03:47:13 +00:00
attribs . localRAM = ( int ) ( ram / MEGA ) ;
attribs . numberOfSIMD = 32 ;
attribs . wavefrontSize = 32 ;
attribs . engineClock = 50 ;
for ( int i = 0 ; i < count ; i + + ) {
device_nums [ i ] = i ;
}
set_peak_flops ( ) ;
}
2012-06-25 23:09:45 +00:00
2012-12-05 13:11:20 +00:00
////////////////// INTEL GPU STARTS HERE /////////////////
# ifndef _USING_FCGI_
void COPROC_INTEL : : write_xml ( MIOFILE & f , bool scheduler_rpc ) {
f . printf (
2012-12-08 18:16:28 +00:00
" <coproc_intel_gpu> \n "
2012-12-05 13:11:20 +00:00
" <count>%d</count> \n "
" <name>%s</name> \n "
" <available_ram>%f</available_ram> \n "
" <have_opencl>%d</have_opencl> \n " ,
count ,
name ,
available_ram ,
have_opencl ? 1 : 0
) ;
if ( scheduler_rpc ) {
write_request ( f ) ;
}
f . printf (
" <peak_flops>%f</peak_flops> \n "
" <version>%s</version> \n " ,
peak_flops ,
version
) ;
if ( have_opencl ) {
2013-04-17 05:42:29 +00:00
opencl_prop . write_xml ( f , " coproc_opencl " ) ;
2012-12-05 13:11:20 +00:00
}
2012-12-08 18:16:28 +00:00
f . printf ( " </coproc_intel_gpu> \n " ) ;
2016-09-01 14:40:31 +00:00
}
2012-12-05 13:11:20 +00:00
# endif
void COPROC_INTEL : : clear ( ) {
2020-02-10 20:23:11 +00:00
static const COPROC_INTEL x ( 0 ) ;
2019-11-05 08:16:02 +00:00
* this = x ;
2013-06-04 03:24:48 +00:00
safe_strcpy ( type , proc_type_name_xml ( PROC_TYPE_INTEL_GPU ) ) ;
2012-12-05 13:11:20 +00:00
estimated_delay = - 1 ;
2016-02-15 22:54:13 +00:00
safe_strcpy ( name , " " ) ;
safe_strcpy ( version , " " ) ;
2015-11-05 15:43:19 +00:00
global_mem_size = 0 ;
2015-11-25 21:39:24 +00:00
is_used = COPROC_USED ;
2012-12-05 13:11:20 +00:00
}
int COPROC_INTEL : : parse ( XML_PARSER & xp ) {
int retval ;
clear ( ) ;
while ( ! xp . get_tag ( ) ) {
2012-12-08 18:16:28 +00:00
if ( xp . match_tag ( " /coproc_intel_gpu " ) ) {
2012-12-05 13:11:20 +00:00
if ( ! peak_flops ) {
set_peak_flops ( ) ;
}
if ( ! available_ram ) {
available_ram = opencl_prop . global_mem_size ;
}
return 0 ;
}
if ( xp . parse_int ( " count " , count ) ) continue ;
if ( xp . parse_double ( " peak_flops " , peak_flops ) ) continue ;
if ( xp . parse_bool ( " have_opencl " , have_opencl ) ) continue ;
if ( xp . parse_double ( " available_ram " , available_ram ) ) continue ;
if ( xp . parse_double ( " req_secs " , req_secs ) ) continue ;
if ( xp . parse_double ( " req_instances " , req_instances ) ) continue ;
if ( xp . parse_double ( " estimated_delay " , estimated_delay ) ) continue ;
if ( xp . parse_str ( " name " , name , sizeof ( name ) ) ) continue ;
if ( xp . parse_str ( " version " , version , sizeof ( version ) ) ) continue ;
if ( xp . match_tag ( " coproc_opencl " ) ) {
2013-04-17 05:42:29 +00:00
retval = opencl_prop . parse ( xp , " /coproc_opencl " ) ;
2012-12-05 13:11:20 +00:00
if ( retval ) return retval ;
continue ;
}
}
return ERR_XML_PARSE ;
}
2012-12-06 10:05:33 +00:00
// http://en.wikipedia.org/wiki/Comparison_of_Intel_graphics_processing_units says:
// The raw performance of integrated GPU, in single-precision FLOPS,
// can be calculated as follows:
// EU * 4 [dual-issue x 2 SP] * 2 [multiply + accumulate] * clock speed.
//
// However, there is some question of the accuracy of this due to Intel's
// Turbo Boost and Dynamic Frequency technologies.
//
2012-12-05 13:11:20 +00:00
void COPROC_INTEL : : set_peak_flops ( ) {
double x = 0 ;
if ( opencl_prop . max_compute_units ) {
2012-12-06 10:05:33 +00:00
x = opencl_prop . max_compute_units * 8 * opencl_prop . max_clock_frequency * 1e6 ;
2012-12-05 13:11:20 +00:00
}
2019-02-07 21:52:35 +00:00
peak_flops = x ;
2012-12-05 13:11:20 +00:00
}
void COPROC_INTEL : : fake ( double ram , double avail_ram , int n ) {
2013-06-04 03:24:48 +00:00
safe_strcpy ( type , proc_type_name_xml ( PROC_TYPE_INTEL_GPU ) ) ;
safe_strcpy ( version , " 1.4.3 " ) ;
safe_strcpy ( name , " foobar " ) ;
2012-12-05 13:11:20 +00:00
count = n ;
available_ram = avail_ram ;
have_opencl = true ;
for ( int i = 0 ; i < count ; i + + ) {
device_nums [ i ] = i ;
}
set_peak_flops ( ) ;
2013-01-23 18:41:19 +00:00
opencl_prop . global_mem_size = ( cl_ulong ) ram ;
2012-12-05 13:11:20 +00:00
}
2012-12-11 00:04:35 +00:00
// used wherever a processor type is specified in XML, e.g.
// <coproc>
// <type>xxx</type>
//
2014-07-23 12:18:51 +00:00
// Don't confuse this with the element names used for GPUS within <coprocs>,
2012-12-11 00:04:35 +00:00
// namely:
// coproc_cuda
// coproc_ati
// coproc_intel_gpu
//
2012-06-25 23:09:45 +00:00
const char * proc_type_name_xml ( int pt ) {
2014-07-22 16:13:29 +00:00
switch ( pt ) {
case PROC_TYPE_CPU : return " CPU " ;
case PROC_TYPE_NVIDIA_GPU : return " NVIDIA " ;
case PROC_TYPE_AMD_GPU : return " ATI " ;
case PROC_TYPE_INTEL_GPU : return " intel_gpu " ;
2014-09-22 04:08:09 +00:00
case PROC_TYPE_MINER_ASIC : return " miner_asic " ;
2014-07-17 09:22:26 +00:00
}
2014-07-22 16:13:29 +00:00
return " unknown " ;
2012-06-25 23:09:45 +00:00
}
const char * proc_type_name ( int pt ) {
2014-07-22 16:13:29 +00:00
switch ( pt ) {
case PROC_TYPE_CPU : return " CPU " ;
case PROC_TYPE_NVIDIA_GPU : return " NVIDIA GPU " ;
case PROC_TYPE_AMD_GPU : return " AMD/ATI GPU " ;
case PROC_TYPE_INTEL_GPU : return " Intel GPU " ;
2014-09-22 04:08:09 +00:00
case PROC_TYPE_MINER_ASIC : return " Miner ASIC " ;
2014-07-17 09:22:26 +00:00
}
2014-07-22 16:13:29 +00:00
return " unknown " ;
2012-06-25 23:09:45 +00:00
}
2013-11-22 06:31:15 +00:00
int coproc_type_name_to_num ( const char * name ) {
2014-07-22 16:13:29 +00:00
if ( ! strcmp ( name , " CUDA " ) ) return PROC_TYPE_NVIDIA_GPU ;
if ( ! strcmp ( name , " NVIDIA " ) ) return PROC_TYPE_NVIDIA_GPU ;
if ( ! strcmp ( name , " ATI " ) ) return PROC_TYPE_AMD_GPU ;
if ( ! strcmp ( name , " intel_gpu " ) ) return PROC_TYPE_INTEL_GPU ;
2014-09-22 04:08:09 +00:00
if ( ! strcmp ( name , " miner_asic " ) ) return PROC_TYPE_MINER_ASIC ;
2014-07-23 12:18:51 +00:00
return - 1 ; // Some other type
2013-11-22 06:31:15 +00:00
}