2015-11-26 6 views
5

Обзор: после нескольких дней исследований я не смог найти быстрый и эффективный способ записи/чтения вектора в/из файла. Большинство ответов, которые я видел, связаны с нажатием/выводом каждого отдельного элемента в/из файла. Это невероятно много времени, поскольку количество элементов увеличивается. Кроме того, я не смог найти попытку ответить на мою конкретную проблему. Поэтому, пожалуйста, убедитесь, что ваше решение будет работать для моего конкретного обстоятельства (т.е. прочитайте весь вопрос).Эффективный способ чтения/записи векторов в файл

Моя проблема: у меня очень большая структура данных, содержащая пиксельные данные об изображениях. Есть 60 000 изображений с 784 пикселами каждый. Каждое изображение представляет собой изображение рукописной цифры. Таким образом, в дополнение к 60 000 * 784 пикселям, мне нужно включить ярлык, чтобы я знал, какую цифру представляет изображение. Ярлык, который я использую, который необходим при просмотре в рамках всего проекта, представляет собой вектор из 10 возможностей, представляющий 0, 1, 2 ... 9, только один из которых содержит '1'/' true ', а остальные -' 0 '/' false '. Кроме того, эта структура данных из-за требований к линейной алгебре во всей остальной части проекта требует, чтобы информация хранилась в структуре «Col», используемой в Библиотеке линейных алгебр Армадилло. Итак, структура, которую я хочу сохранить/прочитать в/из файла, объявляется как std::vector<std::vector<arma::Col<double>>>.

Вот функция, которую я использую, чтобы сохранить данные прямо сейчас, чтобы дать контекст:

void SaveTrainingData(vector<vector<Col<double>>> trainingData) //format: trainingData[60000][2][784, 10] 
{ 
    ofstream ofile("VectorizedTrainingData.dat", ios::binary); 

    for (int i = 0; i < trainingData.size(); i++) 
     for (int j = 0; j < trainingData[i].size(); j++) 
      for (int k = 0; k < trainingData[i][j].size(); k++) 
       ofile.write((char *)&trainingData[i][j][k], sizeof(double)); 
} 

Если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь спрашивать! Заранее спасибо.

+0

'void SaveTrainingData (вектор <вектор >> trainingData)' Если вы не передали вектор по значению, вещи могли бы ускориться только в вызове функции. Кроме того, выполняете ли вы это с включенными оптимизациями или «отлаживаете» неоптимизированную версию вашей программы? Кроме того, обратите внимание, что дисковый ввод-вывод - это сложная задача для оптимизации в некоторых отношениях, поскольку многие из них сводятся к производительности диска. – PaulMcKenzie

ответ

0

мне пришлось искать документацию по этой библиотеке Armadillo, но это, кажется как Col - смежный, плотный векторный класс. Мы можем зависеть от непрерывного представления для устранения вложенного цикла, например, так:

// format: trainingData[60000][2][784, 10] 
void SaveTrainingData(const vector<vector<Col<double>>>& trainingData) 
{ 
    ofstream ofile("VectorizedTrainingData.dat", ios::binary); 

    const int numImages = trainingData.size(); 
    for (int i = 0; i < numImages; i++) 
    { 
     const vector<Col<double>>& img = trainingData[i]; 
     const int numCols = img.size(); 
     for (int j = 0; j < numCols; j++) 
     { 
      const Col<double>& col = img[j]; 
      ofile.write((char*)&col[0], col.size()*sizeof(double)); 
     } 
    } 
} 

Уменьшение частоты при обращении к write из одного элемента в столбце весь столбец уже может немного помочь.

Возможно, стоит измерить это, чтобы убедиться, что на самом деле вы больше привязываетесь к вводу-выводу, а не к памяти. Это немного сложно с фрагментацией потенциальной памяти, включающей все эти векторы векторов столбцов.

Если размер внутреннего вектора всегда один и тот же (что похоже на случай, когда каждое изображение составляет 784 пикселя), например, вы можете получить потенциально лучшие результаты с смежным vector<Col>, или это:

struct Image 
{ 
    Col pixels[768]; 
}; 
... 
vector<Image> trainingData; 

... или что-то в этом роде. , Я не мог полностью следовать тому, как линейная алгебра связана с изображением rep, но, надеюсь, это дает идею.

+0

Большое спасибо! Это, безусловно, поможет мне многое. И материал линейной алгебры позже связывается с остальной частью проекта, поэтому здесь это не очень важно, просто необходимо для остальной части программы. – Rob

+0

Есть ли у вас дополнительный вход, когда дело доходит до чтения файла? – Rob

+0

@Rob Чтение должно быть довольно симметричным с записью - вы можете сделать почти то же самое. Не думайте, что есть что-то дополнительное, что мы могли бы сделать там - почти прямое ввод-вывод двоичных данных. –

0

Я не использовал Армадилло, но так как Col матрица 1xN и которые должны быть сохранены линейно, вы можете избавиться от петли k и выписывать всю колонну на одном дыхании:

ofile.write((char *)&trainingData[i][j][0], sizeof(double) * trainingData[i][j].size()); 

Если это не сработает, скопируйте элементы из Col в локальный вектор, затем напишите их в файл (так как операция файла будет намного медленнее, чем копирование некоторых удвоений).

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

+0

Спасибо! Я попробую это! Кроме того, я обычно пишу размер вектора в файл перед элементами, но на этот раз, чтобы устранить как можно больше ненужных данных (так как я знаю размеры всех векторов раньше времени), я удалил его , – Rob

Смежные вопросы