সি ++ এ, আমি কী ভেরিয়েবলগুলি ক্যাশে করতে বিরক্ত করব, বা সংকলকটিকে অপ্টিমাইজেশন করতে দেওয়া উচিত? (Aliasing)


114

নিম্নলিখিত কোডটি বিবেচনা করুন ( pপ্রকারের unsigned char*এবং bitmap->widthকিছু পূর্ণসংখ্যার ধরণের, ঠিক কোনটি অজানা এবং নির্ভর করে আমরা কোনও বাহ্যিক গ্রন্থাগারের কোন সংস্করণ ব্যবহার করছি):

for (unsigned x = 0;  x < static_cast<unsigned>(bitmap->width);  ++x)
{
    *p++ = 0xAA;
    *p++ = 0xBB;
    *p++ = 0xCC;
}

এটি কি অপ্টিমাইজ করার উপযুক্ত [..]

এমন কোনও ঘটনা ঘটতে পারে যেখানে লেখার মাধ্যমে এটি আরও কার্যকর ফলাফল অর্জন করতে পারে:

unsigned width(static_cast<unsigned>(bitmap->width));
for (unsigned x = 0;  x < width;  ++x)
{
    *p++ = 0xAA;
    *p++ = 0xBB;
    *p++ = 0xCC;
}

... বা কম্পাইলারটি অপ্টিমাইজ করার জন্য এটি তুচ্ছ?

আপনি "আরও ভাল" কোড হিসাবে বিবেচনা করবেন?

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


19
যদি *pএকই ধরণের হয় widthতবে এটি অপ্টিমাইজ করা তুচ্ছ নয়, যেহেতু এটি লুপের অভ্যন্তরে pনির্দেশ করতে widthএবং এটি সংশোধন করতে পারে।
এম্লাই

31
সংকলক নির্দিষ্ট ক্রিয়াকলাপটিকে সর্বোত্তম করে তোলে কিনা তা জিজ্ঞাসা করা সাধারণত ভুল প্রশ্ন। আপনি (সাধারণত) যা সম্পর্কে শেষ পর্যন্ত আগ্রহী তা হ'ল কোন সংস্করণটি দ্রুত সঞ্চালিত হয়, যা আপনার কেবল মাপতে হবে।
স্যারগুই

4
@ গুয়গ্রিয়ার আমি একমত নই, যদিও আমি বলব যে প্রশ্নটি ভাল, বা কমপক্ষে আকর্ষণীয়, দুর্ভাগ্যক্রমে উত্তরটি "আপনার ব্যবহারের ক্ষেত্রে এটি পরিমাপ করতে হবে" thought কারণটি হ'ল কার্যকারিতা বহনযোগ্য তবে কার্য সম্পাদন নয়। সুতরাং এটি প্রকৃতপক্ষে বিল্ড প্রক্রিয়াটির প্রতিটি অংশের উপর নির্ভর করে, সংকলকটি শুরু করে লক্ষ্য সাইটে (OS / হার্ডওয়্যার সংমিশ্রণ) সমাপ্তি। এবং অবশ্যই সর্বোত্তম অনুমান যে সংকলকটি এটির চেয়ে মানুষের চেয়ে বেশি স্মার্ট।
luk32

19
আমি যদি সংকলক হয়ে থাকি তবে আমি দেখতে পেতাম যে আপনার দুটি উদাহরণ একই নয়। এটি pএকই স্মৃতিতে নির্দেশ করে এমনটি সম্ভব bitmap->width। অতএব আমি প্রথমটির উদাহরণটিকে আইনীভাবে সর্বোত্তম করতে পারি না।
রহস্যময়

