Причина избыточного выделения заключается в том, чтобы избежать недостаточного использования физической оперативной памяти. Существует разница между тем, сколько виртуальной памяти выделено процессу, и тем, сколько этой виртуальной памяти фактически отображено на физические фреймы страниц. На самом деле, сразу после запуска процесса он резервирует очень мало оперативной памяти. Это происходит из-за пейджинга по требованию :. Процесс имеет структуру виртуальной памяти, но сопоставление адреса виртуальной памяти с кадром физической страницы не устанавливается до тех пор, пока память не будет прочитана или записана.
Программа обычно никогда не использует все свое пространство виртуальной памяти, и затронутые области памяти меняются во время выполнения программы. Например, сопоставления с фреймами страниц, содержащими код инициализации, который выполняется только в начале выполнения, можно отбросить, а фреймы страниц можно использовать для других сопоставлений.
То же самое относится к данным :, когда программа вызывает malloc
, она резервирует достаточно большое непрерывное виртуальное адресное пространство для хранения данных. Однако сопоставления с кадрами физических страниц не устанавливаются до тех пор, пока страницы не будут фактически использованы, если когда-либо .Или рассмотрим программный стек :: каждый процесс получает довольно большую непрерывную область виртуальной памяти, отведенную для стека (, обычно 8 МБ ). Процесс обычно использует только часть этого пространства стека; маленькие и хорошо работающие -программы используют еще меньше.
Компьютер Linux обычно имеет множество разнородных процессов, работающих на разных стадиях их жизненного цикла. По статистике, в любой момент времени им не требуется сопоставление для каждой виртуальной страницы, которая им была назначена (или будет назначена позже в ходе выполнения программы ).
Схема строго без -чрезмерной фиксации создала бы статическое отображение страниц виртуальных адресов на кадры страниц физической ОЗУ в момент выделения виртуальных страниц. Это привело бы к тому, что система могла бы одновременно запускать гораздо меньше программ, поскольку большое количество кадров страниц ОЗУ было бы зарезервировано ни для чего.
Я не отрицаю, что чрезмерное выделение памяти таит в себе опасность и может привести к -из -ситуаций нехватки памяти, с которыми сложно справиться. Все дело в поиске правильного компромисса.
Предполагая, что ваши файлы называются точно так, как вы показали, т. е. строка snps
, за которой следует имя хромосомы, тогда вы можете использовать
for name in snps*; do
awk 'FNR == 1 { chr = substr(FILENAME, 5) }
{ printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) }' "$name" >"$name.new"
done
Это извлекает имя хромосомы из имени файла с помощьюsubstr()
(имя хромосомы состоит из всех символов в имени файла, начиная с пятого символа ). Это делается только при чтении первой строки файла (FNR == 1
). Затем код выводит текущую строку в желаемом формате, используя printf()
, включая имя хромосомы.
Затем данные записываются в файлы с суффиксом имени файла .new
.
От цикла оболочки можно отказаться, позволив awk
выбирать, куда записывать вывод:
awk 'FNR == 1 { chr = substr(FILENAME, 5); name = FILENAME ".new" }
{ printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) >name }' snps*
Хотите собрать весь вывод в один файл, достаточно
awk 'FNR == 1 { chr = substr(FILENAME, 5) }
{ printf("%s %s:%s:%s:%s\n", $1, chr, $2, $3, $4) }' snps* >all_snps
Вы также можете применить модифицированный вариант к исходным .gen
файлам, которые у вас были:
awk 'FNR == 1 { chr = substr(FILENAME, 4); sub("\.gen$", "", chr)
name = "snps" chr }
{ printf("%s %s:%s:%s:%s\n", $1, chr, $3, $4, $5) >name }' chr*.gen
или, для одного выходного файла,
awk 'FNR == 1 { chr = substr(FILENAME, 4); sub("\.gen$", "", chr) }
{ printf("%s %s:%s:%s:%s\n", $1, chr, $3, $4, $5) }' chr*.gen >all_snps
Это всего лишь вопрос выбора немного отличающихся столбцов данных и извлечения другой части имени файла, чтобы найти имя хромосомы.
Быстрая попытка использования bash (и sed и tr):
for i in snps*
do
n=$(echo $i |tr -d 'a-zA-Z')
sed -i -e "s/ / $n:/" -e 's/ \([A-Z]\)/:\1/g' $i
done
Это просто перебирает набор файлов, начинающихся с snps2, и для каждого файла удаляет все буквенные символы из имени, чтобы получить числовую часть, а затем использует sed для (a )замены первого пробела на пробел, числовая часть имени файла и двоеточие, а (b )заменяет каждый пробел, за которым следует заглавная буква, двоеточием. Я почти уверен, что это можно было бы сделать одинаково хорошо, используя вместо этого awk.