কখন কোনও পদ্ধতির জন্য মেমরি বনাম পারফরম্যান্স গতির জন্য অনুকূলিত করতে হবে?


107

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

আমি এর পিছনে যুক্তিটি বুঝতে পারি তবে আমার প্রশ্নটি হ'ল:

মেথড এ বনাম পদ্ধতি বি এবং এর বিপরীতে কখন ব্যবহার করা উপযুক্ত?

আপনি দেখতে পাচ্ছেন যে মেথডint s এটির উচ্চতর মেমরির ব্যবহার হতে চলেছে, যেহেতু এটি ঘোষিত হয়েছে, তবে এটি কেবল একটি গণনা করতে হবে, অর্থাৎ a + b। অন্যদিকে, মেথড বিতে কম মেমরির ব্যবহার রয়েছে তবে দুটি গণনা করতে হবে, অর্থাৎ a + bদুবার। আমি কখন অন্য একটি কৌশল ব্যবহার করব? বা, একটি কৌশল কি সর্বদা অন্যের চেয়ে পছন্দ হয়? দুটি পদ্ধতির মূল্যায়ন করার সময় কোন বিষয়গুলি বিবেচনা করা উচিত?

পদ্ধতি এ:

private bool IsSumInRange(int a, int b)
{
    int s = a + b;

    if (s > 1000 || s < -1000) return false;
    else return true;
}

পদ্ধতি বি:

private bool IsSumInRange(int a, int b)
{
    if (a + b > 1000 || a + b < -1000) return false;
    else return true;
}

229
আমি বাজি রাখতে ইচ্ছুক যে একটি আধুনিক সংকলক উভয় ক্ষেত্রে একই সমাবেশ তৈরি করবে।
26

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

76
এক সেকেন্ড অপেক্ষা করুন, তারা int sউপরের এবং নিম্ন সীমাগুলির জন্য those যাদু সংখ্যাগুলির সাথে পুরোপুরি সূক্ষ্ম অবস্থায় মুক্ত হওয়ার জন্য জিজ্ঞাসা করলেন ?
নাল

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

142
আমরাও; পাঠযোগ্যতার জন্য অনুকূলিতকরণ।
অ্যান্ডি

উত্তর:


148

কি ঘটতে পারে বা কী ঘটতে পারে তা নিয়ে অনুমান করার পরিবর্তে আসুন আমরা কি দেখব? আমি সি ++ ব্যবহার করতে যেহেতু আমি একটি সি # কম্পাইলার কুশলী হবে না (যদিও থাকবে C # এর উদাহরণ দেখুন থেকে VisualMelon ), কিন্তু আমি নিশ্চিত একই নীতির নির্বিশেষে প্রযোজ্য নই।

সাক্ষাত্কারে আপনার দুটি মুখোমুখি বিকল্প আমরা অন্তর্ভুক্ত করব। আমরা এমন একটি সংস্করণ অন্তর্ভুক্ত করব absযা উত্তরগুলির কয়েকটি দ্বারা প্রস্তাবিত হিসাবে ব্যবহার করে।

#include <cstdlib>

bool IsSumInRangeWithVar(int a, int b)
{
    int s = a + b;

    if (s > 1000 || s < -1000) return false;
    else return true;
}

bool IsSumInRangeWithoutVar(int a, int b)
{
    if (a + b > 1000 || a + b < -1000) return false;
    else return true;
}

bool IsSumInRangeSuperOptimized(int a, int b) {
    return (abs(a + b) < 1000);
}

এখন এটি কোনও অপ্টিমাইজেশন ছাড়াই সংকলন করুন: g++ -c -o test.o test.cpp

এখন আমরা সুনির্দিষ্টভাবে দেখতে পাচ্ছি এটি কী উত্পন্ন করে: objdump -d test.o

0000000000000000 <_Z19IsSumInRangeWithVarii>:
   0:   55                      push   %rbp              # begin a call frame
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 7d ec                mov    %edi,-0x14(%rbp)  # save first argument (a) on stack
   7:   89 75 e8                mov    %esi,-0x18(%rbp)  # save b on stack
   a:   8b 55 ec                mov    -0x14(%rbp),%edx  # load a and b into edx
   d:   8b 45 e8                mov    -0x18(%rbp),%eax  # load b into eax
  10:   01 d0                   add    %edx,%eax         # add a and b
  12:   89 45 fc                mov    %eax,-0x4(%rbp)   # save result as s on stack
  15:   81 7d fc e8 03 00 00    cmpl   $0x3e8,-0x4(%rbp) # compare s to 1000
  1c:   7f 09                   jg     27                # jump to 27 if it's greater
  1e:   81 7d fc 18 fc ff ff    cmpl   $0xfffffc18,-0x4(%rbp) # compare s to -1000
  25:   7d 07                   jge    2e                # jump to 2e if it's greater or equal
  27:   b8 00 00 00 00          mov    $0x0,%eax         # put 0 (false) in eax, which will be the return value
  2c:   eb 05                   jmp    33 <_Z19IsSumInRangeWithVarii+0x33>
  2e:   b8 01 00 00 00          mov    $0x1,%eax         # put 1 (true) in eax
  33:   5d                      pop    %rbp
  34:   c3                      retq

0000000000000035 <_Z22IsSumInRangeWithoutVarii>:
  35:   55                      push   %rbp
  36:   48 89 e5                mov    %rsp,%rbp
  39:   89 7d fc                mov    %edi,-0x4(%rbp)
  3c:   89 75 f8                mov    %esi,-0x8(%rbp)
  3f:   8b 55 fc                mov    -0x4(%rbp),%edx
  42:   8b 45 f8                mov    -0x8(%rbp),%eax  # same as before
  45:   01 d0                   add    %edx,%eax
  # note: unlike other implementation, result is not saved
  47:   3d e8 03 00 00          cmp    $0x3e8,%eax      # compare to 1000
  4c:   7f 0f                   jg     5d <_Z22IsSumInRangeWithoutVarii+0x28>
  4e:   8b 55 fc                mov    -0x4(%rbp),%edx  # since s wasn't saved, load a and b from the stack again
  51:   8b 45 f8                mov    -0x8(%rbp),%eax
  54:   01 d0                   add    %edx,%eax
  56:   3d 18 fc ff ff          cmp    $0xfffffc18,%eax # compare to -1000
  5b:   7d 07                   jge    64 <_Z22IsSumInRangeWithoutVarii+0x2f>
  5d:   b8 00 00 00 00          mov    $0x0,%eax
  62:   eb 05                   jmp    69 <_Z22IsSumInRangeWithoutVarii+0x34>
  64:   b8 01 00 00 00          mov    $0x1,%eax
  69:   5d                      pop    %rbp
  6a:   c3                      retq

000000000000006b <_Z26IsSumInRangeSuperOptimizedii>:
  6b:   55                      push   %rbp
  6c:   48 89 e5                mov    %rsp,%rbp
  6f:   89 7d fc                mov    %edi,-0x4(%rbp)
  72:   89 75 f8                mov    %esi,-0x8(%rbp)
  75:   8b 55 fc                mov    -0x4(%rbp),%edx
  78:   8b 45 f8                mov    -0x8(%rbp),%eax
  7b:   01 d0                   add    %edx,%eax
  7d:   3d 18 fc ff ff          cmp    $0xfffffc18,%eax
  82:   7c 16                   jl     9a <_Z26IsSumInRangeSuperOptimizedii+0x2f>
  84:   8b 55 fc                mov    -0x4(%rbp),%edx
  87:   8b 45 f8                mov    -0x8(%rbp),%eax
  8a:   01 d0                   add    %edx,%eax
  8c:   3d e8 03 00 00          cmp    $0x3e8,%eax
  91:   7f 07                   jg     9a <_Z26IsSumInRangeSuperOptimizedii+0x2f>
  93:   b8 01 00 00 00          mov    $0x1,%eax
  98:   eb 05                   jmp    9f <_Z26IsSumInRangeSuperOptimizedii+0x34>
  9a:   b8 00 00 00 00          mov    $0x0,%eax
  9f:   5d                      pop    %rbp
  a0:   c3                      retq

আমরা স্ট্যাকের ঠিকানাগুলি থেকে দেখতে পারি (উদাহরণস্বরূপ, -0x4ইন mov %edi,-0x4(%rbp)বনাম -0x14ইন mov %edi,-0x14(%rbp)) IsSumInRangeWithVar()স্ট্যাকের মধ্যে 16 টি অতিরিক্ত বাইট ব্যবহার করে।