4
"পি" কোথায় সংরক্ষণ করা হয়? আমি প্রস্তাব দেব যে আপনি "চর * সীমাবদ্ধ পি 2 = পি" এর মতো কিছু করে সত্যিই দুর্দান্ত পারফরম্যান্সের জয় পেতে পারেন; এবং তারপরে আপনার লুপের মধ্যে "পি" পরিবর্তে "পি 2" ব্যবহার করুন। তারপরে, আপনি যদি "p2" তে পরিবর্তনগুলি পি তে প্রয়োগ করতে চান, "p + = (p2-p);" ব্যবহার করুন। নোট করুন যে পি 2 এর জীবদ্দশায় কোনও পয়েন্টার লিখিত পয়েন্টার দ্বারা অনুলিপি করা হয়নি ফর্ম পি 2 অনুলিপি করা হয়েছে পয়েন্টার ব্যবহার করে পি 2 থেকে অনুলিপি করা যাবে না এবং পি 2 এর কোনও অনুলিপি পি 2 এর জীবদ্দশার পরে কোনও উদ্দেশ্যে ব্যবহার করা যাবে না, তবে একটি সংকলক সেগুলি ব্যবহার করতে পারে অপ্টিমাইজেশন সক্ষম করার জন্য তথ্য যা অন্য কোনও উপায়ে সম্পন্ন করা যায় না।
সুপারক্যাট

উত্তর:


81

প্রথম নজরে, আমি ভেবেছিলাম যে সংকলকটি অপটিমাইজেশন পতাকাগুলি সক্রিয় করে উভয় সংস্করণের জন্য সমমানের সমাবেশ তৈরি করতে পারে। যখন আমি এটি যাচাই করেছি, ফলাফলটি দেখে আমি অবাক হয়েছি:

উৎস unoptimized.cpp

দ্রষ্টব্য: এই কোডটি কার্যকর করা নয়।

struct bitmap_t
{
    long long width;
} bitmap;

int main(int argc, char** argv)
{
    for (unsigned x = 0 ; x < static_cast<unsigned>(bitmap.width) ; ++x)
    {
        argv[x][0] = '\0';
    }
    return 0;
}

উৎস optimized.cpp

দ্রষ্টব্য: এই কোডটি কার্যকর করা নয়।

struct bitmap_t
{
    long long width;
} bitmap;

int main(int argc, char** argv)
{
    const unsigned width = static_cast<unsigned>(bitmap.width);
    for (unsigned x = 0 ; x < width ; ++x)
    {
        argv[x][0] = '\0';
    }
    return 0;
}

সংকলন

  • $ g++ -s -O3 unoptimized.cpp
  • $ g++ -s -O3 optimized.cpp

সমাবেশ (নিরবচ্ছিন্ন.স)

    .file   "unoptimized.cpp"
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    movl    bitmap(%rip), %eax
    testl   %eax, %eax
    je  .L2
    xorl    %eax, %eax
    .p2align 4,,10
    .p2align 3
.L3:
    mov %eax, %edx
    addl    $1, %eax
    movq    (%rsi,%rdx,8), %rdx
    movb    $0, (%rdx)
    cmpl    bitmap(%rip), %eax
    jb  .L3
.L2:
    xorl    %eax, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
.globl bitmap
    .bss
    .align 8
    .type   bitmap, @object
    .size   bitmap, 8
bitmap:
    .zero   8
    .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-16)"
    .section    .note.GNU-stack,"",@progbits

সমাবেশ (অনুকূলিত)

    .file   "optimized.cpp"
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    movl    bitmap(%rip), %eax
    testl   %eax, %eax
    je  .L2
    subl    $1, %eax
    leaq    8(,%rax,8), %rcx
    xorl    %eax, %eax
    .p2align 4,,10
    .p2align 3
.L3:
    movq    (%rsi,%rax), %rdx
    addq    $8, %rax
    cmpq    %rcx, %rax
    movb    $0, (%rdx)
    jne .L3
.L2:
    xorl    %eax, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
.globl bitmap
    .bss
    .align 8
    .type   bitmap, @object
    .size   bitmap, 8
bitmap:
    .zero   8
    .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-16)"
    .section    .note.GNU-stack,"",@progbits

পরিবর্তন

