Commit b2e40cba authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Refactoring tnlLogger to make it more structured, like tnlCudaDeviceInfo.

New feature: get sizes of L1, L2, L3 caches.
parent 0ed7d0b6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ set (headers tnlAssert.h
             tnlStaticFor.h
             tnlStatistics.h 
             tnlString.h 
             tnlSystemInfo.h
             tnlReal.h
             tnlTimer.h
             tnlTimerCPU.h  
@@ -48,6 +49,7 @@ set( common_SOURCES
     ${CURRENT_DIR}/tnlObject.cpp
     ${CURRENT_DIR}/tnlStatistics.cpp
     ${CURRENT_DIR}/tnlString.cpp 
     ${CURRENT_DIR}/tnlSystemInfo.cpp 
     ${CURRENT_DIR}/tnlTimer.cpp 
     ${CURRENT_DIR}/tnlTimerCPU.cpp      
     ${CURRENT_DIR}/mfilename.cpp 
+26 −104
Original line number Diff line number Diff line
@@ -15,13 +15,10 @@
 *                                                                         *
 ***************************************************************************/

#include <sys/utsname.h>
#include <time.h>
#include <unistd.h>
#include <fstream>
#include <iomanip>
#include <core/tnlLogger.h>
#include <tnlConfig.h>
#include <core/tnlSystemInfo.h>
#include <core/tnlCudaDeviceInfo.h>

tnlLogger :: tnlLogger( int _width,
@@ -53,98 +50,27 @@ void tnlLogger :: writeSeparator()

bool tnlLogger :: writeSystemInformation( const tnlParameterContainer& parameters )
{
   char host_name[ 256 ];
   struct utsname uts;
   gethostname( host_name, 255 );
   uname( &uts );
   writeParameter< char* >( "Host name:", host_name );
   writeParameter< char* >( "Architecture:", uts. machine );
   fstream file;
   file.open( "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", ios::in );
   int maxCpuFreq( 0 );
   if( file )
   {
      char line[ 1024 ];
      file.getline( line, 1024 );
      maxCpuFreq = atoi( line );
   }
   else
       cerr << "Unable to read information from /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq." << endl;
   file.close();
   file. open( "/proc/cpuinfo", ios :: in );
   if( file )
   {
      char line[ 1024 ];
      char* cpu_id;
      char* cpu_model_name;
      char* cpu_mhz;
      char* cpu_cache;
      tnlString modelName, Mhz, cache;
      int cores( 0 ), siblings( 0 );
      while( ! file. eof() )
      {
         int i;
         file. getline( line, 1024 );
         /*if( strncmp( line, "processor", strlen( "processor" ) ) == 0 )
         {
            i = strlen( "processor" );
            while( line[ i ] != ':' && line[ i ] ) i ++;
            cpu_id = &line[ i + 1 ];
            writeParameter< char * >( "CPU Id.:", cpu_id );
            continue;
         }*/
         if( strncmp( line, "model name", strlen( "model name" ) ) == 0 )
         {
            i = strlen( "model name" );
            while( line[ i ] != ':' && line[ i ] ) i ++;
            //cpu_model_name = &line[ i + 1 ];
            modelName.setString( &line[ i + 1 ] );
            //writeParameter< char * >( "Model name:", cpu_model_name );
            continue;
         }
         if( strncmp( line, "cpu cores", strlen( "cpu cores" ) ) == 0 )
         {
            i = strlen( "cpu MHz" );
            while( line[ i ] != ':' && line[ i ] ) i ++;
            cores = atoi( &line[ i + 1 ] );
            continue;
         }
         if( strncmp( line, "siblings", strlen( "siblings" ) ) == 0 )
         {
            i = strlen( "siblings" );
            while( line[ i ] != ':' && line[ i ] ) i ++;
            siblings = atoi( &line[ i + 1 ] );
         }
         /*if( strncmp( line, "cpu MHz", strlen( "cpu MHz" ) ) == 0 )
         {
            i = strlen( "cpu MHz" );
            while( line[ i ] != ':' && line[ i ] ) i ++;
            //cpu_mhz = &line[ i + 1 ];
            Mhz.setString( &line[ i + 1 ] );
            //writeParameter< char * >( "CPU MHz:", cpu_mhz );
            continue;
         }*/
         if( strncmp( line, "cache size", strlen( "cache size" ) ) == 0 )
         {
            i = strlen( "cache size" );
            while( line[ i ] != ':' && line[ i ] ) i ++;
            //cpu_cache = &line[ i + 1 ];
            cache.setString( &line[ i + 1 ] );
            //writeParameter< char * >( "CPU cache:", cpu_cache );
            continue;
         }
      }
      int threadsPerCore = siblings / cores;
   tnlSystemInfo systemInfo;


   writeParameter< tnlString >( "Host name:", systemInfo.getHostname() );
   writeParameter< tnlString >( "Architecture:", systemInfo.getArchitecture() );
   // FIXME: generalize for multi-socket systems, here we consider only the first found CPU
   const int cpu_id = 0;
   const int threads = systemInfo.getNumberOfThreads( cpu_id );
   const int cores = systemInfo.getNumberOfCores( cpu_id );
   int threadsPerCore = threads / cores;
   writeParameter< tnlString >( "CPU info", tnlString("") );
      writeParameter< tnlString >( "Model name:", modelName, 1 );
   writeParameter< tnlString >( "Model name:", systemInfo.getCPUModelName( cpu_id ), 1 );
   writeParameter< int >( "Cores:", cores, 1 );
   writeParameter< int >( "Threads per core:", threadsPerCore, 1 );
      writeParameter< tnlString >( "Max clock rate (in MHz):", maxCpuFreq / 1000, 1 );
      writeParameter< tnlString >( "Cache:", cache, 1 );
    }
   else
      cerr << "Unable to read information from /proc/cpuinfo." << endl;
   file.close();
   writeParameter< tnlString >( "Max clock rate (in MHz):", systemInfo.getCPUMaxFrequency( cpu_id ) / 1000, 1 );
   tnlCacheSizes cacheSizes = systemInfo.getCPUCacheSizes( cpu_id );
   tnlString cacheInfo = tnlString( cacheSizes.L1data ) + ", "
                       + tnlString( cacheSizes.L1instruction ) + ", "
                       + tnlString( cacheSizes.L2 ) + ", "
                       + tnlString( cacheSizes.L3 );
   writeParameter< tnlString >( "Cache (L1d, L1i, L2, L3):", cacheInfo, 1 );
   if( parameters.getParameter< tnlString >( "device" ) == "cuda" )
   {      
      int devices = tnlCudaDeviceInfo::getNumberOfDevices();
@@ -167,20 +93,16 @@ bool tnlLogger :: writeSystemInformation( const tnlParameterContainer& parameter
        writeParameter< bool >( "ECC enabled", tnlCudaDeviceInfo::getECCEnabled( i ), 2 );         
      }
   }
   writeParameter< char* >( "System:", uts. sysname );
   writeParameter< char* >( "Release:", uts. release );
   writeParameter< tnlString >( "System:", systemInfo.getSystemName() );
   writeParameter< tnlString >( "Release:", systemInfo.getSystemRelease() );
   writeParameter< char* >( "TNL Compiler:", ( char* ) TNL_CPP_COMPILER_NAME );
   return true;
}

void tnlLogger :: writeCurrentTime( const char* label )
{
   time_t timeval;
   time( &timeval );
   tm *tm_ptr = localtime( &timeval );
   char buf[ 256 ];
   strftime( buf, 256, "%a %b %d %H:%M:%S\0", tm_ptr );
   writeParameter< char* >( label, buf );
   tnlSystemInfo systemInfo;
   writeParameter< tnlString >( label, systemInfo.getCurrentTime() );
}

#ifdef TEMPLATE_EXPLICIT_INSTANTIATION
+0 −2
Original line number Diff line number Diff line
@@ -18,9 +18,7 @@
#ifndef mLoggerH
#define mLoggerH

#include <cstring>
#include <ostream>
#include <iomanip>
#include <config/tnlParameterContainer.h>

class tnlLogger
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define TNLLOGGER_IMPL_H_

#include <sstream>
#include <iomanip>

template< typename T >
void tnlLogger::writeParameter( const tnlString& label,
+170 −0
Original line number Diff line number Diff line
#include <set>
#include <iomanip>
#include <cstring>
#include <ctime>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "tnlSystemInfo.h"

tnlSystemInfo::tnlSystemInfo()
{
   uname( &uts );
   parseCPUInfo();
}

void
tnlSystemInfo::parseCPUInfo( void )
{
   std::ifstream file( "/proc/cpuinfo" );
   if( ! file ) {
      std::cerr << "Unable to read information from /proc/cpuinfo." << std::endl;
      return;
   }

   char line[ 1024 ];
   std::set< int > processors;
   while( ! file. eof() )
   {
      int i;
      file.getline( line, 1024 );
      if( strncmp( line, "physical id", strlen( "physical id" ) ) == 0 )
      {
         i = strlen( "physical id" );
         while( line[ i ] != ':' && line[ i ] ) i ++;
         processors.insert( atoi( &line[ i + 1 ] ) );
         continue;
      }
      // FIXME: the rest does not work on heterogeneous multi-socket systems
      if( strncmp( line, "model name", strlen( "model name" ) ) == 0 )
      {
         i = strlen( "model name" );
         while( line[ i ] != ':' && line[ i ] ) i ++;
         CPUModelName.setString( &line[ i + 1 ] );
         continue;
      }
      if( strncmp( line, "cpu cores", strlen( "cpu cores" ) ) == 0 )
      {
         i = strlen( "cpu MHz" );
         while( line[ i ] != ':' && line[ i ] ) i ++;
         CPUCores = atoi( &line[ i + 1 ] );
         continue;
      }
      if( strncmp( line, "siblings", strlen( "siblings" ) ) == 0 )
      {
         i = strlen( "siblings" );
         while( line[ i ] != ':' && line[ i ] ) i ++;
         CPUThreads = atoi( &line[ i + 1 ] );
      }
   }
   numberOfProcessors = processors.size();
}

tnlString
tnlSystemInfo::getHostname( void ) const
{
   char host_name[ 256 ];
   gethostname( host_name, 255 );
   return tnlString( host_name );
}

tnlString
tnlSystemInfo::getArchitecture( void ) const
{
   return tnlString( uts.machine );
}

tnlString
tnlSystemInfo::getSystemName( void ) const
{
   return tnlString( uts.sysname );
}

tnlString
tnlSystemInfo::getSystemRelease( void ) const
{
   return tnlString( uts.release );
}

tnlString
tnlSystemInfo::getCurrentTime( const char* format ) const
{
   const std::time_t time_since_epoch = std::time( nullptr );
   std::tm* localtime = std::localtime( &time_since_epoch );
   std::stringstream ss;
   ss << std::put_time( localtime, format );
   return tnlString( ss.str().c_str() );
}

int
tnlSystemInfo::getNumberOfProcessors( void ) const
{
   return numberOfProcessors;
}

tnlString
tnlSystemInfo::getOnlineCPUs( void ) const
{
   std::string online = readFile< std::string >( "/sys/devices/system/cpu/online" );
   return tnlString( online.c_str() );
}

int
tnlSystemInfo::getNumberOfCores( int cpu_id ) const
{
   return CPUCores;
}

int
tnlSystemInfo::getNumberOfThreads( int cpu_id ) const
{
   return CPUThreads;
}

tnlString
tnlSystemInfo::getCPUModelName( int cpu_id ) const
{
   cout << "model name = " << CPUModelName << endl;
   return CPUModelName;
}

int
tnlSystemInfo::getCPUMaxFrequency( int cpu_id ) const
{
   tnlString fileName( "/sys/devices/system/cpu/cpu" );
   fileName += tnlString( cpu_id ) + "/cpufreq/cpuinfo_max_freq";
   return readFile< int >( fileName );
}

tnlCacheSizes
tnlSystemInfo::getCPUCacheSizes( int cpu_id ) const
{
   tnlString directory( "/sys/devices/system/cpu/cpu" );
   directory += tnlString( cpu_id ) + "/cache";

   tnlCacheSizes sizes;
   for( int i = 0; i <= 3; i++ ) {
      const tnlString cache = directory + "/index" + tnlString( i );

      // check if the directory exists
      struct stat st;
      if( stat( cache.getString(), &st ) != 0 || ! S_ISDIR( st.st_mode ) )
         break;

      const int level = readFile< int >( cache + "/level" );
      const std::string type = readFile< std::string >( cache + "/type" );
      const int size = readFile< int >( cache + "/size" );

      if( level == 1 && type == "Instruction" )
         sizes.L1instruction = size;
      else if( level == 1 && type == "Data" )
         sizes.L1data = size;
      else if( level == 2 )
         sizes.L2 = size;
      else if( level == 3 )
         sizes.L3 = size;
   }
   return sizes;
}
Loading