Skip to content

ptziegler/PInT

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

How to install and use the tool

1. Prerequisites

1) Install clang 12 with libTooling support (May work with clang 9+)
2) Install cmake 3.12+
3) Clone this git repository to your machine

2. Installing the tool

1) Change path of clang include directory which is stored in the Variable CLANG_INCLUDE_DIR to the path to your clang include directory. I.e. the code set (CLANG_INCLUDE_DIR "/rwthfs/rz/SW/UTIL/clang/7.0.0/lib64/clang/7.0.0" CACHE STRING "Directory where the clang system library header files are located") has to be changed to set (CLANG_INCLUDE_DIR "/path/to/your/clang/installation/clang/7.0.0/lib64/clang/7.0.0" CACHE STRING "Directory where the clang system library header files are located")
2) Change into the source directory
3) Create a new directory: mkdir build
4) Change into the new directory: cd build
5) Create the build system: cmake ..
6) Compile the tool: make

3. Using the tool

3.1 Instrumentation of your code

1) Include pattern instrumentation headers (Mind the C and CPP versions) in your source file
2) Add instrumenation commands at the beginning and end of code regions that belong to a pattern Example for code instrumentation
    
    PatternInstrumentation::PatternBegin("SupportingStructure LoopParallelism MainParLoop");
    #pragma omp for
    for (int i = 0; i < MAX_ITERATIONS; i++)
        someCode();
    PatternInstrumentation::PatternEnd("MainParLoop");
    
  

The formal Syntax of the PatternBegin expression is as follows:
'DesignSpace PatternName Identifier'
where DesignSpace is either FindingConcurrency, AlgorithmStructure, SupportingStructure or ImplementationMechanism,
PatternName is the name of the pattern employed in this code region,
and the Identifier is a name for this exact occurence of the pattern.
Identifiers can be re-used to indicate to the tool, that two (or more) code regions belong together.

Please note that patterns that due to implementation, pattern regions have to be closed in the opposite order in which they are opened (First Opened - Last Closed).

3.2 Creating a Compilation Database

PInT is a clang-based tool. Therefore, it requires compilation databases in order to obtain the compiler flags used to build your source code.

If you have a CMake project for your source code

  1. In your CMakeLists.txt, set the variable "EXPORT_COMPILE_COMMANDS" to 1 or ON: SET(EXPORT_COMPILE_COMMANDS 1)
  2. Create/update your build system: mkdir build && cd build && cmake ..
  3. Copy compile_commands.json to the directory containing the sources: cp compilation_commands.json path/to/src

If you use make (or another build tool) to build your source code
Install the Bear Tool. The tool intercepts the exec calls made by your build tool and creates a compilation database from this. Make sure to copy this compilation database to the directory of the source code.
ATTENTION: Sometimes the Bear Tool genearates multiple entries for the same file within the compilation database (compile_commands.json). If so delete those entries with non-absolute paths otherwise every Pattern is analyzed twice. Occurences, lines of codes and Fan-In Fan-Out will double. If you don't want to install the Bear Tool, you can copy the compilation commands from the make file. The syntax of the compilation database is covered in the JSON Compilation Database Format Specification.

If you want to write the compilation database from scratch by yourself consider the following tutorials: Compilation databases for Clang-based tools and JSON Compilation Database Format Specification also make shure to use absolute paths.

3.3 Running the tool

You can call the tool from its build directory like this: ./HPC-pattern-tool /path/to/compile_commands/file/. In our example now the compile_commands.json file is in the folder "file". Now every file specified in the compile_commands.json is analysed. Arbitrary additional arguments can be passed after --extra-arg=.

You'll have to tell PInT where the instrumentation header files are located. You can copy the instrumentation header files to the source directory. Alternatively, you can add an include flag using --extra-arg=, e.g. ./HPC-pattern-tool /path/to/compile_commands/file/ --extra-arg=-I/path/to/headers to your tool call. If you use cmake, you can instead add the flag to the list of include directories with include_directories(/path/to/headers). Finally, you can also add the -I/path/to/headers flag to the compilation database for the files where the instrumentation header is used.

3.4 Tool options

-onlyPattern

If you want to see the patterntree without the function calls you can use the flag -onlyPattern
./HPC-pattern-tool /path/to/compile_commands/file/ -onlyPattern --extra-arg=-I/path/to/headers

-noTree

If you want to see no tree you use the Flag -noTree
./HPC-pattern-tool /path/to/compile_commands/file/ -noTree --extra-arg=-I/path/to/headers

-useSpecFiles

If you want to analyze specific files and not every file in your Compilation Database (in the compile_commands.json file). You can use the flag -useSpecFiles. Then you can specify every file that you want to analyze. ./HPC-pattern-tool /path/to/compile_commands/file/file1.cpp /path/to/compile_commands/file/file2.cpp /path/to/compile_commands/file/file3.cpp -useSpecFiles --extra-arg=-I/path/to/headers Every file specified has to be in the compilation database (in the compile_commands.json file), if not the tool will crash. When using this flag there will be an additional output "ANALYZE LIST:" which shows you which files are analyzed, a file which is not in the compilation database is not analyzed. You should be careful using this flag. The function bodies of the functions in files which where not specified are not analyzed. When a pattern is called from one of those functions this pattern is not displayed in the tree.

