อะไรมีประสิทธิภาพมากขึ้น? ใช้พาวเป็นกำลังสองหรือแค่คูณด้วยตัวเอง?


119

วิธีใดในสองวิธีนี้ใน C มีประสิทธิภาพมากกว่ากัน? และวิธีการ:

pow(x,3)

เมื่อเทียบกับ

x*x*x // etc?

9
เป็นxจุดหนึ่งหรือลอย?
Matthew Flaschen

6
คุณสามารถลองเขียนโปรแกรมที่ดำเนินการสองอย่างข้างต้นและระยะเวลาในการดำเนินการกับไลบรารีการทำโปรไฟล์ นั่นจะให้คำตอบที่ดีในแง่ของเวลาดำเนินการ
J. Polfer

3
เมื่อคุณพูดว่ามีประสิทธิภาพคุณหมายถึงเวลาหรือพื้นที่ (เช่นการใช้หน่วยความจำ) หรือไม่?
J. Polfer

4
@sheepsimulator: +1 เพื่อช่วยฉันประหยัดเวลาที่ต้อง (อีกครั้ง) ชี้ให้เห็นว่าการเขียนการทดสอบอย่างรวดเร็วจะให้คำตอบที่ชัดเจนเร็วกว่าที่คุณจะได้รับคำตอบที่คลุมเครือหรือไม่ถูกต้องจาก SO
เพียงความคิดเห็นที่ถูกต้องของฉัน

5
@kirill_igum หากค่าเหล่านี้เป็นค่าทศนิยมที่ไม่ใช่จุดบกพร่องเลขคณิตทศนิยมจะไม่เชื่อมโยง
effeffe

คำตอบ:


82

ฉันทดสอบความแตกต่างของประสิทธิภาพระหว่างx*x*...เทียบpow(x,i)กับขนาดเล็กiโดยใช้รหัสนี้:

#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

นี่คือ Intel Core Duo ที่ใช้ Ubuntu 9.10 64 บิต รวบรวมโดยใช้ gcc 4.4.1 พร้อมการเพิ่มประสิทธิภาพ -o2

ดังนั้นใน C ใช่x*x*xจะเร็วกว่าpow(x, 3)เพราะไม่มีการpow(double, int)โอเวอร์โหลด ในภาษา C ++ จะเหมือนกันโดยประมาณ (สมมติว่าวิธีการในการทดสอบของฉันถูกต้อง)


นี่เป็นการตอบสนองต่อความคิดเห็นของ An Markm:

แม้มีusing namespace stdคำสั่งออกมาถ้าพารามิเตอร์ตัวที่สองจะpowเป็นintแล้ว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;
}

1
หมายความว่าการแทรก "using namespace std" เลือกตัวเลือก C และจะเป็นอันตรายต่อรันไทม์หรือไม่
Andreas

ในลูปไทม์มิ่งของคุณทั้งสองการคำนวณพาวอาจเกิดขึ้นเพียงครั้งเดียว gcc -O2 ไม่ควรมีปัญหาในการดึงนิพจน์ที่ไม่แปรผันของลูปออกจากลูป ดังนั้นคุณเพียงแค่ทดสอบว่าคอมไพเลอร์ทำงานได้ดีเพียงใดในการเปลี่ยนลูปค่าคงที่เพิ่มเป็นทวีคูณหรือเพียงแค่เพิ่มประสิทธิภาพของลูปค่าคงที่เพิ่ม มีเหตุผลที่ลูปของคุณมีความเร็วเท่ากันโดยมีเลขชี้กำลัง = 1 เทียบกับเลขชี้กำลัง = 5 แม้กระทั่งสำหรับเวอร์ชันที่เขียนออกมา
Peter Cordes

2
ฉันลองใช้กับgodbolt (พร้อมเวลาแสดงความคิดเห็นเนื่องจาก godbolt ไม่ได้ติดตั้ง Boost) มันน่าแปลกใจที่ไม่จริงเรียกstd::pow8 * ลูปครั้ง (สำหรับตัวแทน> 2) -fno-math-errnoเว้นแต่คุณจะใช้ จากนั้นก็สามารถดึงพาวโทรออกจากลูปได้อย่างที่คิด ฉันเดาว่าเนื่องจาก errno เป็นโกลบอลความปลอดภัยของเธรดจึงต้องการให้การเรียกพาวตั้งค่า errno หลาย ๆ ครั้ง ... exp = 1 และ exp = 2 นั้นเร็วเพราะการเรียกพาวถูกยกออกจากลูปด้วยเพียง-O3.. ( มี - ffast-mathมันทำผลรวม-of-8 นอกลูปด้วย)
Peter Cordes

