gpu.js icon indicating copy to clipboard operation
gpu.js copied to clipboard

Order-dependent transpilation of this.thread.x * scale

Open markebowles opened this issue 4 years ago • 1 comments

What is wrong?

Multiplying this.thread.x (and y) by a float scale functions differently depending on the operand order. GPU interprets the scale as an integer in the form "this.thread.x * scale", but in the form "scale * this.thread.x" the scale is interpreted as a float.

Where does it happen?

Latest version of gpu.js in gpu mode, mac os x, chrome browser.

How do we replicate the issue?

        const gpu = new GPU({ mode: "gpu" });
        const canvas1 = document.getElementById("canvas1");
        const ctx1 = canvas1.getContext("webgl2", { alpha: true, premultipliedAlpha: false });

        test1 = gpu.createKernel(
            function (scale) {
                // in this expression, scale is treated as an integer
                return (this.thread.x * scale);
            })
            .setOutput([10])
            .setCanvas(canvas1)
            .setContext(ctx1);

        test2 = gpu.createKernel(
            function (scale) {
                // in this order, scale is treated as a float.
                return (scale * this.thread.x);
            })
            .setOutput([10])
            .setCanvas(canvas1)
            .setContext(ctx1);

        result = test1(1.77);
        console.log(`test1 result: ${result}`);  // 0,1,2,3,4,5,6,7,8,9

        result = test2(1.77);
        console.log(`test2 result: ${result}`);  // 0,1.7699999809265137,3.5399999618530273, ...

How important is this (1-5)?

There's an easy work-around, but it might help to include the workaround in the documentation.

Expected behavior (i.e. solution)

Javascripters are trained (aka brainwashed) to believe that "everything is a number, there's no such thing as an int". This is why it took me a day to find this problem -- the expectation is that regardless of the ordering of the expression, any scalar input to a kernel should be interpreted as a float.

Would this behavior also manifest with other sources of ints in the kernel, e.g. when we extract a cell from a Uint8Array argument?

Is this a bug that should ultimately be fixed, or a necessary side-effect of the transpilation process?

Other Comments

GPU.js is an extraordinarily useful and clever mechanism for producing high-performance code in desktop and mobile applications! Fantastic work!

markebowles avatar Jan 22 '21 00:01 markebowles

Update: replace the argument "scale" with a constant, e.g.:

test1 = gpu.createKernel(
            function () {
                // in this expression, the constant 1.77 is treated as an integer
                return (this.thread.x * 1.77);
            })
            .setOutput([10])
            .setCanvas(canvas1)
            .setContext(ctx1);

This also produces the unexpected integer behavior.

markebowles avatar Jan 22 '21 01:01 markebowles