-maxTreeDisplayDepth

You can use this flag if you want to cut off the deepest parts of the tree. This is really usefull for large files, to avoid printing the tree for hours. The other statistics are working with a uncut version of the tree. Per default this is set to 10. For large codes you can set it to a smaller number for example 5. ./HPC-pattern-tool /path/to/compile_commands/file/ -maxTreeDisplayDepth=5 --extra-arg=-I/path/to/headers

-displayCompilationsList

This flag is usefull for checking if all files you need to analyze are in the compilation database, which means considered by the tool.

-pintVersion

This flag shows you which version of the tool (PInT) you are using by displaying the commit hash. You can use this flag with the following command. /path/to/your/build/directory/of/the/Tool/./HPC-pattern-tool /path/to/your/build/directory/of/the/Tool -pintVersion If you are alredy in the build directory of the tool you can use: ./HPC-pattern-tool . -pintVersion

-relationTree

This flag is used to show the relationTree next to the CallTree. This three only shows relations between the functions and the pattern, but it is not suited to display caller callee relationships. For example multiple calls to the same function are not considered, the nesting of the pattern and functions has to be clear. You can use this flag with the following command. /path/to/your/build/directory/of/the/Tool/./HPC-pattern-tool /path/to/your/build/directory/of/the/Tool -relationTree

4. Limitations

Since our tool is a static analysis tool there are some limitations.

If-else commands

It is not allowed to spread pattern parts through if-else commands.

  #include "PatternInstrumentation.h"

int main(int argc, const char** argv){ if(true){ PatternInstrumentation::Pattern_Begin("FindingConcurrency TypeQualifiers ifA"); } else{ PatternInstrumentation::Pattern_Begin("FindingConcurrency TypeQualifiers elseB"); }

if(true){
  PatternInstrumentation::Pattern_End("ifA");
}
else{
  PatternInstrumentation::Pattern_End("elseB");
}
return 0;

}

This code will give you a stack inconsistency warning. We can not deal properly with patterns parts spread over if statements or if-else statements. If you started your pattern part within an if or an else statement, you should end it in the same statement otherwise you can get wrong results (even without warning). This code for example throws no warning.


  #include "PatternInstrumentation.h"

  int main(int argc, const char** argv){
    if(true){
      PatternInstrumentation::Pattern_Begin("FindingConcurrency TypeQualifiers ifA");
    }
    else{
      PatternInstrumentation::Pattern_Begin("FindingConcurrency TypeQualifiers elseB");
    }

    if(true){
      PatternInstrumentation::Pattern_End("elseB");
    }
    else{
        PatternInstrumentation::Pattern_End("ifA");
    }
  	return 0;
  }

The pattern part of TypeQualifiers, ifA will appear as a parent of elseB.

Pattern parts (CodeRegions) which are spread over different functions

It is allowed to spread pattern parts over different functions.

  #include "PatternInstrumentation.h"

void function1(){ PatternInstrumentation::Pattern_Begin("SupportingStructure func1 One"); }; void function2(){ PatternInstrumentation::Pattern_End("One"); }; int main(int argc, const char** argv){ function1(); function2(); return 0; }

Some metrics are applicable for those constructions. FanIn-FanOut and Cyclomatic Complexity for example.

Remarks for FanIn-FanOut

For the calculation of FanIn-FanOut we excluded the Pattern parts (CodeRegions) which are not nexted clearly, those pattern which are not completely inside or outside of another pattern.
Exmaples would be:

  #include "PatternInstrumentation.h"

int main(int argc, const char** argv){ PatternInstrumentation::Pattern_Begin("SupportingStructure patternName One"); //source code PatternInstrumentation::Pattern_Begin("SupportingStructure patternName Two"); //source code PatternInstrumentation::Pattern_End("One"); //source code PatternInstrumentation::Pattern_End("Two"); //source code PatternInstrumentation::Pattern_Begin("SupportingStructure patternName Three"); //source code PatternInstrumentation::Pattern_End("Three"); //source code return 0; }

In this example the Pattern patternName is divided in three CodeRegions One, Two and Three. The CodeRegions One and Two are excluded in the calculation of FanIn-FanOut because they are not nested clearly.
Those Pattern are listed at the beginning of the output of our tool.

Remarks for Cyclomatic Complexity

The Cyclomatic Complexity is computed on the generated Pattern Graph. We did not change anything on the implementation of this metric. This means when a Pattern_Begin is within another Pattern it is treated as if it were fully within this pattern. You get to decide if this metric is still usefull for your purpose

About

Pattern Instrumentation Tool

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 98.1%
  • CMake 1.7%
  • Other 0.2%