I'm having troubles doing experiments on fpga and gpu using sycl.
I'm working online with intel devcloud and I get these 2 runtime errors when performing the executables:
On FPGA:
terminate called after throwing an instance of 'sycl::_V1::runtime_error'
what(): Invalid device program image: size is zero -30 (PI_ERROR_INVALID_VALUE)
on GPU:
terminate called after throwing an instance of 'sycl::_V1::runtime_error'
what(): Native API failed. Native API returns: -1 (PI_ERROR_DEVICE_NOT_FOUND) -1 (PI_ERROR_DEVICE_NOT_FOUND)
Here's the main Codes:
#include <sycl/sycl.hpp>
#include <sycl/ext/intel/fpga_extensions.hpp>
// #include <oneapi/mkl/blas.hpp>
#include <cmath>
#include <chrono>
#include <iostream>
#include <vector>
#include <cmath>
#include "guideline.h"
#include "print_vector.h"
#include "print_time.h"
#include "read_graph.h"
#include "flatVector.h"
using namespace sycl;
int main(int argc, char* argv[]){
// Check Command Line
if(argc < 6){
// NOT ENOUGH PARAMS BY COMMAND LINE -> PROGRAM HALTS
guideline();
}
else{
// Command Line parsing
int device_selected = atoi(argv[1]);
std::string csv_path = argv[2];
double threshold = atof(argv[3]);
double damping = atof(argv[4]);
int verbose;
try{verbose = atoi(argv[5]);}
catch (exception const& e) {verbose = 0;}
device d = device(default_selector());
// Queue
queue q(d);
std::cout << "Device : " << q.get_device().get_info<info::device::name>() << "\n"; // print del device
// Reading and setup Time Calculation
auto start_setup = std::chrono::steady_clock::now();
// Graph Retrieval by csv file
std::vector<std::vector<int>> graph = Read_graph(csv_path);/*Sparse Matrix Representation with the description of each Edge of the Graph*/
std::vector<int> flatGraph = flatten<int>(graph);
// Calculation of the # Nodes
int numNodes = countNodes(graph);
// Calculation of the Degree of each node
std::vector<int> degreesNodes = getDegrees(graph, numNodes+1);
auto end_setup = std::chrono::steady_clock::now();
// Setup Execution Time print
std::cout << "TIME FOR SETUP" << "\n";
print_time(start_setup, end_setup);
// Check Print
//printVector<int>(degreesNodes);
//Creation of Initial and Final Ranks' vectors of PageRank [R(t); R(t+1)]
std::vector<double> ranks_t(numNodes, (double)(1.0/ (double)(numNodes)));
std::vector<double> ranks_t_plus_one(numNodes, 0.0);
std::vector<double> ranksDifferences(numNodes, 0.0);
// PageRank Execution Time calculation
auto start = std::chrono::steady_clock::now();
buffer<int> bufferEdges(flatGraph.data(),flatGraph.size());
buffer<double> bufferRanks(ranks_t.data(),ranks_t.size());
buffer<int> bufferDegrees(degreesNodes.data(),degreesNodes.size());
buffer<double> bufferRanksNext(ranks_t_plus_one.data(),ranks_t_plus_one.size());
buffer<double> bufferRanksDifferences(ranksDifferences.data(),ranksDifferences.size());
double distance = threshold + 1;
int graph_size = flatGraph.size();
int T = 1;
while (distance > threshold) {
q.submit([&](handler &h){
accessor Edges(bufferEdges,h,read_only);
accessor Ranks(bufferRanks,h,read_only);
accessor Degrees(bufferDegrees,h,read_only);
accessor RanksNext(bufferRanksNext,h,write_only);
accessor RanksDifferences(bufferRanksDifferences,h,write_only);
h.parallel_for(range<1>(numNodes),[=] (id<1> i){
RanksNext[i] = (1.0 - damping) / numNodes;
int index_node_i;
int index_node_j;
for (int j = 0; j<graph_size;j+=2) {
index_node_i = j;
index_node_j = j + 1;
if (Edges[index_node_j] == i) {
RanksNext[i] += damping * Ranks[Edges[index_node_i]] / Degrees[Edges[index_node_i]];
}
}
RanksDifferences[i] = (RanksNext[i] - Ranks[i]) * (RanksNext[i] - Ranks[i]);
});
}).wait();
distance = 0;
for (int i = 0; i < numNodes; i++) {
distance += ranksDifferences[i];
ranks_t[i] = ranks_t_plus_one[i];
ranks_t_plus_one[i] = 0.0;
}
distance = sqrt(distance);
std::cout<< "Time:\t" << T << "\tEuclidian Distance:\t" << distance << std::endl;
T++;
}
auto end = std::chrono::steady_clock::now();
// PageRank Results Printing
if(verbose == 1){
for(int i = 0;i<ranks_t.size();i++){
std::cout<<"Final Vector" << i<< "-th component:\t"<<ranks_t[i]<<std::endl;
}
}
std::cout<<std::endl<<std::endl<<std::endl;
std::cout<<"Final Norm:\t"<<distance<<std::endl;
// PageRank Execution Time Printing
std::cout << "TIME FOR PAGERANK" << "\n";
print_time(start, end);
}
return 0;
}
flatVector.h
#include <iostream>
#include <vector>
template<typename T>
std::vector<T> flatten(const std::vector<std::vector<T>>& nestedVector) {
std::vector<T> flatVector;
for (const auto& subVector : nestedVector) {
for (const auto& element : subVector) {
flatVector.push_back(element);
}
}
return flatVector;
}
guideline.h
#include <iostream>
void guideline(){
std::cout<<"Not enough input parameters!\n\n";
std::cout<<"Usage guide:\n\n";
std::cout<<"First parameter:\tDevice code (as int number)\n";
std::cout<<"\t\t1: CPU\n";
std::cout<<"\t\t2: GPU\n";
std::cout<<"\t\t3: FPGA\n";
std::cout<<"Second parameter:\tCsv path of the dataset\n";
std::cout<<"Available Ones:\n\n";
std::cout<<"\t\t\"datasets/cit-Patents.csv\""<<std::endl;
std::cout<<"\t\t\"datasets/soc-LiveJournal1.csv\""<<std::endl;
std::cout<<"\t\t\"datasets/twitter-2010.csv\""<<std::endl;
std::cout<<"\t\t\"datasets/web-uk-2005-all.csv\""<<std::endl;
std::cout<<"Third parameter:\tThreshold (double value)\n";
std::cout<<"Fourth parameter:\tDamping (double value)\n";
std::cout<<"Fifth parameter:\tVerbose (int value)\n";
std::cout<<"Prints all the ranks of each node\n";
std::cout<<"Watch out! The print is huge\n";
}
printTime.h
#include <iostream>
#include <chrono>
void print_time(std::chrono::time_point<std::chrono::steady_clock> start, std::chrono::time_point<std::chrono::steady_clock> end){
std::cout << "Elapsed time in nanoseconds: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count() << " ns" << std::endl;
std::cout << "Elapsed time in microseconds: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << " µs" << std::endl;
std::cout << "Elapsed time in milliseconds: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl;
std::cout << "Elapsed time in seconds: " << std::chrono::duration_cast<std::chrono::seconds>(end - start).count() << " sec" << std::endl;
}
printVector.h
#include <iostream>
#include <vector>
template <typename T>
void printVector(std::vector<T> vector_like_var){
for(int i = 0; i < vector_like_var.size(); i++){
std::cout<< "element " <<i+1 << "of vector:\t" << vector_like_var[i] <<std::endl;
}
}
read_graph.h
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
// #include "print_vector.h"
std::vector<int> getDegrees(const std::vector<std::vector<int>> &graph, int numNodes) {
std::vector<int> degrees(numNodes);
for (auto &edge : graph) {
++degrees[edge[0]];
++degrees[edge[1]];
}
return degrees;
}
std::vector<std::vector<int>> Read_graph(std::string file_name){
// Apertura del file
std::ifstream file(file_name);
if (!file.is_open()) {
std::cerr << "Impossibile aprire il file" << std::endl;
return {};
}
// Lettura del file riga per riga
std::string line;
std::vector<std::vector<int>> graph;
while (getline(file, line)) {
std::stringstream ss(line);
std::string cell;
std::vector<int> edge;
while (getline(ss, cell, ',')) {
edge.push_back(stoi(cell));
}
graph.push_back(edge);
}
file.close();
return graph;
}
int countNodes(std::vector<std::vector<int>> graph){
int numNodes = 0;
for(auto &i : graph){
for(auto &j : i){
numNodes = std::max(numNodes, j);
}
}
return numNodes;
}
I know that it runs on CPU, because I've done experiments and it prints out the ranks.
I tried executing on different devices the experiment, for example by using gen 9 GPUs of intel, but it was no use.
Related
When I use FFTW, specifically the plan creation function fftw_plan_dft_r2c_1d(), for purely real input, the only "planner flag" (FFTW's terminology) which works is FFTW_ESTIMATE. Any of the others which I try, viz., FFTW_EXHAUSTIVE, FFTW_MEASURE, and FFTW_PATIENT, all generate an output file with all zeros.
I have tried changing the number of input data items from powers of 2 to otherwise. That makes no difference.
Scilab uses FFTW for its fft() and thus I am able to compare the output from my C++ program with the output from Scilab for the same input data file. When I use FFTW_ESTIMATE the two outputs match.
I have read the FFTW documentation. I cannot determine why the other planner flags do not work.
I am interested in using the FFTW_MEASURE planner flag since once the plan is formulated, I will want to use it repeatedly.
Below is my code. I have not included the fftw3.h file as I have not made any changes to it.
#pragma once
// FFT_05.h
//#include <array>
#include <cmath>
#include <complex>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "fftw3.h"
#define M_PI 3.14159265358979323846
// FFT_05_c.cpp
#include "FFT_05.h"
//*****************************************************************************
int32_t main(int argc, char* argv[]) {
std::fstream data_File;
std::string directory = "C:/Documents/Visual Studio 2022/Projects/";
directory += "FFT_05/Scilab programs/02/";
std::string file_Name = "Time_domain_input.txt";
data_File.open(directory + file_Name, std::ios_base::in | std::ios_base::binary);
double input_Value = 0.0;
int data_Count = 0;
if (data_File.is_open()) {
while (!data_File.eof()) {
data_File >> input_Value;
data_Count++;
}
}
std::cout << data_Count << std::endl;
data_File.seekg(0, std::ios_base::beg);
double* in;
fftw_complex* out;
fftw_plan p;
in = (double*)fftw_malloc(sizeof(double) * data_Count);
int data_Count_Out = (data_Count / 2) + 1;
out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * data_Count_Out);
int i = 0;
while (!data_File.eof()) {
data_File >> input_Value;
in[i++] = input_Value;
}
data_File.close();
//for (int i = 0; i < data_Count; i++) {
// //std::cout << in[i][0] << ", " << in[i][1] << std::endl;
// std::cout << (i + 1) << ". " << in[i] << std::endl;
//}
//std::cout << "\n\n";
// FFTW procedure
p = fftw_plan_dft_r2c_1d(data_Count, in, out, FFTW_ESTIMATE);
if (!p) {
std::cout << "FFTW plan is NULL\n";
exit(1);
}
fftw_execute(p);
fftw_destroy_plan(p);
std::fstream FFT_Data_File;
FFT_Data_File.open(directory + "frequency_Domain_File_Name_c.txt",
std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
for (int i = 0; i < (data_Count_Out - 1); i++) {
FFT_Data_File << out[i][0] << " " << out[i][1] << std::endl;
}
FFT_Data_File << out[(data_Count_Out - 1)][0] << " " << out[(data_Count_Out - 1)][1];
FFT_Data_File.close();
fftw_free(in);
fftw_free(out);
}
Below is my sample code through which i'm trying to benchmark hiredis client with IgniteServer to Store and Retrieve a C++ Class Object after serializing.
#include <cassert>
#include <sstream>
#include <string>
#include <unordered_map>
#include <time.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
#include <chrono>
#include <time.h>
#include <hiredis/hiredis.h>
#include <cereal/archives/binary.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/unordered_map.hpp>
using namespace std::chrono;
struct Person
{
friend class cereal::access;
template <typename Archive>
void serialize(Archive& archive) {
// archive(orgId,firstName, lastName,resume,salary,other);
archive & orgId & firstName & lastName & resume & salary & other;
}
Person() {}
Person(int32_t orgId, const std::string& firstName,
const std::string& lastName, const std::string& resume, double sal, const std::string& other) :
orgId(orgId),
firstName(firstName),
lastName(lastName),
resume(resume),
salary(sal),
other(other)
{
// No-op.
}
int64_t orgId;
std::string firstName;
std::string lastName;
std::string resume;
double salary;
std::string other;
};
auto redis_context = redisConnect("127.0.0.1", 6379);
int _set(int32_t key, Person p){
std::ostringstream oss;
cereal::BinaryOutputArchive archive{oss};
archive(p.orgId,p.firstName, p.lastName,p.resume,p.salary,p.other);
const auto set_reply =
redisCommand(redis_context, "SET %ld %b",(long)key,oss.str().c_str(), oss.str().length());
freeReplyObject(set_reply);
}
int _get(int32_t key){
const auto get_reply =
static_cast<redisReply*>(redisCommand(redis_context, "GET %ld",(long)key));
std::string repr{get_reply->str, static_cast<size_t>(get_reply->len)};
if(static_cast<size_t>(get_reply->len) <= 0) {
std::cout << "No key is matching" << std::endl;
return -1;
}
std::istringstream iss{repr};
cereal::BinaryInputArchive input(iss);
Person g;
input(g);
std::cout << g.orgId << " Name: " << g.firstName << " Last: " << g.lastName << "Resume: " << g.resume<< " Salary: " << g.salary << " Other: " << g.other <<std::endl;
freeReplyObject(get_reply);
iss.clear();
// redisFree(redis_context);
}
int _remove(int32_t key){
const auto del_reply =
static_cast<redisReply*>(redisCommand(redis_context, "DEL %ld",(long)key));
freeReplyObject(del_reply);
_get(key);
}
int main(int argc, char **argv) {
int start =1 ;
int range =3;
std::cout << "Starting Redis Testing " << std::endl;
clock_t begin_time = clock();
high_resolution_clock::time_point t1 = high_resolution_clock::now();
**//Person P{10,"John","Cena","Analyst",450000,"Summa"};// Works Fine when object is created in this way**
**Person P;
for (int32_t i = start ; i < range ; ++i)
{
P.orgId = i;
P.firstName = "Gibbi";
P.lastName = "Prakash";
P.resume = "Analyst";
P.salary = 45000;
P.other = "Summa";
_set(i,P);
}
for (int32_t i = start; i < range; ++i)
{
try{
_get(i);
//break;
}catch(cereal::Exception e){
std::cout << "Caught Exception " << std::endl;
}
}
for (int32_t i = start; i < range; ++i)
{
_remove(i);
}
}
When object is created Person P{10,"John","Cena","Analyst",450000,"Summa"}; in this way the program works as expected.
OUTPUT:
Starting Redis Testing
1 Name: John Last: CenaResume: Analyst Salary: 450000 Other: Summa
2 Name: John Last: CenaResume: Analyst Salary: 450000 Other: Summa
No key is matching
No key is matching
when i created object First then assign values
(
Person P; //when object is created first then values are assigned to it.
P.orgId = i;
P.firstName = "Gibbi";
P.lastName = "Prakash";
P.resume = "Analyst";
P.salary = 45000;
P.other = "Summa";
), the output is empty or the client just hangs.
I'm not sure what was happening behind the scenes since i'm very new to using cereal library. I feel the issue is with cereal, but i couldn't figure it.
I have a list of data (in 4 columns) that I would like to sort by a certain column. It was read in from a file to a 2D vector. I the used the std::sort method and wrote my comparator functor. The program compiles and runs, but when I print the first 10 elements it is not sorted, but is certainly different from the order it was added to the 2D vector.
Here is the code:
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
typedef vector<double> Row;
typedef vector<Row> Matrix;
bool sortByFourthColumn(const Row& row1, const Row& row2){
return (double) row1[3] < (double) row2[3];
}
int main(){
std::ifstream infile;
infile.open("Test8_Output.txt");
double x,y,z,E;
char line[200];
int line_count=0;
ofstream outfile;
outfile.open("WO_crp.txt");
if (infile.is_open()){
while (!infile.eof()){
infile.getline(line,170);
if (line[0] != '%'){
outfile<<line<<"\n";
line_count++;
}
else{
}
}
Matrix data(line_count,Row(4));
outfile.close();
std::ifstream myfile;
myfile.open("WO_crp.txt");
int i = 0;
while(myfile >> x >> y >> z >> E){
data[0][i] = x;
data[1][i] = y;
data[2][i] = z;
data[3][i] = E;
i++;
}
myfile.close();
std::sort(data.begin(), data.end(), sortByFourthColumn);
for (int u = 0; u <20; u++){
cout << setprecision(5) << data[0][u] << "\t" << setprecision(5)<< data[1][u] << "\t" << setprecision(5)<< data[2][u] << "\t" << setprecision(5)<< data[3][u] << endl;
}
}
else{
cout << "Error: File is invalid.\n";
}
return(0);
}
EDIT - Sample of what the input file looks like:
EDIT 2 - swapped 4 and line_count in Matrix data(4,Row(line_count));
% Model: CDS_Test8.mph
% Version: COMSOL 5.2.0.220
% Date: Jul 13 2016, 14:33
% Dimension: 3
% Nodes: 86183
% Expressions: 1
% Description: Electric field norm
% Length unit: m
% x y z es.normE (V/m)
0.13774675805195374 0.05012986567931247 0.20735 67.35120820901535
0.13870000000000005 0.04957489750396299 0.20735000000000003 102.8772500513651
0.13870000000000002 0.050800000000000005 0.20735 87.56008679032011
0.13792733849817027 0.050131465727838186 0.20801419247484804 73.55192534768238
0.13674627634411463 0.04992349737428063 0.20735 63.23018910026428
0.13750191177019236 0.0508 0.20735000000000003 67.26176884022838
0.13827743496772454 0.05193409099097887 0.20734999999999998 73.35474409597487
0.13803618792088135 0.05134931748395268 0.20841988134890965 75.3712126982815
0.13905949760011943 0.05141879754884912 0.20734999999999998 83.70739713476813
0.13896970815034013 0.05092428105421264 0.208142746399683 84.73571510992372
0.1390220807917094 0.0501245422629353 0.20817502757007986 85.57119242707628
0.13944867847480893 0.05161480113017738 0.2081969878426443 89.65643851109644
And so on it goes for another 87k lines or so.
I have a list of data (in 4 columns) that I would like to sort by a
certain column.
The problem is that the dimensions of the vector of vectors used to store the data in OP program is not consistent between declaration and use.
A minor problem is the use of while(!infile.eof()){... which should be avoided.
A fixed version is like this:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
#include <iomanip>
using Row = std::array<double,4>; // instead of typedefs
using Matrix = std::vector<Row>;
using std::cout;
bool sortByFourthColumn(const Row& row1, const Row& row2){
return row1[3] < row2[3];
// ^ The cast is unnecessary
}
int main(){
std::string file_name{"Test8_Output.txt"};
std::ifstream infile{file_name, std::ios_base::in};
if ( !infile ) {
cout << "Error: unable to open file " << file_name << '\n';
return EXIT_FAILURE;
}
Matrix data;
data.reserve(90000); // if you are afraid of the reallocations
int count = 0;
std::string line;
// instead of two loops you can use one loop and read the file once
// I'll use std::getline to extract a row in a std::string
while ( std::getline(infile, line) ) {
// skip comments and empty lines
if ( line.empty() || line[0] == '%' )
continue;
++count;
// extract data from the string using a stringstream
std::stringstream ss{line};
Row r;
ss >> r[0] >> r[1] >> r[2] >> r[3];
if ( !ss ) {
cout << "Format error in line " << count << " of file.\n";
break;
}
data.push_back(std::move(r));
}
std::sort(data.begin(), data.end(), sortByFourthColumn);
cout << std::setprecision(5) << std::fixed;
for ( const auto & r : data ) {
for ( auto const &x : r ) {
cout << std::setw(10) << x;
}
cout << '\n';
}
return EXIT_SUCCESS;
}
The output, given the example data is:
0.13675 0.04992 0.20735 63.23019
0.13750 0.05080 0.20735 67.26177
0.13775 0.05013 0.20735 67.35121
0.13828 0.05193 0.20735 73.35474
0.13793 0.05013 0.20801 73.55193
0.13804 0.05135 0.20842 75.37121
0.13906 0.05142 0.20735 83.70740
0.13897 0.05092 0.20814 84.73572
0.13902 0.05012 0.20818 85.57119
0.13870 0.05080 0.20735 87.56009
0.13945 0.05161 0.20820 89.65644
0.13870 0.04957 0.20735 102.87725
I created a vector of vector (10*10000) and try to access this vector through member function. but I got a segmentation fault. I don't know what's wrong here...
Here is Simple.h
class Simple
{
private:
std::vector<double> data_row;
std::vector<std::vector<double> > data;
public:
Simple():data_row(10000), data(10, data_row){};
/*initialize data vector*/
int getSampleCounts(std::istream &File);
/*return number of packet samples in this file*/
Result getModel(std::istream &File);
/*return average and variance of simple delta time*/
void splitData (std::istream &File, const int & sample_in_fold);
};
#endif /* SIMPLE_H */
here is Simple.cpp
void Simple::splitData(std::istream& File, const int & sample_in_fold) {
double value = 0.0;
bool isFailed = true;
int label = 0;
while (File >> value) {
// for each value, generate a label
srand(time(NULL));
label = rand() % 10; // generate label between 0 to 9
while (isFailed) {
// segmentation fault in the next line!
std::cout << "current data size is: " << this->data.size() <<endl;
std::vector<double>::size_type sz = this->data[label].size();
if (sz <= sample_in_fold) {
std::cout << "current size is " << sz << "< samples in fold: " << sample_in_fold << endl;
this->data[label].push_back(value);
std::cout << "push_back succeed!" << endl;
isFailed = false;
} else {
std::cout << "label " << label << "if full. Next label. \n";
srand(time(NULL));
label = rand() % 10;
sz = this->data[label].size();
}
}
}
}
and I'm attaching the main file here.
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // for system())
#include <sys/types.h>
#include <dirent.h>
#include <vector>
#include <limits.h> // for PATH_MAX
#include "Complex.h"
#include "Result.h"
#include "Simple.h"
#include <math.h>
using namespace std;
int main(int argc, char ** argv) {
struct dirent *pDirent;
DIR *pDir;
std::string line;
// check for args
if (argc == 1) {
printf("Usage: ./main + folder name. \n");
return 1;
}
pDir = opendir(argv[1]);
if (pDir == NULL) {
printf("Cannot open directory '%s' \n", argv[1]);
return 1;
}
// readdir returns a pointer to the next direcctory entry dirent structure
while ((pDirent = readdir(pDir)) != NULL) {
// get file name and absolute path
char *name = pDirent->d_name;
char buf[PATH_MAX + 1];
realpath(name, buf);
// std::cout << "Current file is: " << (pDirent->d_name) << endl;
if (has_suffix(pDirent->d_name, ".txt")) {
printf("[%s]\n", pDirent->d_name);
//printf("absolute path is %s. \n", buf);
ifstream infile;
// open file with absolute path
infile.open(buf, ios::in);
if (!infile) {
cerr << "Can't open input file " << buf << endl;
exit(1);
}
//processing for simple pattern
if (has_suffix(name, "testfile.txt")) {
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
Result simplerst = simple_obj->getModel(infile);
std::cout << "Number of delta time is " << number << endl;
infile.clear();
infile.seekg(0);
write_to_file(pDirent->d_name, simplerst);
// divide data into k = 10 folds, get number of data in each fold
int sample_in_fold = floor(number / 10);
std::cout << sample_in_fold << std::endl;
simple_obj->splitData(infile, sample_in_fold);
}
} else {
// printf("This is not a txt file. Continue\n");
}
}
closedir(pDir);
return 0;
}
And here is a sample testfile.txt. I only copied part of the original file, for illustration.
10.145906000
10.151063000
10.131083000
10.143461000
10.131745000
10.151285000
10.147493000
10.123198000
10.144975000
10.144484000
10.138129000
10.131634000
10.144311000
10.157710000
10.138047000
10.122754000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
10.154170000
10.139574000
10.140207000
10.149151000
10.164629000
10.106818000
10.142431000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
Here is Result.h
#ifndef RESULT_H
#define RESULT_H
typedef struct Result {
double average;
double sigma;
}Result;
and getModel function in Simple.cpp:
Result Simple::getModel(std::istream &File) {
double value = 0.0;
double average = 0.0;
double sum = 0.0;
double counter = 0.0;
double sumsqr = 0.0;
double var = 0.0;
double sigma = 0.0;
while (File >> value) {
++counter;
sum += value;
sumsqr += value * value;
}
average = sum / counter;
var = sumsqr / counter - average * average; //E(x^2) - (E(x))^2
sigma = sqrt(var);
std::cout << "average is " << average << std::endl;
std::cout << "std deviation is " << sigma << std::endl;
File.clear();
File.seekg(0);
Result result = {average, sigma};
return result;
}
One issue right away:
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
simple_obj is an uninitialized pointer, thus your program exhibits undefined behavior at this point.
Why use a pointer anyway? You could have simply done this to avoid the issue:
Simple simple_obj;
simple_obj.getSampleCounts(infile);
Also, this line may not be an issue, but I'll mention it anyway:
Result simplerst = simple_obj->getModel(infile);
We already know that in your original code, simple_obj is bogus, but that's not the issue here. If Result is an object, and that object does not have correct copy semantics, then that assignment will also cause undefined behavior.
You've got a couple of uses of endl without specifying std::endl (they're not the same thing - you always have to type the std:: ). Is endl silently referring to another variable somewhere else?
I've been looking at this for a while in the debugger while Googling around, but I think I've stumbled upon some C++ behavior that I'm not familiar with. I'm going to give a quick outline on what I'm doing and what/where the problem is. I'll put code block below.
The rough outline of what's happening is:
Created a custom class (LogReader) to handle a single log file.
LogReader contains a pointer to an ifstream (ifstream *log_file)
The ifstream is used with getline() in the constructor, this works fine.
The LogReader is placed in a vector.
The code below for main.cpp is using the LogReader directly (without the vector). The segfault occurs in both cases.
LogReader.advance() is called. getline() is used in this function. The segfault occurs here (commented in LogReader.cpp).
Thanks for any help on what C++ behaviors I'm missing that might be causing this!
EDIT: Not placing the LogReader into a vector removes the segfault (failing elsewhere now, but not a problem). The change is commenting the following line out in main.cpp
readers.push_back(&label_reader);
I guess now the question is why using std::vector is causing this problem.
LogReader.h
#ifndef LOGREADER
#define LOGREADER
using namespace std;
class LogReader {
private:
LogReader(){} // private default constructor
public:
ifstream *log_file; // file the log is read from
vector<int> val_locations; // offsets in line for values
string next_line; // next line from the file
int current_time; // time for most recent reading
string current_line;
int next_time; // what is the next time in the file
vector<string> current_vals; // what the current vals are
LogReader(string log_loc, vector<int> offsets); // given a file to start on
bool advance(int new_time); // advance the log reader, return true if advanced
bool has_more(); // is there more in the log
};
#endif
LogReader.cpp
// c++ imports
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
using namespace std;
LogReader::LogReader(string log_loc, vector<int> offsets){
// make the file reader
ifstream lf(log_loc);
log_file = &lf;
// pull out the first line
getline(*log_file, current_line);
cout << current_line << endl;
// get the set of current values
val_locations = offsets;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(current_line,
val_locations.at(i)));
}
// get the current time
current_time = stoi(get_line_part(current_line, 0));
// pull down the next line
getline(*log_file, next_line);
cout << next_line << endl;
// get the next time
next_time = stoi(get_line_part(next_line, 0));
}
bool LogReader::advance(int new_time){
if(new_time < next_time)
return false; // nothing to do, current still good
cout << "can check time" << endl;
// update the time and values
current_time = next_time;
current_line = next_line;
current_vals.clear();
cout << "can do housekeeping" << endl;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(next_line,
val_locations.at(i)));
}
cout << "can push in new values" << endl;
// move the line
next_line.clear();
if(!getline(*log_file, next_line)) { // **SEGFAULT**
// no more lines
cout << "no more lines" << endl;
next_line.clear();
next_time = -1;
return true;
}
cout << "got the line" << endl;
// update the time as well
next_time = stoi(get_line_part(next_line, 0));
return true;
}
bool LogReader::has_more(){
return next_time != -1;
}
main.cpp
// c imports
#include <time.h>
// c++ imports
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <boost/date_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
// custom shorter namespaces
namespace bfs = boost::filesystem;
// used namespaces
using namespace std;
void update_line(int *current_time, string *current_line,
ifstream *current_file){
if(!getline(*current_file, *current_line)){
*current_time = -1;
current_line->clear();
return;
}
try {
*current_time = stoi(get_line_part(*current_line, 0));
} catch (int e) {
cout << "update line, bad stoi on time" << endl;
cout << *current_line << endl;
throw e;
}
}
void update_vals(vector<float*> vals, string line) {
for(int i = 0; i < vals.size(); i++) {
// offset for fact that first two are time and sensor
try {
*(vals.at(i)) = stof(get_line_part(line, 2 + i));
} catch (int e) {
cout << "update_vals, bad stof for " << i << endl;
cout << line << endl;
throw e;
}
}
}
string get_correct_file(string name, vector<string> options) {
for(int i =0; i < options.size(); i++) {
string option = options.at(i);
if(boost::algorithm::contains(option, name)){
return option;
}
}
return string("");
}
int main(int argc, char* argv[]) {
// open the base dir
bfs::path base_dir("log/");
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Bad base directory" << endl;
return 1;
}
// create a vector of the possible traces
vector<string> traces;
for(bfs::directory_iterator iter(base_dir);
iter != bfs::directory_iterator(); iter++) {
stringstream trace_path;
trace_path << iter->path().string();
traces.push_back(trace_path.str());
}
int trace_index = user_choose_option(traces);
// load that directory
bfs::path trace_dir(traces.at(trace_index));
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Selected a bad trace directory" << endl;
return 1;
}
// get the image directory
cout << "loading image directory" << endl;
string img_path_string = trace_dir.string();
stringstream img_path_stream;
img_path_stream << img_path_string << "/img/";
bfs::path img_dir(img_path_stream.str());
if(!bfs::exists(img_dir) && !bfs::is_directory(img_dir)){
cout << "no image directory" << endl;
return 1;
}
// get image list, ends up in sorted order from naming conventions
cout << "getting image paths" << endl;
vector<string> image_paths;
for(bfs::directory_iterator iter(img_dir);
iter != bfs::directory_iterator(); iter++) {
stringstream image_path;
image_path << iter->path().string();
image_paths.push_back(image_path.str());
}
// get the data traces
cout << "loading data traces" << endl;
vector<string> log_paths;
vector<string> label_paths;
string trace_path_string = trace_dir.string();
for(bfs::directory_iterator iter(trace_path_string);
iter != bfs::directory_iterator(); iter++) {
string cur_file = iter->path().string();
cout << cur_file << endl;
if(boost::algorithm::contains(cur_file, "label-")) {
label_paths.push_back(cur_file);
} else if(boost::algorithm::contains(cur_file, "log-")) {
log_paths.push_back(cur_file);
}
}
cout << endl;
// temp for reading in line parts
// istringstream temp;
cout << "getting log readers" << endl;
// choose the label file to use, get first line
int label_index = user_choose_option(label_paths);
vector<int> label_offsets;
label_offsets.push_back(1);
LogReader label_reader(label_paths.at(label_index), label_offsets);
/*
ifstream label_file(label_paths.at(label_index));
string label_line;
getline(label_file, label_line);
int label_time;
temp.clear();
temp.str(get_line_part(label_line, 0));
temp >> label_time;
string label_current = get_line_part(label_line, 1);
*/
/*
// get the accel
string accel_path = get_correct_file("accel", log_paths);
vector<int> accel_offsets;
accel_offsets.push_back(2);
accel_offsets.push_back(3);
accel_offsets.push_back(4);
LogReader accel_reader(accel_path, accel_offsets);
*/
vector<LogReader*> readers;
vector<bool> updated;
readers.push_back(&label_reader);
updated.push_back(true);
// readers.push_back(&accel_reader);
// updated.push_back(true);
int l_time = current_time_min(readers);
while(label_reader.has_more() ){ // || accel_reader.has_more()) {
// figure out what time to advance to
int n_time;
cout << label_reader.has_more() << endl;
if(same_current_time(readers)) {
n_time = next_time_min(readers);
} else {
n_time = current_time_nextmin(readers);
}
cout << n_time << endl;
label_reader.advance(n_time);
cout << label_reader.current_line << endl;
/*
// advance all the readers
for(int i = 0; i < readers.size(); i++) {
cout << "loop " << i << endl;
// keep track of which values updated
readers.at(i);
cout << "can get from vector" << endl;
bool advanced = readers.at(i)->advance(n_time);
cout << advanced << endl;
if(advanced) {
updated.at(i) = true;
} else {
updated.at(i) = false;
}
}
// sanity check printing
for(int i = 0; i < readers.size(); i++) {
cout << readers.at(i)->current_line << endl;
}
*/
// deal with statistics here
}
/*
ifstream accel_file(accel_path);
string accel_line;
getline(accel_file, accel_line);
int accel_time;
temp.clear();
temp.str(get_line_part(accel_line, 0));
temp >> accel_time;
float accel_current_x = stof(get_line_part(accel_line, 2));
float accel_current_y = stof(get_line_part(accel_line, 3));
float accel_current_z = stof(get_line_part(accel_line, 4));
vector<float*> accel_vals;
accel_vals.push_back(&accel_current_x);
accel_vals.push_back(&accel_current_y);
accel_vals.push_back(&accel_current_z);
// get the sprox
string sprox_path = get_correct_file("sprox", log_paths);
ifstream sprox_file(sprox_path);
string sprox_line;
getline(sprox_file, sprox_line);
int sprox_time;
temp.clear();
temp.str(get_line_part(sprox_line, 0));
temp >> sprox_time;
float sprox_current = stof(get_line_part(sprox_line, 2));
vector<float*> sprox_vals;
sprox_vals.push_back(&sprox_current);
// get the lprox
string lprox_path = get_correct_file("lprox", log_paths);
ifstream lprox_file(lprox_path);
string lprox_line;
getline(lprox_file, lprox_line);
int lprox_time;
temp.clear();
temp.str(get_line_part(lprox_line, 0));
temp >> lprox_time;
float lprox_current = stof(get_line_part(lprox_line, 2));
vector<float*> lprox_vals;
lprox_vals.push_back(&lprox_current);
// get the light
string light_path = get_correct_file("light", log_paths);
ifstream light_file(light_path);
string light_line;
getline(light_file, light_line);
int light_time;
temp.clear();
temp.str(get_line_part(light_line, 0));
temp >> light_time;
float light_current = stof(get_line_part(light_line, 2));
vector<float*> light_vals;
light_vals.push_back(&light_current);
*/
// int time_current = min(label_time, min(sprox_time,
// min(lprox_time, min(accel_time,
// light_time))));
/*
// variables for processing here
int total_time = 0;
map<string, int> label_counts;
while(label_time != -1 || accel_time != -1 || sprox_time != -1
|| lprox_time != -1 || light_time != -1) {
time_current++;
if(label_time != -1 && time_current > label_time) {
update_line(&label_time, &label_line, &label_file);
if(label_line.size() > 0) // if last label, don't overwrite
label_current = get_line_part(label_line, 1);
}
if(accel_time != -1 && time_current > accel_time) {
update_line(&accel_time, &accel_line, &accel_file);
if(accel_line.size() > 0) // if last line, don't overwrite
update_vals(accel_vals, accel_line);
}
if(sprox_time != -1 && time_current > sprox_time) {
update_line(&sprox_time, &sprox_line, &sprox_file);
if(sprox_line.size() > 0) // if last line, don't overwrite
update_vals(sprox_vals, sprox_line);
}
if(lprox_time != -1 && time_current > lprox_time) {
update_line(&lprox_time, &lprox_line, &lprox_file);
if(lprox_line.size() > 0) // if last line, don't overwrite
update_vals(lprox_vals, lprox_line);
}
if(light_time != -1 && time_current > light_time) {
update_line(&light_time, &light_line, &light_file);
if(light_line.size() > 0) // if last line, don't overwrite
update_vals(light_vals, light_line);
}
// Processing happens here
total_time++;
if(label_counts.count(label_current) == 0)
// not in map
label_counts[label_current] = 0;
label_counts[label_current]++;
}
// post processing happens here
cout << "Labels Counts:" << endl;
for(map<string, int>::iterator it = label_counts.begin();
it != label_counts.end(); it++) {
cout << it->first << " -> " << it->second << " -> ";
cout << 1.0 * it->second / total_time << endl;
}
*/
}
Your program exhibits undefined behavior since you are using a pointer to an object that has been deleted.
ifstream lf(log_loc);
log_file = &lf;
if gets deleted when the constructor returns and you are still holding on to a pointer to the object.
Change log_file to an object instead of a pointer.