You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: lectures/numba.md
+31-57Lines changed: 31 additions & 57 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,6 @@ translation:
21
21
Dangers and Limitations: خطرات و محدودیتها
22
22
Dangers and Limitations::Limitations: محدودیتها
23
23
'Dangers and Limitations::A Gotcha: Global Variables': 'یک مشکل: متغیرهای سراسری'
24
-
Dangers and Limitations::Caching Compiled Code: ذخیرهسازی کد کامپایلشده
25
24
Multithreaded Loops in Numba: حلقههای چندنخی در Numba
26
25
Exercises: تمرینها
27
26
---
@@ -60,9 +59,11 @@ import matplotlib.pyplot as plt
60
59
در یک {doc}`درس قبلی <need_for_speed>` درباره برداریسازی بحث کردیم،
61
60
که میتواند سرعت اجرا را با ارسال دستهای عملیات پردازش آرایه به کد کارآمد سطح پایین بهبود بخشد.
62
61
63
-
با این حال، همانطور که {ref}`قبلاً بحث شد <numba-p_c_vectorization>`، طرحهای سنتی برداریسازی، مانند آنچه در MATLAB، Julia و NumPy یافت میشود، چندین نقطه ضعف دارند.
62
+
با این حال، همانطور که {ref}`در آن درس بحث شد <numba-p_c_vectorization>`،
63
+
طرحهای سنتی برداریسازی، مانند آنچه در MATLAB، Julia و NumPy یافت میشود، نقاط ضعفی دارند.
64
64
65
-
برای مثال، میتوانند بسیار حافظهبر باشند و برای برخی الگوریتمها، برداریسازی ناکارآمد یا غیرممکن است.
65
+
* برای عملیات ترکیبی آرایهها بسیار حافظهبر هستند
66
+
* برای برخی الگوریتمها ناکارآمد یا غیرممکن است.
66
67
67
68
یک راه برای دور زدن این مشکلات، استفاده از [Numba](https://numba.pydata.org/) است، یک
68
69
**کامپایلر در زمان اجرا (JIT)** برای Python که به سمت کار عددی جهتگیری شده است.
@@ -74,6 +75,14 @@ Numba توابع را در حین اجرا به دستورالعملهای ک
74
75
علاوه بر این، Numba میتواند ترفندهای مفید دیگری نیز انجام دهد، مانند {ref}`چندنخی <multithreading>` یا
75
76
ارتباط با GPUها (از طریق `numba.cuda`).
76
77
78
+
کامپایلر JIT نامبا از بسیاری جهات مشابه کامپایلر JIT در JULIA است.
79
+
80
+
تفاوت اصلی در این است که کمتر جاهطلبانه است و تلاش میکند زیرمجموعه کوچکتری از زبان را کامپایل کند.
81
+
82
+
اگرچه این ممکن است مانند یک نقص به نظر برسد، اما از برخی جهات یک مزیت محسوب میشود.
83
+
84
+
Numba سبک، آسان برای استفاده و بسیار خوب در آنچه انجام میدهد است.
85
+
77
86
این درس ایدههای اصلی را معرفی میکند.
78
87
79
88
(numba_link)=
@@ -86,9 +95,9 @@ Numba توابع را در حین اجرا به دستورالعملهای ک
86
95
(quad_map_eg)=
87
96
### یک مثال
88
97
89
-
بیایید مسئلهای را در نظر بگیریم که برداریسازی آن دشوار است: تولید مسیر یک معادله تفاضلی با توجه به یک شرط اولیه.
98
+
بیایید مسئلهای را در نظر بگیریم که برداریسازی آن دشوار است (یعنی واگذاری آن به عملیات پردازش آرایه).
90
99
91
-
معادله تفاضلی را نگاشت درجه دوم در نظر میگیریم:
100
+
این مسئله شامل تولید مسیر از طریق نگاشت درجه دوم است:
92
101
93
102
$$
94
103
x_{t+1} = \alpha x_t (1 - x_t)
@@ -176,10 +185,10 @@ Numba تلاش میکند با استفاده از زیرساختی که [پ
176
185
177
186
* پایتون بسیار انعطافپذیر است و از این رو میتوانیم تابع qm را با انواع مختلفی فراخوانی کنیم.
178
187
* مثلاً `x0` میتواند یک آرایه NumPy یا یک لیست باشد، `n` میتواند یک عدد صحیح یا یک عدد اعشاری باشد و غیره.
179
-
* این امر *پیش*-کامپایل کردن تابع (یعنی کامپایل پیش از زمان اجرا) را دشوار میسازد.
180
-
* اما وقتی واقعاً تابع را فراخوانی میکنیم، مثلاً با اجرای `qm(0.5, 10)`، انواع `x0` و `n` مشخص میشوند.
188
+
* این امر تولید کد ماشین کارآمد *پیش از زمان اجرا* را بسیار دشوار میسازد.
189
+
* اما وقتی واقعاً تابع را *فراخوانی* میکنیم، مثلاً با اجرای `qm(0.5, 10)`، انواع `x0` و `n` مشخص میشوند.
181
190
* علاوه بر این، انواع *سایر متغیرها* در `qm`*میتوانند پس از مشخص شدن انواع ورودی استنتاج شوند*.
182
-
* بنابراین استراتژی Numba و سایر کامپایلرهای JIT این است که تا این لحظه صبر کنند و سپس تابع را کامپایل کنند.
191
+
* بنابراین استراتژی Numba و سایر کامپایلرهای JIT این است که *تا زمان فراخوانی تابع صبر کنند* و سپس کامپایل کنند.
183
192
184
193
به همین دلیل است که به آن کامپایل «درست به موقع» (just-in-time) گفته میشود.
185
194
@@ -241,14 +250,10 @@ Numba همچنین با آرایههای NumPy که انواع به خوبی
241
250
242
251
در یک محیط ایدهآل، Numba میتواند تمام اطلاعات نوع لازم را استنتاج کند.
243
252
244
-
این به آن اجازه میدهد تا کد ماشین بومی تولید کند، بدون نیاز به فراخوانی محیط زمان اجرای Python.
253
+
این به آن اجازه میدهد تا کد ماشین بومی کارآمدی تولید کند، بدون نیاز به فراخوانی محیط زمان اجرای Python.
245
254
246
255
وقتی Numba نمیتواند تمام اطلاعات نوع را استنتاج کند، خطا ایجاد میکند.
247
256
248
-
```{note}
249
-
در نسخههای قدیمیتر Numba، دکوراتور `@jit` در صورت عدم توانایی در استنتاج همه انواع، به آرامی به «حالت شیء» بازمیگشت که سرعت چندانی به همراه نداشت. نسخههای فعلی Numba به طور پیشفرض از حالت `nopython` استفاده میکنند، به این معنا که کامپایلر بر استنتاج کامل نوع اصرار دارد و در صورت شکست، خطا ایجاد میکند. اغلب در کدهای دیگر `@njit` را میبینید که صرفاً یک نام مستعار برای `@jit(nopython=True)` است. از آنجا که حالت nopython اکنون پیشفرض است، `@jit` و `@njit` معادل یکدیگرند.
250
-
```
251
-
252
257
به عنوان مثال، در تنظیم (مصنوعی) زیر، Numba قادر به تعیین نوع تابع `mean` هنگام کامپایل تابع `bootstrap` نیست
253
258
254
259
```{code-cell} ipython3
@@ -294,9 +299,7 @@ with qe.Timer():
294
299
295
300
همانطور که دیدیم، Numba باید اطلاعات نوع را روی تمام متغیرها استنتاج کند تا دستورالعملهای سریع سطح ماشین تولید کند.
296
301
297
-
برای روالهای ساده، Numba انواع را بسیار خوب استنتاج میکند.
298
-
299
-
برای روالهای بزرگتر، یا برای روالهایی که از کتابخانههای خارجی استفاده میکنند، به راحتی میتواند شکست بخورد.
302
+
برای روالهای بزرگ یا روالهایی که از کتابخانههای خارجی استفاده میکنند، این فرایند به راحتی میتواند شکست بخورد.
300
303
301
304
از این رو، بهتر است روی تسریع قطعات کوچک و حیاتی کد تمرکز کنید.
302
305
@@ -328,30 +331,12 @@ print(add_a(10))
328
331
329
332
وقتی Numba کد ماشین را برای توابع کامپایل میکند، متغیرهای سراسری را به عنوان ثابت برای اطمینان از پایداری نوع درمان میکند.
330
333
331
-
### ذخیرهسازی کد کامپایلشده
332
-
333
-
به طور پیشفرض، Numba در هر بار شروع یک نشست Python جدید، توابع را مجدداً کامپایل میکند.
334
-
335
-
برای جلوگیری از این سربار، میتوانید `cache=True` را به دکوراتور ارسال کنید:
336
-
337
-
```{code-cell} ipython3
338
-
@jit(cache=True)
339
-
def qm(x0, n):
340
-
x = np.empty(n+1)
341
-
x[0] = x0
342
-
for t in range(n):
343
-
x[t+1] = α * x[t] * (1 - x[t])
344
-
return x
345
-
```
346
-
347
-
این کد کامپایلشده را روی دیسک ذخیره میکند تا نشستهای بعدی بتوانند از مرحله کامپایل صرفنظر کنند.
348
-
349
334
(multithreading)=
350
335
## حلقههای چندنخی در Numba
351
336
352
-
علاوه بر کامپایل JIT، Numba پشتیبانی از محاسبات موازی در CPUها ارائه میدهد.
337
+
علاوه بر کامپایل JIT، Numba پشتیبانی از محاسبات موازی در CPUها و GPUها ارائه میدهد.
353
338
354
-
ابزار کلیدی برای موازیسازی در Numba تابع `prange` است که به Numba میگوید تا تکرارهای حلقه را به صورت موازی در هستههای CPU موجود اجرا کند.
339
+
ابزار کلیدی برای موازیسازی در CPUها در Numba تابع `prange` است که به Numba میگوید تا تکرارهای حلقه را به صورت موازی در هستههای موجود اجرا کند.
355
340
356
341
برای نمایش، ابتدا به یک قطعه کد ساده تکنخی (یعنی غیرموازی) نگاه میکنیم.
357
342
@@ -408,24 +393,10 @@ plt.show()
408
393
409
394
حالا فرض کنیم که جمعیت زیادی از خانوارها داریم و میخواهیم بدانیم میانه ثروت چه خواهد بود.
410
395
411
-
حل این موضوع با مداد و کاغذ آسان نیست، بنابراین به جای آن از شبیهسازی استفاده خواهیم کرد.
412
-
413
-
به طور خاص، تعداد زیادی از خانوارها را شبیهسازی میکنیم و سپس میانه ثروت را برای این گروه محاسبه میکنیم.
396
+
حل این موضوع با مداد و کاغذ آسان نیست، بنابراین به جای آن از شبیهسازی استفاده خواهیم کرد:
414
397
415
-
فرض کنیم به میانگین بلندمدت این میانه در طول زمان علاقهمند هستیم.
416
-
417
-
برای مشخصاتی که در بالا انتخاب کردهایم، میتوانیم این را با گرفتن یک مقطع عرضی یک دورهای از میانه ثروت گروه در پایان یک شبیهسازی طولانی محاسبه کنیم.
418
-
419
-
علاوه بر این، به شرطی که دوره شبیهسازی به اندازه کافی طولانی باشد، شرایط اولیه اهمیتی ندارند.
420
-
421
-
(این به دلیل [ارگودیسیته](https://python.quantecon.org/finite_markov.html#id15) است.)
422
-
423
-
بنابراین، به طور خلاصه، قصد داریم 50,000 خانوار را شبیهسازی کنیم با
424
-
425
-
1. تنظیم خودسرانه ثروت اولیه به 1 و
426
-
1. شبیهسازی رو به جلو در زمان برای 1,000 دوره.
427
-
428
-
سپس میانه ثروت را در پایان دوره محاسبه خواهیم کرد.
398
+
1. تعداد زیادی از خانوارها را در طول زمان شبیهسازی میکنیم
399
+
2. میانه ثروت را محاسبه میکنیم
429
400
430
401
در اینجا کد است:
431
402
@@ -479,6 +450,8 @@ with qe.Timer():
479
450
480
451
افزایش سرعت قابل توجه است.
481
452
453
+
توجه داشته باشید که موازیسازی را در سطح خانوارها انجام میدهیم نه در طول زمان -- بهروزرسانیهای یک خانوار در دورههای زمانی مختلف ذاتاً ترتیبی هستند.
454
+
482
455
## تمرینها
483
456
484
457
```{exercise}
@@ -534,7 +507,8 @@ with qe.Timer():
534
507
:label: speed_ex2
535
508
```
536
509
537
-
در سری سخنرانی [مقدمهای بر اقتصاد کمی با Python](https://intro.quantecon.org/intro.html) میتوانید همه چیز درباره زنجیرههای مارکوف حالت محدود یاد بگیرید.
510
+
در سری درسهای [مقدمهای بر اقتصاد کمی با
511
+
Python](https://intro.quantecon.org/intro.html) میتوانید همه چیز درباره زنجیرههای مارکوف حالت محدود یاد بگیرید.
538
512
539
513
فعلاً، فقط روی شبیهسازی یک مثال بسیار ساده از چنین زنجیرهای تمرکز کنیم.
540
514
@@ -721,7 +695,7 @@ $$
721
695
722
696
که در آن
723
697
724
-
1. $\beta$ یک فاکتور تنزیل است،
698
+
1. $\beta$ یک ضریب تنزیل است،
725
699
2. $n$ تاریخ انقضا است،
726
700
2. $K$ قیمت اعمال است و
727
701
3. $\{S_t\}$ قیمت دارایی پایه در هر زمان $t$ است.
@@ -742,15 +716,15 @@ $$
742
716
h_{t+1} = \rho h_t + \nu \eta_{t+1}
743
717
$$
744
718
745
-
در اینجا $\{\xi_t\}$ و $\{\eta_t\}$ IID و نرمال استاندارد هستند.
719
+
در اینجا $\{\xi_t\}$ و $\{\eta_t\}$ مستقل و همتوزیع و نرمال استاندارد هستند.
746
720
747
721
(این یک مدل **نوسان تصادفی** است، که در آن نوسان $\sigma_t$ در طول زمان تغییر میکند.)
748
722
749
723
از مقادیر پیشفرض `μ, ρ, ν, S0, h0 = 0.0001, 0.1, 0.001, 10, 0` استفاده کنید.
750
724
751
725
(در اینجا `S0` همان $S_0$ و `h0` همان $h_0$ است.)
752
726
753
-
با تولید $M$ مسیر $s_0, \ldots, s_n$، تخمین Monte Carlo را محاسبه کنید
727
+
با تولید $M$ مسیر $s_0, \ldots, s_n$، تخمین مونتکارلو را محاسبه کنید
0 commit comments