Design: O que são threads de Web Assembly?

Criado em 2 jun. 2015  ·  44Comentários  ·  Fonte: WebAssembly/design

O Web Assembly é especificado em termos de WebWorkers ou eles são diferentes? Quais são as diferenças ou os WebWorkers são apenas um detalhe de implementação?

Talvez o polyfill seja adequado para WebWorkers e o Web Assembly faça seu próprio trabalho, mais próximo de pthreads.

Precisamos garantir que o Web Assembly possa funcionar fora de um navegador.

Comentários muito úteis

Esta é uma importante questão. Em geral, assumi a posição de que devemos trabalhar duro para evitar a duplicação de outras partes da plataforma da Web, permitindo o acesso direto à API da Web a partir do WebAssembly . Dito isso, os threads são uma parte central da semântica de execução, tornando-os mais parecidos com SIMD (óbvio embutido) do que WebGL (API externa óbvia).

Durante uma discussão inicial com @ncbray sobre trabalhadores versus uma versão de threads puramente WebAssembly, eu vi a situação como um ou outro e fiquei do lado dos trabalhadores. Mais recentemente, porém, percebi que os dois podem ser bastante complementares. Primeiro, deixe-me descrever ambos independentemente antes de descrever como eles se compõem:

Com _tarefas baseadas no trabalhador_, para criar uma linha de execução, um aplicativo wasm criaria um trabalhador (na v.1, chamando JS; após a integração WebIDL, importando a API do trabalhador e criando o trabalhador diretamente). Para compartilhar uma pilha wasm / estado global entre os trabalhadores, o próprio objeto do módulo wasm seria postMessage() ed diretamente para o trabalhador de destino, simétrico com a forma como alguém compartilha um SharedArrayBuffer ( importações do módulo WebAssembly seriam reimportados no destino).

Prós:

  • simétrico com o mapeamento óbvio de pthreads-to-asm.js + SAB que Jukka tem funcionando e passando no conjunto de testes pthread.
  • qualquer número de módulos wasm pode ser compartilhado entre qualquer número de trabalhadores, permitindo configurações muito expressivas nos casos de uso not-whole-app-port do wasm.
  • Nenhuma mudança real para a plataforma da web ou APIs da Web em comparação com JS + SAB.

Contras:

  • Workers atualmente estão com muita memória (devido a cada um incluir um contexto de execução JS independente ( JSRuntime / Isolate , etc)).
  • Embora seja definitivamente _possível_ para um trabalhador evitar a criação de contexto JS se nenhum JS for importado no trabalhador (uma vez que tenhamos a integração wasm + WebIDL), esta não será uma tarefa simples de impl (devido a dependências acidentais e ao corte transversal natureza dos trabalhadores). Além disso, há o caso de importação dinâmica de JS (em um trabalhador previamente sem JS) e sobrecarga não JS que pode ser mais difícil de erradicar. Definitivamente interessado em ouvir o que outros navegadores têm a dizer sobre isso. Mas temo que os tópicos não diminuam de forma confiável em todos os navegadores por muitos anos.

Portanto, uma alternativa são os threads puramente definidos pelo WebAssembly. Basicamente, a especificação definiria como você cria, destrói, une, threads etc. Threads estariam logicamente "dentro" de um módulo e todos os threads teriam acesso aos mesmos globais, importações, etc. O que acontece quando um thread não principal chama uma importação que (em um navegador) é JS? (Toda essa ideia de @ncbray) O thread de chamada seria bloqueado e a chamada seria executada no thread principal do módulo (aquele no qual o módulo foi carregado, que tem um Realm etc bem definido) , como se por setTimeout(importedFun.bind(args to import call)) .

Prós:

  • Por construção, cada thread criado pelo WebAssembly não poderia ser nada além de um thread do sistema operacional. Nenhum trabalho especial é necessário para reduzir o tamanho, o que significa threads de custo do sistema operacional a partir do dia 1 em todos os navegadores que implementam o recurso.
  • Podemos acabar querendo algumas operações em threads não desejadas em workers (digamos, pthread_kill ...).

Contras:

  • Latência aumentada em comparação com a chamada síncrona e o gargalo de serialização no encadeamento principal. Uma solução alternativa aqui é que, quando obtemos ligações WebIDL, podemos definir um mecanismo de aceitação (por exemplo, novo atributo de método WebIDL) que as APIs declaram que podem ser chamadas de forma síncrona a partir de threads wasm.

