Kỹ thuật tối ưu hóa để đào tạo CheXNet trên Dell C4140 với GPU Nvidia V100

CẤU HÌNH PHẦN CỨNG: CẤU HÌNH PHẦN MỀM:
  • 4 PowerEdge C4140
  • 4 Nvidia V100 32GB SXM2
  • 2 20 nhân Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
  • RAM 384GB, DDR4 2666MHz
  • 1 Mellanox EDR HCA
  • Hệ thống tập tin bóng
  • Khung học tập sâu: tenorflow-gpu
  • Phiên bản khung: 1.12.0
  • Phiên bản Horovod: 0.16.4
  • Phiên bản MPI: 4.0.0 có hỗ trợ cuda và ucx
  • Phiên bản CUDA: 10.1.105
  • Phiên bản CUDNN: 7.6.0
  • Phiên bản NCCL: 2.4.7
  • Phiên bản Python: 3.6.8
  • Hệ điều hành và phiên bản: RHEL 7.4

 


Đường ống dẫn dữ liệu rất quan trọng để nhận được hiệu suất cao nhất từ ​​các máy gia tốc của bạn:

 

Dữ liệu tf là gì, tại sao bạn nên cố gắng sử dụng nó?

Khi các thiết bị điện toán mới (chẳng hạn như GPU và TPU) có thể huấn luyện mạng lưới thần kinh với tốc độ ngày càng nhanh, quá trình xử lý CPU có xu hướng trở thành nút cổ chai. API tf.data cung cấp cho người dùng các khối xây dựng để thiết kế các đường ống đầu vào sử dụng hiệu quả CPU, tối ưu hóa từng bước của quy trình ETL.

Để thực hiện một bước đào tạo, trước tiên bạn phải trích xuất và chuyển đổi dữ liệu đào tạo, sau đó cung cấp dữ liệu đó cho một mô hình đang chạy trên máy gia tốc. Tuy nhiên, trong một triển khai đồng bộ ngây thơ, trong khi CPU đang chuẩn bị dữ liệu, bộ tăng tốc sẽ không hoạt động. Ngược lại, trong khi máy gia tốc đang đào tạo mô hình, CPU sẽ không hoạt động. Do đó, thời gian bước đào tạo là tổng của cả thời gian xử lý trước của CPU và thời gian đào tạo máy gia tốc

Đường ống chồng chéo quá trình tiền xử lý và thực hiện mô hình của một bước đào tạo. Trong khi máy gia tốc đang thực hiện bước huấn luyện N, CPU đang chuẩn bị dữ liệu cho bước N+1. Làm như vậy sẽ giảm đến mức tối đa thời gian của từng bước (ngược lại với tổng) của quá trình đào tạo và thời gian cần thiết để trích xuất và chuyển đổi dữ liệu.

Nếu không có đường ống dẫn, CPU và GPU/TPU sẽ không hoạt động trong phần lớn thời gian:

SLN318898_en_US__1Thực thi tuần tự
Hình 1: Việc thực thi tuần tự thường khiến GPU không hoạt động

Với pipelining, thời gian nhàn rỗi giảm đáng kể:

SLN318898_en_US__2Chồng chéo đường ống
Hình 2: Đường ống chồng lấp việc sử dụng CPU và GPU, tối đa hóa việc sử dụng GPU

API tf.data cung cấp cơ chế đường ống phần mềm thông qua chuyển đổi tf.data.Dataset.prefetch, có thể được sử dụng để tách rời thời gian dữ liệu được tạo ra từ thời điểm dữ liệu được sử dụng. Cụ thể, quá trình chuyển đổi sử dụng luồng nền và bộ đệm bên trong để tìm nạp trước các phần tử từ tập dữ liệu đầu vào trước thời điểm chúng được yêu cầu.

Thêm thông tin tại đây: https://www.tensorflow.org/guide/performance/datasets

Khi một người tuân theo các nguyên tắc do tensorflow cung cấp, có thể nhận được một đường dẫn dữ liệu giống như thế này (Phương pháp tiếp cận cũ):
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets /old_approach.py

Trong cách tiếp cận này còn được gọi là cách tiếp cận cũ, đường dẫn dữ liệu tf thực hiện như sau (giả sử tập dữ liệu x quang ngực là một chuỗi các TFRecords):

  1. Nhận danh sách tên tệp tuyệt đối.
  2. Xây dựng tập dữ liệu từ danh sách tên tệp bằng TFRecordDataset()
  3. Tạo tập dữ liệu mới tải và định dạng hình ảnh bằng cách xử lý trước chúng.
  4. Phân mảnh tập dữ liệu.
  5. Xáo trộn tập dữ liệu khi đào tạo.
  6. Lặp lại tập dữ liệu.
  7. Batch tập dữ liệu.
  8. Tìm nạp trước tập dữ liệu cho batch_size.

 

Tuy nhiên, đây không phải là mã hiệu quả nhất. Nó gây ra tình trạng đơ máy và thường xuyên sử dụng gpu 0%. Về cơ bản, nó không sử dụng máy gia tốc một cách hiệu quả.