কারণ IsSumInRangeWithoutVar()মধ্যবর্তী মান sএটি পুনরায় গণনা করতে হয় তা সঞ্চয় করার জন্য স্ট্যাকের জন্য কোনও স্থান বরাদ্দ করে না , ফলস্বরূপ এই বাস্তবায়নটি 2 টি নির্দেশিকা আর দীর্ঘায়িত হয়।

মজার, IsSumInRangeSuperOptimized()দেখতে IsSumInRangeWithoutVar()এটি দেখতে অনেকটা ভালো লাগে , বাদে এটি প্রথম -1000 এবং 1000 সেকেন্ডের সাথে তুলনা করে।

এখন কেবল সবচেয়ে মৌলিক অপ্টিমাইজেশন সঙ্গে কম্পাইল যাক: g++ -O1 -c -o test.o test.cpp। ফলাফল:

0000000000000000 <_Z19IsSumInRangeWithVarii>:
   0:   8d 84 37 e8 03 00 00    lea    0x3e8(%rdi,%rsi,1),%eax
   7:   3d d0 07 00 00          cmp    $0x7d0,%eax
   c:   0f 96 c0                setbe  %al
   f:   c3                      retq

0000000000000010 <_Z22IsSumInRangeWithoutVarii>:
  10:   8d 84 37 e8 03 00 00    lea    0x3e8(%rdi,%rsi,1),%eax
  17:   3d d0 07 00 00          cmp    $0x7d0,%eax
  1c:   0f 96 c0                setbe  %al
  1f:   c3                      retq

0000000000000020 <_Z26IsSumInRangeSuperOptimizedii>:
  20:   8d 84 37 e8 03 00 00    lea    0x3e8(%rdi,%rsi,1),%eax
  27:   3d d0 07 00 00          cmp    $0x7d0,%eax
  2c:   0f 96 c0                setbe  %al
  2f:   c3                      retq

আপনি কি এটি তাকান: প্রতিটি বৈকল্পিক অভিন্ন । সংকলকটি বেশ চতুর কিছু করতে সক্ষম: একটি স্বাক্ষরযুক্ত তুলনা abs(a + b) <= 1000করা a + b + 1000 <= 2000বিবেচনার সমতুল্য setbe, তাই একটি নেতিবাচক সংখ্যাটি খুব বড় ধনাত্মক সংখ্যায় পরিণত হয়। leaনির্দেশ আসলে এক নির্দেশ মধ্যে এই সব সংযোজন সঞ্চালন, এবং সমস্ত শর্তাধীন শাখা বাদ দিতে পারে।

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


প্রশ্ন অনুসরণ করুন, এই কোডটি সংকলনের পরিবর্তে কোনও অনুবাদিত ভাষায় আসলে কী পরিবর্তন হবে? তারপরে, অপ্টিমাইজেশনের বিষয়টি কী গুরুত্বপূর্ণ বা এর একই ফল রয়েছে?

আসুন পরিমাপ করা যাক! আমি উদাহরণগুলি পাইথনে প্রতিলিপি করেছি:

def IsSumInRangeWithVar(a, b):
    s = a + b
    if s > 1000 or s < -1000:
        return False
    else:
        return True

def IsSumInRangeWithoutVar(a, b):
    if a + b > 1000 or a + b < -1000:
        return False
    else:
        return True

def IsSumInRangeSuperOptimized(a, b):
    return abs(a + b) <= 1000

from dis import dis
print('IsSumInRangeWithVar')
dis(IsSumInRangeWithVar)

print('\nIsSumInRangeWithoutVar')
dis(IsSumInRangeWithoutVar)

print('\nIsSumInRangeSuperOptimized')
dis(IsSumInRangeSuperOptimized)

print('\nBenchmarking')
import timeit
print('IsSumInRangeWithVar: %fs' % (min(timeit.repeat(lambda: IsSumInRangeWithVar(42, 42), repeat=50, number=100000)),))
print('IsSumInRangeWithoutVar: %fs' % (min(timeit.repeat(lambda: IsSumInRangeWithoutVar(42, 42), repeat=50, number=100000)),))
print('IsSumInRangeSuperOptimized: %fs' % (min(timeit.repeat(lambda: IsSumInRangeSuperOptimized(42, 42), repeat=50, number=100000)),))

পাইথন ৩.৩.২ দিয়ে চালান, এটি আউটপুট উত্পাদন করে:

IsSumInRangeWithVar
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 BINARY_ADD
              7 STORE_FAST               2 (s)

  3          10 LOAD_FAST                2 (s)
             13 LOAD_CONST               1 (1000)
             16 COMPARE_OP               4 (>)
             19 POP_JUMP_IF_TRUE        34
             22 LOAD_FAST                2 (s)
             25 LOAD_CONST               4 (-1000)
             28 COMPARE_OP               0 (<)
             31 POP_JUMP_IF_FALSE       38

  4     >>   34 LOAD_CONST               2 (False)
             37 RETURN_VALUE

  6     >>   38 LOAD_CONST               3 (True)
             41 RETURN_VALUE
             42 LOAD_CONST               0 (None)
             45 RETURN_VALUE

IsSumInRangeWithoutVar
  9           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 BINARY_ADD
              7 LOAD_CONST               1 (1000)
             10 COMPARE_OP               4 (>)
             13 POP_JUMP_IF_TRUE        32
             16 LOAD_FAST                0 (a)
             19 LOAD_FAST                1 (b)
             22 BINARY_ADD
             23 LOAD_CONST               4 (-1000)
             26 COMPARE_OP               0 (<)
             29 POP_JUMP_IF_FALSE       36

 10     >>   32 LOAD_CONST               2 (False)
             35 RETURN_VALUE

 12     >>   36 LOAD_CONST               3 (True)
             39 RETURN_VALUE
             40 LOAD_CONST               0 (None)
             43 RETURN_VALUE

IsSumInRangeSuperOptimized
 15           0 LOAD_GLOBAL              0 (abs)
              3 LOAD_FAST                0 (a)
              6 LOAD_FAST                1 (b)
              9 BINARY_ADD
             10 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             13 LOAD_CONST               1 (1000)
             16 COMPARE_OP               1 (<=)
             19 RETURN_VALUE

Benchmarking
IsSumInRangeWithVar: 0.019361s
IsSumInRangeWithoutVar: 0.020917s
IsSumInRangeSuperOptimized: 0.020171s

পাইথনে বিচ্ছিন্নতা মারাত্মক আকর্ষণীয় নয়, যেহেতু বাইটকোড "সংকলক" অপ্টিমাইজেশনের পথে খুব বেশি কিছু করে না।

তিনটি ফাংশনের অভিনয় প্রায় একই রকম ident IsSumInRangeWithVar()প্রান্তিক গতি লাভের কারণে আমরা এর সাথে যেতে প্রলুব্ধ হতে পারি । যদিও আমি বিভিন্ন পরামিতিগুলি চেষ্টা করার সময় যুক্ত করছিলাম timeit, কখনও কখনও IsSumInRangeSuperOptimized()দ্রুততমভাবে বেরিয়ে আসে, তাই আমি সন্দেহ করি যে এটি কোনও প্রয়োগের অভ্যন্তরীণ সুবিধার পরিবর্তে পার্থক্যের জন্য দায়ী বাহ্যিক কারণ হতে পারে।

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

IsSumInRangeWithVar: 0.000180s
IsSumInRangeWithoutVar: 0.001175s
IsSumInRangeSuperOptimized: 0.001306s

কেবল পাইপি ব্যবহার করে, যা প্রচুর দোভাষী ওভারহেডকে মুছে ফেলার জন্য জেআইটি সংকলন ব্যবহার করে, 1 বা 2 অর্ডারের প্রস্থের পারফরম্যান্স উন্নতি পেয়েছে। আমি IsSumInRangeWithVar()অন্যদের তুলনায় দ্রুততার একটি ক্রম দেখে খুব অবাক হয়েছিলাম । তাই আমি মানদণ্ডের ক্রম পরিবর্তন করে আবার দৌড়েছি:

IsSumInRangeSuperOptimized: 0.000191s
IsSumInRangeWithoutVar: 0.001174s
IsSumInRangeWithVar: 0.001265s

