Phân tích hiệu suất tf.data với TF Profiler

Tổng quan

Hướng dẫn này giả định bạn đã quen thuộc với TensorFlow Profilertf.data . Nó nhằm mục đích cung cấp hướng dẫn từng bước kèm theo các ví dụ để giúp người dùng chẩn đoán và khắc phục các sự cố về hiệu suất của đường dẫn đầu vào.

Để bắt đầu, hãy thu thập hồ sơ về công việc TensorFlow của bạn. Hướng dẫn về cách thực hiện hiện có sẵn cho CPU/GPUCloud TPU .

TensorFlow Trace Viewer

Quy trình phân tích chi tiết bên dưới tập trung vào công cụ xem dấu vết trong Profiler. Công cụ này hiển thị dòng thời gian hiển thị thời lượng của các hoạt động được thực hiện bởi chương trình TensorFlow của bạn và cho phép bạn xác định các hoạt động nào mất nhiều thời gian nhất để thực thi. Để biết thêm thông tin về trình xem dấu vết, hãy xem phần này của hướng dẫn TF Profiler. Nói chung, các sự kiện tf.data sẽ xuất hiện trên dòng thời gian của CPU chủ.

Quy trình phân tích

Hãy làm theo quy trình làm việc dưới đây. Nếu bạn có phản hồi để giúp chúng tôi cải thiện nó, vui lòng tạo một vấn đề trên github với nhãn “comp:data”.

1. Đường dẫn tf.data của bạn có tạo ra dữ liệu đủ nhanh không?

Bắt đầu bằng cách xác định xem đường dẫn đầu vào có phải là nút cổ chai cho chương trình TensorFlow của bạn hay không.

Để làm như vậy, hãy tìm các thao tác IteratorGetNext::DoCompute trong trình xem theo dõi. Nói chung, bạn mong đợi nhìn thấy những điều này khi bắt đầu một bước. Những lát cắt này biểu thị thời gian cần thiết để đường dẫn đầu vào của bạn tạo ra một loạt phần tử khi được yêu cầu. Nếu bạn đang sử dụng máy ảnh hoặc lặp lại tập dữ liệu của mình trong tf.function , thì những thứ này sẽ được tìm thấy trong các chuỗi tf_data_iterator_get_next .

Lưu ý rằng nếu bạn đang sử dụng chiến lược phân phối , bạn có thể thấy các sự kiện IteratorGetNextAsOptional::DoCompute thay vì IteratorGetNext::DoCompute (kể từ TF 2.3).

image

Nếu cuộc gọi quay lại nhanh chóng (<= 50 us), điều này có nghĩa là dữ liệu của bạn sẽ sẵn có khi được yêu cầu. Đường dẫn đầu vào không phải là nút cổ chai của bạn; xem hướng dẫn Profiler để biết thêm các mẹo phân tích hiệu suất chung.

image

Nếu cuộc gọi quay lại chậm, tf.data không thể đáp ứng yêu cầu của người tiêu dùng. Tiếp tục đến phần tiếp theo.

2. Bạn có đang tìm nạp trước dữ liệu không?

Cách tốt nhất để tăng hiệu suất của đường dẫn đầu vào là chèn một phép chuyển đổi tf.data.Dataset.prefetch vào cuối đường dẫn tf.data của bạn. Phép biến đổi này chồng lên quá trình tính toán tiền xử lý của đường dẫn đầu vào với bước tính toán mô hình tiếp theo và cần thiết để có hiệu suất đường dẫn đầu vào tối ưu khi đào tạo mô hình của bạn. Nếu đang tìm nạp trước dữ liệu, bạn sẽ thấy một lát cắt Iterator::Prefetch trên cùng một luồng với IteratorGetNext::DoCompute op.

image

Nếu bạn không có prefetch ở cuối quy trình , bạn nên thêm một quy trình. Để biết thêm thông tin về các đề xuất về hiệu suất tf.data , hãy xem hướng dẫn về hiệu suất của tf.data .

Nếu bạn đã tìm nạp trước dữ liệu và quy trình đầu vào vẫn là nút thắt cổ chai, hãy tiếp tục chuyển sang phần tiếp theo để phân tích thêm hiệu suất.

3. Bạn có đạt mức sử dụng CPU cao không?

tf.data đạt được thông lượng cao bằng cách cố gắng tận dụng tốt nhất các tài nguyên sẵn có. Nói chung, ngay cả khi chạy mô hình của bạn trên bộ tăng tốc như GPU hoặc TPU, các đường dẫn tf.data vẫn chạy trên CPU. Bạn có thể kiểm tra mức sử dụng của mình bằng các công cụ như sarhtop hoặc trong bảng điều khiển giám sát đám mây nếu bạn đang chạy trên GCP.

Nếu mức sử dụng của bạn ở mức thấp, điều này cho thấy rằng đường dẫn đầu vào của bạn có thể không tận dụng tối đa CPU chủ. Bạn nên tham khảo hướng dẫn hiệu suất của tf.data để biết các phương pháp hay nhất. Nếu bạn đã áp dụng các phương pháp hay nhất nhưng mức sử dụng cũng như thông lượng vẫn ở mức thấp, hãy tiếp tục phân tích Nút cổ chai bên dưới.

Nếu mức sử dụng của bạn sắp đạt đến giới hạn tài nguyên , để cải thiện hiệu suất hơn nữa, bạn cần cải thiện hiệu quả của quy trình đầu vào (ví dụ: tránh tính toán không cần thiết) hoặc tính toán giảm tải.

Bạn có thể cải thiện hiệu quả của đường dẫn đầu vào bằng cách tránh tính toán không cần thiết trong tf.data . Một cách để thực hiện việc này là chèn một phép biến đổi tf.data.Dataset.cache sau công việc tính toán chuyên sâu nếu dữ liệu của bạn vừa với bộ nhớ; điều này làm giảm tính toán với chi phí sử dụng bộ nhớ tăng lên. Ngoài ra, việc tắt tính năng song song nội bộ trong tf.data có khả năng tăng hiệu quả lên > 10% và có thể được thực hiện bằng cách đặt tùy chọn sau trên đường dẫn đầu vào của bạn:

dataset = ...
options = tf.data.Options()
options.experimental_threading.max_intra_op_parallelism = 1
dataset = dataset.with_options(options)

4. Phân tích nút cổ chai

Phần sau đây hướng dẫn cách đọc các sự kiện tf.data trong trình xem theo dõi để hiểu nút thắt cổ chai nằm ở đâu và các chiến lược giảm thiểu khả thi.

Hiểu các sự kiện tf.data trong Profiler

Mỗi sự kiện tf.data trong Profiler có tên Iterator::<Dataset> , trong đó <Dataset> là tên của nguồn tập dữ liệu hoặc quá trình chuyển đổi. Mỗi sự kiện cũng có tên dài Iterator::<Dataset_1>::...::<Dataset_n> , bạn có thể thấy bằng cách nhấp vào sự kiện