WedX - журнал о программировании и компьютерных науках

Проблемы при загрузке информации из файла

Я сомневаюсь. Я пишу код для загрузки информации из файла в память компьютера. Но время, необходимое для этого, сильно различается в зависимости от «формата» файла.

Позвольте мне объяснить лучше. В файле, который я читаю, у меня есть своего рода таблица со случайными строками, разделенными знаком «|». Здесь у вас есть пример таблицы (с 5 строками и 5 столбцами).

Table.txt

0|42sKuG^uM|24465\lHXP|2996fQo\kN|293cvByiV
1|14772cjZ`SN|28704HxDYjzC|6869xXj\nIe|27530EymcTU
2|9041ByZM]I|24371fZKbNk|24085cLKeIW|16945TuuU\Nc
3|16542M[Uz\|13978qMdbyF|6271ait^h|13291_rBZS
4|4032aFqa|13967r^\\`T|27754k]dOTdh|24947]v_uzg

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

Итак, возникает вопрос: Почему на этот раз время такое разное, если размер таблицы тот же???

Здесь у вас есть часть кода, которая считывает эту информацию из файла и сохраняет в компьютере.

Код, считывающий данные из файла Table.txt и сохраняющий их в памяти компьютера

string ruta_base("C:\\a\\Table.txt"); // Folder where my "Table.txt" is found

string temp; // Variable where every row from the Table.txt file will be firstly stored
vector<string> buffer; // Variable where every different row will be stored after separating the different elements by tokens.
vector<ElementSet> RowsCols; // Variable with a class that I have created, that simulated a vector and every vector element is a row of my table (vector<string> buffer)

ifstream ifs(ruta_base.c_str());

while(getline( ifs, temp )) // We will read and store line per line until the end of the ".txt" file. 
{
    size_t tokenPosition = temp.find("|"); // When we find the simbol "|" we will identify different element. So we separate the string temp into tokens that will be stored in vector<string> buffer

    while (tokenPosition != string::npos)
    {    
        string element;
        tokenPosition = temp.find("|");      

        element = temp.substr(0, tokenPosition);
        buffer.push_back(element);
        temp.erase(0, tokenPosition+1);
    }

    ElementSet ss(0,buffer); 
    buffer.clear();
    RowsCols.push_back(ss); // We store all the elements of every row (stores as vector<string> buffer) in a different position in "RowsCols" 
}

vector<Table> TablesDescriptor;

Table TablesStorage(RowsCols);
TablesDescriptor.push_back(TablesStorage);

DataBase database(1, TablesDescriptor);

Здесь я добавляю РЕШЕНИЕ, которое я сделал со всеми вашими отзывами.

string ruta_base("C:\\a\\Table.txt"); // Folder where my "Table.txt" is found

string temp; // Variable where every row from the Table.txt file will be firstly stored
vector<string> buffer; // Variable where every different row will be stored after separating the different elements by tokens.
vector<ElementSet> RowsCols; // Variable with a class that I have created, that simulated a vector and every vector element is a row of my table

ifstream ifs(ruta_base.c_str());

while(getline( ifs, temp )) // We will read and store line per line until the end of the ".txt" file. 
{
       size_t tokenPosition = temp.find("|"); // When we find the simbol "|" we will identify different element. So we separate the string temp into tokens that will be stored in vector<string> buffer

       const char* p = temp.c_str();
      char* p1 = strdup(p);

       char* pch = strtok(p1, "|");
    while(pch)
        {
            buffer.push_back(string(pch));
            pch = strtok(NULL,"|");
        }
        free(p1);

        ElementSet sss(0,buffer);
        buffer.clear();
        RowsCols.push_back(sss);
}

vector<Table> TablesDescriptor;

Table TablesStorage(RowsCols);
TablesDescriptor.push_back(TablesStorage);

DataBase database(1, TablesDescriptor);
c++
28.03.2011

  • Я предполагаю, что 100 000 столбцов и 100 строк быстрее, чем 100 столбцов и 100 000 строк? 28.03.2011
  • @ Том: Нет, все наоборот. 28.03.2011

Ответы:


1

Вы не публикуете реализацию для части кода (например, ElementSet), но даже в том, что мы видим, есть некоторые операции, которые потребляют время, линейно увеличивающееся с длиной текущей строки в файле, например.

temp.erase(0, tokenPosition+1);

Было бы более эффективно не удалять биты с начала строки - это заставляет всю строку из 100 000 полей постоянно копироваться в память, сжимаясь до начала строки. Вместо этого отслеживайте позицию, из которой вы извлекли данные в данный момент, и начните следующий поиск с этого смещения, также используя это смещение для операции substr(). Если вы начнете думать о вещах с точки зрения содержимого памяти, вы научитесь анализировать такого рода проблемы. Также используйте профилировщик, чтобы показать вам, какие строки кода медленные.

