13 pontos por GN⁺ 2026-03-09 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Por causa do problema de consultar 3 bilhões de vetores do Jeff Dean, este é um registro de experimento técnico sobre o processo de implementar diretamente uma solução map-reduce otimizada
  • Começando com uma implementação naive que calcula o dot product entre 3 bilhões de vetores float32 de 768 dimensões e 1.000 vetores de consulta, foi obtida uma melhora gradual de desempenho com vetorização em numpy e conversão para float32
  • Com base em 3.000 vetores, o método naive levou cerca de 2 segundos; após a vetorização, caiu para 0,01 s e, com float32, para 0,0045 s
  • Ao escalar para 3 bilhões, a matriz de resultados exige cerca de 8,6 TB de memória, causando OOM, o que exige otimizações adicionais como processamento em lote, mapeamento de memória, reescrita em Rust/C e uso de ferramentas como SimSIMD
  • Enfatiza que, mais do que a solução técnica, o desafio central mais difícil é definir os requisitos (forma de retorno, especificações da máquina, se compressão é aceitável etc.)

O ponto de partida do problema

  • Ao ver a troca sobre Jeff Dean e o problema de consultar 3 bilhões de vetores, tudo começou com a tentativa de implementar diretamente uma solução map-reduce otimizada
  • Um vetor é um arranjo de números de ponto flutuante com n dimensões, e a busca vetorial é usada para encontrar palavras ou itens semanticamente semelhantes
  • Um padrão comum no uso de embeddings em pesquisa, recomendação e aplicações de busca generativa como o Cursor

Implementação naive

  • Suposição inicial: 3 bilhões de vetores de documentos a serem pesquisados e cerca de 1.000 vetores de consulta, todos armazenados em disco no formato .npy
  • A dimensão dos vetores é 768, um tamanho comum usado em muitos modelos de consulta por embeddings baseados em similaridade
  • Um método de laço duplo que compara cada vetor de consulta com todos os vetores de documentos para calcular o dot product e retornar o resultado
  • Testando primeiro com 3.000 vetores, o resultado foi de cerca de 2 segundos em um MacBook M2 (escala 1 milhão de vezes menor que 3 bilhões)

Otimização por vetorização (Vectorized)

  • Aplicação de uma abordagem vetorizada que substitui o laço duplo pela operação de multiplicação de matrizes do numpy (vectors_file @ query_vectors.T)
  • Grande melhora para 0,0107 s com base em 3.000 vetores
  • Ao expandir para 3 milhões de vetores, levou 12,85 s

Conversão para float32

  • Otimização adicional ao converter os dados para np.float32
  • Redução para 0,0045 s com base em 3.000 vetores
  • Como em 3 milhões de vetores leva cerca de 13 s, estima-se que em 3 bilhões levaria 1.000 vezes mais, ou cerca de 3.216 minutos

Resumo da comparação de desempenho

  • Método naive (3.000 vetores): 1,9877 s
  • Método vetorizado (3.000 vetores): 0,0107 s
  • Método vetorizado (3 milhões de vetores): 12,8491 s
  • Método com float32 (3.000 vetores): 0,0045 s

Problema de OOM e direções de otimização adicional

  • Memória necessária ao processar 3 bilhões de objetos em float32 (4 bytes): cerca de 8,6 TB, causando OOM na execução
  • São necessárias otimizações adicionais na direção sugerida por Jeff Dean:
    • Alterar o código para usar geradores e operações de comparação em lote
    • Gravar no disco a cada certo volume de operações ou usar mapeamento de memória
    • Reescrever o código de otimização em nível de sistema em Rust ou C
    • Usar bibliotecas dedicadas à comparação de similaridade vetorial em larga escala, como SimSIMD

A importância de definir os requisitos

  • Antes de otimizações adicionais, surgiram pontos pouco claros no próprio problema:
    • Se é para consultar todos os 3 bilhões de uma vez com um único vetor de consulta e retornar todos os resultados, ou se é uma busca ANN top-k
    • Se também é preciso retornar os vetores originais e se há necessidade de reranqueamento com base em similaridade
    • Se a ideia é consultar o conjunto inteiro de uma vez com 1.000 vetores de consulta
    • Se os vetores já estão em memória, se são lidos um a um do disco ou se o método é por streaming
    • Se a execução é local, quais são as especificações da máquina e se GPU pode ser usada
    • O impacto do tamanho do embedding na representação do resultado e no tamanho dos vetores de entrada e saída
    • Se a compressão de float64 para float32 é aceitável do ponto de vista de precisão
    • Se é um projeto pontual e quanto tempo há disponível para sua criação
  • Mais do que a solução técnica em si, a tarefa mais difícil é definir corretamente os requisitos

Ainda não há comentários.

Ainda não há comentários.