5 पॉइंट द्वारा GN⁺ 2023-10-22 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • GPU की architecture कम single-instruction latency के बजाय बड़े पैमाने की parallel throughput को प्राथमिकता देती है, इसलिए deep learning, graphics और numerical computation जैसे कामों में मजबूत है, जहाँ बड़ी मात्रा में एक ही तरह के operations किए जाते हैं
  • CPU pipelining, out-of-order execution, speculative execution और multilevel cache से sequential execution latency घटाता है, जबकि GPU कई ALU और threads के जरिए latency छिपाकर throughput बढ़ाता है
  • 32-bit precision के आधार पर Nvidia Ampere A100 19.5 TFLOPS देता है, जबकि 2021 का Intel 24-core processor 0.66 TFLOPS पर है; numerical-computation throughput का अंतर लगातार बढ़ रहा है
  • CUDA kernel में CPU का host code execution की तैयारी संभालता है और GPU का device code grid·block·thread structure में चलता है; threads को 32 के groups, यानी warp, में बाँधकर SIMT तरीके से process किया जाता है
  • असली performance इस बात पर बहुत निर्भर करती है कि SM के registers, shared memory, block slots और thread slots को कैसे बाँटा जाता है; occupancy कम हो तो latency छिपाना मुश्किल होता है और peak throughput भी नहीं मिल पाती

CPU और GPU के design goals में फर्क

  • CPU को मुख्य रूप से sequential instruction execution को तेज़ी से process करने के लिए design किया जाता है
    • instruction execution latency घटाने के लिए instruction pipelining, out-of-order execution, speculative execution, multilevel cache जैसी सुविधाओं का उपयोग करता है
    • दो numbers जोड़ने वाला single operation या short operation flow CPU, GPU की तुलना में कम latency से process कर सकता है
  • GPU को large-scale parallelism और high throughput को केंद्र में रखकर design किया जाता है
    • video games, graphics, numerical computation, deep learning जैसे काम, जहाँ बहुत सारे linear algebra·numerical operations तेज़ी से करने होते हैं, इस architecture के लिए अच्छी तरह फिट होते हैं
    • लाखों·अरबों समान तरह के operations में GPU बड़े पैमाने की parallelism से CPU की तुलना में कहीं तेज़ process कर सकता है
  • numerical computation performance को प्रति सेकंड floating-point operations की संख्या, यानी FLOPS, से मापा जाता है
    • Nvidia Ampere A100 32-bit precision पर 19.5 TFLOPS throughput देता है
    • 2021 के आधार पर Intel 24-core processor 32-bit precision पर 0.66 TFLOPS स्तर का है
    • GPU और CPU के throughput का अंतर हर साल बढ़ रहा है

GPU latency को कैसे छिपाता है

  • GPU, individual instruction latency ज्यादा होने पर भी कई threads और compute resources का उपयोग करके latency tolerance हासिल करता है
  • जब कोई thread instruction result का इंतज़ार कर रहा होता है, GPU ऐसे दूसरे threads चलाता है जिन्हें इंतज़ार नहीं करना पड़ता
  • इस scheduling की वजह से compute units जितना संभव हो लगातार काम करते रहते हैं और high throughput बनाए रख सकते हैं

GPU compute architecture

  • GPU कई streaming multiprocessor (SM) के array से बना होता है
  • हर SM में कई streaming processor, core और thread शामिल होते हैं
    • Nvidia H100 में 132 SM हैं, और हर SM में 64 cores हैं, यानी कुल 8,448 cores
  • हर SM में सीमित on-chip memory होती है जिसे सभी cores share करते हैं
    • इस memory को shared memory या scratchpad कहा जाता है
  • SM के control unit resources भी cores मिलकर उपयोग करते हैं
  • हर SM में thread execution के लिए hardware-based thread scheduler होता है
  • workload के अनुसार tensor core, ray tracing unit जैसे special-function units या accelerated compute units भी शामिल हो सकते हैं