ฉันลงคะแนนก่อนที่ฉันจะรู้ว่าฉันมี -ffast-math อยู่ในเซสชั่น godbolt ที่ฉันใช้อยู่ แม้ว่าจะไม่มีสิ่งนั้น testpow <1> และ testpow <2> ก็พังเพราะสอดรับกับpowสายเรียกเข้าออกจากวงดังนั้นจึงมีข้อบกพร่องใหญ่ที่นั่น นอกจากนี้ดูเหมือนว่าคุณกำลังทดสอบเวลาแฝงของการเพิ่ม FP เป็นส่วนใหญ่เนื่องจากการทดสอบทั้งหมดทำงานในเวลาเดียวกัน คุณคาดว่าtest5จะช้ากว่าtest1แต่ก็ไม่ใช่ การใช้ตัวสะสมหลายตัวจะแยกห่วงโซ่การพึ่งพาและซ่อนเวลาแฝง
Peter Cordes

@PeterCordes เมื่อ 5 ปีก่อนคุณอยู่ที่ไหน :-) ฉันจะพยายามแก้ไขเกณฑ์มาตรฐานของฉันโดยใช้powกับค่าที่เปลี่ยนแปลงตลอดเวลา (เพื่อป้องกันไม่ให้นิพจน์ธารซ้ำถูกยกออก)
Emile Cormier

30

นั่นเป็นคำถามที่ผิด คำถามที่ถูกต้องคือ "ข้อใดเข้าใจง่ายกว่าสำหรับผู้อ่านโค้ดของฉันที่เป็นมนุษย์"

ถ้าเรื่องความเร็ว (ทีหลัง) อย่าถาม แต่วัด (และก่อนหน้านั้นให้วัดว่าการเพิ่มประสิทธิภาพนี้จะสร้างความแตกต่างที่เห็นได้ชัดเจนหรือไม่) ก่อนหน้านั้นให้เขียนโค้ดเพื่อให้อ่านง่ายที่สุด

แก้ไข
เพียงเพื่อให้ชัดเจนนี้ (แม้ว่ามันอยู่แล้วควรจะได้รับ): speedups ก้าวหน้ามักจะมาจากสิ่งที่ต้องการโดยใช้ขั้นตอนวิธีการที่ดีขึ้น ,ปรับปรุงท้องที่ของข้อมูล ,การลดการใช้หน่วยความจำแบบไดนามิก ,ผล pre-คอมพิวเตอร์ฯลฯพวกเขาไม่ค่อยเคยมาจาก การเรียกใช้ฟังก์ชันเดี่ยวที่เพิ่มประสิทธิภาพระดับไมโครและที่ไหนพวกเขาทำได้ในสถานที่น้อยมากซึ่งจะพบได้จากการทำโปรไฟล์อย่างระมัดระวัง (และใช้เวลานาน)บ่อยกว่าที่พวกเขาไม่สามารถเร่งความเร็วได้ด้วยการทำแบบไม่ใช้งานง่าย สิ่งต่างๆ (เช่นการแทรกnoop งบ) และอะไรคือการเพิ่มประสิทธิภาพสำหรับแพลตฟอร์มหนึ่งในบางครั้งการมองโลกในแง่ร้ายสำหรับอีกแพลตฟอร์มหนึ่ง (นั่นคือเหตุผลที่คุณต้องวัดผลแทนที่จะถามเพราะเราไม่รู้จัก / ไม่มีสภาพแวดล้อมของคุณทั้งหมด)

ผมขอขีดเส้นใต้นี้อีกครั้งแม้ในการใช้งานไม่กี่สิ่งที่สำคัญเช่นที่พวกเขาทำไม่ได้ไม่ว่าในสถานที่มากที่สุดที่พวกเขากำลังใช้และมันก็เป็นอย่างมากไม่น่าที่คุณจะได้พบกับสถานที่ที่พวกเขาเรื่องโดยดูที่รหัส จริงๆคุณไม่จำเป็นต้องระบุจุดร้อนครั้งแรกเพราะรหัสมิฉะนั้นการเพิ่มประสิทธิภาพเป็นเพียงเสียเวลา