Não vê-los como mutuamente exclusivos sugere um híbrido empolgante:

  • Um módulo pode ser compartilhado com muitos trabalhadores (conforme descrito acima) e, dentro de cada trabalhador, pode bifurcar qualquer número de encadeamentos pure-wasm contidos por esse trabalhador + módulo.

    • O trabalhador que o contém seria o "encadeamento principal" com o propósito de importar chamadas em encadeamentos pure-wasm.

  • Isso permite que um aplicativo wasm controle com precisão quantos loops de eventos e contextos JS ele cria.

    • Por exemplo, eu esperaria que um jogo tivesse um trabalhador OffscreenCanvas (sem threads pure-wasm, apenas renderizando no thread de trabalho sem interrupção), um trabalhador IDB (talvez alguns threads pure-wasm) e um "todos outras threads de fundo "trabalhador (com todas as outras threads como threads pure-wasm).

    • No limite, depois que todas as APIs da Web importantes foram marcadas como chamáveis ​​diretamente de threads pure-wasm, um aplicativo ideal criaria exclusivamente threads pure-wasm.

De um POV de plataforma da Web, acho que nenhum desses muda fundamentalmente o modelo, desde que definamos cuidadosamente coisas como o estado da pilha de objetos de configurações de script (novamente, porém, análogo a setTimeout ). Além disso, os threads pure-wasm são descritíveis e polyfillable em termos de asm.js + SAB: o thread não principal de chamada usa memória compartilhada para enfileirar o trabalho para o thread principal e, em seguida, futexWait() s para uma resposta.

De um POV de ambiente não Web: apenas encadeamentos pure-wasm existiriam de acordo com a especificação (embora a especificação especificasse o que acontece quando algum "outro" encadeamento (leia-se: trabalhador) chama uma função do nada). Essa situação seria simétrica com importações de módulo onde a especificação fala apenas sobre a semântica de um único módulo, deixando o que pode ser importado para o ambiente host. Em particular, isso significa que, com threads pure-wasm, você seria capaz de escrever facilmente um módulo threaded sem quaisquer dependências de host.

O que eu gosto especialmente é que o modelo híbrido evita a necessidade de todos os navegadores reduzirem o número de funcionários (o que pode levar anos e exigir colaboração entre organizações). Estou, no entanto, muito interessado em saber se outros fornecedores de navegadores acham que isso não é grande coisa.

Todos 44 comentários

Parece que existe uma versão do emscripten-fastcomp que usa WebWorkers para implementar threads:
https://github.com/juj/emscripten-fastcomp/tree/pthreads

Como os tópicos estão atualmente listados como um recurso pós-v1 , precisamos resolver isso antes do anúncio público?

Concordado, movendo-se para nenhum marco.

Relacionado a este problema, no nº 103, sugiro que olhemos para as garantias de progresso futuro conforme definidas no comitê de padrões C ++.

Esta é uma importante questão. Em geral, assumi a posição de que devemos trabalhar duro para evitar a duplicação de outras partes da plataforma da Web, permitindo o acesso direto à API da Web a partir do WebAssembly . Dito isso, os threads são uma parte central da semântica de execução, tornando-os mais parecidos com SIMD (óbvio embutido) do que WebGL (API externa óbvia).

Durante uma discussão inicial com @ncbray sobre trabalhadores versus uma versão de threads puramente WebAssembly, eu vi a situação como um ou outro e fiquei do lado dos trabalhadores. Mais recentemente, porém, percebi que os dois podem ser bastante complementares. Primeiro, deixe-me descrever ambos independentemente antes de descrever como eles se compõem:

Com _tarefas baseadas no trabalhador_, para criar uma linha de execução, um aplicativo wasm criaria um trabalhador (na v.1, chamando JS; após a integração WebIDL, importando a API do trabalhador e criando o trabalhador diretamente). Para compartilhar uma pilha wasm / estado global entre os trabalhadores, o próprio objeto do módulo wasm seria postMessage() ed diretamente para o trabalhador de destino, simétrico com a forma como alguém compartilha um SharedArrayBuffer ( importações do módulo WebAssembly seriam reimportados no destino).

Prós:

  • simétrico com o mapeamento óbvio de pthreads-to-asm.js + SAB que Jukka tem funcionando e passando no conjunto de testes pthread.
  • qualquer número de módulos wasm pode ser compartilhado entre qualquer número de trabalhadores, permitindo configurações muito expressivas nos casos de uso not-whole-app-port do wasm.
  • Nenhuma mudança real para a plataforma da web ou APIs da Web em comparação com JS + SAB.

