Bạn có thể giải thích cách máy tính hoạt động từ dưới lên không?


Để hiểu về máy tính, trước tiên bạn phải chấp nhận một thực tế vật lý. Không có phép thuật nào bên trong máy tính cả. Chỉ có các tín hiệu điện. Chính xác hơn, chỉ có điện áp cao và điện áp thấp.

Vật liệu cơ bản cho các chip chúng ta sử dụng ngày nay là silicon. Silicon là một chất bán dẫn. Chất bán dẫn có một tính chất vật lý: bằng cách pha tạp các nguyên tố khác nhau và điều khiển điện áp trên điện cực, có thể điều khiển việc chúng dẫn điện hay không. Cấu trúc tí hon này có thể bật và tắt bằng điện được gọi là transistor.

CPU hiện đại chứa hàng chục tỷ transistor. Quy trình 3 nanomet hiện tại của TSMC có nghĩa là các transistor này được chế tạo vô cùng nhỏ đến nỗi hàng chục tỷ có thể vừa trên một miếng silicon bằng kích thước móng tay.

Bạn chỉ cần nhớ một chức năng cốt lõi của transistor. Nếu bạn đặt một điện áp cao vào đầu điều khiển của nó, nó dẫn điện. Nếu bạn đặt điện áp thấp, nó ngắt. Đây là thực tế vật lý cơ bản. Chúng ta định nghĩa điện áp cao là logic 1 và điện áp thấp là logic 0. Tất cả khoa học máy tính được xây dựng trên hai trạng thái này.

Với transistor, chúng ta có thể kết hợp chúng thành các cổng logic.

Giả sử chúng ta mắc nối tiếp hai transistor. Dòng điện chỉ có thể chảy từ đầu này sang đầu kia – xuất ra 1 – khi cả hai đầu điều khiển nhận được điện áp cao, tức là cả hai đầu vào đều là 1. Nếu một trong hai là 0, dòng điện bị cắt và đầu ra là 0. Mạch vật lý này được gọi là cổng AND.

Cũng với logic đó, nếu hai transistor được mắc song song, dòng điện chảy – xuất ra 1 – miễn là ít nhất một đầu vào là 1. Chỉ khi cả hai là 0 thì đầu ra mới là 0. Đây là cổng OR.

Sử dụng một phương pháp kết nối hơi khác, khi nhập 1 cho đầu ra 0 và nhập 0 cho đầu ra 1, chúng ta tạo ra cổng NOT.

Với các cổng AND, OR và NOT, thế giới vật lý chính thức bước vào thế giới toán học. Tôi rất khuyên một cuốn sách giáo khoa kinh điển ở đây tên là Code, của Charles Petzold. Cuốn sách này không có đồ rườm rà – nó bắt đầu từ máy điện tín và giải thích cách nối dây các cổng logic. Nó hoàn hảo để xây dựng lớp trực giác vật lý đầu tiên đó. Bạn nên xem nó sau khi đọc bài viết này – nó chắc chắn sẽ làm bạn kinh ngạc.

Bây giờ chúng ta đã có cổng logic, làm thế nào để máy tính thực hiện phép cộng?

Trong hệ nhị phân, 1 cộng 1 bằng 10. Điều đó có nghĩa là bit hiện tại trở thành 0 và chúng ta nhớ 1 sang vị trí tiếp theo. Đây thực ra là hai thao tác logic. Thứ nhất, xác định bit hiện tại: nếu cả hai đầu vào là 1, bit hiện tại là 0. Nếu một đầu vào là 1 và đầu kia là 0, bit hiện tại là 1. Logic này có thể được thực hiện bằng cách kết hợp các cổng cơ bản chúng ta đã thảo luận – chúng ta gọi nó là cổng XOR. Thứ hai, xác định số nhớ: chỉ khi cả hai đầu vào là 1 mới có số nhớ, đây chính xác là chức năng của cổng AND.