แม้ว่าการดำเนินการเพียงครั้งเดียว (เช่นการคำนวณกำลังสองของค่าบางค่า) จะใช้เวลาในการดำเนินการของแอปพลิเคชันถึง10% (ซึ่ง IME นั้นค่อนข้างหายาก) และแม้ว่าการเพิ่มประสิทธิภาพจะช่วยประหยัดเวลาได้50%สำหรับการดำเนินการนั้น (ซึ่ง IME คือ แม้มากหายากมาก), คุณยังคงทำโปรแกรมใช้เวลาเพียง 5% เวลาน้อยลง
ผู้ใช้ของคุณจะต้องมีนาฬิกาจับเวลาเพื่อสังเกตสิ่งนั้น (ฉันเดาว่าในกรณีส่วนใหญ่การเร่งความเร็วต่ำกว่า 20% จะไม่มีใครสังเกตเห็นสำหรับผู้ใช้ส่วนใหญ่และนั่นคือสี่จุดดังกล่าวที่คุณต้องหา)


43
อาจเป็นคำถามที่ถูกต้อง บางทีเขาอาจไม่ได้คิดเกี่ยวกับโครงการที่ใช้งานได้จริงของเขาเอง แต่สนใจแค่ว่าภาษา / คอมไพเลอร์ทำงานอย่างไร ...
Andreas Rejbrand

137
Stackoverflow ควรมีปุ่มที่แทรกข้อจำกัดความรับผิดชอบมาตรฐาน: "ฉันรู้อยู่แล้วว่าการเพิ่มประสิทธิภาพก่อนเวลาอันควรเป็นสิ่งชั่วร้าย แต่ฉันถามคำถามการเพิ่มประสิทธิภาพนี้เพื่อจุดประสงค์ทางวิชาการหรือฉันได้ระบุบรรทัด / บล็อกของโค้ดนั้นแล้วเป็นคอขวด"
Emile Cormier

39
ฉันไม่คิดว่าความสามารถในการอ่านเป็นปัญหาที่นี่ การเขียน x * x เทียบกับ pow (x, 2) ดูเหมือนจะค่อนข้างชัดเจน
KillianDS

41
การใช้ตัวหนาและตัวเอียงมากเกินไปไม่ใช่เรื่องง่ายสำหรับดวงตา
stagas

24
ฉันไม่เห็นด้วยกับคำตอบนี้ เป็นคำถามที่ถูกต้องสำหรับการถามเกี่ยวกับประสิทธิภาพ ประสิทธิภาพที่ดีที่สุดที่คุณสามารถทำได้คือข้อกำหนดที่ถูกต้องในบางครั้งและมักเป็นสาเหตุที่มีคนใช้ c ++ มากกว่าภาษาอื่น และการวัดไม่ใช่ความคิดที่ดีเสมอไป ฉันอาจวัดการเรียงฟองและการเรียงคิวและค้นหาฟองอากาศได้เร็วขึ้นด้วย 10 รายการของฉันเพราะฉันไม่มีภูมิหลังที่จะรู้ว่าจำนวนรายการมีความสำคัญอย่างมากและพบในภายหลังด้วยรายการ 1,000,000 รายการของฉันมันเป็นตัวเลือกที่แย่มาก
jcoder

17

x*xหรือx*x*xจะเร็วกว่าpowเนื่องจากpowต้องจัดการกับกรณีทั่วไปในขณะที่x*xเฉพาะเจาะจง นอกจากนี้คุณสามารถยกเลิกการเรียกใช้ฟังก์ชันและเช่นนั้นได้

อย่างไรก็ตามหากคุณพบว่าตัวเองมีการเพิ่มประสิทธิภาพระดับไมโครเช่นนี้คุณจำเป็นต้องมีโปรไฟล์และทำโปรไฟล์อย่างจริงจัง ความน่าจะเป็นที่ท่วมท้นคือคุณจะไม่สังเกตเห็นความแตกต่างระหว่างทั้งสอง


7
ฉันคิดเหมือนกันจนตัดสินใจทดสอบ ฉันเพิ่งทดสอบx*x*xเทียบกับสองเท่าstd::pow(double base, int exponent)ในลูปตามกำหนดเวลาและไม่เห็นความแตกต่างของประสิทธิภาพที่มีความหมายทางสถิติ
Emile Cormier

2
ตรวจสอบให้แน่ใจว่าคอมไพเลอร์ไม่ได้รับการปรับให้เหมาะสม
Ponkadoodle

1
@Emile: ตรวจสอบรหัสที่สร้างโดยคอมไพเลอร์ เครื่องมือเพิ่มประสิทธิภาพทำสิ่งที่ยุ่งยาก (และไม่ชัดเจน) ในบางครั้ง ตรวจสอบประสิทธิภาพในระดับการเพิ่มประสิทธิภาพต่างๆเช่น -O0, -O1, -O2 และ -O3
เพียงแค่ความเห็นที่ถูกต้องของฉัน

