लार्ज एम्बेडिंग मॉडल (एलईएम) के लिए SparseCore के बारे में ज़्यादा जानकारी

SparseCore, टाइल वाला एक खास प्रोसेसर है. इसे ऐसे वर्कलोड की परफ़ॉर्मेंस को बेहतर बनाने के लिए डिज़ाइन किया गया है जिनमें अनियमित और कम मेमोरी ऐक्सेस करने के साथ-साथ कंप्यूटेशन शामिल होता है. खास तौर पर, हाई बैंडविड्थ मेमोरी (एचबीएम) में सेव किए गए बड़े डेटासेट पर. यह एम्बेड किए गए लुकअप जैसे कामों को आसानी से कर सकता है. हालांकि, इसकी क्षमताओं का इस्तेमाल, डाइनैमिक और स्पार्स वर्कलोड को तेज़ी से प्रोसेस करने के लिए भी किया जा सकता है.

1. SparseCore के बारे में जानकारी

आर्किटेक्चर की मुख्य विशेषताएं:

  • टाइल वाला आर्किटेक्चर: इसमें कई कंप्यूट टाइलें शामिल होती हैं. हर टाइल एक पूरी डेटाफ़्लो यूनिट होती है, जिसमें अपनी लोकल मेमोरी और प्रोसेसिंग यूनिट होती है. इससे पैरलल प्रोसेसिंग की जा सकती है.
  • डाइनैमिक एक्ज़ीक्यूशन: यह डेटा पर निर्भर कंट्रोल फ़्लो और मेमोरी ऐक्सेस को नेटिव तौर पर सपोर्ट करता है. यह कम डेटा के लिए ज़रूरी है.
  • वेक्टर प्रोसेसिंग: यह बेहतर तरीके से कंप्यूटेशन करने के लिए, छोटे-वेक्टर टास्क (हार्डवेयर वर्शन के आधार पर 8-एलिमेंट या 16-एलिमेंट) का इस्तेमाल करता है.
  • सेंट्रलाइज़्ड कंट्रोल: एक ही SparseCore सीक्वेंसर, सभी टाइल पर टास्क को व्यवस्थित करता है. इससे यह पक्का होता है कि सभी ऑपरेशन एक साथ हों.
  • डेटा की खास जानकारी देने की सुविधा: इसमें खास क्रॉस-लेन ऑपरेशन शामिल होते हैं. ये ऑपरेशन, सॉर्ट करने, फ़िल्टर करने, और प्रीफ़िक्स सम जैसे कामों के लिए फ़ायदेमंद होते हैं.
  • मेमोरी हैरारकी: यह बड़े डेटासेट को सेव करने के लिए, एचबीएम का इस्तेमाल करता है. साथ ही, बार-बार ऐक्सेस किए जाने वाले डेटा को स्टेज करने के लिए, लोकल स्क्रैचपैड मेमोरी (एसपीएमईएम) का इस्तेमाल करता है. इससे एचबीएम की लेटेन्सी काफ़ी कम हो जाती है.

एक नज़र में खास जानकारी:

एट्रिब्यूट TPU v4 TPU v5p Trillium
SparseCores/Chip 4 4 2
Tiles/SparseCore 16 16 16
SIMD Width 8 8 8 (F32) 16 (BF16)
एचबीएम की क्षमता 32 जीबी 96 GiB 32 जीबी

2. SparseCore होस्ट प्रीप्रोसेसिंग

SparseCore की परफ़ॉर्मेंस के लिए, डेटा को सही तरीके से तैयार करना बहुत ज़रूरी है. इसमें होस्ट प्रीप्रोसेसिंग अहम भूमिका निभाती है. इसमें कई मुख्य फ़ंक्शन शामिल हैं:

  • डेटा बदलना:
    • कच्चे इनपुट डेटा पर ज़रूरी ट्रांसफ़ॉर्मेशन लागू करें.
    • आईडी ट्रांसफ़ॉर्मेशन मैनेज करें. यह सुविधा या टेबल स्टैकिंग के साथ काम करते समय खास तौर पर ज़रूरी होती है.
    • इनपुट डेटा को कोऑर्डिनेट (सीओओ) स्पार्स फ़ॉर्मैट में बदलें. इसके बारे में ज़्यादा जानकारी, यहां दी गई है.
    • डेटा को इस तरह से बांटें कि उसे चिप पर मौजूद अलग-अलग SparseCore में आसानी से डिस्ट्रिब्यूट किया जा सके.
  • सीमा की पुष्टि करना:
    • पक्का करें कि इनपुट डेटा की विशेषताएं (उदाहरण के लिए, आईडी की संख्या), SparseCore की पहले से तय की गई ऑपरेशनल सीमाओं के मुताबिक हों. जैसे, max_ids_per_partition और max_unique_ids_per_partition.
    • अगर इनपुट डेटा इन सीमाओं से ज़्यादा है, तो होस्ट प्रीप्रोसेसिंग लेयर, डेटा को छोटे-छोटे मिनी-बैच में बांटने की कोशिश कर सकती है. इससे डेटा, तय सीमाओं के मुताबिक हो जाएगा.
  • डेटा ट्रांसफ़र:
    • प्रोसेस किए गए और पुष्टि किए गए डेटा को टीपीयू की हाई बैंडविड्थ मेमोरी (एचबीएम) में आसानी से कॉपी करता है, ताकि इसे SparseCore पर लागू किया जा सके.

टेबल स्टैकिंग को समझना:

टेबल स्टैकिंग, ऑप्टिमाइज़ेशन की एक अहम तकनीक है. इसमें कई एम्बेडिंग टेबल को तार्किक तरीके से एक साथ जोड़ा जाता है, ताकि एम्बेडिंग लुकअप की क्षमता को बढ़ाया जा सके. आम तौर पर, इस प्रोसेस को एमएल फ़्रेमवर्क अपने-आप मैनेज करता है.

  • फ़िचर स्टैकिंग: ऐसा तब होता है, जब कई अलग-अलग सुविधाएं एक ही एम्बेडिंग टेबल शेयर करती हैं. इसका एक सामान्य उदाहरण यह है कि अलग-अलग कॉन्टेक्स्ट के ज़िप कोड जैसी कई कैटगरी वाली सुविधाओं के लिए, एक ही एम्बेडिंग डिक्शनरी का इस्तेमाल किया जाता है.
  • टेबल स्टैकिंग: इस स्थिति में, अलग-अलग एम्बेडिंग टेबल को एक साथ स्टैक किया जाता है. एक जैसे एम्बेडिंग डाइमेंशन और ऑप्टिमाइज़र कॉन्फ़िगरेशन वाली टेबल को अक्सर ग्रुप किया जाता है.

टेबल स्टैकिंग का मुख्य फ़ायदा यह है कि इससे स्टैक की गई इन टेबल पर कार्रवाइयों के लिए, ज़्यादा असरदार बैच साइज़ बनाया जा सकता है. इससे कंप्यूटेशनल ओवरहेड कम हो जाता है. साथ ही, यह इंटर-चिप कम्यूनिकेशन (आईसीआई) की लेटेन्सी को छिपाने में असरदार हो सकता है. बेहतर परफ़ॉर्मेंस के लिए, स्टैक की गई टेबल की संख्या सामान्य होनी चाहिए. आम तौर पर, यह संख्या 5 से 100 के बीच होती है.

3. COO टेंसर में कन्वर्ज़न

SparseCore से डेटा प्रोसेस करने से पहले, आम तौर पर इसे कोऑर्डिनेट (COO) स्पार्स टेंसर फ़ॉर्मैट में बदला जाता है. COO फ़ॉर्मैट, स्पार्स मैट्रिक्स को असरदार तरीके से दिखाने का एक तरीका है. आम तौर पर, इसमें तीन ऐरे का इस्तेमाल किया जाता है:

  • row_ids: यह एक ऐसा कलेक्शन है जिसमें हर नॉन-ज़ीरो एलिमेंट के लिए पंक्ति के इंडेक्स होते हैं. बैच प्रोसेसिंग के संदर्भ में, यह अक्सर बैच डाइमेंशन से मेल खाता है.
  • col_ids: यह एक ऐसा कलेक्शन होता है जिसमें हर नॉन-ज़ीरो एलिमेंट के लिए कॉलम इंडेक्स शामिल होते हैं. एम्बेड करने के लिए, ये अक्सर सुविधा या आईडी की वैल्यू होती हैं.
  • values (ज़रूरी नहीं): यह एक ऐसी सरणी होती है जिसमें (row, col) कोऑर्डिनेट पर मौजूद, शून्य से अलग वैल्यू वाले एलिमेंट की असल वैल्यू होती हैं. आईडी की संख्या से जुड़ी सीमाएं तय करते समय, इन वैल्यू (फ़ायदे) को अक्सर ध्यान में नहीं रखा जाता. इस बारे में बाद में बताया गया है.

उदाहरण के लिए:

आईडी के बैच दिखाने वाली स्पार्स मैट्रिक्स के इनपुट पर विचार करें:

[
    [id_A],                 // Sample 0
    [id_A, id_B, id_C],     // Sample 1
    [id_B, id_B, id_D],     // Sample 2 (note duplicate id_B)
]

COO फ़ॉर्मैट में बदलने के बाद (और हो सकता है कि एक ही सैंपल में आईडी को डुप्लीकेट से हटाने के बाद):

row_ids = [0, 1, 1, 1, 2, 2]
col_ids = [id_A, id_A, id_B, id_C, id_B, id_D]

