Se você possui um bilhão de números e cem computadores, qual é a melhor maneira de localizar a mediana desses números?
Uma solução que tenho é:
- Divida o conjunto igualmente entre os computadores.
- Classifique-os.
- Encontre as medianas para cada conjunto.
- Classifique os conjuntos em medianas.
- Mesclar dois conjuntos de uma vez da mediana mais baixa à mais alta.
Se tivermos m1 < m2 < m3 ...
em seguida, primeira fusão Set1
e Set2
e no conjunto resultante podemos descartar todos os números mais baixos do que a média de Set12
(incorporada). Portanto, a qualquer momento, temos conjuntos de tamanhos iguais. A propósito, isso não pode ser feito de maneira paralela. Alguma ideia?
algorithm
distributed-computing
anonia
fonte
fonte
Respostas:
Ah, meu cérebro acabou de funcionar, tenho uma sugestão sensata agora. Provavelmente tarde demais se tivesse sido uma entrevista, mas não importa:
A máquina 1 deve ser chamada de "máquina de controle" e, por uma questão de argumento, começa com todos os dados e a envia em parcelas iguais às outras 99 máquinas, ou então os dados começam distribuídos igualmente entre as máquinas e envia 1/99 de seus dados para cada um dos outros. As partições não precisam ser iguais, apenas fechadas.
As outras máquinas classificam seus dados e o fazem de uma maneira que favorece encontrar os valores mais baixos primeiro. Por exemplo, uma classificação rápida, sempre classificando a parte inferior da partição primeiro [*]. Ele grava seus dados de volta na máquina de controle em ordem crescente o mais rápido possível (usando E / S assíncronas para continuar classificando e, provavelmente, com Nagle ativado: experimente um pouco).
A máquina de controle executa uma mesclagem de 99 vias nos dados à medida que chegam, mas descarta os dados mesclados, apenas mantendo a contagem do número de valores que viu. Ele calcula a mediana como a média dos valores de 1/2 bilhões e 1/2 bilhões mais oneth.
Isso sofre com o problema "mais lento no rebanho". O algoritmo não pode ser concluído até que todo valor menor que a mediana tenha sido enviado por uma máquina de classificação. Há uma chance razoável de que um desses valores seja bastante alto em sua parcela de dados. Portanto, assim que o particionamento inicial dos dados estiver concluído, o tempo de execução estimado é a combinação do tempo para classificar 1/99 dos dados e enviá-los de volta ao computador de controle, e o tempo para o controle ler 1/2 dos dados . A "combinação" está entre o máximo e a soma desses tempos, provavelmente próximo ao máximo.
Meu instinto é que, para enviar dados através de uma rede para ser mais rápido do que classificá-los (quanto mais para selecionar apenas a mediana), ele precisa ser uma rede muito rápida. Pode ser uma perspectiva melhor se se presume que a rede é instantânea, por exemplo, se você tiver 100 núcleos com acesso igual à RAM contendo os dados.
Como é provável que a E / S da rede seja o limite, pode haver alguns truques que você pode executar, pelo menos para os dados que retornam à máquina de controle. Por exemplo, em vez de enviar "1,2,3, .. 100", talvez uma máquina de classificação possa enviar uma mensagem que significa "100 valores menores que 101". A máquina de controle poderia, então, executar uma mesclagem modificada, na qual encontra o menor de todos esses valores de topo de faixa, e depois informar a todas as máquinas de classificação o que era, para que elas possam (a) dizer à máquina de controle como muitos valores para "contar" abaixo desse valor e (b) retomar o envio dos dados classificados a partir desse ponto.
De um modo mais geral, provavelmente existe um jogo de adivinhação inteligente de resposta a desafios que a máquina de controle pode jogar com as 99 máquinas de classificação.
Isso envolve viagens de ida e volta entre as máquinas, o que minha primeira versão mais simples evita. Realmente não sei como estimar às cegas o desempenho relativo deles, e como as compensações são complexas, imagino que haja soluções muito melhores do que qualquer coisa que eu pense, assumindo que esse seja um problema real.
[*] permissão de pilha disponível - sua escolha de qual parte primeiro será restringida se você não tiver espaço extra de O (N). Mas se você tiver espaço extra suficiente, poderá fazer a sua escolha e, se não tiver espaço suficiente, poderá pelo menos usar o que precisa para cortar alguns cantos, fazendo a pequena parte primeiro nas primeiras partições.
fonte
fonte
time
comando aplicado a todo o pipeline, levoureal=36m24s
("relógio de parede"),user=113m15s
("tempo paralelo", todos os núcleos adicionados). O comando mais longo, bem à frente dos outros, foisort
, mesmo que estivesse ligado aos meus quatro núcleos a 100%. O consumo de RAM foi muito aceitável.Odeio ser contrário aqui, mas não acredito que a classificação seja necessária, e acho que qualquer algoritmo que envolva a classificação de bilhões / 100 números será lento. Vamos considerar um algoritmo em um computador.
1) Selecione 1000 valores aleatoriamente do bilhão e use-os para ter uma idéia da distribuição dos números, especialmente um intervalo.
2) Em vez de classificar os valores, aloque-os para os baldes com base na distribuição que você acabou de calcular. O número de baldes é escolhido para que o computador possa lidar com eles com eficiência, mas, caso contrário, deve ser o maior possível. Os intervalos de buckets devem ser de modo que números aproximadamente iguais de valores entrem em cada bucket (isso não é crítico para o algoritmo, mas ajuda na eficiência. 100.000 buckets podem ser adequados). Anote o número de valores em cada bloco. Este é um processo O (n).
3) Descubra em qual intervalo de baldes está a mediana. Isso pode ser feito simplesmente examinando o número total em cada bloco.
4) Encontre a mediana real examinando os valores nesse intervalo. Você pode usar uma classificação aqui, se quiser, pois está classificando apenas talvez 10.000 números. Se o número de valores nesse intervalo for grande, você poderá usar esse algoritmo novamente até ter um número pequeno o suficiente para classificar.
Essa abordagem é paralela trivialmente, dividindo os valores entre os computadores. Cada computador relata os totais de cada bloco para um computador 'controle' que executa a etapa 3. Na etapa 4, cada computador envia os valores (classificados) no intervalo relevante para o computador de controle (você também pode executar os dois algoritmos em paralelo, mas provavelmente não vale a pena).
O processo total é O (n), pois as etapas 3 e 4 são triviais, desde que o número de buckets seja grande o suficiente.
fonte
Um bilhão é realmente uma tarefa bastante chata para um computador moderno. Estamos falando de 4 GB de inteiros de 4 bytes aqui ... 4 GB ... essa é a RAM de alguns smartphones.
Saída na minha máquina:
Portanto, isso é concluído na minha máquina em menos de dois minutos (1:43 dos quais 0:10 são para gerar números aleatórios) usando um único núcleo e até fazendo uma classificação completa. Nada extravagante realmente.
Essa certamente é uma tarefa interessante para conjuntos maiores de números. Eu só quero fazer um ponto aqui: um bilhão é de amendoim. Portanto, pense duas vezes antes de começar a lançar soluções complexas em tarefas surpreendentemente simples;)
fonte
(numbers[numbers.length / 2]+numbers[numbers.length / 2+1])/2
senumbers.length
for par enumbers[numbers.length / 2]
somente senumbers.length
for ímpar.A estimativa de estatísticas de ordem como percentil mediano e 99 podem ser eficientemente distribuída com algoritmos como t-digerir ou Q-digerir .
Usando um algoritmo, cada nó produz um resumo, que representa a distribuição dos valores armazenados localmente. Os resumos são coletados em um único nó, mesclados (somando efetivamente as distribuições) e a mediana ou qualquer outro percentil pode ser consultada.
Essa abordagem é usada pelo elasticsearch e, presumivelmente, pelo BigQuery (seguindo a descrição da função QUANTILES).
fonte
A mediana para esse conjunto de números
2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89, 97
é 67.
A mediana para esse conjunto de números
2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89
é 40.
Supondo que a pergunta fosse cerca de 1.000.000.000 de números inteiros (x), em que 0> = x <= 2.147.483.647 e que o OP estava procurando (elemento (499.999.999) + elemento (500.000.000)) / 2 (se os números foram classificados). Também assumindo que todos os 100 computadores eram todos iguais.
usando meu laptop e GigE ...
O que descobri foi que meu laptop pode classificar 10.000.000 de Int32 em 1,3 segundos. Portanto, uma estimativa aproximada seria que uma classificação de número de bilhões levaria 100 x 1,3 segundos (2 minutos e 10 segundos);).
Uma estimativa de uma transferência unidirecional de arquivos de 40 MB em uma Ethernet de gigabit é de 0,32 segundos. Isso significa que os resultados classificados de todos os computadores serão retornados em aproximadamente 32 segundos (o computador 99 não obteve seu arquivo até 30 segundos após o início). A partir daí, não demorará muito para descartar os números mais baixos de 499.999.998, adicione os próximos 2 e divida por 2.
fonte
a*(1e7)log(1e7) = 1.3sec
=>a = 1.6e-9sec
=>a*(1e9)log(1e9) ~ 167sec
, então sua estimativa não foi tão ruim assim.Isso pode surpreender as pessoas, mas se os números forem inteiros pequenos o suficiente para caber em 32 bits (ou menores) - basta fazer uma classificação de balde! Precisa apenas de 16 GB de RAM para qualquer número de entradas de 32 bits e é executado em O (n), o que deve superar qualquer sistema distribuído por n razoáveis, por exemplo, um bilhão.
Depois de ter a lista classificada, é trivial escolher a mediana. De fato, você não precisa construir a lista classificada, mas apenas olhando os buckets deve fazê-lo.
Uma implementação simples é mostrada abaixo. Funciona apenas para números inteiros de 16 bits, mas a extensão para 32 bits deve ser fácil.
Usando um arquivo de texto com um bilhão (10 9 ) de números e executando o
time
mesmoproduz um tempo de execução na minha máquina 1m49.293s. A maior parte do tempo de execução provavelmente é de E / S de disco.
fonte
Por incrível que pareça, se você tiver computadores suficientes, é melhor classificar do que usar
O(n)
algoritmos de descoberta de mediana. (A menos que seus núcleos sejam muito, muito lentos, basta usar um e usar umO(n)
algoritmo de busca mediana para apenas números 1e9; se você tiver 1e12, isso pode ser menos prático).De qualquer forma, vamos supor que temos mais do que log n núcleos para lidar com esse problema e não nos importamos com o consumo de energia, apenas obtendo a resposta rapidamente. Vamos supor ainda que esta é uma máquina SMP com todos os dados já carregados na memória. (As máquinas de 32 núcleos da Sun são desse tipo, por exemplo.)
Um segmento divide a lista às cegas em pedaços de tamanhos iguais e diz aos outros segmentos M para classificá-los. Esses tópicos diligentemente fazem isso com o
(n/M) log (n/M)
tempo. Eles retornam não apenas suas medianas, mas, digamos, seus percentis 25 e 75 (os piores casos perversos são melhores se você escolher números ligeiramente diferentes). Agora você tem 4 milhões de faixas de dados. Você classifica esses intervalos e trabalha para cima na lista até encontrar um número tal que, se você jogar fora todos os intervalos menores ou que contenham o número, você jogará metade dos seus dados. Esse é o seu limite inferior para a mediana. Faça o mesmo para o limite superior. Isso leva algo comoM log M
tempo, e todos os núcleos precisam esperar por isso, então está realmente desperdiçandoM^2 log M
tempo potencial. Agora você tem seu único thread dizendo aos outros para lançar todos os dados fora do intervalo (você deve jogar cerca de metade em cada passagem) e repetir - esta é uma operação trivialmente rápida, pois os dados já estão classificados. Você não deve repetir isso mais do que olog(n/M)
tempo antes que seja mais rápido capturar os dados restantes e usar umO(n)
localizador mediano padrão .Então, complexidade total é algo parecido
O((n/M) log (n/M) + M^2 log M log (n/M))
. Portanto, isso é mais rápido que aO(n)
classificação média em um núcleo seM >> log(n/M)
eM^3 log M < n
, o que é verdade para o cenário que você descreveu.Penso que é uma péssima ideia, dado o quão ineficiente é, mas é mais rápido.
fonte
n
eM
são as variáveis que podem ser escalonadas arbitrariamente, então uma inclui as duas. Em particular, eu postulei issoM
>log n
, o que significa que se você se importa com isso, emn log n
vez de apenasn
, você também precisa se preocuparM
.Isso pode ser feito mais rapidamente do que o algoritmo votado (n log n)
- Algoritmo de seleção distribuído de estatísticas da ordem - O (n)
Simplifique o problema ao problema original de encontrar o número k em um array não classificado.
- Contando o histograma de classificação O (n)
Você deve assumir algumas propriedades sobre o intervalo dos números - o intervalo pode caber na memória? - Classificação de mesclagem externa - O (n log n) - descrito acima
Você basicamente classifica os números na primeira passagem e encontra a mediana na segunda.
- Se alguma coisa for conhecida sobre a distribuição dos números, outros algoritmos poderão ser produzidos.
Para obter mais detalhes e implementação, consulte:
http://www.fusu.us/2013/07/median-in-large-set-across-1000-servers.html
fonte
Um computador é mais que suficiente para resolver o problema.
Mas vamos assumir que existem 100 computadores. A única coisa complexa que você deve fazer é classificar a lista. Divida-o em 100 partes, envie uma parte para cada computador, deixe-as classificadas lá e mescle-as depois disso.
Em seguida, pegue o número no meio da lista classificada (ou seja, com o índice 5 000 000 000).
fonte
Depende dos seus dados. O pior cenário é que são números distribuídos uniformemente.
Nesse caso, você pode encontrar a mediana no tempo O (N) como neste exemplo:
Suponha que seus números sejam 2,7,5,10,1,6,4,4,6,10,4,7,1,8,4,9,9,3,4,3 (o intervalo é de 1 a 10) .
Criamos 3 baldes: 1-3, 4-7, 8-10. Observe que as partes superior e inferior têm o mesmo tamanho.
Enchemos os baldes com os números, contamos quantas caem em cada um, o máximo e o mínimo
A média cai no balde do meio, desconsideramos o resto
Criamos 3 buckets: 4, 5-6, 7. Low começará com uma contagem de 5 e com um máximo de 3 e alto com um mínimo de 8 e uma contagem de 5.
Para cada número, contamos quantas caem no balde baixo e alto, o máximo e o mínimo, e mantemos o balde do meio.
Agora podemos calcular a mediana diretamente: temos uma situação como esta
então a mediana é 4.5.
Supondo que você conheça um pouco da distribuição, pode ajustar como definir os intervalos para otimizar a velocidade. Em qualquer caso, o desempenho deve ser com O (N), porque 1 + 1/3 + 1/9 ... = 1,5
Você precisa de min e max devido a casos extremos (por exemplo, se a mediana for a média entre o máximo da baixa mais antiga e o próximo elemento).
Todas essas operações podem ser paralelizadas, você pode fornecer 1/100 dos dados para cada computador, calcular os 3 intervalos em cada nó e distribuir o intervalo que você mantém. Isso novamente faz com que você use a rede com eficiência, pois cada número é passado em média 1,5 vezes (então O (N)). Você pode até superar isso se você passar apenas os números mínimos entre os nós (por exemplo, se o nó 1 tiver 100 números e o nó 2 tiver 150 números, o nó 2 poderá fornecer 25 números ao nó 1).
A menos que você saiba mais sobre a distribuição, duvido que você possa fazer melhor que O (N) aqui, porque na verdade você precisa contar os elementos pelo menos uma vez.
fonte
O(n log n)
nesse caso. Isso faz sentido ? Pelo jeito que eu gosto da sua ideiao(n)+o(n/3)+o(n/9)+...
que é imóvelo(n)
e o que não éo(n log n)
.o(n)
nesse caso, com o particionamento ingênuo.Um método mais fácil é ter números ponderados.
fonte
Divida os números 10 ^ 9, 10 ^ 7 para cada computador ~ 80 MB em cada um. Cada computador classifica seus números. Então o computador 1 mescla seus próprios números com os do computador 2, computador 3 e 4, etc ... Em seguida, o computador 1 grava metade dos números em 2, 3 a 4, etc. Em seguida, 1 mescla classifica os números dos computadores 1,2,3,4, escreve-os de volta. E assim por diante. Dependendo do tamanho da RAM nos computadores, você pode não escrever todos os números nos computadores individuais a cada etapa, poderá acumular os números no computador 1 por várias etapas, mas faça as contas.
Oh, finalmente obtenha a média dos valores 500000000 e 500000001st (mas verifique se há 00s suficientes lá, não tenho).
EDIT: @Roman - bem, se você não pode acreditar, mesmo que seja verdade, então não faz sentido revelar a verdade ou a falsidade da proposição. O que eu pretendia afirmar era que a força bruta às vezes é inteligente em uma corrida. Demorei cerca de 15 segundos para criar um algoritmo que estou confiante de que posso implementar, que funcionará e que será adaptável a uma ampla variedade de tamanhos de entradas e números de computadores, e sintonizável com as características dos computadores e arranjos de rede. Se você ou qualquer outra pessoa demorar 15 minutos para criar um algoritmo mais sofisticado, tenho uma vantagem de 14m45s para codificar minha solução e iniciá-la em execução.
Mas admito livremente que tudo isso é afirmação, não medi nada.
fonte
Isso pode ser feito em nós usando dados que não são classificados entre nós (por exemplo, dos arquivos de log) da seguinte maneira.
Há um nó pai e 99 nós filhos. Os nós filhos têm duas chamadas de API:
O nó pai chama stats () em todos os nós filhos, observando o mínimo e o máximo de todos os nós.
Uma pesquisa binária agora pode ser realizada da seguinte maneira:
Há um nó pai e 99 nós filhos. Os nós filhos têm duas chamadas de API:
O nó pai chama stats () em todos os nós filhos, observando o mínimo e o máximo de todos os nós.
Uma pesquisa binária agora pode ser realizada da seguinte maneira:
Se as estatísticas () e compare () puderem ser pré-calculadas com uma classificação O (N / Mlogn / M), um pré-cálculo O (N / M) com uma complexidade de memória de O (N) para o período pré- Cálculo. Então você pode comparar () em tempo constante, para que tudo (incluindo pré-cálculo) seja executado em O (N / MlogN / M) + O (logN)
Deixe-me saber se eu cometi um erro!
fonte
Que tal isso: - cada nó pode levar 1 bilhão / 100 números. Em cada nó, os elementos podem ser classificados e a mediana pode ser encontrada. Encontre a mediana das medianas. Ao agregar as contagens de números abaixo da mediana da mediana em todos os nós, podemos descobrir a divisão x%: y% que a mediana da mediana faz. Agora peça a todos os nós que excluam elementos abaixo da mediana das medianas (por exemplo, 30%: divisão de 70%). Os números de 30% são excluídos. 70% de 1 bilhão é de 700 milhões. Agora todos os nós que excluíram menos de 3 milhões de nós podem enviar esses nós extras de volta para o computador principal. O computador principal é redistribuído de forma que agora todos os nós tenham um número quase igual de nós (7 milhões). Agora que o problema foi reduzido para 700 milhões de números ... continua até termos um conjunto menor que pode ser calculado em uma única composição.
fonte
Vamos primeiro descobrir como encontrar uma mediana de n números em uma única máquina: estou basicamente usando a estratégia de particionamento.
Problema: seleção (n, n / 2): Encontre o n / 2 o número do menor número.
Você escolhe o elemento do meio k e particiona os dados em duas sub-matrizes. o primeiro contém todos os elementos <ke o segundo contém todos os elementos> = k.
se sizeof (1ª sub-matriz)> = n / 2, você sabe que essa sub-matriz contém a mediana. Você pode então retirar o segundo sub-array. Resolva essa seleção de problema (tamanho da 1ª sub-matriz, n / 2) .
Caso contrário, jogue fora esse 1º subarray e resolva a seleção (2º subarray, n / 2 - sizeof (1º subarray))
Faça isso recursivamente.
complexidade do tempo é O (n) tempo esperado.
Agora, se temos muitas máquinas, em cada iteração, temos que processar uma matriz para dividir, distribuímos a matriz em máquinas diff. Cada máquina processa sua parte da matriz e envia de volta o resumo para a máquina controladora de hub, ou seja, tamanho do 1º subarray e tamanho do 2º subarray. As máquinas do hub adicionam resumos e decidem qual subarray (1º ou 2º) processar mais e o segundo parâmetro de seleção e o envia de volta para cada máquina. e assim por diante.
Esse algoritmo pode ser implementado com muito cuidado usando o mapa de redução?
Como se parece?
fonte
Acho que a resposta de Steve Jessop será a mais rápida.
Se o tamanho da transferência de dados da rede for o gargalo, aqui está outra abordagem.
fonte
Eu faria assim:
no começo, todos os 100 trabalham para encontrar o número mais alto e o mais baixo; cada computador possui sua parte do banco de dados / arquivo que consulta;
quando os números mais alto e mais baixo são encontrados, um computador lê os dados e distribui cada número igualmente para o restante dos 99; os números são distribuídos em intervalos iguais; (um pode levar de -100 milhões a 0, outro - de 0 a 100 milhões, etc);
Enquanto recebe números, cada um dos 99 computadores já os classifica;
Então, é fácil encontrar a mediana ... Veja quantos números tem cada computador, adicione todos eles (a soma de quantos números existem, não os próprios números), divida por 2; calcular em qual computador é o número e em qual índice;
:) voilla
PS Parece que há muita confusão aqui; A MÉDIA - É O NÚMERO NO MEIO DE UMA LISTA CLASSIFICADA DE NÚMEROS!
fonte
Você pode usar o método da árvore de torneios para encontrar a mediana. Podemos criar uma árvore com 1000 nós de saída, de modo que cada nó folha seja uma matriz. Em seguida, realizamos torneios n / 2 entre as diferentes matrizes. O valor na raiz após os torneios n / 2 é o resultado.
http://www.geeksforgeeks.org/tournament-tree-and-binary-heap/
fonte
Se os números não são distintos e pertencem apenas a um determinado intervalo, ou seja, eles se repetem, então uma solução simples que me vem à mente é distribuir os números entre 99 máquinas igualmente e manter uma máquina como mestre. Agora, cada máquina itera sobre os números fornecidos e armazena a contagem de cada número em um conjunto de hash. Cada vez que o número é repetido no conjunto de números alocados para esse computador específico, ele atualiza sua contagem no conjunto de hash.
Todas as máquinas retornam seu conjunto de hash para a máquina principal. A máquina principal combina os conjuntos de hash, somando a contagem da mesma chave encontrada em um conjunto de hash. Por exemplo, o conjunto de hash da máquina nº 1 teve uma entrada de ("1", 7) e o conjunto de hash da máquina nº 2 teve uma entrada de ("1", 9); portanto, a máquina principal ao pentear os conjuntos de hash faz uma entrada de ("1", 16) e assim por diante.
Depois que os conjuntos de hash foram mesclados, basta classificar as chaves e agora você pode encontrar facilmente o (n / 2) th item e (n + 2/2) th item, no conjunto de hash classificado.
Este método não será benéfico se os bilhões de números forem distintos.
fonte
Bem, suponha que você saiba que o número de números inteiros distintos é (digamos) 4 bilhões, então você pode agrupá-los em intervalos de 64k e obter uma contagem distribuída para cada intervalo de cada máquina no cluster (100 computadores). Combine todas essas contagens. Agora, encontre o depósito com a mediana e, desta vez, solicite apenas os depósitos de 64k elementos que estariam no depósito de destino. Isso requer O (1) (especificamente 2) consultas no seu "cluster". : D
fonte
Meu centavo vale, depois de tudo o que já foi criado por outros:
Encontrar a mediana em uma única máquina é O (N): https://en.wikipedia.org/wiki/Selection_algorithm .
O envio de números N para 100 máquinas também é O (N). Portanto, para tornar interessante o uso de 100 máquinas, a comunicação deve ser relativamente rápida ou N é tão grande que uma única máquina não pode lidar com ela enquanto o N / 100 é possível, ou queremos apenas considerar o problema matemático sem nos preocuparmos com isso. comunicação de dados.
Para resumir, assumirei, portanto, que, dentro de limites razoáveis, podemos enviar / distribuir os números sem afetar a análise de eficiência.
Considere, então, a seguinte abordagem, em que uma máquina é designada para ser o "mestre" para algum processamento geral. Isso será comparativamente rápido, portanto o "mestre" também participa das tarefas comuns que cada máquina executa.
Complexidade temporal:
fonte
Divida os 1 bilhão de números em 100 máquinas. Cada máquina terá 10 ^ 7 números.
Para cada número recebido em uma máquina, armazene o número em um mapa de frequência, número -> contagem. Guarde também o número mínimo em cada máquina.
Encontre mediana em cada máquina: a partir do número mínimo em cada máquina, some as contagens até o índice mediano ser atingido. A mediana em cada máquina será o aprox. menor e maior que 5 * 10 ^ 6 números.
Encontre a mediana de todas as medianas, que será menor e maior que aprox. 50 * 10 ^ 7 números, que é a mediana de 1 bilhão de números.
Agora, alguma otimização da segunda etapa: em vez de armazenar em um mapa de frequência, armazene as contagens em uma matriz de bits variável. Por exemplo: digamos que a partir do número mínimo em uma máquina, estas são as contagens de frequência:
O acima pode ser armazenado na matriz de bits como:
Observe que, no total, custará cerca de 10 ^ 7 bits para cada máquina, pois cada máquina manipula apenas 10 ^ 7 números. 10 ^ 7bits = 1,25 * 10 ^ 6 bytes, ou seja, 1,25MB
Portanto, com a abordagem acima, cada máquina precisará de 1,25 MB de espaço para calcular a mediana local. E a mediana das medianas pode ser calculada a partir dessas 100 medianas locais, resultando na mediana de 1 bilhão de números.
fonte
Sugiro um método para calcular aproximadamente a mediana. :) Se esses bilhões de números estiverem em uma ordem aleatória, acho que posso escolher 1/100 ou 1/10 de um bilhão de números aleatoriamente, separá-los com 100 máquinas e depois escolher a mediana deles. Ou vamos dividir bilhões de números em 100 partes, deixar cada máquina escolher 1/10 de cada parte aleatoriamente, calcular a mediana delas. Depois disso, temos 100 números e podemos calcular a mediana do número 100 mais facilmente. Apenas uma sugestão, não tenho certeza se é matematicamente correto. Mas acho que você pode mostrar o resultado para um gerente que não é tão bom em matemática.
fonte
A resposta de Steve Jessop está errada:
considere os seguintes quatro grupos:
{2, 4, 6, 8, 10}
{21, 21, 24, 26, 28}
{12, 14, 30, 32, 34}
{16, 18, 36, 38, 40}
A mediana é 21, que está contida no segundo grupo.
A mediana dos quatro grupos é 6, 24, 30, 36; a mediana total é 27.
Então, após o primeiro loop, os quatro grupos se tornarão:
{6, 8, 10}
{24, 26, 28}
{12, 14, 30}
{16, 18, 36}
Os 21 já foram descartados de maneira errada.
Este algoritmo suporta apenas o caso quando existem dois grupos.
fonte