i made a TPU from scratch — Transcript
Full transcript
- 0:00Nvidia.
- 0:00>> AI chips, Nvidia.
- 0:02>> AI, Nvidia.
- 0:03>> Nvidia chips.
- 0:03>> Newcomers to the club like Nvidia, they
- 0:05power that new AI revolution. Up 5.4%.
- 0:08>> It's up 55%.
- 0:09>> Look, Nvidia made people rich like no
- 0:11stock I've ever seen.
- 0:13>> And this
- 0:15is the backbone behind the whole thing.
- 0:17The GPU.
- 0:18Okay, maybe I lied. What's in front of
- 0:20me is actually an FPGA. Unlike standard
- 0:23GPUs and other chips that are
- 0:24manufactured to the same design, this
- 0:27chip is meant to be reprogrammed. And on
- 0:29this board, I've programmed a TPU.
- 0:32You see, here's the goal. I want to
- 0:34create a small AI model on my computer
- 0:36that can do something super cheap. And
- 0:37in this case, I've [music] created an
- 0:39art predictor, where the model will try
- 0:41to guess what you're drawing as you're
- 0:42drawing it. Now, the reason I went with
- 0:44a project of this scope is due to
- 0:46hardware limitations, which brings us
- 0:47back to Nvidia.
- 0:48>> It's about it's accelerated computing.
- 0:49People don't give that enough credit.
- 0:51And
- 0:52I'm going to use it. We're number one.
- 0:54We're number one.
- 0:55>> You see, the strength of an AI model
- 0:57comes from the hardware that supports
- 0:59it. In 2020, OpenAI released GPT-3,
- 1:02which was the first model to really make
- 1:03public headway. Nowadays, we can look
- 1:05back and see how out of date these
- 1:06models seem, but even back then, when we
- 1:08looked at the hardware specs, it's crazy
- 1:10how many resources were needed to
- 1:11support it. GPT-3 needed 350 GB of
- 1:15memory to hold the 175 billion
- 1:17parameters the model needed. In order to
- 1:19support this, OpenAI needed to share the
- 1:21model across eight GPUs, which alone
- 1:24cost it about $200,000 of hardware.
- 1:27Which also explains why memory stock
- 1:29skyrocketed this year.
- 1:30>> This is the biggest gainer in the S&P
- 1:31500, up 19.3%. The market cap now over a
- 1:35trillion dollars.
- 1:36>> If we compare OpenAI's model to the size
- 1:38of mine, it doesn't even show on the
- 1:40charts. This chip in front of me has 512
- 1:43KB of RAM and uses only 2 W of energy.
- 1:46Yet, my thing still works and at 1/1000
- 1:49of the cost.
- 1:50Here's how. On the PC side, we'll have a
- 1:5216 by 16 LED grid in which we can start
- 1:55drawing. The plan is that as we draw,
- 1:57the PC will take a snapshot of our grid
- 1:59as a matrix. It will embed those
- 2:01matrices into 64-dimensional token
- 2:03vectors and add positional encoding. So,
- 2:05each of the 16 rows becomes a token the
- 2:08model can reason about. That 16 by 64
- 2:10matrix then gets quantized to Q8.8
- 2:13fixed-point format and gets sent out to
- 2:15our chip, which is packed into a UART
- 2:17frame with a checksum. The FPGA runs the
- 2:19attention block on it, projecting the
- 2:21tokens into queries, keys, and values,
- 2:23computing the attention scores, applying
- 2:25soft mats and hardware, and producing
- 2:27the weighted output. It then sends the
- 2:28resulting 16 by 64 matrix back over
- 2:31UART. The PC picks up from there. It
- 2:33adds a residual connection, applies a
- 2:35layer norm, and the feed-forward
- 2:36network. After that, it runs a final
- 2:38output projection and a sigmoid, giving
- 2:40a probability for each of the 256
- 2:42pixels. Threshold those, and you have
- 2:44the completed pattern, which gets drawn
- 2:46back onto the grid. So, the loop is:
- 2:48draw, snapshot, embed, FPGA does the
- 2:51attention, PC finishes the layer,
- 2:53predict, and display.
- 2:55But, there is a bottleneck here, and
- 2:58it's this:
- 2:59over and over and over, the same
- 3:02operation a few million times, all in
- 3:05sequence.
- 3:06So, if you step back, over 95% of this
- 3:09is matrix multiplication, which is the
- 3:11same expensive thing just repeated. A
- 3:14normal CPU is going to chew through all
- 3:16of this one by one, since it's a
- 3:17general-purpose chip being asked to do
- 3:19one thing a few million times. So, we
- 3:21got to fix this on the hardware level,
- 3:24and that's where we bring out the TPU.
- 3:27Our chip provides us with configurable
- 3:29logic, dedicated math blocks, and RAM.
- 3:31On the chip itself, we'll need to
- 3:33perform these operations.
- 3:35First, the three projections. Because
- 3:37the training gives us concrete embedding
- 3:39matrices that won't change, we'll
- 3:41actually have those pre-filled in our
- 3:42chip's RAM. But, as we draw on the grid,
- 3:45a snapshot will have to be transmitted
- 3:46live. So, we'll need to make the
- 3:48distinction as to what's live and what's
- 3:50static. Let's take a look at the size of
- 3:52our biggest operation. What we've got is
- 3:54a 16 by 64 matrix times a 64 by 64
- 3:57matrix. Perfect. Let's just design a
- 4:00multiplication unit that can, I'm at, do
- 4:03that.
- 4:05We can't. See, there's an important
- 4:07distinction to note on FPGAs and chips
- 4:09in general, and that is the difference
- 4:10between CLBs and DSPs.
- 4:13An FPGA is mostly made up of
- 4:15configurable logic blocks, which gives a
- 4:17reprogrammable aspect to this chip.
- 4:19These are made with lookup tables and
- 4:21flip flops that you configure into
- 4:22whatever circuit you need when you write
- 4:24Verilog code. These can mimic anything,
- 4:26and we've got about 20,000 of them on
- 4:27the board. A DSP, however, is a
- 4:30specialized non-programmable,
- 4:31purpose-built silicon that does one
- 4:33thing: multiply two numbers and add the
- 4:35result to a running total, one cycle
- 4:38every cycle, and fast. You can build a
- 4:40multiplier out of CLBs, but a 16-bit one
- 4:43eats around 200 lookup tables, and it's
- 4:45slow because you're chaining logic
- 4:47together, and the signal has to ripple
- 4:49through all of the board, which might
- 4:50not meet timing on our chip. And since
- 4:52multiply-accumulate is the only
- 4:54operation we'll really need, the DSPs
- 4:56are the obvious choice. It's a The Basis
- 4:593 only has 90 of them. For a dot
- 5:01product, we need one DSP per output
- 5:03element because each one is its own
- 5:05running total. And if we go spec out how
- 5:07many our biggest operation needed, that
- 5:09would be 1,024 DSPs. So, how big can we
- 5:12really make our matrix multiplier? 8 by
- 5:158, as that will just use [music] 64
- 5:17DSPs. Eight rows, eight columns, one DSP
- 5:19per cell, all 64 running at once, which
- 5:22gives us 26 to spare.
- 5:24Not that it matters.
- 5:25This works out nicely because every
- 5:27matrix we're dealing with is a multiple
- 5:29of eight. So, we can just chop them into
- 5:308 by 8 tiles and feed them through one
- 5:32at a time with nothing left over.
- 5:3416 by 64 * 64 by 64 becomes two tiles
- 5:38down, eight across, eight deep for 128
- 5:40tiles run back-to-back through the same
- 5:42array.
- 5:43Now, here's the point when we make the
- 5:44distinction between a GPU and a TPU. Try
- 5:47to find the bottleneck in this
- 5:48operation.
- 5:51See, that's one cycle. Going out to
- 5:53memory to fetch the values takes time,
- 5:56and you're doing that fetch for every
- 5:57single multiply. So, you end up with a
- 5:59multiplier sitting idle most of the time
- 6:01waiting on data that's slower to arrive
- 6:03than it is to use. In standard GPU
- 6:05architecture, it's done this way. We
- 6:07multiply and fetch, but in TPU
- 6:09architecture, we implement systolic
- 6:11methodology in hopes of eliminating this
- 6:13bottleneck.
- 6:14The idea is that instead of every unit
- 6:17fetching its own data, we fetch once and
- 6:19let the data flow in this offset
- 6:21pattern. We wire the multiply accumulate
- 6:23units into a grid where each one is
- 6:25connected to its neighbors. A value gets
- 6:27read from memory once, enters the edge
- 6:28of the array, and then gets passed hand
- 6:30to hand from one unit to the next every
- 6:32cycle one step further in. So, every
- 6:35unit is doing a multiply every single
- 6:37cycle, and the only memory traffic is at
- 6:39the edges. The data watts through the
- 6:41array, and by the time it comes out the
- 6:42other side, all the multiply accumulates
- 6:44are done.
- 6:46So, when we apply it to our 8 by 8
- 6:47multiply accumulator, it goes like this.
- 6:50We load eight values of A and eight of B
- 6:52at the edges of the array, and then all
- 6:5364 units run for 22 cycles off that
- 6:56single load. We're not fetching per
- 6:58multiply, we're fetching per tile. So,
- 7:00each chunk still gets that flow-through
- 7:02benefit. The tiling doesn't break the
- 7:04systolic idea. It just means we do it
- 7:06128 times in a row instead of once on a
- 7:08giant array. Where it does cost us is
- 7:11the seams between tiles. As every time
- 7:13we finish one and start the next, we go
- 7:15back to memory for the next chunk. And
- 7:16that load takes 64 cycles, which is
- 7:19longer than the 22 cycles of actual
- 7:21compute time. But, the good thing is
- 7:23while the systolic array is computing
- 7:25and the data's flowing through it, we
- 7:26can actually start loading the next tile
- 7:28in at the same time. Two buffers instead
- 7:30of one. The array works out of one while
- 7:32the controller fills the other. Then
- 7:34they swap. The fetch hides underneath
- 7:36the compute instead of stacking on top
- 7:38of it. So, we lose no time between
- 7:40tiles. This principle is called double
- 7:42buffering, and it's what a real TPU
- 7:43does. So, how much time did we really
- 7:45save here? Well, let's look at the math.
- 7:47Each 8 by 8 tile takes 64 cycles to
- 7:50load, and with the double-buffering,
- 7:52that's the entire cost. The 22 cycles of
- 7:54compute hiding underneath it. One layer
- 7:57is 576 tiles * 64 cycles is about 37,000
- 8:02cycles. At 100 MHz, which is what the
- 8:04board operates at, that's 0.37 ms. Six
- 8:09matrix multiplications, half a million
- 8:11multiply accumulates in about a third of
- 8:13a second.
- 8:14That's basically all the matrix math
- 8:16done, and there's two parts left to do.
- 8:18Number one is the softmax, which gives
- 8:20probabilities to our attention tokens,
- 8:22and two is the train the model.
- 8:25The word softmax might sound complex,
- 8:27but all it does is turn a row of raw
- 8:29scores into probabilities. This is why
- 8:31every input can produce a unique output
- 8:33on something like ChatGPT.
- 8:35Our attention scores come out as
- 8:37arbitrary numbers, and what we need is
- 8:39how much should this token pay attention
- 8:41to that one as a fraction. Softmax takes
- 8:44that row and squashes it, so
- 8:45everything's positive and the whole row
- 8:47sums to one. The way you do it is you
- 8:49would exponentiate every score, then
- 8:51divide each one by the total. But,
- 8:53exponentials and divisions are two of
- 8:55the most expensive things you can ask
- 8:56the hardware to do. A divider alone is a
- 8:58huge block of logic, and it's slow.
- 9:01Where a multiply is one cycle, a
- 9:02division takes many. Doing that for
- 9:05every element in the matrix on a chip
- 9:07that only has a 90 multipliers to begin
- 9:09with is not happening.
- 9:11So, we don't. There's a paper from 2021
- 9:14that gets around it entirely using
- 9:15lookup tables. Not to be confused with
- 9:18the ones we saw earlier that are baked
- 9:19into the FPGA.
- 9:21The idea is that instead of calculating
- 9:23the exponential, you precompute the
- 9:25answers once and store them in a table.
- 9:28Then at runtime, you just look it up.
- 9:30Same for division. Rather than dividing,
- 9:32you use the exponential and the sum as
- 9:35coordinates into a second
- 9:36two-dimensional table that hands you the
- 9:39answer directly.
- 9:40So, the whole thing becomes two table
- 9:42reads and an adder, and both tables are
- 9:44small enough to fit in a chip's general
- 9:46purpose logic. So, it costs us zero RAM.
- 9:49Since we're approximating, we'll be off
- 9:51by about 0.9% on average. But, for
- 9:54attention, what matters is which token
- 9:56wins and not the exact decimal. And it
- 9:58gets that right about 96% of the time.
- 10:00After implementing the soft max, along
- 10:02with a few other tweaks like writing the
- 10:04UART driver, we're done with the
- 10:06hardware.
- 10:07Now, we actually have to train our
- 10:09model. This spans two steps. Number one,
- 10:12gather the data set. In our case, that's
- 10:15like really simple, because we're
- 10:16basically just doing pixel art. So, I
- 10:18can literally just draw these out by
- 10:19hand.
- 10:20We've got 69 different pattern types:
- 10:22hearts, skulls, Space Invaders, chess
- 10:24pieces, letters, numbers, arrows, mazes,
- 10:27a yin yang. Then for each one, it makes
- 10:29six variants at slightly different
- 10:30positions, plus noisy copies. So, the
- 10:32model just can't memorize one heart.
- 10:35That gives us 1,200 training examples. I
- 10:37totally made 10,000, since it cost me
- 10:39nothing. More data is free here, but
- 10:41that's actually where we hit the first
- 10:43wall in this project. See, every pattern
- 10:45type I add [music] makes the job harder.
- 10:47The model has to learn 69 different
- 10:49shapes with the same set of weights, and
- 10:50how much it can actually learn is capped
- 10:52by how big the model is, and how big the
- 10:54model can be is ultimately capped by the
- 10:56board, which we know is not the best.
- 10:59Every time you double the embedding
- 11:00dimension, the attention weights
- 11:01quadruple, because they're square
- 11:03matrices, D by D.
- 11:05At an embedding dimension of 64, which
- 11:07is what we use, the whole model is about
- 11:0969K parameters, which is 138 kilobytes
- 11:12in our fixed point format. That fits on
- 11:14our board, which has 225 kilobytes of
- 11:16block RAM. Bump it to 128, now you're
- 11:19roughly looking at 262K parameters,
- 11:21which is over half a megabyte. The board
- 11:24physically cannot hold that. Not that
- 11:26it'd be slow or tight, but the memory
- 11:28physically does not exist on the chip.
- 11:30So, for this project, we're staying at
- 11:32an embedding dimension of 64, which is
- 11:34the biggest I could go with and still
- 11:35have it fit. Loss is 0.11 at 95.8%
- 11:39accuracy.
- 11:41But, there's a trade-off buried in here
- 11:42that I think is the actually interesting
- 11:44part. I could have trained on way fewer
- 11:46shapes, like just hearts and smileys,
- 11:48and gotten near perfect accuracy with a
- 11:50tiny model. But, then it's not really
- 11:52learning anything. It's just memorizing
- 11:53two pictures. Draw anything else and
- 11:55it's not nothing. Throwing 69 different
- 11:58shapes at it forces it to actually learn
- 12:00structure, symmetry, edges, how shapes
- 12:02close up, instead of memorizing specific
- 12:04patterns, which is what I want. Because
- 12:06when I draw something freehand, it's not
- 12:08going to look nice and look like one of
- 12:09my training examples.
- 12:11But, that costs capacity. The more
- 12:13variety you ask for, the bigger the
- 12:14model needs to be to hold it. So, you're
- 12:17getting squeezed from both ends. Too few
- 12:19shapes and it memorizes, too many and
- 12:21you need a model the board can't fit.
- 12:23Step two, train the model.
- 12:26Luckily for us, though, training is the
- 12:28easy part, since PyTorch does it all. We
- 12:31describe the shape of the network, hand
- 12:32it the data, and it works out every
- 12:34adjustment for us.
- 12:35>> [music]
- 12:35>> One decision worth mentioning, at 95.8%
- 12:38accuracy, I wasn't happy with a single
- 12:40attention layer, so I ran two, which
- 12:42means two full sets of weight matrices
- 12:44instead of one. After training, all we
- 12:46walk away with is just matrices,
- 12:49embedding, QKV, output projection, feed
- 12:52forward, and one last one to turn it
- 12:54back into pixels.
- 12:58And with that, the project's done. I
- 13:01finished my code, got my board up and
- 13:02running, and connected my PC with the
- 13:04weights loaded to see how well this
- 13:06actually works. For a quick test, if I
- 13:08click any tile in our predictor, the
- 13:10UART LED should flash, which means it's
- 13:12set up to test. So, now, moment of
- 13:14truth. Let's see how good this TPU
- 13:17actually is.
- 13:21If I draw like this, we can see that it
- 13:22gets it fairly correct. 96% accuracy
- 13:25seems to get us not the healthiest
- 13:27heart, but to be honest, I'm quite
- 13:29surprised with how well this turned out
- 13:30with all the other drawings. This tiny
- 13:32board is reading my input, running the
- 13:34two-layer inference, and is guessing
- 13:36what I'm drawing quite well. And yeah,
- 13:38with some shapes, it doesn't provide
- 13:40exactly what I'm looking for, but it's
- 13:42still giving a really good approximation
- 13:44based on the fact that I'm drawing like
- 13:4630% of the actual shape. And honestly,
- 13:49it does this better than me in some of
- 13:50these.
- 13:51I would not have known this was a boat,
- 13:53but that's probably just because I'm a
- 13:55bad drawer. For comparison's sake, I
- 13:57decided to run the same script, but just
- 13:59using the specs of my PC. I used PyTorch
- 14:02again, not just to train the data, but
- 14:03to help implement the attention pipeline
- 14:05solely on my CPU.
- 14:07And I think the best part of this whole
- 14:09thing is that my CPU is a $400 chip. And
- 14:13while it beats my FPGA in speed, it
- 14:15would have been beat if we took the wire
- 14:17out of the equation and didn't have to
- 14:18spend 21 milliseconds on the UART
- 14:21transfer.
- 14:23Intel, AMD, and other companies spend
- 14:25decades and billions of dollars to get
- 14:27to this point. And this is a $60 FPGA I
- 14:30programmed at my desk over a few months.
- 14:33And I think in some aspects, it wins.
- 14:35The thing behind the trillion-dollar
- 14:37companies, the thing on every news
- 14:39channel right now, the thing that sounds
- 14:41like it should be out of reach, turns
- 14:43out you can just make one.
- 14:56>> Mhm.
About this transcript
This page contains the full transcript of i made a TPU from scratch by traffic in the brain, generated from the public captions YouTube serves with the video. The transcript has 2,876 words across 434 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.
What you can do with it
Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to choose a caption track available on the video.
Free YouTube transcript tool
YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, caption language selection, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.