SparseCore, काम को प्रोसेस और डिस्ट्रिब्यूट करने के लिए इस कन्वर्ज़न का इस्तेमाल करता है. खास तौर पर, col_ids यह तय करने के लिए ज़रूरी हैं कि कोई आईडी किस खास SparseCore पार्टीशन से जुड़ा है. इससे शार्डिंग और लुकअप को बेहतर तरीके से किया जा सकता है.

4. SparsecoreConfig: यह हाई-लेवल एपीआई है

फ़्रेमवर्क के हिसाब से एम्बेड किए जाने वाले एपीआई:

SparsecoreConfig या XLA फ़्लैग जैसे मिलते-जुलते तरीके, SparseCore के कई व्यवहारों को कंट्रोल करने के लिए एक हाई-लेवल इंटरफ़ेस के तौर पर काम करते हैं. इन पैरामीटर के बारे में पूरी जानकारी होना, परफ़ॉर्मेंस को बेहतर बनाने और यह पक्का करने के लिए ज़रूरी है कि आपके मॉडल सही तरीके से काम कर रहे हैं.

  • disable_table_stacking: bool = False
    • वजह: यह फ़्लैग कंट्रोल करता है कि टेबल स्टैकिंग की सुविधा अपने-आप चालू होती है या नहीं. टेबल स्टैकिंग की सुविधा चालू होने पर, फ़्रेमवर्क को टेबल स्टैक करने से रोका जाता है. इससे परफ़ॉर्मेंस कम हो सकती है, क्योंकि ओवरहेड बढ़ जाते हैं. साथ ही, इंटर-चिप इंटरकनेक्ट (आईसीआई) की लेटेन्सी को छिपाने की क्षमता कम हो जाती है.
    • डिफ़ॉल्ट: False (इसका मतलब है कि टेबल स्टैकिंग की सुविधा आम तौर पर डिफ़ॉल्ट रूप से चालू होती है. हालांकि, यह सुविधा सिर्फ़ उन फ़्रेमवर्क में काम करती है जहां इसे इस्तेमाल किया जा सकता है).
  • max_ids_per_chip_per_sample: int = 64
    • जानकारी: यह पैरामीटर, एम्बेड किए गए आईडी की कुल संख्या पर एक ग्लोबल ऊपरी सीमा तय करता है. यह संख्या, इनपुट बैच में मौजूद एक सैंपल से एक चिप प्रोसेस कर सकती है. यह संख्या, सभी टेबल के लिए एग्रीगेट की जाती है. यह चिप लेवल पर संसाधनों को मैनेज करने का एक तरीका है. इसमें, टेबल या पार्टीशन के हिसाब से तय की गई ज़्यादा जानकारी वाली सीमाओं को ध्यान में रखा जाता है. इस वैल्यू को बेहतर बनाने के लिए, आम तौर पर मॉडल की खास बातों और सिस्टम की कुल क्षमता पर निर्भर रहना पड़ता है.
    • डिफ़ॉल्ट: 64.
  • max_ids_per_table: Optional[Dict[str, int]] = None
    • जानकारी: यह पैरामीटर, एम्बेडिंग आईडी की ज़्यादा से ज़्यादा संख्या के बारे में बताता है. इसमें डुप्लीकेट आईडी भी शामिल हो सकते हैं. इन आईडी को हर लॉजिकल टेबल के लिए प्रोसेस किया जा सकता है. इसके लिए, सभी SparseCore में मौजूद सभी पार्टीशन को ध्यान में रखा जाता है. यह max_ids_per_partition से ज़्यादा है. अगर किसी टेबल T को P पार्टिशन में बांटा गया है, तो यह सीमा उन सभी आईडी के योग पर लागू होती है जिन्हें सभी P पार्टिशन पर भेजा गया है. यह अक्सर max_ids_per_partition_per_sample और बैच के कुल साइज़ से जुड़ा होता है.
    • सेटिंग: आम तौर पर, इसे सीमा तय करने वाली फ़ाइल का इस्तेमाल करके कॉन्फ़िगर किया जाता है. उदाहरण के लिए, xla_sparse_core_max_ids_file फ़्लैग का इस्तेमाल करके, जहां max_ids_per_partition को तय किया जाता है. टेबल लेवल का यह कॉन्सेप्ट, पार्टीशन लेवल की उन सीमाओं (max_ids और max_uniques) को सेट करने का एक तरीका है.
    • डिफ़ॉल्ट: None (अगर साफ़ तौर पर नहीं बताया गया है, तो वैल्यू को हर पार्टीशन की सीमाओं या अन्य कॉन्फ़िगरेशन से अनुमानित किया जा सकता है).
  • max_unique_ids_per_table: Optional[Dict[str, int]] = None
    • ब्यौरा: यह max_ids_per_table के जैसा ही है. हालांकि, यह पैरामीटर हर लॉजिकल टेबल के लिए यूनीक आईडी की ज़्यादा से ज़्यादा संख्या तय करता है. यह सेटिंग, डिवाइस पर मौजूद बफ़र के साइज़ को सही तरीके से सेट करने के लिए ज़रूरी है. इन बफ़र का इस्तेमाल, यूनीक आईडी प्रोसेसिंग और उसके बाद की वेक्टर कार्रवाइयों में किया जाता है.
    • सेटिंग: इसे आम तौर पर, सीमाएं तय करने वाली फ़ाइल में भी तय किया जाता है या max_unique_ids_per_partition_per_sample से लिया जाता है.
    • डिफ़ॉल्ट: None.
  • allow_id_dropping: bool = False
    • वजह: यह बूलियन फ़्लैग, आईडी ड्रॉप करने की सुविधा को कंट्रोल करता है. ऐसा तब होता है, जब इनपुट डेटा में मिले आईडी की संख्या (देखी गई सीमाएं), कंपाइल करने के दौरान सेट की गई सीमाओं (उदाहरण के लिए, max_ids_per_partition) से ज़्यादा हो जाती है.
      • अगर True: जिन आईडी की वजह से सीमाएं पार हो सकती हैं उन्हें चुपचाप हटा दिया जाता है. आम तौर पर, किसी पार्टीशन में मौजूद आईडी को क्रम से प्रोसेस किया जाता है. साथ ही, जिस आईडी की वजह से, तय की गई मिनी-बैच की सीमा से ज़्यादा आईडी प्रोसेस हो जाते हैं उसे हटा दिया जाता है. इससे प्रोग्राम को काम करना जारी रखने की अनुमति मिलती है. हालांकि, इससे मॉडल की सटीकता पर बुरा असर पड़ सकता है.
      • अगर False: गड़बड़ी ट्रिगर होती है. साथ ही, अगर तय की गई सीमाएं, कंपाइल की गई सीमाओं से ज़्यादा हो जाती हैं, तो प्रोसेस बंद हो जाएगी. इस तरीके से, यह पक्का किया जाता है कि सभी डेटा को प्रोसेस किया जाए. हालांकि, इसके लिए सीमाओं को ज़्यादा सावधानी से कॉन्फ़िगर करना ज़रूरी होता है.
    • डिफ़ॉल्ट: False (डेटा साइलेंट तरीके से ड्रॉप होने के बजाय, ओवरफ़्लो होने पर गड़बड़ी होती है).
  • initialize_tables_on_host: bool = True

    • जानकारी: यह फ़्लैग तय करता है कि एम्बेडिंग टेबल को होस्ट सीपीयू पर शुरू किया जाए या नहीं. इसके बाद, इन्हें टीपीयू की हाई बैंडविड्थ मेमोरी (एचबीएम) में ट्रांसफ़र किया जाता है. टेबल को होस्ट पर शुरू करना स्टैंडर्ड तरीका है. इसे True पर सेट करने से, इस कन्वेंशन का पालन किया जाता है. अगर इसे False पर सेट किया जाता है, तो इसका मतलब होगा कि डिवाइस पर मौजूद डेटा का इस्तेमाल करके मॉडल को शुरू किया गया है. इससे परफ़ॉर्मेंस पर अलग-अलग तरह के असर पड़ सकते हैं या मॉडल को शुरू करने के लिए कुछ खास शर्तें पूरी करनी पड़ सकती हैं.
  • enable_fast_table_initialization: bool = False

    • जानकारी: यह फ़ंक्शन, टेबल को सीधे तौर पर टीपीयू पर शुरू करता है. इससे मॉडल को शुरू होने में लगने वाला समय कम हो सकता है.

5. परफ़ॉर्मेंस के लिए पाइपलाइनिंग

