No caso do linux você consegue alocar mais 350 threads em outro
processo simultaneamente ou o limite é da máquina? É interessante
lembrar que a implementação de threads é bem diferente entre Windows e
Linux. Se eu entendi bem o "Linux Kernel for Total Dummies", uma
thread no Linux é mais "cara" do que no Windows (assim como o processo
no Windows é muito mais "caro" que no Linux).
Rodrigo Strauss
2008/4/10 Fernando Gomes <fer...@googlemail.com>:
WOW. Pra que vc precisa de tantas threads? Provavelmente vc está
usando o projeto errado.
Se você está preocupado com espera de I/O, dê uma olhada no boost.asio
para asynchronous I/O, que
diminui o uso de threads, e portanto o overhead associado a elas:
stack space, sincronizacao e
troca de contexto.
> Aos colegas que trabalham com C++ e com alta-perfomance, o que vcs
> costumam utilizar quando vcs necessitam fazer algo similar?
Eu começo a pensar em como resolver o problema de forma diferente.
>
> Desde já grato.
>
> []s
>
> ./Fer -G0
--
Felipe Magno de Almeida
O limite de threads está relacionado ao tamanho reservado para a pilha. O default do linux é muito maior que dos outros SOs. Você pode diminuir ele usando pthread_attr_setstacksize no pthread_attr_t usado para criar a thread.
Aqui em casa com Open Suse 64 bits consigo criar 20 mil threads paradas sem problema limitando o stack de cada uma em 64K. Não que isso seja útil enquanto eu não tiver umas 500x mais cores que hoje.
Se você precisa de tanta linhas de execução simultâneas provavelmente não vai ser apenas com threads do SO que vai resolver.
Se o teu problema envolve o processamento de muitos sockets, muito melhor é usar o padrão Reactor com IO assíncrona ou multiplexada. O resultado é excelente e costuma ter baixa latência - já vi roteador de VOIP serem escritos assim - e usando Java que possui uma quota superior de latência muito maior.
Porém se o seu problema não se resume a muitos canais de IO a solução pode ser usar threads cooperativas com userland scheduling, dá um belo trabalho implementar, principalmente por não ser possível aplicar CPS em código C ou C++. Mas é possível tranquilamente escalar para dezenas de milhares de threads em máquinas com 4 cores com um overhead de scheduling baixo.
O limite de threads está relacionado ao tamanho reservado para a pilha. O default do linux é muito maior que dos outros SOs. Você pode diminuir ele usando pthread_attr_setstacksize no pthread_attr_t usado para criar a thread.
Aqui em casa com Open Suse 64 bits consigo criar 20 mil threads paradas sem problema limitando o stack de cada uma em 64K. Não que isso seja útil enquanto eu não tiver umas 500x mais cores que hoje.
Kumpera, você está chegando onde eu queria...Em 10/04/08, Rodrigo Kumpera <kum...@gmail.com> escreveu:O limite de threads está relacionado ao tamanho reservado para a pilha. O default do linux é muito maior que dos outros SOs. Você pode diminuir ele usando pthread_attr_setstacksize no pthread_attr_t usado para criar a thread.
Cara, vou tentar descobrir como fazer isto com o Boost Thread e no QThread, mas vc chegou no ponto onde eu queria.Aqui em casa com Open Suse 64 bits consigo criar 20 mil threads paradas sem problema limitando o stack de cada uma em 64K. Não que isso seja útil enquanto eu não tiver umas 500x mais cores que hoje.
Vc já tentou ver quantas threads simultâneas vc consegue deixar em pseudo-execução?
Com QThread talvez usando QThread::currentThreadId() dê para fazer algo não
portável... mas antes você tem que fazer um trabalho de mineração no código
fonte da Qt para saber o que tem no danado do Qt::HANDLE que esse método
retorna na plataforma que vc estiver usando... se a pthreads usar alguma
variável de ambiente para saber o tamanho da pilha que vai usar seria melhor
ainda.
> --~--~---------~--~----~------------~-------~--~----~
> C/C++ Brasil - http://www.cbrasil.org/
> Para sair dessa lista, envie um e-mail para
> ccppbrasil-...@googlegroups.com Para mais opções, visite
> http://groups.google.com/group/ccppbrasil
> -~----------~----~----~----~------~----~------~--~---
--
Hugo Parente Lima
"Precisamos de mais gênios humildes no mundo, hoje somos poucos!"
JID: hu...@jabber.org
[snip]
> > Vc já tentou ver quantas threads simultâneas vc consegue deixar em
> pseudo-execução?
> >
>
> Depende do workload, pois isso vai ditar qual vai ser a carga média do
> sistema. Quando o objetivo é maximizar o throughput do sistema o ideal é
> tunar para mantar o load o mais próximo do número de cpus lógicas do
> sistema*.
E o minimo de context switches possiveis.
> Para cargas que não dependem de IO e são puramente computacionais usar uma
> thread por core resolve. Porém se você for implementar algo no qual cada
> thread irá passar boa parte do tempo esperando, o número pode chega a uma
> centena sem degradar muito. Um servidor HTTP com uma aplicação web, por
> exemplo, não existe muito problema em uma uma centena de threads se a maior
> parte do tempo será gasta enviando/recebendo dados da rede e conversando com
> o banco de dados.
Nao existe problema em termos né. É um grande overhead desperdiçado,
nao vejo muito sentido em fazer algo desse tipo.
> Porém se você precisa lidar com centenas de conecções persistentes (um
> servidor de jabber, por exemplo) pode ser melhor usar algo como reactor com
> uma thread em listen e um pool tratando as que tem alguma mensagem.
Sou mais usar um Proactor, tanto pra jabber quanto pra HTTP. Eu mesmo
uso este pattern
através do asio para implementar um cliente de SMTP de alta performance.
> Isso tudo, claro, que se você não tem requisitos especiais como baixa
> latência ou consumo de memória.
Mesmo nao tendo requisto de pouca memória, desperdiça-la em 100
threads é na minha opiniao um pouco irresponsável.
> *Com SMT isso não é trivial porém.
SMT? Nao vejo menção a SMT no resto da thread. Perdi algo da discussao?
[]'s
2008/4/10 Rodrigo Kumpera <kum...@gmail.com>:
>
[snip]
E o minimo de context switches possiveis.
> > Vc já tentou ver quantas threads simultâneas vc consegue deixar em
> pseudo-execução?
> >
>
> Depende do workload, pois isso vai ditar qual vai ser a carga média do
> sistema. Quando o objetivo é maximizar o throughput do sistema o ideal é
> tunar para mantar o load o mais próximo do número de cpus lógicas do
> sistema*.
Nao existe problema em termos né. É um grande overhead desperdiçado,
> Para cargas que não dependem de IO e são puramente computacionais usar uma
> thread por core resolve. Porém se você for implementar algo no qual cada
> thread irá passar boa parte do tempo esperando, o número pode chega a uma
> centena sem degradar muito. Um servidor HTTP com uma aplicação web, por
> exemplo, não existe muito problema em uma uma centena de threads se a maior
> parte do tempo será gasta enviando/recebendo dados da rede e conversando com
> o banco de dados.
nao vejo muito sentido em fazer algo desse tipo.
Sou mais usar um Proactor, tanto pra jabber quanto pra HTTP. Eu mesmo
> Porém se você precisa lidar com centenas de conecções persistentes (um
> servidor de jabber, por exemplo) pode ser melhor usar algo como reactor com
> uma thread em listen e um pool tratando as que tem alguma mensagem.
uso este pattern
através do asio para implementar um cliente de SMTP de alta performance.
Mesmo nao tendo requisto de pouca memória, desperdiça-la em 100
> Isso tudo, claro, que se você não tem requisitos especiais como baixa
> latência ou consumo de memória.
threads é na minha opiniao um pouco irresponsável.
SMT? Nao vejo menção a SMT no resto da thread. Perdi algo da discussao?
> *Com SMT isso não é trivial porém.
[]'s
[snip]
> >
> > Nao existe problema em termos né. É um grande overhead desperdiçado,
> > nao vejo muito sentido em fazer algo desse tipo.
>
> Eu vejo, é muito mais fácil programar de maneira síncrona. Escrever um
> programa usando
> thread-per-socket é muito mais fácil, rápido e confiável que outro usando
> qualquer outra
> técnica de I/O.
Nao concordo completamente. Utilizar multi-threading incorre muitos
outros problemas também, como
sincronizacao de recursos compartilhados. Com a ferramenta certa (asio
+ finite state machine) é muito facil
implementar utilizando asynchronous IO.
> Quando o tempo do processamento de cada requisição é grande (0.2s
> user+kernel time) o overhead de context switching
> com 100 threads é desprezível. Já fui pelos dois camínhos e num final
> abandonei a implementação.
Certamente em SMTP existe bastante context switching, é só contar quantos
comandos sao trocados antes de se fazer qualquer coisa útil, e ainda
tem o acesso a disco que
também deve ser feito assincronamente. Com certeza a versao com thread pool
nao escala tanto quanto utilizando asynchronous IO para acessos simultâneos.
> Minha experiência foi ao implementar um servidor de SMTP. A diferença do
> custo para implementár e dar manutenção usando thread-per-socket e proactor
> não se justifica, sai mais barato comprar mais hardware.
Sua experiencia foi certamente diferente da minha.
[snip]
> > Mesmo nao tendo requisto de pouca memória, desperdiça-la em 100
> > threads é na minha opiniao um pouco irresponsável.
>
> Irresponsável? Memória é estupidamente barato hoje em dia. 100 thread vão te
> custar uns 200Mb de ram no pior caso - que por sinal significa que o
> programa tem muitos outros problemas para usar ativamente 2Mb de stack!
> Ainda mais hoje que servidores com 4Gb de ram é perfeitamente normal.
4GB recebendo ou enviando mensagens de 200MB é pouquinho ;).
Esse argumento é o mesmo que os javeiros usam. E mesmo assim
usar programas java me incomoda muito. Só nao incomoda o desenvolvedor
eu presumo.
[snip]
> > SMT? Nao vejo menção a SMT no resto da thread. Perdi algo da discussao?
> >
> > []'s
>
>
> SMT em Symetric Multi Threading. Calcular o load ótimo na presença de SMT
> não é trivial já que duas ou mais threads no mesmo core passam a interferir
> no padrão de acesso a memória entre sí.
Ah sim. Valeu pela clarificação.
> > Nao existe problema em termos né. É um grande overhead desperdiçado,Nao concordo completamente. Utilizar multi-threading incorre muitos
> > nao vejo muito sentido em fazer algo desse tipo.
>
> Eu vejo, é muito mais fácil programar de maneira síncrona. Escrever um
> programa usando
> thread-per-socket é muito mais fácil, rápido e confiável que outro usando
> qualquer outra
> técnica de I/O.
outros problemas também, como
sincronizacao de recursos compartilhados. Com a ferramenta certa (asio
+ finite state machine) é muito facil
implementar utilizando asynchronous IO.
Certamente em SMTP existe bastante context switching, é só contar quantos
> Quando o tempo do processamento de cada requisição é grande (0.2s
> user+kernel time) o overhead de context switching
> com 100 threads é desprezível. Já fui pelos dois camínhos e num final
> abandonei a implementação.
comandos sao trocados antes de se fazer qualquer coisa útil, e ainda
tem o acesso a disco que
também deve ser feito assincronamente. Com certeza a versao com thread pool
nao escala tanto quanto utilizando asynchronous IO para acessos simultâneos.
Sua experiencia foi certamente diferente da minha.
> Minha experiência foi ao implementar um servidor de SMTP. A diferença do
> custo para implementár e dar manutenção usando thread-per-socket e proactor
> não se justifica, sai mais barato comprar mais hardware.
[snip]
4GB recebendo ou enviando mensagens de 200MB é pouquinho ;).
> > Mesmo nao tendo requisto de pouca memória, desperdiça-la em 100
> > threads é na minha opiniao um pouco irresponsável.
>
> Irresponsável? Memória é estupidamente barato hoje em dia. 100 thread vão te
> custar uns 200Mb de ram no pior caso - que por sinal significa que o
> programa tem muitos outros problemas para usar ativamente 2Mb de stack!
> Ainda mais hoje que servidores com 4Gb de ram é perfeitamente normal.
Esse argumento é o mesmo que os javeiros usam. E mesmo assim
usar programas java me incomoda muito. Só nao incomoda o desenvolvedor
eu presumo.
Falei no código fonte da QThread, não no cabeçalho da pthread, a QThread (no
Linux) é só um wrapper para a pthread, por isso esse método
QThread::currentThreadId() pode ser que retorne um handler ou coisa parecida
que você possa utilizar nas funções da pthread... eu sempre usei apenas
bibliotecas de thread mais alto nível e com interfaces bonitinhas for
dummies, por isso não sei se posso ajudar em qualquer coisa que lide
diretamente com a pthread... visto que eu só a utilizei indiretamente (via
QThread por exemplo).
[snip]
> Me corrija se estiver errado, mas mesmo usando AIO você tem os mesmos
> problemas de multi-threading se quiser escalar para múltiplos cores.
Sim, certamente. Mas para programas networking a utlização de CPU será minima.
Muitas vezes nem necessitando utilizar mais de um core.
> Porém
> concordo contigo, escrever programas multi-threaded com C ou C++ é um raro
> tipo de tortura que deve ser evitado.
Lol.
> Certamente usar AIO com uma FSM vai
> ser mais escalável, porém em alguns casos isso é otimizar as partes que não
> são o hotspot do programa.
Acredito que isto nao é o caso de ums servidor. Se alguém precisa de
mais de 350 threads
acredito que seja para manter 350 jobs diferentes e simlutâneos. AIO
beneficiaria *muito*
este caso de uso me parece.
> Ser 2x mais eficiente em 10% do programa só vai
> tornar o programa 5% mais rápido.
Com certeza.
> Como falei, o importante é avaliar a
> necessidade e os requisitos a serem implementados.
Concordo. Mas nao consigo ver como uma aplicação pode se beneficiar de
350 threads de forma alguma.
> Quer um exemplo? Qualquer solução com AIO tem latência maior e eficiência
> menor que thread-per-socket. Os SOs modernos não conseguem fazer
> zero-copy-txer com aio assíncrona ou não bloqueante na maioria dos casos.
> Isso, claro, se tivermos menos sockets que cores. ;)
Nem conseguem fazer zero-copy pra bloqueante. É necessário usar mmap, AFAIK.
[snip]
> Você parou para fazer as contas? Provavelmente não. Vou umar o linux como
> exemplo.
> Usando uma thread por socket, cada uma usar 1 timeslice por comando, serão 3
> context
> switches por email enviado (MAIL TO, RCPT TO e DATA). Um context switch no
> linux
Acho que sua conta está errada.
Para cada email é necessário EHLO, MAIL FROM, RCPT TO, DATA, leitura
dos dados do HD,
os próprios dados, muitas vezes sem sao necessários mais de um envio
para os dados
por falta de buffers, o ponto CRLF.CRLF e opcionalmente o QUIT.
Isso sao 7 context switches por mensagem.
> usa aproximadamente 2500 ciclos. Para um sistema que aceita mil emails por
> segundo,
2500*7 = 17500.
Com 17500 ciclos o custo de receber ou enviar o email está em maior
parte nos context switches.
Podemos ter assim a CPU como limitante, o que é completamente
desnecessário se fosse
utilizado um design melhor desde o início.
É por isso que programas feitos com AIO costumam ter utilizacao de CPU
minuscula, muitas
vezes imperceptível. Isto pra mim acrescenta em muito na qualidade do software.
> isso são 1000 * 2500 * 3, ou 7.5Mhz. Com uma CPU de 2.4Ghz isso são 0.3% de
> economia.
>
> Ainda assim, supondo que vamos ter melhor afinidade de cache e isso vai
> aumentar em dez vezes
> o ganho, são só 3%! Desculpa, mas todo tem algo melhor para fazer que ficar
> se esfolando com AIO
> para ganhar só 3% de performance.
Com 350 threads acredito que o cache thrashing vai ser insano. E bem possivel
que ao inves de 10 vezes, chegue a 100 vezes pior. E nao para o codigo
de context switch.
> Seja AIO ou multiplexação, só tem vantagem sobre thread-per-socket se for
> para lidar com um número muito grande de
> conecções. Nos outros casos a diferença vai ser irrisória entre os dois
> modelos.
Que acredito ser o caso de qualquer um querendo utilizar mais de 350 threads.
> Mensagens de 200Mb? Quem falou em mensagens? Eu falei que o custo de subir
> 100 threads
> não passa de 200Mb no total.
O que eu quis dizer é que você estava presumindo uma utilização minima
de memória para o resto do software, o que
pode nao ser verdade. Isto ocorre se você estiver precisando processar
mensagens grandes in-memory, como por exemplo
com várias mensagens de 200MB.
Porém, 200MB de memória é bastante memória pra ser desperdiçada mesmo
em uma máquina de 4GB.
E utilizando-a somente pra ocupar espaço *é* puro desperdício. Se
estivesse utilizando com algo útil
eu nao discutiria, mas ter 200MB pra só ficar lá sentado esperando é
uma desconsideração com o usuário, IMHO.
Se todo software decidisse fazer isto, eu nao conseguiria rodar nada
nem na minha máquina de 8GB de memória.
> Esse argumento de que o que importante é performance é uma das coisas que
> mais me
> incomoda no povo que usa C++, parece que não existe outra bandeira para
> defender. Eu acredito
> que todo programador tem que ser pragmático, tem que ser da maneira que
> melhor atender os
> propósitos daquilo que estiver fazendo.
Acredito que você me interpretou mal. Nunca irei defender a utilizacao
de asynchronous
IO em um cliente de FTP de console por exemplo. Mas utilizar mais de 350 threads
em um processo é pra mim um *forte* indicativo de que o projeto está
*mal feito*.
> Trocar performance por entregar mais
> cedo é o
> exemplo mais comum disso. Tem que aceitar que usar sua linguagem preferida
> pode não
> ser a ferramenta ideal para resolver o problema em questão.
Dúvido que o Fernando considere C++ uma linguagem inapropriada, se achasse
ele provavelmente nao teria enviado uma mensagem para este grupo.
> []'s
> Rodrigo
[snip]
> IMHO, sobre o Boost::ASIO eu concordo com o Kumpera, ele é um recurso
> interessante
Boost.Asio é uma biblioteca de I/O. Só possui networking até agora,
mas serve tanto
pra asynchronous IO quanto synchronous IO.
> mas o modelo thread-per-socket é sempre mais saudável e
> oferece desempenho melhor,
Eu discordo quanto a parte saudável, o IO é inerentemente assíncrono.
Mas concordo que
nao é tão straightforward de inicio este modelo. Mas a biblioteca asio
tenta tornar o uso
de asynchronous IO tao simples quanto synchronous IO. Um pouco mais
prolixo porém.
> mas quando os recursos do hardware "carecem" o
> software padece e aí lançar mão do ASIO pode ser uma grande sacada.
É.
> [ ]s
>
> Amanda
2008/4/20 Fernando Gomes <fer...@googlemail.com>:
--