"X <y <z" কি "x <y এবং y <z" এর চেয়ে দ্রুত?


129

এই পৃষ্ঠা থেকে , আমরা জানি যে:

চেইনযুক্ত তুলনা andঅপারেটরটি ব্যবহার করার চেয়ে দ্রুত । x < y < zপরিবর্তে লিখুন x < y and y < z

তবে, নিম্নলিখিত কোড স্নিপেটগুলি পরীক্ষা করে আমি একটি ভিন্ন ফলাফল পেয়েছি:

$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.8" "x < y < z"
1000000 loops, best of 3: 0.322 usec per loop
$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.8" "x < y and y < z"
1000000 loops, best of 3: 0.22 usec per loop
$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.1" "x < y < z"
1000000 loops, best of 3: 0.279 usec per loop
$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.1" "x < y and y < z"
1000000 loops, best of 3: 0.215 usec per loop

মনে হচ্ছে যে x < y and y < zদ্রুত চেয়ে x < y < zকেন?

এই সাইটের (মত কিছু পোস্ট অনুসন্ধানের পর এই এক ) আমি জানি যে, "শুধুমাত্র একবার মূল্যায়ন" জন্য চাবিকাঠি x < y < zঅবশ্য আমি এখনও বিভ্রান্ত করছি। আরও অধ্যয়ন করার জন্য, আমি এই দুটি ফাংশন ব্যবহার করে পৃথক করেছিলাম dis.dis:

import dis

def chained_compare():
        x = 1.2
        y = 1.3
        z = 1.1
        x < y < z

def and_compare():
        x = 1.2
        y = 1.3
        z = 1.1
        x < y and y < z

dis.dis(chained_compare)
dis.dis(and_compare)

এবং আউটপুটটি হ'ল:

## chained_compare ##

  4           0 LOAD_CONST               1 (1.2)
              3 STORE_FAST               0 (x)

  5           6 LOAD_CONST               2 (1.3)
              9 STORE_FAST               1 (y)

  6          12 LOAD_CONST               3 (1.1)
             15 STORE_FAST               2 (z)

  7          18 LOAD_FAST                0 (x)
             21 LOAD_FAST                1 (y)
             24 DUP_TOP
             25 ROT_THREE
             26 COMPARE_OP               0 (<)
             29 JUMP_IF_FALSE_OR_POP    41
             32 LOAD_FAST                2 (z)
             35 COMPARE_OP               0 (<)
             38 JUMP_FORWARD             2 (to 43)
        >>   41 ROT_TWO
             42 POP_TOP
        >>   43 POP_TOP
             44 LOAD_CONST               0 (None)
             47 RETURN_VALUE

## and_compare ##

 10           0 LOAD_CONST               1 (1.2)
              3 STORE_FAST               0 (x)

 11           6 LOAD_CONST               2 (1.3)
              9 STORE_FAST               1 (y)

 12          12 LOAD_CONST               3 (1.1)
             15 STORE_FAST               2 (z)

 13          18 LOAD_FAST                0 (x)
             21 LOAD_FAST                1 (y)
             24 COMPARE_OP               0 (<)
             27 JUMP_IF_FALSE_OR_POP    39
             30 LOAD_FAST                1 (y)
             33 LOAD_FAST                2 (z)
             36 COMPARE_OP               0 (<)
        >>   39 POP_TOP
             40 LOAD_CONST               0 (None)

দেখে মনে হচ্ছে এর x < y and y < zচেয়ে কম বিচ্ছিন্ন কমান্ড রয়েছে x < y < z। আমি x < y and y < zতুলনায় দ্রুত বিবেচনা করা উচিত x < y < z?

পাইথন 2.7.6 এর সাথে একটি ইন্টেল (আর) জিয়ন (আর) সিপিইউ E5640 @ 2.67GHz এ পরীক্ষিত।


8
আরও বিচ্ছিন্ন কমান্ডের অর্থ আরও জটিলতা বা ধীর কোড নয়। তবে আপনার timeitপরীক্ষাগুলি দেখে আমি এতে আগ্রহী।
মার্কো বোনেলি

6
আমি ধরে নিয়েছি "একবার মূল্যায়ন করা" থেকে গতির পার্থক্যটি আসে যখন yকেবল কোনও পরিবর্তনশীল অনুসন্ধান নয়, তবে একটি ফাংশন কলের মতো আরও ব্যয়বহুল প্রক্রিয়া? অর্থাত্ 10 < max(range(100)) < 15দ্রুত হয় 10 < max(range(100)) and max(range(100)) < 15কারণ max(range(100))উভয় তুলনার জন্য একবার বলা হয়।
zehnpaard