पाइपलाइनिंग, परफ़ॉर्मेंस को ऑप्टिमाइज़ करने की एक ऐसी तकनीक है जिसकी मदद से TensorCore (टीसी) और SparseCore (एससी) पर एक साथ कई कार्रवाइयां की जा सकती हैं. इन कंप्यूटेशन को ओवरलैप करके, कुल थ्रूपुट को काफ़ी हद तक बेहतर बनाया जा सकता है.

  • मैकेनिज़्म: ट्रेनिंग के स्टैंडर्ड चरण में, स्पार्स एम्बेडिंग लुकअप (SC मैनेज करता है) और डेंस लेयर कंप्यूटेशन (TC मैनेज करता है) शामिल होते हैं. पाइपलाइनिंग की मदद से, SC को चरण i के अपने हिस्से पर काम करने की अनुमति मिलती है. उदाहरण के लिए, फ़ॉरवर्ड या बैकवर्ड पास. वहीं, TC एक साथ उसी चरण i के किसी दूसरे हिस्से या आस-पास के चरणों, जैसे कि i-1 या i+1 के हिस्सों को प्रोसेस करता है.
  • ग्रेडिएंट पर असर: SparseCore, "पुराने" ग्रेडिएंट पर काम कर सकता है. उदाहरण के लिए, ऐसा हो सकता है कि चरण i के बैकप्रॉपैगेशन फ़ेज़ के दौरान कैलकुलेट किए गए ग्रेडिएंट, चरण i+2 तक पूरी तरह से अपडेट न हों और एससी को न दिखें.
  • परफ़ॉर्मेंस बनाम संख्यात्मक ट्रेड-ऑफ़: एक साथ कई निर्देशों को लागू करने से, परफ़ॉर्मेंस में काफ़ी सुधार हो सकता है. इससे डिवाइस के स्टेप टाइम में दो गुना तक सुधार हो सकता है. हालांकि, पुराने ग्रेडिएंट का इस्तेमाल करने से, संख्याओं (embedding_weights) में मामूली बदलाव हो सकते हैं. इससे मॉडल कन्वर्जेंस के व्यवहार या हासिल की गई फ़ाइनल सटीकता पर असर पड़ सकता है. इस ट्रेड-ऑफ़ को स्वीकार किया जा सकता है या नहीं, यह काफ़ी हद तक मॉडल पर निर्भर करता है. साथ ही, इसके लिए अक्सर अनुभवजन्य पुष्टि की ज़रूरत होती है.
  • कंट्रोल फ़्लैग: पाइपलाइनिंग को tf_xla_disable_full_embedding_pipelining से कंट्रोल किया जा सकता है. इस फ़्लैग को true पर सेट करने से, फ़ुल पाइपलाइनिंग (TensorCore और SparseCore कंप्यूटेशन का ओवरलैप होना) बंद हो जाती है. वहीं, इसे false पर सेट करने से (या अगर फ़्लैग के सिमैंटिक का मतलब यह है कि फ़ॉल्स होने पर इसे चालू किया जाता है), यह चालू हो जाती है.

कॉन्सेप्चुअल पाइपलाइनिंग फ़्लो:

  • पाइपलाइनिंग के बिना (आसान क्रमवार फ़्लो):

    Loop: SC/F_i -> TC/F_i -> TC/B_i -> SC/B_i

  • पाइपलाइनिंग (आसानी से ओवरलैप होने वाला फ़्लो) के साथ:

    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+1
    

    ध्यान दें: हार्डवेयर और कंपाइलर में लागू किए गए पाइपलाइनिंग के असली चरण ज़्यादा जटिल हो सकते हैं. इनमें अक्सर प्री-लूप, मुख्य एक्ज़ीक्यूशन लूप, और पोस्ट-लूप शामिल होते हैं. इनका इस्तेमाल डेटा डिपेंडेंसी को मैनेज करने और यह पक्का करने के लिए किया जाता है कि डेटा सही हो.

6. एक्सएलए की भूमिका

XLA (ऐक्सलरेटेड लीनियर अलजेब्रा), डोमेन के हिसाब से काम करने वाला कंपाइलर है. यह TensorFlow जैसे फ़्रेमवर्क से मिले हाई-लेवल के कंप्यूटेशनल ग्राफ़ को, टीपीयू के हिसाब से बनाए गए मशीन कोड में बदलता है. इसमें SparseCore के लिए तय किए गए ऑपरेशंस के निर्देश जनरेट करना शामिल है.

SparseCore कॉन्टेक्स्ट में मुख्य फ़ंक्शन:

  • स्पार्स ऑपरेशंस का कंपाइलेशन: XLA, एम्बेडिंग लुकअप ऑपरेशंस (जैसे कि SparseDenseMatmulOp) और अन्य स्पार्स कंप्यूटेशन को लो-लेवल, एक्ज़ीक्यूटेबल SparseCore प्रोग्राम में कंपाइल करने के लिए ज़िम्मेदार होता है.
  • सीमाओं का इंटिग्रेशन: यह कॉन्फ़िगर की गई ऑपरेशनल सीमाओं का इस्तेमाल करता है. उदाहरण के लिए, max_ids_per_partition, max_unique_ids_per_partition. ये सीमाएं अक्सर xla_sparse_core_max_ids_file जैसे फ़्लैग से तय की गई सीमाओं वाली फ़ाइल के ज़रिए दी जाती हैं. इनका इस्तेमाल, साइज़ तय करने और डिवाइस पर मौजूद मेमोरी बफ़र को स्टैटिक तौर पर असाइन करने के लिए किया जाता है. खास तौर पर, SPMEM में.
  • टारगेट किए गए ऑप्टिमाइज़ेशन: XLA, ऑप्टिमाइज़ेशन का एक सुइट उपलब्ध कराता है. इसे खास तौर पर SparseCore आर्किटेक्चर के लिए डिज़ाइन किया गया है. इनमें, निर्देशों को शेड्यूल करना, मेमोरी लेआउट में बदलाव करना, और ज़्यादा से ज़्यादा दक्षता के लिए ऑपरेशनों को फ़्यूज़ करना शामिल हो सकता है.
  • फ़्लैग का इस्तेमाल करके कंट्रोल करना: SparseCore के व्यवहार, ट्यूनिंग पैरामीटर, और ऑप्टिमाइज़ेशन की रणनीतियों के कई पहलुओं को XLA फ़्लैग के ज़रिए दिखाया और कंट्रोल किया जाता है. उदाहरण के लिए, सीमा का अनुमान लगाने के लिए xla_sparse_core_estimate_max_ids या डीबग करने के लिए xla_sc_detect_nan.

ओपन सोर्स की स्थिति:

फ़िलहाल, Sparsecore Implementation सिर्फ़ अंदरूनी तौर पर उपलब्ध है और इसे libtpu.so का इस्तेमाल करके दिखाया जाता है.

गड़बड़ी की रिपोर्टिंग और डाइग्नोस्टिक्स:

SparseCore कॉन्फ़िगरेशन या संसाधन की सीमाओं से जुड़ी कंपाइल करने की गड़बड़ियां, अक्सर XLA:TPU कंपाइल-टाइम की गड़बड़ियों के तौर पर दिखती हैं. गड़बड़ी के इन मैसेज से, कई समस्याओं के बारे में अहम जानकारी मिल सकती है. जैसे, उपलब्ध SPMEM के लिए बहुत ज़्यादा सीमाएं सेट की गई हैं या ऐसे कॉन्फ़िगरेशन का इस्तेमाल किया जा रहा है जो काम नहीं करते.

7. SparseCore पर टेबल के लिए सीमाएं कैसे लागू होती हैं

SparseCore पर, "सीमाएं" बुनियादी कॉन्फ़िगरेशन पैरामीटर होती हैं. ये मुख्य रूप से, हर उस टेबल के लिए दो पर-पार्टिशन सेटिंग को रेफ़र करती हैं जिसे उपलब्ध SparseCore में शार्ड (डिस्ट्रिब्यूट) किया गया है:

  • max_ids_per_partition: इससे कुल आईडी की ज़्यादा से ज़्यादा संख्या तय होती है. इसमें डुप्लीकेट आईडी भी शामिल होते हैं. यह संख्या बताती है कि किसी एक कंप्यूटेशनल चरण में, कोई भी सिंगल SparseCore, किसी दी गई टेबल के किसी खास पार्टीशन के लिए, कितने आईडी भेज सकता है या प्रोसेस कर सकता है.
  • max_unique_ids_per_partition: इससे यूनीक आईडी की वह ज़्यादा से ज़्यादा संख्या तय होती है जिसे कोई भी SparseCore, किसी

