পাইথনে কোনটি দ্রুত: x **। 5 বা math.sqrt (x)?


187

আমি কিছু সময়ের জন্য এটি ভাবছিলাম। শিরোনামটি যেমন বলে, কোনটি দ্রুত, প্রকৃত ফাংশন বা কেবল অর্ধেক শক্তি বাড়ায়?

হালনাগাদ

এটি অকাল অপটিমাইজেশনের বিষয় নয়। অন্তর্নিহিত কোডটি আসলে কীভাবে কাজ করে তা কেবল এটি একটি প্রশ্ন। পাইথন কোড কীভাবে কাজ করে তার তত্ত্বটি কী?

আমি গাইডো ভ্যান রসমকে একটি ইমেল প্রেরণ করেছি কারণ আমি সত্যই এই পদ্ধতিগুলির মধ্যে পার্থক্য জানতে চেয়েছি।

আমার ইমেইল:

পাইথনে স্কোয়ার রুট করার কমপক্ষে 3 টি উপায় রয়েছে: math.sqrt, '**' অপারেটর এবং পাও (x, .5)। আমি এগুলির প্রতিটি বাস্তবায়নের পার্থক্য সম্পর্কে কেবল কৌতূহলী। এটি দক্ষতা আসে যখন ভাল?

তার প্রতিক্রিয়া:

পাও এবং ** সমতুল্য; math.sqrt জটিল সংখ্যার জন্য কাজ করে না, এবং সি স্কয়ার্ট () ফাংশনের লিঙ্কগুলি। কোনটি দ্রুত, আমার কোনও ধারণা নেই ...


81
গিডো ইমেলের প্রতিক্রিয়া জানায়।
ইভান ফসমার্ক

3
ইভান, আমি অবাক হয়েছি আমি একটি প্রতিক্রিয়া পেয়েছি
নোপ

11
আমি মনে করি না এটি একটি খারাপ প্রশ্ন। উদাহরণস্বরূপ, x * x x ** এর তুলনায় পুরো 10 গুণ দ্রুত 2. 2 পঠনযোগ্যতা এই পরিস্থিতিতে একটি টসআপ, তাই দ্রুত উপায়টি কেন করবেন না?
টিএম

12
ক্যাসি, আমি "অকাল অপটিমাইজেশন" জিনিসটি নিয়ে আপনার সাথে আছি। :) আপনার প্রশ্নটি আমার কাছে অকালীন অপ্টিমাইজেশানের মতো দেখাচ্ছে না: কোনও বৈকল্পিক আপনার কোড ভঙ্গ করে এমন কোনও ঝুঁকি নেই। আপনি যখন ম্যাথ.এসকিউআরটি () এর চেয়ে পাও () বেছে নেবেন তখন আপনি কী (এক্সিকিউশন টাইমের শর্তে) করেন তা আরও ভাল করে জানার বিষয়।
এরিক হে লেবিগোট 21

8
এটি অকাল অপটিমাইজেশন নয়, বরং অকাল হতাশাকে এড়িয়ে চলুন (রেফার্ট নং ২৮, সি ++ কোডিং মান, এ। আলেকান্দ্রসেকু)। যদি math.sqrtআরও অনুকূলিত রুটিন হয় (যেমন এটি হয়) এবং অভিপ্রায়টি আরও স্পষ্টভাবে প্রকাশ করে তবে এটি সর্বদা পছন্দ করা উচিত x**.5। আপনি কী লিখেন তা অকাল অপ্টিমাইজেশন নয়, এবং বিকল্পটি দ্রুততর এবং আরও কোড স্পষ্টতা সরবরাহ করে তা চয়ন করেছেন। যদি তা হয় তবে কেন আপনি অন্যান্য বিকল্পগুলি বেছে নিয়েছেন তা আপনাকে সমানভাবে তর্ক করতে হবে।
সোভাল

উত্তর:


89

math.sqrt(x)তুলনায় উল্লেখযোগ্যভাবে দ্রুত x**0.5

