c++ - বর্গের ক্ষেত্রফল নির্ণয়ের সূত্র




আরো দক্ষ কি? বর্গ ব্যবহার করে বর্গক্ষেত্র বা নিজেই এটি দিয়ে গুণিত? (5)

এই দুটি পদ্ধতি কি সি আরও দক্ষ? এবং কিভাবে সম্পর্কে:

pow(x,3)

বনাম

x*x*x // etc?

আমি x*x*... মধ্যে পারফরম্যান্সের পার্থক্য পরীক্ষা করেছিলাম।

#include <cstdlib>
#include <cmath>
#include <boost/date_time/posix_time/posix_time.hpp>

inline boost::posix_time::ptime now()
{
    return boost::posix_time::microsec_clock::local_time();
}

#define TEST(num, expression) \
double test##num(double b, long loops) \
{ \
    double x = 0.0; \
\
    boost::posix_time::ptime startTime = now(); \
    for (long i=0; i<loops; ++i) \
    { \
        x += expression; \
        x += expression; \
        x += expression; \
        x += expression; \
        x += expression; \
        x += expression; \
        x += expression; \
        x += expression; \
        x += expression; \
        x += expression; \
    } \
    boost::posix_time::time_duration elapsed = now() - startTime; \
\
    std::cout << elapsed << " "; \
\
    return x; \
}

TEST(1, b)
TEST(2, b*b)
TEST(3, b*b*b)
TEST(4, b*b*b*b)
TEST(5, b*b*b*b*b)

template <int exponent>
double testpow(double base, long loops)
{
    double x = 0.0;

    boost::posix_time::ptime startTime = now();
    for (long i=0; i<loops; ++i)
    {
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
        x += std::pow(base, exponent);
    }
    boost::posix_time::time_duration elapsed = now() - startTime;

    std::cout << elapsed << " ";

    return x;
}

int main()
{
    using std::cout;
    long loops = 100000000l;
    double x = 0.0;
    cout << "1 ";
    x += testpow<1>(rand(), loops);
    x += test1(rand(), loops);

    cout << "\n2 ";
    x += testpow<2>(rand(), loops);
    x += test2(rand(), loops);

    cout << "\n3 ";
    x += testpow<3>(rand(), loops);
    x += test3(rand(), loops);

    cout << "\n4 ";
    x += testpow<4>(rand(), loops);
    x += test4(rand(), loops);

    cout << "\n5 ";
    x += testpow<5>(rand(), loops);
    x += test5(rand(), loops);
    cout << "\n" << x << "\n";
}

ফলাফল হল:

1 00:00:01.126008 00:00:01.128338 
2 00:00:01.125832 00:00:01.127227 
3 00:00:01.125563 00:00:01.126590 
4 00:00:01.126289 00:00:01.126086 
5 00:00:01.126570 00:00:01.125930 
2.45829e+54

মনে রাখবেন যে কম্পাইলার এটি অপটিমাইজ করে না তা নিশ্চিত করার জন্য প্রতিটি পা হিসাবের ফলাফল সংগ্রহ করে।

যদি আমি std::pow(double, double) সংস্করণ এবং loops = 1000000l করি তবে আমি পেতে পারি:

1 00:00:00.011339 00:00:00.011262 
2 00:00:00.011259 00:00:00.011254 
3 00:00:00.975658 00:00:00.011254 
4 00:00:00.976427 00:00:00.011254 
5 00:00:00.973029 00:00:00.011254 
2.45829e+52

এটি একটি ইন্টেল কোর ডুয়ে চলছে উবুন্টু 9.10 64 বিট। GO 4.4.1 -O2 অপ্টিমাইজেশান ব্যবহার করে কম্পাইল।

সুতরাং সি তে, হ্যাঁ x*x*x pow(x, 3) চেয়ে দ্রুত হবে কারণ কোনও পা pow(double, int) ওভারলোড নেই। সি ++ তে, এটি প্রায় একই রকম হবে। (আমার পরীক্ষায় পদ্ধতি অনুমান সঠিক।)

এটি একটি Markm দ্বারা মন্তব্যের প্রতিক্রিয়া হয়:

এমনকি যদি একটি using namespace std <cmath> নির্দেশিকা জারি করা হয়, তবে যদি pow দ্বিতীয় প্যারামিটারটি একটি int , তবে <cmath> থেকে std::pow(double, int) <cmath> বলা হবে ::pow(double, double) পরিবর্তে <math.h>