$ diff -uN unoptimized.s optimized.s
--- unoptimized.s   2015-11-24 16:11:55.837922223 +0000
+++ optimized.s 2015-11-24 16:12:02.628922941 +0000
@@ -1,4 +1,4 @@
-   .file   "unoptimized.cpp"
+   .file   "optimized.cpp"
    .text
    .p2align 4,,15
 .globl main
@@ -10,16 +10,17 @@
    movl    bitmap(%rip), %eax
    testl   %eax, %eax
    je  .L2
+   subl    $1, %eax
+   leaq    8(,%rax,8), %rcx
    xorl    %eax, %eax
    .p2align 4,,10
    .p2align 3
 .L3:
-   mov %eax, %edx
-   addl    $1, %eax
-   movq    (%rsi,%rdx,8), %rdx
+   movq    (%rsi,%rax), %rdx
+   addq    $8, %rax
+   cmpq    %rcx, %rax
    movb    $0, (%rdx)
-   cmpl    bitmap(%rip), %eax
-   jb  .L3
+   jne .L3
 .L2:
    xorl    %eax, %eax
    ret

অপ্টিমাইজড সংস্করণটির জন্য উত্পন্ন সমাবেশটি আসলে ( lea) widthঅব্যবহৃত সংস্করণটির বিপরীতে ধ্রুবক লোড করে যা widthপ্রতিটি পুনরাবৃত্তিতে অফসেটটি গণনা করে (movq ) এর ।

যখন আমি সময় পাব, শেষ পর্যন্ত আমি এটিতে কিছু মানদণ্ড পোস্ট করব। ভাল প্রশ্ন.


3
আপনি যদি const unsignedকেবল unsignedবিনা চাপে ফেলে দেওয়া ক্ষেত্রে পরিবর্তে কাস্ট করেন তবে কোডটি অন্যভাবে তৈরি হয়েছিল কিনা তা দেখতে আকর্ষণীয় হবে ।
মার্ক রান্সম

2
@ মার্কারান্সম আমার ধারণা এটির কোনও পার্থক্য করা উচিত নয়: কনস্ট হওয়ার "প্রতিশ্রুতি" কেবলমাত্র একক তুলনা চলাকালীন, পুরো লুপের জন্য নয়
হ্যাগেন ভন ইটজেন

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

3
আপনি @ 100% ঠিক আছেন আমি তাড়াতাড়ি লিখেছি, আমি এটি উন্নতি করব।
ওয়াইএসসি

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

38

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

এর অর্থ এই ক্ষেত্রে যদি bitmap->widthপয়েন্টারের মাধ্যমে লুপটি পরিবর্তন হয় তবে pপুনরায় পড়ার সময় এটি দেখতে হবেbitmap->width পরে , যার পরিবর্তে এর অর্থ হল এটি স্থানীয় ভেরিয়েবলে সংরক্ষণ করা অবৈধ।

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

বলা হচ্ছে, আমি কেবল দুটি সংস্করণের পারফরম্যান্স পরিমাপ করার বিষয়ে আমার মন্তব্যে দাঁড়িয়ে আছি, কোডের দুটি সংস্করণের মধ্যে কোনও সামঞ্জস্যপূর্ণ পারফরম্যান্সের পার্থক্য না দেখায় আমার অর্থ ব্যয় হয়।

আমার মতে, এইগুলির মতো প্রশ্নগুলি ঠিক আছে যদি আপনার উদ্দেশ্যটি সংকলক অপ্টিমাইজেশন তত্ত্ব এবং কৌশলগুলি সম্পর্কে জানতে হয় তবে আপনার প্রোগ্রামটি দ্রুত চালিত করতে যদি এখানে আপনার শেষ লক্ষ্যটি হয় তবে সময়ের অপচয় (অকেজো মাইক্রো-অপ্টিমাইজেশন) is


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

3
@ গুয়গ্রিয়ার - restrictএই ক্ষেত্রে কোন কোয়ালিফায়ার আলিয়াসিং সমস্যার উত্তর হবে না ?
এলটিহোড

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

