اصل ماجرا

کدهای پایتون که از حلقه‌های معمولی استفاده می‌کنن، سرعت را به شدت کم می‌کنن. با استفاده از توابع همگانی، انتشار خودکار، عملیات‑در‑جا و نماهای حافظه می‌شه محاسبه‌ها را به C منتقل کرد و از تخصیص‌های اضافی جلوگیری کرد. این تکنیک‌ها در مثال‌های واقعی سرعت را تا ۵۰ برابر افزایش میدن.

متن کامل ترجمه‌شده

3 اسباب بازی NumPy برای عملکرد شماری در این مقاله، ما سه اسباب بازی NumPy ضروری برای بهینه سازی کد شما را پوشش می دهیم: وکتور سازی و پخش، عملیات در محل، و استفاده از دیدگاه های حافظه به جای کپی ها. # معرفی سیستم محاسبات علمی و یادگیری ماشین Python به شدت به NumPy بستگی دارد. این به عنوان موتور عملکردی پشت کتابخانه های مانند Pandas، Scikit-Learn، SciPy، و PyTorch عمل می کند. سرعت NumPy از اجرای زیرساخت خود در C بهینه سازی، که در آن بلوک های متصل از حافظه بدون کنترل مدل اشیاء Python و تلسکوپ متحرک پردازش می شود. متاسفانه، بسیاری از دانشمندان داده و توسعه دهندگان کد NumPy را می نویسند که از این قدرت استفاده نمی کند.هنگامی که با مجموعه ای از داده های بزرگ کار می کنید، این ناخوشایند ها منجر به استفاده از RAM، از دست دادن کیش و زمان اجرا آهسته می شوند. برای نوشتن کد عددی با عملکرد بالا، شما باید بفهمید که چگونه NumPy حسابداری، توزیع حافظه و طرح داده ها را تحت کلاه مدیریت می کند. در این مقاله، ما سه چگونگی ضروری NumPy را برای بهینه سازی کد خود را پوشش می دهیم: - وکتور سازی و پخش - عملیات در محل با استفاده از outparameter - استفاده از دیدگاه های حافظه به جای نسخه ها # 1. Vectorization & Broadcasting Over Explicit Loops Explicit Python for loops بزرگترین قاتل سرعت در حسابداری عددی است. Iterating بر روی یک عنصر ساختار داده باعث می شود Python مترجم به انجام چک های نوع و روشVectorize تنها یک Wrapper کاربردی است که یک چرخه Python استاندارد و آهسته را پشت یک API پاکیزه تر اجرا می کند و مزایای عملکرد نهایی را فراهم می کند. برای بهینه سازی، شما باید کد را با استفاده از ویژگی های جهانی اصلی (ufuncs) و پخش بنویسید. پخش اجازه می دهد NumPy برای انجام عملیات بر روی مجموعه های شکل های مختلف بدون کپی کردن داده ها، پردازش عملیات به طور مستقیم در C ترکیب شده است. این رویکرد ناخودآگاه از طریق یک مجموعه 2D راند-ب-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-ر-form[0]): res[row, col] = (matrix[row, col] - col_mean) / col_std duration_loop = time.time() - start_time print(f”Nested loop processed matrix in: {duration_loop:.4f} ثانیه”) Output: Nested loop processed matrix in: 10.9986 ثانیه به جای looping، ما متغیر متوسط و استاندارد را در طول اقیانوس مستقیم (آس=0) محاسبه می کنیم. NumPy به طور خودکار این آمار 1D خلاصه را با خطوط مکتب 2D با استفاده از پخش: import numpy به عنوان np import # time Create a sample matrix (50000 rows, 1000 columns) matrix = np.random(00, 1000) start_time = time.() #Compute means and standard4f} ثانیه”) خروج: Vectorized broadcasting پردازش مارتسی در: 0.1972 ثانیه این است که ~56x سرعت! در اجرای مارتسی، عملیات مارتسی - میانه و تقسیم بعد از آن با استفاده از قوانین پخش NumPy اجرا می شود. از آنجا که مارتسی دارای شکل (50000, 1000) و میانه دارای شکل (1000,)، NumPy مفهوم استراتژیک مارتسی میانه را به شکل مارتسی را متصل می کند. زیر کلاه، این گسترش به طور فوری در حافظه بدون duplicating داده ها اتفاق می افتد، و محاسبات به دستورالعمل SIMD (یک دستورالعمل، داده های متعددی) CPU، ارائه یک سرعت بزرگ 50x +. # 2. در محل عملیات و پارامتر در هنگام نوشتن بیانات مانند y = 2 x * + 3, شما ممکن است انتظار می رود که به طوربا این حال، در زیر قفل، NumPy این بیان را قدم به قدم ارزیابی می کند: - آن را به یک مارتین موقت در حافظه اختصاص می دهد تا نتیجه 2 * x را ذخیره کند - آن را به یک مارتین دیگر برای ذخیره نتایج اضافه کردن 3 به مارتین موقت اختصاص می دهد - در نهایت این مارتین موقت دوم را به نام متغیر متصل می کند y هنگامی که با مجموعه های بسیار بزرگ (به عنوان مثال میلیون ها واردات) کار می کند، تخصیص و جمع آوری زباله این مارتین های میانگین موقت را ایجاد می کند. آن را از بین برده می کند CPA ها و محاصره های موقت حافظه را تغذیه می کند. ما می توانیم این مارتین را از طریق انجام محاسبات در محل با استفاده از فعالان مانند *= و +=،زمان() # استاندارد ریاضی زنجیره ای ایجاد آرایه های میانگین موقتی y_naive = مقیاس * x + طول کشیدن_naive = time.time() - چاپ start_time(f”تصویر زنجیره ای اجرا در: {duration_naive:.4f} ثانیه”) تولید: بیان زنجیره ای اجرا در: 0.0393 ثانیه در اینجا، ما پیش تخصیص آرایه محصول هدف = 1.2 start_time = وقت، و بار دیگر استفاده از حافظه آن برای تمام عملیات ریاضی بعدی، از بین بردن تخصیصات موقتی: import numpy به عنوان زمان واردات np # ایجاد یک آرایه 1D بزرگ از 10 میلیون عناصر x = np.random.rand(10000000) مقیاس = 2.5 offset_dury = 1.2 start_time = time.() # پیش تخصی”) Data Output: Optimized in-place expression executed in: 0.0133 seconds In the optimized example, we use np.multiply(x, scale, out=y_optimized) to write the result of the multiplication directly into our pre-allocated y_optimized array. Then, np.add(y_optimized, offset, out=y_optimized) adds the offset and writes the result back into the same buffer. This completely avoids allocating and garbage-collecting temporary buffers, saving system memory, keeping data in the CPU cache, and boosting execution speed. # 3. Memory Views vs. Memory Copies (Slicing vs. Advanced Indexing) Understanding when Numy returns a view of an array versus a copy is one of the most critical topics in numericalاین کار در $O(N)$ زمان و فضای خطی انجام می شود. قطعات پایه (با استفاده از شروع، متوقف، و شاخص قدم، به عنوان مثال arr[0:10:2]) همیشه یک نگاه را باز می کند. در مقابل، indexing پیشرفته (با استفاده از لیست های شاخص یا ماسک های بولو، به عنوان مثال arr[[[0, 2, 4]]) همیشه یک نسخه را باز می کند. اگر شما فقط نیاز به خواندن و یا به روز رسانی بخش های کوچک از یک شاخص، با استفاده از indexing پیشرفته، منجر به تحویل های حافظه بزرگ، غیر ضروری است. در اینجا، ما سعی می کنیم تا یک مکتب بزرگ 2D مکتب (هر رده ثانویه و کلمه) را با عبور از لیست های شاخص. این باعث می شود NumPy برای تخصیص یک مکتب بزرگ جدید و تمام عناصر راوقت() - start_time print(f”Advanced indexing copy completed in: {duration_copy:.4f} seconds”) Output: Advanced indexing copy completed in: 0.1575 seconds Now let’s perform the same operation, but use basic slicing. instead of copying data, NumPy adjusts the step metadata to point to the same buffer instantly: import numpy as np import time.() - start_time(f”Basic slicing view completed in: {duration_view:.8f} seconds”) Output: Basic slicing returns a zero-copy view instantly sub_matrix_view = matrix[2,2] :: duration_view = time.() start_time(f”Basic slicing view completed in: {duration_view:.8f} seconds”) Output: Basicاین عمل در کمتر از یک میکرو ثانیه انجام می شود، بدون توجه به اندازه مارتینکس است. با این حال، در مورد تبادل آگاهی داشته باشید: از آنجایی که نگاه به همان حافظه حافظه تقسیم می کند، تغییر sub_matrix_view نیز می تواند مارتینکس اصلی را تغییر دهد. اگر شما باید از تغییر مارتینیک اصلی اجتناب کنید، شما باید بلافاصله به .copy() تماس بگیرید. # Wrapping Up نوشتن خالص، عملکردی NumPy کد نیاز به تغییر نحوه تفکر شما در مورد حلقه ها، توزیع حافظه، و ساختار داده. با اجتناب از مفاهیم استاندارد Python به نفع مکانییک NumPy اصلی، شما می توانید دکمه های رایانه ای را از بین ببرید. برای تکرار: - Ditch Python loops و np.کاپیتان برای استفاده از قطع کردن فوری، کپی بدون کپی به جای کپی های پیشرفته پیشرفته گران است که این سه مدل طراحی عملکرد را شامل می کند تا خطوط پردازش داده های خود را نرم، سریع و قابل گسترش برای حملات کار تولید نگه می دارد. متیو میگو (@mattmayo13) دارای مدرک کارشناسی ارشد علوم کامپیوتر و مدرک کارشناسی ارشد در معدن داده ها است. به عنوان مدیر عامل KDnuggets & Statology، و مدیر کمک کننده در Machine Learning Mastery، متیو قصد دارد مفهوم های علمی داده های پیچیده را در دسترس قرار دهد. علاقه های حرفه ای او شامل پردازش زبان طبیعی، مدل های زبان، الگوریتم های یادگیری ماشین، و کشف AI جدید است. او توسط یک ماموریت برای دموکراسی دانش در جامعه علوم داده ها هدایت شده است. متیو از سن 6 سالگی است که کد می کند

