【问题标题】:How do I run this function with GPU.js?如何使用 GPU.js 运行此功能?
【发布时间】:2021-05-24 12:41:26
【问题描述】:

我想在 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 上的浏览​​器中运行它?

【问题讨论】:

  • 有任何反馈吗?请查看this

标签: javascript tensorflow gpu gpu.js


【解决方案1】:

GPU.js 仅支持少数操作,因为它被转换为着色器。在此处的测试中,您不能使用它来生成超过 100k 个元素的输出。

operations supported 非常有限,例如,您不能分配给数组元素,这是由于底层计算单元的性质造成的。另外你必须注意branch divergence。

需要两个步骤才能以可在内核中使用的方式实现您的函数。

  1. 使其并行:您的实现是迭代的,每次迭代都会根据前一次迭代的结果构建一个新结果。我创建的是一个函数,给定迭代号 J 可以产生一个排列。
  2. 使其成为标量且无需修改数组:计算置换的函数交换数组上的元素,因此需要分配给数组元素。为了防止我创建的是一个循环,我在其中跟踪每个元素的位置。如果给定元素在位置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);
&lt;script src="https://unpkg.com/gpu.js@latest/dist/gpu-browser.min.js"&gt;&lt;/script&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 2019-08-16
    • 2022-06-12
    • 1970-01-01
    相关资源
    最近更新 更多