В моей программе я читаю файл (здесь только тестовый файл с примерно 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_
Вы используете 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
Вот)
Я лично (по крайней мере) сделал бы это:
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% медленнее на другой машине.
Операторы 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;
}