2
คุณไม่สามารถสันนิษฐานได้ว่าฟังก์ชันทั่วไปทำงานช้าลง บางครั้งสิ่งที่ตรงกันข้ามก็เป็นจริงเพราะโค้ดที่ง่ายกว่านั้นง่ายกว่าสำหรับคอมไพเลอร์ในการปรับให้เหมาะสม
cambunctious

5

ฉันยังสงสัยเกี่ยวกับปัญหาด้านประสิทธิภาพและหวังว่าสิ่งนี้จะได้รับการปรับให้เหมาะสมโดยคอมไพเลอร์ตามคำตอบจาก @EmileCormier อย่างไรก็ตามฉันกังวลว่ารหัสทดสอบที่เขาแสดงจะยังคงอนุญาตให้คอมไพเลอร์ปรับแต่งการเรียก std :: pow () ให้เหมาะสมที่สุดเนื่องจากมีการใช้ค่าเดียวกันในการโทรทุกครั้งซึ่งจะทำให้คอมไพเลอร์สามารถเก็บผลลัพธ์และ ใช้ซ้ำในลูปซึ่งจะอธิบายถึงเวลาทำงานที่เหมือนกันเกือบทุกกรณี ผมก็เลยลองดูด้วย

นี่คือรหัสที่ฉันใช้ (test_pow.cpp):

#include <iostream>                                                                                                                                                                                                                       
#include <cmath>
#include <chrono>

class Timer {
  public:
    explicit Timer () : from (std::chrono::high_resolution_clock::now()) { }

    void start () {
      from = std::chrono::high_resolution_clock::now();
    }

    double elapsed() const {
      return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - from).count() * 1.0e-6;
    }

  private:
    std::chrono::high_resolution_clock::time_point from;
};

int main (int argc, char* argv[])
{
  double total;
  Timer timer;



  total = 0.0;
  timer.start();
  for (double i = 0.0; i < 1.0; i += 1e-8)
    total += std::pow (i,2);
  std::cout << "std::pow(i,2): " << timer.elapsed() << "s (result = " << total << ")\n";

  total = 0.0;
  timer.start();
  for (double i = 0.0; i < 1.0; i += 1e-8)
    total += i*i;
  std::cout << "i*i: " << timer.elapsed() << "s (result = " << total << ")\n";

  std::cout << "\n";

  total = 0.0;
  timer.start();
  for (double i = 0.0; i < 1.0; i += 1e-8)
    total += std::pow (i,3);
  std::cout << "std::pow(i,3): " << timer.elapsed() << "s (result = " << total << ")\n";

  total = 0.0;
  timer.start();
  for (double i = 0.0; i < 1.0; i += 1e-8)
    total += i*i*i;
  std::cout << "i*i*i: " << timer.elapsed() << "s (result = " << total << ")\n";


  return 0;
}

รวบรวมโดยใช้:

g++ -std=c++11 [-O2] test_pow.cpp -o test_pow

โดยทั่วไปความแตกต่างคืออาร์กิวเมนต์ของ std :: pow () คือตัวนับลูป อย่างที่ฉันกลัวความแตกต่างของประสิทธิภาพจะเด่นชัด หากไม่มีแฟล็ก -O2 ผลลัพธ์บนระบบของฉัน (Arch Linux 64-bit, g ++ 4.9.1, Intel i7-4930) คือ:

std::pow(i,2): 0.001105s (result = 3.33333e+07)
i*i: 0.000352s (result = 3.33333e+07)

std::pow(i,3): 0.006034s (result = 2.5e+07)
i*i*i: 0.000328s (result = 2.5e+07)

ด้วยการเพิ่มประสิทธิภาพผลลัพธ์ก็โดดเด่นไม่แพ้กัน:

std::pow(i,2): 0.000155s (result = 3.33333e+07)
i*i: 0.000106s (result = 3.33333e+07)

std::pow(i,3): 0.006066s (result = 2.5e+07)
i*i*i: 9.7e-05s (result = 2.5e+07)

ดังนั้นดูเหมือนว่าอย่างน้อยคอมไพลเลอร์จะพยายามเพิ่มประสิทธิภาพกรณี std :: pow (x, 2) แต่ไม่ใช่กรณี std :: pow (x, 3) (ใช้เวลานานกว่า std :: pow ~ 40 เท่า (x, 2) กรณี) ในทุกกรณีการขยายด้วยตนเองทำได้ดีกว่า - แต่โดยเฉพาะอย่างยิ่งสำหรับเคส power 3 (เร็วกว่า 60 เท่า) นี่เป็นสิ่งที่ควรคำนึงถึงอย่างแน่นอนหากใช้ std :: pow () ที่มีอำนาจจำนวนเต็มมากกว่า 2 ในวงที่แน่น


