O que constitui uma unidade de tempo na análise de tempo de execução?

8

Ao calcular a dependência do tempo de execução da entrada, quais cálculos são considerados? Por exemplo, acho que aprendi que a indexação de array e as instruções de atribuição não são contadas, por que isso?

Rafael
fonte

Respostas:

6

Ao fazer cálculos de complexidade, geralmente usamos o modelo de RAM . Neste modelo, assumimos que a indexação da matriz é O (1). A declaração de atribuição é como atribuir algum valor a alguma variável na matriz de variáveis . Isto é apenas por conveniência. Simplifica a análise do algoritmo. No mundo real, a indexação de array leva O (log I) onde I é o número de coisas indexadas.

Geralmente consideramos coisas que dependem do tamanho da entrada, por exemplo, loops. Mesmo se houver operação O (1) no loop e for executada n vezes, o algoritmo será executado pelo tempo O (n).

Mas a operação O (1) fora do loop leva apenas tempo constante e O (n) + O (1) = O (n).

Leia sobre o algoritmo de classificação de radix no CLRS.

Pratik Deoghare
fonte
E quanto a incrementos em um loop? Esses devem ser O (n), certo?
for (int k = 0; k <N; k ++) {soma = soma + valores [k];} É o código em questão. Dizia-se que fazia 3N + 2 ligações.
Não. Para soma = soma + valores [k], + é O (1) e = também é O (1). Mas o loop executa O (N) vezes . Então é O (N) * O (1 + 1) = O (N). O (3N + 2) chama é apenas O (N).
Pratik Deoghare
Mas por que são chamadas O (3N + 2)?
O valor de acesso [k] é 1 chamada. + é 1 chamada. = é 1 chamada. Isso explica 3 chamadas feitas N vezes, mas eu não sei sobre +2.
Pratik Deoghare
5

O objetivo final é "tempo de execução em segundos" ou mais geralmente (desconsiderando os recursos modernos da CPU) "número de ciclos de clock". Acontece que isso é difícil de analisar e também é específico da máquina ou, pelo menos, do conjunto de instruções. Portanto, geralmente não é feito.

O próximo nível de abstração é contar com precisão todas as operações (de algum pseudocódigo no estilo de montagem), mantendo o custo da operação individual (em ciclos de clock) como parâmetros. Observe que essa análise é encontrada em "A arte da programação de computadores", de Knuth, entre outras. Portanto, certamente há um lugar para esse tipo de abordagem, mesmo que seja difícil e tenda a ser mais difícil na presença da hierarquia de memória.

Por último, mas não menos importante - e certamente mais proeminente - é a análise de operações dominantes, ignorando fatores constantes e as contribuições assintoticamente desaparecidas ("O-analysis "). O raciocínio é que o tempo de execução deve se comportar assintoticamente como o número de operações executadas com mais frequência, vezes algum fator, dependendo da implementação e da máquina reais. Esse tipo de análise produz resultados gerais que se aplicam a todas as máquinas (cobertas por RAM) e é mais fácil de executar do que o descrito acima, mas pode não ter especificidade.

Deixando para trás as estruturas "clássicas", muitos algoritmos são dominados pelo custo de memória e / ou comunicação, portanto, nesse caso, contar o número e o volume de memória considera as respectivas. transmissões de rede é razoável (e talvez suficiente).

Além disso, lembre-se de que muitas vezes não estamos tão interessados ​​no desempenho absoluto de um algoritmo, mas em compará-lo com outros. Isso também pode informar a escolha do parâmetro analisado.

Então você vê, não há uma resposta definitiva. Dependendo dos objetivos da análise em questão, diferentes respostas podem ser dadas.

Veja também a minha resposta aqui para alguns pensamentos relacionados, e a resposta de Sebastian no Quicksort, por exemplo.

Rafael
fonte
Não estou satisfeito em dizer que a abordagem mais importante que você menciona é totalmente coberta pelo modelo de RAM: o modelo de RAM geralmente não considera custos uniformes de multiplicação (a fim de manter a equivalência de problemas solucionáveis ​​pelas TMs no tempo poli com problemas solucionável por RAMs em poli-tempo). No entanto, a multiplicação é geralmente assumido que custar uma quantidade constante de tempo na análise de muitos algoritmos
Cornelius Marca
@cbra: Eu não encontrei um modelo de RAM com custo uniforme para tudo, menos a multiplicação. Em particular, não é necessário para a equivalência poli-tempo.
Raphael
Não sei se entendi direito, mas ao atribuir um custo uniforme à multiplicação, você pode calcular (assim, armazenar) o número 2(2n) no O(n)passos usando esquadrias repetidas.
Cornelius Marca
@cbra Você parece ter razão. O modelo de RAM na forma "pura" não oferece multiplicação como uma ação atômica, mas o implementa adicionando repetidamente. Portanto, o custo uniforme da multiplicação (e potencialmente outras operações) é "perigoso", pois quebra certas relações se aplicado a problemas em que o número se torna grande (ou seja, maior que a entrada (?)).
Raphael