Kết nối một cổng XOR và một cổng AND với nhau, và bạn đã vật lý thực hiện phép cộng của một chữ số nhị phân. Đây được gọi là bộ bán cộng. Kết nối nhiều bộ bán cộng theo tầng, xử lý tín hiệu số nhớ, và bạn có được bộ cộng toàn phần. Nếu bạn kết nối 64 bộ cộng toàn phần này, bạn có được một mạch vật lý có thể cộng các số nhị phân 64-bit.

Khi bạn viết dòng code a = b + c, điều xảy ra ở cấp thấp nhất là các tín hiệu điện đại diện cho b và c đồng thời lao vào mạch cộng này được làm từ hàng chục ngàn transistor. Sau một độ trễ vật lý cực kỳ ngắn, đầu kia của mạch xuất ra các điện áp cao và thấp ổn định đại diện cho kết quả.

Đó là cái được gọi là Đơn vị Tính toán và Logic (ALU). Nó hoàn toàn không phải là một thành phần cốt lõi bí ẩn – nó chỉ là một mạng dày đặc của các cổng logic bán dẫn, được nối dây cứng theo các quy tắc toán học do con người thiết kế. Ngoài phép cộng, thông qua các cấu hình đấu nối khác nhau, nó cũng có thể thực hiện phép trừ, dịch bit và thậm chí cả phép nhân.

Nhưng chỉ có thể tính toán thôi thì vô ích. Kết quả chỉ là một mớ tín hiệu điện – ngay khi mất điện hoặc đầu vào thay đổi, kết quả biến mất. Máy tính phải có thể ghi nhớ dữ liệu. Điều này đưa chúng ta đến bộ nhớ và thanh ghi.

Làm thế nào để sử dụng tín hiệu điện để ghi nhớ một trạng thái? Các kỹ sư điện tử đã phát minh ra một mạch vô cùng tài tình gọi là flip-flop. Đây là một mạch cổng logic có vòng lặp phản hồi. Nói một cách đơn giản, tín hiệu đầu ra được đưa trở lại đầu vào. Thiết kế này cho phép mạch duy trì trạng thái điện áp cao hoặc thấp hiện tại bằng phản hồi nội bộ, ngay cả sau khi loại bỏ đầu vào ban đầu.

Khi bạn đưa cho flip-flop này một tín hiệu ghi cụ thể, nó cập nhật trạng thái nội bộ và khóa nó. Trừ phi bạn gửi cho nó một tín hiệu ghi khác, nó sẽ giữ 0 hoặc 1 đó vô thời hạn.

Sắp xếp 64 flip-flop thành một hàng, và bạn có thể lưu trữ một số nhị phân 64-bit. Bên trong CPU, ngay cạnh ALU, các đơn vị lưu trữ siêu nhanh làm từ flip-flop này được gọi là thanh ghi. Vị trí vật lý của chúng nằm ngay cạnh mạch tính toán, có nghĩa là tín hiệu điện di chuyển quãng đường ngắn nhất có thể, vì vậy chúng cực kỳ nhanh. Tất nhiên, chúng cũng cực kỳ đắt để sản xuất, vì vậy chỉ có thể rất nhỏ.

Ở đây tôi phải giới thiệu mạnh mẽ một cuốn sách huyền thoại tuyệt đối: Computer Systems: A Programmer’s Perspective, được biết đến trong giới IT là CSAPP. Đây là sách giáo khoa được sử dụng tại Đại học Carnegie Mellon. Điều làm cho nó tuyệt vời là nó kết nối từ hợp ngữ đến kiến trúc phần cứng và hệ điều hành. Khi bạn hiểu được nó, bạn sẽ biết tại sao một số code chạy nhanh và một số chạy chậm – bởi vì bạn sẽ bắt đầu viết code với tư duy ở cấp độ vật lý.

Nếu bạn muốn đi xa hơn và kết nối một cách có hệ thống các hệ điều hành, tổ chức máy tính, mạng và các kiến thức cơ bản khác cùng một lúc, tôi đã tập hợp một bộ sưu tập bao gồm cấu trúc dữ liệu và giải thuật, tổ chức máy tính và nhiều hơn nữa.

Hơn 1 triệu lượt tải xuống trên toàn web – kiến thức cơ bản máy tính sẽ nâng tầm kỹ năng của bạn.