GPU memory hierarchy

  • Registers

    • हर SM में बड़ी संख्या में registers होते हैं
    • Nvidia A100 और H100 में प्रति SM 65,536 registers होते हैं
    • registers को cores share करते हैं, और thread requirements के अनुसार dynamically allocate किया जाता है
    • execution के दौरान किसी specific thread को allocate किए गए registers उस thread के exclusive होते हैं, इसलिए दूसरे threads उन्हें read या write नहीं कर सकते
  • constant cache

    • SM पर चलने वाला code जिन constant data का उपयोग करता है, उन्हें cache करता है
    • programmer को code में object को स्पष्ट रूप से constant घोषित करना होता है, तभी GPU उसे constant cache में रख सकता है
  • shared memory

    • हर SM में मौजूद छोटी, तेज़, low-latency on-chip programmable SRAM है
    • इसे उसी SM पर चलने वाले thread blocks share करते हैं
    • जब कई threads data के एक ही टुकड़े का उपयोग करते हैं, तो सिर्फ एक thread global memory से पढ़कर बाकी threads के साथ share करे तो duplicate loads घट सकते हैं
    • thread block के अंदर threads के बीच synchronization mechanism के रूप में भी इसका उपयोग होता है
  • L1 cache और L2 cache

    • हर SM में L1 cache होता है, जो L2 cache से अक्सर access किए जाने वाले data को cache करता है
    • L2 cache सभी SMs द्वारा shared होता है, और global memory से अक्सर access किए जाने वाले data को cache करके latency घटाता है
    • L1 और L2 cache SM के लिए transparent तरीके से काम करते हैं, इसलिए SM के नज़रिए से ऐसा लगता है जैसे data global memory से मिल रहा हो
  • global memory

    • GPU में off-chip global memory होती है, जो large-capacity, high-bandwidth DRAM होती है
    • Nvidia H100 में 80GB HBM और 3000GB/s bandwidth है
    • global memory SM से दूर होती है, इसलिए latency ज्यादा होती है, लेकिन on-chip memory hierarchy और कई compute units इस latency को छिपाने में मदद करते हैं

CUDA kernel और thread structure

  • CUDA, Nvidia GPU के लिए programs लिखने का programming interface है
  • GPU पर चलने वाली computation को C/C++ function जैसे रूप वाले kernel के रूप में व्यक्त किया जाता है
    • उदाहरण एक vector-addition kernel है, जो दो vectors को input के रूप में लेकर element-wise जोड़ता है और result को तीसरे vector में लिखता है
  • kernel execution के समय कई threads शुरू किए जाते हैं, और इस पूरे समूह को grid कहा जाता है
    • grid एक या अधिक thread blocks से बना होता है
    • हर thread block एक या अधिक threads से बना होता है
  • blocks और threads की संख्या data size और desired parallelism के अनुसार बदलती है
    • 256-dimensional vector addition में 256 threads वाला एक block बनाकर हर thread से vector का एक element process कराया जा सकता है
    • बड़े problems में GPU के available threads कम पड़ सकते हैं, इसलिए हर thread से कई data points process कराए जा सकते हैं
  • CUDA implementation दो हिस्सों में बँटा होता है
    • host code CPU पर चलता है और data load, GPU memory allocation, configured thread grid के साथ kernel execution के लिए जिम्मेदार होता है
    • device code GPU पर चलता है और actual kernel function define करता है

