জাভাস্ক্রিপ্টে ফাস্ট ইনভার্স স্কোয়ার রুট প্রয়োগ করবেন?


11

ভূমিকম্প তৃতীয় থেকে দ্রুত বিপরীত স্কোয়ার রুটটি একটি ভাসমান-পয়েন্ট কৌশল ব্যবহার করে বলে মনে হচ্ছে। আমি যেমন বুঝতে পারি, ভাসমান-পয়েন্ট উপস্থাপনার কিছু আলাদা বাস্তবায়ন থাকতে পারে।

তাহলে জাভাস্ক্রিপ্টে ফাস্ট ইনভার্স স্কোয়ার রুট কার্যকর করা সম্ভব?

এটি কি একই ফলাফল ফেরত দেবে?

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 ) );

  return y;

}

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

4
জাভাস্ক্রিপ্ট পয়েন্টার আছে?
পাব্বি

2
আপনার পুরো প্রোগ্রামটির গতি বাড়িয়ে তোলে এমন একটি "বিশেষ" ফাংশন ব্যবহার করার লোভনীয় হলেও, সম্ভাবনাগুলি হ'ল আপনি বাগগুলি পরিচয় করিয়ে দিন বা কেবল জিনিসগুলিকে মোটেও গতি বাড়ান না (উদাহরণস্বরূপ কেভিন রেডের উত্তর নীচে দেখুন)। c2.com/cgi/wiki?PrematureOptimization
ড্যানিয়েল কার্লসন

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

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

উত্তর:


15

কৌতুকটি একটি পূর্ণসংখ্যার হিসাবে ভাসমান-পয়েন্ট সংখ্যাটির বিটগুলিকে পুনরায় ব্যাখ্যা করার উপর নির্ভর করে এবং এটি আবার একাধিক সংখ্যার ভিউ সহ একটি কাঁচা বাইট বাফার তৈরি করতে টাইপড অ্যারে সুবিধা ব্যবহার করে জাভাস্ক্রিপ্টে সম্ভব ।

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

const bytes = new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT);
const floatView = new Float32Array(bytes);
const intView = new Uint32Array(bytes);
const threehalfs = 1.5;

function Q_rsqrt(number) {
  const x2 = number * 0.5;
  floatView[0] = number;
  intView[0] = 0x5f3759df - ( intView[0] >> 1 );
  let y = floatView[0];
  y = y * ( threehalfs - ( x2 * y * y ) );

  return y;
}

আমি কোনও গ্রাফকে চোখের সামনে রেখে নিশ্চিত করেছি যে এটি যুক্তিসঙ্গত সংখ্যার ফলাফল দেয়। তবে এটি স্পষ্ট নয় যে এর থেকে পারফরম্যান্সের কিছুটা উন্নতি হবে, যেহেতু আমরা আরও উচ্চ-স্তরের জাভাস্ক্রিপ্ট ক্রিয়াকলাপ করছি। আমার হাতে থাকা ব্রাউজারগুলিতে আমি বেঞ্চমার্ক চালিয়েছি এবং এটি পেয়েছি যে (এপ্রিল 2018 পর্যন্ত ম্যাকোজে ক্রোম, ফায়ারফক্স এবং সাফারি Q_rsqrt(number)নেওয়া) 50% থেকে 80% সময় নেয় 1/sqrt(number)। এখানে আমার সম্পূর্ণ পরীক্ষার সেটআপ রয়েছে:

const {sqrt, min, max} = Math;

const bytes = new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT);
const floatView = new Float32Array(bytes);
const intView = new Uint32Array(bytes);
const threehalfs = 1.5;

function Q_rsqrt(number) {
  const x2 = number * 0.5;
  floatView[0] = number;
  intView[0] = 0x5f3759df - ( intView[0] >> 1 );
  let y = floatView[0];
  y = y * ( threehalfs - ( x2 * y * y ) );

  return y;
}

// benchmark
const junk = new Float32Array(1);
function time(f) {
  const t0 = Date.now();
  f();
  const t1 = Date.now();
  return t1 - t0;
}
const timenat = time(() => { 
  for (let i = 0; i < 5000000; i++) junk[0] = 1/sqrt(i)
});
const timeq = time(() => {
  for (let i = 0; i < 5000000; i++) junk[0] = Q_rsqrt(i);
});
document.getElementById("info").textContent =
  "Native square root: " + timenat + " ms\n" +
  "Q_rsqrt: " + timeq + " ms\n" +
  "Ratio Q/N: " + timeq/timenat;

// plot results
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
function plot(f) {
  ctx.beginPath();
  const mid = canvas.height / 2;
  for (let i = 0; i < canvas.width; i++) {
    const x_f = i / canvas.width * 10;
    const y_f = f(x_f);
    const y_px = min(canvas.height - 1, max(0, mid - y_f * mid / 5));
    ctx[i == 0 ? "moveTo" : "lineTo"](i, y_px);
  }
  ctx.stroke();
  ctx.closePath();
}
ctx.strokeStyle = "black";
plot(x => 1/sqrt(x));
ctx.strokeStyle = "yellow";
plot(x => Q_rsqrt(x));
<pre id="info"></pre>
<canvas width="300" height="300" id="canvas"
        style="border: 1px solid black;"></canvas>


In classic JavaScript, it is not possible to... reinterpreting the bits of a floating-point number as an integerসত্যি? এটি বছর আগে ছিল তাই আমি ঠিক কী অপারেশনগুলি ব্যবহার করছিলাম তা মনে করতে পারি না, তবে আমি একবার জাভাস্ক্রিপ্টে একটি ডেটা পার্সার লিখেছিলাম যা বাইটের একটি স্ট্রিংকে এন-বিটের একটি সিরিজে রূপান্তরিত করে (এন হেডারে সংজ্ঞায়িত করা হয়েছিল) পূর্ণসংখ্যা। এটি বেশ অনুরূপ।
17:34
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.