Às vezes, ouço as pessoas dizerem que, devido à velocidade dos processadores e à quantidade de memória disponível, a eficiência e o tempo de execução do algoritmo não são, na prática, uma grande preocupação.
Mas imagino que ainda existam áreas em que essas considerações continuam sendo de suma importância. Dois que vêm à mente estão na negociação algorítmica, onde milhares de transações devem ser conduzidas em frações de segundo, e na programação de sistemas incorporados, onde a memória e a energia são frequentemente escassas. Estou certo sobre esses exemplos? e que outras áreas também seriam exemplos?
algorithms
cocojambles
fonte
fonte
O(n*log(n))
algoritmo será concluído mais rapidamente em um computador de 30 anos do que em umO(n!)
ouO(n*n)
no hardware mais caro de hoje, sen
for grande o suficiente.O(c * f(n))
Onde a constantec
é baseada na ineficiência do hardware. Você pode ter um sistema 1000 vezes mais rápido, poisn
vai para o infinito, isso importa menos e menos. Eu escolheria um emO(10000 * log(n))
vez de umO(n)
dia qualquer se suspeitar quen
possa ser grande.Respostas:
A velocidade está sempre em demanda. Eu acho que você está correto. Aqui estão alguns exemplos onde algoritmos puros estão em demanda:
Criptografia
Pesquisando Bancos de Dados Grandes
Classificação e mesclagem
Pesquisa de texto (não indexada), incluindo curingas
Problemas de matemática com cálculos intensivos
Simulação
Aplicativos de mineração de dados
Animação
AI
Visão computacional
fonte
Existem alguns casos em que o tempo de execução do algoritmo pode não ser muito importante, porque chegamos ao ponto em que você pode simplesmente perfurar um algoritmo de execução mais longa com hardware mais poderoso. Mas há definitivamente alguns lugares onde as acelerações são essenciais.
De um modo geral, qualquer coisa que utilize conjuntos de dados enormes será um problema. Quando você tem algo que não se adapta bem a n e, em seguida, gera um número realmente grande, você tem um problema. Suspeito que, se você fosse ao site beta da Computational Science e bisbilhotasse um pouco, poderia encontrar muitos problemas precisando de algoritmos melhores e mais rápidos. Algumas áreas em que eu já deparei:
De um modo geral, a computação científica geralmente parece ser uma área em que a complexidade do que está sendo programado gera oportunidades para lentidão séria se o seu algoritmo for lento (muitos deles sofrendo de n's muito grandes). E, como você mencionou, existem aplicações financeiras. Quando milissegundos podem determinar se você ganha ou perde dinheiro com uma negociação, algoritmos "suficientemente bons" não serão suficientes se houver algo melhor que possa ser feito.
fonte
Tome com um grão de sal. Mais poder de computação basicamente significa apenas que seu n pode se tornar muito maior antes de diminuir significativamente. Para a maioria dos problemas do dia a dia, esse número é grande o suficiente para que você não precise se preocupar. No entanto, você ainda deve conhecer as complexidades de seus algoritmos.
Com mais recursos disponíveis, pode ser necessário processar mais dados posteriormente. Hoje você precisa analisar um arquivo de log de 10 MB com 100.000 linhas. Em um ano, você pode ter um arquivo de log de 100 GB com 1.000.000.000 de linhas. Se a quantidade de dados crescer mais rapidamente que os recursos, você terá problemas mais tarde.
Com mais recursos disponíveis, mais camadas são empilhadas umas sobre as outras. SO, estrutura de SO, estrutura de terceiros, intérprete de linguagem e, finalmente, sobre sua própria ferramenta. Todas as ineficiências desnecessárias em todas as diferentes camadas se multiplicam. Amanhã, sua ferramenta poderá ser executada em um novo sistema operacional com mais detalhes, que consome mais ciclos e mais memória, deixando menos para você.
Portanto, para responder sua pergunta, você ainda precisa se preocupar onde mais e mais dados precisam ser analisados (exemplos suficientes fornecidos nas outras respostas) e onde você não fornece a ferramenta final, mas outra camada de abstração para outras ferramentas.
fonte
Alguns anos atrás, tive que escrever um algoritmo que classificasse os tubos de ensaio dispostos nos
n
racks em duas partições distintas: ou seja, um subconjunto dos tubos foi 'escolhido' e o restante foi 'não escolhido' e o resultado final seria que nenhum rack teria um tubo 'escolhido' e 'não escolhido' nele (havia alguns requisitos extras, como compressão). Cada rack continha um máximo de 100 tubos.O algoritmo deveria ser usado para acionar um robô de triagem de tubos em um laboratório farmacêutico.
Quando a especificação original foi dada a mim, fui alocado na região de 1 minuto de tempo de cálculo para classificar cerca de 2.000 tubos, pois pensávamos que a usabilidade não era muito dolorosa. Exigia-se que o número de movimentos fosse mínimo em todas as combinações possíveis, pois o próprio robô era lento .
A suposição implícita era que a complexidade seria exponencial com o número de tubos. No entanto, enquanto trabalhava no design do algoritmo, descobri que existe um
O(n)
algoritmo rápido em quen
é o número de racks que executam uma partição ideal dos tubos. O resultado disso foi que o tempo de classificação do algoritmo foi instantâneo, para que a exibição da classificação fosse atualizada em tempo real à medida que o usuário configurasse sua operação de classificação.Para mim, a diferença entre o usuário sentado por um minuto após cada alteração e ter uma GUI responsiva instantaneamente era a diferença entre um software que era funcionalmente suficiente e um software que era um prazer de usar.
fonte
Outras áreas incluem muitos tipos de processamento de sinal em tempo real, sistemas de controle de feedback, deconvolução da exploração de petróleo, compressão de vídeo, traçado de raios e renderização de quadros de filmes, sistemas de realidade virtual, jogos em que a alta taxa de quadros pode ser uma vantagem competitiva significativa e smartphones e outros aplicativos para dispositivos móveis, nos quais um grande número de ciclos da CPU consome a vida da bateria dos usuários mais rapidamente.
Estou surpreso que essa pergunta seja feita, já que para qualquer supercomputador Top-500 já construído, é provável que haja uma lista de espera de pesquisadores que possam maximizar isso e desejar magnitudes com maior poder computacional ou algoritmos de magnitudes melhores para resolver algum problema (dobre algumas proteínas para decifrar o câncer, etc.) antes de se aposentarem.
fonte
Acho que mecanismos de pesquisa como Google e Bing são uma das maiores áreas em que algoritmos complexos são usados e desempenham um papel fundamental na aceleração de resultados com relevância (ranking da página), trazendo mais utilidade aos usuários.
fonte
Atualmente, a eficiência do algoritmo não é uma grande preocupação porque estamos usando algoritmos eficientes. Se você usasse um algoritmo O (n!), Seria lento em qualquer tipo de hardware.
fonte
A complexidade do algoritmo está se tornando cada vez mais importante à medida que a grande quantidade de dados aumenta. Felizmente, soluções genéricas eficientes para problemas comuns de programação (pesquisa e classificação, principalmente) estão incluídas em praticamente todas as bibliotecas padrão de qualquer linguagem de programação moderna; portanto, normalmente, um programador não precisa se preocupar muito com essas coisas. A desvantagem é que muitos programadores não sabem o que está acontecendo e quais são as características dos algoritmos que usam.
Isso se torna especialmente problemático, pois muitos aplicativos não são testados adequadamente: as pessoas escrevem código que funciona bem para pequenos conjuntos de dados de teste, mas quando confrontados com alguns milhares de vezes mais dados, o código é interrompido. Algo que funciona bem para dez registros explode rapidamente quando o conjunto de dados cresce. Exemplo do mundo real: um pedaço de código que deveria limpar itens que não estavam vinculados a nenhuma categoria mais usava um loop aninhado de três níveis, que é O (n ^ 3). Com apenas 10 registros no banco de dados de teste, isso significava 1000 verificações - perfeitamente executáveis e não introduzem um atraso perceptível. No entanto, o banco de dados de produção rapidamente preencheu cerca de 1000 linhas e, de repente, o código faz um bilhão de verificações a cada vez.
Portanto: não, você não precisa conhecer os meandros da implementação de todos os tipos de algoritmos, e não precisa inventar seus próprios, mas precisa de algum conhecimento básico de algoritmos comuns, quais são os seus pontos fortes e fracos são, quando e quando não usá-los, e você precisa estar ciente do possível impacto da complexidade algorítmica, para poder decidir qual nível de complexidade é aceitável.
fonte
Não se trata de quais domínios de aplicativo são sensíveis ao tempo de execução. Qualquer programa, em qualquer lugar, tem um desempenho mínimo abaixo do qual é efetivamente inútil. O ponto da complexidade do algoritmo é como ele varia com o aumento do tamanho da entrada. Em outras palavras, as áreas em que a velocidade é particularmente importante são aquelas nas quais você espera ter que escalar além do tamanho do problema atual, mas da ordem de magnitudedo tamanho atual do seu problema. Se você processar os pedidos de impostos dos cidadãos de um departamento da França, a tarefa poderá ser grande, mas não é provável que o tamanho da população ou a complexidade do processamento de um registro aumentem em dez ou cem vezes, portanto, o que funcionar para você agora provavelmente continuará trabalhando. Mas se você tentar criar algo que decolará nos volumes da Internet, a complexidade do algoritmo é fundamental: tudo o que depende mais do que linear ou log-linearmente o tamanho da entrada se tornará muito mais caro muito rapidamente e, eventualmente, a velocidade do processador simplesmente não pode acompanhar o crescimento.
fonte
No meu campo (VFX, que abrange coisas como rastreamento de caminhos, animação por computador, simulação de partículas, dinâmica de fluidos, processamento de imagens etc.), a complexidade algorítmica é fundamental. Não há como algo que funcione em tempo além do tempo linearitmico possa concluir a qualquer momento razoável em entradas que geralmente atingem milhões de vértices, polígonos, voxels, partículas, texels, especialmente quando muitas dessas coisas precisam ser concluídas muitas vezes por segundo para fornecer feedback interativo em tempo real.
Com isso dito, não há uma ênfase tão forte na complexidade algorítmica na discussão normalmente entre colegas, talvez porque seja um pouco dado como certo e um tanto "rudimentar". Geralmente, é assumido que, se você estiver escrevendo um rastreador de caminho, ele funcionará em tempo logarítmico ou melhor, e que estruturas de dados, como hierarquias delimitadoras de volume, são familiares e relativamente triviais de implementar para o leitor. Eu até tive um colega habilidoso que dizia que multithreading e SIMD são mais importantes que algoritmos, e não acho que ele quis dizer isso no sentido de que você poderia esperar muito da paralelização de um tipo de bolha. Acho que ele disse isso porque, por certo, aplicaríamos algoritmos sensíveis,
Atualmente, grande parte do foco atualmente está em pegar muitos desses algoritmos familiares e em explorá-los melhor as características subjacentes do hardware, como cache da CPU, registros e instruções SIMD, GPUs e múltiplos núcleos. Por exemplo, a Intel criou uma nova maneira de pegar o velho BVH familiar e criar o conceito de "pacotes de raios", basicamente testando vários raios coerentes ao mesmo tempo com um tipo recursivo de passagem de árvore (que pode parecer ele vem com sua parcela de complexidade e sobrecarga, exceto que é mais do que compensado pelo fato de que esses raios agora podem ser testados simultaneamente para interseções de raios / AABB e raios / triângulo através de instruções e registros do SIMD).
Coisa semelhante com a subdivisão catmull-clark, que é um material muito rudimentar em computação gráfica. Hoje em dia, o que é competitivo, quente e super eficiente são as implementações de GPU que se aproximam da subdivisão de CC usando Gregory Patches, popularizado por Charles Loop e posteriormente adotado pela Pixar. A implementação mais direta da CPU agora é bastante obsoleta, não necessariamente porque foi substituída em termos de complexidade algorítmica, mas porque foi substituída por algo que funciona bem com a GPU.
Atualmente, esse é o grande desafio hoje em dia: não apresentar o melhor algoritmo de maneira relativamente independente das características subjacentes do hardware. Na verdade, eu peguei o pé na indústria ao criar uma nova estrutura de aceleração que acelerou significativamente a detecção de colisões para animar personagens e outros corpos moles nos anos 90 usando uma abordagem de segmentação hierárquica em oposição a um índice espacial, o que me levou a um monte de ofertas de emprego, mas hoje em dia não é mais tão impressionante desde que a publiquei, muito antes de termos caches de CPU impressionantes, vários núcleos e GPUs programáveis e o que não é, e hoje em dia uso uma abordagem completamente diferente como resultado das mudanças significativas no hardware subjacente.
fonte
Certa vez, encontrei um problema em que um algoritmo geralmente era executado em O (n), mas em circunstâncias raras e extremamente improváveis precisaria de tempo em O (n ^ 3) - as circunstâncias "raras" eram um diretório contendo arquivos com nomes válidos em um sistema operacional, mas não em outro.
Ninguém nunca teve problemas. Então, um cliente usou uma estratégia para nomear arquivos que seriam sistematicamente executados no caso O (n ^ 3) e, com alguns 100 arquivos, o sistema chegou a um impasse virtual. O resultado foi que o algoritmo teve que ser alterado.
fonte
Mais três que não foram mencionados:
1) Muitos jogos de estratégia em tempo real. Veja aqueles que possuem unidades que não podem compartilhar uma posição. Observe o que acontece com a busca de caminhos quando um grande grupo de unidades se move por terrenos restritos. Ainda não encontrei um jogo sem algum problema substancial com isso, porque simplesmente não há energia suficiente na CPU disponível.
2) Muitos problemas de otimização. (Edit: Desde que escrevi esta resposta, atingi uma. Meu objetivo era podar caminhos redundantes para deixar todos os nós conectados com o peso mínimo dos caminhos de conexão. Minha abordagem original funcionou muito bem até que eu movesse mais a poda para essa rotina, então percebi que era 2 ^ N. Agora é n ^ 2, embora às vezes possa produzir um resultado ligeiramente não ideal.)
3) Coisas que devem operar em grandes quantidades de dados em tempo real. Considere um DVD: você geralmente obtém 2 horas de vídeo em 4,7 GB. Considere um arquivo de vídeo típico com a mesma resolução: essas 2 horas de vídeo geralmente custam menos de 1 GB. A razão para isso é que, quando as especificações do DVD foram estabelecidas, você não podia criar um DVD player com preço razoável que pudesse decodificar os formatos mais modernos com rapidez suficiente.
fonte
Bem, qualquer aplicativo que normalmente é executado em um supercomputador ( lista das maiores máquinas ) se qualifica. São diversos, mas uma grande subclasse deles são simulações de física:
Estes são apenas os principais tópicos da minha cabeça, mas basta ler a lista dos diferentes supercomputadores e perceber que cada um deles foi criado para permitir algum tipo de cálculo que não seria possível sem essas máquinas gigantescas.
E, quando você perceber que realmente precisamos dessas máquinas, perceba quanto custos podem ser economizados, apenas acelerando em 10% esses aplicativos . Qualquer otimização desses códigos aumenta diretamente a quantidade de resultados que conseguimos obter com essas máquinas.
fonte