পাইথন 3-তে এক্স ** ৪.০ এক্স ** ৪ এর চেয়ে দ্রুত কেন?


164

এর x**4.0চেয়ে দ্রুত কেন x**4? আমি সিপিথন 3.5.5 ব্যবহার করছি।

$ python -m timeit "for x in range(100):" " x**4.0"
  10000 loops, best of 3: 24.2 usec per loop

$ python -m timeit "for x in range(100):" " x**4"
  10000 loops, best of 3: 30.6 usec per loop

এটি কীভাবে কাজ করে তা দেখার জন্য আমি উত্থাপিত শক্তিটি পরিবর্তন করার চেষ্টা করেছি এবং উদাহরণস্বরূপ যদি আমি 10 বা 16 এর পাওয়ারে এক্স বাড়িয়ে তুলি তবে এটি 30 থেকে 35 পর্যন্ত লাফিয়ে চলেছে, তবে আমি যদি ভাসা হিসাবে 10.0 বাড়িয়ে তুলি তবে এটি কেবল চলছে প্রায় 24.1 ~ 4।

আমার ধারণা এটির 2 এর ভাসমান রূপান্তর এবং শক্তির সাথে কিছু করার আছে তবে আমি সত্যি জানি না।

আমি লক্ষ্য করেছি যে উভয় ক্ষেত্রেই 2 এর শক্তি আরও দ্রুত, আমি অনুমান করি যেহেতু এই গণনাগুলি দাতব্য / কম্পিউটারের জন্য আরও নেটিভ / সহজ। তবে তবুও, ভাসা নিয়ে এটি প্রায় চলমান নয়। 2.0 => 24.1~4 & 128.0 => 24.1~4 কিন্তু 2 => 29 & 128 => 62


টাইগারহকটি 3 উল্লেখ করেছে যে এটি লুপের বাইরে ঘটে না। বেসটি উত্থাপিত হওয়ার সময় আমি পরীক্ষা করেছিলাম এবং পরিস্থিতিটি কেবলমাত্র (যা দেখেছি) থেকে ঘটে) সে সম্পর্কে কোন ধারণা?


11
এর মূল্যটি কীসের জন্য: পাইথন আমার জন্য 2.7.13 একটি ফ্যাক্টর 2 ~ 3 দ্রুত এবং বিপরীত আচরণটি দেখায়: একটি পূর্ণসংখ্যার এক্সপোঞ্জ্যান্ট একটি ভাসমান পয়েন্টের এক্সপোনেন্টের চেয়ে দ্রুত faster

4
@ এভার ইয়েপ, আমি 14 ইউজেক পেয়েছি x**4.0এবং 3.9 এর জন্য x**4
দাদাবাবা

উত্তর:


161

পাইথন 3 * এর চেয়ে x**4.0 দ্রুত কেন ?x**4

পাইথন 3 intঅবজেক্টস একটি পূর্ণ আকারযুক্ত বস্তু যা একটি স্বেচ্ছাসেবী আকারকে সমর্থন করার জন্য ডিজাইন করা হয়েছে; এই সত্যের কারণে, সেগুলি সি স্তরে যেমন পরিচালনা করা হয় (দেখুন কীভাবে সমস্ত ভেরিয়েবল PyLongObject *টাইপ হিসাবে ঘোষণা করা হয় long_pow)। এটি তাদের ক্ষয়ক্ষতি আরও অনেক বেশি জটিল এবং ক্লান্তিকর করে তোলে কারণ ob_digitএটি সম্পাদন করার জন্য এটির মানটি উপস্থাপন করতে ব্যবহৃত অ্যারের সাথে আপনার চারপাশে খেলতে হবে। ( উত্স সাহসী জন্য। - দেখুন: পাইথন বড় পূর্ণসংখ্যার সমঝোতা মেমরি অ্যালোকেশন সম্পর্কে আরো জানার জন্য PyLongObject। গুলি)

