त्वरक बैकएंड

Tensor गणना का वर्णन करना बहुत सरल है, लेकिन वह गणना कब और कैसे की जाती है यह इस बात पर निर्भर करेगा कि Tensor के लिए किस बैकएंड का उपयोग किया जाता है और होस्ट सीपीयू पर परिणामों की आवश्यकता कब होती है।

पर्दे के पीछे, Tensor s पर संचालन GPU या TPUs जैसे त्वरक को भेजा जाता है, या कोई त्वरक उपलब्ध नहीं होने पर CPU पर चलाया जाता है। यह आपके लिए स्वचालित रूप से होता है, और उच्च-स्तरीय इंटरफ़ेस का उपयोग करके जटिल समानांतर गणना करना आसान बनाता है। हालाँकि, यह समझना उपयोगी हो सकता है कि यह प्रेषण कैसे होता है और इसे इष्टतम प्रदर्शन के लिए अनुकूलित करने में सक्षम होना चाहिए।

TensorFlow के लिए स्विफ्ट में त्वरित गणना करने के लिए दो बैकएंड हैं: TensorFlow उत्सुक मोड और X10। डिफ़ॉल्ट बैकएंड TensorFlow उत्सुक मोड है, लेकिन इसे ओवरराइड किया जा सकता है। एक इंटरैक्टिव ट्यूटोरियल उपलब्ध है जो आपको इन विभिन्न बैकएंड के उपयोग के बारे में बताता है।

TensorFlow उत्सुक मोड

TensorFlow उत्सुक मोड बैकएंड प्रत्येक Tensor ऑपरेशन को सामने आने पर GPU या CPU पर भेजने के लिए TensorFlow C API का लाभ उठाता है। फिर उस ऑपरेशन का परिणाम पुनर्प्राप्त किया जाता है और अगले ऑपरेशन में भेज दिया जाता है।

यह ऑपरेशन-दर-ऑपरेशन प्रेषण समझने में सरल है और आपके कोड के भीतर किसी स्पष्ट कॉन्फ़िगरेशन की आवश्यकता नहीं है। हालाँकि, कई मामलों में कई छोटे ऑपरेशनों को भेजने से होने वाले ओवरहेड के कारण ऑपरेशन फ़्यूज़न और अनुकूलन की कमी के कारण इष्टतम प्रदर्शन नहीं होता है, जो ऑपरेशन के ग्राफ़ मौजूद होने पर हो सकता है। अंत में, TensorFlow उत्सुक मोड TPU के साथ असंगत है, और इसका उपयोग केवल CPU और GPU के साथ किया जा सकता है।

X10 (XLA-आधारित ट्रेसिंग)

X10, TensorFlow बैकएंड के लिए स्विफ्ट का नाम है जो कई मामलों में ऑपरेशन-दर-ऑपरेशन डिस्पैच पर प्रदर्शन में काफी सुधार करने के लिए आलसी टेंसर ट्रेसिंग और XLA ऑप्टिमाइज़िंग कंपाइलर का उपयोग करता है। इसके अतिरिक्त, यह टीपीयू के लिए अनुकूलता जोड़ता है, विशेष रूप से मशीन लर्निंग मॉडल के भीतर पाए जाने वाले गणना के प्रकार के लिए अनुकूलित त्वरक।

Tensor गणना के लिए X10 का उपयोग डिफ़ॉल्ट नहीं है, इसलिए आपको इस बैकएंड को चुनने की आवश्यकता है। यह निर्दिष्ट करके किया जाता है कि एक Tensor को XLA डिवाइस पर रखा गया है:

let tensor1 = Tensor<Float>([0.0, 1.0, 2.0], on: Device.defaultXLA)
let tensor2 = Tensor<Float>([1.5, 2.5, 3.5], on: Device.defaultXLA)

उस बिंदु के बाद, गणना का वर्णन करना TensorFlow उत्सुक मोड के समान ही है:

let tensor3 = tensor1 + tensor2

Tensor बनाते समय अधिक विवरण प्रदान किया जा सकता है, जैसे कि किस प्रकार के त्वरक का उपयोग करना है और यहां तक ​​कि कौन सा, यदि कई उपलब्ध हैं तो। उदाहरण के लिए, निम्नलिखित का उपयोग करके दूसरे टीपीयू डिवाइस पर एक Tensor बनाया जा सकता है (यह मानते हुए कि यह उस होस्ट को दिखाई देता है जिस पर प्रोग्राम चल रहा है):

let tpuTensor = Tensor<Float>([0.0, 1.0, 2.0], on: Device(kind: .TPU, ordinal: 1, backend: .XLA))