1
@ মিস্টিকাল: একটি বিষয় মনে রাখবেন তা হ'ল charসকল প্রকারের নাম রাখে, তাই আপনার যদি চর থাকে * তবে আপনাকে সমস্ত কিছু ব্যবহার করতে restrictহবে। অথবা আপনি যদি জিসিসির কঠোরভাবে আলিয়াজিংয়ের নিয়ম বন্ধ করে দিতে বাধ্য করেন -fno-strict-aliasingতবে সমস্ত কিছুকে একটি সম্ভাব্য উপনাম হিসাবে বিবেচনা করা হয়।
Zan Lynx

1
@ রে restrictসি -++ এর মতো-মত শব্দার্থবিদ্যার জন্য সর্বশেষতম প্রস্তাবটি হ'ল এন 4150
টিসি

24

ঠিক আছে, ছেলেরা, তাই আমি পরিমাপ করেছি, দিয়ে GCC -O3 (লিনাক্স x64 এ জিসিসি 4.9 ব্যবহার করে) ।

দেখা যাচ্ছে, দ্বিতীয় সংস্করণটি 54% দ্রুত চলে!

সুতরাং, আমি অনুমান করি যে এলিয়াসিং জিনিসটি, আমি এটি সম্পর্কে ভাবিনি।

[সম্পাদনা]

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

[সম্পাদনা 2]

ঠিক আছে, আমি মনে করি আমি প্রমাণ করতে পেরেছিলাম যে এলিয়াসিং সমস্যা is আমি আমার আসল পরীক্ষার পুনরাবৃত্তি করেছি, এবার পয়েন্টারের চেয়ে অ্যারে ব্যবহার করছি:

const std::size_t n = 0x80000000ull;
bitmap->width = n;
static unsigned char d[n*3];
std::size_t i=0;
for (unsigned x = 0;  x < static_cast<unsigned>(bitmap->width);  ++x)
{
    d[i++] = 0xAA;
    d[i++] = 0xBB;
    d[i++] = 0xCC;
}

এবং পরিমাপ করা হয়েছে (এটি লিঙ্ক করতে "-mcmodel = বৃহত" ব্যবহার করতে হবে)। তারপরে আমি চেষ্টা করেছি:

const std::size_t n = 0x80000000ull;
bitmap->width = n;
static unsigned char d[n*3];
std::size_t i=0;
unsigned width(static_cast<unsigned>(bitmap->width));
for (unsigned x = 0;  x < width;  ++x)
{
    d[i++] = 0xAA;
    d[i++] = 0xBB;
    d[i++] = 0xCC;
}

পরিমাপের ফলাফলগুলি একই ছিল - দেখে মনে হয় যে সংকলকটি নিজে থেকেই এটি অপ্টিমাইজ করতে সক্ষম হয়েছিল।

তারপরে আমি মূল কোডগুলি চেষ্টা করেছি (একটি পয়েন্টার সহ p), এবার pটাইপ করার সময় std::uint16_t*। আবার, ফলাফলগুলি একই ছিল - কড়া আলিয়াজিংয়ের কারণে। তারপরে আমি "-ফনো-কড়া-আলিয়াজিং" দিয়ে নির্মাণের চেষ্টা করেছি এবং আবার সময়ের মধ্যে একটি পার্থক্য দেখেছি।


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

@ গুয়গ্রিয়ার: আমার [সম্পাদনা 2] দেখুন - এখন আমি মনে করি এটি বেশ প্রমাণিত।
ইয়ারন কোহেন-তাল

2
আমি কেবল আশ্চর্য হই যে আপনি যখন আপনার লুপটিতে "x" রেখেছেন তখন আপনি "i" পরিবর্তনশীলটি কেন ব্যবহার শুরু করেছিলেন?
জেস্পার ম্যাডসেন

1
এটি কি আমিই বুঝতে পারি যে 54% শব্দটি বোঝা শক্ত? আপনি কি বোঝাতে চেয়েছেন যে এটি বিনা চাপানো গতির চেয়ে 1.54 গুণ, বা অন্য কিছু?
রডি