floatবিপরীতে পাইথন অবজেক্টসকে একটি সি টাইপে (ব্যবহার করে ) রূপান্তরিত করা যায় এবং সেই দেশীয় প্রকারগুলি ব্যবহার করে অপারেশন করা যেতে পারে । এই মহান , কারণ প্রাসঙ্গিক প্রান্ত মামলা চেক পরে, এটি পাইথন পারবেন প্ল্যাটফর্মের 'ব্যবহার ( সি এর , যে ) প্রকৃত exponentiation হ্যান্ডেল করতে:doublePyFloat_AsDoublepowpow

/* Now iv and iw are finite, iw is nonzero, and iv is
 * positive and not equal to 1.0.  We finally allow
 * the platform pow to step in and do the rest.
 */
errno = 0;
PyFPE_START_PROTECT("pow", return NULL)
ix = pow(iv, iw); 

যেখানে ivএবং iwআমাদের মূল হয় PyFloatObjectযেমন সি গুলি doubleগুলি।

এটির জন্য মূল্য: 2.7.13আমার জন্য পাইথন 2~3দ্রুততর একটি কারণ , এবং বিপরীত আচরণ দেখায়।

পূর্ববর্তী ঘটনাটি পাইথন 2 এবং 3 এর মধ্যে বৈষম্যকে ব্যাখ্যা করে তাই আমি ভেবেছিলাম যে আমি এই মন্তব্যটিও সম্বোধন করব কারণ এটি আকর্ষণীয়।

পাইথন 2 তে, আপনি পুরানো intঅবজেক্টটি ব্যবহার করছেন যা intপাইথন 3 int-তে ( 3.x তে থাকা সমস্ত বস্তু টাইপযুক্ত PyLongObject) the পাইথন ২-তে, একটি পার্থক্য রয়েছে যা বস্তুর মানের উপর নির্ভর করে (বা, যদি আপনি প্রত্যয় ব্যবহার করেন L/l):

# Python 2
type(30)  # <type 'int'>
type(30L) # <type 'long'>

