জন কারম্যাকের অস্বাভাবিক দ্রুত বিপরীত স্কোয়ার রুট (ভূমিকম্প তৃতীয়)


112

জন কারম্যাকের ভূমিকম্প তৃতীয় উত্স কোডে একটি বিশেষ ফাংশন (float)(1.0/sqrt(x))রয়েছে যা একটি অদ্ভুত 0x5f3759dfধ্রুবক সহ নিয়মিত থেকে 4x গতিবেগের, একটি ফ্লোটের বিপরীত স্কোয়ার রুট গণনা করে । নীচের কোডটি দেখুন। কেউ এখানে লাইন দিয়ে কী ব্যাখ্যা করতে পারে যে এখানে ঠিক কী চলছে এবং কেন এটি নিয়মিত প্রয়োগের চেয়ে এত দ্রুত কাজ করে?

float Q_rsqrt( float number )
{
  long i;
  float x2, y;
  const float threehalfs = 1.5F;

  x2 = number * 0.5F;
  y  = number;
  i  = * ( long * ) &y;
  i  = 0x5f3759df - ( i >> 1 );
  y  = * ( float * ) &i;
  y  = y * ( threehalfs - ( x2 * y * y ) );

  #ifndef Q3_VM
  #ifdef __linux__
    assert( !isnan(y) );
  #endif
  #endif
  return y;
}


10
এটি প্রায় কোটি কোটি বার লেখা হয়েছে। দেখুন: google.com/search?q=0x5f3759df
গ্রেগ হিউগিল

15
ধন্যবাদ যদিও. এটি "C # তে কীভাবে ধনাত্মক সংখ্যাটিকে নেতিবাচক করে তুলবেন?" এর চেয়ে অনেক বেশি আকর্ষণীয় প্রশ্ন ছিল?
মুসিজিনিসিস

9
কারম্যাক ছিল না। en.wikipedia.org/wiki/Fast_inverse_square_root
h4xxr

7
পবিত্র বোকা, এটি নিউটনের পদ্ধতির উপর ভিত্তি করে কেবল একটি হ্যাক, এটি কোনও অ্যালগোরিদমের কোনও পবিত্র ধাঁধা নয়, এটির জন্য আবেদন করা বন্ধ করুন: পি
এলডোগ

উত্তর:


75

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

পৌরাণিক ধ্রুবকটি কীভাবে উদ্ভূত হয়েছিল তা রহস্যের কিছু বিষয়।

গ্যারি তারোলির উদ্ধৃতি দিতে:

যা আসলে পূর্ণসংখ্যায় একটি ভাসমান পয়েন্ট গণনা করছে - এটি কীভাবে এবং কেন কাজ করে তা নির্ধারণ করতে অনেক সময় লেগেছিল এবং আমি বিশদটি আর মনে করতে পারি না।

একটি বিশেষজ্ঞ গণিতবিদ (ক্রিস লোমন্ট) মূল অ্যালগরিদম কীভাবে কাজ করেছেন তা চেষ্টা করার চেষ্টা করে তৈরি করা কিছুটা উন্নত ধ্রুবক :

float InvSqrt(float x)
{
    float xhalf = 0.5f * x;
    int i = *(int*)&x;              // get bits for floating value
    i = 0x5f375a86 - (i >> 1);      // gives initial guess y0
    x = *(float*)&i;                // convert bits back to float
    x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy
    return x;
}

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


4
"গাণিতিক বিশুদ্ধ" অর্থ কী?
তারা

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

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

2
ঠিক আছে, আপনি আসলে প্রশ্নের উত্তর দেন নি।
বিজেভকে


52

অবশ্যই এই দিনগুলিতে এটি কেবলমাত্র FPU এর স্কয়ার্ট (বিশেষত ৩ 360০ / PS3) ব্যবহারের চেয়ে ধীর গতিতে পরিণত হয়েছে, কারণ ভাসা এবং ইন্টি রেজিস্টারগুলির মধ্যে অদলবদল করা একটি লোড-হিট-স্টোরকে প্ররোচিত করে, যখন ভাসমান পয়েন্ট ইউনিট পারস্পরিক বর্গক্ষেত্র করতে পারে হার্ডওয়্যার মধ্যে রুট।

এটি কেবল দেখায় যে অন্তর্নিহিত হার্ডওয়্যার পরিবর্তনের প্রকৃতি হিসাবে কীভাবে অপ্টিমাইজেশনগুলি বিকাশ করতে হবে।


4
এটি এখনও স্ট্যান্ড :: স্কয়ার্ট () এর চেয়ে অনেক বেশি দ্রুত।
তারা

2
তোমার কি কোন উত্স আছে? আমি রানটাইমগুলি পরীক্ষা করতে চাই তবে আমার কাছে একটি এক্সবক্স 360 বিকাশ কিট নেই।
DucRP

31

গ্রেগ হিউগিল এবং IllidanS4 চমৎকার গাণিতিক ব্যাখ্যা সহ একটি লিঙ্ক দিয়েছেন। যারা বিশদে বেশি মাত্রায় যেতে চান না তাদের জন্য আমি এখানে এটি সংক্ষিপ্ত করার চেষ্টা করব।

যে কোনও গাণিতিক ক্রিয়াকলাপ, কিছু ব্যাতিক্রম, বহুপদী যোগ দ্বারা প্রতিনিধিত্ব করা যেতে পারে:

y = f(x)

একেবারে রূপান্তরিত হতে পারে :