সুতরাং দেখে মনে হচ্ছে এটি বাস্তবায়ন সম্পর্কে আসলে কিছুই নয় যা এটি দ্রুত করে তোলে, বরং আমি যে আদেশে বেঞ্চমার্কিং করছি তা!

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

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

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


6
সি # তে একটি উদাহরণ দেওয়ার জন্য : শার্পল্যাব উভয় পদ্ধতির জন্য অভিন্ন ছাই তৈরি করে (ডেস্কটপ সিএলআর v4.7.3130.00 (ক্লার্সডেল) x86 এ)
ভিজুয়ালমেলন

2
@ ভিজুয়ালমেলন যথেষ্ট পরিমাণে ইতিবাচক পরীক্ষা করে: "রিটার্ন (((a + b)> = -1000) && ((a + b) <= 1000));" আলাদা ফলাফল দেয়। : sharplab.io/…
পিটার বি

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

1
@ কোরি সম্পাদনা দেখুন।
ফিল ফ্রস্ট

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

67

বর্ণিত প্রশ্নের উত্তর দিতে:

কখন কোনও পদ্ধতির জন্য মেমরি বনাম পারফরম্যান্স গতির জন্য অনুকূলিত করতে হবে?

আপনাকে দুটি জিনিস স্থাপন করতে হবে:

  • আপনার আবেদন সীমাবদ্ধ কি?
  • আমি সেই সংস্থানটির সর্বাধিক দাবি কোথায় করতে পারি?

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

আপনি নিজে যে পদ্ধতিটি সরবরাহ করেছেন সেটি তার নিজের দ্বারা কোনও পারফরম্যান্স সমস্যা সৃষ্টি করবে না, তবে সম্ভবত একটি লুপের মধ্যে এবং প্রচুর পরিমাণে ডেটা প্রক্রিয়াকরণের ক্ষেত্রে, আপনি কীভাবে সমস্যাটির দিকে এগিয়ে চলেছেন সে সম্পর্কে আপনাকে কিছুটা আলাদা চিন্তাভাবনা শুরু করতে হবে।

অ্যাপ্লিকেশনটি কী সীমাবদ্ধ করছে তা সনাক্ত করা হচ্ছে

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

যখন আপনাকে গভীরতর চেহারা প্রয়োজন, সাধারণত আপনি একজন প্রোফাইলার ব্যবহার করবেন । আছে মেমরির profilers এবং প্রক্রিয়া profilers , এবং তারা বিভিন্ন জিনিস পরিমাপ। প্রোফাইলিংয়ের কাজটি একটি উল্লেখযোগ্য পারফরম্যান্সের প্রভাব ফেলে, তবে আপনি কী করছেন তা খুঁজে পেতে আপনার কোডটি ব্যবহার করছেন।

ধরা যাক আপনি দেখতে পাবেন যে আপনার সিপিইউ এবং ডিস্কের ব্যবহার শীর্ষে এসেছে। আপনি প্রথমে "হট স্পট" বা কোড যাচাই করে দেখবেন যা হয় বাকিদের চেয়ে বেশি প্রায়ই ডাকা হয় বা প্রক্রিয়াটির একটি দীর্ঘতর শতাংশ নেয় percentage

আপনি যদি কোনও গরম দাগ খুঁজে না পান, তবে আপনি মেমরিটির দিকে তাকাতে শুরু করবেন। সম্ভবত আপনি প্রয়োজনের চেয়ে বেশি অবজেক্ট তৈরি করছেন এবং আপনার আবর্জনা সংগ্রহ ওভারটাইম কাজ করছে।

কর্মক্ষমতা দাবি করা

জটিলভাবে চিন্তা করুন. নীচের পরিবর্তনের তালিকাটি বিনিয়োগের ক্ষেত্রে আপনি কতটা প্রত্যাবর্তন করবেন তা অনুসারে:

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

এ জাতীয় পরিস্থিতিতে আপনাকে বৈজ্ঞানিক পদ্ধতি প্রয়োগ করতে হবে। একটি অনুমান নিয়ে আসুন, পরিবর্তনগুলি করুন এবং এটি পরীক্ষা করুন it আপনি যদি আপনার পারফরম্যান্সের লক্ষ্যগুলি পূরণ করেন তবে আপনি শেষ করেছেন। যদি তা না হয় তবে তালিকার পরবর্তী জিনিসটিতে যান।


প্রশ্নের সাহসীভাবে উত্তর দেওয়া:

মেথড এ বনাম পদ্ধতি বি এবং এর বিপরীতে কখন ব্যবহার করা উপযুক্ত?

সত্যিই, পারফরম্যান্স বা স্মৃতি সমস্যাগুলি মোকাবিলার চেষ্টা করার এটি সর্বশেষ পদক্ষেপ। ভাষা এবং প্ল্যাটফর্মের (কিছু ক্ষেত্রে) উপর নির্ভর করে মেথড এ বনাম পদ্ধতি বিয়ের প্রভাব সত্যিই আলাদা হবে ।

প্রায় অর্ধেক শালীন অপ্টিমাইজার সহ যে কোনও সংকলিত ভাষা সেগুলির মধ্যে যে কোনও একটির সাথে একই কোড তৈরি করবে। তবে এই অনুমানগুলি অপরিহার্যরূপে মালিকানাধীন এবং খেলনা ভাষায় সত্যই থেকে যায় না।

অবিকল যা এর আরও ভাল প্রভাব ফেলবে তা নির্ভর করে sumস্ট্যাক ভেরিয়েবল বা হিপ ভেরিয়েবল কিনা on এটি একটি ভাষা বাস্তবায়ন পছন্দ। উদাহরণস্বরূপ সি, সি ++ এবং জাভাতে, সংখ্যার আদিমগুলি intডিফল্টরূপে স্ট্যাক ভেরিয়েবল। আপনার কোডটি পুরোপুরি ইনলাইন কোডের চেয়ে স্ট্যাক ভেরিয়েবলকে বরাদ্দ দিয়ে আর কোনও মেমরি প্রভাব ফেলবে না।

অন্যান্য অপ্টিমাইজেশন যা আপনি সি লাইব্রেরিগুলিতে (বিশেষত পুরানোগুলি) সন্ধান করতে পারেন যেখানে আপনাকে প্রথমে 2 টি মাত্রিক অ্যারে অনুলিপি করার আগে বা প্রথমদিকে সিদ্ধান্ত নিতে পারে এটি একটি প্ল্যাটফর্ম নির্ভর অপ্টিমাইজেশন। আপনি যে চিপসেটটিকে লক্ষ্য করে যাচ্ছেন সেটি মেমরি অ্যাক্সেসকে সর্বোত্তম করে তোলে তা সম্পর্কে কিছুটা জ্ঞানের প্রয়োজন। স্থাপত্যের মধ্যে সূক্ষ্ম পার্থক্য রয়েছে।

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


2
এই উত্তরটি আমার প্রশ্নের উপরে সবচেয়ে বেশি আলোকপাত করে এবং আমার কোডিং উদাহরণগুলিতে ধরা পড়ে না, যেমন পদ্ধতি এ এবং পদ্ধতি বি
বাজেট

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

@ এরিক, যেমনটি আমি বলেছি, কর্মক্ষমতা উন্নতির শেষ বিভাগটি হবে আপনার মাইক্রো-অপ্টিমাইজেশান। এর কোনও প্রভাব ফেললে ভাল অনুমানের একমাত্র উপায় হ'ল কোনও প্রোফাইলারের পারফরম্যান্স / স্মৃতি মাপার মাধ্যমে by এটি বিরল যে এই ধরণের উন্নতিগুলির পেওফ রয়েছে, তবে সিমুলেটরগুলিতে আপনার সংবেদনশীল পারফরম্যান্স সমস্যার ক্ষেত্রে বেশ কয়েকটি ভাল পরিবর্তন এনেছে আপনার সময়সীমার লক্ষ্য হিট করার মধ্যে পার্থক্য। আমি মনে করি যে আমি সফটওয়্যারটিতে কাজ করার 20 বছরের বেশি সময় পার হয়েছি তার সংখ্যা আমি একদিকে গুনতে পারি, তবে এটি শূন্য নয়।
বেরিন লরিটশ্চ

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

