মতলবের ইন্টিগ্রাল আউটপারফর্ম স্কিপিতে ইন্টিগ্রেটেড.কোয়াড হয় কেন?


13

মাতলাব যেভাবে সংখ্যার একীকরণ বনাম স্কিপি পরিচালনা করে তা নিয়ে আমি কিছুটা হতাশার মুখোমুখি হয়েছি। আমি নীচে আমার পরীক্ষার কোডে নিম্নলিখিত পার্থক্যগুলি পর্যবেক্ষণ করছি:

  1. মতলব সংস্করণ আমার অজগর সমতুলের চেয়ে গড়ে 24 গুণ দ্রুত গতিতে চলে !
  2. মতলবের সংস্করণ সতর্কতা ছাড়াই অবিচ্ছেদ্য গণনা করতে সক্ষম, যখন অজগর ফেরত দেয় nan+nanj

উল্লিখিত দুটি দফার সম্মানের সাথে পাইথনে একই কর্মক্ষমতা পাওয়ার জন্য আমি কী করতে পারি? ডকুমেন্টেশন অনুসারে উভয় পদ্ধতিতে অবিচ্ছেদ্য আনুমানিক জন্য "বৈশ্বিক অভিযোজিত চতুর্ভুজ" ব্যবহার করা উচিত।

নীচে দুটি সংস্করণে কোডটি রয়েছে (পাইথনের সাথে প্রায় একইরকম প্রয়োজন হলেও একটি অবিচ্ছেদ্য ফাংশন তৈরি করা যাতে এটি জটিল ইন্টিগ্রেন্ডগুলি পরিচালনা করতে পারে))

পাইথন

import numpy as np
from scipy import integrate
import time

def integral(integrand, a, b,  arg):
    def real_func(x,arg):
        return np.real(integrand(x,arg))
    def imag_func(x,arg):
        return np.imag(integrand(x,arg))
    real_integral = integrate.quad(real_func, a, b, args=(arg))
    imag_integral = integrate.quad(imag_func, a, b, args=(arg))   
    return real_integral[0] + 1j*imag_integral[0]

vintegral = np.vectorize(integral)


def f_integrand(s, omega):
    sigma = np.pi/(np.pi+2)
    xs = np.exp(-np.pi*s/(2*sigma))
    x1 = -2*sigma/np.pi*(np.log(xs/(1+np.sqrt(1-xs**2)))+np.sqrt(1-xs**2))
    x2 = 1-2*sigma/np.pi*(1-xs)
    zeta = x2+x1*1j
    Vc = 1/(2*sigma)
    theta =  -1*np.arcsin(np.exp(-np.pi/(2.0*sigma)*s))
    t1 = 1/np.sqrt(1+np.tan(theta)**2)
    t2 = -1/np.sqrt(1+1/np.tan(theta)**2)
    return np.real((t1-1j*t2)/np.sqrt(zeta**2-1))*np.exp(1j*omega*s/Vc);

t0 = time.time()
omega = 10
result = integral(f_integrand, 0, np.inf, omega)
print time.time()-t0
print result

মতলব

function [ out ] = f_integrand( s, omega )
    sigma = pi/(pi+2); 
    xs = exp(-pi.*s./(2*sigma));
    x1 = -2*sigma./pi.*(log(xs./(1+sqrt(1-xs.^2)))+sqrt(1-xs.^2));
    x2 = 1-2*sigma./pi.*(1-xs);
    zeta = x2+x1*1j;
    Vc = 1/(2*sigma);
    theta =  -1*asin(exp(-pi./(2.0.*sigma).*s));
    t1 = 1./sqrt(1+tan(theta).^2);
    t2 = -1./sqrt(1+1./tan(theta).^2);
    out = real((t1-1j.*t2)./sqrt(zeta.^2-1)).*exp(1j.*omega.*s./Vc);
end

t=cputime;
omega = 10;
result = integral(@(s) f_integrand(s,omega),0,Inf)
time_taken = cputime-t

4
আপনার খুশি হওয়া উচিত যে পাইথন কেবল 25x ধীর (এবং 250x নয়)।
stally

4
কারণ আপনি বার বার লুপে অজগর-ফাংশনটি কল করছেন (লুকিয়ে রেখেছেন np.vectorize)। একবারে পুরো অ্যারেতে গণনা করার চেষ্টা করুন। এটি যে সম্ভব নয়, নাম্বা বা সিথনের দিকে নজর দিন, তবে আমি আশা করি পরবর্তীটি প্রয়োজনীয় নয়।
sebix

2
"গ্লোবাল অভিযোজিত চতুর্ভুজ" ইঙ্গিত দেয় যে এটি নির্দিষ্ট অবধি পৌঁছা পর্যন্ত এটি মানিয়ে যায়। আপনি একই জিনিসটির সাথে তুলনা করছেন তা নিশ্চিত করার জন্য প্যারামিটারটির সন্ধান করুন (অবশ্যই একটি আছে) যা যথার্থতা নির্ধারণ করে এবং উভয়ের জন্য সেট করে।
bgschaid

2
@ Bgschaid এর মন্তব্য সম্পর্কে, integralএর ডিফল্ট পরম এবং আপেক্ষিক সহনশীলতা যথাক্রমে 1e-10এবং 1e-6integrate.quadএই উভয় হিসাবে নির্দিষ্ট করে 1.49e-8। আমি দেখতে পাই না যেখানে integrate.quad"গ্লোবাল অ্যাডাপটিভ" পদ্ধতি হিসাবে বর্ণনা করা হয়েছে এবং এটি অবশ্যই ব্যবহৃত (অভিযোজক গাউস-ক্রোনরোড, আমি বিশ্বাস করি) পদ্ধতি থেকে পৃথক integral। আমি নিজেও "গ্লোবাল" অংশটির অর্থ কী তা নিশ্চিত। এছাড়াও, / বা এর cputimeপরিবর্তে কখনও ব্যবহার করা ভাল ধারণা নয় । tictoctime it
হর্চলার 3 ই

