Phân biệt tác vụ I/O và tác vụ chuyên sâu CPU

Phân biệt tác vụ I/O và tác vụ chuyên sâu CPU

Tin ngắn hàng ngày dành cho bạn
  • Mấy hôm trước OpenAI giới thiệu Deep Research - một công cụ duyệt web để nghiên cứu và cho ra một bản tổng hợp chỉ trong vài chục phút - so với nhiều giờ làm việc đối với con người, theo như họ công bố.

    Tính năng này hiện chỉ có sẵn cho người dùng Pro. Mặc dù chưa được dùng thử, nhưng qua nhiều bài viết đều nhấn mạnh vào sự ấn tượng trước khả năng của công cụ mới này. Nếu vẫn chưa biết Deep Research làm được gì thì bạn cứ hình dung như thế này: Nói với nó "Tôi cần thông tin nghiên cứu về lượng tiêu thụ cà phê của thế giới trong năm ngoái". Thế thôi! Ngồi chờ một lúc để nó tìm kiếm và tổng hợp lại kết quả và gửi lại cho bạn một bài báo cáo chi tiết. Chà, ghê thật chứ!

    Ngay lập tức huggingface đã lên một bài viết cố gắng tái tạo lại công cụ này theo cách của họ. Chi tiết tại Open-source DeepResearch – Freeing our search agents. Và không có gì ngạc nhiên khi cả 2 đều mang hơi hướng của AI Agents.

    » Xem thêm
  • Sống đủ lâu trong thế giới Internet, bạn có thể thấy rằng mọi người ở đây khá háo hức chạy theo xu hướng và chúng lan truyền với tốc độ chóng mặt.

    Chỉ vài tháng trước, chúng ta vẫn còn kinh ngạc về trí thông minh của các mô hình ngôn ngữ lớn (LLM) có thể trả lời giống như con người, và ngay sau đó, chúng đã được cập nhật với khả năng suy nghĩ và lý luận đáng kinh ngạc. Chúng được ứng dụng rộng rãi không chỉ trong lĩnh vực lập trình. Gần đây, thuật ngữ AI Agents đã tạo nên một sự khuấy động.

    Vậy, AI Agents là gì? Trong bài viết ngắn này, tất nhiên là không thể đưa ra một định nghĩa ngắn gọn nhưng toàn diện. Bạn đọc có thể tham khảo bài viết rất chi tiết này tại đây Agents | Chip Huyền. Để dễ hình dung hơn, AI Agents có thể được coi là một người hoặc một thực thể nào đó. Bản thân các Agents được trang bị tất cả các công cụ cần thiết. Từ đó, các Agents có thể kết hợp chúng để hoàn thành một nhiệm vụ mà chúng ta giao.

    Vẫn còn hơi mơ hồ phải không? Một ví dụ thực tế là khi bạn ra lệnh cho các Agents truy cập Facebook vào lúc 8 giờ tối mỗi ngày, kiểm tra bất kỳ tin tức nổi bật nào từ bạn bè, sau đó gửi tóm tắt đến Telegram. Vậy là xong!

    » Xem thêm
  • Hôm qua đến nay, lượt truy cập tới từ Facebook tăng đột biến. Thường như thế là do ai đó chia sẻ bài viết của blog vào một nhóm nào đó.

    Cơ mà lần này là liên kết trực tiếp đến trang chủ luôn. Tò mò ghê, không biết ai chia sẻ, chia sẻ ở đâu nữa. Muốn biết để tìm hiểu "insight" ghê 🥹

    » Xem thêm

Vấn đề

Là một lập trình viên Node.js đã bao giờ bạn nghe đến thế mạnh của Node.js là xử lý các tác vụ I/O và không đồng bộ, rằng Node.js không phải là lựa chọn tốt nhất cho các ứng dụng thiên về khả năng khai thác triệt để sức mạnh CPU? Vậy thì tác vụ I/O là gì và tại sao Node.js lại mạnh về I/O? Việc nói Node.js không thực sự tốt với các phép tính lớn là có đúng không. Bài viết ngày hôm nay tôi sẽ dành thời gian nói về vấn đề nêu trên.

Tác vụ I/O là gì?

I/O (Input/Output) đề cập đến sự tương tác của máy tính hay chương trình máy tính với ổ đĩa (disk) và mạng của hệ thống. Ví dụ các hoạt động I/O bao gồm đọc/ghi dữ liệu từ ổ đĩa, thực hiện các yêu cầu HTTP và tương tác với cơ sở dữ liệu. Chúng rất chậm so với việc truy cập bộ nhớ RAM hoặc các phép tính được thực hiện trên CPU.

V8 xử lý mã Javascript như thế nào