@ ডকব্রাউন, আমি এর প্রতিকার করেছি। দ্বিতীয় প্রশ্নটি সম্পর্কে, আমি আপনার সাথে বেশ সম্মত।
বেরিন লরিটস্ক

45

"এটি স্মৃতিশক্তি হ্রাস করবে" - এম, না। এমনকি যদি এটি সত্য হয় (যা কোনও শালীন সংকলকের জন্য নয়) তবে পার্থক্যটি সম্ভবত কোনও বাস্তব বিশ্বের পরিস্থিতির জন্য তুচ্ছ।

তবে, আমি পদ্ধতি এ * (সামান্য পরিবর্তন সহ পদ্ধতি এ) ব্যবহার করার পরামর্শ দেব:

private bool IsSumInRange(int a, int b)
{
    int sum = a + b;

    if (sum > 1000 || sum < -1000) return false;
    else return true;
    // (yes, the former statement could be cleaned up to
    // return abs(sum)<=1000;
    // but let's ignore this for a moment)
}

তবে দুটি সম্পূর্ণ ভিন্ন কারণে:

  • ভেরিয়েবলকে sএকটি ব্যাখ্যাকারী নাম দিয়ে কোডটি আরও স্পষ্ট হয়

  • কোডে দু'বার একই সমষ্টি যুক্তি যুক্ত হওয়া এড়িয়ে যায়, তাই কোডটি আরও ডিআরওয়াই হয়ে যায়, যার অর্থ পরিবর্তনের প্রবণতা কম ত্রুটি।


36
আমি এটিকে আরও পরিষ্কার করে "রিটার্ন যোগ> -1000 && সমষ্টি <1000;" দিয়ে যেতে চাই।
26

36
@ কোরি যে কোনও শালীন অপ্টিমাইজার sumভেরিয়েবলের জন্য সিপিইউ রেজিস্টার ব্যবহার করবে , যার ফলে শূন্য মেমরির ব্যবহার হবে। এবং তা না হলেও এটি একটি "পাত" পদ্ধতিতে মেমরির একক শব্দ। অবিশ্বাস্যরূপে মেমরি-অপব্যয়যোগ্য জাভা বা সি # অন্যথায় তাদের জিসি এবং অবজেক্ট মডেলের কারণে হতে পারে তা বিবেচনা করে, একটি স্থানীয় intভেরিয়েবল আক্ষরিকভাবে কোনও লক্ষণীয় মেমরি ব্যবহার করে না। এটি অর্থহীন মাইক্রো-অপ্টিমাইজেশন।
আমন

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

8
উপরোক্ত বিষয়গুলি ছাড়াও, আমি নিশ্চিত যে সি # / জাভা কীভাবে সংরক্ষণ sumকরতে পছন্দ করে তা বাস্তবায়নের বিশদ হতে পারে এবং আমি সন্দেহ করি যে কোনও লোক এড়িয়ে যাওয়ার মতো নির্বোধ কৌশলটি এর কারণ হতে পারে কিনা তা সম্পর্কে কেউ দৃ a়প্রত্যয়ী মামলা intকরতে পারে বা দীর্ঘমেয়াদে স্মৃতি ব্যবহারের পরিমাণ। আইএমও পাঠযোগ্যতা আরও গুরুত্বপূর্ণ। পঠনযোগ্যতা ব্যক্তিগত হতে পারে, তবে এফডাব্লুআইডাব্লু, ব্যক্তিগতভাবে আমি বরং আপনি সিপিইউ ব্যবহারের জন্য না হয়ে দু'বার একই গণনাটি কখনও করতেন না, কারণ আমি যখন ত্রুটি খুঁজছি তখন কেবল আপনার সংযোজনটি পরীক্ষা করতে হবে।
জুন 22

2
... এও নোট করুন যে আবর্জনা সংগ্রহ ভাষায় সাধারণভাবে একটি অনির্দেশ্য, "মেমরি সমুদ্র ঘোল" যে (গ # যাহাই হউক না কেন জন্য) শুধুমাত্র পরিষ্কার করা যেতে পারে হয় প্রয়োজন হলে , আমি একটি প্রোগ্রাম যা RAM এর গিগাবাইট বরাদ্দ উপার্জন স্মরণ এবং এটি শুধুমাত্র শুরু " পরিষ্কার করার পরে "নিজের পরে যখন স্মৃতি দুষ্প্রাপ্য হয়ে ওঠে। যদি জিসিকে চালানোর দরকার না হয় তবে এটি আরও ভাল সময় নিতে পারে এবং আরও চাপের জন্য আপনার সিপিইউ সংরক্ষণ করতে পারে।
জুন এপ্রিল

35

আপনি যাদের দু'জনের চেয়ে আরও ভাল করতে পারেন

return (abs(a + b) > 1000);

বেশিরভাগ প্রসেসর (এবং তাই সংকলক) একক ক্রিয়ায় অ্যাবস () করতে পারে। আপনার কেবলমাত্র কম পরিমাণে নয়, কম তুলনাও রয়েছে, যা সাধারণত গণনাগতভাবে ব্যয়বহুল। এটি ব্রাঞ্চিংটিও সরিয়ে দেয়, যা বেশিরভাগ প্রসেসরের উপর আরও খারাপ, কারণ এটি পাইপলাইনিং করা বন্ধ করে দেয়।

সাক্ষাত্কারকারক, যেমন অন্য উত্তরগুলি বলেছে, উদ্ভিদজীবন এবং কোনও প্রযুক্তিগত সাক্ষাত্কার পরিচালনার কোনও ব্যবসা নেই।

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

এডিট ফ্যাবিওতুরাটি সঠিকভাবে উল্লেখ করেছেন যে এটি আসল, (আমার ভুল!) এর বিপরীত যুক্তিযুক্ত জ্ঞান, এবং এটি নুথের উদ্ধৃতি থেকে আরও একটি প্রভাব চিত্রিত করে যেখানে আমরা কোডটি ভাঙার ঝুঁকিপূর্ণ হওয়ার চেষ্টা করছি it


2
@ কোরি, আমি নিশ্চিতভাবেই গ্রাহাম অনুরোধটি পিন করেছে " প্রত্যাশার সাথে তিনি আমাকে কম ভেরিয়েবলের সাথে একই সমস্যার সমাধান করার জন্য চ্যালেঞ্জ করেছিলেন" । আমি যদি সাক্ষাত্কার গ্রহণকারী হয়ে থাকি তবে আমি উত্তরটি প্রত্যাশা করতাম, দু'বার a+bপ্রবেশ করিনি ifএবং না করছিলাম। আপনি এটি ভুল বুঝতে পেরেছেন "তিনি সন্তুষ্ট হয়েছিলেন এবং বলেছিলেন যে এই পদ্ধতি দ্বারা স্মৃতি ব্যবহার হ্রাস পাবে" - তিনি আপনার প্রতি ভালো লাগলেন, স্মৃতি সম্পর্কে এই অর্থহীন ব্যাখ্যা দিয়ে নিজের হতাশা লুকিয়ে রেখেছিলেন। এখানে প্রশ্ন জিজ্ঞাসা করা আপনার গুরুত্ব সহকারে নেওয়া উচিত নয়। আপনি কি চাকরি পেয়েছেন? আমার অনুমান আপনি করেন নি :-(
সিনাতর

1
আপনি একই সাথে ২ টি রূপান্তরকরণ প্রয়োগ করছেন: আপনি শর্তটি সত্য ("যদি শাখা" থাকে) তখন এটির পরিবর্তে abs()আপনি দুটি কন্ডিশনটিকে 1 এ ব্যবহার করে 1 তে পরিণত করেছেন এবং আপনার একটিও রয়েছে return, "অন্য শাখা")। আপনি যখন এই জাতীয় কোড পরিবর্তন করেন তখন সাবধান হন: অসাবধানতাবশত কোনও ফাংশন লেখার ঝুঁকি রয়েছে যা সত্য ফিরে আসে যখন এটি মিথ্যা ফিরে আসে এবং তদ্বিপরীত। এখানে যা ঘটেছিল ঠিক তেমনটাই ঘটেছিল। আমি জানি আপনি অন্য কোনও বিষয়ে মনোনিবেশ করেছিলেন এবং আপনি এটিতে একটি দুর্দান্ত কাজ করেছেন। তবুও, এটি সহজেই আপনার কাজের জন্য ব্যয় করতে পারত ...
ফ্যাবিও তুরতি

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

