Как запустить сотни асинхронных c функций с аргументами в JS - PullRequest
0 голосов
/ 18 июня 2020
const width=512
const height=512

img = ctx.createImageData(width,height)
//data = a 2D array that I'm trying to map to img

function data_to_rgb(h,w,data,img){
  //modify the img object at h,w with data at h,w
  //return nothing
}

function draw_loop(){

  //some code that acts on data

  for(let w=0;w<width;++w){
    for(let h=0;h<height;++h){
      data_to_rgb(w,h,data,img)
    }
  }
  ctx.putImageData(img,0,0)
}

Как преобразовать этот фрагмент кода, чтобы начать выполнение data_to_rgb параллельно, дождаться, пока все они завершатся sh, а затем выполнить ctx.putImageData(img,0,0)? Я сам разбирался, как это сделать, но пока все примеры, показывающие, как это сделать, продолжают использовать функции, не имеющие аргументов, тогда как у меня было 4.

Я попробовал приведенный ниже код, но производительность упала. примерно до ~ 1/10. Я потратил слишком много часов, пытаясь решить эту проблему самостоятельно.

const width=512
const height=512

img = ctx.createImageData(width,height)
//data = a 2D array that I'm trying to map to img

async function data_to_rgb(h,w,data,img){    //MADE THIS ONE ASYNC
  //modify the img object at h,w with data at h,w
  //return nothing
}

async function draw_loop(){                  //MADE THIS ONE ASYNC

  //some code that acts on data
  let tasks = []                             //DEFINED THIS TASKS LIST
  for(let w=0;w<width;++w){
    for(let h=0;h<height;++h){
      tasks.push(data_to_rgb(w,h,data,img))  //PUSHED IT INTO THE TASKS LIST
    }
  }
  await Promise.all(tasks)                   //ADDED THIS AWAIT
  ctx.putImageData(img,0,0)
}

Я неправильно использую asyn c? (Может быть, его следует ... больше использовать для вещей, связанных с сетью)
Моя попытка решить эту проблему самостоятельно даже делает то, что я хочу?


Вот фактический код
Вот код с асинхронным c в действии
Вот код без asyn c в действии

Ответы [ 2 ]

0 голосов
/ 28 июня 2020

Вот попытка собрать воедино беспорядок в комментариях под вопросом.

Как запустить сотни асинхронных c функций с аргументами в JS

Вам действительно удалось запустить их все. Однако они по-прежнему будут выполняться только последовательно, потому что ключевое слово asyn c не создает дополнительных потоков.

Я неправильно использую asyn c? (Может быть, его следует ... больше использовать для вещей, связанных с сетью) Моя попытка решить эту проблему самостоятельно даже делает то, что я хочу?

Да, вы неправильно используете asyn c в данном конкретном случае. Да, он делает то, что вы «хотите, чтобы он делал», вы запускаете сотни асинхронных c вызовов, все они генерируют абсурдное количество обещаний, которое все замедляет.


Асин c следует использовать при ожидании прибытия данных, будь то inte rnet, ваш жесткий диск или какое-то устройство, подключенное к USB-кабелю. Некоторые данные, которых сейчас нет в оперативной памяти.


Asyn c не следует использовать, когда в оперативной памяти уже находится много данных, которые должны выполняться параллельно.


Веб-воркеры или webgl должны использоваться в этом конкретном случае, потому что вы хотите обрабатывать информацию, которая уже существует в оперативной памяти, параллельно. Чтобы убедиться, что все веб-воркеры выполнены, посмотрите другой вопрос о переполнении стека , который решает эту проблему.

0 голосов
/ 18 июня 2020

Если я правильно понимаю проблему, вы хотите запустить все преобразования изображения, а затем применить эти преобразования, как только они все будут завершены.

Я думаю, что решение состоит в том, чтобы data_to_rgb действительно что-то возвращал. Но поскольку ваше изображение обрабатывается data_to_rgb, вы можете просто скопировать изображение. Один из них может помочь? html5: копирование холста в изображение и обратно

function draw_loop(){
  const someNewImageData = copyImageSomehow(img)

  // apply the transforms on the copied image
  for(let w=0;w<width;++w){
    for(let h=0;h<height;++h){
      data_to_rgb(w,h,data, someNewImageData)
    }
  }

  // now apply the new image data
  ctx.putImageData(someNewImageData ,0,0)
}
...