Pergunta

Eu estou tentando vir acima com um projeto para um pool de threads com um monte de requisitos de projeto para o meu trabalho.Este é um problema real para o software trabalhar, e é uma tarefa difícil.Eu tenho um trabalho de implementação, mas eu gostaria de jogar esse MODO e ver o que tem de interessante ideias que as pessoas podem vir para cima, de modo que eu posso comparar a minha implementação e ver como ele se enquadra.Eu tentei ser o mais específico para a requisitos como eu posso.

O pool de threads precisa para executar uma série de tarefas.As tarefas podem ser curtos (<1sec) ou longa (horas ou dias).Cada tarefa tem associada uma prioridade (de 1 = muito baixo a 5 = muito elevado).Tarefas podem chegar a qualquer hora, enquanto as outras tarefas que estão em execução, assim como eles chegam o pool de threads precisa pegá-las e programá-los como segmentos se tornam disponíveis.

A prioridade da tarefa é completamente independente da tarefa de comprimento.Na verdade, é impossível dizer quanto tempo uma tarefa para executar, sem justa de executá-lo.

Algumas tarefas são dependente da CPU, enquanto alguns são muito IO bound.É impossível dizer de antemão que uma determinada tarefa seria (embora eu acho que pode ser possível detectar, enquanto as tarefas em execução).

O principal objetivo do pool de threads é maximizar a taxa de transferência.O pool de threads devem usar efetivamente os recursos do computador.Idealmente, para a CPU bound tarefas, o número de segmentos ativos deve ser igual ao número de CPUs.Para IO tarefas limitadas, mais threads devem ser alocados do que há CPUs para que o bloqueio não excessivamente afetar a taxa de transferência.Minimizar o uso de bloqueios e usando thread-safe/fast recipientes é importante.

Em geral, você deve executar tarefas de prioridade maior, com maior prioridade do processador (ref.:SetThreadPriority).Tarefas de menor prioridade não deve "bloco" de maior prioridade tarefas de execução, por isso, se uma tarefa de prioridade mais alta que vem, enquanto todos os de baixa prioridade são as tarefas de execução, a tarefa de prioridade mais alta vai começar a executar.

As tarefas têm um "max tarefas em execução" parâmetro, associado com eles.Cada tipo de tarefa só é permitido para executar em mais este número de instâncias simultâneas a tarefa de cada vez.Por exemplo, podemos ter as seguintes tarefas na fila:

  • A - 1000 instâncias - baixa prioridade - max tarefas 1
  • B - 1000 instâncias - baixa prioridade - max tarefas 1
  • C - 1000 instâncias - baixa prioridade - max tarefas 1

Um trabalho de aplicação só pode executar (no máximo) de 1 A, 1 B e 1 C ao mesmo tempo.

Ele precisa ser executado no Windows XP, Server 2003, Vista e Server 2008 (service packs mais recentes).


Como referência, podemos usar a seguinte interface:

namespace ThreadPool
{
    class Task
    {
    public:
        Task();     
        void run();
    };

    class ThreadPool
    {    
    public:
        ThreadPool();
        ~ThreadPool();

        void run(Task *inst);
        void stop();
    };
}
Foi útil?

Solução

Então, o que vamos pegar como o bloco de construção básico para isso.O Windows tem dois blocos de construção que parecem promissores :- Conclusão de e/S de Portas (IOCPs) e Chamadas de Procedimento Assíncrono (APCs).Ambos estes dê-nos em fila FIFO sem necessidade de realizar o bloqueio explícitas, e com uma certa quantidade de built-in suporte do SO em lugares como o programador (por exemplo, IOCPs pode evitar algumas alternâncias de contexto).

As APCs são, talvez, um pouco melhor ajuste, mas temos que ser um pouco cuidadoso com eles, porque eles não são muito "transparente".Se o item de trabalho executa uma alertable esperar (::SleepEx, ::WaitForXxxObjectEx, etc.) e nós acidentalmente expedição da APC para o segmento, em seguida, o recém-enviados APC vai assumir o segmento, a suspensão anteriormente a execução de APC até que o novo APC é terminado.Isso é ruim para os nossos requisitos de concorrência e pode fazer de estouros de pilha mais provável.

