O hardware / implementação afetará a complexidade de tempo / espaço dos algoritmos?


32

Eu nem sou estudante de CS, então essa pode ser uma pergunta estúpida, mas por favor, tenha paciência comigo ...

Na era pré-computador, só podemos implementar uma estrutura de dados de matriz com algo como uma matriz de gavetas. Como é necessário localizar a gaveta com o índice correspondente antes de extrair o valor, a complexidade de tempo da pesquisa de matriz é , assumindo a pesquisa binária.O(log(n))

No entanto, a invenção dos computadores fez uma grande diferença. Computadores modernos podem ler a partir de sua RAM tão rapidamente que agora consideramos a complexidade de tempo da pesquisa em array como (mesmo que tecnicamente não seja o caso, porque leva mais tempo para mover o registro por uma distância maior, etc.)O(1)

Outro exemplo são os dicionários Python. Embora se possa obter uma complexidade de acesso ao dicionário de com um método mágico sobrecarregado mal escrito (ou ridiculamente azarado, isto é, chaves com muitas colisões de hash), geralmente é considerado . Nesse caso, a complexidade do tempo depende da implementação da tabela de hash dos dicionários Python e da implementação das chaves das funções de hash.O(n)__hash__O(1)

Isso implica que o hardware / implementação pode afetar a complexidade do tempo dos algoritmos? (Embora os dois exemplos sejam sobre estruturas de dados em vez de algoritmos, os últimos são criados sobre a primeira e nunca ouvi falar da complexidade temporal das estruturas de dados, por isso estou usando o termo "algoritmos" aqui)

Para mim, os algoritmos são abstratos e conceituais, cujas propriedades como a complexidade do tempo / espaço não devem ser afetadas se elas são implementadas de uma maneira específica, mas são?


Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Gilles 'SO- parar de ser mau'

Respostas:


42

Certo. Certamente. Veja como conciliar seu desconforto.

Quando analisamos o tempo de execução dos algoritmos, fazemos isso com relação a um modelo específico de computação . O modelo de computação especifica coisas como o tempo que leva para executar cada operação básica (é uma consulta de matriz ou O ( 1 ) ?). O tempo de execução do algoritmo pode depender do modelo de computação.O(logn)O(1)

Depois de escolher um modelo de computação, a análise do algoritmo é um exercício puramente abstrato, conceitual e matemático que não depende mais do hardware.

No entanto, na prática, geralmente queremos escolher um modelo de computação que reflita a realidade de nosso hardware - pelo menos em um grau razoável. Portanto, se o hardware mudar, podemos decidir analisar nossos algoritmos sob um modelo de computação diferente, mais apropriado ao novo hardware. É assim que o hardware pode afetar o tempo de execução.

A razão pela qual isso não é óbvio é porque, nas aulas introdutórias, geralmente não falamos sobre o modelo de computação. Apenas fazemos implicitamente algumas suposições, sem torná-las explícitas. Isso é razoável, para fins pedagógicos, mas tem um custo - esconde esse aspecto da análise. Agora você sabe.


Como você disse, usamos o modelo de acesso aleatório como modelo de computação, mas quando usamos a GPU para certos cálculos, a complexidade do tempo para alguns algoritmos muda conforme ele usa as instruções do SIMD.
Deep Joshi

6
Observe também que a notação O () é um limite superior. Mesmo se você usar a analogia da gaveta, encontrar uma gaveta em um tamanho limitado (a memória real é limitada em tamanho) o edifício leva tempo O (1). Mesmo que você leve 20 minutos para chegar à gaveta mais distante (todo o cache falha e você ainda precisa carregar os dados do swap), ainda é tempo O (1), porque 20 minutos serão sua constante oculta para acessar a memória.
Goswin von Brederlow

2
O(1)O(n)

1
@CortAmmon: Mesmo em uma grande variedade, o uso da pesquisa linear pode ser mais rápido do que o uso de um mapa de hash, se todos, exceto alguns dos elementos pesquisados, estiverem muito próximos do início. Por exemplo, se 50% dos elementos corresponderem ao primeiro elemento, 25% corresponderem ao segundo, 12,5% corresponderem ao terceiro, etc., exceto que um elemento ímpar corresponderá a algo que pode estar em qualquer lugar da matriz, o número esperado de comparações para realizar M pesquisas em uma lista de tamanho N seria 2M + N.
Supercat

5
As instruções do @DeepJoshi SIMD não alteram a complexidade dos algoritmos. Eles apenas alteram a constante multiplicativa.
Gilles 'SO- stop be evil'

