как спроектировать или выбрать структуры данных на основе различных требований к производительности для проекта на C

#c #arrays #performance #structure

#c #массивы #Производительность #структура

Вопрос:

Я изучаю C самостоятельно, и я хотел бы поработать над небольшим проектом, чтобы улучшить свои навыки в C .

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

  1. Различные виды задач могут запускаться одновременно или последовательно.

  2. Один вид задач может выполняться только по одной за раз.

  3. Задачи выполняются обычно продолжительностью не более 24 часов.

  4. По какой-то причине компьютер, на котором запущена программа, должен перезагружаться во время выполнения задач в течение одного дня. (поэтому приходится записывать данные на диск)

  5. Одна задача может запускаться и останавливаться несколько раз, поэтому time_elapsed накапливается.

Например:

задачи, time_limit (единица времени), time_elapsed (единица времени).

t0, 500, 0

t1, 1000, 700

t2, 700, 700

Как вы видите, проект — это просто таймер. Но я не уверен, как сохранить три параметра в моей программе; У меня есть

  1. строка: имена задач;
  2. целое число: ограничение по времени и
  3. целое число: прошедшее время.

В принципе, существует три варианта проекта, в которых запрашиваются различные способы (ваши предложения) хранения вышеуказанных данных:

  1. общее количество задач составляет 10-100; цикл запуска-остановки и интервал запроса могут составлять минуты, и не требуется память;

  2. общее количество задач равно 10 ^ 100; цикл запуска-остановки и интервал запроса могут составлять миллисекунды и не требуют памяти;

  3. общее количество задач равно 100 !; цикл запуска-остановки и интервал запроса могут составлять миллисекунды и иметь как можно меньший объем памяти.

У меня есть несколько решений:

нуль, у меня просто есть все три переменные в трех примитивных массивах [], файлы чтения / записи при каждом обновлении с помощью индексации на основе положения массива.

во-первых, использование векторов вместо массивов в приведенном выше случае.

во-вторых, с помощью unordered_map задайте task-name в качестве ключа и задайте time_limit, time_elapsed в pair<int, int> качестве значения. при каждом обновлении записи вводите имя задачи (строку), чтобы обновить соответствующее целочисленное значение в паре (C STL).

в-третьих, использование кортежа <string, int, int> для хранения <task_name, time_limit, time_elapsed> соответственно.

в-четвертых, используя массивы C struct, чтобы иметь что-то вроде

 struct {
         string task name;
         int time_limit
         int time_elapsed;};
  

Или любые другие типы структур данных.

Редактировать:

Для запроса структуры данных текущее состояние в любое время должно быть передано некоторым другим объектам класса программы для запуска соответствующих событий (что опущено в этом сообщении), таким образом, считывается список каждого незавершенного (time_elapsed меньше time_limit) task_name задач, прошедшее время и оставшееся времяв качестве входных данных для других объектов класса.

Если так думать, это поможет мне многому научиться.

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

Спасибо

Комментарии:

1. Структура данных выбирается не только для хранения данных, но и для поддержки запросов. В вашем вопросе описано, какие данные вы хотите сохранить. Но в нем не указано, какие запросы вы хотите запускать поверх данных. Поэтому я не могу сказать вам, какая структура является наиболее эффективной.

2. О, вы забыли упомянуть о деревьях B и динамических хэш-таблицах…

3. «как выбрать эффективную структуру данных». как вы определяете эффективность? Похоже, что производительность приложения не является проблемой — время сбора данных составляет минуты. Отпечаток памяти? Стиль кодирования / стоимость обслуживания исходного кода?

4. @DonghuiZhang, большое спасибо за ваш комментарий, я обновил вопрос в разделе РЕДАКТИРОВАНИЯ, включив формат запроса — отображение списка задач и его прошедшего / оставшегося времени.

5. @AdrianColomitchi Я внес некоторые изменения в сообщение на основе вашего комментария; вкратце, учитывается объем памяти, и коллекции могут быть разделены на 10 минут, например. Большое спасибо, что спросили.

Ответ №1:

