Linux e prioridade de threads

28 views
Skip to first unread message

Wander Lairson

unread,
Nov 24, 2009, 7:13:42 AM11/24/09
to ccppb...@googlegroups.com
Bom dia à todos,

Seguinte, estou querendo fazer com que a thread principal de um
programa Linux temporariamente execute apenas quando o processador
estiver em idle (ou pelo menos só quando minhas threads de mais alta
prioridade não estiverem rodando).
Minha primeira tentativa foi mudar o sched policy das minhas threads
para SCHED_RR e dar prioridade 1 para todas.
Neste caso, esperava que a thread principal (que a princípio seria
SCHED_OTHER) só rodasse quando as outras estivessem bloqueadas. Mas a
filha da mãe continua sendo agendada e roubando CPU das threads
prioritárias. Depois tentei mudar o sched
policy da thread principal e dar prioridade 1, e, para as outras mais
importantes, prioridade 2. Mesma coisa.

Abaixo o trecho de código da minha segunda tentativa:

pthread_attr_t attr;
struct sched_param param, default_param;
int policy;

pthread_attr_init(&attr);
ASSERT(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0);
ASSERT(pthread_attr_setschedpolicy(&attr, SCHED_RR) == 0);
ASSERT(pthread_attr_getschedparam(&attr, &param) == 0);
param.sched_priority = 2;
ASSERT(pthread_attr_setschedparam(&attr, &param) == 0);
ASSERT(pthread_getschedparam(pthread_self(), &policy, &param) == 0);
default_param = param;
param.sched_priority = 1;
ASSERT(pthread_setschedparam(pthread_self(), SCHED_RR, &param) == 0);
ASSERT(pthread_create(&thread, &attr, thrd_Initialize, this) == 0);

Alguém por acaso sabe o que está errado no meu conceito?

Obrigado pela ajuda que eu sei que virá (com muita fé, irmão), rsrsrsrsrsrs
Wander

Gianni

unread,
Nov 24, 2009, 7:26:10 AM11/24/09
to ccppb...@googlegroups.com
On Tuesday 24 November 2009 10:13:42 Wander Lairson wrote:
> Neste caso, esperava que a thread principal (que a princípio seria
> SCHED_OTHER) só rodasse quando as outras estivessem bloqueadas. Mas a
> filha da mãe continua sendo agendada e roubando CPU das threads
> prioritárias.
Vc está se baseando em uma suposição errada. O kernel vai tentar vai qu TODAS
as threads rodem SEMPRE. Não confunda prioridade com exclusividade. Estes
parâmetros informam ao kernel como distribuir o uso do CPU; e não indicam nada
quando uma thread *pode* rodar.

O que você precisa fazer é usar signals/mutex/conditions/etc para fazer isso.
Faça uma thread ficar em sleep esperando uma condição que será atingida quando
todas as outras threads sinalizarem.

wander

unread,
Nov 24, 2009, 8:03:52 AM11/24/09
to ccppbrasil
Hum.. Pelo que eu tinha entendido da documentacao que eu olhei, as
threads que rodam com policy SCHED_RR sempre tem prioridade sobre as
SCHED_OTHER (isso no escopo de processo, que eh o que me interessa,
escopo de sistema nao cheguei a olhar). Logo Kernel so olha para a
fila de threads no policy SCHED_OTHER quando todas threads com policy
SCHED_RR estiverem dormindo... Mas nao eh o que esta acontecendo...

Quanto a parte de controlar o processamento com primitivas de
sincronizacao, alem de eu nao poder por que o codigo da thread
principal nao estar sobre meu controle depois da criacao das threads
secundarias, isso ainda iria de encontro com a minha intencao, que eh
usar tempo vago da CPU para otimizar o processo e inicializacao. Por
isso tenho que resolver no scheduler...

Rodrigo Kumpera

unread,
Nov 24, 2009, 8:12:32 AM11/24/09
to ccppb...@googlegroups.com
Você não verificou o valor de retorno de nenhuma função, certo?

Digo isso pq SCHED_RR exige algumas permissões que um usuário comum não tem.



2009/11/24 Wander Lairson <wander....@gmail.com>

Gianni

