단일 코어 바운드 작업을 여러 부분으로 분할하고 각 부분을 bash에서 별도의 작업으로 실행하여 병렬화할 수 있는 유사한 상황에 직면했지만 반환된 데이터를 다시 단일 데이터로 변환하는 데 문제가 있습니다. 개울. 지금까지 나의 순진한 접근 방식은 임시 폴더를 만들고, PID를 추적하고, 각 스레드가 해당 PID를 파일에 쓰도록 한 다음 모든 작업이 완료되면 모든 PID를 읽고 순서대로 병합하는 것입니다. PID가 파일로 생성되었습니다. 이러한 다중 입력 및 단일 출력 상황을 처리하기 위해 bash/셸 도구를 사용하는 더 좋은 방법이 있습니까?
답변1
지금까지 나의 순진한 접근 방식은 임시 폴더를 만들고, PID를 추적하고, 각 스레드가 해당 PID를 파일에 쓰도록 한 다음 모든 작업이 완료되면 모든 PID를 읽고 순서대로 병합하는 것입니다. PID가 파일로 생성되었습니다.
이것이 GNU Parallel이 하는 일과 거의 똑같습니다.
parallel do_stuff ::: job1 job2 job3 ... jobn > output
몇 가지 추가 이점이 있습니다.
- 임시 파일은 자동으로 삭제되므로 GNU Parallel을 종료하더라도 정리가 필요하지 않습니다.
- 현재 실행 중인 작업에 임시 공간만 제공하면 됩니다. 완료된 작업에 대한 임시 공간은 작업이 완료된 후 해제됩니다.
- 출력이 입력과 동일한 순서로 이루어지도록 하려면 를 사용하십시오
--keep-order
. - 다른 작업의 한 줄씩 혼합된 출력을 원하는 경우 을 사용하십시오
--line-buffer
.
GNU Parallel에는 작업을 더 작은 작업으로 분할하는 많은 기능이 있습니다. 어쩌면 이 중 하나를 사용하여 더 작은 일자리를 만들 수도 있을까요?
답변2
귀하의 제안은 완료하기 전에 데이터를 병합하는 방법에 대해 생각하지 않으므로 매우 합리적인 것 같습니다. 그러니 솔직히 말해서 그것은 나쁜 접근 방식이 아닙니다!
또 다른 일반적인 솔루션은 데이터를 수집하고, 데이터 "슬라이스" 의미/경계를 이해하고, 언제든지 콘텐츠를 병합하는 중앙 프로그램을 보유하는 것입니다.
이를 수행하는 방법은 생성하는 데이터 유형에 따라 크게 달라집니다! 이것은 UNIX, UDP 또는 TCP 소켓에서 메시지를 읽는 최소한의 프로그램만큼 간단할 수 있습니다(그러나 특정 데이터 포인트가 완료된 지점을 아는 직렬화 형식을 사용하는 것을 고려할 수도 있습니다). . 아니면 소규모 관계형 데이터베이스 서버(PostgreSQL?)를 실행하세요. 또는 ØMQ 소켓을 사용하여 여러 게시자를 보유하고 중앙에서 이러한 게시자의 구독자로 병합할 수 있으며, 이는 네트워크를 통해 즉시 작동한다는 추가 이점도 있습니다. 또는 데이터베이스를 사용하여 시계열 데이터를 저장합니다. 또는 데이터가 로그 메시지처럼 보이기 때문에 syslog 또는 syslog를 통해 결과를 기록하는 작업자를 구현하고 sd_journal_print
Journald의 저널 네임스페이스를 사용하여 모든 로그 메시지를 단일 파일에 저장합니다. 또는...
결국 귀하의 옵션은 다음과 같습니다.
- 많은 파일에 쓰고 나중에 병합합니다(여기서는 다음을 사용하고 있습니다).파일 시스템문제 없이 다른 작업자가 다른 파일에 대한 동시 쓰기 액세스를 허용합니다.
- 일종의 파이프/소켓/프로세스 간 통신 방법을 사용하여 중앙 프로세스에 메시지를 보냅니다. 여기서는 데이터 구조를 알고 있고 즉시 병합을 수행할 수 있다는 사실을 사용합니다.
실제로 이를 수행하는 방법은 데이터 구조, 볼륨 및 병합 방법에 따라 100% 달라집니다.