Итак, проблема в том, что у вас есть коллекция троек {task_name, time_limit, time_elapsed} . Вам часто нужно найти тройку, учитывая ее task_name, чтобы обновить time_elapsed . Вам нужно вставить новые тройки. И когда срок действия задачи истекает (time_elapsed >= time_limt), вы должны удалить ее из коллекции (и, возможно, добавить в другую коллекцию), чтобы иметь возможность печатать задачи, срок действия которых не истек.

Вы могли бы сделать что-то вроде этого:

 #include <set>
#include <string>

struct Task {
  std::string task_name;
  size_t time_limit;
  size_t time_elapsed;
};

struct TaskLess {
  bool operator()(const Taskamp; task1, const Taskamp; task2) {
    return task1.task_name < task2.task_name;
  }
};

std::set<Task, TaskLess> tasks;
  

Чтобы найти / обновить / вставить / удалить задачу, заданную ее task_name, выполняется логарифмический поиск. Для печати задач с истекшим сроком действия необходимо выполнить итерацию по набору.

Вы также могли бы рассмотреть дальнейшие оптимизации: (а) использовать std::unordered_map вместо set ; (б) использовать целое число в качестве ключа задачи вместо строки.

Комментарии:

1. Большое спасибо за ваш ответ! кстати, я снова обновил свой пост, чтобы задать другие требования к времени и пространству. Я бы очень хотел услышать ваш ответ.

Ответ №2:

[«Попадание в движущуюся цель» править]

Приведенный ниже ответ предлагается для сценария 1 — образцы в тысячах или около того.

Примеры в 10 ^ 100 или 100!диапазоны — если у вас нет компьютера размером с мультивселенную, лучше забудьте об этом (количество атомов в нашей наблюдаемой вселенной составляет что-то около 10 ^ 80 — 10 ^ 81). Кроме того, я не думаю, что у вас было бы время накопить такое большое количество выборок, учитывая, что возраст нашей вселенной составляет 13,8 миллиарда лет (что дает величину порядка 10 ^ 20 миллисекунд отсчета с момента Большого взрыва).

По состоянию на 2015 год общий размер данных CERN составляет всего 25 петабайт — это меньше 10 ^ 16.


Исходя из сценария использования (время сбора с интервалом в несколько минут, запрос для незавершенных задач), я бы выбрал ваше четвертое решение, сохраняя эти структуры в a std:vector — количество записей для хранения / обработки не может быть таким большим, поэтому нет необходимости в специальных контейнерах или базе данных (запущено 20 экспериментовмесяц с периодом сбора 10 минут приведет к получению чуть более 3600 записей).

Сторона запроса, стиль C 11, искусственно раздутый код (т. Е. Не Самая компактная форма), чтобы сделать очевидным, что происходит:

 std::vector<MyStruct> allSamples;

// assuming a code that fills allSamples up

// this is a lambda function, used as a predicate
auto unfinishedTest=[](const MyStructamp; s) { 
  return s.time_elapsed < s.time_limit; 
}

auto unfinishedIterator=std::find_if(
  allSamples.begin(), allSamples.end(), // range of lookup
  unfinishedTest // filtering predicate
);

// now you have an iterator which only gives you unfinished tests
while(unfinishedIterator != allSamples.end()) {
  const MySampleamp; unfinishedJobAtHand = *unfinishedIterator;
  // do what you please 
}
  

Ссылки:

Комментарии:

1. Большое спасибо за ваш ответ, особенно за ссылки! кстати, я снова обновил свой пост, чтобы задать другие требования к времени и пространству. Я бы очень хотел услышать ваш ответ.

2. @kaka0512 — «запрашивать разные требования к времени и пространству» ого! Не делайте этого, пожалуйста. Это делает недействительными уже предоставленные ответы — «попадание в движущуюся цель» и все такое. Лучше откройте новый вопрос, ссылающийся на старый.

3. @kaka0512 — обновил мой ответ и исключил ваши второй и третий варианты использования. Я имею в виду… вы действительно хотите рассмотреть эти случаи?