Почему бы не объединить random.uniform со списком?
>>> def random_floats(low, high, size):
... return [random.uniform(low, high) for _ in xrange(size)]
...
>>> random_floats(0.5, 2.8, 5)
[2.366910411506704, 1.878800401620107, 1.0145196974227986, 2.332600336488709, 1.945869474662082]
Стек является памятью, отложенной как пространство царапины для потока выполнения. Когда функция вызвана, блок резервируется на вершине стека для локальных переменных и некоторых бухгалтерских данных. Когда та функция возвращается, блок становится неиспользованным и может использоваться в следующий раз, когда функция вызвана. Стек всегда резервируется в LIFO (метод "последним пришел - первым вышел") порядок; последний раз зарезервированный блок всегда является следующим блоком, который будет освобожден. Это делает действительно простым отслеживать стек; освобождение блока от стека является не чем иным как корректировкой одного указателя.
"куча" является памятью, отложенной для динамического выделения. В отличие от стека, нет никакого вынужденного шаблона к выделению и освобождению блоков от "кучи"; можно выделить блок в любое время и освободить его в любое время. Это делает это намного более сложным для отслеживания, которых части "кучи" выделяются или свободны в любой момент времени; существует много пользовательских средств выделения "кучи", доступных для настройки производительности "кучи" для различных шаблонов использования.
Каждый поток получает стек, в то время как существует обычно только одна "куча" для приложения (хотя это не редко, чтобы иметь несколько "кучи" для различных типов выделения).
Для ответа на вопросы непосредственно:
, До какой степени ими управляют время выполнения языка или ОС?
ОС выделяет стек для каждого потока системного уровня, когда поток создается. Обычно ОС называет время выполнения языка для выделения "кучи" для приложения.
, Каков их объем?
стек присоединен к потоку, поэтому когда поток выходит, стек исправлен. "Куча" обычно выделяется при запуске приложения временем выполнения и исправлена, когда приложение (технически процесс) выходит.
, Что определяет размер каждого из них?
размер стека установлен, когда поток создается. Размер "кучи" установлен на запуске приложения, но может вырасти, поскольку пространство необходимо (средство выделения запрашивает больше памяти от операционной системы).
, Что делает один быстрее?
стек быстрее, потому что схема доступа делает его тривиальным, чтобы выделить и освободить память от него (указатель/целое число просто увеличен или постепенно уменьшен), в то время как "куче" вовлекли намного более сложную бухгалтерию в выделение или освобождение. Кроме того, каждый байт в стеке имеет тенденцию снова использоваться очень часто, что означает, что он имеет тенденцию быть отображенным на кэше процессора, делая его очень быстро. Другой хит производительности для "кучи" состоит в том, что "куча", будучи главным образом глобальным ресурсом, обычно должна быть безопасной многопоточностью, т.е. каждое выделение, и освобождение должно быть - обычно - синхронизировался со "всеми" другими доступами "кучи" в программе.
А очищают демонстрацию:
Источник изображения: vikashazrati.wordpress.com
Стек является частью памяти, которой можно управлять с помощью нескольких ключевых инструкций по ассемблеру, таких как 'поп' (удалите и возвратите значение от стека), и 'нажатие' (продвиньте значение к стеку), но также и вызов (назовите подпрограмму - это продвигает адрес возвращаться к стеку) и возврат (возврат из подпрограммы - это выталкивает адрес прочь стека и переходов к нему). Это - регион памяти ниже регистра указателя вершины стека, который может быть установлен по мере необходимости. Стек также используется для передающих аргументов подпрограммам, и также для сохранения значений в регистрах перед называнием подпрограмм.
"куча" является частью памяти, которая дана приложению операционной системой, обычно через syscall как malloc. На современных Ose эта память является рядом страниц, к которым только обработка вызовов имеет доступ.
размер стека определяется во времени выполнения и обычно не растет после запусков программы. В программе C стек должен быть достаточно большим для содержания каждой переменной, объявленной в каждой функции. "Куча" вырастет динамично по мере необходимости, но ОС в конечном счете выполняет вызов (это будет часто выращивать "кучу" больше, чем значение, которое требует malloc, так, чтобы по крайней мере некоторое будущее mallocs не должно было возвращаться к ядру для получения большей памяти. Это поведение часто настраиваемо)
, поскольку Вы выделили стек прежде, чем запустить программу, Вам никогда не нужно к malloc, прежде чем можно будет использовать стек, таким образом, это - небольшое преимущество там. На практике очень трудно предсказать то, что будет быстро и что будет медленным в современных операционных системах, которые имеют подсистемы виртуальной памяти, потому что то, как страницы реализованы и где они хранятся, является деталью реализации.
Стек:
"куча":
delete
, delete[]
, или free
. new
или malloc
соответственно. Пример:
int foo()
{
char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
bool b = true; // Allocated on the stack.
if(b)
{
//Create 500 bytes on the stack
char buffer[500];
//Create 500 bytes on the heap
pBuffer = new char[500];
}//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
Стек , Когда Вы вызываете функцию, аргументы той функции плюс некоторые другие издержки помещаются на стек. Некоторая информация (такой как, где пойти на возврат) также хранится там. Когда Вы объявляете переменную в своей функции, та переменная также выделяется на стеке.
Освобождение стека довольно просто, потому что Вы всегда освобождаете в обратном порядке, в котором Вы выделяете. Материал стека добавляется, поскольку Вы вводите функции, соответствующие данные удалены, поскольку Вы выходите из них. Это означает, что Вы склонны оставаться в небольшом регионе стека, если Вы не вызываете много функций, которые вызывают много других функций (или создают рекурсивное решение).
"куча" "куча" является родовым названием для того, куда Вы помещаете данные, которые Вы создаете на лету. Если Вы не будете знать, сколько космических кораблей Ваша программа собирается создать, Вы, вероятно, будете использовать новое (или malloc или эквивалентный) оператор для создания каждого космического корабля. Это выделение собирается слоняться поблизости некоторое время, таким образом, вероятно, что мы освободим вещи в другом порядке, чем мы создали их.
Таким образом, "куча" намного более сложна, потому что заканчивают тем, что были регионы памяти, которые являются не использованы чередованный с блоками, которые являются - память фрагментируется. Нахождение свободной памяти размера, в котором Вы нуждаетесь, является трудной проблемой. Поэтому "кучи" нужно избежать (хотя она все еще часто используется).
Реализация Реализация и стека и "кучи" обычно до времени выполнения / ОС. Часто игры и другие приложения, которые являются очень важной производительностью, создают свои собственные решения для памяти, которые захватывают большой блок памяти от "кучи" и затем подают ее внутренне, чтобы не полагаться на ОС для памяти.
Это только практично, если Ваше использование памяти очень отличается от нормы - т.е. для игр, где Вы загружаете уровень в одной огромной операции и можете выбросить всех в другой огромной операции.
Физическое местоположение в памяти Это менее релевантно, чем Вы думаете из-за технологии, названной Виртуальная память , который заставляет Вашу программу думать, что у Вас есть доступ к определенному адресу, где физические данные где-то в другом месте (даже на жестком диске!). Адреса, которые Вы получаете для стека, находятся в увеличивающемся порядке, поскольку Ваше дерево вызова становится глубже. Адреса для "кучи" непредсказуемы (т.е. конкретная реализация) и откровенно не важные.
Другие ответили на широкие штрихи вполне прилично, таким образом, я добавлю несколько деталей.
Стек и "куча" не должны быть исключительными. Общая ситуация, в которой у Вас есть больше чем один стек, состоит в том, если у Вас есть больше чем один поток в процессе. В этом случае каждый поток имеет свой собственный стек. У Вас может также быть больше чем одна "куча", например, некоторые конфигурации DLL могут привести к другому DLLs, выделяющему от различной "кучи", который является, почему это обычно - плохая идея освободить память, выделенную другой библиотекой.
В C можно извлечь пользу из выделения переменной длины с помощью alloca, который выделяет на стеке, в противоположность выделению, которое выделяет на "куче". Эта память не переживет Ваш оператор возврата, но это полезно для буфера царапины.
Создание огромного временного буфера в Windows, из которого Вы не используете большую часть из, не является бесплатным. Это вызвано тем, что компилятор генерирует цикл датчика стека, который называют каждый раз, когда Ваша функция вводится, чтобы удостовериться, что стек существует (потому что Windows использует единственную защитную страницу в конце Вашего стека для обнаружения, когда это должно вырастить стек. При доступе к памяти больше чем одна страница от конца стека, Вы откажете). Пример:
void myfunction()
{
char big[10000000];
// Do something that only uses for first 1K of big 99% of the time.
}
Я думаю, что многие другие люди дали Вам главным образом корректные ответы по этому вопросу.
Одна деталь, которая была пропущена, однако, то, что "кучу" нужно на самом деле, вероятно, назвать "свободным хранилищем". Причина этого различия состоит в том, что исходное свободное хранилище было реализовано со структурой данных, известной как "биномиальная "куча"". По этой причине выделение от ранних реализаций malloc () / свободный () было выделением от "кучи". Однако в этот современный день, самые свободные хранилища реализованы с очень тщательно продуманными структурами данных, которые не являются биномиальной "кучей".
Другие непосредственно ответили на Ваш вопрос, но при попытке понять стек и "кучу", я думаю, что полезно рассмотреть расположение памяти традиционного процесса UNIX (без потоков и mmap()
- базирующиеся средства выделения). веб-страница Глоссария управления памятью имеет схему этого расположения памяти.
стек и "куча" традиционно расположены в противоположных концах виртуального адресного пространства процесса. Стек растет автоматически при доступе, до размера, установленного ядром (который может быть скорректирован с setrlimit(RLIMIT_STACK, ...)
). "Куча" растет, когда средство выделения памяти вызывает brk()
или sbrk()
системный вызов, отображая больше страниц физической памяти в виртуальное адресное пространство процесса.
В системах без виртуальной памяти, таких как некоторые встроенные системы, тот же базовый макет часто применяется, кроме стека и "кучи" фиксируются в размере. Однако в других встроенных системах (таких как те, которые на основе Микрочипа микроконтроллерами PIC), стопка программы является отдельным блоком памяти, которая не адресуема инструкциями по перемещению данных, и может только быть изменена или считана косвенно через инструкции по процессу выполнения программы (вызов, возвратитесь, и т.д.). Другая архитектура, такая как процессоры Intel Itanium, имеет несколько стеков . В этом смысле стек является элементом архитектуры ЦП.
Просто, стек - то, где локальные переменные создаются. Кроме того, каждый раз Вы называете подпрограмму счетчиком команд (указатель на следующую машинную команду) и любые важные регистры, и иногда параметры спешатся стек. Тогда любые локальные переменные в подпрограмме продвигаются на стек (и используются оттуда). Когда подпрограмма заканчивается, тот материал, все выталкивается, замедляет стек. Данные ПК и регистра добираются и отложенный, где это было, поскольку это выталкивается, таким образом, Ваша программа может продолжить свой веселый путь.
"куча" является областью динамических выделений памяти памяти, сделаны из (явный "новый", или "выделите" вызовы). Это - специальная структура данных, которая может отслеживать блоки памяти переменных размеров и их состояния выделения.
В "классической" системной RAM был размечен таким образом, что указатель вершины стека начался у основания памяти, указатель "кучи", начатый наверху, и они выросли друг к другу. Если они накладываются, Вы вне RAM. Это не работает с современными многопоточными Ose все же. Каждый поток должен иметь свой собственный стек, и они могут быть созданы динамично.
Можно сделать некоторые интересные вещи со стеком. Например, у Вас есть функции как alloca (предполагающий, что можно закончить обильные предупреждения относительно его использования), который является формой malloc, который конкретно использует стек, не "кучу", для памяти.
Тем не менее стековые ошибки памяти являются некоторыми худшими, которые я испытал. Если Вы используете память "кучи", и Вы переступаете через границы своего выделенного блока, у Вас есть достойный шанс инициирования отказа сегментов. (Не 100%: Ваш блок может быть случайно непрерывным с другим, что Вы ранее выделили.), Но так как переменные, созданные на стеке, всегда непрерывны друг с другом, писание за пределы может изменить значение другой переменной. Я узнал, что каждый раз, когда я чувствую, что моя программа прекратила подчиняться законам логики, это - вероятно, переполнение буфера.
Наиболее важный момент - то, что "куча" и стек являются общими обозначениями для путей, которыми может быть выделена память. Они могут быть реализованы по-разному, и условия относятся к фундаментальным понятиям.
В стопке объектов, объекты находятся один сверху другого в порядке, они были размещены туда, и можно только удалить лучший (не сваливая все это).
простота стека - то, что Вы не должны поддерживать таблицу, содержащую запись каждого раздела выделенной памяти; единственной информацией состояния, в которой Вы нуждаетесь, является единственный указатель до конца стека. Чтобы выделить и освободить, Вы просто увеличиваете и постепенно уменьшаете тот единственный указатель.Примечание: стек может иногда реализовываться, чтобы запуститься наверху раздела памяти и расшириться вниз вместо того, чтобы расти вверх.
В "куче", нет никакого особого порядка к способу, которым помещаются объекты. Можно достигнуть в и удалить объекты в любом порядке, потому что нет никакого ясного 'главного' объекта.
выделение "кучи" требует поддержания полного отчета того, какая память выделяется и что не, а также некоторое служебное обслуживание, чтобы уменьшить фрагментацию, найти непрерывные сегменты памяти достаточно большими для установки требуемому размеру, и так далее. Память может быть освобождена в любое время, оставив свободное пространство. Иногда средство выделения памяти будет выполнять задачи обслуживания, такие как дефрагментирующаяся память путем перемещения выделенной памяти или сборки "мусора" - определяющий во времени выполнения, когда память больше не будет в объеме и освобождении его.
Эти изображения должны сделать довольно хорошее задание описания двух способов выделить и освободить память в стеке и "куче". Конфетка!
, До какой степени ими управляют время выполнения языка или ОС?
, Как упомянуто, "куча" и стек являются общими терминами и могут быть реализованы во многих отношениях. Компьютерные программы обычно имеют стек, названный стек вызовов , который хранит информацию, относящуюся к текущей функции, такой как указатель на то, какой бы ни функционируют, от этого назвали, и любые локальные переменные. Поскольку функции вызывают другие функции и затем возвращаются, стек растет и уменьшается для содержания информации от функций далее вниз стек вызовов. Программа действительно не имеет контроля во время выполнения над ним; это определяется языком программирования, ОС и даже архитектурой системы.
"куча" А является общим термином, использованным для любой памяти, которая выделяется динамично и случайным образом; т.е. не в порядке. Память обычно выделяется ОС с приложением, называя API-функции, чтобы сделать это выделение. Существует немного издержек, требуемых в управлении динамично выделенной памятью, которая обычно обрабатывается ОС.
, Каков их объем?
стек вызовов является таким низкоуровневым понятием, которое он не связывает с 'объемом' в смысле программирования. При разборке некоторого кода, Вы будете видеть относительные ссылки стиля указателя на части стека, но насколько высокоуровневый язык затронут, язык навязывает свои собственные правления объема. Один важный аспект стека, однако, то, что, как только функция возвращается, что-либо локальное для той функции сразу освобождено от стека. Это прокладывает себе путь, Вы ожидали бы, что это будет работать данное, как работают Ваши языки программирования. В "куче" также трудно определить. Объем - то, что представлено ОС, но Ваш язык программирования, вероятно, добавляет свои правила о том, что "объем" находится в Вашем приложении. Архитектура процессора и ОС используют виртуальное обращение, которое процессор переводит в физические адреса и и т.д. существуют отсутствия страницы. Они отслеживают то, какие страницы принадлежат который приложения. Никогда действительно необходимо волноваться об этом, тем не менее, потому что Вы просто используете любой метод Ваше использование языка программирования, чтобы выделить и свободная память и проверить ошибки (если выделение/освобождение перестало работать по какой-либо причине).
, Что определяет размер каждого из них?
Снова, это зависит от языка, компилятора, операционной системы и архитектуры. Стек обычно предварительно выделяется, потому что по определению это должна быть непрерывная память (больше на этом в последнем абзаце). Языковой компилятор или ОС определяют свой размер. Вы не храните огромные блоки данных по стеку, таким образом, это будет достаточно большим, что это никогда не должно полностью использоваться, кроме случаев нежелательной бесконечной рекурсии (следовательно, "переполнение стека") или другие необычные решения программирования.
"куча" А является общим термином для чего-либо, что может быть динамично выделено. В зависимости от которого пути Вы смотрите на него, это постоянно изменяет размер. В современных процессорах и операционных системах точным путем это работает, очень абстрактно так или иначе, таким образом, Вы не должны обычно волноваться очень о том, как это работает в глубине души, за исключением того, что (на языках, где это позволяет Вам) Вы не должны использовать память, которую Вы еще не выделили или память, которую Вы освободили.
, Что делает один быстрее?
стек быстрее, потому что вся свободная память всегда непрерывна. Никакой список не должен вестись всех сегментов свободной памяти, просто единственный указатель на текущую вершину стека. Компиляторы обычно хранят этот указатель в специальном предложении, быстром регистр с этой целью. Кроме того, последующие операции на стеке обычно концентрируются в очень соседних областях памяти, которая на очень низком уровне хороша для оптимизации процессором на - умирают кэши.
От WikiAnwser.
Когда функция или вызовы метода, другая функция, которая по очереди вызывает другую функцию, и т.д., выполнение всех тех функций, остается приостановленной до самой последней функции, возвращает свое значение.
Эта цепочка приостановленных вызовов функции является стеком, потому что элементы в стеке (вызовы функции) зависят друг от друга.
Стек важен для рассмотрения в выполнении потока и обработке исключений.
"Куча" является просто памятью, используемой программами для хранения переменных. Элемент "кучи" (переменные) не имеет никаких зависимостей друг с другом и может всегда получаться доступ случайным образом в любое время.
(Я переместил этот ответ из другого вопроса, который был более или менее похож на этот.)
Ответ на ваш вопрос зависит от реализации и может варьироваться в зависимости от компилятора и архитектуры процессора. . Однако здесь приводится упрощенное объяснение.
new
или malloc
) выполняются путем создания подходящего блока из одного из свободных блоков. Это требует обновления списка блоков в куче. Эта метаинформация о блоках в куче также сохраняется в куче, часто в небольшой области прямо перед каждым блоком. Можно ли выделить функцию в куче, а не в стеке?
Нет, записи активации для функций (т. Е. локальные или автоматические переменные) выделяются в стеке, который используется не только для хранения этих переменных, но и для отслеживания вызовов вложенных функций.
То, как управляется куча, действительно зависит от среды выполнения. C использует malloc
, а C ++ использует new
, но во многих других языках есть сборка мусора.
Однако стек - это более низкоуровневая функция, тесно связанная с архитектурой процессора. Увеличивать кучу, когда не хватает места, не так уж сложно, поскольку это может быть реализовано в вызове библиотеки, который обрабатывает кучу. Однако увеличение стека часто невозможно, поскольку переполнение стека обнаруживается только тогда, когда уже слишком поздно; и отключение потока выполнения - единственный жизнеспособный вариант.
Как управлять кучей, действительно зависит от среды выполнения. C использует malloc
, а C ++ использует new
, но во многих других языках есть сборка мусора.
Однако стек является более низкоуровневой функцией, тесно связанной с архитектурой процессора. Увеличивать кучу, когда не хватает места, не так уж сложно, поскольку это может быть реализовано в вызове библиотеки, который обрабатывает кучу. Однако увеличение стека часто невозможно, поскольку переполнение стека обнаруживается только тогда, когда уже слишком поздно; и отключение потока выполнения - единственный жизнеспособный вариант.
Как управлять кучей, действительно зависит от среды выполнения. C использует malloc
, а C ++ использует new
, но во многих других языках есть сборка мусора.
Однако стек является более низкоуровневой функцией, тесно связанной с архитектурой процессора. Увеличивать кучу, когда не хватает места, не так уж сложно, поскольку это может быть реализовано в вызове библиотеки, который обрабатывает кучу. Однако увеличение стека часто невозможно, поскольку переполнение стека обнаруживается только тогда, когда уже слишком поздно; и отключение потока выполнения - единственный жизнеспособный вариант.
стек - это функция более низкого уровня, тесно связанная с архитектурой процессора. Увеличивать кучу, когда не хватает места, не так уж сложно, поскольку это можно реализовать в вызове библиотеки, который обрабатывает кучу. Однако увеличение стека часто невозможно, поскольку переполнение стека обнаруживается только тогда, когда уже слишком поздно; и отключение потока выполнения - единственный жизнеспособный вариант. стек - это функция более низкого уровня, тесно связанная с архитектурой процессора. Увеличивать кучу, когда не хватает места, не так уж сложно, поскольку это можно реализовать в вызове библиотеки, который обрабатывает кучу. Однако увеличение стека часто невозможно, поскольку переполнение стека обнаруживается только тогда, когда уже слишком поздно; и отключение потока выполнения - единственный жизнеспособный вариант.