Outras dicas

Ele precisa ser executado no Windows XP, Server 2003, Vista e Server 2008 (service packs mais recentes).

Que característica do sistema built-in thread pools de torná-los impróprios para a sua tarefa?Se você deseja segmentar XP e 2003, você não pode usar o novo brilhante Vista/2008 piscinas, mas você ainda pode usar QueueUserWorkItem e amigos.

@DrPizza - esta é uma pergunta muito boa, e aquele que atinge diretamente ao cerne do problema.Existem algumas razões para que a QueueUserWorkItem e o Windows NT pool de threads foi descartada (embora o Vista não parecer interessante, talvez em alguns anos).

Em primeiro lugar, queríamos ter um maior controlo sobre quando se inicia e pára de threads.Temos ouvido que o NT pool de threads é relutantes em começar uma nova discussão se ele considera que as tarefas são curtos.Podemos usar a WT_EXECUTELONGFUNCTION, mas nós realmente não tenho idéia se a tarefa é longa ou curta

Em segundo lugar, se o pool de threads já estava cheio de longa, baixa prioridade de tarefas, não haveria chance de tarefas de alta prioridade chegando a executar em tempo hábil.O NT pool de thread não tem real noção de prioridades de tarefas, de modo que não pode fazer um QueueUserWorkItem e dizer "ah, a propósito, execute este um direito de distância".

Em terceiro lugar, (de acordo com MSDN) o NT pool de threads não é compatível com o STA apartamento modelo.Eu não tenho certeza se é bem o que isso significaria, mas todos os nossos segmentos de trabalho executado em um STA.

@DrPizza - esta é uma pergunta muito boa, e aquele que atinge diretamente ao cerne do problema.Existem algumas razões para que a QueueUserWorkItem e o Windows NT pool de threads foi descartada (embora o Vista não parecer interessante, talvez em alguns anos).

Sim, parece que tem bastante reforçada em Vista, bastante versátil agora.

OK, eu ainda estou um pouco confusa sobre como deseja que as prioridades para o trabalho.Se a piscina estiver atualmente executando uma tarefa do tipo A com o máximo de simultaneidade de 1 e de baixa prioridade, e é dada uma nova tarefa também do tipo A (e máxima de simultaneidade 1), mas desta vez com uma prioridade alta, o que deveria fazer?

Suspensão da execução actualmente Um é cabeludo (ele poderia realizar um bloqueio que a nova tarefa precisa tomar, travado o sistema).Ele não pode gerar um thread de segundo e apenas deixá-lo correr ao lado (o permitido simultaneidade é apenas 1).Mas ele não pode esperar até que a tarefa de baixa prioridade é concluída, porque o tempo de execução é ilimitado, e isso iria permitir que uma tarefa de baixa prioridade para bloquear uma das tarefas de alta prioridade.

Minha presunção é a de que é este o comportamento que você está procurando?

@DrPizza:

OK, eu ainda estou um pouco confusa sobre como você deseja as prioridades para o trabalho.Se a piscina está actualmente em execução de uma tarefa do tipo A com o máximo de simultaneidade de 1 e baixa prioridade, e ele fica determinado uma nova tarefa também do tipo Um (e o máximo de simultaneidade 1), mas desta vez com um de alta prioridade, o que deveria fazer?

Este é um pouco complicado, embora, neste caso, eu acho que eu seria feliz com simplesmente permitindo que a tarefa de baixa prioridade para o executado para conclusão.Geralmente, nós não iria ver um monte de os mesmos tipos de tarefas com diferentes prioridades de thread.No nosso modelo, na verdade, é possível, com segurança, parar e depois reiniciar tarefas bem determinadas, pontos definidos (por motivos diferentes do que isso), embora as complicações que isso implicaria, provavelmente, não vale a pena o risco.

Normalmente, apenas os diferentes tipos de tarefas com prioridades diferentes.Por exemplo:

  • Uma tarefa - 1000 instâncias - baixa prioridade
  • B tarefa - 1000 instâncias de alta prioridade

Assumindo as tarefas havia chegado e estavam em execução e, em seguida, a B as tarefas havia chegado, nós queremos a B tarefas para ser capaz de executar com mais ou menos imediato.

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