Самый быстрый способ чтения в файле с ++ - PullRequest
0 голосов
/ 11 апреля 2019

Я хотел бы прочитать в файле, подобном этому:

13.3027 29.2191 2.39999
13.3606 29.1612 2.39999
13.3586 29.0953 2.46377
13.4192 29.106 2.37817

В нем более 1mio строк.

Мой текущий код cpp:

loadCloud(const string &filename, PointCloud<PointXYZ> &cloud)
{
    print_info("\nLoad the Cloud .... (this takes some time!!!) \n");
    ifstream fs;
    fs.open(filename.c_str(), ios::binary);
    if (!fs.is_open() || fs.fail())
    {
        PCL_ERROR(" Could not open file '%s'! Error : %s\n", filename.c_str(), strerror(errno));
        fs.close();
        return (false);
    }

    string line;
    vector<string> st;

    while (!fs.eof())
    {
        getline(fs, line);
        // Ignore empty lines
        if (line == "") 
        {
            std::cout << "  this line is empty...." << std::endl;
            continue;
        }

        // Tokenize the line
        boost::trim(line);
        boost::split(st, line, boost::is_any_of("\t\r "), boost::token_compress_on);

        cloud.push_back(PointXYZ(float(atof(st[0].c_str())), float(atof(st[1].c_str())), float(atof(st[2].c_str()))));
    }
    fs.close();
    std::cout<<"    Size of loaded cloud:   " << cloud.size()<<" points" << std::endl;
    cloud.width = uint32_t(cloud.size()); cloud.height = 1; cloud.is_dense = true;
    return (true);
}

Чтение этого файла в настоящее время занимает очень много времени.Я хотел бы ускорить это любые идеи, как это сделать?

Ответы [ 2 ]

2 голосов
/ 11 апреля 2019

Вы можете просто прочитать числа вместо всей строки плюс разбор, если числа всегда входят в наборы из трех.

void readFile(const std::string& fileName)
{
    std::ifstream infile(fileName);

    float vertex[3];
    int coordinateCounter = 0;

    while (infile >> vertex[coordinateCounter])
    {
        coordinateCounter++;
        if (coordinateCounter == 3)
        {
            cloud.push_back(PointXYZ(vertex[0], vertex[1], vertex[2]));
            coordinateCounter = 0;
        }
    }
}
1 голос
/ 11 апреля 2019

Вы используете оптимизированный код?На моей машине ваш код читает миллион значений за 1800 мс.

trim и split, вероятно, занимают большую часть времени.Если в начале строки есть пробел, trim должен скопировать все содержимое строки, чтобы стереть первые символы.split создает новые строковые копии, вы можете оптимизировать это, используя string_view, чтобы избежать копий.

Поскольку ваши разделители являются пробелами, вы можете избежать всех копий с кодом, подобным этому:

bool loadCloud(const string &filename, std::vector<std::array<float, 3>> &cloud)
{
    ifstream fs;
    fs.open(filename.c_str(), ios::binary);
    if (!fs)
    {
        fs.close();
        return false;
    }

    string line;
    vector<string> st;

    while (getline(fs, line))
    {
        // Ignore empty lines
        if (line == "")
        {
            continue;
        }

        const char* first = &line.front();
        const char* last = first + line.length();
        std::array<float, 3> arr;
        for (float& f : arr)
        {
            auto result = std::from_chars(first, last, f);
            if (result.ec != std::errc{})
            {
                return false;
            }
            first = result.ptr;
            while (first != last && isspace(*first))
            {
                first++;
            }
        }
        if (first != last)
        {
            return false;
        }

        cloud.push_back(arr);
    }
    fs.close();
    return true;
}

На моей машине этот код работает за 650 мс.Около 35% времени используется getline, 45% - разбором поплавков, оставшиеся 20% - push_back.

Несколько примечаний:

  1. Я исправил проблему while(!fs.eof()), проверив состояние потока после вызова getline
  2. Я изменил результат на массив, поскольку ваш пример не был mcve поэтому у меня не было определения PointCloud или PointXYZ, вполне возможно, что эти типы являются причиной вашей медлительности.
  3. Если вы знаете количество строк (или хотя бы приблизительное значение) взаранее, затем резервирование размера вектора улучшит производительность
...