Contras:

  • Workers atualmente estão com muita memória (devido a cada um incluir um contexto de execução JS independente ( JSRuntime / Isolate , etc)).
  • Embora seja definitivamente _possível_ para um trabalhador evitar a criação de contexto JS se nenhum JS for importado no trabalhador (uma vez que tenhamos a integração wasm + WebIDL), esta não será uma tarefa simples de impl (devido a dependências acidentais e ao corte transversal natureza dos trabalhadores). Além disso, há o caso de importação dinâmica de JS (em um trabalhador previamente sem JS) e sobrecarga não JS que pode ser mais difícil de erradicar. Definitivamente interessado em ouvir o que outros navegadores têm a dizer sobre isso. Mas temo que os tópicos não diminuam de forma confiável em todos os navegadores por muitos anos.

Portanto, uma alternativa são os threads puramente definidos pelo WebAssembly. Basicamente, a especificação definiria como você cria, destrói, une, threads etc. Threads estariam logicamente "dentro" de um módulo e todos os threads teriam acesso aos mesmos globais, importações, etc. O que acontece quando um thread não principal chama uma importação que (em um navegador) é JS? (Toda essa ideia de @ncbray) O thread de chamada seria bloqueado e a chamada seria executada no thread principal do módulo (aquele no qual o módulo foi carregado, que tem um Realm etc bem definido) , como se por setTimeout(importedFun.bind(args to import call)) .

Prós:

  • Por construção, cada thread criado pelo WebAssembly não poderia ser nada além de um thread do sistema operacional. Nenhum trabalho especial é necessário para reduzir o tamanho, o que significa threads de custo do sistema operacional a partir do dia 1 em todos os navegadores que implementam o recurso.
  • Podemos acabar querendo algumas operações em threads não desejadas em workers (digamos, pthread_kill ...).

Contras:

  • Latência aumentada em comparação com a chamada síncrona e o gargalo de serialização no encadeamento principal. Uma solução alternativa aqui é que, quando obtemos ligações WebIDL, podemos definir um mecanismo de aceitação (por exemplo, novo atributo de método WebIDL) que as APIs declaram que podem ser chamadas de forma síncrona a partir de threads wasm.

Não vê-los como mutuamente exclusivos sugere um híbrido empolgante:

  • Um módulo pode ser compartilhado com muitos trabalhadores (conforme descrito acima) e, dentro de cada trabalhador, pode bifurcar qualquer número de encadeamentos pure-wasm contidos por esse trabalhador + módulo.

    • O trabalhador que o contém seria o "encadeamento principal" com o propósito de importar chamadas em encadeamentos pure-wasm.

  • Isso permite que um aplicativo wasm controle com precisão quantos loops de eventos e contextos JS ele cria.

    • Por exemplo, eu esperaria que um jogo tivesse um trabalhador OffscreenCanvas (sem threads pure-wasm, apenas renderizando no thread de trabalho sem interrupção), um trabalhador IDB (talvez alguns threads pure-wasm) e um "todos outras threads de fundo "trabalhador (com todas as outras threads como threads pure-wasm).

    • No limite, depois que todas as APIs da Web importantes foram marcadas como chamáveis ​​diretamente de threads pure-wasm, um aplicativo ideal criaria exclusivamente threads pure-wasm.

De um POV de plataforma da Web, acho que nenhum desses muda fundamentalmente o modelo, desde que definamos cuidadosamente coisas como o estado da pilha de objetos de configurações de script (novamente, porém, análogo a setTimeout ). Além disso, os threads pure-wasm são descritíveis e polyfillable em termos de asm.js + SAB: o thread não principal de chamada usa memória compartilhada para enfileirar o trabalho para o thread principal e, em seguida, futexWait() s para uma resposta.

De um POV de ambiente não Web: apenas encadeamentos pure-wasm existiriam de acordo com a especificação (embora a especificação especificasse o que acontece quando algum "outro" encadeamento (leia-se: trabalhador) chama uma função do nada). Essa situação seria simétrica com importações de módulo onde a especificação fala apenas sobre a semântica de um único módulo, deixando o que pode ser importado para o ambiente host. Em particular, isso significa que, com threads pure-wasm, você seria capaz de escrever facilmente um módulo threaded sem quaisquer dependências de host.

O que eu gosto especialmente é que o modelo híbrido evita a necessidade de todos os navegadores reduzirem o número de funcionários (o que pode levar anos e exigir colaboração entre organizações). Estou, no entanto, muito interessado em saber se outros fornecedores de navegadores acham que isso não é grande coisa.

Também podemos desenvolver a plataforma da web de duas maneiras:

  • Permitir que algumas APIs da web, como o GL, sejam usadas fora do encadeamento principal, mas ainda apenas de um encadeamento.
  • No entanto, essa abordagem não funciona para muitos casos de uso de sistema de arquivos: os aplicativos esperam ser capazes de read / write de vários threads sem fazer saltos implícitos e não há realmente um grande motivo para proibir isso. Podemos especificar algumas APIs para funcionar a partir de vários threads de wasm (com algumas restrições).

