Cách sử dụng GNU song song hiệu quả


8

Giả sử tôi muốn tìm tất cả các kết quả khớp trong tệp văn bản nén:

$ gzcat file.txt.gz | pv --rate -i 5 | grep some-pattern

pv --rateđược sử dụng ở đây để đo thông lượng đường ống. Trên máy của tôi, tốc độ khoảng 420Mb / giây (sau khi giải nén).

Bây giờ tôi đang cố gắng thực hiện grep song song bằng cách sử dụng GNU song song.

$ gzcat documents.json.gz | pv --rate -i 5 | parallel --pipe -j4 --round-robin grep some-pattern

Bây giờ thông lượng được giảm xuống ~ 260Mb / s. Và parallelbản thân quá trình quan tâm hơn là sử dụng rất nhiều CPU. Nhiều hơn grepcác quy trình (nhưng ít hơn gzcat).

EDIT 1 : Tôi đã thử các kích thước khối khác nhau ( --block), cũng như các giá trị khác nhau cho -N/ -Ltùy chọn. Không có gì giúp tôi ở điểm này.

Tôi đang làm gì sai?

Câu trả lời:


9

Tôi thực sự ngạc nhiên khi bạn nhận được 270 MB / s khi sử dụng GNU Parallel --pipe. Các thử nghiệm của tôi thường đạt tối đa khoảng 100 MB / s.

Nút cổ chai của bạn rất có thể trong GNU Parallel: --pipekhông hiệu quả lắm. --pipeparttuy nhiên, là: Ở đây tôi có thể nhận được thứ tự 1 GB / s cho mỗi lõi CPU.

Thật không may, có một vài hạn chế khi sử dụng --pipepart:

  • Các tập tin phải được tìm kiếm (tức là không có đường ống)
  • Bạn phải có thể tìm thấy sự bắt đầu của một bản ghi với --recstart / - recend (tức là không có tệp nén)
  • Số dòng không xác định (vì vậy bạn không thể có bản ghi 4 dòng).

Thí dụ:

parallel --pipepart -a bigfile --block 100M grep somepattern

1
Cảm ơn. Có bất kỳ lý do tại sao --pipelà không hiệu quả? Tôi có nghĩa là nó là một số loại vấn đề cơ bản hoặc nhiều hơn thực hiện cụ thể.
Denis Bazhenov

2
Có: GNU Parallel được viết bằng perl và với --pipemỗi byte đơn phải trải qua quá trình đơn, phải thực hiện một chút xử lý trên mỗi byte. Với --pipeparthầu hết các byte không bao giờ được nhìn thấy bởi quy trình trung tâm: Chúng được xử lý bởi các công việc được sinh ra. Vì có khá ít dòng là nút cổ chai trong --pipetôi sẽ chào đón một lập trình viên C / C ++, người sẽ viết lại phần mà sau đó sẽ được chạy cho những người có trình biên dịch C trong đường dẫn của họ.
Ole Tange

2

grep rất hiệu quả - không có ý nghĩa gì khi chạy nó song song. Trong lệnh của bạn chỉ giải nén cần nhiều cpu hơn, nhưng điều này không thể song song.

Việc tách đầu vào bằng cách song song cần nhiều cpu hơn là nhận các dòng khớp bằng grep.

Thay đổi tình huống nếu bạn muốn sử dụng thay vì grep một cái gì đó cần nhiều cpu hơn cho mỗi dòng - thì song song sẽ có ý nghĩa hơn.

Nếu bạn muốn tăng tốc thao tác này - hãy xem nút thắt ở đâu - có thể là giải nén (sau đó giúp sử dụng công cụ giải nén khác hoặc cpu tốt hơn) hoặc - đọc từ đĩa (sau đó giúp sử dụng công cụ giải nén khác hoặc hệ thống đĩa tốt hơn).

Theo kinh nghiệm của tôi - đôi khi tốt hơn là sử dụng lzma (ví dụ -2) để nén / giải nén các tệp - nó có độ nén cao hơn gzip nên cần đọc dữ liệu từ đĩa ít hơn và tốc độ tương đương.


1
Thật vậy, đó là trường hợp của tôi. Quá trình Java rất đói CPU được sử dụng thay vì grep. Tôi đã đơn giản hóa câu hỏi một chút. Tuy nhiên, song song việc ăn nhiều CPU không cung cấp nhiều công việc cho các quy trình Java.
Denis Bazhenov

1

Giải nén là nút cổ chai ở đây. Nếu giải nén không song song trong nội bộ, bạn sẽ không tự mình đạt được nó. Nếu bạn có nhiều hơn một công việc như vậy, thì dĩ nhiên khởi động chúng song song, nhưng chính đường ống của bạn rất khó để song song. Chia một luồng thành các luồng song song hầu như không bao giờ có giá trị và có thể rất đau đớn với việc đồng bộ hóa và hợp nhất. Đôi khi bạn phải chấp nhận rằng nhiều lõi sẽ không giúp ích cho mỗi tác vụ bạn đang chạy.

Nói chung, song song trong shell nên chủ yếu ở mức độ của các quá trình độc lập.


1
Dường như giải nén không bị nghẽn cổ chai trong trường hợp sử dụng parallel. Tôi đồng ý rằng nó chắc chắn là trong trường hợp đầu tiên (w / o song song), nhưng trong trường hợp thứ hai (với song song) nút cổ chai nằm ở phía song song. Điều này xuất phát từ quan sát rằng thông lượng giảm xuống đáng kể khi được đo bằng pv. Nếu nút cổ chai đang trong quá trình giải nén, thông lượng sẽ không thay đổi bất cứ điều gì bạn thêm vào đường ống. Đó là định nghĩa rất trực quan về thông lượng, tôi đoán - điều hạn chế thông lượng nhất.
Denis Bazhenov

1
Có thể là grep rất nhanh, nó hoàn thành nhanh hơn parallelcó thể ghi vào đường ống của nó. Trong trường hợp này, hầu hết grepcác quy trình chỉ đơn giản là chờ để nhận được nhiều hơn, trong khi parallelđang làm việc suốt ngày đêm để ghép các khối thành nhiều ống (đó là các hoạt động IO bổ sung và thậm chí có thể chặn giải nén nếu bộ đệm đầy). Bạn cũng đã thử chơi với --blocktham số? Nó mặc định 1Mnhư vậy cho đến khi một grep nhận được 1Mdữ liệu, phần còn lại gần như chắc chắn đã hoàn thành. Vì vậy, chúng tôi trở lại với thực tế rằng nó không có ý nghĩa để song song hóa điều này.
orion

1
Đúng, tôi đã thử tùy chọn này với kích thước khối lớn và nhỏ. Cũng như các giá trị khác nhau cho -N/ -Ltùy chọn. Có vẻ như các tùy chọn mặc định rất gần với tối ưu cục bộ mà tôi đã trải nghiệm :)
Denis Bazhenov

1
Hãy thử thời gian có và không có pv(có time). Bằng cách này bạn có thể thấy nếu pvchính nó đang làm chậm nó. Nếu có, thì parallelsao chép dữ liệu vào đường ống chắc chắn là chi phí bổ sung. Và trong mọi trường hợp, tôi khá chắc chắn rằng, grepgần như là thời gian thực trong trường hợp này, đặc biệt nếu mẫu đó là một chuỗi đơn giản mà không cần quay lại nhiều. Ngoài ra, parallelsẽ xen kẽ và làm rối các grepđầu ra.
orion

1
Tôi sẽ kiểm tra chéo rằng pvchính nó không gây ra vấn đề, cảm ơn bạn đã cho lời khuyên.
Denis Bazhenov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.