11/08/2018, 21:00

Giới thiệu về thread từ phần cứng ra phần mềm.

Không gì đẹp bằng nụ cười khi đôi mắt e lệ nhìn xuống. -- Victor Hugo Các bạn có thể đọc bài viết gốc tại đây Tò mò khi tìm hiểu hoạt động của thread như thế nào trong lập trình single thread và multi thread, mình tranh thủ tìm hiểu luôn các thread này hoạt động như thế nào trong CPU. ...

Không gì đẹp bằng nụ cười khi đôi mắt e lệ nhìn xuống.

-- Victor Hugo

Các bạn có thể đọc bài viết gốc tại đây

Tò mò khi tìm hiểu hoạt động của thread như thế nào trong lập trình single thread và multi thread, mình tranh thủ tìm hiểu luôn các thread này hoạt động như thế nào trong CPU.

a, Sơ lược về bộ nhớ.

  • Bộ nhớ ngoài: là ổ cứng của bạn, ở đây lưu trữ những tệp tin, video, nhạc,...

  • Bộ nhớ trong(RAM): khi nói tới bộ nhớ là mặc định nói tớ bộ nhớ trong, là bộ nhớ để load dữ liệu từ bộ nhớ ngoài lên RAM khi chạy một chương trình cho CPU truy xuất. RAM có tốc độ truy xuất nhanh hơn bộ nhớ ngoài.

  • Bộ nhớ cache: là bộ nhớ nằm trong CPU, được load từ RAM lên, giúp cho các phép toán trong CPU truy xuất dữ liệu nhanh hơn nữa. Bộ nhớ này lại nhanh hơn RAM nhiều.

Vì sao nhà sản xuất không làm máy tính có bộ nhớ tốt nhất từ đầu tới cuối đi mà phải phân loại ra nhiều loại như vậy?

Vì làm thế thì giá của máy tính sẽ đắt hơn rất nhiều ít người mua nổi.

b, Liên quan tới phần lõi máy tính (CPU)

  • 1 processor là 1 bo mạch vật lý, 1 processor có thể là 1 CPU, 1 CPU core hoặc 1 processor có thể được thiết kết để tích hợp nhiều CPU trên nó. Nói chung nó là một bo mạch vật lý.

  • Core là đơn vị tính toán cơ bản nhất của máy tính, 1 core sẽ thực hiện 1 phép toán số học(cộng, trừ, so sánh 2 số hoặc lấy giá trị) ở một thời điểm. Máy tính chúng ta đang dùng, chương trình chúng ta đang chạy tất cả đều là phép tính số học đối với máy tính.
    Ngày xưa 1 core chỉ thực hiện được một phép toán số học trên một đơn vị clock cycle(xem clock cycle là gì bên dưới), nhưng với thiết kết hyperthread của intel thì hiện tại 1 core có thể thực hiện được 2 hoặc nhiều phép toán số học trong một clock cycle. 1 core là 1 đơn vị vật lý nhưng với thiết kế hyperthread thì 1 core có thể được chia thành 2 đơn vị vật lý ảo(2 core ảo nhưng thực chất chúng chỉ nằm trên 1 đơn vị vật lý).

  • Clock cycle là thời gian giữa 2 tín hiệu xung nhịp trong 1 core. Khi chúng ta đi mua máy tính, để ý có thông số ví dụ như "CPU: Intel Core i3 350M at 2.27GHz, dual core with hyperthreading" nghĩa là máy tính đó có 1 CPU với 2 core, mỗi core đều có thiết kế hyperthreading (hyperthread vừa giải thích ở trên) và con số 2,27Ghz(số này gọi là clock speed) nghĩa là mỗi core có tốc độ xử lý xung nhịp là 2,27 tỉ xung nhịp (clock cycle) trên một giây.
    Trong 1 clock cycle, số phép toán được tính toán càng nhiều thì máy tính đó càng nhanh (cái này là nhìn từ cpu chứ nhìn từ người dùng thì còn phụ thuộc vào nhiều yếu tố khác nữa).
    1 CPU có thể có 1 core hoặc nhiều core, máy tính ngày nay thường có 1 CPU và có nhiều core trên CPU đó.

=> Tất cả những khái niệm phía trên là những khái niệm liên quan tới phần cứng.
alt text

c, Multiprogramming, multitasking, multithreading và multiprocessing?

  • Multiprogramming là khái niệm liên quan tới phần mềm, nghĩa là nhiều phần mềm có thể chạy đồng thời với 1 CPU(nói 1 CPU là tương đương với nói 1 CPU core), tuy nói là chạy đồng thời nhưng vì cpu core chỉ thực hiện được 1 phép toán ở một thời điểm nên thật ra là có khoảng thời gian rất nhỏ giữa các lần chuyển các phép toán của các phần mềm, vì khoảng thời gian này rất nhỏ nên khiến người ta nghĩ là các tiến trình đó chạy đồng thời.
    Multiprogramming là khái niệm liên quan tới phần mềm, là thuật ngữ được dùng với máy tính ngày xưa, lúc đó khi load chương trình từ bộ nhớ ngoài lên RAM thì load toàn bộ chương trình. Khái niệm này đã lỗi thời đối với máy tính ngày nay.

  • Multitasking thay thế cho khái niệm multiprogramming đối với máy tính ngày nay, trong các máy tính multitasking, khi load chương trình vào RAM thì sẽ load từng đoạn chương trình và được phân trang chứ không phải load toàn bộ chương trình.

  • Multithreading là khái niệm liên quan tới phần mềm, nghĩa là một phần mềm có thể có nhiều phiên hoạt đông cùng khi. Ví dụ như bạn có 2 request tới server web PHP của bạn thì apache sẽ đẻ ra 2 thread để phục vụ 2 request đó cùng khi (giải thích rõ hơn ở phần 2), 2 thread này sẽ được phục vụ đồng thời trong CPU.

  • Multiprocessing: khác với những khái niệm liên quan tới phần mềm ở trên, multiprocessing là khái niệm liên quan phần cứng, nghĩa là máy tính có nhiều processor(cpu hoặc core) thì có thể phục vụ được nhiều process(tiến trình) cùng lúc.