Để thiết lập chính xác đường dẫn dữ liệu tf, chúng tôi thực hiện theo cách tiếp cận được thực hiện bởi các mô hình chính thức của tensorflow, cụ thể là mô hình dành cho ResNet. Sự khác biệt giữa cách tiếp cận cũ và cách tiếp cận mới là cách thiết lập đường dẫn dữ liệu trước khi đưa nó vào mô hình.

Đây là cách tiếp cận mới trông như thế nào:
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/new_approach.py

Cách tiếp cận mô hình chính thức của TensorFlow còn được gọi là cách tiếp cận mới như sau:

  1. Nhận danh sách tên tệp tuyệt đối.
  2. Xây dựng tập dữ liệu từ danh sách tên tệp bằng from_tensor_slices()
  3. Sharding được thực hiện trước thời hạn.
  4. Tập dữ liệu được xáo trộn trong quá trình đào tạo.
  5. Tập dữ liệu sau đó được xen kẽ song song, xen kẽ và xử lý nhiều tệp (được xác định bởi cycle_length) để chuyển đổi chúng để tạo tập dữ liệu TFRecord.
  6. Tập dữ liệu sau đó được tìm nạp trước. buffer_size xác định số lượng bản ghi được tìm nạp trước, thường là batch_size nhỏ của tác vụ.
  7. Bộ dữ liệu lại được xáo trộn. Chi tiết về xáo trộn được kiểm soát bởi buffer_size.
  8. Bộ dữ liệu được lặp lại. Nó lặp lại tập dữ liệu cho đến khi num_epochs được huấn luyện.
  9. Tập dữ liệu phải tuân theo đồng thời map_and_batch() để phân tích cú pháp các tệp bản ghi tf, từ đó xử lý trước hình ảnh và xử lý hàng loạt chúng.
  10. Hình ảnh được xử lý trước đã sẵn sàng dưới dạng tập dữ liệu và được tìm nạp lại.

 

Dưới đây là so sánh hiệu suất của cả hai phương pháp cũ và mới, sử dụng các mô hình TF Official.

SLN318898_en_US__3hình ảnh(12053)
Hình 3: Với cách tiếp cận mới, có thể mong đợi tỷ lệ gần với tỷ lệ tuyến tính.

Như có thể thấy, có một thành công đáng kể về hiệu suất và hoàn toàn không có sự thay đổi quy mô nào với phương pháp cũ. GPU thường ít hoặc không được sử dụng, khiến hiệu suất giảm xuống. Làm cho tính toán hiệu quả hơn trên một GPU có nghĩa là làm cho tính toán hiệu quả hơn trên nhiều GPU trên nhiều nút, nếu giao tiếp được xử lý tốt.
Để CPU thực hiện quá trình tiền xử lý song song, tìm nạp trước dữ liệu đã xử lý trong bộ nhớ & GPU thực hiện công việc nặng nhọc của phép nhân ma trận với giao tiếp nhanh là một khía cạnh khác khiến phương pháp mới này trở nên hấp dẫn hơn để mở rộng quy mô cho đa nút.

 


Các kỹ thuật khác cần được xem xét để đạt được hiệu suất tối ưu:

 

Có môi trường phù hợp là rất quan trọng:

Môi trường điều hành công việc của bạn cũng quan trọng như công việc của bạn, bởi vì việc có các thư viện/mô-đun phù hợp rất quan trọng vì chúng sẽ tác động đến hiệu suất đào tạo. Ngoài ra, việc có các thư viện liên quan đến CUDA mới nhất có thể giúp cải thiện hiệu suất.

Làm theo hướng dẫn này để cài đặt, nếu bạn chưa thiết lập môi trường làm việc.

 

Sử dụng các tham số ràng buộc chính xác cho MPI:

MPI là một thư viện liên lạc hỗ trợ horovod phân phối công việc. Các tùy chọn tham số liên kết và ánh xạ khác nhau đã được khám phá và các tham số tốt nhất cho C4140 là ánh xạ theo ổ cắm. Cài đặt được đề xuất như sau:
mpirun --map-by socket -np x python pyfile.py --pyoptions

 

Đảm bảo một quy trình hoạt động trên một GPU:

Nếu có nhiều hơn một quy trình đang hoạt động trên một gpu, thì rất có thể chúng đang tranh giành tài nguyên GPU, tiêu tốn bộ nhớ GPU và không thể khớp nhiều hình ảnh hơn mỗi đợt một cách hiệu quả, do đó chịu trách nhiệm làm cho hiệu suất GPU bị ảnh hưởng. Tensorflow 1.13.1 đã được khám phá, nhưng có vẻ như nó có lỗi vào thời điểm đó. Nó đã khởi chạy nhiều hơn một quy trình trên mỗi GPU.

 

Tóm tắt:

  • Việc thiết lập chính xác đường dẫn dữ liệu là rất quan trọng để đạt được hiệu suất.
  • Thiết lập môi trường chính xác là một đóng góp tốt cho hiệu suất tốt hơn.
  • Sử dụng các tham số ràng buộc chính xác cho MPI giúp cải thiện hiệu suất.
  • Cấu hình và khắc phục tắc nghẽn khi GPU không được sử dụng hết.