GPU पर kernel चलने के चरण

  • host से device में data copy करना

    • kernel execution से पहले जरूरी data को CPU memory से GPU global memory में copy करना होता है
    • modern GPU hardware में unified virtual memory का उपयोग करके host memory से सीधे read भी किया जा सकता है
  • thread blocks को SM पर schedule करना

    • GPU memory में जरूरी data तैयार होने के बाद thread blocks को SM पर assign किया जाता है
    • एक block के सभी threads उसी SM पर एक साथ process होते हैं
    • GPU को execution से पहले उन threads के लिए जरूरी SM resources secure करने होते हैं
    • व्यवहार में कई thread blocks एक ही SM पर simultaneously assign किए जा सकते हैं
    • SM की संख्या limited होती है और बड़े kernel में blocks की संख्या बहुत ज्यादा हो सकती है, इसलिए सभी blocks तुरंत execute नहीं होते
    • GPU waiting blocks की list बनाए रखता है, और जब कोई block खत्म होता है तो waiting block में से एक को execution के लिए assign करता है
  • SIMT और warp

    • SM पर assign किए गए threads को फिर 32 के units में group किया जाता है, और इस group को warp कहा जाता है
    • current-generation Nvidia GPU में warp size 32 है, लेकिन future hardware में यह बदल सकता है
    • SM warp के सभी threads के लिए वही instruction fetch और issue करता है
    • threads वही instruction simultaneously execute करते हैं, लेकिन data के अलग-अलग हिस्सों को process करते हैं
    • इस model को single instruction multiple threads(SIMT) कहा जाता है, और यह CPU की SIMD instructions जैसा है
    • Volta के बाद के modern GPUs में independent thread scheduling भी है, जो warp से स्वतंत्र रूप से threads के बीच full concurrency allow करता है
  • warp scheduling और latency tolerance

    • SM के अंदर सभी processing blocks warp process कर रहे हों, फिर भी किसी खास क्षण पर वास्तव में instruction execute करने वाले warps कुछ ही होते हैं
    • वजह यह है कि SM के execution units की संख्या limited होती है
    • यदि कोई warp लंबे समय लेने वाले instruction result का इंतज़ार करता है, तो SM उस warp को waiting state में रखता है और ऐसे दूसरे warp को चलाता है जिसे इंतज़ार नहीं करना पड़ता
    • हर warp के हर thread के पास registers का अपना set होता है, इसलिए warps के बीच switching में अलग overhead नहीं होता
    • CPU में process context switching महंगा होता है, क्योंकि registers को main memory में save करना और दूसरे process की state restore करनी पड़ती है
  • result data को device से host में copy करना

    • kernel के सभी threads का execution खत्म होने पर result को वापस host memory में copy किया जाता है

resource partitioning और occupancy

  • GPU resource utilization को occupancy नामक metric से मापा जाता है
    • occupancy, SM पर assigned warps की संख्या को उस SM द्वारा support किए जा सकने वाले maximum warps से divide करने का ratio है
    • maximum throughput के लिए 100% occupancy desirable है, लेकिन कई constraints के कारण यह हमेशा संभव नहीं होता
  • SM में registers, shared memory, thread block slots, thread slots जैसे execution resources fixed होते हैं
    • ये resources thread requirements और GPU limits के अनुसार dynamically divide होते हैं
  • Nvidia H100 का उदाहरण
    • हर SM 32 blocks, 64 warps, यानी 2048 threads process कर सकता है
    • प्रति block maximum 1024 threads support करता है
    • यदि block size 1024 threads रखकर run किया जाए, तो 2048 thread slots 2 blocks में divide होते हैं
  • dynamic partitioning fixed partitioning की तुलना में compute resources का अधिक efficiently उपयोग कर सकता है
    • fixed partitioning में हर thread block को fixed amount of execution resources मिलते हैं
    • कुछ cases में threads को जरूरत से ज्यादा resources assign हो सकते हैं, जिससे resource waste और throughput drop हो सकता है
  • occupancy घटाने वाले उदाहरण
    • यदि block size 32 threads रखा जाए और कुल 2048 threads चाहिए हों, तो 64 blocks बनते हैं
    • लेकिन हर SM एक समय में केवल 32 blocks process कर सकता है, इसलिए असल में केवल 1024 threads चलते हैं और occupancy 50% होती है
    • जब प्रति SM registers 65,536 हों, तो 2048 threads simultaneously चलाने के लिए हर thread maximum 32 registers ही use कर सकता है
    • यदि kernel को प्रति thread 64 registers चाहिए हों, तो प्रति SM केवल 1024 threads चल सकते हैं, इसलिए occupancy फिर 50% होती है
  • कम occupancy latency को पर्याप्त रूप से छिपाने से रोक सकती है, और hardware की peak throughput तक पहुँचने के लिए जरूरी compute throughput भी घटा सकती है
  • efficient GPU kernel लिखने के लिए high occupancy बनाए रखते हुए latency घटाने के लिए resources को सावधानी से allocate करना होता है
    • बहुत ज्यादा registers का उपयोग code को तेज़ बना सकता है, लेकिन occupancy कम कर सकता है, इसलिए optimization balance महत्वपूर्ण है

