Mẹo và thủ thuật để tối ưu hóa quy trình làm việc với TF và Horovod trên GPU

Sự miêu tả

Bài viết này sử dụng CheXNet làm ví dụ để tham khảo. CheXNet là một mô hình trợ lý bác sĩ X-quang AI sử dụng DenseNet để xác định tối đa 14 bệnh lý từ một hình ảnh X-quang ngực nhất định.

  1. Thiết lập môi trường chính xác có thể tiết kiệm một lượng lớn thời gian khi cố gắng gỡ lỗi các vấn đề về hiệu suất. Đảm bảo phiên bản GPU của khung học sâu đang được sử dụng. Trong ví dụ này, tensorflow-gpu do anaconda đóng gói đang được sử dụng.
  2. Sử dụng horovodrun hoặc mpirun với các tham số ràng buộc có thể mang lại hiệu suất tăng. Lý tưởng nhất là quá trình kiểm soát GPU phải được liên kết với ổ cắm CPU gần nhất. Trên Dell EMC PowerEdge C4140, tùy chọn tối ưu sẽ là –map-by socket. Không cần chỉ định bất kỳ tùy chọn ràng buộc nào.

    Nó sẽ trông giống như thế này: 

    mpirun –map-by socket -np x python pyfile.py – -pyoptions

  3. Công việc phải được thiết lập sao cho một quy trình MPI hoạt động trên một GPU. Nếu có nhiều quy trình hơn số lượng GPU, các quy trình sẽ tranh giành tài nguyên điện toán và sẽ không thể chạy công việc với hiệu suất tốt. Trong ví dụ trên, x phải bằng số lượng GPU được sử dụng.
  4. Để đặt một quy trình cho mỗi GPU, hãy sử dụng ConfigProto() của tensorflow như sau:

    config.gpu_options.visible_device_list=str(hvd.local_size())

  5. Để kiểm tra số lượng quy trình sử dụng GPU, có thể sử dụng mức tiêu thụ bộ nhớ của GPU ‘watch nvidia-smi’ . Điều này cũng cho phép xem mức tiêu thụ điện năng.

    SLN318900_en_US__1hình ảnh(12055)
    Hình 1: Ảnh chụp màn hình xuất lệnh nvidia-smi hiển thị mức sử dụng bộ nhớ, nguồn điện và GPU.

  6. Nếu đường dẫn dữ liệu được thiết lập chính xác và các thông số mpirun chính xác, thì mức sử dụng GPU sẽ luôn vượt quá 90% sau khi quá trình đào tạo mô hình bắt đầu. Đôi khi giảm xuống mức sử dụng 10-25% có thể chấp nhận được, nhưng chúng không nên thường xuyên.
  7. Đặt kích thước lô sao cho bộ nhớ GPU gần đầy nhưng có giới hạn để không vượt quá yêu cầu bộ nhớ. Điều quan trọng là phải xem xét cách thức thực hiện việc mở rộng tỷ lệ học tập. Chia tỷ lệ tốc độ học tập là khái niệm theo đó, khi số lượng GPU tăng lên, tốc độ học tập cũng phải được nhân với một hệ số tỷ lệ thuận với số lượng GPU. Điều này cho phép mô hình hội tụ hiệu quả. Bằng cách này, số lượng thao tác i/o được giảm bằng cách khớp số lượng hình ảnh tối đa có thể có trên một GPU mà không ảnh hưởng đến sự hội tụ của mô hình. Cần lưu ý rằng quy mô tỷ lệ học tập không phải lúc nào cũng là giải pháp tốt nhất để cải thiện sự hội tụ của mô hình trong cài đặt khối lượng công việc phân tán.
    Để kiểm tra xem có cần mở rộng tỷ lệ học tập hay không:

    a) Huấn luyện mô hình có và không có tỷ lệ học tập chia tỷ lệ trong chế độ phân tán.
    b) Nếu mô hình không chia tỷ lệ học tập hoạt động tốt hơn mô hình có chia tỷ lệ học tập, thì không cần mở rộng tỷ lệ học tập. 

    Đặc biệt, khi đào tạo để hội tụ, không phải lúc nào quy tắc bắt buộc cũng phải phù hợp với số lượng hình ảnh cao nhất có thể cho mỗi đợt. Thường có sự đánh đổi giữa kích thước lô và độ hội tụ (cho dù tỷ lệ học tập có được sử dụng hay không) mà nhà khoa học dữ liệu phải có khả năng quyết định dựa trên trường hợp sử dụng của họ.
    Một lần nữa, bạn có thể xem mức tiêu thụ bộ nhớ GPU bằng cách sử dụng ‘watch nvidia-smi’. Trong nghiên cứu điển hình này, tỷ lệ tốc độ học tập không được sử dụng vì nó mang lại mô hình tốt hơn với các giá trị AUC & kích thước lô nhỏ cục bộ là 64. Thông thường, các kỷ nguyên khởi động như được mô tả trong bài báo này , khi sử dụng tỷ lệ học tập.

  8. Lập hồ sơ công việc của bạn bằng cách sử dụng dòng thời gian horovod và nvprof  để xem bất kỳ tắc nghẽn nào có thể xảy ra. Nhiều khả năng, nút cổ chai là do một trong những điều sau đây:

    a) Đường ống dẫn dữ liệu Tf không được thiết lập tốt và do đó mất nhiều thời gian để chuẩn bị dữ liệu trong khi máy gia tốc không hoạt động. Để khắc phục điều này, đường ống tf phải được sửa chữa. 
    Vui lòng đọc bài viết này để biết thông tin về cách thiết lập đường dẫn dữ liệu tf. 

    b) Giao tiếp có thể không sử dụng đúng cấu trúc – đảm bảo bạn đang sử dụng InfiniBand , để xem cách sử dụng cấu trúc bao gồm –x NCCL_DEBUG=INFO trong khi chạy mpirun như sau:
            mpirun -np 8 –map-by socket -x NCCL_DEBUG= THÔNG TIN python $HOME/models/chexnet/chexnet.py –batch_size=128 –epochs=15
            hoặc sử dụng horovodrun bao gồm liên kết –x.

  9. Để triển khai phân phối đúng cách, GPU cần giao tiếp hiệu quả với nhau. Nếu họ không giao tiếp hiệu quả, điều này sẽ gây ra tắc nghẽn giao tiếp. Để kiểm tra xem liệu chúng có đang giao tiếp một cách tối ưu hay không, hãy sử dụng quy trình sau:

    Trước tiên, hãy xem cách GPU đang giao tiếp bằng cách sử dụng liên kết -x như đã thấy ở trên tại điểm 8b

    Nếu GPU đang giao tiếp:

    1) Trong nút theo cách tối ưu sẽ trông giống như thế này:  
    gpu002:1299562:1299573 [0] NCCL INFO Đổ chuông 00 : 0[0] -> 1[1] qua P2P/IPC
    2) Bên ngoài nút theo cách tối ưu sẽ trông giống như thế này:
    gpu028:149460:149495 [0] NCCL INFO Ring 01 : 16 -> 0 [gửi] qua NET/IB/0
    gpu009:164181:164216 [0] NCCL INFO Đổ chuông 01 : 12 -> 8 [nhận] qua NET/IB/0
    gpu009:164181:164216 [0] NCCL INFO Ring 01 : 4 -> 8 [nhận] qua NET/IB/0

Việc phân phối công việc học sâu của bạn đôi khi có thể là một thách thức, đặc biệt là khi số lượng nút/GPU được sử dụng không chuyển thành hiệu suất tương ứng một cách hiệu quả. Để đảm bảo rằng bạn có thể thu được nhiều nhất từ ​​khoản đầu tư vào máy gia tốc của mình, vui lòng đảm bảo rằng các phương pháp hay nhất sau đây được triển khai:

  • các tùy chọn ràng buộc chính xác được đưa ra,
  • đánh giá nhiều quy trình không lãng phí bộ nhớ GPU,
  • sử dụng phương pháp tiếp cận đường ống hiện đại,
  • lập hồ sơ để xem GPU được sử dụng ít nhất 80% thời gian công việc đang chạy,
  • sử dụng các thư viện liên quan đến CUDA mới nhất