Использование gpu.js для клеточных автоматов

Я пытаюсь запустить одномерные клеточные автоматы с помощью gpu.js, но похоже, что мой код без gpu.js работает в 20 раз быстрее. Я не могу понять, где проблема.

The code below runs cellular automata for rule 30 starting from single one ON cell. The length of the automata is 2001 cells. The code calculates the first 10000 generations both using CPU and GPU and for CPU it takes 0.16 sec while for GPU 3.2 sec.

gen = [];
for (var i = 0; i<1000; i++) gen.push(0);
gen.push(1);	
for (var i = 0; i<1000; i++) gen.push(0);

const gpu = new GPU();
const kernel = gpu.createKernel(function(x) {
  const x1 = x[this.thread.x-1];
  const x2 = x[this.thread.x];
  const x3 = x[this.thread.x+1];
  return x1+x2+x3-2*x1*x2-x2*x3-2*x1*x3+2*x1*x2*x3;
}).setOutput([gen.length]);

kernelCPU = function(x){
  var res = [];
  x.unshift(0);
  x.push(0);
  for (var i = 1; i < x.length-1; i++) {
    x1 = x[i-1];
    x2 = x[i];
    x3 = x[i+1];
    res.push(x1+x2+x3-2*x1*x2-x2*x3-2*x1*x3+2*x1*x2*x3);
  }
  return res;

}
var t0 = performance.now();
for (var i = 0; i< 10000; i++) {

  gen = kernelCPU(gen);
}
var t1 = performance.now();
console.log("Took " + (t1 - t0)/1000 + " seconds for CPU")
var t0 = performance.now();
for (var i = 0; i< 10000; i++) {

  gen = kernel(gen);
}
var t1 = performance.now();
console.log("Took " + (t1 - t0)/1000 + " seconds for GPU.")
<script src="https://cdnjs.cloudflare.com/ajax/libs/gpu.js/1.10.4/gpu.min.js"></script>


person Филипп Цветков    schedule 03.06.2019    source источник
comment
Вы запускаете это на интегрированной графике? Ваш код занимает у меня 8-9 секунд.   -  person buffy    schedule 03.06.2019
comment
Да... когда я запускаю тестовый код на странице gpu.js, он работает в 7 раз быстрее, если использую GPU, но мой код работает медленнее. Наверное я что-то пропустил...   -  person Филипп Цветков    schedule 03.06.2019
comment
Попробуйте запустить цикл for в ядре. Это то, что делает эталон.   -  person buffy    schedule 03.06.2019
comment
Я не думаю, что можно распараллелить, т.к. клеточные автоматы вычисляются поколение за поколением.   -  person Филипп Цветков    schedule 05.06.2019


Ответы (1)


Ваша проблема с петлей

for (var i = 0; i< 10000; i++) {
    gen = kernel(gen);
}

Есть некоторые ненулевые накладные расходы, связанные с вызовом функции ядра графического процессора. У вас есть только 2001 ячеек, которые могут быть вычислены параллельно — после начальных накладных расходов на вызов функции ядра графического процессора они должны быть вычислены намного быстрее, чем на ЦП. Однако поскольку вы сталкиваетесь с накладными расходами на вызовы графического процессора 10 000 раз, вы больше, чем теряете достигнутый прирост производительности.

person Tom Wyllie    schedule 09.06.2020