如何解决如何使用 GPU.js 运行此函数?
我想在 GPU 上运行这个排列函数。
function* permute(permutation) {
var length = permutation.length;
var c = Array(length).fill(0);
var i = 1;
var k;
var p;
yield permutation.slice();
while (i < length) {
if (c[i] < i) {
k = i % 2 && c[i];
p = permutation[i];
permutation[i] = permutation[k];
permutation[k] = p;
++c[i];
i = 1;
yield permutation.slice();
} else {
c[i] = 0;
++i;
}
}
}
为了在 GPU 上运行它,我尝试使用 https://gpu.rocks/,但我不明白他们关于如何设置线程的示例。我应该如何编写这个排列函数,以便我可以在 GPU 上的浏览器中运行它?
解决方法
GPU.js 只支持少数操作,因为它被转换为着色器。在此处的测试中,您不能使用它来生成超过 100k 个元素的输出。
operations supported 非常有限,例如不能分配给数组元素,这是由于底层计算单元的性质。您还必须注意 branch divergence。
需要两个步骤才能以可在内核中使用的方式实现您的函数。
-
使其并行:您的实现是迭代的,每次迭代都会根据前一次迭代的结果构建一个新结果。我创建的是一个函数,它给定迭代次数
J
可以产生一个排列。 -
使其成为标量且不修改数组:计算排列的函数交换数组上的元素,因此需要分配给数组元素。为了防止我创建的是一个循环,我在其中跟踪每个元素的位置。如果给定元素在位置
I
结束,则返回该元素。请注意,必须为每个排列中的每个元素调用一次此函数。
const gpu = new GPU();
// For reference
// This is the function to compute the J'th permutation
// of N elements. Rewrited to create the kernel.
function permutation(J,N) {
const arr = []
for(let i = 0; i < N; ++i)arr[i] = i;
let j = J;
for(let i = 2; i <= N; ++i){
let e1 = j % i;
const t = arr[e1];
arr[e1] = arr[i-1];
arr[i-1] = t;
j = (j - e1) / i;
}
return arr;
}
function permuteAt() {
const N = this.constants.length;
let I = N - this.thread.x - 1;
let J = this.thread.y;
for(let d = 0; d < N; ++d){
// check if the I'th element of the J'th permutation is d
let dPos = d;
let j = J;
let i = 0;
for(let i = 2; i <= N; ++i){
let e1 = j % i;
let e2 = i - 1;
// track the movements element d
if(e1 == dPos){
dPos = e2;
}else if(e2 == dPos){
dPos = e1;
}
j = (j - e1) / i;
}
// element d ended at position i
// console.log(JSON.stringify({dPos,I,J,N,t: this.thread}))
if(dPos == I){
return d;
}
}
return -1;
}
// Run it in javascript
let result;
const t0Js = Date.now()
for(let i = 0; i < 1000; ++i){
result = [0,1,2,3,4,5,6,7,8,9].map(v => permuteAt.apply({
thread: {x: i,y: v},constants: {length: 10}
}))
}
const tfJs = Date.now();
console.log('time spend in javascript: ',(tfJs - t0Js)/10000);
const generatePermutations = gpu.createKernel(permuteAt).setOutput([10,10000]).setConstants({length: 10});
const t0GPU = Date.now()
for(let i = 0; i < 100; ++i){
const c = generatePermutations();
}
const tfGPU = Date.now();
console.log('time spend in gpu: ',(tfGPU - t0GPU)/10000/100);
<script src="https://unpkg.com/gpu.js@latest/dist/gpu-browser.min.js"></script>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。