2
@ মার্কোবোনেলি এটি করে যখন ডিসেম্বল্বড কোড 1) এ লুপ থাকে না এবং 2) প্রতিটি একক বাইটকোড খুব দ্রুত হয়, কারণ সেই সময়ে মূললুপের ওভারহেড তাৎপর্যপূর্ণ হয়ে ওঠে।
বাকুরিউ

2
শাখার পূর্বাভাস আপনার পরীক্ষাগুলি বিশৃঙ্খলা করতে পারে।
কোরি ওগবার্ন 18

2
@zehnpaard আমি আপনার সাথে একমত যখন "y" একটি সাধারণ মানের চেয়ে বেশি হয় (যেমন, কোনও ফাংশন কল বা গণনা) আমি আশা করতে পারি যে "y" একবার x <y <z তে একবার আরও মূল্যবান প্রভাব ফেলবে বলে মূল্যায়ন করা হয়। উপস্থাপিত ক্ষেত্রে আমরা ত্রুটি বারের মধ্যে রয়েছি: (ব্যর্থ) শাখার পূর্বাভাসের প্রভাব, কম-অনুকূল বাইটকোড এবং অন্যান্য প্ল্যাটফর্ম / সিপিইউ-নির্দিষ্ট প্রভাবগুলি প্রভাবিত করে। এটি সাধারণ নিয়মকে অকার্যকর করে না যে একবার মূল্যায়ন করা ভাল (পাশাপাশি আরও পঠনযোগ্য) তবে এটি দেখায় যে এটি চূড়ান্তভাবে খুব বেশি মূল্য যোগ করতে পারে না।
মার্টেম্যাকজিভার 21

উত্তর:


111

পার্থক্যটি হ'ল x < y < z yকেবলমাত্র একবারে মূল্যায়ন করা হয়। Y ভেরিয়েবল হলে এটি একটি বড় পার্থক্য তৈরি করে না, তবে এটি যখন ফাংশন কল হয় তখন এটি গণনা করতে কিছুটা সময় নেয় does

from time import sleep
def y():
    sleep(.2)
    return 1.3
%timeit 1.2 < y() < 1.8
10 loops, best of 3: 203 ms per loop
%timeit 1.2 < y() and y() < 1.8
1 loops, best of 3: 405 ms per loop

18
অবশ্যই, একটি অর্থগত পার্থক্য হতে পারে। কেবল y () দুটি পৃথক মান ফেরত দিতে পারে না, তবে একটি পরিবর্তনশীল দ্বারা x <y এর মধ্যে অপেক্ষাকৃত কম অপারেটরের মূল্যায়ন y এর মান পরিবর্তন করতে পারে। এ কারণেই এটি প্রায়শই বাইট কোডে অপ্টিমাইজ করা হয় না (যদি y যদি স্থানীয় নয় এমন পরিবর্তনশীল বা কোনও ক্লোজারে অংশ নেওয়া হয়, উদাহরণস্বরূপ)
র্যান্ডম 832

শুধু কৌতূহলী, আপনি কেন sleep()ফাংশনটির অভ্যন্তরে প্রয়োজন ?
অধ্যাপক

@ প্রফিট এটি এমন একটি ফাংশন সিমুলেট করা যা ফলাফল গণনা করতে কিছুটা সময় নেয়। যদি ফাংশনগুলি এখনই ফিরে আসে তবে দুটি সময়সূচির ফলাফলের মধ্যে খুব বেশি পার্থক্য হবে না।
রব

@ রব কেন খুব একটা পার্থক্য হবে না? এটি 3ms বনাম 205 মিমি হতে পারে, এটি এটি যথেষ্ট পরিমাণে প্রমাণ করে?
অধ্যাপক

@ প্রফ্ট আপনি পয়েন্টটি হারিয়েছেন যে y () দুইবার গণনা করা হয়, সুতরাং এটি 1x200ms এর পরিবর্তে 2x200ms। বাকি (3/5 এমএস) সময় নির্ধারণের ক্ষেত্রে অপ্রাসঙ্গিক শব্দ।
রব

22

আপনি সংজ্ঞায়িত উভয় ফাংশনের জন্য অনুকূল বাইটকোড হবে

          0 LOAD_CONST               0 (None)
          3 RETURN_VALUE

কারণ তুলনা ফলাফল ব্যবহার করা হয় না। আসুন তুলনার ফলাফলটি ফিরিয়ে পরিস্থিতিটিকে আরও আকর্ষণীয় করে তুলি। আসুন, ফলাফলটি সংকলনের সময়টি অজ্ঞাত হতে হবে।

def interesting_compare(y):
    x = 1.1
    z = 1.3
    return x < y < z  # or: x < y and y < z