3
@ ইয়ারনকোহেন-তাল এত দ্বিগুণ? চিত্তাকর্ষক, তবে "54% দ্রুত" বোঝার অর্থ কী তা নয়!
রডি

24

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

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

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

for (unsigned x = static_cast<unsigned>(bitmap->width);x > 0;  x--)
{
    *p++ = 0xAA;
    *p++ = 0xBB;
    *p++ = 0xCC;
}

নোট করুন যে লুপটির এই সংস্করণটি 0 এর পরিসরের পরিবর্তে 1.. প্রস্থে x মান দেয় (প্রস্থ -১)। এটি আপনার ক্ষেত্রে গুরুত্বপূর্ণ নয় কারণ আপনি আসলে কোনও কিছুর জন্য এক্স ব্যবহার করছেন না তবে এটি সচেতন হওয়ার মতো কিছু। আপনি যদি 0 এর পরিসীমাতে x মানগুলির সাথে একটি কাউন্ট ডাউন লুপ চান তবে (প্রস্থ -১) আপনি করতে পারেন।

for (unsigned x = static_cast<unsigned>(bitmap->width); x-- > 0;)
{
    *p++ = 0xAA;
    *p++ = 0xBB;
    *p++ = 0xCC;
}

আপনি উপরের উদাহরণগুলিতে কাস্ট থেকেও মুক্তি পেতে পারেন যদি আপনি তুলনা বিধিগুলির উপর এর প্রভাব সম্পর্কে চিন্তা না করেই চান যেহেতু আপনি বিটম্যাপ-> প্রস্থের সাথে যা যা করছেন সবই এটি সরাসরি একটি ভেরিয়েবলের জন্য বরাদ্দ করে।


2
আমি সেই দ্বিতীয় x --> 0কেসটিকে ফর্ম্যাট করে দেখেছি যার ফলস্বরূপ "ডাউনটো" অপারেটর রয়েছে। খুবই হাস্যকর. পিএস আমি শেষের শর্তটিকে পাঠযোগ্যতার জন্য নেতিবাচক হিসাবে বিবেচনা করি না, এটি আসলে বিপরীত হতে পারে।
মার্ক র্যানসোম

এটি সত্যই নির্ভর করে, কখনও কখনও একটি বিবৃতি এত ভয়াবহ হয় যে এটি একাধিক বিবৃতিতে ভাঙ্গা পাঠযোগ্যতার উন্নতি করে তবে আমি এখানে বিশ্বাস করি না।
প্লাগওয়াশ

1
+1 ভাল পর্যবেক্ষণ, যদিও আমি যুক্তি দিয়ে বলব যে লুপটি উত্তোলন করা static_cast<unsigned>(bitmap->width)এবং widthতার পরিবর্তে লুপটি ব্যবহার করা পঠনযোগ্যতার জন্য উন্নতি কারণ এখন পাঠকটির জন্য প্রতি লাইনে পার্স করার কম জিনিস রয়েছে। অন্যের মতামত ভিন্ন হতে পারে।
সিরগুই

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

3
যদি আপনি এমন লুপগুলি লিখতে চান যা দেখতে সর্বোত্তম asm এর মতো do { } while()লাগে তবে ব্যবহার করুন , কারণ ASM এ আপনি শেষে শর্তযুক্ত শাখা দিয়ে লুপগুলি তৈরি করেন। স্বাভাবিক for(){}এবং while(){}লুপ একবার লুপ আগে, যদি কম্পাইলার এটা প্রমান করতে পারবে না সবসময় অন্তত একবার রান লুপ শর্ত পরীক্ষা করার জন্য অতিরিক্ত নির্দেশাবলী প্রয়োজন। সব উপায়ে, ব্যবহার দ্বারা for()বা while()যখন এটা যদি লুপ এমনকি একবার চালানো উচিত চেক করতে দরকারী, অথবা যখন এটি আরো পাঠযোগ্য নয়।
পিটার কর্ডেস

11

