I am moving a project from Python to C++, partly in order to achieve a speed up.
This part of the code reads large .txt data files (well only about 2MB per file, but quite a lot of files), and needs to convert the data to floating point.
This C++ code does is not faster than Python bytecode (.pyc). Regardless, my application requires faster processing. What can you see are the main things I am doing wrong?
Below is a complete standalone representative example that will compile with:
cl.exe turtlereader.cpp
(or other compiler I believe)
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <iterator>
class TurtleFileReader {
public:
// pointless constructor for this example
TurtleFileReader(){};
// Turtle read looks for zones in the input file and directs the fileread process.
int TurtleRead() {
std::ifstream readfile;
readfile.open("sampleinput.txt");
// records line we are reading on:
int linenumber = 0;
int data_starts_on_line = 0; // init to 0
// find first zone = line
std::string line;
while (std::getline(readfile, line)) {
linenumber += 1;
if ( line.find("ZONE") < line.size() ) {
std::string num_zones = line.substr( line.find("I=")+2 ,
(line.find_first_of(",") -
(line.find("I=")+2))
);
std::stringstream zone_to_int_ss(num_zones);
int total_z_values = 0;
zone_to_int_ss >> total_z_values;
// at this point, we have come across a zone line in the file. And,
// we know how many data lines to read next.
for (size_t i = 0; i < (total_z_values); ++i) {
std::getline(readfile, line);
linenumber += 1;
int check = ReadOneLine(line, linenumber);
if (check !=0) {
return check;
}
}
}
}
readfile.close();
return 0;
}
private:
// The purpose of this method is to take a line of the file as a string,
// and direct the values to the correct member variable, with checks.
int ReadOneLine(std::string line, int linenumber) {
bool error_found = false;
std::vector<double> vec = LineSplit<double>(line);
if (vec.size() == 9) {
a1_.push_back(vec[0]);
a2_.push_back(vec[1]);
a3_.push_back(vec[2]);
a4_.push_back(vec[3]);
a5_.push_back(vec[3]);
a6_.push_back(vec[4]);
a7_.push_back(vec[5]);
a8_.push_back(vec[6]);
a9_.push_back(vec[5]);
// Do some check on the data here:
if (vec[0] > 10 || vec[0] < 0) {
error_found = true;
}
} else {
std::cout << " * ERROR: Expected 9 data elements" << std::endl;
error_found = true;
}
if (error_found) {
std::cout << " file has possible error on line " << linenumber << std::endl;
return 1;
}
return 0;
}
// this splits a string of values and puts into a vector:
template<typename T>
std::vector<T> LineSplit(const std::string& line) {
std::istringstream is(line);
return std::vector<T>(std::istream_iterator<T>(is), std::istream_iterator<T>());
}
// data storage variables:
std::vector<double> a1_;
std::vector<double> a2_;
std::vector<double> a3_;
std::vector<double> a4_;
std::vector<double> a5_;
std::vector<double> a6_;
std::vector<double> a7_;
std::vector<double> a8_;
std::vector<double> a9_;
};
int main() {
TurtleFileReader tfr;
int check = tfr.TurtleRead();
return check;
}
With this sample text file that has to be named "sampleinput.txt" for this example:
# Turtleread input file example TITLE="DATASET1" VARIABLES="a" "b" "c" "d" "e" "f" "g" "h" "i" ZONE I=2, F=POINT, T="DATASET1a" 1.2 -0.3 0.01 0.01 0.0 0.3 0.3 0.04 10 0.1 -0.3 0.01 0.01 0.0 0.3 0.3 0.04 10 ZONE I=5, F=POINT, T="DATASET1b" 1.2 -0.3 0.01 0.01 0.0 0.3 0.3 1.23 100 0.1 -0.3 0.01 0.01 0.0 0.3 0.3 2.04 100 1.2 -0.3 0.01 0.01 0.0 0.3 0.3 2.04 100 0.1 -0.3 0.01 0.01 0.0 0.3 0.3 2.01 100 0.5 -0.3 0.01 0.01 0.0 0.3 0.3 3.01 100