আবার, তুলনার দুটি সংস্করণ শব্দার্থগতভাবে অভিন্ন, সুতরাং উভয় নির্মাণের জন্য অনুকূল বাইটকোডটি একই the সেরা হিসাবে আমি এটি কাজ করতে পারেন, এটি দেখতে এই মত হবে। আমি ফোর নোটেশনে প্রতিটি অপকোডের আগে এবং পরে স্ট্যাকের সামগ্রীগুলি সহ প্রতিটি লাইনটি লিখেছি (ডানদিকে স্ট্যাকের শীর্ষে, --আগে এবং পরে বিভাজক ?করে , পিছনে এমন কিছু নির্দেশ করে যা সেখানে থাকতে পারে বা নাও পারে)। মনে রাখবেন যে RETURN_VALUEপ্রত্যাবর্তিত মানের নীচে স্ট্যাকের মধ্যে যা ঘটেছিল তা বাতিল করে দেয়।

          0 LOAD_FAST                0 (y)    ;          -- y
          3 DUP_TOP                           ; y        -- y y
          4 LOAD_CONST               0 (1.1)  ; y y      -- y y 1.1
          7 COMPARE_OP               4 (>)    ; y y 1.1  -- y pred
         10 JUMP_IF_FALSE_OR_POP     19       ; y pred   -- y
         13 LOAD_CONST               1 (1.3)  ; y        -- y 1.3
         16 COMPARE_OP               0 (<)    ; y 1.3    -- pred
     >>  19 RETURN_VALUE                      ; y? pred  --

যদি ভাষার কোনও প্রয়োগকরণ হয়, তবে সিপিথন, পাইপাই, যাই হোক না কেন, উভয় প্রকারের জন্য এই বাইটোকড (বা তার নিজস্ব সমতুল্য ক্রমগুলি) তৈরি করে না, যা tec বাইটকোড সংকলকটির নিম্নমানের প্রদর্শন করে । উপরের দিকে পোস্ট করা বাইটকোড ক্রমগুলি থেকে পাওয়া একটি সমাধান করা সমস্যা (আমি মনে করি এই ক্ষেত্রে আপনার যা প্রয়োজন তা হল ধ্রুবক ভাঁজ , ডেড কোড নির্মূলকরণ এবং স্ট্যাকের বিষয়বস্তুগুলির আরও ভাল মডেলিং; সাধারণ স্বেচ্ছাসেবক নির্মূলকরণও সস্তা এবং মূল্যবান হতে পারে) ), এবং এটি আধুনিক ভাষা বাস্তবায়নে না করার জন্য কোনও অজুহাত নেই।

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


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

1
@ ভু আমার হ্যান্ড-অপ্টিমাইজড বাইটকোডে স্বেচ্ছাচারী গতিবিধির উপস্থিতিতে এমনকি মূলটির মতো একই শব্দার্থকতা রয়েছে (একটি ব্যতিক্রম: একটি <বি <b> a অনুমান করা হয়)। এছাড়াও, ইনলাইনিং ওভাররেড হয়। আপনি যদি এটির খুব বেশি পরিমাণে করেন - এবং এটির থেকে খুব বেশি করা খুব সহজ you আপনি আই-ক্যাশে ফুটিয়েছেন এবং যা কিছু অর্জন করেছেন তা হারিয়ে ফেলেন এবং তারপরে কিছু।
zwol

আপনি ঠিক বলেছেন আমি ভেবেছিলাম আপনি বোঝাতে চেয়েছেন আপনি interesting_compareশীর্ষে থাকা সাধারণ বাইকোডটিতে (যা কেবল ইনলাইনে কাজ করবে) to সম্পূর্ণরূপে অফটোপিক তবে: যে কোনও সংকলকটির জন্য অন্তর্নিহিত সর্বাধিক প্রয়োজনীয় অপটিমাইজেশন। আপনি বাস্তব প্রোগ্রামগুলিতে হটস্পট বলার সাথে কিছু বেঞ্চমার্ক চালানোর চেষ্টা করতে পারেন (এমন কোনও গণিত পরীক্ষা যা তাদের of৯% সময়কে একটি হট লুপের জন্য ব্যয় করে না যা হাতের অনুকূলিত হয় [এবং তাই কোনও ফাংশনই আর কল করে না]] যখন আপনি এটি অক্ষম করেন যে কোনও কিছুর ইনলাইন করার ক্ষমতা - আপনি বড় আকারগুলি দেখতে পাবেন।
ভু

@ ভু হ্যাঁ, শীর্ষে থাকা সাধারণ বাইকোডটি ওপেনের মূল কোডটির "অনুকূলতম সংস্করণ" হওয়ার কথা ছিল না interesting_compare
zwol