फ़िज़िकल टेबल लेआउट और प्रोसेसिंग में अनुवाद:

  • टेबल शार्डिंग की रणनीति: एम्बेड की गई टेबल को आम तौर पर, सिस्टम में मौजूद सभी SparseCore में "मॉड-शार्ड" किया जाता है. इसका मतलब है कि हर SparseCore, हर टेबल के शब्दावली (पंक्तियों) के अलग-अलग सबसेट के लिए ज़िम्मेदार होता है. आम तौर पर, SparseCore_k को आईडी j असाइन किया जाता है. यह k = j % num_total_sparse_cores जैसे फ़ॉर्मूले के आधार पर होता है.
  • "पार्टिशन" की परिभाषा: इस संदर्भ में, "पार्टिशन" का मतलब एम्बेडिंग टेबल के उस खास सेगमेंट से है जिसके लिए एक SparseCore, लुकअप को हैंडल करता है.
  • एसपीएमईएम बफ़र का असाइनमेंट: इन सीमाओं का इस्तेमाल XLA कंपाइलर करता है. इससे डिवाइस पर मौजूद स्क्रैचपैड मेमोरी (एसपीएमईएम) में बफ़र का साइज़ तय किया जाता है और उन्हें असाइन किया जाता है. बफ़र को इस तरह से डाइमेंशन किया जाता है कि किसी दिए गए पार्टीशन के आईडी से जुड़ा सभी ज़रूरी डेटा, प्रोसेसिंग के लिए SPMEM में लोड किया जा सके. यह डेटा, तय की गई max_ids और max_unique_ids सीमाओं तक हो सकता है. यह खास तौर पर, एलिमेंट के हिसाब से न की जाने वाली कंप्यूटिंग के लिए ज़रूरी है. जैसे, किसी पार्टीशन में डुप्लीकेट आईडी कम करना. उदाहरण के लिए, कंप्रेस की गई स्पार्स लाइन (सीएसआर) का प्रज़ेंटेशन बनाते समय, उस पार्टीशन के आईडी के लिए पूरा काम का डेटासेट, फ़ास्ट मेमोरी में तुरंत उपलब्ध होना चाहिए.
  • तय की गई सीमाएं बनाम देखी गई सीमाएं:

    • मॉनिटर की गई सीमाएं: ये रनटाइम के दौरान, हर पार्टीशन के लिए मिले आईडी की असल संख्या होती है. यह संख्या, प्रोसेस किए जा रहे इनपुट डेटा पर आधारित होती है.
    • अगर देखी गई सीमाएं, कंपाइल की गई सीमाओं से ज़्यादा हैं, तो इससे आईडी ड्रॉप हो सकता है (अगर allow_id_dropping चालू है) या गड़बड़ियां हो सकती हैं.
  • सीमाएं तय करना: सही सीमाएं तय करने के लिए, इनपुट डेटा के डिस्ट्रिब्यूशन का ध्यान से विश्लेषण किया जाता है. किसी भी टेबल के लिए (इसे T1 कहते हैं, जो खुद स्टैक की गई बड़ी टेबल T का हिस्सा हो सकती है):

    1. इनपुट बैच (उदाहरण के लिए, [BatchSize, MaxSequenceLength] शेप का 2D SparseTensor) को शुरुआत में उपलब्ध SparseCore में बांटा जाता है. उदाहरण के लिए, अगर किसी TensorCore को दो SparseCore के साथ जोड़ा जाता है, तो हर SparseCore को [BatchSize/2, MaxSequenceLength] शेप का सब-बैच मिल सकता है.
    2. इसके बाद, इस सब-बैच को सीओओ फ़ॉर्मैट में बदला जाता है. इससे row_ids और col_ids मिलते हैं.
    3. एक ही सैंपल में मौजूद डुप्लीकेट आईडी (यानी कि एक ही row_id और col_id वाली एंट्री) हटा दिए जाते हैं.
    4. हर बचे हुए यूनीक col_id (सैंपल में मौजूद) के लिए, इस आईडी के लिए ज़िम्मेदार टारगेट SparseCore का पता लगाने के लिए, मोड-शार्डिंग के नियम का इस्तेमाल किया जाता है: target_sc_id = col_id % num_total_sparse_cores.
    5. हर target_sc_id के लिए, आईडी (ids_per_sparse_core[target_sc_id]++) की कुल संख्या और यूनीक आईडी (unique_ids_per_sparse_core[target_sc_id]++, यह पक्का करने के बाद कि उस खास target_sc_id के लिए आईडी यूनीक है) की संख्या का हिसाब रखा जाता है.
    6. इसके बाद, टेबल T1 के लिए max_ids_per_partition को max(ids_per_sparse_core_array) पर सेट कर दिया जाता है.
    7. इसी तरह, टेबल T1 के लिए max_unique_ids_per_partition को max(unique_ids_per_sparse_core_array) पर सेट किया गया है.
    8. अगर टेबल T1, स्टैक की गई टेबल का कॉम्पोनेंट है, तो सभी कॉम्पोनेंट टेबल से आंकड़ों को जोड़ने से पहले, आईडी डिस्ट्रिब्यूशन पर रोटेशन या शिफ़्ट जैसे अतिरिक्त बदलाव लागू किए जा सकते हैं. इससे सभी चिप पर लोड को बराबर रखने में मदद मिलती है.

इन सीमाओं को सही तरीके से सेट करना एक मुश्किल काम है: कम सीमाएं सेट करने से, परफ़ॉर्मेंस बेहतर हो सकती है. ऐसा इसलिए, क्योंकि हर चरण में कम डेटा प्रोसेस करना पड़ता है और एसपीएमईएम पर दबाव कम हो जाता है. हालांकि, अगर इन्हें बहुत कम पर सेट किया जाता है, तो इससे बहुत ज़्यादा मिनी-बैचिंग हो सकती है या आईडी को अनचाहे तरीके से हटाया जा सकता है.

8. हर SparseCore कैसे कम्यूनिकेट करता है

स्पार्सकोर कम्यूनिकेशन, खास तौर पर एंबेडिंग लुकअप के लिए आईडी की सूची को प्रोसेस करने के संदर्भ में, कई कोऑर्डिनेटेड तरीकों पर निर्भर करता है:

  • मॉड शार्डिंग और इंप्लिसिट राउटिंग:
    • एम्बेड की गई टेबल को सिस्टम में मौजूद सभी SparseCore में मोड-शार्ड किया जाता है.
    • जब होस्ट, इनपुट डेटा का बैच उपलब्ध कराता है, तो उसे बाद में COO फ़ॉर्मैट में प्रीप्रोसेस किया जाता है. इसमें col_ids भी शामिल होता है. col_id वैल्यू का इस्तेमाल यह तय करने के लिए किया जाता है कि उस खास आईडी: target_sc_id = col_id % num_total_sparse_cores के लिए कौनसी SparseCore ज़िम्मेदार है.
    • हर SparseCore, सिर्फ़ उन आईडी को पाता और प्रोसेस करता है जो उसके असाइन किए गए शब्दावली के हिस्सों से मैप होते हैं. होस्ट प्रीप्रोसेसिंग स्टेज, डेटा को इस तरह से तैयार करने के लिए ज़रूरी है कि हर SparseCore, अपने काम के आईडी को तुरंत पहचान सके और उन पर कार्रवाई कर सके.
  • होस्ट के हिसाब से डेटा डिस्ट्रिब्यूशन:
    • होस्ट प्रीप्रोसेसिंग लॉजिक, पूरे इनपुट बैच को अलग-अलग हिस्सों में बांटता है. इसके बाद, row_ids और col_ids के ज़रूरी हिस्सों को (अगर लागू हो, तो उनसे जुड़ी सुविधाओं या वज़न के साथ) हर SparseCore के लिए सीधे तौर पर उपलब्ध मेमोरी (HBM) या शेयर की गई HBM में डिस्ट्रिब्यूट करता है. SparseCore, शेयर की गई HBM से अपना ज़रूरी डेटा फ़ेच करेंगे.
  • इंट्रा-स्पार्सकोर प्रोसेसिंग:
    • जब किसी SparseCore को किसी टेबल पार्टीशन के लिए आईडी का तय किया गया सेट मिल जाता है, तो वह इन आईडी का डुप्लीकेट डेटा हटाने और उनसे जुड़े एम्बेडिंग वेक्टर इकट्ठा करने जैसे ऑपरेशन करता है. ये मुख्य रूप से लोकल कंप्यूटेशन होते हैं. इन्हें SparseCore के टाइल में ही एक्ज़ीक्यूट किया जाता है. साथ ही, इसके लोकल SPMEM का इस्तेमाल किया जाता है.
  • Inter-SparseCore communication (All-to-All):
    • शुरुआती प्रोसेसिंग फ़ेज़ (जैसे कि एम्बेडिंग लुकअप) के बाद, "ऑल-टू-ऑल" कम्यूनिकेशन पैटर्न का इस्तेमाल किया जा सकता है. इससे SparseCore में मौजूद नतीजों को एक साथ लाया जा सकता है या उन्हें फिर से डिस्ट्रिब्यूट किया जा सकता है. उदाहरण के लिए, ऐक्टिवेशन को TensorCore लेयर में फ़ीड करने से पहले, जो सभी ओरिजनल सैंपल पोज़िशन के हिसाब से इनपुट चाहती है. अगर ओरिजनल इनपुट बैच को पैरलल प्रोसेसिंग के लिए डिस्ट्रिब्यूट किया गया था, तो ऐक्टिवेशन के पूरे सेट को फिर से बनाने के लिए यह ज़रूरी है.
  • TensorCore के साथ कम्यूनिकेशन:
    • SparseCore, TensorCore के साथ कम्यूनिकेट करते हैं. इससे फ़ॉरवर्ड पास के दौरान एम्बेडिंग ऐक्टिवेशन भेजे जाते हैं और बैकवर्ड पास के दौरान ग्रेडिएंट मिलते हैं. इस इंटरैक्शन को XLA-कंपाइल किए गए प्रोग्राम से मैनेज किया जाता है. इसमें अक्सर HBM को इंटरमीडियरी बफ़र के तौर पर इस्तेमाल किया जाता है. पाइपलाइनिंग की रणनीति (जिसके बारे में पहले बताया गया है) से, एससी-टीसी के बीच होने वाले कम्यूनिकेशन के समय और सिंक्रनाइज़ेशन पर काफ़ी असर पड़ता है.

संक्षेप में कहें, तो सही SparseCore को आईडी "डिस्ट्रीब्यूट" करने का काम, मुख्य रूप से शार्डिंग स्कीम और होस्ट प्रीप्रोसेसिंग के चरणों से होता है. इसके बाद, SparseCores अपने लोकल डेटा पर काम करते हैं. इसके बाद, सामूहिक कम्यूनिकेशन ऑपरेशन किए जाते हैं. जैसे, अगर डेटा को TensorCores के ज़रिए आगे प्रोसेस करने से पहले, सभी SparseCores के बीच ग्लोबल स्तर पर एक्सचेंज या फिर से व्यवस्थित करना है, तो सभी के लिए एक ही ऑपरेशन किया जाता है.