Chúng ta biết rằng Node.js sử dụng V8 của Chrome để thực thi mã Javascript có điều với sức mạnh của V8 cũng phải chào thua trước I/O bởi chúng không hoàn toàn phụ thuộc vào tốc độ xử lý của CPU như tốc độ đọc/ghi của ổ đĩa, tốc độ của mạng... Nếu I/O được xử lý trên V8 nó sẽ gây ra một cuộc tắc nghẽn nghiêm trọng vì mất quá nhiều thời gian, chính vì thế Node.js phải tìm ra một giải pháp để tận dụng được sức mạnh của V8 mà vẫn phải xử lý được I/O.

Giải pháp của Node là lựa chọn libuv cho xử lý I/O không đồng bộ. Đây là thư viện C đa nền tảng cung cấp hỗ trợ cho I/O không đồng bộ dựa trên các vòng lặp sự kiện (Event Loop).

V8 + libuv Node.js

Luồng chính gặp các tác vụ I/O sẽ đẩy chúng xuống libuv, kết quả được đưa trở lại cho luồng chính thông qua Event Loop. Cứ như thế tạo nên một vòng lặp vô hạn mà luồng chính không bị chặn bởi I/O nữa.

Trong Node.js có khái niệm worker, chúng có nhiệm vụ chuyển các yêu cầu I/O từ luồng chính đến libuv và chờ nhận phải hồi, trong thời gian đó chúng không phải làm gì khác và có thể bị hệ điều hành huỷ lập lịch (de-scheduled) để cho một worker khác gửi yêu cầu. Do đó các tác vụ I/O được worker chuyển vào từ trước vẫn được xử lý ngay cả khi luồng liên kết không chạy.

Hệ điều hành đã tối ưu các công cụ quản lý tệp và cơ sở dữ liệu cũng được tối ưu hoá cao để xử lý đồng thời nhiều yêu cầu chờ xử lý. Ví dụ như sắp xếp lại thứ tự ưu tiên khi có đồng thời nhiều yêu cầu đọc/ghi dữ liệu vào một tệp.

Khi chạy một ứng dụng Node.js bạn sẽ có một số thread pools chuyên dùng để xử lý các yêu cầu I/O. Nhóm luồng này được tạo bởi libuv. Số lượng mặc định của nó là 4 nhưng có thể tăng lên tối đa 128 thông qua biến môi trường UV_THREADPOOL_SIZE.

cấu trúc libuv

Tác vụ chuyên sâu CPU

Là những công việc đòi hỏi nhiều về khả năng tính toán của CPU. Đó có thể là những phép tính phức tạp về mã hoá/giải mã, xử lý hình ảnh, xử lý video... Các worker cũng có thể chuyển những yêu cầu tính toán phức tạp này, lập lịch và xử lý chúng bên ngoài luồng chính. Nhưng chúng chỉ được xử lý khi worker được lập lịch trên một trong các lõi của CPU. Ví dụ nếu CPU của bạn có 4 lõi và bạn tạo ra 5 worker thì một trong những worker này không được tham gia xử lý, trong khi vẫn phải duy trì một nguồn tài nguyên cho nó (bộ nhớ & lập lịch) gây ra tình trạng lãng phí tài nguyên.

mô hình worker thread

Để hiểu rõ hơn về cách Node.js xử lý các task tính toán nặng thông qua Worker Threads tôi khuyên bạn nên đọc bài Worker threads là gì? Bạn đã biết khi nào thì sử dụng Worker threads trong node.js chưa?.

Có thể thấy nếu như luồng chính đưa các tác vụ I/O ra libuv, nó sẽ ngăn chặn được một cuộc tắc nghẽn nghiêm trọng. Trong khi đó, các tác vụ thiên về CPU suy cho cùng sẽ chiếm thời gian xử lý. Giải pháp là tạo ra các child process hoặc worker threads nhưng những giải pháp này còn phụ thuộc vào sức mạnh của phần cứng.

Tổng kết

Với mô hình kiến trúc của Node.js được thiết kế để tận dụng sức mạnh của V8 mà vẫn giải quyết được I/O thế nên Node.js hoàn toàn phù hợp với những bài toán thiên về I/O. Thế nhưng không phải là Node.js không xử lý được những bài toán nặng về tính toán. Bằng cách tạo ra những child process hoặc worker threads trên CPU đa lõi hoàn toàn có thể xử lý mà không chặn luồng chính.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (1)

Nội dung bình luận...
Avatar
Đăng Khoa2 năm trước
Hoá ra v8 để chạy mã js và nó một luồng đúng ko ạ
Trả lời
Avatar
Thành Đỗ2 năm trước
Đúng rồi bác   
Bấm hoặc cuộn mạnh để sang bài mới