2
বেশিরভাগ প্রসেসর (এবং তাই সংকলক) একক ক্রিয়ায় অ্যাবস () করতে পারে। দুর্ভাগ্যক্রমে পূর্ণসংখ্যার ক্ষেত্রে নয়। addsএআরএম a৪ এর শর্তসাপেক্ষ নেগেট রয়েছে এটি ব্যবহার করতে পারলে পতাকাগুলি ইতিমধ্যে একটি থেকে সেট করা থাকে , এবং এআরএম বিপরীত সাব ( rsblt= কম-থা হলে বিপরীত সাব) পূর্বাভাস দিয়েছে তবে অন্য সমস্ত কিছুর বাস্তবায়নের জন্য একাধিক অতিরিক্ত নির্দেশাবলীর প্রয়োজন abs(a+b)বা abs(a)Godbolt.org/z/Ok_Con x86, এআরএম, এআরচ 64, পাওয়ারপিসি, এমআইপিএস এবং আরআইএসসি-ভি এসএম আউটপুট দেখায়। এটি কেবল (unsigned)(a+b+999) <= 1998Uতুলনাকে একটি পরিসীমা-চেকের মধ্যে রূপান্তরিত করেই জিসিসি ফিলের উত্তরের মতো এটি অপ্টিমাইজ করতে পারে।
পিটার কর্ডস

2
এই উত্তরের "উন্নত" কোডটি এখনও ভুল, যেহেতু এটির জন্য পৃথক উত্তর তৈরি করে IsSumInRange(INT_MIN, 0)। মূল কোডটি ফেরত দেয় falseকারণ INT_MIN+0 > 1000 || INT_MIN+0 < -1000; তবে "নতুন এবং উন্নত" কোডটি ফিরে আসে trueকারণ abs(INT_MIN+0) < 1000। (বা কিছু ভাষায় এটি একটি ব্যতিক্রম ছুঁড়ে ফেলবে বা সংজ্ঞায়িত আচরণ করবে
your

16

মেথড এ বনাম পদ্ধতি বি এবং এর বিপরীতে কখন ব্যবহার করা উপযুক্ত?

হার্ডওয়্যার সস্তা; প্রোগ্রামার ব্যয়বহুল । সুতরাং আপনি এই প্রশ্নে আপনার দু'জনের যে সময় ব্যয় হয়েছে তা উভয় উত্তরের চেয়ে সম্ভবত আরও খারাপ।

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

অন্যদিকে, যদি এটি নিখুঁতভাবে একাডেমিক অনুশীলন হয় তবে আপনি পদ্ধতি সি দিয়ে উভয় বিশ্বের সেরা থাকতে পারেন:

private bool IsSumInRange(int a, int b)
{
    a += b;
    return (a >= -1000 && a <= 1000);
}

17
a+=bএকটি ঝরঝরে কৌশল তবে আমার উল্লেখ করতে হবে (কেবলমাত্র উত্তরটি বাকী থেকে বোঝানো হয়নি) আমার অভিজ্ঞতা পদ্ধতি থেকে যে পরামিতিগুলির সাথে জগাখিচুড়ি করা ডিবাগ করা এবং বজায় রাখা খুব কঠিন হতে পারে।
জুন

1
আমি @ jrh সম্মত আমি আরওসি'র পক্ষে একজন শক্তিশালী উকিল এবং এই ধরণের জিনিসটি কিন্তু কিছু নয়।
জন উউ

3
"হার্ডওয়্যার সস্তা; প্রোগ্রামার ব্যয়বহুল।" কনজিউমার ইলেক্ট্রনিক্সের বিশ্বে সেই বক্তব্যটি মিথ্যা। আপনি যদি কয়েক মিলিয়ন ইউনিট বিক্রি করেন, তবে প্রতি ইউনিট হার্ডওয়্যার ব্যয়ের জন্য 0,10 ডলার বাড়াতে অতিরিক্ত উন্নয়ন ব্যয় $ 500.000 ব্যয় করা খুব ভাল বিনিয়োগ।
বার্ট ভ্যান ইনজেন শেনাও

2
@ জোহানউউ: আপনি চেকটি সহজ করেছেন if, তবে তুলনার ফলাফলটি উল্টাতে ভুলে গেছেন; আপনার ফাংশন এখন ফিরে আসছে trueযখন a + bহয় না সীমার মধ্যে। হয় !শর্তের বাইরের দিকে যুক্ত করুন ( return !(a > 1000 || a < -1000)), বা !বিপরীত পরীক্ষাগুলি বিতরণ করুন , return a <= 1000 && a >= -1000;বা রেঞ্জ চেকটি প্রবাহকে সুন্দরভাবে তৈরি করতেreturn -1000 <= a && a <= 1000;
শ্যাডোর্যাঞ্জার

1
@JohnWu: এখনও সামান্য বন্ধ প্রান্ত মামলা এ, বিতরণ যুক্তিবিজ্ঞান প্রয়োজন <=/ >=না </ >না (এর সাথে </ >, 1000 এবং -1000 সীমার বাইরে হচ্ছে চিকিত্সা করা হয়, মূল কোড তাদের সীমার মধ্যে হিসাবে গণ্য)।
ShadowRanger

11

আমি পঠনযোগ্যতার জন্য অনুকূলিত করব। পদ্ধতি এক্স:

private bool IsSumInRange(int number1, int number2)
{
    return IsValueInRange(number1+number2, -1000, 1000);
}

private bool IsValueInRange(int Value, int Lowerbound, int Upperbound)
{
    return  (Value >= Lowerbound && Value <= Upperbound);
}

ছোট ছোট পদ্ধতি যা কেবল 1 টি কাজ করে তবে তর্ক করা সহজ।

(এটি ব্যক্তিগত পছন্দ, আমি নেতিবাচক পরিবর্তে ইতিবাচক পরীক্ষা পছন্দ করি, আপনার আসল কোডটি আসলে মানটি সীমার বাইরে নয় কিনা তা পরীক্ষা করে নিচ্ছে))


5
এই. (উপরে বর্ণিত মন্তব্যগুলি যা একই রকম ছিল: পঠনযোগ্যতা)। ৩০ বছর আগে, যখন আমরা 1 মিমি র‍্যামের চেয়ে কম মেশিনগুলির সাথে কাজ করছিলাম, তখন সঞ্চালন কর্মক্ষমতা প্রয়োজনীয় ছিল - ওয়াই 2 কে সমস্যার মতো, কয়েক লক্ষ হাজার রেকর্ড পান যে প্রত্যেকে অব্যবহৃত ওয়ারের কারণে মেমরির কয়েকটি বাইট নষ্ট হচ্ছে এবং রেফারেন্স, ইত্যাদি এবং যখন আপনার কেবল 256k র্যাম থাকে তখন তা দ্রুত যুক্ত হয়। এখন যেহেতু আমরা এমন একাধিক গিগাবাইট র‍্যামযুক্ত মেশিনগুলির সাথে কাজ করছি, এমনকি কয়েক মেগাবাইট র‌্যাম ব্যবহার করে বনাম পঠনযোগ্যতা এবং কোডের রক্ষণাবেক্ষণ খুব ভাল বাণিজ্য নয়।
ivanivan

@ivanivan: আমি মনে করি না "y2k সমস্যা" আসলেই ছিল স্মৃতি সম্পর্কে about ডেটা-এন্ট্রিের দৃষ্টিকোণ থেকে, দুটি সংখ্যার প্রবেশ করানো চারটি প্রবেশের চেয়ে বেশি দক্ষ এবং জিনিসকে প্রবেশ করানো হিসাবে রাখা অন্য কিছু আকারে রূপান্তরিত করার চেয়ে সহজ।
সুপারক্যাট

10
কি ঘটছে তা দেখতে এখন আপনাকে 2 টি ফাংশন সন্ধান করতে হবে। আপনি এটিকে ফেস ভ্যালুতে নিতে পারবেন না, কারণ আপনি নাম থেকে বলতে পারবেন না যে এগুলি অন্তর্ভুক্তি বা একচেটিয়া সীমানা কিনা। এবং আপনি যদি সেই তথ্যটি যোগ করেন তবে ফাংশনের নামটি প্রকাশের কোডের চেয়ে দীর্ঘ।
পিটার