import math
N = 1000000
%%timeit
for i in range(N):
    z=i**.5

10 লুপ, প্রতি লুপে 3: 156 এমএসের মধ্যে সেরা

%%timeit
for i in range(N):
    z=math.sqrt(i)

10 লুপ, প্রতি লুপে 3: 91.1 এমএসের মধ্যে সেরা

পাইথন ৩.6.৯ ( নোটবুক ) ব্যবহার করা ।


আমি এখন কোডেপ্যাড.আরগ এ এটি 3 বার চালিয়েছি এবং তিনবার (এ) বি () এর চেয়ে অনেক দ্রুত ছিল।
জেরেমি রুটেন

10
স্ট্যান্ডার্ড টাইমিট মডিউলটি আপনার বন্ধু। যখন মৃত্যুদন্ড কার্যকর করার সময়টি পরিমাপ করার ক্ষেত্রে এটি সাধারণ সমস্যাগুলি এড়ায়!
এরিক হে লেবিগোট 21

1
এখানে আপনার স্ক্রিপ্টের ফলাফল: জোল্টান @ হোস্ট: ~ $ পাইথন 2.5 পিপিপি 0.183226 সেকেন্ড সময় নিয়েছে 0.15829 সেকেন্ডে জোল্টান @ হোস্ট: $ y পাইথন 2.4 পিপিপি নেওয়া হয়েছে 0.181142 সেকেন্ডে 0.153742 সেকেন্ডে জোল্টন @ হোস্ট: ~ $ পাইথন ২..6 পিপিপি 0.157436 সেকেন্ড সময় নিয়েছে 0.093905 সেকেন্ডের টার্গেট সিস্টেম: উবুন্টু লিনাক্স সিপিইউ: ইন্টেল (আর) কোর (টিএম) 2 ডুয়ো সিপিইউ T9600 @ 2.80GHz আপনি দেখতে পাচ্ছেন আমি বিভিন্ন ফলাফল পেয়েছি। এটি অনুসারে আপনার উত্তরটি জেনেরিক নয়।
zoli2k

2
কোডপ্যাড একটি দুর্দান্ত পরিষেবা, তবে সময় পারফরম্যান্সের জন্য ভয়ঙ্কর, আমি বোঝাতে চাইছি একটি নির্দিষ্ট মুহুর্তে সার্ভারটি কতটা ব্যস্ত থাকবে who প্রতিটি রান সম্ভাব্যভাবে খুব আলাদা ফলাফল দিতে পারে
adamJLev

1
আমি লিনাক্সে পাই 32, পাই 31, পাই 30, পাই 27, পাই 26, পাইপ, জাইথন, পাই 25, পাই 24 দোভাষীগুলির জন্য x ** 5 5 বনাম স্কয়ার্ট (এক্স) এর পারফরম্যান্স তুলনা যুক্ত করেছি। gist.github.com/783011
jfs

19
  • অপ্টিমাইজেশনের প্রথম নিয়ম: এটি করবেন না
  • দ্বিতীয় নিয়ম: এটি না , এখনও

এখানে কিছু সময় রয়েছে (পাইথন ২.২.২, উইন্ডোজ):

$ python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
1000000 loops, best of 3: 0.445 usec per loop

$ python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
1000000 loops, best of 3: 0.574 usec per loop

$ python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
1000000 loops, best of 3: 0.727 usec per loop

এই পরীক্ষাটি দেখায় যে x**.5তুলনায় কিছুটা দ্রুত sqrt(x)

পাইথন 3.0 এর জন্য ফলাফলটি বিপরীত:

$ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
1000000 loops, best of 3: 0.803 usec per loop

$ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
1000000 loops, best of 3: 0.695 usec per loop

$ \Python30\python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
1000000 loops, best of 3: 0.761 usec per loop

math.sqrt(x)x**.5অন্য মেশিনের তুলনায় সর্বদা দ্রুত (উবুন্টু, পাইথন ২.6 এবং ৩.১):