y = a0 + a1*x + a2*(x^2) + a3*(x^3) + a4*(x^4) + ...

যেখানে a0, a1, a2, ... ধ্রুবক । সমস্যাটি হ'ল বর্গমূলের মতো অনেকগুলি ক্রিয়াকলাপের জন্য, সঠিক মূল্যের জন্য এই যোগফলটির অসীম সংখ্যা রয়েছে, এটি কোনও x ^ n এ শেষ হয় না । তবে, আমরা যদি কিছু x ^ n এ থামি এখনও কিছুটা নির্ভুলতার ফলাফল হতে পারে।

সুতরাং, যদি আমাদের থাকে:

y = 1/sqrt(x)

এই বিশেষ ক্ষেত্রে তারা গণনার গতির কারণে সম্ভবত দ্বিতীয় বহুর্ধ্ব সদস্যদের দ্বিতীয় থেকে উপরে ফেলে দেওয়ার সিদ্ধান্ত নিয়েছে:

y = a0 + a1*x + [...discarded...]

এবং টাস্কটি এখন নিচে নেমে এসেছে a0 এবং a1 গণনা করার জন্য y এর যথাযথ মান থেকে কমপক্ষে পার্থক্য রাখতে। তারা গণনা করেছেন যে সর্বাধিক উপযুক্ত মানগুলি:

a0 = 0x5f375a86
a1 = -0.5

সুতরাং আপনি যখন এটি সমীকরণ স্থাপন করেন আপনি পাবেন:

y = 0x5f375a86 - 0.5*x

আপনি কোডটিতে যে রেখাটি দেখছেন তা হ'ল:

i = 0x5f375a86 - (i >> 1);

সম্পাদনা: আসলে এখানে y = 0x5f375a86 - 0.5*xযেমন হয় না তেমনi = 0x5f375a86 - (i >> 1); পূর্ণরূপ হিসাবে স্থানটি যেহেতু কেবল দুটি দ্বারা বিভাজক হয় না বরং ঘনিষ্ঠকে দুটি দ্বারা ভাগ করে দেয় এবং কিছু অন্যান্য নিদর্শনগুলিকেও কারণ করে তোলে, তবে এটি এখনও কিছু সংখ্যক a0, a1, a2 গণনাতে নেমে আসে ...

এই মুহুর্তে তারা জানতে পেরেছেন যে এই ফলাফলের নির্ভুলতা এই উদ্দেশ্যে যথেষ্ট নয়। সুতরাং ফলাফলের যথার্থতা উন্নত করতে তারা নিউটনের পুনরাবৃত্তির কেবলমাত্র একটি পদক্ষেপ করেছে:

x = x * (1.5f - xhalf * x * x)

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


সুতরাং সংক্ষেপে, তারা যা করেছে তা হ'ল:

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


2
পয়েন্টারটি দীর্ঘায়িত করা লগ 3 (ফ্লোট) এর একটি অনুমান। এটিকে পুনরায় কাস্ট করা 2 ^ দীর্ঘের প্রায় অনুমান। এর অর্থ আপনি অনুপাতটিকে প্রায় রৈখিক করতে পারেন।
wizzwizz4

22

এই নিবন্ধ অনুযায়ী কিছুক্ষণ আগে লেখা ...

কোডটির যাদুটি আপনি এটি অনুসরণ করতে না পারলেও i = 0x5f3759df - (i >> 1) হিসাবে দাঁড়িয়ে আছেন; লাইন। সরলীকৃত, নিউটন-রাফসন একটি অনুমান যা একটি অনুমান দিয়ে শুরু হয় এবং এটি পুনরাবৃত্তির সাথে সংশোধন করে। ৩২-বিট এক্স ৮86। প্রসেসরের প্রকৃতির সুবিধা গ্রহণ করে, একটি পূর্ণসংখ্যার প্রাথমিকভাবে আপনি পূর্ণসংখ্যা কাস্ট ব্যবহার করে বিপরীত স্কোয়ারটি নিতে চান এমন ভাসমান পয়েন্ট নম্বরটির মান নির্ধারণ করা হয়। তারপরে আমি 0x5f3759df এ সেট হয়েছি, বিয়োগ নিজেই কিছুটা ডানে সরিয়েছে। ডান শিফটটি ন্যূনতম তাৎপর্যপূর্ণ বিট ফেলে দেয়, এটি মূলত অর্ধেক করে।

এটি সত্যিই ভাল পড়া। এটি এটির একটি ক্ষুদ্র অংশ মাত্র।


19

ভাসা হিসাবে ধ্রুবকটি কী ছিল তা দেখার জন্য আমি কৌতূহল ছিলাম তাই আমি এই বিট কোডটি সহজভাবে লিখেছি এবং পূর্ণসংখ্যাটি গুগল করেছিলাম pop

    long i = 0x5F3759DF;
    float* fp = (float*)&i;
    printf("(2^127)^(1/2) = %f\n", *fp);
    //Output
    //(2^127)^(1/2) = 13211836172961054720.000000

দেখে মনে হচ্ছে ধ্রুবকটি হল "2 ^ 127 এর বর্গমূলের একটি পূর্ণসংখ্যার সমান্তরালতা তার ভাসমান-পয়েন্ট উপস্থাপনের হেক্সাডেসিমাল ফর্ম দ্বারা পরিচিত, 0x5f3759df" https://mrob.com/pub/math/numbers-18.html

একই সাইটে এটি পুরো বিষয়টি ব্যাখ্যা করে। https://mrob.com/pub/math/numbers-16.html#le009_16


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