Thế khi cpu có nhiều core thì các tiến trình sẽ được chạy trên core nào?

  • cpu có 1 core:
    alt text
    Ở một thời điểm, cpu core chỉ thực hiện được 1 phép toán thôi nên tính theo thời gian thực thì 4 chương trình trên không phải là chạy đồng thời. Nhưng do thời gian thực hiện những phép toán và thời gian chuyển qua lại của các phép toán giữa các chương trình là rất nhỏ nên xem nó là chạy đồng thời.

  • cpu có 2 core trở lên:
    alt text
    Các tiến trình sẽ được phân phối cho các CPU, còn phân phối như thế nào là do bản thân hệ điều hành.

Single thread chỉ sử dụng một cpu core

n thread sử dụng tương ứng n core trong cpu, nếu số thread lớn hơn số core cpu thì hệ điều hành sẽ phân phối các thread này qua lại cho nhau.

a, Lập trình multi thread

Khi lập trình web, 90% thời gian người dùng phải chờ không phải là thời gian xử lý của CPU mà là thời gian chờ cho các truy xuất I/O (truy xuất dữ liệu, đọc ghi file,...). Mỗi khi có một request từ người dùng tới web của bạn thì sẽ có các truy xuất I/O cần thiết, mỗi khi có truy xuất I/O này chương trình của bạn sẽ bị block(dừng lại) chờ cho truy xuất I/O đó có kết quả trả về mới thực hiện tiếp được các đoạn lệnh tiếp theo(gọi là xử lý đồng bộ - chạy theo thứ tự từ trên xuống dưới- synchronous).

Thế khi có nhiều request đến cùng một lúc thì làm sao web của bạn có thể phục vụ được các request đó và trả về đồng thời cùng lúc cho người dùng được(vì hiện tại 1 request nào đó đang chạy và đang đợi I/O chưa xong). Vì có multi thread, khi có nhiều request tới server web của bạn (apache) thì apache sẽ đẻ ra cho mỗi request một thread, mỗi thread này sẽ đảm nhiệm xử lý một request nên các request đến đồng thời luôn được phục vụ cùng một lúc.

Nhược điểm của multi thread là khi đẻ ra một thread thì sẽ phải tiêu tốn mất một dung lượng RAM để cấp phát cho thread đó, nên những chương trình tiêu tốn quá nhiều RAM thì không nên multi thread.

b, Lập trình single thread

Ví dụ điển hình cho lập trình single thread đó là nodejs. Vì sao nodejs chỉ có một thread nhưng lại có thể xử lý đồng thời nhiều request của người dùng đến thế được? Để hiểu rõ được lý do thì bạn phải hiểu được cơ chế hoạt động của nodejs, nói cơ bản thì nodejs là chạy asynchronous với các lời gọi I/O nên khi có lời gọi I/O thì chương trình sẽ không bị block mà chạy tiếp các câu lệnh tiếp theo. Như đã nói ở trên thì các lời gọi I/O chiếm tới 90% thời gian nên các câu lệnh tiếp theo không bị block được thực hiện rất nhanh(vì là thời gian thực hiện của CPU), do đó các request đến sau sẽ được thực hiện rất nhanh trên cùng thread của nodejs. Các bạn có thể đọc bài cơ chế hoạt động của javascript và nodejs để hiểu rõ hơn.

Có một điểm lưu ý là tuy nói nodejs là single thread nhưng nó chỉ single với main thread(thread để chạy những câu lệnh của nó) thôi, còn các lời gọi I/O thực chất vẫn là đẻ ra các thread khác để thực hiện các yêu cầu I/O này. Các I/O async này là các thread chạy trên cpu core khác với main thread của nodejs.

Nhược điểm của lập trình single thread đó là khi chương trình của bạn tiêu tốn quá nhiều thời gian chạy CPU, vì như thế sẽ khiến các request đến sau phải chờ lâu hơn. Và còn một nhược điểm nữa là nodejs chỉ sự dụng được 1 CPU core thôi nên nếu để các core khác rảnh thì hơi phí(tuy nó cũng chả có mấy khi rảnh đâu :))))

Có điểm cần chú ý là tuy apache là webserver chạy multi thread nhưng nginx mặc định lại là single thread. Nginx cũng tạo ra các lời gọi I/O không bị block như nodejs. Bạn có thể cấu hình cho nginx tạo ra nhiều thread, mỗi thread này lại có thể xử lý được nhiều request đồng thời giống nodejs nhưng được khuyến cáo là bạn nên cấu hình cho nginx đẻ ra số thread nhiều nhất bằng với số lượng cpu core có trong máy tính (vì mỗi thread sử dụng một core mà :)))

https://stackoverflow.com/questions/19225859/difference-between-core-and-processor
http://searchwindowsserver.techtarget.com/definition/clock-cycle
http://www.8bitavenue.com/2012/10/difference-between-multiprogramming-multitasking-multithreading-and-multiprocessing/
http://www.ni.com/white-paper/6424/en/
https://stackoverflow.com/questions/34855352/how-in-general-does-node-js-handle-10-000-concurrent-requests
https://stackoverflow.com/questions/3211936/threads-vs-cores
https://stackoverflow.com/questions/5200821/grasping-the-node-js-alternative-to-multithreading
https://stackoverflow.com/questions/4764731/nginx-its-multithreaded-but-uses-multiple-processes

0