1
পঠনযোগ্যতা অনুকূল করুন এবং ছোট, সহজ-কারণে-কার্যকারিতা করুন - নিশ্চিত, সম্মত হন। কিন্তু আমি দৃঢ়ভাবে যে পুনঃনামকরনের অসম্মতি aএবং bকরতে number1এবং number2অন্য কোন উপায়ে এইডস পাঠযোগ্যতা। এছাড়াও আপনার ফাংশনগুলির নামকরণ অসামঞ্জস্যপূর্ণ: IsSumInRangeহার্ড-কোড কেন রেঞ্জটিকে যদি IsValueInRangeআর্গুমেন্ট হিসাবে গ্রহণ করে?
বাম দিকের বাইরে

1 ম ফাংশন উপচে পড়তে পারে। (অন্যান্য উত্তরের কোডের মতো)) যদিও ওভারফ্লো-সেফ কোডের জটিলতা এটিকে কোনও ফাংশনে রাখার পক্ষে যুক্তি।
ফিলিপ্সি

6

সংক্ষেপে, আমি মনে করি না যে বর্তমান কম্পিউটারে প্রশ্নটির খুব বেশি প্রাসঙ্গিকতা রয়েছে তবে historicalতিহাসিক দৃষ্টিকোণ থেকে এটি একটি আকর্ষণীয় চিন্তার মহড়া।

আপনার সাক্ষাত্কারটি সম্ভবত পৌরাণিক ম্যান মাসের একজন অনুরাগী। বইটিতে ফ্রেড ব্রুকস কেস করেছে যে প্রোগ্রামারদের সাধারণত তাদের সরঞ্জামবক্সে মূল ফাংশনের দুটি সংস্করণ প্রয়োজন: একটি মেমরি-অনুকূলিত সংস্করণ এবং সিপিইউ-অনুকূলিতকরণ সংস্করণ। ফ্রেড তার অভিজ্ঞতার ভিত্তিতে আইবিএম সিস্টেম / 360 অপারেটিং সিস্টেমের উন্নয়নে নেতৃত্ব দেয় যেখানে মেশিনগুলিতে 8 কিলোবাইট র‍্যামের পরিমাণ কম থাকতে পারে। এই জাতীয় মেশিনে, ফাংশনগুলিতে স্থানীয় ভেরিয়েবলের জন্য প্রয়োজনীয় মেমরিটি সম্ভাব্যভাবে গুরুত্বপূর্ণ হতে পারে, বিশেষত যদি সংকলক কার্যকরভাবে তাদের অপ্টিমাইটি না করে (বা কোডটি যদি অ্যাসেম্বলি ভাষায় সরাসরি লেখা থাকে)।

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


4

অ্যাসাইনমেন্টের পরে s = a + b; ভেরিয়েবল a এবং b আর ব্যবহার করা হয় না। অতএব, আপনি যদি সম্পূর্ণ মস্তিষ্ক-ক্ষতিগ্রস্থ সংকলক ব্যবহার না করেন তবে কোনও মেমরি ব্যবহার করা হয় না; মেমরি যা কোনওভাবে এবং খ এর জন্য ব্যবহৃত হয়েছিল তা আবার ব্যবহার করা হয়।

তবে এই ফাংশনটি অপ্টিমাইজ করা একেবারে বাজে কথা। আপনি যদি জায়গা বাঁচাতে পারতেন তবে ফাংশন চলাকালীন এটি 8 বাইট হতে পারে (যা ফাংশনটি ফিরে আসার পরে পুনরুদ্ধার করা হয়) তাই একেবারেই অর্থহীন। আপনি যদি সময় বাঁচাতে পারতেন তবে এটি একক সংখ্যক ন্যানো সেকেন্ড হবে। এটি অনুকূলিতকরণ মোট সময়ের অপচয়।


3

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

তারপরে এটি নির্ভর করে যে আপনি আপনার আবেদনের জন্য সবচেয়ে বেশি যত্নবান। প্রসেসিং গতি? রেসপন্স সময়? স্মৃতি পদচিহ্ন? Maintainability? ডিজাইনে ধারাবাহিকতা? সব আপনার উপর।


4
নিতপিকিং:। নেট কমপক্ষে (পোস্টের ভাষা অনির্ধারিত) স্থানীয় ভেরিয়েবলগুলি "স্ট্যাকের উপরে" বরাদ্দ দেওয়ার বিষয়ে কোনও গ্যারান্টি দেয় না। দেখুন "স্ট্যাক একটি বাস্তবায়ন বিস্তারিত হল" এরিক Lippert দ্বারা।
জুন

1
স্ট্যাক বা হিপগুলিতে @jrh স্থানীয় ভেরিয়েবলগুলি বাস্তবায়নের বিশদ হতে পারে, তবে যদি কেউ সত্যিই স্ট্যাকটিতে একটি ভেরিয়েবল চায় stackallocএবং এখন আছে Span<T>। প্রোফাইলের পরে কোনও গরম জায়গায় সম্ভবত কার্যকর useful এছাড়াও, স্ট্রাক্টের আশেপাশের কয়েকটি ডক্স সূচিত করে যে মানের ধরণ স্ট্যাকের মধ্যে থাকতে পারে যখন রেফারেন্সের ধরণগুলি হবে না । যাইহোক, সর্বোপরি আপনি কিছুটা জিসি এড়াতে পারেন।
বব

2

অন্যান্য উত্তরগুলি যেমন বলেছে, আপনার কী চিন্তা করা উচিত যা আপনি অনুকূল করছেন optim

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

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

বিবেচনা করার বিষয়গুলি:

  • মধ্যবর্তী অভিব্যক্তির কি কোনও পার্শ্ব প্রতিক্রিয়া রয়েছে? যদি এটি কোনও অপরিষ্কার ফাংশনগুলিকে কল করে বা কোনও ভেরিয়েবল আপডেট করে তবে অবশ্যই এটির অনুলিপি করা কেবল শৈলীর নয়, সঠিকতার বিষয় হবে।
  • মধ্যবর্তী প্রকাশটি কতটা জটিল? যদি এটি প্রচুর গণনা করে এবং / অথবা কলগুলি ফাংশন করে, তবে সংকলক এটি অপ্টিমাইজ করতে সক্ষম হতে পারে না এবং তাই এটি কার্য সম্পাদনকে প্রভাবিত করবে। (যদিও নুথ বলেছিলেন , "আমাদের ছোট দক্ষতাগুলি ভুলে যাওয়া উচিত, সময়ের প্রায় 97% বলি"))
  • মধ্যবর্তী পরিবর্তনশীলটির কোনও অর্থ আছে কি ? এটি কি এমন কোনও নাম দেওয়া যেতে পারে যা ঘটছে তা ব্যাখ্যা করতে সহায়তা করে? একটি সংক্ষিপ্ত তবে তথ্যবহুল নাম কোডটি আরও ভালভাবে ব্যাখ্যা করতে পারে, যখন অর্থহীন কোনওটি কেবল ভিজ্যুয়াল শোরগোল।
  • মধ্যবর্তী প্রকাশটি কতক্ষণ? যদি দীর্ঘ হয়, তবে এর সদৃশ করা কোডটি আরও দীর্ঘতর এবং আরও বেশি শক্ত করে পড়তে পারে (বিশেষত যদি এটি একটি লাইন বিরতিতে বাধ্য করে); যদি তা না হয় তবে সদৃশটি সর্বোপরি সংক্ষিপ্ত হতে পারে।

1

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

তবে আসুন এই প্রশ্নটি আবার দেখুন: এটি একটি সাক্ষাত্কারের প্রশ্ন। সুতরাং আসল বিষয়টি হ'ল, আপনি চেষ্টা করে কাজটি পেতে চান তা ধরে নিয়ে এর উত্তর কীভাবে দেওয়া উচিত?

আসুন ধরে নেওয়া যাক যে সাক্ষাত্কারকারক তারা কী সম্পর্কে কথা বলছে তা জানে এবং তারা কেবল আপনি কী জানেন তা দেখার চেষ্টা করছেন।

আমি উল্লেখ করব, অপ্টিমাইজারকে উপেক্ষা করে, প্রথমটি স্ট্যাকের উপর একটি অস্থায়ী পরিবর্তনশীল তৈরি করতে পারে যেখানে দ্বিতীয়টি নয়, তবে দুটি বার গণনা সম্পাদন করবে। অতএব, প্রথমটি আরও মেমরি ব্যবহার করে তবে দ্রুত is

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

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

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

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

