C - Динамический массив - PullRequest
3 голосов
/ 19 июля 2011

Я пытаюсь передать массив с помощью fscanf (), перебирая файл, содержащий список целых чисел, длиной n целых чисел.Кажется, мне нужно использовать malloc и / или потенциально realloc.Я слышал, что команда malloc занимает заметное количество времени выполнения и что ее лучше перераспределить.Может ли кто-нибудь помочь мне разобраться в основных принципах достижения этой цели?

Отказ от ответственности: Я новичок в C.

Ответы [ 7 ]

7 голосов
/ 19 июля 2011

Нет, то, что вы слышали, вводит в заблуждение (по крайней мере, для меня).malloc - это просто функция, обычно быстрая.

  • Большую часть времени она выполняет всю свою работу в пользовательском пространстве.Он «перераспределяется», поэтому вам не нужно
  • Бухгалтерия (связанный список со свободными блоками и т. Д.) Высоко оптимизирована, поскольку практически все используют malloc

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

6 голосов
/ 19 июля 2011

Чтение файла будет намного медленнее, чем выделение памяти!

Возможно, вы захотите прочитать весь файл и выяснить, сколько нужно энтов, а затем malloc () все за один раз.

таНос (SizeOf (INT) * п)

4 голосов
/ 19 июля 2011

Преждевременная оптимизация - корень всего зла (гугл это).

Тем не менее, выделите любую сумму, которую вы считаете разумной / типичной для поставленной задачи, и удваивайте ее всякий раз, когда вам нужно перераспределить. Эту стратегию довольно сложно победить.

0 голосов
/ 20 июля 2011

Это текстовый файл (не двоичный) и не в фиксированном формате, верно?В противном случае было бы легко вычислить размер массива из размера файла (buffer_size = file_size / record_size, размер буфера в словах (размер целого числа), другие размеры в байтах).

Вот чтоЯ бы сделал (но я немного сумасшедший, когда дело доходит до прикладной статистики).

1) Какое максимальное количество символов (или байтов) число (или запись) будет занимать вфайл, не забудьте включить символы конца строки (CR, NF) и другие пустые глифы (пробелы, табуляции и т. д.)?Если вы уже можете оценить, какой будет средний размер записи, то еще лучше, вы используете это вместо максимального размера.

initial_buffer_size = file_size / max_record_size + 1    (/ is integer division)

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

resize_size = 
   prev_buffer_size
   + bytes_not_read / ( bytes_already_read / number_of_records_already_read ) 
   + 1

3) Считайте в этот буфер (с того места, где закончилось предыдущее чтение), пока он не заполнитсяили все файлы были прочитаны.

4) Если не закончено, повторите с шага 2) с новым prev_buffer_size.

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

0 голосов
/ 19 июля 2011

Вы не хотите звонить malloc или realloc с каждым прочитанным целым числом, это точно. Можете ли вы оценить, сколько места вам понадобится? Вы контролируете формат файла? Если это так, вы можете получить в первой строке файла одно целое число, обозначающее, сколько целых чисел необходимо прочитать из файла. Тогда вы можете выделить все необходимое пространство за один раз. Если вы не управляете форматом и не можете этого сделать, следуйте другой рекомендации, упомянутой в этой теме: выделите буфер разумного размера и удваивайте его каждый раз, когда у вас заканчивается свободное пространство.

0 голосов
/ 19 июля 2011

Обратите внимание, что malloc() добавляет некоторые издержки к каждому выделению для поддержки своих внутренних структур данных (по крайней мере, 4 байта в общих реализациях), поэтому, если целые числа имеют длину 4 байта, выполнение malloc() для каждого целого будет иметь>= 50% накладных расходов (вероятно, 75%).Это было бы эквивалентно использованию массива Integer в Java вместо массива int.

Как сказал @Charles Dowd, гораздо лучше выделить всю память водин раз, чтобы избежать накладных расходов.

0 голосов
/ 19 июля 2011

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

...