Skip to content

Experimental/corbett/jit #225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e9f5e2c
Added JIT proof of concept.
corbett5 Jul 16, 2020
e898a2c
Working on grabbing compilation comands from cmake.
corbett5 Jul 20, 2020
2c45cf7
Squash, cmake scraping working on quartz.
corbett5 Jul 20, 2020
3bf28dd
Working out a runtime link error with raja on lassen...
corbett5 Jul 20, 2020
4481496
compile and link working on quartz.
corbett5 Jul 26, 2020
fbe983d
Compiling and linking working. testDynamicLibrary segfaults when usin…
corbett5 Jul 26, 2020
478d779
Works on Lassen when not using Chai. Try building tpls as shared obje…
corbett5 Jul 26, 2020
c90a8f3
Everything working except testTemplateCompiler on Lassen. Linking to …
corbett5 Jul 27, 2020
ba7632e
All tests passing on Quartz and Lassen.
corbett5 Jul 27, 2020
5bd1ff9
Update
corbett5 Feb 20, 2021
6567177
Changes for geosx
corbett5 Feb 23, 2021
d2202cd
Working with CUDA
corbett5 Feb 23, 2021
c21bdb9
Working on a cache.
corbett5 Feb 27, 2021
57ac783
Working with CUDA, now need to add lots of tests.
corbett5 Feb 27, 2021
ca9a9bc
More tests.
corbett5 Feb 28, 2021
876651a
Added tests, still need to test Cache.
corbett5 Mar 1, 2021
33c9977
Temp
corbett5 Mar 1, 2021
5f49543
merge
wrtobin Jun 23, 2021
593a880
wut
wrtobin Jun 23, 2021
d447a0c
wut
wrtobin Jun 23, 2021
5d250c1
small cleanup and fix testCache
wrtobin Jul 7, 2021
48e8365
changes to accomodate functionality in geosx
wrtobin Sep 1, 2021
850e13c
removing generated header
wrtobin Sep 2, 2021
7b9e4e3
reverting some temp cmake changes
wrtobin Sep 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ blt_list_append( TO lvarray_dependencies ELEMENTS cuda IF ENABLE_CUDA )

blt_list_append( TO lvarray_dependencies ELEMENTS caliper IF ENABLE_CALIPER )


add_subdirectory( src )

if( ENABLE_TESTS AND NOT DISABLE_UNIT_TESTS )
Expand All @@ -108,5 +107,3 @@ endif()
if( ENABLE_DOCS )
add_subdirectory( docs )
endif()


10 changes: 8 additions & 2 deletions cmake/SetupTPL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ set(ENABLE_RAJA ON CACHE BOOL "")

set(thirdPartyLibs ${thirdPartyLibs} RAJA)


###############################
# UMPIRE
###############################
Expand All @@ -43,7 +42,12 @@ if(ENABLE_UMPIRE)

find_package(umpire REQUIRED
PATHS ${UMPIRE_DIR})


blt_register_library(NAME umpire
INCLUDES ${UMPIRE_INCLUDE_DIRS}
LIBRARIES umpire
TREAT_INCLUDES_AS_SYSTEM ON)

set(thirdPartyLibs ${thirdPartyLibs} umpire)
else()
message(STATUS "Not using Umpire.")
Expand Down Expand Up @@ -92,6 +96,8 @@ if(ENABLE_CALIPER)

message(STATUS "Using caliper from ${CALIPER_DIR}")

set(FIND_LIBRARY_USE_LIB64_PATHS TRUE)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this? Also why do we need to blt_register_library for Umpire? I prefer not to do this unless it's necessary (usually only for non-CMake targets).