এই সমস্ত প্রমাণ করে যে আপনি কী সম্পর্কে কথা বলছেন তা আপনি জানেন।

আমি এটিকে শেষ পর্যন্ত ছেড়ে দিয়ে বলব যে পরিবর্তে পঠনযোগ্যদের উপর ফোকাস করা ভাল। যদিও এই ক্ষেত্রে সত্য, সাক্ষাত্কারের প্রসঙ্গে এটি ব্যাখ্যা করা যেতে পারে "আমি পারফরম্যান্স সম্পর্কে জানি না তবে আমার কোডটি জ্যানেট এবং জন গল্পের মতো পড়ে "।

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

কোড পারফরম্যান্স একটি দুর্দান্ত অনেক সংস্থার একটি জেনুইন সমস্যা এবং অনেক সংস্থার এটি বুঝতে যারা প্রোগ্রামার প্রয়োজন।

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

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

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

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

সুতরাং, যদি সাক্ষাত্কারকারী আপনাকে পারফরম্যান্স সম্পর্কে জিজ্ঞাসা করে আমি যতটা সম্ভব জ্ঞান চেষ্টা করার চেষ্টা করব। যদি প্রশ্নটি খারাপ মনে হয় তবে আপনি কেন মনে করেন যে এটি কেন সেই ক্ষেত্রে সমস্যা হবে না pol নাথকে উদ্ধৃতি দেবেন না।


0

আপনার প্রথমে নির্ভুলতার জন্য অনুকূলিত করা উচিত।

আপনার ফাংশনটি ইনপ্যাক্স ম্যাক্সভ্যালুর কাছাকাছি থাকা ইনপুট মানগুলির জন্য ব্যর্থ:

int a = int.MaxValue - 200;
int b = int.MaxValue - 200;
bool inRange = test.IsSumInRangeA(a, b);

এটি সত্য প্রত্যাবর্তন করে কারণ যোগফল -400 এ প্রবাহিত হয়। ফাংশনটি a = int.MINValue + 200 এর জন্যও কাজ করে না ((ভুলভাবে "400" পর্যন্ত যোগ করে)

সাক্ষাত্কারকারীর কী চাওয়া ছিল তা আমরা জানব না যদি না সে বাতলে না পড়ে তবে "ওভারফ্লোটি আসল"

একটি সাক্ষাত্কারের পরিস্থিতিতে সমস্যার ক্ষেত্রটি পরিষ্কার করতে প্রশ্ন জিজ্ঞাসা করুন: অনুমোদিত সর্বোচ্চ এবং সর্বনিম্ন ইনপুট মানগুলি কী কী? একবার আপনার কাছে এটি হয়ে গেলে, যদি কলার সীমাটির বাইরে মান জমা দেয় তবে আপনি একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারেন। অথবা (সি # তে), আপনি একটি চেক করা}} বিভাগটি ব্যবহার করতে পারেন, যা ওভারফ্লোতে ব্যতিক্রম ঘটতে পারে। হ্যাঁ, এটি আরও বেশি কাজ এবং জটিল, তবে কখনও কখনও এটি এটি নেয়।


পদ্ধতিগুলি কেবল উদাহরণ ছিল। এগুলি সঠিক হতে লেখা হয়নি, তবে আসল প্রশ্নটি বর্ণনা করার জন্য। যদিও ইনপুট জন্য ধন্যবাদ!
ভাল বাজেট

আমি মনে করি সাক্ষাত্কারের প্রশ্নটি পারফরম্যান্সের ভিত্তিতে পরিচালিত হয়েছে, সুতরাং আপনাকে প্রশ্নের উদ্দেশ্যটির উত্তর দেওয়া দরকার। সাক্ষাত্কার প্রদানকারী সীমাতে আচরণ সম্পর্কে জিজ্ঞাসা করছে না। তবে আকর্ষণীয় দিক পয়েন্ট যাইহোক।
rghome

1
@ কোরির প্রশ্নের উত্তম হিসাবে ভাল সাক্ষাত্কারকারকগণ) বিষয়টি নিয়ে প্রার্থীর দক্ষতার মূল্যায়ন করুন, যেমনটি রাঘোমের পরামর্শ অনুসারে এখনও 2) বৃহত্তর ইস্যুগুলির উদ্বোধন হিসাবে (অব্যক্ত কার্যকরী নির্ভুলতার মতো) এবং সম্পর্কিত জ্ঞানের গভীরতা - এটি আরও তাই পরবর্তী কেরিয়ার সাক্ষাত্কারে - শুভকামনা।
chux

0

আপনার প্রশ্নটি হওয়া উচিত ছিল: "আমার কি এটিকে আদৌ অনুকূলিতকরণ করা দরকার?" "

সংস্করণ A এবং B একটি গুরুত্বপূর্ণ বিশদে পৃথক হয়েছে যা একটি পছন্দনীয় করে তোলে তবে এটি অপ্টিমাইজেশনের সাথে সম্পর্কিত নয়: আপনি কোডটি পুনরাবৃত্তি করবেন না।

প্রকৃত "অপ্টিমাইজেশন" কে সাধারণ সুব্রপ এক্সারিমেশন নির্মূল বলা হয়, যা প্রতিটি সংকলক এটি করে। অপ্টিমাইজেশন বন্ধ থাকলেও কেউ কেউ এই বেসিক অপ্টিমাইজেশনটি করে। সুতরাং এটি সত্যই কোনও অপ্টিমাইজেশন নয় (উত্পন্ন কোডটি অবশ্যই প্রতিটি ক্ষেত্রে প্রায় একই রকম হবে)।

তবে যদি এটি অপ্টিমাইজেশন না হয় তবে এটি কেন পছন্দনীয়? ঠিক আছে, আপনি কোড পুনরাবৃত্তি করবেন না, কে যত্নশীল!

ঠিক আছে সবার আগে, আপনার শর্তাধীন শর্তাদির ভুলটির অর্ধেক ভুল হওয়ার ঝুঁকি নেই। তবে আরও গুরুত্বপূর্ণ বিষয়, এই কোডটি পড়ার সাথে সাথেif((((wtf||is||this||longexpression)))) অভিজ্ঞতার পরিবর্তে আপনি যা করার চেষ্টা করছেন তা তাত্ক্ষণিকভাবে কুঁচকে যেতে পারে । পাঠক if(one || theother)যা দেখতে পায় তা হ'ল এটি একটি ভাল জিনিস। খুব কমই হয় না, আমি ঘটছি যে আপনিই সেই ব্যক্তি যে তিন বছর পরে আপনার নিজের কোড পড়ছেন এবং "ডাব্লুটিএফএফ এর অর্থ কি?" সেক্ষেত্রে এটি সর্বদা সহায়ক যদি আপনার কোডটি অবিলম্বে অভিপ্রায়টি কী তা জানিয়ে দেয়। একটি সাধারণ subexpression সঠিকভাবে নামকরণ করা হয়, এটি ক্ষেত্রে।
এছাড়াও, যদি ভবিষ্যতে কোনও সময়ে, আপনি সিদ্ধান্ত নেন যে উদাহরণস্বরূপ আপনাকে পরিবর্তন a+bকরতে হবে a-b, আপনাকে একটি পরিবর্তন করতে হবেঅবস্থান, দুটি নয়। এবং দুর্ঘটনাক্রমে দ্বিতীয়টি ভুল হওয়ার কোনও ঝুঁকি নেই।

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

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

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

অপ্টিমাইজেশন একটি কঠিন বিষয় (আপনি এটি সম্পর্কে পুরো বই লিখতে এবং শেষ করতে পারেন), এবং কিছু নির্দিষ্ট জায়গা অন্ধভাবে অপ্টিমাইজ করার জন্য সময় ব্যয় করা (এমনকি এটুকুও যে বাধা নয় তা না জেনেও!) সাধারণত সময় নষ্ট হয়। প্রোফাইলিং ছাড়া, অপ্টিমাইজেশন সঠিকভাবে পাওয়া খুব কঠিন hard

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

