чтение из istringstream медленнее, чем ifstream - PullRequest
0 голосов
/ 17 октября 2018

Я пытаюсь прочитать файл облака точек (PTX).Для этого я попробовал 2 решения:

Первое: Самый простой способ.std::ifstream и getline(...), пока я могу читать.
Второй: я все читаю и помещаю все в std::istringstream, затем читаю из этого, используя operator >>.
Поскольку я помещаю все в память с помощьюВторой метод, я считал, что чтение с него будет быстрее, но нет.
В среднем: 45 секунд для метода № 1 и 49 для номера 2.

Вот мои коды:
Метод 1:

std::istringstream getLine(std::ifstream& file) {
    std::string line;
    std::getline(file, line);
    return std::istringstream{ line };
}

void readPoint(std::ifstream& file, TinyPTX& tptx) {
    std::vector<PointPTX> ptxPoints(tptx.numPoints);

    size_t num_pts_to_remove = 0;
    tptx.asCol = true;
    for (int i = 0; i < tptx.numPoints; ++i) {
        float x, y, z, intens;
        uint8_t r, g, b;
        getLine(file) >> x >> y >> z >> intens >> r >> g >> b;
        PointPTX& _pptx = tptx.cloud->points[i - num_pts_to_remove];
        if (!isZero(x, 10e-4) || !isZero(y, 10e-4) || !isZero(z, 10e-4)) {
            _pptx.x = x;  _pptx.y = y; _pptx.z = z; _pptx.intensity = intens;
            _pptx.r = r;
            _pptx.g = g;
            _pptx.b = b;
        }
        else
            num_pts_to_remove++;
    }
    tptx.numPoints -= num_pts_to_remove;
    tptx.cloud->points.resize(tptx.numPoints);
}

Метод 2:

bool readPoint(std::istringstream& str, TinyPTX& tptx, std::streamsize& size) {
    std::vector<PointPTX> ptxPoints(tptx.numPoints);

    size_t num_pts_to_remove = 0;
    for (int i = 0; i < tptx.numPoints; ++i) {
        float x, y, z, intens;
        int r, g, b;
        str >> x >> y >> z >> intens >> r >> g >> b;
        PointPTX& _pptx = tptx.cloud->points[i - num_pts_to_remove];
        if (!isZero(x, 10e-4) || !isZero(y, 10e-4) || !isZero(z, 10e-4)) {
            _pptx.x = x;  _pptx.y = y; _pptx.z = z; _pptx.intensity = intens;
            _pptx.r = r;
            _pptx.g = g;
            _pptx.b = b;
        }
        else
            num_pts_to_remove++;
    }
    tptx.numPoints -= num_pts_to_remove;
    tptx.cloud->points.resize(tptx.numPoints);

    int pos = str.tellg();
    std::cout << pos << " " << size;
    return pos > size - 10 ;//Used to know if we're at the end of the file. 
}

Мой вопрос: почему версия, в которой я помещаю все в память, медленнее, чем другая?Я что-то упускаю?Я делаю не так?

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Первый метод медленнее!

Я запустил ваш код на коротком примере (20 тыс. Строк), и я наблюдал следующие исполнения:

  • Первый метод:
    • 1004 мс всего
    • 1004 мс в методе readPoint
    • 553 мс в методе std :: getline (внутри метода readPoint)
  • второй метод:
    • 101 мс всего
    • 56 мс в методе readPoint.
    • 54 мс в методе ifstream :: rdbuf (внеметод readPoint)

Конечно, мне пришлось написать код, который читает файл, и поместить его в istringstream во втором случае, и производительность второго метода действительно зависит откак вы создали свой istringstream.

Я подозреваю, что часть вашей проблемы не в коде, который вы здесь показываете.

Почему это так?

Основная причина, по которой первый метод намного медленнее, заключается в том, что Максим Егорушкин объяснил вам здесь .

Но даже если вы сэкономите всю эту ненужную упаковку, которую вы делаете, это так или иначе, потому что операции с файлами буферизуются, и один вызов ifstream :: rdbuf быстрее, чем множественный вызов >> opreator.

К сожалению, этот второй метод станет очень медленным, если по какой-то причине вам не хватит памяти.

Используя код, предложенный Максимом Егорушкиным, у меня были такие результаты:

  • 310 мс всего
  • 305 мс в методе readPoint

С уважением,

0 голосов
/ 17 октября 2018

Есть ли что-то, чего мне не хватает?Я делаю неправильно?

Имеет смысл создавать промежуточные значения std::istringstream для каждой строки, если вы хотите игнорировать остальную часть строки.

Если все строкисодержат только эти 7 значений, которые вы можете прочитать непосредственно из std::istream& file (вместо std::ifstream& file).Т.е. изменить:

getLine(file) >> x >> y >> z >> intens >> r >> g >> b;

на:

file >> x >> y >> z >> intens >> r >> g >> b;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...