Hãy tiếp tục đi ra ngoài. Nếu thanh ghi không đủ thì sao? Chúng ta cần bộ nhớ lớn hơn. Đây là lúc các thanh RAM cắm trên bo mạch chủ của bạn phát huy tác dụng. Tên kỹ thuật là Bộ nhớ Truy cập Ngẫu nhiên Động, hay DRAM.

Nguyên lý vật lý của DRAM hoàn toàn khác với thanh ghi. Thay vì flip-flop, nó sử dụng các tụ điện cực nhỏ để lưu trữ điện tích. Một tụ điện có điện tích là 1, không có điện tích là 0. Bởi vì cấu trúc tụ điện cực kỳ đơn giản – chỉ cần một transistor và một tụ điện để lưu trữ một bit dữ liệu – dung lượng có thể được làm rất lớn. Ngày nay, hàng chục hoặc thậm chí hàng trăm gigabyte là phổ biến.

Nhưng tụ điện có một khuyết điểm chết người: chúng bị rò điện. Nếu để yên, điện tích đại diện cho 1 sẽ rò hoàn toàn trong vài mili giây, trở thành 0. Vì vậy bo mạch chủ phải có một mạch điều khiển chuyên dụng đọc dữ liệu từ bộ nhớ và nạp lại ở các khoảng thời gian cực kỳ ngắn. Đây được gọi là làm tươi động. Đây là lý do tại sao khi bạn rút điện máy tính, mọi thứ trong bộ nhớ biến mất ngay lập tức.

Bây giờ chúng ta có ALU có thể làm tính toán, và thanh ghi và bộ nhớ có thể lưu trữ dữ liệu. Câu hỏi cốt lõi là: làm thế nào những vật vô tri này bắt đầu chuyển động? Ai chỉ huy chúng thực hiện phép cộng trước, rồi phép nhân, và cuối cùng lưu trữ kết quả?

Đây là công việc của bộ điều khiển, và là cơ chế cốt lõi làm cho máy tính trở thành một cái máy.

Bo mạch chủ có một bộ dao động tinh thể – một tinh thể thạch anh tạo ra một tín hiệu xung có tần số cố định miễn là có điện. Ví dụ, nếu CPU của bạn được định mức ở 4.0 GHz, có nghĩa là tinh thể này tạo ra 4 tỷ chuyển tiếp điện áp cao-thấp mỗi giây.

Đây là nhịp tim của máy tính. Tất cả các cổng logic và flip-flop bên trong CPU hoạt động đồng bộ nghiêm ngặt với nhịp tim này.

Bên trong CPU, có một thanh ghi rất đặc biệt gọi là bộ đếm chương trình. Nó không chứa gì ngoài một địa chỉ bộ nhớ.

Khi nhịp đầu tiên của trái tim vang lên, CPU làm việc đầu tiên: lấy lệnh. Nó gửi địa chỉ được lưu trong bộ đếm chương trình đến bộ nhớ thông qua các đường dây kim loại trên bo mạch chủ. Bộ nhớ gửi trả lại chuỗi 0 và 1 dài được lưu tại địa chỉ đó.

Chuỗi 0 và 1 dài này là lệnh. Khi lệnh quay trở lại CPU, nó đi vào bộ điều khiển. Bộ điều khiển cũng chỉ là một mớ cổng logic nối dây cứng – công việc của nó là giải mã. Ví dụ, khi nó thấy rằng các chữ số đầu tiên của 0 và 1 đến là 1011, cấu trúc dây nối bên trong của nó xác định rằng các điện áp cao và thấp này kích hoạt chính xác công tắc dẫn đến mạch cộng trong ALU. Đồng thời, phần còn lại của lệnh xác định thanh ghi nào chứa hai giá trị dữ liệu cần cộng.

Khi nhịp tiếp theo vang lên, giai đoạn thực thi bắt đầu. Mạch cộng được kích hoạt nhận dữ liệu, các tín hiệu điện chớt lóa qua mạng cổng logic của bộ cộng trong chớp mắt, và kết quả được tạo ra.

