微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

GPU.js 代码获取数组的最大值

如何解决GPU.js 代码获取数组的最大值

我正在尝试使用 GPU.js 使用简单的 Jacobi 迭代运行拉普拉斯求解器计算。

我想要实现的一件事是在每次迭代后计算数组的“最大误差”。也许一个更简单的问题是在迭代后计算整个数组的最大值,希望使用 GPU。我想以此作为收敛标准来停止计算。

我不知道如何做到这一点,也不清楚如何从示例中获取“并行化”函数中的单个值。

感谢任何帮助。

这是我正在使用的代码

<html>
<head>
<title>Laplace Solver Speed Test Using GPU.js library

</title>
</head>
<body>
    
    <p><button onclick="btn_runcalculation_click(event)">Start calculation</button> </p>
    <br>Laplace Solver Speed Test Using GPU.js library
    <br> <a href = "https://gpu.rocks/#/" >https://gpu.rocks/#/</a>
    <br><br>In Opera browser
    <br> 500 x 500 with 2 electrodes at position 20 and 480. Height of 200 each.
        Left electrode at +1 V and right electrode at -1V.
        447 iterations
    <br>
    <br>Iteration = <span id="txt_iter"></span>
    <br>
    <br>Number of iterations = <span id="txt_niter"></span>
    <br>Max change = <span id="txt_maxchange"></span>
    <br> Time taken to complete / ms = <span id="txt_tiMetaken"></span>
    <br>
    <br>For some reason it only runs in server,not in client mode

    <script src="gpu-browser.min.js"></script>

    <script>
        //Initialisation,no need for init() function
        
        const arraydim=500;

        //Setup potential array
        let pot2DArray = [];
        let electrodes2DArray = [];
        let pot2DArray_buffer = [];

        //const iterationVMaxError = 1e-3;

        
        //let maxchange=0;
        let niterations = 0;
        const maxiterations = 447;

        const gpu = new GPU();

        function init(){
            niterations=0;

            pot2DArray = new Array(arraydim); //Creates a new array
            pot2DArray_buffer = new Array(arraydim);

            electrodes2DArray = new Array(arraydim);
            
            for (let iy = 0 ; iy<arraydim ; iy++){
                pot2DArray[iy] = new Array(arraydim);
                pot2DArray_buffer[iy] = new Array(arraydim);

                electrodes2DArray[iy] = new Array(arraydim);

                for (let ix = 0 ; ix < arraydim ; ix++){

                    pot2DArray[iy][ix] = 0;
                    pot2DArray_buffer[iy][ix] = 0;

                    electrodes2DArray[iy][ix] = 0.0;

                    if ( ix==20 && (iy>=150 && iy<350) ) {
                        pot2DArray[iy][ix] = 1;
                        electrodes2DArray[iy][ix] = 1.0;
                    }
                    if ( ix==480 && (iy>=150 && iy<350) ) {
                        pot2DArray[iy][ix] = -1;
                        electrodes2DArray[iy][ix] = 1.0;
                    }
                }
            }
        }

        function btn_runcalculation_click(event){
            event.preventDefault();

            init();

            let t0= (new Date()).getTime();
            
            doCalculationGPU();

            let t1= (new Date()).getTime();

            let deltat = t1-t0;

            //Completed,Now display results
            document.getElementById("txt_niter").innerHTML= niterations.toString();
            document.getElementById("txt_tiMetaken").innerHTML= deltat.toString();

        }

        var txt_iter = document.getElementById("txt_iter");

        function doCalculationGPU(){

            //Todo

            //Setting up convergence is pretty hard. GPU is good to operate in each pixel in the array individually
            //Instead,this will run several iterations (maxiterations)
            niterations=0;

            do {
                pot2DArray_buffer = doSingleIterationGPU( pot2DArray,electrodes2DArray,arraydim );
                
                niterations++;

                pot2DArray = pot2DArray_buffer;
                
                txt_iter.innerHTML = niterations.toString(); 

            }while (niterations< maxiterations) ; 

        }

        const doSingleIterationGPU = gpu.createKernel( function (pot2DArray,arraydim) {
            //Do the calculation for each output pixel with coordinates (ix,iy)
            //The result at each pixel is the "Average" of all the values in points around it
            // (Laplace - Jacob algorithm)

            let sum=0.0;
            let nsums = 0.0;
            //let vchange=0;

            let iy= this.thread.y;
            let ix= this.thread.x;

            let newval= pot2DArray[iy][ix];

            if ( electrodes2DArray[iy][ix] == 0.0){
                if (iy>0){
                    sum +=pot2DArray[iy-1][ix];
                    nsums++;
                }
                if (iy<arraydim-1){
                    sum += pot2DArray[iy+1][ix];
                    nsums++;
                }
                if (ix>0){
                    sum += pot2DArray[iy][ix-1];
                    nsums++;
                }
                if (ix<arraydim-1){
                    sum += pot2DArray[iy][ix+1];
                    nsums++;
                }
                //sets the new value
                if (nsums>0) {
                    newval = sum/nsums;

                }
            }

            return newval;
        }
        ).setoutput([arraydim,arraydim]); //Results in a 2D array with the new values that are returned



    </script>
</body>
</html>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。