$ python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
10000000 loops, best of 3: 0.173 usec per loop
$ python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
10000000 loops, best of 3: 0.115 usec per loop
$ python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
10000000 loops, best of 3: 0.158 usec per loop
$ python3.1 -mtimeit -s"from math import sqrt; x = 123" "x**.5"
10000000 loops, best of 3: 0.194 usec per loop
$ python3.1 -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
10000000 loops, best of 3: 0.123 usec per loop
$ python3.1 -mtimeit -s"import math; x = 123" "math.sqrt(x)"
10000000 loops, best of 3: 0.157 usec per loop

10

আপনি কতটি বর্গমূলের সত্যিকার অর্থে পারফর্ম করছেন? আপনি কি পাইথনে কিছু 3 ডি গ্রাফিক্স ইঞ্জিন লেখার চেষ্টা করছেন? যদি তা না হয়, তবে কেন এমন কোডের সাথে যান যা পড়তে সহজ যে কোডের চেয়ে ক্রিপ্টিক? সময়ের পার্থক্যটি হ'ল আমি যে কোনও অ্যাপ্লিকেশনটি পারদর্শী হতে পারছি সে সম্পর্কে যে কেউ খেয়াল করতে পারে তার চেয়ে কম হবে। আমি আপনার প্রশ্নটি আসলেই বোঝাতে চাইছি না তবে মনে হচ্ছে অকাল অপটিমাইজেশন নিয়ে আপনি কিছুটা দূরে চলে যাচ্ছেন।


16
আমি সত্যই অনুভব করি না যে আমি একটি অকালীন অপটিমাইজেশন করছি। এটি 2 টি বিভিন্ন পদ্ধতি থেকে সিদ্ধান্ত নেওয়ার আরও সহজ প্রশ্ন, যা গড়ে, দ্রুততর হয়।
নাহ

2
কিব্বি: এটি অবশ্যই একটি বৈধ প্রশ্ন, তবে আমি স্ট্যাক ওভারফ্লোতে যে প্রশ্নগুলি করেছি তাতে ইঙ্গিত হয় যে প্রশ্নকর্তা সব ধরণের অকাল অপটিমাইজেশন করছেন is এটি অবশ্যই প্রতিটি ভাষার জন্য জিজ্ঞাসিত প্রশ্নগুলির একটি বড় শতাংশ।
এলি কোর্টরাইট

2
ম্যাথ.এসকিআরটি (এক্স) কি এক্স ** 0.5 এর চেয়ে বেশি সহজ পড়তে পারে? আমি মনে করি এগুলি উভয়ই বেশ স্পষ্টতই বর্গমূল ... কমপক্ষে যদি আপনি যাইহোক পাইথনের সাথে পরিচিত হন। ** "ক্রিপটিক" এর মতো স্ট্যান্ডার্ড পাইথন অপারেটরকে কল করুন না কারণ আপনি পাইথনের সাথে পরিচিত নন।
টিএম

5
আমি মনে করি না ** অপারেটর ক্রিপ্টিক। আমি মনে করি যে বর্গমূলকে তাদের গণিত অব্যাহত রাখে না তাদের কাছে কিছুটা ক্রিপ্টিক হওয়ার জন্য বর্ধিত অংশটি 0.5 তে কিছু উত্থাপন করার পদ্ধতি হিসাবে।
কিব্বি

13
যদি সে পাইথনে 3 ডি ইঞ্জিন তৈরি করছে?
ক্রিস বার্ট-ব্রাউন

9

এই মাইক্রো-বেঞ্চমার্কগুলিতে, math.sqrtধীরে ধীরে হবে কারণ sqrtগণিতের নামস্থানে অনুসন্ধান করতে সামান্য সময় লাগে । আপনি এটি দিয়ে কিছুটা উন্নতি করতে পারেন

 from math import sqrt

তারপরেও, টাইমাইটের মাধ্যমে কয়েকটি ভিন্নতা চালানো, এর জন্য সামান্য (4-5%) পারফরম্যান্স সুবিধা দেখান x**.5

মজার বিষয় হচ্ছে, করছেন

 import math
 sqrt = math.sqrt