9. SparseCore में मेमोरी मैनेज करने की सुविधा

हर SparseCore, कैलकुलेशन करने के लिए अलग-अलग तरह की मेमोरी को असरदार तरीके से मैनेज करता है:

  • स्क्रैचपैड मेमोरी (एसपीएमईएम):
    • नेचर: यह एक छोटा, लेकिन बहुत तेज़ लोकल एसआरएएम है. यह सिर्फ़ हर स्पार्सकोर के लिए उपलब्ध होता है. यह ध्यान रखना ज़रूरी है कि SPMEM, कैश मेमोरी नहीं है. इसका इस्तेमाल, XLA कंपाइलर मैनेज करता है.
    • मकसद: SPMEM का इस्तेमाल "डेटा को स्टेज करने के लिए" किया जाता है. इसमें इनपुट, आउटपुट, और इंटरमीडिएट नतीजे शामिल होते हैं. ये नतीजे, एससी की मौजूदा गणनाओं के लिए ज़रूरी होते हैं. SPMEM में डेटा को स्टेज करने से, HBM को ऐक्सेस करने में लगने वाला समय काफ़ी कम हो जाता है. आम तौर पर, HBM को ऐक्सेस करने में ज़्यादा समय लगता है.
    • साइज़ तय करना: "सीमाएं" सेक्शन में बताया गया है कि SPMEM बफ़र का साइज़, कंपाइल टाइम पर स्टैटिक तौर पर तय किया जाता है. यह साइज़िंग, max_ids_per_partition और max_unique_ids_per_partition जैसे पैरामीटर पर आधारित होती है. स्टैटिक तौर पर मेमोरी असाइन करने से यह पक्का होता है कि टेबल पार्टीशन पर की जाने वाली किसी भी कार्रवाई (जैसे कि सीएसआर कम करना) के लिए, उस पार्टीशन के आईडी का ज़रूरी डेटा (तय की गई सीमाओं तक) SPMEM में फ़िट हो सकता है.
    • कंपाइलर ऑप्टिमाइज़ेशन: XLA कंपाइलर में, बेहतर ऑप्टिमाइज़ेशन शामिल होते हैं. इनसे यह सटीक तरीके से तय किया जाता है कि HBM की लेटेन्सी को असरदार तरीके से छिपाने और परफ़ॉर्मेंस को ज़्यादा से ज़्यादा बढ़ाने के लिए, SPMEM में कितना डेटा और कौनसे डेटा एलिमेंट को स्टेज करने की ज़रूरत है.
    • डाइनैमिक ऐलोकेशन की सीमा: फ़िलहाल, SparseCore कंपाइलर, डाइनैमिक स्क्रैचपैड ऐलोकेशन की सुविधा के साथ काम नहीं करता. इससे पता चलता है कि सीमाएं तय करके, स्टैटिक साइज़िंग कितनी ज़रूरी है.
  • हाई बैंडविड्थ मेमोरी (एचबीएम):
    • नेचर: यह एक बड़ा, शेयर किया गया मेमोरी रिसॉर्स है. इसे सभी SparseCore, TensorCore, और होस्ट सिस्टम ऐक्सेस कर सकते हैं. प्राइमरी एम्बेडिंग टेबल, एचबीएम में सेव की जाती हैं.
    • स्टैक का इस्तेमाल: SparseCore ऑपरेशनों के लिए, अक्सर इंटरमीडिएट नतीजों को HBM में कुछ समय के लिए सेव करने की ज़रूरत होती है. ये नतीजे, सीमित SPMEM में फ़िट नहीं होते या इन्हें प्रोसेसिंग पाइपलाइन के बड़े चरणों के बीच पास करने की ज़रूरत होती है. फ़ॉरवर्ड और बैकवर्ड, दोनों पास के दौरान एचबीएम स्टैक के इस्तेमाल का अनुमान इस तरह लगाया जा सकता है -
      • फ़ॉरवर्ड पास एचबीएम स्टैक (सिंगल टेबल) ≈ (2 * feature_width + 1) * max_unique_nz_per_row * logical_replica_count * 4 बाइट
      • बैकवर्ड पास एचबीएम स्टैक (सिंगल टेबल) ≈ 3 * feature_width * max_unique_nz_per_row * logical_replica_count * 4 बाइट
    • हीप का इस्तेमाल: एचबीएम में हीप भी शामिल होता है, जिसे होस्ट मैनेज करता है. हीप में, डेंस लेयर के वेट, मॉडल में इस्तेमाल होने वाले कॉन्स्टेंट, और पहले से फ़ेच किया गया इनपुट डेटा जैसे डेटा को सेव किया जाता है. होस्ट जितने ज़्यादा चरणों के लिए डेटा को पहले से फ़ेच करता है, Heap का इस्तेमाल उतना ही ज़्यादा होता है. इसे maximum_parallel_iterations फ़्लैग से कंट्रोल किया जाता है. ज़्यादा प्रीफ़ेचिंग से परफ़ॉर्मेंस बेहतर हो सकती है. ऐसा इसलिए, क्योंकि यह होस्ट से डिवाइस में डेटा ट्रांसफ़र करने की प्रोसेस को डिवाइस पर डेटा प्रोसेस करने की प्रोसेस के साथ ओवरलैप कर देती है. हालांकि, इससे ज़्यादा एचबीएम का इस्तेमाल होता है.
    • एचबीएम ऑप्टिमाइज़ेशन के लिए सीरियलाइज़ेशन: फ़्लैग xla_sc_num_serialized_tables_to_optimize_hbm की मदद से यह कंट्रोल किया जा सकता है कि किसी भी समय एचबीएम स्टैक मेमोरी में कितनी टेबल का डेटा "लाइव" रखा जाए. इस संख्या को बढ़ाने से, ज़्यादा टेबल के लिए प्रोसेसिंग को असरदार तरीके से क्रम से किया जाता है. इससे पीक एचबीएम स्टैक के इस्तेमाल को कम किया जा सकता है. हालांकि, पैरललिज़्म कम होने की वजह से, परफ़ॉर्मेंस पर असर पड़ सकता है.
  • वेक्टर मेमोरी (वीएमईएम):
    • वीएमईएम, लोकल स्क्रैचपैड मेमोरी होती है. इसका इस्तेमाल सिर्फ़ टीसी (टेंसरकोर) करता है. VMEM को सीधे तौर पर SparseCore मैनेज नहीं करता है. हालांकि, यह मेमोरी इकोसिस्टम का एक अहम हिस्सा है. SC, मुख्य रूप से TensorCore के ज़रिए इससे इंटरैक्ट करता है.

मेमोरी मैनेज करने की पूरी रणनीति:

SparseCore के लिए मेमोरी मैनेजमेंट की मुख्य रणनीति, "हॉट" डेटा के लिए छोटे और तेज़ SPMEM का इस्तेमाल करने के बारे में है. इस डेटा को SparseCore टाइल से प्रोसेस किया जाता है. इससे, धीमी गति वाले HBM को कम से कम ऐक्सेस किया जा सकता है. कॉन्फ़िगर की गई सीमाएं, यह पक्का करने का मुख्य तरीका है कि SPMEM ओवरफ़्लो न हो. एचबीएम का इस्तेमाल, बड़ी एम्बेडिंग टेबल और कुछ समय के लिए सेव किए जाने वाले ऐसे डेटा को सेव करने के लिए किया जाता है जो एसपीएमईएम की क्षमता से ज़्यादा होता है. इसके अलावा, इसका इस्तेमाल ऐसे डेटा को सेव करने के लिए भी किया जाता है जिसे अलग-अलग प्रोसेसिंग यूनिट या पाइपलाइन स्टेज के साथ शेयर करना होता है. XLA कंपाइलर, इन आर्किटेक्चरल सिद्धांतों और उपयोगकर्ता की ओर से कॉन्फ़िगर की गई सीमाओं के आधार पर, सभी डेटा मूवमेंट और बफ़र के बंटवारे को व्यवस्थित करने के लिए ज़िम्मेदार होता है.

10. परफ़ॉर्मेंस और मेमोरी बॉटलनेक

SparseCore की मदद से बेहतर परफ़ॉर्मेंस पाने के लिए, संभावित समस्याओं और उन्हें ठीक करने के तरीके के बारे में साफ़ तौर पर जानकारी होना ज़रूरी है. ये समस्याएं, होस्ट पर, SparseCore में या TensorCore के साथ इंटरैक्ट करते समय हो सकती हैं.

