Mojo — bahasa pemrograman baru untuk semua pengembang, ilmuwan AI/ML, dan insinyur perangkat lunak.
Daftar kurasi kode Mojo yang mengagumkan, pemecahan masalah, solusi, dan perpustakaan, kerangka kerja, perangkat lunak, dan sumber daya di masa depan.
Mari kumpulkan pengetahuan teknologi baru dan praktik terbaik di sini.
Mojo adalah bahasa pemrograman yang menggabungkan kemudahan penggunaan Python dengan kemampuan kinerja C++ dan Rust. Selain itu, Mojo memungkinkan pengguna untuk memanfaatkan ekosistem perpustakaan Python yang luas.
Secara singkat
Mojo adalah bahasa pemrograman baru yang menjembatani kesenjangan antara penelitian dan produksi dengan menggabungkan sintaksis Python terbaik dengan pemrograman sistem dan metaprogramming.
hello.mojo
atau hello.
ekstensi file bisa berupa emoji!
Anda dapat membaca lebih lanjut tentang mengapa Modular melakukan Mengapa Mojo ini
Yang kami inginkan adalah model pemrograman yang inovatif dan terukur yang dapat menargetkan akselerator dan sistem heterogen lainnya yang banyak digunakan di bidang AI. ... Sistem AI yang diterapkan perlu mengatasi semua masalah ini, dan kami memutuskan tidak ada alasan hal itu tidak dapat dilakukan hanya dengan satu bahasa. Maka lahirlah Mojo.
Tapi Python telah melakukan tugasnya dengan sangat baik =)
Kami tidak melihat adanya kebutuhan untuk berinovasi dalam sintaksis bahasa atau komunitas. Jadi kami memilih untuk menggunakan ekosistem Python karena penggunaannya sangat luas, disukai oleh ekosistem AI, dan karena kami yakin bahasa ini sangat bagus.
Mojo berarti “pesona magis” atau “kekuatan magis”. Kami pikir ini adalah nama yang cocok untuk bahasa yang memberikan kekuatan ajaib pada Python :python:, termasuk membuka model pemrograman inovatif untuk akselerator dan sistem heterogen lainnya yang banyak digunakan dalam AI saat ini.
Guido van Rossum diktator yang baik hati seumur hidup dan Christopher Arthur Lattner penemu, pencipta dan pemimpin terkenal tentang Mojopronunciation =)
Sesuai dengan deskripsi
Siapa tahu bahasa pemrograman ini akan sangat membahagiakan, karena Mojo mendapat manfaat dari pembelajaran luar biasa dari bahasa lain Rust, Swift, Julia, Zig, Nim, dll.
[baru]
Github sekarang mendeteksi kode Mojo secara otomatis!
Kerangka kerja HTTP sederhana dan cepat untuk Mojo! Sempurna untuk membangun layanan web dan API sederhana. Untuk orang Mojician
Kerangka kerja benchmarking implementasi LLama
Terjemahan otomatis kode Python ke Mojo
Penelitian Basis Data Bahasa Pemrograman
19 Oktober 2023 Mojo sekarang tersedia di Mac! Gunakan konsol pengembang
Chris Lattner: Masa Depan Pemrograman dan AI | Podcast Lex Fridman #381
Penjelasan sistem tipe Mojo dan Python | Chris Lattner dan Lex Fridman
Bisakah Mojo menjalankan kode Python? | Chris Lattner dan Lex Fridman
Beralih dari bahasa pemrograman Python ke Mojo | Chris Lattner dan Lex Fridman
Topik GitHub Baru mojo-lang. Jadi Anda bisa mengikutinya.
Guido van Rossum tentang Mojo = Python dengan kinerja C++/GPU?
Struktur tensor dengan beberapa operasi dasar #251
Matriks fn dengan numpy #267
Pembaruan tentang lambda
dan parameter
Penutupan dan fungsi urutan yang lebih tinggi di mojo #244
25 Mei-2023, Guido van Rossum (gvanrossum#8415), pencipta dan emeritus BDFL Python, kunjungi Obrolan Perselisihan publik Mojo
Menunggu penyorotan sintaksis Mojo di GitHub
Rilis Mojo baru 24-05-2023
[tua]
Mojo
brew install hyperfine
brew install macchina
pip3 install numpy matplotlib scipy
brew install silicon
Versi Python / Mojo / Codon / Rust
> python3 --version
Python 3.11.6
> mojo --version
mojo 0.4.0 (9e33b013)
> codon --version
0.16.3
> rustc --version
rustc 1.65.0-nightly (9243168fa 2022-08-31)
Mari kita cari Deret Fibonacci dimana
tidak = 100
def fibonacci_recursion ( n ):
return n if n < 2 else fibonacci_recursion ( n - 1 ) + fibonacci_recursion ( n - 2 )
fibonacci_recursion ( 100 )
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json python_recursion.json ' python3 benchmarks/fibonacci_sequence/python_recursion.py '
HASIL: TIMEOUT, saya membatalkan perhitungan setelah 1m
def fibonacci_iteration ( n ):
a , b = 0 , 1
for _ in range ( n ):
a , b = b , a + b
return a
fibonacci_iteration ( 100 )
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/python_iteration.json ' python3 benchmarks/fibonacci_sequence/python_iteration.py '
HASIL :
Tolok ukur 1: benchmark python3/fibonacci_sequence/python_iteration.py
Waktu (rata-rata ± σ): 16374,7 µs ± 904,0 µs [Pengguna: 11483,5 µs, Sistem: 3680,0 µs]
Rentang (min … maks): 15361,0 µs … 22863,3 µs 100 kali berjalan
python3 -m compileall benchmarks/fibonacci_sequence/python_recursion.py
python3 -m compileall benchmarks/fibonacci_sequence/python_iteration.py
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/python_recursion.cpython-311.json ' python3 benchmarks/fibonacci_sequence/__pycache__/python_recursion.cpython-311.pyc '
# TIMEOUT!
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/python_iteration.cpython-311.json ' python3 benchmarks/fibonacci_sequence/__pycache__/python_iteration.cpython-311.pyc '
HASIL :
Tolok ukur 1: benchmark python3/fibonacci_sequence/ pycache /python_iteration.cpython-311.pyc
Waktu (rata-rata ± σ): 16584,6 µs ± 761,5 µs [Pengguna: 11451,8 µs, Sistem: 3813,3 µs]
Rentang (min … maks): 15592,0 µs … 20953,2 µs 100 kali berjalan
fn fibonacci_recursion ( n : Int) -> Int:
return n if n < 2 else fibonacci_recursion(n - 1 ) + fibonacci_recursion(n - 2 )
fn main ():
_ = fibonacci_recursion( 100 )
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/mojo_recursion.json ' mojo run benchmarks/fibonacci_sequence/mojo_recursion.mojo '
HASIL: TIMEOUT, saya membatalkan perhitungan setelah 1m
fn fibonacci_iteration ( n : Int) -> Int:
var a : Int = 0
var b : Int = 1
for _ in range (n):
a = b
b = a + b
return a
fn main ():
_ = fibonacci_iteration( 100 )
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/mojo_iteration.json ' mojo run benchmarks/fibonacci_sequence/mojo_iteration.mojo '
HASIL :
Tolok ukur 1: mojo run benchmarks/fibonacci_sequence/mojo_iteration.mojo
Waktu (rata-rata ± σ): 43852,7 µs ± 1353,5 µs [Pengguna: 38156,0 µs, Sistem: 10407,3 µs]
Rentang (min … maks): 42033,6 µs … 49357,3 µs 100 kali berjalan
mojo build benchmarks/fibonacci_sequence/mojo_recursion.mojo
mojo build benchmarks/fibonacci_sequence/mojo_iteration.mojo
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/mojo_recursion.exe.json ' ./benchmarks/fibonacci_sequence/mojo_recursion '
# TIMEOUT!
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/mojo_iteration.exe.json ' ./benchmarks/fibonacci_sequence/mojo_iteration '
HASIL :
Tolok Ukur 1: ./benchmarks/fibonacci_sequence/mojo_iteration
Waktu (rata-rata ± σ): 934,6 µs ± 468,9 µs [Pengguna: 409,8 µs, Sistem: 247,8 µs]
Rentang (min … maks): 552,7 µs … 4522,9 µs 100 kali berjalan
def fibonacci_recursion(n):
return n if n < 2 else fibonacci_recursion(n - 1) + fibonacci_recursion(n - 2)
fibonacci_recursion(100)
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/codon_recursion.json ' codon run --release benchmarks/fibonacci_sequence/codon_recursion.codon '
HASIL: TIMEOUT, saya membatalkan perhitungan setelah 1m
def fibonacci_iteration(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a+b
return a
fibonacci_iteration(100)
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/codon_iteration.json ' codon run --release benchmarks/fibonacci_sequence/codon_iteration.codon '
HASIL :
Tolok ukur 1: menjalankan kodon --release benchmarks/fibonacci_sequence/codon_iteration.codon
Waktu (rata-rata ± σ): 628060,1 µs ± 10430,5 µs [Pengguna: 584524,3 µs, Sistem: 39358,5 µs]
Rentang (min … maks): 612742,5 µs … 662716,9 µs 100 kali berjalan
codon build --release -exe benchmarks/fibonacci_sequence/codon_recursion.codon
codon build --release -exe benchmarks/fibonacci_sequence/codon_iteration.codon
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json codon_recursion.exe.json ' ./benchmarks/fibonacci_sequence/codon_recursion '
# TIMEOUT!
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/codon_iteration.exe.json ' ./benchmarks/fibonacci_sequence/codon_iteration '
HASIL :
Tolok Ukur 1: ./benchmarks/fibonacci_sequence/codon_iteration
Waktu (rata-rata ± σ): 2732,7 µs ± 1145,5 µs [Pengguna: 1466,0 µs, Sistem: 1061,5 µs]
Rentang (min … maks): 2036,6 µs … 13236,3 µs 100 kali berjalan
fn fibonacci_recursive ( n : i64 ) -> i64 {
if n < 2 {
return n ;
}
return fibonacci_recursive ( n - 1 ) + fibonacci_recursive ( n - 2 ) ;
}
fn main ( ) {
let _ = fibonacci_recursive ( 100 ) ;
}
rustc -C opt-level=3 benchmarks/fibonacci_sequence/rust_recursion.rs -o benchmarks/fibonacci_sequence/rust_recursion
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/rust_recursion.json ' ./benchmarks/fibonacci_sequence/rust_recursion '
HASIL: TIMEOUT, saya membatalkan perhitungan setelah 1m
fn fibonacci_iteration ( n : usize ) -> usize {
let mut a = 1 ;
let mut b = 1 ;
for _ in 1 ..n {
let old = a ;
a = b ;
b += old ;
}
b
}
fn main ( ) {
let _ = fibonacci_iteration ( 100 ) ;
}
rustc -C opt-level=3 benchmarks/fibonacci_sequence/rust_iteration.rs -o benchmarks/fibonacci_sequence/rust_iteration
hyperfine --warmup 10 -r 100 --time-unit=microsecond --export-json benchmarks/fibonacci_sequence/rust_iteration.json ' ./benchmarks/fibonacci_sequence/rust_iteration '
HASIL :
Tolok Ukur 1: ./benchmarks/fibonacci_sequence/rust_iteration
Waktu (rata-rata ± σ): 848,9 µs ± 283,2 µs [Pengguna: 371,8 µs, Sistem: 261,4 µs]
Rentang (min … maks): 525,9 µs … 2607,3 µs 100 kali berjalan
# Merge all JSON files into benchmarks.json
python3 benchmarks/hyperfine-scripts/merge_jsons.py benchmarks/fibonacci_sequence/ benchmarks/fibonacci_sequence/benchmarks.json
python3 benchmarks/hyperfine-scripts/plot2.py benchmarks/fibonacci_sequence/benchmarks.json
python3 benchmarks/hyperfine-scripts/plot3.py benchmarks/fibonacci_sequence/benchmarks.json
python3 benchmarks/hyperfine-scripts/advanced_statistics.py benchmarks/fibonacci_sequence/benchmarks.json > benchmarks/fibonacci_sequence/benchmarks.json.md
silicon benchmarks/fibonacci_sequence/benchmarks.json.md -l python -o benchmarks/fibonacci_sequence/benchmarks.json.md.png
Statistik tingkat lanjut
Bersama
Diperbesar
Rinci satu per satu
Tempat
Tapi di sini banyak pertanyaan:
mojo run
sangat lambat?codon run --release
sangat lambat?run
?Jadi, bisa dibilang Mojo sama cepatnya dengan Rust di Mac!
Ayo temukan Mandelbrot Set dimana
LEBAR = 960
TINGGI = 960
MAX_ITERS = 200
MIN_X = -2,0
MAX_X = 0,6
MIN_Y = -1,5
MAX_Y = 1,5
def mandelbrot_kernel ( c ):
z = c
for i in range ( MAX_ITERS ):
z = z * z + c # Change this for different Multibrot sets (e.g., 2 for Mandelbrot)
if z . real * z . real + z . imag * z . imag > 4 :
return i
return MAX_ITERS
def compute_mandelbrot ():
t = [[ 0 for _ in range ( WIDTH )] for _ in range ( HEIGHT )] # Pixel matrix
dx = ( MAX_X - MIN_X ) / WIDTH
dy = ( MAX_Y - MIN_Y ) / HEIGHT
for row in range ( HEIGHT ):
for col in range ( WIDTH ):
t [ row ][ col ] = mandelbrot_kernel ( complex ( MIN_X + col * dx , MIN_Y + row * dy ))
return t
compute_mandelbrot ()
python3 -m compileall benchmarks/multibrot_set/multibrot.py
hyperfine --warmup 10 -r 10 --time-unit=microsecond --export-json benchmarks/multibrot_set/multibrot.cpython-311.json ' python3 benchmarks/multibrot_set/__pycache__/multibrot.cpython-311.pyc '
HASIL :
Tolok ukur 1: python3 benchmarks/multibrot_set/ pycache /multibrot.cpython-311.pyc
Waktu (rata-rata ± σ): 5444155,4 µs ± 23059,7 µs [Pengguna: 5419790,1 µs, Sistem: 18131,3 µs]
Rentang (min … maks): 5408155,3 µs … 5490548,4 µs 10 kali berjalan
Versi Mojo tanpa optimasi.
# Compute the number of steps to escape.
def multibrot_kernel ( c : ComplexFloat64) -> Int:
z = c
for i in range ( MAX_ITERS ):
z = z * z + c # Change this for different Multibrot sets (e.g., 2 for Mandelbrot)
if z.squared_norm() > 4 :
return i
return MAX_ITERS
def compute_multibrot () -> Tensor[FloatType]:
# create a matrix. Each element of the matrix corresponds to a pixel
t = Tensor[FloatType]( HEIGHT , WIDTH )
dx = ( MAX_X - MIN_X ) / WIDTH
dy = ( MAX_Y - MIN_Y ) / HEIGHT
y = MIN_Y
for row in range ( HEIGHT ):
x = MIN_X
for col in range ( WIDTH ):
t[Index(row, col)] = multibrot_kernel(ComplexFloat64(x, y))
x += dx
y += dy
return t
_ = compute_multibrot()
mojo build benchmarks/multibrot_set/multibrot.mojo
hyperfine --warmup 10 -r 10 --time-unit=microsecond --export-json benchmarks/multibrot_set/multibrot.exe.json ' ./benchmarks/multibrot_set/multibrot '
HASIL :
Tolok Ukur 1: ./benchmarks/multibrot_set/multibrot
Waktu (rata-rata ± σ): 135880,5 µs ± 1175,4 µs [Pengguna: 133309,3 µs, Sistem: 1700,1 µs]
Rentang (min … maks): 134639,9 µs … 137621,4 µs 10 kali berjalan
fn mandelbrot_kernel_SIMD [
simd_width : Int
]( c : ComplexSIMD[float_type, simd_width]) -> SIMD [float_type, simd_width]:
""" A vectorized implementation of the inner mandelbrot computation. """
let cx = c.re
let cy = c.im
var x = SIMD [float_type, simd_width]( 0 )
var y = SIMD [float_type, simd_width]( 0 )
var y2 = SIMD [float_type, simd_width]( 0 )
var iters = SIMD [float_type, simd_width]( 0 )
var t : SIMD [DType.bool, simd_width] = True
for i in range ( MAX_ITERS ):
if not t.reduce_or():
break
y2 = y * y
y = x.fma(y + y, cy)
t = x.fma(x, y2) <= 4
x = x.fma(x, cx - y2)
iters = t.select(iters + 1 , iters)
return iters
fn compute_multibrot_parallelized () -> Tensor[float_type]:
let t = Tensor[float_type](height, width)
@parameter
fn worker ( row : Int):
let scale_x = (max_x - min_x) / width
let scale_y = (max_y - min_y) / height
@parameter
fn compute_vector [ simd_width : Int]( col : Int):
""" Each time we operate on a `simd_width` vector of pixels. """
let cx = min_x + (col + iota[float_type, simd_width]()) * scale_x
let cy = min_y + row * scale_y
let c = ComplexSIMD[float_type, simd_width](cx, cy)
t.data().simd_store[simd_width](
row * width + col, mandelbrot_kernel_SIMD[simd_width](c)
)
# Vectorize the call to compute_vector where call gets a chunk of pixels.
vectorize[simd_width, compute_vector](width)
# Parallelized
parallelize[worker](height, height)
return t
def main ():
_ = compute_multibrot_parallelized()
mojo build benchmarks/multibrot_set/multibrot_mojo_parallelize.mojo
hyperfine --warmup 10 -r 10 --time-unit=microsecond --export-json benchmarks/multibrot_set/multibrot_mojo_parallelize.exe.json ' ./benchmarks/multibrot_set/multibrot_mojo_parallelize '
HASIL :
Tolok ukur 1: ./benchmarks/multibrot_set/multibrot_mojo_parallelize
Waktu (rata-rata ± σ): 7139,4 µs ± 596,4 µs [Pengguna: 36535,2 µs, Sistem: 6670,1 µs]
Rentang (min … maks): 6222,6 µs … 8269,7 µs 10 kali berjalan
def mandelbrot_kernel(c):
z = c
for i in range(MAX_ITERS):
z = z * z + c # Change this for different Multibrot sets (e.g., 2 for Mandelbrot)
if z.real * z.real + z.imag * z.imag > 4:
return i
return MAX_ITERS
def compute_mandelbrot():
t = [[0 for _ in range(WIDTH)] for _ in range(HEIGHT)] # Pixel matrix
dx = (MAX_X - MIN_X) / WIDTH
dy = (MAX_Y - MIN_Y) / HEIGHT
@par(collapse=2)
for row in range(HEIGHT):
for col in range(WIDTH):
t[row][col] = mandelbrot_kernel(complex(MIN_X + col * dx, MIN_Y + row * dy))
return t
compute_mandelbrot()
Untuk uji coba atau plot (batalkan komentar pada kode dalam file)
CODON_PYTHON=/opt/homebrew/opt/[email protected]/Frameworks/Python.framework/Versions/3.11/lib/libpython3.11.dylib codon run --release benchmarks/multibrot_set/multibrot.codon
Bangun dan jalankan
codon build --release -exe benchmarks/multibrot_set/multibrot.codon -o benchmarks/multibrot_set/multibrot_codon
hyperfine --warmup 10 -r 10 --time-unit=microsecond --export-json benchmarks/multibrot_set/multibrot_codon.json ' ./benchmarks/multibrot_set/multibrot_codon '
HASIL :
Tolok ukur 1: ./benchmarks/multibrot_set/multibrot_codon
Waktu (rata-rata ± σ): 44184,7 µs ± 1142,0 µs [Pengguna: 248773,9 µs, Sistem: 72935,3 µs]
Rentang (min … maks): 42963,8 µs … 46456,2 µs 10 kali berjalan
codon build --release -exe benchmarks/multibrot_set/multibrot_codon_par.codon -o benchmarks/multibrot_set/multibrot_codon_par
hyperfine --warmup 10 -r 10 --time-unit=microsecond --export-json benchmarks/multibrot_set/multibrot_codon_par.json ' ./benchmarks/multibrot_set/multibrot_codon_par '
# Merge all JSON files into benchmarks.json
python3 benchmarks/hyperfine-scripts/merge_jsons.py benchmarks/multibrot_set/ benchmarks/multibrot_set/benchmarks.json
python3 benchmarks/hyperfine-scripts/plot2.py benchmarks/multibrot_set/benchmarks.json
python3 benchmarks/hyperfine-scripts/plot3.py benchmarks/multibrot_set/benchmarks.json
python3 benchmarks/hyperfine-scripts/advanced_statistics.py benchmarks/multibrot_set/benchmarks.json > benchmarks/multibrot_set/benchmarks.json.md
silicon benchmarks/multibrot_set/benchmarks.json.md -l python -o benchmarks/multibrot_set/benchmarks.json.md.png
Statistik tingkat lanjut
Bersama
Diperbesar
Rinci satu per satu
Tempat
Tautan:
Mandelbrot = Multibrot dengan power = 2
z = z ** power + c # You can change this for different set
Bantal ImagingEffectMandelbrot bawaan
Mandelbrot versi Exaloop Codon
Mandelbrot versi Mojo modular
Kompleks Mojo squared_norm
Matplotlib Mandelbrot
Dalam ilmu komputer, algoritma pencarian biner, juga dikenal sebagai pencarian setengah interval, pencarian logaritmik, atau potongan biner, adalah algoritma pencarian yang menemukan posisi nilai target dalam array yang diurutkan.
Mari kita buat beberapa kode dengan Python, Mojo, Swift, V, Julia, Nim, Zig.
Catatan: Untuk versi Python dan Mojo , saya meninggalkan beberapa optimasi dan membuat kode serupa untuk pengukuran dan perbandingan.
from typing import List
import timeit
SIZE = 1000000
MAX_ITERS = 100
COLLECTION = tuple ( i for i in range ( SIZE )) # Make it aka at compile-time.
def python_binary_search ( element : int , array : List [ int ]) -> int :
start = 0
stop = len ( array ) - 1
while start <= stop :
index = ( start + stop ) // 2
pivot = array [ index ]
if pivot == element :
return index
elif pivot > element :
stop = index - 1
elif pivot < element :
start = index + 1
return - 1
def test_python_binary_search ():
_ = python_binary_search ( SIZE - 1 , COLLECTION )
print (
"Average execution time of func in sec" ,
timeit . timeit ( lambda : test_python_binary_search (), number = MAX_ITERS ),
)
"""Implements basic binary search."""
from Benchmark import Benchmark
from Vector import DynamicVector
alias SIZE = 1000000
alias NUM_WARMUP = 0
alias MAX_ITERS = 100
fn mojo_binary_search ( element : Int , array : DynamicVector [ Int ]) - > Int :
var start = 0
var stop = len ( array ) - 1
while start <= stop :
let index = ( start + stop ) // 2
let pivot = array [ index ]
if pivot == element :
return index
elif pivot > element :
stop = index - 1
elif pivot < element :
start = index + 1
return - 1
@ parameter # statement runs at compile-time.
fn get_collection () - > DynamicVector [ Int ]:
var v = DynamicVector [ Int ]( SIZE )
for i in range ( SIZE ):
v . push_back ( i )
return v
fn test_mojo_binary_search () - > F64 :
fn test_closure ():
_ = mojo_binary_search ( SIZE - 1 , get_collection ())
return F64 ( Benchmark ( NUM_WARMUP , MAX_ITERS ). run [ test_closure ]()) / 1e9
print (
"Average execution time of func in sec " ,
test_mojo_binary_search (),
)
Ini adalah pencarian biner pertama yang ditulis di komunitas Mojoby (@ego) dan diposting di mojo-chat.
func binarySearch ( items : [ Int ] , elem : Int ) -> Int {
var low = 0
var high = items . count - 1
var mid = 0
while low <= high {
mid = Int ( ( high + low ) / 2 )
if items [ mid ] < elem {
low = mid + 1
} else if items [ mid ] > elem {
high = mid - 1
} else {
return mid
}
}
return - 1
}
let items = [ 1 , 2 , 3 , 4 , 0 ] . sorted ( )
let res = binarySearch ( items : items , elem : 4 )
print ( res )
function binarysearch (lst :: Vector{T} , val :: T ) where T
low = 1
high = length (lst)
while low ≤ high
mid = (low + high) ÷ 2
if lst[mid] > val
high = mid - 1
elseif lst[mid] < val
low = mid + 1
else
return mid
end
end
return 0
end
proc binarySearch [T](a: openArray [T], key: T): int =
var b = len (a)
while result < b:
var mid = ( result + b) div 2
if a[mid] < key: result = mid + 1
else : b = mid
if result >= len (a) or a[ result ] != key: result = - 1
let res = @ [ 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 12 , 14 , 16 , 18 , 20 , 22 , 25 , 27 , 30 ]
echo binarySearch (res, 10 )
const std = @import ( "std" );
fn binarySearch ( comptime T : type , arr : [] const T , target : T ) ? usize {
var lo : usize = 0 ;
var hi : usize = arr . len - 1 ;
while ( lo <= hi ) {
var mid : usize = ( lo + hi ) / 2 ;
if ( arr [ mid ] == target ) {
return mid ;
} else if ( arr [ mid ] < target ) {
lo = mid + 1 ;
} else {
hi = mid - 1 ;
}
}
return null ;
}
fn binary_search (a [] int , value int ) int {
mut low := 0
mut high := a.len - 1
for low < = high {
mid := (low + high) / 2
if a[mid] > value {
high = mid - 1
} else if a[mid] < value {
low = mid + 1
} else {
return mid
}
}
return - 1
}
fn main () {
search_list := [ 1 , 2 , 3 , 5 , 6 , 7 , 8 , 9 , 10 ]
println ( binary_search (search_list, 9 ))
}
fn breadth_first_search_path (graph map [ string ][] string , vertex string , target string ) [] string {
mut path := [] string {}
mut visited := [] string {init: vertex}
mut queue := [][][] string {}
queue << [[vertex], path]
for queue.len > 0 {
mut idx := queue.len - 1
node := queue[idx][ 0 ][ 0 ]
path = queue[idx][ 1 ]
queue. delete (idx)
if node == target {
path << node
return path
}
for child in graph[node] {
mut tmp := path. clone ()
if child ! in visited {
visited << child
tmp << node
queue << [[child], tmp]
}
}
}
return path
}
fn main () {
graph := map {
'A' : [ 'B' , 'C' ]
'B' : [ 'A' , 'D' , 'E' ]
'C' : [ 'A' , 'F' ]
'D' : [ 'B' ]
'E' : [ 'B' , 'F' ]
'F' : [ 'C' , 'E' ]
}
println ( 'Graph: $graph ' )
path := breadth_first_search_path (graph, 'A' , 'F' )
println ( 'The shortest path from node A to node F is: $path ' )
assert path == [ 'A' , 'C' , 'F' ]
}
import timeit
SIZE = 100
MAX_ITERS = 100
def _fizz_buzz (): # Make it aka at compile-time.
res = []
for n in range ( 1 , SIZE + 1 ):
if ( n % 3 == 0 ) and ( n % 5 == 0 ):
s = "FizzBuzz"
elif n % 3 == 0 :
s = "Fizz"
elif n % 5 == 0 :
s = "Buzz"
else :
s = str ( n )
res . append ( s )
return res
DATA = _fizz_buzz ()
def fizz_buzz ():
print ( " n " . join ( DATA ))
print (
"Average execution time of Python func in sec" ,
timeit . timeit ( lambda : fizz_buzz (), number = MAX_ITERS ),
)
# Average execution time of Python func in sec 0.005334990004485007
( import '[java.io OutputStream])
( require '[clojure.java.io :as io])
( def devnull ( io/writer ( OutputStream/nullOutputStream )))
( defmacro timeit [n expr]
`(with-out-str ( time
( dotimes [_# ~( Math/pow 1 n)]
( binding [*out* devnull]
~expr)))))
( defmacro macro-fizz-buzz [n]
`( fn []
( print
~( apply str
( for [i ( range 1 ( inc n))]
( cond
( zero? ( mod i 15 )) " FizzBuzz n "
( zero? ( mod i 5 )) " Buzz n "
( zero? ( mod i 3 )) " Fizz n "
:else ( str i " n " )))))))
( print ( timeit 100 ( macro-fizz-buzz 100 )))
; ; "Elapsed time: 0.175486 msecs"
; ; Average execution time of Clojure func in sec 0.000175486 seconds
from String import String
from Benchmark import Benchmark
alias SIZE = 100
alias NUM_WARMUP = 0
alias MAX_ITERS = 100
@ parameter # statement runs at compile-time.
fn _fizz_buzz () - > String :
var res : String = ""
for n in range ( 1 , SIZE + 1 ):
if ( n % 3 == 0 ) and ( n % 5 == 0 ):
res += "FizzBuzz"
elif n % 3 == 0 :
res += "Fizz"
elif n % 5 == 0 :
res += "Buzz"
else :
res += String ( n )
res += " n "
return res
fn fizz_buzz ():
print ( _fizz_buzz ())
fn run_benchmark () - > F64 :
fn _closure ():
_ = fizz_buzz ()
return F64 ( Benchmark ( NUM_WARMUP , MAX_ITERS ). run [ _closure ]()) / 1e9
print (
"Average execution time of func in sec " ,
run_benchmark (),
)
# Average execution time of func in sec 0.000104
Ini adalah Fizz buzz pertama yang ditulis di Mojo oleh komunitas (@Ego).
Kami akan menggunakan algoritma dari referensi terkenal untuk buku algoritma Pengantar Algoritma A3
Ketenarannya menyebabkan penggunaan umum singkatan " CLRS " (Cormen, Leiserson, Rivest, Stein), atau, dalam edisi pertama, " CLR " (Cormen, Leiserson, Rivest).
Bab 2 "2.3.1 Pendekatan membagi-dan-menaklukkan".
% % python
import timeit
MAX_ITERS = 100
def merge ( A , p , q , r ):
n1 = q - p + 1
n2 = r - q
L = [ None ] * n1
R = [ None ] * n2
for i in range ( n1 ):
L [ i ] = A [ p + i ]
for j in range ( n2 ):
R [ j ] = A [ q + 1 + j ]
i = 0
j = 0
k = p
while i < n1 and j < n2 :
if L [ i ] <= R [ j ]:
A [ k ] = L [ i ]
i += 1
else :
A [ k ] = R [ j ]
j += 1
k += 1
while i < n1 :
A [ k ] = L [ i ]
i += 1
k += 1
while j < n2 :
A [ k ] = R [ j ]
j += 1
k += 1
def merge_sort ( A , p , r ):
if p < r :
q = ( p + r ) // 2
merge_sort ( A , p , q )
merge_sort ( A , q + 1 , r )
merge ( A , p , q , r )
def run_benchmark_merge_sort ():
A = [ 14 , 72 , 50 , 83 , 18 , 20 , 13 , 30 , 17 , 87 , 94 , 65 , 24 , 99 , 70 , 44 , 5 , 12 , 74 , 6 , 32 , 63 , 91 , 88 , 43 , 54 , 27 , 39 , 64 , 78 , 29 , 62 , 58 , 59 , 61 , 89 , 2 , 15 , 41 , 9 , 93 , 90 , 23 , 96 , 73 , 14 , 8 , 28 , 11 , 42 , 77 , 34 , 52 , 80 , 57 , 84 , 21 , 60 , 66 , 40 , 7 , 85 , 47 , 98 , 97 , 35 , 82 , 36 , 49 , 3 , 68 , 22 , 67 , 81 , 56 , 71 , 4 , 38 , 69 , 95 , 16 , 48 , 1 , 31 , 75 , 19 , 10 , 25 , 79 , 45 , 76 , 33 , 53 , 55 , 46 , 37 , 26 , 51 , 92 , 86 ]
merge_sort ( A , 0 , len ( A ) - 1 )
print (
"Average execution time of Python `merge_sort` in sec" ,
timeit . timeit ( lambda : run_benchmark_merge_sort (), number = MAX_ITERS ),
)
# Average execution time of Python `merge_sort` in sec 0.019136679999064654
def run_benchmark_sort ():
A = [ 14 , 72 , 50 , 83 , 18 , 20 , 13 , 30 , 17 , 87 , 94 , 65 , 24 , 99 , 70 , 44 , 5 , 12 , 74 , 6 , 32 , 63 , 91 , 88 , 43 , 54 , 27 , 39 , 64 , 78 , 29 , 62 , 58 , 59 , 61 , 89 , 2 , 15 , 41 , 9 , 93 , 90 , 23 , 96 , 73 , 14 , 8 , 28 , 11 , 42 , 77 , 34 , 52 , 80 , 57 , 84 , 21 , 60 , 66 , 40 , 7 , 85 , 47 , 98 , 97 , 35 , 82 , 36 , 49 , 3 , 68 , 22 , 67 , 81 , 56 , 71 , 4 , 38 , 69 , 95 , 16 , 48 , 1 , 31 , 75 , 19 , 10 , 25 , 79 , 45 , 76 , 33 , 53 , 55 , 46 , 37 , 26 , 51 , 92 , 86 ]
A . sort ()
print (
"Average execution time of Python builtin `sort` in sec" ,
timeit . timeit ( lambda : run_benchmark_sort (), number = MAX_ITERS ),
)
# Average execution time of Python builtin `sort` in sec 0.00019922800129279494
from Benchmark import Benchmark
from Vector import DynamicVector
from StaticTuple import StaticTuple
from Sort import sort
alias NUM_WARMUP = 0
alias MAX_ITERS = 100
fn merge ( inout A : DynamicVector [ Int ], p : Int , q : Int , r : Int ):
let n1 = q - p + 1
let n2 = r - q
var L = DynamicVector [ Int ]( n1 )
var R = DynamicVector [ Int ]( n2 )
for i in range ( n1 ):
L [ i ] = A [ p + i ]
for j in range ( n2 ):
R [ j ] = A [ q + 1 + j ]
var i = 0
var j = 0
var k = p
while i < n1 and j < n2 :
if L [ i ] <= R [ j ]:
A [ k ] = L [ i ]
i += 1
else :
A [ k ] = R [ j ]
j += 1
k += 1
while i < n1 :
A [ k ] = L [ i ]
i += 1
k += 1
while j < n2 :
A [ k ] = R [ j ]
j += 1
k += 1
fn merge_sort ( inout A : DynamicVector [ Int ], p : Int , r : Int ):
if p < r :
let q = ( p + r ) // 2
merge_sort ( A , p , q )
merge_sort ( A , q + 1 , r )
merge ( A , p , q , r )
@ parameter
fn create_vertor () - > DynamicVector [ Int ]:
let st = StaticTuple [ MAX_ITERS , Int ]( 14 , 72 , 50 , 83 , 18 , 20 , 13 , 30 , 17 , 87 , 94 , 65 , 24 , 99 , 70 , 44 , 5 , 12 , 74 , 6 , 32 , 63 , 91 , 88 , 43 , 54 , 27 , 39 , 64 , 78 , 29 , 62 , 58 , 59 , 61 , 89 , 2 , 15 , 41 , 9 , 93 , 90 , 23 , 96 , 73 , 14 , 8 , 28 , 11 , 42 , 77 , 34 , 52 , 80 , 57 , 84 , 21 , 60 , 66 , 40 , 7 , 85 , 47 , 98 , 97 , 35 , 82 , 36 , 49 , 3 , 68 , 22 , 67 , 81 , 56 , 71 , 4 , 38 , 69 , 95 , 16 , 48 , 1 , 31 , 75 , 19 , 10 , 25 , 79 , 45 , 76 , 33 , 53 , 55 , 46 , 37 , 26 , 51 , 92 , 86 )
var v = DynamicVector [ Int ]( st . __len__ ())
for i in range ( st . __len__ ()):
v . push_back ( st [ i ])
return v
fn run_benchmark_merge_sort () - > F64 :
fn _closure ():
var A = create_vertor ()
merge_sort ( A , 0 , len ( A ) - 1 )
return F64 ( Benchmark ( NUM_WARMUP , MAX_ITERS ). run [ _closure ]()) / 1e9
print (
"Average execution time of Mojo `merge_sort` in sec " ,
run_benchmark_merge_sort (),
)
# Average execution time of Mojo `merge_sort` in sec 1.1345999999999999e-05
fn run_benchmark_sort () - > F64 :
fn _closure ():
var A = create_vertor ()
sort ( A )
return F64 ( Benchmark ( NUM_WARMUP , MAX_ITERS ). run [ _closure ]()) / 1e9
print (
"Average execution time of Mojo builtin `sort` in sec " ,
run_benchmark_sort (),
)
# Average execution time of Mojo builtin `sort` in sec 2.988e-06
Anda dapat menggunakannya seperti:
# Usage: merge_sort
var A = create_vertor ()
merge_sort ( A , 0 , len ( A ) - 1 )
print ( len ( A ))
print ( A [ 0 ], A [ 99 ])
Built-in from Sort import sort
quicksort sedikit lebih cepat daripada implementasi kami, namun kami dapat mengoptimalkannya selama mendalami bahasa dan seperti biasa dengan algoritma =) dan paradigma pemrograman.
Lang | detik |
---|---|
Penggabungan_sortir Python | 0,019136679 |
Pengurutan bawaan Python | 0,000199228 |
Mojo menggabungkan_sort | 0,000011346 |
Semacam bawaan Mojo | 0,000002988 |
Mari buat plot untuk tabel ini.
#%%python
import matplotlib . pyplot as plt
import numpy as np
languages = [ 'Python merge_sort' , 'Python builtin sort' , 'Mojo merge_sort' , 'Mojo builtin sort' ]
seconds = [ 0.019136679 , 0.000199228 , 0.000011346 , 0.000002988 ]
# Apply a custom transformation to the values
transformed_seconds = [ np . sqrt ( 1 / x ) for x in seconds ]
plt . barh ( languages , transformed_seconds )
plt . xlabel ( 'Custom Transformation' )
plt . ylabel ( 'Language and Sort Type' )
plt . title ( 'Comparison of Sorting Algorithms (Custom Transformation)' )
plt . show ()
Catatan plot, lebih banyak lebih baik dan lebih cepat.
Saya sangat menyarankan untuk memulai dari sini HelloMojo dan memahami parameterisasi [parameter] dan [ekspresi parameter] di sini. Seperti dalam contoh ini:
fn concat [ len1 : Int , len2 : Int ]( lhs : MySIMD [ len1 ], rhs : MySIMD [ len2 ]) - > MySIMD [ len1 + len2 ]:
let result = MySIMD [ len1 + len2 ]()
for i in range ( len1 ):
result [ i ] = lhs [ i ]
for j in range ( len2 ):
result [ len1 + j ] = rhs [ j ]
return result
let a = MySIMD [ 2 ]( 1 , 2 )
let x = concat [ 2 , 2 ]( a , a )
x . dump ()
Waktu kompilasi [Parameter]: fn concat[len1: Int, len2: Int]
.
Waktu berjalan (Args) : fn concat(lhs: MySIMD, rhs: MySIMD)
.
Sintaks parameter PEP695 dalam tanda kurung siku []
.
Sekarang dengan Python:
def func ( a : _T , b : _T ) -> _T :
...
Sekarang di Mojo:
def func [ T ]( a : T , b : T ) -> T :
...
[Parameter] diberi nama dan memiliki tipe seperti nilai normal dalam program Mojo, tetapi parameters[]
dievaluasi pada waktu kompilasi .
Program runtime dapat menggunakan nilai [parameter] - karena parameter diselesaikan pada waktu kompilasi sebelum dibutuhkan oleh program runtime - tetapi ekspresi parameter waktu kompilasi tidak boleh menggunakan nilai runtime.
Tipe Self
dari PEP673
fn __sub__ ( self , rhs : Self ) - > Self :
let result = MySIMD [ size ]()
for i in range ( size ):
result [ i ] = self [ i ] - rhs [ i ]
return result
Di dokumen Anda dapat menemukan kata Fields alias Atribut kelas dengan Python.
Jadi, Anda memanggil mereka dengan dot
.
from DType import DType
let bool_type = DType . bool
from DType import DType
DType . si8
from DType import DType
from SIMD import SIMD , SI8
alias MY_SIMD_DType_si8 = SIMD [ DType . si8 , 1 ]
alias MY_SI8 = SI8
print ( MY_SIMD_DType_si8 == MY_SI8 )
# true
from DType import DType
from SIMD import SIMD , SI8
from Vector import DynamicVector
from String import String
alias a = DynamicVector [ SIMD [ DType . si8 , 1 ]]
alias b = DynamicVector [ SI8 ]
print ( a == b )
print ( a == String )
print ( b == String )
# all true
Jadi String
hanyalah alias untuk sesuatu seperti DynamicVector[SIMD[DType.si8, 1]]
.
VariadicList
untuk merusak/membongkar/mengakses argumen from List import VariadicList
fn destructuring_arguments ( * args : Int ):
let my_var_list = VariadicList ( args )
for i in range ( len ( my_var_list )):
print ( "argument" , i , ":" , my_var_list [ i ])
destructuring_arguments ( 1 , 2 , 3 , 4 )
Ini sangat berguna untuk membuat koleksi awal. Kita bisa menulis seperti ini:
from Vector import DynamicVector
from StaticTuple import StaticTuple
fn create_vertor () - > DynamicVector [ Int ]:
let st = StaticTuple [ 4 , Int ]( 1 , 2 , 3 , 4 )
var v = DynamicVector [ Int ]( st . __len__ ())
for i in range ( st . __len__ ()):
v . push_back ( st [ i ])
return v
v = create_vertor ()
print ( v [ 0 ], v [ 3 ])
# or
from List import VariadicList
fn create_vertor () - > DynamicVector [ Int ]:
let var_list = VariadicList ( 1 , 2 , 3 , 4 )
var v = DynamicVector [ Int ]( len ( var_list ))
for i in range ( len ( var_list )):
v . push_back ( var_list [ i ])
return v
v = create_vertor ()
print ( v [ 0 ], v [ 3 ])
Baca selengkapnya tentang fungsi def dan fn
from String import String
# String concatenation
print ( String ( "'" ) + String ( 1 ) + "' n " )
# Python's join
print ( String ( "|" ). join ( "a" , "b" , "c" ))
# String format
from IO import _printf as print
let x : Int = 1
print ( "'%i' n " , x . value )
Untuk string Anda dapat menggunakan Builtin Slice dengan format string slice[start:end:step].
from String import String
let hello_mojo = String ( "Hello Mojo!" )
print ( "Till the end:" , hello_mojo [ 0 ::])
print ( "Before last 2 chars:" , hello_mojo [ 0 : - 2 ])
print ( "From start to the end with step 2:" , hello_mojo [ 0 :: 2 ])
print ( "From start to the before last with step 3:" , hello_mojo [ 0 : - 1 : 3 ])
Ada beberapa masalah dengan unicode, saat mengiris:
let hello_mojo_unicode = String ( "Hello Mojo!" )
print ( "Unicode efore last 2 chars:" , hello_mojo_unicode [ 0 : - 2 ])
# no result, silents
Berikut ini penjelasan dan sedikit pembahasannya.
mbstowcs - mengonversi string multibyte menjadi string berkarakter lebar
dekorator struct
alias Python @dataclass
. Ini akan menghasilkan metode __init__
, __copyinit__
, __moveinit__
untuk Anda secara otomatis.
@ value
struct dataclass :
var name : String
var age : Int
Perhatikan bahwa dekorator @value
hanya berfungsi pada tipe yang anggotanya copyable
dan/atau movable
.
Tipe sepele. Dekorator ini memberi tahu Mojo bahwa tipenya harus __copyinit__
yang dapat disalin dan __moveinit__
yang dapat dipindahkan. Ini juga memberitahu Mojo untuk memilih meneruskan nilai dalam register CPU. Memungkinkan structs
untuk ikut serta dalam register
alih-alih melewati memory
.
@ register_passable ( "trivial" )
struct Int :
var value : __mlir_type . `!pop.scalar<index>`
Dekorator yang memberikan kontrol penuh atas optimasi kompiler . Menginstruksikan kompiler untuk selalu menyejajarkan fungsi ini ketika dipanggil.
@ always_inline
fn foo ( x : Int , y : Int ) - > Int :
return x + y
fn bar ( z : Int ):
let r = foo ( z , z ) # This call will be inlined
Itu dapat ditempatkan pada fungsi bersarang yang menangkap nilai runtime untuk membuat penutupan penangkapan “parametrik”. Hal ini memungkinkan penutupan yang menangkap nilai runtime untuk diteruskan sebagai nilai parameter.
@ always_inline
@ parameter
fn test (): return
Beberapa contoh casting
s : StringLiteral
let p = DTypePointer [ DType . si8 ]( s . data ()). bitcast [ DType . ui8 ]()
var result = 0
result += (( p . simd_load [ 64 ]( offset ) >> 6 ) != 0b10 ). cast [ DType . ui8 ](). reduce_add (). to_int ()
let rest_p : DTypePointer [ DType . ui8 ] = stack_allocation [ simd_width , UI8 , 1 ]()
from Bit import ctlz
s : String
i : Int
let code = s . buffer . data . load ( i )
let byte_length_code = ctlz ( ~ code ). to_int ()
DTypePointer - menyimpan alamat dengan DType tertentu, memungkinkan Anda mengalokasikan, memuat, dan mengubah data dengan akses mudah ke operasi SIMD.
from Pointer import DTypePointer
from DType import DType
from Random import rand
from Memory import memset_zero
# `heap`
var my_pointer_on_heap = DTypePointer [ DType . ui8 ]. alloc ( 8 )
memset_zero ( my_pointer_on_heap , 8 )
# `stack or register`
var data = my_pointer_on_heap . simd_load [ 8 ]( 0 )
print ( data )
rand ( my_pointer_on_heap , 4 )
# `data` does not contain a reference to the `heap`, so load the data again
data = my_pointer_on_heap . simd_load [ 8 ]( 0 )
print ( data )
# simd_load and simd_store
var half = my_pointer_on_heap . simd_load [ 4 ]( 0 )
half = half + 1
my_pointer_on_heap . simd_store [ 4 ]( 4 , half )
print ( my_pointer_on_heap . simd_load [ 8 ]( 0 ))
# Pointer move back
my_pointer_on_heap -= 1
print ( my_pointer_on_heap . simd_load [ 8 ]( 0 ))
# Mast free memory
my_pointer_on_heap . free ()
Struct dapat meminimalkan potensi bahaya pointer dengan membatasi scoup.
Artikel bagus di blog Mojo Dojo tentang DTypePointer di sini
Ditambah contohnya Matrix Struct dan DTypePointer
Pointer menyimpan alamat ke register_passable type
apa pun, dan mengalokasikan n
jumlahnya ke heap
.
from Pointer import Pointer
from Memory import memset_zero
from String import String
@ register_passable # for syntaxt like `let coord = p1[0]` and let it be passed through registers.
struct Coord : # memory-only type
var x : UI8
var y : UI8
var p1 = Pointer [ Coord ]. alloc ( 2 )
memset_zero ( p1 , 2 )
var coord = p1 [ 0 ] # is an identifier to memory on the stack or in a register
print ( coord . x )
# Store the value
coord . x = 5
coord . y = 5
print ( coord . x )
# We need to store the data.
p1 . store ( 0 , coord )
print ( p1 [ 0 ]. x )
# Mast free memory
p1 . free ()
Artikel lengkap tentang Pointer
Ditambah contoh Pointer dan Struct
Intrinsik Modular itu adalah semacam backend eksekusi :
Mojo-> Dialek MLIR -> backend eksekusi dengan kode dan arsitektur pengoptimalan.
MLIR adalah penyihir infrastruktur kompiler yang mengimplementasikan berbagai transformasi dan optimasi untuk berbagai bahasa pemrograman dan arsitektur .
MLIR sendiri tidak secara langsung menyediakan fungsionalitas untuk berinteraksi dengan syscall sistem operasi.
Yang merupakan antarmuka tingkat rendah ke layanan sistem operasi, biasanya ditangani pada tingkat bahasa pemrograman target atau sistem operasi itu sendiri. MLIR dirancang agar tidak bergantung pada bahasa dan target, dan fokus utamanya adalah menyediakan representasi perantara untuk melakukan pengoptimalan. Untuk melakukan syscall sistem operasi di MLIR, kita perlu menggunakan backend khusus target.
Namun dengan execution backends
ini, pada dasarnya, kami memiliki akses ke syscall OS. Dan kami memiliki seluruh dunia hal-hal C/LLVM/Python.
Mari kita lihat sekilas dalam praktiknya:
from OS import getenv
print ( getenv ( "PATH" ))
print ( getenv ( StringRef ( "PATH" )))
# or like this
from SIMD import SI8
from Intrinsics import external_call
var path1 = external_call [ "getenv" , StringRef ]( StringRef ( "PATH" ))
print ( path1 . data )
var path2 = external_call [ "getenv" , StringRef ]( "PATH" )
print ( path2 . data )
let abs_10 = external_call [ "abs" , SI8 , Int ]( - 10 )
print ( abs_10 )
Dalam contoh sederhana ini kami menggunakan external_call
untuk mendapatkan variabel lingkungan OS dengan tipe casting antara fungsi Mojo dan libc. Keren sekali, ya!
Saya punya banyak ide dari topik ini dan saya menantikan kesempatan untuk segera mengimplementasikannya. Mengambil tindakan dapat membawa hasil yang luar biasa =)
Mari kita lakukan sesuatu yang menarik - panggil libc function
gethostname.
Fungsi memiliki antarmuka ini int gethostname (char *name, size_t size)
.
Untuk itu kita bisa menggunakan fungsi pembantu external_call dari modul Intrinsik atau menulis MLIR sendiri.
Ayo kode:
from Intrinsics import external_call
from SIMD import SIMD , SI8
from DType import DType
from Vector import DynamicVector
from DType import DType
from Pointer import DTypePointer , Pointer
# We can use `from String import String` but for clarification we will use a full form.
# DynamicVector[SIMD[DType.si8, 1]] == DynamicVector[SI8] == String
# Compile time stuff.
alias cArrayOfStrings = DynamicVector [ SIMD [ DType . si8 , 1 ]]
alias capacity = 1024
var c_pointer_to_array_of_strings = DTypePointer [ DType . si8 ]( cArrayOfStrings ( capacity ). data )
var c_int_result = external_call [ "gethostname" , Int , DTypePointer [ DType . si8 ], Int ]( c_pointer_to_array_of_strings , capacity )
let mojo_string_result = String ( c_pointer_to_array_of_strings . address )
print ( "C function gethostname result code:" , c_int_result )
print ( "C function gethostname result value:" , star_hostname ( mojo_string_result ))
@ always_inline
fn star_hostname ( hostname : String ) - > String :
# [Builtin Slice](https://docs.modular.com/mojo/MojoBuiltin/BuiltinSlice.html)
# string slice[start:end:step]
return hostname [ 0 : - 1 : 2 ]
Mari kita lakukan beberapa hal untuk WEB dengan Mojo. Kami tidak memiliki akses Internet di play.modular.com Tapi kami bisa mencuri melakukan beberapa hal menarik seperti TCP pada satu mesin.
Mari kita tulis kode server klien TCP pertama di Mojo dengan PythonInterface
Anda harus membuat dua buku catatan terpisah, dan menjalankan TCPSocketServer terlebih dahulu, lalu TCPSocketClient .
Versi Python dari kode ini hampir sama, kecuali:
with
sintaksislet
menugaskana, b = (1, 2)
Setelah TCP Server di Mojo kita maju =)
Ini gila, tapi mari kita coba menjalankan FastAPI server web Python modern dengan Mojo!
Kita perlu mengunggah kode FastAPI ke taman bermain. Jadi, lakukan di mesin lokal Anda
pip install --target=web fastapi uvicorn
tar -czPf web.tar.gz web
dan unggah web.tar.gz
ke taman bermain melalui antarmuka web.
Kemudian kita perlu install
, cukup masukkan ke folder yang sesuai:
% % python
import os
import site
site_packages_path = site . getsitepackages ()[ 0 ]
# install fastapi
os . system ( f"tar xzf web.tar.gz -C { site_packages_path } " )
os . system ( f"cp -r { site_packages_path } /web/* { site_packages_path } /" )
os . system ( f"ls { site_packages_path } | grep fastapi" )
# clean packages
os . system ( f"rm -rf { site_packages_path } /web" )
os . system ( f"rm web.tar.gz" )
from PythonInterface import Python
# Python fastapi
let fastapi = Python . import_module ( "fastapi" )
let uvicorn = Python . import_module ( "uvicorn" )
var app = fastapi . FastAPI ()
var router = fastapi . APIRouter ()
# tricky part
let py = Python ()
let py_code = """lambda: 'Hello Mojo!'"""
let py_obj = py . evaluate ( py_code )
print ( py_obj )
router . add_api_route ( "/mojo" , py_obj )
app . include_router ( router )
print ( "Start FastAPI WEB Server" )
uvicorn . run ( app )
print ( "Done" )
from PythonInterface import Python
let http_client = Python . import_module ( "http.client" )
let conn = http_client . HTTPConnection ( "localhost" , 8000 )
conn . request ( "GET" , "/mojo" )
let response = conn . getresponse ()
print ( response . status , response . reason , response . read ())
Seperti biasa, Anda harus membuat dua buku catatan terpisah, dan menjalankan FastAPI terlebih dahulu, lalu FastAPIClient .
Ada banyak pertanyaan terbuka, tapi pada dasarnya kami mencapai tujuan.
Mojo bagus sekali!
Beberapa pertanyaan terbuka:
from PythonInterface import Python
let pyfn = Python . evaluate ( "lambda x, y: x+y" )
let functools = Python . import_module ( "functools" )
print ( functools . reduce ( pyfn , [ 1 , 2 , 3 , 4 ]))
# How to, without Mojo pyfn.so?
def pyfn ( x , y ):
retyrn x + y
Masa depan terlihat sangat optimis!
Tautan:
Tolok ukur Mojo vs Numba oleh Nick Wogan
Penggunaan waktu oleh Samay Kapadia @Zalando
Menghubungkan ke taman bermain mojo Anda dari VSCode atau DataSpell
oleh Maxim Zaks
from String import String
from PythonInterface import Python
let pathlib = Python . import_module ( 'pathlib' )
let txt = pathlib . Path ( 'nfl.csv' ). read_text ()
let s : String = txt . to_string ()
implementasi libc
from DType import DType
from Buffer import Buffer
from Pointer import Pointer
from String import String , chr
let hello = "hello"
let pointer = Pointer ( hello . data ())
print ( "variant 1" )
var result = String ()
for i in range ( len ( hello )):
result += chr ( pointer . bitcast [ Int8 ](). offset ( i ). load (). to_int ())
print ( result )
print ( "variant 2" )
print ( StringRef ( hello . data ()))
print ( "variant 3" )
print ( StringRef ( pointer . address ))
print ( "variant 4" )
let pm : Pointer [ __mlir_type . `!pop.scalar<si8>` ] = Pointer ( hello . data ())
print ( StringRef ( pm . address ))
print ( "variant 5" )
print ( String ( pointer . address ))
print ( "variant 6" )
let x = Buffer [ 8 , DType . int8 ]( pointer )
let array = x . simd_load [ 10 ]( 0 )
var result = String ()
for i in range ( len ( array )):
result += chr ( array [ i ]. to_int ())
print ( result )
right click
file di explorer dan tekan Open With > Editor
select all
dan copy
.ipynb
Github merendernya dengan benar, dan kemudian jika seseorang ingin mencoba kode di taman bermainnya, mereka dapat menyalin dan menempelkan kode mentahnya.
Ini adalah pandangan pribadi saya, jadi jangan menilai saya terlalu keras.
Saya tidak bisa mengatakan bahwa Mojo adalah bahasa pemrograman yang mudah dipelajari, seperti Python misalnya.
Ini membutuhkan banyak pemahaman, kesabaran dan pengalaman dalam bahasa pemrograman lainnya.
Kalau mau membangun sesuatu yang tidak sepele, susah tapi lucu!
Sudah 2 minggu sejak saya memulai perjalanan ini, dan saya sangat senang untuk berbagi bahwa saya sekarang telah mengenal baik Mojo.
Seluk-beluk struktur dan sintaksisnya mulai terkuak di depan mata saya , dan saya dipenuhi dengan pemahaman baru.
Saya bangga untuk mengatakan bahwa saya sekarang dapat dengan percaya diri membuat kode dalam bahasa ini, sehingga memungkinkan saya mewujudkan beragam ide .
Mojo adalah bahasa pemrograman Modular Inc. Kenapa Mojo kita bahas disini. Tentang Perusahaan yang kurang kita ketahui, namun memiliki nama yang sangat keren Modular
, yang dapat dirujuk:
"Dengan kata lain: Mojo bukanlah sihir, melainkan modular."
Semua tentang komputasi, pemrograman, AI/ML. Nama domain yang sangat bagus yang secara akurat menggambarkan arti Perusahaan.
Terdapat beberapa materi tambahan mengenai Kisah Merek Modular dan Membantu Modular Memanusiakan AI Melalui Merek
Hari ini saya ingin bercerita tentang masalah Python Enum. Sebagai seorang software engineer kita sering menemuinya di WEB. Asumsikan kita memiliki Skema DataBase (PostgreSQL) dengan status enum
:
CREATE TYPE public .status_type AS ENUM (
' FIRST ' ,
' SECOND '
);
Dalam kode Python kita memerlukan nama dan nilai sebagai string (asumsikan kita menggunakan GraphQL dengan beberapa tipe ENUM untuk sisi frontend kita), dan kita perlu menjaga urutannya dan memiliki kemampuan untuk membandingkan enum berikut:
order2.status > order1.status > 'FIRST'
Jadi ini masalah bagi sebagian besar bahasa umum =) tetapi kita dapat menggunakan fitur Python little-known
dan mengganti metode kelas enum: __new__
.
MALE -> 1
, FEMALE -> 2
, seperti yang dilakukan PostgreSQL.len
! import enum
from functools import total_ordering
@ total_ordering
@ enum . unique
class BaseUniqueSortedEnum ( enum . Enum ):
"""Base unique enum class with ordering."""
def __new__ ( cls , * args , ** kwargs ):
obj = object . __new__ ( cls )
obj . index = len ( cls . __members__ ) + 1 # This code line is a piece of advice, an insight and a tip!
return obj
# and then boring Python's magic methods as usual...
def __hash__ ( self ) -> int :
return hash (
f" { self . __module__ } _ { self . __class__ . __name__ } _ { self . name } _ { self . value } "
)
def __eq__ ( self , other ) -> bool :
self . _check_type ( other )
return super (). __eq__ ( other )
def __lt__ ( self , other ) -> bool :
self . _check_type ( other )
return self . index < other . index
def _check_type ( self , other ) -> None :
if type ( self ) != type ( other ):
raise TypeError ( f"Different types of Enum: { self } != { other } " )
class Dog ( BaseUniqueSortedEnum ):
# THIS ORDER MATTERS!
BLOODHOUND = "BLOODHOUND"
WEIMARANER = "WEIMARANER"
SAME = "SAME"
class Cat ( BaseUniqueSortedEnum )
# THIS ORDER MATTERS!
BRITISH = "BRITISH"
SCOTTISH = "SCOTTISH"
SAME = "SAME"
# and some tests
assert Dog . BLOODHOUND < Dog . WEIMARANER
assert Dog . BLOODHOUND <= Dog . WEIMARANER
assert Dog . BLOODHOUND != Dog . WEIMARANER
assert Dog . BLOODHOUND == Dog . BLOODHOUND
assert Dog . WEIMARANER == Dog . WEIMARANER
assert Dog . WEIMARANER > Dog . BLOODHOUND
assert Dog . WEIMARANER >= Dog . BLOODHOUND
assert Cat . BRITISH < Cat . SCOTTISH
assert Cat . BRITISH <= Cat . SCOTTISH
assert Cat . BRITISH != Cat . SCOTTISH
assert Cat . BRITISH == Cat . BRITISH
assert Cat . SCOTTISH == Cat . SCOTTISH
assert Cat . SCOTTISH > Cat . BRITISH
assert Cat . SCOTTISH >= Cat . BRITISH
assert hash ( Dog . BLOODHOUND ) == hash ( Dog . BLOODHOUND )
assert hash ( Dog . WEIMARANER ) == hash ( Dog . WEIMARANER )
assert hash ( Dog . BLOODHOUND ) != hash ( Dog . WEIMARANER )
assert hash ( Dog . SAME ) != hash ( Cat . SAME )
# raise TypeError
Dog . SAME <= Cat . SAME
Dog . SAME < Cat . SAME
Dog . SAME > Cat . SAME
Dog . SAME >= Cat . SAME
Dog . SAME != Cat . SAME
Akhir cerita. dan gunakan wawasan Python ENUM
ini untuk pengkodean yang baik!