Lập trình Python Machine learning Mojo
Nguyễn Nhân  

Ngôn ngữ lập trình Mojo🔥: Python++ nhanh hơn Python tùy theo tác vụ đến 68.000 lần

Ngôn ngữ lập trình Mojo dù chỉ mới ra mắt chưa được 1 năm, nhưng đến nay đã nhận được sự chú ý của cộng đồng lập trình viên và nhận nhiều phản hồi tích cực. Dù tiếp xúc chưa được lâu, nhưng với những gì cảm nhận được thì đây là một ngôn ngữ lập trình đáng được quan tâm trong vòng 10 năm tới.

Bài viết này sẽ tập trung vào việc đo hiệu suất của ngôn ngữ lập trình Mojo, để xem thực tế chính xác đến đâu nhé. Bạn cũng đừng bỏ qua bài viết Tại sao nên học Python nhé.

Nội dung chính

Sơ lược về ngôn ngữ lập trình Mojo

Ngôn ngữ lập trình Mojo là gì

Ngôn ngữ lập trình Mojo được phát triển bởi công ty Modular, có cú pháp tương tự như Python và đạt hiệu cao hơn Python nhiều lần như C. Ban đầu họ hướng đến ngôn ngữ lập trình dành cho lập trình AI, nhưng ở thời điểm hiện tại thì đã trở thành ngôn ngữ lập trình cho những mục tiêu chung.

Ngôn ngữ lập trình Mojo khá dễ học do tương đồng với ngôn ngữ lập trình Python và được xem là Python++ nên sẽ giúp rút ngắn khoảng cách của những người nghiên cứu AI (thường sử dụng Python) đến phát triển sản phẩm (Python khá chậm và đòi hỏi nhiều tối ưu để sản phẩm đạt hiệu suất tốt)

Những đặc tính của ngôn ngữ lập trình Mojo

  • Sử dụng được các thư viện Python (numpy, pandas, …): sử dụng thông Cython nên có thể dùng được hầu hết các thư viện này. Tuy nhiên, theo kết quả đo hiệu suất bên dưới, thì việc sử dụng các thư viện này không mang lại kết quả tốt về hiệu suất mong muốn.
  • Sử dụng được cú pháp Python: Bạn hoàn toàn có thể sử dụng code Python trong Mojo, tuy nhiên việc sử dụng Python trong Mojo không nên ưu tiên nếu quan tâm đến hiệu suất.
  • Cú pháp tương tự Python: phong cách viết tương tự Python, tuy nhiên thuần Mojo thì sẽ khắt khe trong type-checker
  • Chạy đa luồng: Mojo sử dụng hạ tầng biên dịch (MLIR) để hỗ trợ nhiều loại phần cứng, bao gồm GPU chạy CUDA và phần cứng tương tự, mà không làm tăng thêm sự phức tạp trong lập trình.

Những điểm còn thiếu sót của ngôn ngữ lập trình Mojo

  • Chưa hỗ trợ Mac Intel, Window và các hệ Linux khác ngoài Ubuntu
  • Còn xa để đạt được mức tập cha (superset) của Python
  • Rất ít các thư viện hỗ trợ
  • Chưa có dependencies management: làm gì có thư viện khác mà đòi quản lý :))

Bạn có thể xem những vấn đề đang tồn tại: https://docs.modular.com/mojo/roadmap#mojo-sdk-known-issues

Cha đẻ của Mojo: Chris Latter

Thật thiếu sót nếu không nói về cha đẻ của ngôn ngữ lập trình Mojo: Chris Latter – người cũng là tác giả của trình biên dịch LLVM. Đồng thời ông cũng là người tạo ra MLIR – compiler stack thế hệ tiếp theo, và Mojo được thiết kế để biên dịch trên MLIR, đó cũng có thể là lý do vì sao Mojo nhanh hơn Rust (Rust và Swift được xây dựng trên nền tảng LLVM). Người sáng lập ngôn ngữ lập trình cũng là người tham gia vào quá trình thiết kế compiler, vì vậy ông rất am hiểu về cách vận hành của các chip cũng như trình biên dịch tương ứng. Đó cũng là ưu thế rất lớn để phát triển ngôn ngữ lập trình Mojo trở thành ngôn ngữ của thập niên tiếp theo – đặc biệt là trong mảng lập trình AI.

So sánh hiệu suất với Python

Môi trường