परफ़ॉर्मेंस से जुड़ी आम समस्याएं:

  • होस्ट बॉटलनेक:
    • समस्या: ऐसा हो सकता है कि होस्ट सीपीयू, डेटा को पहले से प्रोसेस न कर पाए और उसे टीपीयू को तेज़ी से फ़ीड न कर पाए. इससे SparseCore और TensorCore का कम इस्तेमाल होता है. यह परफ़ॉर्मेंस को अक्सर सीमित करने वाला फ़ैक्टर है.
    • समस्या हल करना: होस्ट सीपीयू के इस्तेमाल और इनपुट पाइपलाइन मेट्रिक पर नज़र रखें. होस्ट-साइड डेटा लोड करने और प्रीप्रोसेसिंग रूटीन को ऑप्टिमाइज़ करें. इसके लिए, सीओओ कन्वर्ज़न से जुड़ी सलाह देखें. डेटा प्रीफ़ेच करने की सुविधा को बेहतर बनाने के लिए, maximum_parallel_iterations फ़्लैग में बदलाव करें.
  • टीसी/एससी के बीच सिंक्रनाइज़ेशन ठीक से न होना (पाइपलाइनिंग की कमी):
    • समस्या: अगर TensorCore और SparseCore के बीच पाइपलाइनिंग की सुविधा बंद है या ठीक से काम नहीं कर रही है, तो हो सकता है कि एक यूनिट को दूसरी यूनिट के लिए इंतज़ार करना पड़े. इससे सिस्टम की परफ़ॉर्मेंस कम हो जाती है.
    • कम करना: पक्का करें कि पाइपलाइनिंग चालू हो. उदाहरण के लिए, tf_xla_disable_full_embedding_pipelining = false या इसके बराबर.
  • सीमा की वजह से होने वाली रुकावटें:
    • समस्या:
      • सीमाएं बहुत कम हैं: इससे बहुत ज़्यादा मिनी-बैचिंग ट्रिगर हो सकती है. मिनी-बैचिंग का मतलब है कि इनपुट बैच को कई छोटे-छोटे सब-बैच में बांटना, ताकि तय की गई सीमाओं को पूरा किया जा सके. इससे सटीकता बनी रहती है. हालांकि, हर मिनी-बैच में कुछ प्रोसेसिंग ओवरहेड होता है. इससे पूरे प्रोसेस की स्पीड कम हो सकती है. अगर allow_id_dropping को 'सही है' पर सेट किया जाता है, तो बहुत कम सीमाएं तय करने से आईडी ड्रॉप हो सकता है. इससे मॉडल की परफ़ॉर्मेंस पर असर पड़ता है.
      • सीमाएं बहुत ज़्यादा हैं, लेकिन अब भी तय सीमा के अंदर हैं: सीमाएं बहुत ज़्यादा होने पर, मिनी-बैचिंग को रोका जा सकता है. हालांकि, अगर डेटा की विशेषताएं कभी-कभार ही इन पीक वैल्यू के आस-पास पहुंचती हैं, तो इससे SPMEM पर बेवजह दबाव बढ़ सकता है. इनसे, ज़रूरत से ज़्यादा एचबीएम स्टैक का इस्तेमाल भी हो सकता है.
      • कंपाइलेशन में गड़बड़ियां: अगर कॉन्फ़िगर की गई सीमाओं के लिए, उपलब्ध फ़िज़िकल मेमोरी से ज़्यादा SPMEM या HBM स्टैक की ज़रूरत होती है, तो कंपाइलेशन पूरा नहीं होगा.
    • कम करना: पक्का करें कि सीमाएं सही तरीके से सेट की गई हों.
  • डेटा डिस्ट्रिब्यूशन स्क्यू:
    • समस्या: अगर कुछ SparseCore पार्टीशन को लगातार, अन्य पार्टीशन की तुलना में बहुत ज़्यादा आईडी मिलते हैं, तो इसका मतलब है कि आईडी का डिस्ट्रिब्यूशन सही नहीं है. ऐसे में, ज़्यादा आईडी वाले SparseCore, परफ़ॉर्मेंस में रुकावट पैदा करेंगे.
    • कम करना: मिनी-बैचिंग की प्रोसेस के दौरान आईडी शफ़ल करने से, स्टैक की गई टेबल के लिए इस समस्या को कम किया जा सकता है. खास तौर पर, "हॉट" यूज़र टेबल के लिए. आईडी डिस्ट्रिब्यूशन का ध्यान से विश्लेषण करें, ताकि हर टेबल के लिए सही और संतुलित सीमाएं सेट की जा सकें.
  • टेबल स्टैक करने से जुड़ी समस्याएं:
    • समस्या:
      • बहुत कम टेबल स्टैक की गई हैं: इससे आईसीआई की लेटेन्सी को असरदार तरीके से छिपाया नहीं जा सकता या प्रोसेसिंग के ओवरहेड को ठीक से कम नहीं किया जा सकता.
      • बहुत ज़्यादा टेबल स्टैक की गई हैं: इससे बहुत बड़ी लॉजिकल टेबल बन सकती हैं. इन्हें मैनेज करना मुश्किल हो सकता है या ये उपलब्ध संसाधन की सीमाओं से ज़्यादा हो सकती हैं.
    • कम करना:
      • यह पक्का करें कि स्टैक करने के लिए टेबल की संख्या सही हो. सामान्य दिशा-निर्देश के मुताबिक, स्टैक करने के लिए 5 से 100 टेबल "सबसे सही" होती हैं.
  • संख्याओं/क्वांटाइज़ेशन का सही तरीके से इस्तेमाल न करना:
    • समस्या: जब BF16 या पूर्णांकों को क्वांटाइज़ करने जैसे कम सटीक फ़ॉर्मैट का इस्तेमाल किया जा सकता है, तब FP32 का इस्तेमाल करने से परफ़ॉर्मेंस में रुकावट आ सकती है. साथ ही, इससे कंप्यूटेशन की प्रोसेस धीमी हो सकती है.
    • कम करना: कम सटीक विकल्पों को एक्सप्लोर करें. हालांकि, ध्यान रखें कि क्वांटाइज़ेशन में कुछ ओवरहेड होता है. साथ ही, मॉडल की सटीक जानकारी बनाए रखने के लिए, क्वांटाइज़ेशन पैरामीटर को ध्यान से ट्यून करने की ज़रूरत पड़ सकती है.
  • एचबीएम बैंडविड्थ सैचुरेशन:
    • समस्या: एचबीएम में बहुत ज़्यादा डेटा ट्रांसफ़र होने की वजह से, एचबीएम का उपलब्ध बैंडविड्थ खत्म हो सकता है. इसकी वजहें ये हो सकती हैं: फ़ीचर की चौड़ाई बहुत कम होने की वजह से पैडिंग का ओवरहेड ज़्यादा होना, मेमोरी ऐक्सेस करने के पैटर्न का सही न होना या लुकअप की संख्या बहुत ज़्यादा होना.
    • कम करना: टीपीयू की संख्या बढ़ाने से, एचबीएम बैंडविड्थ की समस्या को कम किया जा सकता है.

मेमोरी से जुड़ी आम समस्याएं:

  • SPMEM ओवरफ़्लो (कंपाइलेशन में गड़बड़ी):
    • समस्या: अगर max_ids_per_partition और max_unique_ids_per_partition को बहुत ज़्यादा पर सेट किया जाता है, तो हो सकता है कि XLA कंपाइलर, SPMEM को ज़रूरत के मुताबिक असाइन न कर पाए. इससे कंपाइलेशन से जुड़ी गड़बड़ियां हो सकती हैं. जैसे: "Fixed size allocations (...) do not fit in TileSpmem (...)". इसके अलावा, अगर (sample_count * feature_width) / kNumTiles (जहां kNumTiles, एससी के हिसाब से टाइल की संख्या है) टाइल SPMEM में ऑपरेंड इकट्ठा करने के लिए बहुत बड़ा है, तो "Gather operand too large..." जैसी गड़बड़ियां हो सकती हैं.
    • समस्या हल करना: बैच का साइज़ कम करें या प्रोसेसिंग के लिए इस्तेमाल किए जाने वाले चिप की संख्या बढ़ाएं.
  • एचबीएम स्टैक ओवरफ़्लो (रनटाइम या कंपाइलेशन):
    • समस्या: अगर feature_width, max_unique_nz_per_row, और logical_replica_count के कॉम्बिनेशन की वजह से, एचबीएम स्टैक मेमोरी की ज़रूरतें उपलब्ध एचबीएम से ज़्यादा हो जाती हैं, तो इससे रनटाइम या कंपाइलेशन के दौरान, आउट-ऑफ़-मेमोरी (ओओएम) गड़बड़ियां हो सकती हैं.
    • समस्या हल करना: टेबल की प्रोसेसिंग को क्रम से करने के लिए, xla_sc_num_serialized_tables_to_optimize_hbm फ़्लैग को ट्यून करें. इससे, एचबीएम स्टैक का इस्तेमाल कम हो जाएगा. हालांकि, इससे परफ़ॉर्मेंस पर असर पड़ सकता है.
  • एचबीएम हीप का खत्म होना:
    • समस्या: यह समस्या मुख्य रूप से, बहुत ज़्यादा डेंस लेयर वेट, मेमोरी में सेव किए गए कई कॉन्स्टेंट या इनपुट प्रीफ़ेचिंग (ज़्यादा maximum_parallel_iterations) की वजह से होती है.
    • कम करना: XProf Memory Viewer जैसे टूल का इस्तेमाल करके, हीप के इस्तेमाल पर नज़र रखें.
  • पैडिंग ओवरहेड:
    • समस्या: फ़ीचर डाइमेंशन में, एम्बेड की गई टेबल को 32B-लाइन में रखा जाता है. यह आठ फ़्लोट के बराबर होता है. इसलिए, कम चौड़ाई वाली सुविधाओं (उदाहरण के लिए, 1 फ़्लोट) के लिए, पैडिंग काफ़ी ज़्यादा होती है. उदाहरण के लिए, आवंटित बफ़र स्पेस का 7/8 हिस्सा पैडिंग होता है. इससे एचबीएम का इस्तेमाल नहीं हो पाता. टेबल के शब्दावली डाइमेंशन को भी सिस्टम में मौजूद SparseCore की संख्या के हिसाब से पैड किया जाता है. हालांकि, शब्दावली के साइज़ के हिसाब से बड़ी टेबल पर इसका असर न के बराबर होता है.

