Ubuntu에서 병렬로 작업 실행 - Perl과 Java 간의 I/O 경합 차이점

Ubuntu에서 병렬로 작업 실행 - Perl과 Java 간의 I/O 경합 차이점

이것이 주제에서 벗어나면 죄송합니다. 이는 Ubuntu 시스템에서 I/O가 많은 Perl/Java 스크립트를 병렬로 실행하는 상대적 효율성과 관련이 있습니다.

저는 두 가지 간단한 파일 복사 스크립트 버전(Perl 및 Java)을 작성했습니다. 아래를 참조하세요. 15GB 파일에서 스크립트를 실행하면 Ubuntu Server 12.04(perl 2m10s, java 2m27s)를 실행하는 48코어 시스템에서 각각 비슷한 시간이 걸립니다.

그러나 각각 다른 15GB 입력 파일에서 작동하는 6개의 인스턴스를 병렬로 실행하면 처리 시간이 매우 다릅니다.

  • Perl: 하나의 인스턴스는 2분 6초 안에 완료되고, 다른 모든 인스턴스는 27분 26초 - 28분 10초가 걸립니다.
  • Java: 모든 인스턴스에는 3분 27초~4분 37초가 걸립니다.

장기 실행 Perl 프로세스 중에 프로세서 코어를 살펴보면 top점유된 코어의 I/O 대기 비율(%wa)이 70% 이상인 것을 볼 수 있는데, 이는 일종의 디스크 경합을 암시합니다(모든 파일이 하나의 HD에 있음). 아마도 Java는 BufferedReader이 디스크 경합에 덜 민감할 것입니다.

질문 - 이것이 합리적인 결론처럼 보입니까? 그렇다면 이러한 종류의 작업에 대해 Perl 스크립트를 Java만큼 효율적으로 만들기 위해 OS 수준이나 Perl에서 취할 수 있는 조치를 제안할 수 있는 사람이 있습니까?

참고 - 내 목표는 단순히 파일을 복사하는 것이 아닙니다. 실제 스크립트에는 추가 논리가 포함되어 있지만 아래의 단순화된 스크립트와 동일한 성능 동작을 나타냅니다.

#!/usr/bin/perl -w
open(IN, $ARGV[0]) || die();
open(OUT, ">$ARGV[1]") || die();
while (<IN>) {
    print OUT $_
}
close(OUT);
close(IN);

자바

import java.io.*;
public class CopyFileLineByLine {
    public static void main(String[] args) throws IOException {
        BufferedReader br = null;
        PrintWriter pw = null;
        try {
            br = new BufferedReader(new FileReader(new File(args[0])));
            pw = new PrintWriter(new File(args[1]));
            String line;
            while ((line = br.readLine()) != null) {
                pw.println(line);
            }
        }
        finally {
            if (pw != null) pw.close();
            if (br != null) br.close();
        }
    }
}

답변1

Perl과 Java 간의 버퍼링 작동 방식에서 성능 차이가 발생할 가능성이 높습니다. 이 경우 Java에서 A bufferedReader를 사용하여 이점을 얻었습니다. Perl은 디스크에서 약 4k를 버퍼링합니다.

여기서 몇 가지를 시도해 볼 수 있습니다. 하나는 Perl의 읽기 기능을 사용하여 한 번에 더 큰 블록을 얻는 것입니다. 저것5월성능을 향상시킵니다.

또 다른 옵션은 다양한 mmap 관련 Perl 모듈을 조사하는 것입니다.

답변2

실제로 답변은 아니지만 주석에서 코드 형식이 제대로 지정되지 않았습니다.

GNU Parallel의 경우 이 버전을 사용하여 복사합니다. 1GB/s/코어 순서로 제공할 수 있으며 병렬로 잘 작동합니다.

perl -e '$left=-s STDIN;
  while($read=sysread(STDIN,$buf,$left>131072?131072:$left)){
    $left-=$read;
    syswrite(STDOUT,$buf);
  }' < in > out

답변3

안녕하세요 이것은 사실이 아닐 수도 있지만 처음 관찰했을 때 Perl 스크립트는 순차적으로 해석된 방식으로 실행되고 있습니다. Java 프로그램이 컴파일된 프로그램으로 실행되고 병렬 방식으로 실행되는 동안. 이는 완료 속도의 차이를 설명할 수 있습니다.

관련 정보