5
কোনও কিছুর আগে আমি যাচাই করতাম সমস্যাটি অ্যালগরিদম বা ভাষা কিনা: ফাংশনের অভ্যন্তরে বাড়ানো একটি বৈশ্বিক কাউন্টার ভেরিয়েবল যুক্ত করুন। সংহতকরণের পরে এটি আপনাকে প্রতিটি ফাংশন কতবার মূল্যায়ন করা হয় তা বলা উচিত। যদি এই কাউন্টারগুলি উল্লেখযোগ্যভাবে পৃথক হয় তবে সমস্যার অন্তত অংশটি হ'ল ম্যাটল্যাব আরও ভাল অ্যালগরিদম ব্যবহার করে
bgschaid

উত্তর:


15

প্রশ্ন দুটি খুব পৃথক সাবকেশন আছে। আমি কেবল প্রথমটিকে সম্বোধন করব।

মতলব সংস্করণ আমার অজগর সমতুলের চেয়ে গড়ে 24 গুণ দ্রুত গতিতে চলে !

দ্বিতীয়টি বিষয়গত। আমি বলব যে ইন্টিগ্রালটি নিয়ে কিছু সমস্যা আছে তা ব্যবহারকারীকে জানানো একটি ভাল জিনিস এবং এই সায়পি ব্যবহারটি মাতলবকে নীরব রাখতে চালিত করে এবং একরকমভাবে অভ্যন্তরীণভাবে এটি মোকাবেলা করার চেষ্টা করে যা কেবল মাতলব প্রকৌশলীরা জানেন। এটি সেরা হতে হবে।

এনএএন ওয়ারিং এড়ানোর জন্য আমি ইন্টিগ্রেশন স্প্যান 0 থেকে 30 ( 0 থেকে এনপি.inf এর পরিবর্তে ) এ পরিবর্তিত করে একটি জেআইটি সংকলন যুক্ত করেছি। সমাধানটি বেনমার্ক করতে আমি 300 বার সংহতকরণটির পুনরাবৃত্তি করেছি, ফলাফলগুলি আমার ল্যাপটপ থেকে।

জেআইটি সংকলন ব্যতীত:

$ ./test_integrate.py
34.20992112159729
(0.2618828053067563+0.24474506983644717j)

জেআইটি সংকলন সহ:

$ ./test_integrate.py
0.8560323715209961
(0.261882805306756+0.24474506983644712j)

এইভাবে দুটি লাইনের কোড যুক্ত করা অ-জেআইটি সংস্করণের তুলনায় পাইথন কোডের প্রায় 40 গুণ গতিবেগ ফ্যাক্টারে নিয়ে যায় । আমার ল্যাপটপে আরও ভাল তুলনা করার জন্য আমার মতলব নেই, তবে এটি যদি আপনার পিসিতে 24/40 = 0.6 এর চেয়ে ভাল স্কেল করে তবে জাইটি সহ পাইথন এই নির্দিষ্ট ব্যবহারকারীর অ্যালগরিদমের জন্য মতলব থেকে দ্বিগুণ দ্রুত হওয়া উচিত । সম্পূর্ণ কোড:

#!/usr/bin/env python3
import numpy as np
from scipy import integrate
from numba import complex128,float64,jit
import time

def integral(integrand, a, b,  arg):
    def real_func(x,arg):
        return np.real(integrand(x,arg))
    def imag_func(x,arg):
        return np.imag(integrand(x,arg))
    real_integral = integrate.quad(real_func, a, b, args=(arg))
    imag_integral = integrate.quad(imag_func, a, b, args=(arg))   
    return real_integral[0] + 1j*imag_integral[0]

vintegral = np.vectorize(integral)


@jit(complex128(float64, float64), nopython=True, cache=True)
def f_integrand(s, omega):
    sigma = np.pi/(np.pi+2)
    xs = np.exp(-np.pi*s/(2*sigma))
    x1 = -2*sigma/np.pi*(np.log(xs/(1+np.sqrt(1-xs**2)))+np.sqrt(1-xs**2))
    x2 = 1-2*sigma/np.pi*(1-xs)
    zeta = x2+x1*1j
    Vc = 1/(2*sigma)
    theta =  -1*np.arcsin(np.exp(-np.pi/(2.0*sigma)*s))
    t1 = 1/np.sqrt(1+np.tan(theta)**2)
    t2 = -1/np.sqrt(1+1/np.tan(theta)**2)
    return np.real((t1-1j*t2)/np.sqrt(zeta**2-1))*np.exp(1j*omega*s/Vc);

t0 = time.time()
omega = 10
for i in range(300): 
    #result = integral(f_integrand, 0, np.inf, omega)
    result = integral(f_integrand, 0, 30, omega)
print (time.time()-t0)
print (result)

আপনার পিসির জন্য পার্থক্যটি দেখতে @ অজিত লাইনে মন্তব্য করুন।


1

কখনও কখনও সংহত করার ফাংশনটি জেআইটিড করা যায় না। সেক্ষেত্রে আর একটি সংহত পদ্ধতি ব্যবহার করা সমাধান হবে।

আমি সুপারিশ করবে scipy.integrate.romberg (সুত্র)rombergজটিল ফাংশনগুলি সংহত করতে পারে এবং অ্যারের সাথে ফাংশনটি মূল্যায়ন করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.