Também queremos permitir alguma forma de encadeamento leve no modo de usuário. Outras linguagens, como Go, terão melhor desempenho com isso, e o próprio C ++ ganhará esses recursos no C ++ 17 ou logo depois. Vamos garantir que nossa abordagem torne isso possível.

Desde que conversamos, tenho tentado desvendar uma bola confusa e confusa de problemas de interação e pontos de partida não articulados (re: superfície api + ffi + threads) e dividi-los em pedaços menores para conversarmos. Espero começar a postar alguns problemas em breve, considere este um esboço de suporte insuficiente acenando com a mão até então.

Em geral, acho que estamos começando a ver as coisas de uma perspectiva semelhante, mas há muitos problemas relacionados que precisam ser trabalhados até que os detalhes desse problema se encaixem.

Depois de ler as especificações do Web Worker, é muito centrado em JS. Não adianta nada, a menos que um thread tenha um loop de evento implícito (estilo JS) e um isolado JS de thread local. Nesse caso, pode fazer sentido tratá-lo como um trabalhador. (Mas esses tipos de encadeamentos podem não existir, dependendo de outras opções de design.) Tenho algumas outras preocupações sobre como as vidas úteis do trabalhador são especificadas e o fato de que a "origem" do aplicativo pode ser diferente por encadeamento, mas acho que esses problemas podem ser adiados para o momento.

Não acredito que queremos que os trabalhadores se tornem “threads do nada” chamando qualquer código WASM que desejarem. Qual ID de pthreads eles obtêm? Como funciona o TLS? A menos que o gerenciamento de encadeamentos seja hermético ao WASM, haverá algumas perguntas difíceis de responder.

Eu gosto do código WASM interagindo com trabalhadores arbitrários, entretanto. Algo na linha de portas de mensagem + cópias de dados em massa, se nada mais? (Sim, parece um retrocesso, tentarei justificá-lo em outro lugar.)

Reimportar os módulos ES6 associados no postMessage meio que me assusta. Ele resolve alguns problemas desagradáveis, mas também parece um grande martelo que inevitavelmente esmagará outra coisa. Precisarei pensar nas consequências.

Observação: pelo menos no Chrome, eu sei que muitas APIs de trabalho são implementadas pulando pelo thread principal. Portanto, o gargalo explícito no segmento principal pode não prejudicar muito o desempenho, no curto prazo?

Observação: mesmo com SAB, a única maneira real de enfileirar uma tarefa em um thread com um loop de evento implícito (estilo JS) é postMessage. Alternativamente, poderíamos criar algum tipo de funcionalidade do tipo “evento em futex wake”, mas isso pode ser mais adequado para um loop de evento explícito (estilo nativo, rentrant, bombeado pelo programa).

Observação: o mutex de armazenamento implícito parece um deadlock esperando para acontecer, embora eu não consiga encontrar nenhuma API que realmente o adquira em um trabalhador ...

Na terça-feira, 9 de junho de 2015 às 2h05, Nick Bray [email protected] escreveu:

Desde que conversamos, tenho tentado desvendar uma bola confusa e cabeluda de
problemas de interação e pontos de partida não articulados (re: superfície api + ffi

  • threads) e dividi-los em pedaços menores sobre os quais possamos conversar.
    Espero começar a postar alguns problemas em breve, considere isso um aceno de mão
    toco de mal suporte até então.

Em geral, acho que estamos começando a ver as coisas de uma forma semelhante
perspectiva, mas há muitos problemas relacionados que precisam ser trabalhados
até que os detalhes desse problema se encaixem.

Depois de ler as especificações do Web Worker, é muito centrado em JS. Não faz
compre muito para você, a menos que um thread tenha um loop de evento implícito (estilo JS)
e um isolado JS thread-local. Nesse caso, pode fazer sentido tratá-lo
como trabalhador. (Mas esses tipos de tópicos podem não existir, dependendo de outro
escolhas de design.) Eu tenho algumas outras preocupações sobre como as vidas dos trabalhadores são
especificado e o fato de que a "origem" do aplicativo pode ser diferente por thread, mas eu
acho que essas questões podem ser adiadas por enquanto.

Os loops de eventos também podem fazer sentido fora do JS. Por exemplo, há um
alguns modelos que podem ser interessantes de usar, como promessas, IO assíncrono
eventos, etc. Não estou propondo nada de concreto aqui, mas talvez o wasm
caso de uso solicitará uma generalização aqui.