28.03.2011
  • Спасибо за Ваш ответ. Я изменил свой код с учетом ваших отзывов. Посмотрите и скажите мне, могу ли я улучшить его еще больше. Теперь время, затрачиваемое на загрузку информации, меньше, но время, затрачиваемое на последующий доступ к информации, хранящейся в памяти компьютера, по-прежнему медленное. На самом деле время загрузки таблиц со 100 000 столбцов и 100 строк меньше (0,325 мин, намного лучше, чем раньше), чем со 100 000 строк и 100 столбцов (1,61198 мин, то же, что и раньше). Но время доступа к некоторым данным лучше во втором случае (в примере 47 секунд против 6079 секунд в первом случае), есть идеи почему?? 29.03.2011
  • Я загрузил код доступа в другой пост, чтобы не смешивать разные темы. Вы можете найти его здесь и попытаться снова помочь мне: код, имитирующий базу данных 2">stackoverflow.com/questions/5479013/ Большое спасибо! :D 30.03.2011

  • 2

    Я считаю, что проблема в операторе temp.erase(0, tokenPosition+1);. Если строка мала (как в первом случае), данных для сдвига не так много, но в последнем случае слишком много данных для сдвига, поэтому он медленнее. Я предлагаю вам попробовать удалить erase и использовать метод find на основе диапазона. Вероятно, вы можете использовать вторую перегруженную версию, указанную здесь. Используйте c_str(), чтобы получить const char* для строки, и добавьте к ней смещение, чтобы указать начальную точку. Кроме того, если вы можете использовать boost, рассмотрите возможность использования Boost.Tokenizer для токенизации строки.

    28.03.2011
  • @Аша. Спасибо большое за вашу помощь. Я смотрел на ссылку, но я не понимаю окончательной идеи, как это сделать. Было бы просто написать temp.find(0, tokenPosition+1); вместо temp.erase(0, tokenPosition+1);? На самом деле, когда я писал эту часть кода, я не совсем понимал оператор стирания. Не могли бы вы помочь мне с этим? Заранее спасибо еще раз! :) 28.03.2011
  • @thomas: Извините, идея, упомянутая в ответе, неверна. Я запутался с параметрами. Вы можете увидеть код для разделения строки здесь: ideone.com/KX0lF 28.03.2011
  • @Аша. Спасибо за Ваш ответ. Я изменил свой код с учетом ваших отзывов. Посмотрите и скажите мне, могу ли я улучшить его еще больше. Теперь время, затрачиваемое на загрузку информации, меньше, но время, затрачиваемое на последующий доступ к информации, хранящейся в памяти компьютера, по-прежнему медленное. На самом деле время загрузки таблиц со 100 000 столбцов и 100 строк меньше (0,325 мин, намного лучше, чем раньше), чем со 100 000 строк и 100 столбцов (1,61198 мин, то же, что и раньше). Но время доступа к некоторым данным лучше во втором случае (в примере 47 секунд против 6079 секунд в первом случае), есть идеи почему?? 29.03.2011
  • @thomas: можете ли вы опубликовать код того, как вы получаете доступ к данным? 29.03.2011
  • @thomas: Также, если вы подозреваете, что создание потока требует времени (для токенизации), вы можете попробовать использовать необработанный strtok API. У меня такой же код: ideone.com/iQav0 29.03.2011
  • @Аша. Еще раз спасибо за помощь, Аша! Я загрузил код доступа в другой пост, чтобы не смешивать разные темы. Вы можете найти его здесь и попытаться помочь мне: stackoverflow.com/questions/5479013/ 30.03.2011

  • 3

    Строковые операции — убийца. Вы стираете уже прочитанную часть строки; каждый раз, когда это происходит, строка должна быть перераспределена и/или перемещена.

    Сохраняйте указатель на строку и избегайте любых операций, которые ее перераспределяют.

    28.03.2011
  • Спасибо за Ваш ответ. Я изменил свой код с учетом ваших отзывов. Посмотрите и скажите мне, могу ли я улучшить его еще больше. Теперь время, затрачиваемое на загрузку информации, меньше, но время, затрачиваемое на последующий доступ к информации, хранящейся в памяти компьютера, по-прежнему медленное. На самом деле время загрузки таблиц со 100 000 столбцов и 100 строк меньше (0,325 мин, намного лучше, чем раньше), чем со 100 000 строк и 100 столбцов (1,61198 мин, то же, что и раньше). Но время доступа к некоторым данным лучше во втором случае (в примере 47 секунд против 6079 секунд в первом случае), есть идеи почему?? 29.03.2011
  • Я загрузил код доступа в другой пост, чтобы не смешивать разные темы. Вы можете найти его здесь и попытаться снова помочь мне: код, имитирующий базу данных 2">stackoverflow.com/questions/5479013/ Большое спасибо! :D 30.03.2011
  • Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

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

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: [email protected]