Thursday 3 August 2017

Mudança De Fila Média


2.4 Filas de prioridade Muitas aplicações exigem que processemos itens com chaves em ordem, mas não necessariamente em ordem ordenada completa e não necessariamente ao mesmo tempo. Muitas vezes, nós coletamos um conjunto de itens e, em seguida, processamos aquele com a maior chave, então talvez coletem mais itens, depois processemos aquele com a chave maior atual, e assim por diante. Um tipo de dados apropriado em um ambiente desse tipo suporta duas operações: remova o máximo e insira. Esse tipo de dados é chamado de fila de prioridade. As filas de prioridades são caracterizadas pela remoção das operações de máximo e inserir. Por convenção, vamos comparar as chaves apenas com um método menor (), como fizemos para a classificação. Assim, se os registros podem ter chaves duplicadas, o máximo significa qualquer registro com o maior valor da chave. Para completar a API, também precisamos adicionar construtores e um teste se operação vazia. Para flexibilidade, usamos uma implementação genérica com uma Chave de tipo genérico que implementa Comparável. O programa TopM. java é um cliente de fila de prioridade que leva um argumento de linha de comando M. Lê transações de entrada padrão e imprime as maiores transações M. Implementações elementares. As estruturas básicas de dados que discutimos na Seção 1.3 nos fornecem quatro pontos de partida imediatos para implementar filas prioritárias. Representação de matrizes (não ordenadas). Talvez a implementação da fila de prioridade mais simples seja baseada em nosso código para pilhas pushdown. O código para inserir na fila de prioridade é o mesmo que para empurrar a pilha. Para implementar, remova o máximo. Podemos adicionar código como o loop interno do tipo de seleção para trocar o item máximo pelo item no final e, em seguida, excluir esse, como fizemos com o pop () para pilhas. O Programa UnorderedArrayMaxPQ. java implementa uma fila de prioridade usando essa abordagem. Representação da matriz (ordenada). Outra abordagem é adicionar código para inserir para mover entradas maiores uma posição para a direita, mantendo as entradas na matriz em ordem (como na classificação da inserção). Assim, o maior item está sempre no final e o código para remover o máximo na fila de prioridade é o mesmo que para pop na pilha. O programa CommandedArrayMaxPQ. java implementa uma fila de prioridade usando essa abordagem. Representações de lista vinculada (não ordenadas e ordenadas de forma reversa). Da mesma forma, podemos começar com nosso código de lista vinculada para pilhas pushdown, quer modificando o código para pop () para encontrar e retornar o máximo ou o código para push () para manter os itens na ordem inversa e o código para pop () para Desvincular e retornar o primeiro (máximo) item na lista. Todas as implementações elementares que acabamos de discutir têm a propriedade de que a inserção ou a remoção da operação máxima leva tempo linear no pior dos casos. Encontrar uma implementação em que ambas as operações é garantida para ser rápido é uma tarefa mais interessante, e é o assunto principal desta seção. Definições de Heap. O heap binário é uma estrutura de dados que pode suportar de forma eficiente as operações básicas da fila de prioridade. Em uma pilha binária, os itens são armazenados em uma matriz de modo que cada chave seja garantida para ser maior do que (ou igual) as chaves em outras duas posições específicas. Por sua vez, cada uma dessas chaves deve ser maior do que mais duas chaves, e assim por diante. Este pedido é fácil de ver se visualizarmos as chaves como sendo em uma estrutura de árvore binária com arestas de cada tecla para as duas chaves conhecidas como menores. Definição. Uma árvore binária é ordenada por pilha se a chave em cada nó for maior do que (ou igual) as chaves nesses dois filhos (se houver). Proposição. A maior chave em uma árvore binária ordenada por pilha é encontrada na raiz. Podemos impor a restrição de ordenação de heap em qualquer árvore binária. No entanto, é particularmente conveniente usar uma árvore binária completa como a que está abaixo. Representamos árvores binárias completas sequencialmente dentro de uma matriz colocando os nós com ordem de nível. Com a raiz na posição 1, seus filhos nas posições 2 e 3, seus filhos nas posições 4, 5, 6 e 7, e assim por diante. Definição. Uma pilha binária é um conjunto de nós com chaves dispostas em uma árvore binária com ordens completas, representadas em ordem de nível em uma matriz (não usando a primeira entrada). Em um heap, o pai do nó na posição k está na posição k2 e, inversamente, os dois filhos do nó na posição k estão nas posições 2k e 2k 1. Podemos viajar para cima e para baixo fazendo simples aritmética em índices de matrizes : Para mover a árvore de ak, definimos k para k2 para mover a árvore, definimos k para 2k ou 2k1. Algoritmos em pilhas. Nós representamos um monte de tamanho N em matriz privada pq de comprimento N1, com pq0 não utilizado eo heap em pq1 através de pqN. Nós acessamos chaves somente através de funções auxiliares privadas menos () e exch (). As operações de pilha que consideramos trabalho primeiro fazem uma simples modificação que pode violar a condição do heap, depois viajando pelo heap, modificando o heap conforme necessário para garantir que a condição do heap esteja satisfeita em todos os lugares. Referimo-nos a este processo como reapreciado. Ou restaurando a ordem do heap. O bottom-up re-se adequa (nadar). Se a ordem de heap for violada porque uma chave de nó se torna maior do que a chave dos pais dos nós, então podemos progredir para corrigir a violação trocando o nó com seu pai. Após a troca, o nó é maior do que os seus filhos (um é o pai antigo e o outro é menor do que o pai antigo porque era filho desse nó), mas o nó ainda pode ser maior do que o pai. Podemos corrigir essa violação da mesma maneira, e assim por diante, subindo a pilha até chegar a um nó com uma chave maior ou a raiz. Top-down heapify (pia). Se a ordem do heap for violada porque uma chave de nós se torna menor do que uma ou ambas as chaves de crianças dos nós, então podemos progredir para corrigir a violação trocando o nó com o maior de seus dois filhos. Esta mudança pode causar uma violação na criança, nós corrigimos essa violação da mesma maneira, e assim por diante, deslocando a pilha até alcançar um nó com crianças menores ou a parte inferior. Fila de prioridade baseada em Heap. Essas operações sink () e swim () fornecem a base para a implementação eficiente da API da fila de prioridade, conforme diagrama abaixo e implementado em MaxPQ. java e MinPQ. java. Inserir. Nós adicionamos o novo item no final da matriz, incrementamos o tamanho do heap e, em seguida, nadamos através do heap com esse item para restaurar a condição do heap. Remova o máximo. Nós tiramos o maior item do topo, coloque o item no final da pilha na parte superior, diminua o tamanho da pilha e, em seguida, afundar-se através do heap com esse item para restaurar a condição do heap. Proposição. Em uma fila de prioridade de N-item, os algoritmos de heap requerem não mais do que 1 lg N compara para inserção e não mais do que 2 lg N compara para remover o máximo. Considerações práticas. Concluímos nosso estudo da API de fila de prioridade de heap com algumas considerações práticas. Multiplos montes. Não é difícil modificar o nosso código para criar montões com base em uma representação de matriz de árvores ternárias ou d - árias feitas com pilhas completas. Há uma compensação entre o custo mais baixo da altura reduzida da árvore e o maior custo de encontrar o maior dos três ou d crianças em cada nó. Redimensionamento de matrizes. Podemos adicionar um construtor sem argumentos, o código para a duplicação de matriz na inserção (). E código para redução de metade da tabela no delMax (). Assim como fizemos para pilhas na seção 1.3. Os limites de tempo logarítmicos são amortizados quando o tamanho da fila de prioridade é arbitrário e os arrays são redimensionados. Imutabilidade das chaves. A fila de prioridade contém objetos criados por clientes, mas assume que o código do cliente não altera as chaves (o que pode invalidar os invariantes de heap). Fila de prioridade de índice. Em muitas aplicações, faz sentido permitir aos clientes se referirem a itens que já estão na fila de prioridade. Uma maneira fácil de fazer é associar um índice inteiro inteiro com cada item. IndexMinPQ. java é uma implementação baseada em heap desta API IndexMaxPQ. java é semelhante, mas para filas prioritárias orientadas ao máximo. Multiway. java é um cliente que combina vários fluxos de entrada classificados em um fluxo de saída classificado. Podemos usar qualquer fila de prioridade para desenvolver um método de classificação. Nós inserimos todas as chaves para serem ordenadas em uma fila de prioridade orientada ao mínimo, então use repetidamente o mínimo para removê-los em ordem. Ao usar um heap para a fila de prioridade, obtemos heapsort. Com foco na tarefa de classificação, abandonamos a noção de ocultar a representação de pilha da fila de prioridade e usar nadar () e pia () diretamente. Isso permite que nós classifiquem uma matriz sem precisar de espaço extra, mantendo o heap dentro da matriz para ser ordenado. Heapsort divide-se em duas fases: construção de pilha. Onde reorganizamos a matriz original em uma pilha e a classificação. Onde tiramos os itens da pilha em ordem decrescente para construir o resultado ordenado. Construção de montes. Podemos realizar esta tarefa em tempo proporcional a N lg N, procedendo da esquerda para a direita através da matriz, usando swim () para garantir que as entradas à esquerda do ponteiro de digitalização compõem uma árvore completa ordenada por pilha, como sucessivas Inserções de fila de prioridade. Um método inteligente que é muito mais eficiente é prosseguir da direita para a esquerda, usando sink () para fazer subaquemas à medida que avançamos. Toda posição na matriz é a raiz de uma pequena subposição de coletor () obras ou sub-heaps também. Se os dois filhos de um nó são montes, então o coletor de chamadas () nesse nó torna a subárvore enraizada há um heap. Triagem. A maior parte do trabalho durante heapsort é feito durante a segunda fase, onde removemos os maiores itens restantes da pilha e colocamos na posição da matriz desocupada à medida que o heap diminui. Heap. java é uma implementação completa da heapsort. Abaixo está um rasto do conteúdo da matriz após cada pia. Proposição. A construção de pilha baseada em pia é tempo linear. Proposição. Heapsort usuários com menos de 2n lg n comparar e trocar para classificar n itens. A maioria dos itens reinsertos no heap durante a classificação vão todo o caminho até a parte inferior. Podemos, portanto, poupar tempo, evitando verificar se o item atingiu sua posição, simplesmente promovendo o maior dos dois filhos até que o fundo seja atingido e, em seguida, movendo de volta o monte para a posição apropriada. Essa idéia reduz o número de comparações por um fator de 2 à custa da contabilidade extra. Suponha que a seqüência (onde uma letra significa inserção e um asterisco significa remover o máximo) é aplicada a uma fila de prioridade inicialmente vazia. Dê a seqüência de valores retornados, remova as operações máximas. Solução. R R P O T Y I I U Q E U (E deixado no PQ) Critique a seguinte ideia: implementar encontrar o máximo em tempo constante, por que não acompanhar o valor máximo inserido até agora, então retornar esse valor para encontrar o máximo. Solução. Será necessário atualizar o valor máximo a partir do zero após uma operação de remoção máxima. Forneça implementações de fila de prioridade que suporte a inserção e remova o máximo. Um para cada uma das seguintes estruturas de dados subjacentes: matriz não ordenada, matriz ordenada, lista vinculada não ordenada e lista vinculada ordenada. Dê uma tabela dos limites do pior caso para cada operação para cada uma das suas quatro implementações no exercício anterior. Solução parcial. OrderedArrayMaxPQ. java e UnorderedArrayMaxPQ. java É uma matriz que é classificada em ordem decrescente, uma pilha orientada ao máximo. Responda. Sim. Suponha que seu aplicativo tenha um grande número de operações de inserção, mas apenas alguns removem as operações máximas. Qual implementação de fila de prioridade você acha que seria mais eficaz: heap, matriz não ordenada, ordem ordenada Resposta. Arranque desordenado. Inserir é um tempo constante. Suponha que seu aplicativo tenha um grande número de encontrar as operações máximas, mas um número relativamente pequeno de inserir e remover as operações máximas. Qual implementação de fila de prioridade você acha que seria mais eficaz: heap, matriz não ordenada, ordem ordenada Resposta. Arranque ordenado. Encontre o máximo é tempo constante. Qual é o número mínimo de itens que devem ser trocados durante a remoção da operação máxima em um monte de tamanho N sem chaves duplicadas Dê um monte de tamanho 15 para o qual o mínimo é alcançado. Responda a mesma pergunta para duas e três sucessivas remover as operações máximas. Resposta parcial. (A) 2. Crie um algoritmo de certificação de tempo linear para verificar se uma matriz pq é um heap orientado a min. Solução. Veja o método isMinHeap () em MinPQ. java. Prove que a construção de pilha baseada na pia usa mais de 2 n compara e no máximo n trocas. Solução. Basta provar que a construção de pilha baseada em pia usa menos de n trocas porque o número de comparações é no máximo duas vezes o número de trocas. Por simplicidade, suponha que o hebra binário é perfeito (ou seja, uma árvore binária em que cada nível é preenchido preenchido) e tem altura h. Definimos a altura de um nó em uma árvore para ser a altura da subárvore enraizada nesse nó. Uma chave à altura k pode ser trocada com o máximo de teclas k abaixo dela quando está afundada. Uma vez que existem 2 h menos k nós à altura k. O número total de permutas é no máximo: a primeira igualdade é para uma soma não padrão, mas é direto verificar se a fórmula é realizada por meio de indução matemática. A segunda igualdade é válida porque uma árvore binária perfeita de altura h tem 2 h 1 menos 1 nós. Provar que o resultado é válido quando a árvore binária não é perfeita requer um pouco mais de cuidado. Você pode fazer isso usando o fato de que o número de nós na altura k em uma pilha binária em n nós é no máximo de ceil (n 2 k 1). Solução alternativa. Novamente, por simplicidade, suponha que o hebra binário é perfeito (ou seja, uma árvore binária em que cada nível é preenchido preenchido). Definimos a altura de um nó em uma árvore para ser a altura da subárvore enraizada nesse nó. Primeiro, observe que uma pilha binária em nós n tem links menos de 1 (porque cada link é o pai de um nó e cada nó possui um link pai, exceto a raiz). Diminuir um nó de altura k requer no máximo k trocas. Vamos cobrar k links para cada nó em altura k. Mas não necessariamente os links no caminho seguido ao afundar o nó. Em vez disso, cobramos o nó nos links k ao longo do caminho do nó que vai para a esquerda-direita-direita-direita. Por exemplo, no diagrama abaixo, o nó da raiz é carregado os 4 links vermelhos, o nó azul está carregado os 3 links azuis e assim por diante. Observe que nenhum link é carregado para mais de um nó. (Na verdade, existem dois links não carregados para qualquer nó: o link direito da raiz e o link pai do nó inferior mais à direita). Assim, o número total de trocas é no máximo n. Uma vez que existem no máximo 2 comparações por troca, o número de comparações é no máximo 2 n. Problemas criativos Teoria dos números computacionais. Escreva um programa CubeSum. java que imprime todos os inteiros da forma a 3 b 3 em que a e b são inteiros entre 0 e N em ordem ordenada, sem usar espaço excessivo. Ou seja, ao invés de calcular uma matriz das somas N 2 e classificá-las, crie uma fila de prioridade orientada no mínimo, contendo inicialmente (0 3. 0, 0), (1 3. 1, 0), (2 3. 2 , 0). (N 3. N, 0). Então, enquanto a fila de prioridade não for vazia, remova o item mais pequeno (i 3 j 3. i, j), imprima e, em seguida, se j 3 (j1) 3. i, j1). Use este programa para encontrar todos os inteiros distintos a, b, c e d entre 0 e 106 de tal modo que um 3b 3 c 3 d 3., por exemplo, 1729 93 103 13 123. Encontre o mínimo. Adicione um método min () a MaxPQ. java. Sua implementação deve usar tempo constante e espaço extra constante. Solução. Adicione uma variável de instância extra que aponte para o item mínimo. Atualize-o após cada chamada para inserir (). Reponha-o para nulo se a fila de prioridade ficar vazia. Pesquisa mediana dinâmica. Crie um tipo de dados que suporte inserir em tempo logarítmico, encontre a mediana em tempo constante e remova a mediana em tempo logarítmico. Solução. Mantenha a chave mediana em v use uma pilha orientada no máximo para chaves menores do que a chave de v use um heap orientado a min para chaves maiores do que a tecla v. Para inserir, adicione a nova chave ao heap apropriado, substitua v com A chave extraída dessa pilha. Limite inferior. Demonstrar que é impossível desenvolver uma implementação da API MinPQ de modo que tanto inserir e excluir a garantia mínima para usar N registro log N compara. Solução. Isso geraria um algoritmo de classificação baseado em N log logs N (insira os itens N e remova repetidamente o mínimo), violando a proposição da Seção 2.3. Implementação da fila de prioridade do índice. Importe IndexMaxPQ. java modificando MaxPQ. java da seguinte maneira: mude pq para manter índices, adicione uma matriz de teclas para manter os valores das chaves e adicione uma matriz qp que seja o inverso de pq mdash qpi dá a posição de i em pq (o Índice j tal que pqj é i). Em seguida, modifique o código para manter essas estruturas de dados. Use a convenção de que qpi é -1 se eu não estiver na fila e inclua um método contém () que teste esta condição. Você precisa modificar os métodos auxiliares exch () e less (), mas não sink () ou swim (). Exercícios de internet Melhor, médio e pior caso de heapsort. Qual é o melhor caso, caso médio e número de pior caso de comparações para heapsorting uma matriz de comprimento N Solução. Se permitimos duplicatas, o melhor caso é o tempo linear (N teclas iguais) se dissolvermos duplicatas, o melhor caso é N lg N compara (mas a melhor entrada do caso é não trivial). O número médio e o pior caso de comparações é de 2 N lg N compara. Veja The Analysis of Heapsort para obter detalhes. Melhor e pior caso de heapify. Qual é o menor número e a maioria dos pacotes comparativos necessários para a heapificação de uma série de itens N Solução. Habilitar uma série de N itens em ordem decrescente requer 0 trocas e N-1 compara. Habilitar uma série de itens N em ordem crescente exige N trocas e 2N compara. Números de táxi. Encontre os números inteiros mais pequenos que podem ser expressos como a soma de cubos de inteiros de duas formas diferentes (1.729), três maneiras diferentes (87.539.319), quatro formas diferentes (6.963.472,309,248), cinco maneiras diferentes (48.988.65 .276.962.496) e seis maneiras diferentes (24.153.319.581.254.312,065,344 ). Esses números inteiros são chamados de números de Taxicab após a famosa história de Ramanujan. Os números inteiros mais pequenos que podem ser expressos como a soma de cubos de inteiros em sete formas diferentes são atualmente desconhecidos. Escreva um programa Taxicab. java que lê em um parâmetro de linha de comando N e imprime todas as soluções não triviais de um 3 b 3 c 3 d 3. de modo que a, b, c e d sejam menores ou iguais a N. Computacional Teoria dos Números. Encontre todas as soluções para a equação a 2b 2 3c 3 4d 4 para as quais a, b, c e d são inferiores a 100.000. Dica. Use um monte mínimo e um montão máximo. Manipulação de interrupção. Ao programar um sistema em tempo real que pode ser interrompido (por exemplo, com um clique do mouse ou conexão sem fio), é necessário atender as interrupções imediatamente, antes de prosseguir com a atividade atual. Se as interrupções devem ser tratadas na mesma ordem, elas chegam, então uma fila FIFO é a estrutura de dados apropriada. No entanto, se diferentes interrupções tiverem prioridades diferentes (por exemplo), então precisamos de uma fila de prioridade. Simulação de redes de enfileiramento. Fila MM1 para filas duplas paralelas, etc. Difícil de analisar matematicamente redes complexas de enfileiramento. Em vez disso, use a simulação para traçar a distribuição dos tempos de espera, etc. Precisa de fila de prioridade para determinar qual evento processar a seguir. Distribuição Zipf. Use o resultado dos exercícios anteriores para amostra da distribuição Zipfian com os parâmetros s e N. A distribuição pode assumir valores inteiros de 1 a N e assume o valor k com probabilidade 1ks soma (i 1 a N) 1 é . Exemplo: as palavras em Shakespeares desempenham Hamlet com s aproximadamente igual a 1. Processo aleatório. Comece com N caixas, cada uma consistindo de uma bola. Selecione aleatoriamente uma das N bolas e mova a bola para uma lixeira ao acaso, de modo que a probabilidade de uma bola ser colocada em um compartimento com bolas é mN. Qual é a distribuição de bolas que resulta após várias iterações. Use o método de amostragem aleatória descrito acima para tornar a simulação eficiente. Os vizinhos mais próximos. Dado N vetores x 1. X 2. X N de comprimento M e outro vetor x do mesmo comprimento, encontre os 20 vetores que são mais próximos de x. Círculo desenhado em um pedaço de papel quadrado. Escreva um programa para encontrar o raio de um círculo, centrado na origem, que toca 32 pontos com coordenadas inteiras x e y. Dica: procure um número que possa ser expresso como a soma de dois quadrados de várias maneiras diferentes. Resposta: há dois triplos de Pitágoras com hipotenusa 25: 152 202 252, 72 242 252 produzindo 20 pontos de rede, existem 22 diferentes triplos de Pitágoras com hipotenusa 5,525, o que leva a 180 pontos de rede. 27,625 é o menor raio que toca mais de 64. 154,136,450 tem 35 triplos pitagóricos. Poderes perfeitos. Escreva um programa PerfectPower. java para imprimir todos os poderes perfeitos que podem ser representados como inteiros longos de 64 bits: 4, 8, 9, 16, 25, 27. Um poder perfeito é um número que pode ser escrito como ab para números inteiros a E b ge 2. Adições de pontos flutuantes. Adicione N números de ponto flutuante, evitando o erro de roundoff. Exclua os dois mais pequenos: adicione um ao outro e reinsira. Primeiro em forma para embalagem de lixeira. 1710 OPT 2, 119 OPT 4 (decrescente). Use a árvore máxima do torneio na qual os jogadores são N caixas e valorizam a capacidade disponível. Pilha com minmax. Crie um tipo de dados que suporte push, pop, size, min e max (onde min e max são os itens mínimos e máximos na pilha). Todas as operações devem levar tempo constante no pior dos casos. Dica: Associe a cada entrada de pilha os itens mínimos e máximos atualmente na pilha. Fila com minmax. Crie um tipo de dados que suporte enqueue, dequeue, size, min e max (onde min e max são os itens mínimos e máximos na fila). Todas as operações devem levar tempo constante amortizado. Dica: faça o exercício anterior e simule uma fila com duas pilhas. 2i 5j. Imprima números da forma 2i 5j em ordem crescente. Montão mínimo-máximo. Crie uma estrutura de dados que suporte min e max em tempo constante, insira, exclua min e exclua max no tempo logarítmico, colocando os itens em uma única matriz de tamanho N com as seguintes propriedades: A matriz representa uma árvore binária completa. A chave em um nó em um nível par é menor do que (ou igual a) as chaves em sua subárvore a chave em um nó em um nível ímpar é maior que (ou igual) as chaves em sua subárvore. Observe que o valor máximo é armazenado na raiz e o valor mínimo é armazenado em uma das raízes. Resolução dos filhos. Min-Max Heaps e consulta de prioridade de fila de prioridades generalizadas. Dada uma seqüência de N itens, uma consulta mínima de intervalo do índice i para j é o índice do item mínimo entre i e j. Crie uma estrutura de dados que preprocesse a seqüência de N itens em tempo linear para suportar consultas mínimas de alcance em tempo logarítmico. Mostre que uma árvore binária completa com nós N tem nós de folha de teto (N2) (nós sem crianças). Fila prioritária orientada para o máximo com min. Qual é a ordem de crescimento do tempo de execução para encontrar uma chave mínima em uma pilha binária orientada ao máximo. Solução. Linearmdash a chave mínima poderia ser em qualquer um dos nós de folha do teto (N2). Fila prioritária orientada para o máximo com min. Crie um tipo de dados que suporte inserir e remover-o-máximo em tempo logarítmico, juntamente com o máximo de um minuto em tempo constante. Solução. Crie uma pilha binária orientada ao máximo e também armazene a chave mínima inserida até agora (o que nunca aumentará a menos que esta pilha fique vazia). Kth maior item maior do que x. Dado um amontoado binário orientado máximo, projete um algoritmo para determinar se o kth maior item é maior ou igual a x. Seu algoritmo deve ser executado em tempo proporcional a k. Solução. Se a chave no nó for maior ou igual a x, procure recursivamente a subárvore esquerda e a subárvore direita. Pare quando o número de nós explorados for igual a k (a resposta é sim) ou não há mais nós para explorar (não). O menor item menor em uma pilha binária orientada a min. Projete um k log k algoritmo para encontrar o kth item menor em um min-orientado binário heap H contendo N itens. Solução. Construa uma nova pilha min-orientada H. Não modificaremos H. Insira a raiz de H em H juntamente com seu índice de heap 1. Agora, exclua repetidamente o item mínimo x em H e insira em H os dois filhos de x de H O item kth excluído de H é o kth item mais pequeno em H. Fila aleatória. Implementar um RandomQueue para que cada operação seja garantida para levar ao máximo o tempo logarítmico. Dica. Não posso pagar a duplicação de matrizes. Nenhuma maneira fácil com listas vinculadas para localizar um elemento aleatório no tempo O (1). Em vez disso, use uma árvore binária completa com links explícitos. Fila FIFO com exclusão aleatória. Implementar um tipo de dados que suporte as seguintes operações: insira um item. Apague o item que foi adicionado o mais recentemente possível. E exclua um item aleatório. Cada operação deve levar (no máximo) tempo logarítmico no pior dos casos. Solução. Use uma árvore binária completa com links explícitos atribua a prioridade de inteiro inteiro i ao i item adicionado à estrutura de dados. Tops k de dois arrays classificados. Dado dois arrays classificados a e b, cada um de comprimento N, encontre os maiores som k da forma ai bj. Dica. Usando uma fila de prioridade (semelhante ao problema da taxicab), você pode alcançar um algoritmo O (k log N). Surpreendentemente, é possível fazê-lo em tempo de O (k), mas o algoritmo é complicado. Análise empírica da construção de pilhas. Compare empiricamente a construção de pilha de baixo para cima do tempo linear versus a construção de heap de cima para baixo linearitmicamente ingênua. Certifique-se de procurá-lo sobre uma série de valores de N. LaMarca e Ladner relatam que, devido à localização do cache, o algoritmo ingênuo pode ser melhor na prática do que a abordagem mais inteligente para valores grandes de N (quando o heap já não se encaixa no Cache), embora o último faça muitas comparações e trocas menos. Análise empírica de montes multi-estradas. Compare empiricamente o desempenho de montes 2- 4- e 8-way. LaMarca e Ladner sugerem várias otimizações, levando em conta os efeitos de cache. Análise empírica de heapsort. Compare empiricamente o desempenho das heapsort de 2 a 4 e 8 vias. LaMarca e Ladner sugerem várias otimizações, levando em conta os efeitos de cache. Seus dados indicam que um heapsort de 8 vias otimizado (e com ajuste de memória) pode ser duas vezes mais rápido do que o heapsort clássico. Heapify por inserções. Suponha que você coloque uma pilha binária em N teclas inserindo repetidamente a próxima chave na pilha binária. Mostre que o número total de comparações é na maioria das respostas. O número de comparações é no máximo lg 1 lg 2. Lg N lg (N) N lg N. Heapify lower bound. (Gonnet e Munro) Mostre que qualquer algoritmo de comparação para construir uma pilha binária em teclas N leva pelo menos 1,3644 N no pior dos casos. Responda . Use um argumento de teoria da informação, ala classificando o limite inferior. Existem N possíveis montes (permutação dos N inteiros) em N teclas distintas, mas há muitos montes que correspondem ao mesmo pedido. Por exemplo, existem dois montões (cabina e cba) que correspondem aos 3 elementos a. O objetivo deste documento é descrever como os IOs estão em fila no driver do dispositivo de disco e no driver do dispositivo do adaptador, SDD e SDDPCM e para explicar como estes podem Seja sintonizado para aumentar o desempenho. E isso também inclui o uso de VIO. Esta informação também é útil para AIX LPARs usando outro código multi-caminho também. Onde este material se encaixa na pilha de IO A seguir está a pilha de IO do aplicativo no disco: Sistema de arquivo de aplicativo (opcional) Driver de dispositivo LVM (opcional) SDD ou SDDPCM ou outro driver de múltiplos caminhos (se usado) Dispositivo de adaptador de driver de dispositivo hdisk Interligação do driver no disco Subsistema de disco Disco Observe que, mesmo que o disco esteja conectado ao adaptador, o código do driver hdisk é utilizado antes do código do driver do adaptador. Então, esta pilha representa o software de pedido que entra em jogo ao longo do tempo, enquanto o IO atravessa a pilha. Por que precisamos enviar simultaneamente mais de um IO para um disco Isso melhora o desempenho. E isso seria o desempenho do ponto de vista das aplicações. Isto é especialmente importante com os subsistemas de disco onde um disco virtual (ou LUN) é suportado por vários discos físicos. Em tal situação, se possamos apenas enviar um único IO de cada vez, encontremos bons tempos de serviço de IO, mas muito fracos. O envio de múltiplas IOs para um disco físico permite que o disco minimize o movimento do atuador (usando um algoritmo de elevador) e obtenha mais IOPS do que é possível enviando uma IO por vez. A analogia do elevador é apropriada. Quanto tempo as pessoas estariam esperando para usar um elevador, se apenas uma pessoa de cada vez pudesse entrar nessa situação, espere que as pessoas esperassem um bom tempo para usar o elevador (tempo de fila), mas uma vez que conseguiram isso , Eles chegaram rapidamente ao seu destino (tempo de serviço). Então, enviar múltiplos IOs em vôo para um subsistema de disco permite descobrir como obter o tempo de serviço IO geral mais rápido e rápido. Teoricamente, o IOPS para um disco é limitado pelo queuedepth (tempo médio de serviço IO). Assumindo um horário de espera de 3 e um tempo médio de serviço IO de 10 ms, isso produz um máximo de 300 IOPS para o hdisk. E, para muitas aplicações, isso pode não ser suficiente. Onde os IOs estão em fila À medida que as IOs atravessam a pilha de IO, o AIX precisa acompanhá-las em cada camada. Então, as IOs são essencialmente em fila em cada camada. Geralmente, um número de IOs em vôo pode ser emitido em cada camada e se o número de pedidos de IO exceder esse número, eles residem em uma fila de espera até que o recurso necessário fique disponível. Portanto, há essencialmente uma fila de processo e uma fila de espera em cada camada (SDD e SDDPCM são um pouco mais complicados). Na camada do sistema de arquivos, os buffers do sistema de arquivos limitam o número máximo de IOs em vôo para cada sistema de arquivos. Na camada do driver do dispositivo LVM, os buffers hdisk limitam o número de IOs em vôo. Na camada SDD, as IOs são enfileiradas se o atributo dpo devices, qdepthenable, for definido como sim (o que é por padrão). Algumas versões do SDD não fazem fila de IOs por isso depende da liberação do SDD. O SDDPCM, por outro lado, não faz fila de IOs antes de enviá-los para o driver do dispositivo de disco. Os hdisks têm um número máximo de IOs em vôo que é especificado pelo atributo queuedepth. E os adaptadores FC também possuem um número máximo de IOs em vôo especificadas por numcmdelems. Os próprios subsistemas de disco em fila de IOs e discos físicos individuais podem aceitar múltiplas solicitações de IO, mas apenas atendem um de cada vez. Aqui estão os atributos de um disco ESS: lsattr - El hdisk33 PRkeyvalue nenhum Chave de reserva Localização verdadeira Localização Etiqueta True lunid 0x5515000000000000 Número de unidade lógica ID True lunresetspt sim Suporte SCSI LUN reset True maxtransfer 0x40000 NA True nodename 0x5005076300c096ab FC Nome do nó False pvid nenhum Identificador de volume físico Falso Qtype simples Queuing TYPE Verdadeiro qfulldly 20 atraso em segundos para SCSI TASK SET FULL Verdadeiro queuedepth 20 Queue DEPTH True reservepolicy singlepath Política de reserva True rwtimeout 60 READWRITE valor de tempo limite True scbsydly 20 atraso em segundos para SCSI BUSY True scsiid 0x620713 ID SCSI True starttimeout 180 START Valor de limite de tempo da unidade True wwname 0x5005076300cd96ab FC Nome do Mundo Falso O predefinido queuedepth é 20, mas pode ser alterado para 256 para ESS, DS6000 e DS8000. One can display allowable values with: lsattr - Rl hdisk33 - a queuedepth 1. 256 (1) indicating the value can be anywhere from 1 to 256 in increments of 1. One can use this command to see any allowable value for attributes which can be changed (showing a value of True in the last field of lsattr - El ltdevicegt for the device using: lsattr - Rl ltdevicegt - a ltattributegt Heres a FC adapters attributes: lsattr - El fcs0 busintrlvl 65703 Bus interrupt level False busioaddr 0xdec00 Bus IO address False busmemaddr 0xe8040000 Bus memory address False initlink al INIT Link flags True intrpriority 3 Interrupt priority False lgtermdma 0x800000 Long term DMA True maxxfersize 0x100000 Maximum Transfer Size True numcmdelems 200 Maximum number of COMMANDS to queue to the adapter True prefalpa 0x1 Preferred ALPA True swfcclass 2 FC Class for Fabric True The default queue depth (numcmdelems) for FC adapters is 200 but can be increased up to 2048 for most adapters. Heres the dpo devices attributes for one release of SDD: lsattr - El dpo Enterprmaxlun 600 Maximum LUNS allowed for Enterprise Products True Virtualmaxlun 512 Maximum LUNS allowed for Virtualization Products False persistentresv yes Subsystem Supports Persistent Reserve Command False qdepthenable yes Queue Depth Control True When qdepthenableyes, SDD will only submit queuedepth IOs to any underlying hdisk (where queuedepth here is the value for the underlying hdisks queuedepth attribute). When qdepthenableno, SDD just passes on the IOs directly to the hdisk driver. So the difference is, if qdepthenableyes (the default), IOs exceeding the queuedepth will queue at SDD, and if qdepthenableno, then IOs exceed the queuedepth will queue in the hdisks wait queue. In other words, SDD with qdepthenableno and SDDPCM do not queue IOs and instead just pass them to the hdisk drivers. Note that at SDD 1.6, its preferable to use the datapath command to change qdepthenable, rather than using chdev, as then its a dynamic change, e. g. datapath set qdepth disable will set it to no. Some releases of SDD dont include SDD queueing, and some do, and some releases dont show the qdepthenable attribute. Either check the manual for your version of SDD or try the datapath command to see if it supports turning this feature off. If youve used both SDD and SDDPCM, youll remember that with SDD, each LUN has a corresponding vpath and an hdisk for each path to the vpath or LUN. And with SDDPCM, you just have one hdisk per LUN. Thus, with SDD one can submit queuedepth x paths to a LUN, while with SDDPCM, one can only submit queuedepth IOs to the LUN. If you switch from SDD using 4 paths to SDDPCM, then youd want to set the SDDPCM hdisks to 4x that of SDD hdisks for an equivalent effective queue depth. And migrating to SDDPCM is recommended as its more strategic than SDD. Both the hdisk and adapter drivers have an in process and wait queues. Once the queue limit is reached, the IOs wait until an IO completes, freeing up a slot in the service queue. The in process queue is also sometimes referred to as the service queue Its worth mentioning, that many applications will not generate many in flight IOs, especially single threaded applications that dont use asynchronous IO. Applications that use asynchronous IO are likely to generate more in flight IOs. What tools are available to monitor the queues For AIX, one can use iostat (at AIX 5.3 or later) and sar (5.1 or later) to monitor the hdisk driver queues. The iostat - D command generates output such as: hdisk6 xfer: tmact bps tps bread bwrtn 4.7 2.2M 19.0 0.0 2.2M read: rps avgserv minserv maxserv timeouts fails 0.0 0.0 0.0 0.0 0 0 write: wps avgserv minserv maxserv timeouts fails 19.0 38.9 1.1 190.2 0 0 queue: avgtime mintime maxtime avgwqsz avgsqsz sqfull 15.0 0.0 83.7 0.0 0.0 136 Here, the avgwqsz is the average wait queue size, and avgsqsz is the average service queue size. The average time spent in the wait queue is avgtime. The sqfull value has changed from initially being a count of the times weve submitted an IO to a full queue, to now where its the rate of IOs per second submitted to a full queue. The example report shows the prior case (a count of IOs submitted to a full queue), while newer releases typically show decimal fractions indicating a rate. Its nice that iostat - D separates reads and writes, as we would expect the IO service times to be different when we have a disk subsystem with cache. The most useful report for tuning is just running iostat - D which shows statistics since system boot, assuming the system is configured to continuously maintain disk IO history (run lsattr - El sys0. or smitty chgsys to see if the iostat attribute is set to true). And the authors favorite iostat command flags are iostat - RDTl ltintervalgt ltintervalsgt. From the applications point of view, the length of time to do an IO is its service time plus the time it waits in the hdisk wait queue. The sar - d command changed at AIX 5.3, and generates output such as: 16:50:59 device busy avque rws Kbss avwait avserv 16:51:00 hdisk1 0 0.0 0 0 0.0 0.0 hdisk0 0 0.0 0 0 0.0 0.0 The avwait and avserv are the average times spent in the wait queue and service queue respectively. And avserv here would correspond to avgserv in the iostat output. The avque value changed at AIX 5.3, it represents the average number of IOs in the wait queue, and prior to 5.3, it represents the average number of IOs in the service queue. SDDPCM provides the pcmpath query devstats and pcmpath query adaptstats commands to show hdisk and adapter queue statistics. SDD similarly has datapath query devstats and datapath query adaptstats. You can refer to the SDDSDDPCM manual for syntax, options and explanations of all the fields. Heres some devstats output for a single LUN: Device : 0 Total Read Total Write Active Read Active Write Maximum IO: 29007501 3037679 1 0 40 SECTOR: 696124015 110460560 8 0 20480 Transfer Size: lt 512 lt 4k lt 16K lt 64K gt 64K 21499 10987037 18892010 1335598 809036 and heres some adaptstats output: Adapter : 0 Total Read Total Write Active Read Active Write Maximum IO: 439690333 24726251 7 0 258 SECTOR: 109851534 960137182 608 0 108625 Here, were mainly interested in the Maximum field which indicates the maximum number of IOs submitted to the device since system boot. For SDD, the Maximum for devstats will not exceed queuedepth x paths when qdepthenableyes. But Maximum for adaptstats can exceed numcmdelems as it represents the maximum number of IOs submitted to the adapter driver and includes IOs for both the service and wait queues. If, in this case, we have 2 paths and are using the default queuedepth of 20, then the 40 indicates weve filled the queue at least once and increasing queuedepth can help performance. For SDDPCM, if the Maximum value equals the hdisks queuedepth, then the hdisk driver queue was filled during the interval, and increasing queuedepth is usually appropriate. One can similarly monitor adapter IOPS with iostat - at ltintervalgt lt of intervalsgt and for adapter queue information, run iostat - aD. optionally with an interval and number of intervals. For FC adapters, the fcstat command provides information on the adapter queue and resource use, and can tell us if we need to increase its queue sizes. For adapter queues, the fcstat command is used and is discussed below. First, one should not indiscriminately just increase these values. Its possible to overload the disk subsystem or cause problems with device configuration at boot. So the approach of adding up the hdisks queuedepths and using that to determine the numcmdelems isnt necessarily the best approach. Instead, its better to use the maximum number of submitted IOs to each device for tuning. When you increase the queuedepths and number of in flight IOs that are sent to the disk subsystem, the IO service times are likely to increase, but throughput will also increase. If IO service times start approaching the disk timeout value, then youre submitting more IOs than the disk subsystem can handle. If you start seeing IO timeouts and errors in the error log indicating problems completing IOs, then this is the time to look for hardware problems or to make the pipe smaller. A good general rule for tuning queuedepths, is that one can increase queuedepths until IO service times start exceeding 15 ms for small random reads or writes or one isnt filling the queues. Once IO service times start increasing, weve pushed the bottleneck from the AIX disk and adapter queues to the disk subsystem. Two approaches to tuning queue depth are 1) base the queue depths on actual IO requests your application generate or 2) use a test tool to see what the disk subsystem can handle and tune the queues based on what the disk subsystem can handle. The ndisk tool (part of the nstress package available on the internet at www-941.ibmcollaborationwikidisplayWikiPtypenstress ) can be used to stress the disk subsystem to see what it can handle. The authors preference is to tune based on your application IO requirements, especially when the disk is shared with other servers. For tuning, we can categorize the situation into four categories: Were filling up the queues and IOs are waiting in the hdisk or adapter drivers Were not filling up the queues, and IO service times are good Were not filling up the queues, and IO service times are poor Were not filling up the queues, and were sending IOs to the storage faster than it can handle and it loses the IOs We want to tune the queues to be in either situation 2 or 3. If were in situation 3, that indicates a bottleneck beyond the hdisk driver which will typically be in the disk subsystem itself, but could also be in the adapter driver or SAN fabric. Situation 4 is something we do want to avoid. All disks and disk subsystem have limits regarding the number of in-flight IOs they can handle, mainly due to memory limitations to hold the IO request and data. When the storage loses IOs, the IO will eventually time out at the host, recovery code will be used and resubmit the IO, but in the meantime transactions waiting on that IO will be stalled. This isnt a desirable situation, as the CPU ends up doing more work to handle IOs than necessary. If the IO eventually fails, then this can lead to an application crash or worse. So be sure to check your storage documentation to understand its limits. Then after running your application during peak IO periods look at the statistics and tune again. Regarding the qdepthenable parameter for SDD, the default is yes which essentially has SDD handling the IOs beyond queuedepth for the underlying hdisks. Setting it to no results in the hdisk device driver handling them in its wait queue. In other words, with qdepthenableyes, SDD handles the wait queue, otherwise the hdisk device driver handles the wait queue. There are error handling benefits to allowing SDD to handle these IOs, e. g. if using LVM mirroring across two ESSs. With heavy IO loads and a lot of queueing in SDD (when qdepthenableyes) its more efficient to allow the hdisk device drivers to handle relatively shorter wait queues rather than SDD handling a very long wait queue by setting qdepthenableno. In other words, SDDs queue handling is single threaded where each hdisk driver has its own thread. So if error handling is of primary importance (e. g. when LVM mirroring across disk subsystems) then leave qdepthenableyes. Otherwise, setting qdepthenableno more efficiently handles the wait queues when they are long. Note that one should set the qdepthenable parameter via the datapath command as its a dynamic change that way (using chdev is not dynamic for this parameter). If error handling is of concern, then its also advisable, assuming the disk is SAN switch attached, to set the fscsi device attribute fcerrrecov to fastfail rather than the default of delayedfail, and also change the fscsi device dyntrk attribute to yes rather than the default of no. These attributes assume a SAN switch that supports this feature. What are reasonable average IO service times What is good or reasonable is somewhat a factor of the technology of the storage and the storage cache sizes. Assuming no IOs are queued to a disk, a typical read will take somewhere from 0 to 15 ms, or so, depending on how far the actuator has to travel (seek time), how long it takes the disk to rotate to the right sector (rotation time), and how long it takes to read the data (transfer time). Then the data must move from the storage to the host. Typically the time is dominated by seek time rotation time, though for large IOs transfer time also can be significant. Sometimes the data will be in disk subsystem read cache, in which case the IO service time is around 1 ms. Typically for large disk subsystems that arent overloaded, IO service times will average around 5-10 ms. When small random reads start averaging greater than 15 ms, this indicates the storage is getting busy. Writes typically go to write cache (assuming it exists) and then these average typically less than about 2.5 ms. But there are exceptions. If the storage is synchronously mirroring the data to a remote site, writes can take much longer. And if the IO is large (say 64 KB or larger) then the transfer time becomes more significant and the average time is slightly worse. If theres no cache, then writes take about the same as reads. If the IO is large block sequential, then besides the increased transfer time, we expect IOs to queue at the physical disk, and IO service times to be much longer on average. E. G. if an application submits 50 IOs (say 50 64 KB IOs reading a file sequentially) then the first few IOs will have reasonably good IO service times, while the last IO will have had to wait for the other 49 to finish first, and will have a very long IO service time. IOs to SSDs are typically less than 1 ms, and for SSDs in disk subsystems, typically less than 2 ms, and on occasion higher. Tuning the FC adapter numcmdelems The fcstat command is perhaps the easiest tool to look for blocked IOs in the adapters queues, e. g. FIBRE CHANNEL STATISTICS REPORT: fcs0 . FC SCSI Adapter Driver Information No DMA Resource Count: 0 No Adapter Elements Count: 104848 No Command Resource Count: 13915968 . The values for No Adapter Elements Count and No Command Resource Count are the number of times since boot that an IO was temporarily blocked due to an inadequate numcmdelems attribute value. Non-zero values indicate that increasing numcmdelems may help improve IO service times. Of course if the value increments slowly, then the improvement may be very small, while quickly incrementing values means tuning is more likely to have a measurable improvement in performance. Like the hdisk queuedepth attribute, changing the numcmdelems value requires stopping use of the resources or a reboot. Queue depths with VSCSI VIO When using VIO, one configures VSCSI adapters (for each virtual adapter in a VIOS, known as a vhost device, there will be a matching VSCSI adapter in a VIOC). These adapters have a fixed queue depth that varies depending on how many VSCSI LUNs are configured for the adapter. There are 512 command elements of which 2 are used by the adapter, 3 are reserved for each VSCSI LUN for error recovery and the rest are used for IO requests. Thus, with the default queuedepth of 3 for VSCSI LUNs, that allows for up to 85 LUNs to use an adapter: (512 - 2) (3 3) 85 rounding down. So if we need higher queue depths for the devices, then the number of LUNs per adapter is reduced. E. G. if we want to use a queuedepth of 25, that allows 51028 18 LUNs. We can configure multiple VSCSI adapters to handle many LUNs with high queue depths. each requiring additional memory. One may have more than one VSCSI adapter on a VIOC connected to the same VIOS if you need more bandwidth. Also, one should set the queuedepth attribute on the VIOCs hdisk to match that of the mapped hdisks queuedepth on the VIOS. For a formula, the maximum number of LUNs per virtual SCSI adapter (vhost on the VIOS or vscsi on the VIOC) is INT(510(Q3)) where Q is the queuedepth of all the LUNs (assuming they are all the same). Note that to change the queuedepth on an hdisk at the VIOS requires that we unmap the disk from the VIOC and remap it back, or a simpler approach is to change the values in the ODM (e. g. chdev - l hdisk30 - a queuedepth20 - P) then reboot the VIOS. For LV VSCSI hdisks, where multiple VIOC hdisks are created from a single VIOS hdisk, then one may take a dedicated resource, shared resource or an in between approach to the VIOS hdisk queue slots. See the section below entitled Further theoretical thoughts on shared vs. dedicated resources . Queue depths with NPIV VIO When using NPIV, we have virtual FC adapters (vFC) and real FC adapters, and often have multiple vFCs tied to a single real FC adapter. If you increase numcmdelems on the virtual FC (vFC) adapter, then you should also increase the setting on the real FC adapter. You can use the fcstat command for both the virtual adapter as well as the real adapter for tuning purposes. A special note on the FC adapter maxxfersize attribute This attribute for the fscsi device, which controls the maximum IO size the adapter device driver will handle, also controls a memory area used by the adapter for data transfers. When the default value is used (maxxfersize0x100000) the memory area is 16 MB in size. When setting this attribute to any other allowable value (say 0x200000) then the memory area is 128 MB in size. At AIX 6.1 TL2 or later a change was made for virtual FC adapters so the DMA memory area is always 128 MB even with the default maxxfersize. This memory area is a DMA memory area, but it is different than the DMA memory area controlled by the lgtermdma attribute (which is used for IO control). The default value for lgtermdma of 0x800000 is usually adequate. So for heavy IO and especially for large IOs (such as for backups) its recommended to set maxxfersize0x200000. The fcstat command can also be used to examine whether or not increasing numcmdelems or maxxfersize could increase performance fcstat fcs0 . FC SCSI Adapter Driver Information No DMA Resource Count: 0 No Adapter Elements Count: 0 No Command Resource Count: 0 This shows an example of an adapter that has sufficient values for numcmdelems and maxxfersize. Non zero value would indicate a situation in which IOs queued at the adapter due to lack of resources, and increasing numcmdelems and maxxfersize would be appropriate. Note that changing maxxfersize uses memory in the PCI Host Bridge chips attached to the PCI slots. The salesmanual, regarding the dual port 4 Gbps PCI-X FC adapter states that If placed in a PCI-X slot rated as SDR compatible andor has the slot speed of 133 MHz, the AIX value of the maxxfersize must be kept at the default setting of 0x100000 (1 megabyte) when both ports are in use. The architecture of the DMA buffer for these slots does not accommodate larger maxxfersize settings If there are too many FC adapters and too many LUNs attached to the adapter, this will lead to issues configuring the LUNs. Errors will look like: LABEL: DMAERR IDENTIFIER: 00530EA6 DateTime: Mon Mar 3 10:48:09 EST 2008 Sequence Number: 863 Machine Id: 00C3BCB04C00 Node Id: p595back Class: H Type: UNKN Resource Name: PCIDMA Resource Class: NONE Resource Type: NONE Location: Description UNDETERMINED ERROR Probable Causes SYSTEM IO BUS SOFTWARE PROGRAM ADAPTER DEVICE Recommended Actions PERFORM PROBLEM DETERMINATION PROCEDURES Detail Data BUS NUMBER FFFF FFFF 9000 00E4 CHANNEL UNIT ADDRESS 0000 0000 0000 018B ERROR CODE 0000 0000 1000 0003 So if you get these errors, youll need to change the maxxfersize back to the default value. Also note that if you are booting from SAN, if you encounter this error, you wont be able to boot, so be sure to have a back out plan if you plan to change this and are booting from SAN. Further theoretical thoughts on shared vs. dedicated resources The astute reader will have considered the fact that typically we have many hdisk drivers sharing multiple adapters and adapter drivers, thus, the FC queue slots are a shared resource for the hdisk drivers: Thus, its possible to ensure that we never fill the adapter queues, by making SUM(hdisk0 queuedepth, hdisk1 queuedepth. hdiskM queuedepth) lt SUM (fcs0 numcmdelems, fcs1 numcmdelems. fcsN numcmdelems). This assumes that IO are evenly spread across the adapters. And most multi-path code does balance IOs across the adapters (or at least can). Though often, environments have many more hdisks than FC ports, and ensuring we wont fill the adapter drivers can lead to small values for queuedepth, and full queues on the hdisk drivers. So there is the dedicated resource approach, the shared resource approach, and in between dedicated and shared. Taking this simple example where Q represents the queue depth for the device driver: This would be considered a dedicated resource approach, where 10 of the adapter driver queue slots are dedicated to each hdisk driver. Here we know well never submit an IO to a full queue on the adapter driver. This would be considered a shared resource approach where the 10 adapter queue slots could be filled up from a single hdisk driver. And heres an example of something in between: Here, there will always be at least 5 queue slots available in the adapter driver for either hdisk driver. There are pros and cons to each approach. The benefit of the dedicated resource approach is that the resources allocated will always be available but typically there will be fewer resources available to each user of the resource (here the resource were considering is the adapter queue slots, and the users of the resource are the hdisk drivers). The benefit of the shared resource approach is that well have more resources for an individual user of the resource when it needs it and it will be able to get greater thruput than in the dedicated resource approach. The author generally prefers a shared resource approach, as generally provides the best thruput and price performance. Note that this situation of shared resources occurs in several possible ways beyond hdisk drivers using adapter drivers. It is also involved when: Several LV VSCSI hdisks for a single hdisk on a VIOS Several vFC adapters using a single real FC adapter Several LPARs using the same disk subsystem

No comments:

Post a Comment