Pergunta

Estou trabalhando em uma biblioteca fazendo codificação/decodificação de áudio. O codificador deve poder usar vários núcleos (ou seja, vários threads, usando a biblioteca Boost), se disponível. O que tenho agora é uma classe que executa todas as operações relevantes para codificação.

O próximo passo que quero dar é fazer essa aula rosqueada. Então, estou me perguntando como fazer isso.

Pensei em escrever uma classe de threads, criar n threads para n núcleos e depois chamar o codificador com os argumentos apropriados. Mas talvez seja um exagero e não há necessidade de outra classe, então vou usar a "interface do usuário" para criação de threads.

Espero que haja alguma sugestão.

Editar: Sou forçado a usar vários threads para o pré-processamento, criando estatísticas dos dados de entrada usando CUDA. Portanto, se houver vários cartões em um sistema, a única maneira de usá -los em paralelo é criar vários threads.

Exemplo: 4 arquivos, 4 diferente Unidades de cálculo (memórias separadas, ID de dispositivo exclusivo). Cada um dos arquivos deve ser executado em uma unidade de cálculo.

O que tenho agora é:

class Encoder {
[...]
public:
    worker(T data, int devId);
[...]
}

Então eu acho que a melhor maneira é chamar o trabalhador de rosca de Main ()

boost::thread w1(&Encoder::worker, data0, 0);
boost::thread w2(&Encoder::worker, data1, 1);
boost::thread w3(&Encoder::worker, data2, 2);
boost::thread w4(&Encoder::worker, data3, 3);

e não implementar uma classe de threads.

Foi útil?

Solução

Eu acho que o problema está mais em um nível de design, você pode elaborar um pouco sobre quais aulas você tem? Também trabalho no CUDA, e geralmente um cria uma interface (também conhecida como padrão de fachada) para usar a camada específica da arquitetura (CUDA).

Editar: Depois de ler a interface de atualização, acho que você está fazendo a coisa certa. Mantenha a lógica do codificador dentro da classe e use threads de impulso simples :: para executar diferentes unidades de trabalho. Basta preste atenção na segurança do encadeamento dentro dos métodos do codificador.

Outras dicas

Dê uma olhada em OpenMP, se o seu compilador suportar. Pode ser tão fácil quanto adicionar uma bandeira do compilador e pulverizar em alguns #pragmas.

Sua sugestão atual funciona apenas se Encoder::worker é static. Presumo que seja esse o caso. Uma preocupação seria, se sua implementação atual suporta uma maneira de abortar graciosamente um trabalho de codificação. Suponho que existe algum método no seu código do formulário:

while( MoreInputSamples ) {
    // Do more encoding
}

Isso pode ser modificado com algumas condições adicionais que verifica se os trabalhos receberam um sinal de abortamento. Eu trabalho muito em vídeo e gosto de ter minhas aulas de decodificador como essa:

class Decoder {
public:
    void DoOneStepOfDecoding( AccessUnit & Input );
}

A saída geralmente vai para algum buffer de anel. Dessa forma, posso envolver isso facilmente em cenários únicos e multithread.

O código anterior

  boost::thread w1(&Encoder::worker, data0, 0);

não é válido até que o trabalhador seja estático.

Boost.Task no cronograma de revisão que permite chamar de forma assíncrona qualquer chamável, como segue

  boost::tasks::async(
    boost::tasks::make_task( &Encoder::worker, data0, 0) ) );

Isso resulta em codificador :: trabalhador foi chamado em um threadpool padrão. A função retorna um identificador que permite saber quando a tarefa foi executada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top