Ở nhịp tiếp theo, kết quả được ghi trở lại vào thanh ghi được chỉ định.

Cuối cùng, bộ đếm chương trình tự động tăng lên một, trỏ đến lệnh tiếp theo trong bộ nhớ. Sau đó chu kỳ lặp lại. Hàng tỷ lần mỗi giây.

Đây là sự thật hoàn chỉnh ở cấp thấp nhất về cách máy tính hoạt động. Không có bất kỳ trí tuệ tiên tiến nào – chỉ có một bộ dao động tinh thể đánh nhịp một cách mù quáng, một bộ đếm chương trình tăng địa chỉ một cách máy móc, một bộ điều khiển chuyển đổi đường tín hiệu một cách robot dựa trên các 0 và 1 nó đọc, và một ALU thụ động chuyển đổi các mức điện áp đến thành các mức điện áp mới.

Code Python hoặc Java bạn viết trong công việc hàng ngày cuối cùng được dịch bởi một phần mềm gọi là trình biên dịch thành một chuỗi các lệnh máy dài và tẻ nhạt dành cho kiến trúc CPU cụ thể – 0 và 1 thuần túy.

Tại thời điểm này, bạn đã thực sự hoàn thành toàn bộ chuỗi từ cát (silicon) đến chương trình. Nhiều người cảm thấy hiểu ở giai đoạn này, nhưng trong môi trường công nghiệp thực tế ngày nay, chỉ hiểu các nguyên lý CPU truyền thống thậm chí không đạt đến mức đạt yêu cầu.

Với chủ đề nóng nhất hiện nay là các mô hình AI lớn, tôi phải mở rộng tầm nhìn của bạn. Hãy xem xét thực tế của bức tranh sức mạnh điện toán ngày nay.

Bất kỳ nhóm nào làm việc với mô hình lớn ngày nay, dù cho huấn luyện hay suy luận, tuyệt đối không thể sử dụng CPU để tính toán. Tại sao?

Bởi vì CPU được thiết kế để xử lý điều khiển logic phức tạp. Nhìn vào CPU: một phần lớn diện tích của nó được dành cho dự đoán nhánh, quản lý bộ nhớ đệm và bộ điều khiển. Phần thực sự được sử dụng cho tính toán số thuần túy – ALU – không lớn lắm. Nó giống như CPU là một trí thức trình độ cao, xuất sắc trong các quy trình quản lý phức tạp. Hãy bảo nó tính 1+1, nó có thể làm, và nó thậm chí có thể phân tích xem có lỗi gì không – nhưng nó chỉ có thể xử lý một vài cái cùng một lúc.

Bản chất toán học cốt lõi của các mô hình lớn là phép nhân ma trận quy mô cực lớn. Ví dụ, nhân hai ma trận vài nghìn với vài nghìn. Điều này đòi hỏi hàng trăm triệu phép nhân và cộng. Logic cực kỳ đơn giản – nhân-cộng, nhân-cộng – không có nhánh phức tạp nào, nhưng khối lượng dữ liệu thì kinh ngạc.

Nếu bạn sử dụng CPU truyền thống để tính toán điều này, nó chắc chắn có thể thực thi hàng tỷ lệnh mỗi giây, nhưng đối mặt với hàng trăm tỷ tham số, nó sẽ như muối bỏ vào biển.

Để thực sự hiểu các mô hình lớn đang tính toán gì, nếu trực giác toán học của bạn vẫn dựa trên công thức học thuộc, tôi rất khuyên bạn nên xem bài “Essence of Linear Algebra” của 3Blue1Brown. Để dễ dàng ôn tập và suy luận, bạn có thể kết hợp với tập hợp các ghi chép 3Blue1Brown bằng tiếng Trung và tiếng Anh. Nó đạt được sự trực quan hóa thực sự về phép nhân ma trận nâng cao và các biến đổi tuyến tính. Sau khi xem, bạn sẽ có một hình ảnh tâm thần cấp độ vật lý thực tế về các phép toán nhân-tích lũy qua hàng nghìn tham số.