এই পরীক্ষা কোড যে আচরণ নিশ্চিত করে:

#include <iostream>

namespace foo
{

    double bar(double x, int i)
    {
        std::cout << "foo::bar\n";
        return x*i;
    }


}

double bar(double x, double y)
{
    std::cout << "::bar\n";
    return x*y;
}

using namespace foo;

int main()
{
    double a = bar(1.2, 3); // Prints "foo::bar"
    std::cout << a << "\n";
    return 0;
}

আমি একই সমস্যা নিয়ে ব্যস্ত ছিলাম, এবং আমি ফলাফল দ্বারা বেশ বিরক্তিকর। আমি n-body অবস্থানে নিউটনীয় মহাকর্ষের জন্য x⁻³ / ² অনুমান করছিলাম (ভর দ্রবণের অন্য কোনও দেহ থেকে দ্রুতি ভেক্টর ডি এ অবস্থিত): a = MG d*(d²)⁻³/² (যেখানে d² হয় ডট (scalar) পণ্য নিজেই দ্বারা), এবং আমি গণনা M*G*pow(d2, -1.5) M*G/d2/sqrt(d2) তুলনায় সহজ হবে

কৌশলটি ছোট সিস্টেমগুলির জন্য সত্য, কিন্তু সিস্টেমগুলি আকারে বৃদ্ধি পায়, M*G/d2/sqrt(d2) আরও দক্ষ হয়ে ওঠে এবং আমি বুঝতে পারছি না কেন সিস্টেমের আকার এই ফলাফলকে প্রভাবিত করে, কারণ পুনরাবৃত্তি বিভিন্ন তথ্য অপারেশন না। যেমন সিস্টেমটি হত্তয়া সম্ভব সম্ভাব্য অপটিমাইজেশন ছিল, কিন্তু যা পা সঙ্গে সম্ভব হয় না


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

(যদি আপনি ভিজ্যুয়াল সি ++ ব্যবহার করেন তবে std::pow(float,int) অপ্টিমাইজেশানটি আমি সম্পাদন করি যা অপারেশনের ক্রমটি এক্সপোনেন্টের বিট প্যাটার্নের সাথে সম্পর্কিত। আমি কোন গ্যারান্টি দেয় না যে কম্পাইলার লুপটি আনলোল করবে আপনি, যদিও, তাই এটা হাত দ্বারা এটা এখনও মূল্য।)

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


যে ভুল ধরনের প্রশ্ন। সঠিক প্রশ্নটি হ'ল: "আমার কোডের মানুষের পাঠকদের জন্য কোনটি সহজে বোঝা সহজ?"

গতি গতি (পরে), জিজ্ঞাসা করবেন না, কিন্তু পরিমাপ। (এবং এর আগে, অনুমান করুন যে এটি আসলেই কোনও উল্লেখযোগ্য পার্থক্য তৈরি করবে কিনা তা পরিমাপ করুন।) তারপরে, কোডটি লিখুন যাতে এটি সহজে পড়তে পারে।

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

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

এমনকি যদি কোন একক অপারেশন (কিছু মানের স্কোয়ার গণনা করার মতো) অ্যাপ্লিকেশনটির কার্যকর সময় (যা আইএমই খুব বিরল) এর 10% নেয় এবং এমনকি যদি এটি অপ্টিমাইজেশান করা হয় তবে সেই ক্রিয়াকলাপের জন্য প্রয়োজনীয় 50% সময় সঞ্চয় করে (যা আইএমই হয় এমনকি অনেক, খুব বিরল), আপনি এখনও অ্যাপ্লিকেশনটি 5% কম সময় নিচ্ছেন
আপনার ব্যবহারকারী এমনকি যে বিজ্ঞপ্তি একটি স্টপওয়াচ প্রয়োজন হবে। (বেশিরভাগ ক্ষেত্রেই ২0% স্পিডআপের যেকোনো কিছুই বেশিরভাগ ব্যবহারকারীর জন্য নজর দেওয়া যায় না এবং এটি এমন চারটি দাগ যা আপনাকে খুঁজে বের করতে হবে।)


x*x বা x*x*x pow তুলনায় দ্রুততর হবে, কারণ pow সাধারণ ক্ষেত্রে মোকাবেলা করতে হবে, তবে x*x নির্দিষ্ট। এছাড়াও, আপনি ফাংশন কল এবং অনুরূপ উপভোগ করতে পারেন।

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





optimization