आगे देखने लायक resources

1 टिप्पणियां

 
GN⁺ 2023-10-22
Hacker News की राय
  • किसी ने इस लेख के बारे में शिकायत वाला ईमेल भेजा था: https://twitter.com/abhi9u/status/1715753871564476597
    यह HN नियमों का उल्लंघन है। वास्तव में यह इतना महत्वपूर्ण एकमात्र बिंदु है कि यह साइट guidelines और FAQ दोनों में शामिल है, और HN उपयोगकर्ता इस मामले पर बहुत संवेदनशील हैं
    Q: क्या मैं अपने लेख के लिए upvote माँग सकता हूँ?
    A: नहीं। उपयोगकर्ताओं को वोट इसलिए देना चाहिए कि उन्हें कुछ बौद्धिक रूप से रोचक लगे, न कि इसलिए कि किसी ने उसे promote करने को कहा हो। इस नियम का उल्लंघन करने पर पोस्ट, अकाउंट, या साइट पर penalty लग सकती है या block किया जा सकता है, इसलिए ऐसा नहीं करना चाहिए
    https://news.ycombinator.com/newsfaq.html
    upvote, comment, या submit करने के लिए न कहें। उपयोगकर्ताओं को promotional उद्देश्य से नहीं, बल्कि तब वोट और comment करना चाहिए जब उन्हें खुद अपने सामने आई कोई चीज़ व्यक्तिगत रूप से रोचक लगे
    https://news.ycombinator.com/newsguidelines.html

    • मुझे यह नियम पता नहीं था, और जिसने पोस्ट किया वह भी कोई परिचित नहीं है
      अब पता चल गया है, इसलिए दोबारा ऐसा नहीं करूँगा
  • “host से device में data copy” वाले हिस्से में asynchronous copy का ज़िक्र नहीं देखकर हैरानी हुई। GPU का पूरा उपयोग करने के लिए host और GPU के बीच data copy होते समय GPU idle नहीं रहना चाहिए
    कई framework asynchronous job submission के साथ चल सकने वाला asynchronous copy scheduling mechanism देते हैं। लेख खुद GPU परिचय के काफ़ी करीब है, लेकिन असली GPU programming में महँगे GPU से आख़िरी बूंद तक performance निकालने के लिए इसके आगे तरह-तरह की tricks और techniques होती हैं। आजकल ज़्यादातर optimization की तरह इसमें भी hidden cliffs और non-linearity बहुत हैं, इसलिए profiling tools बहुत मददगार होते हैं

    • शायद आप 64-bit floating point(double) इस्तेमाल करेंगे, और उस स्थिति में हर GPU बहुत मददगार नहीं होगा। खासकर किसी शक्तिशाली CPU की तुलना में तो और भी कम
      लेकिन अगर FP64 units अधिक वाले GPU का इस्तेमाल करें तो काफ़ी तेज़ी मिल सकती है। आम तौर पर ऐसे GPU gaming GPU नहीं होते, लेकिन अगर आपके पास बस 4060 ही है, तब भी उसका FP64 performance लगभग 300 GFLOPS है, जो CPU से अधिक हो सकता है। आधुनिक CPU भी इस क्षेत्र में काफ़ी शक्तिशाली हैं, क्योंकि वे प्रति core प्रति clock कई FP64 operations issue कर सकते हैं
  • “ज़्यादातर programmer CPU को गहराई से समझते हैं” वाला शुरुआती वाक्य इतना साफ़ तौर पर तथ्यात्मक नहीं लगा कि लेख अच्छा हो सकता है, फिर भी बाकी बातों को गंभीरता से लेना मुश्किल हो जाता है

    • इसे ऐसे बदलने के बारे में क्या ख़याल है: “काफ़ी संख्या में computer scientists, computer engineers, electrical engineers, और hobbyist developers …”
      मैंने कॉलेज में शौकिया तौर पर philosophy की class ली थी, और वहाँ मैंने सीखा कि किसी वाक्य को तुरंत खारिज करने के बजाय उसे बेहतर रूप में पढ़ना चाहिए। अब मेरा दिमाग अपने-आप अत्यधिक generalization या साफ़ झूठ को भी किसी तर्कसंगत, लगभग-सही कथन में बदल देता है। फिर तर्क आगे बढ़ने पर उन विचारों को पुनर्गठित कर सकता हूँ और पूरे लेख को तर्कसंगत रूप से सुसंगत मानकर परख सकता हूँ
      इसकी वजह से, खराब लिखे लेख पढ़ने पर भी रुचि वाले विषय के बारे में नए सही-गलत premises और claims बच जाते हैं, और उसी हद तक मेरी मानसिक दुनिया फैलती है
    • यह ज़्यादातर programmer पर तो निश्चित ही लागू नहीं होता, लेकिन संभव है लेखक का मतलब CS-trained engineers से रहा हो। औपचारिक computer science course करने पर CPU की काफ़ी गहरी समझ बन जाती है, जबकि GPU को अक्सर बहुत सतही तौर पर पढ़ाया जाता है
    • समझ नहीं आता कि इंटरनेट पर हर लेख के साथ “मैं X पर पढ़ना बंद कर दिया” जैसी comment क्यों ज़रूर जुड़ जाती है। ऐसी बात कुछ भी नहीं जोड़ती
    • इस बहस का आधे से ज़्यादा हिस्सा शायद इस पर निर्भर करता है कि गहराई से समझते हैं को कैसे define किया जाए
      मैंने यूनिवर्सिटी में CPU architecture के बुनियादी तथ्य सीखे, समग्र परिदृश्य की बहुत शुरुआती समझ है, और कभी-कभी उस सीमित ज्ञान के अपडेट भी देखता हूँ, लेकिन मैं उसे “गहरी समझ” नहीं कहूँगा। शायद “CPU कैसे काम करता है, कैसे design होता है, और कैसे इस्तेमाल होता है, इसकी बुनियादी समझ” कहना ज़्यादा सही होगा
      अगर कोई assembly में दक्ष है तो शायद कहा जा सकता है कि वह low-level पर CPU का इस्तेमाल “गहराई से समझता” है, लेकिन तब भी यह कुछ बढ़ा-चढ़ा सा लगता है। और यह CPU/GPU design expert होने से भी अलग बात है
      इसलिए मैं सहमत हूँ। फिर भी लेख दिलचस्प है, खासकर diagrams अच्छे हैं
    • मैंने यह दोनों जगह सीखा था, degree program में भी और Structure and Interpretation of Computer Programs class में भी, और low-level computing में रुचि रखने वालों को मैं वह class recommend करूँगा
  • “चल रहे thread को assign किए गए registers उसी thread के लिए विशेष होते हैं, इसलिए दूसरे thread उन्हें पढ़ या लिख नहीं सकते” — इस बात के कुछ अपवाद हैं
    HLSL के wave intrinsics और CUDA में मिलते-जुलते features मौजूदा wavefront के भीतर दूसरे threads के registers पढ़ सकते हैं। साथ ही memory architecture वाले paragraph में यह भी जोड़ा जा सकता है कि cache एक ही dispatch/grid के threads के बीच coherence की गारंटी नहीं देता, लेकिन chip-व्यापी global विशेष function blocks global memory atomic operations को implement करते हैं

  • SIMD programming वाकई बहुत खुरदुरी चीज़ है
    स्क्रीन के हर pixel पर computation चलाना है? कोई दिक्कत नहीं
    branch condition डालनी है? बस, दर्द शुरू

    • eval डालना है? सब कुछ रुक जाता है
    • निष्पक्ष रूप से कहें तो इसमें तुक है। चतुर निर्णय लेना, साधारण computation को बहुत सारे workers तक scale करने की तुलना में “ज़्यादा कठिन” काम है
  • इसे अब भी GPU ही क्यों कहते हैं? PPU(Parallel Processing Unit) ज़्यादा अच्छा नाम लगता है

    • क्योंकि general-purpose GPU capabilities के अलावा इसमें graphics-specific silicon भी होता है
    • क्योंकि GPU कहने पर सब समझ जाते हैं कि मतलब क्या है
      drone और quad-copter का रिश्ता भी कुछ ऐसा ही है
    • vector processing unit ज़्यादा उपयुक्त नाम हो सकता है
    • CPU भी PPU है
    • General Processing Unit
  • यह शानदार लेख है। और GPU अपने काम के मामले में मेरी कल्पना की लगभग हर चीज़ से ज़्यादा विकसित और अधिक performant हो चुका है।
    लेकिन SIMD को, जब आप दूसरे और अधिक flexible paradigms सीख लेते हैं, तो मैं ऐसी श्रेणी में रखना चाहूँगा जहाँ वह अनिवार्य नहीं रह जाता। मुझे MIMD और cluster/transputer ज़्यादा पसंद हैं, लेकिन वे शायद 2000 के दशक के आसपास गायब हो गए। आज की स्थिति में developers को data खुद इधर-उधर ले जाना पड़ता है, एक मनमानी सीमा के तहत shaders लिखने पड़ते हैं कि एक साथ कितनी memory locations access की जा सकती हैं, GPU/CPU के लिए अलग-अलग languages इस्तेमाल करके काम duplicate करना पड़ता है, ray tracing जैसी सुविधाओं के लिए कौन-सा hardware मौजूद है यह जानना पड़ता है, और OpenGL/Metal/Vulkan जैसे opinionated frameworks से बँधना पड़ता है। GPU मेरे लिए एक ऐसा side branch है जो मुझे कभी वहाँ नहीं ले जा सकता जहाँ मैं जाना चाहता हूँ, इसलिए पिछले 25 साल गलत timeline में जीने जैसा अनुभव रहे हैं।
    ढीले तौर पर कहें तो, Moore’s law के खत्म होने की constraints के भीतर scalable general-purpose CPU को local memory वाले multicore के रूप में होना चाहिए, जो copy-on-write content-addressed memory या किसी दूसरे caching तरीके से data share करे, और users को desktop computing environment में computation के हर तरीके को स्वतंत्र रूप से explore करने देने के लिए एक single unified address space दे। इसमें standard assembly language का उपयोग हो, लेकिन सामान्यतः Erlang/Go, Octave/MATLAB, और आदर्श रूप से Julia जैसी functional programming languages में programming की जाए। 3D rendering और AI libraries उसके ऊपर की layers हैं, मूल तत्व नहीं।
    दिलचस्प बात यह है कि GPU लगभग उस multicore संरचना तक पहुँच चुका है जिसकी मैं बात कर रहा हूँ, लेकिन drivers users को general-purpose MIMD के लिए ज़रूरी bare-metal access से अलग कर देते हैं। मुझे लगता था कि GPU की बढ़त को तोड़ने का एकमात्र तरीका FPGA है, लेकिन शायद ऐसा driver लिखने का मौका हो सकता है जो GPU hardware को unified memory वाले MIMD की तरह दिखाए। मुझे नहीं पता कि GPU cores integer operations कितनी अच्छी तरह संभालते हैं, लेकिन शायद 64-bit floating point के 32-bit integer हिस्से से इसका approximation किया जा सकता है। ऐसे समझौतों की वजह से MIMD machine GPU से 10–100 गुना धीमी हो सकती है, लेकिन CPU से 10–100 गुना तेज़ भी हो सकती है। साथ ही यह बड़े cache और तेज़ bus पर अत्यधिक निर्भर हुए बिना scale कर सकती है—वही चीज़ें जिन्होंने 2007 के बाद, जब mobile market ने नेतृत्व संभाला और performance से ज़्यादा price तथा power efficiency को प्राथमिकता मिली, CPU को ठहरा दिया। MIMD machine को cluster भी किया जा सकता है ताकि बिना code बदले SETI@home जैसे distributed computation network बनाए जा सकें। आम users के लिए यह कितनी ताकतवर हो सकती है, इसका अंदाज़ा लगाने के लिए इसे data के नहीं बल्कि computation के BitTorrent बनाम FTP की तुलना जैसा समझें

  • मुझे ठीक से समझ नहीं आता कि Apple Silicon architecture, NVIDIA से कैसे अलग है।
    जब मैं यह वाक्य देखता हूँ—“Nvidia H100 GPU में 132 SM हैं, और हर SM में 64 cores, यानी कुल 8448 cores”—तो 8448 cores निश्चित रूप से प्रभावशाली लगते हैं। लेकिन Apple M2 Ultra में सिर्फ 76 cores हैं?
    NVIDIA H100 GPU में 110 गुना से भी ज़्यादा cores कैसे हो सकते हैं? स्पष्ट है कि उसकी performance, M2 Ultra से 110 गुना नहीं है, तो यहाँ असल में क्या हो रहा है?

    • सामान्य रूप से देखें तो NVIDIA का SM, AMD GPU के CU या Apple GPU के core के सबसे क़रीब है। यहाँ “core” शायद SM का एक subcomponent है जो individual operations करता है।
      NVIDIA ब्लॉग का यह diagram देखें: https://developer-blogs.nvidia.com/wp-content/uploads/2021/g...
      (https://developer.nvidia.com/blog/nvidia-ampere-architecture...)
    • NVIDIA जिस चीज़ को असल में vector lane कहना चाहिए, उसे “core” कहता है, और SIMT के “thread” शब्द का भी उपयोग इस तरह करता है कि मानो वह ऐसे ही किसी vector lane के execution को दर्शाता हो; यह जानबूझकर अस्पष्ट है और साफ़ कहें तो ईमानदार नहीं है।
      हाँ, हर lane में अलग program counter का support होने के कारण उसे “thread” कहने का कुछ आधार महसूस हो सकता है, लेकिन आखिरकार अहम चीज़ ALU की speed और throughput है।
    • H100 से एक कमरा गर्म किया जा सकता है। यह M2 Ultra की तुलना में 10 गुना से भी ज़्यादा power खाता है।
  • अब समझ आया कि machine learning precision के लिए floating point क्यों इस्तेमाल करती है। यह कोई पसंद नहीं थी, बल्कि इसलिए था क्योंकि graphics code इसी तरह लिखा गया था
    यह “machine learning इतनी inefficient क्यों है” वाली पहेली का एक और हिस्सा है
    यह जानने की जिज्ञासा है कि real-world environment में memory copy overhead कितना होता है। अगर यह आम तौर पर लगता है, तो काफ़ी कठोर होगा। इसे टालने के लिए TCP processing तक hardware को सौंप दी जाती है। यहाँ data बहुत ज़्यादा है, लेकिन इसे बड़े chunks में process भी किया जाता है

    • कई आधुनिक बड़े networks में gradient calculation और backpropagation का GPU compute time इतना धीमा होता है कि PCIe bus पर floating-point data कॉपी करना bottleneck नहीं बनता
      यानी floating-point images की minibatch कॉपी करना अब भी काफ़ी तेज़ है। क्योंकि gradient/SGD iteration धीमी होती है और compute मात्रा बहुत बड़ी होती है। mixed precision इस्तेमाल करने पर भी ऐसा ही है
      shallow networks में मूल compressed data को GPU memory में कॉपी करके, decompression वगैरह GPU पर करने का फ़ायदा हो सकता है। लेकिन आधुनिक GPU ने अभी तक PCIe 5 नहीं अपनाया है, क्योंकि raw compute performance ज़्यादा महत्वपूर्ण है
      आख़िर में Tensor Cores का असर भी बड़ा रहा, और कुछ networks में वे इतने तेज़ हो सकते हैं कि utilization बहुत कम रह जाए
    • मुझे नहीं लगता कि floating-point numbers इस्तेमाल करने का फ़ैसला अपने-आप में खास तौर पर inefficient है। अगर framework डिफ़ॉल्ट रूप से fixed-point होता, तो पूरे network में dynamic range मिलाना मुश्किल होता
      training का गणित भी यह मानकर चलता है कि numbers continuous हैं
    • floating point बड़ा होता है, और उसके operations भी ज़्यादा कठिन होते हैं
      लेकिन यह जिज्ञासा थी कि CPU-आधारित LLM quantization क्यों करते हैं। मेरी समझ के मुताबिक यह weights की precision घटाकर memory कम इस्तेमाल करने की प्रक्रिया है
      precision की कमी वास्तव में फ़र्क पैदा करती है या नहीं, यह स्पष्ट नहीं है। अगर नहीं करती, तो फिर शुरू से floating point क्यों इस्तेमाल किया जाता है? अगर precision महत्वपूर्ण नहीं है, तो अतिरिक्त precision सिर्फ़ बिना किसी वास्तविक कारण के resources ज़्यादा खर्च कराती है, और संभव है कि ज़रूरत से कई orders of magnitude अधिक resources लगें
      इस क्षेत्र की शुरुआत performance को समझने वाले लोगों ने नहीं की थी। उन्होंने tools का इस्तेमाल करके कुछ बनाया, लेकिन “क्यों” का जवाब नहीं था। tool ऐसा करता था, इसलिए उन्होंने भी वैसा ही किया
      यह इसलिए महत्वपूर्ण है: सामान्य CPU पर भी data access का एक तरीका दूसरे तरीके से कई orders of magnitude तेज़ हो सकता है, लेकिन इसके लिए यह जानना ज़रूरी है। क्या आप LLM की लागत को कई orders of magnitude तक कम नहीं करना चाहेंगे?
    • floating point में exactly क्या inefficient है? ऐसा लगता है कि machine learning को कई orders of magnitude वाली dynamic range तक पहुँच से बड़ा लाभ मिलता है
  • कुछ साल पहले का यह talk और slides भी देखने लायक हैं, जो CPU और GPU के पेचीदा हिस्सों को कवर करते हैं
    Alexander Titov — Know your hardware: CPU memory hierarchy https://youtu.be/QOJ2hsop6hM
    https://github.com/alexander-titov/public/blob/master/confer...
    Know Your Hardware - CPU Memory Hierarchy -- Alexander Titov -- C%2B%2B Moscow Meetup March 2019.pdf
    https://github.com/alexander-titov/public/blob/master/confer...
    GPGPU - what it is and why you should care -- Alexander Titov -- CoreHard 2019.pdf