Ghi chép Đại số Tuyến tính 3Blue1Brown: Có lẽ là tổng hợp tiếng Trung-Anh tốt nhất trên web

Bản chất của các tính toán ma trận khổng lồ này đã sinh ra GPU, Bộ xử lý Đồ họa – ngày nay nên được gọi là Bộ tính toán Song song Đa năng.

Triết lý thiết kế của GPU hoàn toàn ngược lại với CPU. Nó cắt bỏ phần lớn mạch điều khiển phức tạp và các bộ nhớ đệm lớn, lấp đầy từng bit không gian vật lý được giải phóng bằng các ALU đơn giản nhất có thể. Một chip NVIDIA H100 hiện tại chứa hàng chục ngàn lõi tính toán. Mặc dù mỗi lõi có thể chạy ở tần số thấp hơn lõi CPU và có logic điều khiển yếu, nhưng chúng đều có thể làm việc đồng thời.

Hãy tưởng tượng GPU là một đội hình 100.000 học sinh tiểu học chỉ biết số học. Bạn cho chúng một mệnh lệnh cực kỳ đơn giản: nhân con số bên trái của bạn với con số bên phải của bạn. Tất cả 100.000 học sinh tính toán kết quả đồng thời trên cùng một nhịp clock. Đối với các thao tác ma trận song song hàng loạt mà các mô hình lớn yêu cầu, GPU hiệu quả gấp hàng trăm đến hàng nghìn lần so với CPU.

Thực ra, AI – giống như bộ cộng của CPU – không thực sự huyền bí đến vậy. Nó vẫn chỉ là từng lớp logic và ma trận. Nếu bạn muốn xây dựng hiểu biết về học sâu từ đầu, tôi khuyên một cuốn sách mà nhiều người trên Twitter đã khen ngợi đã hoàn toàn khử bí cho AI: Deep Learning with Python. Khi bạn tự hiểu được các tính toán tensor trong lan truyền tiến và lan truyền ngược, bạn sẽ nhận ra rằng không có phép thuật nào bên trong các mô hình lớn cả.

Sau khi đọc cuốn sách này, tôi đã hoàn toàn khử bí về AI!

Trở lại phần cứng. Khi chúng ta tối ưu giải thuật cấp thấp, phần lớn công sức chúng ta dành để đánh nhau với băng thông VRAM. Đây cũng là nơi nhiều lập trình viên trình độ cao bị vấp.

Bởi vì ALU tính toán quá nhanh. Như đã đề cập trước đó, các module bộ nhớ lưu trữ dữ liệu bằng cách nạp và xả tụ điện, và chúng ở một khoảng cách vật lý nhất định khỏi CPU hoặc GPU – các tín hiệu điện cần thời gian để di chuyển trên bo mạch chủ. Thách thức lớn nhất mà các chip AI phải đối mặt ngày nay là điều mà giới học thuật gọi là nút cổ chai von Neumann.

Nghĩa là: hàng nghìn lõi tính toán kết thúc xử lý dữ liệu trong tay trong chớp mắt, và sau đó chúng chỉ có thể ngồi không, chờ dữ liệu mới được di chuyển từ bộ nhớ chậm. Ngay cả nếu bạn làm cho các mạch tính toán trên chip nhanh hơn, nếu bạn không thể nạp dữ liệu đủ nhanh, sức mạnh tính toán sẽ bị lãng phí.

Để giải quyết vấn đề này, các kỹ sư phần cứng đã bị đẩy đến cực điểm. Vì các module bộ nhớ thông thường quá xa và quá chậm, tại sao không đóng gói bộ nhớ và chip GPU trực tiếp trên cùng một bo mạch nền? Để tăng độ rộng kênh truyền dữ liệu, thay vì sử dụng các dây dẫn truyền thống, họ sử dụng công nghệ gọi là bộ xen silicon – khoan hàng ngàn lỗ dẫn điện vi mô bên trong silicon để kết nối trực tiếp bộ nhớ và các lõi tính toán. Đây là thứ được gọi là Bộ nhớ Băng thông Cao, hay HBM.