Não acredito que queremos que os trabalhadores se tornem "fios do nada" por
chamando qualquer código WASM que quiserem. Qual ID de pthreads eles obtêm?
Como funciona o TLS? A menos que o gerenciamento de encadeamentos seja hermético ao WASM, existem
vão ter algumas perguntas difíceis de responder.

A questão é como um trabalhador entraria no código wasm? Eles teriam que
obter uma referência ao módulo wasm de alguma forma, presumivelmente tendo aquele primeiro
postMessage () 'd para eles.

Eu gosto do código WASM interagindo com trabalhadores arbitrários, entretanto. Algo
ao longo da linha de portas de mensagem + cópias de dados em massa, se nada mais? (Sim,
parece um retrocesso, tentarei justificá-lo em outro lugar.)

Reimportar os módulos ES6 associados no postMessage meio que me assusta.
Ele resolve alguns problemas desagradáveis, mas também parece um grande martelo que
inevitavelmente esmagar outra coisa. Vou precisar pensar sobre o
consequências.

Nota: pelo menos no Chrome, eu sei que muitas APIs de trabalho são implementadas por
saltando pelo thread principal. Então, explicitamente, o gargalo através do
o fio condutor pode não prejudicar muito o desempenho, no curto prazo?

Nota: mesmo com SAB, a única maneira real de enfileirar uma tarefa em um thread com
um loop de evento implícito (estilo JS) é postMessage. Alternativamente, poderíamos
criar algum tipo de funcionalidade do tipo “evento em futex wake”, mas que
pode ser mais adequado para um explícito (estilo nativo, rentável, bombeado por
o programa) loop de eventos.

Observação: o mutex de armazenamento implícito parece um deadlock esperando para acontecer,
embora eu não consiga encontrar nenhuma API que realmente o adquira em um trabalhador ...

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/WebAssembly/spec/issues/104#issuecomment -110178097.

Concorde com @titzer que podemos oferecer suporte à programação de estilo assíncrono, permitindo que o wasm participe diretamente do loop de eventos (o que não é nem mesmo um esforço de imaginação). Em um nível alto, acho que veremos:

  1. Aplicativos com um C ++ POV portátil que não quer assíncronos, eles querem threads puros e muitos deles e podem se limitar a threads puros wasm (usando trabalhadores apenas para evitar gargalos até que todas as APIs da Web importantes possam ser chamadas diretamente do puro tópicos do wasm).
  2. Aplicativos com um POV da web que são compostos de módulos JS, módulos wasm, são baseados em estruturas populares da web, usam toneladas de assincronia. É aqui que definitivamente precisamos de todo o poder do compartilhamento de funcionários e boa integração com o ciclo de eventos, promessas, etc.

e acho que ambos os casos de uso serão muito importantes no futuro próximo.

De uma perspectiva C ++, poderíamos mapear os 2 POVs que @lukewagner propõe em:

  1. Base de código que exporta _start .
  2. Base de código que exporta algo como um manipulador select ou epoll .

Um interpretador (lua, python, ...) pode caber bem em 2, e as implementações podem muxar o processamento de loop de evento JS com o processamento dos eventos do módulo wasm, incluindo algum descritor de arquivo e manipulação de pipe que o JS normalmente não pode fazer, mas wasm módulo poderia. Para ser claro, não estou dizendo que expomos epoll no estado em que se encontra, mas algo próximo a isso que ainda se encaixa perfeitamente na plataforma da web.

IIUC, select / epoll equivaleria a um bloqueio síncrono em um conjunto limitado de eventos do loop de eventos. Isso tem sido proposto de forma independente para trabalhadores em JS, e provavelmente devemos levar isso adiante (é uma extensão transversal para a plataforma que provavelmente tem amplas consequências semânticas, não algo que podemos fazer apenas localmente no wasm), mas eu acho se quisermos integrar com a plataforma web _existente_, estes não são os primitivos lógicos para fazê-lo: temos que permitir o retorno ao loop de eventos, o que significa que o wasm se registrou como o manipulador onmessage (que poderia ser expressa de forma wasm-y) e participando com as outras formas de filas de micro / nano / pico-tarefas já definidas nas especificações do HTML5. Ou seja, se você pode fazer com que o navegador chame JS, você deve ser capaz de fazer com que ele chame wasm (o que é vagamente possível no MVP, uma vez que você pode fazer com que o JS chame o wasm, mas estamos teorizando um mundo onde o trabalhador (ou mesmo o tópico principal) _somente_ contém wasm). (Exceção: estou bem deixando manipuladores de eventos embutidos como JS apenas para sempre :)