পূর্ববর্তী অনুচ্ছেদটিকে দৃষ্টিকোণে রাখার জন্য বিবেচনা করুন যে আপনি কী করতে পারেন বিভিন্ন জিনিস। a+bএক বা দুটি চক্র লাগে ( যেমন অপ্টিমাইজ না করা হয়) জাতীয় কিছু কার্যকর করা , তবে সিপিইউ সাধারণত চক্র প্রতি বেশ কয়েকটি নির্দেশনা শুরু করতে পারে এবং নির্ভরশীল নির্দেশগুলি পাইপলাইন করতে পারে তাই আরও বাস্তবসম্মতভাবে এটি আপনাকে অর্ধ চক্র বা তারও কম কিছু ব্যয় করতে পারে। আদর্শভাবে, যদি সংকলকটি সময় নির্ধারণে ভাল হয় এবং পরিস্থিতির উপর নির্ভর করে এটির দাম শূন্য হতে পারে।
ডেটা ("মেমরি") আনতে আপনার ভাগ্য হয় যদি আপনি ভাগ্যবান হন তবে 4-5 চক্র এবং এটি L1 এ এবং যদি আপনি এত ভাগ্যবান না হন তবে প্রায় 15 টি চক্র (এল 2 হিট) হয়। যদি ডেটা একেবারে ক্যাশে না থাকে তবে কয়েকশো চক্র লাগে। যদি আপনার হাফিজার্ড অ্যাক্সেস প্যাটার্নটি টিএলবির সক্ষমতা ছাড়িয়ে যায় (কেবলমাত্র ~ 50 এন্ট্রি দিয়ে করা সহজ), আরও কয়েক শতাধিক চক্র যুক্ত করুন। যদি আপনার হাফিজার্ড অ্যাক্সেস প্যাটার্নটি আসলে কোনও পৃষ্ঠা ত্রুটির কারণ হয়ে থাকে, তবে আপনাকে সেরা ক্ষেত্রে কয়েক দশ হাজার চক্র এবং সবচেয়ে খারাপের জন্য কয়েক মিলিয়ন খরচ করতে হবে।
এখন এটি সম্পর্কে চিন্তা করুন, আপনি কী জরুরি জিনিসটি জরুরিভাবে এড়াতে চান?


0

কখন কোনও পদ্ধতির জন্য মেমরি বনাম পারফরম্যান্স গতির জন্য অনুকূলিত করতে হবে?

পাওয়ার পর কার্যকারিতা ডান প্রথম । তারপরে মাইক্রো অপ্টিমাইজেশানগুলি নিয়ে চূড়ান্ততার বিষয়টি উদ্বেগ প্রকাশ করে।


অপ্টিমাইজেশান সম্পর্কিত একটি সাক্ষাত্কারের প্রশ্ন হিসাবে, কোডটি স্বাভাবিক আলোচনার প্ররোচনা দেয় না তবুও কোডটির উচ্চ স্তরের লক্ষ্যটি কী মিস হয় ?

সি ++ এবং সি এবং অন্যরা উভয়ই intওভারফ্লোকে এটিকে একটি সমস্যা হিসাবে বিবেচনা করে a + b। এটি ভালভাবে সংজ্ঞায়িত হয়নি এবং সি এটিকে অপরিজ্ঞাত আচরণ বলে । এটি "মোড়ানোর জন্য" নির্দিষ্ট করা হয়নি - যদিও এটি সাধারণ আচরণ।

bool IsSumInRange(int a, int b) {
    int s = a + b;  // Overflow possible
    if (s > 1000 || s < -1000) return false;
    else return true;
}

এই জাতীয় ক্রিয়াকলাপটি IsSumInRange()প্রত্যাশিত হবে যে সমস্ত intমানগুলির জন্য সঠিকভাবে সংজ্ঞায়িত হবে এবং সঠিকভাবে সম্পাদন করবে a,b। কাঁচা a + bহয় না। এসি সমাধান ব্যবহার করতে পারে:

#define N 1000
bool IsSumInRange_FullRange(int a, int b) {
  if (a >= 0) {
    if (b > INT_MAX - a) return false;
  } else {
    if (b < INT_MIN - a) return false;
  }
  int sum = a + b;
  if (sum > N || sum < -N) return false;
  else return true;
}

উপরের কোড চেয়ে বৃহত্তর পূর্ণসংখ্যা টাইপ ব্যবহার করে অপ্টিমাইজ করা যেতে পারে intনীচের হিসাবে, যদি পাওয়া যায় বা বিতরণ করছে sum > N, sum < -Nমধ্যে পরীক্ষার if (a >= 0)যুক্তি। তবুও এই ধরনের অপ্টিমাইজেশানগুলি স্মার্ট সংকলক প্রদত্ত "দ্রুত" নির্গত কোডের দিকে না যেতে পারে এবং চালাক হওয়ার অতিরিক্ত রক্ষণাবেক্ষণের পক্ষে মূল্যবান হতে পারে না।

  long long sum a;
  sum += b;

এমনকি ব্যবহার abs(sum)করা যখন সমস্যার ঝুঁকিপূর্ণ হয় sum == INT_MIN


0

আমরা কোন ধরণের সংকলক সম্পর্কে কথা বলছি এবং "মেমরি" কী ধরণের? কারণ আপনার উদাহরণে, যুক্তিসঙ্গত অপ্টিমাইজার ধরে ধরে, a+bএইরকম গাণিতিক করার আগে অভিব্যক্তিটি সাধারণত একটি রেজিস্টারে (মেমরির একটি ফর্ম) সংরক্ষণ করা দরকার।

সুতরাং আমরা যদি এমন বোবা সংকলক সম্পর্কে কথা বলি যা a+bদু'বার মুখোমুখি হয়, তবে এটি আপনার দ্বিতীয় উদাহরণে আরও রেজিস্ট্রি (মেমরি) বরাদ্দ করতে চলেছে , কারণ আপনার প্রথম উদাহরণটি কেবলমাত্র স্থানীয় ভেরিয়েবলের সাথে ম্যাপ করা একক রেজিস্টারে এই অভিব্যক্তিটি সংরক্ষণ করতে পারে, তবে আমরা 'এই মুহুর্তে খুব নিরীহ সংকলকগুলির বিষয়ে কথা বলছি ... আপনি যদি অন্য কোনও নির্বোধ সংকলক নিয়ে কাজ না করেন যা স্ট্যাকের জায়গায় সমস্ত একক চলক ছড়িয়ে পড়ে, এমন ক্ষেত্রে সম্ভবত প্রথমটি এটির চেয়ে অনুকূল হওয়ার জন্য আরও শোক করতে পারে দ্বিতীয়*.

আমি এখনও এটি স্ক্র্যাচ করতে চাই এবং মনে করি দ্বিতীয়টি সম্ভবত বোবা সংকলকটির সাথে আরও মেমরি ব্যবহার করতে পারে এমনকি যদি এটি স্রাবের ঝাঁকুনির ঝুঁকিপূর্ণ হয় তবে এটি তিনটি নিবন্ধ a+bএবং স্পিল aএবং bআরও অনেক কিছু বরাদ্দ করতে পারে । যদি আমরা সর্বাধিক আদিম অপটিমাইজারের সাথে কথা বলি তবে ক্যাপচার a+bকরা sসম্ভবত এটি "নিবন্ধ" কম রেজিস্টার / স্ট্যাকের স্পিল ব্যবহার করবে use

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

কখন কোনও পদ্ধতির জন্য মেমরি বনাম পারফরম্যান্স গতির জন্য অনুকূলিত করতে হবে?

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

তবে আমি খুঁজে পেয়েছি যে অনেকগুলি ডিভাইস এই ধরণের ক্ষেত্রে মেমরির ব্যবহারের হ্রাস কতটা সময় ব্যয় প্রক্রিয়াজাতকরণের আনুপাতিক হ্রাসকে অনুবাদ করতে পারে তা অবমূল্যায়ন করে। কেবলমাত্র অতিরিক্ত মেমরি অ্যাক্সেসের সাথে কর্মক্ষমতা হ্রাস করতে পারার জন্য কিছু ছোট ছোট কম্পিউটেশনকে গতিবদ্ধ করার ব্যর্থ প্রচেষ্টাতে বড় এলটিউইউগুলির কাছে পৌঁছানোর বিন্দুতে মেমরি অ্যাক্সেসের চেয়ে কর্মক্ষমতা ব্যয়কে নির্দেশনাতে অনুবাদ করা খুব মানবিক স্বজ্ঞাত।

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

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