Công cụ được sử dụng đo hiệu suất: Hyperfine (https://github.com/sharkdp/hyperfine)
Hàm sử dụng: Fibonacci (thuật toán không tối ưu)
Cấu hình máy chính: 2.4 GHz 8-Core Intel Core i9
Cấu hình docker: RAM 8GB, max 200% CPU

Cài đặt Mojo

Cài đặt ngôn ngữ lập trình Mojo chỉ mới dành cho MacOS Apple, và Ubuntu. Với các máy khác có thể sử dụng docker. Chi tiết cho từng phiên bản thì bạn tham khảo ở đây:

https://docs.modular.com/mojo/manual/get-started/

Việc cài đặt cũng không mất nhiều thời gian và khó khăn gì cả nên mình không bổ sung gì thêm.

Code

# fibonacci.mojo
# Fibonacci thuần mojo
import sys
fn fibonacci(n: Int) -> Int:
    if n == 0 or n == 1:
        return n
    else:
        return fibonacci(n - 2) + fibonacci(n - 1)


fn main():
    try:
        print(fibonacci(atol(sys.argv()[1])))
    except:
        pass
# fibonacci_python_style_no_type_annotation.mojo
# Fibonacci không  type-annotation với code kiểu Python
import sys
def fibonacci(n):
    if n == 0 or n == 1:
        return n
    else:
        return fibonacci(n - 2) + fibonacci(n - 1)

fn main():
    try:
        print(fibonacci(atol(sys.argv()[1])))
    except:
        pass
# fibonacci_python_style_with_type_annotation.mojo
# Fibonacci  type-annotation với code kiểu Python
import sys
def fibonacci(n: Int) -> Int:
    if n == 0 or n == 1:
        return n
    else:
        return fibonacci(n - 2) + fibonacci(n - 1)

fn main():
    try:
        print(fibonacci(atol(sys.argv()[1])))
    except:
        pass
# fibonacci.py
# Fibonacci không  type-annotation (Python)
import sys

def fibonacci(n):
    if n == 0 or n == 1:
        return n
    else:
        return fibonacci(n - 2) + fibonacci(n - 1)

def main():
    print(fibonacci(int(sys.argv[1])))

main()
vscode/workspaces/ubuntu $ hyperfine "mojo fibonacci.mojo 40"
Benchmark 1: mojo fibonacci.mojo 40
  Time (mean ± σ):     700.7 ms ±  16.8 ms    [User: 431.9 ms, System: 19.5 ms]
  Range (minmax):   677.3 ms735.1 ms    10 runs
 
vscode/workspaces/ubuntu $ hyperfine "mojo fibonacci_python_style_with_type_annotation.mojo 40"
Benchmark 1: mojo fibonacci_python_style_with_type_annotation.mojo 40
  Time (mean ± σ):      1.202 s ±  0.012 s    [User: 0.927 s, System: 0.021 s]
  Range (minmax):    1.184 s1.217 s    10 runs
 
vscode/workspaces/ubuntu $ hyperfine "mojo fibonacci_python_style_no_type_annotation.mojo 40"
Benchmark 1: mojo fibonacci_python_style_no_type_annotation.mojo 40
  Time (mean ± σ):     15.129 s ±  3.435 s    [User: 14.793 s, System: 0.059 s]
  Range (minmax):   10.228 s19.135 s    10 runs
 
vscode/workspaces/ubuntu $ hyperfine "python3 fibonacci.py 40"
Benchmark 1: python3 fibonacci.py 40
  Time (mean ± σ):     44.586 s ±  3.859 s    [User: 44.502 s, System: 0.033 s]
  Range (minmax):   37.771 s51.637 s    10 runs
 
vscode/workspaces/ubuntu $ hyperfine "./fibonacci 40"
Benchmark 1: ./fibonacci 40
  Time (mean ± σ):     350.3 ms ±   5.5 ms    [User: 346.5 ms, System: 2.4 ms]
  Range (minmax):   340.9 ms358.6 ms    10 runs
 
vscode/workspaces/ubuntu $ hyperfine "./fibonacci_python_style_no_type_annotation 40"
Benchmark 1: ./fibonacci_python_style_no_type_annotation 40
  Time (mean ± σ):     10.667 s ±  0.872 s    [User: 10.650 s, System: 0.007 s]
  Range (minmax):    9.323 s11.830 s    10 runs
 
vscode/workspaces/ubuntu $ hyperfine "./fibonacci_python_style_with_type_annotation 40"
Benchmark 1: ./fibonacci_python_style_with_type_annotation 40
  Time (mean ± σ):     831.7 ms ±  11.5 ms    [User: 827.4 ms, System: 2.5 ms]
  Range (minmax):   814.2 ms852.2 ms    10 runs

Kết quả so sánh

MinMaxMeanHiệu suất
Python thuần37.771 (s)51.637(s)44.586(s)N/A
Mojo phong cách Python10.228(s)19.135(s)15.129(s)x3
Mojo phong cách Python có type-annotation1.184(s)1.217(s)1.202(s)x37
Mojo thuần677.3(ms)735.1 (ms)700.7(ms)x75
Mojo phong cách Python [compiled]9.323(s)11.830(s)10.667(s)x3
Mojo phong cách Python có type-annotation [compiled]814.2(ms)852.2(ms)831.7(ms)x55
Mojo thuần [compiled]340.9(ms)358.6(ms)350.3(ms)x127
Hiệu suất thực tế của ngôn ngữ lập trình Mojo theo từng cách viết so sánh với Python.

Bonus

Với phiên bản Python thuần, nếu bạn tối ưu bằng decorator cache thì tốc độ cũng cải thiện rất nhiều, tuy nhiên Mojo chưa hỗ trợ decorator này nên chưa so sánh được.

import sys
from functools import cache

@cache
def fibonacci(n):
    if n == 0 or n == 1:
        return n
    else:
        return fibonacci(n - 2) + fibonacci(n - 1)

def main():
    print(fibonacci(int(sys.argv[1])))

main()
vscode/workspaces/ubuntu $ hyperfine "python3 fibonacci_with_cache.py 40"
Benchmark 1: python3 fibonacci_with_cache.py 40
  Time (mean ± σ):      14.0 ms ±   1.1 ms    [User: 11.6 ms, System: 2.2 ms]
  Range (minmax):    12.7 ms19.3 ms    159 runs
 

Kết luận

Nhanh hơn Python 68.000 lần?

Without a parallel Python implementation, It would be more fair to claim that Mojo is 874 times faster than a naive CPython implementation, 175 times faster than a (rather naive) Numpy code, and 40 times faster than a PyPy implementation (on this specific Mandelbrot set computation).

StackOverflow

Mặc dù con số 68.000 lần là thực tế từ kết quả, tuy nhiên đây chỉ là con số mang tính chất biểu tượng/marketing là chính chứ không có tác dụng trong thực tế nhiều lắm.

  • Mojo là ngôn ngữ multi-threaded chứ không có chạy tuần tự, nên một số tác vụ tính toán có thể hưởng lợi
  • Sử dụng tính toán vector, lại là về tính toán con số; numpy có thực hiện tính toán vector nên vẫn ổn
  • Sử dụng chiến thuật thực thi song hành (parallel) trên con CPU khủng 88-Core Intel Xeon

Bạn có thể đọc thêm cách đo hiệu suất trong 3 bài viết từ blog của Modular có gắn kèm bên dưới.

Bài toán thực tế

Với kết quả từ thực nghiệm ở trên với hàm Fibonacci (một hàm thường được dùng cho việc tính hiệu suất vì có dùng đệ quy), có thể kết luận việc sử dụng ngôn ngữ lập trình Mojo có thể nhanh hơn Python khoảng 100 lần. Đây là con số khá hấp dẫn trong việc chọn lựa với những hệ thống yêu cầu tốc độ. Với những người yêu thích tốc độ như mình thì khó có thể cưỡng lại được 😀

Tốc độ đến từ ngôn ngữ biên dịch và type-checked cũng là điều dễ hiểu, ngoài ra kết hợp tính toán vector, multi-thread thì ngôn ngữ lập trình Mojo có thể còn phát huy được nhiều ứng dụng khác. Về điểm này thì chúng ta nên so sánh với Golang mới đúng, hi vọng sẽ có thời gian để viết bài so sánh với Golang.

Fullstack Station Tips:

  • Không khuyến khích dành cho người mới học lập trình, khuyến khích dành cho người đã biết Python
  • Mặc dù có thể sử dụng cú pháp Python, nhưng với kết quả kiểm tra hiệu suất thì rõ ràng không nên sử dụng cú pháp Python nếu muốn có hiệu suất cao, chí ít cũng phải có type-annotation (xem thêm MyPy là gì). Tốt nhất cũng là sử dụng ngôn ngữ lập trình Mojo thuần để cho tốt độ cao nhất.
  • Tuy tuổi đời còn ít, nhưng với những thành tựu đã đạt được thì ngôn ngữ lập trình Mojo sẽ còn phát triển nhanh và xa. Đặc biệt là rút ngắn khoảng cách từ nghiên cứu đến phát triển sản phẩm AI.
  • Vì chưa trưởng thành, nên nhiều cú pháp sẽ bị thay đổi, không nên sử dụng ngôn ngữ lập trình cho sản phẩm thực tế.
  • Với những lợi ích mà ngôn ngữ lập trình Mojo mang lại, mình nghĩ sẽ rất có lợi cho bạn ở tương lai gần khi học Mojo. Giống như lập trình viên Golang, là một ngôn ngữ lập trình cho bạn mức thu nhập rất tốt.

Tham khảo:

  • https://www.modular.com/blog/how-mojo-gets-a-35-000x-speedup-over-python-part-1
  • https://www.modular.com/blog/how-mojo-gets-a-35-000x-speedup-over-python-part-2
  • https://www.modular.com/blog/mojo-a-journey-to-68-000x-speedup-over-python-part-3
  • https://dev.classmethod.jp/articles/try-mojo-programming-langurage/
  • https://stackoverflow.com/questions/77070883/performance-comparison-mojo-vs-python
  • https://augierpi.gricad-pages.univ-grenoble-alpes.fr/mojo-the-point-of-view-of-a-researcher-using-python.html

Comments

Leave A Comment