কখনও কখনও আপনার অ-অহংকারমূলক নিম্পি কোডটি লিখতে হবে যদি আপনি সত্যিই আপনার গণনাটি গতি বাড়িয়ে তুলতে চান যা আপনি দেশী আঙ্কুল দিয়ে না করতে পারেন।
numba
আপনার পাইথন কোডটি নিম্ন-স্তরের সি তে সংকলন করে যেহেতু প্রচুর আর্দ্রতা নিজেই সাধারণত সি এর মতো দ্রুত হয় তাই আপনার সমস্যাটি যদি আঙ্কুর সাথে দেশীয় ভেক্টরাইজেশনকে ndণ না দেয় তবে এটি বেশিরভাগ ক্ষেত্রেই কার্যকর হয়ে যায়। এটি একটি উদাহরণ (যেখানে আমি ধরে নিয়েছি যে সূচকগুলি সুসংগত এবং সাজানো রয়েছে, যা উদাহরণের ডেটাতেও প্রতিফলিত হয়):
import numpy as np
import numba
# use the inflated example of roganjosh https://stackoverflow.com/a/58788534
data = [1.00, 1.05, 1.30, 1.20, 1.06, 1.54, 1.33, 1.87, 1.67]
index = [0, 0, 1, 1, 1, 1, 2, 3, 3]
data = np.array(data * 500) # using arrays is important for numba!
index = np.sort(np.random.randint(0, 30, 4500))
# jit-decorate; original is available as .py_func attribute
@numba.njit('f8[:](f8[:], i8[:])') # explicit signature implies ahead-of-time compile
def diffmedian_jit(data, index):
res = np.empty_like(data)
i_start = 0
for i in range(1, index.size):
if index[i] == index[i_start]:
continue
# here: i is the first _next_ index
inds = slice(i_start, i) # i_start:i slice
res[inds] = data[inds] - np.median(data[inds])
i_start = i
# also fix last label
res[i_start:] = data[i_start:] - np.median(data[i_start:])
return res
আইপিথনের %timeit
যাদু ব্যবহার করে এখানে কিছু সময় দেওয়া হল :
>>> %timeit diffmedian_jit.py_func(data, index) # non-jitted function
... %timeit diffmedian_jit(data, index) # jitted function
...
4.27 ms ± 109 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
65.2 µs ± 1.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
প্রশ্নগুলিতে আপডেট হওয়া উদাহরণস্বরূপ ডেটা ব্যবহার করে এই সংখ্যাগুলি (উদাহরণস্বরূপ পাইথন ফাংশনের রানটাইম বনাম জেআইটি-এক্সিলারেটড ফান্টিটিওর রানটাইম) হ'ল
>>> %timeit diffmedian_jit.py_func(data, groups)
... %timeit diffmedian_jit(data, groups)
2.45 s ± 34.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
93.6 ms ± 518 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
এটি ক্ষুদ্র ক্ষেত্রে 65x স্পিডআপ এবং বৃহত্তর ক্ষেত্রে 26x গতিসম্পন্ন (অবশ্যই ধীর লুপী কোডের সাথে তুলনা করে) ত্বকযুক্ত কোড ব্যবহার করে। আরেকটি উত্সাহটি হ'ল (নেটিভ নিম্পির সাথে আদর্শ ভেক্টরাইজেশনের বিপরীতে) আমাদের এই গতি অর্জনের জন্য অতিরিক্ত মেমরির প্রয়োজন নেই, এটি সর্বোত্তম এবং সংকলিত নিম্ন-স্তরের কোড যা চালানো শেষ হয় about
উপরের ফাংশনটি অনুমান করে যে নাম্পি ইনট অ্যারেগুলি int64
ডিফল্টরূপে হয় যা উইন্ডোজে আসলে হয় না। সুতরাং একটি বিকল্প হ'ল কল থেকে স্বাক্ষর সরিয়ে ফেলা numba.njit
, যথাযথ ইন-টাইম সংকলন ট্রিগার করে। তবে এর অর্থ এই যে ফাংশনটি প্রথম নির্বাহের সময় সংকলিত হবে, যা সময়সীমার ফলাফলের সাথে হস্তক্ষেপ করতে পারে (আমরা হয় প্রতিনিধি ডেটা ধরণের সাহায্যে ম্যানুয়ালি একবার ফাংশনটি সম্পাদন করতে পারি, বা কেবল গ্রহণ করতে পারি যে প্রথম সময় নির্বাহের কাজটি অনেক ধীর হবে, যা হওয়া উচিত) অবহেলা করা)। এটি হ'ল আমি হ'ল একটি স্বাক্ষর নির্দিষ্ট করে বাধা দেওয়ার চেষ্টা করেছি, যা সময়ের-সংকলনকে ট্রিগার করে।
যাইহোক, সঠিকভাবে জেআইটি ক্ষেত্রে ডেকরেটারটি আমাদের দরকার need
@numba.njit
def diffmedian_jit(...):
নোট করুন যে জিট-সংকলিত ফাংশনের জন্য আমি উপরে বর্ণিত সময়গুলি কেবলমাত্র ফাংশনটি সংকলিত হয়ে গেলে প্রয়োগ করা হয়। এটি হয় সংজ্ঞায় হয় (উত্সাহ সংকলন সহ, যখন একটি স্পষ্ট স্বাক্ষর প্রেরণ করা হয় numba.njit
), বা প্রথম ফাংশন কল চলাকালীন (অলস সংকলন সহ, যখন কোনও স্বাক্ষর পাস করা হয় না)numba.njit
)। যদি ফাংশনটি কেবল একবার সম্পাদন হতে চলেছে তবে এই পদ্ধতির গতির জন্য সংকলনের সময়টিও বিবেচনা করা উচিত। সংকলন + নির্বাহের মোট সময় অসম্পূর্ণ রানটাইমের চেয়ে কম হলে (সাধারণত উপরের ক্ষেত্রে এটি সত্য, যেখানে নেটিভ পাইথন ফাংশনটি খুব ধীর) এটি সাধারণত ফাংশন সংকলন করার উপযুক্ত। এটি বেশিরভাগ ক্ষেত্রে ঘটে যখন আপনি আপনার সংকলিত ফাংশনটিকে অনেকবার কল করছেন।
হিসাবে max9111 একটি মন্তব্যে উল্লেখ করা হয়েছে, এক গুরুত্বপূর্ণ বৈশিষ্ট্য numba
হল cache
শব্দ থেকে jit
। পাসিং cache=True
করতে numba.jit
, ডিস্কে কম্পাইল ফাংশন সংরক্ষণ করবে যাতে দেওয়া পাইথন মডিউল পরবর্তী সম্পাদনের সময় ফাংশন থেকে সেখানে বদলে recompiled, যা আবার অনাবশ্যক করতে পারেন দীর্ঘ রান রানটাইম লোড হবে।
scipy.ndimage.median
উত্তরে আপনি কি পরামর্শটি দিয়েছিলেন? এটি আমার কাছে মনে হয় না যে এটির প্রতি লেবেল সমান সংখ্যক উপাদান দরকার। নাকি আমি কিছু মিস করেছি?