Nếu phần này gây hứng thú sâu sắc cho bạn và bạn muốn đảm bảo một mức lương cao không thể thay thế với tư cách kiến trúc sư hoặc nhà phát triển cấp thấp trong kỷ nguyên AI sắp tới, tôi rất khuyên bạn nên đọc Computer Architecture: A Quantitative Approach. Cuốn sách này được viết bởi hai người đoạt giải Turing, và hầu như mọi kỹ sư phần cứng ở Thung lũng Silicon đều có một bản. Nó sử dụng khối lượng lớn dữ liệu thực tế và công thức để cho bạn biết tại sao chip phải được thiết kế với các kiến trúc bộ nhớ đệm cụ thể và chính xác nút cổ chai trong song song đa lõi nằm ở đâu. Mặc dù đọc vô cùng khô khan, và một số chương rất khó xử, nhưng đó là con đường cần thiết để vượt qua khoảng cách nhận thức trong hiểu biết cấp thấp.

Trở lại câu hỏi ban đầu của bạn. Tại sao bạn vẫn cảm thấy bối rối sau khi học tất cả những thuật ngữ này? Bởi vì giáo dục truyền thống cắt đứt mối liên hệ sống động giữa các thực thể vật lý và các trừu tượng logic.

Khi bạn coi CPU như một hộp đen kỳ diệu, những thuật ngữ đó có cảm giác như các định nghĩa khó hiểu. Nhưng nếu bạn đi theo các định luật vật lý đi lên:

  • Bởi vì điện áp cao và thấp có thể tạo thành các cổng logic, chúng ta có các đơn vị tính toán có thể làm toán.
  • Bởi vì các mạch phản hồi có thể khóa các trạng thái điện áp, chúng ta có các thanh ghi có thể lưu trữ dữ liệu.
  • Bởi vì chúng ta cần điều khiển nhịp nhàng dòng chảy của các tín hiệu điện, chúng ta có các bộ dao động tinh thể và các bộ điều khiển.
  • Bởi vì hệ thống này quá phức tạp để con người trực tiếp nhập các mức điện áp, chúng ta đã phát minh ra các tập lệnh, gói 0 và 1 vào hợp ngữ, và cuối cùng vào C và Python.

Là một người hành nghề đã trải qua thăng trầm trong ngành này, tôi có thể nói với bạn một cách rất trách nhiệm: trong kỷ nguyên này, các framework frontend đến rồi đi, các kiến trúc microservice backend thịnh hành vài năm, và thậm chí các kiến trúc mô hình AI lớn cũng đang phát triển với tốc độ chóng mặt. Nhiều kỹ thuật phát triển ứng dụng cấp cao bạn học hôm nay có thể trở nên lạc hậu vào năm sau. Trên thực tế, chính các mô hình lớn đã có thể thực hiện nhiều tác vụ code cơ bản tốt hơn lập trình viên trung bình.

Nhưng điều duy nhất không bao giờ thay đổi là tập hợp các nguyên lý hoạt động cơ bản của máy tính bắt nguồn từ vật lý bán dẫn. Bất kể phần mềm được trừu tượng hóa như thế nào, bất kể giải thuật có tinh vi đến đâu, tất cả cuối cùng đều quy về những biến động điện áp trên một miếng silicon. Sự tối ưu hiệu suất càng cao, việc điều phối tính toán càng tiên tiến, các kỹ sư càng cần khả năng nhìn thấu tất cả các lớp trừu tượng phần mềm và cảm nhận trực tiếp trạng thái hoạt động của phần cứng bên dưới.

Đừng nghĩ rằng kiến thức cấp thấp này xa vời với bạn. Khi bạn gặp một đoạn code ngốn tài nguyên cực kỳ, và bởi vì bạn hiểu cơ chế các dòng bộ nhớ đệm ở cấp thấp nhất, bạn điều chỉnh cách bố trí các mảng trong bộ nhớ để cải thiện đáng kể tỷ lệ truy cập bộ nhớ đệm CPU – làm cho code chạy nhanh gấp mười lần – vào lúc đó, bạn sẽ cảm thấy cảm giác kiểm soát to lớn đến từ việc nắm vững các nguyên lý cơ bản.