এখানে একমাত্র জিনিস যা অপ্টিমাইজেশন প্রতিরোধ করতে পারে তা হ'ল কঠোর আলিয়াজিং নিয়মসংক্ষেপে :

"স্ট্রাইক অ্যালাইজিং হ'ল একটি অনুমান যা সি (বা সি ++) সংকলক দ্বারা তৈরি করা হয় যে বিভিন্ন ধরণের বস্তুর প্রতি পয়েন্টারগুলি ডিপ্রিফারেন্সিং কখনও একই মেমোরি অবস্থানের (যেমন একে অপরকে ওরফে।) উল্লেখ করে না" "

[...]

নিয়মের ব্যতিক্রম ক char*, যা কোনও প্রকারের দিকে নির্দেশ করার অনুমতিপ্রাপ্ত is

ব্যতিক্রমটিও প্রযোজ্য unsignedএবংsigned char পয়েন্টার।

এটি আপনার কোডে ক্ষেত্রে দেখা যায়: তুমি পরিবর্তন *pমাধ্যমে pযা হয় unsigned char*, তাই কম্পাইলার আবশ্যক অনুমান এটি নির্দেশ পারে bitmap->width। সুতরাং ক্যাচিং bitmap->widthএকটি অবৈধ অপ্টিমাইজেশন। এই অপ্টিমাইজেশন-প্রতিরোধকারী আচরণটি ওয়াইএসসির উত্তরে দেখানো হয়েছে

যদি এবং কেবল যদি pঅ- charএবং অ- টাইপকে নির্দেশ করা হয় decltype(bitmap->width), তবে ক্যাশিংটি একটি সম্ভাব্য অপ্টিমাইজেশন হতে পারে।


10

প্রশ্নটি মূলত:

এটা কি এটি অনুকূলকরণ মূল্য?

এবং আমার এই উত্তর (উভয় আপ এবং ডাউন ভোটের একটি ভাল মিশ্রণ সংগ্রহ করে ..)

সংকলকটি এটি সম্পর্কে উদ্বিগ্ন হোক।

সংকলকটি অবশ্যই আপনার চেয়ে আরও ভাল কাজ করবে। এবং আপনার 'অপ্টিমাইজেশন' 'সুস্পষ্ট' কোডের চেয়ে ভাল যে কোনও গ্যারান্টি নেই - আপনি কি এটি পরিমাপ করেছেন ??

আরও গুরুত্বপূর্ণ, আপনি যে কোডটি অপ্টিমাইজ করছেন সেটি আপনার প্রোগ্রামের কার্যকারণে কোনও প্রভাব ফেলেছে তার কোনও প্রমাণ আছে কি?

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

একটি বরং ভিন্ন প্রশ্ন, অবশ্যই এটি হবে:

কোডের একটি টুকরোটি অনুকূল করার মতো কিনা তা আমি কীভাবে বলতে পারি?

প্রথমত, আপনার অ্যাপ্লিকেশন বা লাইব্রেরিটি বর্তমানে চালিত হওয়ার চেয়ে দ্রুত চালানো দরকার? ব্যবহারকারী কি খুব দীর্ঘ অপেক্ষায় রয়েছেন? আপনার সফ্টওয়্যার কি আগামীকালের পরিবর্তে গতকালের আবহাওয়ার পূর্বাভাস দেয়?

আপনার সফ্টওয়্যারটি কী এবং আপনার ব্যবহারকারীরা কী আশা করছেন তার উপর নির্ভর করে কেবলমাত্র আপনি সত্যিই এটি বলতে পারবেন।

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

যাইহোক, 'অনুকূলিতকরণ' বলতে কী বোঝ?

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

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

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


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

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

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

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

6

আমি পরিস্থিতিটিতে নিম্নলিখিত প্যাটার্নটি ব্যবহার করি। এটি আপনার প্রথম কেস হিসাবে প্রায় সংক্ষিপ্ত, এবং দ্বিতীয় কেসের চেয়ে ভাল, কারণ এটি অস্থায়ী পরিবর্তনশীল স্থানীয় লুপকে রাখে।

