файл — C ++ медленное чтение / поиск

В моей программе я читаю файл (здесь только тестовый файл с примерно 200 тысячами точек данных, потом будут миллионы). Теперь я делаю следующее:

for (int i=0;i<n;i++) {
fid.seekg(4,ios_base::cur);
fid.read((char*) &x[i],8);
fid.seekg(8,ios_base::cur);
fid.read((char*) &y[i],8);
fid.seekg(8,ios_base::cur);
fid.read((char*) &z[i],8);
fid.read((char*) &d[i],8);
d[i] = (d[i] - p)/p;
z[i] *= cc;
}

При этом n обозначает количество точек для чтения.

После этого я пишу их снова с

for(int i=0;i<n;i++){
fid.write((char*) &d[i],8);
fid.write((char*) &z[i],8);

temp = (d[i] + 1) * p;
fid.write((char*) &temp,8);
}

При этом запись быстрее, чем чтение. (Время измеряется с помощью clock_t)

Мой вопрос сейчас. Я сделал какую-то довольно глупую ошибку с чтением или можно ожидать такого поведения?

Я использую Win XP с магнитным приводом.

твое magu_

4

Решение

Вы используете seekg слишком часто. Я вижу, что вы используете его для пропуска байтов, но вы также можете прочитать весь буфер и пропустить байты в буфере:

char buffer[52];

for (int i=0;i<n;i++) {
fid.read(buffer, sizeof(buffer));
memcpy(&x[i], &buffer[4], sizeof(x[i]));
memcpy(&y[i], &buffer[20], sizeof(y[i]));
// etc
}

Однако вы можете определить структуру, которая представляет данные в вашем файле:

#pragma pack(push, 1)
struct Item
{
char dummy1[4]; // skip 4 bytes
__int64 x;
char dummy2[8]; // skip 8 bytes
__int64 y;
char dummy3[8]; // skip 8 bytes
__int64 z;
__int64 d;
};
#pragma pack(pop)

затем объявите массив этих структур и прочитайте все данные сразу:

Item* items = new Item[n];
fid.read(items, n * sizeof(Item)); // read all data at once will be amazing fast

(примечание: я не знаю типы x, y, z а также dтак что я предполагаю __int64 Вот)

13

Другие решения

Я лично (по крайней мере) сделал бы это:

for (int i=0;i<n;i++) {
char dummy[8];
fid.read(dummy,4);
fid.read((char*) &x[i],8);
fid.read(dummy,8);
fid.read((char*) &y[i],8);
fid.read(dummy,8);
fid.read((char*) &z[i],8);
fid.read((char*) &d[i],8);
d[i] = (d[i] - p)/p;
z[i] *= cc;
}

Выполнение структуры или чтение большого количества данных за один раз (скажем, добавление второго слоя, где вы читаете 4 КБ за раз, а затем использование пары функций, которые «пропускают» и «выбирают» различные поля, будут немного больше работы, но, вероятно, гораздо быстрее).

Другой вариант заключается в использовании mmap в Linux или MapViewOfFile в винде. Этот метод уменьшает накладные расходы при чтении файла на небольшую часть, поскольку для передачи данных в приложение требуется еще одна копия.

Изменить: я должен добавить «Убедитесь, что вы проводите сравнительные измерения», и если ваше приложение предназначено для работы на многих машинах, убедитесь, что вы делаете измерения на нескольких типах машин, с различными альтернативами дисковода, процессора и памяти. Вы действительно не хотите настраивать код так, чтобы он работал на 50% быстрее на вашей машине, но на 25% медленнее на другой машине.

4

Операторы assert () являются наиболее важной частью этого кода, так что если ваша платформа когда-либо изменится и изменится ширина ваших собственных типов, тогда утверждения не будут выполнены. Вместо того, чтобы искать, я читал в пустую область. Переменные p * облегчают чтение кода, IMO.

assert(sizeof x[0] == 8);
assert(sizeof y[0] == 8);
assert(sizeof z[0] == 8);
assert(sizeof d[0] == 8);

for (int i=0;i<n;i++) {
char unused[8];
char * px = (char *) &x[i];
char * py = (char *) &y[i];
char * pz = (char *) &z[i];
char * pd = (char *) &d[i];

fid.read(unused, 4);
fid.read(px, 8);
fid.read(unused, 8);
fid.read(py, 8);
fid.read(unused, 8);
fid.read(pz, 8);
fid.read(pd, 8);

d[i] = (d[i] - p)/p;
z[i] *= cc;
}
1
По вопросам рекламы [email protected]