Se eu puder oferecer algumas idéias do lado do servidor das coisas (especificamente nó). Existem três casos de uso principais para threads (provavelmente há nomes "próprios" para eles, mas você vai ter uma ideia):

  • Trabalho nativo computacionalmente pesado. Eles não têm pilha JS. Os valores são passados, um retorno de chamada é definido e quando os números foram processados, o retorno de chamada recebe o valor de retorno.
  • Saindo imediatamente do tópico. Um único arquivo é passado, junto com argumentos opcionais, que são executados até a conclusão, durante o qual os valores de retorno podem ser enviados de volta para o encadeamento pai. Este tem duas variações.

    • Sem thread de acesso de E / S. O encadeamento gerado é essencialmente síncrono, mas para restringir ainda mais o escopo de trabalho que esses encadeamentos podem fazer, eles também não têm permissão para fazer qualquer operação de sincronização de E / S.

    • Thread de E / S. Tem permissão para exigir outros módulos e realizar E / S de sincronização.

  • Thread de loop de evento. Estes são essencialmente como um processo em execução. Exceto na forma como se comunicam e têm a capacidade de compartilhar memória.

Eles têm variações sobre como os desenvolvedores desejam implementá-los. Assim como o encadeamento que sai imediatamente cria uma nova pilha JS toda vez ou usa uma nova. O encadeamento é fechado quando a operação é concluída ou reutilizada. E também é um thread, sync ou async, unido fazendo com que o thread principal pare até que o thread gerado seja concluído.

Desculpe se foram muitos exemplos. O que estou querendo dizer é que parece que a capacidade do wasm de trabalhar com threads não será de nível baixo ou extensa o suficiente para atender a essas necessidades (não espero que seja no primeiro exemplo). Deixando os aplicativos de servidor precisando usar suas próprias ligações. Está correto?

Não tenho todas as respostas, mas uma coisa que posso comentar é que os threads do WebAssembly terão acesso a uma API de nível de pthreads, portanto, os aplicativos terão bastante controle. Decisões como quando e como usar pthread_join são amplamente determinadas pelo aplicativo (ou por uma biblioteca vinculada ao aplicativo).

Além disso, o próprio WebAssembly está sendo projetado para ser independente de JS e será possível ter threads de WebAssembly sem nenhum código JS na pilha.

Obrigada. É excelente ouvir isso.

O que precisamos decidir aqui para o MVP e o que podemos esperar até que realmente introduzamos a memória compartilhada?

Não o vejo bloqueando nada diretamente no MVP. Dito isso, para algo tão central, parece que devemos ter uma ideia bastante clara sobre o recurso (e alguma experiência experimental) antes que o MVP seja realmente finalizado / lançado. Não vejo "blocks_binary", no entanto.

Alguns problemas sobre WebWorkers detalhados aqui: https://github.com/lars-t-hansen/ecmascript_sharedmem/issues/2

FWIW, ambos são problemas de implemento e esperamos abordar no FF.

@lukewagner , eles não são inteiramente problemas de implementação. A semântica de inicialização do trabalhador é permitida pela especificação do trabalhador. A limitação no número de threads é uma consequência de querer evitar ataques DOS, mas é muito rude e algo melhor, com capacidade de observação (ou seja, exceção lançada na falha ao criar um trabalhador), seria bem-vindo por muitos aplicativos, mas provavelmente requer um mudança de especificações também. Além disso, pelo que posso dizer, não há como detectar se um trabalhador foi embora, o que é um orifício de especificação bizarro, mas não encontrei um mecanismo para isso.

@ lars-t-hansen Quanto aos workers que não começam antes de retornar ao loop de eventos, quando você diz "permitido pela especificação", você quer dizer apenas que a especificação não especifica quando o progresso é feito ou menciona especificamente esse caso? Quanto à limitação do número de threads, você está certo, o que é necessário (além de uma cota maior) é algum erro visível para indicar que a cota foi excedida.

Acho que uma garantia de progresso é o que queremos aqui, de acordo com o artigo N4439 de Torvald Riegel para o comitê de padrões C ++ .

@lukewagner , minha memória é que a especificação não tem nenhuma linguagem que trate do progresso. Inicialmente, pensei que não importasse (muito), pois não era observável para o agente de criação sem aquele agente esperando por um evento, mas não é realmente assim - se o trabalhador tiver acesso a XHR ou renderização, o thread principal pode bifurcar um trabalhador teria um efeito externo, e a ausência do efeito seria visível para um servidor web remoto ou para o usuário.