for (unsigned int x = 0, n = static_cast<unsigned>(bitmap->width); x < n; ++x)
{
  *p++ = 0xAA;
  *p++ = 0xBB;
  *p++ = 0xCC;
}

এটি স্মার্ট সংকলক, ডিবাগ বিল্ড, বা নির্দিষ্ট সংকলন পতাকাগুলির চেয়ে কম সহ দ্রুত হবে।

সম্পাদনা 1 : একটি লুপের বাইরে ধ্রুবক ক্রিয়াকলাপ স্থাপন করা ভাল প্রোগ্রামিং প্যাটার্ন। এটি মেশিন ক্রিয়াকলাপের বিশেষত সি / সি ++ এর বুনিয়াদি বোঝে। আমি যুক্তি দিয়ে বলছি যে এই প্রথাটি অনুসরণ করে না এমন লোকদের নিজেদের প্রমাণ করার চেষ্টা করা উচিত। সংকলক যদি কোনও ভাল প্যাটার্নের জন্য শাস্তি দেয় তবে এটি সংকলকটিতে একটি বাগ।

সম্পাদনা 2 : আমি বনাম 2013 এর মূল কোডটির বিপরীতে আমার পরামর্শ পরিমাপ করেছি,% 1 উন্নতি পেয়েছি। আমরা কি আরও ভাল করতে পারি? একটি সাধারণ ম্যানুয়াল অপ্টিমাইজেশন বিদেশী নির্দেশাবলী অবলম্বন না করে x64 মেশিনে মূল লুপের চেয়ে 3 গুণ উন্নতি দেয়। নীচের কোডটি সামান্য এন্ডিয়ান সিস্টেম ধরেছে এবং যথাযথভাবে বিটম্যাপটি সংযুক্ত করেছে। টেস্ট 0 মূল (9 সেকেন্ড), টেস্ট 1 দ্রুত (3 সেকেন্ড)। আমি বাজি ধরছি যে কেউ এটি আরও দ্রুত তৈরি করতে পারে এবং পরীক্ষার ফলাফল বিটম্যাপের আকারের উপর নির্ভর করবে। অবশ্যই ভবিষ্যতে খুব শীঘ্রই, সংকলক ধারাবাহিকভাবে দ্রুততম কোড তৈরি করতে সক্ষম হবে। আমি আশঙ্কা করি এটি ভবিষ্যতে যখন সংকলকটিও একজন প্রোগ্রামার এআই হবে, সুতরাং আমরা কাজের বাইরে থাকব। তবে আপাতত, কেবল কোড লিখুন যা দেখায় যে আপনি জানেন যে লুপে অতিরিক্ত অপারেশন প্রয়োজন হয় না।

#include <memory>
#include <time.h>

struct Bitmap_line
{
  int blah;
  unsigned int width;
  Bitmap_line(unsigned int w)
  {
    blah = 0;
    width = w;
  }
};

#define TEST 0 //define 1 for faster test

int main(int argc, char* argv[])
{
  unsigned int size = (4 * 1024 * 1024) / 3 * 3; //makes it divisible by 3
  unsigned char* pointer = (unsigned char*)malloc(size);
  memset(pointer, 0, size);
  std::unique_ptr<Bitmap_line> bitmap(new Bitmap_line(size / 3));
  clock_t told = clock();
#if TEST == 0
  for (int iter = 0; iter < 10000; iter++)
  {
    unsigned char* p = pointer;
    for (unsigned x = 0; x < static_cast<unsigned>(bitmap->width); ++x)
    //for (unsigned x = 0, n = static_cast<unsigned>(bitmap->width); x < n; ++x)
    {
      *p++ = 0xAA;
      *p++ = 0xBB;
      *p++ = 0xCC;
    }
  }
#else
  for (int iter = 0; iter < 10000; iter++)
  {
    unsigned char* p = pointer;
    unsigned x = 0;
    for (const unsigned n = static_cast<unsigned>(bitmap->width) - 4; x < n; x += 4)
    {
      *(int64_t*)p = 0xBBAACCBBAACCBBAALL;
      p += 8;
      *(int32_t*)p = 0xCCBBAACC;
      p += 4;
    }

    for (const unsigned n = static_cast<unsigned>(bitmap->width); x < n; ++x)
    {
      *p++ = 0xAA;
      *p++ = 0xBB;
      *p++ = 0xCC;
    }
  }
#endif
  double ms = 1000.0 * double(clock() - told) / CLOCKS_PER_SEC;
  printf("time %0.3f\n", ms);

  {
    //verify
    unsigned char* p = pointer;
    for (unsigned x = 0, n = static_cast<unsigned>(bitmap->width); x < n; ++x)
    {
      if ((*p++ != 0xAA) || (*p++ != 0xBB) || (*p++ != 0xCC))
      {
        printf("EEEEEEEEEEEEERRRRORRRR!!!\n");
        abort();
      }
    }
  }

  return 0;
}

