C ++ এ দীর্ঘ সমীকরণ প্রয়োগ করার সময় আমি কীভাবে একটি উচ্চ-স্তরের পদ্ধতির মাধ্যমে কর্মক্ষমতা উন্নত করতে পারি


92

আমি কিছু ইঞ্জিনিয়ারিং সিমুলেশন বিকাশ করছি। এর মধ্যে উপাদানের মতো রাবারের স্ট্রেস গণনা করার জন্য এই সমীকরণের মতো কিছু দীর্ঘ সমীকরণ বাস্তবায়ন করা হয়:

T = (
    mu * (
            pow(l1 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a
            * (
                pow(l1 * l2 * l3, -0.1e1 / 0.3e1)
                - l1 * l2 * l3 * pow(l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1
            ) * pow(l1 * l2 * l3, 0.1e1 / 0.3e1) / l1
            - pow(l2 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a / l1 / 0.3e1
            - pow(l3 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a / l1 / 0.3e1
        ) / a
    + K * (l1 * l2 * l3 - 0.1e1) * l2 * l3
) * N1 / l2 / l3

+ (
    mu * (
        - pow(l1 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a / l2 / 0.3e1
        + pow(l2 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a
        * (
            pow(l1 * l2 * l3, -0.1e1 / 0.3e1)
            - l1 * l2 * l3 * pow(l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1
        ) * pow(l1 * l2 * l3, 0.1e1 / 0.3e1) / l2
        - pow(l3 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a / l2 / 0.3e1
    ) / a
    + K * (l1 * l2 * l3 - 0.1e1) * l1 * l3
) * N2 / l1 / l3

+ (
    mu * (
        - pow(l1 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a / l3 / 0.3e1
        - pow(l2 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a / l3 / 0.3e1
        + pow(l3 * pow(l1 * l2 * l3, -0.1e1 / 0.3e1), a) * a
        * (
            pow(l1 * l2 * l3, -0.1e1 / 0.3e1)
            - l1 * l2 * l3 * pow(l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1
        ) * pow(l1 * l2 * l3, 0.1e1 / 0.3e1) / l3
    ) / a
+ K * (l1 * l2 * l3 - 0.1e1) * l1 * l2
) * N3 / l1 / l2;

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

এই বাস্তবায়নটি অপ্টিমাইজ করার জন্য আমি কোন পদ্ধতি গ্রহণ করতে পারি? আমি উচ্চ-স্তরের কৌশলগুলি সন্ধান করছি যা এ জাতীয় সমীকরণগুলি প্রয়োগ করার সময় আমার প্রয়োগ করা উচিত, উপরের উদাহরণের জন্য প্রয়োজনীয় অপরিহার্যতা অগত্যা নয়।

আমি g ++ ব্যবহার করে সংকলন করছি --enable-optimize=-O3

হালনাগাদ:

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

l1, l2, l3, mu, a, K সমস্ত ইতিবাচক বাস্তব সংখ্যা (শূন্য নয়)।

আমি প্রতিস্থাপিত হয়েছে l1*l2*l3একটি সমতুল্য পরিবর্তনশীল সঙ্গে J। এটি কার্যকারিতা উন্নত করতে সহায়তা করেছিল।

প্রতিস্থাপন করা হচ্ছে pow(x, 0.1e1/0.3e1)সঙ্গে cbrt(x)একটি ভাল পরামর্শ ছিল।

এটি সিপিইউতে পরিচালিত হবে, অদূর ভবিষ্যতে জিপিইউতে সম্ভবত এটি আরও ভাল চলবে, তবে আপাতত এই বিকল্পটি উপলব্ধ নেই।


32
ঠিক আছে, যা মনে মনে প্রথম আসে (যদি না সংকলক নিজেই এটি অপ্টিমাইজ করে না) হ'ল তাদের pow(l1 * l2 * l3, -0.1e1 / 0.3e1)পরিবর্তনশীল সহ সমস্তগুলি প্রতিস্থাপন করা ... এটি দ্রুত বা ধীর গতিতে চলছে কিনা তা নিশ্চিত করার জন্য আপনার কোডটি বেনমার্ক করা উচিত though
সিঙ্গার অফ দ্যফাল 2'15

6
কোডটিকে আরও পঠনযোগ্য করার জন্যও ফর্ম্যাট করুন - উন্নতির সম্ভাবনাগুলি সনাক্ত করতে সহায়তা করতে পারে।
এড হিল

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

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

13
এই প্রশ্নটি এখানে
নাথানঅলিভার

উত্তর:


88

সংক্ষিপ্তসার সম্পাদনা করুন

  • আমার মূল উত্তরটি কেবলমাত্র উল্লেখ করেছে যে কোডটিতে অনেকগুলি প্রতিলিপিযুক্ত গণনা রয়েছে এবং অনেকগুলি ক্ষমতা 1/3 এর সাথে জড়িত। উদাহরণস্বরূপ, pow(x, 0.1e1/0.3e1)হিসাবে একই cbrt(x)
  • আমার দ্বিতীয় সম্পাদনাটি কেবল ভুল ছিল এবং আমার তৃতীয়টি এই অন্যায়টি নিয়ে প্রকাশিত হয়েছিল। এটিই লোকজনকে 'এম' অক্ষর দিয়ে শুরু হওয়া প্রতীকী গণিত প্রোগ্রামগুলি থেকে ওরাকলের মতো ফলাফলগুলি পরিবর্তন করতে ভয় করে। আমি সেগুলি সম্পাদনা করেছি (অর্থাত্ ধর্মঘট ) এবং এগুলি এই উত্তরটির বর্তমান সংশোধনের নীচে নিয়ে এসেছি । তবে আমি সেগুলি মুছলাম না। আমি মানুষ. আমাদের পক্ষে ভুল করা সহজ।
  • আমার চতুর্থ সম্পাদন করা একটি খুব কম্প্যাক্ট অভিব্যক্তি যে সঠিকভাবে প্রশ্নে সংবর্ত অভিব্যক্তি প্রতিনিধিত্ব করে উন্নত যদি পরামিতি l1, l2এবং l3ইতিবাচক বাস্তব সংখ্যা এবং যদি aএকটি নন-জিরো বাস্তব সংখ্যা। (এই গুণাগুণগুলির নির্দিষ্ট প্রকৃতি সম্পর্কে আমরা এখনও ওপি থেকে শুনতে পাইনি the সমস্যার প্রকৃতি প্রদত্ত, এগুলি যুক্তিসঙ্গত অনুমান)
  • এই সম্পাদনাগুলি কীভাবে এই অভিব্যক্তিগুলি সরল করতে পারে তার জেনেরিক সমস্যার উত্তর দেওয়ার চেষ্টা করে।

আগেরটা আগে

আমি ভুল এড়াতে সি ++ কোড উত্পন্ন করতে ম্যাপেল ব্যবহার করি।

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

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


প্রতীকী গণিত প্রোগ্রামগুলি থেকে কীভাবে এই বড় মেসগুলি সরল করা যায় (এই সম্পাদনা)

প্রতীকী গণিত প্রোগ্রামগুলি সাধারণত বিভিন্ন পরামিতি সম্পর্কে তথ্য সরবরাহ করার ক্ষমতা সরবরাহ করে। সেই ক্ষমতাটি ব্যবহার করুন, বিশেষত যদি আপনার সমস্যায় বিভাজন বা ক্ষয়ক্ষতি জড়িত। হাতে উদাহরণে, আপনি Maple এটা কহন যে যে অভিব্যক্তি প্রক্রিয়া সহজ করেছে থাকতে পারে l1, l2এবং l3হয় ইতিবাচক বাস্তব সংখ্যা এবং যে aএকটি নন-জিরো বাস্তব সংখ্যা। যদি ঘটনাটি হয় তবে তা বলুন। এই প্রতীকী গণিত প্রোগ্রামগুলি সাধারণত হাতের পরিমাণগুলি জটিল বলে ধরে নেয়। ডোমেইন সীমাবদ্ধ যেমন একটি প্রোগ্রাম করতে অনুমানের দেয় এক্সএক্স = (AB) এক্স । এটি কেবলমাত্র যদি aএবং bইতিবাচক বাস্তব সংখ্যা এবং যদি xবাস্তব হয়। জটিল সংখ্যায় এটি বৈধ নয়।

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

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


নির্দিষ্ট প্রশ্ন সম্পর্কে

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

এরপরে, আপনি বারবার গণনা করে প্রচুর সিপিইউ নষ্ট করছেন। আপনি সক্ষম না করা থাকলে -ffast-math, যা সংকলকটি আইইইই ভাসমান পয়েন্টের কিছু বিধি ভাঙতে দেয়, সংকলকটি আপনার পক্ষে এই অভিব্যক্তিটি সহজতর করবে না (বাস্তবে, অবশ্যই তা নয়)। এটি পরিবর্তে আপনি যা করতে বলেছিলেন ঠিক তা করবে। সর্বনিম্ন, আপনার এই জগাখিচির গণনা করার l1 * l2 * l3আগে হিসাব করা উচিত ।

অবশেষে, আপনি অনেক কল করছেন pow, যা অত্যন্ত ধীর। নোট করুন যে এই কলগুলির মধ্যে বেশ কয়েকটি ফর্মের (l1 * l2 * l3) (1/3) । এই কলগুলির মধ্যে অনেকগুলি powএকক কল দিয়ে সম্পাদিত হতে পারে std::cbrt:

l123 = l1 * l2 * l3;
l123_pow_1_3 = std::cbrt(l123);
l123_pow_4_3 = l123 * l123_pow_1_3;

এর সাথে,

  • X * pow(l1 * l2 * l3, 0.1e1 / 0.3e1)হয়ে X * l123_pow_1_3
  • X * pow(l1 * l2 * l3, -0.1e1 / 0.3e1)হয়ে X / l123_pow_1_3
  • X * pow(l1 * l2 * l3, 0.4e1 / 0.3e1)হয়ে X * l123_pow_4_3
  • X * pow(l1 * l2 * l3, -0.4e1 / 0.3e1)হয়ে X / l123_pow_4_3


ম্যাপেল স্পষ্টতই মিস করেছে।
উদাহরণস্বরূপ, লেখার অনেক সহজ উপায় রয়েছে

(pow(l1 * l2 * l3, -0.1e1 / 0.3e1) - l1 * l2 * l3 * pow(l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1)

ধরে নিই যে l1, l2এবং l3জটিল সংখ্যার চেয়ে বাস্তব এবং সত্যিকারের কিউব মূলটি (মূল নীতিটি জটিল মূলের চেয়ে) উত্তোলন করতে হবে, উপরেরটি হ্রাস পেয়েছে

2.0/(3.0 * pow(l1 * l2 * l3, 1.0/3.0))

বা

2.0/(3.0 * l123_pow_1_3)

cbrt_l123পরিবর্তে ব্যবহার করে l123_pow_1_3, প্রশ্নে দুষ্টু প্রকাশটি হ্রাস পায়

l123 = l1 * l2 * l3; 
cbrt_l123 = cbrt(l123);
T = 
  mu/(3.0*l123)*(  pow(l1/cbrt_l123,a)*(2.0*N1-N2-N3)
                 + pow(l2/cbrt_l123,a)*(2.0*N2-N3-N1)
                 + pow(l3/cbrt_l123,a)*(2.0*N3-N1-N2))
 +K*(l123-1.0)*(N1+N2+N3);

সর্বদা ডাবল চেক করুন, তবে পাশাপাশি সর্বদা সহজ করুন।


উপরের দিকে পৌঁছাতে আমার কয়েকটি পদক্ষেপ এখানে দেওয়া হল:

// Step 0: Trim all whitespace.
T=(mu*(pow(l1*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a*(pow(l1*l2*l3,-0.1e1/0.3e1)-l1*l2*l3*pow(l1*l2*l3,-0.4e1/0.3e1)/0.3e1)*pow(l1*l2*l3,0.1e1/0.3e1)/l1-pow(l2*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l1/0.3e1-pow(l3*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l1/0.3e1)/a+K*(l1*l2*l3-0.1e1)*l2*l3)*N1/l2/l3+(mu*(-pow(l1*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l2/0.3e1+pow(l2*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a*(pow(l1*l2*l3,-0.1e1/0.3e1)-l1*l2*l3*pow(l1*l2*l3,-0.4e1/0.3e1)/0.3e1)*pow(l1*l2*l3,0.1e1/0.3e1)/l2-pow(l3*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l2/0.3e1)/a+K*(l1*l2*l3-0.1e1)*l1*l3)*N2/l1/l3+(mu*(-pow(l1*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l3/0.3e1-pow(l2*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l3/0.3e1+pow(l3*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a*(pow(l1*l2*l3,-0.1e1/0.3e1)-l1*l2*l3*pow(l1*l2*l3,-0.4e1/0.3e1)/0.3e1)*pow(l1*l2*l3,0.1e1/0.3e1)/l3)/a+K*(l1*l2*l3-0.1e1)*l1*l2)*N3/l1/l2;

// Step 1:
//   l1*l2*l3 -> l123
//   0.1e1 -> 1.0
//   0.4e1 -> 4.0
//   0.3e1 -> 3
l123 = l1 * l2 * l3;
T=(mu*(pow(l1*pow(l123,-1.0/3),a)*a*(pow(l123,-1.0/3)-l123*pow(l123,-4.0/3)/3)*pow(l123,1.0/3)/l1-pow(l2*pow(l123,-1.0/3),a)*a/l1/3-pow(l3*pow(l123,-1.0/3),a)*a/l1/3)/a+K*(l123-1.0)*l2*l3)*N1/l2/l3+(mu*(-pow(l1*pow(l123,-1.0/3),a)*a/l2/3+pow(l2*pow(l123,-1.0/3),a)*a*(pow(l123,-1.0/3)-l123*pow(l123,-4.0/3)/3)*pow(l123,1.0/3)/l2-pow(l3*pow(l123,-1.0/3),a)*a/l2/3)/a+K*(l123-1.0)*l1*l3)*N2/l1/l3+(mu*(-pow(l1*pow(l123,-1.0/3),a)*a/l3/3-pow(l2*pow(l123,-1.0/3),a)*a/l3/3+pow(l3*pow(l123,-1.0/3),a)*a*(pow(l123,-1.0/3)-l123*pow(l123,-4.0/3)/3)*pow(l123,1.0/3)/l3)/a+K*(l123-1.0)*l1*l2)*N3/l1/l2;

// Step 2:
//   pow(l123,1.0/3) -> cbrt_l123
//   l123*pow(l123,-4.0/3) -> pow(l123,-1.0/3)
//   (pow(l123,-1.0/3)-pow(l123,-1.0/3)/3) -> 2.0/(3.0*cbrt_l123)
//   *pow(l123,-1.0/3) -> /cbrt_l123
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T=(mu*(pow(l1/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l1-pow(l2/cbrt_l123,a)*a/l1/3-pow(l3/cbrt_l123,a)*a/l1/3)/a+K*(l123-1.0)*l2*l3)*N1/l2/l3+(mu*(-pow(l1/cbrt_l123,a)*a/l2/3+pow(l2/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l2-pow(l3/cbrt_l123,a)*a/l2/3)/a+K*(l123-1.0)*l1*l3)*N2/l1/l3+(mu*(-pow(l1/cbrt_l123,a)*a/l3/3-pow(l2/cbrt_l123,a)*a/l3/3+pow(l3/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l3)/a+K*(l123-1.0)*l1*l2)*N3/l1/l2;

// Step 3:
//   Whitespace is nice.
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
  (mu*( pow(l1/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l1
       -pow(l2/cbrt_l123,a)*a/l1/3
       -pow(l3/cbrt_l123,a)*a/l1/3)/a
   +K*(l123-1.0)*l2*l3)*N1/l2/l3
 +(mu*(-pow(l1/cbrt_l123,a)*a/l2/3
       +pow(l2/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l2
       -pow(l3/cbrt_l123,a)*a/l2/3)/a
   +K*(l123-1.0)*l1*l3)*N2/l1/l3
 +(mu*(-pow(l1/cbrt_l123,a)*a/l3/3
       -pow(l2/cbrt_l123,a)*a/l3/3
       +pow(l3/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l3)/a
   +K*(l123-1.0)*l1*l2)*N3/l1/l2;

// Step 4:
//   Eliminate the 'a' in (term1*a + term2*a + term3*a)/a
//   Expand (mu_term + K_term)*something to mu_term*something + K_term*something
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
  (mu*( pow(l1/cbrt_l123,a)*2.0/(3.0*cbrt_l123)*cbrt_l123/l1
       -pow(l2/cbrt_l123,a)/l1/3
       -pow(l3/cbrt_l123,a)/l1/3))*N1/l2/l3
 +K*(l123-1.0)*l2*l3*N1/l2/l3
 +(mu*(-pow(l1/cbrt_l123,a)/l2/3
       +pow(l2/cbrt_l123,a)*2.0/(3.0*cbrt_l123)*cbrt_l123/l2
       -pow(l3/cbrt_l123,a)/l2/3))*N2/l1/l3
 +K*(l123-1.0)*l1*l3*N2/l1/l3
 +(mu*(-pow(l1/cbrt_l123,a)/l3/3
       -pow(l2/cbrt_l123,a)/l3/3
       +pow(l3/cbrt_l123,a)*2.0/(3.0*cbrt_l123)*cbrt_l123/l3))*N3/l1/l2
 +K*(l123-1.0)*l1*l2*N3/l1/l2;

// Step 5:
//   Rearrange
//   Reduce l2*l3*N1/l2/l3 to N1 (and similar)
//   Reduce 2.0/(3.0*cbrt_l123)*cbrt_l123/l1 to 2.0/3.0/l1 (and similar)
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
  (mu*( pow(l1/cbrt_l123,a)*2.0/3.0/l1
       -pow(l2/cbrt_l123,a)/l1/3
       -pow(l3/cbrt_l123,a)/l1/3))*N1/l2/l3
 +(mu*(-pow(l1/cbrt_l123,a)/l2/3
       +pow(l2/cbrt_l123,a)*2.0/3.0/l2
       -pow(l3/cbrt_l123,a)/l2/3))*N2/l1/l3
 +(mu*(-pow(l1/cbrt_l123,a)/l3/3
       -pow(l2/cbrt_l123,a)/l3/3
       +pow(l3/cbrt_l123,a)*2.0/3.0/l3))*N3/l1/l2
 +K*(l123-1.0)*N1
 +K*(l123-1.0)*N2
 +K*(l123-1.0)*N3;

// Step 6:
//   Factor out mu and K*(l123-1.0)
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
  mu*(  ( pow(l1/cbrt_l123,a)*2.0/3.0/l1
         -pow(l2/cbrt_l123,a)/l1/3
         -pow(l3/cbrt_l123,a)/l1/3)*N1/l2/l3
      + (-pow(l1/cbrt_l123,a)/l2/3
         +pow(l2/cbrt_l123,a)*2.0/3.0/l2
         -pow(l3/cbrt_l123,a)/l2/3)*N2/l1/l3
      + (-pow(l1/cbrt_l123,a)/l3/3
         -pow(l2/cbrt_l123,a)/l3/3
         +pow(l3/cbrt_l123,a)*2.0/3.0/l3)*N3/l1/l2)
 +K*(l123-1.0)*(N1+N2+N3);

// Step 7:
//   Expand
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
  mu*( pow(l1/cbrt_l123,a)*2.0/3.0/l1*N1/l2/l3
      -pow(l2/cbrt_l123,a)/l1/3*N1/l2/l3
      -pow(l3/cbrt_l123,a)/l1/3*N1/l2/l3
      -pow(l1/cbrt_l123,a)/l2/3*N2/l1/l3
      +pow(l2/cbrt_l123,a)*2.0/3.0/l2*N2/l1/l3
      -pow(l3/cbrt_l123,a)/l2/3*N2/l1/l3
      -pow(l1/cbrt_l123,a)/l3/3*N3/l1/l2
      -pow(l2/cbrt_l123,a)/l3/3*N3/l1/l2
      +pow(l3/cbrt_l123,a)*2.0/3.0/l3*N3/l1/l2)
 +K*(l123-1.0)*(N1+N2+N3);

// Step 8:
//   Simplify.
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
  mu/(3.0*l123)*(  pow(l1/cbrt_l123,a)*(2.0*N1-N2-N3)
                 + pow(l2/cbrt_l123,a)*(2.0*N2-N3-N1)
                 + pow(l3/cbrt_l123,a)*(2.0*N3-N1-N2))
 +K*(l123-1.0)*(N1+N2+N3);


ভুল উত্তর, ইচ্ছাকৃতভাবে নম্রতার জন্য রাখা

নোট করুন যে এটি জড়িত। এটা ভুল.

হালনাগাদ

ম্যাপেল স্পষ্টতই মিস করেছে। উদাহরণস্বরূপ, লেখার অনেক সহজ উপায় আছে

(পাও (l1 * l2 * l3, -0.1e1 / 0.3e1) - l1 * l2 * l3 * পাও (l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1)

ধরে নিই যে l1, l2এবং l3জটিল সংখ্যার চেয়ে বাস্তব এবং সত্যিকারের কিউব মূলটি (মূল নীতিটি জটিল মূলের চেয়ে) উত্তোলন করতে হবে, উপরেরটি শূন্যে হ্রাস পাবে। শূন্যের এই গণনাটি বহুবার পুনরাবৃত্তি হয়।

দ্বিতীয় আপডেট

আমি যদি গণিতটি সঠিকভাবে করে ফেলেছি ( কোনও অঙ্কের গ্যারান্টি নেই যে আমি গণিতটি সঠিকভাবে করেছি) তবে প্রশ্নের মধ্যে কদর্য ভাব কমিয়ে দেয়

l123 = l1 * l2 * l3; 
cbrt_l123_inv = 1.0 / cbrt(l123);
nasty_expression =
    K * (l123 - 1.0) * (N1 + N2 + N3) 
    - (  pow(l1 * cbrt_l123_inv, a) * (N2 + N3) 
       + pow(l2 * cbrt_l123_inv, a) * (N1 + N3) 
       + pow(l3 * cbrt_l123_inv, a) * (N1 + N2)) * mu / (3.0*l123);

উপরেরটি ধরে নেয় যে l1, l2এবং l3ইতিবাচক বাস্তব সংখ্যা।


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

4
@ উত্সাহক - ভাসমান পয়েন্ট সহ নয়। কেউ যদি অনিরাপদ গণিতের অপ্টিমাইজেশানগুলি সক্ষম না করে (উদাহরণস্বরূপ, -ffast-mathজিসিসি বা ঝাঁকুনির সাহায্যে নির্দিষ্ট করে ), সংকলকটি pow(x,-1.0/3.0)সমান হওয়ার উপর নির্ভর করতে পারে না x*pow(x,-4.0/3.0)। প্রথমটি ডুবে থাকতে পারে যখন প্রথমটি নাও পারে। ভাসমান পয়েন্ট স্ট্যান্ডার্ডের সাথে সঙ্গতিপূর্ণ হতে, সংকলক অবশ্যই সেই গণনাটি শূন্যের সাথে অপ্টিমাইজ করতে পারবেন না।
ডেভিড হামেন

ঠিক আছে, এগুলি আমার অর্থের চেয়ে অনেক বেশি উচ্চাকাঙ্ক্ষী।
উত্সাহক

4
@ প্রতিলিপি: যেমন আমি অন্য উত্তরে মন্তব্য করেছি : আপনার -fno-math-errnoসিএসই অভিন্ন powকলের জন্য জি ++ প্রয়োজন । (যদি না হতে পারে যে এটি প্রমাণ করতে পারে যে পাও এর ত্রুটি স্থাপন করার দরকার নেই?)
পিটার কর্ডস

4
@ লেফটি - ওয়ালটারের উত্তরে আপনি অনেকটা নিন। এটি একটি ভাল চুক্তি দ্রুত। এই সমস্ত উত্তরগুলির সাথে একটি সম্ভাব্য সমস্যা রয়েছে যা সংখ্যার বাতিল। আপনার N1, N2এবং N3অ-নেতিবাচক হিসাবে ধরে নেওয়া, এর মধ্যে একটি 2*N_i-(N_j+N_k)নেতিবাচক হবে, একটি ইতিবাচক হবে, এবং অন্যটি কোথাও কোথাও থাকবে। এটি সহজেই সংখ্যার বাতিলকরণের সমস্যা তৈরি করতে পারে।
ডেভিড হামেন

32

প্রথম জিনিসটি লক্ষণীয় যে powএটি সত্যিই ব্যয়বহুল, সুতরাং আপনার এটিকে যথাসম্ভব মুক্তি দেওয়া উচিত। প্রকাশের মাধ্যমে স্ক্যান করা হচ্ছে আমি অনেক পুনরাবৃত্তির দেখতে pow(l1 * l2 * l3, -0.1e1 / 0.3e1)এবং pow(l1 * l2 * l3, -0.4e1 / 0.3e1)। সুতরাং আমি এগুলি প্রাক-গণনা থেকে একটি বড় লাভ আশা করব:

 const double c1 = pow(l1 * l2 * l3, -0.1e1 / 0.3e1);
const double c2 = boost::math::pow<4>(c1);

যেখানে আমি বুস্ট পাও ফাংশনটি ব্যবহার করছি ।

উপরন্তু, আপনি কি আরো বেশি পেতে powএক্সপোনেন্ট সঙ্গে a। যদি সংখ্যক aএবং সংকলক সময়ে পরিচিত হয়, আপনি boost::math::pow<a>(...)আরও কার্য সম্পাদন করতে তাদের সাথে প্রতিস্থাপন করতে পারেন । আমিও এর a / l1 / 0.3e1সাথে পদগুলি প্রতিস্থাপন করার পরামর্শ দেব a / (l1 * 0.3e1)কারণ গুণগুলি তত্ক্ষণাত্বক ভাগ করা তত দ্রুত হয়।

অবশেষে, আপনি জি ++ ব্যবহার করলে আপনি -ffast-mathপতাকাটি ব্যবহার করতে পারেন যা সমীকরণকে রূপান্তরকরণে অপ্টিমাইজারকে আরও আগ্রাসী হতে দেয়। এই পতাকাটি আসলে কী করে সে সম্পর্কে পড়ুন , যদিও এর পার্শ্ব প্রতিক্রিয়া রয়েছে।


4
আমাদের কোডে, -ffast-mathঅস্থির হতে বা ফ্ল্যাটকে ভুল উত্তর দেওয়ার জন্য কোডটি ব্যবহার করে । আমাদের ইন্টেল সংকলকগুলির সাথে একই রকম সমস্যা রয়েছে এবং -fp-model preciseবিকল্পটি ব্যবহার করতে হবে , অন্যথায় কোড হয় ফুরিয়েছে বা ভুল উত্তর দেয়। সুতরাং -ffast-mathএটির গতি বাড়িয়ে দিতে পারে, তবে আমি আপনার লিঙ্কযুক্ত প্রশ্নের তালিকাভুক্ত পার্শ্ব-প্রতিক্রিয়াগুলি ছাড়াও সেই বিকল্পটি দিয়ে খুব সতর্কতার সাথে এগিয়ে যাওয়ার পরামর্শ দেব।
tpg2114

4
@ tpg2114: আমার টেস্টিং অনুসারে,-fno-math-errnopow লুপ থেকে বেরিয়ে যাওয়ার জন্য আপনার কেবল জি ++ অভিন্ন কলগুলি উত্তোলন করতে সক্ষম হতে হবে । এটি বেশিরভাগ কোডের জন্য -স্টাস্ট-ম্যাথের ন্যূনতম "বিপজ্জনক" অংশ।
পিটার কর্ডেস

4
@ পিটারকর্ডস এগুলি আকর্ষণীয় ফলাফল! আমরা pow খুব ধীর হয়ে dlsymযাওয়ার সাথে মতামত পেয়েছি এবং মন্তব্যগুলিতে উল্লিখিত হ্যাকটি ব্যবহার করে উল্লেখযোগ্য পারফরম্যান্স বৃদ্ধি পেতে যখন আমরা আসলে কিছুটা কম নির্ভুলতার সাথে করতে পারি তখন তা ব্যবহার করতে পেরেছি।
tpg2114

জিসিসি বুঝতে পারবে না যে পাও একটি খাঁটি ফাংশন? এটি সম্ভবত অন্তর্নির্মিত জ্ঞান।
usr

6
@ অ্যাসার: আমার মনে হয়, এটাই মূল কথা। powহয় না , কারণ এটা সেট অনুমিত হয় একটি বিশুদ্ধ ফাংশন, মান অনুযায়ী, errnoকিছু পরিস্থিতিতে। ফ্ল্যাগ সেট করা যেমন -fno-math-errnoএটি সেট না করার কারণ errno(এইভাবে মান লঙ্ঘন করে) তবে এটি একটি খাঁটি ফাংশন এবং এরূপে অনুকূলিত করা যায়।
নাট এল্ডারেজ

20

ওহ, কী প্রকাশ! ম্যাপেলের সাহায্যে এক্সপ্রেশন তৈরি করা এখানে একটি সাবপটিমাল পছন্দ ছিল। ফলাফলটি কেবল অপঠনযোগ্য।

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

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


8
"সংকলকটি এটি করা উচিত, তবে কখনও কখনও এটি হয় না", এখানে মূল কী। পাঠযোগ্যতার পাশাপাশি, অবশ্যই।
জাভিয়ার 13

4
যদি সংকলকটি কিছু করার প্রয়োজন না হয় তবে ধরে নিই যে এটি প্রায় সর্বদা ভুল।
edmz

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

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

4
@DavidHammen: ওয়েল, সেই ক্ষেত্রে, এক অক্ষর বেশী হয় "ভাষী নাম"। যেমন, যখন একটি 2-মাত্রিক কার্টিজিয়ান মধ্যে জ্যামিতি করছেন তুল্য সিস্টেম, xএবং yহয় না অর্থহীন একক অক্ষর ভেরিয়েবল, তারা সুস্থ লোকের কথায় একটি সুনির্দিষ্ট সংজ্ঞা এবং একটি ভাল এবং ব্যাপকভাবে বোঝা অর্থ দিয়ে।
জার্গ ডব্লু মিট্টাগ

17

ডেভিড হ্যামেনের উত্তরটি ভাল তবে এখনও সর্বোত্তম থেকে অনেক দূরে। আসুন তার শেষ প্রকাশটি চালিয়ে যাবো (এটি লেখার সময়)

auto l123 = l1 * l2 * l3;
auto cbrt_l123 = cbrt(l123);
T = mu/(3.0*l123)*(  pow(l1/cbrt_l123,a)*(2.0*N1-N2-N3)
                   + pow(l2/cbrt_l123,a)*(2.0*N2-N3-N1)
                   + pow(l3/cbrt_l123,a)*(2.0*N3-N1-N2))
  + K*(l123-1.0)*(N1+N2+N3);

যা আরও অনুকূলিত করা যায়। বিশেষত, যদি কিছু গাণিতিক পরিচয় ব্যবহার cbrt()করে pow()তবে আমরা কল এবং কলগুলির মধ্যে একটি এড়াতে পারি । এটি আবার ধাপে ধাপে করা যাক।

// step 1 eliminate cbrt() by taking the exponent into pow()
auto l123 = l1 * l2 * l3;
auto athird = 0.33333333333333333 * a; // avoid division
T = mu/(3.0*l123)*(  (N1+N1-N2-N3)*pow(l1*l1/(l2*l3),athird)
                   + (N2+N2-N3-N1)*pow(l2*l2/(l1*l3),athird)
                   + (N3+N3-N1-N2)*pow(l3*l3/(l1*l2),athird))
  + K*(l123-1.0)*(N1+N2+N3);

লক্ষ্য করুন আমি অপ্টিমাইজ আছে 2.0*N1করতে N1+N1ইত্যাদি পরে, আমরা একমাত্র দুটি কল করতে পারেন pow()

// step 2  eliminate one call to pow
auto l123 = l1 * l2 * l3;
auto athird = 0.33333333333333333 * a;
auto pow_l1l2_athird = pow(l1/l2,athird);
auto pow_l1l3_athird = pow(l1/l3,athird);
auto pow_l2l3_athird = pow_l1l3_athird/pow_l1l2_athird;
T = mu/(3.0*l123)*(  (N1+N1-N2-N3)* pow_l1l2_athird*pow_l1l3_athird
                   + (N2+N2-N3-N1)* pow_l2l3_athird/pow_l1l2_athird
                   + (N3+N3-N1-N2)/(pow_l1l3_athird*pow_l2l3_athird))
  + K*(l123-1.0)*(N1+N2+N3);

যেহেতু কলগুলি pow()এখানে সবচেয়ে ব্যয়বহুল ক্রিয়াকলাপ, তাই এগুলি যথাসম্ভব হ্রাস করা উচিত (পরবর্তী ব্যয়বহুল অপারেশনটি ছিল কল cbrt(), যা আমরা সরিয়ে দিয়েছিলাম)।

যদি কোনও সুযোগে aপূর্ণসংখ্যা হয়, কলগুলি powকল cbrt(আরও পূর্ণসংখ্যার শক্তি) এর কলগুলিতে অনুকূলিত হতে পারে বা যদি athirdঅর্ধ-পূর্ণসংখ্যা হয় তবে আমরা ব্যবহার করতে পারি sqrt(আরও পূর্ণসংখ্যার শক্তি)। উপরন্তু, যদি থাকে সুযোগ দ্বারা l1==l2বা l1==l3বা l2==l3এক বা উভয় কল powকাটানো যেতে পারে। সুতরাং, যদি এ জাতীয় সম্ভাবনা বাস্তবে বিদ্যমান থাকে তবে এগুলি বিশেষ বিষয় হিসাবে বিবেচনা করা উচিত।


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

4
আমি কেবল সম্পাদনা করেছি কারণ আমি আপনাকে এটি স্পষ্টভাবে উল্লেখ করতে দেখেছি; আমি ডেভিডের উত্তরটি পুনরায় পড়লাম এবং সেখানে আপনার উত্তরের রেফারেন্সটি খুঁজে পেলাম না। আমি সম্পাদনাগুলি এড়াতে চেষ্টা করি যেখানে এটি 100% পরিষ্কার নয় যে স্টাফ আমি যুক্ত করি লেখকের উদ্দেশ্যগুলির সাথে মেলে
gnat

4
@ ওয়াল্টার - আমার উত্তর এখন আপনার সাথে লিঙ্ক।
ডেভিড হামেন

4
এটা অবশ্যই আমি ছিল না। আমি কিছু দিন আগে আপনার উত্তর upvated। আমি আমার উত্তরে একটি এলোমেলো ফ্লাইবাই ডাউনভোটও পেয়েছি। স্টাফ কখনও কখনও কখনও ঘটে।
ডেভিড হামেন

4
আপনি এবং আমি প্রত্যেকে একটি পল্ট্রি ডাউনভোট পেয়েছি। প্রশ্নে সমস্ত ডাউনভোটকে দেখুন! এখন পর্যন্ত, প্রশ্নটি 16 টি ডাউনওয়োটস পেয়েছে। এটি 80 টি upvotesও পেয়েছে যা এই সমস্ত ডাউনভোটারদের চেয়ে অফসেটের চেয়ে বেশি।
ডেভিড হামেন

12
  1. "অনেক অনেক" কত?
  2. এতে কতক্ষণ সময় লাগবে?
  3. কি সব পরামিতি এই সূত্রের: গণনার মধ্যে অদলবদল? অথবা আপনি কিছু প্রাক-গণনা করা মানগুলি ক্যাশে করতে পারেন?
  4. আমি সেই সূত্রটির একটি ম্যানুয়াল সরলকরণ চেষ্টা করেছি, জানতে চাইলে এটি কিছু সংরক্ষণ করে কিনা?

    C1 = -0.1e1 / 0.3e1;
    C2 =  0.1e1 / 0.3e1;
    C3 = -0.4e1 / 0.3e1;
    
    X0 = l1 * l2 * l3;
    X1 = pow(X0, C1);
    X2 = pow(X0, C2);
    X3 = pow(X0, C3);
    X4 = pow(l1 * X1, a);
    X5 = pow(l2 * X1, a);
    X6 = pow(l3 * X1, a);
    X7 = a / 0.3e1;
    X8 = X3 / 0.3e1;
    X9 = mu / a;
    XA = X0 - 0.1e1;
    XB = K * XA;
    XC = X1 - X0 * X8;
    XD = a * XC * X2;
    
    XE = X4 * X7;
    XF = X5 * X7;
    XG = X6 * X7;
    
    T = (X9 * ( X4 * XD - XF - XG) / l1 + XB * l2 * l3) * N1 / l2 / l3 
      + (X9 * (-XE + X5 * XD - XG) / l2 + XB * l1 * l3) * N2 / l1 / l3 
      + (X9 * (-XE - XF + X6 * XD) / l3 + XB * l1 * l2) * N3 / l1 / l2;
    

[যুক্ত] আমি শেষ তিন-লাইনের সূত্রটিতে আরও কিছু কাজ করেছি এবং এটিকে এই সৌন্দর্যে নামিয়েছি:

T = X9 / X0 * (
      (X4 * XD - XF - XG) * N1 + 
      (X5 * XD - XE - XG) * N2 + 
      (X5 * XD - XE - XF) * N3)
  + XB * (N1 + N2 + N3)

আমাকে আমার কাজটি ধাপে ধাপে দেখিয়ে দিন:

T = (X9 * (X4 * XD - XF - XG) / l1 + XB * l2 * l3) * N1 / l2 / l3 
  + (X9 * (X5 * XD - XE - XG) / l2 + XB * l1 * l3) * N2 / l1 / l3 
  + (X9 * (X5 * XD - XE - XF) / l3 + XB * l1 * l2) * N3 / l1 / l2;


T = (X9 * (X4 * XD - XF - XG) / l1 + XB * l2 * l3) * N1 / (l2 * l3) 
  + (X9 * (X5 * XD - XE - XG) / l2 + XB * l1 * l3) * N2 / (l1 * l3) 
  + (X9 * (X5 * XD - XE - XF) / l3 + XB * l1 * l2) * N3 / (l1 * l2);

T = (X9 * (X4 * XD - XF - XG) + XB * l1 * l2 * l3) * N1 / (l1 * l2 * l3) 
  + (X9 * (X5 * XD - XE - XG) + XB * l1 * l2 * l3) * N2 / (l1 * l2 * l3) 
  + (X9 * (X5 * XD - XE - XF) + XB * l1 * l2 * l3) * N3 / (l1 * l2 * l3);

T = (X9 * (X4 * XD - XF - XG) + XB * X0) * N1 / X0 
  + (X9 * (X5 * XD - XE - XG) + XB * X0) * N2 / X0 
  + (X9 * (X5 * XD - XE - XF) + XB * X0) * N3 / X0;

T = X9 * (X4 * XD - XF - XG) * N1 / X0 + XB * N1 
  + X9 * (X5 * XD - XE - XG) * N2 / X0 + XB * N2
  + X9 * (X5 * XD - XE - XF) * N3 / X0 + XB * N3;


T = X9 * (X4 * XD - XF - XG) * N1 / X0 
  + X9 * (X5 * XD - XE - XG) * N2 / X0
  + X9 * (X5 * XD - XE - XF) * N3 / X0
  + XB * (N1 + N2 + N3)

4
তা লক্ষণীয়, তাই না? :) ফরট্রান, আইআইআরসি দক্ষ সূত্র গণনার জন্য ডিজাইন করা হয়েছিল ("ফর" সূত্রের জন্য)।
ভ্লাদ ফিনস্টেইন

আমি দেখেছি বেশিরভাগ F77 কোড এর মতো দেখতে পাওয়া যায় (যেমন, BLAS & NR)। খুব খুশি
ফোর্টরান

হ্যাঁ. আপনি যদি কোনও সূত্রটি অনুবাদ করছেন তবে ফর্মুলাট্রান্সেলের চেয়ে ভাল উপায় কী?
ব্রায়ান ড্রামন্ড

4
আপনার 'অপ্টিমাইজেশন' ভুল জায়গায় আক্রমণ করে। ব্যয়বহুল বিটগুলি হল কলগুলি std::pow(), যার মধ্যে আপনার কাছে এখনও প্রয়োজনের চেয়ে 6, 3 গুণ বেশি রয়েছে। অন্য কথায়, আপনার কোডটি সম্ভবের চেয়ে 3 গুণ ধীর।
ওয়াল্টার

7

এটি একটি সামান্য বাহুল্যবর্জিত হতে পারে, কিন্তু আমি আসলে Horner ফর্ম, যা মূলত নতুন করে লেখা হয় ব্যবহার করে polynomials জন্য ভাল speedup (শক্তি ফাংশন ক্ষেপক) পেয়েছি ax^3 + bx^2 + cx + dহিসাবে d + x(c + x(b + x(a)))। এই পুনরাবৃত্তি কল অনেকটা এড়াতে হবে pow()এবং আপনি আলাদাভাবে কলিং মত নিরীহ জিনিসগুলি থেকে স্টপ pow(x,6)এবং pow(x,7)পরিবর্তে মাত্র করছেন x*pow(x,6)

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

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


বহির্মুখী কোডিংয়ের জন্য হর্ণার ফর্মটি বেশ স্ট্যান্ডার্ড এবং এটির প্রশ্নের কোনও মিল নেই।
ওয়াল্টার

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

3

দেখে মনে হচ্ছে আপনার অনেক বার বার ক্রিয়াকলাপ চলছে।

pow(l1 * l2 * l3, -0.1e1 / 0.3e1)
pow(l1 * l2 * l3, -0.4e1 / 0.3e1)

আপনি সেগুলি প্রাক-গণনা করতে পারতেন যাতে আপনি powব্যয়বহুল হতে পারে এমন ফাংশনটি বারবার কল করছেন না ।

আপনি প্রাক-কলুষিত করতে পারে

l1 * l2 * l3

আপনি যে শব্দটি বারবার ব্যবহার করেন।


6
আমি বাজি দিচ্ছি অপ্টিমাইজারটি ইতিমধ্যে আপনার জন্য এটি করছে ... যদিও এটি কমপক্ষে কোডটিকে আরও পঠনযোগ্য করে তোলে।
করলি হরভাথ

আমি এটি করেছি, তবে এটি কিছুতেই গতি পায় না। কম্পাইলার অপ্টিমাইজেশন ইতিমধ্যে এটি যত্ন নিচ্ছিল কারণ আমি এটি অনুভব করেছি।

l1 * l2 * l3 সংরক্ষণ করা গতিসম্পন্ন জিনিসগুলি বাড়িয়ে

কারণ সংকলক মাঝে মাঝে কিছু অপ্টিমাইজেশন করতে পারে না বা অন্যান্য বিকল্পগুলির সাথে এগুলিকে বিরোধের মধ্যে খুঁজে পায়।
জাভিয়ার 13

4
প্রকৃতপক্ষে, -ffast-mathসংকলকটি সক্ষম না হওয়া অবধি এই অপটিমাইজেশনগুলি করা উচিত নয় এবং @ tpg2114- এর একটি মন্তব্যে উল্লিখিত হয়েছে যে এই অপটিমাইজেশন চরম অস্থির ফলাফল তৈরি করতে পারে।
ডেভিড হামেন

0

আপনার যদি এনভিডিয়া সিইউডিএ গ্রাফিক্স কার্ড থাকে, আপনি গ্রাফিক্স কার্ডে গণনাগুলি অফলোড করার কথা বিবেচনা করতে পারেন - যা নিজেই গণনাগত জটিল গণনার জন্য আরও উপযুক্ত।

https://developer.nvidia.com/how-to-cuda-c-cpp

যদি তা না হয় তবে আপনি গণনার জন্য একাধিক থ্রেড বিবেচনা করতে পারেন।


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

4
মূল প্রশ্নে: "যেহেতু এই কোডটি বহুবার কার্যকর করা একটি পার্থক্য" " এটি "অনেক" এর চেয়েও একটি বেশি। বিকল্পটি থ্রেডযুক্ত পদ্ধতিতে গণনাগুলি পাঠাতে পারে can
ব্যবহারকারী 3791372

0

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

এটি কল্পনাযোগ্য (অফ-টপিক হওয়ার ঝুঁকিতে?) যে আপনি অজস্র এবং / বা স্কিপি দিয়ে অজগর ব্যবহার করতে সক্ষম হতে পারেন। যে পরিমাণে এটি সম্ভব ছিল, আপনার গণনাগুলি আরও পঠনযোগ্য হতে পারে।


0

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

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

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

শুভকামনা!

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