-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Release 0.0.2: Generate and compile serial C++ code for SPNs;
- Loading branch information
Showing
53 changed files
with
2,518 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
## About `spnc` ## | ||
|
||
`spnc` is a multi-target compiler for Sum-Product Networks, | ||
a class of machine learning models. | ||
|
||
`spnc` currently supports generation of serial C++ code for SPNs, | ||
support for generating multi-threaded OpenMP code and CUDA code for | ||
Nvidia GPUs is under way. Additionally, `spnc` allows to compute | ||
statistics about an SPNs graph and output them to JSON. | ||
|
||
### Prerequisites ### | ||
|
||
`spnc` requires a recent version of Java to run and | ||
at least one of `g++` or `clang++` to be installed on your machine. | ||
|
||
### Installation ### | ||
|
||
Either download one of the release zips from the github page or | ||
compile `spnc` from source. To compile from source, simply run | ||
`./gradlew installDist` in the root folder of `spnc` and use the executable | ||
found at `build/install/spnc/bin/spnc`. | ||
|
||
### Usage ### | ||
|
||
`spnc` compiles SPNs from a textual representation | ||
(see `src/main/resources/NIPS5.spn` for an example). | ||
|
||
Running `spnc` with the desired input-file will generate an executable. | ||
The executable contains an automatically generated `main`-method which will | ||
read input-data from a plain-text file and, if a second file-name is given, | ||
compare them to the reference data from the reference-file (also plain text). | ||
The executable will also track the time spent to execute the SPN inference | ||
for all examples in the input sample. | ||
|
||
Run `spnc --help` to see additional options. | ||
|
||
##### Limitations ##### | ||
`spnc` *currently does not yet support Poisson or Gaussian distributions.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#include <iostream> | ||
#include <fstream> | ||
#include <sstream> | ||
#include <iomanip> | ||
#include <cmath> | ||
#include <chrono> | ||
#include <vector> | ||
#include "spn.hpp" | ||
|
||
#ifndef VALUES_PER_SAMPLE | ||
#define VALUES_PER_SAMPLE 5 | ||
#endif | ||
|
||
int* readInputSamples(char * inputfile, int * sample_count){ | ||
std::ifstream infile(inputfile); | ||
std::string line; | ||
std::vector<std::string> lines; | ||
while(std::getline(infile, line)){ | ||
lines.push_back(line); | ||
} | ||
|
||
auto * input_data = (int*) malloc(VALUES_PER_SAMPLE * lines.size() * sizeof(int)); | ||
int sample_count_int = 0; | ||
for(const std::string& s : lines){ | ||
std::istringstream stream(s); | ||
std::string token; | ||
int value_count = 0; | ||
while(std::getline(stream, token, ';')){ | ||
std::istringstream value_string(token); | ||
double value; | ||
if(!(value_string >> value)){ | ||
std::cout << "ERROR: Could not parse double from " << token.c_str() << std::endl; | ||
exit(-1); | ||
} | ||
input_data[sample_count_int*VALUES_PER_SAMPLE + value_count] = (int) value; | ||
++value_count; | ||
} | ||
++sample_count_int; | ||
} | ||
|
||
std::cout << "Read " << sample_count_int << " input samples" << std::endl; | ||
*sample_count = sample_count_int; | ||
return input_data; | ||
} | ||
|
||
double* readReferenceValues(char * outputfile, int sample_count){ | ||
std::ifstream infile(outputfile); | ||
std::string line; | ||
auto * output_data = (double*) malloc(sample_count * sizeof(double)); | ||
int count = 0; | ||
while(count < sample_count && std::getline(infile, line)){ | ||
std::istringstream value_string(line); | ||
double value; | ||
if(!(value_string >> value)){ | ||
std::cout << "ERROR: Could not parse double from " << line.c_str() << std::endl; | ||
exit(-1); | ||
} | ||
output_data[count] = value; | ||
++count; | ||
} | ||
|
||
std::cout << "Read " << count << " reference values" << std::endl; | ||
return output_data; | ||
} | ||
|
||
int main(int argc, char ** argv) { | ||
if(argc != 3){ | ||
std::cout << "Please provide input- and output-data file as first and second argument!" << std::endl; | ||
exit(1); | ||
} | ||
|
||
int sample_count = 0; | ||
|
||
void * input_data = readInputSamples(argv[1], &sample_count); | ||
double result[sample_count]; | ||
for(int i=0; i<sample_count; ++i){ | ||
result[i] = 42.0; | ||
} | ||
double * reference_data = readReferenceValues(argv[2], sample_count); | ||
|
||
auto begin = std::chrono::high_resolution_clock::now(); | ||
|
||
// TODO Kernel invocation | ||
spn_toplevel(sample_count, (activation_t*) input_data, result); | ||
|
||
auto end = std::chrono::high_resolution_clock::now(); | ||
int num_errors = 0; | ||
std::cout << "Sample count: " << sample_count << std::endl; | ||
for(int i=0; i<sample_count; ++i){ | ||
if(std::abs(std::log(result[i])-reference_data[i])>1e-6){ | ||
std::cout << "ERROR: Significant deviation @" << i << ": " << std::log(result[i]) << " (" << result[i] << ") " << " vs. " << reference_data[i] << std::endl; | ||
++num_errors; | ||
} | ||
} | ||
if(num_errors==0){ | ||
std::cout << "COMPUTATION OK" << std::endl; | ||
} | ||
|
||
std::cout << std::setprecision(15)<< "time per instance " << std::chrono::duration_cast<std::chrono::microseconds>(end-begin).count() / (double) sample_count << " us" << std::endl; | ||
std::cout << std::setprecision(15) << "time per task " << std::chrono::duration_cast<std::chrono::microseconds>(end-begin).count() << " us" << std::endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
SumNode_0 SumNode(0.5*Histogram1, 0.5*Histogram2){ | ||
Histogram1 Histogram(var1|[0., 1., 5.];[0.1,0.2]) | ||
Histogram2 Histogram(var2|[0., 3., 7.];[0.3,0.4]) | ||
} | ||
|
||
# var1;var2 |
Oops, something went wrong.