Tôi là một trong những người đóng góp cho dự án mã nguồn mở Spark NLP và gần đây thư viện này bắt đầu hỗ trợ các mô hình Vision Transformers (ViT) end-to-end. Tôi sử dụng Spark NLP và các thư viện mã nguồn mở ML / DL khác cho công việc hàng ngày và tôi đã quyết định triển khai đường dẫn ViT cho nhiệm vụ phân loại hình ảnh hiện đại và cung cấp các so sánh chuyên sâu giữa Hugging Face và Spark NLP .
Mục đích của bài viết này là để chứng minh cách mở rộng mô hình Vision Transformer (ViT) từ Khuôn mặt ôm và triển khai chúng trong môi trường sẵn sàng sản xuất để tăng tốc và suy luận hiệu suất cao. Cuối cùng, chúng tôi sẽ mở rộng mô hình ViT từ Ôm khuôn mặt lên 25 lần (2300%) bằng cách sử dụng Databricks, Nvidia và Spark NLP.
Trong bài viết này tôi sẽ:
Với tinh thần minh bạch hoàn toàn, tất cả sổ ghi chép với nhật ký, ảnh chụp màn hình và thậm chí cả bảng excel có số đều được cung cấp tại đây trên GitHub
Quay trở lại năm 2017, một nhóm các nhà nghiên cứu tại Google AI đã xuất bản một bài báo giới thiệu kiến trúc mô hình biến áp thay đổi tất cả các tiêu chuẩn Xử lý ngôn ngữ tự nhiên (NLP). Bài báo mô tả một cơ chế mới được gọi là tự chú ý như một mô hình mới và hiệu quả hơn cho các ứng dụng ngôn ngữ. Ví dụ, hai trong số các họ mô hình dựa trên máy biến áp phổ biến nhất là GPT và BERT.
Một chút lịch sử của Transformer https://huggingface.co/course/chapter1/4
Có một chương rất hay về “ Cách thức hoạt động của người máy biến hình ” mà tôi rất khuyên bạn nên đọc nếu bạn quan tâm.
Mặc dù các mô hình dựa trên Transformer mới này dường như đang cách mạng hóa các tác vụ NLP, nhưng việc sử dụng chúng trong Computer Vision (CV) vẫn còn khá nhiều hạn chế. Lĩnh vực Thị giác máy tính đã bị chi phối bởi việc sử dụng mạng nơ-ron tích tụ (CNN) và có những kiến trúc phổ biến dựa trên CNN (như ResNet). Điều này đã xảy ra cho đến khi một nhóm các nhà nghiên cứu khác lần này tại Google Brain giới thiệu “Vision Transformer” (ViT) vào tháng 6 năm 2021 trong một bài báo có tiêu đề: “ An Image is Worth 16x16 Words: Transformers for Image Recognition in Scale ”
Bài báo này thể hiện một bước đột phá khi nói đến nhận dạng hình ảnh bằng cách sử dụng cùng một cơ chế tự chú ý được sử dụng trong các mô hình dựa trên máy biến áp như BERT và GPT như chúng ta vừa thảo luận. Trong các mô hình ngôn ngữ dựa trên Biến đổi như BERT, đầu vào là một câu (ví dụ: danh sách các từ). Tuy nhiên, trong các mô hình ViT, trước tiên, chúng tôi chia một hình ảnh thành một lưới các bản vá hình ảnh phụ, sau đó chúng tôi nhúng từng bản vá với một dự án tuyến tính trước khi mỗi bản vá được nhúng trở thành một mã thông báo. Kết quả là một chuỗi các bản vá lỗi nhúng mà chúng tôi chuyển vào mô hình tương tự như BERT.
Tổng quan về cấu trúc mô hình ViT như được giới thiệu trong bài báo gốc năm 2021 của Google Research
Vision Transformer tập trung vào độ chính xác cao hơn nhưng với thời gian tính toán ít hơn. Nhìn vào điểm chuẩn được công bố trong bài báo, chúng ta có thể thấy thời gian đào tạo dựa trên tập dữ liệu Noisy Student (được Google xuất bản vào tháng 6 năm 2020) đã giảm 80% mặc dù trạng thái chính xác ít nhiều như nhau. Để biết thêm thông tin về hiệu suất ViT ngày hôm nay, bạn nên truy cập trang của nó trên Papers With Code :
So sánh với hiện đại trên các tiêu chuẩn phân loại hình ảnh phổ biến. ( https://arxiv.org/pdf/2010.11929.pdf )
Điều quan trọng cần đề cập là một khi bạn đã đào tạo một mô hình thông qua kiến trúc ViT, bạn có thể đào tạo trước và tinh chỉnh máy biến áp của mình giống như bạn làm trong NLP. (Điều đó thực sự khá tuyệt!)
Nếu chúng ta so sánh các mô hình ViT với CNN, chúng ta có thể thấy rằng chúng có độ chính xác cao hơn với chi phí tính toán thấp hơn nhiều. Bạn có thể sử dụng các mô hình ViT cho nhiều tác vụ xuôi dòng trong Computer Vision như phân loại hình ảnh, phát hiện đối tượng và phân đoạn hình ảnh. Điều này cũng có thể là miền cụ thể trong Chăm sóc sức khỏe, bạn có thể đào tạo trước / tinh chỉnh các mô hình ViT của mình cho các trường hợp gãy xương đùi , khí phế thũng , ung thư vú , COVID-19 và bệnh Alzheimer .¹
Tôi sẽ để lại tài liệu tham khảo ở cuối bài viết này chỉ trong trường hợp bạn muốn tìm hiểu sâu hơn về cách hoạt động của các mô hình ViT.
[1]: Deep Dive: Vision Transformers trên khuôn mặt ôm Biểu đồ tối ưu https://huggingface.co/blog/vision-transformers
Mô hình Vision Transformer (ViT) ( vit-base-patch16–224 ) được đào tạo trước trên ImageNet-21k (14 triệu hình ảnh, 21.843 lớp) ở độ phân giải 224x224 và được tinh chỉnh trên ImageNet 2012 (1 triệu hình ảnh, 1.000 lớp) tại độ phân giải 224x224:
https://huggingface.co/google/vit-base-patch16-224
Các mô hình ViT tinh chỉnh được sử dụng để phân loại thực phẩm:
https://huggingface.co/nateraw/food - https://huggingface.co/julien-c/hotdog-not-hotdog
Tuy nhiên, có những giới hạn & hạn chế đối với bất kỳ mô hình DL / ML nào khi nói đến dự đoán. Không có mô hình nào có độ chính xác 100% vì vậy hãy lưu ý khi bạn sử dụng chúng cho những việc quan trọng như Chăm sóc sức khỏe:
Hình ảnh được lấy từ: https://www.akc.org/expert-advice/lifestyle/do-you-live-in-dog-state-or-cat-state/ - ViT model : https://huggingface.co / julien-c / hotdog-not-hotdog
Chúng ta có thể sử dụng các mô hình này từ Khuôn mặt ôm hoặc tinh chỉnh các mô hình ViT mới và sử dụng chúng để suy luận trong sản xuất thực tế không? Làm cách nào chúng ta có thể chia tỷ lệ chúng bằng cách sử dụng các dịch vụ được quản lý cho tính toán phân tán như AWS EMR, Azure Insight, GCP Dataproc hoặc Databricks?
Hy vọng rằng một số trong số này sẽ được giải đáp ở cuối bài viết này.
Một số chi tiết về điểm chuẩn của chúng tôi:
1- Tập dữ liệu: ImageNet mini: mẫu (> 3K) - đầy đủ (> 34K)
Tôi đã tải xuống bộ dữ liệu ImageNet 1000 (mini) từ Kaggle: https://www.kaggle.com/datasets/ifigotin/imagenetmini-1000
Tôi đã chọn thư mục tàu với hơn 34K hình ảnh và gọi nó là imagenet-mini vì tất cả những gì tôi cần là đủ hình ảnh để thực hiện các điểm chuẩn mất nhiều thời gian hơn. Ngoài ra, tôi đã chọn ngẫu nhiên ít hơn 10% của tập dữ liệu đầy đủ và gọi nó là imagenet-mini-sample có 3544 hình ảnh cho các điểm chuẩn nhỏ hơn của tôi và cũng để tinh chỉnh các thông số phù hợp như kích thước lô.
2- Mô hình: “ vit-base-patch16–224 ” của Google
Chúng tôi sẽ sử dụng mô hình này của Google được lưu trữ trên Hugging Face: https://huggingface.co/google/vit-base-patch16-224
3- Thư viện: Transformers 🤗 & Spark NLP 🚀
Mô hình ViT trên Dell PowerEdge C4130
Máy chủ kim loại trần là gì? Một máy chủ kim loại trần chỉ là một máy tính vật lý chỉ được sử dụng bởi một người dùng. Không có hypervisor nào được cài đặt trên máy này, không có ảo hóa và mọi thứ đang được thực thi trực tiếp trên hệ điều hành chính (Linux - Ubuntu) - thông số kỹ thuật chi tiết của CPU, GPU và bộ nhớ của máy này nằm trong máy tính xách tay.
Khi các thử nghiệm ban đầu của tôi cộng với hầu hết mọi bài đăng trên blog được viết bởi nhóm kỹ thuật Khuôn mặt ôm so sánh tốc độ suy luận giữa các công cụ DL đã tiết lộ, hiệu suất tốt nhất để suy luận trong thư viện Khuôn mặt ôm (Transformer) đạt được bằng cách sử dụng PyTorch qua TensorFlow. Tôi không chắc liệu điều này có phải do TensorFlow là công dân hạng hai trong Ôm mặt hay không do ít tính năng được hỗ trợ hơn, ít mô hình được hỗ trợ hơn, ít ví dụ hơn, hướng dẫn lỗi thời và các cuộc khảo sát hàng năm trong 2 năm qua được trả lời bởi những người dùng yêu cầu nhiều hơn về TensorFlow hoặc PyTorch chỉ có độ trễ suy luận thấp hơn trên cả CPU và GPU.
TensorFlow vẫn là khung học sâu được sử dụng nhiều nhất
Bất kể lý do là gì, tôi đã chọn PyTorch trong thư viện Khuôn mặt ôm để nhận được kết quả tốt nhất cho các tiêu chuẩn phân loại hình ảnh của chúng tôi. Đây là một đoạn mã đơn giản để sử dụng mô hình ViT (tất nhiên là PyTorch) trong Ôm mặt:
from transformers import ViTFeatureExtractor, ViTForImageClassification from PIL import Image import requests url = 'http://images.cocodataset.org/val2017/000000039769.jpg'
image = Image.open(requests.get(url, stream= True ).raw) feature_extractor = ViTFeatureExtractor.from_pretrained( 'google/vit-base-patch16-224' ) model = ViTForImageClassification.from_pretrained( 'google/vit-base-patch16-224' ) inputs = feature_extractor(images=image, return_tensors= "pt" ) outputs = model(**inputs) logits = outputs.logits # model predicts one of the 1000 ImageNet classes
predicted_class_idx = logits.argmax(- 1 ).item() print("Predicted class:", model.config.id2label [predicted_class_idx] )
Điều này có vẻ đơn giản để dự đoán một hình ảnh làm đầu vào, nhưng nó không phù hợp với lượng hình ảnh lớn hơn, đặc biệt là trên GPU. Để tránh dự đoán hình ảnh một cách tuần tự và để tận dụng phần cứng được tăng tốc như GPU, tốt nhất là cung cấp cho mô hình các lô hình ảnh có thể thực hiện được trong chế độ Ôm mặt qua Đường ống . Không cần phải nói, bạn có thể thực hiện kỹ thuật trộn của mình bằng cách kéo dài Đường ống của Khuôn mặt Ôm hoặc tự mình thực hiện.
Một đường dẫn đơn giản cho Phân loại hình ảnh sẽ giống như sau:
from transformers import ViTFeatureExtractor, ViTForImageClassification from transformers import pipeline feature_extractor = ViTFeatureExtractor.from_pretrained( 'google/vit-base-patch16-224' ) model = ViTForImageClassification.from_pretrained( 'google/vit-base-patch16-224' ) pipe = pipeline( "image-classification" , model=model, feature_extractor=feature_extractor, device=- 1 )
Theo tài liệu, tôi đã tải xuống / tải google / vit-base-patch16–224 cho trình trích xuất tính năng và mô hình (tất nhiên là các điểm kiểm tra PyTorch) để sử dụng chúng trong đường dẫn với phân loại hình ảnh làm nhiệm vụ. Có 3 điều trong quy trình này quan trọng đối với điểm chuẩn của chúng tôi:
> device : Nếu là -1 (mặc định), nó sẽ chỉ sử dụng CPU trong khi nếu là số int dương, nó sẽ chạy mô hình trên id thiết bị CUDA được liên kết. (tốt nhất là ẩn GPU và buộc PyTorch sử dụng CPU chứ không chỉ dựa vào con số này ở đây).
> batch_size: Khi đường ống sẽ sử dụng DataLoader (khi truyền tập dữ liệu, trên GPU đối với mô hình Pytorch), kích thước của lô sẽ sử dụng, theo suy luận không phải lúc nào cũng có lợi.
> Bạn phải sử dụng DataLoader hoặc PyTorch Dataset để tận dụng tối đa lợi thế của việc chia lô trong các đường ống ôm trên khuôn mặt trên GPU.
Trước khi chúng ta tiếp tục với các điểm chuẩn, bạn cần biết một điều liên quan đến việc phân lô trong Đường ống ôm mặt để suy luận, rằng nó không phải lúc nào cũng hoạt động. Như đã nêu trong tài liệu của Hugging Face, việc đặt batch_size có thể không làm tăng hiệu suất của đường dẫn của bạn chút nào. Nó có thể làm chậm đường dẫn của bạn:
https://huggingface.co/docs/transformers/main_classes/pipelines#pipeline-batching
Công bằng mà nói, trong các điểm chuẩn của tôi, tôi đã sử dụng một loạt các kích thước lô bắt đầu từ 1 để đảm bảo rằng tôi có thể tìm thấy kết quả tốt nhất trong số đó. Đây là cách tôi đánh giá điểm chuẩn của đường dẫn khuôn mặt ôm trên CPU:
from transformers import pipeline pipe = pipeline( "image-classification" , model=model, feature_extractor=feature_extractor, device=- 1 ) for batch_size in [ 1 , 8 , 32 , 64 , 128 ]: print ( "-" * 30 ) print ( f"Streaming batch_size= {batch_size} " ) for out in tqdm(pipe(dataset, batch_size=batch_size), total= len (dataset)): pass
Hãy cùng xem kết quả của điểm chuẩn đầu tiên của chúng tôi cho quy trình phân loại hình ảnh Khuôn mặt ôm trên CPU qua tập dữ liệu ImageNet mẫu (3K):
Đường ống phân loại hình ảnh Hugging Face trên CPU - dự đoán 3544 hình ảnh
Như có thể thấy, mất khoảng 3 phút ( 188 giây) để xử lý xong khoảng 3544 hình ảnh từ tập dữ liệu mẫu. Bây giờ tôi đã biết kích thước lô (8) nào là tốt nhất cho đường ống / tập dữ liệu / phần cứng của mình, tôi có thể sử dụng cùng một đường dẫn trên tập dữ liệu lớn hơn ( hình ảnh 34K ) với kích thước lô này:
Đường ống phân loại hình ảnh khuôn mặt ôm trên CPU - dự đoán 34745 hình ảnh
Lần này mất khoảng 31 phút ( 1.879 giây ) để hoàn thành dự đoán các lớp cho 34745 hình ảnh trên CPU.
Để cải thiện hầu hết các mô hình học sâu, đặc biệt là các mô hình dựa trên máy biến áp mới này, người ta nên sử dụng phần cứng tăng tốc như GPU. Chúng ta hãy xem cách đánh giá điểm chuẩn của cùng một đường dẫn trên cùng một bộ dữ liệu nhưng lần này là trên một thiết bị GPU . Như đã đề cập trước đây, chúng ta cần thay đổi thiết bị thành id thiết bị CUDA như 0 (GPU đầu tiên):
from transformers import ViTFeatureExtractor, ViTForImageClassification from transformers import pipeline import torch device = "cuda:0" if torch.cuda.is_available() else "cpu"
print (device) feature_extractor = ViTFeatureExtractor.from_pretrained( 'google/vit-base-patch16-224' ) model = ViTForImageClassification.from_pretrained( 'google/vit-base-patch16-224' ) model = model.to(device) pipe = pipeline( "image-classification" , model=model, feature_extractor=feature_extractor, device= 0 ) for batch_size in [ 1 , 8 , 32 , 64 , 128 , 256 , 512 , 1024 ]: print ( "-" * 30 ) print ( f"Streaming batch_size= {batch_size} " ) for out in tqdm(pipe(dataset, batch_size=batch_size), total= len (dataset)): pass
Ngoài việc đặt thiết bị = 0, tôi cũng đã làm theo cách được khuyến nghị để chạy mô hình PyTorch trên thiết bị GPU thông qua .to (thiết bị). Vì chúng tôi đang sử dụng phần cứng tăng tốc (GPU) nên tôi cũng đã tăng kích thước lô tối đa cho các thử nghiệm của mình lên 1024 để tìm ra kết quả tốt nhất.
Chúng ta hãy xem quy trình phân loại hình ảnh Khuôn mặt ôm của chúng tôi trên thiết bị GPU qua tập dữ liệu ImageNet mẫu (3K):
Đường ống phân loại hình ảnh Khuôn mặt ôm trên GPU - dự đoán 3544 hình ảnh
Như có thể thấy, mất khoảng 50 giây để xử lý xong khoảng 3544 hình ảnh từ tập dữ liệu mẫu mini-imagenet của chúng tôi trên thiết bị GPU . Lô cải thiện tốc độ đặc biệt là so với kết quả đến từ CPU, tuy nhiên, các cải tiến dừng lại ở kích thước lô là 32. Mặc dù kết quả giống nhau sau kích thước lô 32, tôi đã chọn kích thước lô 256 cho điểm chuẩn lớn hơn của mình để sử dụng đủ bộ nhớ GPU.
Đường ống phân loại hình ảnh Khuôn mặt ôm trên GPU - dự đoán 34745 hình ảnh
Lần này điểm chuẩn của chúng tôi mất khoảng 8:17 phút ( 497 giây ) để hoàn thành dự đoán các lớp cho 34745 hình ảnh trên thiết bị GPU . Nếu chúng tôi so sánh kết quả từ điểm chuẩn của chúng tôi trên CPU và thiết bị GPU, chúng tôi có thể thấy rằng GPU ở đây là người chiến thắng:
Khuôn mặt ôm (PyTorch) nhanh hơn tới 3,9 lần trên GPU so với CPU
Tôi đã sử dụng Đường ống ôm mặt để tải các điểm kiểm tra ViT PyTorch, tải dữ liệu của tôi vào tập dữ liệu đèn pin và sử dụng lô được cung cấp sẵn cho mô hình trên cả CPU và GPU. GPU nhanh hơn tới ~ 3,9 lần so với chạy cùng một đường ống trên CPU.
Chúng tôi đã cải thiện đường dẫn ViT của mình để thực hiện phân loại hình ảnh bằng cách sử dụng thiết bị GPU thay vì CPU, nhưng liệu chúng ta có thể cải thiện đường dẫn của mình hơn nữa trên cả CPU và GPU trong một máy trước khi mở rộng ra nhiều máy không? Hãy cùng xem thư viện Spark NLP.
Spark NLP là một thư viện xử lý ngôn ngữ tự nhiên hiện đại mã nguồn mở ( https://github.com/JohnSnowLabs/spark-nlp )
Spark NLP là một thư viện Xử lý Ngôn ngữ Tự nhiên hiện đại được xây dựng trên Apache Spark. Nó cung cấp các chú thích NLP đơn giản, hiệu quả và chính xác cho các đường ống học máy có thể mở rộng quy mô dễ dàng trong môi trường phân tán. Spark NLP đi kèm với hơn 7000 đường ống và mô hình được đào tạo trước bằng hơn 200 ngôn ngữ . Nó cũng cung cấp các tác vụ như Mã hóa, Phân đoạn từ, Gắn thẻ một phần giọng nói, Nhúng từ và câu, Nhận dạng đối tượng được đặt tên, Phân tích cú pháp phụ thuộc, Kiểm tra chính tả, Phân loại văn bản, Phân tích tình cảm, Phân loại mã thông báo, Dịch máy (+180 ngôn ngữ), Tóm tắt & Trả lời câu hỏi, Tạo văn bản, Phân loại hình ảnh (ViT) và nhiều tác vụ NLP khác .
Spark NLP là thư viện NLP mã nguồn mở duy nhất được sản xuất cung cấp các máy biến áp hiện đại như BERT , CamemBERT , ALBERT , ELECTRA , XLNet , DistilBERT , RoBERTa , DeBERTa , XLM-RoBERTa , Longformer , ELMO , Universal Câu Encoder , Google T5 , MarianMT , GPT2 và Vision Transformer ( ViT ) không chỉ cho Python và R , mà còn cho hệ sinh thái JVM ( Java , Scala và Kotlin ) trên quy mô lớn bằng cách mở rộng Apache Spark nguyên bản.
Các mô hình ViT trên Dell PowerEdge C4130
Spark NLP có các tính năng ViT tương tự để Phân loại hình ảnh như Khuôn mặt ôm đã được thêm vào trong bản phát hành 4.1.0 gần đây. Tính năng này được gọi là ViTForImageClassification, nó có hơn 240 mô hình được đào tạo trước sẵn sàng hoạt động và một mã đơn giản để sử dụng tính năng này trong Spark NLP trông như sau:
from sparknlp.annotator import * from sparknlp.base import * from pyspark.ml import Pipeline imageAssembler = ImageAssembler() \ .setInputCol( "image" ) \ .setOutputCol( "image_assembler" ) imageClassifier = ViTForImageClassification \ .pretrained( "image_classifier_vit_base_patch16_224" ) \ .setInputCols( "image_assembler" ) \ .setOutputCol( "class" ) \ .setBatchSize( 8 ) pipeline = Pipeline(stages=[ imageAssembler, imageClassifier ])
Nếu chúng ta so sánh Spark NLP và Hugging Face cạnh nhau để tải xuống và tải một mô hình ViT được đào tạo trước cho dự đoán Phân loại hình ảnh, ngoài việc tải hình ảnh và sử dụng các phép tính bài đăng như argmax bên ngoài thư viện Khuôn mặt ôm, cả hai đều khá đơn giản. Ngoài ra, cả hai đều có thể được lưu và phục vụ sau này như một đường dẫn để giảm các dòng này thành chỉ 1 dòng mã:
Tải và sử dụng các mô hình ViT để Phân loại hình ảnh trong Spark NLP (trái) và Khuôn mặt ôm (phải)
Vì Apache Spark có một khái niệm gọi là Đánh giá Lười biếng nên nó không bắt đầu thực hiện quy trình cho đến khi một HÀNH ĐỘNG được gọi. Các hành động trong Apache Spark có thể là .count () hoặc .show () hoặc .write () và rất nhiều thao tác dựa trên RDD khác mà tôi sẽ không trình bày ngay bây giờ và bạn sẽ không cần biết chúng trong bài viết này. Tôi thường chọn đếm () cột mục tiêu hoặc ghi () kết quả trên đĩa để kích hoạt thực thi tất cả các hàng trong DataFrame. Ngoài ra, giống như điểm chuẩn của Ôm khuôn mặt, tôi sẽ lặp lại các kích thước lô đã chọn để đảm bảo rằng tôi có thể có tất cả các kết quả có thể mà không bỏ lỡ kết quả tốt nhất.
Bây giờ, chúng tôi biết cách tải (các) mô hình ViT trong Spark NLP, chúng tôi cũng biết cách kích hoạt một hành động để buộc tính toán trên tất cả các hàng trong DataFrame của chúng tôi thành điểm chuẩn và tất cả những gì còn lại để tìm hiểu là oneDNN từ oneAPI Deep Neural Thư viện mạng (oneDNN) . Vì công cụ DL trong Spark NLP là TensorFlow, bạn cũng có thể kích hoạt oneDNN để cải thiện tốc độ trên CPU (giống như mọi thứ khác, bạn cần kiểm tra điều này để chắc chắn rằng nó cải thiện tốc độ chứ không phải ngược lại). Tôi cũng sẽ sử dụng cờ này ngoài các CPU bình thường mà không bật oneDNN
Bây giờ chúng ta đã biết tất cả các mô hình ViT từ Hugging Face cũng có sẵn trong Spark NLP và cách sử dụng chúng trong một quy trình, chúng tôi sẽ lặp lại các điểm chuẩn trước đây trên máy chủ Dell bằng kim loại để so sánh CPU và GPU. Hãy cùng xem kết quả phân loại hình ảnh của Spark NLP trên CPU qua tập dữ liệu ImageNet mẫu (3K) của chúng tôi:
Spark NLP đường ống phân loại hình ảnh trên CPU không có oneDNN - dự đoán 3544 hình ảnh
Mất khoảng 2,1 phút ( 130 giây) để xử lý xong khoảng 3544 hình ảnh từ tập dữ liệu mẫu của chúng tôi. Có một tập dữ liệu nhỏ hơn để thử các kích thước lô khác nhau sẽ hữu ích để chọn kích thước lô phù hợp cho tác vụ, tập dữ liệu và máy của bạn. Rõ ràng là kích thước lô 16 là kích thước tốt nhất để đường ống của chúng tôi mang lại kết quả tốt nhất.
Tôi cũng muốn bật oneDNN để xem liệu trong tình huống cụ thể này, nó có cải thiện điểm chuẩn của tôi so với các CPU không có oneDNN hay không. Bạn có thể bật oneDNN trong Spark NLP bằng cách đặt biến môi trường của TF_ENABLE_ONEDNN_OPTS thành 1. Hãy xem điều gì sẽ xảy ra nếu tôi bật cờ này và chạy lại điểm chuẩn trước đó trên CPU để tìm kích thước lô tốt nhất:
Spark NLP đường ống phân loại hình ảnh trên CPU với oneDNN - dự đoán 3544 hình ảnh
Được rồi, rõ ràng việc bật oneDNN cho TensorFlow trong tình huống cụ thể này đã cải thiện kết quả của chúng tôi ít nhất 14%. Vì chúng tôi không phải làm / thay đổi bất cứ điều gì và tất cả những gì cần thiết là xuất TF_ENABLE_ONEDNN_OPTS = 1 Tôi sẽ sử dụng nó cho điểm chuẩn với một tập dữ liệu lớn hơn cũng như để thấy sự khác biệt. Ở đây nhanh hơn khoảng vài giây, nhưng 14% trên tập dữ liệu lớn hơn có thể làm mất đi vài phút kết quả của chúng tôi.
Bây giờ tôi biết kích thước lô là 16 cho CPU không có oneDNN và kích thước lô là 2 cho CPU có bật oneDNN có kết quả tốt nhất mà tôi có thể tiếp tục bằng cách sử dụng cùng một đường dẫn trên tập dữ liệu lớn hơn ( 34K hình ảnh ):
Đường ống phân loại hình ảnh Spark NLP trên CPU không có oneDNN - dự đoán 34745 hình ảnh
Lần này, điểm chuẩn của chúng tôi mất khoảng 24 phút ( 1423 giây ) để hoàn thành dự đoán các lớp cho 34745 hình ảnh trên thiết bị CPU mà không bật oneDNN. Bây giờ, hãy xem điều gì sẽ xảy ra nếu tôi bật oneDNN cho TensorFlow và sử dụng kích thước lô là 2 (kết quả tốt nhất):
Đường ống phân loại hình ảnh Spark NLP trên CPU với oneDNN - dự đoán 34745 hình ảnh
Lần này mất khoảng 21 phút ( 1278 giây ). Như mong đợi từ các điểm chuẩn mẫu của chúng tôi, chúng tôi có thể thấy khoảng 11% cải thiện trong kết quả, điều này đã giảm bớt vài phút so với việc không bật oneDNN.
Hãy cùng xem cách đánh giá đường dẫn tương tự trên một thiết bị GPU. Trong Spark NLP, tất cả những gì bạn cần để sử dụng GPU là khởi động nó bằng gpu = True khi bạn bắt đầu phiên Spark NLP:
spark = sparknlp.start (gpu = True)
# bạn cũng có thể đặt bộ nhớ ở đây
spark = sparknlp.start (gpu = True, memory = "16g")
Đó là nó! Nếu bạn có thứ gì đó trong đường dẫn của mình có thể chạy trên GPU, nó sẽ tự động làm điều đó mà không cần phải làm bất cứ điều gì rõ ràng.
Hãy cùng xem đường dẫn phân loại hình ảnh Spark NLP của chúng tôi trên thiết bị GPU qua tập dữ liệu ImageNet mẫu (3K):
Hệ thống phân loại hình ảnh Spark NLP trên GPU - dự đoán 3544 hình ảnh
Vì tò mò muốn biết liệu cuộc thập tự chinh của tôi để tìm kích thước lô tốt trên một tập dữ liệu nhỏ hơn có đúng hay không, tôi đã chạy cùng một đường dẫn với GPU trên tập dữ liệu lớn hơn để xem liệu kích thước lô 32 sẽ có kết quả tốt nhất hay không:
Đường ống phân loại hình ảnh Spark NLP trên GPU - dự đoán 34745 hình ảnh
Rất may, đó là kích thước lô 32 mang lại thời gian tốt nhất. Vì vậy, nó mất khoảng 4 phút rưỡi ( 277 giây).
Tôi sẽ chọn kết quả từ các CPU có oneDNN vì chúng nhanh hơn và tôi sẽ so sánh chúng với kết quả GPU :
Spark NLP (TensorFlow) nhanh hơn tới 4,6 lần trên GPU so với CPU (oneDNN)
Điều đó thật tuyệt! Chúng ta có thể thấy Spark NLP trên GPU nhanh hơn gấp 4,6 lần so với CPU ngay cả khi bật oneDNN.
Hãy cùng xem những kết quả này được so sánh như thế nào với điểm chuẩn của tính năng Ôm trên khuôn mặt:
Spark NLP nhanh hơn 65% so với Ôm mặt trên CPU trong việc dự đoán các lớp hình ảnh cho tập dữ liệu mẫu với hình ảnh 3K và 47% trên tập dữ liệu lớn hơn với hình ảnh 34K. Spark NLP cũng nhanh hơn 79% so với Ôm mặt trên một GPU duy nhất, suy ra tập dữ liệu lớn hơn với 34K hình ảnh và nhanh hơn tới 35% trên tập dữ liệu nhỏ hơn.
Spark NLP nhanh hơn Ôm khuôn mặt trong một máy bằng cách sử dụng CPU hoặc GPU - phân loại hình ảnh bằng cách sử dụng Vision Transformer (ViT)
Databricks là gì? Tất cả dữ liệu, phân tích và AI của bạn trên một nền tảng
Databricks là một nền tảng dựa trên Đám mây với một bộ công cụ kỹ thuật dữ liệu & khoa học dữ liệu được nhiều công ty sử dụng rộng rãi để xử lý và chuyển đổi một lượng lớn dữ liệu. Người dùng sử dụng Databricks cho nhiều mục đích từ xử lý và chuyển đổi một lượng lớn dữ liệu đến chạy nhiều đường ống ML / DL để khám phá dữ liệu.
Tuyên bố từ chối trách nhiệm: Đây là cách giải thích của tôi về Databricks, nó đi kèm với rất nhiều tính năng khác và bạn nên xem chúng: https://www.databricks.com/product/data-lakehouse
Databricks hỗ trợ đám mây AWS, Azure và GCP: https://www.databricks.com/product/data-lakehouse
Ôm khuôn mặt trong Databricks Single Node với CPU trên AWS
Databricks cung cấp loại cụm “Single Node” khi bạn tạo một cụm phù hợp cho những người muốn sử dụng Apache Spark chỉ với 1 máy hoặc sử dụng các ứng dụng không phải spark, đặc biệt là các thư viện Python dựa trên ML và DL. Hugging Face đã được cài đặt sẵn khi bạn chọn thời gian chạy Databricks 11.1 ML. Đây là cấu hình cụm trông như thế nào đối với Mã dữ liệu nút đơn của tôi (chỉ CPU) trước khi chúng tôi bắt đầu điểm chuẩn của mình:
Cụm nút đơn Databricks - Thời gian chạy CPU
Tóm tắt về cụm này sử dụng phiên bản m5n.8xlarge trên AWS là nó có 1 Trình điều khiển (chỉ 1 nút), 128 GB bộ nhớ, 32 lõi CPU và chi phí 5,71 DBU mỗi giờ. Bạn có thể đọc về “DBU” trên AWS tại đây: https://www.databricks.com/product/aws-pricing
Databricks một cụm - hồ sơ cá thể AWS
Hãy sao chép các điểm chuẩn của chúng tôi từ phần trước (máy chủ Dell bằng kim loại thô) tại đây trên Databricks một nút của chúng tôi (chỉ dành cho CPU). Chúng tôi bắt đầu với Khuôn mặt ôm và tập dữ liệu ImageNet có kích thước mẫu của chúng tôi để tìm ra kích thước lô nào là kích thước tốt để chúng tôi có thể sử dụng nó cho tập dữ liệu lớn hơn vì đây đã là một thực tiễn đã được chứng minh trong các điểm chuẩn trước đây:
Đường ống phân loại hình ảnh Hugging Face trên các CPU một nút Databricks - dự đoán 3544 hình ảnh
Mất khoảng 2 phút rưỡi ( 149 giây ) để xử lý xong khoảng 3544 hình ảnh từ tập dữ liệu mẫu của chúng tôi trên Databricks một nút chỉ sử dụng CPU . Kích thước lô tốt nhất trên máy này chỉ sử dụng CPU là 8 , vì vậy tôi sẽ sử dụng kích thước đó để chạy điểm chuẩn trên tập dữ liệu lớn hơn:
Đường ống phân loại hình ảnh Hugging Face trên các CPU một nút của Databricks - dự đoán 34745 hình ảnh
Trên tập dữ liệu lớn hơn với hơn 34K hình ảnh, mất khoảng 20 phút rưỡi ( 1233 giây ) để hoàn thành dự đoán các lớp cho những hình ảnh đó. Đối với điểm chuẩn tiếp theo của chúng tôi, chúng tôi cần có một cụm Databricks một nút, nhưng lần này chúng tôi cần có thời gian chạy dựa trên GPU và chọn một phiên bản AWS dựa trên GPU.
Ôm khuôn mặt trong Databricks Single Node với GPU trên AWS
Hãy tạo một cụm mới và lần này chúng ta sẽ chọn thời gian chạy với GPU mà trong trường hợp này được gọi là 11.1 ML (bao gồm Apache Spark 3.3.0, GPU, Scala 2.12) và nó đi kèm với tất cả phần mềm CUDA và NVIDIA cần thiết được cài đặt. Điều tiếp theo chúng ta cần là chọn một phiên bản AWS có GPU và tôi đã chọn g4dn.8xlarge có 1 GPU và số lõi / bộ nhớ tương tự như cụm còn lại. Phiên bản GPU này đi kèm với Tesla T4 và bộ nhớ 16 GB ( 15 GB bộ nhớ GPU khả dụng).
Cụm nút đơn Databricks - Thời gian chạy GPU
Đây là tóm tắt về cụm nút đơn của chúng tôi giống như cụm trước và nó giống nhau về số lõi và dung lượng bộ nhớ, nhưng nó đi kèm với GPU Tesla T4:
Cụm nút đơn Databricks - Hồ sơ cá thể AWS
Bây giờ chúng ta đã có một cụm nút đơn với GPU, chúng ta có thể tiếp tục các điểm chuẩn của mình để xem cách Ôm mặt hoạt động trên máy này trong Databricks. Tôi sẽ chạy điểm chuẩn trên tập dữ liệu nhỏ hơn để xem kích thước lô nào phù hợp hơn cho máy dựa trên GPU của chúng tôi:
Đường ống phân loại hình ảnh Hugging Face trên CPU một nút Databricks - dự đoán 3544 hình ảnh
Mất khoảng một phút ( 64 giây ) để xử lý xong khoảng 3544 hình ảnh từ tập dữ liệu mẫu của chúng tôi trên cụm Databricks một nút của chúng tôi với thiết bị GPU. Lô hàng cải thiện tốc độ nếu chúng ta nhìn vào kết quả kích thước lô 1, tuy nhiên, sau kích thước lô 8, kết quả vẫn giữ nguyên. Mặc dù kết quả giống nhau sau kích thước lô 8, tôi đã chọn kích thước lô 256 cho điểm chuẩn lớn hơn của mình để sử dụng nhiều bộ nhớ GPU hơn. (thành thật mà nói, 8 và 256 đều hoạt động khá giống nhau)
Hãy chạy điểm chuẩn trên tập dữ liệu lớn hơn và xem điều gì xảy ra với kích thước lô 256:
Đường ống phân loại hình ảnh Hugging Face trên CPU một nút Databricks - dự đoán 34745 hình ảnh
Trên một tập dữ liệu lớn hơn, phải mất gần 11 phút ( 659 giây ) để hoàn thành dự đoán các lớp cho hơn 34K hình ảnh. Nếu chúng tôi so sánh kết quả từ các điểm chuẩn của chúng tôi trên một nút duy nhất với CPU và một nút duy nhất đi kèm với 1 GPU, chúng tôi có thể thấy rằng nút GPU ở đây là người chiến thắng:
Khuôn mặt ôm (PyTorch) nhanh hơn tới 2,3 lần trên GPU so với CPU
GPU nhanh hơn đến ~ 2,3 lần so với chạy cùng một đường dẫn trên CPU ở chế độ ôm mặt trên Databricks Single Node
Bây giờ chúng ta sẽ chạy các điểm chuẩn giống nhau bằng cách sử dụng Spark NLP trong cùng các cụm và trên cùng bộ dữ liệu để so sánh nó với Khuôn mặt ôm.
Đầu tiên, hãy cài đặt Spark NLP trong CPU Single Node Databricks của bạn:
Trong tab Thư viện bên trong cụm của bạn, bạn cần làm theo các bước sau:
- Cài đặt Mới -> PyPI -> spark-nlp == 4.1.0 -> Cài đặt
- Cài đặt Mới -> Maven -> Tọa độ -> com.johnsnowlabs.nlp: spark-nlp_2.12: 4.1.0 -> Cài đặt
- Sẽ thêm ` TF_ENABLE_ONEDNN_OPTS = 1 'vào` Cluster-> Advacend Options-> Spark-> Môi trường biến` để kích hoạt oneDNN
Cách cài đặt Spark NLP trong Databricks trên CPU cho Python, Scala và Java
Spark NLP trong Databricks Single Node với CPU trên AWS
Bây giờ chúng tôi đã cài đặt Spark NLP trên cụm nút đơn Databricks của mình, chúng tôi có thể lặp lại các điểm chuẩn cho một bộ dữ liệu mẫu và đầy đủ trên cả CPU và GPU. Trước tiên, hãy bắt đầu với điểm chuẩn trên CPU qua tập dữ liệu mẫu:
Đường ống phân loại hình ảnh Spark NLP trên các CPU một nút Databricks (oneDNN) - dự đoán 3544 hình ảnh
Mất khoảng 2 phút ( 111 giây ) để xử lý xong 3544 hình ảnh và dự đoán các lớp của chúng trên cùng một cụm Databricks một nút với các CPU mà chúng tôi sử dụng để Ôm mặt. Chúng ta có thể thấy rằng kích thước lô là 16 có kết quả tốt nhất vì vậy tôi sẽ sử dụng điều này trong điểm chuẩn tiếp theo trên tập dữ liệu lớn hơn:
Đường ống phân loại hình ảnh Spark NLP trên các CPU một nút Databricks (oneDNN) - dự đoán 34742 hình ảnh
Trên tập dữ liệu lớn hơn với hơn 34K hình ảnh , mất khoảng 18 phút ( 1072 giây ) để hoàn thành dự đoán các lớp cho những hình ảnh đó. Tiếp theo, tôi sẽ lặp lại các điểm chuẩn tương tự trên cụm với GPU.
Databricks Single Node với GPU trên AWS
Trước tiên, hãy cài đặt Spark NLP trong GPU Mã dữ liệu nút đơn của bạn (sự khác biệt duy nhất là việc sử dụng “ spark-nlp-gpu” từ Maven):
Cài đặt Spark NLP trong cụm Databricks của bạn
- Trong tab Thư viện bên trong cụm, bạn cần làm theo các bước sau:
- Cài đặt Mới -> PyPI -> spark-nlp == 4.1.0 -> Cài đặt
- Cài đặt Mới -> Maven -> Tọa độ -> com.johnsnowlabs.nlp: spark-nlp-gpu_2.12: 4.1.0 -> Cài đặt
Cách cài đặt Spark NLP trong Databricks trên GPU cho Python, Scala và Java
Tôi sẽ chạy điểm chuẩn trên tập dữ liệu nhỏ hơn để xem kích thước lô nào phù hợp hơn cho máy dựa trên GPU của chúng tôi:
Đường ống phân loại hình ảnh Spark NLP trên GPU một nút Databricks - dự đoán 3544 hình ảnh
Chỉ mất chưa đến một phút ( 47 giây ) để xử lý xong khoảng 3544 hình ảnh từ tập dữ liệu mẫu trên Databricks một nút của chúng tôi bằng thiết bị GPU. Chúng tôi có thể thấy rằng kích thước lô 8 hoạt động tốt nhất trong trường hợp sử dụng cụ thể này, vì vậy tôi sẽ chạy điểm chuẩn trên tập dữ liệu lớn hơn:
Đường ống phân loại hình ảnh Spark NLP trên GPU một nút Databricks - dự đoán 34742 hình ảnh
Trên một tập dữ liệu lớn hơn, phải mất gần 7 phút rưỡi ( 435 giây ) để hoàn thành dự đoán các lớp cho hơn 34K hình ảnh . Nếu chúng tôi so sánh kết quả từ các điểm chuẩn của chúng tôi trên một nút duy nhất với CPU và một nút duy nhất đi kèm với 1 GPU, chúng tôi có thể thấy rằng nút GPU ở đây là người chiến thắng:
Spark NLP nhanh hơn tới 2,5 lần trên GPU so với CPU trong Databricks Single Node
Điều đó thật tuyệt! Chúng ta có thể thấy Spark NLP trên GPU nhanh hơn gấp 2,5 lần so với CPU ngay cả khi bật oneDNN (oneDNN cải thiện kết quả trên CPU từ 10% đến 20%).
Hãy cùng xem các kết quả này được so sánh như thế nào so với điểm chuẩn của Ôm trên khuôn mặt trong cùng một cụm Databricks Single Node:
Spark NLP nhanh hơn tới 15% so với Ôm mặt trên CPU trong việc dự đoán các lớp hình ảnh cho tập dữ liệu mẫu với hình ảnh 3K và lên đến 34% trên tập dữ liệu lớn hơn với hình ảnh 34K. Spark NLP cũng nhanh hơn 51% so với Ôm mặt trên một GPU duy nhất để có tập dữ liệu lớn hơn với hình ảnh 34K và nhanh hơn tới 36% trên tập dữ liệu nhỏ hơn với hình ảnh 3K.
Spark NLP nhanh hơn trên cả CPU và GPU so với Ôm khuôn mặt trong Databricks Single Node
Cho đến nay, chúng tôi khẳng định rằng tính năng Ôm mặt trên GPU nhanh hơn so với tính năng Ôm mặt trên CPU trên máy chủ kim loại trần và Nút đơn Databricks. Đây là những gì bạn mong đợi khi so sánh GPU với CPU với các mô hình dựa trên máy biến áp mới này.
Chúng tôi cũng đã xác nhận rằng Spark NLP hoạt động tốt hơn Hugging Face cho cùng một đường dẫn (mô hình ViT), trên cùng một bộ dữ liệu, trong cả máy chủ bare-metal và cụm nút đơn Databricks, đồng thời nó hoạt động tốt hơn trên cả thiết bị CPU và GPU. Mặt khác, điều này không phải là điều tôi mong đợi. Khi tôi chuẩn bị bài viết này, tôi mong đợi suy luận TensorFlow trong Spark NLP sẽ chậm hơn một chút so với suy luận trong Ôm mặt bằng cách sử dụng PyTorch hoặc ít nhất là cổ và cổ. Tôi đã nhắm đến phần này, mở rộng đường ống vượt ra ngoài một máy duy nhất . Nhưng có vẻ như Spark NLP nhanh hơn Ôm khuôn mặt ngay cả trong một máy duy nhất, trên cả CPU và GPU , trên cả tập dữ liệu nhỏ và lớn .
Câu hỏi: Điều gì xảy ra nếu bạn muốn làm cho đường dẫn ViT của mình nhanh hơn nữa? Điều gì sẽ xảy ra nếu bạn có bộ dữ liệu thậm chí lớn hơn và bạn không thể lắp chúng vào bên trong một máy hoặc chỉ mất quá nhiều thời gian để lấy lại kết quả?
Trả lời: Mở rộng quy mô! Điều này có nghĩa là thay vì thay đổi kích thước của cùng một máy, hãy thêm nhiều máy hơn vào cụm của bạn. Bạn cần một cái gì đó để quản lý tất cả các công việc / nhiệm vụ / lập lịch DAGs / quản lý các nhiệm vụ thất bại / v.v. và những thứ đó có chi phí chung, nhưng nếu bạn cần thứ gì đó nhanh hơn hoặc khả thi hơn (ngoài một máy duy nhất), bạn phải sử dụng một số loại hệ thống phân tán.
Mở rộng quy mô = làm cho máy của bạn lớn hơn hoặc nhanh hơn để có thể xử lý nhiều tải hơn.
Mở rộng quy mô = thêm nhiều máy song song để dàn đều một tải.
Nhìn vào trang trên Trang web chính thức của Hugging Face cho thấy chỉ có thể suy luận về tỷ lệ bằng cách sử dụng Đa GPU. Như chúng tôi mô tả việc mở rộng quy mô là gì, điều này vẫn còn bị mắc kẹt trong một máy duy nhất:
https://huggingface.co/docs/transformers/performance
Ngoài ra, chưa kể rằng giải pháp Đa GPU để suy luận trong Ôm khuôn mặt hiện không tồn tại:
https://huggingface.co/docs/transformers/perf_infer_gpu_many
Vì vậy, có vẻ như không có cách tự nhiên / chính thức để mở rộng các đường ống Hugging Face. Bạn có thể triển khai kiến trúc của mình bao gồm một số dịch vụ vi mô như hàng đợi công việc, giao thức nhắn tin, phần phụ trợ API RESTful và một số thành phần bắt buộc khác để phân phối từng yêu cầu trên các máy khác nhau, nhưng điều này sẽ chia tỷ lệ yêu cầu của từng người dùng thay vì mở rộng hệ thống thực tế chính nó.
Ngoài ra, độ trễ của các hệ thống như vậy không thể so sánh được với các hệ thống phân tán nguyên bản như Apache Spark (gRPC có thể giảm độ trễ này, nhưng vẫn không cạnh tranh). Chưa kể đến vấn đề lỗi duy nhất, quản lý các công việc / nhiệm vụ / đầu vào không thành công và hàng trăm tính năng khác mà bạn nhận được từ Apache Spark mà bây giờ bạn phải tự thực hiện / duy trì.
Có một bài đăng blog trên trang web Hugging Face mô tả kiến trúc giống nhau bằng cách mở rộng điểm cuối REST để phục vụ nhiều người dùng hơn: “ Triển khai 🤗 ViT trên Kubernetes với TF Serving ” - Tuy nhiên, tôi tin rằng các công ty khác đang sử dụng các cách tiếp cận tương tự để mở rộng quy mô của tính năng Ôm mặt , tất cả chúng đều đang mở rộng số lượng người dùng / yêu cầu chạm vào các điểm cuối REST suy luận. Ngoài ra, bạn không thể mở rộng khuôn mặt Ôm theo cách này trên Databricks.
Ví dụ: suy luận bên trong fastAPI chậm hơn 10 lần so với suy luận cục bộ: https://towardsdatascience.com/hugging-face-transformer-inference-under-1-millisecond-latency-e1be0057a51c
Sau khi Ôm mặt đưa ra một số giải pháp tự nhiên để mở rộng quy mô, tôi sẽ chạy lại các điểm chuẩn một lần nữa. Cho đến lúc đó, không có quy mô khi bạn phải lặp qua tập dữ liệu từ một máy duy nhất để đạt được các điểm cuối REST trong một thuật toán tổng hợp. (hãy nghĩ lại về phần chúng tôi đã ghép các hàng / chuỗi / hình ảnh để cấp cho GPU cùng một lúc, sau đó bạn sẽ nhận được nó)
Spark NLP là một phần mở rộng của Spark ML, do đó nó mở rộng quy mô nguyên bản và liền mạch trên tất cả các nền tảng được Apache Spark hỗ trợ như (và không giới hạn) Databricks, AWS EMR, Azure Insight, GCP Dataproc, Cloudera, SageMaker, Kubernetes, v.v.
Không cần thay đổi mã nào! Spark NLP có thể mở rộng quy mô từ một máy thành vô số máy mà không cần thay đổi bất kỳ điều gì trong mã!
Bạn cũng không cần xuất bất kỳ mô hình nào ra khỏi Spark NLP để sử dụng nó trong một thư viện hoàn toàn khác nhằm tăng tốc hoặc mở rộng quy mô suy luận.
Hệ sinh thái Spark NLP: tích hợp được tối ưu hóa, thử nghiệm và hỗ trợ
Hãy tạo một cụm và lần này chúng tôi chọn chế độ Chuẩn bên trong Cụm . Điều này có nghĩa là chúng ta có thể có nhiều hơn 1 nút trong cụm của mình, trong thuật ngữ Apache Spark, nó có nghĩa là 1 Trình điều khiển và N số Công nhân (Người thực thi).
Chúng tôi cũng cần cài đặt Spark NLP trong cụm mới này thông qua tab Thư viện. Bạn có thể làm theo các bước tôi đã đề cập trong phần trước đối với Mã dữ liệu nút đơn với CPU. Như bạn có thể thấy, tôi đã chọn cùng một phiên bản AWS có CPU mà tôi đã sử dụng để làm điểm chuẩn cho cả Hugging Face và Spark NLP để chúng ta có thể thấy nó mở rộng ra sao khi chúng ta thêm nhiều nút hơn.
Đây là cấu hình Cluster của chúng tôi trông như thế nào:
Cụm đa nút (tiêu chuẩn) Databricks chỉ với CPU
Tôi sẽ sử dụng lại cùng một đường dẫn Spark NLP mà tôi đã sử dụng trong các điểm chuẩn trước đó (không cần thay đổi bất kỳ mã nào) và tôi cũng sẽ chỉ sử dụng tập dữ liệu lớn hơn với 34K hình ảnh. Hãy bắt đầu nào!
Databricks với 2x Nodes - chỉ dành cho CPU
Hãy chỉ thêm 1 nút nữa và làm cho tổng số máy sẽ thực hiện xử lý là 2 máy. Đừng quên vẻ đẹp của Spark NLP khi bạn chuyển từ thiết lập máy đơn lẻ (Colab, Kaggle, Databricks Single Node hoặc thậm chí máy tính xách tay Jupyter cục bộ của bạn) sang thiết lập cụm nhiều nút (Databricks, EMR, GCP, Azure, Cloudera , YARN, Kubernetes, v.v.), cần thay đổi mã 0! Và ý tôi là số không! Với ý nghĩ đó, tôi sẽ chạy cùng một điểm chuẩn bên trong cụm mới này trên tập dữ liệu lớn hơn với hình ảnh 34K:
Đường ống phân loại hình ảnh Spark NLP trên 2 nút có CPU (oneDNN) - dự đoán 34742 hình ảnh
Mất khoảng 9 phút ( 550 giây ) để hoàn thành dự đoán các lớp cho hình ảnh 34K. Hãy so sánh kết quả này trên 2x Nút với Spark NLP và kết quả Ôm mặt trên nút đơn Databricks (Tôi sẽ tiếp tục lặp lại kết quả Ôm mặt trên một Nút duy nhất để tham khảo vì Ôm mặt không thể được chia tỷ lệ trên nhiều máy, đặc biệt là trên Databricks) :
Spark NLP nhanh hơn 124% so với Ôm mặt với 2 nút
Trước đây, Spark NLP đã đánh bại tính năng Ôm khuôn mặt trên một cụm Dữ liệu nút đơn bằng cách chỉ sử dụng CPU 15% .
Lần này, với việc chỉ có 2x nút thay vì 1 nút, Spark NLP đã hoàn thành quá trình xử lý hơn 34K hình ảnh nhanh hơn 124% so với Hugging Face.
Hãy tăng gấp đôi kích thước của cụm của chúng ta như trước và đi từ 2x Nodes đến 4x Nodes. Đây là cách mà cụm sẽ trông như thế nào với 4x nút:
Databricks với 4x Nodes - Chỉ dành cho CPU
Tôi sẽ chạy cùng một điểm chuẩn trên cụm mới này trên bộ dữ liệu lớn hơn với hình ảnh 34K:
Đường ống phân loại hình ảnh Spark NLP trên 4x nút có CPU (oneDNN) - dự đoán 34742 hình ảnh
Mất khoảng 5 phút ( 289 giây ) để hoàn thành dự đoán các lớp cho hình ảnh 34K. Hãy so sánh kết quả này trên 4x Nodes với Spark NLP so với Khuôn mặt ôm trên CPU trên Databricks:
Spark NLP nhanh hơn 327% so với Ôm mặt với 4 nút
Có thể thấy, Spark NLP hiện nhanh hơn 327% so với Ôm khuôn mặt trên CPU trong khi chỉ sử dụng 4x Nodes trong Databricks.
Bây giờ, hãy nhân đôi cụm trước đó bằng cách thêm 4 nút nữa và tạo ra tổng số 8 nút . Nhân tiện, việc thay đổi kích thước cụm này khá dễ dàng, bạn chỉ cần tăng số lượng nhân viên trong cấu hình cụm của mình:
Thay đổi kích thước Cụm Spark trong Databricks
Databricks với 8x Nodes - chỉ dành cho CPU
Hãy chạy cùng một điểm chuẩn lần này trên 8x Nodes:
Đường ống phân loại hình ảnh Spark NLP trên 8x nút với CPU (oneDNN) - dự đoán 34742 hình ảnh
Phải mất hơn 2 phút rưỡi ( 161 giây ) để hoàn thành dự đoán các lớp cho hình ảnh 34K. Hãy cùng so sánh kết quả này trên 8x Nodes với Spark NLP so với Khuôn mặt ôm trên CPU trên Databricks:
Spark NLP nhanh hơn 666% so với Ôm mặt với 8x nút
Có thể thấy, Spark NLP hiện nhanh hơn 666% so với Ôm khuôn mặt trên CPU trong khi chỉ sử dụng 8x Nodes trong Databricks.
Hãy bỏ qua con số 6s ở đây! (nó là 665,8% nếu nó làm cho bạn cảm thấy tốt hơn)
Để hoàn thành việc mở rộng dự đoán mô hình ViT của chúng tôi trên CPU trong Databricks bằng cách sử dụng Spark NLP, tôi sẽ thay đổi kích thước cụm một lần nữa và tăng nó lên 10x Nodes:
Databricks với 10x Nodes - chỉ dành cho CPU
Hãy chạy cùng một điểm chuẩn lần này trên 10x Nodes:
Đường ống phân loại hình ảnh Spark NLP trên 10 lần nút với CPU (oneDNN) - dự đoán 34742 hình ảnh
Mất chưa đầy 2 phút ( 112 giây ) để hoàn thành dự đoán các lớp cho hình ảnh 34K. Hãy so sánh kết quả này trên 10x Nodes với tất cả các kết quả trước đó từ Spark NLP so với Khuôn mặt ôm trên CPU trên Databricks:
Spark NLP nhanh hơn 1000% so với Ôm mặt với 10 nút
Và đây là cách bạn mở rộng mô hình Vision Transformer đến từ Khuôn mặt ôm trên các nút 10x bằng cách sử dụng Spark NLP trong Databricks! Đường ống của chúng tôi hiện nhanh hơn 1000% so với Ôm mặt trên CPU.
Chúng tôi đã quản lý để làm cho đường dẫn ViT của mình nhanh hơn 1000% so với Ôm khuôn mặt bị mắc kẹt trong 1 nút đơn bằng cách sử dụng Spark NLP, nhưng chúng tôi chỉ sử dụng CPU . Hãy xem liệu chúng ta có thể nhận được những cải tiến tương tự bằng cách mở rộng quy mô của chúng tôi trên một cụm GPU hay không.
Có một cụm Databricks nhiều nút dựa trên GPU cũng giống như việc có một cụm nút đơn. Sự khác biệt duy nhất là chọn Tiêu chuẩn và giữ cùng Thời gian chạy ML / GPU với cùng thông số AWS Instance mà chúng tôi đã chọn trong các điểm chuẩn của chúng tôi cho GPU trên một nút duy nhất.
Chúng tôi cũng cần cài đặt Spark NLP trong cụm mới này thông qua tab Thư viện . Tương tự như trước đây, bạn có thể làm theo các bước tôi đã đề cập trong Mã dữ liệu nút đơn với GPU.
Cụm đa nút (tiêu chuẩn) Databricks với GPU
Cụm GPU Databricks đa nút của chúng tôi sử dụng cùng một phiên bản GPU AWS của g4dn.8xlarge mà chúng tôi đã sử dụng trước đây để chạy các điểm chuẩn nhằm so sánh Spark NLP với Khuôn mặt ôm trên một cụm Databricks một nút.
Đây là bản tóm tắt về giao diện lần này với 2 nút:
Databricks với 2x Nodes - với 1 GPU cho mỗi nút
Tôi sẽ chạy cùng một đường dẫn trong cụm GPU này với 2x nút:
Đường ống phân loại hình ảnh Spark NLP trên 2 nút có GPU - dự đoán 34742 hình ảnh
Phải mất 4 phút ( 231 giây ) để hoàn thành dự đoán các lớp cho hình ảnh 34K . Hãy so sánh kết quả này trên 2x Nodes với Spark NLP so với Khuôn mặt ôm trên GPU trong Databricks:
Spark NLP nhanh hơn 185% so với Ôm mặt với 2 nút
Spark NLP với 2x Nodes nhanh hơn gần gấp 3 lần ( 185% ) so với Ôm mặt trên 1 nút duy nhất trong khi sử dụng GPU.
Hãy thay đổi kích thước cụm GPU của chúng tôi từ 2x Nodes thành 4x Nodes. Đây là bản tóm tắt về giao diện lần này với 4x Nodes sử dụng GPU:
Databricks với 4x Nodes - với 1 GPU cho mỗi nút
Hãy chạy cùng một điểm chuẩn trên 4x Nodes và xem điều gì sẽ xảy ra:
Đường ống phân loại hình ảnh Spark NLP trên 4x nút có GPU - dự đoán 34742 hình ảnh
Lần này mất gần 2 phút ( 118 giây ) để phân loại tất cả các hình ảnh 34K trong tập dữ liệu của chúng tôi. Hãy hình dung điều này chỉ để có cái nhìn rõ hơn về ý nghĩa của điều này đối với Khuôn mặt ôm trong một nút so với Spark NLP trong một cụm nhiều nút:
Spark NLP nhanh hơn 458% so với Ôm mặt với 4 nút
Đó là hiệu suất tăng 458% so với Ôm mặt. Chúng tôi vừa làm cho đường ống của mình nhanh hơn gấp 5,6 lần bằng cách sử dụng Spark NLP với 4 nút.
Tiếp theo, tôi sẽ thay đổi kích thước cụm để có 8x Nodes trong Databricks của tôi với bản tóm tắt sau:
Databricks với 8x Nodes - với 1 GPU cho mỗi nút
Xin lưu ý rằng mỗi phiên bản AWS ( g4dn.8xlarge ) có 1 GPU NVIDIA T4 16GB (bộ nhớ có thể sử dụng 15 GB). Hãy chạy lại điểm chuẩn và xem liệu chúng ta có thể phát hiện ra bất kỳ cải tiến nào không vì mở rộng quy mô trong bất kỳ hệ thống phân tán nào đều có chi phí chung và bạn không thể tiếp tục thêm máy:
Đường ống phân loại hình ảnh Spark NLP trên các nút 8x có GPU - dự đoán 34742 hình ảnh
Phải mất gần một phút ( 61 giây ) để phân loại xong hình ảnh 34K với 8x Nodes trong cụm Databricks của chúng tôi. Có vẻ như chúng tôi vẫn cố gắng cải thiện hiệu suất. Hãy đặt kết quả này bên cạnh kết quả trước đó từ Ôm khuôn mặt trong một nút so với Spark NLP trong một cụm nhiều nút:
Spark NLP nhanh hơn 980% so với Ôm mặt với 8x nút
Spark NLP với 8x Nodes nhanh hơn gần 11 lần (980%) so với Ôm khuôn mặt trên GPU.
Tương tự như điểm chuẩn đa nút của chúng tôi trên CPU, tôi muốn thay đổi kích thước cụm GPU một lần nữa để có 10 lần Nút và khớp chúng về số lượng nút cuối cùng. Tóm tắt cuối cùng của cụm này như sau:
Databricks với 10x Nodes - với 1 GPU cho mỗi nút
Hãy chạy điểm chuẩn cuối cùng của chúng tôi trong cụm GPU cụ thể này (không có thay đổi mã):
Đường ống phân loại hình ảnh Spark NLP trên các nút 10x có GPU - dự đoán 34742 hình ảnh
Mất chưa đầy một phút ( 51 giây ) để hoàn thành dự đoán các lớp cho hơn 34743 hình ảnh . Hãy đặt tất cả chúng bên cạnh nhau và xem chúng tôi đã tiến triển như thế nào trong việc mở rộng mô hình Vision Transformer của mình đến từ Khuôn mặt ôm trong đường ống Spark NLP trong Databricks:
Spark NLP nhanh hơn 1200% so với Ôm mặt với 10 nút
Và chúng tôi đã hoàn thành!
Chúng tôi đã quản lý để mở rộng mô hình Vision Transformer của mình đến từ Khuôn mặt ôm trên các nút 10x bằng cách sử dụng Spark NLP trong Databricks! Đường ống của chúng tôi hiện nhanh hơn 13 lần với cải thiện hiệu suất 1200% so với Ôm mặt trên GPU.
Hãy tổng hợp tất cả các điểm chuẩn này bằng cách so sánh trước tiên những cải tiến giữa CPU và GPU, sau đó là tốc độ đường ống của chúng tôi có thể nhanh hơn bao nhiêu khi chuyển từ CPU trên khuôn mặt đến 10x Nodes trên Databricks bằng cách sử dụng Spark NLP trên GPU.
Spark NLP 🚀 trên 10 lần Nút có CPU nhanh hơn 1000% (11 lần) so với Ôm mặt 🤗 bị kẹt trong một nút có CPU
Spark NLP 🚀 trên 10 lần Nút có GPU nhanh hơn 1192% (13 lần) so với Ôm mặt 🤗 bị mắc kẹt trong một nút có GPU
Còn về sự khác biệt về giá giữa phiên bản AWS CPU và phiên bản GPU AWS của chúng tôi thì sao? (Ý tôi là, bạn sẽ nhận được nhiều hơn nếu bạn trả nhiều hơn, phải không?)
AWS m5d.8xlarge với CPU so với AWS g4dn.8xlarge với 1 GPU và các thông số kỹ thuật tương tự
OK, vì vậy giá có vẻ khá giống nhau! Với suy nghĩ đó, bạn sẽ nhận được những cải tiến nào nếu chuyển từ Ôm khuôn mặt trên CPU bị mắc kẹt trong một máy sang Spark NLP trên 10x Nodes với GPU 10x ?
Spark NLP trên GPU nhanh hơn 25 lần (2366%) so với Ôm mặt trên CPU
Spark NLP 🚀 trên 10 lần Nút có GPU nhanh hơn 2366% (25 lần) so với Ôm mặt 🤗 trong một nút có CPU
ViT
Ôm mặt
Databricks
Spark NLP