Mojo — لغة برمجة جديدة لجميع المطورين وعلماء الذكاء الاصطناعي/تعلم الآلة ومهندسي البرمجيات.
قائمة منسقة من أكواد Mojo الرائعة وحل المشكلات والحلول وفي المكتبات والأطر والبرامج والموارد المستقبلية.
دعونا نجمع هنا المعرفة التكنولوجية الجديدة وأفضل الممارسات.
Mojo هي لغة برمجة تجمع بين سهولة استخدام Python وإمكانيات الأداء لـ C++ وRust. بالإضافة إلى ذلك، يتيح Mojo للمستخدمين الاستفادة من النظام البيئي الواسع لمكتبات Python.
باختصار
Mojo هي لغة برمجة جديدة تعمل على سد الفجوة بين البحث والإنتاج من خلال الجمع بين أفضل بناء جملة Python وبرمجة الأنظمة والبرمجة الوصفية.
hello.mojo
أو hello.
يمكن أن يكون امتداد الملف رمزًا تعبيريًا!
يمكنك قراءة المزيد حول سبب قيام Modular بذلك لماذا Mojo
ما أردناه هو نموذج برمجة مبتكر وقابل للتطوير يمكنه استهداف المسرعات والأنظمة الأخرى غير المتجانسة المنتشرة في مجال الذكاء الاصطناعي. ... تحتاج أنظمة الذكاء الاصطناعي التطبيقي إلى معالجة كل هذه المشكلات، وقررنا أنه لا يوجد سبب يمنع القيام بذلك باستخدام لغة واحدة فقط. وهكذا ولد موجو.
لكن بايثون قامت بعملها بشكل جيد جدًا =)
لم نرى أي حاجة للابتكار في بناء جملة اللغة أو المجتمع. لذلك اخترنا أن نتبنى نظام بايثون البيئي لأنه يستخدم على نطاق واسع جدًا، وهو محبوب من قبل النظام البيئي للذكاء الاصطناعي، ولأننا نعتقد أنها لغة جميلة حقًا.
موجو تعني "سحر سحري" أو "قوى سحرية". لقد اعتقدنا أن هذا هو الاسم المناسب للغة التي تجلب قوى سحرية إلى بايثون: python:، بما في ذلك فتح نموذج برمجة مبتكر للمسرعات والأنظمة الأخرى غير المتجانسة المنتشرة في الذكاء الاصطناعي اليوم.
غويدو فان روسوم، ديكتاتور خير مدى الحياة وكريستوفر آرثر لاتنر ، مخترع ومبدع وقائد معروف في نطق الموجوب =)
حسب الوصف
من يدري أن لغات البرمجة هذه ستكون سعيدة للغاية، لأن Mojo يستفيد من الدروس الهائلة المستفادة من اللغات الأخرى Rust وSwift وJulia وZig وNim وما إلى ذلك.
[جديد]
يقوم Github الآن بالكشف التلقائي عن كود Mojo!
إطار عمل HTTP بسيط وسريع لـ Mojo! مثالية لبناء خدمات الويب وواجهات برمجة التطبيقات البسيطة. للموجيكيين
إطار قياس أداء تطبيقات LLama
الترجمة الآلية لرمز Python إلى Mojo
أبحاث قواعد بيانات لغة البرمجة
19 أكتوبر 2023، Mojo متوفر الآن على نظام Mac! استخدم وحدة تحكم المطور
كريس لاتنر: مستقبل البرمجة والذكاء الاصطناعي | ليكس فريدمان بودكاست #381
شرح نظام النوع Mojo وPython | كريس لاتنر وليكس فريدمان
هل يستطيع موجو تشغيل كود بايثون؟ | كريس لاتنر وليكس فريدمان
التحول من لغة البرمجة بايثون إلى موجو | كريس لاتنر وليكس فريدمان
موضوع جديد على GitHub موجو لانج. حتى تتمكن من متابعته.
جويدو فان روسوم حول Mojo = Python مع أداء C++/GPU؟
هيكل الموتر مع بعض العمليات الأساسية رقم 251
مصفوفة fn مع numpy #267
تحديثات حول عمليات إغلاق lambda
parameter
ووظائف الترتيب العالي في mojo #244
25 مايو 2023، Guido van Rossum (gvanrossum#8415)، المبدع والفخري لـ BDFL لـ Python، قم بزيارة Mojo Public Discord Chat
في انتظار تسليط الضوء على بناء جملة Mojo في GitHub
إصدار موجوري الجديد 2023-05-24
[قديم]
موجو
brew install hyperfine
brew install macchina
pip3 install numpy matplotlib scipy
brew install silicon
إصدارات بايثون/موجو/كودون/رست
> 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)
دعونا نجد تسلسل فيبوناتشي حيث
ن = 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 '
النتيجة: انتهاء المهلة، لقد ألغيت الحساب بعد دقيقة واحدة
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 '
نتيجة :
المعيار 1: معايير python3/fibonacci_sequence/python_iteration.py
الوقت (المتوسط ± σ): 16374.7 s ± 904.0 s [المستخدم: 11483.5 s، النظام: 3680.0 s]
النطاق (الحد الأدنى … الحد الأقصى): 15361.0 ميكروثانية … 22863.3 ميكروثانية 100 أشواط
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 '
نتيجة :
المعيار 1: معايير python3/fibonacci_sequence/ pycache /python_iteration.cpython-311.pyc
الوقت (المتوسط ± σ): 16584.6 s ± 761.5 s [المستخدم: 11451.8 s، النظام: 3813.3 s]
النطاق (الحد الأدنى … الحد الأقصى): 15592.0 ميكروثانية … 20953.2 ميكروثانية 100 أشواط
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 '
النتيجة: انتهاء المهلة، لقد ألغيت الحساب بعد دقيقة واحدة
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 '
نتيجة :
المعيار 1: معايير تشغيل موجو/fibonacci_sequence/mojo_iteration.mojo
الوقت (المتوسط ± σ): 43852.7 s ± 1353.5 s [المستخدم: 38156.0 s، النظام: 10407.3 s]
النطاق (الحد الأدنى … الحد الأقصى): 42033.6 ميكروثانية … 49357.3 ميكروثانية 100 أشواط
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 '
نتيجة :
المعيار 1: ./benchmarks/fibonacci_sequence/mojo_iteration
الوقت (المتوسط ± σ): 934.6 s ± 468.9 s [المستخدم: 409.8 s، النظام: 247.8 s]
النطاق (الحد الأدنى … الحد الأقصى): 552.7 ميكروثانية … 4522.9 ميكروثانية 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 benchmarks/fibonacci_sequence/codon_recursion.json ' codon run --release benchmarks/fibonacci_sequence/codon_recursion.codon '
النتيجة: انتهاء المهلة، لقد ألغيت الحساب بعد دقيقة واحدة
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 '
نتيجة :
المعيار 1: تشغيل الكودون - معايير الإصدار/fibonacci_sequence/codon_iteration.codon
الوقت (المتوسط ± σ): 628060.1 s ± 10430.5 s [المستخدم: 584524.3 s، النظام: 39358.5 s]
النطاق (الحد الأدنى ... الحد الأقصى): 612742.5 ميكروثانية ... 662716.9 ميكروثانية 100 أشواط
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 '
نتيجة :
المعيار 1: ./benchmarks/fibonacci_sequence/codon_iteration
الوقت (المتوسط ± σ): 2732.7 s ± 1145.5 s [المستخدم: 1466.0 s، النظام: 1061.5 s]
النطاق (الحد الأدنى … الحد الأقصى): 2036.6 ميكروثانية … 13236.3 ميكروثانية 100 أشواط
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 '
النتيجة: انتهاء المهلة، لقد ألغيت الحساب بعد دقيقة واحدة
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 '
نتيجة :
المعيار 1: ./benchmarks/fibonacci_sequence/rust_iteration
الوقت (المتوسط ± σ): 848.9 s ± 283.2 s [المستخدم: 371.8 s، النظام: 261.4 s]
النطاق (الحد الأدنى … الحد الأقصى): 525.9 ميكروثانية … 2607.3 ميكروثانية 100 أشواط
# 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
إحصائيات متقدمة
كل ذلك معًا
تم تكبيره
مفصلة واحدة تلو الأخرى
الأماكن
ولكن هنا أسئلة كثيرة:
mojo run
ببطء شديد؟codon run --release
بطيء جدًا؟run
Mojo/Codon؟لذلك، يمكننا القول أن Mojo سريع مثل Rust على نظام Mac!
دعونا نجد مجموعة ماندلبروت حيث
العرض = 960
الارتفاع = 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 '
نتيجة :
المعيار 1: معايير python3/multibrot_set/ pycache /multibrot.cpython-311.pyc
الوقت (المتوسط ± σ): 5444155.4 s ± 23059.7 s [المستخدم: 5419790.1 s، النظام: 18131.3 s]
النطاق (الحد الأدنى ... الحد الأقصى): 5408155.3 ميكروثانية ... 5490548.4 ميكروثانية 10 أشواط
نسخة Mojo بدون تحسين.
# 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 '
نتيجة :
المعيار 1: ./benchmarks/multibrot_set/multibrot
الوقت (المتوسط ± σ): 135880.5 s ± 1175.4 s [المستخدم: 133309.3 s، النظام: 1700.1 s]
النطاق (الحد الأدنى ... الحد الأقصى): 134639.9 ميكروثانية ... 137621.4 ميكروثانية 10 أشواط
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 '
نتيجة :
المعيار 1: ./benchmarks/multibrot_set/multibrot_mojo_parallelize
الوقت (المتوسط ± σ): 7139.4 s ± 596.4 s [المستخدم: 36535.2 s، النظام: 6670.1 s]
النطاق (الحد الأدنى … الحد الأقصى): 6222.6 ميكروثانية … 8269.7 ميكروثانية 10 أشواط
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()
للتشغيل التجريبي أو الرسم (رمز إلغاء التعليق في الملف)
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
بناء وتشغيل
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 '
نتيجة :
المعيار 1: ./benchmarks/multibrot_set/multibrot_codon
الوقت (المتوسط ± σ): 44184.7 s ± 1142.0 s [المستخدم: 248773.9 s، النظام: 72935.3 s]
النطاق (الحد الأدنى … الحد الأقصى): 42963.8 ميكروثانية … 46456.2 ميكروثانية 10 أشواط
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
إحصائيات متقدمة
كل ذلك معًا
تم تكبيره
مفصلة واحدة تلو الأخرى
الأماكن
الروابط:
ماندلبروت = مولتيبروت power = 2
z = z ** power + c # You can change this for different set
وسادة مدمجة ImagingEffectMandelbrot
نسخة Exaloop Codon من ماندلبروت
نسخة موجو المعيارية من ماندلبروت
مجمع موجو Squared_norm
ماتبلوتليب ماندلبروت
في علوم الكمبيوتر، خوارزمية البحث الثنائي، والمعروفة أيضًا باسم البحث بنصف الفاصل الزمني، أو البحث اللوغاريتمي، أو القطع الثنائي، هي خوارزمية بحث تبحث عن موضع القيمة المستهدفة ضمن مصفوفة مرتبة.
لنقم ببعض التعليمات البرمجية باستخدام Python وMojo وSwift وV وJulia وNim وZig.
ملحوظة: بالنسبة لإصدارات Python و Mojo ، أترك بعض التحسين وأجعل الكود مشابهًا للقياس والمقارنة.
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 (),
)
إنه أول بحث ثنائي مكتوب في مجتمع Mojoby (@ego) ويتم نشره في 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
إنها أول مشاركة Fizz مكتوبة في Mojo على الإطلاق بواسطة المجتمع (@Ego).
سوف نستخدم الخوارزمية من المرجع المعروف لكتاب الخوارزميات مقدمة إلى الخوارزميات A3
وقد أدت شهرتها إلى الاستخدام الشائع للاختصار " CLRS " (كورمن، ليسرسون، ريفست، ستاين)، أو في الطبعة الأولى، " CLRS " (كورمن، ليسرسون، ريفست).
الفصل الثاني "2.3.1 نهج فرق تسد".
% % 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
يمكنك استخدامه مثل:
# Usage: merge_sort
var A = create_vertor ()
merge_sort ( A , 0 , len ( A ) - 1 )
print ( len ( A ))
print ( A [ 0 ], A [ 99 ])
المدمج from Sort import sort
سريع أسرع قليلاً من تنفيذنا، ولكن يمكننا تحسينه من خلال التعمق في اللغة وكالمعتاد مع الخوارزميات =) ونماذج البرمجة.
لانج | ثانية |
---|---|
بايثون merge_sort | 0.019136679 |
نوع بايثون المدمج | 0.000199228 |
موجو merge_sort | 0.000011346 |
موجو المدمج في النوع | 0.000002988 |
دعونا نبني مؤامرة لهذا الجدول.
#%%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 ()
ملاحظات المؤامرة، أكثر هو أفضل وأسرع.
أوصي بشدة بالبدء من هنا HelloMojo وفهم معلمات [المعلمة] و [تعبيرات المعلمة] هنا. كما في هذا المثال:
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 ()
وقت الترجمة [المعلمات]: fn concat[len1: Int, len2: Int]
.
وقت التشغيل (Args) : fn concat(lhs: MySIMD, rhs: MySIMD)
.
معلمات بناء الجملة PEP695 بين قوسين مربعين []
.
الآن في بايثون:
def func ( a : _T , b : _T ) -> _T :
...
الآن في موجو:
def func [ T ]( a : T , b : T ) -> T :
...
تتم تسمية [المعلمات] ولها أنواع مثل القيم العادية في برنامج Mojo، ولكن يتم تقييم parameters[]
في وقت الترجمة .
قد يستخدم برنامج وقت التشغيل قيمة [المعلمات] - لأنه يتم حل المعلمات في وقت الترجمة قبل أن يحتاجها برنامج وقت التشغيل - لكن تعبيرات معلمات وقت الترجمة قد لا تستخدم قيم وقت التشغيل.
النوع Self
من PEP673
fn __sub__ ( self , rhs : Self ) - > Self :
let result = MySIMD [ size ]()
for i in range ( size ):
result [ i ] = self [ i ] - rhs [ i ]
return result
في المستندات، يمكنك العثور على حقول الكلمات، وهي تُعرف أيضًا باسم سمات الفئة في Python.
لذلك، يمكنك الاتصال بهم 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
لذا فإن String
هي اسم مستعار فقط لشيء مثل DynamicVector[SIMD[DType.si8, 1]]
.
VariadicList
لتدمير/تفريغ/الوصول إلى الوسائط 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 )
إنه مفيد جدًا لإنشاء المجموعات الأولية. يمكننا أن نكتب مثل هذا:
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 ])
اقرأ المزيد عن الدالة def و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 )
بالنسبة للسلسلة، يمكنك استخدام شريحة مدمجة مع تنسيق شريحة السلسلة [بدء: نهاية: خطوة].
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 ])
هناك بعض المشاكل مع يونيكود، عند التقطيع:
let hello_mojo_unicode = String ( "Hello Mojo!" )
print ( "Unicode efore last 2 chars:" , hello_mojo_unicode [ 0 : - 2 ])
# no result, silents
وهنا شرح وبعض المناقشة.
mbstowcs - تحويل سلسلة متعددة البايت إلى سلسلة ذات أحرف واسعة
مصمم struct
المعروف أيضًا باسم Python @dataclass
. سيقوم بإنشاء الأساليب __init__
و __copyinit__
و __moveinit__
لك تلقائيًا.
@ value
struct dataclass :
var name : String
var age : Int
لاحظ أن مصمم @value
يعمل فقط على الأنواع التي copyable
و/أو movable
أعضائها.
أنواع تافهة. يخبر مصمم الديكور Mojo أن النوع يجب أن يكون قابلاً للنسخ __copyinit__
ومنقول __moveinit__
. كما يخبر Mojo بتفضيل تمرير القيمة في سجلات وحدة المعالجة المركزية. يسمح structs
باختيار تمريرها في register
بدلاً من المرور عبر memory
.
@ register_passable ( "trivial" )
struct Int :
var value : __mlir_type . `!pop.scalar<index>`
أدوات الديكور التي توفر التحكم الكامل في تحسينات المترجم . يوجه المترجم إلى تضمين هذه الوظيفة دائمًا عند استدعائها.
@ 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
يمكن وضعها على وظائف متداخلة تلتقط قيم وقت التشغيل لإنشاء عمليات إغلاق التقاط "بارامترية". يسمح بتمرير عمليات الإغلاق التي تلتقط قيم وقت التشغيل كقيم معلمات.
@ always_inline
@ parameter
fn test (): return
بعض الأمثلة على الصب
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 - قم بتخزين عنوان باستخدام DType معين، مما يسمح لك بتخصيص البيانات وتحميلها وتعديلها مع سهولة الوصول إلى عمليات 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 ()
يمكن للهيكل أن يقلل من خطورة المؤشرات عن طريق الحد من السكوب.
مقالة ممتازة على مدونة Mojo Dojo حول DTypePointer هنا
بالإضافة إلى مثاله Matrix Struct وDTypePointer
يقوم المؤشر بتخزين عنوان لأي register_passable type
، ويخصص كمية n
منها إلى 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 ()
مقالة كاملة عن المؤشر
بالإضافة إلى المؤشر والهيكل
الوحدات الجوهرية هي نوع من الواجهات الخلفية للتنفيذ :
موجو-> لهجات MLIR -> واجهات التنفيذ الخلفية مع كود التحسين والبنيات.
MLIR عبارة عن ساحرة بنية تحتية للمترجم تنفذ العديد من عمليات التحويل والتحسين لمختلف لغات البرمجة والبنيات .
لا يوفر MLIR نفسه وظيفة مباشرة للتفاعل مع مكالمات نظام التشغيل.
وهي عبارة عن واجهات منخفضة المستوى لخدمات نظام التشغيل، ويتم التعامل معها عادةً على مستوى لغة البرمجة المستهدفة أو نظام التشغيل نفسه. تم تصميم MLIR ليكون مستقلاً عن اللغة والهدف، وينصب تركيزه الأساسي على توفير تمثيل وسيط لإجراء التحسينات. لإجراء عمليات استدعاء نظام التشغيل في MLIR، نحتاج إلى استخدام واجهة خلفية خاصة بالهدف.
ولكن مع هذه execution backends
، يمكننا بشكل أساسي الوصول إلى مكالمات نظام التشغيل. ولدينا العالم كله من عناصر C/LLVM/Python تحت الغطاء.
دعونا نلقي نظرة سريعة على ذلك في الممارسة العملية:
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 )
في هذا المثال البسيط، استخدمنا external_call
للحصول على متغير بيئة نظام التشغيل بنوع الصب بين وظائف Mojo وlibc. رائع جدا، نعم!
لدي الكثير من الأفكار في هذا الموضوع وأنتظر بفارغ الصبر الفرصة لتنفيذها قريباً. اتخاذ الإجراءات يمكن أن يؤدي إلى نتائج مذهلة =)
دعونا نفعل شيئًا مثيرًا للاهتمام - استدعاء gethostname libc function
.
تحتوي الوظيفة على هذه الواجهة int gethostname (char *name, size_t size)
.
لذلك يمكننا استخدام وظيفة المساعدة External_call من وحدة Intrinsics أو كتابة MLIR الخاص.
دعنا نذهب الكود:
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 ]
دعونا نفعل بعض الأشياء للويب مع موجو. ليس لدينا إمكانية الوصول إلى الإنترنت على موقع Stadium.modular.com ولكن يمكننا سرقة بعض الأشياء المثيرة للاهتمام مثل TCP على جهاز واحد.
لنكتب أول كود خادم عميل TCP في Mojo باستخدام PythonInterface
يجب عليك إنشاء دفترين منفصلين، وتشغيل TCPSocketServer أولاً ثم TCPSocketClient .
نسخة بايثون من هذا الكود هي نفسها تقريبًا، باستثناء:
with
بناء الجملةlet
للتخصيصa, b = (1, 2)
بعد خادم TCP في Mojo، نمضي قدمًا =)
إنه أمر جنوني، ولكن دعونا نحاول تشغيل FastAPI لخادم الويب Python الحديث باستخدام Mojo!
نحتاج إلى تحميل رمز FastAPI إلى الملعب. لذلك، على جهازك المحلي القيام به
pip install --target=web fastapi uvicorn
tar -czPf web.tar.gz web
وتحميل web.tar.gz
إلى الملعب عبر واجهة الويب.
ثم نحتاج إلى install
، فقط ضعه في المجلد المناسب:
% % 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 ())
كالعادة، يجب عليك إنشاء دفترين منفصلين، وتشغيل FastAPI أولاً ثم FastAPIClient .
هناك الكثير من الأسئلة المفتوحة، ولكن في الأساس نحن نحقق الهدف.
موجو أحسنت!
بعض الأسئلة المفتوحة:
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
المستقبل يبدو متفائلا جدا!
الروابط:
Benchmark Mojo vs Numba بواسطة نيك ووجان
استخدامات الوقت بقلم Samay Kapadia @Zalando
الاتصال بملعب موجو الخاص بك من VSCode أو DataSpell
بواسطة مكسيم زاكس
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 ()
تنفيذ ليبك
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
الملف في المستكشف واضغط على Open With > Editor
select all
، ثم copy
.ipynb
يعرضه Github بشكل صحيح، وبعد ذلك إذا أراد شخص ما تجربة الكود في ملعبه، فيمكنه نسخ الكود الأولي ولصقه.
هذه وجهة نظري الشخصية فلا تحكم علي بقسوة.
لا أستطيع أن أقول إن موجو هي لغة برمجة سهلة التعلم، مثل لغة بايثون كمثال.
يتطلب الأمر الكثير من الفهم والصبر والخبرة في أي لغة برمجة أخرى.
إذا كنت ترغب في بناء شيء ليس تافهاً، فسيكون الأمر صعباً ولكنه مضحك!
لقد مر أسبوعان منذ أن بدأت هذه الرحلة ، ويسعدني أن أشارككم أنني أصبحت الآن على دراية جيدة بموجو.
لقد بدأت تعقيدات بنيتها وصياغتها تتكشف أمام عيني ، وأنا ممتلئ بفهم جديد.
أنا فخور بأن أقول إنني أستطيع الآن صياغة التعليمات البرمجية بهذه اللغة بثقة، مما يسمح لي بإحياء مجموعة متنوعة من الأفكار .
Mojo هي لغة برمجة Modular Inc. لماذا موجو ناقشنا هنا. نحن نعرف القليل عن الشركة، ولكن لها اسم رائع جدًا Modular
، والذي يمكن الإشارة إليه:
"بعبارة أخرى: موجو ليس سحرًا، إنه معياري."
كل شيء عن الحوسبة والبرمجة والذكاء الاصطناعي/التعلم الآلي. اسم نطاق جيد جدًا يصف بدقة معنى الشركة.
هناك بعض المواد الإضافية حول قصة العلامة التجارية لـ Modular ومساعدة Modular على إضفاء الطابع الإنساني على الذكاء الاصطناعي من خلال العلامة التجارية
أود أن أحكي قصة عن مشكلة Python Enum. كمهندسي برمجيات، غالبًا ما نلتقي به على شبكة الإنترنت. افترض أن لدينا مخطط قاعدة البيانات (PostgreSQL) مع enum
الحالة:
CREATE TYPE public .status_type AS ENUM (
' FIRST ' ,
' SECOND '
);
في كود Python، نحتاج إلى أسماء وقيم كسلاسل (بافتراض أننا نستخدم GraphQL مع بعض أنواع ENUM لواجهة الواجهة الأمامية لدينا)، ونحتاج إلى الحفاظ على ترتيبها ولدينا القدرة على مقارنة هذه التعدادات:
order2.status > order1.status > 'FIRST'
إنها مشكلة بالنسبة لمعظم اللغات الشائعة =) ولكن يمكننا استخدام ميزة Python little-known
وتجاوز طريقة فئة التعداد: __new__
.
MALE -> 1
، FEMALE -> 2
، كما تفعل 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
نهاية القصة. واستخدم رؤية Python ENUM
هذه لترميزك الجيد!