परफ़ॉर्मेंस और मेमोरी पर असर डालने वाले सामान्य फ़ैक्टर:

  • टपोलॉजी: उपलब्ध चिप की संख्या और उनके इंटरकनेक्शन का आर्किटेक्चर.
  • बैच का साइज़: इससे सीधे तौर पर हर SparseCore के लिए sample_count पर असर पड़ता है. इससे मेमोरी की खपत और कंप्यूट लोड पर असर पड़ता है.
  • डेटा फ़ॉर्मैटिंग: बेहतर परफ़ॉर्मेंस के लिए, डिवाइस पर डेटा का लेआउट सही होना ज़रूरी है.

11. SparseCore प्रोफ़ाइल का विश्लेषण करना

परफ़ॉर्मेंस प्रोफ़ाइल का विश्लेषण करना, बॉटलनेक की पहचान करने और अपने SparseCore वर्कलोड में ऑप्टिमाइज़ेशन के अवसरों का पता लगाने का एक अहम तरीका है.

  1. ट्रेस पाना:
    • प्रोफ़ाइलिंग टूल का इस्तेमाल करें. जैसे, XProf. इससे, मॉडल की ट्रेनिंग या अनुमान लगाने के दौरान, एक्ज़ीक्यूशन के बारे में पूरी जानकारी कैप्चर की जा सकती है. इस ट्रेस से, होस्ट, TensorCore, और SparseCore पर होने वाले ऑपरेशनों की टाइमलाइन मिलेगी.
  2. ट्रेस व्यूअर की जांच करें. उदाहरण के लिए, XProf या TensorBoard में:
    • होस्ट की गतिविधि: होस्ट की गतिविधि की जांच करें. क्या टीपीयू की गतिविधि में कोई बड़ा अंतर है? इस तरह के अंतर से पता चल सकता है कि होस्ट एक बॉटलनेक है और वह डेटा को तेज़ी से प्रोसेस नहीं कर पा रहा है. अपनी इनपुट पाइपलाइन की परफ़ॉर्मेंस का विश्लेषण करें.
    • TensorCore (टीसी) और SparseCore (एससी) की गतिविधि:
      • टीसी और एससी, दोनों के लिए एक्ज़ीक्यूशन टाइमलाइन देखें. क्या दोनों एक साथ काम कर रहे हैं, जिससे पाइपलाइनिंग के असरदार होने का पता चलता है? या क्या ऐसी लंबी अवधि होती है, जब एक यूनिट निष्क्रिय रहती है और दूसरी यूनिट का इंतज़ार करती है?
      • SC और TC, दोनों पर सबसे ज़्यादा समय लेने वाली कार्रवाइयों की पहचान करें.
      • विज़ुअल ट्रेस आउटपुट (इसमें अक्सर रंगीन ब्लॉक दिखते हैं. ये ब्लॉक, समय के साथ अलग-अलग कार्रवाइयों को दिखाते हैं, जैसे कि TPU:0 SparseCore 1 (pid 1005)) की मदद से, मुख्य कार्रवाइयों और निष्क्रियता की अवधि को विज़ुअली पहचाना जा सकता है.
    • स्टेप टाइम का विश्लेषण: पूरे स्टेप टाइम को देखें. साथ ही, यह समझें कि इसे होस्ट प्रोसेसिंग, एससी कंप्यूटेशन, और टीसी कंप्यूटेशन के बीच कैसे बांटा गया है.
  3. मेमोरी का विश्लेषण (XProf Memory Viewer):
    • हीप का इस्तेमाल: HBM हीप के इस्तेमाल की जांच करने के लिए, XProf के "Memory Viewer" टैब जैसे टूल इस्तेमाल करें. इससे यह पता लगाने में मदद मिल सकती है कि बड़े मॉडल के वज़न, कॉन्स्टेंट या इनपुट प्रीफ़ेचिंग की वजह से, ज़्यादा मात्रा में एचबीएम का इस्तेमाल हो रहा है या नहीं. --vmodule=best_fit_allocator=1 जैसे फ़्लैग चालू करने से, हीप मेमोरी के सबसे ज़्यादा इस्तेमाल के लॉग मिल सकते हैं.
    • स्टैक का इस्तेमाल (अप्रत्यक्ष): सीधे तौर पर एचबीएम स्टैक की प्रोफ़ाइलिंग करना मुश्किल हो सकता है. हालांकि, अगर आपको मेमोरी से जुड़ी गड़बड़ियां दिखती हैं और हीप का इस्तेमाल सही लगता है, तो एचबीएम स्टैक के खत्म होने की वजह से ऐसा हो सकता है. ऐसा अक्सर बहुत बड़ी सीमाओं या फ़ीचर की चौड़ाई की वजह से होता है. एचबीएम स्टैक के इस्तेमाल के लिए दिए गए फ़ॉर्मूले से, इसका अनुमान लगाया जा सकता है.
  4. खास पैटर्न ढूंढना:
    • मिनी-बैचिंग: अगर सीमाएं बार-बार पार की जा रही हैं, तो आपको ट्रेस में मिनी-बैचिंग के सबूत दिख सकते हैं. उदाहरण के लिए, ग्लोबल बैच साइज़ के लिए उम्मीद से ज़्यादा छोटी एससी कार्रवाइयां. इसका पता अक्सर लॉग से या कुछ कार्रवाइयों के इनवोकेशन की संख्या देखकर लगाया जा सकता है.
    • आईडी ड्रॉपिंग: अगर आईडी ड्रॉपिंग की सुविधा चालू है और ऐसा हो रहा है, तो सिस्टम लॉग से इसकी जानकारी मिल सकती है. इससे यह भी पता चलेगा कि कॉन्फ़िगर की गई सीमाएं, इनपुट डेटा के लिए बहुत ज़्यादा पाबंदियां लगाती हैं.
    • कंपाइलेशन में लगने वाला समय: अगर बार-बार रीकंपाइल किया जाता है, तो कंपाइलेशन में ज़्यादा समय लग सकता है. खास तौर पर, अगर फ़ीडबैक के आधार पर ऑप्टिमाइज़ेशन (एफ़डीओ) की सुविधा चालू है और सीमाएं बार-बार बदली जा रही हैं, तो ट्रेनिंग में लगने वाले कुल समय में काफ़ी बढ़ोतरी हो सकती है.
  5. फ़्लैग और कॉन्फ़िगरेशन से जोड़ें:
    • प्रोफ़ाइल में देखे गए व्यवहार को अपने SparseCore कॉन्फ़िगरेशन (सीमाओं वाली फ़ाइलों में सेटिंग, XLA फ़्लैग) से जोड़ें. उदाहरण के लिए, अगर xla_sc_num_serialized_tables_to_optimize_hbm को ज़्यादा वैल्यू पर सेट किया जाता है, तो आपको एससी की परफ़ॉर्मेंस धीमी होने की उम्मीद हो सकती है. हालांकि, एचबीएम स्टैक का इस्तेमाल कम होगा.
  6. बार-बार दोहराई जाने वाली प्रोसेस:
    • प्रोफ़ाइलिंग, अक्सर बार-बार इस्तेमाल होने वाली रिफ़ाइनमेंट प्रोसेस होती है. कोई खास बदलाव करें (सीमा में बदलाव करें, किसी सुविधा को चालू या बंद करें), नई प्रोफ़ाइल कैप्चर करें. इसके बाद, बदलाव का असर देखने के लिए, इसकी तुलना पिछली प्रोफ़ाइल से करें.

12. डीबग करने के लिए सामान्य फ़्लैग

SparseCore के एक्ज़ीक्यूशन से जुड़ी समस्याओं को डीबग करने के लिए, कई फ़्लैग चालू किए जा सकते हैं. यह ध्यान रखना ज़रूरी है कि इन जांचों को चालू करने से, अक्सर परफ़ॉर्मेंस पर असर पड़ता है. इसलिए, आम तौर पर इन्हें प्रोडक्शन रन के लिए बंद कर देना चाहिए.

  • आईडी की जांच (रेंज से बाहर):
    • फ़्लैग: xla_sparse_core_enable_id_bound_check = true
    • मकसद: यह कुकी, होस्ट सिस्टम पर जांच करने की सुविधा चालू करती है. इससे यह पता चलता है कि इनपुट डेटा में मौजूद कोई भी एम्बेडिंग आईडी, किसी एम्बेडिंग टेबल के लिए तय की गई मान्य शब्दावली की सीमा से बाहर तो नहीं है. इससे, गलत या खराब इनपुट डेटा से जुड़ी समस्याओं का पता लगाने में मदद मिलती है.
  • NaN checker:
    • फ़्लैग: xla_sc_detect_nan = true
    • मकसद: यह कुकी, SparseCore पर प्रोसेस किए गए फ़्लोटिंग-पॉइंट डेटा में NaN (संख्या नहीं है) वैल्यू का पता लगाने में मदद करती है. अगर कंपाइलर के अलग-अलग पास के इनपुट या आउटपुट में NaN का पता चलता है, तो यह फ़्लैग गड़बड़ी की वजह बनेगा. इस तरह की गड़बड़ियों से आम तौर पर यह जानकारी मिलती है कि NaN कहां मिला.
  • बाउंड्स चेकर (मेमोरी ऐक्सेस):
    • फ़्लैग: xla_sc_assert_level=bounds
    • मकसद: यह फ़्लैग, ASAN (AddressSanitizer) स्टाइल वाले टूल को चालू करता है. यह टूल, मेमोरी ऐक्सेस करने के निर्देशों (जैसे कि VMEM लोड/स्टोर और डीएमए ऑपरेशन) को फिर से लिखता है, ताकि उनमें डाइनैमिक जांच शामिल की जा सके. इन जांचों से यह पुष्टि होती है कि मेमोरी का ऐक्सेस, टारगेट मेमोरी क्षेत्र के तय किए गए दायरे में है या नहीं.
    • व्यवहार: अगर मेमोरी ऐक्सेस करने पर कोई रोक नहीं लगाई जाती है, तो टास्क पूरा नहीं हो पाएगा.
    • चेतावनी: ऐसा हो सकता है कि यह चेकर, गलत पॉज़िटिव नतीजे दे. उदाहरण के लिए, जटिल स्ट्राइड ऐक्सेस पैटर्न की वजह से, चेकर को पूरी तरह से समझ में नहीं आता. यह ट्रांसफ़ॉर्मेशन, बैकएंड कंपाइलेशन प्रोसेस के आखिरी चरण में लागू होता है.
  • बफ़र चेकर (मेमोरी करप्शन):
    • फ़्लैग:
      • 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
    • मकसद: इन फ़्लैग से यह पक्का करने में मदद मिलती है कि मेमोरी बफ़र को गलती से खराब न किया जाए या उन पर ऐसी कार्रवाइयां न की जाएं जो उनसे जुड़ी नहीं हैं. बफ़र सैनिटाइज़र, बफ़र के कॉन्टेंट की जांच करता है. इससे यह पुष्टि की जाती है कि उनमें अचानक कोई बदलाव नहीं हो रहा है.