"একটি ব্যতিক্রম: একটি <b> b> একটি অনুমান করা হয়" → যা পাইথনে কেবল সত্য নয়। এছাড়াও, আমি মনে করি যে সিপিথন yস্ট্যাকটি পরিবর্তন করবেন না তার উপর সত্যিকারের ক্রিয়াকলাপ ধরে নিতে পারে না, কারণ এতে প্রচুর ডিবাগ সরঞ্জাম রয়েছে।
Veedrac

8

যেহেতু আউটপুটটিতে পার্থক্যটি অপ্টিমাইজেশনের অভাবে দেখা গেছে বলে মনে হয় আপনার বেশিরভাগ ক্ষেত্রে এই পার্থক্যটি উপেক্ষা করা উচিত - এটি হতে পারে যে পার্থক্যটি চলে যাবে will পার্থক্যটি হ'ল কেবল yএকবার মূল্যায়ন করা উচিত এবং এটি স্ট্যাকের অনুলিপি করে সমাধান করা হয় যার জন্য অতিরিক্ত প্রয়োজন POP_TOP- ব্যবহারের সমাধান LOAD_FASTযদিও সম্ভব হতে পারে।

যদিও গুরুত্বপূর্ণ পার্থক্যটি হ'ল x<y and y<zদ্বিতীয়টি yযদি x<yসত্য হিসাবে মূল্যায়ন করা হয় তবে দু'বার মূল্যায়ন করা উচিত , যদি মূল্যায়ণে yযথেষ্ট সময় লাগে বা পার্শ্ব প্রতিক্রিয়া হয় তবে এর অর্থ হয় has

বেশিরভাগ পরিস্থিতিতে আপনার x<y<zকিছুটা ধীর হওয়া সত্ত্বেও ব্যবহার করা উচিত ।


6

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

x < y < zকনস্ট্রাক্ট:

  1. এর অর্থ আরও পরিষ্কার এবং আরও সরাসরি।
  2. Evalute: এর শব্দার্থবিদ্যা কি আপনি "গাণিতিক অর্থ" তুলনা থেকে আশা করতে চাই হয় x, yএবং z একবার এবং চেক যদি পুরো শর্ত ঝুলিতে। একাধিকবার andমূল্যায়ন করে শব্দার্থবিজ্ঞান ব্যবহার করে ফলাফল পরিবর্তন করতে পারেy

সুতরাং আপনি যে শব্দার্থকতা চান তার উপর নির্ভর করে অন্যটির স্থানে একটি চয়ন করুন এবং যদি সেগুলি সমান হয় তবে একজনের তুলনায় আরও বেশি পাঠযোগ্য।

এটি বলেছে: আরও বিচ্ছিন্ন কোডটি ধীর কোড বোঝায় না । তবে আরও বাইটকোড অপারেশনগুলি কার্যকর করার অর্থ প্রতিটি অপারেশন সহজতর এবং তবুও এটির জন্য মূল লুপটির পুনরাবৃত্তি প্রয়োজন। এর অর্থ এই যে যদি অপারেশন আপনি সম্পাদন করা হয় অত্যন্ত দ্রুত (যেমন স্থানীয় পরিবর্তনশীল লুকআপ যেমন তুমি সেখানে করছেন) হয়, তবে মাথার উপরে আরো বাইটকোড অপারেশন নির্বাহ ব্যাপার পারবেন না।

তবে মনে রাখবেন যে এই ফলাফলটি বেশি জেনেরিক পরিস্থিতি ধারণ করে না , কেবলমাত্র "সবচেয়ে খারাপ ক্ষেত্রে" যা আপনি প্রোফাইলটিতে ঘটে। যেমনটি অন্যরা উল্লেখ করেছে, আপনি যদি yএমন কিছু পরিবর্তন করেন যা আরও খানিকটা সময় নেয় আপনি দেখতে পাবেন যে ফলাফলগুলি পরিবর্তিত হবে, কারণ শৃঙ্খলিত বিবৃতি এটি একবারে মূল্যায়ন করে।

সারমর্ম:

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

5
আমি মনে করি আপনার উত্তরটিতে সোজা এবং প্রাসঙ্গিক সত্যটি অন্তর্ভুক্ত নয় যে উদ্ধৃত পৃষ্ঠাটি, প্রশ্নের বিশেষ ক্ষেত্রে - ভাসমানের তুলনা করা সহজভাবে ভুল। শৃঙ্খলযুক্ত তুলনা দুটি পরিমাপে এবং উত্পন্ন বাইকোডে দেখা যায় তেমন দ্রুত হয় না।
পিভিজি

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

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