খুব কম পরিসংখ্যানগত তাত্পর্য সহ গতিতে 1% পার্থক্যের মধ্যে এটিকে আরও গতিবেগ এনেছে।


আমি কিব্বির পুনরাবৃত্তি করব এবং বলব যে এটি সম্ভবত একটি অকালীন অপটিমাইজেশন।


7

পাইথন ২.6 এ (float).__pow__() ফাংশনটি সি ফাংশন ব্যবহার করে pow()এবং math.sqrt()ফাংশনগুলি সি sqrt()ফাংশন ব্যবহার করে ।

গ্লিবিসি সংকলনে বাস্তবায়ন pow(x,y)বেশ জটিল এবং এটি বিভিন্ন ব্যতিক্রমী ক্ষেত্রে ভালভাবে অনুকূলিত হয়েছে। উদাহরণস্বরূপ, সি pow(x,0.5)কল করা সহজভাবে sqrt()ফাংশন কল করে ।

ব্যবহারের গতিতে পার্থক্য .**বা math.sqrtসি ফাংশনগুলির চারপাশে ব্যবহৃত মোড়কগুলির দ্বারা সৃষ্ট হয় এবং গতিটি দৃ strongly়ভাবে সিস্টেমে ব্যবহৃত অপটিমাইজেশন পতাকা / সি সংকলক উপর নির্ভর করে।

সম্পাদনা:

এখানে আমার মেশিনে ক্লডিয়ুর অ্যালগরিদমের ফলাফল রয়েছে। আমি বিভিন্ন ফলাফল পেয়েছি:

zoltan@host:~$ python2.4 p.py 
Took 0.173994 seconds
Took 0.158991 seconds
zoltan@host:~$ python2.5 p.py 
Took 0.182321 seconds
Took 0.155394 seconds
zoltan@host:~$ python2.6 p.py 
Took 0.166766 seconds
Took 0.097018 seconds

4

এটি মূল্যবান জন্য (জিম এর উত্তর দেখুন)। আমার মেশিনে, অজগর 2.5 রান করুন:

PS C:\> python -m timeit -n 100000 10000**.5
100000 loops, best of 3: 0.0543 usec per loop
PS C:\> python -m timeit -n 100000 -s "import math" math.sqrt(10000)
100000 loops, best of 3: 0.162 usec per loop
PS C:\> python -m timeit -n 100000 -s "from math import sqrt" sqrt(10000)
100000 loops, best of 3: 0.0541 usec per loop

4

ক্লডিউ এর কোড ব্যবহার করা, আমার মেশিনে এমনকি "ম্যাথ ইম্পোর্ট স্কয়ার্ট" x ** এর সাথেও। 5 দ্রুত তবে সাইকো.ফুল () স্কয়ার্ট (এক্স) ব্যবহার করা আরও দ্রুততর হয়, কমপক্ষে 200% দ্বারা


3

সম্ভবত math.sqrt (x), কারণ এটি বর্গমূলের জন্য অনুকূলিত ized

বেঞ্চমার্কগুলি আপনার সন্ধানের উত্তর সরবরাহ করবে provide


3

কেউ ভূমিকম্প 3 থেকে "দ্রুত নিউটন-রেফসন স্কোয়ার রুট" সম্পর্কে মন্তব্য করেছিলেন ... আমি এটি সিটিপস দিয়ে প্রয়োগ করেছি, তবে দেশীয় সংস্করণের তুলনায় এটি খুব ধীর গতিতে। আমি কয়েকটি অপ্টিমাইজেশন এবং বিকল্প বাস্তবায়ন চেষ্টা করে যাচ্ছি।

from ctypes import c_float, c_long, byref, POINTER, cast

def sqrt(num):
 xhalf = 0.5*num
 x = c_float(num)
 i = cast(byref(x), POINTER(c_long)).contents.value
 i = c_long(0x5f375a86 - (i>>1))
 x = cast(byref(i), POINTER(c_float)).contents.value

 x = x*(1.5-xhalf*x*x)
 x = x*(1.5-xhalf*x*x)
 return x * num