unread,
Nov 24, 2009, 8:15:42 AM11/24/09
to ccppb...@googlegroups.com
On Tuesday 24 November 2009 11:03:52 wander wrote:
> Hum.. Pelo que eu tinha entendido da documentacao que eu olhei, as
> threads que rodam com policy SCHED_RR sempre tem prioridade sobre as
> SCHED_OTHER (isso no escopo de processo, que eh o que me interessa,
> escopo de sistema nao cheguei a olhar). Logo Kernel so olha para a
> fila de threads no policy SCHED_OTHER quando todas threads com policy
> SCHED_RR estiverem dormindo... Mas nao eh o que esta acontecendo...
Hmm... acho que estamos então falando de coisas diferentes. De qual versão de
kernel você está falando? Posso estar enganado, mas acho que esse
comportamento que você descreve para o SCHED_RR se aplica a kernéis antigos
(pré 2.6).

Veja se o que está em 'man 2 sched_setscheduler' corresponde ao que você leu.

wander

unread,
Nov 24, 2009, 8:21:11 AM11/24/09
to ccppbrasil
Sim, verifiquei, e meu processo roda como root...

On 24 nov, 22:12, Rodrigo Kumpera <kump...@gmail.com> wrote:
> Você não verificou o valor de retorno de nenhuma função, certo?
>
> Digo isso pq SCHED_RR exige algumas permissões que um usuário comum não tem.
>
> 2009/11/24 Wander Lairson <wander.lair...@gmail.com>

wander

unread,
Nov 24, 2009, 8:22:17 AM11/24/09
to ccppbrasil
Meu kernel eh 2.6, vou dar uma olhada na man page.... Valeu pela dica.

Rodrigo Mizobe

unread,
Nov 24, 2009, 7:31:44 AM11/24/09
to ccppb...@googlegroups.com


2009/11/24 Gianni nasus....@gmail.com



O que você precisa fazer é usar signals/mutex/conditions/etc para fazer isso.
Faça uma thread ficar em sleep esperando uma condição que será atingida quando
todas as outras threads sinalizarem.
 
Mas parece que o Wander deseja que a thread principal se desbloqueie assim que todas as outras threads se bloqueiam... Como não há ordem, a solução seria um segundo semaforo para verificar se todas estao bloqueadas, e um daemon para um wakeup?(dúvida)
 
Regards,
Rodrigo Mizobe

wander

unread,
Nov 24, 2009, 8:43:32 AM11/24/09
to ccppbrasil
Na verdade a thread principal nao bloqueia, apenas as atividades das
outras threads sao mais prioritarias.
Atualmente, a thread principal voltar a rodar quando todas as outras
finalizam seus trabalhos. Mas neste meio
tempo, existe CPU ociosa quando todas as threads estao esperando I/O.
Eu queria usar esse periodo ocioso
na thread principal, mas sem roubar CPU das threads mais prioritarias,
para otimizar o tempo de inicializacao do
programa.

On 24 nov, 21:31, Rodrigo Mizobe <m1z...@gmail.com> wrote:
> 2009/11/24 Gianni nasus.maxi...@gmail.com

Ronaldo Faria Lima

unread,
Nov 24, 2009, 9:06:39 AM11/24/09
to ccppb...@googlegroups.com
Olá, Wander.

Eu sou da mesma opinião do David Butenhof, criador das threads posix:
não mexa na prioridade nem no scheduling das threads, a não ser que
isso seja extremamente necessário para o sistema operacional no qual
você está operando - a exemplo do Solaris 6 que exige que você mude a
política de scheduling manualmente sob risco de ter as threads
executando sequencialmente.

Eu não consegui entender bem o cenário do seu problema, visto que você
focou-se na questão do scheduling das threads. Pelo pouco que você
descreveu, você tem uma thread principal que dispara diversas outras
que executam tarefas de inicialização.O que não entendi é a
dependência entre as suas threads: as tarefas, depois de completadas,
alimentam com dados alguma outra parte do seu processo?

O entendimento do Rodrigo Mizobe foi mais ou menos o meu entendimento.
Aparentemente você precisa rever o design da sua aplicação. Seria
interessante se você descrevesse um pouco melhor, do ponto de vista
funcional, a função das threads.

