चाल एक पूर्णांक के रूप में फ़्लोटिंग-पॉइंट संख्या के बिट्स को फिर से स्थापित करने पर निर्भर करती है , जो कि टाइप किए गए एरे के सुविधा का उपयोग करके जावास्क्रिप्ट में संभव है , उस पर कई संख्यात्मक विचारों के साथ एक कच्ची बाइट बफर बनाने के लिए।
यहां आपके द्वारा दिए गए कोड का शाब्दिक रूपांतरण है; ध्यान दें कि यह बिल्कुल वैसा ही नहीं है, क्योंकि जावास्क्रिप्ट में सभी अंकगणितीय ऑपरेशन 64-बिट फ्लोटिंग पॉइंट हैं, न कि 32-बिट, इसलिए इनपुट आवश्यक रूप से परिवर्तित हो जाएगा। इसके अलावा, मूल कोड की तरह, यह प्लेटफ़ॉर्म-आश्रित है कि यह बकवास परिणाम देगा यदि प्रोसेसर आर्किटेक्चर एक अलग बाइट ऑर्डर का उपयोग करता है; यदि आप इस तरह की चीजें करते हैं, तो मैं सुझाव देता हूं कि आपके आवेदन से पहले यह निर्धारित करने के लिए एक परीक्षण मामले को निष्पादित करें कि पूर्णांक और फ़्लोट्स आपके द्वारा अपेक्षित बाइट का प्रतिनिधित्व करते हैं।
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>