چرا مهمه؟

حلقه‌های پایتونی و کپی‌های حافظه‌ای باعث مصرف RAM زیاد و کش‌میزان میشن؛ متخصصان داده و مهندسان ML که با ماتریس‌های بزرگ کار می‌کنن، با این روش‌ها می‌تونن زمان پردازش را به‌طور چشمگیری کاهش بدن. خواننده باید این نکات را بگیرد تا برنامه‌های عددی‌اش مقیاس‌پذیر و بهینه بمانند.

به درد کی می‌خوره؟

• متخصصان داده • مهندسان یادگیری ماشین • برنامه‌نویسان پایتون علمی • تیم‌های تحقیق و توسعه

تو عمل چی کار کنیم؟

پس از خواندن این مقاله می‌توانید کدهای موجود را با توابع ufunc و پارامتر out بازنویسی کنید، از برش‌های ساده به‌جای ایندکس پیشرفته استفاده کنید و به‌سرعت بهبود عملکرد در پردازش‌های بزرگ دست یابید. این کار نه تنها زمان اجرا را کم می‌کند، بلکه مصرف حافظه را نیز به‌طور قابل‌توجهی کاهش می‌دهد.

نظر Blue IT News

به‌کارگیری این ترفندها در پروژه‌های تولیدی می‌تواند هزینه‌های زیرساختی را کاهش دهد؛ توصیه می‌کنیم قبل از هر بهینه‌سازی، پروفایل دقیق بگیرید تا بیشترین بازده را از هر تغییر ببینید.

<div class=“disclosure”> این صفحه ترجمه و تفسیر کاملی از گزارش اصلی Kdnuggets است که توسط تیم تحریریه بلو آی تی نیوز به فارسی ترجمه و تحلیل شده. برای مشاهده نسخه اصلی، به منبع مراجعه کنید. </div>