13. क्वांटाइज़ेशन की सुविधा

SparseCore के SparseDenseMatmulOp को इस तरह से डिज़ाइन किया गया है कि यह 32-बिट फ़्लोटिंग-पॉइंट (FP32) और पूर्णांक, दोनों तरह के डेटा टाइप का इस्तेमाल करके एम्बेडिंग टेबल पर कार्रवाइयों को सपोर्ट कर सके. आम तौर पर, मॉडल ट्रेनिंग के दौरान एम्बेडिंग टेबल के लिए FP32 प्रेसिज़न का इस्तेमाल किया जाता है. हालांकि, ट्रेनिंग के बाद क्वांटाइज़ेशन (पीटीक्यू) लागू किया जा सकता है. पीटीक्यू, अनुमान के लिए कम सटीक डेटाटाइप (जैसे कि 8-बिट पूर्णांक) का इस्तेमाल करने की अनुमति देता है. इससे परफ़ॉर्मेंस बेहतर हो सकती है और मेमोरी का इस्तेमाल कम हो सकता है.

सिम्युलेटेड क्वांटाइज़ेशन:

SparseDenseMatmulOp को "सिम्युलेटेड क्वांटाइज़ेशन" करने के लिए कॉन्फ़िगर किया जा सकता है. इस ऑपरेशनल मोड में, एंबेड किए जा रहे वेक्टर को सबसे पहले कम सटीक वैल्यू में बदला जाता है. इसके बाद, उन्हें ज़्यादा सटीक वैल्यू (उदाहरण के लिए, FP32) में वापस बदला जाता है. ऐसा तब किया जाता है, जब उनका इस्तेमाल आगे की कैलकुलेशन में किया जाना हो. इस तकनीक की मदद से, मॉडल को क्वांटाइज़ेशन नॉइज़ के असर को ध्यान में रखते हुए ट्रेन किया जा सकता है. सिम्युलेटेड क्वांटाइज़ेशन के साथ ट्रेनिंग करने से, फ़ाइनल मॉडल की सटीकता को बेहतर बनाया जा सकता है. ऐसा तब होता है, जब अनुमान के लिए मॉडल को पूरी तरह से क्वांटाइज़ किया जाता है.

क्वांटाइज़ेशन के लिए, SparseDenseMatmulOp के कॉन्फ़िगरेशन एट्रिब्यूट:

  • quantization_config_num_buckets = 256
    • इस एट्रिब्यूट से, अलग-अलग बकेट या लेवल की संख्या के बारे में पता चलता है. इसमें यह जानकारी होती है कि 32-बिट फ़्लोटिंग-पॉइंट नंबर को कितने हिस्सों में बांटा जाएगा. उदाहरण के लिए, 8-बिट पूर्णांकों में बदलने के लिए, आम तौर पर 2^8 =256 बकेट तय किए जाते हैं.
  • quantization_config_low = -X.X
    • यह एट्रिब्यूट, क्वॉन्टाइज़ेशन रेंज में फ़्लोटिंग-पॉइंट की सबसे छोटी वैल्यू तय करता है. क्वांटाइज़ेशन के दौरान, इस तय की गई सबसे कम वैल्यू से कम की किसी भी इनपुट वैल्यू को इस सबसे कम वैल्यू पर क्लिप कर दिया जाएगा.
  • quantization_config_high = Y.Y
    • यह एट्रिब्यूट, क्वॉन्टाइज़ेशन रेंज में फ़्लोटिंग-पॉइंट की ज़्यादा से ज़्यादा वैल्यू तय करता है. क्वांटाइज़ेशन के दौरान, इस तय की गई ज़्यादा से ज़्यादा वैल्यू से ज़्यादा की किसी भी इनपुट वैल्यू को इस ज़्यादा से ज़्यादा वैल्यू पर क्लिप कर दिया जाएगा.

नंबर और पाइपलाइनिंग इंटरैक्शन:

मॉडल का संख्यात्मक व्यवहार, इस बात पर निर्भर करता है कि TensorCore और SparseCore के बीच पाइपलाइनिंग चालू है या नहीं. अगर पाइपलाइनिंग चालू है, तो SparseCore से प्रोसेस किए गए ग्रेडिएंट "पुराने" हो सकते हैं (पिछले इटरेशन से). यह क्वानटाइज़ेशन प्रोसेस के साथ इंटरैक्ट कर सकता है. इससे मॉडल ट्रेनिंग के डाइनैमिक या फ़ाइनल सटीकता पर असर पड़ सकता है.

14. आने वाली सुविधाएं और हाल ही में किए गए सुधार

SparseCore के नेटवर्क को लगातार डेवलप और बेहतर बनाया जा रहा है.

रोडमैप:

  • सैंपल-डाइमेंशन मिनी-बैचिंग:
    • इसे शब्दावली-डाइमेंशन के हिसाब से मिनी-बैचिंग की मौजूदा सुविधाओं के साथ काम करने वाली सुविधा के तौर पर डिज़ाइन किया गया है.
    • इससे, सैंपल डाइमेंशन के साथ-साथ एंबेडिंग इनपुट को और भी ज़्यादा हिस्सों में बांटा जा सकेगा. इसके लिए, डिवाइस पर लूप की सुविधा शुरू की जाएगी. इससे एक बार में, सैंपल के सबसेट से लुकअप को फ़िल्टर और प्रोसेस किया जा सकेगा. इस तरह की सुविधा, हर सैंपल के आईडी की बहुत बड़ी संख्या को मैनेज करने या प्रोसेसिंग यूनिट के बीच लोड बैलेंसिंग को बेहतर बनाने के लिए फ़ायदेमंद हो सकती है.
  • हर लाइन में आठ से कम पूर्णांक (छोटी सुविधा की चौड़ाई) वाले डेटा को एम्बेड करने की बेहतर सुविधा:
    • मौजूदा डिज़ाइन में, एम्बेड की गई सुविधाओं की चौड़ाई के लिए अक्सर काफ़ी पैडिंग का इस्तेमाल किया जाता है. यह चौड़ाई आठ फ़्लोट (जो 32 बाइट के बराबर है) से कम होती है. इस पैडिंग की वजह से, एचबीएम का इस्तेमाल नहीं हो पाता. साथ ही, कंप्यूट संसाधनों का इस्तेमाल कम हो सकता है. आने वाले समय में, इस समस्या को ठीक करने के लिए सुधार किए जाएंगे. इससे कम फ़ीचर डाइमेंशन वाली टेबल के लिए, इस समस्या को कम किया जा सकेगा.

हाल ही में किए गए सुधार:

  • एचबीएम में गैदर ऑपरेंड की स्टेजिंग:
    • इस ऑप्टिमाइज़ेशन से, शेयर की गई स्क्रैचपैड मेमोरी (एसपीएमईएम) पर पड़ने वाले दबाव को कम करने में मदद मिलती है. ऐसा इसलिए होता है, क्योंकि यह कुछ इकट्ठा करने की कार्रवाई के इनपुट या आउटपुट को बड़े एचबीएम में स्टेज करने की अनुमति देता है.
  • स्टैक मेमोरी के इस्तेमाल में कमी:
    • स्पार्सकोर ऑपरेशंस के दौरान, एचबीएम स्टैक मेमोरी की खपत को कम करने के लिए सुधार किए गए हैं. इससे, परफ़ॉर्मेंस या थ्रूपुट पर कोई बुरा असर नहीं पड़ता.

इन सुधारों का मकसद, SparseCore की परफ़ॉर्मेंस, मेमोरी की क्षमता, और ऑपरेशनल फ़्लेक्सिबिलिटी को बेहतर बनाना है, ताकि स्पार्स वर्कलोड की ज़्यादा से ज़्यादा रेंज को हैंडल किया जा सके.