亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 7913 | 回復: 15
打印 上一主題 下一主題

perl的內(nèi)存占用,求教&探討 [復制鏈接]

論壇徽章:
1
程序設(shè)計版塊每日發(fā)帖之星
日期:2015-10-07 06:20:00
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2011-04-01 14:48 |只看該作者 |倒序瀏覽
今天有個生物信息的任務(wù),完成了,但是很不爽的搞死了電腦兩次。于是全程播報我的思路和步驟,來論壇求教了,求拍磚:

1. 數(shù)據(jù)描述

有基因組數(shù)據(jù)如下,大寫的是正常序列,小寫的是repeat區(qū)域:
  1. >chr1
  2. GAATTCCAAAGCCAAAGATTGCATCAGTTCTGCTGCTATTTCCTCCTATCATTCTTTCTG
  3. ATGTTGAAAATGATATTAAGCCTAGGATTCGTGAATGGGAGAAGGTATTTTTGTTCATGG
  4. TAGTCATTGGAACCTGCTAGATTGTACACTTGACAATAACATATATTAATATTAGTGACC
  5. CCATTTTTAAATTTCCTAGGCTGGCATTGAACAAGACTATGTTAGTAGGATGTTGTTGAA
  6. GTATCCATGGATTCTTTCAACGAGTGTGATAGAGAACTACAGTCAAATGCTGTTGTTTTT
  7. CAACCAAAAAAGGGTAAGTAAAAAAGAATACTTACTATGCTGTGCCTCAAGTTCATGTTA

  8. TATTCAAATGCCGCAGCTCTGAtaaccactcttttctggaccaataaatggctgcttggt
  9. tcctctataggagatgtgtcgctggctgttcttgctatggtacccgcaaaaataattaaa

  10. cgtcttcgaAGGTTTGCAGCTGAGTATGTGGAATGTTCTGCATGCTCTCGAAGATGAACA
  11. GCATCTCTGGTGTCTCGCCGGAGTGCAAGGACTGCAGAGTTTAGGCCTGGGCTCCCTGAG
  12. CGGTTAGGTGGCATTTCCTGGTCTGGTCTCACCATTTCTATTTGCTGTAAGAGTTTTGTT
  13. >chr2
  14. .............
  15. .............
復制代碼
2. 任務(wù)要求
按照小寫的序列區(qū)域,將一個長的染色體分割成較短的片段,小寫區(qū)域丟棄,大寫片段短于500字符就丟棄。

3. 分析每一行的可能格式

1.
>chr1

2.
大寫片段-----小寫片段-----大寫片段
小寫----大寫---小寫(由于每行60字符,這里的大寫片段顯然不夠500字符)
小寫------大寫
大寫------小寫

3.
一直小寫
一直大寫