@jfbastien , ainda não li esse artigo, mas concordo, algo assim é desejável.

(Vou escrever para o nosso pessoal de padrões da Web sobre as especificações do Worker.)

Mais algumas notas sobre os trabalhadores. A seção central é WHATWG spec 10.2.4, Modelo de Processamento

  • O algoritmo "executar um trabalhador": "1. Crie um ambiente de execução paralela separado (ou seja, uma thread ou processo separado ou construção equivalente) e execute o restante dessas etapas nesse contexto."). Isso implica fortemente ("paralelo", "encadeamento ou processo") que um trabalhador requer verdadeira simultaneidade, proibindo tanto o retardo de loop de evento de retorno quanto o retardo de espera indefinido por recurso.
  • O algoritmo "matar um trabalhador" tem uma observação interessante: "Os agentes do usuário podem invocar o modelo de processamento" matar um trabalhador "em um trabalhador a qualquer momento", ou seja, um trabalhador pode simplesmente morrer sem motivo. (E não é óbvio que isso seja diretamente observável.)

@ lars-t-hansen Hah, um bom ponto a respeito da capacidade de observação via rede (especialmente quando você leva em conta a sincronização XHR no tópico principal)> :)

Em relação à parte "a qualquer momento" "mate um trabalhador", isso é estranho. Espero que esteja se referindo à caixa de diálogo de script lento, mas, nesse caso, parece útil definir melhor isso como parte de um evento de aplicativo maior que elimina todos os workers e scripts.