5

Eu acho que há um mal-entendido fundamental na questão. Você compara uma pessoa que encontra um objeto em uma lista classificada (por exemplo, uma página específica de um livro, dado seu número) com um computador que procura um item de uma matriz.

O(registron)O(1)

Portanto, sim, o hardware (ou seja, o modelo de computação) afeta o tempo de execução dos algoritmos, como explica o DW , mas não é nisso que o seu exemplo de acesso ao array parece se basear.


2
Para ser justo, você pulou todas as partes entre "o controlador de memória define as tensões nos fios de endereço para a representação binária de dezessete" e "os dados retornam". Uma dessas peças quase certamente é uma árvore de pesquisa binária do tipo descrito pelo OP; mas, no entanto, é executado em tempo constante porque o log n é aproximadamente 64, para todos os n .
Quuxplusone

@Quuxplusone Que parte da memória usa pesquisa binária? As linhas de endereço selecionam diretamente as células da memória.
David Richerby

Estamos operando muito longe da minha área de especialização, mas o que eu estava tentando sugerir é que um decodificador de endereço será implementado em termos de uma árvore de desmotivadores . (Supondo que estamos atingindo diretamente a memória física, ignorando qualquer complicação extra que vem com o armazenamento em cache .) Novamente, toda essa complicação extra acrescenta apenas O(lg size-of-memory), isto é, insignificante - mas é exatamente isso que o OP estava perguntando!
Quuxplusone

2

Não, o hardware não afeta a complexidade dos algoritmos.

Mas isso afeta a escolha do algoritmo e pode afetar a utilidade da análise de complexidade a um ponto em que a análise se torna praticamente sem sentido (ou apenas de interesse acadêmico).

Encontrar a gaveta direita (como acessar um elemento da matriz) usa o algoritmo "aberto enésimo elemento diretamente pelo índice", não o algoritmo "pesquisar linearmente" ou "fazer pesquisa binária". Os algoritmos não são alterados, mas a escolha.

Por outro lado, a própria análise de complexidade, ou melhor, sua significância, é afetada grandemente pelo hardware.

Muitos algoritmos estelares por sua análise de complexidade são de baixo desempenho ou até inúteis na prática, porque o fator constante insignificante não é de todo insignificante, mas dominante .

Ou porque suposições que antes eram verdadeiras (ou na maior parte verdadeiras) não são mais válidas. Por exemplo, toda operação é basicamente a mesma (apenas pequenas diferenças constantes que não importam) ou não faz diferença quais locais de memória você acessa em que ordem. Pela análise da complexidade, você pode concluir que algum algoritmo é muito superior, pois só precisa de tantas e muitas operações. Na prática, você pode achar que cada operação causa uma falta de cache garantida (ou pior ainda, falha de página), que introduz um k tão grande que não é mais insignificante, mas domina tudo.
Se o algoritmo A leva 500 operações para processar um conjunto de dados de um determinado tamanho e o algoritmo B leva apenas 5, mas B causa 5 falhas que queimam vinte milhões de ciclos cada, então, apesar do que a analise ou o bom senso podem lhe dizer, A é melhor.

Isso levou a surpresas engraçadas, como por exemplo, no Cuckoo Hashing, há alguns anos atrás. O que foi muito superior porque [longa lista de benefícios]. Após o hype esfriar, descobriu-se que era muito inferior porque garantia duas falhas de cache (falhas, para conjuntos de dados maiores) em todos os acessos.

Similar aconteceu com a identificação e processamento de subconjuntos de dados. Atualmente, a solução correta atualmente é: "faça tudo" , ou seja, em vez de descobrir o que você precisa avaliar e fazer isso, processe o conjunto de dados completo linearmente, mesmo que você precise apenas metade dele. Porque, acredite ou não, isso é mais rápido devido a erros de previsão de ramificação, falta de cache, falhas de página.
Precisa ler os primeiros 8kB e os últimos 3kB de um arquivo de 3MB? Bem, leia o arquivo completo e jogue fora o que você não quer, porque procurar no meio será dez vezes mais lento do que apenas ler a coisa completa.

Use um mapa porque possui complexidade logarítmica? Ou uma tabela de hash, que tem tempo de acesso constante? Constant parece incrível. Bem, para qualquer coisa com menos de mil coisas (dependendo do hardware, tamanho dos dados e padrão de acesso), uma pesquisa linear pode ser tão boa ou melhor. Surpresa.

Portanto, não são os algoritmos per se que são afetados, mas sua utilidade e escolha.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.