Abraços,

Ronaldo

2009/11/24 wander <wander....@gmail.com>:

Rodrigo Mizobe

unread,
Nov 24, 2009, 4:29:52 PM11/24/09
to ccppb...@googlegroups.com


2009/11/24 wander <wander....@gmail.com>


Na verdade a thread principal nao bloqueia, apenas as atividades das
outras threads sao mais prioritarias.
Se ela não bloqueia, mesmo com baixa prioridade, ela tera um slice da cpu... Ou seja, se as threads estivem bloqueadas por estarem executando I/O, a thread principal estará sendo executada, a menos que esteja bloqueada tbm....
 
Atualmente, a thread principal voltar a rodar quando todas as outras
finalizam seus trabalhos. Mas neste meio
tempo, existe CPU ociosa quando todas as threads estao esperando I/O.
Eu queria usar esse periodo ocioso
na thread principal, mas sem roubar CPU das threads mais prioritarias,
para otimizar o tempo de inicializacao do
programa.
Posso não estar compreendendo bem o cenário, mas há uma incoerência ao dizer que a thread não está bloqueada, e posteriormente afirmar que ela só volta a executar após o termino das outras threads, e que há cpu ociosa....
 
Regards,
Rodrigo Mizobe

P.

unread,
Nov 24, 2009, 4:50:22 PM11/24/09
to ccppbrasil
On 24 nov, 19:29, Rodrigo Mizobe <m1z...@gmail.com> wrote:

> > Atualmente, a thread principal voltar a rodar quando todas as outras
>
> finalizam seus trabalhos. Mas neste meio> tempo, existe CPU ociosa quando todas as threads estao esperando I/O.
> > Eu queria usar esse periodo ocioso
> > na thread principal, mas sem roubar CPU das threads mais prioritarias,
> > para otimizar o tempo de inicializacao do
> > programa.
>
> Posso não estar compreendendo bem o cenário, mas há uma incoerência ao dizer
> que a thread não está bloqueada, e posteriormente afirmar que ela só volta a
> executar após o termino das outras threads, e que há cpu ociosa....

O cenário parece simples.
O requisito é: o escalonador deve entregar um timeslice a um thread de
baixa prioridade apenas se, e somente se, não houver uma thread de
alta prioridade competindo por timeslices.

--
P.

wander

unread,
Nov 24, 2009, 5:20:38 PM11/24/09
to ccppbrasil
Rapaz, queria ter essa capacidade de dar uma explicacao simples
dessa... rs
Eh exatamento isso... Quanto aquelas questoes de rever design, mexer
em prioridade etc...
O que estou fazendo eh uma otimizacao do produto (muito importante por
sinal), em cima de
uma arquitetura que ja existe, nao existe problemas de design, mas
estou tentando expremer um pouco
mais o limao pra ver se sai mais caldo. Eu nao posso ficar detalhando
muito porque os caras da empresa
sao muito chatos (eu mesmo nao veria problema em abrir o que estou
fazendo, mas nao sou o dono
da empresa).

Obrigado pela ajuda de todos,
Wander

Rodrigo Mizobe

unread,
Nov 24, 2009, 5:20:58 PM11/24/09
to ccppb...@googlegroups.com

 
O cenário parece simples.
O requisito é: o escalonador deve entregar um timeslice a um thread de
baixa prioridade apenas se, e somente se, não houver uma thread de
alta prioridade competindo por timeslices.
Sim, mas o nivel de prioridade foi uma solução proposta pelo Wander para designar
tempo de CPU para a thread principal apenas se as outras threads estivessem bloqueadas.
Nisto se baseia minha dúvida, que foi reportada acima, se o desejo é de que a thread principal não
consuma recurso da CPU em detriemento das demais threads, porque não utilizar um semáforo para 
sincronismo baseado em condições.... Essa seria uma outra proposta, pelo visto, pegamos uma tentiva de 
solução do problema(nivel diferentes de prioridades-Wander), e transformamos no alvo de análise.
 
Perdão pelo post grande...
 
Regards,
Rodrigo Mizobe 
--
 P.

Gianni

