2016-11-17 5 views
1

これは特定の問題です。私は最近、gpu.jsをテストしました。このライブラリは、計算を並列化するためにwebglを使って計算を高速化することになっています。私は簡単なテスト製:GPUのパラレル化が遅くなる

var gpu = new GPU(); 

function product(v, u) { 
    return gpu.createKernel(function(X, Y) { 
     return X[this.thread.x] * Y[this.thread.x]; 
    }).dimensions([v.length])(v, u); 
} 


var before = new Date().getTime(); 
console.log(product(numeric.random([100000]), numeric.random([100000])).length); 
console.log('Parallel Time: ', (new Date().getTime()) - before); 

before = new Date().getTime(); 
v = numeric.random([100000]) 
u = numeric.random([100000]) 
for(var i = 0; i < v.length; i++){ 
    v[i] = v[i] * u[i]; 
} 
console.log(v.length); 
console.log('Procedural Time: ', (new Date().getTime()) - before); 

をそして次の出力ました:

script.js:11 100000 
script.js:12 Parallel Time: 340 
script.js:20 100000 
script.js:21 Procedural Time: 15 

並列時間が遅く桁を超えているが。これがどうなるのか何らかの理由がありますか?私は、GPUの異なるいくつかのマシンでこれを試しました。私は同様の操作をいくつか試みました。間違ったことをやっているのですか、それとも図書館に問題がありますか?私はこれを改善できる方法はありますか?

+0

「http:// gpu.rocks /」でベンチマークを実行すると、大幅に加速しますか? –

+0

ええ、私はそれをもともとやったし、私は5.72倍速くなった。私は何が間違っているのか分かりません。 – user5505266

答えて

0

用途:

t0 = performance.now(); 
 
yourFunctionCall(); 
 
t1 = performance.now(); 
 
console.log("Function yourFunctionCall took " + (t1 - t0) + " ms.");

それが問題の核心だが、私はあまりにも日との問題を抱えてきたかどうかわかりません。

+0

問題の中核ではありませんが、チップのおかげです。私はそれを日付と一緒に働かせましたが、私がこのようなことをすれば、私はパフォーマンスを使用します。ありがとう! – user5505266

1

GPUを扱う際には、オーバーヘッドに注意する必要があります。

gpu.createKernelへの呼び出しは、JavaScriptコードを解析し、適切なGLSLコードを作成し、WebGLに送信してコンパイルしてリンクする必要があるため、非常に高価になりがちです。

少なくとも、そのコマンドを一度呼び出すと、productを呼び出すたびに再利用できるようにグローバル変数に結果を格納することをお勧めします。

また、GPUとの間でデータを移動するために必要な作業量がゼロでないことにも注意してください。計算が複雑になるほど多くの利益が得られます。

+0

この回答をありがとう、私はそれを読むときに私の答えを入力していた。私はオーバーヘッドの問題だと思っていますが、私はそれを毎回呼び出すことでまだ作業しています。私が実際にそれを使って何かを作るなら、私は間違いなくあなたのヒントに従います。ありがとう! – user5505266

0

私はベンチマークのソースコードを調べましたが、多くの操作を連続して実行するとスピードアップが得られることがわかりました。私はそれが頭上の問題だと思う。私はgpu.jsとnumeric.jsを比較して次のような非常に簡単なベンチマークを作成しました。誰もが興味を持っている場合はここにある:これらの結果はかなり良いです

scriptfour.js:26 Parallel Time: 20490 
scriptfour.js:36 Procedural Time: 28736 
scriptfour.js:38 1.402440214738897 times faster 
scriptfour.js:48 Normalized RMSD: 0.009671934749138042 

var gpu = new GPU(); 

var size = 512; 
var scale = 10; 
var iterations = 100; 

// Scaling up the matricies decreases the effect of precision errors 
A = numeric.mul(numeric.random([size, size]), scale) 
B = numeric.mul(numeric.random([size, size]), scale) 

// I know eval is dangerous but I couldn't get the size in any other way 
function multGen(size) { 
    return eval("(function(A, B) { var sum = 0; for (var i=0; i<"+ size +"; i++) {sum += A[this.thread.y][i] * B[i][this.thread.x];} return sum;})") 
} 

var mat_mult = gpu.createKernel(multGen(size)).dimensions([size, size]); 

var before = new Date().getTime(); 
var parallel = mat_mult(A, B); 

// Need to do many computations to get the advantages of the GPU 
for(var i = 0; i < iterations; i++) { 
    parallel = mat_mult(A, B); 
} 
var parTime = (new Date().getTime()) - before; 
console.log('Parallel Time: ', parTime); 

before = new Date().getTime(); 
var procedural = numeric.dot(A, B); 

// Need to do many computations to get the advantages of the GPU 
for(var i = 0; i < iterations; i++) { 
    procedural = numeric.dot(A, B); 
} 
var procTime = (new Date().getTime()) - before; 
console.log('Procedural Time: ', procTime); 

console.log((procTime/parTime) + ' times faster'); 

// This is for RMSD nornalization, flattening and doing min and max that way exceeded the call stack 
var max = Math.max(Math.max(...A.map((function(row) {return Math.max(...row);}))), Math.max(...B.map((function(row) {return Math.max(...row);})))) 

var min = Math.min(Math.min(...A.map((function(row) {return Math.min(...row);}))), Math.min(...B.map((function(row) {return Math.min(...row);})))) 

// The matricies will be different due to precision issues so the Normalized RMDS can give you an idea of the difference 
var nrmsd = Math.sqrt(numeric.sum(numeric.pow(numeric.sub(parallel, procedural), 2))/size)/(max - min); 

console.log('Normalized RMSD: ', nrmsd); 

これは私に次のような出力を与えました。 evalはパラレルなものを不公平に減速させましたが、それはもっと速いです。私はそのような設定は生産には良いとは思いませんが、まだここでもうまくいきます。

関連する問題