SparseCore là một bộ xử lý chuyên biệt được thiết kế để tăng tốc hiệu suất cao cho các tải công việc liên quan đến hoạt động truy cập và tính toán bộ nhớ thưa thớt, không thường xuyên, đặc biệt là trên các tập dữ liệu lớn được lưu trữ trong Bộ nhớ băng thông cao (HBM). Mặc dù có khả năng vượt trội trong các tác vụ như tra cứu nhúng, nhưng khả năng của nó còn mở rộng sang việc tăng tốc nhiều khối lượng công việc động và thưa thớt khác.
1. Giới thiệu về SparseCore
Các đặc điểm kiến trúc chính:
- Cấu trúc xếp ô: Bao gồm nhiều ô điện toán (mỗi ô là một đơn vị luồng dữ liệu hoàn chỉnh có bộ nhớ cục bộ và đơn vị xử lý riêng) cho phép xử lý song song.
- Thực thi linh hoạt: Hỗ trợ tự nhiên luồng kiểm soát phụ thuộc vào dữ liệu và quyền truy cập vào bộ nhớ, rất quan trọng đối với dữ liệu thưa thớt.
- Xử lý vectơ: Sử dụng các tác vụ vectơ nhỏ (8 phần tử hoặc 16 phần tử, tuỳ thuộc vào phiên bản phần cứng) để tính toán hiệu quả.
- Khả năng kiểm soát tập trung: Một trình tự SparseCore duy nhất điều phối các tác vụ trên tất cả các ô, đảm bảo các hoạt động được đồng bộ hoá.
- Hỗ trợ tóm tắt dữ liệu: Bao gồm các hoạt động chuyên biệt trên nhiều làn đường, có lợi cho các tác vụ như sắp xếp, lọc và tính tổng tiền tố.
- Hệ thống phân cấp bộ nhớ: Tận dụng HBM một cách chiến lược để lưu trữ các tập dữ liệu lớn và bộ nhớ tạm cục bộ (SPMEM) để dàn dựng dữ liệu thường xuyên được truy cập, giảm đáng kể độ trễ HBM.
Thông số kỹ thuật:
| Thuộc tính | TPU phiên bản 4 | TPU v5p | Trillium |
|---|---|---|---|
| SparseCores/Chip | 4 | 4 | 2 |
| Tiles/SparseCore | 16 | 16 | 16 |
| Độ rộng SIMD | 8 | 8 | 8 (F32) 16 (BF16) |
| Dung lượng HBM | 32 GiB | 96 GiB | 32 GiB |
2. Xử lý trước máy chủ SparseCore
Việc chuẩn bị dữ liệu hiệu quả là điều tối quan trọng đối với hiệu suất của SparseCore và đây là nơi mà quá trình tiền xử lý trên máy chủ đóng vai trò quan trọng. Tính năng này bao gồm một số chức năng chính:
- Chuyển đổi dữ liệu:
- Áp dụng các phép biến đổi cần thiết cho dữ liệu đầu vào thô.
- Quản lý các phép biến đổi mã nhận dạng, điều này đặc biệt quan trọng khi xử lý việc xếp chồng các đối tượng hoặc bảng.
- Chuyển đổi dữ liệu đầu vào thành định dạng thưa thớt Toạ độ (COO), được trình bày chi tiết trong phần sau.
- Phân vùng dữ liệu để phân phối hiệu quả trên các SparseCore khác nhau có trên chip.
- Xác thực giới hạn:
- Đảm bảo rằng các đặc điểm của dữ liệu đầu vào (ví dụ: số lượng mã nhận dạng) tuân thủ các giới hạn hoạt động được xác định trước của SparseCore, chẳng hạn như
max_ids_per_partitionvàmax_unique_ids_per_partition. - Nếu dữ liệu đầu vào vượt quá các giới hạn này, lớp tiền xử lý máy chủ lưu trữ có thể cố gắng phân đoạn dữ liệu thành các lô nhỏ hơn phù hợp với các ràng buộc.
- Đảm bảo rằng các đặc điểm của dữ liệu đầu vào (ví dụ: số lượng mã nhận dạng) tuân thủ các giới hạn hoạt động được xác định trước của SparseCore, chẳng hạn như
- Chuyển dữ liệu:
- Sao chép hiệu quả dữ liệu đã xử lý và xác thực vào Bộ nhớ băng thông cao (HBM) của TPU, giúp dữ liệu sẵn sàng cho quá trình thực thi SparseCore.
Tìm hiểu về tính năng xếp chồng bảng:
Xếp chồng bảng là một kỹ thuật tối ưu hoá quan trọng, trong đó nhiều bảng nhúng được kết hợp một cách hợp lý để nâng cao hiệu quả tra cứu thông tin nhúng. Quy trình này thường được khung ML cơ bản xử lý tự động.
- Xếp chồng tính năng: Điều này xảy ra khi nhiều tính năng riêng biệt dùng chung cùng một bảng nhúng cơ bản. Một ví dụ phổ biến là sử dụng một từ điển nhúng duy nhất cho nhiều đặc điểm phân loại như mã bưu chính từ các ngữ cảnh khác nhau.
- Xếp chồng bảng: Trong trường hợp này, nhiều bảng nhúng riêng biệt được xếp chồng lên nhau. Các bảng dùng chung cùng một phương diện nhúng và cấu hình trình tối ưu hoá thường được nhóm lại.
Ưu điểm chính của việc xếp chồng bảng là tạo ra kích thước lô hiệu quả lớn hơn cho các thao tác trên những bảng được xếp chồng này. Điều này giúp giảm mức hao tổn về điện toán và có thể hiệu quả trong việc ẩn độ trễ giao tiếp giữa các chip (ICI). Để đạt hiệu suất tối ưu, bạn nên sử dụng một số lượng vừa phải các bảng xếp chồng (thường trong khoảng từ 5 đến 100).
3. Chuyển đổi thành tensor COO
Trước khi được SparseCore xử lý, dữ liệu thường được chuyển đổi thành định dạng tensor thưa thớt Coordinate (COO). Định dạng COO là một cách biểu thị ma trận thưa một cách hiệu quả, thường sử dụng 3 mảng:
row_ids: Một mảng chứa chỉ mục hàng cho từng phần tử khác 0. Trong ngữ cảnh xử lý hàng loạt, điều này thường tương ứng với phương diện lô.col_ids: Một mảng chứa chỉ mục cột cho từng phần tử khác 0. Đối với các mục nhúng, đây thường là các giá trị tính năng hoặc giá trị mã nhận dạng.values(không bắt buộc): Một mảng chứa các giá trị thực của các phần tử khác 0 tại toạ độ (row,col) tương ứng. Đối với các phép tính giới hạn (sẽ được thảo luận sau) liên quan đến số lượng mã nhận dạng, những giá trị này (mức tăng) thường không được xem xét.
Ví dụ minh hoạ:
Hãy xem xét một ma trận thưa đầu vào đại diện cho các lô mã nhận dạng:
[
[id_A], // Sample 0
[id_A, id_B, id_C], // Sample 1
[id_B, id_B, id_D], // Sample 2 (note duplicate id_B)
]
Sau khi chuyển đổi sang định dạng COO (và có thể sau khi loại bỏ các mã nhận dạng trùng lặp trong cùng một mẫu):
row_ids = [0, 1, 1, 1, 2, 2]
col_ids = [id_A, id_A, id_B, id_C, id_B, id_D]
Việc chuyển đổi này là nền tảng cho cách SparseCore xử lý và phân phối công việc.
Cụ thể, col_ids rất quan trọng trong việc xác định phân vùng SparseCore cụ thể mà một mã nhận dạng thuộc về, cho phép phân đoạn và tra cứu hiệu quả.
4. SparsecoreConfig: API cấp cao
API nhúng dành riêng cho khung:
- JAX: https://github.com/jax-ml/jax-tpu-embedding
- TensorFlow: https://www.tensorflow.org/recommenders/api_docs/python/tfrs/layers/embedding/TPUEmbedding
- Keras: https://keras.io/keras_rs/api/embedding_layers/distributed_embedding
SparsecoreConfig hoặc các cơ chế tương đương (chẳng hạn như cờ XLA) đóng vai trò là giao diện cấp cao để kiểm soát nhiều hành vi SparseCore. Việc hiểu rõ các tham số này là rất quan trọng để điều chỉnh hiệu suất một cách hiệu quả và đảm bảo các mô hình của bạn hoạt động chính xác.
disable_table_stacking: bool = False- Giải thích: Cờ này kiểm soát việc tính năng tự động xếp chồng bảng có ngăn khung xếp chồng bảng hay không, có thể dẫn đến hiệu suất giảm do tăng chi phí và giảm khả năng ẩn độ trễ Kết nối giữa các chip (ICI).
- Mặc định:
False(ngụ ý rằng tính năng xếp chồng bảng thường được bật theo mặc định khi khung hỗ trợ tính năng này).
max_ids_per_chip_per_sample: int = 64- Giải thích: Tham số này thiết lập một giới hạn trên toàn cầu về tổng số mã nhận dạng nhúng mà một chip có thể xử lý từ một mẫu trong lô đầu vào, được tổng hợp trên tất cả các bảng. Đây là một cơ chế quản lý tài nguyên ở cấp độ chip, trước khi tính đến các giới hạn chi tiết hơn cho mỗi bảng hoặc mỗi phân vùng. Việc tinh chỉnh giá trị này thường phụ thuộc vào các đặc điểm cụ thể của mô hình và dung lượng tổng thể của hệ thống.
- Mặc định:
64.
max_ids_per_table: Optional[Dict[str, int]] = None- Giải thích: Tham số này chỉ định số lượng tối đa mã nhận dạng nhúng (có thể bao gồm cả mã nhận dạng trùng lặp) có thể được xử lý cho mỗi bảng logic, có tính đến tất cả các phân vùng của bảng đó trên tất cả SparseCore. Đây là giới hạn rộng hơn so với
max_ids_per_partition. Nếu một bảngTđược chia thànhPphân vùng, thì giới hạn này sẽ áp dụng cho tổng số mã nhận dạng được chuyển đến tất cả các phân vùng P. Thông số này thường liên quan đếnmax_ids_per_partition_per_samplevà kích thước lô tổng thể. - Setting (Cài đặt): Thường được định cấu hình bằng tệp giới hạn (ví dụ: sử dụng cờ
xla_sparse_core_max_ids_file), trong đómax_ids_per_partitionđược xác định. Khái niệm ở cấp bảng này là một phương pháp để đặt các giới hạn ở cấp phân vùng (max_idsvàmax_uniques). - Mặc định:
None(giá trị có thể được suy ra từ giới hạn cho mỗi phân vùng hoặc các cấu hình khác nếu không được cung cấp một cách rõ ràng).
- Giải thích: Tham số này chỉ định số lượng tối đa mã nhận dạng nhúng (có thể bao gồm cả mã nhận dạng trùng lặp) có thể được xử lý cho mỗi bảng logic, có tính đến tất cả các phân vùng của bảng đó trên tất cả SparseCore. Đây là giới hạn rộng hơn so với
max_unique_ids_per_table: Optional[Dict[str, int]] = None- Giải thích: Tương tự như
max_ids_per_table, nhưng tham số này chỉ định số lượng tối đa mã nhận dạng riêng biệt cho mỗi bảng logic. Đây là một chế độ cài đặt quan trọng để định cỡ thích hợp các vùng đệm trên thiết bị được dùng trong quá trình xử lý mã nhận dạng riêng biệt và các thao tác vectơ tiếp theo. - Cài đặt: Thường được xác định trong tệp giới hạn hoặc bắt nguồn từ
max_unique_ids_per_partition_per_sample. - Mặc định:
None.
- Giải thích: Tương tự như
allow_id_dropping: bool = False- Giải thích: Cờ boolean này kiểm soát việc loại bỏ mã nhận dạng khi số lượng mã nhận dạng gặp phải trong dữ liệu đầu vào (giới hạn quan sát được) vượt quá giới hạn được đặt trong quá trình biên dịch (ví dụ:
max_ids_per_partition).- Nếu
True: Những mã nhận dạng khiến bạn vượt quá hạn mức sẽ bị loại bỏ mà không có thông báo. Thông thường, các mã nhận dạng trong một phân vùng sẽ được xử lý theo thứ tự sắp xếp và mọi mã nhận dạng đẩy số lượng đang chạy vượt quá giới hạn cho lô nhỏ được chỉ định sẽ bị loại bỏ. Điều này cho phép chương trình tiếp tục thực thi nhưng có thể ảnh hưởng tiêu cực đến độ chính xác của mô hình. - Nếu
False: Lỗi sẽ xảy ra và quy trình có thể sẽ kết thúc nếu các giới hạn quan sát được vượt quá giới hạn đã biên dịch. Phương pháp này đảm bảo mọi dữ liệu đều được xử lý nhưng yêu cầu bạn phải định cấu hình các giới hạn một cách thận trọng hơn.
- Nếu
- Mặc định:
False(gây ra lỗi tràn thay vì loại bỏ dữ liệu một cách âm thầm).
- Giải thích: Cờ boolean này kiểm soát việc loại bỏ mã nhận dạng khi số lượng mã nhận dạng gặp phải trong dữ liệu đầu vào (giới hạn quan sát được) vượt quá giới hạn được đặt trong quá trình biên dịch (ví dụ:
initialize_tables_on_host: bool = True- Giải thích: Cờ này xác định xem các bảng nhúng có được khởi tạo trên CPU máy chủ trước khi được chuyển sang Bộ nhớ băng thông cao (HBM) của TPU hay không. Thông thường, các bảng sẽ được khởi tạo trên máy chủ lưu trữ. Việc đặt giá trị này thành
Truesẽ tuân theo quy ước này. Nếu được đặt thànhFalse, điều này sẽ ngụ ý một cơ chế khởi động trên thiết bị, có thể có những tác động khác nhau đến hiệu suất hoặc các điều kiện tiên quyết cụ thể để khởi động.
- Giải thích: Cờ này xác định xem các bảng nhúng có được khởi tạo trên CPU máy chủ trước khi được chuyển sang Bộ nhớ băng thông cao (HBM) của TPU hay không. Thông thường, các bảng sẽ được khởi tạo trên máy chủ lưu trữ. Việc đặt giá trị này thành
enable_fast_table_initialization: bool = False- Giải thích: Khởi tạo các bảng trực tiếp trên TPU. Điều này có thể giúp giảm thời gian khởi động mô hình.
5. Phân đoạn để tăng hiệu suất
Pipelining là một kỹ thuật tối ưu hoá hiệu suất, cho phép thực hiện đồng thời các thao tác trên TensorCore (TC) và SparseCore (SC). Bằng cách chồng chéo các phép tính này, bạn có thể cải thiện đáng kể thông lượng tổng thể.
- Cơ chế: Trong bước huấn luyện tiêu chuẩn liên quan đến các lượt tìm kiếm nhúng thưa thớt (do SC xử lý) và các phép tính lớp dày đặc (do TC xử lý), việc tạo quy trình cho phép SC xử lý phần
icủa bước (ví dụ: truyền xuôi hoặc truyền ngược) trong khi TC đồng thời xử lý một phần khác của cùng bướci, hoặc thậm chí các phần của các bước liền kề nhưi-1hoặci+1. - Tác động đến độ dốc: SparseCore có thể hoạt động trên độ dốc "cũ".
Ví dụ: các độ dốc được tính trong giai đoạn truyền ngược của bước
icó thể chưa được cập nhật đầy đủ và hiển thị cho SC cho đến bướci+2. - Đánh đổi giữa hiệu suất và số liệu: Việc thực thi trùng lặp này có thể dẫn đến tốc độ tăng đáng kể, có thể cải thiện gấp 2 lần thời gian bước của thiết bị. Tuy nhiên, những thay đổi nhỏ về số liệu (embedding_weights) do việc sử dụng các độ dốc cũ có thể ảnh hưởng đến hành vi hội tụ của mô hình hoặc độ chính xác cuối cùng đạt được. Mức độ chấp nhận của sự đánh đổi này phụ thuộc rất nhiều vào mô hình và thường yêu cầu xác thực thực nghiệm.
- Cờ kiểm soát: Bạn có thể kiểm soát quy trình truyền dữ liệu bằng
tf_xla_disable_full_embedding_pipelining. Việc đặt cờ này thànhtruesẽ vô hiệu hoá tính năng truyền dữ liệu theo quy trình đầy đủ (tính toán TensorCore và SparseCore chồng chéo), trong khi việc đặt cờ này thànhfalse(hoặc nếu ngữ nghĩa của cờ ngụ ý bật khi sai) sẽ kích hoạt tính năng này.
Luồng quy trình theo khái niệm:
Không có quy trình truyền tải (luồng tuần tự đơn giản):
Loop: SC/F_i -> TC/F_i -> TC/B_i -> SC/B_iVới quy trình song song (quy trình chồng chéo đơn giản):
Time -> Step i: SC/F_i | TC/F_i | TC/B_i | SC/B_i Step i+1: SC/F_i+1| TC/F_i+1| TC/B_i+1| SC/B_i+1Lưu ý: Các giai đoạn tạo quy trình thực tế được triển khai trong phần cứng và trình biên dịch có thể phức tạp hơn, thường liên quan đến các vòng lặp trước, vòng lặp thực thi chính và vòng lặp sau để quản lý các phần phụ thuộc dữ liệu và đảm bảo tính chính xác.
6. Vai trò của XLA
XLA (Đại số tuyến tính được tăng tốc) là trình biên dịch dành riêng cho miền, có chức năng dịch các biểu đồ tính toán cấp cao (thường là từ các khung như TensorFlow) thành mã máy được tối ưu hoá cao, phù hợp với TPU. Điều này bao gồm việc tạo hướng dẫn cho các hoạt động dành cho SparseCore.
Các hàm chính trong bối cảnh SparseCore:
- Biên dịch các thao tác thưa thớt: XLA chịu trách nhiệm biên dịch các thao tác tra cứu nhúng (chẳng hạn như
SparseDenseMatmulOp) và các phép tính thưa thớt khác thành các chương trình SparseCore có thể thực thi ở cấp thấp. - Tích hợp các giới hạn: Thư viện này sử dụng các giới hạn hoạt động đã định cấu hình (ví dụ:
max_ids_per_partition,max_unique_ids_per_partition, thường được cung cấp thông qua một tệp giới hạn do các cờ nhưxla_sparse_core_max_ids_filechỉ định) để xác định tĩnh kích thước và phân bổ các vùng đệm bộ nhớ trên thiết bị, đặc biệt là trong SPMEM. - Tối ưu hoá có mục tiêu: XLA thực hiện một bộ các hoạt động tối ưu hoá được thiết kế riêng cho cấu trúc SparseCore. Những hoạt động này có thể bao gồm lập lịch hướng dẫn, chuyển đổi bố cục bộ nhớ và hợp nhất các hoạt động để tối đa hoá hiệu quả.
- Kiểm soát bằng cờ: Nhiều khía cạnh của hành vi SparseCore, các thông số điều chỉnh và chiến lược tối ưu hoá được hiển thị và kiểm soát thông qua các cờ XLA (ví dụ:
xla_sparse_core_estimate_max_idsđể ước tính giới hạn hoặcxla_sc_detect_nanđể gỡ lỗi).
Trạng thái nguồn mở:
Hiện tại, việc triển khai Sparsecore là nội bộ và được phân phát bằng libtpu.so.
Báo cáo lỗi và chẩn đoán:
Lỗi biên dịch liên quan đến cấu hình SparseCore hoặc các hạn chế về tài nguyên thường biểu hiện dưới dạng lỗi biên dịch XLA:TPU. Những thông báo lỗi này có thể cung cấp thông tin chi tiết có giá trị về các vấn đề, chẳng hạn như việc đặt giới hạn quá cao cho SPMEM hiện có hoặc việc sử dụng các cấu hình không được hỗ trợ.
7. Cách các giới hạn chuyển đổi thành bảng trên SparseCore
Trên SparseCore, "limits" (giới hạn) là các tham số cấu hình cơ bản, chủ yếu đề cập đến 2 chế độ cài đặt cho mỗi phân vùng của mỗi bảng được phân mảnh (phân phối) trên các SparseCore hiện có:
max_ids_per_partition: Tham số này xác định số lượng mã nhận dạng tối đa (bao gồm cả mã nhận dạng trùng lặp) mà bất kỳ SparseCore nào dự kiến sẽ gửi đến hoặc xử lý cho một phân vùng cụ thể của một bảng nhất định trong một bước tính toán duy nhất.max_unique_ids_per_partition: Tham số này xác định số lượng tối đa mã nhận dạng duy nhất mà bất kỳ SparseCore nào dự kiến sẽ gửi đến hoặc xử lý cho một
Chuyển đổi sang bố cục và xử lý bảng vật lý:
- Chiến lược phân mảnh bảng: Các bảng nhúng thường được "phân mảnh theo mô-đun" trên tất cả SparseCore trong hệ thống. Điều này có nghĩa là mỗi SparseCore sẽ chịu trách nhiệm cho một tập hợp con riêng biệt của từ vựng (hàng) của mỗi bảng. Thông thường, một mã nhận dạng
jsẽ được chỉ định choSparseCore_kdựa trên một công thức nhưk = j % num_total_sparse_cores. - Định nghĩa về "phân vùng": Trong ngữ cảnh này, "phân vùng" đề cập đến phân khúc cụ thể của một bảng nhúng mà một SparseCore duy nhất xử lý các lượt tìm kiếm.
- Phân bổ vùng đệm SPMEM: Trình biên dịch XLA sử dụng các giới hạn này để định cỡ và phân bổ vùng đệm một cách tĩnh trong bộ nhớ tạm thời trên thiết bị (SPMEM). Các vùng đệm được định kích thước sao cho tất cả dữ liệu cần thiết liên quan đến mã nhận dạng cho một phân vùng nhất định (tối đa theo giới hạn
max_idsvàmax_unique_idsđã chỉ định) có thể được tải vào SPMEM để xử lý. Điều này đặc biệt quan trọng đối với các phép tính không theo phần tử, chẳng hạn như giảm các mã nhận dạng trùng lặp trong một phân vùng (ví dụ: khi tạo biểu diễn Hàng thưa được nén (CSR)), trong đó toàn bộ tập dữ liệu có liên quan cho mã nhận dạng của phân vùng đó cần có sẵn trong bộ nhớ nhanh. Giới hạn được biên dịch so với giới hạn quan sát được:
- Hạn mức quan sát được: Đây là số lượng mã nhận dạng thực tế gặp phải cho mỗi phân vùng trong thời gian chạy, dựa trên dữ liệu đầu vào đang được xử lý.
- Nếu các giới hạn quan sát được vượt quá các giới hạn đã biên dịch, thì điều này có thể dẫn đến việc giảm mã nhận dạng (nếu
allow_id_droppingđược bật) hoặc lỗi.
Tính toán giới hạn: Quá trình xác định giới hạn phù hợp bao gồm việc phân tích kỹ lưỡng sự phân phối dữ liệu đầu vào. Đối với một bảng bất kỳ (gọi là
T1, bản thân bảng này có thể là một phần của bảng xếp chồng lớn hơnT):- Lô đầu vào (ví dụ:
SparseTensor2D có hình dạng[BatchSize, MaxSequenceLength]) ban đầu được chia thành các SparseCore có sẵn. Ví dụ: nếu TensorCore được ghép nối với 2 SparseCore, thì mỗi SparseCore có thể nhận được một lô con có hình dạng[BatchSize/2, MaxSequenceLength]. - Sau đó, lô phụ này được chuyển đổi sang định dạng COO, tạo ra
row_idsvàcol_ids. - Các mã nhận dạng trùng lặp trong cùng một mẫu (tức là các mục có cùng
row_idvàcol_id) sẽ bị xoá. - Đối với mỗi
col_idduy nhất còn lại (trong một mẫu), SparseCore đích chịu trách nhiệm cho mã nhận dạng này được xác định bằng quy tắc phân mảnh theo mô-đun:target_sc_id = col_id % num_total_sparse_cores. - Hệ thống duy trì số lượng tổng cộng của mã nhận dạng (
ids_per_sparse_core[target_sc_id]++) và số lượng mã nhận dạng riêng biệt (unique_ids_per_sparse_core[target_sc_id]++, sau khi đảm bảo tính riêng biệt chotarget_sc_idcụ thể đó) được dành cho mỗitarget_sc_id. - Sau đó,
max_ids_per_partitioncho bảngT1được đặt thànhmax(ids_per_sparse_core_array). - Tương tự,
max_unique_ids_per_partitioncho bảngT1được đặt thànhmax(unique_ids_per_sparse_core_array). - Nếu bảng
T1là một thành phần của bảng xếp chồng, thì các phép biến đổi bổ sung như xoay hoặc dịch chuyển có thể được áp dụng cho các phân phối mã nhận dạng trước khi tính tổng số liệu thống kê từ tất cả các bảng thành phần. Điều này giúp cân bằng tải trên các chip.
- Lô đầu vào (ví dụ:
Việc đặt các giới hạn này một cách chính xác là một hành động cân bằng: giới hạn thấp hơn có thể dẫn đến hiệu suất cao hơn (vì cần xử lý ít dữ liệu hơn cho mỗi bước và giảm áp lực SPMEM), nhưng nếu đặt quá thấp, chúng có thể dẫn đến việc tạo quá nhiều lô nhỏ hoặc loại bỏ mã nhận dạng không mong muốn.
8. Cách mỗi SparseCore giao tiếp
Hoạt động giao tiếp SparseCore, đặc biệt là trong bối cảnh xử lý danh sách mã nhận dạng để tra cứu thông tin nhúng, dựa trên một số cơ chế phối hợp:
- Phân đoạn mô-đun và định tuyến ngầm:
- Các bảng nhúng được phân đoạn theo mô-đun trên tất cả SparseCore trong hệ thống.
- Khi máy chủ lưu trữ cung cấp một lô dữ liệu đầu vào (sau đó được xử lý trước thành định dạng COO, bao gồm cả
col_ids), giá trịcol_idsẽ được dùng để xác định SparseCore nào chịu trách nhiệm cho mã nhận dạng cụ thể đó:target_sc_id = col_id % num_total_sparse_cores. - Mỗi SparseCore chỉ nhận và xử lý hiệu quả một nhóm nhỏ mã nhận dạng ánh xạ đến các phân vùng từ vựng được chỉ định. Giai đoạn tiền xử lý trên máy chủ lưu trữ là giai đoạn quan trọng để chuẩn bị dữ liệu theo cách mà mỗi SparseCore có thể dễ dàng xác định và hoạt động trên các mã nhận dạng có liên quan.
- Phân phối dữ liệu theo máy chủ lưu trữ:
- Logic tiền xử lý máy chủ lưu trữ phân vùng lô đầu vào tổng thể và phân phối các phần liên quan của
row_idsvàcol_ids(cùng với mọi đặc điểm hoặc trọng số liên quan nếu có) vào bộ nhớ (HBM) mà mỗi SparseCore có thể truy cập trực tiếp hoặc vào HBM dùng chung mà SparseCore sẽ tìm nạp dữ liệu cần thiết.
- Logic tiền xử lý máy chủ lưu trữ phân vùng lô đầu vào tổng thể và phân phối các phần liên quan của
- Xử lý Intra-SparseCore:
- Sau khi nhận được nhóm mã nhận dạng được chỉ định cho một phân vùng bảng nhất định, SparseCore sẽ thực hiện các thao tác như loại bỏ trùng lặp các mã nhận dạng này và thu thập các vectơ nhúng tương ứng. Đây chủ yếu là các phép tính cục bộ được thực thi trong các ô riêng của SparseCore và sử dụng SPMEM cục bộ.
- Giao tiếp giữa các SparseCore (Tất cả đến tất cả):
- Sau giai đoạn xử lý ban đầu (chẳng hạn như tra cứu nhúng), bạn có thể sử dụng mẫu giao tiếp "tất cả đến tất cả" để kết hợp hoặc phân phối lại kết quả trên các SparseCore (ví dụ: trước khi đưa các lượt kích hoạt vào một lớp TensorCore dự kiến sẽ có dữ liệu đầu vào tương ứng với tất cả các vị trí mẫu ban đầu). Điều này rất quan trọng để tái tạo toàn bộ tập hợp các lượt kích hoạt nếu lô đầu vào ban đầu được phân phối để xử lý song song.
- Giao tiếp với TensorCore:
- SparseCore giao tiếp với TensorCore để gửi các lượt kích hoạt nhúng (trong quá trình truyền xuôi) và nhận các độ dốc (trong quá trình truyền ngược). Tương tác này được điều phối bởi chương trình được biên dịch XLA và thường liên quan đến HBM dưới dạng bộ đệm trung gian. Chiến lược pipelining (đã thảo luận trước đó) có ảnh hưởng lớn đến thời gian và việc đồng bộ hoá thông tin liên lạc SC-TC này.
Về cơ bản, việc "phân phối" ban đầu các mã nhận dạng đến SparseCore thích hợp chủ yếu được xử lý bằng lược đồ phân đoạn và các bước tiền xử lý máy chủ. Các hoạt động giao tiếp tiếp theo liên quan đến SparseCore hoạt động trên dữ liệu cục bộ của chúng, có thể theo sau là các hoạt động giao tiếp tập thể như tất cả-đến-tất cả nếu cần trao đổi hoặc sắp xếp lại dữ liệu trên toàn cầu trên các SparseCore trước khi TensorCore xử lý thêm.
9. Quản lý bộ nhớ SparseCore
Mỗi SparseCore quản lý hiệu quả một số loại bộ nhớ riêng biệt để thực hiện các phép tính:
- Bộ nhớ tạm (SPMEM):
- Tự nhiên: Một SRAM cục bộ tương đối nhỏ nhưng rất nhanh, chỉ có sẵn cho mỗi SparseCore. Điều quan trọng cần lưu ý là SPMEM không phải là bộ nhớ đệm; việc sử dụng bộ nhớ này được trình biên dịch XLA quản lý và điều phối một cách rõ ràng.
- Mục đích: SPMEM được dùng để "dàn xếp dữ liệu một cách có cơ hội". Trong đó bao gồm dữ liệu đầu vào, đầu ra và kết quả trung gian cần thiết cho các phép tính SC đang diễn ra. Việc dàn xếp dữ liệu trong SPMEM giúp giảm đáng kể độ trễ cao thường liên quan đến việc truy cập vào HBM.
- Định cỡ: Như đã thảo luận trong phần "Giới hạn", các vùng đệm SPMEM được định cỡ tĩnh tại thời gian biên dịch. Việc định cỡ này dựa trên các thông số như
max_ids_per_partitionvàmax_unique_ids_per_partition. Việc phân bổ tĩnh này đảm bảo rằng đối với bất kỳ thao tác nào trên một phân vùng bảng (chẳng hạn như giảm CSR), tất cả dữ liệu cần thiết cho mã nhận dạng của phân vùng đó (tối đa theo giới hạn đã xác định) đều có thể nằm trong SPMEM. - Tối ưu hoá trình biên dịch: Trình biên dịch XLA kết hợp các phương pháp tối ưu hoá tinh vi để xác định chính xác lượng dữ liệu và những phần tử dữ liệu cụ thể cần được dàn dựng trong SPMEM nhằm ẩn độ trễ HBM một cách hiệu quả và tối đa hoá hiệu suất.
- Ràng buộc phân bổ động: Trình biên dịch SparseCore hiện không hỗ trợ việc phân bổ vùng nhớ tạm động. Điều này cho thấy tầm quan trọng của việc định cỡ tĩnh thông qua việc định cấu hình cẩn thận các giới hạn.
- Bộ nhớ băng thông cao (HBM):
- Nature: Một tài nguyên bộ nhớ dùng chung, có dung lượng lớn mà tất cả SparseCore, TensorCore và hệ thống máy chủ đều có thể truy cập. Các bảng nhúng chính được lưu trữ trong HBM.
- Mức sử dụng ngăn xếp: Các hoạt động của SparseCore thường yêu cầu bộ nhớ tạm thời trong HBM cho các kết quả trung gian không phù hợp với SPMEM có hạn hoặc cần được truyền giữa các giai đoạn lớn hơn của quy trình xử lý. Mức sử dụng ngăn xếp HBM trong cả lượt chuyển tiếp và lượt truyền ngược có thể được ước tính như sau –
- Ngăn xếp HBM truyền xuôi (bảng đơn) ≈ (2 *
feature_width+ 1) *max_unique_nz_per_row*logical_replica_count* 4 byte - Backward Pass HBM Stack (single table) ≈ 3 *
feature_width*max_unique_nz_per_row*logical_replica_count* 4 bytes
- Ngăn xếp HBM truyền xuôi (bảng đơn) ≈ (2 *
- Mức sử dụng vùng nhớ khối xếp: HBM cũng chứa vùng nhớ khối xếp do máy chủ lưu trữ quản lý. Heap lưu trữ dữ liệu như trọng số lớp dày đặc, hằng số mà mô hình sử dụng và dữ liệu đầu vào được tìm nạp trước. Mức sử dụng heap có xu hướng tăng lên theo số bước mà máy chủ tìm nạp trước dữ liệu (do cờ
maximum_parallel_iterationskiểm soát). Mặc dù việc tìm nạp trước nhiều hơn có thể cải thiện hiệu suất bằng cách chồng chéo các hoạt động truyền từ máy chủ đến thiết bị với hoạt động tính toán của thiết bị, nhưng việc này cũng tiêu tốn nhiều HBM hơn. - Serialization for HBM optimization (Nối tiếp hoá để tối ưu hoá HBM): Cờ
xla_sc_num_serialized_tables_to_optimize_hbmcung cấp một cơ chế để kiểm soát số lượng dữ liệu của bảng được giữ "trực tiếp" trong bộ nhớ ngăn xếp HBM tại bất kỳ thời điểm nào. Việc tăng số lượng này sẽ tuần tự hoá hiệu quả quá trình xử lý cho nhiều bảng hơn, có thể làm giảm mức sử dụng ngăn xếp HBM cao nhất nhưng có thể ảnh hưởng đến hiệu suất do giảm tính song song.
- Bộ nhớ vectơ (VMEM):
- VMEM là bộ nhớ tạm cục bộ chỉ được dùng bởi TC (TensorCore). Mặc dù VMEM không được SparseCore quản lý trực tiếp, nhưng đây là một phần không thể thiếu trong hệ sinh thái bộ nhớ mà SC tương tác, chủ yếu thông qua TensorCore.
Chiến lược quản lý bộ nhớ tổng thể:
Chiến lược quản lý bộ nhớ cốt lõi cho SparseCore xoay quanh việc sử dụng SPMEM nhỏ, nhanh cho dữ liệu "nóng" đang được một ô SparseCore xử lý tích cực, nhờ đó giảm thiểu quyền truy cập vào HBM chậm hơn. Các giới hạn đã định cấu hình là cơ chế chính để đảm bảo rằng SPMEM không bị tràn. HBM được dùng để lưu trữ các bảng nhúng lớn và dữ liệu tạm thời vượt quá dung lượng SPMEM hoặc cần được chia sẻ giữa các đơn vị xử lý hoặc giai đoạn của quy trình. Trình biên dịch XLA chịu trách nhiệm điều phối mọi hoạt động di chuyển dữ liệu và phân bổ vùng đệm dựa trên các nguyên tắc kiến trúc này và các giới hạn do người dùng định cấu hình.
10. Nút thắt cổ chai về hiệu suất và bộ nhớ
Để đạt được hiệu suất tối ưu với SparseCore, bạn cần hiểu rõ các điểm tắc nghẽn tiềm ẩn và cách giải quyết chúng. Những vấn đề này có thể phát sinh trên máy chủ lưu trữ, trong chính SparseCore hoặc trong quá trình tương tác của SparseCore với TensorCore.
Các điểm tắc nghẽn hiệu suất thường gặp:
- Nút thắt của máy chủ lưu trữ:
- Vấn đề: CPU máy chủ lưu trữ có thể không xử lý trước dữ liệu và cung cấp dữ liệu cho TPU đủ nhanh, dẫn đến tình trạng sử dụng không hết SparseCore và TensorCore. Đây là yếu tố thường xuyên hạn chế hiệu suất.
- Giảm thiểu: Giám sát mức sử dụng CPU của máy chủ và các chỉ số về quy trình đầu vào. Tối ưu hoá các quy trình tải và tiền xử lý dữ liệu phía máy chủ lưu trữ (tham khảo các mẹo chuyển đổi COO). Điều chỉnh cờ
maximum_parallel_iterationsđể tinh chỉnh việc tìm nạp trước dữ liệu.
- Đồng bộ hoá TC/SC không tối ưu (thiếu quy trình xử lý song song):
- Vấn đề: Nếu quy trình xử lý song song giữa TensorCore và SparseCore bị vô hiệu hoá hoặc không hoạt động hiệu quả, thì một đơn vị có thể mất nhiều thời gian chờ đơn vị kia, do đó làm giảm thông lượng tổng thể của hệ thống.
- Giảm thiểu: Đảm bảo bạn đã bật tính năng truyền dữ liệu theo quy trình (ví dụ:
tf_xla_disable_full_embedding_pipelining = falsehoặc tính năng tương đương).
- Nghẽn do giới hạn:
- Vấn đề:
- Giới hạn quá thấp: Có thể kích hoạt quá trình phân lô nhỏ quá mức (chia các lô đầu vào thành nhiều lô con nhỏ hơn để đáp ứng các giới hạn chặt chẽ). Mặc dù điều này duy trì tính chính xác, nhưng mỗi lô nhỏ sẽ gây ra một số hao tổn xử lý, có thể làm chậm quá trình thực thi tổng thể. Nếu
allow_id_droppinglà true, thì giới hạn quá thấp cũng có thể dẫn đến việc giảm số lượng mã nhận dạng, ảnh hưởng đến độ chính xác của mô hình. - Giới hạn quá cao (nhưng vẫn phù hợp): Mặc dù giới hạn quá cao có thể ngăn chặn việc phân lô nhỏ, nhưng chúng có thể làm tăng áp lực SPMEM một cách không cần thiết nếu đặc điểm dữ liệu thực tế hiếm khi đạt đến các giá trị đỉnh này. Chúng cũng có thể dẫn đến việc sử dụng ngăn xếp HBM lớn hơn mức cần thiết.
- Lỗi biên dịch: Nếu các giới hạn đã định cấu hình yêu cầu nhiều ngăn xếp SPMEM hoặc HBM hơn bộ nhớ vật lý có sẵn, thì quá trình biên dịch sẽ không thành công.
- Giới hạn quá thấp: Có thể kích hoạt quá trình phân lô nhỏ quá mức (chia các lô đầu vào thành nhiều lô con nhỏ hơn để đáp ứng các giới hạn chặt chẽ). Mặc dù điều này duy trì tính chính xác, nhưng mỗi lô nhỏ sẽ gây ra một số hao tổn xử lý, có thể làm chậm quá trình thực thi tổng thể. Nếu
- Giảm thiểu: Đảm bảo bạn đặt giới hạn chính xác.
- Vấn đề:
- Độ lệch phân phối dữ liệu:
- Vấn đề: Nếu một số phân vùng SparseCore nhất định liên tục nhận được số lượng mã nhận dạng lớn hơn một cách không cân xứng so với các phân vùng khác (cho thấy việc phân phối mã nhận dạng kém), thì những SparseCore bị quá tải đó sẽ trở thành điểm nghẽn hiệu suất.
- Giảm thiểu: Việc xáo trộn mã nhận dạng trong quá trình tạo lô nhỏ có thể giúp giảm thiểu vấn đề này đối với các bảng xếp chồng, đặc biệt là những bảng có bảng người dùng "nóng". Phân tích cẩn thận việc phân phối mã nhận dạng để đặt giới hạn phù hợp và cân bằng cho mỗi bảng.
- Vấn đề về việc xếp chồng bảng:
- Vấn đề:
- Có quá ít bảng được xếp chồng lên nhau: Có thể không đủ để ẩn độ trễ ICI một cách hiệu quả hoặc giảm đủ chi phí xử lý.
- Có quá nhiều bảng được xếp chồng lên nhau: Có thể dẫn đến việc tạo ra các bảng logic rất lớn, khó quản lý hoặc có thể vượt quá giới hạn tài nguyên hiện có.
- Giảm thiểu:
- Đảm bảo số lượng bàn tối ưu để xếp chồng. Nguyên tắc chung là nên xếp từ 5 đến 100 bảng.
- Vấn đề:
- Số học/lượng tử hoá không hiệu quả:
- Vấn đề: Việc sử dụng độ chính xác FP32 đầy đủ khi các định dạng có độ chính xác thấp hơn như BF16 hoặc số nguyên được lượng tử hoá là đủ (và mang lại khả năng tính toán nhanh hơn) có thể là một điểm nghẽn về hiệu suất.
- Giảm thiểu: Khám phá các lựa chọn có độ chính xác thấp hơn. Tuy nhiên, hãy lưu ý rằng bản thân quá trình lượng tử hoá có một số chi phí và có thể yêu cầu điều chỉnh cẩn thận các tham số lượng tử hoá để duy trì độ chính xác của mô hình.
- Độ bão hoà băng thông HBM:
- Vấn đề: Di chuyển quá nhiều dữ liệu đến và đi từ HBM, có thể do chiều rộng của đối tượng rất nhỏ (dẫn đến chi phí bổ sung cao), các mẫu truy cập bộ nhớ không hiệu quả hoặc số lượng tra cứu cực lớn, có thể làm bão hoà băng thông HBM có sẵn.
- Giảm thiểu: Việc tăng số lượng TPU có thể giúp giảm tình trạng bão hoà băng thông HBM.
Các điểm tắc nghẽn bộ nhớ thường gặp:
- SPMEM tràn (lỗi biên dịch):
- Vấn đề: Nếu
max_ids_per_partitionvàmax_unique_ids_per_partitionđược đặt quá cao, trình biên dịch XLA có thể không phân bổ đủ SPMEM, dẫn đến các lỗi biên dịch như:"Fixed size allocations (...) do not fit in TileSpmem (...)". Ngoài ra, nếu số hạng(sample_count * feature_width) / kNumTiles(trong đókNumTileslà số lượng ô trên mỗi SC) quá lớn để dàn dựng các toán hạng thu thập trong ô SPMEM, thì có thể xảy ra các lỗi như"Gather operand too large...". - Giảm thiểu: Giảm kích thước lô hoặc tăng số lượng chip dùng để xử lý.
- Vấn đề: Nếu
- HBM stack overflow (thời gian chạy hoặc biên dịch):
- Vấn đề: Nếu tổ hợp
feature_width,max_unique_nz_per_rowvàlogical_replica_countdẫn đến các yêu cầu về bộ nhớ ngăn xếp HBM vượt quá HBM có sẵn, thì điều này có thể gây ra lỗi hết bộ nhớ (OOM) tại thời gian chạy hoặc trong quá trình biên dịch. - Giảm thiểu: Điều chỉnh cờ
xla_sc_num_serialized_tables_to_optimize_hbmđể giảm mức sử dụng ngăn xếp HBM bằng cách tuần tự hoá quá trình xử lý các bảng (việc này thường làm giảm hiệu suất).
- Vấn đề: Nếu tổ hợp
- HBM heap exhaustion (Cạn kiệt heap HBM):
- Vấn đề: Chủ yếu là do trọng số lớp dày rất lớn, nhiều hằng số được lưu trữ trong bộ nhớ hoặc việc tìm nạp trước dữ liệu đầu vào quá mức (
maximum_parallel_iterationscao). - Giảm thiểu: Giám sát mức sử dụng heap bằng các công cụ như XProf Memory Viewer.
- Vấn đề: Chủ yếu là do trọng số lớp dày rất lớn, nhiều hằng số được lưu trữ trong bộ nhớ hoặc việc tìm nạp trước dữ liệu đầu vào quá mức (
- Chi phí phụ của khoảng đệm:
- Vấn đề: Các bảng nhúng được đệm để căn chỉnh 32B (tương đương với 8 số thực) theo phương diện của đối tượng. Do đó, độ rộng của các đối tượng nhỏ (ví dụ: 1 số thực) sẽ gây ra chi phí đáng kể cho việc bổ sung (ví dụ: 7/8 không gian vùng đệm được phân bổ là phần bổ sung), dẫn đến việc lãng phí HBM. Phương diện từ vựng của các bảng cũng được đệm để trở thành bội số của số SparseCore trong hệ thống; tuy nhiên, tác động này thường không đáng kể đối với các bảng có kích thước từ vựng đủ lớn.
Các yếu tố chung ảnh hưởng đến hiệu suất và bộ nhớ:
- Cấu trúc liên kết: Số lượng chip có sẵn và kiến trúc kết nối của chúng.
- Kích thước lô: Ảnh hưởng trực tiếp đến
sample_counttrên mỗi SparseCore, từ đó ảnh hưởng đến mức tiêu thụ bộ nhớ và tải trọng tính toán. - Định dạng dữ liệu: Việc đảm bảo bố cục dữ liệu hiệu quả trên thiết bị là yếu tố quan trọng để đạt được hiệu suất tối ưu.
11. Phân tích hồ sơ SparseCore
Phân tích hồ sơ hiệu suất là một bước quan trọng trong việc xác định các điểm tắc nghẽn và khám phá các cơ hội tối ưu hoá trong khối lượng công việc SparseCore.
- Lấy dấu vết:
- Sử dụng các công cụ lập hồ sơ, chẳng hạn như XProf, để ghi lại dấu vết thực thi chi tiết trong khi mô hình của bạn đang huấn luyện hoặc chạy suy luận. Dấu vết này sẽ cung cấp dòng thời gian của các hoạt động diễn ra trên máy chủ lưu trữ, TensorCore và SparseCore.
- Kiểm tra Trình xem dấu vết (ví dụ: trong XProf hoặc TensorBoard):
- Hoạt động của người tổ chức: Xem xét kỹ lưỡng hoạt động của người tổ chức. Có khoảng trống đáng kể nào trong hoạt động của TPU không? Những khoảng trống như vậy có thể cho thấy máy chủ lưu trữ là một điểm tắc nghẽn, không cung cấp dữ liệu đủ nhanh. Phân tích hiệu suất của quy trình đầu vào.
- Hoạt động của TensorCore (TC) và SparseCore (SC):
- Xem tiến trình thực thi cho cả TC và SC. Chúng có hoạt động song song không, cho thấy việc tạo quy trình hiệu quả? Hoặc có những khoảng thời gian dài mà một đơn vị ở trạng thái chờ, chờ đơn vị còn lại?
- Xác định những thao tác tốn nhiều thời gian nhất (thao tác chạy lâu nhất) trên cả SC và TC.
- Đầu ra dấu vết trực quan (thường cho thấy các khối màu biểu thị các thao tác khác nhau theo thời gian, chẳng hạn như
TPU:0 SparseCore 1 (pid 1005)) là vô giá để xác định trực quan các thao tác chính và khoảng thời gian không hoạt động.
- Phân tích thời gian bước: Quan sát thời gian bước tổng thể và tìm hiểu cách phân phối hoặc chia nhỏ thời gian này giữa quá trình xử lý máy chủ lưu trữ, tính toán SC và tính toán TC.
- Phân tích bộ nhớ (XProf Memory Viewer):
- Mức sử dụng vùng nhớ khối xếp: Sử dụng các công cụ như thẻ "Trình xem bộ nhớ" của XProf để kiểm tra mức sử dụng vùng nhớ khối xếp HBM. Điều này có thể giúp xác định xem các trọng số, hằng số của mô hình lớn hay việc tìm nạp trước dữ liệu đầu vào quá mức có đang tiêu thụ quá nhiều HBM hay không. Việc bật các cờ như
--vmodule=best_fit_allocator=1có thể cung cấp nhật ký về mức sử dụng heap cao nhất. - Mức sử dụng ngăn xếp (gián tiếp): Mặc dù việc lập hồ sơ ngăn xếp HBM trực tiếp có thể phức tạp, nhưng nếu bạn gặp lỗi hết bộ nhớ và mức sử dụng heap có vẻ hợp lý, thì việc cạn kiệt ngăn xếp HBM (thường là do giới hạn hoặc chiều rộng tính năng quá lớn) là một nguyên nhân đáng nghi ngờ. Các công thức được cung cấp để sử dụng ngăn xếp HBM có thể giúp ước tính điều này.
- Mức sử dụng vùng nhớ khối xếp: Sử dụng các công cụ như thẻ "Trình xem bộ nhớ" của XProf để kiểm tra mức sử dụng vùng nhớ khối xếp HBM. Điều này có thể giúp xác định xem các trọng số, hằng số của mô hình lớn hay việc tìm nạp trước dữ liệu đầu vào quá mức có đang tiêu thụ quá nhiều HBM hay không. Việc bật các cờ như
- Tìm các mẫu hình cụ thể:
- Xử lý theo lô nhỏ: Nếu thường xuyên vượt quá hạn mức, bạn có thể thấy bằng chứng về việc xử lý theo lô nhỏ trong dấu vết (ví dụ: số lượng thao tác SC nhỏ nhiều hơn dự kiến đối với kích thước lô toàn cục). Bạn thường có thể suy luận điều này từ nhật ký hoặc bằng cách quan sát số lần gọi của một số thao tác nhất định.
- Giảm mã nhận dạng: Nếu bạn bật và đang sử dụng tính năng giảm mã nhận dạng, thì nhật ký hệ thống có thể cho biết điều này. Đây cũng là dấu hiệu rõ ràng cho thấy các giới hạn đã định cấu hình quá hạn chế đối với dữ liệu đầu vào.
- Thời gian biên dịch: Thời gian biên dịch lại kéo dài (đặc biệt là nếu bạn bật tính năng Tối ưu hoá dựa trên phản hồi (FDO) và thường xuyên điều chỉnh các giới hạn) có thể làm tăng đáng kể chi phí chung cho tổng thời gian huấn luyện.
- Tương quan với cờ và cấu hình:
- Liên hệ hành vi quan sát được trong hồ sơ với cấu hình SparseCore (chế độ cài đặt trong tệp giới hạn, cờ XLA). Ví dụ: nếu đặt
xla_sc_num_serialized_tables_to_optimize_hbmthành một giá trị cao, bạn có thể dự kiến hiệu suất SC sẽ chậm hơn nhưng mức tiêu thụ ngăn xếp HBM sẽ thấp hơn.
- Liên hệ hành vi quan sát được trong hồ sơ với cấu hình SparseCore (chế độ cài đặt trong tệp giới hạn, cờ XLA). Ví dụ: nếu đặt
- Quy trình lặp lại:
- Lập hồ sơ thường là một quy trình tinh chỉnh lặp đi lặp lại. Thực hiện một thay đổi cụ thể (điều chỉnh hạn mức, bật hoặc tắt một tính năng), ghi lại một hồ sơ mới, rồi so sánh hồ sơ đó với hồ sơ trước đó để xem mức độ tác động của nội dung sửa đổi.
12. Cờ gỡ lỗi chung
Bạn có thể bật một số cờ để hỗ trợ gỡ lỗi các vấn đề liên quan đến việc thực thi SparseCore. Điều quan trọng cần lưu ý là việc bật các chế độ kiểm tra này thường làm giảm hiệu suất. Do đó, bạn thường nên tắt các chế độ này cho các lần chạy sản xuất.
- Kiểm tra giấy tờ tuỳ thân (ngoài phạm vi):
- Gắn cờ:
xla_sparse_core_enable_id_bound_check = true - Mục đích: Cho phép kiểm tra hệ thống lưu trữ để phát hiện xem có mã nhận dạng nhúng nào trong dữ liệu đầu vào nằm ngoài phạm vi từ vựng hợp lệ được xác định cho một bảng nhúng nhất định hay không. Điều này giúp phát hiện các vấn đề liên quan đến dữ liệu đầu vào không chính xác hoặc bị hỏng.
- Gắn cờ:
- Trình kiểm tra NaN:
- Gắn cờ:
xla_sc_detect_nan = true - Mục đích: Cho phép phát hiện các giá trị NaN (Không phải là số) trong dữ liệu dấu phẩy động được xử lý trên SparseCore. Nếu phát hiện thấy một NaN trong các đầu vào hoặc đầu ra của nhiều lượt truyền trình biên dịch, thì cờ này sẽ khiến một lỗi được đưa ra. Những lỗi như vậy thường cung cấp thông tin về vị trí gặp phải NaN.
- Gắn cờ:
- Bounds checker (truy cập bộ nhớ):
- Gắn cờ:
xla_sc_assert_level=bounds - Mục đích: Cờ này cho phép một công cụ kiểu ASAN (AddressSanitizer) ghi lại các chỉ dẫn truy cập bộ nhớ (chẳng hạn như các thao tác tải/lưu trữ VMEM và DMA) để đưa vào các quy trình kiểm tra động. Các bước kiểm tra này giúp xác minh xem quyền truy cập vào bộ nhớ có nằm trong giới hạn được phân bổ của vùng nhớ đích hay không.
- Hành vi: Nếu phát hiện thấy một hoạt động truy cập bộ nhớ ngoài phạm vi, quá trình thực thi sẽ không thành công.
- Thận trọng: Trình kiểm tra này có thể tạo ra kết quả dương tính giả, chẳng hạn như do các mẫu truy cập phức tạp theo bước mà trình kiểm tra không hiểu hết. Quy tắc biến đổi này được áp dụng ở giai đoạn cuối trong quá trình biên dịch phụ trợ.
- Gắn cờ:
- Trình kiểm tra vùng đệm (hỏng bộ nhớ):
- Cờ:
xla_tpu_buffer_contents_sanitizer_config='cores_to_sanitize: [TC, SC_SCS, SC_TILE], sanitizer_mode: LOCAL_ONLY'xla_tpu_verify_launch_id_across_cores=true
- Mục đích: Các cờ này giúp đảm bảo rằng các thao tác không liên quan không vô tình làm hỏng hoặc ghi đè các vùng đệm bộ nhớ. Buffer Sanitizer (Trình dọn dẹp vùng đệm) kiểm tra nội dung của các vùng đệm để xác minh rằng nội dung đó không thay đổi một cách bất ngờ.
- Cờ:
13. Hỗ trợ lượng tử hoá
SparseDenseMatmulOp của SparseCore được thiết kế để hỗ trợ các thao tác trên bảng nhúng bằng cả kiểu dữ liệu số nguyên và số có dấu phẩy động 32 bit (FP32). Mặc dù quá trình huấn luyện mô hình thường được thực hiện bằng độ chính xác FP32 cho các bảng nhúng, nhưng bạn có thể áp dụng phương pháp định lượng sau huấn luyện (PTQ). PTQ cho phép sử dụng các kiểu dữ liệu có độ chính xác thấp hơn (chẳng hạn như số nguyên 8 bit) để suy luận, điều này có thể giúp cải thiện hiệu suất và giảm dấu vết bộ nhớ.
Lượng tử hoá mô phỏng:
Bạn có thể định cấu hình SparseDenseMatmulOp để thực hiện "lượng tử hoá mô phỏng". Trong chế độ hoạt động này, các vectơ nhúng trước tiên được lượng tử hoá thành độ chính xác thấp hơn, sau đó được giải lượng tử hoá trở lại độ chính xác cao hơn (ví dụ: FP32) trước khi được dùng trong các phép tính tiếp theo. Kỹ thuật này cho phép huấn luyện các mô hình trong khi tính đến ảnh hưởng của nhiễu lượng tử hoá. Việc huấn luyện bằng cách mô phỏng lượng tử hoá có thể cải thiện độ chính xác của mô hình cuối cùng khi mô hình này được lượng tử hoá hoàn toàn để suy luận.
Thuộc tính cấu hình cho SparseDenseMatmulOp (để định lượng):
quantization_config_num_buckets = 256- Thuộc tính này chỉ định số lượng nhóm hoặc cấp độ riêng biệt mà số có dấu phẩy động 32 bit sẽ được lượng tử hoá. Ví dụ: khi lượng tử hoá thành số nguyên 8 bit, người ta thường chỉ định 2^8 =256 nhóm.
quantization_config_low = -X.X- Thuộc tính này xác định giá trị dấu phẩy động tối thiểu trong dải lượng tử hoá. Mọi giá trị đầu vào thấp hơn giá trị tối thiểu được chỉ định này sẽ được cắt thành giá trị tối thiểu này trong quá trình lượng tử hoá.
quantization_config_high = Y.Y- Thuộc tính này xác định giá trị dấu phẩy động tối đa trong dải lượng tử hoá. Mọi giá trị đầu vào lớn hơn giá trị tối đa được chỉ định này sẽ bị cắt thành giá trị tối đa này trong quá trình lượng tử hoá.
Tương tác bằng số và bằng cách truyền dữ liệu theo quy trình:
Hành vi số học của mô hình có thể thay đổi tuỳ thuộc vào việc bạn có bật tính năng pipelining giữa TensorCore và SparseCore hay không. Nếu quy trình truyền dữ liệu tuần tự đang hoạt động, thì các độ dốc do SparseCore xử lý có thể "cũ" (từ một lần lặp lại trước đó). Điều này có thể tương tác với quy trình lượng tử hoá và có khả năng ảnh hưởng đến động lực huấn luyện mô hình hoặc độ chính xác cuối cùng.
14. Các tính năng sắp ra mắt và điểm cải tiến gần đây
Hệ sinh thái SparseCore không ngừng được phát triển và cải tiến.
Lộ trình:
- Phân lô nhỏ theo phương diện mẫu:
- Đây là tính năng bổ sung cho các chức năng phân lô nhỏ theo phương diện từ vựng hiện có.
- Điều này sẽ cho phép phân vùng thêm các đầu vào nhúng theo phương diện mẫu. Điều này sẽ đạt được bằng cách giới thiệu các vòng lặp trên thiết bị có thể lọc và xử lý các lượt tra cứu từ một nhóm nhỏ mẫu tại một thời điểm. Tính năng như vậy có thể hữu ích cho việc quản lý số lượng mã nhận dạng rất lớn trên mỗi mẫu hoặc để cải thiện việc cân bằng tải trên các đơn vị xử lý.
- Cải thiện khả năng hỗ trợ nhúng với ít hơn 8 số nguyên trên mỗi hàng (chiều rộng đối tượng nhỏ):
- Thiết kế hiện tại thường sử dụng khoảng đệm đáng kể cho các chiều rộng của tính năng nhúng nhỏ hơn 8 số thực (tương ứng với 32 byte). Việc thêm khoảng đệm này có thể dẫn đến lãng phí HBM và có khả năng không tận dụng hết tài nguyên điện toán. Những điểm cải thiện trong tương lai nhằm giảm thiểu tình trạng không hiệu quả này đối với các bảng có kích thước đối tượng nhỏ.
Các điểm cải tiến gần đây:
- Giai đoạn thu thập toán hạng trong HBM:
- Việc tối ưu hoá này giúp giảm áp lực lên bộ nhớ tạm dùng chung (SPMEM) bằng cách cho phép một số đầu vào hoặc đầu ra của thao tác thu thập được dàn dựng trong HBM lớn hơn.
- Giảm mức sử dụng bộ nhớ ngăn xếp:
- Chúng tôi đã triển khai các điểm cải tiến để giảm mức tiêu thụ bộ nhớ ngăn xếp HBM trong các hoạt động SparseCore, lý tưởng nhất là không ảnh hưởng tiêu cực đến hiệu suất hoặc thông lượng tổng thể.
Những điểm cải tiến này tập trung vào việc cải thiện hiệu suất, hiệu quả bộ nhớ và tính linh hoạt trong hoạt động của SparseCore cho nhiều loại tải công việc thưa thớt hơn nữa.