unread,
Nov 24, 2009, 5:29:16 PM11/24/09
to ccppb...@googlegroups.com
Então, minha dúvida sobre isso é: todos os posts (incluindo o original) considera só uma lista de prioridade.  Assim, se nesta lista há threads SHED_RR nenhum thread SCHED_OTHER será executado.  Porém, eu não sei se o que vou falar é verdade ou não, pode haver uma lista por CPU. Se seu processador é quad-core então serão 4 listas.  Em um core pode haver um SCHED_RR rodando e em outro não há nenhum, logo um SCHED_OTHER rodará.  Em qual CPU cada thread roda não é determinístico.  Se essa suposição for verdade, então explicaria por que o código postado teve o resultado observado.  

Isso eu digo por ter lido algo em algum lugar, não me lembro aonde nem achei mais o texto, que era um comportamento que tinha mudado em alguma versão do Kernel (2.6?).

Isso tudo que falei é palpite de quem não sabe bem o que ta falando... :-)



Gianni Rossi

unread,
Nov 24, 2009, 5:52:34 PM11/24/09
to ccppb...@googlegroups.com
2009/11/24 Gianni <nasus....@gmail.com>

ps: se por acaso eu falei algo que faz sentido, haveria um teste para saber se é essa a causa dos sintomas do paciente: recompile seu kernel deshabilitando o SMP, ou seja, force o kernel a só usar 1 CPU.  Então, rode o programa do jeito que você havia descrito originalmente.  Se funcionar como vc queria, terá seu diagnóstico! (sim, estava assistindo House qdo escrevi isso ;-) )
 

wander

unread,
Nov 24, 2009, 6:16:00 PM11/24/09
to ccppbrasil
Não, o sistema só roda em um único core. To vendo que o problema é bem
mais complicado do que eu imaginava...

Wander

On Nov 25, 7:52 am, Gianni Rossi <nasus.maxi...@gmail.com> wrote:
> 2009/11/24 Gianni <nasus.maxi...@gmail.com>

Ronaldo Faria Lima

unread,
Nov 24, 2009, 6:28:35 PM11/24/09
to ccppb...@googlegroups.com
Olá, Wander.

O fato é que a sua mensagem original ficou suficientemente vaga para
meu entendimento andar para o lado do design. Enfim, opinião de sapo
de fora. Afinal, você, melhor do que ninguém, sabe onde o sapato
aperta.

Mas já que você está fazendo uma otimização do produto e não
desenvolvendo uma solução nova, que foi o meu entendimento inicial,
pergunto-lhe o seguinte: você já verificou a complexidade, alcance e
estruturas que repetem-se durante o tempo de execução do seu sistema?
Normalmente a otimização ocorre nessas estruturas antes de você chegar
a um nível tão baixo a ponto de olhar scheduling de threads.

Eu tenho alguma experiência no assunto e gostaria de compartilhá-la.
Sempre que precisava otimizar um software, a primeira coisa a fazer é
determinar qual rotina precisa realmente de otimização. Funções que
são acionadas algumas dezenas de milhares de vezes são uma boa dica.
Se a sua aplicação faz muito acesso ao banco de dados, é bom tentar
otimizar esses acessos, seja melhorando a estrutura das buscas, seja
minimizando os hits no banco de dados com relação às estruturas de
dados relativamente estáticas. Já vi processos que duravam mais de 45
minutos serem otimizados para menos de 3 segundos por conta de ajustes
nos acessos ao banco de dados.

É importante olhar a complexidade das funções que são muito CPU bound,
por exemplo as funções que executam muitas operações de busca em
memória. Uma boa é analisá-las pela notação O. Isso pode lhe dar uma
pista se o algoritmo implementado pela função é adequado para o volume
de dados que ela trata ou não.

Excesso de I/O também pode ser otimizado, principalmente com relação à
dados de referência que existem em disco. Dicionários em memória
normalmente são uma boa opção para esses casos. Outro ponto que acaba
com a performance é a alocação e a desalocação de recursos. Se você
puder manter o recurso alocado, reaproveitando-o, melhor. Essa idéia
está muito presente na biblioteca STDC, nos alocadores de memória.

Uma idéia é você fazer o profiling da sua aplicação, uma thread por
vez. Isso lhe dará uma boa visão do que está comendo sua CPU durante a
execução do seu programa.

