Pergunta

Eu estou escrevendo um aplicativo que tenha um produtor múltipla, modelo de consumo individual (vários segmentos enviar mensagens para um único segmento escritor arquivo).

Cada segmento produtor contém duas filas, uma para gravação em, e um para um consumidor a ler de fora. Cada alça da linha do consumidor, ele itera através de cada produtor e bloqueio que mutex do produtor, swaps as filas, desbloqueado, e escreve para fora da fila que o produtor não está mais usando.

No circuito do segmento de consumo, ele dorme por um período de tempo designado após ele processa os tópicos produtores. Uma coisa que eu imediatamente notei foi que o tempo médio para um produtor para escrever algo para a fila e retorno aumentado dramaticamente (por 5x) quando me mudei de 1 thread de produtor a 2. Como mais threads são adicionados, este tempo médio diminui até chegar ao fundo fora - não há muita diferença entre o tempo tomado com 10 produtores vs 15 produtores. Este é provavelmente porque com mais produtores a processo, há menos disputa por mutex do segmento produtor.

Infelizmente, tendo <5 produtores é um cenário bastante comum para a aplicação e eu gostaria de otimizar o tempo de sono para que eu obter um desempenho razoável, independentemente de como existem muitos produtores. Tenho notado que, ao aumentar o tempo de sono, eu posso obter um melhor desempenho para baixa contagem de produtores, mas pior desempenho para grandes contagens de produtores.

Tem mais alguém encontrou isto, e se assim o que era a sua solução? Eu tentei escalar o tempo de sono com o número de threads, mas parece um pouco específico da máquina e de tentativa-e-erro bonito.

Foi útil?

Solução

Você pode escolher o tempo de sono com base no número de produtores ou até mesmo fazer o tempo de sono se adaptar com base em algum esquema dyanmic. Se o consumidor acorda e não tem trabalho, o dobro do tempo de sono, caso contrário, reduzir pela metade dela. Mas limitar o tempo de sono para alguns mínimo e máximo.

De qualquer maneira você está papering sobre uma questão mais fundamental. Dormir e sondagem é fácil chegar à direita e às vezes é a única abordagem possível, mas tem muitos inconvenientes e não é o caminho "certo".

Você pode ir na direção certa, adicionando um semáforo que é incrementado sempre que um produtor adiciona um item a uma fila e diminuído quando o consumidor processa um item em uma fila. O consumidor só vai acordar quando existem itens para processo e vai fazê-lo imediatamente.

Polling as filas ainda pode ser um problema, no entanto. Você pode adicionar uma nova fila que se refere a qualquer fila que tem itens nele. Mas em vez levanta a questão de saber por que você não tem uma única fila que o consumidor processa em vez de uma fila por produtor. Todo ser outra coisa igual que soa como a melhor abordagem.

Outras dicas

Em vez de dormir, eu recomendaria que seu bloco consumidor em uma condição sinalizado pelos produtores. Em um sistema compatível com POSIX, você poderia fazê-lo funcionar com pthread_cond. Criar uma matriz de pthread_cond_t, um para cada produtor, em seguida, criar um adicional que é compartilhado entre eles. Os produtores primeiro sinal de sua variável condição individual, e então a compartilhado. As esperas de consumidores sobre a condição compartilhada e, em seguida, itera sobre os elementos do array, realizando uma pthread_cond_timed_wait() em cada elemento da matriz (pthread_get_expiration_np() uso para obter o tempo absoluto para "agora"). Se a espera retorna 0, em seguida, que o produtor tem escrito dados. O consumidor deve reinicializar as variáveis ??de condição antes de esperar novamente.

Usando espera de bloqueio, você vai minimizar a quantidade de tempo que o consumidor está travando-out desnecessariamente os produtores. Você também pode fazer este trabalho com semáforos, como declarou, em resposta anterior. Semáforos simplificaram semântica em comparação com as condições, em minha opinião, mas você tem que ter cuidado para diminuir o semáforo compartilhados uma vez para cada produtor que foi processado em cada passagem pelo loop consumidor. variáveis ??de condição tem a vantagem de que você pode basicamente usá-los como semáforos boolean se você reinicializar após terem sido sinalizado.

Tente encontrar uma implementação de uma fila de bloqueio na linguagem que você usa para a programação. Não mais do que uma fila será suficiente para qualquer número de produtores e um consumidor.

Para mim, parece que você está a introdução acidental de algum buffer por ter o fio do consumidor estar ocupado em outro lugar, seja dormindo ou fazendo o trabalho real. (A fila agindo como o tampão) Talvez fazendo algum buffer simples no lado do produtor irá reduzir a sua contenção.

Parece que o seu sistema é altamente sensível a lock-contenda entre o produtor eo consumidor, mas estou sem entender por que tal operação de swap simples ocuparia tempo de CPU suficiente para aparecer em suas estatísticas de execução.

Você pode mostrar algum código?

edit:? Talvez você está tendo o seu bloqueio e trocando filas, mesmo quando não há trabalho a fazer

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