여러 개의 대형 gzip 파일을 사용하는 awk 스크립트의 속도를 높이는 방법은 무엇입니까?

여러 개의 대형 gzip 파일을 사용하는 awk 스크립트의 속도를 높이는 방법은 무엇입니까?

두 개의 데이터 파일이 있습니다.

  1. File_1.in, 2,000개가 넘는 행을 포함합니다."12 AB0001":

    10 AB0001
    11 AC0002
    12 AD0003
    ...
    
  2. gzip 압축 파일 목록 *.gz(약 100만 ~ 300만 라인)을 추출하고 구문 분석하여 라인(두 번째 열)이라는 출력 파일을 생성 해야 합니다.File_1.in.

    ##comment..
    ##comment..
    #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT AB0001 AC0002 AD0003
    21 1234567 ab11111 G A 100 PASS info1;info2 GT 0|0 0|1 0|0
    21 1234568 ab22222 C A 100 PASS info1,info2 GT 1:23:2 .:.:. 0:32:2
    21 1234569 ab33333 A C 100 PASS info1;info2 GT 0|2 1|0 0|0
    

다양한 접근 방식을 시도해 본 결과 다음과 같은 결론에 도달했습니다.

{
if(FNR==NR){list[$1]=$2;next}
if(!/^#/){
    for(p in list){
        split($p, sp, ":");
        if (sp[1] != "0|0" && sp[1] != "0" && sp[1] != "."){
            printf("%s %s %s %s %s %s %s %s %s %s\n", 
            $1, $2, $3, $4, $5, $6, $7, $8, $9, $p) >> out"/"list[p]".tmp"
        }
    }
} 
}

명령줄을 통해 실행:

awk -v out="outfolder/" -f myscript.awk file_1.in <(zcat *.gz)

하지만 파일 하나를 만드는 데만 2시간 이상이 소요됩니다. 내 코드를 개선할 수 있는 방법이 있나요? 대부분의 시간을 파일 하나하나에 소비 zcat하고 추가 쓰기 기능이 느린 것 같아요. 어떻게 생각하나요?

답변1

이 코드는 반복 간에 동일한 루프에서 많은 처리를 수행합니다. awks에는 이를 루프에서 제거하기 위한 복잡한 루프 최적화가 없습니다.

    for(p in list){
        split($p, sp, ":");
        if (sp[1] != "0|0" && sp[1] != "0" && sp[1] != "."){

연관 배열을 채우기 위해 첫 번째 파일을 읽은 후 연관 list배열은 변경되지 않지만 이 조건을 테스트하기 위해 인덱스 값을 반복적으로 분할합니다. 대신 배열을 반복하여 일치하지 않는 항목을 제거할 수 있습니다. 아니면... 처리하는 동안 처음부터 이러한 항목을 배열에 삽입하지 마십시오 file_1.in! 그런 다음 분할 및 테스트를 제거할 수 있습니다. 루프의 각 항목은 무조건 액세스됩니다 list.

            printf("%s %s %s %s %s %s %s %s %s %s\n", 
            $1, $2, $3, $4, $5, $6, $7, $8, $9, $p) >> out"/"list[p]".tmp"

%s여기에 인쇄된 자료는 마지막 필드를 제외하고 루프의 각 반복에 대해 동일합니다 $p. sprintf루프 외부를 사용하여 9개 필드를 문자열로 형식화한 str후 다음을 수행할 수 있습니다 printf("%s %s", str, $p) >> out "/" list[p] ".tmp".

명확하지 않은 점: $p가정의 표현식은 인덱스 필드에 맞는 정수입니다. 따라서 전체 논리는 가짜처럼 보입니다. 즉, 역할을 분할한 다음 해당 분할의 일부 필드를 테스트합니다. 양의 정수가 예상되는 경우 콜론이 포함되어서는 안 됩니다. 아마도 여기서 두 번째 열을 테스트할 계획인가요?printfpsplitp:plist[p]

그 외에도 프로그램 속도가 크게 느려질 수 있습니다. 수많은 출력 파일에 소량의 자료가 추가되는 수천 개의 열린 파일 설명자를 유지 관리합니다. 압축된 파일의 수백만 줄: 각 줄에 대해 루프는 2,000개 이상의 항목이 포함된 연관 배열을 반복하고 출력을 여러 다른 파일로 생성합니다. 따라서 수백만 개의 압축된 행은 수십억 개의 압축되지 않은 행이 됩니다.

데이터를 이 표현으로 확장하는 목적이 무엇인지 스스로에게 물어보고 싶을 수도 있습니다. 후속 처리를 위한 경우에는 공간을 더 절약하는 표현을 사용할 수 있습니다. 코드 awk는 일종의 데이터베이스가 암시적으로 처리할 수 있는 일종의 연관을 사전 계산하는 것처럼 보입니다.

관련 정보