Otimização de software não é um trabalho trivial. Exige muita análise
e muito estudo do software em questão. E principalmente paciência e
cuidado. Afinal, a otimização do seu código não pode introduzir
defeitos no software.

Espero que tenha lhe ajudado de alguma maneira.
Abraços,

Ronaldo

2009/11/24 wander <wander....@gmail.com>:
>

P.

unread,
Nov 24, 2009, 7:35:45 PM11/24/09
to ccppbrasil
On 24 nov, 20:29, Gianni <nasus.maxi...@gmail.com> wrote:
> Então, minha dúvida sobre isso é: todos os posts (incluindo o original) considera só uma lista de prioridade.  Assim, se nesta lista há threads SHED_RR nenhum thread SCHED_OTHER será executado.  Porém, eu não sei se o que vou falar é verdade ou não, pode haver uma lista por CPU. Se seu processador é quad-core então serão 4 listas.  Em um core pode haver um SCHED_RR rodando e em outro não há nenhum, logo um SCHED_OTHER rodará.  Em qual CPU cada thread roda não é determinístico.  Se essa suposição for verdade, então explicaria por que o código postado teve o resultado observado.  
>

Encontrei na seguinte seção da especificação POSIX:

http://www.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_04_01

esta afirmação:

"The effect of scheduling threads with the SCHED_OTHER policy in a
system in which other threads are executing under SCHED_FIFO,
SCHED_RR, or SCHED_SPORADIC is implementation-defined."

Creio que POSIX não suporta o efeito desejado.
Realmente me parece muito confuso que alguns threads de um processo
sejam regidos por SCHED_FOO e outros por SCHED_BAR.
Por que não trocar a política de escalonamento do processo inteiro de
uma só vez?

--
P.

wander

unread,
Nov 25, 2009, 5:04:41 AM11/25/09
to ccppbrasil
Bem, analisando melhor o problema, e indo olhar os 2GB de código do
sistema, descobri que essas threads que eu dei alta prioridade vão,
indiretamente, criar outras threads (e esperar por elas), e essas sim,
estão competindo por CPU com a thread principal... Depois que muita
pesquisa, achei esse link: http://www.kernel.org/doc/man-pages/online/pages/man2/sched_setscheduler.2.html.
A partir do kernel 2.6.23, você tem o SCHED_IDLE, que faz exatamente o
que estou querendo. Obviamente (por Murphy), meu kernel é inferior ao
2.6.23...

Wander

On Nov 25, 9:35 am, "P." <pedro.lama...@member.fsf.org> wrote:
> On 24 nov, 20:29, Gianni <nasus.maxi...@gmail.com> wrote:
>
> > Então, minha dúvida sobre isso é: todos os posts (incluindo o original) considera só uma lista de prioridade.  Assim, se nesta lista há threads SHED_RR nenhum thread SCHED_OTHER será executado.  Porém, eu não sei se o que vou falar é verdade ou não, pode haver uma lista por CPU. Se seu processador é quad-core então serão 4 listas.  Em um core pode haver um SCHED_RR rodando e em outro não há nenhum, logo um SCHED_OTHER rodará.  Em qual CPU cada thread roda não é determinístico.  Se essa suposição for verdade, então explicaria por que o código postado teve o resultado observado.  
>
> Encontrei na seguinte seção da especificação POSIX:
>
>  http://www.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.ht...

Rodrigo Mizobe

unread,
Nov 25, 2009, 7:04:01 AM11/25/09
to ccppb...@googlegroups.com


2009/11/24 wander <wander....@gmail.com>



O que estou fazendo eh uma otimizacao do produto (muito importante por
sinal), em cima de
uma arquitetura que ja existe, nao existe problemas de design, mas
estou tentando expremer um pouco
mais o limao pra ver se sai mais caldo.
 
Perdão, então, estava pensando que você estava estruturando o desing da aplicação
 
Eu nao posso ficar detalhando
muito porque os caras da empresa
sao muito chatos (eu mesmo nao veria problema em abrir o que estou
fazendo, mas nao sou o dono
da empresa).
 
Regards,
Rodrigo Mizobe
Reply all
Reply to author
Forward
0 new messages