find_package(caliper REQUIRED
PATHS ${CALIPER_DIR})

Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ lvarray_add_code_checks( PREFIX lvarray
if( ENABLE_PYLVARRAY )
add_subdirectory( python )
endif()

add_subdirectory( jitti )
19 changes: 19 additions & 0 deletions src/jitti/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
set( jitti_headers
types.hpp
CompilationInfo.hpp
utils.hpp
Function.hpp
Cache.hpp
)

set( jitti_sources
CompilationInfo.cpp
Function.cpp
utils.cpp
)

blt_add_library( NAME jitti
SOURCES ${jitti_sources}
HEADERS ${jitti_headers}
DEPENDS_ON lvarray dl
)
237 changes: 237 additions & 0 deletions src/jitti/Cache.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
#pragma once

#include "Function.hpp"
#include "utils.hpp"
#include "CompilationInfo.hpp"
#include "../Macros.hpp"
#include "../typeManipulation.hpp"

#include <string>
#include <vector>
#include <unordered_map>

namespace jitti
{

// template < const char * TYPE, const char * HEADER >
// struct constexpr_jitti_info
// {
// constexpr static const char * typeName = TYPE;
// constexpr static const char * headerFile = HEADER;
// };

//
// NOTE: The TYPE value in the following macros needs to be *FULLY SCOPED*!
//
#if JITTI == 1
// We can't programmatically get a constexpr expression with the name of the type without fully
// specifying the type e.g. specifying all the template parameters
// Since JIITTI is based around delaying that specification until we JIT a function, we can't
// use templates to derive this info, it can only happen via preprocessing
//
// C++20 will allow using string literals as template parameters, until then we have to
// declare/define a constexpr character array and use a pointer to that instead
// but when it is available we can obsolete the JITTI_DECL macro, and jitti::Name struct entirely
#define JITTI_DECL( VARNAME, TYPE, HEADER ) \
constexpr const char VARNAME##Name[] = STRINGIZE( TYPE ); \
Comment on lines +35 to +36
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure this is used in GEOSX, but what exactly is it used for?

constexpr const char VARNAME##Header[] = HEADER;
#define JITTI_TPARAM( VARNAME, TYPE ) VARNAME##Name, VARNAME##Header
#else
#define JITTI_DECL( VARNAME, TYPE, HEADER )
#define JITTI_TPARAM( VARNAME, TYPE ) TYPE
#endif

template< typename ARG0, typename ... ARGS >
std::string getInstantiationName( std::string const & templateName,
ARG0 const & firstTemplateParam,
ARGS const & ... remainingTemplateParams )
{
std::string output = templateName;
output += "< " + firstTemplateParam;
LvArray::typeManipulation::forEachArg( [&output] ( auto const & param )
{
output += ", " + param;
}, remainingTemplateParams... );

output += " >";
return output;
}

/**
*
*/
template< typename FUNC_POINTER >
class Cache
{
public:

/**
*
*/
Cache( time_t const compilationTime,
std::string const & libraryOutputDir,
std::vector< std::string > const & libraryDirs={} ):
m_compilationTime( compilationTime ),
m_libraryOutputDir( libraryOutputDir ),
m_libraryDirs( libraryDirs )
{
utils::makeDirsForPath( libraryOutputDir );
m_libraryDirs.push_back( libraryOutputDir );
refresh();
}

Cache( Cache const & ) = delete;
Cache( Cache && ) = delete;

/**
*
*/
void refresh() const
{
for( std::string const & libraryDir : m_libraryDirs )
{
utils::readDirectoryFiles( m_compilationTime, libraryDir, m_libraries );
}
}

/**
*
*/
Function< FUNC_POINTER > const * tryGet( std::string const & instantiationName ) const
{
auto const iter = m_cache.find( instantiationName );
if( iter == m_cache.end() )
{ return nullptr; }

return &iter->second;
}

/**
*
*/
Function< FUNC_POINTER > const * tryGet( CompilationInfo const & info ) const
{
return tryGet( getInstantiationName( info.templateFunction, info.templateParams ) );
}

/**
*
*/
Function< FUNC_POINTER > const & get( std::string const & instantiationName ) const
{
Function< FUNC_POINTER > const * const function = tryGet( instantiationName );
LVARRAY_ERROR_IF( function == nullptr,
"Could not find an instantiation called '" << instantiationName << "' in the cache. " <<
"Maybe you need to compile it (use getOrLoadOrCompile)." );

return *function;
}

/**
*
*/
Function< FUNC_POINTER > const & get( CompilationInfo const & info ) const
{
return get( getInstantiationName( info.templateFunction, info.templateParams ) );
}

/**
*
*/
Function< FUNC_POINTER > const * tryGetOrLoad( std::string const & instantiationName )
{
Function< FUNC_POINTER > const * function = tryGet( instantiationName );
if( function != nullptr )
{
return function;
}

// Then look among those already compiled.
std::string const libraryName = getLibraryName( instantiationName );
auto const iter = m_libraries.find( libraryName );
if( iter != m_libraries.end() )
{
auto const result = m_cache.emplace( std::make_pair( instantiationName, Function< FUNC_POINTER >( iter->second ) ) );
LVARRAY_ERROR_IF( !result.second, "This shouldn't be possible." );

function = &result.first->second;
LVARRAY_ERROR_IF_NE_MSG( function->getName(), instantiationName,
"Expected a different function at '" << iter->second << "'." );

return function;
}

return nullptr;
}

/**
*
*/
Function< FUNC_POINTER > const * tryGetOrLoad( CompilationInfo const & info )
{
return tryGetOrLoad( getInstantiationName( info.templateFunction, info.templateParams ) );
}

/**
*
*/
Function< FUNC_POINTER > const & getOrLoad( std::string const & instantiationName )
{
Function< FUNC_POINTER > const * function = tryGetOrLoad( instantiationName );
LVARRAY_ERROR_IF( function == nullptr,
"Could not find an instantiation called '" << instantiationName << "' in the cache. " <<
"Maybe you need to compile it (use getOrLoadOrCompile)." );

return *function;
}

/**
*
*/
Function< FUNC_POINTER > const & getOrLoad( CompilationInfo & info )
{
return getOrLoad( getInstantiationName( info.templateFunction, info.templateParams ) );
}

/**
*
*/
Function< FUNC_POINTER > const & getOrLoadOrCompile( CompilationInfo & info )
{
std::string const instantiationName = getInstantiationName( info.templateFunction, info.templateParams );

Function< FUNC_POINTER > const * function = tryGetOrLoad( instantiationName );
if( function != nullptr )
{
return *function;
}

// Otherwise we have to compile it.
info.outputLibrary = m_libraryOutputDir + "/" + getLibraryName( instantiationName );
info.outputObject = info.outputLibrary.substr( 0, info.outputLibrary.size() - 3 ) + ".o";
auto const result = m_cache.emplace( std::make_pair( instantiationName, Function< FUNC_POINTER >( info ) ) );
LVARRAY_ERROR_IF( !result.second, "This shouldn't be possible." );
return result.first->second;
}

private:

std::string getLibraryName( std::string const & instantiationName ) const
{ return "lib" + std::to_string( std::hash< std::string >{}( instantiationName ) ) + ".so"; }

time_t const m_compilationTime;

/// The directory in which to create new libraries.
std::string const m_libraryOutputDir;

/// A vector of library directories to search for libraries.
std::vector< std::string > m_libraryDirs;

/// A map from library names to library paths.
std::unordered_map< std::string, std::string > mutable m_libraries;

/// A map containing all the compiled libraries that have been loaded.
std::unordered_map< std::string, Function< FUNC_POINTER > > m_cache;
};

} // namespace jitti
63 changes: 63 additions & 0 deletions src/jitti/CompilationInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "CompilationInfo.hpp"
#include "../Macros.hpp"

#include <cstring>
#include <time.h>

static int monthStringToInt( char const * const month )
{
if ( strncmp( month, "Jan", 3 ) == 0 )
{ return 0; }
if ( strncmp( month, "Feb", 3 ) == 0 )
{ return 1; }
if ( strncmp( month, "Mar", 3 ) == 0 )
{ return 2; }
if ( strncmp( month, "Apr", 3 ) == 0 )
{ return 3; }
if ( strncmp( month, "May", 3 ) == 0 )
{ return 4; }
if ( strncmp( month, "Jun", 3 ) == 0 )
{ return 5; }
if ( strncmp( month, "Jul", 3 ) == 0 )
{ return 6; }
if ( strncmp( month, "Aug", 3 ) == 0 )
{ return 7; }
if ( strncmp( month, "Sep", 3 ) == 0 )
{ return 8; }
if ( strncmp( month, "Oct", 3 ) == 0 )
{ return 9; }
if ( strncmp( month, "Nov", 3 ) == 0 )
{ return 10; }
if ( strncmp( month, "Dec", 3 ) == 0 )
{ return 11; }

LVARRAY_ERROR( "Uncrecognized month: " << month );
return -1;
}

namespace jitti
{

namespace internal
{

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
time_t getCompileTime( char const * const date, char const * const time )
{
struct tm dateTime {};
dateTime.tm_mon = monthStringToInt( date );
dateTime.tm_mday = std::atoi( date + 4 );
dateTime.tm_year = std::atoi( date + 7 ) - 1900;

dateTime.tm_hour = std::atoi( time );
dateTime.tm_min = std::atoi( time + 3 );
dateTime.tm_sec = std::atoi( time + 6 );

dateTime.tm_isdst = -1;

return mktime( &dateTime );
}

} // namespace internal

} // namespace jitti
Loading