আপনি যদি int64_t এবং int32_t এর পরিবর্তে তিনটি int64_t ব্যবহার করেন তবে আপনি আরও 25% 64 বিট এ সঞ্চয় করতে পারবেন।
আন্তোনে লেজসেক

5

দুটি বিষয় বিবেচনা করতে হবে।

ক) কতক্ষণ অপটিমাইজেশন চলবে?

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

খ) এটি কি কোডটিকে রক্ষণাবেক্ষণ / সমস্যা সমাধানে আরও শক্ত করে তুলবে?

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

এটি বলেছিল আমি ব্যক্তিগতভাবে বি উদাহরণটি ব্যবহার করব।


4

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


4

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

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

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

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

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


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

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

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

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

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

4

তুলনা ভুল দুই কোড স্নিপেট যেহেতু

for (unsigned x = 0;  x < static_cast<unsigned>(bitmap->width);  ++x)

এবং

unsigned width(static_cast<unsigned>(bitmap->width));
for (unsigned x = 0;  x<width ;  ++x)

সমতুল্য নয়

প্রথম ক্ষেত্রে widthনির্ভরশীল এবং দৃ const় নয়, এবং কেউ অনুমান করতে পারে না যে এটি পরবর্তী পুনরাবৃত্তির মধ্যে পরিবর্তন হতে পারে না। সুতরাং এটি অনুকূলিত করা যায় না, তবে প্রতিটি লুপে পরীক্ষা করতে হবে

আপনার অপ্টিমাইজড ক্ষেত্রে একটি স্থানীয় ভেরিয়েবলেরbitmap->width প্রোগ্রাম নির্বাহের সময় কোনও সময়ে এর মান নির্ধারিত হয় । সংকলকটি যাচাই করতে পারে যে এটি আসলে পরিবর্তন হয় না।

আপনি কি একাধিক থ্রেডিংয়ের কথা ভেবেছিলেন বা মানটি বহিরাগতভাবে নির্ভর করতে পারে যে এর মানটি উদ্বায়ী। আপনি যদি না বলেন তবে কীভাবে কেউ এই সমস্ত বিষয়টি সংকলকটি খুঁজে বের করতে পারে?

সংকলকটি কেবল আপনার কোড যেমন দেয় তেমন ভাল করতে পারে।


2

সংকলক কোডটি ঠিক কীভাবে অনুকূল করে তা আপনি যদি না জানেন তবে কোডের পঠনযোগ্যতা এবং ডিজাইন রেখে নিজেরাই অনুকূলিতকরণ করা ভাল। ব্যবহারিকভাবে আমরা নতুন সংকলক সংস্করণে যে ফাংশনটি লিখি তার জন্য সমাবেশ কোড পরীক্ষা করা শক্ত to


1

সংকলক অনুকূলিত করতে পারে না bitmap->widthকারণ widthমানগুলির পুনরাবৃত্তির মধ্যে পরিবর্তন করা যায়। কয়েকটি খুব সাধারণ কারণ রয়েছে:

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

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

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