@lukewagner , A especificação do service worker (https://slightlyoff.github.io/ServiceWorker/spec/service_worker/) fornece justificativa mínima para o comportamento de "matar um trabalhador" (na verdade, falta de IU para uma caixa de diálogo de script lento, consulte o seção "Lifetime"), mas nenhuma orientação real sobre como evitar ser baleado. Para um trabalhador computacional em um contexto SAB, essa licença para matar é particularmente problemática, já que o modo padrão para esse trabalhador será que ele aguarde uma variável de condição por mais trabalho, não que ele retorne ao seu loop de eventos.

Bug apresentado contra a especificação WHATWG aqui: https://www.w3.org/Bugs/Public/show_bug.cgi?id=29039.

@slightlyoff provavelmente pode

Eu acho que a execução do webasm em ambientes estritamente de processo único seria possível, mesmo se a especificação exigir a presença de uma API de nível de pthreads. Como o paralelismo, ao contrário da simultaneidade, não pode ser garantido, uma implementação estaria livre para simplesmente tratar os "pthreads" criados como blocos a serem agendados arbitrariamente?

As garantias mais rígidas do que o soft realtime serão garantidas pela especificação?

@emanuelpalm concordou, uma implementação válida poderia emular um sistema de processador único.

Hard-realtime não é algo que eu acho que podemos garantir em geral, porque o WebAssembly não sabe a priori em qual máquina será executado. Vejo essa limitação como semelhante a algoritmos de tempo constante promissores: o arquivo .wasm não sabe como realmente será reduzido e quais garantias pode esperar do JIT e da máquina em que será executado.

Estou muito animado com isso:
http://images.nvidia.com/events/sc15/SC5105-open-source-cuda-compiler.html
https://developer.nvidia.com/CUDA-LLVM-Compiler

Alguma idéia de se implementar um loop paralelo forall seria viável no Web Assembly?

Como o pipeline poderia ser uma forma concreta de experimentar?
web assembly -> wasm binary -> chrome -> gpu

Parece mais conveniente ter algo como:
web assembly -> binary (jit?) -> chrome -> gpu

@jbondc Acho que seu pensamento está mais próximo do paralelismo de C ++ TS, que requer suporte de tempo de execução. Seria possível, mas o WebAssembly atualmente não tem trabalho em andamento para GPUs. É importante, mas não o foco principal do MVP. O trabalho da equipe de Robert é muito diferente do que o WebAssembly faria (embora pudesse se beneficiar desse trabalho).

Sim, parece certo:
https://github.com/cplusplus/parallelism-ts/blob/master/parallelism-ts.pdf

Mas estou mais interessado em escrever minha própria linguagem que compila até o Web Assembly (e tem suporte para paralelismo).

Acho que a melhor coisa que wasm pode e deve fazer é fornecer os primitivos de hardware brutos para paralelismo ( threads e SIMD ) dentro do modelo de CPU de uso geral assumido pelo WebAssembly para os autores da linguagem / biblioteca / ferramenta, deixando APIs da Web existentes e futuras para acessar o hardware fora da CPU de uso geral (como WebGL para a GPU). Em seguida, os autores da linguagem / biblioteca / ferramenta podem construir abstrações que visam um modelo específico de paralelismo. (Este é basicamente apenas um argumento Extensible Web .) Com base nisso, eu acho que as bibliotecas no paralelismo C ++ TS seriam fornecidas como bibliotecas no topo das primitivas acima mencionadas da plataforma web, não como funções embutidas (pelo menos, não no curto prazo).

@jbondc É uma abstração de nível superior e uma estrutura que eu esperava que pudesse ser implementada no wasm com bom desempenho. Se alguém tentou portar isso e encontrou alguns obstáculos, isso pode sugerir suporte a threading de baixo nível extra a ser considerado para o wasm?

Meu entendimento por trás das razões para evitar tais abstrações de alto nível é que eles geralmente têm usos de nicho e também têm suposições e limitações inerentes que não mapeiam bem para o hardware, então pode não haver o interesse geral em garantir suporte direto, mas talvez alguém pode reunir suporte para alguns outros modelos de computação paralela.

Não é uma abstração de nível superior. O "Modelo de ator" (https://en.wikipedia.org/wiki/Actor_model) é um modelo teórico diferente para pensar sobre computação (versus uma máquina de turing finita).

Com base no hardware (por exemplo, GPU da Nvidia), você pode implementar em uma VM algumas mensagens que passam atorLike. A meu ver, se o Chrome, Chakra, Firefox ou Webkit implementassem correspondência de padrões + uma coisa do atorLike, então obteríamos paralelismo C ++ de graça, compartilhamento de memória + threads e praticamente qualquer outro modelo simultâneo.

Relacionado no caso de alguém querer hackear algo junto:
https://github.com/solodon4/Mach7

@jbondc Não é SMP e duvida que possa implementar código SMP com algum nível de eficiência? Considere como ele implementaria pilhas e filas atualizadas atomicamente, caches etc. em um código escrito para memória compartilhada? O suporte wasm planejado deve permitir que algumas dessas linguagens de programação de 'Modelo de Ator' sejam implementadas em wasm, e as operações atômicas podem ser usadas para implementar filas de mensagens rápidas e gerenciamento de memória para manter os atores separados, etc.

@JSStats Estou mais tentando ver bons blocos de construção. Melhor hardware já está aqui.

Há uma boa discussão sobre hardware aqui:
http://amturing.acm.org/acm_tcc_webcasts.cfm (Arquitetura de Computador)

O projeto de threads / memória compartilhada está ruim.
O Actor Model Hewitt ou alguma variação dele é o caminho a percorrer.

Como um exemplo concreto, este é um bom trabalho:
http://2014.rtss.org/wp-content/uploads/2014/12/RTSS2014-sifakis-distr.pdf

Página 34. Tópicos ruins.
Página 48. Bom modelo.

Página 59-60. Um ~ 'jit binário' pode ser aplicado aqui: gerador BIP distribuído.

Vou tentar alguns experimentos nos próximos meses, espero que outros se juntem.

Movendo este marco para Pós-MVP, para que o marco do MVP se concentre em tarefas acionáveis ​​para o MVP. Obviamente, é importante planejar os threads, mas tenho a impressão de que já existe conhecimento suficiente, portanto, não precisamos desse problema para nos lembrar. Se as pessoas discordarem, estou bem em movê-lo de volta.

@jbondc Se você está planejando fazer alguns experimentos, abra uma nova edição para relatar suas descobertas. Obrigado!

@sunfishcode servirá , mas desistiu em grande parte.

Para qualquer pessoa interessada em BIP:
http://www-verimag.imag.fr/New-BIP-tools.html

É o pensamento, então, com threads WASM, que um código como este seria compilado em operações de carga / armazenamento atômicas?

class FastBlockableMutex {
 protected:
  atomic<bool> mIsLocked;
  atomic<int> mWaiters;
  atomic<int> mBlockers;
  mutex mMutex;

};

@jbondc ele precisaria de instruções para reduzir para ops ;-)
Sim, os acessos atômicos seriam, desde que o tamanho esteja livre de bloqueio. Mutex provavelmente iria para um atômico e depois para algum tipo de futex. Espero que o modelo esteja próximo disso .

@jbondc não é a ideia de fornecer encadeamentos e comparar e trocar etc. para que se possa construir uma implementação de ator livre de bloqueio em cima deles?

@binji irá abordar a proposta de tópicos . Fechando.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

void4 picture void4  ·  5Comentários

Artur-A picture Artur-A  ·  3Comentários

beriberikix picture beriberikix  ·  7Comentários

mfateev picture mfateev  ·  5Comentários

arunetm picture arunetm  ·  7Comentários