Ir ao conteúdo
  • Cadastre-se

Como criar delays de


Tranzorb

Posts recomendados

Saudações pessoal,

Gostaria de saber se algum dos colegas conhece uma forma de criar delays de microssegundos em programas de linguagem C. O windows, em suas APIs, provê a função SLEEP, e várias linguagens possuem em suas bibliotecas funções semelhantes. Mas o menor intervalo de tempo possível de se executar com essas rotinas é 1 milissegundo (equivalente a 1000 microssegundos).

Imagino que, trazendo ao conhecimento do programa a duração do ciclo de instrução da máquina, ele pode calcular a quantidade de ciclos que são executados durante 1 microssegundo... Mas como descobrir a duração do ciclo de instrução? O programa precisa ser portátil. Logo, ele sempre terá que medir esse valor no início de sua execução, para adaptar-se às diferentes máquinas em que será instalado.

Alguém poderia ajudar?

Desde já, agradeço a todos,

Tranzorb.

Link para o comentário
Compartilhar em outros sites

Olá sviola,

Essa, acredito, é a rotina mais usual para esse tipo de problema, e é uma das opções que estou cogitando e que até já tentei implementar.

O problema é que eu preciso conhecer a duração do ciclo de instrução da máquina para saber a quantidade de ciclos que meu loop deverá percorrer até que se passe 1 microssegundo.

Fora outros problemas que, acredito, precisarão ser contornados, como a distribução do tempo de processador, ou seja, penso que o tempo que o processador levará cuidando de outras tarefas manterá meu loop interrompido e terminará por somar tempo ao 1 microssegundo que desejo criar. Isso poderia ficar menos perceptível em delays maiores, mas, acredito que num de 1 microssegundo já é possível perceber deformações.

De qualquer forma, muito obrigado pela colaboração e aguardo mais idéias para a discussão.

Tranzorb.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Olha, loop com somas não é um modo adequado de fazer isso.

Desde o Pentium os processadores tem um contador do número de ciclos que é a forma mais rápida de se medir o tempo. Só precisa fazer uma calibração, para transformar o número de ciclos em tempo (que é descobrir o clock do processador).

O contador é acessado pela instrução rdtsc (assembler, mas alguns compiladores já tem ela implementada para a linguagem). você não disse qual é o compilador que irá usar e também não entendi se irá rodar apeans no Windows ou também em outros SO (você diz que ele tem que ser portátil).

Se for apenas em Windows, ao invés de você criar toda a medição com base na instrução rdtsc, você pode usar uma versão da API do Windows que usa essa instrução, porém ela não te dá a mesma precisão, mas é suficiente para o que você precisa, pois na pior das hipóteses a precisão é de 1 microsegundo (na minha máquina é de 0.3 microsegundos, varia conforme o processador). Eu descobri um falha nessa função para processadores P4 com mais de 4GHz, mas isso não veremos tão cedo e acho que a MS corrige até lá.

Então, procure no google pela por QueryPerformanceCounter e QueryPerformanceFrequency. Para chamar a função se perde alguns microsegundos (+/-5ms), mas acho que serve para o que você quer. Qualquer coisa, procure pela instrução rdtsc, que a penalidade dela é de apenas 80-200 ciclos do processador (da ordem de décimos de microsegundo) e a resolução é de nanosegundos.

Sempre depende do clock do processador.

Link para o comentário
Compartilhar em outros sites

Estou agora sem compilador pra testar mas acredito que a solução abaixo funcione independentemente de SO(ANSI C).

Teste assim:

(inclua a biblioteca time.h)

void wait ( int microseconds )

{

clock_t endwait;

endwait = clock () + microseconds*CLK_TCK/(1000000);

while (clock() < endwait) {};

}

//CLK_TCK é uma constante que guarda o numero de TICKS por segundo. com a qual //você não precisa se preocupar pois ela é interna da biblioteca.

//Dividi por 10^6 para que converter para numero de ticks por milissegundos.

ps.: essa é uma pequena modificação do código encontrado em:

http://www.cplusplus.com/ref/

que é um site bem legal com que tem também a documentação das bibliotecas da STDLIB

Abraços!

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

csilvano, esse dai não tem a precisão de microsegundos. Clock() tem resolução em torno de 10 ms.

Ai vai minha sugestão, para um com boa resolução:

Variáveis:


double start_time,clockrate;
static LARGE_INTEGER qw;

Funções:


void calibratetimer(void)
{
 QueryPerformanceFrequency(&qw);
 clockrate = (double)qw.QuadPart;
}
void starttimer(void)
{
QueryPerformanceCounter(&qw);
start_time = (1E6*(double)qw.QuadPart);
}

double readtimer(void)
{
 QueryPerformanceCounter(&qw);
 return ((1E6*(double)qw.QuadPart - start_time)/clockrate);  // tempo em microsegundos
}

Loop para aguardar o tempo que se quer aguardar:


calibratetimer();  // apenas a primeira vez, quando iniciar o processo
starttimer();
 while (readt()<tempoparaesperaremmicrosegundos)
 {   }

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
Postado Originalmente por csilvano@01 jan 2005, 21:03

Legal!

Tomara que funcione então.

Desculpem se me equivoquei com meu código... é que como eu tinha dito eu estou sem compilador para testar.

Abraços!

Ah não tem o que se desculpar. E foi bom você falar no compilador. Esse código eu já usei no Mingw. Precisa adicionar o windows.h, também esqueci de citar.

Acredito que funcione bem no compilador da MS e Intel também, sem modificar nada.

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...