এখানে স্ট্রাক ব্যবহারের অন্য পদ্ধতিটি সিটিপস সংস্করণের চেয়ে প্রায় 3.6x দ্রুত বেরিয়ে আসে তবে এখনও সি এর গতি 1/10 করে comes

from struct import pack, unpack

def sqrt_struct(num):
 xhalf = 0.5*num
 i = unpack('L', pack('f', 28.0))[0]
 i = 0x5f375a86 - (i>>1)
 x = unpack('f', pack('L', i))[0]

 x = x*(1.5-xhalf*x*x)
 x = x*(1.5-xhalf*x*x)
 return x * num

1

ক্লডিউর ফলাফল আমার থেকে পৃথক। আমি পাইথন ২.6 উবুন্টুতে একটি পুরানো পি ৪.৪ গিগাহার্টজ মেশিনে ব্যবহার করছি ... আমার ফলাফলগুলি এখানে:

>>> timeit1()
Took 0.564911 seconds
>>> timeit2()
Took 0.403087 seconds
>>> timeit1()
Took 0.604713 seconds
>>> timeit2()
Took 0.387749 seconds
>>> timeit1()
Took 0.587829 seconds
>>> timeit2()
Took 0.379381 seconds

স্কয়ারটি আমার জন্য ধারাবাহিকভাবে দ্রুত ... এমনকি কোডপ্যাড.আরও এখনই একমত হয় যে স্থানীয় প্রেক্ষাপটে স্কয়ারটি দ্রুত ( http://codepad.org/6trzcM3j )। কোডপ্যাডটি বর্তমানে পাইথন ২.০ চালাচ্ছে বলে মনে হচ্ছে। ক্লোদিয়ু যখন প্রথম উত্তর দিয়েছিল তখন তারা সম্ভবত ২.৪ বা তার বেশি বয়সী ব্যবহার করছে?

প্রকৃতপক্ষে, এমনকি arth (i) এর জায়গায় math.sqrt (i) ব্যবহার করেও আমি স্কয়ার্টের জন্য আরও ভাল সময় পাই। এক্ষেত্রে টাইমাইট 2 () আমার মেশিনে 0.53 থেকে 0.55 সেকেন্ডের মধ্যে নিয়েছে, যা এখনও সময়সীমা 1 থেকে 0.56-0.60 পরিসংখ্যানের চেয়ে ভাল।

আমি বলতে চাই, আধুনিক পাইথন-এ, গণিত.এসকিউআরটি ব্যবহার করুন এবং অবশ্যই স্থানীয় প্রসঙ্গে আনুন, তা হয় সোমবার = ম্যাথ.এসকিআরটি বা গণিত আমদানি স্কয়ার্ট সহ।


1

পাইথোনিক জিনিসটির জন্য অনুকূলকরণটি হ'ল পাঠযোগ্যতা। এর জন্য আমি মনে করি sqrtফাংশনটির সুস্পষ্ট ব্যবহার সবচেয়ে ভাল। এই কথাটি বলে, আসুন যাই হোক পারফরম্যান্স তদন্ত করি।

আমি পাইথন 3 এর জন্য ক্লডিউয়ের কোড আপডেট করেছি এবং গণনাগুলি অপ্টিমাইজ করাও অসম্ভব করে দিয়েছি (একটি ভাল পাইথনের সংকলক ভবিষ্যতে কিছু করতে পারে):

from sys import version
from time import time
from math import sqrt, pi, e

print(version)

N = 1_000_000

def timeit1():
  z = N * e
  s = time()
  for n in range(N):
    z += (n * pi) ** .5 - z ** .5
  print (f"Took {(time() - s):.4f} seconds to calculate {z}")

def timeit2():
  z = N * e
  s = time()
  for n in range(N):
    z += sqrt(n * pi) - sqrt(z)
  print (f"Took {(time() - s):.4f} seconds to calculate {z}")

def timeit3(arg=sqrt):
  z = N * e
  s = time()
  for n in range(N):
    z += arg(n * pi) - arg(z)
  print (f"Took {(time() - s):.4f} seconds to calculate {z}")

timeit1()
timeit2()
timeit3()

ফলাফলগুলি ভিন্ন হয়, তবে একটি নমুনা আউটপুট হয়:

3.6.6 (default, Jul 19 2018, 14:25:17) 
[GCC 8.1.1 20180712 (Red Hat 8.1.1-5)]
Took 0.3747 seconds to calculate 3130485.5713865166
Took 0.2899 seconds to calculate 3130485.5713865166
Took 0.2635 seconds to calculate 3130485.5713865166

এটি নিজে চেষ্টা করো.


0

SQRMINSUM যে সমস্যাটি আমি সম্প্রতি সমাধান করেছি তার জন্য একটি বড় ডেটা सेटে বারবার স্কয়ার রুট গণনা করা দরকার। আমার ইতিহাসের প্রাচীনতম 2 টি জমা , আমি অন্যান্য অপ্টিমাইজেশানগুলি তৈরি করার আগে, ** 0.5 কে স্কয়ার্ট () দিয়ে প্রতিস্থাপন করে পৃথক হয়ে যায়, এভাবে পিপিপিতে রানটাইমটি 3.74s থেকে 0.51 এর মধ্যে হ্রাস করে। এটি ক্লাউডিয়ো পরিমাপ করা প্রায় 400% উন্নতি ইতিমধ্যে দ্বিগুণ।


0

অবশ্যই, যদি কেউ আক্ষরিক সাথে কাজ করে এবং একটি ধ্রুবক মান প্রয়োজন হয়, পাইথন রানটাইম সংকলন সময়ে মানটি প্রাক-গণনা করতে পারে, যদি এটি অপারেটরগুলির সাথে লেখা থাকে - এই ক্ষেত্রে প্রতিটি সংস্করণ প্রোফাইল করার দরকার নেই:

In [77]: dis.dis(a)                                                                                                                       
  2           0 LOAD_CONST               1 (1.4142135623730951)
              2 RETURN_VALUE

In [78]: def a(): 
    ...:     return 2 ** 0.5 
    ...:                                                                                                                                  

In [79]: import dis                                                                                                                       

In [80]: dis.dis(a)                                                                                                                       
  2           0 LOAD_CONST               1 (1.4142135623730951)
              2 RETURN_VALUE

-3

আরও দ্রুততর কি হবে যদি আপনি গণিত.পি এ যান এবং "স্কয়ার্ট" ফাংশনটি আপনার প্রোগ্রামটিতে অনুলিপি করেন। আপনার প্রোগ্রামটির জন্য ম্যাথ.পি খুঁজে পেতে সময় লাগে, তারপরে এটি খুলুন, আপনি যে ফাংশনটি সন্ধান করছেন তা সন্ধান করুন এবং তারপরে এটি আপনার প্রোগ্রামে ফিরিয়ে আনুন। যদি "ফাংশন" পদক্ষেপের পরেও যদি এই ফাংশনটি দ্রুত হয়, তবে ফাংশনটি নিজেই খুব ভয়ঙ্করভাবে দ্রুত হতে হবে। সম্ভবত আপনার সময় অর্ধেক কাটা হবে। সংক্ষেপে:

  1. Math.py এ যান
  2. "স্কয়ার্ট" ফাংশনটি সন্ধান করুন
  3. এটি কপি করুন
  4. স্কয়ার্ট অনুসন্ধানকারী হিসাবে আপনার প্রোগ্রামে ফাংশন আটকান।
  5. সময়।

1
এটি কাজ করবে না; দেখতে stackoverflow.com/q/18857355/3004881 । মূল প্রশ্নে উদ্ধৃতিটিও নোট করুন যা বলে যে এটি কোনও সি ফাংশনের লিঙ্ক। এছাড়াও, কীভাবে ফাংশনের উত্স কোডটি অনুলিপি করা হতে পারে from math import sqrt?
ড্যান গেটেজ

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