डिवाइसों के बीच Tensor s का कोई अंतर्निहित संचलन नहीं किया जाता है, इसलिए यदि विभिन्न डिवाइसों पर दो Tensor s को एक साथ एक ऑपरेशन में उपयोग किया जाता है, तो एक रनटाइम त्रुटि उत्पन्न होगी। किसी Tensor की सामग्री को किसी नए डिवाइस पर मैन्युअल रूप से कॉपी करने के लिए, आप Tensor(copying:to:) इनिशियलाइज़र का उपयोग कर सकते हैं। कुछ बड़े पैमाने की संरचनाएं जिनमें मॉडल और ऑप्टिमाइज़र जैसे Tensor होते हैं, उनके सभी आंतरिक Tensor को एक चरण में एक नए डिवाइस में ले जाने के लिए सहायक कार्य होते हैं।

TensorFlow उत्सुक मोड के विपरीत, X10 बैकएंड का उपयोग करने वाले संचालन को व्यक्तिगत रूप से प्रेषित नहीं किया जाता है क्योंकि उनका सामना किया जाता है। इसके बजाय, त्वरक को प्रेषण केवल या तो गणना किए गए मानों को होस्ट पर वापस पढ़ने या एक स्पष्ट अवरोध लगाने से शुरू होता है। यह जिस तरह से काम करता है वह यह है कि रनटाइम होस्ट पर पढ़े जा रहे मान (या मैन्युअल बैरियर से पहले अंतिम गणना) से शुरू होता है और उस मान के परिणामस्वरूप गणना के ग्राफ का पता लगाता है।

इस ट्रेस किए गए ग्राफ़ को फिर XLA HLO मध्यवर्ती प्रतिनिधित्व में परिवर्तित किया जाता है और त्वरक पर निष्पादन के लिए अनुकूलित और संकलित करने के लिए XLA कंपाइलर को पास किया जाता है। वहां से, संपूर्ण गणना त्वरक को भेजी जाती है और अंतिम परिणाम प्राप्त किया जाता है।

गणना एक समय लेने वाली प्रक्रिया है, इसलिए X10 का उपयोग बड़े पैमाने पर समानांतर गणनाओं के साथ किया जाता है जो एक ग्राफ के माध्यम से व्यक्त की जाती हैं और जिन्हें कई बार किया जाता है। हैश मान और कैशिंग का उपयोग किया जाता है ताकि प्रत्येक अद्वितीय कॉन्फ़िगरेशन के लिए समान ग्राफ़ केवल एक बार संकलित किए जाएं।

मशीन लर्निंग मॉडल के लिए, प्रशिक्षण प्रक्रिया में अक्सर एक लूप शामिल होता है जहां मॉडल को बार-बार गणनाओं की एक ही श्रृंखला के अधीन किया जाता है। आप चाहेंगे कि इनमें से प्रत्येक पास को उसी ट्रेस की पुनरावृत्ति के रूप में देखा जाए, न कि उसके अंदर दोहराई गई इकाइयों वाले एक लंबे ग्राफ के रूप में। यह आपके कोड के उन स्थानों पर LazyTensorBarrier() फ़ंक्शन में कॉल के मैन्युअल सम्मिलन द्वारा सक्षम किया गया है जहां आप ट्रेस को समाप्त करना चाहते हैं।

X10 में मिश्रित-परिशुद्धता समर्थन

X10 के माध्यम से मिश्रित परिशुद्धता के साथ प्रशिक्षण समर्थित है और इसे नियंत्रित करने के लिए निम्न-स्तरीय और उच्च-स्तरीय एपीआई दोनों प्रदान किए जाते हैं। निम्न-स्तरीय एपीआई दो परिकलित गुण प्रदान करता है: toReducedPrecision और toFullPrecision जो परिशुद्धता को क्वेरी करने के लिए isReducedPrecision के साथ-साथ पूर्ण और कम परिशुद्धता के बीच परिवर्तित होते हैं। Tensor s के अलावा, इस API का उपयोग करके मॉडल और ऑप्टिमाइज़र को पूर्ण और कम परिशुद्धता के बीच परिवर्तित किया जा सकता है।

ध्यान दें कि कम परिशुद्धता में रूपांतरण Tensor के तार्किक प्रकार को नहीं बदलता है। यदि t एक Tensor<Float> है, तो t.toReducedPrecision भी कम परिशुद्धता वाले अंतर्निहित प्रतिनिधित्व के साथ एक Tensor<Float> है।

उपकरणों की तरह, विभिन्न परिशुद्धता वाले टेंसरों के बीच संचालन की अनुमति नहीं है। यह 32-बिट फ़्लोट में मौन और अवांछित प्रचार से बचता है, जिसे उपयोगकर्ता द्वारा पता लगाना कठिन होगा।