4

วิธีที่มีประสิทธิภาพที่สุดคือการพิจารณาการเติบโตของการคูณ ตรวจสอบรหัสนี้สำหรับ p ^ q:

template <typename T>
T expt(T p, unsigned q){
    T r =1;
    while (q != 0) {
        if (q % 2 == 1) {    // if q is odd
            r *= p;
            q--;
        }
        p *= p;
        q /= 2;
    }
    return r;
}

2

ถ้าเลขชี้กำลังมีค่าคงที่และมีขนาดเล็กให้ขยายออกโดยลดจำนวนการคูณให้เหลือน้อยที่สุด (ตัวอย่างเช่นx^4ไม่เหมาะสมที่สุดx*x*x*xแต่y*yอยู่ที่ไหนy=x*xและx^5อยู่y*y*xที่ไหนy=x*xและอื่น ๆ ) สำหรับเลขชี้กำลังจำนวนเต็มคงที่ให้เขียนแบบฟอร์มที่ปรับให้เหมาะสมแล้ว ด้วยเลขชี้กำลังขนาดเล็กนี่คือการเพิ่มประสิทธิภาพมาตรฐานที่ควรดำเนินการไม่ว่าโค้ดจะถูกจัดทำโปรไฟล์หรือไม่ก็ตาม รูปแบบที่ปรับให้เหมาะสมจะเร็วกว่าในหลาย ๆ กรณีซึ่งโดยพื้นฐานแล้วควรค่าแก่การทำ

(ถ้าคุณใช้ Visual C ++ ให้std::pow(float,int)ทำการเพิ่มประสิทธิภาพที่ฉันพูดถึงโดยลำดับของการดำเนินการเกี่ยวข้องกับรูปแบบบิตของเลขชี้กำลังฉันไม่รับประกันว่าคอมไพเลอร์จะคลายการวนซ้ำให้คุณ แต่ก็ยังคุ้มค่าที่จะทำ ด้วยมือ)

[แก้ไข] BTW powมีแนวโน้มที่น่าแปลกใจในการครอบตัดในผลลัพธ์ของโปรไฟล์ หากคุณไม่จำเป็นต้องใช้มัน (เช่นเลขชี้กำลังมีขนาดใหญ่หรือไม่คงที่) และคุณกังวลเกี่ยวกับประสิทธิภาพดังนั้นควรเขียนโค้ดที่เหมาะสมที่สุดออกมาและรอให้ผู้สร้างโปรไฟล์แจ้งให้คุณทราบ (น่าแปลกใจ ) เสียเวลาก่อนที่จะคิดต่อไป (อีกทางเลือกหนึ่งคือโทรหาpowและให้โปรไฟล์บอกคุณว่ามันเสียเวลา (ไม่แปลกใจเลย) - คุณกำลังตัดขั้นตอนนี้ออกไปโดยทำอย่างชาญฉลาด)


0

ฉันยุ่งอยู่กับปัญหาที่คล้ายกันและฉันค่อนข้างงงกับผลลัพธ์ ฉันกำลังคำนวณx⁻³ / ²สำหรับความโน้มถ่วงของนิวตันในสถานการณ์ n-body (การเร่งความเร็วเกิดขึ้นจากมวลกายอื่น M ซึ่งอยู่ที่เวกเตอร์ระยะทาง d): a = M G d*(d²)⁻³/²(โดยที่d²คือผลคูณของจุด (สเกลาร์) ของ d ด้วยตัวมันเอง) และฉันคิดว่าการคำนวณM*G*pow(d2, -1.5)จะง่ายกว่าM*G/d2/sqrt(d2)

เคล็ดลับคือมันเป็นเรื่องจริงสำหรับระบบขนาดเล็ก แต่เมื่อระบบมีขนาดใหญ่M*G/d2/sqrt(d2)ขึ้นจะมีประสิทธิภาพมากขึ้นและฉันไม่เข้าใจว่าทำไมขนาดของระบบจึงส่งผลต่อผลลัพธ์นี้เนื่องจากการดำเนินการซ้ำกับข้อมูลที่แตกต่างกันไม่ได้ เหมือนกับว่ามีการเพิ่มประสิทธิภาพที่เป็นไปได้ในขณะที่ระบบเติบโตขึ้น แต่เป็นไปไม่ได้ด้วยpow

ใส่คำอธิบายภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.