কৌতুকটি একটি পূর্ণসংখ্যার হিসাবে ভাসমান-পয়েন্ট সংখ্যাটির বিটগুলিকে পুনরায় ব্যাখ্যা করার উপর নির্ভর করে এবং এটি আবার একাধিক সংখ্যার ভিউ সহ একটি কাঁচা বাইট বাফার তৈরি করতে টাইপড অ্যারে সুবিধা ব্যবহার করে জাভাস্ক্রিপ্টে সম্ভব ।
আপনার দেওয়া কোডটির এখানে আক্ষরিক রূপান্তর; মনে রাখবেন যে এটি হুবহু এক নয়, জাভাস্ক্রিপ্টে সমস্ত পাটিগণিত ক্রিয়াকলাপ 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>