<type 'int'>আপনি এখানে দেখতে একই জিনিস আছে floatগুলি না এটা নিরাপদে একটি সি রূপান্তরিত হয়, long যখন exponentiation এটিতে সঞ্চালিত হয় ( int_pow, এছাড়াও একটি রেজিস্টারে ই.এম. লাগাতে 'কম্পাইলার সংকেতগুলি যদি এটা তা করতে পারেন, যাতে পারে একটি পার্থক্য করতে) :

static PyObject *
int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
{
    register long iv, iw, iz=0, ix, temp, prev;
/* Snipped for brevity */    

এটি একটি ভাল গতি লাভের অনুমতি দেয়।

<type 'long'>এর তুলনায় তুলনামূলকভাবে কতটা অলস রয়েছে তা দেখার জন্য <type 'int'>, আপনি পাইথন 2 এ কলটিতে xনামটি মুড়ে রাখলে long(মূলত long_powপাইথন 3 এর মতো এটি ব্যবহার করতে বাধ্য করা হয় ), গতি বৃদ্ধি অদৃশ্য হয়ে যায়:

# <type 'int'>
(python2)  python -m timeit "for x in range(1000):" " x**2"       
10000 loops, best of 3: 116 usec per loop
# <type 'long'> 
(python2)  python -m timeit "for x in range(1000):" " long(x)**2"
100 loops, best of 3: 2.12 msec per loop

নোট নিন যে, যদিও এক স্নিপেট রূপান্তরগুলির intকরতে longযখন অন্যান্য না (@pydsinger দ্বারা সরু আউট হিসাবে), এই ঢালাই মন্দার পিছনে অবদান বল নয়। বাস্তবায়ন long_powহয়। (বিবৃতিগুলি সম্পূর্ণরূপে long(x)দেখার জন্য সময় দিন )।

[...] এটি লুপের বাইরে ঘটে না। [...] সে সম্পর্কে কোন ধারণা?

এটি আপনার জন্য ধ্রুবকগুলি ভাঁজ করে সিপিথনের পিফহোল অপটিমাইজার। আপনি ক্ষতিকারক ফলাফল আবিষ্কার করার জন্য কোনও প্রকৃত গণনা নেই, কেবলমাত্র মূল্যবোধ লোড করার পরে আপনি একই সঠিক সময় পাবেন:

dis.dis(compile('4 ** 4', '', 'exec'))
  1           0 LOAD_CONST               2 (256)
              3 POP_TOP
              4 LOAD_CONST               1 (None)
              7 RETURN_VALUE

আইডেন্টিকাল বাইট-কোডটি '4 ** 4.'কেবলমাত্র পার্থক্যের জন্যই তৈরি করা হয় যেটি ইনট এর পরিবর্তে LOAD_CONSTভাসা লোড করে :256.0256

dis.dis(compile('4 ** 4.', '', 'exec'))
  1           0 LOAD_CONST               3 (256.0)
              2 POP_TOP
              4 LOAD_CONST               2 (None)
              6 RETURN_VALUE

তাই সময়গুলি অভিন্ন।


* উপরের সমস্তগুলি পাইথনের রেফারেন্স বাস্তবায়নের জন্য শুধুমাত্র সিপিথনের জন্য আবেদন করে। অন্যান্য বাস্তবায়নগুলি ভিন্নভাবে সম্পাদন করতে পারে।


এটি যাই হোক না কেন, এটি একটি লুপের সাথে সম্পর্কিত range, কারণ কেবলমাত্র **অপারেশনের সময়সীমা নিজেই পূর্ণসংখ্যা এবং ভাসমানগুলির মধ্যে কোনও তফাত লাভ করে না।
টাইগারহকটি 3

পার্থক্যটি কেবল তখন কোনও ভেরিয়েবল সন্ধান করার সময় উপস্থিত হয় ( 4**4ঠিক তত দ্রুত 4**4.0) এবং এই উত্তরটি তেমন স্পর্শ করে না।
টাইগারহকটি 3

1
তবে, ধ্রুবকগুলি @ টাইগারহকটি 3 ( dis(compile('4 ** 4', '', 'exec'))) ভাঁজ হয়ে যাবে তাই সময়টি ঠিক একই রকম হওয়া উচিত ।
দিমিত্রিস ফাসারাকিস হিলিয়ার্ড

আপনার শেষ সময়গুলি আপনি কী বলছেন তা প্রদর্শিত হবে না বলে মনে হচ্ছে। 4-5 এর ফ্যাক্টরের long(x)**2.চেয়ে এখনও দ্রুত long(x)**2। (যদিও
ডাউন ডাউনদের

3
@ mbomb007 <type 'long'>পাইথন 3 এ ধরণের নির্মূলকরণ সম্ভবত ভাষাকে সরল করার প্রচেষ্টা দ্বারা ব্যাখ্যা করা হয়েছে। আপনার যদি পূর্ণসংখ্যার উপস্থাপনের জন্য এক প্রকার থাকতে পারে তবে এটি দুটিয়ের চেয়ে বেশি পরিচালনাযোগ্য (এবং যখন প্রয়োজন হয় তখন একজনের থেকে অন্যটিতে রূপান্তরিত হওয়ার বিষয়ে চিন্তাভাবনা করা, ব্যবহারকারীরা বিভ্রান্ত হয়ে পড়েন ইত্যাদি)। গতি বৃদ্ধি যে গৌণ। পিইপি 237 এর যৌক্তিক বিভাগটি আরও কিছু অন্তর্দৃষ্টি দেয়।
দিমিত্রিস ফাসারাকিস হিলিয়ার্ড

25

আমরা যদি বাইটকোডটি দেখি, আমরা দেখতে পাব যে এক্সপ্রেশনগুলি সম্পূর্ণরূপে অভিন্ন। পার্থক্যটি ধ্রুবতার এক ধরণের যা একটি আর্গুমেন্ট হবে BINARY_POWER। সুতরাং এটি অবশ্যই intরেখার নিচে ভাসমান পয়েন্ট সংখ্যায় রূপান্তরিত হওয়ার কারণে ।

>>> def func(n):
...    return n**4
... 
>>> def func1(n):
...    return n**4.0
... 
>>> from dis import dis
>>> dis(func)
  2           0 LOAD_FAST                0 (n)
              3 LOAD_CONST               1 (4)
              6 BINARY_POWER
              7 RETURN_VALUE
>>> dis(func1)
  2           0 LOAD_FAST                0 (n)
              3 LOAD_CONST               1 (4.0)
              6 BINARY_POWER
              7 RETURN_VALUE

আপডেট: আসুন সিপিথন উত্স কোডের অবজেক্টস / অ্যাবস্ট্রাক্ট.কে একবার দেখে নিই :

PyObject *
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
{
    return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}

PyNumber_Powerকলগুলি ternary_op, যা এখানে আটকানো খুব দীর্ঘ, তাই লিঙ্কটি এখানে

এটি আর্গুমেন্ট হিসাবে পাস করে nb_powerস্লটকে কল করে ।xy

অবশেষে, অবজেক্টস / ফ্লোটোবজেক্ট.-এরfloat_pow() 686 লাইনে আমরা দেখতে পাই যে আর্গুমেন্টগুলি প্রকৃত ক্রিয়াকলাপের আগে ডান সিতে রূপান্তরিত হয় :double

static PyObject *
float_pow(PyObject *v, PyObject *w, PyObject *z)
{
    double iv, iw, ix;
    int negate_result = 0;

    if ((PyObject *)z != Py_None) {
        PyErr_SetString(PyExc_TypeError, "pow() 3rd argument not "
            "allowed unless all arguments are integers");
        return NULL;
    }

    CONVERT_TO_DOUBLE(v, iv);
    CONVERT_TO_DOUBLE(w, iw);
    ...

1
@ জিন-ফ্রেঞ্চোইস ফ্যাবরে আমি বিশ্বাস করি যে এটি নিয়মিত ভাঁজ হওয়ার কারণে।
দিমিত্রিস ফাসারাকিস হিলিয়ার্ড

2
আমি মনে করি যে এই রূপান্তরটি আছে যে কোনও রূপান্তর আছে এবং তারা "খুব অবশ্যই" লাইনের নীচে আলাদাভাবে পরিচালনা করা হয় না এটি উত্স ছাড়াই কিছুটা প্রসারিত।
মিরাদুলো

1
@ মিচ - বিশেষত যেহেতু এই নির্দিষ্ট কোডটিতে, এই দুটি অপারেশনের জন্য মৃত্যুদণ্ডের সময়টিতে কোনও পার্থক্য নেই। পার্থক্যটি কেবল ওপির লুপের সাথেই দেখা দেয়। এই উত্তরটি সিদ্ধান্তে ঝাঁপিয়ে পড়েছে।
টাইগারহকটি 3

2
আপনি কেবল float_powতখন কেন তাকিয়ে আছেন যখন এটি এমনকি ধীর মামলায়ও চলে না?
ব্যবহারকারী 2357112

2
@ টাইগারহকটি 3: 4**4এবং 4**4.0নিয়মিত ভাঁজ পান। এটি সম্পূর্ণ আলাদা প্রভাব
ব্যবহারকারী 2357112

-1

কারণ একটি সঠিক, অন্যটি আনুমানিক x

>>> 334453647687345435634784453567231654765 ** 4.0
1.2512490121794596e+154
>>> 334453647687345435634784453567231654765 ** 4
125124901217945966595797084130108863452053981325370920366144
719991392270482919860036990488994139314813986665699000071678
41534843695972182197917378267300625

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

1
ব্যাখ্যার জন্য ধন্যবাদ. ঠিক আছে, আমি সত্যই ভেবেছিলাম যে এটি স্পষ্টই ছিল যে সমস্ত সংখ্যার সুনির্দিষ্ট গণনা না করে কেবল 12 বা এতগুলি সংখ্যার সান্নিধ্য গণনা করা আরও দ্রুত। সর্বোপরি, আমরা কেন অনুমানের ব্যবহারের একমাত্র কারণ হ'ল তারা গণনা করার জন্য দ্রুত, তাই না?
ভিকি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.