4. 寫代碼如下:
  1. #!/usr/bin/perl -w
  2. #
  3. #Author **
  4. #This script is uesd for matching the repeat masked region, and then split
  5. #by them.

  6. use POSIX;

  7. my $repeat=$ARGV[0];#file repeat.fa
  8. my $out=$ARGV[1];#splited file
  9. my $min_seq_length=500;
  10. my $out_line_length=50;

  11. #repeat file load
  12. open REPEAT,"<$repeat" or die "hi:$!";
  13. my %chrom;
  14. my $base;
  15. while(<REPEAT>){
  16.         chomp;
  17.         if($_ =~ /^\>(.*?)$/){
  18.                 $base=$1;
  19.                 $chrom{$base}="";
  20.         }
  21.         else{
  22.                 $chrom{$base}.=$_;
  23.         }
  24. }
  25. close REPEAT;

  26. #print file splited by repeats
  27. open OUT,">$out" or die"Oh:$!";
  28. foreach $base (sort keys %chrom){

  29.         my @seq=split(//,$chrom{$base});
  30.         my $count=0;
  31.         my $start;
  32.         my $stop;
  33.         my $seq="";
  34.         my $switch=0;#1 == ATCG, 0 == N

  35.         foreach $a(@seq){
  36.                 if($a !~ /[atcg]/ && $switch == 0){  #new seq after repeat
  37.                         $switch=1;
  38.                         $start=$count+1;
  39.                         $seq.=$a;
  40.                 }
  41.                 elsif($a !~/[atcg]/ && $switch == 1){
  42.                         $seq.=$a;
  43.                 }
  44.                 elsif($a =~ /[atcg]/ && $switch == 1){
  45.                         $switch=0;
  46.                         $stop=$count;

  47.                         if(  ($stop - $start)   >=    $min_seq_length){
  48.                                 print OUT "\>$base\_$start\_$stop\n";
  49.                                 seq_print($seq,$out_line_length);
  50.                         }

  51.                         $seq="";
  52.                 }

  53.                 $count++;
  54.         }
  55.         #print the last seq
  56.         if($switch == 1){$stop=$count-1;}
  57.         if(     ($stop - $start)   >=    $min_seq_length){
  58.                 print OUT "\>$base\_$start\_$stop\n";
  59.                 seq_print($seq,$out_line_length);
  60.         }

  61. print "work on $base\n";
  62. }
  63. close OUT;



  64. sub seq_print{
  65.         my ($seq,$length)=@_;
  66.         my $step=floor(length($seq)/$length);
  67.         for(my $i=1;$i<=$step;$i++){
  68.                 my $out=substr($seq,($i-1)*$length,$length);
  69.                 print OUT "$out\n";
  70.         }
  71.         my $out=substr($seq,$step*$length);
  72.         print OUT "$out\n";
  73. }
復制代碼
5. 測試小量數(shù)據(jù)通過
......


6. 大數(shù)據(jù)量,死機
于是在應(yīng)用在了基因組上,數(shù)據(jù)量2G多

瞬間占用40G以上內(nèi)存,服務(wù)器死機

7. 修改代碼
想了想,我的@seq可能太過于恐怖了,于是修改代碼如下:
  1. #!/usr/bin/perl -w
  2. #
  3. #Author **
  4. #This script is uesd for matching the repeat masked region NNNNN, and then split
  5. #by them.

  6. use POSIX;

  7. my $repeat=$ARGV[0];#file repeat.fa
  8. my $out=$ARGV[1];#splited file
  9. my $min_seq_length=500;
  10. my $out_line_length=50;

  11. #repeat file load
  12. open REPEAT,"<$repeat" or die "hi:$!";
  13. my %chrom;
  14. my $base;
  15. my $count=0;
  16. while(<REPEAT>){
  17.         chomp;
  18.         if($_ =~ /^\>(.*?)$/){
  19.                 $base=$1;
  20.                 $count=0;
  21.         }
  22.         else{
  23.                 $chrom{$base}[$count]=$_;
  24.                 $count++;
  25.         }
  26. }
  27. close REPEAT;


  28. open OUT,">$out" or die"Oh:$!";
  29. foreach $base (sort keys %chrom){

  30.         my $array_hash=$chrom{$base};
  31.         my $count=0;
  32.         my $start;
  33.         my $stop;
  34.         my $seq="";
  35.         my $switch=0;#1 == ATCG, 0 == N

  36.         foreach $name(@$array_hash){
  37.           my @line=split(//,$name);
  38.           foreach $a(@line){
  39.                 if($a !~ /[atcg]/ && $switch == 0){  # first base of seq after repeat
  40.                         $switch=1;
  41.                         $start=$count+1;
  42.                         $seq.=$a;
  43.                 }
  44.                 elsif($a !~ /[atcg]/ && $switch == 1){ #continue seq
  45.                         $seq.=$a;
  46.                 }
  47.                 elsif($a =~ /[atcg]/ && $switch == 1){ #come across repeat
  48.                         $switch=0;
  49.                         $stop=$count;

  50.                         if(  ($stop - $start)   >=    $min_seq_length){
  51.                                 print OUT "\>$base\_$start\_$stop\n";
  52.                                 seq_print($seq,$out_line_length);
  53.                         }

  54.                         $seq="";
  55.                 }

  56.                 $count++;
  57.           }
  58.         undef(@line);

  59.         }
  60.         #print the last seq
  61.         if($switch == 1){$stop=$count-1;}
  62.         if(     ($stop - $start)   >=    $min_seq_length){
  63.                 print OUT "\>$base\_$start\_$stop\n";
  64.                 seq_print($seq,$out_line_length);
  65.         }

  66. print "work on $base\n";
  67. }
  68. close OUT;



  69. sub seq_print{
  70.         my ($seq,$length)=@_;
  71.         my $step=floor(length($seq)/$length);
  72.         for(my $i=1;$i<=$step;$i++){
  73.                 my $out=substr($seq,($i-1)*$length,$length);
  74.                 print OUT "$out\n";
  75.         }
  76.         my $out=substr($seq,$step*$length);
  77.         print OUT "$out\n";
  78. }
復制代碼
8. 求教
這次占用了大概4.3G的內(nèi)存,程序順利跑完,但是我依然不明白哪里需要4G內(nèi)存了。
在我看來,這兩行:
$seq="";
undef(@line);
已經(jīng)釋放了內(nèi)存,應(yīng)該只是%chrom存儲的2G序列而已了。

論壇徽章:
46
15-16賽季CBA聯(lián)賽之四川
日期:2018-03-27 11:59:132015年亞洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49雙魚座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亞冠之布里斯班獅吼
日期:2015-07-13 10:44:56
2 [報告]
發(fā)表于 2011-04-01 14:55 |只看該作者
2G 的原始數(shù)據(jù)才占 4G 的內(nèi)存,已經(jīng)很省了啊?

論壇徽章:
1
程序設(shè)計版塊每日發(fā)帖之星
日期:2015-10-07 06:20:00
3 [報告]
發(fā)表于 2011-04-01 15:01 |只看該作者
回復 2# zhlong8


    這個....這樣啊....
    那另外2G內(nèi)存被什么吃掉了?

    或者說,
    為什么4G就很省了?

論壇徽章:
46
15-16賽季CBA聯(lián)賽之四川
日期:2018-03-27 11:59:132015年亞洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49雙魚座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亞冠之布里斯班獅吼
日期:2015-07-13 10:44:56
4 [報告]
發(fā)表于 2011-04-01 15:06 |只看該作者
本帖最后由 zhlong8 于 2011-04-01 15:07 編輯

將一個長的染色體分割成較短的片段,小寫區(qū)域丟棄,大寫片段短于500字符就丟棄。

這個用 RE 就能做了?你為什么一個一個字符處理?

@seq 那里 split 成單個字符每1K個占用內(nèi)存是 48K,如果你一段基因超長的話……

Perl 的字符串可變,所以可能分配的內(nèi)存比需要的多,而且是以2^n 的速度擴大的,所以平均長度越長浪費的也就越多

數(shù)據(jù)結(jié)構(gòu)不也要占用內(nèi)存,建一個空空的數(shù)組或 hash 難道就不需要空間了?

論壇徽章:
1
程序設(shè)計版塊每日發(fā)帖之星
日期:2015-10-07 06:20:00
5 [報告]
發(fā)表于 2011-04-01 15:24 |只看該作者
回復 4# zhlong8


謝謝說明!


將一個長的染色體分割成較短的片段,小寫區(qū)域丟棄,大寫片段短于500字符就丟棄。
這個用 RE 就能做了。磕銥槭裁匆粋一個字符處理?

我只能說是,想到什么就寫什么了,另,RE是什么?


@seq 那里 split 成單個字符每1K個占用內(nèi)存是 48K,如果你一段基因超長的話……

是的,恐怖的長,2G只有10個基因組,平均一個200MB. 看來這就是我第一次程序掛掉的原因


Perl 的字符串可變,所以可能分配的內(nèi)存比需要的多,而且是以2^n 的速度擴大的,所以平均長度越長浪費的也就越多
數(shù)據(jù)結(jié)構(gòu)不也要占用內(nèi)存,建一個空空的數(shù)組或 hash 難道就不需要空間了?

$seq的長度經(jīng)常會有幾千上萬,一直在變,那這就是原因了?
我是不是可以理解為:

$a="A";
$b="B";
$c="CCCCC";


$a="AA";
$b="BB";
$c="CC";

前者比后者 消耗的內(nèi)存多?

論壇徽章:
46
15-16賽季CBA聯(lián)賽之四川
日期:2018-03-27 11:59:132015年亞洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49雙魚座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亞冠之布里斯班獅吼
日期:2015-07-13 10:44:56
6 [報告]
發(fā)表于 2011-04-01 15:38 |只看該作者
對于很長的數(shù)據(jù)按行存儲和處理比較高效。

說用 RE 指的是對于每一行的數(shù)據(jù)可以用正則表達式來判斷分割。

對于比較短的字符串不需要考慮這么多,一個變量保存字符串的長度是曾經(jīng)最長的長度,即使賦值了個比較短的字符串,相當于剩余的空間就是緩沖區(qū)了。用 undef 可以釋放

論壇徽章:
1
程序設(shè)計版塊每日發(fā)帖之星
日期:2015-10-07 06:20:00
7 [報告]
發(fā)表于 2011-04-01 15:46 |只看該作者
回復 6# zhlong8


謝謝,變量占用內(nèi)存大概明白了...


    RE指,類似這樣的處理么?
     if (   $line=~/([ATCG]*)([atcg]*)([ATCG]*)/ ) {
                $1;
                $2;
                $3;
   }

其實一開始我是有想這么寫的,但是還需要計算大寫片段在染色體上的位置, 每一列的可能又多,寫到一半就懶了...

論壇徽章:
0
8 [報告]
發(fā)表于 2011-04-02 11:43 |只看該作者
本帖最后由 longbow0 于 2011-04-02 14:07 編輯

可能會占用巨大內(nèi)存的方法。具體消耗的內(nèi)存與每條序列長度相關(guān)。

  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;

  4. use Bio::SeqIO;

  5. my $seqi = Bio::SeqIO->new(
  6.     -file => 'chr.fasta',
  7.     -format => 'fasta',
  8. );

  9. while ( my $seq = $seqi->next_seq ) {
  10.     my @sseqs = split /[a-z]+/, $seq->seq; # 提取大寫序列
  11.    
  12.     # 或者更精確一點
  13.     # my @sseqs = split /[atcg]+/, $seq->seq;

  14.     for my $sseq ( @sseqs ) {
  15.         next if length( $sseq ) < 500;

  16.         print $sseq, "\n"; # 直接打印
  17.     }
  18. }

復制代碼

論壇徽章:
0
9 [報告]
發(fā)表于 2011-04-02 16:44 |只看該作者
不耗內(nèi)存版,行處理:

  1. use strict;
  2. use warnings;

  3. my $repeat=$ARGV[0];#file repeat.fa
  4. my $out=$ARGV[1];#splited file
  5. my $min_seq_length=500;
  6. my $out_line_length=50;

  7. #repeat file load
  8. open REPEAT,"<$repeat" or die "hi:$!";
  9. open OUT,">$out" or die"Oh:$!";
  10. my $DNA="";
  11. my $ok_flag=1;
  12. my $txt;
  13. while($txt=<REPEAT>){
  14.   chomp $txt;
  15.   next unless($txt);
  16.   if($txt =~ /^\>/){  #new DNA, clean the old one
  17.     if($ok_flag) {
  18.             while(length($DNA)>$out_line_length) {
  19.                     print OUT substr($DNA,0,$out_line_length,""),"\n";
  20.             }
  21.             print OUT $DNA,"\n";
  22.             $ok_flag=0;
  23.     }
  24.     elsif(length($DNA)>=$min_seq_length) {
  25.             while(length($DNA)>$out_line_length) {
  26.                     print OUT substr($DNA,0,$out_line_length,""),"\n";
  27.             }
  28.             print OUT $DNA,"\n";
  29.     }
  30.     $DNA="";
  31.     print OUT "$txt\n";
  32.   }
  33.   elsif($txt=~/[atcg]/){
  34.          
  35.                 if($txt=~/^([ATCG]+)/) {
  36.                         $DNA .=$1;
  37.                 }
  38.                
  39.                 if($ok_flag) {
  40.             while(length($DNA)>$out_line_length) {
  41.                     print OUT substr($DNA,0,$out_line_length,""),"\n";
  42.             }
  43.             print OUT $DNA,"\n";       
  44.             $ok_flag = 0;
  45.     }
  46.     else {
  47.                         if(length($DNA)>=$min_seq_length) {
  48.                     while(length($DNA)>$out_line_length) {
  49.                             print OUT substr($DNA,0,$out_line_length,""),"\n";
  50.                     }
  51.                     print OUT $DNA,"\n";       
  52.             }          
  53.     }
  54.                 $DNA="";
  55.                 if($txt=~/([ATCG]+)$/) {
  56.                         $DNA = $1;
  57.           }         
  58.         }
  59.         else {
  60.                 $DNA .= $txt;
  61.                
  62.                 if($ok_flag) {
  63.             while(length($DNA)>$out_line_length) {
  64.                     print OUT substr($DNA,0,$out_line_length,""),"\n";
  65.             }
  66.     }
  67.     else {
  68.                         if(length($DNA)>=$min_seq_length) {
  69.                     while(length($DNA)>$out_line_length) {
  70.                             print OUT substr($DNA,0,$out_line_length,""),"\n";
  71.                     }
  72.                     $ok_flag = 1;
  73.             }          
  74.     }               
  75.         }
  76. }

  77. close REPEAT;
  78. close OUT;

復制代碼

論壇徽章:
1
程序設(shè)計版塊每日發(fā)帖之星
日期:2015-10-07 06:20:00
10 [報告]
發(fā)表于 2011-04-04 08:08 |只看該作者
回復 8# longbow0


    謝謝了, 跑了一遍,很快,1.6 G~2.4G內(nèi)存之間,看來Seq:IO很強大啊..
    只是,我的scripts其實還計算了每一段大寫片段的在基因組上的位置...用split ...不好記錄吧:)
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP