David A. Patterson Organização e Projeto de Computadores.pdf

June 8, 2018 | Author: c4rl0s87 | Category: Personal Computers, Server (Computing), Computer Science, Human, Desktop Environment
Report this link


Description

4ª.E D I Ç Ã O ORGANIZAÇÃO E PROJETO DE COMPUTADORES 4ª. E D I Ç Ã O ORGANIZAÇÃO E PROJETO DE COMPUTADORES I N T E R F A C E H A R D W A R E / S O F T W A R E David A. Patterson John L. Hennessy © 2014, Elsevier Editora Ltda. Todos os direitos reservados e protegidos pela Lei n° 9.610, de 19/02/1998. Nenhuma parte deste livro, sem autorização prévia por escrito da editora, poderá ser reproduzida ou transmitida sejam quais forem os meios empregados: eletrônicos, mecânicos, fotográficos, gravação ou quaisquer outros. Copyright © 2009 by Elsevier Inc. All rights reserved Morgan Kaufmann Publishers is an imprint of Elsevier. Copidesque: Adriana Kramer Revisão: Carla de Cássia Camargo e Bruna Baldini Editoração Eletrônica: Thomson Digital Elsevier Editora Ltda. Conhecimento sem Fronteiras Rua Sete de Setembro, 111 – 16° andar 20050-006 – Centro – Rio de Janeiro – RJ – Brasil Rua Quintana, 753 – 8° andar 04569-011 – Brooklin – São Paulo – SP Serviço de Atendimento ao Cliente 0800-0265340 [email protected] ISBN original 978-0-12-374493-7 ISBN 978-85-352-3585-2 ISBN digital 978-85-352-6410-4 Nota: Muito zelo e técnica foram empregados na edição desta obra. No entanto, podem ocorrer erros de digitação, impressão ou dúvida conceitual. Em qualquer das hipóteses, solicitamos a comunicação ao nosso Serviço de Atendimento ao Cliente, para que possamos esclarecer ou encaminhar a questão. Nem a editora nem o autor assumem qualquer responsabilidade por eventuais danos ou perdas a pes- soas ou bens, originados do uso desta publicação. CIP-BRASIL. CATALOGAÇÃO NA PUBLICAÇÃO SINDICATO NACIONAL DOS EDITORES DE LIVROS, RJ P344o 4. ed. Patterson, David A. Organização e projeto de computadores : interface hardware/software / David A. Patterson, John L. Hennessy ; [tradução Daniel Vieira]. - 4. ed. - Rio de Janeiro : Elsevier, 2014. 28 cm. Tradução de: Computer organization and design: the hardware/software interface ISBN 978-85-352-3585-2 1. Organização de computador. 2. Engenharia de computador. 3. Interfaces (Computadores). I. Hennessy, John L. II. Título. 13-05059 CDD: 004.22 CDU: 004.2 Para Linda, que foi, é e sempre será o amor da minha vida. Prefácio O que podemos experimentar de mais belo é o mistério. Ele é a fonte de toda arte e ciência verdadeira. Albert Einstein, Como vejo o mundo, 1930 Este livro Acreditamos que o aprendizado na Ciência da Computação e na Engenharia deve refletir o estado atual da área, além de apresentar os princípios que estão moldando a computação. Também achamos que os leitores em cada especialidade da computação precisam apreciar os paradigmas organizacionais que determinam as capacidades, o desempenho e, por fim, o sucesso dos sistemas computacionais. A tecnologia computacional moderna exige que os profissionais de cada especiali- dade da computação entendam tanto o hardware quanto o software. A interação entre hardware e software em diversos níveis também oferece uma estrutura para se entender os fundamentos da computação. Não importa se seu interesse principal é hardware ou software, Ciência da Computação ou Engenharia Elétrica, as ideias centrais na organização e projeto de computadores são as mesmas. Assim, nossa ênfase neste livro é mostrar o relacionamento entre hardware e software e apresentar os conceitos que são a base para os computadores atuais. A passagem recente de processador para microprocessadores multicore confirmou a solidez desse ponto de vista, dado desde a primeira edição. Embora os programadores pudessem ignorar e confiar em arquitetos de computador, escritores de compilador e engenheiros de silício para fazer os seus programas executarem mais rápido, sem mu- danças, essa era já terminou. Para os programas executarem mais rápido, eles precisam se tornar paralelos. Embora o objetivo de muitos pesquisadores seja possibilitar que os programadores não precisem saber a natureza paralela subjacente do hardware que eles estão programando, serão necessários muitos anos para se concretizar essa visão. Nossa visão é que, pelo menos na próxima década, a maioria dos programadores terá de entender a interface hardware/software se quiser que os programas executem de modo eficiente em computadores paralelos. Este livro é útil para aqueles com pouca experiência em linguagem assembly ou pro- jeto lógico, que precisam entender a organização básica do computador, e também para leitores com base em linguagem assembly e/ou projeto lógico, que queiram aprender a projetar um computador ou entender como um sistema funciona e por que se comporta de determinada forma. O outro livro Alguns leitores podem estar familiarizados com Arquitetura de Computadores: Uma abor- dagem quantitativa, conhecido popularmente como Hennessy e Patterson. (Este livro, por sua vez, é chamado Patterson e Hennessy.) Nossa motivação ao escrever aquele livro foi descrever os princípios da arquitetura de computadores usando fundamentos sólidos de engenharia e a relação custo/benefício. Usamos um enfoque que combinava exemplos e xii Prefácio medições, baseado em sistemas comerciais, para criar experiências de projeto realísticas. Nosso objetivo foi demonstrar que arquitetura de computadores poderia ser aprendida por meio de metodologias quantitativas, em vez de por uma técnica descritiva. O livro era voltado para profissionais de computação sérios, que desejam um conhecimento detalhado dos computadores. A maioria dos leitores deste livro não planeja se tornar arquiteto de computador. Contudo, o desempenho dos sistemas de software futuros será drasticamente afetado pela forma como os projetistas de software entendem as técnicas de hardware básicas em funcionamento em um sistema. Assim, aqueles que escrevem compiladores, projetistas de sistema operacional, programadores de banco de dados e a maioria dos outros engenheiros de software precisam de um fundamento sólido sobre os princípios apresentados neste livro. De modo semelhante, os projetistas de hardware precisam entender claramente os efeitos de seu trabalho sobre as aplicações de software. Assim, sabíamos que este livro tinha de ser muito mais do que um subconjunto do material contido em Arquitetura de Computadores, e o material foi bastante revisado para corresponder a esse público-alvo diferente. Ficamos tão satisfeitos com o resultado que as edições seguintes do Arquitetura de Computadores foram revisadas para remover a maior parte do material introdutório; logo, há muito menos repetição hoje do que nas primeiras edições dos dois livros. Mudanças para a quarta edição Tivemos cinco objetivos principais para esta terceira edição de Organização e Projeto de Computadores: dada a revolução multicore nos microprocessadores, destacar os tópicos de hardware e software paralelo no decorrer do livro; dinamizar o conteúdo existente de modo a dar espaço para tópicos sobre paralelismo; melhorar a pedagogia em geral; atualizar o conteúdo técnico para refletir mudanças ocorridas na área desde a publicação da terceira edição em 2004; e restaurar a utilidade dos exercícios nesta era da Internet. Antes de discutirmos os objetivos com detalhes, vejamos a tabela a seguir. Ela mostra as sequências de hardware e software no decorrer do livro. Os Capítulos 1, 4, 5 e 7 são encontrados nas duas sequências, não importando a experiência ou o foco. O Capítulo 1 é uma nova introdução, que inclui uma discussão sobre a importância da potência e como ela motiva a mudança de microprocessadores de “core” único para “multicore”. Também apresenta conteúdo sobre desempenho e benchmarking, que tinham um capítulo separado na terceira edição. O Capítulo 2 provavelmente será material de revisão para os que são voltados para o hardware, mas é uma leitura essencial para aqueles voltados para o software, especialmente para os leitores interessados em aprender mais sobre os compiladores e as linguagens de programação orientadas a objeto. Ele inclui material do Capítulo 3 da terceira edição, de modo que a arquitetura MIPS completa agora está em um único capítulo, menos as instruções de ponto flutuante. O Capítulo 3 é para os leitores interessados em construir um caminho de dados ou em aprender mais sobre aritmética de ponto flutuante. Alguns pularão o Capítulo 3, ou porque não precisam dele ou porque é uma revisão. O Capítulo 4 combina dois capítulos da terceira edição para explicar os processadores em pipeline. As Seções 4.1, 4.5 e 4.10 oferecem resumos para os que são voltados a software. Porém, aqueles mais interessados em hardware descobrirão que esse capítulo apresenta um material básico; eles também podem, dependendo de sua base, querer ler primeiro o Apêndice C, sobre projeto lógico. O Capítulo 6, que trata de armazenamento, é essencial para os leitores com foco no software, e deve ser lido pelos outros, se houver tempo. O último capítulo sobre multicores, multiprocessadores e clusters é um material basicamente novo, e deve ser lido por todos. Prefácio xiii Capítulo ou apêndice Seções Foco no software Foco no hardware 1. Abstrações e Tecnologias 1.1 a 1.9 Computacionais 1.10 (História) 2. Instruções: A Linguagem 2.1 a 2.14 de Máquina 2.15 (Compiladores & Java) 2.16 a 2.19 2.20 (História) E. Arquiteturas do conjunto de E.1 a E.19 instruções RISC 3. Aritmética Computacional 3.1 a 3.9 3.10 (História) C. Fundamentos do Projeto C.1 a C.13 Lógico 4. O Processador 4.1 (Visão Geral) 4.2 (Convenções Lógicas) 4.3 a 4.4 (Implementação Simples) 4.5 (Visão Geral do Pipelining) 4.6 (Caminho de Dados em Pipeline) 4.7 a 4.9 (Hazards, Exceções) 4.10 a 4.11 (Paralelo, Vida Real) 4.12 (Controle de Pipeline Verilog) 4.13 a 4.14 (Falácias) 4.15 (História) D. Mapeando o Controle D.1 a D.6 no Hardware 5. Grande e Rápida: 5.1 a 5.8 Explorando a Hierarquia 5.9 (Controlador de Cache de Memória Verilog) 5.10 a 5.12 5.13 (História) 6. Armazenamento e outros 6.1 a 6.10 tópicos de E/S 6.11 (Redes) 6.12 a 6.13 6.14 (História) 7. Multicores, 7.1 a 7.13 multiprocessadores e clusters 7.14 (História) A. Unidades de A.1 a A.12 Processamento Gráfico B. Montadores, Link-editores B.1 a B.12 e o Simulador SPIM Leia cuidadosamente      Leia se tiver tempo       Referência  Revise ou leia             Leia para ter cultura  xiv Prefácio O primeiro objetivo foi tornar o paralelismo um cidadão de primeira classe nesta edição, pois era um capítulo separado no material complementar da edição anterior. O exemplo mais óbvio é o Capítulo 7. Em particular, esse capítulo apresenta o modelo de desempenho Roofline, e mostra seu valor, avaliando quatro arquiteturas multicore recentes em dois kernels. Esse modelo poderia demonstrar ser tão compreensível para multiprocessadores multicore quanto o modelo 3Cs é para os caches. Dada a importância do paralelismo, não seria sensato esperar até o último capítulo para falar a respeito, de modo que existe uma seção sobre paralelismo em cada um dos seis capítulos anteriores: j [B] Capítulo 1: Paralelismo e Potência. Mostra como os limites de potência forçaram a indústria a passar para o paralelismo, e por que o paralelismo ajuda nesse aspecto. j [B] Capítulo 2: Paralelismo e Instruções: Sincronização. Esta seção discute os bloqueios para variáveis compartilhadas, especificamente as instruções Load Linked e Store Conditional do MIPS. j [B] Capítulo 3: Paralelismo e Aritmética de Computador: Associatividade de Ponto Flutuante. Essa seção discute os desafios da precisão numérica e cálculos de ponto flutuante. j [B] Capítulo 4: Paralelismo e Paralelismo Avançado em Nível de Instrução. Aborda ILP avançado — superescalar, especulação, VLIW, desdobramento de loop e OOO — além do relacionamento entre profundidade de pipeline e consumo de potência. j [B] Capítulo 5: Paralelismo e Hierarquias de Memória: Coerência de Cache. Apresenta coerência, consistência e snooping dos protocolos de cache. j [B] Capítulo 6: Paralelismo e E/S: Redundant Arrays of Inexpensive Disks. Descreve RAID como um sistema de E/S paralela, além do sistema ICO altamente disponível. O Capítulo 7 conclui com os motivos para o otimismo pelo qual a incursão no paralelis- mo deverá ter mais sucesso do que aquelas do passado. Estou particularmente entusiasmado com o acréscimo de um apêndice sobre Unidades de Processamento Gráfico, escrito pelo cientista chefe da NVIDIA, David Kirk, e arquiteto chefe John Nickolls. O Apêndice A é a primeira descrição em profundidade das GPUs, que representam uma investida nova e interessante em arquitetura de computador. O apêndice se baseia em temas paralelos dessa edição para apresentar um estilo de computação que permite que o programador pense em MIMD embora o hardware tente executar no estilo SIMD sempre que for possível. Como as GPUs são baratas e encontradas com facilidade — até mesmo em muitos laptops — e seus ambientes de programação estão disponíveis gratuitamente, elas oferecem uma plataforma de hardware paralela que muitos poderiam experimentar. O segundo objetivo foi enxugar o livro para criar espaço para o material novo sobre paralelismo. O primeiro passo foi simplesmente passar um pente fino em todos os pará- grafos acumulados nas três edições anteriores, para ver se ainda eram necessários. As principais mudanças foram a junção de capítulos e o descarte de tópicos. Mark Hill sugeriu a remoção da implementação de processador multiciclo e, em vez disso, acrescentar um controlador de cache multiciclo ao capítulo sobre hierarquia de memória. Isso permitiu que o processador fosse apresentado em um único capítulo, em vez de dois, melhorando o material sobre processador pela omissão. O material sobre desempenho, de um capítulo separado na terceira edição, agora está junto com o primeiro capítulo. O terceiro objetivo foi melhorar a pedagogia do livro. O Capítulo 1 agora está mais recheado, incluindo desempenho, circuitos integrados e potência, e prepara o palco para o Prefácio xv restante do livro. Os Capítulos 2 e 3 foram escritos originalmente em um estilo evolutivo, começando com uma arquitetura de “célula única” e terminando com a arquitetura MIPS completa ao final do Capítulo 3. Esse estilo vagaroso não combina com o leitor moderno. Esta edição junta todo o material sobre conjunto de instruções para as instruções de inteiros no Capítulo 2 — tornando o Capítulo 3 opcional para muitos leitores — e cada seção agora tem significado próprio. O leitor não precisa mais ler todas as seções anteriores. Logo, o Capítulo 2 agora é ainda melhor como referência do que nas edições anteriores. O Capítulo 4 funciona melhor porque o processador agora está em um único capítulo, pois a implementação de multiciclos hoje é uma distração. O Capítulo 5 tem uma nova seção sobre a montagem de controladores de cache. O Material Complementar nos permitiu reduzir o custo do livro, economizando páginas e também aprofundando-nos em assuntos que eram de interesse de alguns, mas não de todos os leitores. Cada capítulo agora tem a seção de Perspectivas Históricas no site (www.elsevier.com.br/organizacaoeprojeto), e quatro capítulos também possuem uma seção de conteúdo avançado. Para aqueles que perguntam por que incluímos material complementar além do livro, a resposta é simples: o material complementar apresenta conteúdo que acreditamos que será fácil e imediatamente acessível ao leitor, não importa onde ele esteja. Se você estiver interessado no conteúdo avançado, ou se quiser rever um tutorial sobre VHDL (por exem- plo), ele está no site, pronto para você utilizar. Este é um campo de mudanças rápidas, e como sempre acontece para nossas novas edições, um objetivo importante é atualizar o conteúdo técnico. O AMD Opteron X4 modelo 2356 (apelidado de “Barcelona”) serve como um exemplo contínuo no livro, e aparece nos Capítulos 1, 4, 5 e 7. Os Capítulos 1 e 6 acrescentam resultados do novo benchmark de potência do SPEC. O Capítulo 2 acrescenta uma seção sobre arquitetura ARM, que atualmente é a ISA de 32 bits mais comum. O Capítulo 5 acrescenta uma nova seção sobre máquinas virtuais, que estão ressurgindo em importância. O Capítulo 5 possui medições detalhadas de desempenho de cache no multicore Opteron X4 e alguns detalhes sobre seu rival, o Intel Nehalem, que foi anunciado no final de 2008. O Capítulo 6 descreve a memória flash pela primeira vez, além de um servidor incrivelmente compacto da Sun, que comprime 8 núcleos, 16 DIMMs e 8 discos em um único bit 1U. Ele também inclui os resultados recentes sobre falhas de disco a longo prazo. O Capítulo 7 aborda diversos tópicos com relação a paralelismo — incluindo multithreading, SIMD, vetor, GPUs, modelos de desempenho, benchmarks, redes de multiprocessadores — e descreve três multicores mais o Opteron X4: Intel Xeon modelo e5345 (Clovertown), IBM Cell modelo QS20 e o Sun Microsystems T2 modelo 5120 (Niagara 2). O objetivo final foi tentar tornar os exercícios úteis a instrutores nesta era da Internet, pois os trabalhos de casa há muito tempo têm sido um modo importante de aprender sobre o material. Infelizmente, hoje as respostas são postadas on-line assim que o livro aparece. Temos uma técnica em duas partes. Primeiro, colaboradores especialistas trabalharam para desenvolver exercícios inteiramente novos para cada capítulo do livro. Segundo, a maioria dos exercícios possui uma descrição qualitativa com o apoio de uma tabela que oferece vários parâmetros quantitativos alternativos, necessários para responder a essa questão. O simples número mais a flexibilidade em termos de como o instrutor pode es- colher para atribuir variações dos exercícios tornará difícil para os alunos encontrarem as soluções correspondentes on-line. Os instrutores também poderão mudar esses parâmetros quantitativos como desejarem, novamente frustrando os alunos que contam com a Internet para buscar soluções para um conjunto de exercícios estático e inalterável. Achamos que essa nova técnica é um novo acréscimo valioso ao livro — por favor, nos informe a sua opinião, seja como aluno ou como instrutor! xvi Prefácio Preservamos elementos úteis do livro das edições anteriores. Para fazer com que o livro funcione melhor como referência, ainda colocamos definições de novos termos nas margens, em sua primeira ocorrência. A seção “Entendendo o Desempenho do Programa”, presente em cada capítulo, ajuda os leitores a entenderem o desempe- nho de seus programas e como melhorá-lo, assim como o elemento “Interface de Hardware/Software” do livro ajudou os leitores a entenderem as escolhas nessa interface. A seção “Colocando em Perspectiva” continua, de modo que o leitor verá a floresta apesar de todas as árvores. As seções “Verifique Você Mesmo” ajudam os leitores a confirmarem sua compreensão do material na primeira vez com as respostas fornecidas ao final de cada capítulo. Esta edição também inclui a placa de referência MIPS verde, que foi inspirada pelo “Green Card” do IBM System/360. O cartão removível foi atualizado e deverá ser uma referência prática na escrita de programas em linguagem assembly MIPS. Comentários finais Ao ler a seção de agradecimentos a seguir, você verá que trabalhamos bastante para corrigir erros. Como um livro passa por muitas tiragens, temos a oportunidade de fazer ainda mais correções. Se você descobrir quaisquer outros erros, por favor, entre em contato com a editora por correio eletrônico em [email protected], ou pelo correio low-tech, usando o endereço encontrado na página de copyright. Esta edição marca uma quebra na colaboração duradoura entre Hennessy e Patterson, que começou em 1989. As demandas da condução de uma das maiores universidades do mundo significam que o Presidente Hennessy não poderia mais se comprometer com a escrita de uma nova edição. O outro autor se sentiu como um malabarista que sempre trabalhou com um parceiro e que, de repente, é lançado no palco como um ato solo. Assim, as pessoas nos agradecimentos e os colegas da Berkeley desempenharam um papel ainda maior na formação do conteúdo deste livro. Apesar disso, desta vez só existe um único autor a culpar pelo novo material que você está para ler. Agradecimentos da quarta edição Gostaria de agradecer a David Kirk, John Nickolls e seus colegas na NVIDIA (Michael Garland, John Montrym, Doug Voorhies, Lars Nyland, Erik Lindholm, Paulius Micikevicius, Massimiliano Fatica, Stuart Oberman e Vasily Volkov) por escreverem o primeiro apêndice detalhado sobre GPUs. Gostaria de expressar novamente meu apreço a Jim Larus, da Mi- crosoft Research, por sua disposição em contribuir com sua experiência em programação na linguagem assembly, além de aceitar que os leitores deste livro usem o simulador que ele desenvolveu e mantém. Também sou agradecido pelas contribuições de muitos especialistas que desenvolveram os novos exercícios para esta nova edição. A escrita de bons exercícios não é uma tarefa fácil, e cada colaborador trabalhou muito para desenvolver problemas que sejam desafiadores e atraentes: j Capítulo 1: Javier Bruguera (Universidade de Santiago de Compostela) j Capítulo 2: John Oliver (Cal Poly, San Luis Obispo), com colaborações de Nicole Kaiyan (University of Adelaide) e Milos Prvulovic (Georgia Tech) j Capítulo 3: Matthew Farrens (University of California, Davis) j Capítulo 4: Milos Prvulovic (Georgia Tech) Prefácio xvii j Capítulo 5: Jichuan Chang, Jacob Leverich, Kevin Lim e Partha Ranganathan (todos da Hewlett-Packard), com colaborações de Nicole Kaiyan (University of Adelaide) j Capítulo 6: Perry Alexander (The University of Kansas) j Capítulo 7: David Kaeli (Northeastern University) Peter Ashenden realizou um esforço gigantesco de edição e avaliação de todos os novos exercícios. Obrigado a David August e Prakash Prabhu, da Princeton University, por seu trabalho nos exames de capítulo que estão disponíveis para os instrutores no site da editora. Contei com meus colegas do Vale do Silício para grande parte do material que este livro utiliza: j AMD — para os detalhes e medição do Opteron X4 (Barcelona): William Brantley, Vasileios Liaskovitis, Chuck Moore e Brian Waldecker. j Intel — para a informação de pré-lançamento sobre o Intel Nehalem: Faye Briggs. j Micron — para a base sobre Memória Flash no Capítulo 6: Dean Klein. j Sun Microsystems — para as medições dos mixes de instruções nos benchmarks SPEC2006 no Capítulo 2 e detalhes e medições do Sun Server x4150 no Capítulo 6: Yan Fisher, John Fowler, Darryl Gove, Paul Joyce, Shenik Mehta, Pierre Reynes, Dimitry Stuve, Durgam Vahia e David Weaver. j U.C. Berkeley — Krste Asanovic (que forneceu a ideia para concorrência de software versus paralelismo do hardware no Capítulo 7), James Demmel e Velvel Kahan (que comentaram sobre paralelismo e cálculos de ponto flutuante), Zhangxi Tan (que projetou o controlador de cache e escreveu o Verilog para ele no Capítulo 5), Sam Williams (que forneceu o modelo Roofline e as medições multicore no Capítulo 7), e o restante dos meus colegas na Par Lab, que me deram muitas suges- tões e opiniões sobre os tópicos de paralelismo encontrados no decorrer do livro. Sou grato aos muitos instrutores que responderam às pesquisas da editora, revisaram nossas propostas e participaram de grupos de foco para analisar e responder aos nossos planos para esta edição. Entre eles estão os seguintes: Grupo de foco: Mark Hill (University of Wisconsin, Madison), E. J. Kim (Texas A&M University), Jihong Kim (Seoul National University), Lu Peng (Louisiana State University), Dean Tullsen (UC San Diego), Ken Vollmar (Missouri State University), David Wood (University of Wisconsin, Madison), Ki Hwan Yum (University of Texas, San Antonio); Inspeções e críticas: Mahmoud Abou-Nasr (Wayne State University), Perry Alexander (The University of Kansas), Hakan Aydin (George Mason University), Hussein Badr (State University of New York em Stony Brook), Mac Baker (Virginia Military Institute), Ron Barnes (George Mason University), Douglas Blough (Georgia Institute of Technology), Kevin Bolding (Seattle Pacific University), Miodrag Bolic (University of Ottawa), John Bonomo (Westminster College), Jeff Braun (Montana Tech), Tom Briggs (Shippensburg University), Scott Burgess (Humboldt State University), Fazli Can (Bilkent University), Warren R. Carithers (Rochester Institute of Technology), Bruce Carlton (Mesa Community College), Nicholas Carter (University of Illinois at Urbana-Champaign), Anthony Cocchi (The City University of New York), Don Cooley (Utah State University), Robert D. Cupper (Allegheny College), Edward W. Davis (North Carolina State University), Nathaniel J. Davis (Air Force Institute of Technology), Molisa Derk (Oklahoma City University), Derek Eager (University of Saskatchewan), Ernest Ferguson (Northwest Missouri State University), Rhonda Kay Gaede (The University of Alabama), Etienne M. Gagnon (UQAM), Costa Gerousis xviii Prefácio (Christopher Newport University), Paul Gillard (Memorial University of Newfoun- dland), Michael Goldweber (Xavier University), Georgia Grant (College of San Mateo), Merrill Hall (The Master's College), Tyson Hall (Southern Adventist University), Ed Harcourt (Lawrence University), Justin E. Harlow (University of South Florida), Paul F. Hemler (Hampden-Sydney College), Martin Herbordt (Boston University), Steve J. Hodges (Cabrillo College), Kenneth Hopkinson (Cornell University), Dalton Hunkins (St. Bonaventure University), Baback Izadi (State University of New York — New Paltz), Reza Jafari, Robert W. Johnson (Colorado Technical University), Bharat Joshi (University of North Carolina, Charlotte), Nagarajan Kandasamy (Drexel University), Rajiv Kapadia, Ryan Kastner (University of California, Santa Barbara), Jim Kirk (Union University), Geoffrey S. Knauth (Lycoming College), Manish M. Kochhal (Wayne State), Suzan Koknar-Tezel (Saint Joseph's University), Angkul Kongmunvattana (Columbus State University), April Kontostathis (Ursinus College), Christos Kozyrakis (Stanford Univer- sity), Danny Krizanc (Wesleyan University), Ashok Kumar, S. Kumar (The University of Texas), Robert N. Lea (University of Houston), Baoxin Li (Arizona State University), Li Liao (University of Delaware), Gary Livingston (University of Massachusetts), Michael Lyle, Douglas W. Lynn (Oregon Institute of Technology), Yashwant K Malaiya (Colorado State University), Bill Mark (University of Texas at Austin), Ananda Mondal (Claflin University), Alvin Moser (Seattle University), Walid Najjar (University of California, Riverside), Danial J. Neebel (Loras College), John Nestor (Lafayette College), Joe Oldham (Centre College), Timour Paltashev, James Parkerson (University of Arkansas), Shaunak Pawagi (SUNY em Stony Brook), Steve Pearce, Ted Pedersen (University of Minnesota), Gregory D Peterson (The University of Tennessee), Dejan Raskovic (University of Alaska, Fairbanks) Brad Richards (University of Puget Sound), Roman Rozanov, Louis Rubinfield (Villanova University), Md Abdus Salam (Southern University), Augustine Samba (Kent State University), Robert Schaefer (Daniel Webster College), Carolyn J. C. Schauble (Colorado State University), Keith Schubert (CSU San Bernardino), William L. Schultz, Kelly Shaw (University of Richmond), Shahram Shirani (McMaster University), Scott Sigman (Drury University), Bruce Smith, David Smith, Jeff W. Smith (University of Georgia, Athens), Philip Snyder (Johns Hopkins University), Alex Sprintson (Texas A&M), Timothy D. Stanley (Brigham Young University), Dean Stevens (Morningside College), Nozar Tabrizi (Kettering University), Yuval Tamir (UCLA), Alexander Taubin (Boston University), Will Thacker (Winthrop University), Mithuna Thottethodi (Purdue University), Manghui Tu (Southern Utah University), Rama Viswanathan (Beloit College), Guoping Wang (Indiana-Purdue University), Patricia Wenner (Bucknell University), Kent Wilken (University of California, Davis), David Wolfe (Gustavus Adolphus College), David Wood (University of Wisconsin, Madison), Mohamed Zahran (City College of New York), Gerald D. Zarnett (Ryerson University), Nian Zhang (South Dakota School of Mines & Technology), Jiling Zhong (Troy University), Huiyang Zhou (The University of Central Florida), Weiyu Zhu (Illinois Wesleyan University). Gostaria de agradecer especialmente ao pessoal da Berkeley, que deu a opinião principal para o Capítulo 7 e o Apêndice A, que foram as partes mais desafiadoras para se escrever nesta edição: Krste Asanovic, Christopher Batten, Rastilav Bodik, Bryan Catanzaro, Jike Chong, Kaushik Data, Greg Giebling, Anik Jain, Jae Lee, Vasily Volkov e Samuel Williams. Um agradecimento especial a Mark Smotherman, que fez uma revisão final cuidadosa, para descobrir problemas técnicos e de escrita, o que melhorou significativamente a qualidade desta edição. Ele desempenhou um papel ainda mais importante neste ato, visto que esta edição foi feita como um ato solo. Prefácio xix Gostaríamos de agradecer a toda a família Morgan Kaufmann, que concordou em pu- blicar este livro novamente, sob a liderança capaz de Denise Penrose. Nathaniel McFadden foi revisor de desenvolvimento para esta edição, e trabalhou comigo semanalmente no conteúdo do livro. Kimberlee Honjo coordenou a inspeção de usuários e suas respostas. Dawnmarie Simpson administrou o processo de produção do livro. Também agra- decemos aos muitos fornecedores autônomos que contribuíram para este volume, es- pecialmente Alan Rose, da Multiscience Press, e à diacriTech, pela composição. As contribuições de quase 200 pessoas que mencionamos aqui tornaram esta quarta edição nosso melhor livro até agora. Divirta-se! David A. Patterson 6 Mudança de mares: Passando de processadores para multiprocessadores  31 .3 Sob as tampas  9 1.2 Por trás do programa  6 sem se pensar nelas. 1.4 Desempenho  19 Alfred North Whitehead  Uma Introdução à Matemática.1 Introdução  1 que podem ser realizadas 1.5 A barreira da potência  29 1. 1911 1. 1 Abstrações e Tecnologias A civilização avança estendendo Computacionais o número de operações importantes 1. 10 Perspectiva histórica e leitura adicional  43 1.11 Exercícios 43 1. indo para Moscou no início da noite a fim de assistir a uma apresentação do balé de Bolshoi. Essa corrida para inovar levou a um progresso sem precedentes desde o início da compu- tação eletrônica no final da década de 1940. Agora. As seguintes aplicações. A revolução dos computadores continua. as oportunidades para os computadores se multiplicam. além de ter mudado a maneira como conduzimos a busca de novos conhecimentos. usando controles no motor. por exemplo. no qual o progresso é glacial e as novas ideias se atrofiam pelo esquecimento. Não! Os computadores são o produto da impressionante e vibrante indústria da tecnologia da informação. Cada vez que o custo da computação melhora por um fator de 10.7 Vida real: Fabricação e benchmarking do AMD Opteron X4  34 1. eram “ficção científica para a computação”: j Computação em automóveis: até os microprocessadores melhorarem significati- vamente de preço e desempenho no início dos anos 80. cujos aspectos são responsáveis por quase 10% do produto interno bruto dos Estados Unidos. Imagine por alguns instantes como esse progresso mudaria a sociedade – morar em Taiti e trabalhar em São Francisco. os computadores reduzem a poluição e melhoram a eficiência do combustível. além de aumentarem a segurança por meio da prevenção de derrapagens perigosas e pela ativação de air-bags para proteger os passageiros em caso de colisão. Hoje. Esse não é um campo árido e monótono. tivesse tido o mesmo desenvolvimento da indústria da computação.8 Falácias e armadilhas  39 1. que assumiu seu lugar junto das revoluções industrial e agrícola. . As aplicações que eram economicamente proibitivas de repente se tornam viáveis. química. Nos últimos 25 anos. Não é difícil imaginar as implicações dessa mudança.1. Os computadores levaram a humanidade a enfrentar uma terceira revolução. essas revoluções foram interrompidas porque alguém sempre construía um computador ainda melhor. hoje nós poderíamos viajar de Nova York até Londres em aproximadamente um segundo por apenas alguns centavos. A multiplicação da força e do alcance intelectual do ser humano naturalmente afetou muito nossas vidas cotidianas. o controle dos carros por computadores era considerado um absurdo.1  Introdução Bem-vindo a este livro! Estamos felizes por ter a oportunidade de compartilhar o entusias- mo do mundo dos sistemas computacionais. Essa área incomum abraça a inovação com uma velocidade surpreendente. no passado recente. existe um novo veio de investigação científica. física etc. a revo- lução da informação.9 Comentários finais  41 1. com a ciência da computação unindo os cientistas teóricos e experimentais na exploração de novas fronteiras na astronomia. Se o setor de transportes. surgiram inúmeros novos computadores que prometiam revolucionar a indústria da computação. biologia. muitas pessoas contam com máquinas de busca para tantas coisas em suas vidas que seria muito difícil viver sem elas. como ocorreria no caso de um grande servidor Web. encontrar informações relevantes tornou-se cada vez mais importante. Claramente. permitindo que a as- sistência médica seja ajustada a você mesmo. Para muitos. Hoje. Os servidores são projetados para suportar grandes cargas de trabalho. em geral. os custos continuam a cair. e.7) seja usado em computadores variando dos dispositivos domésticos inteligentes e telefones celulares aos maiores supercomputadores. Classes de aplicações de computador e suas características Embora um conjunto comum de tecnologias de hardware (discutidas nas Seções 1. um teclado e um mouse. os avanços dessa tecnologia hoje afetam quase todos os aspectos da nossa sociedade. Os servidores abrangem a faixa mais ampla em termos de custo e capacidade. os servidores também dão grande ênfase à estabilidade. Genericamente falando. j World Wide Web: ainda não existente na época da primeira edição deste livro. computadores desktop  Um Os computadores desktop são possivelmente a forma mais conhecida de computação computador projetado para uso por e caracterizam-se pelo computador pessoal. como há dez ou 20 anos. j Máquinas de busca: à medida que o conteúdo da Web crescia em tamanho e em valor. a World Wide Web transformou nossa sociedade. A evolução de muitas tecnologias de computação é motivada por essa classe da computação. minicom- para executar grandes programas putadores e supercomputadores. Os servidores são construídos a partir da mesma tecnologia básica dos computadores desktop. você poderá adquirir seu próprio genoma. Na sua forma mais simples. Esses servidores de baixa capacidade normalmente são usados para armazenamento de arquivos. que podem sempre de maneira simultânea e normalmente acessado apenas consistir em uma única aplicação complexa. a um único usuário por um baixo custo e normalmente são usados para executar softwa- re independente. Em geral. permitindo a comunicação pessoa a pessoa em quase todo lugar do mundo? j Projeto do genoma humano: o custo do equipamento computacional para mapear e analisar as sequências do DNA humano é de centenas de milhares de dólares. Essas aplicações muitas vezes são baseadas em software de outra origem (como um banco de dados ou sistema de simulação). a Web substituiu as bibliotecas. normalmente científica ou de engenharia. ou manipular muitas tarefas pequenas. Além do mais. antes. Os computadores desktop enfatizam o bom desempenho incorporando um monitor gráfico. são acessados apenas por meio de uma para múltiplos usuários quase rede. mas fornecem uma maior capa- cidade de expansão tanto da capacidade de processamento quanto de entrada/saída. os computadores são usados em três diferentes classes de aplicações. que só tem cerca de 30 anos! servidor  Um computador usado Os servidores são a forma moderna do que. já que uma falha normalmente é mais prejudicial do que seria em um computador desktop de um único usuário. pequenas aplicações comerciais . reconhecimento de voz prático e assistência médica personalizada. por meio de uma rede.3 e 1. eram os mainframes. normalmente velmente já usou extensivamente. A ficção científica de hoje sugere as aplicações que fazem sucesso amanhã: já a caminho estão os mundos virtuais. essas diferentes aplicações possuem diferentes necessidades de projeto e empregam os fundamentos das tecnologias de hardware de diversas maneiras. um servidor pode ser pouco mais do que uma máquina desktop sem monitor ou teclado e com um custo de mil dólares.2 Capítulo 1  Abstrações e Tecnologias Computacionais j Telefones celulares: quem sonharia que os avanços dos sistemas computacionais levariam aos telefones portáteis. Os avanços de hardware permitiram que os programadores criassem softwares maravilhosamente úteis e explicassem por que os computadores são onipresentes. É improvável que alguém teria considerado esse projeto se os custos computacionais fossem 10 a 100 vezes mais altos. que a maioria dos leitores deste livro prova- uma única pessoa. mas frequentemente são modificadas ou personalizadas para uma função específica. redefinido como significando processadores encontrados em seu carro. exploração de de dólares. (Temos dados de televisão somente a partir de 2004. Os computadores embutidos incluem os micro.627. resfriamento e rede de um grande que contam com computadores embutidos foi muito mais rápido do que a taxa de cres- número de servidores.4B em 2004. tidos são projetados para executar uma aplicação ou um conjunto de aplicações relacio- nadas como um único sistema. eles são bytes de memória e de petabytes de armazenamento.0B de televisores.) Mais de um bilhão de novos telefones celulares foram entregues em 2006. Nas aplicações FIGURA 1.000. No outro extremo. players de computador embutido  Um música. incluindo 3 TVs. estão os supercomputadores.1 Introdução 3 ou serviço Web simples (veja Seção 6. mas a taxa cresceu para 4. os computadores em um telefone celular. petróleo. até a completa devastação que poderia ocorrer quando o computador em um avião ou em um navio falha. apesar do grande número de computadores centro de dados  Uma sala embutidos. 1000 ou 1024 terabytes.000 (1012) bytes. dois PCs e outros dispositivos. Como a população do mundo era cerca de 6. petabyte  Dependendo da situação. como previsão do tempo. e custam desde milhões até centenas configurados como servidores de milhões de dólares.099. em geral. computadores em um video game ou televisão digital. Os sistemas de computação embu. cimento dos computadores desktop. . e as redes de processadores que controlam um avião moderno ou um navio de carga. computadores pessoais e televisores fabricados por ano entre 1997 e 2007.511. os 1. Embora esses supercomputadores representem o máximo da capacidade de computação. minimizar custo e potência é o objetivo mais importante. um desempenho mínimo com limitações rígidas em relação a custo ou potência. câmeras digitais. havia aproximadamente um PC. embora alguns sistemas de em termos de receita total. considere um telefone celular: o processador só precisa ser tão rápido quanto o necessário para manipular sua função limitada. tocadores de MP3 e telefones celulares. supercomputador  Uma classe que. comunicações e de armazenamento Os computadores embutidos são a maior classe de computadores e abrangem a faixa secundário o tenham mais ampla de aplicações e desempenho. Um estudo de 2006 das famílias dos Estados Unidos descobriu que eles possuíam.2 telefones celulares e 2. Observe que os computadores embutidos também são encontrados em TVs digitais e sintonizadores.5 televisores para cada oito pessoas no planeta. Por exemplo.8B de telefones celulares e 0. determinação da estrutura da proteína e outros problemas de grande porte. a maioria dos usuários nunca vê realmente que está usando um computador! ou prédio criado para tratar A Figura 1. video games e uma série de outros dispositivos do consumidor.10). Os supercomputadores normalmente são usados para cálculos e normalmente custam milhões científicos e de engenharia de alta capacidade.000. além disso. 2.5 em 2007. de computadores com desempenho e custo mais altos.1  O número de telefones celulares. quando sua nova televisão falha. automóveis. Apesar do seu baixo custo. o que aumenta ainda computador dentro de outro mais a lacuna entre o número de computadores embutidos e os computadores de desktop.4 em 1997. de tera. 1. 12 aparelhos. O número total em uso em 2004 é estimado como sendo 2.776 (240) bytes. usado para executar As aplicações embutidas normalmente possuem necessidades específicas que combinam uma aplicação predeterminada ou uma coleção de software. o crescimento em telefones celulares das necessidades de energia.1 mostra que.000. 1. dispositivo. durante os últimos anos. atualmente. como consoles de jogos. os computadores embutidos frequentemente possuem menor tolerância a falhas. consistem em centenas ou milhares de processadores e. eles são uma fração relativamente pequena dos servidores e do mercado de computadores 1. na média. As vendas de telefones celulares ultrapassaram os PCs por um fator apenas de 1. terabyte  Originalmente.8B de PCs. já que os resultados podem variar desde um simples incômodo. portanto. 9). Nos grandes sistemas embutidos. Na última década. Detalhamento:  os detalhamentos são seções curtas usadas em todo o texto para fornecer mais detalhes sobre um determinado assunto. O leitor interessado encontrará muito mais material sobre esse assunto em nosso livro avançado. que pode ser de interesse. a maioria dos conceitos se aplica diretamente – ou com ligeiras modificações – aos computadores embutidos. Ao concluir este livro. já que o material subsequente nunca dependerá do conteúdo desta seção. Muitos processadores embutidos são projetados usando núcleos de processador. O que você pode aprender neste livro Os bons programadores sempre se preocuparam com o desempenho de seus programas porque gerar resultados rapidamente para o usuário é uma condição essencial na cria- ção bem-sucedida de software. acreditamos que você será capaz de responder às seguintes perguntas: j Como os programas escritos em uma linguagem de alto nível. portanto. aumentar seu conhecimento em organização de computadores. como C ou Java. . a estabilidade é obtida principalmente por meio da simplicidade – a ênfase está em realizar uma função o mais perfeitamente possível. j O que determina o desempenho de um programa e como um programador pode melhorar o desempenho? Como veremos. bancos de dados e mesmo aplicações precisarão. em geral. Os programadores que desejam construir versões competitivas de compiladores. uma grande limitação no desempenho dos computadores era o tamanho da memória do computador. são traduzidos para a linguagem de máquina e como o hardware executa os programas resultantes? Compreender esses conceitos forma o alicerce para entender os aspectos do hardware e software que afetam o desempenho dos programas. uma versão de um processador escrita em uma linguagem de descrição de hardware como Verilog ou VHDL (veja Capítulo 4). os avanços em arquitetura de computadores e nas tecnologias de fabricação de memórias reduziram drasticamente a importância do tamanho da memória na maioria das aplicações. j Que técnicas podem ser usadas pelos projetistas de hardware para melhorar o desempenho? Este livro apresentará os conceitos básicos do projeto de com- putador moderno. Assim. Arquitetura de Computadores: Uma abordagem quantitativa. j O que é a interface entre o software e o hardware. os programadores interessados em desempenho precisam entender os problemas que substituíram o modelo de memória simples dos anos 60: a natureza paralela dos processadores e a natureza hierárquica das memórias. são empregadas as mesmas técnicas de redundância utilizadas nos servidores (veja Seção 6. Agora.4 Capítulo 1  Abstrações e Tecnologias Computacionais embutidas orientadas ao consumidor. isso depende do programa original. sistemas operacionais. Sentimo-nos honrados com a oportunidade de explicar o que existe dentro da máquina revolucionária. decifrando o software por trás do seu programa e o hardware sob a tampa do seu computador. e como o software instrui o hardware a realizar as funções necessárias? Esses conceitos são vitais para entender como escrever muitos tipos de software. como um eletrodoméstico digital. com exceção dos sistemas embutidos. Embora este livro se concentre nos computadores de uso geral. Nas décadas de 1960 e 1970. os programadores em geral seguiam um princípio simples: minimizar o espaço ocupado na memória para tornar os programas mais rápidos. da tradução desse programa para a linguagem do computador e da eficiência do hardware em executar o programa. O núcleo permite que um projetista integre outro hardware específico de uma aplicação com o núcleo do processador para a fabricação de um único chip. Os leitores que não possuem um interesse específico no tema podem pular essas seções. Algumas questões “Verifique você mesmo” possuem res- postas simples. que são fáceis de entender quando se sabe o que as letras signifi. incluímos uma definição destacada de construída tomando-se as cada termo novo na primeira vez que aparece no texto. Além disso. há muita terminologia especial usada para descrever os computadores mo- dernos. você provavelmente verá muitas palavras novas ou palavras que já pode ter ouvido. 1. em todo o livro. melhorar o desempenho do seu programa múltiplos processadores (“cores” em um computador moderno ou avaliar que recursos podem tornar um computador ou núcleos) em um único circuito melhor do que outro para uma determinada aplicação será um complicado processo integrado. dos programas”. A tabela a seguir descreve dos programas como o hardware e o software afetam o desempenho. mas não sabe ao certo o que significam. DIMM. os projetistas de computador (inclusive estes autores) adoram usar acrônimos. mostra como avaliar o desempenho e a potência. uma vez que nos permite descrever precisamente uma função ou capacidade. outras são para discussão em grupo. Por exemplo: RAM é um acrônimo lhando com a terminologia. usamos uma seção especial. Verifique você preenderam os principais conceitos apresentados em um capítulo e se entenderam as mesmo implicações desses conceitos. em vez de um procedimento científico conduzido por consciência e análise. DRAM. 5 e 7 de memória instruções podem ser executadas Sistema de E/S (hardware Determina a velocidade em que Capítulo 6 e sistema operacional) as operações de E/S podem ser executadas As Seções “Verifique você mesmo” se destinam a ajudar os leitores a avaliar se com. letras iniciais das palavras. de tentativa e erro. Processing Unit (unidade central grama irão afetar o desempenho. Entendendo ritmos usados no programa. SATA (memória de acesso aleatório) e e muitas outras. O desempenho de um programa depende de uma combinação entre a eficácia dos algo. Componente de hardware Como este componente afeta Onde este assunto ou software o desempenho é abordado? Algoritmo Determina o número de instruções Outros livros! do código-fonte e o número de operações de E/S realizadas Linguagem de programação. você estará fluente e seus amigos ficarão impressionados para Random Access Memory quando você usar corretamente palavras como BIOS.1 Introdução 5 j Quais são os motivos e as consequências da mudança recente do processamento sequencial para o processamento paralelo? Este livro oferece a motivação. apresenta os circuitos integrados. descreve os mecanismos de hardware atuais para dar suporte ao paralelismo e estuda a nova geração de microprocessadores “multicore” (veja Capítulo 7). microprocessador multicore  Um microprocessador contendo Sem entender as respostas a essas perguntas. os sistemas de software usados para criar e traduzir o pro- grama para instruções de máquina e da eficácia do computador em executar essas ins- o desempenho truções. a primeira aparece a seguir. As respostas às questões específicas . Após um pequeno período traba. coloca os principais componentes de software e hardware em perspectiva. CPU é um acrônimo para Central Para enfatizar como os sistemas de software e hardware usados para executar um pro. Neste capítulo e em capítulos seguintes. Este primeiro capítulo é a base para o restante do livro. mas ela realmente ajuda. “Entendendo o desempenho de processamento). e explica a mudança para multicores. Não entre em pânico! Sim. Acrônimo  Uma palavra cam! Para ajudá-lo a lembrar e localizar termos. Ele apresenta as ideias e definições básicas. PCIE. a tecnologia que estimula a revolução dos computadores. Determina o número de instruções Capítulos 2 e 3 compilador e arquitetura de máquina para cada instrução em nível de fonte Processador e sistema Determina a velocidade em que as Capítulos 4. que podem incluir operações de entrada/saída (E/S). CPU. Esses elementos resumem importantes conceitos quanto ao desempenho do programa. 6 Capítulo 1  Abstrações e Tecnologias Computacionais podem ser encontradas no final do capítulo. As questões “Verifique você mesmo” apare- cem apenas no final de uma seção, fazendo com que fique mais fácil pulá-las se você es- tiver certo de que entendeu o assunto. 1. A Seção 1.1 mostrou que o número de processadores embutidos vendidos a cada ano supera, e muito, o número de processadores para desktops. Você pode confir- mar ou negar isso com base em sua própria experiência? Tente contar o número de processadores embutidos na sua casa. Compare esse número com o número de computadores desktop em sua casa. 2. Como mencionado anteriormente, tanto o software quanto o hardware afetam o desempenho de um programa. Você pode pensar em exemplos em que cada um dos fatores a seguir é o responsável pelo gargalo no desempenho? j O algoritmo escolhido j A linguagem de programação ou compilador j O sistema operacional j O processador j O sistema de E/S e os dispositivos Em Paris, eles simplesmente olhavam perdidos quando eu falava em francês; nunca 1.2   Por trás do programa consegui fazer aqueles idiotas entenderem sua própria Uma aplicação típica, como um processador de textos ou um grande sistema de banco de língua. dados, pode consistir em milhões de linhas de código e se basear em bibliotecas de soft- Mark Twain, The ware sofisticadas que implementam funções complexas no apoio à aplicação. Como vere- Innocents Abroad, 1869 mos, o hardware em um computador só pode executar instruções de baixo nível extrema- mente simples. Ir de uma aplicação complexa até as instruções simples envolve várias camadas de software que interpretam ou traduzem operações de alto nível nas instruções simples do computador. A Figura 1.2 mostra que essas camadas de software são organizadas principalmente de maneira hierárquica, na qual as aplicações são o anel mais externo e uma variedade de software de sistemas  Software software de sistemas situa-se entre o hardware e as aplicações. que fornece serviços que normalmente são úteis, incluindo sistemas operacionais, compiladores e montadores. FIGURA 1.2  Uma visão simplificada do hardware e software como camadas hierárquicas, mos- tradas como círculos concêntricos, em que o hardware está no centro e as aplicações aparecem externamente. Nas aplicações complexas, muitas vezes existem múltiplas camadas de software de aplicação. Por exemplo, um sistema de banco de dados pode ser executado sobre o software de sistemas hospedando uma aplicação, que, por sua vez, executa sobre o banco de dados. 1.2  Por trás do programa 7 Existem muitos tipos de software de sistemas, mas dois tipos são fundamentais em todos os sistemas computacionais modernos: um sistema operacional e um compilador. Um sistema operacional fornece a interface entre o programa de usuário e o hardware e Sistema operacional  Programa disponibiliza diversos serviços e funções de supervisão. Entre as funções mais importantes de supervisão que gerencia os estão: recursos de um computador em favor dos programas executados j Manipular as operações básicas de entrada e saída nessa máquina. j Alocar armazenamento e memória j Possibilitar e controlar o compartilhamento do computador entre as diversas apli- cações que o utilizam simultaneamente Exemplos de sistemas operacionais em uso hoje são Linux, MacOS e Windows. Os compiladores realizam outra função fundamental: a tradução de um programa es- compilador  Um programa que crito em uma linguagem de alto nível, como C, C + +, Java ou Visual Basic, em instruções traduz as instruções de linguagem de alto nível para instruções de que o hardware possa executar. Em razão da sofisticação das linguagens de programação linguagem assembly. modernas e das instruções simples executadas pelo hardware, a tradução de um programa de linguagem de alto nível para instruções de hardware é complexa. Voltaremos a um breve resumo do processo aqui e depois entraremos em mais detalhes no Capítulo 2 e no Apêndice B. De uma linguagem de alto nível para a linguagem do hardware Para poder falar com uma máquina eletrônica, você precisa enviar sinais elétricos. Os sinais mais fáceis de serem entendidos pelas máquinas são ligado e desligado; portanto, o alfabeto da máquina se resume a apenas duas letras. Assim como as 26 letras do alfabeto português não limitam o quanto pode ser escrito, as duas letras do alfabeto do computador não limitam o que os computadores podem fazer. Os dois símbolos para essas duas letras são os números 0 e 1, e normalmente pensamos na linguagem de máquina como números na base 2, ou números binários. Chamamos cada “letra” de um dígito binário ou bit. Os dígito binário computadores são escravos dos nossos comandos, chamados de instruções. As instruções, Também chamado bit. Um que são apenas grupos de bits que o computador entende e obedece, podem ser imaginadas dos dois números na base 2 (0 ou 1) que são os componentes da como números. Por exemplo, os bits informação. 1000110010100000 Instrução Um comando que o hardware do dizem ao computador para somar dois números. O Capítulo 2 explica por que usamos computador entende e obedece. números para instruções e dados; não queremos roubar o brilho desse capítulo, mas usar números para instruções e dados é um dos conceitos básicos da computação. Os primeiros programadores se comunicavam com os computadores em números binários, mas isso era tão maçante que rapidamente inventaram novas notações mais parecidas com a maneira como os humanos pensam. No início, essas notações eram traduzidas para binário manualmente, mas esse processo ainda era cansativo. Usando a própria máquina para ajudar a programá-la, os pioneiros inventaram programas que traduzem da notação simbólica para binário. O primeiro desses programas foi chamado de montador (assembler). Esse programa traduz uma versão simbólica de uma instrução montador (assembler) para uma versão binária. Por exemplo, o programador escreveria Um programa que traduz uma versão simbólica de instruções para a versão binária. add A,B e o montador traduziria essa notação como 1000110010100000 8 Capítulo 1  Abstrações e Tecnologias Computacionais Essa instrução diz ao computador para somar dois números, A e B. O nome criado para linguagem assembly essa linguagem simbólica, ainda em uso hoje, é linguagem assembly. Ao contrário, a lin- Uma representação simbólica das guagem binária que a máquina entende é a linguagem de máquina. instruções de máquina. Embora seja um fantástico avanço, a linguagem assembly ainda está longe da notação linguagem de máquina que um cientista poderia desejar usar para simular fluxos de fluidos ou que um conta- Uma representação binária das dor poderia usar para calcular seus saldos de contas. A linguagem assembly requer que instruções de máquina. o programador escreva uma linha para cada instrução que a máquina seguirá, obrigando o programador a pensar como a máquina. A descoberta de que um programa poderia ser escrito para traduzir uma linguagem mais poderosa em instruções de computador foi um dos mais importantes avanços nos primeiros dias da computação. Os programadores atuais devem sua produtividade – e sua linguagem de programação sanidade mental – à criação de linguagens de programação de alto nível e de compiladores de alto nível  Uma linguagem, que traduzem os programas escritos nessas linguagens em instruções. A Figura 1.3 mostra como C, C++, Java ou Visual os relacionamentos entre esses programas e linguagens. Basic, composta de palavras e notação algébrica, que pode ser Um compilador permite que um programador escreva esta expressão em linguagem traduzida por um compilador para de alto nível: a linguagem assembly. A +B FIGURA 1.3  Programa em C compilado para assembly e depois montado em linguagem de máquina. Embora a tradução de linguagem de alto nível para a linguagem de máquina seja mostrada em duas etapas, alguns compiladores removem a fase intermediária e produzem linguagem de máquina diretamente. Essas linguagens e esse programa são analisados com mais detalhes no Capítulo 2. 1.3  Sob as tampas 9 O compilador compilaria isso na seguinte instrução em assembly: add A,B Como podemos ver, o montador traduziria essa instrução para a instrução binária, que diz ao computador para somar os dois números, A e B. As linguagens de programação de alto nível oferecem vários benefícios importantes. Primeiro, elas permitem que o programador pense em uma linguagem mais natural, usando palavras em inglês e notação algébrica, resultando em programas que se parecem muito mais com texto do que com tabelas de símbolos enigmáticos (veja a Figura 1.3). Além disso, elas permitem que linguagens sejam projetadas de acordo com o uso pretendido. É por isso que a linguagem Fortran foi projetada para computação científica, Cobol para proces- samento de dados comerciais, Lisp para manipulação de símbolos e assim por diante. Há também linguagens específicas de domínio para grupos ainda mais estreitos de usuários, como aqueles interessados em simulação de fluidos, por exemplo. A segunda vantagem das linguagens de programação é a maior produtividade do pro- gramador. Uma das poucas áreas em que existe consenso no desenvolvimento de software é que é necessário menos tempo para desenvolver programas quando são escritos em linguagens que exigem menos linhas para expressar uma ideia. A concisão é uma clara vantagem das linguagens de alto nível em relação à linguagem assembly. A última vantagem é que as linguagens de programação permitem que os programas sejam independentes do computador no qual elas são desenvolvidas, já que os compiladores e montadores podem traduzir programas de linguagem de alto nível para instruções binárias de qualquer máquina. Essas três vantagens são tão fortes que, atualmente, pouca programação é realizada em assembly. 1.3   Sob as tampas Agora que olhamos por trás do programa para descobrir como ele funciona, vamos abrir a tampa do computador para aprender sobre o hardware dentro dele. O hardware de qualquer computador realiza as mesmas funções básicas: entrada, saída, processamento e armazenamento de dados. A forma como essas funções são realizadas é o principal tema deste livro, e os capítulos subsequentes lidam com as diferentes partes dessas quatro tarefas. Quando tratamos de um aspecto importante neste livro, tão importante que esperamos que você se lembre dele para sempre, nós o enfatizamos identificando-o como um item “Colocando em perspectiva”. Há aproximadamente 12 desses itens no livro; o primeiro descreve os cinco componentes de um computador que realizam as tarefas de entrada, saída, processamento e armazenamento de dados. Os cinco componentes de um computador são entrada, saída, memória, caminho de dados e controle; os dois últimos, às vezes, são combinados e chamados de em processador. A Figura 1.4 mostra a organização padrão de um computador. Essa organização é independente da tecnologia de hardware: você pode classificar Colocando cada parte de cada computador, antigos ou atuais, em uma dessas cinco categorias. perspectiva Para ajudar a manter tudo isso em perspectiva, os cinco componentes de um computador são mostrados na primeira página dos capítulos seguintes, com a parte relativa ao capítulo destacada. 10 Capítulo 1  Abstrações e Tecnologias Computacionais FIGURA 1.4  A organização de um computador, mostrando os cinco componentes clássicos. O processador obtém instruções e dados da memória. A entrada escreve dados na memória, e a saída lê os dados desta. O controle envia os sinais que determinam as operações do caminho de dados, da memória, da entrada e da saída. A Figura 1.5 mostra um computador desktop típico com teclado, mouse sem fio e monitor. Essa fotografia revela dois dos principais componentes dos computadores: os dispositivo de entrada  Um dispositivos de entrada, como o teclado e o mouse, e os dispositivos de saída, como o mecanismo por meio do qual o monitor. Como o nome sugere, a entrada alimenta o computador, e a saída é o resultado computador é alimentado com da computação, enviado para o usuário. Alguns dispositivos, como redes e discos, forne- informações, como o teclado e o mouse. cem tanto entrada quanto saída para o computador. O Capítulo 6 descreve dispositivos de entrada e saída (E/S) em mais detalhes, mas dispositivo de saída  Um vamos dar um passeio introdutório pelo hardware do computador, começando com os mecanismo que transmite o dispositivos de E/S externos. resultado de uma computação para o usuário ou para outro computador. Anatomia do mouse Tive a ideia de criar o mouse Embora muitos usuários agora aceitem o mouse sem questionar, a ideia de um dispositi- enquanto ouvia uma palestra vo apontador como um mouse foi mostrada pela primeira vez por Doug Engelbart usan- de uma conferência. O orador do um protótipo em 1967. A Alto, que foi a inspiração para todas as estações de trabalho, era tão chato que comecei a inclusive para o Macintosh, incluiu um mouse como seu dispositivo apontador em 1973. me distrair e conceber a ideia. Na década de 1990, todos os computadores desktop tinham esse dispositivo, e as novas interfaces gráficas com o usuário e os mouses se tornaram regra. Doug Engelbart O mouse original era eletromecânico e usava uma grande esfera que, quando rolada sobre uma superfície, fazia com que um contador x e um y fossem incrementados. A quantidade do aumento de cada contador informava a distância e a direção em que o mouse tinha sido movido. O mouse eletromecânico está sendo substituído pelo novo mouse ótico. O mouse ótico é, na verdade, um processador ótico em miniatura incluindo um LED para fornecer iluminação, uma minúscula câmera em preto e branco e um processador ótico simples. O LED ilumina a superfície abaixo do mouse; a câmera tira 1.500 fotografias em cada segundo 1.3  Sob as tampas 11 FIGURA 1.5  Um computador desktop. O monitor de cristal líquido (LCD) é o principal dispositivo de saída, e o teclado e o mouse são os principais dispositivos de entrada. À direita está um cabo Ethernet que conecta o laptop à rede e à Web. O laptop contém o processador, a memória e os dispositivos de E/S adicionais. Esse sistema é um laptop Macbook Pro 15” conectado a um monitor externo. sob a iluminação. Os quadros sucessivos são enviados para um processador ótico simples, Pela tela do computador que compara as imagens e determina se e quanto o mouse foi movido. A substituição aterrissei um avião no pátio do mouse eletromecânico pelo mouse eletro-óptico é uma ilustração de um fenômeno de uma transportadora, comum, no qual os custos cada vez menores e a segurança cada vez maior fazem uma observei uma partícula solução eletrônica substituir a tecnologia eletromecânica mais antiga. Mais tarde, veremos nuclear colidir com uma fonte outro exemplo: a memória flash. potencial, voei em um foguete quase na velocidade da luz Diante do espelho e vi um computador revelar seus sistemas mais íntimos. Talvez o dispositivo de E/S mais fascinante seja o monitor gráfico. Todos os computadores laptop e portáteis, calculadoras, telefones celulares e quase todos os computadores desktop Ivan Sutherland, o “pai” da agora utilizam monitores de cristal líquido (LCDs) para obterem uma tela fina, com baixa computação gráfica, potência. O LCD não é a fonte da luz; em vez disso, ele controla a transmissão da luz. Um Scientific American, 1984 LCD típico inclui moléculas em forma de bastão em um líquido que forma uma hélice giratória que encurva a luz que entra na tela, de uma fonte de luz atrás da tela ou, menos frequentemente, da luz refletida. Os bastões se esticam quando uma corrente é aplicada e monitor de cristal líquido  não encurvam mais a luz. Como o material de cristal líquido está entre duas telas polari- Uma tecnologia de vídeo usando zadas a 90 graus, a luz não pode passar a não ser que esteja encurvada. Hoje, a maioria dos uma fina camada de polímeros líquidos que podem ser usados monitores LCD utiliza uma matriz ativa que tem uma minúscula chave de transistor para transmitir ou bloquear a luz em cada pixel para controlar a corrente com precisão e gerar imagens mais nítidas. Uma conforme uma corrente seja ou não máscara vermelha-verde-azul associada a cada ponto na tela determina a intensidade aplicada. dos três componentes de cor na imagem final; em um LCD de matriz ativa colorida, existem três chaves de transistor em cada ponto. monitor de matriz ativa  Um monitor de cristal líquido A imagem é composta de uma matriz de elementos de imagem, ou pixels, que podem usando um transistor para ser representados como uma matriz de bits, chamada mapa de bits, ou bitmap. Dependen- controlar a transmissão da luz em do do tamanho da tela e da resolução, o tamanho da matriz de vídeo variava de 640 × 480 cada pixel individual. 12 Capítulo 1  Abstrações e Tecnologias Computacionais pixel  O menor elemento da a 2560 × 1600 pixels em 2008. Um monitor colorido pode usar 8 bits para cada uma das imagem. A tela é composta de três cores primárias (vermelho, verde e azul), totalizando 24 bits por pixel, permitindo que centenas de milhares a milhões de milhões de cores diferentes sejam exibidas. pixels, organizados em uma matriz. O suporte de hardware do computador para a utilização de gráficos consiste principal- mente em um buffer de atualização de varredura, ou buffer de quadros, para armazenar o mapa de bits. A imagem a ser representada na tela é armazenada no buffer de quadros, e o padrão de bits de cada pixel é lido para o monitor gráfico a uma certa taxa de atualização. A Figura 1.6 mostra um buffer de quadros com 4 bits por pixel. FIGURA 1.6  Cada coordenada no buffer de quadros à esquerda determina o tom da coordenada correspondente para o monitor TRC de varredura à direita. O pixel (X0, Y0) contém o padrão de bits 0011, que, na tela, é um tom de cinza mais claro do que o padrão de bits 1101 no pixel (X1, Y1). placa-mãe  Uma placa de plástico contendo pacotes de circuitos integrados ou chips, incluindo O objetivo do mapa de bits é representar fielmente o que está na tela. As dificuldades processador, cache, memória e dos sistemas gráficos surgem porque o olho humano é muito bom em detectar mesmo as conectores para dispositivos de E/S, como redes e discos. mais sutis mudanças na tela. circuito integrado  Também Abrindo o gabinete chamado chip, é um dispositivo que combina de dezenas a milhões de Se abrirmos o gabinete de um computador, veremos uma interessante placa de plástico, transistores. coberta com dezenas de pequenos retângulos cinzas ou pretos. A Figura 1.7 mostra o conteúdo do computador laptop da Figura 1.5. A placa-mãe é mostrada na parte superior memória  A área de armazenamento temporária em que da foto. Duas unidades de disco estão na frente – o disco rígido à esquerda e uma unidade os programas são mantidos quando de DVD à direita. O furo no meio é para a bateria do laptop. estão sendo executados e que Os pequenos retângulos na placa-mãe contêm os dispositivos que impulsionam nossa contém os dados necessários para tecnologia avançada, os circuitos integrados, apelidados de chips. A placa é composta de os programas em execução. três partes: a parte que se conecta aos dispositivos de E/S mencionados anteriormente, a memória e o processador. RAM dinâmica (DRAM)  Memória construída como um A memória é onde os programas são mantidos quando estão sendo executados; ela circuito integrado para fornecer também contém os dados necessários aos programas em execução. Na Figura 1.8, a memó- acesso aleatório a qualquer local. ria é encontrada nas duas pequenas placas, e cada pequena placa de memória contém oito circuitos integrados. A memória na Figura 1.8 é construída de chips DRAM. DRAM signi- dual inline memory module fica RAM dinâmica (Dynamic Random Access Memory). Várias DRAMs são usadas em (DIMM)  Uma pequena placa que conjunto para conter as instruções e os dados de um programa. Ao contrário das memórias contém chips DRAM em ambos os lados. (Os SIMMs possuem DRAMs de acesso sequencial, como as fitas magnéticas, a parte RAM do termo DRAM significa que em apenas um lado.) os acessos à memória levam o mesmo tempo independente da parte da memória lida. O processador é a parte ativa da placa, que segue rigorosamente as instruções de um unidade central de programa. Ele soma e testa números, sinaliza dispositivos de E/S para serem ativados e processamento (CPU)  Também assim por diante. O processador é o quadrado abaixo da ventoinha e coberto por um dis- chamada de processador. A parte ativa do computador, que contém sipador de calor à esquerda na Figura 1.7. Ocasionalmente, as pessoas chamam o proces- o caminho de dados e o controle e sador de CPU, que significa o termo pomposo unidade central de processamento. que soma e testa números e sinaliza Penetrando ainda mais no hardware, a Figura 1.9 revela detalhes de um microprocessador. dispositivos de E/S para que sejam O processador contém dois componentes principais: o caminho de dados e o controle, ativados etc. correspondendo, respectivamente, aos músculos e ao cérebro do processador. O caminho 1.3  Sob as tampas 13 FIGURA 1.7  Dentro do computador laptop da Figura 1.5. A pequena caixa com o rótulo branco no canto caminho de dados  O componente inferior esquerdo é uma unidade de disco rígido SATA de 100 GB, e a pequena caixa de metal no canto inferior direito do processador que realiza é a unidade de DVD. O espaço entre elas é onde ficaria a bateria do laptop. O pequeno furo acima do espaço da bateria operações aritméticas. é para as memórias DIMMs. A Figura 1.8 é uma imagem ampliada das DIMMs, que são inseridas por baixo nesse laptop. Acima do espaço da bateria e da unidade de DVD existe uma placa de circuito impresso, chamada placa-mãe, controle  O componente do que contém a maior parte da eletrônica do computador. Os dois pequenos círculos na metade superior da figura são processador que comanda o duas ventoinhas com tampas. O processador é o grande retângulo elevado logo abaixo da ventoinha da esquerda. Foto caminho de dados, a memória e os por cortesia da OtherWorldComputing.com. dispositivos de E/S de acordo com as instruções do programa. de dados realiza as operações aritméticas, e o controle diz ao caminho de dados, à memória memória cache  Uma memória e aos dispositivos de E/S o que fazer de acordo com as instruções do programa. O Capítulo 4 pequena e rápida que age como um explica o caminho de dados e o controle para um projeto de desempenho mais alto. buffer para uma memória maior e Descer até as profundezas de qualquer componente de hardware revela os interiores da mais lenta. máquina. Dentro do processador, existe outro tipo de memória – a memória cache. A memória cache consiste em uma memória pequena e rápida que age como um buffer Static Random Access Memory (SRAM)  Também uma memória para a memória DRAM. (A definição não-técnica de cache é um lugar seguro para es- montada como um circuito conder as coisas.) A cache é construída usando uma tecnologia de memória diferente, a integrado, porém mais rápida e RAM estática – Static Random Access Memory (SRAM). A SRAM é mais rápida, mas menos densa que a DRAM. menos densa e, portanto, mais cara do que a DRAM. Você pode ter observado um conceito comum nas descrições de software e de hardwa- abstração  Um modelo que revela detalhes de nível inferior re: penetrar nas profundezas do hardware ou software revela mais informações, ou seja, dos sistemas computacionais detalhes de nível mais baixo estão ocultos para oferecer um modelo mais simples aos níveis temporariamente invisíveis, a fim mais altos. O uso dessas camadas, ou abstrações, é uma técnica importante para projetar de facilitar o projeto de sistemas sistemas computacionais extremamente sofisticados. sofisticados. 14 Capítulo 1  Abstrações e Tecnologias Computacionais FIGURA 1.8  Close do fundo do laptop revela a memória. A memória principal está contida em uma ou mais placas pequenas mostradas à esquerda. O furo para a bateria está à direita. Os chips de DRAM são montados nessas placas (chamadas Dual Inline Memory Modules – DIMMs) e, então, ligados aos conectores. Foto por cortesia da OtherWorldComputing.com. FIGURA 1.9  Dentro do microprocessador AMD Barcelona. O lado esquerdo é uma microfotografia do chip processador AMD Barcelona, e o lado direito mostra os principais blocos no processador. O chip tem quatro processadores ou “cores”. O microprocessador no laptop da Figura 1.8 tem dois cores por chip, chamado Intel Core 2 Duo. Uma das abstrações mais importantes é a interface entre o hardware e o software de nível arquitetura do conjunto de mais baixo. Em decorrência de sua importância, ela recebe um nome especial: a arquitetu- instruções  Também chamada ra do conjunto de instruções, ou simplesmente arquitetura, de uma máquina. A arquite- simplesmente de arquitetura. Uma tura do conjunto de instruções inclui tudo o que os programadores precisam saber para interface abstrata entre o hardware e o software de nível mais baixo fazer um programa em linguagem de máquina binária funcionar corretamente, incluindo de uma máquina que abrange instruções, dispositivos de E/S etc. Em geral, o sistema operacional encapsulará os detalhes todas as informações necessárias da E/S, da alocação de memória e de outras funções de baixo nível do sistema, para que os para escrever um programa em programadores das aplicações não precisem se preocupar com esses detalhes. A combinação linguagem de máquina que será do conjunto de instruções básico e a interface do sistema operacional fornecida para os corretamente executado, incluindo instruções, registradores, acesso à programadores das aplicações é chamada de interface binária de aplicação (ABI). memória, E/S e assim por diante. Uma arquitetura do conjunto de instruções permite aos projetistas de computador falarem sobre funções independente do hardware que as realiza. Por exemplo, podemos falar sobre as funções de um relógio digital (marcar as horas, exibir as horas, definir o 1.3  Sob as tampas 15 alarme) sem falar sobre o hardware do relógio (o cristal de quartzo, os visores de LEDs, os interface binária de aplicação botões plásticos). Os projetistas de computador distinguem entre a arquitetura e uma (ABI)  A parte voltada ao usuário do conjunto de instruções mais as implementação da arquitetura da mesma maneira: uma implementação é o hardware que interfaces do sistema operacional obedece à abstração da arquitetura. Esses conceitos nos levam a outra seção “Colocando usadas pelos programadores das em perspectiva”. aplicações. Define um padrão para a portabilidade binária entre computadores. implementação  Hardware que obedece à abstração de uma arquitetura. Tanto o hardware quanto o software consistem em camadas hierárquicas, com cada camada inferior ocultando detalhes do nível acima. Esse princípio de abs- em tração é o modo como os projetistas de hardware e os de software lidam com a complexidade dos sistemas computacionais. Uma interface-chave entre os níveis Colocando de abstração é a arquitetura do conjunto de instruções — a interface entre o perspectiva hardware e o software de baixo nível. Essa interface abstrata permite que mui- tas implementações com custo e desempenho variáveis executem um software idêntico. memória volátil  Armazenamento, como a DRAM, que conserva os dados apenas enquanto estiver recebendo energia. memória não volátil  Uma forma de memória que conserva os dados Um lugar seguro para os dados mesmo na ausência de energia e que Até agora, vimos como os dados são inseridos, processados e exibidos. Entretanto, se é usada para armazenar programas entre execuções. O disco magnético é houvesse uma interrupção no fornecimento de energia, tudo seria perdido porque a me- não volátil. mória dentro do computador é volátil – ou seja, quando perde energia, ela se esquece. Por outro lado, um DVD não se esquece da música gravada quando você desliga o aparelho memória principal  A memória usada para armazenar os programas de DVD e, portanto, é uma tecnologia de memória não volátil. enquanto estão sendo executados; Para distinguir entre a memória usada para armazenar dados e programas enquanto normalmente consiste na DRAM nos estão sendo executados e essa memória não volátil usada para armazenar programas entre computadores atuais. as execuções, o termo memória principal é usado para o primeiro e o termo memória memória secundária  Memória secundária é usado para o último. As DRAMs dominam a memória principal desde 1975; não volátil usada para armazenar e os discos magnéticos dominam a memória secundária desde 1965. O principal armaze- programas e dados entre execuções; namento não volátil usado em todos os computadores servidores e estações de trabalho normalmente consiste em discos é o disco rígido magnético. A memória flash, uma memória semicondutora não volátil, é magnéticos nos computadores atuais. usada no lugar dos discos em dispositivos móveis, como telefones celulares, e está cada vez mais substituindo os discos em tocadores de música e laptops. disco magnético (também Como mostra a Figura 1.10, um disco rígido magnético consiste em uma série de discos, chamado de disco rígido)  Uma forma de memória secundária que giram em torno de um eixo a velocidades que variam entre 5.400 e 15.000 rotações não volátil composta por discos por minuto. Os discos de metal são cobertos por um material de gravação magnético em giratórios cobertos com um ambos os lados, semelhante ao material encontrado em uma fita cassete ou de vídeo. Para material de gravação magnético. ler e gravar informações em um disco rígido, um braço móvel com um pequena bobina memória flash  Uma memória eletromagnética, chamada de cabeça de leitura/gravação, é localizada pouco acima de cada semicondutora não volátil. Ela superfície. A unidade inteira é selada permanentemente para controlar o ambiente dentro é mais barata e mais lenta que a da unidade, o que, por sua vez, permite que as cabeças do disco estejam muito mais DRAM, porém mais cara e mais próximas da superfície da unidade. rápida que os discos magnéticos. O uso de componentes mecânicos significa que os tempos de acesso para os discos gigabyte  Tradicionalmente, magnéticos são muito maiores do que para as DRAMs: os discos em geral levam de 5 a 1.073.741.824 (230) bytes, embora 20 milissegundos, enquanto as DRAMs levam de 50 a 70 nanossegundos – tornando as alguns sistemas de comunicações e de armazenamento secundário DRAMs cerca de 100.000 vezes mais rápidas. Entretanto, os discos possuem custos muito o tenham definido como mais baixos do que a DRAM para a mesma capacidade de armazenamento, pois os custos 1.000.000.000 (109) bytes. De de produção para uma determinada quantidade de armazenamento em disco são menores modo semelhante, dependendo do do que para a mesma quantidade de circuito integrado. Em 2008, o custo por gigabyte de contexto, o megabyte é 220 ou 106 disco era aproximadamente de 30 a 100 vezes menor do que o custo da DRAM. bytes. 16 Capítulo 1  Abstrações e Tecnologias Computacionais FIGURA 1.10  Uma unidade de disco mostrando 10 discos e as cabeças de leitura/gravação. Os diâmetros dos discos rígidos atuais variam por um fator de mais de 3, de menos de 2,5cm até 9cm, e têm sido reduzidos ao longo dos anos para se adequarem a novos produtos; servidores, estações de trabalho, computadores pessoais, laptops, palmtops e câmeras digitais têm inspirado novos tamanhos de disco. Tradicionalmente, os discos maiores possuem melhor desempenho, os discos menores possuem o menor custo, e o melhor custo por gigabyte varia. Embora a maioria dos discos rígidos apareça dentro dos computadores (como na Figura 1.7), os discos rígidos também podem ser conectados usando-se interfaces externas, como Universal Serial Bus (USB). Assim, existem três principais diferenças entre os discos magnéticos e a memória principal: os discos não são voláteis porque são magnéticos; possuem um tempo de acesso maior porque são dispositivos mecânicos; e são mais baratos por gigabyte porque possuem capacidade de armazenamento muito alta a um custo razoável. Muitos tentaram inventar uma tecnologia mais barata que a DRAM, porém mais rápida que o disco, para preencher a lacuna, mas fracassaram. Os desafiantes nunca levaram um produto ao mercado no momento certo. Quando um novo produto estava para ser en- tregue, as DRAMs e os discos continuavam a ter avanços rápidos, os custos caíam de modo correspondente e os produtos desafiantes ficavam imediatamente obsoletos. A memória flash, porém, é um desafiante sério. Essa memória semicondutora é não volátil como os discos e tem aproximadamente a mesma largura de banda, mas a latência é 100 a 1.000 vezes mais rápida que o disco. Flash é popular em câmeras e players de música portáteis, pois vem com capacidades muito menores, é mais reforçado e mais eficiente em termos de potência do que os discos, apesar de o custo por gigabyte em 2008 ser cerca de 6 a 10 vezes maior que o de disco. Diferente dos discos e da DRAM, os bits da memória flash se desgastam após 100.000 a 1.000.000 de escritas. Assim, os sistemas de arquivo precisam registrar o número de escritas e ter uma estratégia para evitar desgastar o armazenamento, por exemplo, movendo dados populares. O Capítulo 6 descreve a memória flash com mais detalhes. Embora os discos rígidos não sejam removíveis, há várias tecnologias de armazenamento em uso que incluem as seguintes: j Os discos óticos, incluindo os compact disks (CDs) e digital video disks (DVDs), cons- tituem a forma mais comum de armazenamento removível. O padrão de disco ótico Blu-Ray (BD) é o aparente sucessor do DVD. 1.3  Sob as tampas 17 j As placas de memória removíveis baseadas em FLASH geralmente são conectadas por uma conexão Universal Serial Bus (USB) e muitas vezes são usadas para transferir arquivos. j A fita magnética fornece apenas acesso serial lento e tem sido usada para realização de backups de disco – uma função que, hoje, normalmente está sendo substituída por discos rígidos duplicados. A tecnologia de disco ótico funciona de uma maneira completamente diferente da tecnologia de disco magnético. Em um CD, os dados são gravados em espiral, com os bits individuais gravados queimando-se pequenas cavidades – de aproximadamente 1 micron (10-6 metros) de diâmetro – na superfície do disco. O disco é lido emitindo-se um laser na superfície do CD e determinando-se, pelo exame da luz refletida, se existe uma cavidade ou uma superfície plana (reflexiva). Os DVDs usam o mesmo método de emissão de um feixe de laser em direção a uma série de cavidades e superfícies planas. Além disso, há diversas camadas em que o feixe de laser pode ser focalizado, e o tamanho de cada cavidade é muito menor, o que, em conjunto, representa um significativo aumento na capacidade. Blu-Ray utiliza lasers com menor comprimento de onda, o que reduz o tamanho dos bits e, portanto, aumenta a capacidade. Os gravadores de disco ótico nos computadores pessoais usam um laser para criar as cavidades na camada de gravação na superfície do CD ou DVD. Esse processo de gravação é relativamente lento, levando de minutos (para um CD inteiro) a dezenas de minutos (para um DVD inteiro). Portanto, para grandes quantidades, é usada uma técnica diferente, chamada impressão, que custa apenas alguns centavos por disco ótico. Os CDs e DVDs regraváveis usam uma superfície de gravação diferente que possui um material reflexivo cristalino; as cavidades não reflexivas são formadas de maneira seme- lhante ao CD ou DVD de gravação única. Para apagar o CD ou DVD, a superfície é aquecida e resfriada lentamente, permitindo um processo de recozimento para restaurar a camada de gravação da superfície à sua estrutura cristalina original. Esses discos regraváveis são mais caros do que os discos de gravação única; para os discos somente de leitura – usados para distribuir software, música ou filmes – os custos do disco e da gravação são muito menores. Comunicação com outros computadores Explicamos como podemos realizar entrada, processamento, exibição e armazenamento de dados, mas ainda falta um item que é encontrado nos computadores modernos: as redes de computadores. Exatamente como o processador mostrado na Figura 1.4 está conectado à memória e aos dispositivos de E/S, as redes conectam computadores inteiros, permitindo que os usuários estendam a capacidade de computação incluindo a comu- nicação. As redes se tornaram tão comuns que, hoje, constituem o backbone (espinha dorsal) dos sistemas de computação atuais; uma máquina nova sem uma interface de rede opcional seria ridicularizada. Os computadores em rede possuem diversas vantagens importantes: j Comunicação: as informações são trocadas entre computadores em altas velocidades. j Compartilhamento de recursos: em vez de cada máquina ter seus próprios dispositivos de E/S, os dispositivos podem ser compartilhados pelos computadores que compõem a rede. j Acesso remoto: conectando computadores por meio de longas distâncias, os usuários não precisam estar perto do computador que estão usando. As redes variam em tamanho e desempenho, com o custo da comunicação aumentan- do de acordo com a velocidade de comunicação e a distância em que as informações viajam. Talvez o tipo de rede mais comum seja a Ethernet. Sua extensão é limitada em aproximadamente um quilômetro, transferindo até 10 gigabits por segundo. Sua extensão e velocidade tornam a Ethernet útil para conectar computadores no mesmo andar de um 18 Capítulo 1  Abstrações e Tecnologias Computacionais rede local (LAN)  Uma rede prédio; portanto, esse é um exemplo do que é chamado genericamente de rede local (LAN). projetada para transportar As redes locais são interconectadas com switches que também podem fornecer serviços de dados dentro de uma área roteamento e segurança. As redes remotas (WAN) atravessam continentes e são a espinha geograficamente restrita, em geral, dentro de um mesmo prédio. dorsal da Internet, que é o suporte da World Wide Web. Elas costumam ser baseadas em cabos de fibra ótica e são alugadas de empresas de telecomunicações. rede remota (WAN)  Uma As redes mudaram a cara da computação nos últimos 25 anos, por se tornarem muito rede estendida por centenas de mais comuns e aumentarem dramaticamente o desempenho. Na década de 1970, poucas quilômetros, que pode atravessar pessoas tinham acesso ao correio eletrônico (e-mail). A Internet e a Web não existiam, e a continentes. remessa física de fitas magnéticas era o meio principal de transferir grandes quantidades de dados entre dois locais. Nessa década, as redes locais eram quase inexistentes e as poucas redes remotas existentes tinham capacidade limitada e acesso restrito. À medida que a tecnologia de redes avançou, ela se tornou muito mais barata e obteve uma capacidade de transmissão muito mais alta. Por exemplo, a primeira tecnologia de rede local a ser padronizada, desenvolvida há cerca de 25 anos, foi uma versão da Ethernet que tinha uma capacidade máxima (também chamada de largura de banda) de 10 mi- lhões de bits por segundo, normalmente compartilhada por dezenas, se não centenas, de computadores. Hoje, a tecnologia de rede local oferece uma capacidade de transmissão de 100 milhões de bits por segundo até 10 gigabits por segundo, em geral compartilhada por, no máximo, alguns computadores. A tecnologia de comunicação ótica permitiu um crescimento semelhante na capacidade das redes remotas de centenas de kilobits até gigabits, e de centenas de computadores conectados a uma rede mundial até milhões de computadores conectados. Essa combinação do dramático aumento no emprego das redes e os aumentos em sua capacidade tornaram a tecnologia de redes o ponto central para a revolução da informação nos últimos 25 anos. Recentemente, outra inovação na tecnologia de redes está reformulando a maneira como os computadores se comunicam. A tecnologia sem fio se tornou amplamente utilizada e a maioria dos laptops hoje incorpora essa tecnologia. A capacidade de criar um rádio com a mesma tecnologia de semicondutor de baixo custo (CMOS) usada para memória e microprocessadores permitiu uma significativa melhoria no preço, levando a uma explosão no consumo. As tecnologias sem fio disponíveis atualmente, conhecidas pelo padrão IEEE 802.11, permitem velocidades de transmissão de 1 a quase 100 milhões de bits por segundo. A tecnologia sem fio é um pouco diferente das redes baseadas em fios, já que todos os usuários em uma área próxima compartilham as ondas aéreas. Verifique você j A DRAM e o armazenamento de disco diferem significativamente. Descreva a mesmo principal diferença quanto a cada um dos seguintes aspectos: volatilidade, tempo de acesso e custo. Tecnologias para construção de processadores e memórias Os processadores e a memória melhoraram em uma velocidade espantosa porque os projetistas de computadores, durante muito tempo, abraçaram o que havia de mais mo- derno na tecnologia eletrônica a fim de tentar vencer a corrida para projetar um compu- tador melhor. A Figura 1.11 mostra as tecnologias usadas ao longo do tempo, com uma estimativa do desempenho relativo por custo unitário para cada tecnologia. A Seção 1.7 explora a tecnologia que impulsionou a indústria da computação desde 1975 e continuará FIGURA 1.11  Desempenho relativo por custo unitário das tecnologias usadas nos computadores ao longo do tempo. Fonte: Computer Museum, Boston, com o ano de 2005 estimado pelos autores. Ver Seção 1.10 no site. 1.4 Desempenho 19 FIGURA 1.12  Crescimento da capacidade por chip de DRAM ao longo do tempo. O eixo y é medido em Kbits, em que K = 1024 (210). A indústria de DRAM quadruplicou a capacidade a cada quase três anos, um aumento de 60% por ano, durante 20 anos. Nos últimos anos, essa taxa diminuiu um pouco e está próximo do dobro a cada válvula  Um componente dois anos. eletrônico, predecessor do transistor, que consiste em um tubo de vidro oco de aproximadamente 5 a 10 centímetros de comprimento a impulsioná-la no futuro previsível. Como essa tecnologia esboça o que os computadores do qual o máximo de ar foi serão capazes de fazer e a velocidade com que irão evoluir, acreditamos que todos os profis- removido e que usa um feixe de sionais de computação devem estar familiarizados com os fundamentos dos circuitos in- elétrons para transferir dados. tegrados. Um transistor é simplesmente uma chave liga/desliga controlada por eletricidade. O transistor  Uma chave liga/desliga circuito integrado (CI) combinou dezenas a centenas de transistores em um único chip. controlada por um sinal elétrico. Para descrever o incrível aumento no número de transistores de centenas para milhões, o adjetivo escala muito grande é acrescentado ao termo, criando a abreviação VLSI (de Very circuito Very Large Scale Large Scale Integrated). Integrated (VLSI)  Um dispositivo com centenas de milhares a milhões Essa taxa de integração crescente tem se mantido notavelmente estável. A Figura 1.12 de transistores. mostra o crescimento na capacidade da DRAM desde 1977. Durante 20 anos, a indústria quadruplicou consistentemente a capacidade a cada três anos, resultando em um aumento de mais de 16.000 vezes! Esse aumento no número de transistores para um circuito in- tegrado é popularmente conhecido como a Lei de Moore, que diz que a capacidade em transistores dobra a cada 18 a 24 meses. A Lei de Moore resultou de uma previsão desse cres- cimento na capacidade do circuito integrado feita por Gordon Moore, um dos fundadores da Intel durante a década de 1960. Sustentar essa taxa de progresso por quase 40 anos exigiu incríveis inovações nas técnicas de fabricação. Na Seção 1.7, discutimos como os circuitos integrados são fabricados. 1.4  Desempenho Avaliar o desempenho dos computadores pode ser desafiador. A escala e a complexidade dos sistemas de software modernos, junto com a grande variedade de técnicas de me- lhoria de desempenho empregadas por projetistas de hardware, tornaram a avaliação do desempenho muito mais difícil. Ao tentar escolher entre diferentes computadores, o desempenho é um atributo impor- tante. Comparar e avaliar com precisão diferentes computadores é crítico para compradores e por consequência, também para os projetistas. O pessoal que vende computadores também sabe disso. Normalmente, os vendedores desejam que você veja seu computador da melhor maneira possível, não importa se isso reflete ou não as necessidades da aplicação do comprador. Logo, ao escolher um computador, é importante entender como medir melhor o desempenho e as limitações das medições de desempenho. O restante desta seção descreve diferentes maneiras como o desempenho pode ser determinado; depois, descrevemos as métricas para avaliar o desempenho do ponto de vista alcance e velocidade de uma série de aviões comerciais. O tempo total exigido para o Se você estivesse rodando um programa em dois computadores desktop diferentes. Você poderia definir o avião mais rápido como aquele com a velocidade de voo mais alta. o que queremos dizer? Embora essa pergunta possa parecer simples. incluindo acessos ao disco. o avião com o maior alcance é o DC-8. Substituir o processador em um computador por uma versão mais rápida. na maioria dos casos. Se você quisesse saber qual dos aviões nessa tabela tem o melhor desempenho. levando um único passageiro de um ponto para outro com o menor tempo. overhead do sistema usuários. juntamente com a velocidade de cruzeiro. contra servidores. que são mais voltados para o throughput. aplicações para avaliar computadores embutidos e de desktop. FIGURA 1. A última coluna mostra a taxa com que o avião transporta passageiros. além de diferentes conjuntos de completadas por unidade de tempo. Também analisamos como essas métricas estão relacionadas e apresentamos a equação clássica de desempenho do processador. Por exemplo. que são mais voltados para o tempo de resposta. Vamos supor que o desempenho seja definido em termos de velocidade. tempo de execução de tarefas durante um dia. que é a capacidade vezes a velocidade de voo (ignorando o alcance e os tempos de decolagem e pouso).13 mostra alguns aviões de passageiros típicos. Se estivesse gerencian- tarefa. Os gerentes de centro de dados normalmen- throughput  Também chamado te estão interessados em aumentar o throughput ou largura de banda — a quantidade largura de banda. Logo. podemos definir o desempenho do computador tempo de resposta  Também chamado tempo de execução. atividades de E/S. Porém. você está interessado CPU e assim por diante. alcance e capacidade. Outra medida de total de trabalho realizado em determinado tempo. De modo semelhante. diria computador completar uma que o mais rápido é o computador que termina o trabalho primeiro. uma analogia com aviões de passageiros mostra como a questão de desempenho pode ser sutil. você diria que o computador mais rápido é aquele que completasse o máximo de operacional. ainda desempenho. se você estivesse interessado em transportar 450 passageiros de um ponto para outro. Isso ainda deixa duas definições possíveis. A Figura 1. considerando diferentes medidas de desempenho.20 Capítulo 1  Abstrações e Tecnologias Computacionais de um usuário do computador e um projetista. como mostra a última coluna da figura. vemos que o avião com a maior velocidade de cruzeiro é o Concorde. Definindo o desempenho Quando dizemos que um computador tem melhor desempenho que outro. de diferentes maneiras. primeiro precisaríamos definir o desempenho. Throughput e tempo de resposta As mudanças a seguir em um sistema de computador aumentam o throughput.13  A capacidade. e o avião com a maior capacidade é o 747. Como um usuário de computador individual. . que usaremos no decorrer do texto. EXEMPLO diminuem o tempo de resposta ou ambos? 1. o 747 certamente seria o mais rápido. do um centro de dados com diversos servidores rodando tarefas submetidas por muitos acessos à memória. é o número de tarefas precisaremos de diferentes métricas de desempenho. em reduzir o tempo de resposta — o tempo entre o início e o término de uma tarefa — também conhecido como tempo de execução. normalmente queremos relacionar o desempenho de dois computadores diferentes quantitativamente. Nesse caso. o sistema poderia forçar as solicitações a se enfileirarem. se o desempenho de X for maior que o desempenho de Y. o tempo de execução em Y é maior que o de X. temos Desempenho X > Desempenho Y 1 1 > Tempo de execução X Tempo de execução Y Tempo de execução Y > Tempo de execução X Ou seja. ninguém realiza o RESPOSTA trabalho mais rapidamente. Acrescentar processadores adicionais a um sistema que utiliza múltiplos proces- sadores para tarefas separadas — por exemplo. Usaremos a frase “X é n vezes mais rápido que Y” — ou. 1. Na discussão de um projeto de computador. Assim. em muitos sistemas de computado- res reais. Porém. então o tempo de execução em Y é n vezes maior do que em X: Desempenho X Tempo de execução Y = =n Desempenho Y Tempo de execução X Desempenho relativo Se o computador A executa um programa em 10 segundos e o computador B execu- ta o mesmo programa em 15 segundos. Na discussão sobre o desempenho dos computadores. No caso 2. queremos minimizar o tempo de resposta ou o tempo de execução para alguma tarefa. Diminuir o tempo de resposta quase sempre melhora o throughput. Assim. “X tem n vezes a velocidade de Y” — para indicar Desempenho X =n Desempenho Y Se X for n vezes mais rápido que Y. de modo equivalente. aumentar o throughput também poderia melhorar o tempo de resposta. vamos nos preocupar principal- mente com o tempo de resposta nos primeiros capítulos. no caso 1. se a demanda para processamento no segundo caso fosse quase tão grande quanto o throughput. podemos relacionar desempenho e tempo de execução para o computador X: 1 Desempenho X = Tempo de execução X Isso significa que. o quanto A é mais rápido que B? EXEMPLO . Para maximizar o desempenho. se X for mais rápido que Y. busca na World Wide Web. para dois computadores X e Y. de modo que somente o throughput aumenta. mudar o tempo de execução ou o throughput normalmente afeta o outro. Logo. pois poderia reduzir o tempo de espera na fila. o tempo de resposta e o throughput são melhorados.4 Desempenho 21 2. normalmente dizemos “melhorar o desempenho” ou “melhorar o tempo de execução” quando queremos dizer “aumentar o desempenho” e “diminuir o tempo de execução”.5 vez mais lento que o computador A. e não inclui o tempo gasto esperando pela E/S ou pela execução de outros programas. Para evitar a confusão em potencial entre os termos aumentar e diminuir. chamado tempo de CPU do sistema.5 10 e A. Esses termos significam o tempo total para completar uma tarefa. O tempo de execução do progra- ma é medido em segundos por programa. portanto. atividades de entrada/saída (E/S). tempo de execução de CPU Logo. ou simplesmente CPU. e o tempo de CPU gasto no sistema operacional. é 1. e por causa das diferenças de funcionalidade entre os sistemas operacionais. normalmente usaremos a terminologia mais rápido que quando tentamos comparar computadores quantitativamente.) O tempo de CPU pode ser O tempo de CPU gasto em um dividido ainda mais no tempo de CPU gasto no programa. A definição mais clara de tempo é chamada de tempo do relógio. Como o desempenho e o tempo de execução são recíprocos. porém. O tempo real que a CPU tempo de CPU. os computadores normalmente são compartilhados e um processador pode trabalhar em vários programas simultaneamente. normalmente queremos distinguir entre o tempo decorrido e o tempo que o proces- Também chamado tempo de sador está trabalhando em nosso favor. para essa tarefa. pois Desempenho A = 1. tempo de resposta ou tempo decorrido. é o tempo que a CPU gasta computando gasta calculando para uma tarefa específica. pois normalmente é difícil atribuir operacional realizando tarefas em a responsabilidade pelas atividades do sistema operacional a um programa do usuário em favor do programa. . acessos à memória. usuário. chamado tempo de CPU do programa propriamente dito. Nesses casos. A diferenciação entre o tempo de CPU do O tempo de CPU gasto no sistema sistema e do usuário é difícil de se realizar com precisão. aumentar o desempenho requer diminuir o tempo de execução. também poderíamos dizer que o computador B é 1.22 Capítulo 1  Abstrações e Tecnologias Computacionais Sabemos que A é n vezes mais rápido que B se RESPOSTA Desempenho A Tempo de execuçãoB = =n DesempenhoB Tempo de execução A Assim. o tempo pode ser definido de diferentes maneiras. o sistema pode tentar otimizar o throughput em vez de tentar minimizar o tempo decorrido para um programa.5 vez mais rápido que B. No exemplo anterior. realizando tarefas em favor tempo de CPU do sistema do programa.5 DesempenhoB significando que Desempenho A = DesempenhoB 1. Tempo de execução de CPU. overhead do sistema operacional — tudo. a razão de desempenho é 15 = 1. Contudo. vez do outro. (Lembre-se.5 Para simplificar. que reconhece essa distinção. dependendo do que contamos. e não o tempo de CPU. incluindo acessos ao disco. Medindo o desempenho O tempo é a medida de desempenho do computador: o computador que realiza a mesma quantidade de trabalho no menor tempo é o mais rápido. Porém. de que o tempo de resposta experimentado pelo usuário tempo de CPU do usuário será o tempo decorrido do programa. b. Nos próximos capítulos. o tempo de resposta e o throughput mesmo melhoram. ciclo. é conveniente pensar sobre o desempenho em outras métricas. 2. O tempo para um período de clock. ou 250 ps) e como a taxa de clock (por exemplo. vamos descrever como procurar gargalos e melhorar o desempenho em diversas partes do sistema. embora nossas discussões de como resumir o desempenho possam ser aplicadas às medições de tempo decorrido ou tempo de CPU. Suponha que saibamos que uma aplicação que usa um cliente de desktop e um Verifique você servidor remoto seja limitada pelo desempenho da rede. indique se somente o throughput melhora. 1. dependem muito do desempenho da E/S. especialmente aquelas rodando em servidores. de clock. período de clock  A extensão de segundos. 1. c. tempo de resposta ou uma combinação complexa dos dois (por exemplo. a. normalmente truídos usando-se um clock que determina quando os eventos ocorrem no hardware. do clock do processador. batida de clock. ou 4 GHz). Quase todos os computadores são cons. períodos de clock. por sua vez. Em particular. Um canal de rede extra é acrescentado entre o cliente e o servidor. Na próxima subseção. poderíamos determinar o efeito de uma mudança de projeto sobre o desempenho experimentado pelo usuário. que é cada ciclo de clock. Vamos focalizar o desempenho da CPU neste capítulo. O o desempenho tempo decorrido total medido por um relógio comum é a medida de interesse. ciclos).4 Desempenho 23 Por uma questão de consistência. mas não aumentando o throughput. ou nenhum destes melhora. 250 picos. clocks. como usuários de computador. Se pudéssemos relacionar essas diferentes métricas. formalizaremos o relacionamento entre os ciclos de clock do projetista de hardware e os segundos do usuário do computador. os projetistas de comunicação podem querer pensar a ciclo de clock  Também chamado respeito de um computador usando uma medida que se relaciona à velocidade com que batida. o throughput máximo com o tempo de resposta no pior caso). aumentando o throughput total da rede e reduzindo o atraso para obter o acesso à rede (pois agora existem dois canais). clock. Em alguns do programa ambientes de aplicação. deve-se ter uma definição clara de qual métrica de desempenho interessa e depois prosseguir para procurar gargalos de desempenho medindo a execução do programa e procurando os prováveis gargalos. Quanto tempo o computador C levará para executar essa aplicação? Desempenho da CPU e seus fatores Usuários e projetistas normalmente examinam o desempenho usando diferentes métricas. período de o hardware pode realizar suas funções básicas. Como estamos . Para melhorar o desempenho de um programa. conta com o hardware e o software. O desempenho do computador C é quatro vezes mais rápido que o desempenho do computador B. quando exa- minamos os detalhes de um computador. Para as mudanças a seguir. que executa determinada aplicação em 28 segundos. clock. que. Usaremos o termo desempe- nho do sistema para nos referirmos ao tempo decorrido em um sistema não carregado e desempenho da CPU para nos referirmos ao tempo de CPU do usuário. O software de rede é melhorado. nos importemos com o tempo. Os projetistas referem-se à extensão de um período de clock como o tempo para um ciclo de clock completo (por exemplo. Mais memória é acrescentada ao computador. reduzindo assim o atraso na comunicação da rede. o usuário pode se importar com o throughput. mantemos uma distinção entre o desempenho baseado no tempo decorrido e baseado no tempo de execução da CPU. Muitas aplicações. o inverso do período de clock. que Esses intervalos de tempo discretos são chamados de ciclos de clock (ou batidas. Diferentes aplicações são sensíveis a diferentes aspectos do desempenho de um sistema de Entendendo computador. Embora. batidas trabalha a uma taxa constante. 4 gigahertz. Que taxa de clock o projetista deve ter como alvo? Vamos primeiro achar o número de ciclos de clock exigidos para o programa em A: RESPOSTA Ciclos de clock de CPU A Tempo de CPU A = Taxa de clock A Ciclos de clock de CPU A 10 segundos = ciclos 2 × 109 segundo ciclos Ciclos de clock de CPU A = 10 segundos × 2 × 109 = 20 × 109 ciclos segundo O tempo de CPU para B pode ser encontrado por meio desta equação: 1. Estamos tentando ajudar um projetista de computador a montar um computador B. mas esse aumento afetará o restante do projeto da CPU. Muitas técnicas que diminuem o número de ciclos de clock podem também aumentar o tempo do ciclo de clock. que executará esse programa em 6 segundos. Uma fórmula simples relaciona as métricas mais básicas (ciclos de clock e tempo do ciclo de clock) ao tempo da CPU: Tempo de execução da CPU Ciclos de clock da CPU = × Tempo do ciclo de clock para um programa para um programa Como alternativa. que tem um EXEMPLO clock de 2 GHz. Melhorando o desempenho Nosso programa favorito executa em 10 segundos no computador A. 2 × Ciclos de CPU A Tempo de CPU B = Taxa de clock B 1. como a taxa de clock e o tempo do ciclo de clock são inversos. Conforme veremos em outros capítulos.24 Capítulo 1  Abstrações e Tecnologias Computacionais interessados no desempenho da CPU neste ponto. Tempo de execução da CPU Ciclos de clock da CPU para um programa = para um programa Taxa de clock Essa fórmula deixa claro que o projetista de hardware pode melhorar o desempenho reduzindo o número de ciclos de clock exigidos para um programa ou o tamanho do ciclo de clock.2 vez a quantidade de ciclos de clock do computador A para esse programa. a medida de desempenho final é o tempo de execução da CPU. 2 × 20 × 109 ciclos 6 segundos = Taxa de clock B . O projetista determinou que é possível haver um aumento substancial na taxa de clock. fazendo com que o computador B exija 1. os projetistas normalmente têm de escolher entre o número de ciclos de clock necessários para um programa e a extensão de cada ciclo. 0 Ciclos de clock de CPU B = I × 1. 1. logicamente. pois o número de instruções executadas para um programa. que é o número médio de ciclos de clock que ciclos de clock por instruções cada instrução leva para executar.4 Desempenho 25 1. Um modo de pensar a respeito do tempo de execução é que ele é igual ao número de instruções executadas multiplicado pelo tempo médio por instrução. O computador A tem um tempo de ciclo de clock de 250 ps e um CPI de EXEMPLO 2. vamos chamar esse número de I. Primeiro. Qual computador é mais rápido para esse programa e por quanto? Sabemos que cada computador executa o mesmo número de instruções para o pro- grama.0 × 250 ps = 500 × I ps . Como diferentes (CPI)  Número médio de ciclos de clock por instrução para instruções podem exigir diferentes quantidades de tempo.0 para algum programa. 2 × 20 × 109 ciclos 4 × 109 ciclos Taxa de clock B = = = = 4GHz 6 segundos segundo segundo Para executar o programa em 6 segundos. (Veremos como são as instruções que compõem um programa no próximo capítulo. um programa ou fragmento de CPI é uma média de todas as instruções executadas no programa. 2 Agora. será o mesmo. normalmente é abreviado como CPI. e o computador B tem um tempo de ciclo de clock de 500 ps e um CPI de 1. como o compilador claramente gera instruções para executar. B deverá ter o dobro da taxa de clock de A. e o computador teve de rodá-las para executar o programa. o tempo de execução deverá depender do número de instruções em um programa. encontramos o número de ciclos RESPOSTA de clock do processador para cada computador: Ciclos de clock de CPU A = I × 2.2 para o mesmo programa.) Porém. o número de ciclos de clock exigido para um programa pode ser escrito como Ciclos de clock de CPU = Instruções para um programa × Ciclos de clock médios por instrução O termo ciclos de clock por instrução. podemos calcular o tempo de CPU para cada computador: Tempo de CPU A = Ciclos de clock de CPU A × Tempo de ciclo de clock = I × 2. Portanto. Usando a equação de desempenho Suponha que tenhamos duas implementações da mesma arquitetura de conjunto de instruções. de comparar duas implementações diferentes da mesma arquitetura do conjunto de ins- truções. dependendo do que elas fazem. 2 × 20 × 109 ciclos 0. Desempenho da instrução Essas equações de desempenho não incluíram qualquer referência ao número de instruções necessárias para o programa. CPI oferece um modo programa. para B: Tempo de CPU B = I × 1. 2 × 500 ps = 600 × I ps Claramente. A equação clássica de desempenho da CPU contador de instrução  O número Agora.2 vez mais rápido que o computador B para esse programa. CPI e tempo de ciclo do programa. Podemos usá-las para comparar duas implementações diferentes ou para avaliar uma alternativa de projeto se soubermos seu impacto sobre esses três pa- râmetros. clock: Tempo de CPU = Contador de instrução × CPI × Tempo de ciclo de clock ou então. Os projetistas de hardware forneceram os seguintes fatos: CPI para cada classe de instrução A B C CPI 1 2 3 Para determinada instrução na linguagem de alto nível. podemos escrever essa equação de desempenho básica em termos do contador de de instruções executadas pelo instrução (o número de instruções executadas pelo programa). como a taxa de clock é o inverso do tempo de ciclo de clock: Contador de instrução × CPI Tempo de CPU = Taxa de clock Essas fórmulas são particularmente úteis porque separam os três fatores principais que afetam o desempenho. o computador A é mais rápido. 2 Desempenho da CPU B Tempo de execução A 500 × I ps Podemos concluir que o computador A é 1. o escritor do compilador está considerando duas sequências de código que exigem as seguintes contagens de instruções: Contagens de instruções para cada classe de instrução Sequência de código A B C 1 2 1 2 2 4 1 1 . Comparando segmentos de código Um projetista de compilador está tentando decidir entre duas sequências de código EXEMPLO para determinado computador. A quantidade mais rápida é dada pela razão dos tempos de execução: Desempenho da CPU A Tempo de execuçãoB 600 × I ps = = = 1.26 Capítulo 1  Abstrações e Tecnologias Computacionais De modo semelhante. RESPOSTA Podemos usar a equação para ciclos de clock de CPU com base na contagem de ins- truções e CPI a fim de descobrir o número total de ciclos de clock para cada sequência: n Ciclos de clock de CPU = ∑(CPIi × C i ) i =1 Isso gera Ciclos de clock de CPU1 = (2 × 1) + (1 × 2) + (2 × 3) = 2 + 2 + 6 = 10 ciclos Ciclos de clock de CPU 2 = (4 × 1) + (1 × 2) + (1 × 3) = 4 + 2 + 3 = 9 ciclos Assim.4 Desempenho 27 Qual sequência de código executa mais instruções? Qual será mais rápida? Qual é o CPI para cada sequência? A sequência 1 executa 2 + 1 + 2 = 5 instruções. o código que executa o menor número de instruções pode não ser o mais rápido. Os valores de CPI podem ser calculados por Ciclos de clock de CPU CPI = Contagem de instruções Ciclos de clock de CPU1 10 CPI1 = = = 2. Podemos ver como esses fatores são combinados para gerar um tempo de execução medido em segundos por pro- grama: Segundos Instruções Ciclos de clock Segundos Tempo = = × × Programa Programa Instrução Ciclo de clock Colocando em Lembre-se sempre de que a única medida completa e confiável do desempenho perspectiva do computador é o tempo.14 mostra as medições básicas em diferentes níveis no computador e o que está sendo medido em cada caso.5 Contagem de instruções 2 6 A Figura 1. Portanto. ela deverá ter um CPI menor. como o CPI depende do tipo das instruções executadas. De modo semelhante. mas tem mais instruções. 1. que compensa a melhoria na contagem de instruções. Como a sequência de código 2 leva menos ciclos de clock em geral. a sequência de código 2 é mais rápida. mudar o conjunto de instruções para reduzir a contagem de instruções pode levar a uma organização com um tempo de ciclo de clock menor ou CPI maior. a sequência 1 executa menos instruções. A sequência 2 executa 4 + 1 + 1 = 6 instruções. Por exemplo. . embora execute uma instrução extra.0 Contagem de instruções1 5 Ciclos de clock de CPU 2 9 CPI2 = = = 1. Como a contagem de instruções depende da arquitetura. Entendendo O desempenho de um programa depende do algoritmo. . Por exemplo. o CPI varia por aplicação. Ao comparar dois computadores. A contagem de instruções e o CPI podem ser mais difíceis de se obter. e o tempo do ciclo de clock normalmente é publicado como parte da documentação de um computador. o número de instruções de processador possivelmente CPI executadas. Se alguns dos fatores forem idênticos. Vários exercícios ao final deste capítulo lhe programas. tanto a contagem de instruções quanto o CPI precisam ser comparados. uma linguagem com um suporte intenso para abstração de dados (por exemplo. do programa Componente de hardware ou software Afeta o quê? Como? Algoritmo Contagem de O algoritmo determina o número de instruções do programa-fonte instruções. que usarão instruções de CPI mais alto. Naturalmente.8. CPI instruções. examinaremos uma medida de desempenho comum. Podemos medir a contagem de instruções usando ferramentas de software que deter- minam o perfil da execução ou usando um simulador da arquitetura. pedem para avaliar uma série de melhorias de computador e compilador. se o algoritmo utiliza mais operações de ponto flutuante. só precisamos da contagem de instruções ou do CPI para determinar o outro. Na Seção 1. CPI e contagem de instruções. que não incorpora todos os termos e. que se combinam para formar o tempo de execução. da linguagem. O exemplo anterior mostra o perigo de usar apenas um fator (contagem de instruções) para avaliar o desempenho. o CPI depende de diversos detalhes de projeto no computador. da arquitetura e do hardware real. podemos usar contadores de hardware. as origens da perda de desempenho. o CPI médio e. pode ser enganosa. que afetam a taxa de clock. do compilador. além da mistura de tipos de instruções executados em uma aplicação. favorecendo instruções mais lentas ou mais rápidas.14  Os componentes básicos do desempenho e como cada um é medido. para registrar uma série de medidas. Como alternativa. mas não da implementação exata. por exemplo. o desempenho pode mix de instruções  Uma medida ser determinado comparando-se todos os fatores não idênticos. pois as instruções na linguagem são traduzidas para instruções de processador. incluindo o sistema de memória e a estrutura do processador (conforme veremos nos Capítulos 4 e 5). Como o CPI varia por mix da frequência dinâmica das de instruções. bem como entre implementações com o mesmo conjunto de instruções. ele tenderá a ter um CPI mais alto. portanto.28 Capítulo 1  Abstrações e Tecnologias Computacionais FIGURA 1. portanto. Assim. frequentemente. instruções por um ou muitos mesmo que as taxas de clock sejam idênticas. A linguagem também pode afetar o CPI por causa dos seus recursos. você precisa examinar todos os três componentes. podemos medir a contagem de instruções sem conhecer todos os detalhes da implementação. O algoritmo também pode afetar o CPI. o que determina a contagem de instruções. como a taxa de clock no exemplo anterior. Java) exigirá chamadas indiretas. incluindo o número de instruções executadas. Porém. se soubermos a taxa de clock e o tempo de execução da CPU. A tabela a seguir resume como esses componentes afetam o desempenho os fatores na equação de desempenho da CPU. que estão incluídos na maioria dos processadores. executadas e. Linguagem de Contagem de A linguagem de programação certamente afeta a contagem de programação instruções. Como determinar o valor desses fatores na equação de desempenho? Podemos medir o tempo de execução da CPU rodando o programa. Arquitetura do Contagem de A arquitetura do conjunto de instruções afeta todos os três conjunto de instruções. Um novo compilador Java é lançado. a principal fonte de dissipação de potência é a chamada potência dinâmica — ou seja.1 = 9.15 mostra o aumento na taxa de clock e na potência de oito gerações de micro- processadores Intel durante 25 anos.1.5  A barreira da potência 29 Componente de hardware ou software Afeta o quê? Como? Compilador Contagem de A eficiência do compilador afeta a contagem de instruções instruções. CPI e os ciclos médios por instruções. Para refletir essa técnica. taxa de aspectos do desempenho da CPU. Se um processador executa em média duas instruções por ciclo de clock. 2 seg 1. pois o compilador determina a tradução das instruções da linguagem-fonte para instruções do computador. pois afeta as instruções instruções clock. então ele tem um IPC de 2 e. ou instruções por ciclo de clock. .9 seg 15 × 1. Tanto a taxa de clock quanto a potência aumentaram rapidamente durante décadas e depois se estabilizaram recentemente. 15 × 0. que determina a capacitância dos fios e dos transistores.6 a. = 27. CPI necessárias para uma função. da tensão elétrica aplicada e da frequência com que o transistor é comutado: Potência = Carga capacitiva × Tensão elétrica 2 × Frequência comutada A frequência comutada é uma função da taxa de clock.1 c. Infelizmente. portanto. O papel do compilador pode ser muito complexo e afetar o CPI de maneiras complexas. A dissipação da potência dinâmica depende da carga capacitiva de cada transistor. A tecnologia dominante para circuitos integrados é denominada Complementary Metal Oxide Semiconductor (CMOS). Determinada aplicação escrita em Java roda por 15 segundos em um processador de Verifique você desktop. isso aumenta o CPI por 1. O motivo pelo qual elas cresceram juntas é que estão correlacionadas e o motivo para o seu recuo recente é que chegamos ao limite de potência prático para o resfriamento dos microprocessadores comuns.5 seg 0. um CPI de 0.0. o custo em ciclos de cada instrução e a taxa de clock geral do processador.5. Para CMOS.6 × 1. Detalhamento:  Embora você possa esperar que o CPI mínimo seja 1. = 8. conforme veremos no Capítulo 4. Com que velocidade pode- mos esperar que a aplicação rode usando esse novo compilador? Escolha a resposta certa a partir das três opções a seguir: 15 × 0. alguns processadores buscam e executam múltiplas instruções por ciclo de clock.5   A barreira da potência A Figura 1.6 1.1 b. a potência que é consumida durante a comutação. A carga capacitiva por transistor é uma função do número de transistores conectados a uma saída (chamado de fanout) e da tecnologia. 1. alguns projetistas invertem o CPI para falar sobre IPC. exigindo apenas 60% das instruções do mesmo compilador antigo. Além do mais. motivo pelo qual o aumento na potência é de apenas 30 vezes. os projetistas já conectaram grandes dis- positivos a fim de aumentar o resfriamento e depois desligaram partes do chip que não são usadas em determinado ciclo de clock.85 RESPOSTA Potência antiga = Carga capacitiva × Tensão 2 × Frequência comutada Assim. porém menor em desempenho. Embora existam muitas maneiras mais dispendiosas de resfriar os chips e. considere que ele tenha tensão ajustável.854 = 0. o novo processador usa cerca de metade da potência do processador antigo. A linha Core 2 retorna a uma pipeline mais simples. O problema hoje é que reduzir ainda mais a tensão parece causar muito vazamento nos transistores. cerca de 40% do consumo de potência é decorrente de vazamentos. o que ocorreu a cada nova geração da tecnologia. o processo inteiro poderia se tornar incontrolável.85 × Tensão × 0. Para tentar resolver o problema de potência. digamos.15  Taxa de clock e potência para microprocessadores Intel x86 durante oito gerações e 25 anos. com menores taxas de clock e múltiplos processadores por chip.30 Capítulo 1  Abstrações e Tecnologias Computacionais FIGURA 1. O Pentium 4 fez um salto dramático na taxa de clock e potência. a razão de potência é 0. mais simples. Se os transistores começassem a vazar mais. Em 20 anos. 300 watts. como torneiras de água que não conseguem ser completamente fechadas. as tensões passaram de 5V para 1V. Potência relativa Suponha que tenhamos desenvolvido um novo processador.52 Logo. de modo que pode reduzir a tensão em 15% em comparação com o processador B. o que resulta em um encolhimento de 15% na frequência. essas técnicas são muito caras para computadores de desktop. e a potência é uma função da tensão elétrica ao quadrado. .000 enquanto a potência crescia por um fator apenas de 30? A potência pode ser diminuída reduzindo-se a tensão elétrica. Normalmente. aumentar a potência para. que tem EXEMPLO 85% da carga capacitiva do processador mais antigo e mais complexo. a tensão elétrica foi reduzida em 15% por geração.85 × Frequência comutada × 0. portanto. Até mesmo hoje. Qual é o impacto sobre a potência dinâmica? 2 Potência nova Carga capacitiva × 0. Como as taxas de clock poderiam crescer por um fator de 1. Os problemas térmicos do Prescott levaram ao abandono da linha Pentium 4. Para reforçar como os sistemas de software e hardware trabalham lado a lado. usamos uma seção especial. O plano de registro oficial para muitas empresas é dobrar o número de núcleos por microprocessador por geração de tecnologia de semicondutor. Este é um exem.5 por um trabalho para grande ano para um fator de menos de 1. o vazamento normal- mente é responsável por 40% do consumo de potência em 2008. eles precisam reescrever seus programas de modo que tirem proveito de múltiplos processadores. os programadores terão de continuar a melhorar o desempenho de seu código à medida que dobra o número de núcleos. O paralelismo sempre foi fundamental para o desempenho na computação. para os programadores obterem uma melhoria significativa no tempo de resposta. de desafio diferente. Assim. potência e taxas de clock de microprocessadores recentes. em 2006 todas as empresas de desktop e servidor estavam usando microprocessadores com múltiplos processadores por chip. A Figura 1. aumentar o número de transistores aumenta a dissipação de potência. eles preci- saram de uma nova maneira de prosseguir e escolheram um caminho diferente do modo como projetaram microprocessadores nos seus primeiros 30 anos. O Capítulo 4 explicará sobre o pipelining. Conforme já mencionamos. na arquitetura e nos compiladores para dobrar o desempenho de seus programas a cada 18 meses sem ter de mudar uma linha de código. em que a natureza paralela do hardware é reti. os programadores podiam contar com inovações no hardware. Brian Hayes. estamos adquirindo alguma experiência com O limite de potência forçou uma mudança dramática no projeto dos microprocessadores. 1. a taxa reduziu de um fator de 1. duetos e quartetos e outros A Figura 1. Além do mais. Logo. software rada de modo que o programador e o compilador possam pensar no hardware como executando instruções sequencialmente. a dissipação de potência estática ocorre devido à corrente de vazamento que flui mesmo quando um transistor está desligado. de hardware/ plo de paralelismo em nível de instrução. a maior parte Mudança de mares: Passando do software tem sido como 1. que é aproximadamente a cada dois anos (veja Capítulo 7). com a primeira apare- cendo logo em seguida. 2007. ou quatro núcleos. Essas seções resumem ideias importantes nessa interface crítica. mas normal. Hoje. Interface hardware/software.6  Mudança de mares: Passando de processadores para multiprocessadores 31 Como os projetistas de computador bateram contra a barreira da potência.2 por ano. as empresas se referem aos processadores como “cores” (ou núcleos). Detalhamento:  Embora a potência dinâmica seja a principal fonte de dissipação de potência na CMOS. Computing malmente está mais no throughput do que no tempo de resposta. pequenos grupos.17 mostra o número de processadores (núcleos). um microprocessador “quadcore” é um chip que contém quatro processadores. tando num único processador. Forçar os programadores a estarem cientes do hardware paralelo e reescrever expli- citamente seus programas para serem paralelos foi a “terceira trilha” da arquitetura de . orquestra e coro é um tipo Em vez de continuar diminuindo o tempo de resposta de um único programa execu. com a geração atual de chips. mesmo que os transistores estejam sempre desligados. Desde 2002. e esses microprocessadores são chamados genericamente de microprocessadores “multicore” (ou múltiplos núcleos). entre as palavras processador e microprocessador. Até agora. uma técnica elegante que roda programas mais rapidamente sobrepondo a execução de instruções. Diversas técnicas de projeto e inovações de tecnologia estão sendo implantadas para controlar o vazamento. no livro inteiro.16 mostra a melhoria no tempo de resposta dos programas para microproces. mas é difícil reduzir mais a tensão.6   de processadores para multiprocessadores música escrita para um solista. Interface mente esteve oculto. No passado. para obter o benefício histórico de rodar mais rapidamente nos microprocessadores mais novos. mas compor sadores de desktop ao longo dos anos. em que o benefício nor. Para reduzir a confusão in a Parallel Universe. que dependiam dessa mudança no comporta- mento. os limites de potência. Por que tem sido tão difícil para os programadores escreverem programas explicitamente paralelos? O primeiro motivo é que a programação paralela é. Desde 2002. o paralelismo disponível em nível de instrução e a latência de memória longa reduziram o desempenho do processador recentemente. programação de desempenho. se você não precisasse de desempenho. . para o hardware paralelo. para cerca de 20% por ano. FIGURA 1.8). Este gráfico representa o desempenho relativo ao VAX 11/780 medido pelos benchmarks SPECint (veja Seção 1. por definição.14 no site).17  Número de núcleos por chip. mas ele também precisa ser rápido. O aumento no crescimento para cerca de 52% desde então é atribuído a ideias arquiteturais e organizacionais mais avançadas.16  Crescimento do desempenho do processador desde meados da década de 1980. Caso contrário. O desempenho para cálculos orientados a ponto flutuante aumentou ainda mais rapidamente. o que aumenta a dificuldade da programação. Por volta de 2002. significa que o programador precisa dividir uma aplicação de modo que cada processador tenha aproximadamente a mesma quantidade de coisas a fazer ao mesmo tempo. FIGURA 1. O segundo motivo é que rápido. Antes de meados da década de 1980. pois empresas no passado. Do ponto de vista histórico. é surpreendente que a indústria inteira de TI tenha apostado seu futuro em que os programadores finalmente passarão com sucesso para a programação explicitamente paralela. bastaria escrever um programa sequencial. solucionar um problema importante e oferecer uma interface útil às pessoas ou outros programas que o chamam. e que o overhead do escalonamento e coordenação não afasta os benefícios de desempenho em potencial do paralelismo. o crescimento do desempenho do processador foi em grande parte controlado pela tecnologia e teve uma média de 25% por ano. Não apenas o programa precisa estar correto. esse crescimento levou a uma diferença no desempenho por um fator de cerca de sete. fracassaram (veja Seção 7.32 Capítulo 1  Abstrações e Tecnologias Computacionais computadores. taxa de clock e potência para os microprocessadores multicore em 2008. Seção 2. Essa lógica considera que a aritmética do computador é associativa: você recebe a mesma soma quando adiciona um milhão de números. RAID pode melhorar tanto o desempenho quanto a disponibilidade da E/S. um esforço tremendo foi investido na década de 1990 para que o hardware e o compilador revelassem o paralelismo implícito. uma conclusão lógica é que existem bugs na nova versão. deve-se ter o cuidado para reduzir o overhead de comunicação e sincronização. j Capítulo 3.10: Paralelismo e paralelismo avançado em nível de instrução.8: Paralelismo e hierarquias de memória: coerência do cache. não pudesse ser escrita até que todas as outras partes fossem concluídas. uma técnica para acelerar o desempenho dos acessos ao armazenamento. Para conseguir essa velocidade aumentada. j Capítulo 5. Esse capítulo descreve algumas dessas técnicas agressivas. j Capítulo 6. RAID assinala outro benefício em potencial do paralelismo: tendo muitas cópias dos recursos. suponha que a tarefa fosse escrever um artigo de jornal. Uma questão natural para descobrir se sua versão paralela funciona é: “ela tem a mesma resposta?” Se não. temos de escalonar as subtarefas. Seção 6. com a execução especulativa das instruções. 1.9: Paralelismo e E/S: Redundant Arrays of Inexpensive Disks. Dada a dificuldade da programação explicitamente paralela. balanceamento de carga. Normalmente. o desafio é ainda maior com mais repórteres de um artigo de jornal e mais processadores na programação paralela.6: Paralelismo e aritmética de computador: Associatividade. não serve para os números de ponto flutuante. mais próxima do processador. de modo que qualquer processador possa ler ou gravar quaisquer dados. Esse capítulo explica as instruções usadas por proces- sadores multicore para sincronizar tarefas. Outro perigo seria se os repórteres tivessem de gastar muito tempo falando uns com os outros para escrever suas seções. j Capítulo 4. Seção 4. a consequência não intencionada da programação paralela pode ser fazer com que seu programa paralelo gaste a maior parte do seu tempo esperando pela E/S.11: Paralelismo e instruções: sincronização. como a conclusão. Assim. tempo para sincronismo e overhead para comunicação entre as partes. não importando a ordem. Seção 3. Em geral. temos de balancear a carga por igual para obter o ganho de velocidade desejado. Logo.6  Mudança de mares: Passando de processadores para multiprocessadores 33 Como uma analogia. Um modo de reduzir o custo da comunicação é fazer com que todos os processadores usem o mesmo espaço de endereço. Para refletir essa mudança de mares no setor. como dizer quando elas completaram seu trabalho. seria preciso desmembrar a tarefa de modo que cada repórter tivesse algo para fazer ao mesmo tempo. Como você poderia imaginar. então o benefício de ter oito escritores seria diminuído. Assim. é fácil imaginar que a programação paralela seria ainda mais difícil se os caches associados a cada processador tivessem valores inconsistentes dos dados compartilhados. Esse capítulo descreve RAID. os próximos cinco capítulos desta edição do livro possuem uma seção sobre as implicações da revolução paralela relacionadas a cada capítulo: j Capítulo 2. embora essa lógica se mantenha para números inteiros. o sistema pode continuar a fornecer serviço apesar de uma falha de um recurso. Se algo saísse errado e apenas um repórter levasse mais tempo do que os sete outros levaram. Você também se atrasaria se uma parte do artigo. Esse capítulo explica que. Visto que todos os processadores atuais utilizam caches para manter uma cópia temporária dos dados na memória mais rápida. Oito repórteres trabalhando no mesmo artigo poderiam potencialmente escrever um artigo oito vezes mais rápido. Seção 5. Se você ignorar a entrada e saída nessa revolução paralela. tarefas paralelas independentes às vezes precisam ser coordenadas. Assim. . Para essa analogia e para a programação paralela. os desafios incluem escalonamento. incluindo a busca e a execução simultâneas de múltiplas instruções e a estimativa dos resultados das decisões. Esse capítulo descreve os mecanismos que mantêm coerentes os dados em todos os caches. os programadores paralelos começam de um programa sequencial funcionan- do. as GPUs estão se tornando plataformas de programação por si sós.19 é uma fotografia de um wafer com mi- . é chamado de semicondutor. Inventada para acelerar os colocamos. isolantes e chaves. assim como os explícita de mensagens. o Apêndice A descreve um componente de hardware de colocar tantas peças em cada vez mais comum. coinventor do Eniac. barra composta de um cristal de consequentemente. várias estratégias têm sido usadas. Os transistores se encaixam na última categoria. cortado em seções individuais desses componentes. apresenta que se desenvolveriam tão um novo modelo de desempenho simples para microprocessadores multicore e finalmente rapidamente.18 mostra silício que possui entre 15 e 30cm esse processo.25cm wafer  Uma fatia de um lingote de de espessura. uma subs- tância encontrada na areia. tornam praticamente impossível fabricar um wafer perfeito. poderia esperar. J. simplesmente consiste em bilhões de combinações de condutores. Vamos começar do início. Nesta primeira “Vida Real”. como são chamados. O wafer com os padrões contém esse defeito. Como você apareceu inesperadamente. A Figura 1. que se parece com de diâmetro e cerca de 30 a 60cm de comprimento.7   do AMD Opteron X4 Cada capítulo possui uma seção intitulada “Vida Real”. chamados dies.34 Capítulo 1  Abstrações e Tecnologias Computacionais Eu acreditava que [os Além dessas seções.5mm de quais são depositados padrões de elementos químicos em cada lâmina. Hoje. neste momento. fabricados em um único e pequeno pacote. então. que está incluído com os computadores de desktop: a unidade de um chip quanto finalmente processamento de gráficos (Graphics Processing Unit – GPU). tores. Esses wafers passam por uma série de etapas de processamento. veremos como os circuitos integrados são fabricados e como o desempenho e a potência são me- didos com o AMD Opteron X4 como exemplo. que associa os conceitos no livro com um computador que você pode usar em seu dia a dia. Uma única imperfeição microscópica no wafer propriamente dito ou em uma das de- zenas de passos da aplicação dos padrões pode resultar na falha dessa área do wafer. fundamental para os projetistas de computador. separados por camadas de isolantes. descreve o modelo restrito de paralelismo que é mais fácil de livros. Como não é um bom condutor de eletricidade. os condutores e os isolantes discutidos anteriormente. falando Vida real: Fabricação e benchmarking em 1991 1. usada para criar chips. Esses defeito  Uma imperfeição defeitos. mas a mais simples é pode resultar na falha do die que colocar muitos componentes independentes em um único wafer. durante as silício de não mais de 2. Só não imaginava programar. é possível acrescentar ao silício materiais que permitem que minúsculas áreas se transformem em um entre três dispositivos: j Excelentes condutores de eletricidade (usando fios microscópicos de cobre ou alumínio) silício  Um elemento natural que é j Excelentes isolantes de eletricidade (como cobertura plástica ou vidro) um semicondutor. Com um processo químico especial. Essas seções abordam a tecno- logia na qual se baseiam os computadores modernos. microscópica em um wafer ou nos passos da aplicação dos padrões que Para lidar com a imperfeição. O processo inicia com um lingote de cristal de silício. pois não descreve e avalia quatro exemplos de microprocessadores multicore usando esse modelo. então. Um lingote é finamente fatiado em wafers de não mais que 0. Os circuitos integrados de hoje contêm apenas uma camada de transistores. rápido do que esperávamos. mas podem ter de dois a oito níveis de condutor de metal. as GPUs são altamente paralelas. existe um capítulo inteiro sobre processamento paralelo. O transistor gráficos. pensei que fôssemos capazes A partir desta edição do livro. apresenta as duas uma ideia universalmente técnicas contrastantes para a comunicação de endereçamento compartilhado e passagem aplicável. Presper Eckert. A Figura 1. criando os transis- espessura. O Capítu- computadores] seriam lo 7 entra em mais detalhes sobre os desafios da programação paralela. discute a dificuldade do benchmarking de processadores paralelos. A fabricação de um chip começa com o silício. O Apêndice A descreve Tudo aconteceu muito mais a GPU NVIDIA e realça partes de seu ambiente de programação paralelo. uma salsicha gigante. lingote de cristal de silício  Uma O processo de fabricação dos circuitos integrados é decisivo para o custo dos chips e. os lingotes possuem de 20 a 30cm de diâmetro e cerca de 30 a 60cm de comprimento. Um circuito VLSI. j Áreas que podem conduzir ou isolar sob condições especiais (como uma chave) semicondutor  Uma substância que não conduz bem a eletricidade. mais infor- malmente conhecidos como chips. é. ) O aproveitamento de dies bons nesse caso foi de 17/20. Para reduzir o custo. os wafers são divididos em dies (moldes) (veja a Figura 1. Esses dies bons são soldados a encapsulamentos e testados outra vez antes de serem remetidos para os clientes. a Figura 1. Conforme já foi mencionado. e são remetidas aos clientes. definido como a porcentagem de dies bons do número total de dies em um wafer. Primeiro. já que podem ocorrer erros no encapsulamento. um wafer produziu 20 dies. múltiplos níveis de interconexões são usados unicamente para distribuição de corrente e aterramento para as partes do chip. Um die encapsulado ruim foi encontrado nesse teste final. O custo de um circuito integrado sobe rapidamente conforme aumenta o tamanho do aproveitamento  A porcentagem die. Isso melhora o aproveitamento e o número de dies por wafer. que incorpora tamanhos menores de transistores e de fios. ou 85%. Segundo. Essas peças encapsuladas são testadas uma última vez. Após ser fatiado de um lingote de silício.18  Processo de fabricação de um chip. a corrente precisa ser trazida para o chip e distribuída por toda sua área.19).0 GHz produz 120 watts em 2008.9 mostrou um die dies  As seções retangulares individual do microprocessador e seus principais componentes. Cortar os wafers em seções permite descartar apenas aqueles dies que possuem falhas. em razão do aproveitamento mais baixo e do menor número de dies que pode caber de dies bons do número total de em um wafer. mas informalmente conhecidos como chips. a energia é dissipada como calor e precisa ser removida. eles são conectados aos pinos de entrada/saída de um encapsulamento usando um processo chamado soldagem. os microprocessadores modernos usam centenas de pinos apenas para alimentação e aterramento! Da mesma forma. processo da próxima geração. Nessa figura. 1. Depois. Esses wafers com padrões são testados com um testador de wafers e é criado um mapa das partes boas. um die grande normalmente é “encolhido” usando um dies em um wafer.7  Vida real: Fabricação e benchmarking do AMD Opteron X4 35 FIGURA 1. dos quais 17 passaram no teste. croprocessadores antes de serem cortados. Tendo dies bons. (X significa que o die está ruim. O consumo é um problema por duas razões. os wafers virgens passam por 20 a 40 passos para criar wafers com padrões (veja a Figura 1. anteriormente. outra limitação de projeto cada vez mais importante é o consumo de energia. em vez do wafer inteiro. Um AMD Opteron X4 modelo 2356 a 2. Esse conceito é quantificado pelo aproveitamento de um proces- so. individuais cortadas de um wafer. que precisam ser removidos de um chip cuja área de superfície é de apenas 1cm2! Detalhamento:  O custo de um circuito integrado pode ser expresso em três equações simples: Custo por wafer Custo por die = Dies por wafer × aproveitamento Área do wafer Dies por wafer = Área do die 1 Aproveitamento = (1 + (Defeitos por área × Área do die / 2))2 .9). junto de benchmarks — programas escolhidos especificamente para medir o desempenho. os custos geralmente não são lineares em relação à área do die. A maioria das aplicações executadas por um dos usuários. o predecessor dos chips Opteron X4 (Cortesia da AMD). Os benchmarks formam uma carga de trabalho que o usuário acredita que irá prever o benchmark  Um programa desempenho da carga de trabalho real. que se refere ao tamanho dos transistores como “desenhados” versus o tamanho final fabricado.36 Capítulo 1  Abstrações e Tecnologias Computacionais FIGURA 1. esperando que os programas reais para aproximar métodos reflitam como o computador funcionará com a carga de trabalho do usuário. porém. Logo. tal mistura. Para avaliar dois sistemas. o que significa que os menores transistores possuem um tamanho de aproximadamente 90 nm. A segunda é uma aproximação.19  Um wafer de 300mm de diâmetro dos chips AMD Opteron X2. são incluídas porque é mais fácil criar as máscaras usadas para imprimir os padrões desejados ao silício. embora normalmente sejam um pouco menores do que o tamanho real catalogado. eles precisam contar com ou- usuário ou construídas a partir de tros métodos que medem o desempenho de um computador candidato. selecionado para uso na O System Performance Evaluation Cooperative (SPEC) é um esforço com patrocínio e comparação do desempenho de suporte de uma série de fornecedores de computador a fim de criar conjuntos padrão de computadores. benchmarks para sistemas de computador modernos. com o expoente relacionado ao número de etapas de processamento crítico. O número de dies de Pentium por wafer em 100% de aproveitamento é 117. o SPEC criou originalmente . Benchmark de CPU SPEC Um usuário de computador que executa os mesmos programas todos os dias seria o candidato perfeito para avaliar um novo computador. Em 1989. O conjunto de programas executa- carga de trabalho  Um conjunto dos formaria uma carga de trabalho. não está nessa situação. A primeira equação é simples de se derivar. Esse die usa uma tecnologia de 90 nanômetros. A equação final é baseada nas observações empíricas dos aproveitamentos nas fábricas de circuito integrado. Em vez disso. pois não subtrai a área perto da borda do wafer arredondado que não pode acomodar os dies retangulares (veja Figura 1.19). dependendo da taxa de defeito e do tamanho do die e wafer. um usuário simplesmente de programas executados em um computador que é a coleção real compararia o tempo de execução da carga de trabalho nos dois computadores. As várias dezenas de chips parcialmente arredondados nas bordas do wafer são inúteis. Uma carga de trabalho Essa alternativa normalmente é seguida pela avaliação do computador usando um con- típica especifica o programa e as frequências relativas. anteriormente neste capítulo. Os benchmarks de ponto flutuante incluem códigos de grade estruturados para modelagem de elemento finito. libquantum. A Figura 5. que tem a vantagem de que resultados numéricos maiores indicam desempenho melhor (ou seja. chamada SPECratio. o tempo de execução é o produto dos três fatores nesta tabela: contagem de instruções em bilhões. CPI e tempo do ciclo de clock. Detalhamento:  Ao comparar dois computadores usando SPECratios. Observe que o CPI varia por um fator de 13. que consiste em um conjunto de 12 benchmarks de inteiros (CINT2006) e 17 benchmarks de ponto flutuante (CFP2006). mostrando os fatores que explicam o tempo de execução: contagem de ins- truções. use a média geomé- trica. A mais recente é SPEC CPU2006. Os benchmarks de inteiros variam desde parte de um compilador C até um programa de xadrez e uma simulação de computador quântico. omnetpp e xalancbmk possuem CPIs relativamente altos. Conforme explica a equação na seção “A equação clássica de desempenho da CPU. um conjunto de benchmark focalizando o desempenho do processador (agora chamado SPEC89). Uma medição de resumo CINT2006 ou CFP2006 é obtida apanhando-se a média geométrica dos SPECratios.20  Benchmarks SPECINTC2006 executando no AMD Opteron X4 modelo 2356 (Barcelona). As medidas do tempo de execução são primeiro normalizadas dividindo-se o tempo de execução em um processador de refe- rência pelo tempo de execução no computador medido. 1.20 descreve os benchmarks de inteiros SPEC e seu tempo de execução no Opteron X4. clocks por instrução (CPI) e tempo do ciclo de clock em nanossegundos. o SPEC decidiu informar um único número para resumir todos os 12 benchmarks de inteiros. o SPECratio é o inverso do tempo de execução). A fórmula para a média geométrica é n n ∏ Razão do tempo de execução i i =1 . que é fornecido pelo SPEC.7  Vida real: Fabricação e benchmarking do AMD Opteron X4 37 FIGURA 1. Se calculássemos a média dos valores de tempo de execução normalizados com uma média aritmética. Para simplificar o marketing dos computadores. pois possuem taxas de perda de cache altas. que evoluiu por cinco gerações. essa normalização gera uma medida. SPECratio é simplesmente o tempo de referência. A Figura 1. de modo que ela informe a mesma resposta relativa não importa o computador utilizado para normalizar os resultados. os resultados variariam dependendo do computador que escolhêssemos como referência. códigos de método de partículas para dinâmica molecular e códigos de álgebra linear esparsa para dinâmica de fluidos. dividido pelo tempo de execução medido. O único número mencionado como SPECINTC2006 é a média geométrica dos SPECratios.40 mostra que mcf. Verifique você Um fator fundamental para determinar o custo de um circuito integrado é o volume de mesmo produção. Com altos volumes de produção. O mais recente é o SPECpower. 2. Mais uma vez. normalizado ao computador de referência. A fórmula para essa única métrica de resumo é  10   10  ssj_ ops geral por Watt = ∑ ssj_ ops i  / ∑ potência i   i =0   i =0  em que ssj_opsi é o desempenho em cada incremento de 10% e potênciai é a potência consumida em cada nível de desempenho. projetados para testar uma grande variedade de ambientes de computação usando aplicações reais e regras de execução e requisitos de relatório estritamente especificados. coletor de lixo e partes do sistema operacional. A Figura 1. o processo de fabricação pode ser transformado em um projeto particular. para o i° programa de um total de n na carga de trabalho. o SPEC oferece uma dúzia de conjuntos de benchmark diferentes. para simplificar o marketing dos computadores. além da máquina virtual Java.3 GHz e soquete dual com 16 GB de DRAM DDR2-667 e um disco de 500 GB. chamado “ssj_ops geral por Watt”. caches e memória principal. SPECpower começou com o benchmark SPEC para aplicações comerciais em Java (SPECJBB2005). Ele informa o consumo de potência dos servidores em diferentes níveis de carga de trabalho. Quais das seguintes afirmativas são razões para um chip fabricado com alto volume de produção custar menos? 1. O desempenho é medido no throughput e as unidades são operações de negócios por segundo. É menos trabalhoso projetar uma peça com alto volume de produção do que uma com baixo volume de produção.21 mostra os resultados para um servidor usando o Barcelona. compilador. por um período de tempo.21  SPECpower_ssj2008 executando no AMD Opteron X4 2345 (Barcelona) a 2. o SPEC resume esses números em um único número.38 Capítulo 1  Abstrações e Tecnologias Computacionais FIGURA 1. . aumentando o aproveitamento. e n ∏ a significa oproduto a i 1 × a2 × … × an i =1 Benchmark de potência SPEC Hoje. em que Razão do tempo de execuçãoi é o tempo de execução. dividido em incrementos de 10%. que exercita processadores. Quantidade de aprimoramento Essa é uma versão quantitativa da lei dos retornos decrescentes. O propósito dessas seções é ajudar a evitar esses erros nas máquinas que você pode proje- tar ou usar. Quanto terei de melhorar a velocidade da multiplicação se eu quiser que meu programa execute cinco vezes mais rápido? O tempo de execução do programa depois de fazer a melhoria é dado pela seguinte equação simples. Suponha que um programa execute em 100 segundos em um computador. 5. Para este problema: 80 seg Tempo de execução após o aprimoramento = + (100 − 80 segundos) n Como queremos que o desempenho seja cinco vezes mais rápido. Vamos começar com uma armadilha que engana muitos projetistas e revela um relacionamento importante no projeto de computadores. tentaremos fornecer um contraexemplo. com operações de multiplicação responsáveis por 80 segundos desse tempo. 4. Também discutiremos armadilhas ou erros facilmente cometidos. A ciência deve começar com os mitos e com a análise dos 1. Como as máscaras usadas para fabricar o chip são caras. esta seção não poupa exemplos rele- vantes. Essa melhoria tem visitado os projetistas de hardware e de software. Chamamos esses equívocos de falácias. o custo de desenvolvimento por die é menor com peças de alto volume de produção. as armadilhas são generalizações de princípios verdadeiros em um contexto restrito. Quando estivermos discutindo uma falácia. conhecida como lei de Amdahl: lei de Amdahl  Uma regra indicando que a melhoria de Tempo de execução após o aprimoramento = desempenho possível com determinado aprimoramento é Tempo de execução afetado pelo aprimoramento limitada pela quantidade com que + Tempo de execução não afetado o recurso aprimorado é utilizado. Um problema de pro- jeto simples ilustra isso muito bem. Os custos de desenvolvimento de engenharia são altos e quase sempre independem do volume de produção.8  Falácias e armadilhas 39 3. Peças de alto volume de produção normalmente possuem dies menores do que as peças de baixo volume de produção e.8   Falácias e armadilhas mitos. Falácias e armadilhas de custo/desempenho têm confundido muitos arquitetos de computador. portanto. gerando 80 seg 20 seg = + 20 seg n 80 seg 0= n . Sir Karl Popper. o novo tempo de execução deverá ser 20 segundos. 1. incluindo nós. portanto. o custo por chip é menor para volumes de produção mais altos. Armadilha: Esperar que a melhoria de um aspecto de um computador aumente o desempe- nho geral por uma quantidade proporcional ao tamanho da melhoria. Em geral. A finalidade de uma seção de falácias e armadilhas. Consequentemente. 1957 explicar alguns conceitos errôneos comuns que você pode encontrar. é The Philosophy of Science. têm um aproveitamento mais alto por wafer. que será incluída em cada capítulo. normalmente é mais fácil de melhorar. FIGURA 1. digamos. o conceito facilmente também é mal utilizado. A Figura 1. Falácia: Os computadores com pouca utilização demandam menos potência. 50% de carga. e. A lei de Amdahl também é usada para se demonstrar limites práticos do número de processadores paralelos.22  Resultados do SPECPower para três servidores com o melhor ssj_ops geral por watt no quarto trimestre de 2007. A eficiência de potência importa em baixas utilizações. 682 e 677. Outro erro comum é usar apenas dois dos três fatores para comparar o desempenho. Luiz Barroso e Urs Hölzle [2007] argumentam que deveríamos reprojetar o hardware para alcançar a “computação proporcional à energia”. Ironicamente. pois as cargas de trabalho do servidor variam. A utilização de CPU para os servidores no Google. Um tema comum no projeto do hardware é um corolário da lei de Amdahl: torne mais rápido o caso comum. junto com a equação de desempenho da CPU. Como as cargas de trabalho dos servidores variam. a frequência com que um evento ocorre pode ser muito mais alta do que a frequência de outro evento. Assim. Essa orientação simples nos faz lembrar que. 10% de carga e ocioso. A lei de Amdahl é explorada com mais detalhes nos exercícios. A lei de Amdahl. Já mostramos a falácia de prever o desempenho com base simplesmente na taxa de clock. é uma ferramenta prática para avaliar melhorias em potencial. Sem dúvida. Examinamos esse argumento na seção de Falácias e Armadilhas do Capítulo 7. Até mesmo os servidores com apenas 10% de utilização se queimam com cerca de dois terços de sua potência máxima. em muitos casos. mas utilizam uma grande fração da potência máxima. poderíamos reduzir a conta de eletricidade dos centros de dados e nos tornarmos bons cidadãos corporativos em uma era de preocupação crescente com as emissões de CO2.40 Capítulo 1  Abstrações e Tecnologias Computacionais Ou seja. não existe quantidade pela qual podemos melhorar a multiplicação para conseguir um aumento quíntuplo no desempenho. Esse conceito também gera o que chamamos de lei dos retornos decrescentes na vida diária. portanto. tornar o caso comum rápido tenderá a melhorar o desempenho mais do que otimizar o caso raro. o caso comum normalmente é mais simples do que o caso raro. A memória para o dois primeiros servidores é de 16 GB e do último é 8 GB. está entre 10% e 50% na maior parte do tempo e em 100% em menos de 1% do tempo. por exemplo. Armadilha: Usar um subconjunto da equação de desempenho como uma métrica de desempenho. respectivamente. Se os servidores futuros usassem.22 mostra a potência para os servidores com os melhores resultados do SPECpower em 100% de carga. A melhoria de desempenho possível com determinado aprimoramento é limitada pela quantidade com que o recurso aprimorado é utilizado. ou na contagem de instruções ou no CPI. A lei de Amdahl nos lembra que a oportunidade para melhoria é afetada por quanto tempo o evento consome. se a multiplicação é responsável por apenas 80% da carga de trabalho. Embora o uso de dois dos três fatores possa ser válido em um contexto limitado. Podemos usar a lei de Amdahl para estimar os aprimoramentos no desempenho quando sabemos o tempo consumido para alguma função e seu ganho de velocidade em potencial. 10% da potência máxima a 10% de carga de trabalho. O ssj_ops geral por watt dos três servidores são 698. quase . 1 a. Como MIPS é uma taxa de execução de instruções. os computadores no futuro poderão ter 1. Não podemos comparar computadores com diferentes conjuntos de instruções usando MIPS. Para deter.9  Comentários finais 30 toneladas. questões.000 válvulas e pesa 1. mas isso não significa que os projetistas podem se limitar a conhecer uma única tecnologia. vemos o relacionamento entre MIPS. 1. Segundo. Por exemplo. Existem três problemas com o uso do MIPS como uma medida para comparar com- putadores. é seguro dizer que serão muito melhores do que são hoje. se um novo programa executa mais instruções. Esse princípio de abstração é fundamental para compreender os sistemas computacionais atuais. Finalmente. cada camada inferior oculta seus detalhes do nível acima. Talvez o exemplo mais importante de abstração seja a interface entre hardware e software de baixo . MIPS especifica o desempenho inversamente ao tempo de execução. milhões de instruções por minado programa. que corresponde à intuição. computadores mais rápidos possuem uma taxa de MIPS mais alta. e mais importante. pois as contagens de instruções certamente serão diferentes. Para participar desses avanços. substituindo o tempo de execução. assim. MIPS varia entre os programas no mesmo computador. MIPS Tempo de execução × 106 é calculado como a contagem de instruções dividida pelo produto do tempo de execução e 106. Primeiro.0 1. taxa de clock e CPI: Contagem de instruções Taxa de clock MIPS = = Contagem de instruções × CPI CPI × 106 × 10 6 Taxa de clock Lembre-se de que o CPI variou em 13× para SPEC2006 no Opteron X4. um computador não pode ter uma única avaliação MIPS. terão no futuro. Uma alternativa ao tempo é o milhões de instruções por segundo (MIPS). Qual computador é mais rápido? Enquanto o Eniac é equipado com 18. os projetistas e programadores de computador precisam entender várias Popular Mechanics. de modo que o MIPS também varia. Que computador tem a avaliação MIPS mais alta? b.9  Comentários finais 41 todas as alternativas propostas para o uso do tempo como métrica de desempenho por fim levaram a afirmações enganosas. A boa notícia sobre MIPS é que ele é fácil de entender e computadores mais rápidos significam um MIPS maior. MIPS especifica a taxa de execução de instruções. o MIPS é simplesmente segundo (MIPS)  Uma medida da velocidade de execução do programa baseada no número Contagem de instruções MIPS = de milhões de instruções.000 válvulas e talvez pesar apenas Embora seja difícil prever exatamente o nível de custo/desempenho que os computadores 1. março de 1949 Os projetistas de hardware e de software constroem sistemas computacionais em cama- das hierárquicas. mas não leva em conta as capacidades das instruções. mas cada instrução é mais rápida. o MIPS pode variar independentemente do desempenho! Considere as seguintes medidas de desempenho para um programa: Verifique você mesmo Medida Computador A Computador B Número de instruções 10 bilhões 8 bilhões Taxa de clock 4 GHz 4 GHz CPI 1. resultados distorcidos ou interpretações incorretas.5 tonelada. Duas das principais ideias são a exploração do paralelismo no programa. Mapa para este livro Na base dessas abstrações estão os cinco componentes clássicos de um computador: cami- nho de dados. em geral por meio de caches. Enquanto o silício impulsiona o rápido avanço do hardware. Manter a arquitetura do conjunto de instruções como uma constante permite que muitas implementações dessa arquitetura – provavelmente variando em custo e desempenho – executem software idêntico. os melhores projetos buscarão o equilíbrio apropriado para determinado mercado entre todos esses fatores. Esse tempo de execução está relacionado a outras medições importantes que podemos fazer pela seguinte equação: Segundos Instruções Ciclos de clock Segundos = × × Programa Programa Instrução Ciclo de clock Usaremos essa equação e seus fatores constituintes muitas vezes. O tempo de execução é a única medida válida e incontestável do desempenho. 7 e Apêndice A j Memória: Capítulo 5 j Entrada: Capítulo 6 j Saída: Capítulo 6 . que é igual ao tempo de execução. Os projetos de computadores sempre foram medidos pelo custo e desempenho. Esses cinco componentes também servem de estrutura para os demais capítulos do livro: j Caminho de dados: Capítulos 3. é uma medida confiável do desempenho. perspectiva uma métrica que é válida em um contexto limitado é estendida e usada além desse contexto ou sem o esclarecimento adicional necessário para torná-la válida. 5.42 Capítulo 1  Abstrações e Tecnologias Computacionais nível. não refletindo o tempo de execução. controle. o setor de software a passar para a programação do hardware em paralelo. Lembre-se. As tecnologias vitais para os processadores modernos são os compiladores e o silício. chamada arquitetura do conjunto de instruções. Conservar energia enquanto se tenta aumentar o desempenho tem forçado o setor de hardware a passar para microprocessadores multicore. o desempenho e a potência. No lado negativo. outras vezes. e a exploração da localidade dos acessos a uma hierarquia de memória. de que individualmente os fatores não determinam o desempenho: somente o produto. forçando. normalmente por meio de processadores múltiplos. Existe um método confiável para determinar e informar o desempenho usando o tempo de execução dos programas reais como métrica.4). porém. De igual importância para uma compreensão da tecnologia de circuito integrado é o co- nhecimento das taxas de mudança tecnológica esperadas. 7 e Apêndice A j Controle: Capítulos 4. além de outros fatores importantes. essas métricas possuem falhas desde o início. Colocando em Muitas outras métricas foram propostas e desapareceram. a arquitetura pode impedir a introdução de inovações que exijam a mudança da interface. assim. entrada e saída (veja novamente a Figura 1. A potência substituiu a área do die como o recurso mais crítico do projeto de micro- processadores. confiabilidade. memória. como potência. Às vezes. custo de proprietário e es- calabilidade (ou facilidade de expansão). Embora este capítulo tenha focalizado o custo. novas ideias na organização dos computadores melhoraram seu custo/desempenho. no site. substituindo os parâmetros indicados pelos seus próprios valores exclusivos. caso você esteja interessado em pesquisar mais a fundo.1 usando os parâmetros dados na linha A da tabela”. <1. Como alternativa.10  Perspectiva histórica e leitura adicional a pessoa quase desaparece na massa de mentes afundando umas sobre as outras. por meio de uma série de máquinas ou descrever alguns projetos importantes. 1. velocidade da luz. você pode compreender melhor as forças que formarão a 1974 computação no futuro. O Capítulo 3 descreve como os computadores realizam operações aritméticas. histórico. Use os números à esquerda das palavras na resposta. 1. Um campo ativo da ciência é como um imenso formigueiro. por exemplo. Podemos traçar o desenvolvimento de uma ideia de um lugar para outro. Esses parâmetros são necessários para solucionar as perguntas que compreendem o exercício.3.11  Exercícios   1 A maioria dos exercícios nesta edição é projetada de modo que apresente uma descrição qualitativa com o apoio de uma tabela que oferece parâmetros quantitativos alternativos. 1.10 está no site.1 Encontre a palavra ou frase da seguinte lista que melhor corresponde à descrição nas ques- tões a seguir. e o Apêndice A descreve o chip de proces- sador gráfico altamente paralelo. Exercício 1. apresenta o projeto lógico. “Natural humana por trás dos avanços tecnológicos e colocar as realizações dentro de seu contexto Science”. é possível dizer “complete a Pergunta 4. As seções do texto.3> significa que você deve ler a Seção 1. O restante da Seção 1. 1 Contribuição de Javier Bruguera da Universidade de Santiago de Compostela. Por exemplo. As avaliações do tempo relativo à solução dos exercícios são mostradas entre colchetes após cada número de exercício. Entendendo o passado. e fornece- passando-as adiante na mos referências. o Capítulo 7 descreve os microprocessadores multicore explicitamente paralelos. em The Lives of a Cell. que também são coletadas separadamente no site na seção “Further Reading”. Em média. O Apêndice B oferece uma referência para o conjunto de instruções do Capítulo 2. Sua finalidade é apresentar a história Lewis Thomas. para ajudar a resolver esse exercício. o Capítulo 4 descreve como os processadores exploram o paralelismo implícito. serão indicadas entre sinais de maior e menor.1. que estão no núcleo da revolução paralela. há uma seção dedicada à perspectiva histórica que pode ser encon- carregando informações trada no site que acompanha este livro. O Apêndice C. Esta perspectiva histórica desse capítulo fornece uma base para algumas das principais ideias apresentadas neste capítulo de abertura. O Capítulo 2 descreve os conjuntos de instruções – a interface entre os compiladores e a máquina – e destaca o papel dos compiladores e das linguagens de programação ao usar os recursos do conjunto de instruções. Cada seção de perspectiva histórica no site termina com sugestões para leitura adicional. O Capítulo 5 descreve como a hierarquia de memória explora a localidade. Cada resposta deve ser usada apenas uma vez.11 Exercícios 43 Como dissemos. um exercício avaliado em [10] levará o dobro do tempo de um avaliado em [5]. “Sob as tampas”. Para cada capítulo. os instrutores podem personalizar esses exercícios para criar novas soluções. Perguntas individuais podem ser solucionadas usando-se qualquer um ou todos os parâmetros — você decide quantos dos parâmetros deverão ser considerados para qualquer pergunta do exercício. que devem ser lidas antes de resolver um exercício. . centros de dados 21.1. RAM 25.6 [2] <1. petabyte 20.1> Atualmente a maior classe de computador que executa uma aplicação ou um conjunto de aplicações relacionadas 1.9 [2] <1.1> Um tipo de memória chamada memória de acesso aleatório 1. processadores multicore 23. assembler 9. terabyte 19.1> Parte de um computador. computadores embutidos 22.16 [2] <1.12 [2] <1.1. servidores inferiores 17.1. linguagem assembly 6.11 [2] <1.1. supercomputadores 18. fortran 1. CPU 26. cobol 13.2> Programa que traduz instruções simbólicas para instruções binárias 1.1.10 [2] <1.3 [2] <1.1.1.1> Linguagem especial usada para descrever componentes de hardware 1.1> Computador composto de centenas a milhares de processadores e terabytes de memória 1.1.1> Computador usado para executar grandes problemas e normalmente acessado por meio de uma rede 1. VHDL 24.2> Linguagem binária que o processador pode entender .1 [2] <1. normalmente acessado por uma rede 1.15 [2] <1. chamada unidade central de processamento 1. computadores desktop 15.1. mundos virtuais 14.1> 1015 ou 250 bytes 1.1. instrução 5.1> Milhares de processadores formando um grande cluster 1. linguagem de alto nível 10. bit 4.7 [2] <1.4 [2] <1.1. software de aplicação 12.1> Computador desktop sem a tela ou teclado.44 Capítulo 1  Abstrações e Tecnologias Computacionais 1. compilador 3.1.1.2> Linguagem de alto nível para processamento de dados comerciais 1.8 [2] <1.2> Computador pessoal que oferece bom desempenho para usuários isolados a um baixo custo 1.5 [2] <1. C 8.14 [2] <1.1> Aplicação atual da ficção científica que provavelmente estará disponível no futuro próximo 1.1> Um microprocessador contendo vários processadores no mesmo chip 1.13 [2] <1.1.1. linguagem de máquina 7. sistema operacional 2.2> Programa que traduz instruções na linguagem de alto nível para a linguagem assembly 1.2 [2] <1. software do sistema 11. servidores 16.1. composta de palavras e expressões algébricas. que precisa ser traduzida para a linguagem assembly antes de ser executada em um computador 1.2 [5] <1.2.2> Comandos que os processadores entendem 1. que inclui o sistema operacional e os compiladores 1.2> 1012 ou 240 bytes Exercício 1. 5 ns 50 ns 5 ms 5 ms b.3> Se um computador tem uma memória principal de 2 GB.4 [5] <1.17 [2] <1.2. 7 ns 70 ns 15 ms 20 ms 1. quanto tempo levará para chegar? Para os problemas abaixo.1.3> Para uma tela colorida usando 8 bits para cada uma das cores primárias (vermelho.3> Descubra quanto tempo é necessário para ler um arquivo de uma memória DRAM se a memória cache demora 2 microssegundos para isso.26 [2] <1.3> Se um arquivo de 256 KB for enviado por uma rede Ethernet.11 Exercícios 45 1.2> Interface entre o programa do usuário e o hardware.1 [10] <1. Cache DRAM Memória Flash Disco magnético a.1.20 [2] <1. 1 1024 x 768 2 GB 100 Mbit 2 2560 x 1600 4 GB 1 Gbit 1.2. azul) por pixel e com uma resolução de 1280 × 800 pixels. .2> Linguagem de alto nível para computação científica 1. qual deve ser o tamanho (em bytes) do buffer de frame a fim de armazenar um frame? 1.2> Camada de software entre o software de aplicação e o hardware. utilize as informações da tabela abaixo para o tempo de acesso para cada tipo de memória. supondo que a memória não contém outra informação? 1.5 [5] <1.21 [2] <1.2> Representação simbólica das instruções de máquina 1.18 [2] <1.25 [2] <1.2> Software/programas desenvolvidos pelos usuários 1.1.22 [2] <1.23 [2] <1.24 [2] <1.3> Descubra quanto tempo é necessário para ler um arquivo de um disco magnético se a memória cache demora 2 microssegundos para isso. quantos frames ele poderia armazenar.1.1. 1. oferecendo uma série de serviços e funções de supervisão 1.2.1.3 [5] <1.1.1.1.2> Linguagem portável. Configuração Resolução Memória Principal Rede Ethernet a.1.2. 1.19 [2] <1. verde. 1 640 x 480 2 GB 100 Mbit 2 1280 x 1024 4 GB 1 Gbit b.2 Considere as diferentes configurações mostradas na tabela seguinte.2> Linguagem de alto nível usada para escrever software de aplicação e de sistemas 1.2> Dígito binário (valor 0 ou 1) 1. utilize as informações da tabela seguinte.3 [10] <1.6 [5] <1. Qual a taxa de clock que deve ser utilizada para a redução de tempo? Para os problemas abaixo.3.46 Capítulo 1  Abstrações e Tecnologias Computacionais 1. Processador Taxa de clock Número de instruções Tempo a. 20% classe B. C e D. P1 3 GHz 1.4> Se cada processador executa um programa em 10 segundos.1 [10] <1. Existem quatro classes de instruções: A.4 Considere duas implementações diferentes da mesma arquitetura do conjunto de ins- truções.8 P3 4 GHz 2. 50% classe C e 20% classe D.4.3.4 [10] <1. A taxa de clock e o CPI de cada implementação são dados na tabela a seguir.4> Ache a taxa de clock para P2 que reduz o tempo de execução para o P1.3. 1. B. Exercício 1. P2 e P3 executando o mesmo conjunto de instruções com as taxas de clock e CPIs dadas na tabela a seguir. P1 3 GHz 20 x 109 7s P2 2.5 GHz 1.2 P2 3 GHz 0.3> Descubra quanto tempo é necessário para ler um arquivo de uma memória flash se a memória cache demora 2 microssegundos para isso.5 [5] <1. Exercício 1.4> Dado um programa com 106 instruções divididas em classes das seguin- tes formas: 10% classe A.0 P3 4 GHz 2. P1 2 GHz 20 x 109 5s P2 3 GHz 30 x 109 8s P3 4 GHz 25 x 109 7s 1. Processador Taxa de clock CPI Classe A CPI Classe B CPI Classe C CPI Classe D P1 1.3.4> Ao tentar reduzir o tempo em 30%. 1.3. encontre o número de ciclos e o número de instruções.6 [5] <1.2 [10] <1. Processador Taxa de clock CPI a.2. a CPI aumenta em 20%.0 1.2 b.5 GHz 30 x 109 10 s P3 4 GHz 90 x 109 9s b.4> Ache instruções por ciclos (IPC) para cada processador. P1 2 GHz 1.1 [5] <1. que implementação é mais rápida? .3.4> Ache o número de instruções para P2 que reduz o tempo de execução para o P3. 1.5 P2 2.3 Considere os três diferentes processadores P1.4> Qual processador possui o desempenho mais rápido expressado pelas instruções por segundo? 1.5 GHz 1 2 3 4 P2 2 GHz 2 2 2 2 1. 5 Considere duas implementações diferentes.4. CPI CPI CPI CPI CPI Taxa de clock Classe A Classe B Classe C Classe D Classe E a.2 [5] <1. que ocorre com o dobro da frequência das outras. 1.4 [5] <1. A taxa de clock e o CPI de cada classe são dados a seguir. para a classe A.4> Se o número de instruções executadas em um certo programa for dividi- do igualmente entre as classes de instruções exceto. Existem cinco classes de instruções (A. Número de Instruções Cálculo Load Store Desvio Total a.5.0 GHz 1 1 2 3 2 P2 1. C.4. qual computador é o mais rápido? O quanto ele é mais rápido? 1.0 GHz 1 2 3 4 3 P2 1.4> Se o número de instruções executadas em um certo programa é dividido igualmente entre as classes de instruções. P1 1. D e E) no conjunto de instruções.5. qual é o tempo de execução do programa em um processador de 2 GHz? 1. Programa 4 1500 300 100 100 2000 1.11 Exercícios 47 1.4> Ache o CPI para o programa.4.5 GHz 1 2 3 4 3 1. .6 [10] <1.3 [5] <1.4> Suponha que o desempenho de pico seja definido como a taxa mais rápida que um computador pode executar qualquer sequência de instruções.4> Qual é o CPI global para cada implementação? 1. Usando esses dados.5. A tabela a seguir mostra o número de instruções para um programa.1 [5] <1. do mesmo conjunto de instruções. ache o tempo de execução de cada programa em um processador MIPS de 3 GHz. que ocorre com o dobro da frequência das outras.3 [5] <1.4. 1. qual é o ganho de velocidade e o CPI? Exercício 1.4 [5] <1. load e store 5 ciclos e desvio 2 ciclos.4> Ache os ciclos de clock exigidos nos dois casos. B. você estará explorando as opções de desempenho com diferentes mudanças feitas em um processador MIPS.4> Considerando que as instruções aritméticas levam 1 ciclo.4> Supondo que os cálculos usem 1 ciclo.2 [5] <1.4> Se o número de instruções de carga puder ser reduzido pela metade. P1 1. P1 e P2.5 GHz 2 2 2 4 4 b.4. Quais são os desempenhos de pico de P1 e P2 expressos em instruções por segundo? 1. instruções de load e store usem 10 ciclos e desvios usem 3 ciclos.5. Aritmética Store Load Desvio Total 500 50 100 50 700 1. Programa 1 1000 400 100 50 1550 b. qual computador é o mais rápido? O quanto ele é mais rápido? A tabela a seguir mostra o desmembramento de tipo de instrução para diferentes progra- mas. exceto para a classe E.5 [5] <1. Existem cinco classes de instruções (A. Classe CPI em P1 CPI em P2 a. Os números médios de ciclos para cada classe de instruções para P1 e P2 são listados na tabela a seguir.3 [5] <1. instruções de load e store usem 2 ciclos e desvios usem 3 ciclos. qual é o ganho de velocidade de um programa se o número de instruções de cálculo puder ser reduzido pela metade? Exercício 1.5 [5] <1. instruções de load e store usem 2 ciclos e desvios usem 3 ciclos. Se os tempos de execução nos dois processadores forem os mesmos. e tendo um CPI médio de 1. A 1 2 B 1 2 C 1 2 D 4 4 E 5 4 .4> Um novo compilador é desenvolvido. o quão mais rápido é o clock do processador rodando o código do compilador A versus o clock do processador rodando o código do compilador B? 1. mas que os pro- gramas compilados executem em dois processadores diferentes. C.6 Os compiladores podem ter um impacto profundo sobre o desempenho de uma aplicação em determinado processador. 1.4> Considere os CPIs médios encontrados em 1. B.5. dois compiladores diferentes são utilizados. e P2 tem uma taxa de clock de 6 GHz. P1 1 2 3 4 5 P2 2 2 2 2 6 1. P1 tem uma taxa de clock de 4 GHz. Qual é o ganho de velocidade do uso desse novo compilador versus o uso do Compilador A ou B no processador original de 1. P1 1 2 3 4 5 P2 3 3 3 5 5 b.48 Capítulo 1  Abstrações e Tecnologias Computacionais 1. do mesmo conjunto de instruções. Este problema explorará o impacto que os compiladores têm sobre o tempo de execução. D e E) no conjunto de instruções. ache o tempo de execução de cada programa em um proces- sador MIPS de 3 GHz. Ache o CPI médio para cada programa dado que o processador tem um tempo de ciclo de clock de 1 nS. A 1 2 B 2 2 C 3 2 D 4 4 E 5 4 Classe CPI em P1 CPI em P2 b.4> Supondo que os cálculos usem 1 ciclo.4> Para o mesmo programa. usando apenas 600 milhões de instruções. P1 e P2.2 [5] <1.1.6.1 [5] <1. Essa tabela mostra o tempo de execução dos dois programas compilados diferentes.6 [5] <1.5.6. CPI Classe A CPI Classe B CPI Classe C CPI Classe D CPI Classe E a.4> Supondo que os cálculos usem 1 ciclo.1.6.6. 1.6.1? Considere duas implementações diferentes. 3 W Pentium 4 Prescott (2004) 3.7.6 GHz 103 W Core 2 Ketsfield (2007) 2.7.1 W Pentium 4 Willamette (2001) 2 GHz 75.) 1.4> Em que frequência.9 W Pentium (1993) 66 MHz 10.1 W 80486 (1989) 25 MHz 4.6 [5] <1.11 Exercícios 49 1.1 W Pentium Pro (1997) 200 MHz 29. exceto para a classe A. Processador Taxa de clock Potência 80286 (1982) 12.7.6 [5] <1.5> Qual é a média geométrica das razões entre as gerações consecutivas para taxa de clock e potência? (A média geométrica é descrita na Seção 1.4 [5] <1.5> Ache a média das cargas capacitivas.5> Ache a maior mudança relativa em tensão entre as gerações.6.5? Exercício 1. .25 Core 2 Ketsfield (2007) 1.2 [5] <1. considerando um consumo de energia estática desprezível.5> Qual é a maior mudança relativa na taxa de clock e potência entre as gerações? 1.7.5> Ache a média geométrica das razões de tensão nas gerações desde o Pentium. 1.6.7 A tabela a seguir mostra o aumento na taxa de clock e potência de oito gerações de proces- sadores Intel durante 28 anos.6.4.667 GHz 95 W 1.4> Se o número de instruções executadas em um certo programa for divi- dido igualmente entre as classes de instruções no Problema 2.4 [5] <1.7.5 MHz 3.7.1 [5] <1.3 W 80386 (1985) 16 MHz 4. o quão mais rápido é P2 em relação a P1? 1.1 1. que ocorre com o dobro da frequência das outras.3 Pentium 4 Willamette (2001) 1.36. 1.7.5 [5] <1.75 Pentium 4 Prescott (2004) 1.6. Quais são os desempenhos de pico de P1 e P2 expressos em instruções por segundo? 1.5 [5] <1.4> Suponha que o desempenho de pico seja definido como a taxa mais rápida que um computador pode executar qualquer sequência de instruções. P2 tem o mesmo desempenho de P1 para o mix de instruções dado em 1. Processador Tensão 80286 (1982) 5 80386 (1985) 5 80486 (1989) 5 Pentium (1993) 5 Pentium Pro (1997) 3.5> O quão maior é a taxa de clock e potência da última geração com relação à primeira geração? Considere os valores a seguir para a voltagem em cada geração.3 [5] <1. 1. 8.5> Se a potência total dissipada for reduzida em 10% enquanto mantém a estática para a taxa de potência total do problema 1.8 Suponha que tenhamos desenvolvido novas versões de um processador com as caracterís- ticas a seguir. 1.1 V. 1 1/21/4 1. Versão 1 1.5> Supondo que a carga capacitiva da versão 2 é 80% da carga capacitiva da versão 1.1 V 3 GHz Versão 2 0.9 Embora a potência dinâmica seja a principal fonte de dissipação de energia na CMOS.8. Considere os valores mostrados na tabela a seguir para a dissipação de potência estática e dinâmica para várias gerações de processadores.9.8.3 [5] <1.5> Ache a porcentagem da potência total dissipada compreendida por potência estática. ache a voltagem para a versão 2 se a potência dinâmica da versão 2 for reduzida em 40% a partir da versão 1.5> Encontre a expansão da capacitância por área unitária.2 1/21/4 1. a corrente de vazamento produz uma dissipação de potência estática V × Ivazamento.5 [5] <1.2 V 2 GHz b. Versão 1 1. Supondo que as tendências da indústria mostrem que a geração de um novo processo se expanda da seguinte forma: Capacitância Tensão Taxa de clock Área a.2 [5] <1.8.1 [5] <1.5> Em quanto foi reduzida a potência dinâmica se a carga capacitiva não muda? 1.5> Encontre o fator de expansão para a potência dinâmica. Tecnologia Potência dinâmica (W) Potência estática (W) Tensão (V) a. um poder de consumo de 95 W e uma tensão de 1. quanto a tensão deve ser reduzida para que a corrente de vazamento continue igual? .9.5 GHz Versão 2 1.8. Versão Tensão Taxa de clock a.6 [5] <1.9.8. 180 nm 50 10 1.15 1/21/2 b. 1.1.75 V 1. encontre a tensão e a taxa de clock do processador para sua próxima geração de processamento.50 Capítulo 1  Abstrações e Tecnologias Computacionais Exercício 1. Quanto menores as dimensões no chip.2 [5] <1.9 1.8 V 4 GHz 1.5> Em quanto foi reduzida a carga capacitiva entre as versões se a potência dinâmica foi reduzida em 10%? 1. 1. 1 1/21/2 1. 70 nm 90 60 0. Exercício 1.1 [5] <1.4 [5] <1.5> Assumindo que um processador Core 2 com a taxa de clock de 2. mais significativa é a potência estática.667 GHz.2 b. 4.2 [5] <1. Considere que cada proces- sador tem uma frequência de clock de 2 GHz. 1.10. 62 W 50 W 30 W 1. 4 ou 8 núcleos. 2.3 [5] <1. Exercício 1. você estará explorando o ganho de velocidade das aplicações em processadores paralelos. 2.5> Determine a razão entre potência estática e potência dinâmica para cada tecnologia. Qual é o número total de instruções executadas por processador? Qual é o número agregado de instruções executadas por todos os processadores? 1. 2.10. 4 ou 8 processadores.6. 1.5> Determine a potência estática para cada versão em 0.4. Usando esses dados. ache o tempo de execução total para esse programa em 1. considerando uma razão entre potência estática e dinâmica de 0. Considere agora a dissipação de potência dinâmica de diferentes versões de um processador para três diferentes tensões dadas na tabela seguinte.10.9.4 [5] <1. 1.9.6> A tabela apresentada mostra o número de instruções exigido por processador para completar um programa em um multiprocessador com 1. .9.1 [5] <1. 4 ou 8 processadores. 1.6> Se o CPI das instruções aritméticas fosse dobrado. 1 2560 1280 256 1 4 2 2 1350 800 128 1 6 2 4 800 600 64 1 9 2 8 600 500 32 1 13 2 1.8 V a. 2. 75 W 60 W 35 W b. qual seria o impacto sobre o tempo de execução do programa em 1.9.3 [5] <1.2 V 1. Processadores # Instruções por processador CPI Load/ Load/ Aritmética Store Desvio Aritmética Store Desvio a.4. 4 e 8 processadores.6 [10] <1. 1.1. 2.0 V 0. 4 ou 8 processadores? A tabela a seguir mostra o número de instruções por núcleo de processador em um proces- sador multicore. além do CPI médio para executar o programa em 1. 1.6> Dados os valores de CPI à direita da tabela.5> Determine a média geométrica das variações de potência entre as versões.10 A tabela a seguir mostra o desmembramento de tipo de instrução de determinada aplicação executada em 1.11 Exercícios 51 1. 1.9.5 [5] <1.5> Determine a dissipação das potências estática e dinâmica utilizando as taxas obtidas no problema 1.8 V. 1. 1 2560 1280 256 1 4 2 2 1280 640 128 1 4 2 4 640 320 64 1 4 2 8 320 160 32 1 4 2 Processadores # Instruções por processador CPI Load/ Load/ Aritmética Store Desvio Aritmética Store Desvio b. 4 ou 8 núcleos? 1.11.10. a tensão seria 1.3 [10] <1.031 defeitos/cm2 25 1.50E + 09 1. De modo semelhante. Ache o consumo de potência do programa executando em 1. qual é o tempo de execução do programa usando 1.00E + 09 1. 1 1.50E + 09 1.10. Defeitos por área Diâmetro do wafer Dies por wafer unitária Custo por wafer a.8 Núcleos por processador Instruções por núcleo CPI médio b.52 Capítulo 1  Abstrações e Tecnologias Computacionais Usando esses dados.5. 1.2 1.4 [10] <1.4).11 A tabela a seguir mostra os dados de manufatura para diversos processadores. Núcleos por processador Instruções por núcleo CPI médio a.5.00E + 10 1.00E + 09 1.2 2 5.11. ache o consumo de potência do programa executando em 1. 1 1. 4 e 8 núcleos.1 [10] <1.25E + 09 1. 15 cm 84 0.11.4 V.6> Suponha que o consumo de potência do núcleo de um proces- sador possa ser descrito pela equação a seguir 5mA Potência = Tensão2 MHz em que a tensão de operação do processador é descrita pela equação a seguir 1 Tensão = Frequência + 0. 4 5 com a frequência medida em GHz.7> Ache o custo por die.00E + 10 1. Exercício 1. Repare que o número de instruções deve ser o número agregado de instruções executadas entre todos os núcleos. 1.7> Ache o aproveitamento. a 5 GHz.7> Se o número de dies por wafer for aumentado em 10% e os defeitos por unidade de área aumentar em 15%.6> Ao utilizar um único núcleo. Assim. 2. 1. 1.2 [5] <1. 4 ou 8 núcleos supondo que cada núcleo esteja operando a 500 MHz. supondo que cada núcleo esteja operando a uma frequência de clock de 3 GHz.6 [10] <1. 2.25E + 09 1. 2. 1. encontre o CPI requerido para o núcleo conseguir o tempo de execução igual ao tempo obtido ao utilizar o número de núcleos da tabela acima (vezes de execução do problema 1. 20 cm 100 0.2 2 5.6> Considerando uma frequência de clock de 3 GHz. . você estará explorando o ganho de velocidade das aplicações em processadores multicore.2 8 1. ache a área do die e o aproveitamento.2 4 2.4.10. 1.10.3 4 2.5 8 1.020 defeitos/cm2 12 b.5 [10] <1. 7> Ache o número de defeitos por unidade de área para cada tecnologia.4090 1. libquantum 1.7> Ache a mudança na SPECratio para a mudança descrita em 1.6 [5] <1. Os tempos de execução obtidos aparecem na tabela a seguir. Tempo de execução Tempo de referência Nome (seg) (seg) SPECratio a.4 [10] <1.11. astar 1.3 [5] <1. go 1658 700 10.13 Suponha que estejamos desenvolvendo uma nova versão do processador AMD Barcelona com uma taxa de clock de 4 GHz. 1.89 0. 1.79 4 GHz 9. A tabela a seguir mostra dados para outros benchmarks.12. o aproveitamento varie como mostra a tabela a seguir. T1 T2 T3 T4 aproveitamento 0. encontre a média geométrica. Exercício 1. Contagem Tempo de execução Tempo de referência Nome instruções × 109 (seg) (seg) a.92 0.5 [5] <1.12 A tabela a seguir mostra os resultados para os programas de benchmark SPE CPU2006 rodando em um AMD Barcelona.9 . 1.7> Descubra o CPI se o tempo de ciclo de clock for 0.7> Represente graficamente a variação do aproveitamento junto com a variação dos defeitos por área unitária.12.85 0.12.1 1. dada uma área de die de 200 mm2.2 [5] <1.11 Exercícios 53 Suponha que.4 [5] <1. Nome CPI Taxa de clock SPECratio a.7 b.95 1.5. 1. Acrescentamos algumas instruções ao conjunto de ins- truções.12.12.5 [5] <1.61 4 GHz 19.12. bzip2 2389 750 9650 b.7> Para esses dois benchmarks.11.8 b. bzip2 700 9.7> Ache o aumento em tempo de CPU se o número de instruções do benchmark for aumentado em 10% sem afetar o CPI. com a evolução da tecnologia de manufatura dos dispositivos eletrônicos.12. de modo que o número de instruções foi reduzido em 15% a partir dos valores mostrados para cada benchmark no Exercício 1.650 13.490 16.12. 1. 1. go 620 10. Exercício 1.7> Ache a razão SPEC.7> Encontre o aumento no tempo de CPU se o número de instruções do benchmark aumentar em 10% e o CPI for aumentado em 5%.333 ns.1 [5] <1. 13. por que isso ocorre? 1. Processador Taxa de clock CPI P1 4 GHz 1.14.8> Outra falácia é considerar que o processador executando o maior número de instruções precisará de um tempo de CPU maior. astar 690 1.54 Capítulo 1  Abstrações e Tecnologias Computacionais 1.4 [10] <1.13.13.25 P2 3 GHz 0.8> Ache o novo CPI. esses valores de CPI são maiores que aqueles obtidos nos exercícios anteriores para os mesmos benchmarks.8> Por quanto o tempo de CPU foi reduzido? A tabela a seguir mostra dados para outros benchmarks.13. 1.8> Uma falácia comum é usar milhões de instruções por segundo (MIPS) para comparar o desempenho de dois processadores diferentes e considerar que o processador com o maior valor de MIPS tem o maior desempenho.5 [10] <1. Tempo de execução Nome (seg) CPI Taxa de clock a.8> Uma falácia comum é considerar o computador com a maior taxa de clock como tendo o maior desempenho.8 cita como armadilha a utilização de um subconjunto da equação de de- sempenho como uma métrica de desempenho. 1. Se eles forem diferentes. Para ilustrar isso.2 [10] <1.1 [10] <1.2 [10] <1. considere os dados a seguir para a execução de determinada sequência de 106 instruções em diferentes processadores.13.14. 3 GHz e 4 GHz.14 A Seção 1. 1.1 [5] <1. Isso é decorrente principalmente da taxa de clock usada nos dois casos. definido como Nº de operações de PF MFLOPS = (Tempo de execução × 106 ) . 1.8> Em geral. 1.3 [10] <1. Verifique se isso é verdade para P1 e P2.8> Se o tempo de execução for reduzido por outros 10% sem afetar o CPI e com uma taxa de clock de 4 GHz. Exercício 1. libquantum 960 1. determine o número de instruções que P2 pode executar ao mesmo tempo em que P1 precisa para executar 106 instruções.3 [5] <1. Verifique se isso é verdade para P1 e P2. determine o número de instruções.75 1.6 [10] <1.8> Determine a taxa de clock exigida para gerar uma redução de mais 10% no tempo de CPU enquanto mantém o número de instruções e CPI inalterados.14.8> Determine a taxa de clock se o CPI for reduzido em 15% e o tempo de CPU em 20% enquanto o número de instruções for inalterado.79 3 GHz 1. Outro valor de desempenho comum é milhões de operações de ponto flutuante por segundo (MFLOPS).13. Determine se o aumento no CPI é semelhante ao da taxa de clock. Considerando que o proces- sador P1 está executando uma sequência de 106 instruções e que o CPI dos processadores P1 e P2 não muda.61 3 GHz b. 4 [10] <1.15 Outra armadilha citada na Seção 1. P1 1 x 106 50% 40% 10% 0.11 Exercícios 55 mas esse valor tem os mesmos problemas do MIPS.15. Instruções Instruções Instruções Instruções CPI Processadores PF INT L/S desvio CPI (PF) CPI (INT) CPI (L/S) (Desvio) a.8 1.15. Considere um computador rodando programas com os tempos de CPU mostrados na tabela a seguir. 40 s 90 s 60 s 20 s 210 s 1.15.8> O tempo total pode ser reduzido em 20% reduzindo-se apenas o tempo para as instruções de desvio? A tabela a seguir mostra o desmembramento de tipo de instrução por processador de determinada aplicação executada em diferentes números de processadores.0 1. Isso pode ser verdade.4 [10] <1.8> Ache o desempenho para os programas e compare com MIPS e MFLOPS. mas nem sempre é.1 [5] <1.8> Em quanto é reduzido o tempo total se o tempo para as operações de PF for reduzido em 20%? 1.14. 2 280 × 106 1000 × 106 640 × 106 128 × 106 1 1 4 2 b. Exercício 1.15.75 1. 1.14.5 1.8> Por quanto devemos melhorar o CPI das instruções de PF se quiser- mos que o programa execute duas vezes mais rápido? 1. Considere os programas na tabela a seguir.5 3 GHz 1. de Processador instruções L/S PF Desvio L/S PF Desvio clock a. 70 s 85 s 55 s 40 s 250 s b. Instruções Instruções PF Instruções INT Instruções L/S desvio Tempo total a.14. 1.5 [10] <1.0 4 GHz P2 2 x 106 40% 30% 30% 1.0 2.3 [5] <1.8> Ache os valores de MIPS para os programas.5 4 GHz P2 5 x 106 40% 40% 20% 1.25 0. Número de instruções CPI Taxa Cont.2 [5] <1.5 [10] <1.8> Por quanto devemos melhorar o CPI das instruções de L/S se quiser- mos que o programa execute duas vezes mais rápido? . 16 50 × 106 110 × 106 80 × 106 16 × 106 1 1 4 2 Considere que cada processador tenha uma taxa de clock de 2 GHz.25 3 GHz b. rodando nos dois processadores a seguir. 1.0 2.15.25 1.6 [10] <1. P1 5 × 106 30% 30% 40% 1.8 é esperar aprimorar o desempenho geral de um computador melhorando apenas um aspecto do computador.8> Encontre os valores de MFLOPS para os programas.8> Em quanto o tempo para operações INT é reduzido se o tempo total for reduzido em 20%? 1. 1. 15.5 3 1 26 1.16. N° Rotina A Rotina B Rotina C Rotina D Rotina E Roteamento processadores (ms) (ms) (ms) (ms) (ms) (ms) 2 40 78 9 70 4 11 4 29 60 4 36 2 13 8 15 45 3 19 3 17 16 7 35 1 11 2 22 32 4 23 1 6 1 23 64 2 12 0.2 [10] <1. Nesse caso.6 [10] <1.4 [10] <1.8> Para cada duplicação do número de processadores determine a razão do tempo de computação novo para antigo e a razão do tempo de roteamento novo para antigo.16. 4 12 45 6 36 3 b.8> Em quanto o tempo total é reduzido se a rotina B for melhorada em 10%? 1.56 Capítulo 1  Abstrações e Tecnologias Computacionais 1. o tempo de roteamento é um componente importante do tempo total.16.16 Outra armadilha. 1. 1. A tabela a seguir mostra o tempo de execução de cinco rotinas de um programa rodando em diferentes quantidades de processadores.8> Usando a média geométrica das razões extrapole para descobrir o tempo de computação e o tempo de roteamento em um sistema com 128 processadores.8> Ache o tempo de computação e o tempo de roteamento para um sistema com um processador. 1.3 [10] <1.8> Por quanto o tempo de execução do programa é melhorado se o CPI das instruções de INT e PF for reduzido em 40% e o CPI das instruções de L/S e desvio for reduzido em 30%? Exercício 1.16. Considere o tempo de execução e o tempo de roteamento dados na tabela a seguir.1 [10] <1. Rotina A Rotina B Rotina C Rotina D Rotina E N° processadores (ms) (ms) (ms) (ms) (ms) a. C e E for melhorado em 15%. .16. 32 2 7 1 6 2 1.8> Ache o tempo de execução total e em quanto ele é reduzido se o tempo das rotinas A. relacionada à execução dos programas em sistemas multiprocessadores.8> Em quanto o tempo total é reduzido se a rotina D for melhorada em 10%? O tempo de execução em um sistema multiprocessador pode ser dividido em tempo de computação para as rotinas mais tempo de roteamento gasto enviando dados de um proces- sador para outro.6 [5] <1. é esperar melhoria no desempenho aprimorando apenas o tempo de execução de parte das rotinas.16.5 [5] <1. tempo de acesso longo (milissegundos). §1.20 a US$2.1: Questões para discussão: muitas respostas são aceitáveis. b. Respostas das §1.a: ambos. digamos.7: 1. 2. Computador A tem a maior avaliação MIPS.11 Exercícios 57 §1.4: b. Memória usando semicondutores: volátil. §1. uma boa decisão econômica.7 segundos. 10%. Computador B é mais rápido. 1. pois o alto volume pode tornar o investimento extra para reduzir o tamanho do die em. 3 e 4 são motivos válidos. A resposta 5 geralmente pode ser verdadeira. c: nenhum. mas isso não precisa ser verdadeiro.00/GB. §1.4: 1.8: 53: a. §1.3: Memória em disco: não volátil. b: latência. tempo de acesso curto você mesmo” (nanossegundos) e custo de US$20 a US$75/GB. . e custo de Seções “Verifique US$0. 2. 2 Instruções: A Linguagem Eu falo espanhol com Deus. de Máquina italiano com as mulheres.4 Números com sinal e sem sinal  69 Charles V. 2.1 Introdução  60 francês com os homens 2.3 Operandos do hardware do computador  63 2. rei da França 1337-1380 2.6 Operações lógicas  80 2.7 Instruções para tomada de decisões  83 .2 Operações do hardware do computador  62 e alemão com meu cavalo.5 Representando instruções no computador  74 2. 2.8 Suporte a procedimentos no hardware do computador  88 2.14 Arrays versus ponteiros  127 2.13 Um exemplo de ordenação em C para juntar tudo isso  119 2.19 Comentários finais  143 2.20 Perspectiva histórica e leitura adicional  145 2.10 Endereçamento no MIPS para operandos imediatos e endereços de 32 bits  101 2.12 Traduzindo e iniciando um programa  111 2.17 Vida real: instruções do x86  134 2.15 Material avançado: Compilando C e interpretando Java  130 2.21 Exercícios 145 Os cinco componentes clássicos de um computador .9 Comunicando-se com as pessoas  97 2.18 Falácias e armadilhas  141 2.11 Paralelismo e instruções: Sincronização  109 2.16 Vida real: instruções do ARM  130 2. tanto na forma escrita pelos humanos quanto na forma lida pelo com- arquitetura. que existem certos [conjuntos de instruções] que são adequados para controlar e causar a execução de qualquer sequência de operações. Apresentamos as instruções em um padrão top-down. . geral dos outros dialetos do computador. junto com a velocidade com que tratam esses problemas. O outro exemplo. até que você veja a linguagem real de um computador. mais parecidas com dialetos regionais do que linguagens independentes. está dentro de quase todos os 330 milhões de PCs fabricados em 2008. por métodos lógicos formais. do ponto de vista atual. Você poderia pensar que as linguagens dos computadores fossem tão diversificadas quanto as dos humanos. expondo a representação dos números inteiros e de ponto flutuante e o hard- ware que os opera.. Con- memória como números. 1947 A “simplicidade do equipamento” é uma consideração tão valiosa para os computadores da década iniciada no ano 2000 quanto foi para os da década de 1950. você também descobrirá o segredo da conceito de programa computação: o conceito de programa armazenado. O conjunto de instruções escolhido vem da MIPS Technology. levando ao computador de programa cluímos com uma visão da evolução histórica dos conjuntos de instruções e uma visão armazenado. nós a refinamos passo a passo. a Seção 2. será fácil entender as outras. Burks. Logo. Aprendendo como representar as instruções. Além disso. quando você aprender uma. Você também verá o impacto das tipos podem ser armazenados na linguagens de programação e das otimizações do compilador sobre o desempenho.60 Capítulo 2  Instruções: A Linguagem de Máquina 2. a citação a seguir foi escrita antes que você pudesse comprar um computador e é tão verdadeira hoje quanto era em 1947: É fácil ver. são mais de natureza prática: a simplicidade do equipamento exigido pelo [conjunto de instruções] e a clareza de sua aplicação para os problemas realmente importantes. Começando com uma notação parecida com uma linguagem de programação restrita. O Capítulo 3 continua nos- sa descida. Essa semelhança ocorre porque todos os computadores são construídos a partir de tecnologias de hardware baseadas em princípios básicos semelhantes e porque existem algumas operações básicas que todos os computadores precisam oferecer.1   Introdução Para controlar o hardware de um computador é preciso falar sua linguagem. Mais adiante.. veremos dois outros conjuntos de instruções populares. Nossos exemplos estão na linguagem de programação C. Esse objetivo é antigo. Goldstine e von Neumann. O objetivo deste capítulo é ensinar um conjunto de instruções que siga esse conselho. ARM é muito semelhante ao MIPS e mais de três bilhões de processadores ARM foram entregues em dispositivos embutidos em 2008. As considerações realmente decisivas. putador. os projetistas de computador pos- suem um objetivo comum: encontrar uma linguagem que facilite o projeto do hardware e do compilador enquanto maximiza o desempenho e minimiza o custo. Além do mais. que é um exemplo elegante dos conjuntos de instruções criados desde a década de 1980. exercitará suas habilida- armazenado  A ideia de que as des com “linguagem estrangeira”. como Java. na realidade. mas. escrevendo programas na linguagem do computador e instruções e os dados de muitos executando-os no simulador que acompanha o livro. as linguagens de computador são muito seme- lhantes. na seleção de um [conjunto de instruções].15 no site mostra como esses exemplos mudariam para uma linguagem orientada a objetos. mostrando como ele é representado no hardware e o relacionamento entre as linguagens de programação de alto nível e essa linguagem mais primitiva. As palavras da linguagem de um computador são chamadas instruções e seu vocabulário é denomina- conjunto de instruções O do conjunto de instruções. Neste capítulo você verá o conjunto de instruções de um vocabulário dos comandos entendidos por uma determinada computador real. o Intel x86. 2. tornando a linguagem de máquina mais fácil de digerir.1 oferece uma prévia do conjunto de instruções abordado neste capítulo. Esse tutorial passo a passo entrelaça os componentes com suas explicações.9 .8 e 2.1 Introdução 61 Revelamos o conjunto de instruções do MIPS aos poucos. mostrando o raciocínio juntamente com as estruturas do computador.1  Assembly do MIPS revelado no Capítulo 2. FIGURA 2. As partes destacadas mostram o que foi introduzido nas Seções 2. A Figura 2. nos dois exemplos a seguir. d e e na variável a. Note que como não é o caso comum em lingua- gens de programação. está de acordo com a filosofia de manter o hardware simples: o hardware para um número variável de operandos é mais complicado do que o hardware para um número fixo. (Nesta seção.e # A soma b + c + d + e agora está em a. Burks. Uma instrução MIPS opera com dois operandos de origem e coloca o resultado em RESPOSTA um operando de destino.b. são necessárias três instruções para somar quatro variáveis.62 Capítulo 2  Instruções: A Linguagem de Máquina Certamente é preciso haver instruções para realizar as operações aritméticas 2. Portanto. e os computadores os ignoram. Goldstine e von Todo computador precisa ser capaz de realizar aritmética.2  Operações do hardware do computador fundamentais. este exemplo e os próximos funcionam para qualquer uma dessas linguagens de programação de alto nível: a = b + c.d # A soma b + c + d agora está em a. b. as duas instruções simples anteriores são compiladas diretamente nessas duas instruções em assembly do MIPS: add a. suponha que queiramos colocar a soma das variáveis b. As palavras à direita do símbolo (#) em cada linha acima são comentários para o leitor humano. c. no máximo.a.b. c instrui um computador a somar as duas variáveis b e c para colocar sua soma em a. Por exemplo. Como EXEMPLO o Java evoluiu a partir da linguagem C.c sub d.e . Exigir que cada instrução te- nha exatamente três operações. Logo. A notação em assembly do MIPS Neumann. na próxima seção. nem mais nem menos.) Esta sequência de instruções soma as quatro variáveis: add a. d = a − e. add a. b. Compilando duas instruções de atribuição C no MIPS Este segmento de um programa em C contém as cinco variáveis a. add a.c # A soma b + c é colocada em a. O número natural de operandos para uma operação como a adição é três: os dois números sendo somados e um local para colocar a soma. c. 1947 add a.a. Mostre o código do MIPS produzido por um compilador. estamos sendo deliberadamente vagos com relação ao que é uma “variável”. Essa notação é rígida no sentido de que cada instrução aritmética do MIPS realiza apenas uma operação e sempre precisa ter exatamente três variáveis.a. Essa situação ilustra o primeiro dos quatro princípios básicos de projeto do hardware: Princípio de Projeto 1: Simplicidade favorece a regularidade. vamos explicar com detalhes. uma instrução. Agora podemos mostrar. Outra diferença para a linguagem C é que comentários sempre terminam no final da linha. cada linha desta linguagem pode conter. d e e. A tradução de C para as instruções em linguagem assembly do MIPS é realizada pelo compilador. o relacionamento dos programas escritos nas linguagens de programação de mais alto nível com os programas nessa notação mais primitiva. t1 # f recebe t0 − t1. os sistemas Java de hoje normalmente compilam os bytecodes Java para os conjuntos de instruções nativos. A Seção 2. Os registradores são primitivas usadas no projeto do hardware que também são visíveis ao programador quando o computador .15 no site).que é(g + h) − (i + j) Para determinada função. Java 2. O conjunto de instruções desse interpretador é chamado bytecode Java (veja a Seção 2. Temos de colocar o resultado em algum lugar. chamada t1: add t1.g. precisam ser de um grupo limitado de locais especiais.13 mostra as consequências no desempenho de compilar versus interpretar programas Java. 2. Assim.h # variável temporária t0 contém g + h Embora a próxima operação seja subtrair.i. esses compiladores Java normalmente são denominados compiladores Just-In-Time (JIT – na hora exata).j # variáveltemporária t1 contém i + j Finalmente. embutidos diretamente no hardware. 2. você mesmo 1.12 mostra como os JITs são usados mais tarde que os compiladores C no processo de inicialização e a Seção 2. i e j: EXEMPLO f = (g + h) − (i + j). precisamos calcular a soma de i e j antes de podermos subtrair. C 3. Como essa compilação em geral é feita muito mais tarde do que para programas C.3  Operandos do hardware do computador Ao contrário dos programas nas linguagens de alto nível. Para chegar a um desempenho próximo ao programa em C equivalente. h.t0. Assembly do MIPS Detalhamento:  para aumentar a portabilidade. os operandos das instruções aritméticas são restritos. de modo que o compilador crie uma variável temporária. a instrução de subtração subtrai a segunda soma da primeira e coloca a diferença na variável f.3  Operandos do hardware do computador 63 Compilando uma atribuição C complexa no MIPS Uma instrução um tanto complexa contém as cinco variáveis f. chamados registradores. Java foi idealizada originalmente contando com um interpretador de software. g. O que um compilador C poderia produzir? O compilador precisa desmembrar essa instrução em várias instruções assembly. que é muito diferente do conjunto de instruções do MIPS. A primeira instrução MIPS RESPOSTA calcula a soma de g e h. pois somente uma operação é realizada por instrução MIPS. a segunda instrução coloca a soma de i e j em outra variável temporária criada pelo compilador. como MIPS. completando o código compilado: sub f. chamada t0: add t0. que linguagem de programação provavelmente utiliza mais Verifique linhas de código? Coloque as três representações a seguir em ordem. que correspondem às variáveis temporárias de antes: add $t0. h. normalmente 32 nos computadores atuais. usaremos $s0. nesta seção. O tamanho de um registrador na arquitetura MIPS é de 32 bits. O motivo para o limite dos 32 registradores pode ser encontrado no segundo dos quatro princípios de projeto básicos da tecnologia de hardware: Princípio de Projeto 2: Menor significa mais rápido. EXEMPLO por exemplo. As variáveis f. como o MIPS. e $t0.64 Capítulo 2  Instruções: A Linguagem de Máquina é completado.$s2 # registrador $t0 contém g + h add $t1. Embora pudéssemos simplesmente escrever instruções usando números para os regis- tradores. incluímos a restrição de que cada um dos três operandos das instruções aritméticas do MIPS precisa ser escolhido a partir de um dos 32 registradores de 32 bits. quitetura MIPS. exceto que subs- RESPOSTA tituímos as variáveis pelos nomes dos registradores mencionados anteriormente. $s3 e $s4. mais dois registradores temporários. para os registradores temporários necessários para compilar o programa nas instruções MIPS. como veremos neste capítulo. o projetista precisa equilibrar o desejo dos programas por mais registradores com o desejo do projetista de manter o ciclo de clock rápido. como demonstra a Seção 2. $s1. os grupos palavra (word)  A unidade de de 32 bits ocorrem com tanta frequência que recebem o nome de palavra (word) na ar- acesso natural de um computador. Nesse caso. A Seção 2. continuando em nossa evolução passo a passo da representação simbólica da linguagem MIPS. normalmente um grupo de 32 bits.$s3. $s2. a verdade por trás dessas observações faz com que os projetistas de computador as levem a sério. (Consulte a Seção 2. O Capítulo 4 mostra o papel central que os registradores desempenham na construção do hardware.5. Qual é o código MIPS compilado? O programa compilado é muito semelhante ao exemplo anterior. Considere. a convenção do MIPS é usar nomes com um sinal de cifrão seguido por dois caracteres para representar um registrador. Orientações como “menor significa mais rápido” não são absolutas.$t0.. $t0 e $t1.$t1 # f recebe $t0 − $t1. Por enquanto. a instrução de atribuição do nosso exemplo anterior: f = (g + h) − (i + j).. $t1. Uma quantidade muito grande de registradores pode aumentar o tempo do ciclo do clock simplesmente porque os sinais eletrônicos levam mais tempo quando precisam atravessar uma distância maior. o uso eficaz dos registradores é fundamental para o desempenho do programa. Outro motivo para não usar mais de 32 é o número de bits que seria necessário no formato da instrução. g. de 0 a 31. Compilando uma atribuição em C usando registradores É tarefa do compilador associar variáveis do programa aos registradores.. $s1. 31 registradores podem não ser mais rápidos do que 32. para os registradores que corres- pondem às variáveis dos programas em C e Java. corresponde ao tamanho de um Uma diferença importante entre as variáveis de uma linguagem de programação e os registrador na arquitetura MIPS.8 explicará os motivos por trás desses nomes..20 no site para ver a história do número de registradores. Mesmo assim.$s1. respectivamente. i e j são associadas aos registradores $s0. registradores é o número limitado de registradores.) Assim.que é(g + h) − (i + j) .$s4 # registrador $t1 contém i + j sub $s0. 2. como antes. FIGURA 2. como nesses exemplos. com cada palavra representando quatro bytes. Essas instruções são denominadas instruções de trans. Logo. apresentados no Capítulo 1 e de- senhados no início deste capítulo. .3  Operandos do hardware do computador 65 Operandos em memória As linguagens de programação possuem variáveis simples. O nome MIPS real para essa instrução é lw. depois uma constante e o registrador usado para acessar a memória. mas a memória do computador contém milhões de elementos de dados. na delinear o local de um elemento Figura 2.2  Endereços de memória e conteúdo da memória nesses locais. A instrução de transferência de dados que copia dados da memória para um registrador tradicionalmente é chamada de load. começando de 0. pois o MIPS. que contêm elementos de dados isolados. o endereço do terceiro elemento de dados é 2 e o valor de Memória[2] é 10. dados entre a memória e os ferência de dados. Se esses elementos fossem palavras. o endereço de memória. na realidade. O formato da instrução load é o nome da operação seguido pelo registrador a ser carregado. esses endereços estariam incorretos. a instrução precisa fornecer registradores. A Figura 2. de dados específico dentro de uma sequência da memória. 2.3 mostra o endereçamento para palavras sequenciais na memória. significando load word (carregar palavra). Compilando uma atribuição quando um operando está na memória Vamos supor que A seja uma sequência de 100 palavras e que o compilador tenha associado as variáveis g e h aos registradores $s1 e $s2. as estruturas de dados (arrays e estruturas) são mantidas na memória. como um computador pode representar e acessar estruturas tão grandes? Lembre-se dos cinco componentes de um computador. ou endereço base. endereço  Um valor usado para com o endereço atuando como índice para esse array. Compile esta instrução de atribuição em C: g = h + A[8]. as operações aritméticas só ocorrem com registradores nas instrução de transferência de instruções MIPS. Por exemplo. Conforme explicamos. assim. usa endereços de bytes. Para acessar uma palavra na memória. o MIPS precisa incluir instruções que transferem dados entre dados  Um comando que move a memória e os registradores. Essas estruturas de dados complexas podem conter muito mais elementos de dados do que a quantidade de registradores em um computador. mas também possuem estruturas de dados mais com- plexas. Vamos supor EXEMPLO também que o endereço inicial da sequência. esteja em $s3. A soma da parte constante da instrução com o conteúdo do segundo registrador forma o endereço da memória. O processador só pode manter uma pequena quantidade de dados nos registradores. Logo. A memória é apenas uma sequência grande e unidimensional. o compilador aloca estruturas de dados. O endereço desse elemento da sequência é a soma da base da sequência A.3  Endereços de memória do MIPS e conteúdo da memória para essas palavras. com o número para selecionar o elemento 9. ou big end.) alinhados na memória em limites Os computadores se dividem naqueles que utilizam o endereço do byte mais à esquerda. Logo. (O requisito de que os dados estejam Capítulo 4 explica por que o alinhamento ocasiona transferências de dados mais rápidas.2. já que está em um registrador. Esse restrição de alinhamento Um requisito é denominado restrição de alinhamento e muitas arquiteturas o têm.2. No MIPS. Com base na Figura 2. O compilador pode. .2. em locais na memória. então. um dos operandos RESPOSTA está na memória.$t0 # g = h + A[8] A constante na instrução de transferência de dados (8) é chamada de offset e o regis- trador acrescentado para formar o endereço ($s3) é chamado de registrador base. como arrays e estruturas. ou little end. O MIPS está no campo do Big Endian. endereços de palavras são múltiplos de 4: existem 4 bytes em uma palavra. para uso na próxima ins- trução. Os dados devem ser colocados em um registrador temporário.) O endereçamento em bytes também afeta o índice do array. Portanto. o endereço de uma palavra combina os endereços dos 4 bytes dentro da palavra. Como o MIPS endereça cada byte.3 mostra os endereços MIPS reais para a Figura 2. palavras precisam começar em endereços que sejam múltiplos de 4. encontrada no registrador $s3. o endereço em bytes da terceira palavra é 8. Interface Além de associar variáveis a registradores. colocar o endereço hardware/ inicial apropriado nas instruções de transferência de dados.66 Capítulo 2  Instruções: A Linguagem de Máquina Embora haja uma única operação nessa instrução de atribuição. software Como os bytes de 8 bits são úteis em muitos programas. (O Apêndice A mostra as duas opções para numerar os bytes de uma palavra. o offset a ser somado ao registrador base $s3 precisa FIGURA 2. a Figura 2. de modo que primeiro precisamos transferir A[8] para um regis- trador.) A seguinte instrução pode operar sobre o valor em $t0 (que é igual a A[8]). naturais. mas usaremos essa versão simplificada por enquanto. os endereços sequenciais das palavras diferem em quatro vezes. 8($s3) # Registrador temporário $t0 recebe A[8] (A seguir. A instrução precisa somar h (contido em $s2) com A[8] ($t0) e colocar a soma no registrador correspondente a g (associado a $s1): add $s1. Por exemplo. Para obter o endereço em bytes apropriado no código anterior. faremos um pequeno ajuste nessa instrução.$s2. A mudança de endereços está destacada para comparar com a Figura 2. a primeira instrução compilada é lw $t0. como endereço da palavra e aqueles que utilizam o byte mais à direita. a maioria das arquiteturas endereça bytes individuais. desta vez. As duas RESPOSTA primeiras instruções são iguais às do exemplo anterior.$t0 # Registrador temporário $t0 recebe h + A[8] A instrução final armazena a soma em A[12]. ao invés de estarem na memória. Outras marcas de computadores utilizam outras instruções juntamente com load e store para transferir dados.$s2.) A instrução complementar ao load tradicionalmente é chamada de store. ela copia dados de um registrador para a memória. por uma constante e. Consequentemente. o endereço MIPS é especificado. de modo que precisamos de ainda mais instruções MIPS. (Veja a armadilha relacionada na Seção 2. agora dois dos operandos es- tão na memória.3  Operandos do hardware do computador 67 ser 4 × 8. Embora haja uma única operação na instrução em C. O formato de um store é semelhante ao de um load: o nome da operação. usamos o offset apropriado para o endereçamento do byte na instrução load word a fim de selecionar A[8]. operar sobre eles e escrever o resultado. descrita na Seção 2. O nome real no MIPS é SW. Interface res. 48($s3) # Armazena h + A[8] de volta em A[12] Load word e store word são as instruções que copiam words entre memória e regis- tradores na arquitetura MIPS. Muitos programas possuem mais variáveis do que os computadores possuem registrado. Uma arquitetura com essas alternativas é a Intel x86. Compilando com load e store Suponha que a variável h esteja associada ao registrador $s2 e o endereço base do array A esteja em $s3. O princípio de hardware relacionando tamanho e velocidade sugere que a memória deve ser mais lenta que os registradores. usando loads e stores para mover hardware/ variáveis entre os registradores e a memória. Uma instrução aritmética MIPS pode ler dois registradores.17. Qual é o código assembly do MIPS para a instrução de EXEMPLO atribuição em C a seguir? A[12]=h+A[8]. em parte. O processo de colocar as variáveis menos software utilizadas (ou aquelas necessárias mais adiante) na memória é chamado de spilled registers (ou registradores derramados). Além do mais. em parte. significando store word (armazena palavra). os acessos aos dados são mais rápidos se os dados estiverem nos registradores. 2. seguido pelo registrador a ser armazenado. ou 32. depois o offset para selecionar o elemento do array e finalmente o registrador base. Mais uma vez. os dados são mais úteis quando em um registrador. usando 48 (4 × 12) como offset e o registrador $s3 como registrador base. sw $t0. de modo que o endereço de load selecione A[8]. e não A[8/4]. o compilador tenta manter as variáveis usadas com mais frequên- cia nos registradores e coloca o restante na memória. e a instrução add coloca a soma em $t0: lw $t0. Isso realmente acontece. pelo conteúdo de um registrador.18. pois existem menos registradores. Uma . exceto que. 32($s3) # Registrador temporário $t0 recebe A[8] add $t0. o número de registradores aumenta apenas quando novos conjuntos de instruções se tornam viáveis. O Apêndice E mostra as diferenças entre MIPS-32 e MIPS-64.) Por exemplo. usamos um subconjunto do MIPS-32. que é simplificar o conjunto de instruções por oferecer variações utéis. a operação mova é apenas uma instrução de soma na qual cada operando é zero. . simplesmente escrevemos addi $s3. Muito rápida: eles aumentam tão rapidamente quanto a Lei de Moore. com uma constante no lugar do operando. para somar a constante 4 ao registrador $s3. Portanto. um programa usará uma constante em uma operação – por exemplo. Essa instrução add rápida. mencio- nado inicialmente na Seção “Falácias e armadilhas”. incluindo constantes dentro das instruções aritméticas. (Como você deve esperar. ao incrementar um índice a fim de apontar para o próximo elemento de um array. os compiladores precisam usar os registradores de modo eficaz. do Capítulo 1: Princípio de Projeto 3: Agilize os casos mais comuns. definido com 32 registradores de 64 bits.$s3. os registradores MIPS levam menos tempo para serem acessados e possuem maior vazão do que a memória – uma combinação rara –. A constante zero tem outro emprego. o que prevê o dobro do número de transistores em um chip a cada 18 meses.$s3. por isso. Muito lenta: como os programas normalmente são distribuídos em linguagem de máquina.) Verifique você Dada a importância dos registradores. Para somar 4 ao registrador $s3. eles são chamados oficialmente de MIPS-32 e MIPS-64. o MIPS dedica o registrador $zero para ter o valor zero. e. Neste capítulo. Detalhamento:  Embora os registradores MIPS neste livro tenham 32 bits de largura. AddrConstant4($s1) # $t0 = constante 4 add $s3. (As constantes teriam de ser colocadas na memória quando o programa fosse carregado. existe uma versão de 64 bits do conjunto de instruções MIPS. 2. qual é a taxa de aumento no número de registradores em um chip com o passar do tempo? mesmo 1. Para distingui-los. Assim. Usando apenas as instruções vistas até aqui. Os operandos constantes ocorrem com frequência e. as operações são muito mais rápidas e usam menos energia do que se as constantes fossem lidas da memória. tornando os dados nos regis- tradores mais rápidos de acessar e mais simples de usar. 4 # $s3 = $s3 + 4 As instruções imediatas ilustram o terceiro princípio de projeto do hardware.68 Capítulo 2  Instruções: A Linguagem de Máquina instrução de transferência de dados MIPS só lê um operando ou escreve um operando. mais da metade das instruções aritméticas do MIPS possuem uma constante como operando quando executam os benchmarks SPEC2006. Por exemplo. Para conseguir o melhor desempe- nho. Constantes ou operandos imediatos Muitas vezes. sem operar sobre ele. é chamada add imediato. poderíamos usar o código lw $t0. é o registrador zero.$t0 # $s3 = $s3 + $t0($t0 == 4) supondo que AddrConstant4 seja o endereço de memória da constante 4. teríamos de ler uma constante da memória para utilizá-la. ou addi. Uma alternativa que evita a instrução load é oferecer versões das instruções aritméticas em que o operando seja uma constante. Na ver- dade. existe uma inércia na arquitetura do conjunto de instruções. básicos da informação. (Assim como os números de base 10 são chamados números decimais. O desenho a seguir mostra a numeração dos bits dentro de uma word MIPS e o posicio- namento do número 1011bin: . Veremos esse exemplo na Seção 2.4  Números com sinal e sem sinal Primeiro. 2. . vamos revisar rapidamente como um computador representa números. em qualquer base numérica. Generalizando. Por exemplo. o valor do i-ésimo dígito d é d × Basei em que i começa com 0 e aumenta da direita para a esquerda. Os humanos são ensinados a pensar na base 10. verdadeiro ou falso. de modo que o endereço-base do array normalmente é passado em um registrador. ou 1 ou 0. Os números são mantidos no hardware do computador como uma série de sinais ele- trônicos altos e baixos. portanto.) Um único dígito de um número binário. mas os números podem ser representados em qualquer base. Esse bloco de montagem dígito binário  Também chamado fundamental pode assumir dois valores. Isso leva a um modo óbvio de numerar os bits na word: basta usar a potência da base para esse bit. conforme veremos. Subscritamos os números decimais com dec e os números binários com bin. e o offset pode selecionar o elemento desejado. 2. 1. pois o registrador pode apontar para o início da es- trutura. Assim. que são os componentes tivas: alto ou baixo. Um dos dois números na base 2 (0 ou 1). ou bits.13. Como o MIPS admite constantes negativas... pois não caberá no offset. o registrador-base também é chamado registrador índice. os números de base 2 são chamados números binários. Por exemplo. a subtração imediata não é necessária no MIPS.4  Números com sinal e sem sinal 69 O endereçamento formado pelo registrador-base mais o offset do MIPS é uma combinação excelente para as estruturas e os arrays. e por isso são considerados números de base 2. da direita para a esquerda em uma palavra. 3. ligado ou desligado. os bits são numerados com 0. As memórias de hoje são muito maiores e o modelo de software para alocação de dados é mais sofisticado. pois toda a informação é composta de dígitos binários. que podem ser imaginados como várias alterna. O registrador nas instruções de transferência de dados foi criado originalmente para manter o índice do array com o offset utilizado para o endereço inicial do array. é o “átomo” da computação. 123 base 10 = 1111011 base 2. bit. 2. 1011bin representa (1 × 23) +(0 × 22) +(1 × 21) +(1 × 20)dec = (1 × 8) +(0 × 4) +(1 × 2) +(1 × 1)dec = 8 +0 +2 +1dec = 11dec Logo. não mostramos os 0s à esquerda. xi significa o i-ésimo bit de x): (x 31 × 231 ) + (x 30 × 230 ) + (x 29 × 229 ) + .967.70 Capítulo 2  Instruções: A Linguagem de Máquina Como as palavras são desenhadas vertical e horizontalmente. os somadores de sinal e magnitude podem precisar de uma etapa extra para definir o sinal. para números sem sinal. qual será o sinal correto. a representação com sinal e magnitude logo foi abandonada. subtrair. Os números. Logo. exceto por alguns dos dígitos mais à direita. A resposta é que ele tentaria pegar emprestado de uma sequência de 0s à esquerda. de modo que precisamos de uma representação que faça a distinção entre o positivo e o negativo. Segundo. o que pode ocasionar problemas para os programadores desatentos. Só que.. o termo bit menos significativo é usado para se referir mais à direita em uma palavra ao bit mais à direita (bit 0. Pri- meiro. possuem uma quantidade infinita de dígitos. Como não havia uma alternativa melhor óbvia. do sistema operacional e do programa determinar o que fazer quando isso ocorre. É natural deixar que essas representações mostrem os números de 0 a 232 – 1 (4. esquerda (bit 31). Infelizmente. À direita? À esquerda? Os primeiros compu- tadores tentaram ambos.294. pois não podemos saber. um bit de sinal separado significa que a representação com sinal e magnitude possui um zero positivo e um zero negativo. Fica a critério da linguagem de programação. Em busca de uma alternativa mais atraente. no exemplo anterior) e bit mais significativo para o bit mais à MIPS. na realidade. se tentássemos subtrair um número grande de um número pequeno. a solução final foi escolher a represen- tação que tornasse o hardware simples: 0s iniciais significa positivo e 1s iniciais significa negativo. que convenientemente possa ser re- presentado em um único bit. Os programas de computador calculam números positivos e negativos. de modo que podemos representar 232 padrões diferentes de 32 bits. levantou-se a questão com relação a qual seria o resultado. o nome dessa representação é sinal e magnitude. não é óbvio onde colocar o bit de sinal.. com antecedência. multiplicar e dividir esses padrões de bits. A palavra MIPS possui 32 bits de largura. diz-se que houve um overflow. os números binários de 32 bits podem ser representados em termos do valor do bit vezes uma potência de 2 (aqui. esquerda e direita podem bit menos significativo  O bit não ser termos muito claros.295dec): Ou seja. normalmente. Essa convenção para representar os números binários com sinal é chamada representação por complemento de dois: . A solução mais óbvia é acrescentar um sinal separado. a representação com sinal e magnitude possui várias desvantagens. com quase todos sendo 0. + (x1 × 21 ) + (x 0 × 20 ) Lembre-se de que os padrões de bits binários que acabamos de mostrar simplesmente representam os números. Finalmente. Se o número que é o resultado correto de tais operações não puder ser representado por esses bits de hardware mais à direita. de modo que o resultado seria uma sequência de 1s à esquerda. O hardware pode ser projetado para somar. Como resultado desses problemas. . Ele é seguido por um conjunto decrescente de números negativos: –2.. O padrão de bits seguinte (1000 .648dec (–231).. Consequentemente.647dec (1000 .147. utiliza a mesma re- presentação de antes.647dec (231 – 1).. 0000bin) representa o número mais negativo –2.483. Reconhecendo o papel do bit de sinal.483. Esse desequilíbrio era uma preocu- pação para o programador desatento. de 0 a 2. todo computador hoje em dia utiliza a representação de números binários por complemento de dois para os números com sinal..483. Conversão de binário para decimal Qual é o valor decimal deste número em complemento de dois com 32 bits? EXEMPLO 1111 1111 1111 1111 1111 1111 1111 1100bin Substituindo os valores dos bits do número na fórmula anterior: RESPOSTA (1 × −231 ) + (1 × 230 ) + (1 × 229 ) + .147. Esse bit normalmente é denominado bit de sinal..648dec.648dec + 2. –2. 483.. + 22 + 0 + 0 = −2. mas a representação com sinal e magnitude gerava problemas para o programador e para o projetista do hardware.147. .483.147. Consequentemente..147. o hardware só precisa testar esse bit para ver se um número é positivo ou negativo (com 0 considerado positivo).. A representação em complemento de dois possui um número negativo.4  Números com sinal e sem sinal 71 A metade positiva dos números. 1111bin).147.. 0001bin) até –1dec (1111 .644 dec = −4 dec Logo. A representação por complemento de dois tem a vantagem de que todos os números negativos possuem 1 no bit mais significativo. que não possui um número positivo correspondente. 2.. 483.. + (x1 × 21 ) + (x 0 × 20 ) O bit de sinal é multiplicado por –231 e o restante dos bits é multiplicado pelas versões positivas de seus respectivos valores de base. veremos um atalho para simplificar a conversão. podemos representar números positivos e negativos de 32 bits em termos do valor do bit vezes uma potência de 2: (x 31 × 231 ) + (x 30 × 230 ) + (x 29 × 229 ) + . + (1 × 22 ) + (0 × 21 ) + (0 × 20 ) = −231 + 230 + 229 + . os endereços de memória começam com 0 e continuam até o maior endereço. O overflow ocorre quando o bit mais à esquerda da representação binária do hardware não é igual ao número infinito de dígitos à esquerda (o bit de sinal está incorreto): 0 à esquerda do padrão de bits quando o número é negativo ou 1 quando o número é positivo. Atalho para negação EXEMPLO Negue 2dec e depois verifique o resultado negando –2dec. A linguagem C. portanto. por exemplo.. x +  x  + 1 = 0.. e os últimos de unsigned integers. chama os primeiros de integers. Como x +  x  = –1. endereços negativos não fazem hardware/ sentido. para deixar a distinção clara. invertendo os bits e somando um. Interface Diferente dos números discutidos anteriormente. 2dec = 00000000000000000000000000000010 bin RESPOSTA Negando esse número. Algumas linguagens de programação refletem essa distinção.72 Capítulo 2  Instruções: A Linguagem de Máquina Assim como uma operação com números sem sinal pode ocasionar overflow na capacidade do hardware de representar o resultado. uma operação com números em complemento de dois também pode. Basta inverter cada 0 para 1 e cada 1 para 0. ou inteiros (declarados como int no programa). O primeiro atalho é um modo rápido de negar um número binário no complemento de dois. Esse atalho é baseado na observação de que a soma de um número e sua representação invertida precisa ser 111 . depois somar um ao resultado. 1111 1111 1111 1111 1111 1111 1111 1110bin primeiro é invertido e depois incrementado: . Alguns guias de estilo C recomendam ainda declarar os primeiros como sighned int. Na outra direção. Em outras palavras. que representa –1. Assim. Vamos examinar alguns atalhos úteis quando trabalhamos com os números em com- plemento de dois. ou x  + 1 = –x. 111bin. os programas desejam lidar às vezes com números que podem ser positivos software ou negativos e às vezes com números que só podem ser positivos. ou inteiros sem sinal (unsighned int). O padrão binário que representa um número esconde os bits iniciais para caber na largura do hardware. a escolha predominante desde 1965 tem sido o complemento de dois. Atalho para extensão de sinal Converta as versões binárias de 16 bits de 2dec e –2dec para números binários de 32 bits. Esse atalho normalmente é chamado de extensão de sinal. a extensão do sinal simplesmente restaura alguns deles. branch.767dec (215 – 1). Resumo O ponto principal desta seção é que precisamos representar inteiros positivos e negativos dentro de uma palavra do computador e.4  Números com sinal e sem sinal 73 O próximo atalho nos diz como converter um número binário representado em n bits para um número representado com mais de n bits. O atalho é pegar o bit mais significativo da menor quantidade – o bit de sinal – e replicá-lo para preencher os novos bits na quantidade maior. Os bits antigos são simplesmente copiados para a parte da direita da nova word. o computador precisa converter esse número de 16 bits para o seu equivalente em 32 bits. Para somar o campo imediato a um registrador de 32 bits. 0000 0000 0000 0010bin torna-se Criar uma versão de 32 bits do número negativo significa copiar o bit de sinal 16 vezes e colocá-lo à esquerda: 1111 1111 1111 1111 1111 1111 1111 1110bin = –2dec Esse truque funciona porque os números positivos em complemento de dois realmente possuem uma quantidade infinita de 0s à esquerda e os que são negativos em complemento de dois possuem uma quantidade infinita de 1s.768dec (–215) a 32. 2. Por exemplo. store. add e set on less than contém um número de 16 bits em complemento de dois. . Assim. A metade direita recebe o valor antigo: 0000 0000 0000 0000 0000 0000 0000 0010bin = 2dec Vamos negar a versão de 16 bits de 2 usando o atalho anterior. representando de –32. o campo imediato nas instruções load. EXEMPLO A versão binária de 16 bits do número 2 é RESPOSTA 0000 0000 0000 0010bin = 2dec Ele é convertido para um número de 32 bits criando-se 16 cópias do valor do bit mais significativo (0) e colocando-as na metade esquerda da word. embora existam prós e contras a qualquer opção. cada parte da instrução pode ser considerada um número individual e a colocação desses números lado a lado forma a instrução.. presentar o valor mais negativo por 00.709. o complemento ou a negação de um número em complemento de dois x é 2n – x. Na verdade. Essa também foi uma tentativa de o valor mais positivo por 01 . os registradores $s0 a $s7 são mapeados nos registradores de 16 a 23 e os registradores $t0 a $t7 são mapeados nos registradores de 8 a 15.. 11bin. sequências de bits binárias e hexadecimais (veja Figura 2.. $s0 significa o registrador 16. No assembly MIPS. por isso. Nas próximas seções. logo.. O termo também é balanceados. pois o complemento de x é 2n – x – 1.00bin é o 0 positivo. e 11. é re- 1 para 0..744.000bin e o valor mais positivo por 11. que veremos quando tratarmos de ponto flutuante no Capítulo 3. Essa representação é semelhante ao complemento de dois. Os que aderiram ao complemento de um precisaram de uma etapa extra para usado para significar a inversão de subtrair um número e. representação não negativa.. é preciso haver uma convenção para mapear nomes de registrador em números.446.. mas também possui dois 0s: 00. ...11bin é o 0 negativo.. 000bin e a explicar seu nome. o que ajuda mais negativo por 10 . Dado um tamanho de palavra mais o deslocamento têm uma fixo... normalmente não usamos “ + ” ou “-” com notação binária ou hexadecimal.647dec e. de modo que o número pois não existem limites para o tamanho de um número decimal. $s1significa o registrador 17... e assim por diante. deslocando assim o Detalhamento:  Para números decimais com sinal. $t0 significa o registrador 8. deixando um número igual utilizaram a notação. 00bin. Isso é chamado de notação deslocada (biased notation). de 0 para 1 e de 1 para 0. número.. logo. com 0 normalmente tendo o valor 10. $s2 significa o registrador 18.. os positivos e negativos são positivo (00 ....5  Representando instruções no computador Agora.. Logo. Como os registradores são referenciados por quase todas as instruções. o complemento de dois domina hoje.073. e vários computadores científicos 11bin. exceto que de negativos e positivos..00bin. . 000bin e o valor não negativa. estamos prontos para explicar a diferença entre o modo como os humanos instruem os computadores e como os computadores veem as instruções. O maior número terminando com dois zeros. um negativo 10. por isso.74 Capítulo 2  Instruções: A Linguagem de Máquina Verifique Qual é o valor decimal deste número de 64 bits em complemento de dois? você mesmo 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000bin 1) −4dec 2) −8dec 3) −16dec 4) 18. complemento de um Uma Uma terceira representação alternativa é chamada complemento de um. usamos “-” a fim de representar negativo.... descreveremos a convenção para o restante dos 32 registradores. 00bin) e um negativo (11 . 11bin)...000bin representa –2.483. com 0 normalmente tendo o valor 10 ..147. mais positivo por 11 . ser uma solução melhor do que a técnica de sinal e magnitude.551.. As instruções são mantidas no computador como uma série de sinais eletrônicos altos e baixos e podem ser representadas como números.4) podem codificar o sinal. $t1 significa o registrador 9.609dec Detalhamento:  o complemento de dois recebe esse nome em decorrência da regra de que a soma sem sinal de um número de b bits e seu negativo é 2n. O negativo de um notação que representa o valor complemento de um é encontrado invertendo-se cada bit.11bin. 2.. notação deslocada  Uma notação que representa o valor mais pois desloca o número de modo que o número mais o deslocamento tenha uma representação negativo por 00 . cada bit em um padrão: 0 para 1 e Uma notação final. A Figura 2. em vez de decimal: Esse leiaute da instrução é chamado formato de instrução. 2. essa instrução MIPS ocupa exatamente 32 bits – o mesmo de representação de uma instrução. que computacional. nesse caso) combinados dizem ao computador MIPS que essa instrução realiza soma.5  Representando instruções no computador 75 Traduzindo uma instrução assembly MIPS para uma instrução de máquina Realizaremos a próxima etapa no refinamento da linguagem do MIPS como um exemplo. Como quase todos os tamanhos de dados no computador são múltiplos de 4. todas as instruções MIPS possuem 32 bits de extensão.) A propósito. hexadecimal  Números na base 16. vamos anexar em subscrito dec aos números decimais. bin aos números binários e hex aos números hexadecimais. Mostraremos a versão da linguagem real do MIPS para a instrução re. a base padrão é 10. Para distinguir do assembly. e a sequência dessas instruções é o código de máquina. Evitamos esse tédio usando uma base maior do que a binária. pode ser convertida com facilidade para binária. plicidade favorece a regularidade. O segundo campo indica o número do registrador que é o primeiro operando de origem da operação de soma (17 = $s1) e o terceiro campo indica o outro operando fonte para a soma (18 = $s2). $s2 primeiro como uma combinação dos números decimais e depois dos números biná- rios. O quarto campo con- tém o número do registrador que deverá receber a soma (8 = $t0). máquina  Representação binária utilizada para a comunicação Pode parecer que agora você estará lendo e escrevendo sequências longas e cansativas dentro de um sistema de números binários. O primeiro e o último campos (contendo 0 e 32. Como a base 16 é uma potência de 2. os números hexadecimais (base 16) são muito comuns. O quinto campo não é utilizado nessa instrução. para evitar confusão. (Se não houver um subscrito. a instrução soma o registrador $s1 ao registrador $s2 e coloca a soma no registrador $t0. Acompanhando nosso princípio de projeto.4 converte hexadecimal para binário e vice-versa. chamamos a versão numérica das instruções de linguagem linguagem de de máquina. Como você pode ver pela formato de instrução  Uma forma contagem do número de bits. podemos converter de modo trivial substituindo cada grupo de quatro dígitos binários por um único dígito hexadecimal e vice-versa. Assim. Visto que frequentemente lidamos com bases numéricas diferentes. C e Java utilizam a notação 0xnnnn para os números hexadecimais. tamanho da palavra de dados. composta de campos de números binários. de modo que é definido como 0. de que a sim. EXEMPLO presentada simbolicamente por add$t0. . Essa instrução também pode ser representada com campos em números binários. A representação decimal é RESPOSTA 0 17 18 8 0 32 Cada um desses segmentos de uma instrução é chamado de campo. $s1. instrução.4. Se o tamanho do número binário não for um múltiplo de 4. a operação e formato de uma j rs: o registrador do primeiro operando fonte. prossiga da direita para a esquerda. Basta substituir um dígito hexadecimal pelos quatro dígitos binários correspondentes e vice-versa. . Binário para hexadecimal e vice-versa Converta os seguintes números hexadecimais e binários para a outra base: EXEMPLO eca8 6420hex 0001 0011 0101 0111 1001 1011 1101 1111bin Usando a Figura 2.76 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2.4  A tabela de conversão hexadecimal-binário. tradicionalmente chamado de opcode. temos a solução bastando olhar na tabela em uma direção: RESPOSTA E depois na outra direção: Campos do MIPS Os campos do MIPS recebem nomes para facilitar seu tratamento: Aqui está o significado de cada nome dos campos nas instruções MIPS: opcode  O campo que denota j op: operação básica da instrução. às vezes. Por exemplo. ele não será usado até lá. assim. e. exigindo. Caso você esteja curioso. diferentes tipos de formatos para diferentes tipos de instruções. de modo que o hardware sabe se deve tratar a última metade da instrução como três campos (tipo R) ou como um único campo (tipo I). Esse campo seleciona a variante específica da operação no campo op e. Observe que o significado do campo rt mudou para essa instrução: em uma instrução load word. o formato anterior é chamado de tipo-R (de registrador) ou formato R. j shamt: “Shift amount” (quantidade de deslocamento). Embora o uso de vários formatos complique o hardware. o campo rt especifica o registrador de destino.) j funct: função. e é utilizado pelas instruções imediatas e de transferência de dados. tornando mais difícil encaixar tudo em uma palavra. Vejamos a instrução load word da página 83: lw $t0. ou 8. 2. que recebe o resultado do load. Ele recebe o resultado da operação. Um segundo tipo de formato de instrução é chamado tipo I (de imediato). e 32 é colocado no campo de endereço. podemos reduzir a com- plexidade mantendo os formatos semelhantes. 19 (para $s3) é colocado no campo rs. o campo contém zero nesta seção. De modo semelhante. Existe um problema quando uma instrução precisa de campos maiores do que aqueles mostrados. A Figura 2.192 words) do endereço no registrador base rs. ou 32. Esse campo de 5 bits é muito pequeno para realizar algo útil.5  Representando instruções no computador 77 j rt: o registrador do segundo operando fonte.768 bytes (±213. 8 (para $t0) é colocado no campo rt. Essa constante é utilizada para selecionar elementos dos arrays ou estruturas de dados e normalmente precisa ser muito maior do que 32. pois os campos rs e rt precisariam cada um de outro bit. Se o endereço tivesse de usar um dos campos de 5 bits no formato anterior.6 explica as ins- truções de shift e esse termo. a instrução load word precisa especificar dois registradores e uma constante. 32($s3) # Registrador temporário $t0 recebe A[8] Aqui. Isso nos leva ao último princípio de projeto de hardware: Princípio de Projeto 4: Um bom projeto exige bons compromissos. o tamanho do quarto campo no tipo I é igual à soma dos tamanhos dos três últimos campos do tipo R. Logo. Vemos que o uso de mais de 32 registradores seria difícil nesse formato. O compromisso escolhido pelos projetistas do MIPS é manter todas as instruções com o mesmo tamanho. é chamado de código de função. j rd: o registrador do operando de destino. ou formato I.5 mostra os números utilizados em cada campo para as instruções MIPS descritas aqui. Por exemplo. Por exemplo. a cons- tante dentro da instrução load word seria limitada a apenas 25. Os campos do formato I são O endereço de 16 bits significa que uma instrução load word pode carregar qualquer palavra dentro de uma região de ±215. ou 32. os formatos são diferenciados pelos valores no primeiro campo: cada formato recebe um conjunto distinto de valores no primeiro campo (op). os três primeiros campos nos formatos de tipo R e tipo I possuem o mesmo tamanho e têm os mesmos nomes. a soma imediata é limitada a constantes que não sejam maiores do que ±215. por isso. . (A Seção 2. temos um conflito entre o desejo de manter todas as instruções com o mesmo tamanho e o desejo de ter um formato de instrução único. e “n. O offset para selecionar A[300] (1200 = 300 × 4) aparece no campo final (endereço). A instrução add. Traduzindo do assembly MIPS para a linguagem de máquina Agora. que vem em seguida. Se $t1 possui a base do array A e $s2 corresponde a h.$s2. podemos determinar as três instruções em linguagem de máquina: op rs rt rd endereço/shamt funct 35 9 8 1200 0 18 8 8 0 32 43 9 8 1200 A instrução lw é identificada por 35 (Figura 2.5  Codificação de instruções MIPS. primeiro vamos representar as instruções em linguagem de má- RESPOSTA quina usando os números decimais.1200($t1) # Armazena h + A[300] de volta para A[300] Qual o código em linguagem de máquina MIPS para essas três instruções? Por conveniência. que está destacado aqui. então a instrução de atribuição A [ 3 0 0 ] = h + A[300].temporário $t0 recebe A[300] add $t0.5) no primeiro campo (op).a.1200($t1) # Reg. Observe que as instruções add e sub têm o mesmo valor no campo op.5. é compilada para lw $t0.$t0 # Reg. A instrução sw é identificada com 43 no primeiro campo. O restante dessa última instrução é idêntico à instrução lw. já podemos usar um exemplo completo daquilo que o programador escreve EXEMPLO até o que o computador executa. Na tabela. o equivalente binário ao formato decimal é o seguinte: 100011 01001 01000 0000 0100 1011 0000 000000 10010 01000 01000 00000 100000 101011 01001 01000 0000 0100 1011 0000 Observe a semelhança das representações binárias da primeira e última instruções. no terceiro e no quarto campos e correspondem a $s2. é especificada com 0 no primeiro campo (op) e 32 no último campo (funct). $t0 e $t0.” (não se aplica) significa que esse campo não aparece nesse formato. 8 e 8) apare- cem no segundo. “endereço” significa um endereço de 16 bits. Como 1200dec = 0000 0100 1011 0000bin.temporário $t0 recebe h + A[300] sw $t0. o hardware usa o campo funct para decidir sobre a variante da operação: somar (32) ou subtrair (34). . A única diferença está no terceiro bit a partir da esquerda. Os três registradores operandos (18. Pela Figura 2.78 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2. “reg” significa um número de registrador entre 0 e 31. e o registrador de des- tino 8 ($t0) é especificado no terceiro campo (rt). O registrador base 9 ($t1) é especificado no segundo campo (rs). 7 mostra o poder do conceito. especificamente. explicado na Seção 2. o texto que o programa compilado está usando e até mesmo o compilador que gerou o código de máquina. um campo rs. Esses princípios levam ao conceito de programa armazenado. sua invenção permite que o “gênio da computação saia de sua garrafa”. e o campo funct.5  Representando instruções no computador 79 A Figura 2. exceto para load word. o código de máquina compilado correspondente. FIGURA 2. Como veremos no Capítulo 4.6  Arquitetura MIPS revelada até a Seção 2. que especifica o outro operando origem. indicando um dos operandos origem. em que especifica o registrador destino. A implicação comercial é que os computadores podem herdar softwares já prontos desde que sejam compatíveis com um conjunto de instruções existente. assim como os números. A Figura 2. a semelhança das representações binárias de instruções relacionadas simplifica o projeto do hardware. a memória pode conter o código-fonte de um editor de textos. Os 16 primeiros bits são iguais: ambos contêm um campo op. . um campo shamt.5. Os programas são armazenados na memória para serem lidos ou escritos. Uma consequência de instruções em forma de números é que os programas normalmente são entregues como arquivos de números binários. e um campo rt. indicando a operação básica. Os computadores de hoje são baseados em dois princípios fundamentais: Colocando em 1. que especifica a operação específica das instruções no formato R. O formato I mantém os 16 bits finais como um único campo de endereço.6 resume as partes do assembly do MIPS descritas nesta seção.6. 2. Essas instruções são outro exemplo da regularidade da arquitetura MIPS. Os dois formatos de instrução MIPS até aqui são R e I. perspectiva 2. Essa “compatibili- dade binária” normalmente alinha o setor em torno de uma quantidade muito pequena de arquiteturas de conjuntos de instruções. O formato R divide os 16 últimos bits em um campo rd. As instruções são representadas como números. especificando o registrador destino. 7  O conceito de programa armazenado. então não é. poderia ser. A Figura 2. a tecnologia de memória necessária para os dados também pode ser usada para programas. add $s2. por exemplo.” Embora os primeiros computadores se concentrassem em palavras completas. continuou Tweedledee. Java e MIPS. Isso é lógico. Especificamente. “se foi assim. mas como não é. logo ficou Lewis Carroll.9). cada um dos quais armazenados como 8 bits. $s0 4. $s1 “Ao contrário”. . $s2 2. em um piscar de olhos. Instruções foram acres- centadas para simplificar. add $s2.6   Operações lógicas seria. e se fosse assim. Tratar as instruções da mesma maneira que os dados simplifica bastante tanto o hardware da memória quanto o software dos sistemas computacionais.8 mostra as operações lógicas em C. você mesmo op rs rt rd shamt funct 0 8 9 10 0 34 1.80 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2. podem traduzir o código escrito em uma notação muito mais conveniente para os humanos em código que o computador consiga entender. Essas instruções são chamadas operações lógicas. $s1. o empacotamento e o desempacotamento dos bits em words. add $s0. $s0. Verifique Que instrução MIPS isto representa? Escolha dentre uma das quatro opções a seguir. entre outras tarefas. um computador que ajuda um autor a escrever um livro. 2. Examinar os caracteres dentro de uma palavra. $s0. A troca acontece simplesmente carregando a memória com programas e dados e depois dizendo ao computador para iniciar a execução em determinado local na memória. Alice no país das claro que era útil atuar sobre campos de bits dentro de uma palavra ou até mesmo sobre bits maravilhas. sub $s2. $s1 3. 1865 individuais. Os programas armazenados permitem que um computa- dor que realiza contabilidade se torne. e programas como compiladores. é um exemplo dessa operação (veja a Seção 2. $s1. assim como o deslocamento de um número decimal por i dígitos é equivalente a multiplicar por 10i. supondo que o valor original estava no registrador $t0 e o resultado deverá ir para o registrador $t2: sll $t2. rd contém 10 (registrador $t2). Por exemplo. do formato R. o valor do segundo padrão de bits. o que gera o mesmo resultado que multiplicar por 24.$s0. Os nomes reais das duas instruções shift no MIPS são shift left logical (sll) e shift right logical (srl). Logo. se o registrador $s0 tivesse 0000 0000 0000 0000 0000 0000 0000 0000 1001bin = 9dec e fosse executada a instrução para deslocar 4 bits à esquerda. se bit com dois operandos. O deslocamento lógico à esquerda oferece um benefício adicional. Elas movem todos os bits de uma word para a esquerda ou direita. Outra operação útil que isola os campos é AND. 2. ou 16. A primeira classe dessas operações é chamada de shifts (deslocamentos).6  Operações lógicas 81 FIGURA 2. AND é uma operação bit a bit que AND  Uma operação lógica bit a deixa um 1 no resultado somente se os dois bits dos operandos forem 1. por isso. e 9 × 16 = 144. a instrução sll anterior desloca de 4.8  Operadores lógicos em C e Java e suas instruções MIPS correspondentes. O nome significa shift amount (quantidade de deslocamento) e é usado nas instruções de deslocamento. O deslocamento à es- querda de i bits gera o mesmo resultado que multiplicar por 2i. é definido como 0. o novo valor se pareceria com: 0000 0000 0000 0000 0000 0000 0000 1001 0000bin = 144dec O dual de um shift à esquerda é um shift à direita. MIPS implementa NOT usando um NOR com um operando sendo zero. Por exemplo. a versão em linguagem de máquina da instrução anterior é A codificação de sll é 0 nos campos op e funct. preenchendo os bits que ficaram vazios com 0s. 4 # reg $t2 = reg $s0 << 4 bits Adiamos até agora a explicação do campo shamt. 0000 0000 0000 0000 0000 1101 0000 0000bin e o registrador $t1 tiver 0000 0000 0000 0000 0011 1100 0000 0000bin . rt contém $s0 e shamt contém 4. Por exemplo. O campo rs não é utilizado e. A instrução a seguir realiza essa operação. O primeiro padrão de bits descrito anteriormente representa 9. que calcula o registrador $t2 tiver um 1 somente se houver um 1 em ambos os operandos. pois seu uso principal é inverter os bits de um único operando. ambos permitindo que os objetos sejam empacotados com uma palavra e combinem com uma interface imposta externamente.8 mostrou o relacionamento entre os operadores em C e Java e as ins- truções MIPS. e como 0 quando eles são iguais. o resultado da instrução MIPS se houver um 0 em ambos os operandos. tradicionalmente é chamado de máscara. Os campos recebem inteiros que podem ser tão curtos quanto 1 bit. ela substitui cada 1 por operandos. depois de executar a instrução MIPS and $t0. pois a máscara “oculta” alguns bits. se os registradores $t1 e $t2 não tiverem sido alterados do exemplo um dos operandos. assim como nas operações aritméticas. o hardware não possui uma versão imediata. or. e vice-versa. os projetistas do MIPS decidiram incluir a instrução NOR (NOT OR) no lugar um 0.82 Capítulo 2  Instruções: A Linguagem de Máquina então.$t2 # reg $t0 = reg $t1 & reg $t2 o valor do registrador $t0 seria 0000 0000 0000 0000 0000 1100 0000 0000bin Como você pode ver. como um dispositivo de E/S. que coloca 1 no resultado se qualquer um dos bits do operando for 1. que calcula Se o registrador $t1 não tiver mudado desde o exemplo anterior e o registrador $t3 o NOT do OR dos dois operandos. Ou seja.$t2 # reg $t0 = reg $t1 | reg $t2 é este valor no registrador $t0: 0000 0000 0000 0000 0011 1101 0000 0000bin NOT  Uma operação lógica bit a bit A última operação lógica é um contrário. Se um operando for zero. OR  Uma operação lógica bit a bit Para colocar um valor em um desses 0s. então ele é equivalente a NOT: A NOR 0 = NOT (A OR NOT  Uma operação lógica bit a 0) = NOT (A). C permite que campos de bit ou campos sejam definidos dentro das palavras. bit com dois operandos. que calcula operação bit a bit. anterior. em conjunto com o AND. Esse padrão de bits. O NOT apanha um operando e coloca um 1 com um operando. que define o bit como 1 quando dois bits correspondentes diferem. As constantes são úteis nas operações lógicas AND e OR. nor $t0. sll e srl. chamado OR. o AND pode aplicar um padrão de bits a um conjunto de bits para forçar 0s onde houver um 0 no padrão de bits. ela calcula um 1 somente tiver o valor 0.$t1.$t1. ou seja. Os compiladores C inserem e extraem campos usando instruções lógicas no MIPS: and. As constantes são raras para NOR. e cada 0 por um 1. Detalhamento:  O conjunto de instruções MIPS completo também inclui exclusive or (XOR). que inverte os no resultado se um bit do operando for 0. o resultado da instrução MIPS or $t0. existe o dual do AND. de NOT. Essa é uma com dois operandos. Todos os campos precisam caber dentro de uma única palavra. de modo que o MIPS também oferece as instruções and imediato (andi) e or imediato (ori).$t3 # reg $t0 = ~ (reg $t1 | reg $t3) é este valor no registrador $t0: 1111 1111 1111 1111 1100 0011 1111 1111bin A Figura 2. assim. . Acompanhando o formato de dois bits. um 1 se houver um 1 em qualquer Exemplificando.$t1. for igual). Se as cinco variáveis de f a j correspondem aos cinco registradores de $s0 a $s4. O mnemônico bne significa branch if not equal (desviar se não desvio condicional Uma for igual). g. Essas duas instruções tradicionalmente são denominadas desvios condicionais. com base no resultado da comparação. A Figura 2. e se todos os operan- dos estiverem em registradores. escolha pode depender do truções são executadas.9 é um fluxograma de como deve ser o código MIPS. h. . Goldstine e von bne registrador1. causa a execução de igual ao valor no registrador2. a uma instrução if com um go to. resultados do cálculo. qual é o código MIPS EXEMPLO compilado para esta instrução if em C? if (i = = j) f = g + h. de modo que poderíamos querer desviar se os registradores RESPOSTA forem a instrução de igual (beq). dependendo do sinal de determinado Essa instrução significa ir até a instrução chamada L1 se o valor no registrador1 for número. Compilando if-then-else em desvios condicionais No segmento de código a seguir. registrador2. O assembly do MIPS inclui duas instruções para tomada de decisões.$s4. i e j são variáveis. A segunda instrução é Burks. o código será mais eficiente se testarmos a condição oposta ao desvio no lugar do código que realiza a parte then subsequente do if (o rótulo Else é definido a seguir) e assim usamos o desvio se os registradores forem a instrução de não igual (bne): bne $s3. f. diferentes ins.L1 Neumann. instrução que requer a comparação de dois valores e que leva em conta uma transferência de controle subsequente para um novo endereço no programa.Else # vá para Else se i ≠ j A próxima instrução de atribuição realiza uma única operação. apresentamos uma [instrução] beq registrador1. O mnemônico beq significa branch if equal (desviar se uma dentre duas rotinas. Com base nos dados de entrada e nos valores criados durante o cálculo. A tomada de decisão normalmente é representada nas linguagens de sinal de um número (zero programação usando a instrução if. às vezes combinadas com instruções go to e rótulos é considerado positivo para (labels). De modo geral.Essa cisões.else f = g − h. 2. Um deslocamento à esquerda seguido por um deslocamento à direita A utilidade de um computador automático se encontra na possibilidade de usar determinada sequência de instruções repetidamente 2. semelhantes as finalidades da máquina). 1947 Ela significa ir até a instrução chamada L1 se o valor no registrador1 não for igual ao valor no registrador2. essa é apenas uma instrução: .. AND mesmo 2.registrador2. A primeira expressão compara a igualdade. A primeira instrução é Consequentemente..7  Instruções para tomada de decisões o número de vezes em que ela é repetida depende dos O que distingue um computador de uma calculadora simples é a sua capacidade de tomar de.7  Instruções para tomada de decisões 83 Que operações podem isolar um campo em uma word? Verifique você 1. L1 (a [instrução] de transferência condicional) que. Só precisamos anexar um rótulo Else a essa instrução. abreviado como j (o rótulo Exit é definido a seguir). o nome MIPS para esse tipo de instrução é jump. A caixa da esquerda corresponde à parte then da instrução if.$s2 # f = g − h (ignorada se i = j) Exit : FIGURA 2. precisamos ir até o final da instrução if. Interface Os compiladores constantemente criam desvios e rótulos onde não aparecem na linguagem de programação. Loops Decisões são importantes tanto para escolher entre duas alternativas – como encontramos nas instruções if – quanto para repetir um cálculo – como nos loops. Essa instrução diz que o proces- sador sempre deverá seguir o desvio. Para distinguir entre os desvios condicionais e incondicionais.$s1. e a caixa da direita corresponde à parte else. normalmente chamado desvio incondicional. Observe que o montador alivia o compilador e o programador assembly do trabalho de calcular endereços para os desvios. Evitar o trabalho de escrever rótulos e desvios explícitos é um benefício hardware/ em linguagens de programação de alto nível e um dos motivos para a codificação ser mais software rápida nesse nível. assim como evita o cálculo dos endereços de dados para loads e stores (veja Seção 2.9  Ilustração das opções na instrução if acima. . As mesmas instruções assembly são os blocos de montagem para os dois casos. Também mostramos o rótulo Exit que está após essa instrução. Este exemplo apresenta outro tipo de desvio.12).$s2 # f = g + h (ignorada se i ≠ j) Agora. mostrando o final do código compilado de if-then-else: Else : sub $s0. j Exit # vá para Exit A instrução de atribuição na parte else da instrução if pode novamente ser compilada para uma única instrução.84 Capítulo 2  Instruções: A Linguagem de Máquina add $s0.$s1. precisamos ter seu endereço. podemos usar o deslocamento lógico à esquerda. O teste de igualdade ou desigualdade provavelmente é o teste mais comum. 2.$s3. um loop for pode querer testar destinos de desvio ou rótulos de se a variável de índice é menor do que 0. Qual é o código assembly MIPS correspondente a esse segmento C? O primeiro passo é ler save[i] para um registrador temporário. Por exemplo. no final) e sem é útil ver se uma variável é menor do que outra. anteriormente neste capítulo). exceto.$s3. pois o deslocamento à esquerda de 2 bits multiplica por 22 ou 4 (veja a Seção “Operações Lógicas”. Essas comparações são realizadas em assembly desvio (exceto.$t1. temos de somar $t1 e a base do array save em $t6: add $t1.2 # Registrador temporário $t1 = 4 * i Para obter o endereço de save[i]. temos de multiplicar o índice i por 4. e sem destinos de desvio ou rótulos hardware/ de desvio. Felizmente.$s6 # $t1 = endereço de save[i] Agora. Antes que RESPOSTA possamos somar i à base do array save para formar o endereço.) Essas sequências de instruções que terminam em um desvio são tão fundamentais para a Interface compilação que recebem seu próprio termo: um bloco básico é uma sequência de ins- truções sem desvios. software membrar o programa em blocos básicos. no do MIPS com uma instrução que compara dois registradores e atribui 1 a um terceiro início). bloco básico  Uma sequência de instruções sem desvios (exceto.$s5.7  Instruções para tomada de decisões 85 Compilando um WHILE loop em C Aqui está um loop tradicional em C: EXEMPLO Suponha que i e K correspondam aos registradores $s3 e $s5 e a base do array save esteja em $s6. mas às vezes possivelmente. no final. possivelmente.0($t1) # Registro temporário $t0 = save[i] A próxima instrução realiza o teste do loop. em razão do problema do endereçamento em bytes. Antes que possamos ler save[i] para um registrador temporário. podemos usar esse endereço para ler save[i] para um registrador temporário: lw $t0. possivelmente. . terminando se save[i] ≠ k : bne $t0. Precisamos acrescentar o rótulo Loop para podermos desviar de volta a essa instrução no final do loop: Loop : sll $t1. Simplesmente acrescentamos o rótulo Exit depois dele e terminamos: (Veja nos exercícios uma otimização para essa sequência. no início.1 # i = i+ 1 O final do loop desvia de volta ao teste do while no início do loop. Exit # vá para Exit se save[i] ≠ k A próxima instrução soma 1 a i: add $s3. possivelmente. Uma das primeiras fases da compilação é des. exceto. menor ou igual. caso contrário. Por exemplo. diferente.) MIPS oferece duas versões da comparação set on less than para tratar dessas alternati- vas. a arquitetura do MIPS não inclui “desvio se menor que”. software Duas instruções mais rápidas são mais úteis. Comparação de números com sinal e sem sinal EXEMPLO Suponha que o registrador $s0 tenha o número binário 1111 1111 1111 1111 1111 1111 1111 1111bin e que o registrador $s1 tenha o número binário 0000 0000 0000 0000 0000 0000 0000 0001bin . podemos simplesmente escrever slti $t0. slti. Os compiladores MIPS utilizam as instruções slt. naturalmente. maior que. bne e o valor fixo 0 (sempre à disposição com a leitura do registrador $zero) para criar todas as condições relativas: igual. A instrução MIPS é chamada set on less than (atribuir se menor que).$s2. Operadores constantes são comuns nas comparações. Os inteiros sem sinal são comparados por meio de set on less than unsigned (sltu) e set on less than immediate unsigned (sltiu). é atribuído 0. um padrão de bits com 1 no bit mais significativo representa um hardware/ número negativo e. é menor que qualquer número positivo. hardware/ ou ela esticaria o tempo do ciclo de clock ou exigiria ciclos de clock extras por instrução. beq. de modo que existe uma versão imediata da instrução set on less than. pois isso é muito complicado. Para testar se o registrador $s2 é menor do que a constante 10. (Logo tiraremos proveito desse significado dual do bit mais significativo para reduzir o custo da verificação dos limites do array. slt $t0. é atribuído 0 ao registrador $t0. caso contrário. Set on less than (slt) e set on less than immediate (slti) funcionam com inteiros com sinal. por outro lado. menor que.10 # $t0 = 1 se $s2 < 10 Interface Atentando para a advertência de von Neumann quanto à simplicidade do “equipamento”. ou slt. $s3. que precisa ter software um 0 no bit mais significativo. $s4 # $t0 = 1 se $s3 < $s4 significa que é atribuído 1 ao registrador $t0 se o valor no registrador $s3 for menor do que o valor no registrador $s4.86 Capítulo 2  Instruções: A Linguagem de Máquina registrador se o primeiro for menor do que o segundo. um 1 no bit mais significativo representa um número que é maior que qualquer um que comece com um 0. maior ou igual. Às vezes. Com inteiros sem sinal. Interface As instruções de comparação precisam lidar com a dicotomia entre números com sinal e sem sinal. chamada tabela de endereços de tabela de endereços de desvio ou tabela de desvio. Embora haja muitas instruções para decisões e loops em linguagens de programação como Interface C e Java. O registrador $t0 tem o valor 1. dependendo de um único valor. $s0. uma comparação sem sinal de x < y também verifica se x é negativo. mas uma grande parte do número na segunda. a instrução básica que as implementa no nível do conjunto de instruções é o desvio condicional. e o registrador $t1 tem o valor 0. Depois desvia para o endereço apropriado usando essa instrução. as alternativas podem ser codificadas de forma mais eficiente como uma tabela de endereços de sequências de instruções alternativas. computadores como o MIPS incluem uma instrução jump register (jr).967. não se preocupe: o montador do MIPS os torna invisíveis ao programador assembly. Para apoiar tais situações.$t2 # $t0 = 0 se $s1 >= tamanho ou $s1 < 0 beq $t0.7  Instruções para tomada de decisões 87 Quais são os valores dos registradores $t0 e $t1 após essas duas instruções? slt $t0. o bit mais significativo é um bit de sinal na primeira notação. instruções alternativas.$s1. pois 4. Assim. que corresponde à verificação de índice fora de limite dos arrays. O valor no registrador $s1 representa 1dec em qualquer RESPOSTA caso. ou seja. significando um desvio incondicional para o endereço especificado em um registrador. Atalho para verificação de limites Use este atalho para reduzir uma verificação de índice fora dos limites: salte para IndexOutOfBounds se $s1 ≥ $t2 ou se $s1 é negativo. explicados no Capítulo 4. e o programa só precisa indexar na tabela e depois desviar desvio  Também chamada de para a sequência apropriada.$zero. hardware/ software Detalhamento:  se você já ouviu falar em delayed branches. . bem como se x é menor que y.IndexOutOfBounds # se erro. 2.294. O modo mais simples de implementar switch é por meio de uma sequência de testes condicionais. Às vezes.295dec se for um inteiro sem sinal. para o programador poder selecionar uma dentre muitas alternativas. transformando a instrução switch em uma cadeia de instruções if-then-else. $s1 # comparação com sinal sltu $t1. Uma tabela de endereços de sequências de com endereços que correspondem aos rótulos no código. pois -1dec < 1dec.294. goto Error Instrução Case/Switch A maioria das linguagens de programação possui uma instrução case ou switch. apenas um array de palavras tabela de desvios.967. $s1 # comparação sem sinal O valor no registrador $s0 representa -1dec se for um inteiro e 4. Tratar números com sinal como se fossem sem sinal é um modo de baixo custo para verificar se 0 ≤ x < y. O principal é que os inteiros negativos na notação de complemento de dois se parecem com números grandes na notação sem sinal. então. A tabela de desvios é.295dec > 1dec. que é descrita na próxima seção. EXEMPLO O código de verificação só usa sltu para realizar as duas verificações: RESPOSTA sltu $t0. $s0. 6. um espião opera apenas sobre aquilo que ele “precisa saber”. 2. de modo que não pode fazer suposições sobre seu patrão. Elas são redundantes e significam a mesma coisa: && e || são simplesmente herdados da linguagem de programação B. 5. Mais instruções de decisão significam menos linhas de código. De modo semelhante. II. Mais instruções de decisão significam menos linhas de código. Suporte a procedimentos no hardware 2.15 do CD. Além do mais. enquanto os desvios con- dicionais implementam && e ||. cobre seus rastros e depois retorna ao ponto de origem com o resultado desejado. com os parâmetros atuando como uma barreira entre o procedimento e o restante do programa e dos dados. 3. pois um procedimento pode ser cha- mado de vários pontos em um programa. Colocar o valor de retorno em um local onde o programa que o chamou possa acessá-lo. Os procedimentos permitem que o programador se concen- tre em apenas uma parte da tarefa de cada vez. 3. 4. o que geralmente resulta na execução de menos operações. o programa precisa seguir estas seis etapas: 1. 2. enquanto o MIPS você mesmo possui poucas. adquire recursos. Você pode pensar em um procedimento como um espião que sai com um plano secreto. o que geralmente reduz o tempo de codificação. realiza a tarefa.  Por que a linguagem C oferece dois conjuntos de operadores para AND (& e &&) e dois conjuntos de operadores para OR (| e ||). Quais dos seguintes itens explicam ou não esse desequilíbrio? Por quê? 1.  A linguagem C possui muitas instruções para decisões e loops. a antecessora do C. permitindo que sejam passados valores e resultados de retorno. 4. A afirmativa anterior é o contrário: && e || correspondem a operações lógicas. Nada mais deverá ter sido perturbado depois que a missão terminar. tanto para torná-los mais fáceis de entender quanto para permitir com base nos parâmetros com os quais ela é provida.8   do computador procedimento  Uma sub-rotina Um procedimento ou função é uma ferramenta que os programadores utilizam a fim de armazenada que realiza uma tarefa estruturar programas. mas a linguagem Java precisa de tudo de um computador que a linguagem C também necessita. 2. Transferir o controle para o procedimento. Retornar o controle para o ponto de origem. que o código seja reutilizado. . Adquirir os recursos de armazenamento necessários para o procedimento. 3. As operações lógicas AND e OR implementam & e |. Colocar parâmetros em um lugar onde o procedimento possa acessá-los. Realizar a tarefa desejada.88 Capítulo 2  Instruções: A Linguagem de Máquina Verifique I. Menos instruções de decisão simplificam a tarefa da camada inferior responsável pela execução. na execução de um procedimento. Mais instruções de decisão tornam o código mais fácil de ler e entender. enquanto & e | são mapeados para desvios condicionais. Descrevemos o equivalente aos procedimentos em Java na Seção 2. enquanto o MIPS não faz isso? 1. embora um nome mais sensato teria sido registrador de endereço de instrução. esse registrador quase sempre é caller novamente. a fim de mostrar onde o próximo procedimento deverá recentemente em uma pilha. . A parte do link no nome da instrução significa que um endereço ou link é formado de modo a apontar para o local de chamada. registrador que contém o endereço A instrução jal salva o PC + 4 no registrador $ra para o link com a instrução seguinte. que colocar os spilled registers ou onde os valores antigos dos registradores estão localizados. pop  Remover elemento da pilha. uma fila do tipo “último a entrar. 2. mostra onde spilled registers devem O stack pointer é ajustado em uma palavra para cada registrador salvo ou restaurado. computadores como o MIPS utilizam uma instrução de jump no MIPS. de parâmetro em $a0-$a3 e utiliza jal X para desviar para o procedimento X (às vezes callee  Um procedimento que denominado callee). O callee. para retornar ao ponto de origem Além de alocar esses registradores. um desvio incondicional para o endereço especificado em um registrador: jr $ra caller  O programa que instiga um A instrução de jump register pula para o endereço armazenado no registrador $ra – que procedimento e oferece os valores é exatamente o que queremos. Como temos de cobrir nossos rastros após o término desta missão. Uma pilha precisa de um ponteiro para o endereço stack pointer  Um valor indicando o endereço alocado mais alocado mais recentemente na pilha. o assembly do MIPS inclui uma instrução apenas para os procedimentos: ela desvia para um endereço e simultaneamente salva o endereço da instrução seguinte no registrador $ra. significando registrador $ra. Essa situação é um exemplo em que são usados os spilled registers em memória. para valores de retorno j $ra: um registrador de endereço de retorno. As pilhas são tão comuns que possuem seus próprios termos para transferir dados localizados. para passar parâmetros j $v0-$v1: dois registradores de valor. é denominado pop. coloca os resultados em $v0-$v1 executa uma série de instruções e retorna o controle para o caller usando jr $ra. armazenadas com base nos Num programa armazenado é necessário ter um registrador para manter o endereço da parâmetros fornecidos pelo caller e depois retorna o controle para o instrução atual sendo executada. ele é armazenado no register (jr). e remover dados da pilha push  Acrescentar elemento à pilha. ser armazenados ou onde os valores O software MIPS reserva o registrador 29 para o stack pointer. coloca os valores de parâmetro necessários. Por motivos históricos. A estrutura de dados ideal para armazenar os spilled registers é uma pilha – uma fila do tipo “último a entrar. primeiro a sair”. A instrução de jump-and-link (jal) é escrita instrução de jump-and-link  simplesmente como Uma instrução que salta para um endereço e simultaneamente salva o endereço da instrução seguinte jal EndereçoProcedimento em um registrador ($ra no MIPS). Esse “link”. o programa que chama. dando-lhe o nome óbvio antigos dos registradores podem ser $sp. denominado contador de programa. ou caller.8  Suporte a procedimentos no hardware do computador 89 Como já dissemos. os registradores são o local mais rápido para manter dados em um computador. realiza os cálculos. armazenado no registrador $ra. permitindo que um procedimento chamado de várias partes do programa. é denominado endereço de endereço de retorno Um retorno. então. Assim. da instrução sendo executada no a fim de preparar o retorno do procedimento. retorne ao endereço correto. apresentada anteriormente para ajudar com as instruções case. primeiro a sair”. programa. organizada como conforme mencionamos na Seção “Interface hardware/software”. de modo que queremos usá-los ao máximo possível. O software do MIPS utiliza a seguinte convenção na alocação de seus 32 registradores: j $a0-$a3: quatro registradores de argumento. quaisquer registradores necessários pilha (stack)  Uma estrutura de ao caller deverão ser restaurados aos valores que possuíam antes de o procedimento ser dados utilizada para armazenar os chamado. O endereço de retorno é necessário porque o mesmo procedimento poderia ser link para o local de chamada. Para apoiar tais situações. abreviado como PC (Program Counter) na arquite- contador de programa (PC) O tura MIPS. Usando mais registradores Suponha que um compilador precise de mais registradores para um procedimento do que os quatro registradores para argumentos e os dois para valores de retorno. permitindo que o procedimento retorne ao endereço correto. spilled registers. da pilha e para ela: colocar dados na pilha é denominado push. restauramos os três valores antigos dos registradores que salvamos. $t0 e $t1. removendo seus valores. que usa dois registradores temporários. $a2 e $a3. precisamos salvar três registradores: $s0. nós o copiamos para um registrador de valor de retorno: add $v0. e f corresponde a $s0. h.$zero # retorna f ($v0 = $s0 + 0) Antes de retornar. Essa convenção significa que você põe valores na pilha subtraindo do valor do stack pointer. A instrução de atribuição em C no corpo do procedimento é idêntica ao exemplo da Seção 2.10 mostra a pilha antes. Assim. as pilhas “crescem” de endereços maiores para endereços me- nores.2.$s0. $a1. O programa compilado começa com o rótulo do procedimento: exemplo_folha: O próximo passo é salvar os registradores usados pelo procedimento. i e j correspondem aos registradores de argumen- RESPOSTA to$a0. criando espaço para três palavras (12 bytes) na pilha e depois as armazenamos: A Figura 2.2: Para retornar o valor de f. “Empilhamos” os valores antigos. As três instruções seguintes correspondem ao corpo do procedimento. Somar ao stack pointer diminui essa pilha.2 em um procedimento em C: EXEMPLO Qual é o código assembly do MIPS compilado? As variáveis de parâmetro g. que segue o exemplo da Seção 2.90 Capítulo 2  Instruções: A Linguagem de Máquina Por motivos históricos. Compilando um procedimento em C que não chama outro procedimento Vamos transformar o exemplo da Seção 2. durante e após a chamada do procedimento. desempilhando-os: . Ainda temos de salvar e restaurar $s0. também precisamos ter mais cuidado ao chamar procedimentos não folha. Além do mais. suponha que o procedimento A chame o procedimento B por meio de jal B com um argumento 7. os procedimentos também chamam outros procedimentos. No exemplo anterior. que. Assim como um espião poderia empregar outros espiões como parte de uma missão. por sua vez. suponha que o programa principal chame o procedimento A com um argumento 3. mas não são. os procedimentos recursivos ainda chamam “clones” de si mesmos. (b) durante e (c) após a chamada do procedimento. o software do MIPS separa 18 dos registradores em dois grupos: j $t0–$t9: dez registradores temporários que não são preservados pelo procedimento chamado em uma chamada de procedimento j (se forem usados. Como A ainda não terminou sua tarefa. No exemplo anterior. Assim como precisamos ter cuidado ao usar registradores nos procedimentos. o procedimento chamado os salva e restaura)$s0–$s7: oito regis- tradores salvos que precisam ser preservados em uma chamada de procedimento Essa convenção simples reduz o register spilling. colocando o valor 3 no registro $a0 e depois usando jal A. Depois. O stack pointer sempre aponta para o “topo” da pilha ou para a última palavra na pilha neste desenho.8  Suporte a procedimentos no hardware do computador 91 O procedimento termina com um jump register usando o endereço de retorno: jr $ra # desvia de volta à rotina que chamou FIGURA 2. existe um conflito com . Para evitar salvar e restaurar um registrador cujo valor nunca é utilizado. A vida seria simples se todos os procedimentos fossem procedimentos folha. Procedimentos aninhados Os procedimentos que não chamam outros são denominados procedimentos folha. usamos registradores temporários e consideramos que seus valores antigos precisam ser salvos e restaurados. 2.10  Os valores do stack pointer e a pilha (a) antes. Por exemplo. também colocado em $a0. podemos descartar dois stores e dois loads do código. poderiam utilizar ainda mais espiões. como o caller não espera que os registradores $t0 e $t1 sejam preservados durante uma chamada de procedimento. pois o procedimento chamado deve considerar que o caller precisa de seu valor. o que poderia acontecer com um registrador temporário. o endereço de retorno e $a0: Na primeira vez que fact é chamado. sw salva um endereço do programa que chamou fact. A menos que tomemos medidas para evitar o problema. fact retorna 1. indo para L1 se n ≥ 1 . Uma solução é empilhar todos os outros registradores que precisam ser preservados. Compilando um procedimento C recursivo. O programa compilado RESPOSTA começa com o rótulo do procedimento e depois salva dois registradores na pilha. O callee empilha o registrador do endereço de retorno $ra e quaisquer registradores salvos ($s0–$s7) usados por ele. Depois. mostrando a ligação do procedimento aninhado Vamos realizar um procedimento recursivo que calcula o fatorial: EXEMPLO Qual é o código assembly do MIPS? O parâmetro n corresponde ao registrador de argumento $a0. os regis- tradores são restaurados da memória e o stack pointer é reajustado. ele retira os dois valores salvos da pilha e desvia para o endereço de retorno: . colocando 1 em um registrador de valor: ele soma 1 a 0 e coloca essa soma em $v0. assim como fizemos com os registradores salvos. As duas instruções seguintes testam se n é menor do que 1. O caller empilha quaisquer registradores de argumento ($a0–$a3) ou registradores temporários ($t0–$t9) que sejam necessários após a chamada. No retorno. esse conflito eliminará a capacidade do procedimento A de retornar para o procedimento que o chamou. existe um conflito em relação ao endereço de retorno no registrador $ra.92 Capítulo 2  Instruções: A Linguagem de Máquina relação ao uso do registrador $a0. De modo semelhante. O stack pointer $sp é ajustado para levar em consideração a quantidade de registradores colocados na pilha. Se n for menor do que 1. pois ele agora tem o endereço de retorno para B. Alguns exemplos são inteiros e caracteres (veja Seção 2. A Figura 2. juntamente com o stack pointer: Em seguida. A próxima instrução é onde fact retorna. poderíamos ter restaurado $a0 e $ra. embora isso não seja explicado antes do Capítulo 3: mul $v0. . A linguagem C possui duas classes de armazenamento: automática e estática. o endereço de retorno antigo e o argumento antigo são restaurados. As outras são automáticas. Agora.$a0. o argumento n é decrementado e depois fact é chamado novamente com o valor decrementado. Consideramos que exista uma instrução de multiplicação à disposição. eles também são preservados. e os outros registradores são preservados por serem salvos na pilha (se forem usados) e restaurados de lá. assim como quaisquer variáveis declaradas por meio da palavra reservada static. ponteiro global  O registrador reservado para apontar para a área estática. o registrador de valor $v0 recebe o produto do argumento antigo $a0 e o valor atual do registrador de valor. A pilha acima de $sp é preservada simplesmente verificando se o procedimento chamado não escreve acima de $sp. Se n não for menor do que 1. garantindo que o caller receberá os mesmos dados em um load da pilha que foram armazenados nela. As variáveis estáticas permanecem durante entradas e saídas de pro- cedimentos. Como $a0 e $ra não mudam quando n é menor do que 1. FIGURA 2. fact salta novamente para o endereço de retorno: jr $ra # retorna para o procedimento que chamou Uma variável em C é um local na memória e sua interpretação depende tanto do seu tipo Interface quanto da sua classe de armazenamento. discutidos nas próximas seções. As variáveis C declaradas fora de todos os procedimentos são consideradas estáticas. Para simplificar o acesso aos dados estáticos. ou $gp. o software do MIPS reserva outro registrador. software cedimento termina. 2. hardware/ As variáveis automáticas são locais a um procedimento e são descartadas quando o pro.$v0 # retorna n * fact(n − 1) Finalmente.9).11  O que é e o que não é preservado durante uma chamada de procedimento. pulamos essas instruções. chamado ponteiro global. Observe que vários esquemas preservam a pilha.11 resume o que é preservado em uma chamada de procedimento. $sp é preservado pelo procedimento chamado somando-se exatamente o mesmo valor que foi subtraído dele.8  Suporte a procedimentos no hardware do computador 93 Antes de retirar dois itens da pilha. Se o software contar com o registrador de frame pointer ou com o registrador de ponteiro global. e depois.13 mostra a convenção do MIPS para a alocação de memória. restaurando-o. registrador base estável dentro de um procedimento para as referências locais à memória.12 chamado registro de ativação. que não cabem nos registradores. correspondam muito bem ao segmento de dados estático. o compilador ganhará tempo não atribuindo um endereço ao frame pointer. A Figura 2.12  Ilustração da alocação de pilha (a) antes. no início deste livro. A pilha começa na parte alta da memória e cresce para baixo. segmento da pilha contendo os Alguns softwares MIPS utilizam o frame pointer ($fp) a fim de apontar para a primei- registradores salvos e as variáveis locais de um procedimento. Acima do código existe o segmento de dados es- de máquina para as rotinas do táticos. portanto. O frame pointer ($fp) aponta para a primeira palavra do frame. FIGURA 2. normalmente um registrador de argumento salvo. e o stack pointer ($sp) aponta para o topo da pilha. ter um tamanho fixo e. O stack pointer poderia mudar durante o procedimento.94 Capítulo 2  Instruções: A Linguagem de Máquina Alocando espaço para novos dados na pilha A complexidade final é que a pilha também é utilizada para armazenar variáveis que são locais ao procedimento. como arrays ou estruturas locais. a pilha é ajustada apenas na entrada e na saída do pro- cedimento. Se não houver variáveis locais na pilha dentro de um procedimento. ra word do registro de ativação de um procedimento. o que torna o indicando o local dos registradores procedimento mais difícil de entender. Como alternativa. A primeira parte da extremidade segmento de texto  O segmento de um arquivo-objeto Unix que baixa da memória é reservada. Alocando espaço para novos dados no heap Além das variáveis automáticas que são locais aos procedimentos. . Quando um frame pointer é usado. Evitamos o $fp impedindo mudanças no $sp dentro de um pro- cedimento: em nossos exemplos. um frame pointer oferece um salvos e as variáveis locais para um determinado procedimento. O segmento da pilha que contém os registradores salvos e as variáveis locais de um pro- frame de procedimento Também cedimento é chamado frame de procedimento. A Figura 2. que é o local para constantes e outras variáveis estáticas. Essa informação também aparece na Coluna 4 do Guia de Instrução Rápida do MIPS. seguida pelo código de máquinas do MIPS. ele é inicializado usando o endereço que está no $sp em uma chamada. A pilha é ajustada de modo a criar espaço para todos os registradores salvos e quaisquer variáveis locais residentes na memória. Observe que um registro de ativação aparece na pilha independente de o frame pointer explícito ser utilizado. Embora os arrays costumem arquivo-fonte. os programadores C precisam de espaço na memória para as variáveis globais e para estruturas de dados dinâ- micas. e assim as referências a uma variável local na memória poderiam frame pointer  Um valor ter offsets diferentes. O mostra o estado da pilha antes. durante e após a chamada de um procedimento. é mais fácil para os programadores referenciarem variáveis por meio do frame pointer estável. (b) durante e (c) após a chamada de um procedimento. e o $sp é restaurado usando o valor do $fp. embora isso também pudesse ser feito por meio do stack pointer e um pouco de aritmética de endereços. dependendo de onde estiverem no procedimento. tradicional- contém o código em linguagem mente denominado segmento de texto. Como o stack pointer pode mudar durante a execução do programa. ou registro de ativação. é definido como um endereço para facilitar o acesso aos dados. O registrador 1. Os dados estáticos começam em 1000 0000hexa . Os dados dinâmicos. FIGURA 2. o stack pointer é inicializado com 7fff fffchexa e cresce para baixo. são reservados para o sistema operacional. é reservado para o montador (veja Seção 2. permitindo. e os registradores 26-27. em uma área chamada heap. assim. o código do pro- grama (“texto”) começa em 0040 0000 . vêm em seguida e crescem para cima em direção à pilha. que. . chamado $at . $gp. hexa alocados por malloc em C e por new em Java. O segmento para tais estruturas de dados é tradicionalmente chamado de heap e fica posicionado logo a seguir na memória.12). por fim. chamados $k0-$k1. em direção ao segmento de dados.14  Convenções de registradores MIPS. Liberar espaço muito cedo ocasiona “ponteiros pendentes”. Java utiliza alocação de memória e coleta de lixo automáticas justamente para evitar esses problemas. no início deste livro. pode vir a causar a falha do sistema operacional. o uso eficiente da memória enquanto os dois segmentos aumentam e diminuem. De cima para baixo. podendo fazer os ponteiros apontarem para áreas que o programa nunca desejou.13  A alocação de memória do MIPS para programas e dados. Essa informação também aparece na Coluna 4 do Guia de Instrução Rápida do MIPS.14 resume as convenções de registrador para o assembly do MIPS. Esquecer de liberar espaço ocasiona um “vazamento de memória”. e free() libera o espaço no heap para o qual o ponteiro está apontando.8  Suporte a procedimentos no hardware do computador 95 estruturas de dados como listas encadeadas costumam crescer e diminuir durante suas vidas. A linguagem C aloca e libera espaço no heap com funções explícitas. Esses endereços são apenas uma convenção do software e não fazem parte da arquitetura MIPS. A Figura 2. 2. malloc() aloca espaço no heap e retorna um ponteiro para ela. Na outra extremidade. A alocação da memória é controlada por programas em C e essa é a fonte de muitos bugs comuns e difíceis de serem encontrados. Essa informação também aparece na Coluna 2 do Guia de Instrução Rápida do MIPS. Ele é inicializado com 1000 8000 para poder acessar de 1000 0000 até 1000 ffffhexa usando os offsets hexa hexa de 16 bits positivos e negativos a partir do $gp. no início deste livro. O ponteiro global. FIGURA 2. Observe que essa alocação permite que a pilha e o heap cresçam um em direção ao outro. Isso resultará em chamadas recur- sivas a sum(2. endereçável por meio do frame pointer. logo acima do stack pointer. Essa chamada recursiva de sum é conhecida como tail call e esse exemplo de uso da recursão tail pode ser implementado de modo muito eficiente (suponha que $a0 =n e $a1=acc): Verifique Quais das seguintes afirmações sobre C e Java geralmente são verdadeiras? você mesmo 1. ele trata o registrador 30 como outro registrador de valor salvo ($a8). Os programadores C gerenciam os dados explicitamente. então. e depois o resultado 6 será retornado quatro vezes. o frame pointer é conveniente porque todas as referências a variáveis na pilha dentro de um procedimento terão o mesmo offset. removendo o overhead associado a chamadas de procedimento.5)e sum(0. o frame pointer não é necessário. mas não o compilador C do MIPS.6). Contudo. O procedimento. A linguagem C leva a mais problemas de ponteiro e vazamento de memória do que Java. sum(1. considere um procedimento usado para acumular uma soma: Considere a chamada de procedimento sum(3. Por exemplo.12. O compilador C para MIPS sob licença GNU utiliza um frame pointer. Conforme dissemos na legenda da Figura 2.3).0). 2. enquanto isso é automático em Java. . e que o restante esteja na memória. espera que os quatro primeiros parâmetros estejam nos registradores de $a0 a $a3. Detalhamento:  Alguns procedimentos recursivos podem ser implementados iterativamente sem o uso de recursão.96 Capítulo 2  Instruções: A Linguagem de Máquina Detalhamento:  e se houver mais do que quatro parâmetros? A convenção do MIPS é colocar os parâmetros extras na pilha. A iteração pode melhorar significativamente o desempenho. 8 representa backspace. no início deste livro. software sentado por vários dígitos binários. essa observação pode levar a atalhos na verificação ou mudança entre maiúsculas e minúsculas. Os computadores foram inventados para devorar números. 9 representa o caractere de tabulação e 13. O decimal provou ser tão ineficaz que os computado- res subsequentes reverteram para tudo binário. o American Standard Code for “(” é open. Observe que as letras maiúsculas e minúsculas diferem exatamente em 32. temos 10 dedos e por isso achamos a base Interface 10 natural. de modo que um dígito decimal era simplesmente repre. o primeiro compu- tador comercial oferecia aritmética decimal. convertendo para a base 10 somente os eventos de entrada/saída relativamente infrequentes. Essa informação também aparece na Coluna 3 do Guia de Instrução Rápida do MIPS. A Figura 2. e assim Information Interchange (ASCII) é a representação que quase todos seguem. . assim que se tornaram 1991 (alguns dão nomes aos comercialmente viáveis.9  Comunicando-se com as pessoas Quarta linha do poema de teclado “Hatless Atlas”. Por exemplo. Outro valor útil é 0 para null. A maioria dos computa. O problema foi que o computador ainda hardware/ usava sinais ligado e desligado. um carriage return. Os valores não mostrados incluem caracteres de formatação.15  Representação dos caracteres no código ASCII.9  Comunicando-se com as pessoas 97 !(@ | = > (wow open tab at bar is great) 2. 2. Por que os computadores não usam decimal? Na verdade. dores hoje utiliza bytes de 8 bits para representar caracteres. o valor que a linguagem de pro- gramação C utiliza para marcar o final de uma string. mas. “|” é bar. caracteres ASCII: “!” é “wow”.15 por diante) resume o código ASCII. eles foram usados para processar textos. A base 2 não é natural para os seres humanos. FIGURA 2. a string “Cal” é representada em C pelos 4 bytes a seguir. mas sua finalidade é colocar uma representação correta software do número dentro desse registrador. colocando-o nos 8 bits mais à direita de um registrador. que possuem uma quantidade variável de caracteres. A linguagem C utiliza a terceira opção. em ASCII). 97. enquanto load byte unsigned (lbu) funciona com inteiros sem sinal. em vez de considerar bytes como inteiros com sinal muito curtos.0($gp) # Escreve byte no destino (Conforme veremos. loads com sinal e sem sinal são idênticos. O MIPS oferece dois tipos de loads de byte: load byte (lb) trata o byte como um número com sinal e. Load byte (lb) lê um byte da memória. pois o número representado pelo padrão de bits é sem sinal. de modo que load word e store word são suficientes para transferir bytes e também palavras. Existem três opções para representar uma string: (1) a primeira posição da string é reservada para indicar o tamanho de uma string. o hardware para somar. terminando uma string com um byte cujo valor é 0 (denominado null. Interface A presença ou ausência de sinal aplica-se a loads e também à aritmética. Ao carregar uma palavra de 32 bits para um registrador de 32 bits. subtrair. Essas dificuldades explicam por que os profissionais de computação são levados a crer que o binário é natural e que o computador decimal ocasional é bizarro.) Os caracteres normalmente são combinados em strings. o MIPS oferece instruções para mover bytes. a expansão no armazenamento seria (10 x 8)/32. multiplicar e dividir esses números decimais é difícil. estende o sinal para preencher os 24 bits mais à esquerda do registrador. lbu é usado de modo praticamente exclusivo para loads de byte. . 108. cada RESPOSTA um com 8 bits de extensão. ou (3) a última posição da string é ocupada por um caractere que serve para marcar o final da string. ou 2. de modo que ele precisaria de 10 dígitos ASCII. copiamos um byte com a sequência lb $t0. Assim.000. o ponto é irrelevante. Além da expansão no armazenamento. em forma de números decimais: 67. portanto. Entretanto.98 Capítulo 2  Instruções: A Linguagem de Máquina ASCII versus números binários Poderíamos representar números como strings de dígitos ASCII em vez de inteiros. (2) uma variável acompanhante possui o tamanho da string (como em uma estrutura). Os loads sem sinal simplificam o preenchimento com 0s à esquerda dos dados.000. Como os programas em C quase sempre utilizam bytes para representar caracteres. A função de um load com sinal é copiar o sinal repetidamente para preencher o restante do registrador hardware/ – chamado extensão de sinal –. em razão da popularidade do texto em alguns programas. Diversas instruções podem extrair um byte de uma palavra. Java utiliza a primeira opção. 0. Assim. Assim. EXEMPLO Em quanto o armazenamento aumenta se o número 1 bilhão for representado em ASCII em vez de inteiro com 32 bits? Um bilhão é 1.0($sp) # Lê byte da origem sb $t0.5. Store byte (sb) separa o byte mais à direita de um registrador e o escreve na memória.000. a próxima instrução define $s0 como 0. para demonstrar o uso de strings em C O procedimento strcpy copia a string y para a string x.9  Comunicando-se com as pessoas 99 Compilando um procedimento de cópia de string.$zero. Para carregar o caracter em y[i]. ou seja.$zero. usando a convenção de término com byte nulo da linguagem C: EXEMPLO Qual é o código assembly correspondente no MIPS? A seguir está o segmento básico em código assembly do MIPS. O endereço de y[i] é formado inicialmente pela soma de i a y[] : L1: add $t1. Em seguida.$zero # i = 0 + 0 Esse é o início do loop. como nos exemplos anteriores.$a1 # endereço de y[i] em $t1 Observe que não temos de multiplicar i por 4. e não de palavras. incrementamos i e voltamos ao loop: . vai para L2 Se não. Considere que os endereços base para os arrays x e y são encontrados em $a0 e $a1. e depois o caractere em $t2 é armazenado nesse endereço. strcpy ajusta o stack pointer e depois salva o registrador de valores salvos $s0 na pilha: Para inicializar i como 0.$s0. somando 0 a 0 e colocando essa soma em $s0: add $s0. saímos do loop se o caractere foi 0.L2 # se y[i] == 0. que coloca o caractere em $t2: lbu $t2. 0($t1) # $t2 = y[i] Um cálculo de endereço semelhante coloca o endereço de x[i] em $t3. esse é o último caractere da string: beq $t2. enquanto i está RESPOSTA em$s0. 2. usamos load byte. pois y é um array de bytes. Ao contrário da linguagem C. Java inclui uma palavra que indica o tamanho da string.100 Capítulo 2  Instruções: A Linguagem de Máquina Se não voltamos. Como padrão. uma explicação sobre arrays e ponteiros. load half ( lh ) trata a halfword como um número com sinal e. permitindo que o programa sempre use lw e sw (que precisam estar alinhados) para acessar a pilha. para depois retornar. restauramos $s0 e o stack pointer. Store half ( sh ) separa a halfword correspondente aos 16 bits mais à direita de um registrador e a escreve na memória. ele esgota todos os registradores temporários antes de usar registradores que precisa salvar. Veja. Copiamos uma halfword com a sequência As strings são uma classe padrão do Java. estende o sinal para preen- cher os 16 bits mais à esquerda do registrador. então esse foi o último caractere da string. comparação e conversão. Java utiliza Unicode para os caracteres. Para ser mais específico. Load half (lh) lê uma halfword da memória. Contudo. Assim como load byte. podemos pensar neles como registradores que o procedimento chamado deve utilizar sempre que for conveniente. o compilador poderia alocar i a um registrador temporário e evitar as operações de salvar e restaurar $s0. ela utiliza 16 bits a fim de representar um caractere. Caracteres e strings em Java Unicode é uma codificação universal dos alfabetos da maior parte das linguagens humanas. uma variável string ou um array de bytes em C agrupará 4 bytes por palavra. portanto. A Figura 2. Em virtude disso. As cópias de string normalmente utilizam ponteiros no lugar de arrays em C. para evitar as operações com i no código anterior. Assim. Detalhamento:  o software do MIPS tenta manter a pilha alinhada em endereços de pala- vra. enquanto load halfword unsigned ( lhu ) trabalha com inteiros sem sinal. semelhante aos arrays Java. chamadas halfwords.16 é uma lista de alfabetos Unicode. em vez de pensar nos registradores $t como sendo apenas para temporários. na Seção 2. e uma variável string ou array de shorts em Java agrupará 2 halfwords por palavra. lhu é o mais comum dos dois.14. Essa convenção significa que uma variável char alocada na pilha ocupa 4 bytes. Como o procedimento strcpy anterior é um procedimento folha. colocando-a nos 16 bits mais à direita de um registrador. com suporte interno especial e métodos predefinidos para concatenação. O conjunto de instruções do MIPS possui instruções explícitas para carregar e armazenar quantidades de 16 bits. Quando um compilador encontra um procedimento folha. . existem tantos alfabetos em Unicode quanto símbolos úteis em ASCII. embora precise de menos. int em C 2. Quais das seguintes afirmações sobre caracteres e strings em C e Java são verdadeiras? Verifique 1. Strings são apenas um nome informal para arrays de uma única dimensão de caracteres em C e Java. existem ocasiões em que seria conveniente ter uma constante de 32 bits ou endereço de 32 bits. UTF-32 utiliza 32 bits por caractere. Cada bloco é um múltiplo de 16. chamada UTF-16.000. às vezes elas são maiores. A última coluna possui 16 blocos que são multilinguais e não estão em ordem. Uma string em C utiliza cerca da metade da memória da mesma string em Java. O conjunto de instruções MIPS inclui a instrução load upper . são mais rápidas em C do que em Java. As operações sobre strings. II.10  Endereçamento no MIPS para operandos imediatos e endereços de 32 bits 101 FIGURA 2. I. 3. string em Java Endereçamento no MIPS para operandos 2. é o padrão.10  imediatos e endereços de 32 bits Embora manter todas as instruções MIPS com 32 bits simplifique o hardware. Para saber mais sobre isso. Esta seção começa com a solução geral para constantes grandes e depois apresenta as otimizações para endereços de instruções usados em desvios condicionais e jumps. 4.000dec ocupa mais espaço na memória? 1. As strings em C e Java utilizam null (0) para marcar o fim de uma string. Por exemplo. As três primeiras colunas mostram 48 blocos que correspondem a linguagens humanas em ordem numérica aproximada no Unicode. que é o nome para uma coleção de símbolos. string em C 3. Uma codificação de 16 bits. Que tipo de variável que pode conter 1. Grego começa em 0370hexa e Cirílico em 0400hexa. como saber seu tamanho.16  Exemplos de alfabetos em Unicode. você mesmo 2. chamada UTF-8.org.000. Operandos imediatos de 32 bits Embora as constantes normalmente sejam curtas e caibam em um campo de 16 bits. Uma codificação de tamanho variável.unicode.0 possui mais de 160 “blocos”. 2. mantém o subconjunto ASCII como 8 bits e utiliza 16-32 bits para os outros caracteres. consulte www. O Unicode versão 4. indicando quando usarmos a linguagem avançada do montador que não se encontra no processador. Logo. então o montador precisa ter um registrador temporário disponível. e também para constantes em instruções imediatas. que é reservado para o montador. onde criará valores longos. carregaríamos os 16 bits mais altos. a restrição hardware/ de tamanho do campo imediato pode ser um problema para endereços de memória em software loads e stores. a representação simbólica da linguagem de máquina do MIPS não está mais limitada pelo hardware. preenchendo os 16 bits de menor ordem (direita) com 0s. $s0.102 Capítulo 2  Instruções: A Linguagem de Máquina immediate (lui) especificamente para atribuir os 16 bits mais altos de uma constante a um registrador. A instrução lui transfere o valor do campo de constante imediata de 16 bits para os 16 bits mais à esquerda do registrador. Carregando uma constante de 32 bits Qual é o código assembly do MIPS para carregar esta constante de 32 bits no regis- EXEMPLO trador $s0? 0000 0000 0011 1101 0000 1001 0000 0000 Primeiro. mas a qualquer coisa que o criador de um montador decidir in- cluir (veja Seção 2. Se esse trabalho recair para o montador. 61 # 61 decimal = 0000 0000 0011 1101 binário O valor do registrador $s0 depois disso é 0000 0000 0011 1101 0000 0000 0000 0000 O próximo passo é acrescentar os 16 bits inferiores.17  O efeito da instrução lui. Interface Tanto o compilador quanto o montador precisam desmembrar constantes grandes em partes e depois remontá-las em um registrador. Esse é um motivo para o registrador $at.17 mostra a operação de lui.12). FIGURA 2. como acontece para o software do MIPS. usando a ins- RESPOSTA trução lui: lui $s0. A Figura 2. 2304 # 2304 decimal = 0000 1001 0000 0000 O valor final no registrador $s0 é o valor desejado: 0000 0000 0011 1101 0000 1001 0000 0000 . Como você poderia esperar. cujo valor decimal é 2304: ori $s0. Vamos examinar o hardware de perto para explicar a arquitetura do computador. permitindo que uma instrução subsequente atribua os 16 bits mais baixos da constante. que é 61 em decimal. Quase todos os loops e as instruções if são muito menores do que 216 palavras. Elas utilizam o último formato de instrução do MIPS. carrega 0s nos 16 bits superiores e. Eles são encontrados em loops e em instruções if. é: qual registrador? A resposta vem da observação de como os desvios condicionais são usados. Assim. chamado tipo J.10  Endereçamento no MIPS para operandos imediatos e endereços de 32 bits 103 Detalhamento:  a criação de constantes de 32 bits requer cuidado.Exit # vai para Exit se $s0 ≠ $s1 é gerada nesta instrução. a instrução de desvio condicional precisa especificar dois operandos além do endereço de desvio. podemos desviar dentro de ±215 palavras da instrução atual se usarmos o PC como o registrador a ser somado ao endereço. portanto. de modo que costumam desviar para uma instrução próxima. j 10000 # vai para a posição 10000 poderia ser gerada neste formato (normalmente. é usado pelo montador em conjunto com lui para criar constantes de 32 bits. Como o contador de programa (PC) contém o endereço da instrução atual. A questão. Por exemplo. A instrução addi copia o bit mais à esquerda do campo imediato de 16 bits da instrução para todos os 16 bits mais altos de uma palavra.6. portanto. isso é um pouco mais complicado. O OR immediate lógico. Assim. que é muito pequeno para ser uma opção real nos dias atuais. de modo que uma instrução de desvio pudesse calcular o seguinte: Contador de programa = Registrador + Endereçodedesvio Essa soma permite que o contador de programa tenha até 232 bits e ainda possa usar desvios condicionais. Uma alternativa seria especificar um registrador que sempre seria somado ao endereço de desvio. da Seção 2. deixando apenas 16 bits para o endereço de desvio: Se os endereços do programa tivessem de caber nesse campo de 16 bits. de modo que o PC é a opção ideal. cerca de metade de todos os desvios condicionais nos benchmarks SPEC vão para locais a menos de 16 instruções de distância. como veremos): em que o valor do código da operação de jump é 2 e o endereço destino é 10000. Ao contrário da instrução de jump. bne $s0. Endereçamento em desvios condicionais e jumps As instruções de jump no MIPS possuem o endereçamento mais simples possível. nenhum pro- grama poderia ser maior do que 216. 2. solucionando o problema do tamanho do endereço de desvio.$s1. que consiste em 6 bits para o campo de operação e o restante dos bits para o campo de endereço. . constante na instrução. Como na maioria dos computadores atuais. instruções de jump-and-link chamam procedimentos que não têm motivo para estarem próximos à chamada e. o endereço MIPS. Assim. Logo.12) precisam ter cuidado para evitar colocar um programa entre um limite de endereços de 256MB (64 milhões de instruções). na realidade. deixando os 4 bits mais significativos inalterados. o MIPS utiliza o endereçamento relativo ao PC para todos os desvios condicionais. 4 bits precisam vir de outro lugar para os jumps. por isso.104 Capítulo 2  Instruções: A Linguagem de Máquina endereçamento relativo ao PC  Essa forma de endereçamento de desvio é denominada endereçamento relativo ao PC. em vez da instrução atual (PC). a fim de que aponte para a próxima instrução. A instrução de jump do MIPS substitui apenas os 28 bits menos significativos do PC. a fim de carregar o endereço de 32 bits inteiro em um registrador.7 foi compilado para este código em assembly do MIPS: EXEMPLO Se consideramos que o loop inicia na posição 80000 da memória. Por outro lado. normalmente utilizam outras formas de endereçamento. caso contrário. o campo de 16 bits pode se desviar para uma distância quatro vezes maior. interpretando o campo como um endereço relativo à palavra. é conveniente que o hardware incremente o PC desde em que o endereço é a soma do contador de programa (PC) e uma cedo. em vez de um endereço relativo a byte. pois o destino dessas instruções provavelmente estará próximo do desvio. Um regime de endereçamento Conforme veremos no Capítulo 4. Como todas as instruções MIPS possuem 4 bytes de extensão. usando o formato do tipo J para instruções de jump e jump-and-link. o MIPS aumenta a dis- tância do desvio fazendo com que o endereçamento relativo ao PC se refira ao número de palavras até a próxima instrução. o campo de 26 bits nas instruções de jump também é um endereço de palavra. é relativo ao endereço da instrução seguinte (PC + 4). Detalhamento:  como o contador de programa (PC) utiliza 32 bits. significando que representa um endereço de 28 bits. a arquitetura MIPS oferece endereços longos para chamadas de procedimento. O loader e o link-editor (Seção 2. De modo semelhante. um jump precisa ser substituído por uma instrução de jump register precedida por outras instruções. Logo. Mostrando o offset do desvio em linguagem de máquina O loop while da Seção 2. no lugar do número de bytes. qual é o código de RESPOSTA máquina do MIPS para esse loop? As instruções montadas e seus endereços são: . 1. $s1. em que o endereço de jump são os 26 bits da ins- trução concatenados com os bits mais altos do PC . A Figura 2. Estas instruções substituem o desvio condicional com endereço curto: RESPOSTA Resumo dos modos de endereçamento no MIPS Múltiplas formas de endereçamento geralmente são denominadas modos de endereça. A instrução de salto na última linha utiliza o endereço completo (20000 × 4 = 80000). em que o operando é uma constante dentro da própria instrução 2. especificando o destino do desvio em relação à instrução seguinte (8 + 80016). a quantidade de bytes em uma palavra. no qual o endereço de desvio é a soma do PC e uma constante na instrução 5. e inverte a condição de modo que o desvio decida para onde fazer o jump. EXEMPLO beq $s0. L1 substitua-o por um par de instruções que ofereça uma distância de desvio muito maior. em que o operando está no local de memória cujo endereço é a soma de um registrador e uma constante na instrução 4. ocasio. Endereçamento pseudodireto. Endereçamento relativo ao PC. A maioria dos desvios condicionais é feita para um local nas proximidades. modo de endereçamento  Um dos mento. Interface nalmente. Endereçamento imediato. Endereçamento em registrador. no qual o operando é um registrador 3. de modo que os endereços das palavras sequenciais diferem em 4. 2. A instrução bne na quarta linha acrescenta 2 palavras ou 8 bytes ao endereço da instrução seguinte (80016). Os modos de endereçamento do MIPS são os seguintes: operandos e/ou endereços. correspondente ao rótulo Loop. Desviando para um lugar mais distante Dado um desvio em que o registrador $s0 é igual ao registrador $s1. O montador vem ao auxílio como fez com hardware/ endereços ou constantes grandes: ele insere um jump incondicional para o destino do software desvio. mas. e não em relação à instrução de desvio (12 + 80012) ou ao uso do endereço de destino completo (80024).10  Endereçamento no MIPS para operandos imediatos e endereços de 32 bits 105 Lembre-se de que as instruções do MIPS possuem endereços em bytes.18 mostra como os operandos são identificados para cada modo de diversos regimes de endereçamento delimitados por seu uso variado de endereçamento. Endereçamento de base ou deslocamento. eles se desviam para um ponto mais distante do que pode ser representado nos 16 bits da instrução de desvio condicional. O processo de extensão do conjunto de instruções permite que as arquiteturas se expandam de modo que o software possa prosseguir de forma compatível para a próxima geração da arquitetura. Decodificando a linguagem de máquina Às vezes. enquanto o operando para o modo 2 é um registrador. Para o modo 1. Observe que as versões de load e store acessam bytes. Essas extensões foram a resposta às necessidades de software software para programas maiores. Os modos 4 e 5 endereçam as instruções na memória. você é forçado a usar engenharia reversa na linguagem de máquina para criar o código assembly original. Os operandos estão sombreados na figura. com o modo 4 adicionando um endereço de 16 bits deslocado à esquerda em 2 bits ao PC. Add.18  Ilustração dos cinco modos de endereçamento do MIPS. A Figura 2. quase todos os microprocessadores (incluindo o MIPS) possuem extensões de endereço hardware/ de 64 bits (ver o Apêndice E). por exemplo. halfwords ou palavras. Um exemplo é quando se examina um dump de memória. Observe que uma única operação pode usar mais de um modo de endereçamento. Interface Embora tenhamos mostrado a arquitetura MIPS como tendo endereços de 32 bits. utiliza um endereçamento imediato (addi) e por registrador (add). Essa figura ajuda na tradução manual entre o assembly e a linguagem de máquina. O operando do modo 3 está na memória. .106 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2. e o modo 5 concatenando um endereço de 26 bits deslocado à esquerda em 2 bits com os 4 bits superiores do PC.19 mostra a codificação dos campos para a linguagem de máquina do MIPS. o operando é formado pelos 16 bits da própria instrução. no Capítulo 3. Bltz/gez é o opcode para quatro instruções encontradas no Apêndice B: bltz. coluna 1. Logo. é definido na Figura 3.19  Codificação de instruções do MIPS. O valor de ponto flutuante na linha 2. O Apêndice B abrange todas as instruções. bltzal e bgezal. Essa notação indica o valor de um campo por linha e por coluna. subtract na linha 4 e coluna 2 da seção inferior significa que o campo funct (bits 5-0) da instrução é 100010bin e o campo op (bits 31-26) é 000000bin. . 2.10  Endereçamento no MIPS para operandos imediatos e endereços de 32 bits 107 FIGURA 2. enquanto o Capítulo 3 descreve as instruções indicadas em mnemônicos usando cor. Este capítulo descreve as instruções indicadas com nome completo usando cor. Por exemplo. a parte superior da figura mostra load word na linha número 4 (100bin para os bits 31-29 da instrução) e a coluna número 3 (011bin para os bits 28-26 da instrução). bgez. de modo que o valor correspondente do campo op (bits 31-26) é 100011bin.18. Formato R na linha 0 e coluna 0 (op = 000000bin) é definido na parte inferior da figura. 19 determina a operação de uma instrução no Formato R. $a7 e $s0. abordados no próximo capítulo. FIGURA 2. listado na Figura 2. Endereços entre 0 e 256K – 1 3. os bits 5-3 são 100 e os bits 2-0 são 000. Endereços desde cerca de 128K antes do desvio até cerca de 128K depois . Endereços desde cerca de 32K antes do desvio até cerca de 32K depois 4. Nesse caso. A Figura 2.20 mostra todos os formatos de instrução do MIPS. 15 para rt. $a1. A Figu- ra 2. Vamos reformatar a instrução binária para campos no Formato R. essa é uma instrução no Formato R. Decodificamos as demais instruções examinando os valores de campo.19. quando os bits 31-29 são 000 e os bits 28-26 são 000. Verifique I. Qual é o intervalo de endereços para desvios condicionais no MIPS (K = 1024)? você mesmo 1. Consultando a Figura 2.20: A parte inferior da Figura 2.1 mostra o assembly do MIPS revelado neste capítulo. o que significa que esse padrão binário representa uma instrução add. a outra parte ainda oculta das instruções MIPS trata principalmente de aritmética e números reais. $t7 A Figura 2.20  Formatos das instruções do MIPS. Endereços entre 0 e 64K – 1 2. 16 para rd (shamt não é usado). podemos mostrar a instrução assembly: add $s0.108 Capítulo 2  Instruções: A Linguagem de Máquina Decodificando a linguagem de máquina EXEMPLO Qual é a instrução em assembly correspondente a esta instrução de máquina? 00af8020hexa O primeiro passo na conversão de hexadecimal para binário é encontrar os campos RESPOSTA op: Examinamos o campo op para determinar a operação.14 diz que esses números representam os registradores $a1. Os valores decimais são 5 para o campo rs. Agora. 11  Paralelismo e instruções: Sincronização 109 II. Qualquer lugar dentro de um bloco de 256M endereços. pelo menos um é de escrita. Endereços desde cerca de 128M antes do desvio até cerca de 128M depois 5. temos de saber quando os outros repórteres terminaram suas seções. Nesta seção. o custo da montagem de primitivos de sincronização básicos será muito alto e aumentará à medida que crescer a quantidade de processadores. é melhor que eles sincronizem a escrita e leitura de cada seção. Na computação. além de implementar mecanismos de sincronização mais complexos. dependendo de como os eventos ocorram. em que os resultados data race  Dois acessos à memória do programa podem mudar. sll 5. nada mais pode se interpor entre a leitura e a escrita do local da memória. Logo. Endereços entre 0 e 64M – 1 2. addi 4. A cooperação normalmente significa que algumas tarefas estão escrevendo novos valores que outras precisam ler. em que o PC fornece os 6 bits mais altos 6. A habilidade fundamental que exigimos para implementar a sincronização em um multiprocessador é um conjunto de primitivos de hardware com a capacidade de ler e modificar um local de memória atomicamente. focalizamos a implementação das operações de sincronização lock e unlock. 2. Qualquer lugar dentro de um bloco de 64M endereços. em que o PC fornece os 4 bits mais altos III. Qual é o intervalo de endereços para jump e jump-and-link no MIPS (M = 1024K)? 1. uma conclusão. de modo que ele não se preocupe se será alterado depois disso. Lock e unlock podem ser usados facilmente para criar regiões nas quais apenas um único processador possa operar. . Suponha que um repórter precise ler todas as seções anteriores antes de escrever local. lembre-se da analogia citada no Capítulo 1 dos oito repórteres escrevendo de threads diferentes para o mesmo um artigo. Para saber quando uma tarefa terminou de escrever. para que a conclusão seja coerente com o que é impresso nas seções anteriores. e eles ocorrem um após o outro. Opcode indefinido: não existe uma instrução válida que corresponda a 0. os mecanismos de sincronização normalmente estão embutidos com as rotinas de software em nível de usuário que contam com as instruções de sincronização fornecidas pelo hardware. formam uma data race se eles forem Por exemplo. Formato R 3. j 2. 2. Ou seja. Sem essa capacidade. Endereços entre 0 e 256M – 1 3. Se elas não estiverem sincronizadas. de modo que é seguro que outra tarefa leia. mfc0 6. elas precisam de sincronização. Endereços desde cerca de 32M antes do desvio até cerca de 32M depois 4. Ou seja. haverá um perigo de data race. chamada exclusão mútua.11  Paralelismo e instruções: Sincronização A execução paralela é mais fácil quando as tarefas são independentes. Qual é a instrução em assembly do MIPS correspondente à instrução de máquina com o valor 0000 0000hexa? 1. mas frequentemen- te elas precisam cooperar. No segundo caso. Para ver como usar isso a fim de montar uma primitiva de sincronização básica. e duas trocas simultâneas serão ordenadas pelo hardware. retornando 0. o conteúdo de $s4 e o local de memória especificado por $s1 foram trocados atomicamente. e um store especial. em que o valor 0 é usado para indicar que o bloqueio está livre e 1 é usado para indicar que o bloqueio está indisponível.110 Capítulo 2  Instruções: A Linguagem de Máquina Existem diversas formulações alternativas das primitivas de hardware básicas. com o endereço de memória correspondendo ao bloqueio. No MIPS. A implementação de uma única operação de memória atômica apresenta alguns desafios no projeto do processador. Por exemplo. A chave para o uso da primitiva de troca para implementar a sincronização é que a operação seja atômica: a troca é indivisível. considere dois processadores que tentam cada um realizar a troca simul- taneamente. o script retorna 0 em $t0. O valor retornado da instrução de troca é 1 se algum outro processador já tiver solicitado acesso. Como o load vinculado retorna o valor inicial. mas em vez disso esperam que as primitivas sejam usadas pelos programadores de sistemas para montar uma biblioteca de sincronização. Em geral. Assim. que troca um valor em um registrador por um valor na memória. o valor também é trocado para 1. O par de instruções é efetivamente atômico se parecer que todas as outras operações executadas por qualquer processador ocorreram antes ou depois do par. nenhum outro processador pode alterar o valor entre o par de instruções. os arquitetos não esperam que os usuários empreguem as primitivas de hardware básicas. Uma alternativa é ter um par de instruções em que a segunda instrução retorna um valor mostrando se o par de instruções foi executado como se fosse atômico. essa race é interrompida. impedindo que qualquer outra troca em outro processador também recupere um 0. pois exatamente um dos processadores realizará a troca primeiro. que está em um registrador. chamado store condicional. e o store condicional retorna 1 somente se tiver sucesso. O store condicional é definido para armazenar o valor de um registrador na memória e alterar o valor desse registrador para 1 se tiver sucesso e para 0 se falhar. junto com algum modo de dizer se a leitura e escrita foram realizadas atomicamente. Uma operação típica para a montagem de operações de sincronização é a troca atômica ou swap atômico. e o segundo processador retornará 1 quando realizar a troca. a sequência a seguir implementa uma troca atômica no local de memória especificado pelo conteúdo de $s1: Ao final dessa sequência. suponha que queremos montar um bloqueio simples. Um proces- sador tenta definir o bloqueio realizando uma troca de 1. esse par de instruções inclui um load especial. e 0 em caso contrário. mostrando como ela pode ser usada para montar um primitivo de sincronização básico. Essas instruções são usadas em sequência: se o conteúdo do local de memória especificado pelo load vinculado for alterado antes que ocorra o store condicional para o mesmo endereço. Vamos começar com uma primitiva de hardware desse tipo. todas oferecendo a capacidade de ler e modificar um local atomicamente. fazendo com que a sequência de código tente novamente. É impossível que dois processadores tentando definir a variável de sincronização dessa maneira pensem que definiram a variável simultaneamente. chamado load vinculado. quando um par de instruções é efetivamente atômico. então o store condicional falha. um processo que normalmente é complexo e intricado. pois requer uma leitura e uma escrita na memória em uma única instrução ininterrupta. Sempre que um processador intervém e modifica o valor na memória entre as instruções ll e sc. . porém. A Figura 2. Uma vantagem do mecanismo de load vinculado/store condicional é que ele pode ser usado para montar outras primitivas de sincronização. Alguns sistemas combinam essas etapas para reduzir o tempo de tradução.12  Traduzindo e iniciando um programa 111 Detalhamento:  Embora fosse apresentada para sincronização de multiprocessador. em que o processador nunca pode completar o sc. é possível criar situações de impasse.12  Traduzindo e iniciando um programa Esta seção descreve as quatro etapas para a transformação de um programa em C. a troca atô- mica também é útil para o sistema operacional lidar com múltiplos processos em um único proces- sador. de modo que a produtividade do programador é muito mais alta. e às vezes ainda melhores. comum das instruções em assembly. somente instruções registrador-registrador podem ser permitidas com segurança. Os programas em linguagem de alto nível usam muito menos linhas de código do que o assembly. normalmente tratada como se fosse Essas instruções são conhecidas como pseudoinstruções.000 vezes na capacidade de memória em um único chip de DRAM reduz os traduzida para o formato binário. Quando threads em cooperação de um programa paralelo precisarem ser sincro- você mesmo nizados para obter um comportamento apropriado para leitura e escrita de dados compartilhados 2. o número de instruções entre o load vinculado e o store condicional deve ser pequeno. truções. para um programa executando em um computador. problemas com tamanho do programa e os compiladores otimizadores de hoje podem produzir programas em assembly quase tão bem quanto um especialista em assembly. O au. pois as memórias eram pequenas e os compiladores eram ineficientes. Como o store condicional falhará após outro store tentado ao endereço do load vinculado ou qualquer exceção. seu aparecimento em assembly simplifica a tradução e a programação. mas elas são as quatro fases lógicas pelas quais os programas passam. que são usados em alguns modelos de programação paralela. em consequência das faltas de página repetidas. Esta seção segue essa hierarquia de tradução. o montador também pode cuidar de variações comuns das instruções em linguagem de máquina como pseudoinstrução  Uma variação se fossem instruções propriamente ditas. Quando processos em cooperação em um processador precisarem ser sincronizados para a leitura e escrita de dados compartilhados 2. uma forma simbólica daquilo que a máquina entende. O hardware não precisa implementar essas ins. Em 1975. deve-se ter o cuidado na escolha de quais instruções são inseridas entre as duas instruções. Em particular. 2. caso contrário. Quando você usará primitivas como load vinculado e store condicional? Verifique 1. o store condicional também falha se o processador realizar uma troca de contexto entre as duas instruções (veja Capítulo 5). para programas grandes. linguagem simbólica. que pode ser mento de 500. Estes envolvem mais instruções entre o ll e o sc. A fim de garantir que nada interfira em um único processador. . como compare e swap atômicos ou fetch-e-in- crement atômicos. Montador Como a linguagem assembly é a interface com o software de nível superior. uma instrução propriamente dita. Além disso. Compilador O compilador transforma o programa C em um programa em assembly. arma- zenado em um arquivo no disco. muitos sistemas operacionais e montadores foram escritos em linguagem linguagem assembly Uma assembly.21 mostra a hierarquia de tradução. para minimizar a probabilidade de que um evento não relacionado ou um processador concorrente faça com que o store condicional falhe com frequência. que realizam as duas últimas etapas. $t1 O montador do MIPS também converte blt (branch on less than) para as duas instruções slt e bne mencionadas no segundo exemplo da Seção 2. estude as instruções reais do MIPS.o.DLL e . os arquivos em assembly são x. o montador do MIPS aceita esta instrução. de modo a ser executado pelo proces- sador. O MS-DOS utiliza os sufixos . bge e ble. $at. algumas etapas são puladas ou combinadas.1 e 2. $t1 # registrador $t0 recebe reg. os arquivos-objeto são x. Um programa em linguagem de alto nível é inicialmente compilado para um programa em assembly e depois montado em um módulo objeto em linguagem de máquina.LIB. apesar do limite de 16 bits das instruções imediatas. encontradas nas Figuras 2. então.s. . as rotinas de biblioteca link-editadas estaticamente são x. para entender a arquitetura do MIPS e ter certeza de que obterá o melhor desempenho. O link-editor combina vários módulos com as rotinas de biblioteca para resolver todas as referências. que copia o conteúdo de um registrador para outro.5. Outros exemplos são bgt. o UNIX segue uma convenção de sufixo para os arquivos: os arquivos-fonte em C são chamados x. e os arquivos executáveis.EXE para indicar a mesma coisa.so. Como já dissemos. as pseudoinstruções dão ao MIPS um conjunto mais rico de instruções assembly do que é implementado pelo hardware. . o hardware do MIPS garante que o registrador $zero sempre tenha o valor 0. Assim.19.$t1 # registrador $t0 recebe 0 + reg.ASM.21  Uma hierarquia de tradução para a linguagem C. Contudo. Ou seja. Para agilizar o processo de tradução. O loader. e o pro- gramador não pode alterar o valor do registrador $zero. o montador do MIPS permite que constantes de 32 bits sejam atribuídas a um registrador.OBJ. são chamados a. sempre que o registrador $zero é utilizado. A fim de identificar o tipo de arquivo. O registrador $zero é usado para criar a instrução move em assembly. Resumindo. Como já dissemos. .C. O único custo é reservar um registrador. $t1 O montador converte essa instrução em assembly para o equivalente em linguagem de máquina da seguinte instrução: add $t0.out. Se você tiver de escrever programas em assembly. para ser usado pelo montador. coloca o código de máquina nos locais apropriados da memória. Alguns compiladores produzem módulos-objeto diretamente e alguns sistemas utilizam loaders com link-editores. ele fornece um 0. use pseudoinstruções de modo a simplificar seu trabalho.112 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2.$zero. embora ela não se encontre na arquitetura do MIPS: move $t0. . .c. como padrão. Ele também converte desvios a locais distantes para um desvio e um jump. tabela de símbolos  Uma tabela lo e endereço. por definição. O montador transforma o programa assembly em um arquivo objeto. dados e informa- ções necessárias a fim de colocar instruções corretamente na memória. como referências externas. chamado link-editor. Link-editor O que apresentamos até aqui sugere que uma única mudança em uma linha de um pro- cedimento exige a compilação e a montagem do programa inteiro. Como você poderia esperar. A tradução completa é um desperdício terrível de recursos computacionais. que são alocados para o programa inteiro. Para produzir a versão binária de cada instrução no programa em assembly. link-editor. é um programa de sistema que combina programas em Existem três etapas realizadas por um link-editor: linguagem de máquina montados de maneira independente e traduz 1. Essa repetição é um desperdício principalmente para rotinas de bibliotecas padrão. que combina nomes de rótulos aos endereços das palavras na memória O arquivo-objeto para os sistemas UNIX normalmente contém seis partes distintas: ocupados pelas instruções. mas que seja convertida facilmente para um padrão de bits. j O segmento de texto contém o código na linguagem de máquina. 3. que podem crescer ou diminuir conforme a necessidade do programa. Esses recursos são convenientes. ou dados dinâmicos.12  Traduzindo e iniciando um programa 113 Os montadores também aceitarão números em diversas bases. a tabela contém pares de símbo. quase nunca mudam. de modo que a tarefa desse programa é muito semelhante à de um editor: ele encontra os endereços antigos e os substitui pelos novos. como as rotinas de biblioteca. j As informações de depuração contêm uma descrição resumida de como os módulos foram compilados. que é uma combinação de instruções de linguagem de máquina. pois os programadores estariam com- pilando e montando rotinas que. 2. de modo que uma mudança em uma linha só exija a compilação e a montagem de um procedimento. o montador precisa determinar os endereços correspondentes a todos os rótulos. Uma alternativa é compilar e montar cada procedimento de forma independente. j A tabela de símbolos contém os rótulos restantes que não estão definidos. O link-editor utiliza a informação de relocação e a tabela de símbolos em cada módulo objeto para resolver todos os rótulos indefinidos. eles normalmente aceitam uma base mais sucinta do que o binário. Essa alternativa requer um novo programa de sistema. Essas referências ocorrem em instruções de desvio e endereços de dados. mas a tarefa principal de um montador é a montagem para código de máquina. Remendar as referências internas e externas. Além de binário e decimal. j O segmento de dados estáticos contém os dados alocados por toda a vida do programa. j O cabeçalho do arquivo objeto descreve o tamanho e a posição das outras partes do arquivo objeto. 2. que apanha todos linker  Também chamado os programas em linguagem de máquina montados independentes e os “remenda”. A próxima subseção mostra como juntar rotinas que já foram montadas.) j As informações de relocação identificam instruções e palavras de dados que dependem de endereços absolutos quando o programa é carregado na memória. ou linker.13. Colocar os módulos de código e dados simbolicamente na memória. para o depurador poder associar as instruções de máquina aos arquivos-fonte em C e tornar as estruturas de dados legíveis. Determinar os endereços dos rótulos de dados e instruções. A edição é a . todos os rótulos indefinidos para um arquivo executável. Os montadores regis- tram os rótulos utilizados nos desvios e nas instruções de transferência de dados por meio de uma tabela de símbolos. Veja a Figura 2. (O UNIX permite que os programas usem dados estáticos. Link-edição de arquivos-objeto Link-edite os dois arquivos-objeto a seguir. o montador não poderia saber onde as instruções e os dados do módulo serão colocados em relação a outros módulos. Mostre os endereços atualizados das pri- EXEMPLO meiras instruções do arquivo executável gerado. todas as referências absolutas. Ele ceto que não contém referências não resolvidas. ou linker para abreviar. “executável despido” não contém essa informação. Observe que. Mostramos as instruções em assembly só para tornar o exemplo compreensível. Se todas as referências externas forem resolvidas. que não contém referências não resolvidas. Como os arquivos foram montados isoladamente. ou seja. Cabeçalho do arquivo-objeto Nome Procedimento A Tamanho do texto 100hexa Tamanho dos dados 20 hexa Segmento de texto Endereço Instrução 0 lw $a0. 0($gp) 4 jal 0 … … Segmento de dados 0 (X) … … Informações de Endereço Tipo de instrução Dependência relocação 0 lw X 4 jal B Tabela de símbolos Rótulo Endereço X – B – Cabeçalho do arquivo-objeto Nome Procedimento B Tamanho do texto 200 hexa Tamanho dos dados 30 hexa . precisam ser relocadas a fim de refletir seu verdadeiro local. Um portanto. ex- arquivo-objeto. Lembre-se de que a Figura 2. na realidade. É possível ter arquivos parcialmente pode conter tabelas de símbolos link-editados. Quando o link-editor coloca um módulo na memória. como rotinas de biblioteca. O uso de um link-editor faz sentido porque é muito mais rápido remendar o código do que recompilá-lo e remontá-lo. Normalmente. nos arquivos-objeto. as instruções seriam números. e informações de depuração. As informações de relocação podem ser incluídas para o loader. resultam em arquivos-objeto. arquivo executável  Um programa O link-editor produz um arquivo executável que pode ser executado em um compu- funcional no formato de um tador. esse arquivo possui o mesmo formato de um arquivo-objeto.13 mostra a convenção do MIPS para alocação de programas e dados na memória. que ainda possuem endereços não resolvidos e.114 Capítulo 2  Instruções: A Linguagem de Máquina origem do nome “link-editor”. destacamos os endereços e símbolos que pre- cisam ser atualizados no processo de link-edição: as instruções que se referem a endereços dos procedimentos A e B e as instruções que se referem aos endereços das words de dados X e Y. endereços de memória que não são relativos a um registrador. o link-editor em seguida determina os locais da memória que cada módulo ocupará. 13. de modo que o endereço inicial para o texto do procedimento B é 40 0100hexa e seus dados começam em 1000 0020hexa . Cabeçalho do arquivo executável Tamanho do texto 300hexa Tamanho dos dados 50hexa Segmento de texto Endereço Instrução 0040 0000hexa lw $a0. 2. 8000hexa($gp) 0040 0004hexa jal 40 0100hexa … … 0040 0100hexa sw $a1.12  Traduzindo e iniciando um programa 115 Segmento de texto Endereço Instrução 0 sw $al. O cabeçalho do arquivo-objeto para o procedimento A diz que seu texto possui 100hexa bytes e seus dados possuem 20hexa bytes. Pela Figura 2. O texto do procedimento A é colocado no primeiro endereço e seus dados no segundo. 0($gp) 4 jal 0 … … Segmento de dados 0 (Y) … … Informações de Endereço Tipo de instrução Dependência relocação 0 sw Y 4 jal A Tabela de símbolos Rótulo Endereço Y – A – O procedimento A precisa encontrar o endereço para a variável cujo rótulo é X a fim de colocá-lo na instrução load e encontrar o endereço do procedimento B para colocá-lo RESPOSTA na instrução jal. 8020hexa($gp) 0040 0104hexa jal 40 0000hexa … … Segmento de dados Endereço 1000 0000hexa (X) … … 1000 0020hexa (Y) … … . O procedimento B precisa do endereço da variável cujo rótulo é Y para a instrução store e o endereço do procedimento A para sua instrução jal. sabemos que o segmento de texto começa no endereço 40 0000hexa e o segmento de dados em 1000 0000hexa. De modo seme- lhante. e o jal em 40 0104hexa recebe 40 0000hexa (o endereço do procedimento A) em seu campo de endereço. Os jal são fáceis porque utilizam o endereçamento pseudodireto. a rotina de partida termina o programa com uma chamada ao sistema exit. Este exemplo utiliza o ponteiro global como registrador de base. Desvia para uma rotina de partida. Detalhamento:  Lembre-se de que as instruções MIPS são alinhadas na palavra. Assim. O cabeçalho do arquivo objeto para o procedimento A diz que seu texto é 100hexa bytes e seus dados 20hexa bytes.13 também mostra que o segmento de texto começa no endereço 40 0000hexa e o segmento de dados no 1000 0000hexa . texto e de dados. que copia os parâmetros para os registradores de argumento e chama a rotina principal do programa. Logo.4 no Apêndice B descrevem os link-editores e os loaders com mais detalhes. Embora essa técnica estática seja o modo mais rápido de chamar rotinas de biblioteca. 6. Os endereços de load e store são mais difíceis. Para obter o endereço 1000 0000hexa (o endereço da palavra X). Lê o cabeçalho do arquivo executável para determinar o tamanho dos segmentos de esteja pronto para ser executado. 5. Temos dois tipos aqui: 1. O jal no 40 0004hexa recebe 40 0100hexa (o endereço do procedimento B ) em seu campo de endereço. então o começo do endereço do texto do procedimento B é 40 0100hexa .13 mostra que $gp é inicializado com 1000 8000hexa .116 Capítulo 2  Instruções: A Linguagem de Máquina A Figura 2. de modo que 1. A Figura 2. Ele usa o campo de tipo de instrução para saber o formato do endereço a ser editado. o sistema operacional o lê para a memória loader  Um programa de sistema e o inicia. colocamos 8000hexa no campo de endereço da instrução lw. no endereço 40 0000hexa . Dinamically Linked Libraries (DLLs) A primeira parte desta seção descreve a técnica tradicional para a link-edição de bibliotecas antes de o programa ser executado. 4. de modo que jal remove os dois bits da direita para aumentar a faixa de endereços da instrução. Copia os parâmetros (se houver) do programa principal para a pilha. e seus dados começam em 1000 0020hexa . O texto do procedimento A é colocado no primeiro endereço e seus dados no segundo. Loader Agora que o arquivo executável está no disco. Agora. As Seções B.3 e B. ele usa 26 bits para criar um endereço de byte de 28 bits. o endereço real nos 26 bits inferiores da instrução jal neste exemplo é 10 0040hexa . Cria um espaço de endereçamento grande o suficiente para o texto e os dados. 3. o link-editor atualiza os campos de endereço das instruções. Copia as instruções e os dados do arquivo executável para a memória. colocamos 8020hexa no campo de endereço da instrução sw no endereço 40 0100hexa para obter o endereço 1000 0020hexa (o endereço da palavra Y). O loader segue estas etapas nos sistemas UNIX: que coloca o programa-objeto na memória principal. pois são relativos a um regis- trador de base. em vez de 40 0100hexa . 2. Quando a rotina principal retorna. ela possui algumas desvantagens: . 2. Inicializa os registradores da máquina e define o stack pointer para o primeiro local livre. a biblioteca padrão da linguagem C possui 2. Essa observação levou à versão da link-edição de procedimento tardio das DLLs. (b) As etapas para encontrar a rotina. FIGURA 2. com uma entrada por rotina não local. quando apenas algumas são chamadas durante a execução do programa.22 mostra a técnica. o programa link-editado estaticamente continua usando a versão antiga. Conforme veremos no Capítulo 5. dos procedimentos não locais e seus nomes. j Ela carrega todas as rotinas na biblioteca que são chamadas de qualquer lugar no executável. . Essas entradas fictícias contêm. esse truque conta com um certo nível de indireção. A biblioteca pode ser grande em relação ao programa.22  DLL por meio da link-edição de procedimento tardio. um jump indireto. 2. nas quais as rotinas Dynamically Linked Libraries da biblioteca não são link-editadas e carregadas até que o programa seja executado. Se uma nova versão da biblioteca for lançada para reparar os erros ou dar suporte a novos dispositivos de hardware. A Figura 2. o sistema operacional pode evitar copiar a rotina desejada remapeando-a por meio do gerenciamento de memória virtual. o loader executa- va um link-editor dinâmico. Essas desvantagens levaram às Dynamic Linked Libraries (DLLs).5MB. Tanto (DLLs)  Rotinas de bit que são o programa quanto as rotinas da biblioteca mantêm informações extras sobre a localização vinculadas a um programa durante a execução. no qual cada rotina só é link-editada depois de chamada. (a) Etapas para a primeira vez em que uma chamada é feita à rotina da DLL. usando as informações extras no arquivo para descobrir as bibliotecas apropriadas e atualizar todas as referências externas. Como muitas inovações em nosso campo. Na versão inicial das DLLs.12  Traduzindo e iniciando um programa 117 j As rotinas de biblioteca se tornam parte do código executável. A desvantagem da versão inicial das DLLs era que ela ainda link-editava todas as rotinas da biblioteca que poderiam ser chamadas. cada uma. por exemplo. mesmo que essas chamadas não sejam executadas. Ela começa com as rotinas não locais chamando um conjunto de rotinas fictícias no final do programa. remapeá-la e link-editá-la são puladas em chamadas subsequentes. O programa em Java agora está pronto para ser executado no interpretador. o programa chama a entrada fictícia e segue o jump indireto. as DLLs exigem espaço extra para as informações necessárias à link-edição dinâmica. Elas realizam muito trabalho extra na primeira vez em que uma rotina é chamada. Resumindo. Java foi inventada com objetivos diferentes. pode executar os byte- programa que interpreta os codes Java.15 no site). remapeia essa rotina e altera o endereço do desvio indireto. O Microsoft Windows conta bastante com as DLLs dessa forma e esse também é um modo normal de executar programas nos sistemas UNIX atuais. Em vez de compilar para assembly de um computador de destino. que compila os métodos seletivamente para a linguagem nativa da máquina em que está executando. chamado Java Virtual Machine (JVM). mas não exigem que as bibliotecas inteiras sejam copiadas ou link-editadas.23  Uma hierarquia de tradução para Java. Um programa em Java primeiro é compilado para uma versão binária dos bytecodes Java. Um interpretador é um programa que simula um conjunto de instruções. Esse conjunto de instruções foi criado para ser próximo da em um conjunto de instruções linguagem Java. ele retorna ao local de chamada original. Assim como o compilador C. chamado Java Virtual Machine (JVM – máquina virtual Java). Quando a rotina termina. Observe que o retorno da biblioteca não realiza trabalho extra. é possível executar programas Java da mesma forma que programas C. no qual a ênfase está no tempo de execução rápido para um programa voltado a uma arquitetura específica. Iniciando um programa Java A discussão anterior captura o modelo tradicional de execução de um programa. Praticamente nenhuma elaborado para ser interpretado. No entanto. pois ou a tradução é tão simples que o compilador preenche os endereços ou a JVM os encontra durante a execução.118 Capítulo 2  Instruções: A Linguagem de Máquina Na primeira vez em que a rotina da biblioteca é chamada. . Para conseguir melhor desempenho. exemplo. FIGURA 2. ou mesmo para uma implementação específica dessa arquitetura. A Figura 2. Por bytecodes Java. o compilador Java verifica os tipos dos dados e produz a operação apropriada a cada tipo. escritas (ver Seção 2. com todos os endereços definidos pelo compilador. Os programas em Java são distri- buídos na versão binária desses bytecodes. Depois disso. O loader com link-editor encontra a rotina desejada. de modo a apontar para essa rotina. sem os desvios extras. Não é necessária uma etapa de montagem separada. otimização é realizada. Na verdade. de modo que essa etapa de compilação seja trivial. Java Virtual Machine (JVM) O Um interpretador Java.23 mostra as etapas típicas de tradução e execução para os programas em Java. Java é compilado bytecode Java  Instruções que primeiro para instruções fáceis de interpretar: o conjunto de instruções do bytecode Java formam programas em Java. Ele aponta para o código que coloca um número em um registrador para identificar a rotina de biblioteca desejada e depois desvia para o loader com link-editor dinâmico. ele desvia para ela. a JVM pode chamar o compilador Just-In-Time (JIT). Um deles era funcionar rapidamente e de forma segura em qualquer computador. mas executam somente um desvio indireto depois disso. mesmo que isso pudesse aumentar o tempo de execução. a chamada para rotina de biblioteca desvia indiretamente para a rotina. Depois. o simulador do MIPS usado com este livro é um interpretador. A JVM link-edita os métodos desejados na biblioteca Java enquanto o programa está sendo executado. de modo que os programas Java computador. Qual das vantagens de um interpretador em relação a um tradutor você acredita que tenha Verifique sido mais importante para os criadores do Java? você mesmo 1. A Seção 2. dos bytecodes Java. Nesta seção. deduzimos o código do MIPS a partir de dois procedimentos escritos em C: um para trocar elementos do array e outro para ordená-los. seguimos estas etapas gerais: 1. em tudo desde telefones celulares até navegadores da Internet. as máquinas virtuais Java são encontradas em centenas de milhões de dispositivos. de modo que os compiladores possam fazer mais.13  tudo isso Um perigo de mostrar o código em assembly em partes é que você não terá ideia de como se parece um programa inteiro em assembly. A fim de preservar a portabilidade e melhorar a velocidade de execução. Esses compiladores Just-In-Time (JIT) normalmente traçam o compilador Just-In-Time perfil do programa em execução para descobrir onde estão os métodos “quentes”. Código-objeto menor 4. Preservar registradores durante a chamada do procedimento. Esse equilíbrio para o código nativo do entre interpretação e compilação evolui com o tempo. traduzindo os tando. . durante a execução. A disponibilidade das máquinas virtuais Java em software significou que muitos puderam escrever e executar programas Java pouco tempo depois que o Java foi anunciado.13  Um exemplo de ordenação em C para juntar tudo isso 119 A vantagem da interpretação é a portabilidade.24. mas um fator de atraso de 10 vezes. de segmentos de código interpretados modo que possa ser executado mais rapidamente cada vez que for executado. em comparação com os programas C compilados tradicionalmente. A desvantagem da interpretação é o desempenho fraco. Melhores mensagens de erro 3. Produzir código para o corpo do procedimento. Esse procedimento simplesmente troca os conteúdos de duas posições de memória. e os pesquisadores inventam melhores meios de compilar Java durante a execução. Facilidade de escrita de um interpretador 2. Independência de máquina Um exemplo de ordenação em C para juntar 2. À medida que os computadores ficam mais rápidos. 2. A parte compilada é salva para a próxima vez em que o programa for executado. a fase seguinte do desenvolvimento do Java foram compiladores que traduziam enquanto o programa es- tava sendo executado. executados com frequência sofrem muito pouco com o trabalho extra da interpretação. Alocar registradores a variáveis do programa. Os avanços incríveis no desem- penho dos anos 80 e 90 do século passado tornaram a interpretação viável para muitas aplicações importantes. O procedimento swap Vamos começar com o código para o procedimento swap na Figura 2.15 do CD contém muito mais detalhes sobre a implementação do Java. tornou o Java pouco atraente para algumas aplicações. 3. Ao traduzir de C para assembly manualmente. 2. e depois (JIT)  O nome normalmente dado a um compilador que opera os compilam para o conjunto de instruções nativo em que a máquina virtual está execu. Hoje. da JVM e dos compiladores JIT. a lacuna de desempenho entre Java e C ou C + + está se fechando. 24  Um procedimento em C que troca o conteúdo de duas posições de memória. Esquecer que os endereços de palavras sequenciais diferem em 4. lemos v[k] para $t1. por isso. na realidade. A única outra variável é temp. Alocação de registradores para swap Como mencionamos anteriormente na Seção 2. precisamos multi- plicar o índice k por 4 antes de somá-lo ao endereço. Lembre-se de que o endereço de memória para o MIPS refere-se ao endereço em bytes. armazenamos $t0 e $t2 nos endereços trocados: .120 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2. pois swap é um procedimento folha (veja seção “Procedimentos aninhados”). v[k] = v[k + 1]. estão afastadas por 4 bytes. Código do corpo do procedimento swap As linhas restantes do código em C do swap são temp = v[k]. Esta subseção utiliza esse procedimento em um exemplo de ordenação. o primeiro passo é obter o endereço de v[k] multiplicando k por 4 por meio de um des- locamento à esquerda por 2: Agora. Essa alocação de regis- tradores corresponde às declarações de variável na primeira parte do procedimento swap da Figura 2. que associamos com o registrador $t0. a convenção do MIPS sobre pas- sagem de parâmetros é usar os registradores $a0 .8. v e k. concluindo com a junção de todas as partes. Esta seção descreve o procedimento swap nessas três partes. $a2 e $a3 . Como swap tem apenas dois parâmetros. eles serão encontrados nos registradores $a0 e $a1. em vez de 1. v[k + 1] = temp. as palavras. $a1 . e.24. é um erro comum na programação em assembly. Logo. Logo. e depois v[k+1] somando 4 a $t1: Agora. vamos experimentar um segundo exemplo. Código para o corpo do procedimento sort O corpo do procedimento consiste em dois loops for aninhados e uma chamada a swap que inclui parâmetros. apresentamos esse procedimento em várias etapas.13  Um exemplo de ordenação em C para juntar tudo isso 121 Até agora. Alocação de registradores para sort Os dois parâmetros do procedimento sort. A fim de facilitar o acompanhamento. Vamos desvendar o código de fora para o meio. O que está faltando é o código para preservar os registradores salvos usa- dos dentro do swap. O primeiro passo de tradução é o primeiro loop for: . e alocamos o regis- trador $s0 a i e o registrador $s1 a j. Como não estamos usando registradores salvos nesse procedimento folha.26  Um procedimento em C que realiza uma ordenação no array v. estamos prontos para a rotina inteira. identificamos na Figura 2. maior. FIGURA 2. A Figura 2. que inclui o rótulo do procedimento e o jump de retorno. 2. Nesse caso.25  Código assembly do MIPS do procedimento swap na Figura 2. Esse programa ordena um array de inteiros. alocamos registradores e escrevemos o código de modo a realizar as operações do procedimento. mas não a mais rápida. estão nos registradores de parâmetro $a0 e $a1.26 mostra a versão em C do programa. usando ordenação por trocas. Mais uma vez. montaremos uma rotina que chama o procedi- mento swap.24. que é uma das mais simples. O procedimento sort Para garantir que você apreciará o rigor da programação em assembly. O procedimento swap completo Agora. FIGURA 2. não há nada para preservar. concluindo com o procedimento completo.25 cada bloco de código com sua finalidade no procedimento. v e n. ver seção “Montador”. caso contrário. anteriormente neste capítulo. Como queremos testar se $s0>$a1. a última parte da instrução for: O loop deverá terminar se i<n não for verdadeiro ou. ele é 0. Voilà! Os exercícios exploram a escrita de código mais rápido para loops semelhantes. então. a primeira parte da instrução for: (Lembre-se de que move é uma pseudoinstrução fornecida pelo montador para a con- veniência do programador em assembly. A instrução set on less than atribui 1 ao registrador $t0 se $s0<$a1. Esse teste utiliza duas instruções: O final do loop só desvia de volta para o teste do loop: O código da estrutura do primeiro loop for é.122 Capítulo 2  Instruções: A Linguagem de Máquina Lembre-se de que a instrução for em C possui três partes: inicialização. O segundo loop for se parece com o seguinte em C: A parte de inicialização desse loop novamente é uma instrução: O decremento de j no final do loop também tem uma instrução: .) Também é necessária apenas uma instrução para incrementar i. É necessária apenas uma instrução para inicializar i como 0. em outras palavras. deverá terminar se i ≥ n . teste de loop e incremento da iteração. desviamos se o registrador $t0 for zero. termina se v[j] ≤ v[j + 1] . de modo que as duas instruções do teste de saída são O final do loop desvia de volta para o teste do loop interno: Combinando as partes. Se não pular. Saímos do loop se a condição falhar. somamos 4 ao endereço no registrador $t2 para obter v[j+1]: O teste de v[j] ≤ v[j + 1] é o mesmo que v[j + 1] ≥ v[j] . 2. de modo que o primeiro teste precisa terminar o loop se falhar (j<0): Esse desvio pulará o segundo teste de condição.13  Um exemplo de ordenação em C para juntar tudo isso 123 O teste do loop possui duas partes. criamos o endereço multiplicando j por 4 (pois precisamos de um endereço em bytes) e somamos ao endereço base de v: Agora. lemos o conteúdo de v[j]: Como sabemos que o segundo elemento é exatamente a palavra seguinte. então j ≥ 0 . O segundo teste termina se V[j]>v[j +1] não for verdadeiro. ou seja. Primeiro. a estrutura do segundo loop for se parece com o seguinte: . 124 Capítulo 2  Instruções: A Linguagem de Máquina A chamada de procedimento em sort A próxima etapa é o corpo do segundo loop for: Chamar swap é muito fácil: Passando parâmetros em sort O problema vem quando queremos passar parâmetros. enquanto o procedimento swap precisa que seus parâmetros sejam colocados nesses mesmos registradores. de modo que precisam ser salvos. Com certeza. deixando os registradores $a0 e $a1 disponíveis para a chamada de swap. temos de salvar o endereço de retorno no registrador $ra. $s1. . (Essa cópia é mais rápida do que salvar e restaurar na pilha. Uma solução é copiar os parâmetros para sort em outros registradores antes do procedimento. identificamos cada bloco de código com sua finalidade no procedimento. Neste capítulo. tendo o cuidado de substituir as referências aos registradores $a0 e $a1 nos loops for por referências aos registradores $s2 e $s3. copiamos $a0 e $a1 para $s2 e $s3durante o procedimento: Depois. $s2 e $s3. porque o procedimento sort precisa dos valores nos registradores $a0 e $a1. nove linhas do procedimento sort em C tornaram-se 35 em assembly do MIPS. pois sort é um procedimento que foi chamado por outro procedimento. O prólogo do procedimento sort. depois acrescenta um jr para retornar. O procedimento sort também utiliza os registradores salvos $s0.) Primeiro. juntamos todas as partes na Figura 2. Novamente para tornar o código mais fácil de acompanhar. é O final do procedimento simplesmente reverte todas essas instruções.27. passamos os parâmetros para swap com estas duas instruções: Preservando registradores em sort O único código restante é o salvamento e a restauração dos registradores. portanto. O procedimento sort completo Agora. Essa otimização evitaria quatro instruções neste exemplo. Essa expansão de código poderia ter um desempenho inferior se aumentasse a taxa de falhas na cache. 2.26. Detalhamento:  Uma otimização que funciona com este exemplo é a utilização de procedimen- tos inline. A desvantagem da otimização que utiliza procedimentos inline é que o código compilado seria maior se o procedimento inline fosse chamado de vários locais. ver Capítulo 5.27  Versão em assembly do MIPS para o procedimento AAAA da Figura 2.13  Um exemplo de ordenação em C para juntar tudo isso 125 FIGURA 2. o compilador copiaria o código do corpo do procedimento swap onde a chamada a swap aparece no código. Em vez de passar argumentos em parâmetros e invocar o código com uma instrução jal. . Um motivo é que a linguagem C oferece varang que permite que um ponteiro apanhe.05 x 2468 ou 123 vezes mais rápido que o código C não otimizado versus 2. compilação versus interpretação.28  Comparando desempenho. A Figura 2. A última coluna demonstra o impacto de um algoritmo melhor.3 vezes mais rápido do que o código Java interpretado para o Bubble Sort. A JVM é Sun versão 1. eles sempre decrementam o $sp de 16. e o JIT é o Sun Hotspot versão 1.28 mostra o impacto da otimização do compilador sobre o desempenho do programa de ordenação. o Quicksort vence o Bubble Sort por um fator de 50 (0. digamos.3. raramente.3. (A Seção 2. tempo de compilação. ciclos de clock.29  Desempenho de dois algoritmos de ordenação em C e Java usando interpretação e compiladores otimizadores em relação à versão C não otimizada. Mesmo comparando o programa Java interpretado na coluna 5 com o programa C compilado com as melhores otimizações na coluna 4. na realidade. .000 words com o array inicializado com valores aleatórios.4. de modo a dar espaço para todos os quatro registradores de argumento (16 bytes). contagem de instruções e CPI usando otimizações do compilador para o Bubble Sort.41).000 itens.15 do CD contém mais detalhes sobre interpretação versus compilação de Java e o código Java e MIPS para o Bubble Sort. Os programas ordenaram 100. mas O3 é a mais rápida.126 Capítulo 2  Instruções: A Linguagem de Máquina Entendendo A Figura 2. Esses programas foram executados em um Pentium 4 com clock de 3. o compilador encontra varang. lembrando que o tempo é a única medida precisa do desempenho do programa. e os algoritmos sobre o desempenho das ordenações. possivelmente porque é mais difícil amortizar o custo da compilação em runtime pelo tempo de execução mais curto. A quarta coluna mos- tra que o programa C otimizado é 8. Observe que o código não otimizado tem o melhor CPI. FIGURA 2. ele copia os quatro registradores de argumento para os quatro locais reservados na pilha. O uso do compilador JIT torna o programa em Java 2.13 mais rápido do que o código C mais otimizado. de modo que. Detalhamento:  Os compiladores MIPS sempre reservam espaço na pilha para os argumentos. contagem de instruções e o desempenho CPI.1 vezes mais rápido do que o programa em C não otimizado e dentro de um fator de 1. o terceiro argumento de um procedimento. A última coluna mostra a vantagem no desempenho do Quicksort em relação ao Bubble Sort para cada linguagem e opção de execução. oferecendo um aumento de desempenho de três ordens de grandeza quando são ordenados 100.20. Esses programas foram executados no mesmo sistema da Figura 2.1. caso precisem ser armazenados.28.06GHz e um barramento de 533MHz com 2GB de memória SDRAM DDR PC2100.1.29 compara o impacto das linguagens de programação. FIGURA 2. Quando. Ele usava o Linux versão 2. e a otimização O1 tem a dos programas menor contagem de instruções.) As razões não são tão próximas para o Quicksort na coluna 5. o compilador gerará instruções MIPS para incrementar p de quatro.14   Arrays versus ponteiros Um tópico desafiador para qualquer programador novo é entender os ponteiros. significa mover o ponteiro para o próximo objeto sequencial do seu tamanho declarado. Comece multi- plicando i por 4. As declarações indicam que array e p são ponteiros para inteiros. a primeira parte do loop for. A segunda parte do loop for testa se o ponteiro está apontando além do último elemento do array. temos primeiro de obter seu endereço. clear 1. A Figura 2. clear1 usa índices. e a referência ao objeto apontando por um ponteiro é indicada por *. A com- paração entre o código assembly que usa arrays e índices de array com o código assembly que usa ponteiros fornece esclarecimentos sobre ponteiros.14 Arrays versus ponteiros 127 2.30  Dois procedimentos em C para definir um array com todos os valores iguais a zero. Incrementar um ponteiro em um. Ao final da seção. Como p é um ponteiro para inteiros. 2. enquanto clear2 usa ponteiros. para obter o endereço em bytes: Como o endereço inicial do array está em um registrador. O segundo procedimento precisa de alguma explicação para os que não estão acostumados com C. A inicialização de i. . Esta seção mostra as versões C e assembly do MIPS de dois procedimentos para zerar (clear) uma sequência de palavras na memória: uma usando índices de array e uma usando ponteiros. temos de somá-lo ao índice para obter o endereço de array[i] usando uma instrução add: FIGURA 2. é simples: Para definir array[i]como 0. o número de bytes de um inteiro MIPS. O endereço de uma variável é indicado por &. A atribuição no loop coloca 0 no objeto apontado por p. Consideramos que os dois parâmetros array e size são encontrados nos registradores $a0 e $a1.30 mostra os dois procedimentos em C. focalizando o corpo do loop e igno- rando o código de ligação do procedimento. veremos o impacto das otimizações do compilador moderno sobre esses dois procedimentos. A primeira parte do loop for em clear2 atribui o endereço do primeiro elemento do array ao ponteiro p. Versão de clear usando arrays Vamos começar com a versão que usa arrays. A finalidade desta seção é mostrar como os ponteiros são mapeados em instruções MIPS. e não endossar um estilo de programação ultrapassado. e que i é alocado ao registrador $t0. na última parte do loop for. 128 Capítulo 2  Instruções: A Linguagem de Máquina Finalmente. mas pularemos essa legalidade aqui. o ANSI C requer um teste de tamanho antes do loop. que simplesmente armazena 0 em p: Essa instrução implementa o corpo do loop. de modo que o próximo código é o incremento da iteração. O código para o segundo procedi- mento começa com a atribuição do ponteiro p ao endereço do primeiro elemento do array: O código a seguir é o corpo do loop for.) Versão de clear usando ponteiros O segundo procedimento que usa ponteiros aloca os dois parâmetros array e size aos registradores $a0 e $a1 e aloca p ao registrador $t0. cada um usando 4 bytes. Como p é um ponteiro para inteiros. já vimos todas as partes do procedimento. o compilador in- crementa p de 4. . podemos armazenar 0 nesse endereço: Essa instrução é o final do corpo do loop. que muda p de modo que aponte para a próxima palavra: Incrementar um ponteiro em 1 significa mover o ponteiro para o próximo objeto sequencial em C. de modo que o próximo passo é incrementar i: O teste do loop verifica se i é menor do que size: Agora. Aqui está o código MIPS para zerar um array usando índices: (Esse código funciona desde que size seja maior que 0. O primeiro passo é calcular o endereço do último elemento de array. 2. esse código considera que size é maior do que 0.14 Arrays versus ponteiros 129 O teste do loop vem em seguida. podemos mostrar uma versão do código para zerar um array usando ponteiros: Como no primeiro exemplo. Uma versão mais rápida do código move esse cálculo para fora do loop: Comparando as duas versões de clear A comparação das duas sequências lado a lado ilustra a diferença entre os índices de array e ponteiros (as mudanças introduzidas pela versão de ponteiro estão destacadas): . Observe que esse programa calcula o endereço do final do array em cada iteração do loop. Comece multiplicando size por 4 para obter seu endereço em bytes: e depois acrescentamos o produto ao endereço inicial do array para obter o endereço da primeira word após o array: O teste do loop é simplesmente para ver se p é menor do que o último elemento de array: Com todas essas partes completadas. embora não mude. Ela mostra os programação que é orientada em torno de objetos. Essas otimizações manuais correspondem a otimizações do compilador chamadas redução de força (des- locamento em vez de multiplicação) e eliminação da variável de indução (eliminando cálculos de endereço de array dentro dos loops). porque i é incrementado e cada endereço precisa ser recalculado a partir do novo índice. a versão usando ponteiros para a memória à direita incrementa o ponteiro p diretamente. Existe um núcleo semelhante dos conjuntos de instruções para instruções aritmética-ló- gica e de transferência de dados para o MIPS e ARM. entender a tecnologia do compilador hoje é fundamental para se entender o desempenho. incluindo o Bubble Sort. em vez de ações. Os modernos compiladores com otimizações podem produzir um código dos programas muito bom para a versão usando arrays. ARM surgiu no mesmo ano em que o MIPS e seguiu filosofias semelhantes. Lembre-se de que o assunto da construção de compilador normalmente é lecionado em um curso de um ou dois semestres. bytecodes Java usados para a interpretação e o código MIPS para a versão Java de alguns ou dados versus lógica. A principal diferença é que MIPS tem mais registradores e ARM tem mais modos de endereçamento. Material avançado: Compilando 2. para a instrução slt. 2. Preparada originalmente para a Acorn RISC Machine. imediatamente antes da primeira instrução do loop.32. A versão usando ponteiros reduz as instruções executadas por iteração de 6 para 4. mais tarde modificada para Advanced RISC Machine. é executada em uma arquitetura MIPS. Detalhamento:  como mencionamos. o compilador C acrescentaria um teste para garantir que size seja maior do que 0. Entendendo As pessoas costumavam ser ensinadas a usar ponteiros em C para conseguir mais eficiên- cia do que era possível com os arrays: “Use ponteiros. . A Figura 2. de modo que nossa introdução neces- sariamente só tocará nos fundamentos. linguagem orientada a A segunda parte desta seção é para leitores interessados em ver como uma linguagem objetos  Uma linguagem de orientada a objeto. Uma maneira seria acrescentar um desvio.31 lista as semelhanças. como Java.15 no site descreve estas duas e muitas outras otimizações.130 Capítulo 2  Instruções: A Linguagem de Máquina A versão da esquerda precisa ter a “multiplicação” e a soma dentro do loop. A Seção 2. O restante desta seção está no site. com mais de três bilhões de dispositivos por ano usando ARM.15  C e interpretando Java Esta seção oferece uma breve visão geral de como o compilador C funciona e como Java é executada.16   Vida real: instruções do ARM ARM é a arquitetura de conjunto de instruções mais comum para dispositivos embutidos. dos segmentos C nas seções anteriores. como mostra a Figura 2. Ela aborda a Java Virtual Machine e os compiladores JIT. A maioria dos programadores de hoje prefere que o compilador realize o trabalho pesado. mesmo que você não consiga enten- o desempenho der o código”. Como o compilador afetará significativamente o desempenho de um computador. Por exemplo.18).16  Vida real: instruções do ARM 131 FIGURA 2. e depois atualizar um registrador com esse novo endereço.31  Semelhanças nos conjuntos de instruções ARM e MIPS. de modo que os shift com sobrescrito 1 1 são apenas uma variação de uma instrução move. Observe que o ARM não possui instrução de divisão. Os traços significam que a operação não está disponível nessa arquitetura ou não é sintetizada em poucas instruções. 2.32  Instruções ARM registrador-registrador e transferência de dados equivalente ao núcleo MIPS. Diferente do MIPS. elas são separadas por vírgulas. incluindo cálculos bastante complexos. Modos de endereçamento A Figura 2. Embora o MIPS tenha apenas três modos de endereçamento de dados simples (veja Figura 2. ARM tem um modo de endereçamento que pode deslocar um registrador por qualquer quantidade. como lsr . ARM inclui deslocamentos como parte de cada instrução de operação de dados. somá-lo aos outros registradores a fim de formar o endereço. . FIGURA 2. ARM não reserva um registrador para conter 0.33 mostra os modos de endereçamento de dados admitidos pelo ARM. ARM tem nove. Se houver várias escolhas de instruções equivalente ao núcleo MIPS. Cada instrução começa com um campo de 4 bits que determina se ele atuará como uma instrução de nenhuma operação (nop) ou como uma instrução real. Logo. enquanto TEQ utiliza OR exclusivo a fim de definir os três primeiros códigos de condição. Eles podem ser definidos em qualquer instrução aritmética ou lógica. Comparação e desvio condicional MIPS usa o conteúdo dos registradores para avaliar desvios condicionais.132 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2. Um recurso incomum do ARM é que cada instrução tem a opção de executar con- dicionalmente. e a soma define os códigos de condição. essa configuração é opcional em cada instrução. Além disso. pois ARM tem metade do número de registradores. diferente das arquiteturas anteriores.33  Resumo dos modos de endereçamento de dados. A execução condicional permite evitar que um desvio salte sobre uma instrução isolada. É preciso menos espaço de código e tempo para apenas executar uma instrução condicionalmente. e a diferença define os códigos de condição. zero. As principais dife- renças são o campo de execução condicional de 4 bits em cada instrução e o campo de registrador menor. CMP subtrai um operando do outro. ARM tem suporte para aritmética de múltiplas palavras. Recursos exclusivos do ARM A Figura 2. ARM usa os quatro bits de código de condição tradicionais armazenados na palavra de status do pro- grama: negativo. o ARM desloca o offset à esquerda 1 ou 2 bits se o tamanho dos dados for halfword ou uma palavra inteira. Uma vantagem é que esse esquema pode representar todas as potências de dois em . CMN (compare negative) soma um operando ao outro.34 mostra os formatos de instrução para ARM e MIPS. O campo imediato de 12 bits do ARM tem uma nova interpretação. ARM tem modos de endereçamento separados registrador indireto e registrador + offset. A Figura 2. dependendo dos códigos de condição. ARM utiliza desvios condicionais para testar os códigos de condição a fim de determinar todas as relações sem sinal e com sinal possíveis. TST realiza um AND lógico sobre os dois operandos para definir todos os códigos de condição menos overflow. Os oito bits menos significativos são estendidos em zero a um valor de 32 bits. os des- vios condicionais são corretamente considerados como executando condicionalmente a instrução de desvio incondicional. carry e overflow. Uma opção explícita leva a menos problemas em uma implementação em pipeline. Para obter um maior intervalo de endereçamento. ARM tem opcodes separados para realizar algumas operações que MIPS pode fazer com $zero. depois girados para a direita pelo número de bits especificado nos quatro primeiros bits do campo multiplicado por dois. dependendo dos códigos de condição.35 mostra algumas instruções aritmética-lógica não encontradas no MIPS. Por não possuir um registrador dedicado para 0. em vez de colocar apenas 0 no deslocamento do segundo modo. Um estudo interessante seria descobrir se essa divisão realmente apanha mais imediatos do que um campo simples de 12 bits. ARM e MIPS. As opções de deslocamento são shift left logical.35  Instruções aritméticas/lógicas do ARM não encontradas no MIPS. As diferenças resultam de arquiteturas com 16 ou 32 registradores. 2. O segundo registrador de todas as operações de processamento aritmético e lógico tem a opção de ser deslocado antes de ser atuado.16  Vida real: instruções do ARM 133 FIGURA 2. uma palavra de 32 bits. shift right arithmetic e rotate right. . O deslocamento de operandos não é limitado a imediatos.34  Formatos de instrução. shift right logical. FIGURA 2. chamados loads e stores em bloco. e. portanto. pois as instruções são mais lentas. A beleza está toda nos olhos de quem vê. 1877 Os projetistas de conjuntos de instruções às vezes oferecem operações mais poderosas do que aquelas encontradas no ARM e MIPS. qualquer um dos 16 registradores pode ser carregado ou armazenado na memória em uma única instrução. por registradores de uso geral (GPR – isso. com apenas quatro instruções acrescentadas ao conjunto de instruções visíveis ao usuário: três para ajudar com o multiproces- samento (veja Capítulo 7) e uma instrução move condicional. Essas instruções podem salvar e restaurar registradores na entrada e retorno do procedimento. As instruções adicionais tornam o 80386 quase uma máquina de uso geral. como alguém poderia acrescentar roupas em uma mala pronta. com todos os registradores internos com 16 bits de largura. Sob o controle de uma máscara de 16 bits dentro das instruções. Pentium em 1992 e Pentium Pro em 1995 visaram a um desempenho maior. com estende o 8086 com cerca de 60 instruções de ponto flutuante. um microprocessador de 8 bits. Essa arquitetura para endereços ou para dados. Margaret Wolfe Hungerford. A fim de evitar esses problemas. as partes dessas arquiteturas se encaixam muito bem e a arquitetura inteira pode ser descrita de forma sucinta. o 80386 possui um modo para executar programas do 8086 sem alteração. aumentando o espaço de endereçamento para 24 bits. Além de uma arquitetura de 32 bits com registradores de 32 bits e um espaço de endereçamento de 32 bits. O 80386 também acrescentou suporte para paginação além de endereçamento segmentado (veja Capítulo 5). j 1982: o 80286 estendeu a arquitetura 8086. 2. Ao contrário do MIPS. sendo este o uso mais importante dessa instrução hoje em dia. o 80386 acrescentou novos modos de endereçamento e operações adicionais. j 1985: o 80386 estendeu a arquitetura 80286 para 32 bits. . tradores. j 1989-95: os posteriores 80486 em 1989.17  Vida real: instruções do x86 Molly Bawn. Isso não acontece com o X86. os projetistas passaram para instruções mais simples. aumentando o tempo que um programa leva para executar. os registradores possuem usos dedicados. O objetivo geralmente é reduzir o número de instruções executadas por um programa. Assim como o 80286. criando um modelo de mapeamento e proteção de memória elaborado (veja Capítulo 7) e acrescentando algumas instruções para preencher o conjunto de instruções e manipular o modelo de proteção. Essa lentidão pode ser o resultado de um tempo de ciclo de clock mais lento ou a requisição de mais ciclos de clock do que uma sequência mais simples. o 8086 não é considerado uma arquitetura com registradores de uso geral. acrescentando novos recursos ao conjunto de instruções original. General-Purpose Register)  Um registrador que pode ser usado j 1980: o coprocessador de ponto flutuante Intel 8087 foi anunciado. A Seção 2. Em vez de usar regis- praticamente qualquer instrução. O perigo é que essa redução pode ocorrer ao custo da simplicidade. ele conta com uma pilha (veja Seção 2. A evolução do Intel x86 O ARM e o MIPS foram a visão de grupos pequenos e únicos em 1985. ele é o produto de vários grupos independentes.134 Capítulo 2  Instruções: A Linguagem de Máquina ARM também possui instruções para salvar grupos de registradores. O caminho em direção à complexidade da operação é. Elas também podem ser usadas para cópia de memória em bloco. O 8086 é uma arquitetura de 16 bits. repleto de perigos. Aqui estão os marcos importantes do X86: j 1978: a arquitetura Intel 8086 foi anunciada como uma extensão compatível com o assembly para o então bem-sucedido Intel 8080. que evoluíram a arquitetura por quase 30 anos.20 e Seção 3.18 demonstra as armadilhas da complexidade.7). 11). operações gráficas sobre arrays de estruturas. dobrar sua largura para 128 bits e incluir um tipo de dados de ponto flutuante com precisão simples. Quase todas essas 144 instruções são versões de instruções MMX e SSE existentes que operam sobre 64 bits de dados em paralelo. trocando seu nome para Extended Memory 64 Technology (EM64T). Essa mudança aumentou o desempenho de ponto flutuante no Pentium 4. Para melhorar o desempe- nho da memória. com o 80386. denominadas Streaming SIMD Ex- tensions (SSE). Logo. j 1999: a Intel acrescentou outras 70 instruções. A principal mudança no ISA vem da inclusão de um novo modo. mas permite que os sistemas operacionais utilizem o AMD64 (modo de compatibilidade). O novo tipo de dados tem aritmética de precisão dupla. A AMD anunciou um conjunto de extensões arquitetônicas para aumentar o es- paço de endereçamento de 32 para 64 bits. conversão de ponto flutuante e sincronismo de threads (veja Seção 2. a Intel anunciou outra geração de extensões de mídia. foi outra empresa. Essa mudança não apenas habilita mais operações de multimídia.17  Vida real: instruções do x86 135 j 1997: depois que o Pentium e o Pentium Pro estavam sendo vendidos. Semelhante à transição do espaço de endereçamento de 16 para 32 bits em 1985. ele acrescenta um novo prefixo às instruções. o primeiro microprocessador a incluir instruções SSE2. 2. A AMD oferecerá o SSE3 nos próximos chips e quase certamente incluirá a instrução de troca atômica que estava faltando no ADM64. que redefine a execução de todas as instruções x86 com endereços e dados de 64 bits. a Intel anun- ciou que expandiria as arquiteturas Pentium e Pentium Pro com as Multi Media Extensions (MMX). que provavelmente deveria ter sido incluída no AMD64. que contornam as caches e escrevem diretamente na memória. como aqueles encontrados em outros computadores. O SSE3 acrescenta 13 instruções para dar suporte à aritmética complexa. Ele também aumenta a quantidade de registradores para 16 e aumenta o número de registradores SSE de 128 bits para 16. O Pentium II não introduziu novas instruções. Esse novo conjunto de 57 instruções utiliza a pilha de ponto flutuante de modo a acelerar aplicações de multimídia e comunicações. . Multiple Data) (veja Capítulo 7). que melhorou a arquitetura x86. Esses modos permitem uma transição mais controlada para o endereçamento de 64 bits do que a arquitetura IA-64 da HP/Intel. mais instruções de armazenamento de streaming. para manter a compatibilidade binária com a Intel. como parte do Pentium III. A principal diferença é que a Intel acrescentou uma instrução de comparação e troca atômica de 128 bits. O endereçamento de dados relativo ao PC é outra extensão. o AMD64 alarga todos os registradores para 64 bits. dessa vez denominadas SSE2. O AMD64 ainda possui um modo idêntico ao x86 (modo legado) e mais um modo que restringe os programas do usuário ao x86. as SSE incluem instruções de prefetch (pré-busca) da cache. codificação de vídeo. quatro operações de ponto flutuante de 32 bits podem ser realizadas em paralelo. Ao mesmo tempo. As instruções MMX normalmente operam sobre vários elementos de dados curtos de uma só vez. As principais mudanças foram incluir oito registradores separados. mas dá ao compilador um alvo diferente para operações de ponto flutuante do que a arquitetura de pilha única. na tradição das arquiteturas de única instrução e múltiplos dados (SIMD – Single Instruction. e não a Intel. Para enfrentar a quantidade maior de registradores. Dependendo de como você conta. Os compiladores podem decidir usar os oito registradores SSE como registradores de ponto flutuante. o modo longo também acrescenta de 4 a 10 novas instruções e perde 27 antigas. j 2004: a Intel se rende e abraça o AMD64. o que permite pares de operações de ponto flutuante de 64 bits em paralelo. chamado modo longo. j 2003: dessa vez. j 2001: a Intel acrescentou ainda outras 144 instruções. como MIPS. contagem de população e assim por diante. Apesar disso. Registradores e modos de endereçamento de dados do x86 Os registradores do 80386 mostram a evolução do conjunto de instruções (Figura 2. Vamos nos referir a eles genericamente como registradores de uso geral (ou GPRs – General-Purpose Registers). cerca de 250 instruções e acrescentando 128 novas instruções. esse ancestral diversificado levou a uma arquitetura difícil de explicar e impossível de amar.36). Preste bem atenção ao que você está para ver! Não tente ler esta seção com o cuidado que precisaria para escrever programas x86. duas vezes. que acrescenta três instruções de operando. em média a arquitetura foi estendida em uma instrução por mês! Quaisquer que sejam as falhas artísticas do x86. aumentando em 250 milhões por ano. oferecem dois tamanhos de endereços dentro da instrução. o ARM e o MIPS admitem registradores separados para origem e destino. Começamos nossa explicação com os registradores e os modos de endereçamento. o objetivo é que você tenha alguma familiaridade com os pontos fortes e fracos da arquitetura para desktops mais popular do mundo. Isso significa que os programas do MIPS podem usar quatro vezes isso e os ARM.38 mostra os modos de endereçamento do x86 e quais GPRs não podem ser usados com cada modo. j 2008: a Intel anuncia a Advanced Vector Extension. O 80386 contém apenas oito GPRs.136 Capítulo 2  Instruções: A Linguagem de Máquina j 2006: a Intel anuncia 54 novas instruções como parte das extensões do conjunto de instruções SSE4. que expande a largura de regis- trador das SSE de 128 para 256 bits. incluindo 46 instruções do conjunto de instruções básico. pois a base de software existente em cada etapa era muito importante para ser colocada em risco com mudanças arquitetônicas significativas. Os modos de endereçamento de memória. A Figura 2. Em vez de mostrar o conjunto de instruções inteiro de 16 e 32 bits. assim. extensão de sinal ou zero de dados estreitos para tamanhos mais largos. lembre-se de que houve mais incidência dessa família arquitetônica nos desktops do que de qualquer outra arquitetura. descritos com detalhes a seguir. redefinindo. . Essa restrição coloca mais pressão sobre os registradores limitados. inserindo um E no início de seus nomes para indicar a versão de 32 bits. em vez disso. praticamente qualquer instrução pode ter um operando na memória. Esses chamados deslocamentos podem ser de 8 bits ou de 32 bits. Se você examinou a vida do x86. produtos escalares para arrays de estruturas. existem restrições em relação a quais registradores podem ser usados em um modo. Assim. além de como obter o mesmo efeito usando instruções MIPS. lógicas e de transferência de dados são instruções de dois ope- randos que permitem as combinações mostradas na Figura 2.37. As instruções aritméticas e lógicas do x86 precisam ter um operando que atue como origem e destino. pois essa parte da arquitetura é a usada. prosseguimos para as operações com inteiros e concluímos com um exame da codificação da instrução. Essa história ilustra o impacto das “algemas douradas” da compatibilidade com o x86. Essas extensões realizam coisas como soma de diferenças absolutas. nesta seção. j 2007: a AMD anuncia 170 instruções como parte das SSE5. Embora um operando da memória possa usar qualquer modo de endereçamento. ao contrário do ARM e do MIPS. vamos nos concentrar no subconjunto de 32 bits originado com o 80386. pois um registrador de origem precisa ser modificado. Eles também acrescentaram suporte para máquinas virtuais (veja Capítulo 5). Existem duas diferenças importantes aqui. As instruções aritméticas. A segunda diferença importante é que um dos operandos pode estar na memória. O 80386 estendeu todos os registradores de 16 bits (exceto os registradores de segmento) para 32 bits. Os imediatos podem ser de 8.) As distinções de tipo de dados se aplicam a operações com registrador e também a acessos à memória. Operações com inteiros do x86 O 8086 oferece suporte para tipos de dados de 8 bits (byte) e 16 bits (word). Começando com o 80386.36 (não EIP ou EFLAGS).37  Tipos de instrução para instruções aritméticas. O 80386 acres- centa endereços e dados de 32 bits (double words) ao x86.36  O conjunto de registradores do 80386. FIGURA 2. lógicas e de transferência de dados. Quase toda operação funciona sobre dados de 8 bits e sobre um tamanho de dados maior. vamos ficar com o 80386 nesta seção. . chamados quad words.17  Vida real: instruções do x86 137 FIGURA 2. os oito registradores iniciais foram estendidos para 32 bits e também poderiam ser usados como registradores de uso geral. (AMD64 acrescenta endereços e dados de 64 bits. O x86 permite as combinações mostradas. A única restrição é a ausência de um modo memória-memória. Esse tamanho é determinado pelo modo e é de 16 bits ou de 32 bits. um registrador é qualquer um dos 14 principais registradores da Figura 2. 2. 16 ou 32 bits de extensão. Esse último prefixo tinha por finalidade estar emparelhado com uma instrução mover byte para mover um número variável de bytes. Fluxo de controle. Os códigos de condição são definidos como um efeito colateral de uma operação.38  Modos de endereçamento de 32 bits do x86 com restrições de registrador e o código MIPS equivalente. (A Intel oferece dois nomes diferentes para o que é chamado modo de endereçamento com Base – com Base e Indexado –. ao contrário do ARM e MIPS. Esse tamanho de dados padrão é definido por um bit no regis- trador do segmento de código. inteiros e decimais 3. Elas decidiram que os dados de 16 bits ou de 32 bits dominam a maioria dos programas e. jumps incondicionais. bloqueiam o barramento para dar suporte a sincronização (Seção 2. testam os códigos de condição. incluindo movimento e comparação de strings As duas primeiras categorias não precisam de comentários. O fator de escala 0 significa que o endereço não é escalado. O modo de endereçamento Base mais Índice Escalado. então. por isso. para dados de 64 bits. incluindo operações aritméticas de teste.) Logicamente. foi incluído para evitar as multiplicações por quatro (fator de escala 2) para transformar um índice de um registrador em um endereço em bytes (veja Figuras 2.25 e 2. Instruções para movimentação de dados. Para redefini-lo. e os combinamos aqui. Instruções aritméticas e lógicas.11) ou repetem a instrução seguinte até o registrador ECX chegar a 0. chamadas e retornos 4. o que permite que múltiplos prefixos modifiquem o comportamento da instrução. Instruções para manipulação de strings. mas eles são basicamente idênticos. O 80386 também acrescentou um prefixo para redefinir o tamanho de endereço padrão. exceto que as operações de instruções aritméticas e lógicas permitem que o destino seja um registrador ou um local da memória. Se o deslocamento for maior do que 16 bits no segundo ou quarto modos então o modo MIPS equivalente precisa de mais duas instruções: um lui para ler os 16 bits mais altos do deslocamento e um add para somar a parte alta do endereço ao registrador base $s1. As operações com inteiros do x86 podem ser divididas em quatro classes principais: 1. Os três prefixos originais redefinem o regis- trador de segmento padrão.138 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2. Os desvios. . Os desvios condicionais no x86 são baseados em códigos de condição ou flags. a maioria é usada para comparar o valor de um resultado com 0. faz sentido poder definir um tamanho grande padrão. visto que. um prefixo de 8 bits é anexado à instrução a fim de dizer à máquina para usar o outro tamanho grande para essa instrução. A solução do prefixo foi emprestada do 8086. de modo que as arquiteturas 80386 oferecem uma forma conveniente de especificar cada versão sem expandir muito o tamanho do código.39 mostra algumas instruções x86 típicas e suas funções. A Figura 2.27). que não aparece no ARM ou no MIPS. Um fator de escala 1 é usado para dados de 16 bits e um fator de escala 3. assim como no ARM. incluindo desvios condicionais. push e pop 2. nem todas as instruções do 80386 possuem 4 bytes de extensão. incluindo move. alguns programas querem operar sobre dados de todos os três tamanhos. Os endereços de desvio relativos ao PC precisam ser especificados no número de bytes. Muitas operações utilizam o formato registrador-memória. A Figura 2. Uma lista de operações frequentes aparece na Figura 2.18).40. Muitas das instruções estão disponíveis nos formatos byte e word.40  Algumas operações típicas do x86. FIGURA 2. Em geral.17  Vida real: instruções do x86 139 As instruções para manipulação de strings fazem parte da linhagem 8080 do x86 e não são comumente executadas na maioria dos programas.40 lista algumas das instruções do x86 com inteiros. O CALL salva na pilha o EIP da próxima instrução. são mais lentas do que as rotinas de software equivalentes (veja a falácia na Seção 2. no qual a origem ou o destino pode ser a memória e o outro pode ser um registrador ou um operando imediato. . 2.) FIGURA 2. (EIP é o PC da Intel.39  Algumas instruções x86 típicas e suas funções. 41 mostra o formato de instrução para várias instruções de exemplo na Figu- ra 2. Para algumas instruções. isso acontece em muitas instruções que possuem a forma “registrador = regis- trador op imediato”. Em geral. FIGURA 2. até 15 bytes. base”. Outras instruções utilizam um “pós-byte”. Muitas instruções contêm o campo de 1 bit w. o opcode pode incluir o modo de endereçamento e o registrador. reg. O tamanho grande vem dos prefixos extras de 1 byte.41  Formatos típicos de instruções x86. que acrescenta outro byte. índice. visto que no modo de 32 bits. A Figura 2.42 mostra a codificação dos dois especificadores de endereço pós-byte para os modos de 16 e 32 bits. O modo “base mais índice escalado” utiliza um segundo pós-byte. você precisa ver a codificação de todos os modos de endereçamento e.39. a codificação de instruções no 80386 é complexa. Infelizmente. As instruções para o 80386 podem variar de 1 byte. O campo d em MOV é usado em instruções que podem mover de ou para a memória. e mostra a direção do movimento. rotulado “mod. quando não existem operandos. A Figura 2. usando um opcode de 2 bytes e usando o especificador do modo de índice escalado. O campo imediato no TEST tem 32 bits de extensão. . que indica se a operação é de um byte ou double word. tendo tanto um imediato de 4 bytes quanto um endereço de deslocamento de 4 bytes.140 Capítulo 2  Instruções: A Linguagem de Máquina Codificação de instruções do x86 Deixando o pior para o final. os imediatos são de 8 bits ou de 32 bits. Esse pós-byte é usado para muitas das instruções que endereçam a memória. ou byte de opcode extra. O byte de opcode normalmente contém um bit indicando se o operando é de 8 bits ou de 32 bits. com muitos formatos de instrução diferentes. às vezes. A Figura 2. até mesmo a codificação das instruções. A instrução ADD requer 32 bits para o campo imediato. que contém a informação sobre o modo de endereçamento.42 mostra a codificação do pós-byte. rotulado com “sc. as instruções podem variar de 1 a 17 bytes de extensão. para entender quais registradores e quais modos de endereçamento estão disponíveis. pois não existe um imediato de 8 bits para testar no modo de 32 bits. r/m”. Um método alternativo. usando a mesma codificação que o campo reg combinado com o bit w. As quatro primeiras colunas mostram a codificação do campo reg de 3 bits. e essa dianteira levou à seleção do 8086 como CPU para o IBM PC. As demais colunas explicam os campos mod e r/m. pode parecer que a sequência de instruções natural seria usar move com o prefixo de repetição para realizar movimentações de memória para memória em 32 bits. é carregar os dados nos registradores e depois armazenar os registradores na memória. para mover dados na memória.38. com mod = 1 acrescentando um deslocamento de 8 bits e mod = 2 acrescentando um deslocamento de 16 ou 32 bits. mostrado na Figura 2. reg. em que (sib) significa o uso do modo de índice escalado. que usava os registradores de ponto flutuante maiores no lugar dos registradores inteiros do x86. 2.18   Falácias e armadilhas Falácia: instruções mais poderosas significam maior desempenho. sob mod = 0. r/m”. A graça salvadora é que os componentes arquitetônicos mais usados do x86 não são tão difíceis de implementar. Uma terceira versão. Basicamente. O significado do campo r/m de 3 bits depende do valor do campo mod de 2 bits e do tamanho do endereço. do ponto de vista apropriado. 2. mas o mercado maior significa que a AMD e a Intel podem abrir mão de mais recursos para ajudar a contornar a complexidade adicional. tornando-o belo. Um prefixo pode repetir a instrução seguinte até que um contador chegue a 0. Conclusão sobre o x86 A Intel tinha um microprocessador de 16 bits dois anos antes das arquiteturas mais elegan- tes de seus concorrentes. Os engenheiros da Intel geralmente reconhecem que o x86 é mais difícil de ser montado do que máquinas como ARM e MIPS. 2) r/m = 5 quando mod = 1 ou mod = 2 no modo 16 bits seleciona EBP mais deslocamento. como a AMD e a Intel já demonstraram. os compiladores precisam evitar as partes da arquitetura difíceis de implementar com rapidez. copia cerca de 2. que usa as instruções padrão encontradas em todos os com- putadores.18  Falácias e armadilhas 141 FIGURA 2. a sofisticação cada vez maior dos compiladores significa que a lacuna entre o código compilado e o código produzido à mão está se . Parte do poder do Intel x86 são os prefixos que podem modificar a execução da instrução seguinte. Houve uma época em que os compiladores para as linguagens de programação produ- ziam sequências de instrução ingênuas. e 3) r/m = 4 no modo de 32 bits quando mod não é igual a 3. dependendo do modo do endereço. Quando mod = 3.42  A codificação do primeiro especificador de endereço do x86: “mod. O que o x86 perde no estilo é compensado na quantidade. copia cerca de 1. As exceções são: 1) r/m = 6 quando mod = 1 ou mod = 2 no modo de 16 bits seleciona BP mais o deslocamento.0 vezes mais rápido do que a instrução complexa. com o código replicado para reduzir o traba- lho extra do loop. Essa segunda versão do programa. o campo r/m indica um registrador. Assim. Para obter esse desempenho. que depende do bit w do opcode e se a máquina está no modo de 16 bits (8086) ou no modo de 32 bits (80386). melhorando rapidamente o desempenho dos programas com inteiros desde 1978. Falácia: escreva em assembly para obter o maior desempenho. como o Motorola 68000. os registradores utilizados no cálculo do endereço são listados na sexta e sétima colunas.5 vez mais rápido. Quando os compiladores eram fracos na alocação de registradores. em vez de passar para a memória. Embora haja um valor técnico claro em algumas dessas extensões. alguns livros-texto sobre C gastavam muito tempo dando exemplos com sugestões de como usar registradores com eficiência. perda de portabilidade e dificuldade de manter esse código. Mesmo se a escrita à mão resultasse em código mais rápido. A média é mais de uma instrução por mês no decorrer do seu tempo de vida de 30 anos! Armadilha: esquecer que os endereços sequenciais de palavras em máquinas com endere- çamento em bytes não diferem em um. Essa batalha entre compiladores e codificadores assembly é uma situação em que os humanos estão perdendo terreno. Além do mais. Prevenir é melhor do que remediar! Armadilha: usando um ponteiro para uma variável automática fora de seu procedimento de definição. . e claramente é preciso mais linhas para escrever um programa em assembly do que em C ou Java. De fato. Um dos poucos axiomas aceitos de modo generalizado na engenharia de software é que a codificação leva mais tempo se você escrever mais linhas. Embora a compatibilidade binária seja sacrossanta.43  Crescimento do conjunto de instruções do x86 com o tempo. significando que alguém terá de atualizar o código por vários anos e fazer com que funcione com novas versões dos sistemas operacionais e novos modelos de máquinas. ignoram essas suges- tões. FIGURA 2. para competir com os compiladores atuais.142 Capítulo 2  Instruções: A Linguagem de Máquina fechando rapidamente. o próximo perigo é que ele se torne um programa popular. De fato. os perigos de escrever em assembly são maior tempo gasto codificando e depurando. a Figura 2. em vez do tamanho da palavra em bytes. Esses programas sempre vivem por mais tempo do que o esperado. Por exemplo. mas também torna o software mais fácil de manter e permite que o programa execute em mais modelos de computadores. A escrita em linguagem de alto nível no lugar do assembly não apenas permite que os compiladores futuros ajustem o código a máquinas futuras. o programador assembly precisa entender perfeitamente os conceitos dos Capítulos 4 e 5 (pipelining do processador e hierarquia de memória). a linguagem C oferece ao programador uma chance de dar uma sugestão ao compilador sobre quais variáveis manter em regis- tradores. uma vez codificado. Falácia: a importância da compatibilidade binária comercial significa que os conjuntos de instruções bem-sucedidos não mudam. pois o compilador realiza um trabalho melhor na alocação do que o programador. Os compiladores C de hoje. essas sugestões eram vitais para o desempenho. em geral.43 mostra que a arquitetura do x86 cresceu drasticamente. Muitos programadores assembly têm lutado contra erros cometidos pela suposição de que o endereço da próxima palavra pode ser encontrado incrementando-se o endereço em um regis- trador por um. essa mudança rápida também aumenta a dificuldade para outras empresas tentarem montar processadores compatíveis. A regularidade motiva muitos recursos do conjunto de instruções do MIPS: mantendo todas as instruções com um único tamanho.19   Comentários finais Menos significa mais. j Os desvios condicionais são usados em instruções if e em loops.19  Comentários finais 143 Um engano comum ao lidar com ponteiros é passar um resultado de um procedimento que inclui um ponteiro para um array que é local a esse procedimento. 4.45 mostra a popularidade de cada classe de instruções para o . sempre exigindo três operandos de registrador nas instruções aritméticas e mantendo os campos de registrador no mesmo lugar em cada formato de instrução. 3. Andrea del Os dois princípios do computador com programa armazenado são o uso de instruções que Sarto. j Os jumps incondicionais são usados em chamadas de procedimento e em retornos. quatro princípios de projeto orientam os autores de conjuntos de instruções para fazer esse equilíbrio delicado: 1. Alguns exemplos de tornar o caso comum do MIPS veloz são o endereçamento relativo ao PC para desvios condicionais e o endereçamento imediato para constantes como operandos. variações comuns de instruções recebem seu próprio nome. Cada categoria de instruções MIPS está associada a construções que aparecem nas linguagens de programação: j As instruções aritméticas correspondem às operações encontradas nas instruções de atribuição. Essas instruções não nasceram iguais.12. O desejo de velocidade é o motivo para que o MIPS tenha 32 registradores em vez de muito mais. A Figura 2. Um exemplo do MIPS foi o compromisso entre providenciar endereços e constantes maiores nas instruções e manter todas as instruções com o mesmo tamanho. uma linguagem que os humanos podem ler. Simplicidade favorece a regularidade. criando instruções simbólicas que não estão no hardware. 2. Menor é mais rápido.44 lista as instruções MIPS que abordamos até aqui. Um bom projeto exige bons compromissos. Esses princípios permitem que uma única máquina auxilie cientistas ambientais. 2. constantes ou endereços que são muito grandes são divididos em partes com tamanho apropriado. e para instruções case/switch. Robert Browning. a Figura 2. 1855 sejam indistintas de números e o uso de memória alterável para os programas. como arrays e estruturas. consultores financeiros e autores de romance em suas especialidades. tanto instruções reais quanto pseudoinstruções. Torne o caso comum veloz. a popularidade das poucas domina as muitas. Acima desse nível de máquina está o assembly. Os ponteiros para variáveis automáticas podem levar ao caos. e assim por diante. j As instruções de transferência de dados provavelmente ocorrerão quando se lidam com estruturas de dados. Por exemplo. 2. Seguindo a disciplina de pilha da Figura 2. Por exemplo. O montador traduz isso para os números binários que as máquinas podem entender e até mesmo “estende” o conjunto de instruções. Como ilustramos neste capítulo. a quantidade de ciclos de clock necessários por uma instrução e a velocidade do clock. A seleção de um conjunto de instruções que a máquina possa entender exige um equilíbrio delicado entre a quantidade de instruções necessárias para executar um programa. a memória que contém o array local será reutilizada assim que o procedimento retornar. A Figura 3.1 mostra mais detalhes da arquitetura do MIPS revelada neste capítulo.45  Classes de instruções MIPS. As informações que aparecem aqui são encontradas nas colunas 1 e 2 do Guia de Instrução Rápida do MIPS. com as instruções MIPS reais à esquerda e as pseudoinstruções à direita.44  O conjunto de instruções do MIPS explicado até aqui. no início do livro.144 Capítulo 2  Instruções: A Linguagem de Máquina FIGURA 2. exemplos.26 no Capítulo 3 mostra a porcentagem das instruções MIPS individuais executadas. FIGURA 2. O Apêndice B (Seção B.10) descreve a arquitetura MIPS completa. correspondência com construções de linguagem de programação de alto nível e porcentagem média de instruções do MIPS executadas por categoria dos cinco programas de inteiros do SPEC2006. . A Figura 2. além de oferecer um pequeno histórico das linguagens de programação e compiladores. 2.2> Se as variáveis f. elas são muito convenientes e resultam em código mais legível (por exem- plo. tente não usá-las em qualquer exercício que pedir para produzir código do MIPS. sua contagem deverá refletir as instruções reais executadas. 2.2 [5] <2.1 Os problemas a seguir lidam com a tradução de C para MIPS. revelaremos mais da arquitetura do conjunto de instruções do MIPS. qual é o valor final de f? . a. Lisp.1. O restante desta seção está no site.1.20 Perspectiva histórica e leitura adicional Esta seção analisa a história das arquiteturas de conjuntos de instruções (ISAs) ao longo do tempo. e não as pseudoinstruções. caminho de dados. 2. b. f=g+(h-5). acrescente uma sentença ou duas à sua solução. e se você tiver de contar instruções. San Luis Obispo. g. Também revemos os assuntos controvertidos de arquiteturas de computadores de linguagem de alto nível e arquiteturas de computadores com conjunto de instruções reduzido. com colaborações de Nicole Kaiyan (Universidade de Adelaide) e Milos Prvulovic (Georgia Tech) O Apêndice B descreve o simulador do MIPS. Exercício 2. arquiteturas de pilha e uma rápida história do ARM e do x86. Algol. Se você decidir usar pseudoinstruções por esses motivos.1. Smalltalk. controle e pipelining. g. A história das linguagens de programação inclui Fortran. C + + e Java.21 Exercícios1 1 Contribuição de John Oliver. A popularidade variada das instruções desempenha um papel importante nos capítulos sobre desempenho. indicando quais pseudoinstruções usou e por quê. As ISAs incluem arquiteturas de acumulador. 2. as instruções li e move). por favor. h e i possuem o valor de 1.2> Para essas instruções C. Suponha que as variáveis f. conforme declarado em um programa C. 3 e 4. que é útil para estes exercícios. 2. Existem alguns casos em que as pseudoinstruções precisam ser usadas (por exemplo. respectivamente. Cobol.3 [5] <2. a instrução la quando um valor real não é conhecido durante a codificação em assembly). Depois que explicarmos a aritmética do computador no Capítulo 3.21 Exercícios 145 SPEC2000. e a história dos compiladores inclui os principais marcos e os pioneiros que os alcançaram. Embora o simulador aceite pseudoinstruções.1 [5] <2. da Cal Poly. Pascal.2> Para essas instruções C. Simula. qual é o código assembly do MIPS corres- pondente? Use um número mínimo de instruções assembly do MIPS. C. h e i sejam dadas e possam ser consideradas inteiros de 32 bits. quantas instruções assembly do MIPS são neces- sárias a fim de executar a instrução C? 2. f=g-h. Seu objetivo deverá ser aprender o conjunto de instruções MIPS real. Em muitos casos. arquiteturas de registrador de uso geral. 2. $0. h e i têm valores 1.2> Se as variáveis f. qual é o valor final de f? Exercício 2. 2. addi f. f. add f. Suponha que as variáveis g. f. 3 e 4.3 [5] <2. h e i têm valores 1. i e j sejam dadas e possam ser consideradas inteiros de 32 bits. a. f addi f.2. 3 e 4. add f. f = −g − f. h. h b. . 2. f=g-f. quantas instruções assembly do MIPS são neces- sárias a fim de executar a instrução C? 2. b. f 2.1. 3 e 4. g. b. qual é a instrução C correspondente? 2. f.5 [5] <2. i e j sejam dadas e possam ser consideradas inteiros de 32 bits. conforme declarado em um programa C. i. 2. respectivamente.2. a. g.2> Se as variáveis f. g. respectivamente. sub f. conforme declarado em um programa C.2 Os problemas a seguir lidam com a tradução de C para MIPS. h add f. f=i+(h-2).2> Se as variáveis f. 1 2. h.4 [5] <2. a. qual é o valor final de f? Os problemas a seguir lidam com a tradução de MIPS para C. conforme declarado em um programa C. 4 b. g.2> Para essas instruções C. h e i têm valores 1. a.1.2 [5] <2.146 Capítulo 2  Instruções: A Linguagem de Máquina Os problemas a seguir lidam com a tradução de MIPS para C.2. qual é o código assembly do MIPS corres- pondente? Use um número mínimo de instruções assembly do MIPS.2> Para as instruções assembly de MIPS apresentadas. conforme declarado em um programa C.2> Para essas instruções MIPS. qual é a instrução C correspondente? 2.2.2> Para essas instruções C. Para o exercício a seguir. Considere que as variáveis f e g sejam dadas e possam ser consideradas inteiros de 32 bits.1 [5] <2. qual é o valor final de f? Exercício 2. 2. g.3 Os problemas a seguir lidam com a tradução de C para MIPS. 2.4 [5] <2.5 [5] <2. h e i sejam dadas e possam ser consideradas inteiros de 32 bits. suponha que as variáveis f. respectivamente. Considere que as variáveis g.2. f = g + (−f − 5). a. h add f.3. Suponha que as variáveis f.1 [5] <2. f.2.4 Os problemas a seguir lidam com a tradução de C para MIPS.21 Exercícios 147 2. qual é o valor final de f? Os problemas a seguir lidam com a tradução de MIPS para C. h. 2.2 [5] <2. $s3e $s4.1 [10] <2. quantos registradores diferentes são necessários a fim de executar a instrução C? Os problemas a seguir lidam com a tradução de MIPS para C. 2. 2.3> Para as mesmas instruções C. respectivamente. qual é o valor final de f? Exercício 2. respectivamente. 2. i e j sejam atribuídas aos registradores $s0.5 [5] <2. $s3e $s4. respectivamente.2> Se as variáveis f.2. h.3. Considere que o endereço de base dos arrays A e B estejam nos registradores $s6 e $s7. conforme declarado em um programa C.3. − 4 b. respectivamente. i e j sejam dadas e possam ser consideradas inteiros de 32 bits. h. i.2. 2. h e i têm valores 1.3> Para as instruções C anteriores.2> Para essas instruções C. $s1. . $s1. Considere que o endereço de base dos arrays A e B estejam nos registradores $s6 e $s7. g. respectivamente. g. 2. f = g + h + B[4] . quantas instruções assembly do MIPS são necessárias a fim de executar a instrução C? 2. add i. h. g. 3 e 4. b. $s2. 2. g.3 [5] <2. f 2. $s2. 4 e 5. g.2> Para essas instruções MIPS. a. qual é o código assembly do MIPS corres- pondente? 2. Suponha que as variáveis f. 3. f = g – A[B[4]] .4.4. 2.2> Se as variáveis f. qual é o código assembly do MIPS corres- pondente? Use um número mínimo de instruções assembly do MIPS.4.2> Para as instruções C anteriores. respectivamente.4 [5] <2. qual é a instrução C correspondente? 2. addi f.3 [5] <2.2 [5] <2. i e j sejam atribuídas aos registradores $s0. Suponha que as variáveis g. quantas instruções assembly do MIPS são necessárias a fim de executar a instrução C? 2.3> Para essas instruções C.3.3. i e j têm valores 1. 2. 2. Suponha que os dados mostrados representem a variável C chamada Array.2.3> Para os locais de memória na tabela anterior. colocando o menor valor no menor local de memória mostrado na figura. reescreva o código assembly de modo a minimizar o número de instruções MIPS (se possível) necessárias para executar a mesma função.6 [5] <2. 2.2.4 [10] <2. Suponha que o endereço de base de Array esteja armazenado no registrador $s6.3> Para os locais de memória na tabela anterior. 2. a.5 [5] <2.3 [5] <2.3> A fim de classificar o array anterior. Endereço Dados 24 2 38 4 32 3 36 6 40 1 2.5.4. escreva o código MIPS que classifique os dados do mais baixo ao mais alto.2. 2. 2. 2.2. Suponha que essa máquina em particular seja uma máquina endereçável por byte e uma word consista em 4 bytes.5. a. Considere que o endereço de base do array está armazenado no registrador $s6 e faça o offset considerando o endereço de base do array. qual é a ins- trução C correspondente? 2.5 Nos problemas a seguir estaremos investigando as operações da memória no contexto de um processador MIPS. A tabela a seguir mostra os valores de um array armazenado na memória. 0xabcdef12 b.4. escreva o código C de modo a classificar os dados do mais baixo ao mais alto.5. qual é o número mínimo de registradores necessários? Exercício 2. Endereço Dados 20 4 24 5 28 3 32 2 34 1 b. 2.2 [10] <2.2. colocando o menor valor no menor local de memória.3> Quantos registradores são necessários para executar o assembly MIPS conforme escrito anteriormente: se você pudesse reescrever esse código. que é um array do tipo int. Use um número mínimo de instruções MIPS. de quantas instruções MIPS você precisa? Os problemas a seguir exploram a tradução de números hexadecimais para outros formatos numéricos.1 [10] <2. 0x10203040 .4.3> Para essas instruções assembly do MIPS.2. quantas instruções são neces- sárias para o código MIPS? Se você não tiver permissão para usar o campo imediato nas instruções lw e sw.3> Para as instruções assembly de MIPS apresentadas.148 Capítulo 2  Instruções: A Linguagem de Máquina 2. 2. 3 [5] <2. h. $s1. B[8] = A[i] + A[j] . a. respectivamente. 2.4 [5] <2. 2.2. res- pectivamente.6.4 [5] <2.5 [5] <2. 2.6 Os problemas a seguir lidam com a tradução de C para MIPS.1 [10] <2. suponha que o registrador $s6 contenha o valor 0x00000100. qual é a instrução C corres- pondente? 2. $s1. 2. 0x00000014. quantos registradores são necessários a fim de executar a instrução C usando o código assembly do MIPS? Os problemas a seguir lidam com a tradução de MIPS para C. $s3 e $s4. respectivamente. i e j sejam atribuídas aos registradores $s0. respectivamente.2.3> Para essas instruções C. g.21 Exercícios 149 2. $s2. 2.2. $s2. g. considere que os registradores $s0. 2.3> Para essas instruções assembly do MIPS. f = f + A[2] . e que os elementos dos arrays A e B seja words de 4 bytes.5 [5] <2. 0x0000001e e 0x00000028.5. $s2.2 [5] <2.2. e que a memória contém os seguintes valores: Endereço Valor 0x00000100 0x00000064 0x00000104 0x000000c8 0x00000106 0x0000012c .3> Traduza esses números hexadecimais para decimal. $s1. 2. qual é o código assembly do MIPS corres- pondente? 2.3> Mostre como os dados na tabela seriam arrumados na memória de uma máquina little-endian ou big-endian. b. Suponha que as variáveis f. i e J sejam atribuídas aos registradores $s0. Considere que o endereço de base dos arrays A e B estejam nos registradores $s6 e $s7. 2. quantas instruções assembly do MIPS são necessárias a fim de executar a instrução C? 2.2.5.6. $s3 contêm os valores 0x0000000a.3> Para essas instruções C. 2.3> Para as instruções C anteriores. Suponha que os dados sejam armazenados começando no endereço 0. respectivamente. Exercício 2.6. $s3e $s4.6. Além disso. Suponha que as variáveis f.3> Para o assembly MIPS anterior.6. Considere que o endereço de base dos arrays A e B esteja nos registradores $s6 e $s7. h. 0010 0100 1001 0010 0100 1001 0010 0100dois b.4> Para os padrões anteriores.1 [5] <2.5 [5] <2. 2. considerando que ele é um inteiro de complemento de dois? 2.4> Para o conteúdo dos registradores $t0 e $t1.$s1 O resultado em $t0 é o resultado desejado ou houve overflow? . mostre o valor do campo imediato.7.7.7. supondo que seja um inteiro sem sinal? 2. 1024dec 2.5> Em cada instrução MIPS.6 [5] <2. mostre o valor do campo rd. qual número de base 10 o código binário re- presenta.6. a. converta para binário em complemento de dois. rs e rt.7.7. Para as instruções tipo I.4 [5] <2.8. Exercício 2.3. 0101 1111 1011 1110 0100 0000 0000 0000dois 2.6 [10] <2.3 [5] <2.$s0. Os registradores $s0 e $s1 mantêm os valores mostrados na tabela a seguir. Exercício 2. que número de base 10 ele representa.4> Para os padrões acima. converta os valores negados da tabela para hexadecimal em complemento de dois. a.7. converta para hexadecimal em complemento de dois. que número hexadecimal eles representam? Os problemas a seguir exploram conversões numéricas de números decimais para binários com sinal e sem sinal.4> Para os mesmos números de base dez. 2.2 [5] <2.4> Ainda em relação aos números de base dez.4> Para esses números de base dez. qual é o valor de $t0 para o código assembly a seguir: add $t0. mostre o valor dos campos op. conforme especificado anteriormente. 2. Você deverá executar uma assembly de instrução de código MIPS sobre esses registradores e mostrar o resultado.4> Para os padrões anteriores.7 Os problemas a seguir exploram as conversões numéricas de número binário com sinal e sem sinal para números decimais. 2. −1dec b. e com as instruções tipo R.8 Os problemas a seguir lidam com extensão de sinal e overflow.150 Capítulo 2  Instruções: A Linguagem de Máquina Encontre o valor de $s0 ao final do código assembly. 2.1 [5] <2. a. a.$s0.$s1 add $t0. Se a instrução add $s0.4> Para o conteúdo dos registradores $t0 e $t1 conforme especificado anteriormente. Dados os valores de $t0 e $t1 em cada uma das questões a seguir.$s1 O resultado em $t0 é o resultado desejado ou houve overflow? 2.8.$s0.4 [5] <2.8. indique se haverá overflow. haverá overflow? Exercício 2.3 [5] <2.$s1 add $s0. Para a tabela anterior.$s0.$s0.$s1 b. $s1 for executada.4> Suponha que o registrador $s0 = 0x8FFF FFFF e $s1 = 0xD000 0000.4> Suponha que o registrador $s0 = 0x7000 0000 e $s1 = 0x1000 0000. Você deverá avaliar se haverá overflow para determinada operação.4> Considere que o registrador $s0 = 0x8000 0000 e $s1 tenha o valor dado na tabela. $s0.1 [5] <2. qual é o valor de $t0 para o seguinte código assembly: add $t0.9.8.9.4> Considere que o registrador $s0 = 0x7000 0000 e $s1 tenha o valor dado na tabela. Se a instrução add $s0. add $s0. haverá overflow? 2.3 [5] <2. você executará várias operações MIPS sobre um par de regis- tradores.4> Para o conteúdo dos registradores $t0 e $t1 conforme especificado anteriormente.$s0.$t0. Se a instrução sub $s0. Para a tabela anterior.$s1 add $s0. qual é o valor de $t0 para o seguinte código assembly: sub $t0. 2.9. $t0 e $t1. $s1 for executada. haverá overflow? 2. $s0.8. $s1 for executada. Para a tabela anterior. haverá overflow? . haverá overflow? 2.$s1 2. 1024dec 2.$s0 O resultado em $t0 é o resultado desejado ou houve overflow? Nos problemas a seguir.21 Exercícios 151 2. haverá overflow? 2.8.2 [5] <2.$s0.9 A tabela a seguir contém diversos valores para o registrador $s1.4> Considere que o registrador $s0 = 0x7FFF FFFF e $s1 tenha o valor dado na tabela.6 [5] <2.4> Suponha que o registrador $s0 = 0x4000 0000 e $s1 = 0x2000 0000. $s0.5 [5] <2. add $s0.$s1 add $s0.$s0.2 [5] <2. −1dec b. 5> Se as entradas binárias anteriores fossem bits de dados.10.5> Que tipo (tipo I. Rs e Rt nessa instrução? Para as instruções de tipo R. 32($t2) 2. 1111 1111 1111 1111 1011 0011 0101 0011bin 2.5> Que tipo de instrução (tipo I. a tabela de dados contém instruções MIPS. qual é o resultado em hexadecimal? 2. Você deverá traduzir as entradas para o código assembly e determinar que formato da instrução MIPS os bits representam. $s1 for executada.152 Capítulo 2  Instruções: A Linguagem de Máquina A tabela a seguir contém diversos valores para o registrador $s1. tipo R) as mesmas entradas binárias representam? 2.1 [5] <2. $s0. 2.4> Considere que o registrador $s0 = 0x7000 0000 e $s1 tenha o valor dado na tabela. 2.0 b. qual é a representação hexadecimal dos campos Rd e funct? Para as instruções de tipo I. que número elas representariam em hexadecimal? Nos problemas a seguir. addi$t0. a. tipo R) essas instruções representam? 2. 1010 1101 0001 0000 0000 0000 0000 0010bin b. sw $t1.6 [5] <2. $s1 for executada.10 Nos problemas a seguir.5> Para essas entradas binárias. $s0.4> Considere que o registrador $s0 = 0x7000 0000 e $s1 tenha o valor dado na tabela.5> Mostre a representação hexadecimal dessas instruções. 0000 0001 0100 1011 0100 1000 0010 0010dois 2. a.4. $s1 for executada.4 [5] <2.5> Qual é a representação binária e hexadecimal dos campos opcode. Você deverá avaliar se haverá overflow para determinada operação.10.9.4. haverá overflow? 2.2 [5] <2.4 [5] <2. qual é a representação hexadecimal do campo imediato? .10.10.9.3 [5] <2. 2. a. que instrução elas representam? 2. Se a instrução add $s0. a tabela de dados contém bits que representam o opcode de uma instrução.9.5 [5] <2. $s0.5 [5] <2.6 [5] <2. qual é o resultado na base dez? Exercício 2.10. 0000 0010 0001 0000 1000 0000 0010 0000dois b. Você deverá traduzir as entradas para os bits do opcode e determinar qual é o formato da instrução MIPS. Se a instrução add $s0. Se a instrução add $s0.$t0.10.4> Considere que o registrador $s0 = 0x7000 0000 e $s1 tenha o valor dado na tabela. 2.5> Que tipo (tipo I.11. op = 0.12. 128 registradores b.5. 2.5> Se o conjunto de instruções do processador MIPS for modificado.10> Por que a mudança sugerida na tabela anterior poderia diminuir o tamanho de um programa assembly do MIPS? Por que a mudança sugerida na tabela anterior aumenta o tamanho de um programa assembly do MIPS? .5 [5] <2. a. Você deverá traduzir as entradas para código assembly e determinar que formato de instrução MIPS os bits representam.5> Que instrução o número hexadecimal anterior representa? Nos problemas a seguir.11. a.funct = 34 b.3 [5] <2.rt = 2.5> Que número binário esse número hexadecimal acima representa? 2. 2.4 [5] <2.5> Se o conjunto de instruções do processador MIPS for modificado.21 Exercícios 153 Exercício 2.6 [5] <2.12. Qual é o número total de bits necessários para cada instrução? 2.5> Que número decimal esse número hexadecimal representa? 2. Você investigará o impacto dessas mudanças sobre o formato da instrução da arquitetura MIPS.3 [5] <2. mostre o tamanho dos campos de bit de uma instrução no formato de tipo I.5> Qual é a representação binária dessas instruções? Exercício 2. 0x02538822 2.11 Nos problemas a seguir. o formato da instrução também deverá ser alterado. a tabela de dados contém os valores de diversos campos das ins- truções MIPS.rt = 2. 2.const = 0x4 2.5> Qual é a instrução assembly do MIPS descrita anteriormente? 2. 2.rs = 1. a tabela de dados contém bits que representam o opcode de uma instrução.4. Qual é o número total de bits necessários para cada instrução? 2.rs = 3. a.2 [5] <2.4. o formato da instrução também deverá ser alterado. a tabela de dados contém diversas modificações que poderiam ser feitas à arquitetura do conjunto de instruções do MIPS. 0x01084020 b.1 [5] <2.12. Quatro vezes mais diferentes instruções 2.11.rd = 3.1 [5] <2.4.shamt = 0.11.11.2 [5] <2. Você deverá determinar qual é a instrução e descobrir o formato MIPS para ela. op = 0x23.11. mostre o tamanho dos campos de bit de uma instrução no formato de tipo R. Para cada uma das mudanças sugeridas anteriormente. Para cada uma das mudanças sugeridas. tipo R) essas instruções representam? 2.12 Nos problemas a seguir. 6> Com relação aos valores na tabela anterior. 2.154 Capítulo 2  Instruções: A Linguagem de Máquina Nos problemas a seguir. $t1 = 0x12345678 b.4. Você deverá de- terminar qual instrução MIPS o valor representa e descobrir o formato da instrução MIPS.4 [5] <2.6> Considere que $t0 = 0xA5A5FFFF e $t1 = A5A5FFFF. a tabela de dados contém valores hexadecimais.6> Considere que $t0 = 0xA5A50000 e $t1 = A5A50000. a tabela de dados contém os valores para os registradores $t0 e $t1. a.13.13.13.5 [5] <2. a. 2.12.5> Que tipo de instrução (tipo I.1 [5] <2.3 [5] <2. 0x01090012 b.13. qual é o valor de $t2 nesta sequência de instruções: No exercício a seguir.6> Para essas linhas.6 [5] <2. qual é o valor do número em decimal? 2. Qual é o valor de $t2 após as duas instruções na tabela? 2. Qual é o valor de $t2 após as duas instruções na tabela? .13. qual é o valor de $t2 para esta sequência de instruções: 2.5> Para essas entradas hexadecimais.12.4 [5] <2.6> Para essas linhas. Você deverá realizar diversas operações lógicas do MIPS sobre esses registradores. $t0 = 0xAAAAAAAA. 0xAD090012 2.13.5 [5] <2.13 Nos problemas a seguir.2 [5] <2. $t0 = 0xF00DD00D. Qual é o valor de $t2 após as duas instruções na tabela? 2. Você deverá encontrar o resultado dessas operações dados os valores para os registradores $t0 e $t1.6> Considere que $t0 = 0x0000A5A5 e que $t1 = 00005A5A.6 [5] <2. que instrução elas representam? 2.5> Para essas entradas. $t1 = 0x11111111 2. qual é o valor de $t2 nesta sequência de instruções: 2. a tabela de dados contém diversas operações lógicas do MIPS.12. tipo R) as entradas binárias anteriores representam? Qual é o valor do campo op e do campo rt? Exercício 2. 14.14. você deverá escrever instruções MIPS para extrair os bits “Campo” do registrador $t0 e colocá-los no registrador $t1 no local indicado na tabela a seguir. 2.6> Encontre a sequência mais curta de instruções MIPS que extrai um campo de $t0 para os valores constantes i = 17 e j = 11 e coloca o campo em $t1 no formato mostrado na tabela de dados.6 [5] <2.21 Exercícios 155 Exercício 2.2 [5] <2. . 2.6> Encontre a sequência mais curta de instruções MIPS que extrai um campo de $t0 para os valores constantes i = 5 e j = 0 e coloca o campo em $t1 no formato mostrado na tabela de dados. você deverá escrever instruções MIPS para extrair os bits “Campo” do registrador $t0 mostrado na figura e colocá-los no registrador $t1 no local indicado na tabela a seguir.6> Encontre a sequência mais curta de instruções MIPS que extrai um campo de $t0 para os valores constantes i = 31 e j = 28 e coloca o campo em $t1 no formato mostrado na tabela de dados.14.14 Nos problemas a seguir.14. 2.6> Encontre a sequência mais curta de instruções MIPS que extrai um campo de $t0 para os valores constantes i = 22 e j = 5 e coloca o campo em $t1 no formato mostrado na tabela de dados.14.14. Os bits mostrados como “XXX” devem permanecer inalterados. Nos problemas a seguir.4 [20] <2. 2.6> Encontre a sequência mais curta de instruções MIPS que extrai um campo de $t0 para os valores constantes i = 31 e j = 29 e coloca o campo em $t1 no formato mostrado na tabela de dados.3 [5] <2.1 [20] <2. 2.6> Encontre a sequência mais curta de instruções MIPS que extrai um campo de $t0 para os valores constantes i = 4 e j = 0 e coloca o campo em $t1 no formato mostrado na tabela de dados. 2.5 [5] <2. 2. 15.15. Neste exercício.15. a tabela mantém diversos valores binários para o registrador $t0.16 Para estes problemas.15. 0010 0100 1001 0010 0100 1001 0010 0100dois b. A = C[0] << 4 .2.6> Para a sua sequência de instruções em 2.4 [5] <2. Diversas instruções lógicas em nível de C aparecem na tabela a seguir.1 [5] <2. a.6> A tabela anterior mostra diferentes instruções C que utilizam operadores lógicos.16.6> Essas instruções lógicas não estão incluídas no conjunto de instruções MIPS.7> Suponha que o registrador $t0 contenha um desses valor e $t1 tenha o valor 0011 1111 1111 1000 0000 0000 0000 0000bin .1 [5] <2. mostre a representação em nível de bit de cada instrução. você deverá avaliar o resultado de diferentes desvios. 2. a tabela mantém algumas operações lógicas que não estão incluídas no conjunto de instruções MIPS.$t2.6> Essas instruções lógicas não estão incluídas no conjunto de ins- truções MIPS.!$t3 2. 0101 1111 1011 1110 0100 0000 0000 0000dois 2.15.5 [5] <2. qual é o valor resultante de A? 2. mas são descritas aqui. not $t1. Se o local de memória em C[0] contém o valor inteiro 0x00001234 e os valores inteiros iniciais de A e B são 0x00000000 e 0x00002222.156 Capítulo 2  Instruções: A Linguagem de Máquina Exercício 2. mostre a representação em nível de bit de cada instrução. Dado o valor de $t0.2 [10] <2. A = B|! A . qual é o resultado em $t1? 2. Exercício 2.6> Para a sua sequência de instruções em 2.6> Para as instruções C na tabela anterior. a.15 Para estes problemas.15. Forneça um conjunto mínimo de instruções MIPS que podem ser usadas no lugar das instruções na tabela anterior. você deverá avaliar as instruções e implementar essas instruções C usando instruções assembly do MIPS. b. Se o valor de $t2  = 0x00FFA5A5 e o valor de $t3 = 0xFFFF003C.$t3 / / bit-wise OR de $t2. 2.15.6 [5] <2.$t2 // bit-wise invertido b. 2. escreva uma sequência mínima de instruções assembly do MIPS que realiza a operação idêntica.3 [5] <2. mas podem ser sintetizadas usando-se uma ou mais instruções assembly do MIPS.15.5. orn $t1. Como essas instruções podem ser implementadas? a. 2. Dado o valor de $t0.7> Suponha que o registrador $t0 contenha um valor da tabela anterior e seja comparado com o valor X.16.7> Suponha que o registrador $t0 contenha um valor da tabela anterior. É possível usar a instrução assembly do MIPS para salto (j) a fim de definir o PC como o endereço mostrado na tabela de dados anterior? É possível usar uma instrução assembly do MIPS branch-on-equal (beq) para definir o PC como o endereço mostrado na tabela de dados anterior? Para estes problemas.5 [5] <2.7> Suponha que o registrador $t0 contenha um valor da tabela anterior.X 2.2 [10] <2. .16. Qual é o valor de $t2 depois das seguintes instruções? 2.21 Exercícios 157 Note o resultado da execução de tais instruções em certos registradores. 0x80001000 2.$t0. $t0 será igual a 1? slti$t2.6. É possível usar a instrução assembly do MIPS para salto (j) a fim de definir o PC como o endereço mostrado na tabela de dados anterior? É possível usar uma instrução assembly do MIPS branch-on-equal (beq) para definir o PC como o endereço mostrado na mesma tabela de dados? Note o formato das instruções de tipo J.6 [5] <2.16.4 [5] <2.3 [5] <2. se houver.16. Para que valores de X. 0x00101000 b.7> Suponha que o contador de programa (PC) seja definido como 0x2000 0000.2 slt $t2.$t0.7> Suponha que o contador de programa (PC) seja definido como 0x0000 0020. Qual é o valor de $t2 após as instruções a seguir? sll$t0. a tabela mantém diversos valores binários para o registrador $t0.$0 2. a. 2. conforme usado na instrução MIPS a seguir. você deverá avaliar o resultado de diferentes desvios. Qual é o valor de $t2 após as instruções a seguir? 2.$t0.16. Para estes problemas. rpt $t2.4 [5] <2. $t1 e $t2 sejam inteiros A. a. 2. Qual é o valor no registrador $t2 considerando que o $t2 é inicialmente zero? 2. encontre a sequência mais curta de instruções do MIPS que executa a mesma operação.3 [5] <2. a tabela mantém algum código C.17. a tabela mantém fragmentos de código assembly do MIPS. B. subi$t2. familiarizando-se com as diferentes instruções de desvio do MIPS.17 Para estes problemas.7> A tabela anterior contém algumas instruções não incluídas no conjunto de instruções do MIPS e a descrição de cada instrução. Se essas instruções tivessem de ser imple- mentadas no conjunto de instruções do MIPS. 2.7> Para os loops escritos anteriormente em assembly MIPS. suponha que o registrador $t1 seja inicializado com o valor 10.loop # if(R[rs] > 0)R[rs] = R[rs] − 1. .17. Considere que os registradores $t1.17.5 # R[rt] = R[rs] − SignExtImm b. Por que essas instruções não estão incluídas no conjunto de instruções do MIPS? 2. Você deverá avaliar essas instruções de código C no código assembly do MIPS. Quantas instruções MIPS são executadas? Exercício 2. $t2.$t3.2 [5] <2.17. suponha que o registrador $t1 seja inicializado com o valor N.7> A tabela anterior contém algumas instruções não incluídas no conjunto de instruções do MIPS e a descrição de cada instrução.1 [5] <2. escreva a rotina de código C equi- valente.158 Capítulo 2  Instruções: A Linguagem de Máquina Exercício 2.17.6 [5] <2.7> Para os loops escritos em assembly do MIPS anterior.17.PC = PC + 4 + BranchAddr 2. Você deverá avaliar cada um dos fragmentos de código. qual é o formato de instrução mais apropriado? 2.5 [5] <2.7> Para cada um dos loops anteriores. respectivamente.7> Para cada instrução na tabela anterior.18 Para estes problemas. mostramos diversas instruções que não estão incluídas no conjunto de instruções do MIPS. i e temp. 5 [5] <2. $t1.18.19 Para os problemas a seguir.7> Traduza esses loops para C.3 [5] <2. Suponha que a primeira função listada na tabela se chame first.7> Reescreva o loop para reduzir o número de instruções MIPS executadas. 2. a tabela mantém fragmentos de código assembly do MIPS. familiarizando-se com as diferentes instruções de desvio do MIPS. Exercício 2. j estejam nos registradores $s0.18.6 [5] <2.2 [5] <2.18.18. desenhe um gráfico de fluxo de controle do código C. 2. .7> Para a tabela anterior.1 [5] <2. traduza o código C para o código assembly do MIPS. qual é o número total de instruções MIPS que são executadas para completar o loop? Para estes problemas. 2. suponha que o regis- trador $s2 mantenha o endereço de base do array D.21 Exercícios 159 2.18.7> Quantas instruções MIPS são necessárias para implementar o código C? Se as variáveis a e b forem inicializadas como 10 e 1 e todos os elementos de D forem inicialmente 0. e $s0 mantenha o endereço de base do inteiro MemArray. Além disso. $t0. $s2 mantenha o inteiro em nível de C chamado result.7> Qual é o número total de instruções MIPS executadas? 2. b. Suponha que os valores de a.4 [5] <2. Suponha que o inteiro i em nível de C seja mantido no registrador $t1. 2. 2.7> Para a tabela anterior. $s1. Você deverá avaliar cada um dos fragmentos de código.18. respectivamente. Você deverá traduzir essas rotinas de código C para o assembly do MIPS. a tabela mantém funções de código em C. Use um número mínimo de instruções. i. fatorial de n = 1 x 2 x 3 x . Exercício 2.20 Este exercício lida com chamadas de procedimento recursivas. Suponha que o ponteiro de pilha esteja originalmente no endereço 9x7ffffffc e siga as convenções de registrador especificadas na Figura 2.1 [15] <2. A declaração de função para func é “int func(int a. . $s3. 2.8> Podemos usar a otimização “tail-call” nesta função? Se negativo.19. e você deverá corrigi-los. a tabela tem um fragmento de código assembly que calcula o fatorial de um número. qual é a diferença no número de instruções executadas em f com e sem a otimização? 2. mas. O código para a função func em C já está compilado em outro módulo usando a convenção chamada MIPS da Figura 2.160 Capítulo 2  Instruções: A Linguagem de Máquina 2.6 [5] <2.4 [10] <2. Qual é a redução no número total de instruções assembly do MIPS necessárias para completar a função? Suponha que a variável C n seja inicializada como 5. O código para a função f é o seguinte: 2.19. que chama outra função func.8> Traduza a função f para o montador MIPS. Porém. use primeiro os registradores de número mais baixo. Qual é o número total de instruções MIPS necessárias para executar a função? 2.5 [5] <2.2 [5] <2. Implemente uma versão “em linha” do código C da tabela em assembly do MIPS. Se afirmativo. .19.8> Implemente o código C na tabela em assembly do MIPS. Uma função em linha é quando o corpo da função é copiado para o espaço do programa.8> As funções normalmente podem ser implementadas pelos compiladores “em linha”. o que sabemos sobre o conteúdo dos registradores $t5.14. mostre o conteúdo da pilha após a chamada de função ser feita. ex- plique por que não. Para os problemas a seguir. 2. int b). Para o número n.4 retorne. para a função func . permitindo que o overhead da chamada de função seja eliminado. as entradas na tabela têm erros.19. Os três problemas a seguir neste exercício referem-se a uma função f.”.19.14.11.3 [5] <2. x n. $ra e $sp? Lembre-se de que sabemos o conteúdo da função f . também usando a con- venção de chamada do MIPS da Figura 2.19. só conhecemos sua declaração.8> Para cada chamada de função.19.. Se você precisar usar os registradores de $t0 até $t7.8> Imediatamente antes que a sua função f do Problema 2.. Para o número n. suponha que a entrada seja 4.1 [5] <2. Qual é o número total de instruções usadas a fim de executar sua solução de 2.8> O programa assembly do MIPS anterior calcula o fatorial de determi- nada entrada. Corrija os erros do MIPS.3 [5] <2. Porém.8> Mostre o conteúdo da pilha após cada chamada de função. a tabela tem um fragmento de código assembly que calcula um número de Fibonacci. supondo que a entrada seja 4.21 Exercícios 161 2. o Fibonacci de n é calculado do seguinte modo: n Fibonacci de n 1 1 2 1 3 2 4 3 5 5 6 8 7 13 8 21 .8> Para o programa MIPS de fatorial recursivo.20. as entradas na tabela possuem erros e você deverá corrigi-los. 2. Para os problemas a seguir. A entrada inteira é passada pelo registrador $a0 e o resultado é retornado no registrador $v0. Restrinja seu uso de registrador aos registradores $s0-$s7.20.20. Reescreva o programa de fatorial para operar de uma maneira não recursiva.20. No código assembly existem alguns erros.2 [10] <2. 2.2 contra a versão recursiva do programa de fatorial? 2. Restrinja seu uso de registrador aos registradores $s0-$s7. Suponha que as funções de folha só possam utilizar registradores salvos. . Qual é o número total de instruções usadas para executar sua solução de 2.2 contra a versão recursiva do programa de fatorial? 2.8> Mostre o conteúdo da pilha após cada chamada de função. considerando que a entrada seja 4.20.11 e que as entradas de função são passadas usando-se os registradores $a0-$a3 e retornadas no registrador $r0. A entrada inteira é passada pelo registrador $a0 e o resultado é retornado no registrador $v0.20. Corrija os erros do MIPS.21 Considere que a pilha e os segmentos de dados estáticos estejam vazios e que a pilha e os ponteiros globais comecem no endereço 0x7fff fffc e 0x1000 8000. suponha que a entrada seja 4.20. existem alguns erros. 2.5 [10] <2. Reescreva o programa de Fibonacci a fim de operar de uma maneira não recursiva. respectivamente.8> Esse programa em assembly MIPS calcula o número de Fibonacci de determinada entrada.8> Para o programa de Fibonacci em MIPS anterior. No código assembly. Exercício 2.20.6 [5] <2.162 Capítulo 2  Instruções: A Linguagem de Máquina 2.4 [5] <2. Considere as convenções de chamada especificadas na Figura 2. 21 Exercícios 163 2. respectivamente.5 [10] <2. $t1.8> Escreva o código assembly do MIPS para o código da tabela anterior.4 [10] <2.21.8> Mostre o conteúdo da pilha e os segmentos de dados estáticos depois de cada chamada de função. 2. 2.8> Se a função leaf pudesse usar registradores temporários ($t0.3 [5] <2.14: 2. $a1.000 e 30.8> Qual é o equivalente C desse código? Suponha que os argumentos da função se chamem a.8> Este código contém um erro que viola a convenção de chamada do MIPS. 100. Qual é o valor retornado por essa função? Se outra função g for chamada a partir de f. 2. Qual é o erro e como ele deve ser consertado? 2.2 [5] <2. 2.). Os três problemas a seguir neste exercício referem-se a essa função.21.8> No ponto em que essa função é chamada. os registradores $a0. c etc.21. $a2 e $a3 têm os valores 1.21. escrita no assembler do MIPS seguindo as convenções de chamada da Figura 2. 1. etc. suponha que o valor retornado de g sempre seja 500.21.6 [10] <2. na versão C da função. b. . escreva o código MIPS para o código na tabela anterior.21.1 [5] <2. 1 [10] <2.9> Escreva um programa em linguagem assembly do MIPS para converter uma string de números ASCII com as condições listadas na tabela anterior.22. Exercício 2.22.23 Neste exercício.2 [5] <2.24 Considere que o registrador $t1 contenha o endereço 0x1000 0000 e o registrador $t2 contenha o endereço 0x1000 0010. 0dec (a string “24” terminada em nulo). 52dec. contendo alguma combinação dos dígitos de 0 até 9.1 [5] <2. você deverá escrever um programa em assembly MIPS que converte strings para o formato numérico especificado na tabela. inteiros hexadecimais positivos 2. A tabela a seguir mostra strings de caracteres. Seu programa deverá calcular o valor inteiro equivalente a essa string de dígitos. strings decimais inteiros positivos e negativos b. hello world b.3 [5] <2. 40 49 50 53 2. a. 2. 0123456789 2. para um inteiro.22. . Seu programa deverá esperar que o registrador $a0 contenha o endereço de uma string terminada em nulo.9> Traduza as strings para Unicode com 16 bits (usando a notação hexa e o conjunto de caracteres Basic Latin). A tabela a seguir mostra valores de caracteres em ASCII hexadecimal.164 Capítulo 2  Instruções: A Linguagem de Máquina Exercício 2. Se um caractere não de dígito aparecer em qualquer lugar da string. 2. quando o programa terminar.23.9> Traduza as strings para valores de bytes ASCII decimais. a.22 Este exercício explora a conversão ASCII e Unicode. Note que a arquitetura MIPS utiliza endereçamento de extremidades. o registrador $v0 deverá conter o valor 24dec. a.9> Traduza os valores ASCII hexadecimais para texto. Exercício 2. Por exemplo. 41 44 44 b. depois colocar o número no registrador $v0.5. seu programa deverá parar com um valor -1 no registrador $v0. se o registrador $a0 apontar para uma sequência de três bytes 50dec. então. 10> Se o valor atual do PC for 0x0000 0000. você estará usando os dados binários desta tabela: a. 2. Exercício 2. 2.10> Se o valor atual do PC for 0x0000 0600. Não use a instrução lui. Para os problemas seguintes.24.24.4 [5] <2. conforme mostrado na tabela anterior? 2.10> Se o campo imediato de uma instrução MIPS tivesse apenas 8 bits de largura. 2. .3 [5] <2.25.21 Exercícios 165 2.9> Suponha que os dados (em hexadecimal) no endereço 0x1000 0000 sejam: 1000 0000 11 00 00 FF Que valor é armazenado no endereço apontado pelo registrador $t2? Suponha que o local de memória apontado por $t2 seja inicializado como 0x5555 5555.1 [5] <2. 2. você pode usar uma única instrução de desvio para chegar ao endereço do PC. escreva o código MIPS que cria as constantes de 32 bits listadas anteriormente e armazena esse valor no registrador $t1.25.25 Neste exercício. você pode usar uma única instrução de salto para chegar ao endereço do PC.6.25.24. você pode usar uma única instrução de desvio a fim de chegar ao endereço do PC. 0000 1111 1011 1110 0100 0000 0000 0000dois 2.6.9> Suponha que os dados (em hexadecimal) no endereço 0x1000 0000 sejam: 1000 0000 12 34 56 78 Que valor é armazenado no endereço apontado pelo registrador $t2? Considere que o local da memória apontado para $t2 seja inicializado como 0xFFFF FFFF. você explorará as constantes de 32 bits em MIPS.25. 0010 0000 0000 0001 0100 1001 0010 0100dois b.9> Suponha que os dados (em hexadecimal) no endereço 0x1000 0000 sejam: 10000000 80 80 80 80 Que valor é armazenado no endereço apontado pelo registrador $t2? Suponha que o local de memória apontado para $t2 seja inicializado como 0x0000 0000. 2. 2.5 [10] <2.25. conforme mostrado na tabela anterior? 2. 2.6.1 [10] <2. conforme mostrado na tabela anterior? 2.10> Se o valor atual do PC for 0x1FFFf000.2 [5] <2.3 [5] <2.2 [5] <2.10> Escreva o código MIPS que cria as constantes de 32 bits listadas anteriormente e armazena esse valor no registrador $t1. Exercício 2. 0x00020000 b.166 Capítulo 2  Instruções: A Linguagem de Máquina Para os problemas a seguir.6.6. 2.3 [10] <2. use os dados hexadecimais desta tabela: a. 128 registradores b. o formato da instrução também deverá ser alterado.26. quantas instruções de desvio (não de salto) você precisa para chegar ao endereço na tabela anterior? 2. 2.1 [10] <2.7 [5] <2. Para cada uma das mudanças sugeridas anteriormente.6. o formato da instrução também deverá ser alterado.25. 2.26 Neste exercício. 0xffffff00 2.2 [10] <2. Se o PC estiver no endereço 0x0000 0000.26. 2.10> Se o PC estiver no endereço 0x0000 0000. os projetistas do MIPS decidiram cortar o campo imediato das instruções tipo I de 16 bits para 8 bits.10> Qual é o valor do registrador $t0 após a sequência de código na tabela anterior? 2. qual é o impacto sobre a faixa de endereços em uma instrução beq? Suponha que todas as instruções permaneçam com 32 bits de extensão e que quaisquer mudanças feitas ao formato das instruções de tipo I só aumentem/diminuam o campo imediato da instrução beq. Suponha que a maior constante que você pode carregar em um inteiro de 32 bits seja 16 bits.26.6.10> Se o PC estiver no endereço 0x0000 0000. de quantas instruções de salto (não de desvio ou de salto para registrador) você precisa para chegar ao endereço de destino na tabela anterior? 2. 2. Para cada uma das mudanças .26.6 [5] <2.26. quantas instruções de desvio são necessárias a fim de definir o PC como o endereço na tabela anterior? Nos problemas a seguir.6. você explorará a gama de instruções de desvio e salto no MIPS. a.10> Escreva o código C que é equivalente ao código assembly na tabela.6. 2.10> Para reduzir o tamanho dos programas em MIPS.5 [10] <2.10> Se o conjunto de instruções do processador MIPS for modificado.6. 2. Quatro vezes mais diferentes operações 2. você estará usando o código assembly do MIPS conforme lis- tado nesta tabela: 2. você estará fazendo modificações na arquitetura do conjunto de instruções MIPS. 2. Nos pro- blemas seguintes.10> Se o conjunto de instruções do processador MIPS for modifi- cado.4 [10] <2.25. você usará o código assembly do MIPS conforme listado a seguir. Endereçamento de Base ou Deslocamento b. reescreva o código MIPS apresentado para refletir essa mudança.10> Quantas instruções extras são necessárias para executar seu código nas instruções da tabela em 2.6 [10] <2. Para cada uma das mudanças sugeridas anteriormente. Nos problemas a seguir. 2.2 [5] <2. Endereçamento Pseudodireto 2. qual é o impacto sobre a faixa de endereços em uma instrução jump register.27.10> Na tabela anterior existem modos de endereçamento diferentes do conjunto de instruções MIPS. Dê um exemplo de instruções MIPS que mostre o modo de endereçamento do MIPS.27. você explorará diferentes modos de endereçamento na arquitetura do conjunto de instruções MIPS. Evite usar a instrução lui.10> Se o conjunto de instruções do processador MIPS for modificado. podemos economizar no número de bits necessários para representar instruções. o formato da instrução também deverá ser alterado. para explorar as opções do campo imediato nas instruções tipo I do MIPS. 2.10> Liste benefícios e desvantagens de determinado modo de endereça- mento do MIPS.1 [5] <2.27. 2.5 [10] <2. 2.6.1. Exercício 2. qual é o impacto sobre a faixa de endereços em uma instrução jump? Suponha que todas as instruções permaneçam com 32 bits de extensão e que quais- quer mudanças feitas ao formato das instruções de tipo J só afetem o campo de endereço da instrução jump. a.21 Exercícios 167 sugeridas anteriormente.27 Nos problemas a seguir. 2. Escreva o código do MIPS que mostra esses benefícios e as desvantagens.27.27.26. 2. Se o campo imediato das instruções tipo I fosse de 8 bits e o campo imediato das instruções de tipo J fosse de 18 bits. mostre a representação da instrução em nível de bit de cada uma das instruções em hexadecimal.27.27.10> Reduzindo o tamanho dos campos imediatos das instruções de tipo I e J.6 [5] <2. supondo que cada instrução precise ter 32 bits.4 [15] <2. qual é o tipo de formato de instrução usado em determinada instrução? 2.5 contra o código mostrado na tabela anterior? .10> Para as instruções MIPS da tabela anterior.10> Para as instruções em 2.27.3 [5] <2. 2. Esses diferentes modos de endereçamento são listados na tabela a seguir. 28 A tabela a seguir contém código assembly do MIPS para um lock. 0($s1) 4 b. . 0($s1) 1 11 $t1.28.11> Preencha a tabela com o valor dos registradores para cada ciclo in- dicado. Processador 1 MEM Processador 2 Processador 1 Processador 2 Ciclo $t1 $t0 ($s1) $t1 $t0 0 1 2 99 30 40 11 $t1.28. O código assembly em cada tabela é executado no ciclo mostrado em processadores paralelos.2 [5] <2. 0($s1) 3 sc $t0. Faça referência à definição de ll e pares sc das instruções MIPS.11> Reescreva o código anterior de modo que ele possa operar correta- mente. a.4 [5] <2.3 [15] <2. 5 0($s1) 2. 1 0($s1) 11 $t1. Cada entrada na tabela a seguir possui código e também mostra o conteúdo de diversos registradores. com um espaço de memória compartilhado.11> Para cada teste e falha do store condicional. Processador 1 MEM Processador 2 Processador 1 Processador 2 Ciclo $t1 $t0 ($s1) $t1 $t0 0 1 2 99 30 40 11 $t1. 0($s1) 2 Addi $t1.28. quantas instruções precisam ser executadas? 2. Não se esqueça de evitar quaisquer condições de race. 2.28. A notação “($s1)” mostra o conteúdo de um local de memória apontado pelo registrador $s1.1 [5] <2.11> Para o código de load locked/store condicional apresentado. 2. explique por que esse código poderá falhar. $t 3 sc $t0. 0($s1) 4 sc $t0.168 Capítulo 2  Instruções: A Linguagem de Máquina Exercício 2. 0($s1) 2 sc $t0. 1. o registrador $a1 contém o endereço da variável shvar e não o valor dessa variável.29.29. supondo que cada processador executa exatamente uma instrução por ciclo.11> Usando o seu código de 2. Observe que.2.11> Compare o desempenho do melhor caso do seu código de 2.29. ou seja. e por que o registrador $a2 contém o valor da variável x e não seu endereço.6 [10] <2.1 [10] <2.21 Exercícios 169 Exercício 2. e a operação unlock() é simplesmente uma instrução store comum.29.x) .x) .29. 2. 2. por que não podemos usar ll/sc para acessar variáveis compartilhadas de um modo que garanta que ambas as atualizações sejam executadas juntas como uma única operação atômica. operação unlock(lk). Sua seção crítica não deverá conter quaisquer chamadas de função.3 [10] <2. não existe uma variável lk. shvar1 e shvar2) na mesma seção crítica.29.29. o endereço da variável shvar esteja em $a1 e o valor da variável x esteja em $a2.29.11> Explique por que no seu código de 2. supondo que cada instrução leva um ciclo para ser executada.11> Repita o Problema 2.1 (simplesmente coloque as duas atualizações entre a operação lock e a operação unlock correspondente).11> Se quisermos executar atomicamente a mesma operação sobre duas variáveis compartilhadas (por exemplo.4 [10] <2. 2. shvar = max(shvar.29. 2.29.29 Os três primeiros problemas neste exercício referem-se à seção crítica na forma lock(lk). podemos fazer isso facilmente usando a técnica de 2. o lock sempre está livre quando queremos usar lock() e. explique o que acon- tece quando dois processadores começam a executar essa seção crítica ao mesmo tempo. se houver um desvio. Nota: melhor caso significa que ll/sc sempre tem sucesso.2. . 2. neste problema.2 [10] <2. 2.11> Escreva o código do montador MIPS para essa seção crítica. unlock() . Use instruções ll/sc a fim de implementar a operação lock(). em que “operation” atualiza a variável compartilhada shvar utilizando a variável (não- compartilhada) local x da seguinte maneira: Operação a. ou seja.2 como exemplo. b. max() e min() .29. supondo que o endereço da variável lk esteja em $a0. mas desta vez use ll/sc para realizar uma atualização atômica da variável shvar diretamente. sem usar lock() e unlock().29. seguimos o caminho que completa a operação com a menor quantidade de instruções executadas.5 [10] <2. Explique por que não podemos fazer isso usando a técnica de 2. 2. você deverá incluir as instruções MIPS para as operações lock() .29.1 e 2.2. if(shvar > 0) shvar = max(shvar. clear $t0 b.2 [5] <2.1 [5] <2.30. beq $t1. 0($gp) 4 jal 0 4 jal 0 Segmento de dados 0 (X) Segmento de dados 0 (Y) — — — — Informação de Endereço Tipo de instrução Dependência Informação de Endereço Tipo de Dependência relocação relocação instrução 0 lbu X 0 sw Y 4 jai B 4 jal A Tabela de símbolos Endereço Símbolo Tabela de símbolos Endereço Símbolo — X — Y — B — A . a. LOOP 2. $v0. v 2. 0($gp) 0 sw $a1. bltu $s0.12> Para cada pseudoinstrução na tabela anterior. A tabela a seguir contém algumas instruções do assem- bler do MIPS que são traduzidas para instruções reais do MIPS.31 A tabela a seguir contém os detalhes em nível de link de dois procedimentos diferentes. mas normalmente aparecem nos programas do MIPS.12> A instrução na tabela precisa ser editada durante a fase de link-edição? Por quê? Exercício 2. $t1. A tabela a seguir contém algumas instruções assembly do MIPS que foram traduzidas para instruções reais do MIPS.30 Instruções assembler não são parte do conjunto de instruções do MIPS.30. Loop b. produza uma sequência mínima de instruções MIPS reais a fim de realizar a mesma coisa. a. ulw. large.170 Capítulo 2  Instruções: A Linguagem de Máquina Exercício 2. Na tabela. Você pode ter de usar registradores temporários em alguns casos. large refere-se a um número que exige 32 bits para ser representado e small a um número que pode ser contido em 16 bits. a. você tomará o lugar do link-editor. Procedimento A Procedimento B Segmento de texto Endereço Instrução Segmento de texto Endereço Instrução 0 lbu $a0. Neste exercício. $at.2 [5] <2.3 [5] <2.32 Os três primeiros problemas neste exercício consideram que a função swap. 0 4 jmp 0 — — — — 0x84 jr $ra 0x180 jr $ra — — — … Segmento de dados 0 (X) Segmento de dados 0 (Y) — — — — Informação de Endereço Tipo de instrução Dependência Informação de Endereço Tipo de Dependência relocação relocação instrução 0 lui X 0 sw Y 4 ori X 4 jmp F00 0x180 jal A Tabela de símbolos Endereço Símbolo Tabela de símbolos Endereço Símbolo — X — Y 0x180 F00 — A 2. se houver alguma.13> O que precisa mudar na função sort? 2.2 [5] <2. é definida em C da seguinte forma: 2. 2. Suponha que o Procedimento A tenha um tamanho de texto 0x140. por que um montador poderia ter problemas implementando diretamente as ins- truções de desvio e salto em um arquivo objeto? Exercício 2. 2.24.21 Exercícios 171 b.32.32.31.1 [10] <2.31.1 mudaria? . existem sobre o tamanho de um executável? 2. 2.1 [5] <2. 0($gp) 4 ori $a0.13> Se estivéssemos classificando bytes de 8 bits.32. em vez do código da Figura 2.32.12> Link-edite os arquivos objetos dessa tabela para formar o cabeçalho do arquivo executável.12> Que limitações. tamanho de dados 0x40 e o Procedimento B tenha um tamanho de texto 0x300 e tamanho de dados 0x50. 0 0 sw $a0. e não words de 32 bits.12> Dado o seu conhecimento das limitações das instruções de desvio e salto. Considere também a estratégia de alocação de memória mostrada na Figura 2.13> Traduza esta função para o código do montador MIPS. como o seu código MIPS para o swap em 2.3 [5] <2.31. Procedimento A Procedimento B Segmento de texto Endereço Instrução Segmento de texto Endereço Instrução 0 lui $at.13. 33.1 [10] <2.33.3 [10] <2.33. assim como $s0-$s7? Exercício 2.33. você traduzirá o código assembly do ARM para MIPS. quantas instruções a mais (ou a menos) são executadas como resultado dessa mudança? 2.2 [10] <2.33 Os problemas neste exercício referem-se à função a seguir.13> Ao classificar um array de 10 elementos que já estava classificado em ordem decrescente (oposto à ordem que sort() cria).14> Traduza esta função para o assembly MIPS.32.6 [10] <2.4 se os registradores $t0-$t7 e $a0-$a3 na convenção de chamada do MIPS fossem salvos por quem foi chamado.33. o resultado da verificação de condição é tal que o caminho com mais instruções é escolhido. 2. quantas instruções a mais (ou a menos) são executadas como resultado dessa mudança? Exercício 2. 2. se existe uma instrução if.33.32.34 A tabela a seguir contém o código assembly do ARM. 2. consideramos que a função sort da Figura 2.1 e seu código baseado em ponteiro de 2.14> Converta esta função para o código baseado em ponteiro (em C).13> Essa mudança afeta o código para salvar e restaurar registradores na Figura 2.14> Traduza seu código C baseado em ponteiro de 2. se o resultado da verificação de condição fizer com que o loop termine.33. .6 [5] <2. Nota: o pior caso ocorre quando as condições de desvio são tais que o caminho mais longo pelo código é tomado.5 [10] <2.32.33. dada como um código de array: 2. Use a função swap desde o começo deste exercício.4 [10] <2. 2.27? 2. Nos problemas a seguir. 2. ou seja.5 [5] <2.1 e para o seu código baseado em ponteiro de 2.14> Compare o número de registradores temporários (registradores t) necessários para o seu código baseado em array de 2. 2.3.2 para o assembly MIPS.33.14> Compare o número do pior caso das instruções executadas por iteração de loop não final em seu código baseado em array de 2. então supomos que o caminho que nos mantém no loop é escolhido. Ordene um array de n bytes ao invés de n words. Porém.3.4 [5] <2.172 Capítulo 2  Instruções: A Linguagem de Máquina Para os três problemas restantes neste exercício.27 é alterada da seguinte forma: a.33.13> Ao classificar um array de 10 elementos que já estava classificado.33. b.33.14> O que mudaria na sua resposta de 2. 34. 2. Suponha que os registradores ARM r0 .35.2 2 [5] <2.34.34.16> Para a tabela anterior.35. $s2. $t0 b. a. traduza este código assembly ARM para código assembly MIPS. Exercício 2. A tabela a seguir contém código assembly MIPS. ache o código assembly ARM que corresponde à sequência de código assembly MIPS. r1 e r2 mantenham os mes- mos valores dos registradores MIPS $s0. respectivamente.16> Para a tabela anterior. # s0.1 [5] <2.4 [5] <2. $s2 2. $s1 e $s2. mostre os campos de bit que representam as instruções ARM.) onde for necessário.34. nor $t0. 2.16> Identifique o tipo dos modos de endereçamento das instruções as- sembly do ARM na tabela anterior.16> Para as instruções assembly do ARM anteriores. 16 or $s1. 16 srl $s0.16> Para as instruções assembly ARM na tabela anterior. 2. . $s1. 2. escreva uma se- quência de instruções assembly do MIPS para conseguir a mesma transferência de dados. $s2. Use registradores temporários do MIPS ($t0 etc. 0 and $s1.21 Exercícios 173 2. você irá comparar o código escrito utilizar as configurações de instruções ARM e MIPS. sll $s1.16> Mostre os campos de bit que representam o código assembly ARM. Nos problemas a seguir. você traduzirá o código assembly MIPS para ARM.1 [5] <2.2 [5] <2. A tabela seguinte mostra os códigos escritos na configuração de instruções ARM. Os problemas a seguir exploram esses novos modos de endereçamento. Nos problemas seguintes. $s1. 2.35 O processador ARM tem alguns modos de endereçamento diferentes que não são aceitos no MIPS.3 [5] <2. escreva uma rotina de código assembly MIPS correspondente. 0x2 b. 2.35.36. 2. escreva o código assembly ARM equivalente.16> Escreva o código MIPS equivalente para o código assembly ARM anterior.16> Se o registrador R1 tiver o valor constante de 0x0600 0000.174 Capítulo 2  Instruções: A Linguagem de Máquina 2. – 1 2. Esse exercício investiga essas diferenças.16> Supondo que o CPI médio da rotina assembly MIPS é igual ao CPI médio da rotina assembly ARM.5 vez o processador ARM. A tabela a seguir contém instruções ARM. addi r3.16> Qual é o número total de instruções assembly MIPS exigido para executar o código? Qual é o número total de instruções assembly MIPS exigido para executar o código? 2.4 [5] <2.16> Se o registrador R1 tiver o valor constante de 8. . a. r2.1 [5] <2. 2. e o processador MIPS tem uma frequência de operação que é 1.35. reescreva seu código MIPS para minimizar o número de instruções assembly MIPS necessárias. Exercício 2. r2.36. 2.36.16> Para o código assembly MIPS acima.4 [5] <2. A tabela a seguir contém código assembly x86.37 Este exercício explora as diferenças entre os conjuntos de instruções MIPS e x86. A tabela a seguir contém instruções MIPS. addi r3.16> Para o código assembly ARM anterior. o quanto o processador ARM é mais rápido que o processador MIPS? Exercício 2.3 [5] <2.36 O processador ARM tem um modo interessante de dar suporte a constantes imediatas.3 [10] <2.35.5 [5] <2.2 [5] <2.36. reescreva seu código MIPS para diminuir o número de instruções assembly MIPS necessárias. e como resultado a convenção de chamada do x86 é empurrar todos os argumentos para a pilha.37. Trate o rótulo MY_FUNCTION como uma constante de 32 bits. qual é o ganho de velocidade do uso dessa instrução x86 em vez do código MIPS equivalente quando o ECX é muito grande? Suponha que o tempo de ciclo de clock para x86 e MIPS seja o mesmo.17> Para o código da tabela anterior. 16 bits como um word e 32 bits como um dou- bleword.17> Escreva as instruções assembly MIPS equivalentes. 2. Observe que a arquitetura x86 tem muito poucos registradores em comparação com MIPS. Os três problemas restantes neste exercício referem-se à função a seguir.4 [10] <2.38. Para cada instrução x86.37. $a2 a ESI e $a3 a EAX. 2. que faz com que a instrução seja repetida por determinado número de vezes ou até que uma condição seja satisfeita.3 [10] <2. dada em as- sembly C e x86. Note que as ins- truções x86 referem-se a 8 bits como um byte.17> Qual seria um uso típico para esta instrução? 2.17> Se a instrução x86 exige um ciclo para ler da memória. mostre o tamanho de cada um dos campos de bit que representam a instrução. text eax. também mostramos seu tamanho no formato de instrução de tamanho variável x86 e a interpretação (o que a instrução faz).37. . supondo que $a0 corresponda a ECX.1 [5] <2.17> Escreva o pseudocódigo para a rotina indicada. push eax b. Exercício 2.38. 0x00200010 2. O valor de retorno de uma função x86 é passado de volta a quem chamou no registrador EAX.38 O conjunto de instruções x86 inclui o prefixo REP. $a1 a EDI.17> Para cada instrução assembly. um ciclo para escrever a memória e um ciclo para cada atualização de registrador. 2.37. Os primeiros três problemas deste exercício referem-se às seguintes instruções x86: 2. a. 2. e se o MIPS exigir um ciclo por instrução. qual é o equivalente MIPS para a rotina dada? A tabela seguinte contém instruções assembly x86.2 [[10] <2.38.3 [5] <2.1 [10] <2.17> Escreva o código MIPS que realiza a mesma operação.21 Exercícios 175 2.2 [5] <2. 38. Aritmética Load/Store Desvio a. Explique como isso seria feito no MIPS e como seria feito no x86. Observe que a instrução ret do x86 lê o endereço de retorno da pilha.38. e que a execução toma o caminho mais curto possível pela função (ou seja.17> Se o processador pode executar duas instruções por ciclo.1 [5] <2.17> Se cada instrução MIPS ocupa um ciclo.17> Traduza esta função para o assembly MIPS.38. Compare o tamanho (quantos bytes de memória de instrução são necessários) para este código x86 e para o seu código MIPS. 2. cada loop termina imediatamente e cada instrução if toma a direção que leva para o retorno da função). 1 10 3 b.176 Capítulo 2  Instruções: A Linguagem de Máquina 2. qual é o ganho de velocidade do uso do x86 em vez do MIPS? Suponha que o tempo de ciclo do clock seja o mesmo no x86 e MIPS. Exercício 2.6 [5] <2.39 O CPI dos diferentes tipos de instrução é dado na tabela a seguir. 2.18> Considere o seguinte desmembramento de instruções dado para executar determinado programa: Instruções (em milhões) Aritméticas 500 Load/Store 300 Desvio 100 .39.4 [5] <2.5 [5] <2. ele precisa pelo menos ser capaz de ler duas instruções consecutivas em cada ciclo. e se cada instrução x86 ocupa um ciclo mais um ciclo para cada leitura ou escrita de memória que ele tem de executar. 4 40 3 2. 2.21 Exercícios 177 Qual é o tempo de execução para o processador se a frequência de operação é de 5 GHz? 2.39.2 [5] <2.18> Suponha que instruções aritméticas novas e mais poderosas sejam acrescentadas ao conjunto de instruções. Na média, com o uso dessas instruções aritméticas mais poderosas, podemos reduzir em 25% o número de instruções aritméticas necessárias para executar um programa, e o custo de aumentar o tempo de ciclo de clock em apenas 10%. Essa é uma boa escolha de projeto? Por quê? 2.39.3 [5] <2.18> Suponha que achemos um modo de dobrar o desempenho das instruções aritméticas. Qual é o ganho de velocidade geral de nossa máquina? E se des- cobrirmos um modo de melhorar o desempenho das instruções aritméticas em 10 vezes!? A tabela a seguir mostra as proporções de execução de instruções para diferentes tipos de instrução. Aritméticas Load/Store Desvio a. 70% 10% 20% b. 50% 40% 10% 2.39.4 [5] <2.18> Dado o arranjo de instruções anterior e a suposição de que uma ins- trução aritmética requer dois ciclos, uma instrução de load/store utiliza seis ciclos, e uma instrução de desvio usa três ciclos, ache o CPI médio. 2.39.5 [5] <2.18> Para uma melhoria de 25% no desempenho, quantos ciclos, na média, uma instrução aritmética pode gastar se as instruções de load/store e desvio não forem melhoradas? 2.39.6 [5] <2.18> Para uma melhoria de 50% no desempenho, quantos ciclos, na média, uma instrução aritmética pode gastar se as instruções de load/store e desvio não forem melhoradas? Exercício 2.40 Os três primeiros problemas neste exercício referem-se à função a seguir, dada em assembly MIPS. Infelizmente, o programador dessa função caiu na armadilha de supor que o MIPS é uma máquina endereçada por word, mas na realidade o MIPS é endereçado por byte. 178 Capítulo 2  Instruções: A Linguagem de Máquina Observe que, no assembly MIPS, o caractere “;” indica que o restante da linha é um comentário. 2.40.1 [5] <2.18> A arquitetura MIPS requer que os acessos do tamanho de uma word (lw e sw) sejam alinhados na word, ou seja, os dois bits mais baixos do endereço devem ser, ambos, zero. Se um endereço não for alinhado na word, o processador levanta uma exceção de “erro de barramento”. Explique como esse requisito de barramento afeta a execução dessa função. 2.40.2 [5] <2.18> Se “a” fosse um ponteiro para o início de um array de elementos de um byte, e se substituíssemos lw e sw por lb (load byte) e sb (store byte), respectivamente, essa função estaria correta? Nota: lb lê um byte da memória, o estende por sinal e o coloca no registrador de destino, enquanto sb armazena o byte menos significativo do registrador na memória. 2.40.3 [5] <2.18> Mude esse código para torná-lo correto para inteiros de 32 bits. Os três problemas restantes neste exercício referem-se a um programa que aloca memória para um array, preenche o array com alguns números, chama a função sort da Figura 2.27 e depois imprime o array. A função principal do programa é a seguinte (dada como código C e MIPS): A função my_alloc é definida como a seguir (dada como código C e MIPS). Observe que o programador dessa função caiu na armadilha de usar um ponteiro para uma variável automática arr fora da função em que é definida. A função my_init é definida da seguinte forma (código MIPS): 2.21 Exercícios 179 2.40.4 [5] <2.18> Qual é o conteúdo (valores de todos os cinco elementos) do array v imediatamente antes de a instrução “jal sort” no código main ser executada? 2.40.5 [15] <2.18, 2.13> Qual é o conteúdo do array v imediatamente antes de a função sort entrar em seu loop mais externo pela primeira vez? Suponha que os registradores $sp, $s0, $s1, $s2 e $s3 tenham valores 0x1000, 20, 40 7 e 1, respectivamente, no início do código principal (imediatamente antes que “li $s0, 5” seja executado). 2.40.6 [10] <2.18, 2.13> Qual é o conteúdo do array de cinco elementos apontado por v imediatamente após o “jal sort” retornar ao código main? §2.2, página 80: MIPS, C, Java §2.3, página 87: 2) Muito lento Respostas das §2.4, página 93: 3) –8dec Seções “Verifique §2.5, página 101: 4) sub $s2, $s0, $s1 você mesmo” §2.6, página 104: Ambos. AND com um padrão de máscara de 1s deixa 0s em todo lugar menos no campo desejado. O deslocamento à esquerda pela quantidade correta remove os bits da esquerda do campo. O deslocamento à direita pela quantidade apropriada coloca o campo nos bits mais à direita da palavra, com 0s no restante da palavra. Observe que AND deixa o campo onde ele estava originalmente e o par deslocado move o campo para a parte mais à direita da palavra. §2.7, página 111: I. Todos são verdadeiros. II. 1). §2.8, página 122: Ambos são verdadeiros. §2.9, página 127: I. 2) II. 3) §2.10, página 136: I. 4) +-128K. II. 6) um bloco de 256M. III. 4) sll §2.11, página 139: Ambos são verdadeiros. §2.12, página 148: 4) Independência de máquina. 3 Aritmética Computacional 3.1 Introdução  182 A precisão numérica é a própria 3.2 Adição e subtração  182 alma da ciência. 3.3 Multiplicação  186 3.4 Divisão  191 Sir D’arcy Wentworth Thompson  On Growth and Form, 1917 3.5 Ponto flutuante  197 3.6 Paralelismo e aritmética computacional: Associatividade  219 3.7 Vida real: ponto flutuante no x86  220 3.8 Falácias e armadilhas  222 3.9 Comentários finais  226 3.10 Perspectiva histórica e leitura adicional  228 3.11 Exercícios 228 Os cinco componentes clássicos de um computador 182 Capítulo 3  Aritmética Computacional 3.1   Introdução As palavras do computador são compostas de bits; assim, podem ser representadas como números binários. O Capítulo 2 mostra que os inteiros podem ser representados em formato decimal ou binário, mas e quanto aos outros números que ocorrem normalmente? Por exemplo: j Como são representadas frações e outros números reais? j O que acontece se uma operação cria um número maior do que poderia ser re- presentado? j E por trás de todas essas perguntas existe um mistério: como o hardware realmente multiplica ou divide números? O objetivo deste capítulo é desvendar esse mistério, incluindo a representação dos nú- meros, algoritmos aritméticos, hardware que acompanha esses algoritmos e as implicações de tudo isso para os conjuntos de instruções. Essas ideias podem ainda explicar truques que você já pode ter encontrado nos computadores Subtração: o companheiro esquisito da adição No. 10, Top Ten Courses for 3.2  Adição e subtração Athletes at a Football Factory, David Letterman e outros, Book A adição é exatamente o que você esperaria nos computadores. Dígitos são somados bit of Top Ten Lists, 1990 a bit, da direita para a esquerda, com carries (“vai-uns”), sendo passados para o próximo dígito à esquerda, como você faria manualmente. A subtração utiliza a adição: o operando apropriado é simplesmente negado antes de ser somado. Adição e subtração binária Vamos tentar somar 6dec a 7dec em binário e depois subtrair 6dec de 7dec em binário. EXEMPLO Os 4 bits à direita fazem toda a ação; a Figura 3.1 mostra as somas e os carries. Os carries aparecem entre parênteses, com as setas mostrando como são passados. A subtração de 6dec de 7dec pode ser feita diretamente: RESPOSTA ou por meio da soma, usando a representação de complemento de dois de –6: 3.2  Adição e subtração 183 FIGURA 3.1  Adição binária, mostrando carries da direta para a esquerda. O bit mais à direita adiciona 1 a 0, resultando em uma soma de 1 e um carry out de 0 para esse bit. Logo, a operação para o segundo dígito da direita é 0 + 1 + 1. Isso gera uma soma de 0 e um carry out de 1 para esse bit. O terceiro dígito é a soma de 1 + 1 + 1, resultando em um carry out de 1 e uma soma de 1 para esse dígito. O quarto bit é 1 + 0 + 0, tendo uma soma de 1 e nenhum carry. Já dissemos que o overflow ocorre quando o resultado de uma operação não pode ser representado com o hardware disponível, nesse caso, uma palavra de 32 bits. Quando pode ocorrer um overflow na adição? Quando se somam operandos com sinais diferentes, não poderá haver overflow. O motivo é que a soma não pode ser maior do que um dos operandos. Por exemplo, –10 + 4 = –6. Como os operandos cabem nos 32 bits, e a soma não é maior do que um operando, a soma também precisa caber nos 32 bits. Portanto, nenhum overflow pode ocorrer ao somar operandos positivos e negativos. Existem restrições semelhantes à ocorrência do overflow durante a subtração, mas esse é apenas o princípio oposto: quando os sinais dos operandos são iguais, o overflow pode ocorrer. Para ver isso, lembre-se de que x – y = x + (-y), pois subtraímos negando o segundo operando e depois somamos. Assim, quando subtraímos operandos do mesmo sinal, acabamos somando operandos de sinais diferentes. Pelo parágrafo anterior, sabemos que não pode ocorrer overflow também nesse caso. Tendo examinado quando um overflow pode ocorrer na adição e na subtração, ainda não respondemos como detectar quando ele ocorre. Logicamente, a soma ou a subtração de dois números de 32 bits pode gerar um resultado que precisa de 33 bits para ser totalmente expresso. A falta de um 33° bit significa que, quando o overflow ocorre, o bit de sinal está sendo definido com o valor do resultado, no lugar do sinal apropriado do resultado. Como precisamos apenas de um bit extra, somente o bit de sinal pode estar errado. Logo, o over- flow ocorre quando se somam dois números positivos, e a soma é negativa, ou vice-versa. Isso significa que um carry ocorreu no bit de sinal. O overflow ocorre na subtração quando subtraímos um número negativo de um número positivo e obtemos um resultado negativo, ou quando subtraímos um número positivo de um número negativo e obtemos um resultado positivo. Isso significa que houve um empréstimo do bit de sinal. A Figura 3.2 mostra a combinação de operações, operandos e resultados que indicam um overflow. Acabamos de ver como detectar o overflow para os números em complemento de dois em um computador. E com relação aos inteiros sem sinal? Os inteiros sem sinal normalmente são usados para endereços de memória em que os overflows são ignorados. Logo, o projetista de computador precisa oferecer uma maneira de ignorar o overflow em alguns casos e reconhecê-lo em outros. A solução do MIPS é ter dois tipos de instruções aritméticas para reconhecer as duas escolhas: j Adição (add), adição imediata (addi) e subtração (sub) causam exceções no overflow. j Adição sem sinal (addu), adição imediata sem sinal (addiu) e subtração sem sinal (subu) não causam exceções no overflow. FIGURA 3.2  Condições de overflow para adição e subtração. 184 Capítulo 3  Aritmética Computacional Como a linguagem C ignora os overflows, os compiladores C do MIPS sempre gerarão as versões sem sinal das instruções aritméticas addu , addiu e subu , sem importar o tipo das variáveis. No entanto, os compiladores Fortran do MIPS apanham as instruções Unidade Lógica e Aritmética (ALU)  Hardware que realiza aritméticas apropriadas, dependendo do tipo dos operandos. adição, subtração e normalmente O Apêndice C descreve o hardware que realiza a adição e subtração, que é chamado operações lógicas como AND e OR. de Unidade Lógica e Aritmética, ou ULA. Interface O projetista de computador precisa decidir como tratar overflows aritméticos. Embora algumas linguagens como C e Java ignorem o overflow de inteiros, linguagens como Ada hardware/ e Fortran exigem que o programa seja notificado. O programador ou o ambiente de pro- software gramação precisa, então, decidir o que fazer quando ocorre o overflow. O MIPS detecta o overflow com uma exceção, também chamada de interrupção em exceção  Também chamada muitos computadores. Uma exceção ou interrupção é basicamente uma chamada de interrupção. Um evento não procedimento não planejada. O endereço da instrução que gerou o overflow é salvo em planejado que interrompe um registrador e o computador desvia para um endereço predefinido, a fim de invocar a a execução do programa; usada para rotina apropriada para essa exceção. O endereço interrompido é salvo de modo que, em detectar overflow. algumas situações, o programa possa continuar após o código corretivo ser executado. (A Seção 4.9 abrange as exceções com mais detalhes; os Capítulos 5 e 6 descrevem outras interrupção  Uma exceção que vem de fora do processador. situações em que ocorrem exceções e interrupções.) (Algumas arquiteturas utilizam o O MIPS inclui um registrador, chamado contador de programa de exceção (EPC – Ex- termo interrupção para todas as ception Program Counter), para conter o endereço da instrução que causou a exceção. A exceções.) instrução move from system control (mfc0) é usada a fim de copiar o EPC para um regis- trador de uso geral, de modo que o software do MIPS tem a opção de retornar à instrução problemática por meio de uma instrução jump register. Aritmética para Multimídia Já que cada microprocessador desktop por definição tem suas próprias telas gráficas, e como as quantidades de transistores aumentaram, foi inevitável que seria acrescentado suporte para operações gráficas. Muitos sistemas gráficos originalmente usavam 8 bits para representar cada uma das três cores primárias, mais 8 bits para um local de um pixel. O acréscimo de alto-falantes e microfones para teleconferência e jogos de vídeo sugeriu também o suporte para som. As amostras de áudio precisam de mais de 8 bits de precisão, mas 16 bits são suficientes. Cada microprocessador tem suporte especial, de modo que os bytes e meias palavras ocupam menos espaço quando armazenados na memória (veja Seção 2.9), mas, em razão da infrequência das operações aritméticas nesses tamanhos de dados nos programas de inteiros típicos existe pouco suporte além das transferências de dados. Os arquitetos reconhecem que muitas aplicações gráficas e de áudio realizariam a mesma operação sobre vetores desses dados. Particionando as cadeias de carry dentro de um somador de 64 bits, um processador poderia realizar operações simultâneas sobre vetores curtos de operandos de 8 bits, quatro operandos de 16 bits ou dois operandos de 32 bits. O custo desses somadores particionados era pequeno. Essas extensões têm sido chamadas de vetor ou SIMD, para única instrução, múltiplos dados (veja Seção 2.17 e Capítulo 7). Um recurso geralmente não encontrado nos microprocessadores de uso geral é a satu- ração de operações. A saturação significa que, quando um cálculo estoura, o resultado é definido como o maior número positivo ou o maior número negativo, em vez de um cálculo de módulo, como na aritmética do complemento de dois. A saturação provavelmente é o que você deseja para operações de mídia. Por exemplo, o botão de volume em um aparelho de rádio seria frustrante se, enquanto você o girasse, o volume aumentasse continuamente 3.2  Adição e subtração 185 por um tempo e depois imediatamente ficasse baixo. Um botão com saturação pararia no volume mais alto, não importa o quanto você o girasse. A Figura 3.3 mostra as operações aritméticas e lógicas encontradas em muitas extensões de multimídia dos conjuntos de instruções modernos. FIGURA 3.3  Resumo do suporte de multimídia para computadores desktop. Detalhamento:  o MIPS pode interceptar um overflow, mas, diferente de muitos outros computadores, não existe desvio condicional para testar o overflow. A sequência de instruções do MIPS pode descobrir overflow. Para a adição com sinal, a sequência é a seguinte (veja o Detalhamento na Seção 2.6 do Capítulo 2, para obter uma descrição da instrução xor): Para adição sem sinal ( $t0 = $t1 + $t2 ), o teste é Resumo A questão principal desta seção é que, independente da representação, o tamanho finito da palavra dos computadores significa que as operações aritméticas podem criar resultados muito grandes para caber nesse tamanho de palavra fixo. É fácil detectar o overflow em números sem sinal, embora quase sempre sejam ignorados, pois os programas não querem detectar overflow para a aritmética de endereço, o uso mais comum dos números naturais. O complemento de dois apresenta um desafio maior, embora alguns sistemas de software exijam detecção de overflow, de modo que, hoje, todos os computadores tenham um meio de detectá-lo. A crescente popularidade das aplicações de multimídia levou a instruções aritmé- ticas que dão suporte a operações mais estreitas, que podem operar facilmente em paralelo. 186 Capítulo 3  Aritmética Computacional Verifique você Algumas linguagens de programação permitem a aritmética de inteiros em complemento de mesmo dois com variáveis declaradas com um byte e meio. Que instruções do MIPS seriam usadas? 1. Load com lbu, lhu ; aritmética com add, sub, mult, div ; depois, armazenamento usando sb, sh. 2. Load com lb, lh ; aritmética com add, sub, mult, div ; depois, armazenamento usando sb, sh. 3. Load com lb, lh; aritmética com add, sub, mult, div; usando AND para mascarar o resultado com 8 ou 16 bits após cada operação; depois, armazenamento usando sb, sh. Detalhamento:  no texto anterior, dissemos que você copia o EPC para um registrador por meio de mfc0 e depois retorna ao código interrompido por meio de jump register. Isso leva a uma pergunta interessante: já que você primeiro precisa transferir o EPC para um registrador a fim de usar com jump register, como jump register pode retornar ao código interrompido e restaurar os valores originais de todos os registradores? Você restaura os registradores antigos primeiro, destruindo, assim, seu endereço de retorno do EPC, que colocou em um registrador para uso em jump register, ou restaura todos os registradores, menos aquele com o endereço de retorno, para que possa desviar – significando que uma exceção resultaria em alterar esse único registrador a qualquer momento durante a execução do programa! Nenhuma dessas opções é satisfatória. Para auxiliar o hardware nesse dilema, os programadores MIPS concordaram em reservar os registradores $k0 e $k1 para o sistema operacional; esses registradores não são restaurados nas exceções. Assim como os compiladores MIPS evitam o uso do registrador $at, de modo que o montador possa utilizá-lo como um registrador temporário (veja a Seção “Interface Hardware/ Software”, na Seção 2.10), os compiladores também se abstêm do uso dos registradores $k0 e $k1, de modo que fiquem disponíveis para o sistema operacional. As rotinas de exceção colocam o endereço de retorno em um desses registradores e depois usam o jump register para armazenar o endereço da instrução. Detalhamento:  A velocidade da adição é aumentada determinando-se o carry in para os bits de alta ordem mais cedo. Existem diversos esquemas para antecipar o carry, de modo que o cenário do pior caso é uma função do log2 do número de bits no somador. Esses sinais antecipados são mais rápidos, pois percorrem menos portas na sequência, mas exigem mais portas para antecipar o carry apropriado. O mais comum é o carry lookahead, descrito na Seção C.6 do Apêndice C no site. Multiplicação é vexação, Divisão também é ruim; A regra de três me intriga, e a 3.3   Multiplicação prática me deixa louco. Anônimo, manuscrito de Agora que completamos a explicação de adição e subtração, estamos prontos para montar Elizabeth, 1570 a operação mais vexatória da multiplicação. Primeiro, vamos rever a multiplicação de números decimais à mão para nos lembrar das etapas e dos nomes dos operandos. Por motivos que logo se tornarão claros, limitamos esse exemplo decimal ao uso apenas dos dígitos 0 e 1. Multiplicando 1000dec por 1001dec: Multiplicando 1000dec Multiplicador × 1001dec 1000 0000 0000 1000 Produto 1001000dec 3.3 Multiplicação 187 O primeiro operando é chamado multiplicando e o segundo é o multiplicador. O re- sultado final é chamado produto. Como você pode se lembrar, o algoritmo aprendido na escola é pegar os dígitos do multiplicador um a um, da direita para a esquerda, calculando a multiplicação do multiplicando pelo único dígito do multiplicador e deslocando o produto intermediário um dígito para a esquerda dos produtos intermediários anteriores. A primeira observação é que o número de dígitos no produto é muito maior do que o número no multiplicando ou no multiplicador. De fato, se ignorarmos os bits de sinal, o tamanho da multiplicação de um multiplicando de n bits por um multiplicador de m bits é um produto que possui n + m bits de largura. Ou seja, n + m bits são necessários para representar todos os produtos possíveis. Logo, como na adição, a multiplicação precisa lidar com o overflow, pois constantemente desejamos um produto de 32 bits como resultado da multiplicação de dois números de 32 bits. Neste exemplo, restringimos os dígitos decimais a 0 e 1. Com somente duas opções, cada etapa da multiplicação é simples: 1. Basta colocar uma cópia do multiplicando (1 x multiplicando) no lugar apropriado se o dígito do multiplicador for 1, ou 2. Colocar 0 (0 x multiplicando) no lugar apropriado se o dígito for 0. Embora o exemplo decimal anterior utilize apenas 0 e 1, a multiplicação de números binários sempre usa 0 e 1 e, por isso, sempre oferece apenas essas duas opções. Agora que já revisamos os fundamentos tradicionais da multiplicação, a próxima etapa é mostrar o hardware de multiplicação altamente otimizado. Quebramos essa tradição na crença de que você entenderá melhor vendo a evolução do hardware e do algoritmo de multiplicação no decorrer das diversas gerações. Por enquanto, vamos supor que es- tamos multiplicando apenas números positivos. Versão sequencial do algoritmo e hardware de multiplicação Esse projeto imita o algoritmo que aprendemos na escola; o hardware aparece na Figura 3.4. Desenhamos o hardware de modo que os dados fluam de cima para baixo, para que fique mais semelhante à técnica do lápis e papel. Vamos supor que o multiplicador esteja no registrador Multiplicador de 32 bits e que o registrador Produto de 64 bits esteja inicializado como 0. Pelo exemplo de lápis e papel, visto anteriormente, fica claro que precisaremos mover o multiplicado para a esquerda um FIGURA 3.4  Primeira versão do hardware de multiplicação. O registrador do Multiplicando, a ALU, e o registrador do Produto possuem 64 bits de largura, apenas com o registrador do Multiplicador contendo 32 bits. ( O Apêndice C descreve as ALUs.) O multiplicando com 32 bits começa na metade direita do registrador do Multiplicando e é deslocado à esquerda 1 bit em cada etapa. O multiplicador é deslocado na direção oposta em cada etapa. O algoritmo começa com o produto inicializado com 0. O controle decide quando deslocar os registradores Multiplicando e Multiplicador e quando escrever novos valores no registrador do Produto. 188 Capítulo 3  Aritmética Computacional dígito a cada passo, pois pode ser somado aos produtos intermediários. Durante 32 etapas, um multiplicando de 32 bits moveria 32 bits para a esquerda. Logo, precisamos de um registrador Multiplicando de 64 bits, inicializado com o multiplicando de 32 bits na metade direita e 0 na metade esquerda. Esse registrador, em seguida, é deslocado 1 bit para a es- querda a cada etapa, de modo a alinhar o multiplicando com a soma sendo acumulada no registrador Produto de 64 bits. A Figura 3.5 mostra as três etapas clássicas necessárias para cada bit. O bit menos significativo do multiplicador (Multiplicador0) determina se o multiplicando é somado ao registrador Produto. O deslocamento à esquerda na etapa 2 tem o efeito de mover os operandos intermediários para a esquerda, assim como na multiplicação manual. O des- locamento à direita na etapa 3 nos indica o próximo bit do multiplicador a ser examinado na iteração seguinte. Essas três etapas são repetidas 32 vezes, para obter o produto. Se cada etapa usasse um ciclo de clock, esse algoritmo exigiria quase 100 ciclos de clock para multiplicar dois números de 32 bits. A importância relativa de operações aritméticas, como a multiplicação, varia com o programa, mas a soma e a subtração podem ser de 5 a 100 vezes mais comuns do que a multiplicação. Como consequência, em muitas aplicações, a multiplicação pode demorar vários ciclos de clock sem afetar o desempenho de forma significativa. Mesmo assim, a lei de Amdahl (veja Seção 1.8) nos lembra que até mesmo uma frequência moderada para uma operação lenta pode limitar o desempenho. FIGURA 3.5  O primeiro algoritmo de multiplicação, usando o hardware mostrado na Figura 3.4. Se o bit menos significativo do multiplicador for 1, some o multiplicando ao produto. Caso contrário, vá para a etapa seguinte. Desloque o multiplicando para a esquerda e o multiplicador para a direita nas duas etapas seguintes. Essas três etapas são repetidas 32 vezes. 3.3 Multiplicação 189 Esse algoritmo e o hardware são facilmente refinados para usar 1 ciclo de clock por etapa. O aumento de velocidade vem da realização das operações em paralelo: o multiplicador e o multiplicando são deslocados enquanto o multiplicando é somado ao produto se o bit do multiplicador for 1. O hardware simplesmente precisa garantir que testará o bit da direita do multiplicador e receberá a versão previamente deslocada do multiplicando. O hardware normalmente é otimizado ainda mais para dividir a largura do somador e dos registradores ao meio, observando onde existem partes não utilizadas dos registradores e somadores. A Figura 3.6 mostra o hardware revisado. Substituir a aritmética por deslocamentos também pode ocorrer quando se multiplica por Interface constantes. Alguns compiladores substituem multiplicações por constantes curtas com uma série de deslocamentos e adições. Como deslocar um bit à esquerda representa um hardware/ número duas vezes maior na base 2, o deslocamento de bits para a esquerda tem o mesmo software efeito de multiplicar por uma potência de 2. Como dissemos no Capítulo 2, quase todo compilador realizará a otimização por redução de força substituindo uma multiplicação na potência de 2 por um deslocamento à esquerda. FIGURA 3.6  Versão refinada do hardware de multiplicação. Compare com a primeira versão na Figura 3.4. O registrador Multiplicando, a ALU, e o registrador Multiplicador possuem 32 bits de extensão, com somente o regis- trador Produto restando nos 64 bits. Agora, o produto é deslocado para a direita. O registrador Multiplicador separado também desapareceu. O multiplicador é colocado na metade direita do registrador Produto. Essas mudanças estão destacadas. (O registrador Produto na realidade deverá ter 65 bits, a fim de manter o carry do somador, mas ele aparece aqui como 64 bits para destacar a evolução da Figura 3.4.) Um algoritmo de multiplicação Usando números de 4 bits para economizar espaço, multiplique 2 dec x 3 dec , ou 0010bin x 0011bin. EXEMPLO A Figura 3.7 mostra o valor de cada registrador para cada uma das etapas rotuladas de acordo com a Figura 3.5, com o valor final de 0000 0110bin ou 6dec. A cor é usada RESPOSTA para indicar os valores de registrador que mudam nessa etapa e o bit circulado é aquele examinado para determinar a operação da próxima etapa. 190 Capítulo 3  Aritmética Computacional FIGURA 3.7  Exemplo de multiplicação usando o algoritmo da Figura 3.5. O bit examinado para determinar a próxima etapa está circulado. Multiplicação com sinal Até aqui, tratamos de números positivos. O modo mais fácil de entender como tratar dos números com sinal é primeiro converter o multiplicador e o multiplicando para números positivos e depois lembrar dos sinais originais. Os algoritmos deverão, então, ser executados por 31 iterações, deixando os sinais fora do cálculo. Conforme aprendemos na escola, o produto só será negativo se os sinais originais forem diferentes. Acontece que o último algoritmo funcionará para números com sinais se nos lem- brarmos de que os números com que estamos lidando possuem dígitos infinitos e que só os estamos representando com 32 bits. Logo, as etapas de deslocamento precisariam estender o sinal do produto para números com sinal. Quando o algoritmo terminar, a palavra menos significativa terá o produto de 32 bits. Multiplicação mais rápida A Lei de Moore ofereceu tantos recursos que os projetistas de hardware agora podem cons- truir um hardware de multiplicação muito mais rápido. Não importa se o multiplicando deve ser somado ou não, isso é conhecido no início da multiplicação analisando cada um dos 32 bits do multiplicador. Multiplicações mais rápidas são possíveis basicamente fornecendo um somador de 32 bits para cada bit do multiplicador: uma entrada é o AND do multiplicando pelo bit do multiplicador e a outra é a saída de um somador anterior. Uma técnica simples seria conectar as saídas dos somadores à direita das entradas dos somados à esquerda, criando uma pilha de somadores com altura 32. Um modo alternati- vo de organizar essas 32 adições é em uma árvore paralela, como mostra a Figura 3.8. Em vez de esperar 32 tempos de add, esperamos apenas o log2(32) ou cinco tempos de add com 32 bits. A Figura 3.8 mostra como esse é o modo mais rápido de conectá-los. De fato, a multiplicação pode se tornar ainda mais rápida do que cinco tempos de add, veja uso de somadores para salvar carry (veja Seção C.6 no Apêndice C) e porque é fácil usar um pipeline nesse projeto para que possam ser realizadas muitas multiplicações simultaneamente (veja Capítulo 4). Multiplicação no MIPS O MIPS oferece um par separado de registradores de 32 bits, de modo a conter o produto de 64 bits, chamados Hi e Lo. Para produzir um produto com ou sem o devido sinal, o MIPS possui duas instruções: multiply (mult) e multiply unsigned (multu). Para apanhar o produto de 32 bits inteiro, o programador usa move from lo (mflo). O montador MIPS gera uma pseudoinstrução para multiplicar, que especifica três registradores de uso geral, gerando instruções mflo e mfhi que colocam o produto nos registradores. Em vez de usar um único somador de 32 bits 31 vezes.4 Divisão 191 FIGURA 3. ainda menos frequente e ainda mais Maquiavel. Os compiladores utilizam até mesmo as instruções de deslocamento para multiplicações por potências de dois. Ela oferece até mesmo a oportunidade de realizar uma operação matematicamente inválida: dividir por 0. a fim de testar o overflow. máxima política antiga. software Divide et impera. Resumo A multiplicação é feita pelo hardware simples de deslocamento e adição.010dec por 1000dec: 1001dec Quociente Divisor1000dec 1001010dec Dividendo −1000 10 101 1010 −1000 10dec Resto . de modo que fica a critério do Interface software verificar se o produto é muito grande para caber nos 32 bits. para lembrar os nomes dos operandos e do algoritmo de divisão que aprendemos na escola. A instrução move from hi (mfhi) hardware/ pode ser usada para transferir Hi a um registrador de uso geral.8  Hardware da multiplicação rápida. vamos limitar os dígitos decimais a apenas 0 ou 1. esse hardware “desenrola o loop” para usar 31 somadores e depois os organiza para minimizar o atraso.4   Divisão Tradução do latim para “Dividir e conquistar”. 3. 3. Vamos começar com um exemplo de divisão longa usando números decimais.001. Por motivos semelhantes aos da seção anterior. O exemplo é a divisão de 1. 1532 peculiar. derivado do método de lápis e papel que aprendemos na escola. As duas instruções multiply do MIPS ignoram o overflow. citada por A operação recíproca da multiplicação é a divisão. Não existe overflow se Hi for 0 para multu ou o sinal replicado de Lo para mult. lembre-se de que é assim que realizamos a comparação na instrução set on less than. logo. O divisor é deslocado para a direita e depois repetimos.10 mostra três etapas do primeiro algoritmo de divisão. Raramente os programas utilizam a instrução quando multiplicado pelo divisor de divisão só para obter o resto. de modo que a divisão binária é restrita a essas duas opções. e ignoraremos o sinal por enquanto. o quociente e o resto sejam não negativos. .9 mostra o hardware para imitar nosso algoritmo da escola. um número que. o divisor foi menor ou igual ao dividendo. Se o resultado for positivo.9  Primeira versão do hardware de divisão. dividendo. de modo que geramos um 1 no quociente (etapa 2a). O registrador Resto é inicializado com o dividendo. acompanhados por um segundo resultado. o computador não é inteligente o bastante para saber.192 Capítulo 3  Aritmética Computacional Os dois operandos (dividendo e divisor) e o resultado (quociente) da divisão são dividendo  Um número sendo dividido. com antecedência. Os números quando somado ao produto do binários contêm apenas 0 ou 1. em que o resto é menor do que o divisor. de modo que começaremos com o divisor colocado na metade esquerda do registrador Divisor de 64 bits e o deslocaremos para a direita 1 bit a cada etapa. Veja aqui outra maneira de expressar o relacionamento entre os componentes: divisor  Um número pelo qual o dividendo é dividido. Os operandos da divisão e os dois resultados são valores de 32 bits. Vamos supor que o dividendo e o divisor sejam positivos e. O divisor de 32 bits começa na metade esquerda do registrador Divisor e é deslocado 1 bit para a direita em cada iteração. Algoritmo e hardware de divisão A Figura 3. a próxima etapa é restaurar o valor original. a ALU e o registrador Resto possuem 64 bits de largura. tenta ver o quanto um número dividendo. Cada iteração do algoritmo precisa des- locar o divisor para a direita um dígito. Se o resultado é negativo. Ao contrário dos humanos. produz o O algoritmo básico de divisão. A Figura 3. FIGURA 3. O resto e o quociente serão encontrados em seus registradores de mesmo nome depois que as iterações terminarem. Começamos com o registrador Quociente de 32 bits definido como 0. somando o divisor de volta ao resto e gerar um 0 no quociente (etapa 2b). a divisão binária. pode ser subtraído. de modo que é fácil resto  O resultado secundário de uma divisão. criando um dígito do quociente em cada tentativa. com apenas o registrador Quociente tendo 32 bits. e somado ao resto. O controle decide quando deslocar os registradores Divisor e Quociente e quando escrever o novo valor para o registrador Resto. Dividendo = Quociente × Divisor + Resto quociente  O resultado principal de uma divisão. um número que. O registrador Divisor. quociente pelo divisor. a fim de alinhá-lo com o dividendo. Ele primeiro precisa subtrair o divisor na etapa 1. se o divisor é menor do que o dividendo. que aprendemos na escola. Nosso exemplo decimal cuidadosamente selecionado usa apenas os números 0 e 1. produz o simplificando. descobrir quantas vezes o divisor cabe na parte do dividendo: deve ser 0 ou 1. ignorando o quociente. O resto é inicializado com o dividendo. chamado resto. assim. revertendo. Um algoritmo de divisão Usando uma versão de 4 bits do algoritmo para economizar páginas.4 Divisão 193 FIGURA 3. a subtração da etapa 1. 3. de modo que a etapa 2a gera um 1 no quociente.10  Um algoritmo de divisão.9. . de modo que a etapa 2b gera um 0 no quociente e soma o divisor ao resto. vamos tentar dividir 7dec por 2dec. Se o Resto é positivo. O deslocamento final. EXEMPLO A Figura 3. para a próxima iteração.11 mostra o valor de cada registrador para cada uma das etapas. Observe que o teste na etapa 2 (se o resto é RESPOSTA positivo ou negativo) simplesmente testa se o bit de sinal do registrador Resto é um 0 ou um 1. assim. usando o hardware da Figura 3. alinha o divisor corretamente. o divisor coube no dividendo. com o quociente sendo 3dec e o resto sendo 1dec. O requisito surpreendente desse algoritmo é que ele utiliza n + 1 etapas para obter o quociente e resto corretos. na etapa 3. Essas etapas são repetidas 33 vezes. em relação ao dividendo. ou 0000 0111bin por 0010bin. Um Resto negativo após a etapa 1 significa que o divisor não coube no dividendo. A Figura 3. (Assim como na Figura 3. Divisão com sinal Até aqui. Esse algoritmo e esse hardware podem ser refinados para que sejam mais rápidos e menos dispendiosos. Essa melhoria divide ao meio a largura do somador e dos registradores. A rapidez vem do deslocamento dos operandos e do quociente no mesmo momento da subtração.10. Lembre-se de que a seguinte equação precisa ser sempre mantida: Dividendo = Quociente × Divisor + Resto Para entender como definir o sinal do resto. Essa versão também combina o registrador Quociente com a metade direita do registrador Resto. A solução mais simples é lembrar os sinais do divisor e do dividendo e depois negar o quociente se os sinais forem diferentes.9.194 Capítulo 3  Aritmética Computacional FIGURA 3. os registradores ALU e Divisor são divididos ao meio.) . Detalhamento:  Uma complicação da divisão com sinal é que também temos de definir o sinal do resto. com apenas o registrador Resto ficando com 64 bits.12 mostra o hardware revisado.12  Uma versão melhorada do hardware de divisão. a ALU e o registrador Quociente possuem 32 bits de largura.6. O primeiro caso é fácil: +7 ÷+ 2:Quociente =+ 3. observando onde existem partes não usadas dos registradores e somadores. vejamos o exemplo da divisão de todas as combinações de ± 7dec por ± 2dec. Em comparação com a Figura 3.11  Exemplo de divisão usando o algoritmo da Figura 3. e o resto é deslocado à esquerda.Resto =+1 FIGURA 3. O registrador Divisor. O bit examinado para determinar a próxima etapa está em destaque. ignoramos os números com sinal na divisão. o registrador Resto na realidade deveria ter 65 bits para garantir que o carry do somador não se perca. que também caberia nessa fórmula. mas não podemos fazer o mesmo truque para a divisão.Resto = +1 −7 ÷ −2 :Quociente = +3.12. enquanto.Resto = −1 Verificando os resultados novamente: −7 = −3 × 2 + (−1) = −6 − 1 O motivo pelo qual a resposta não é um quociente de –4 e um resto de +1. A precisão desse método rápido depende de haver valores apropriados na tabela de pesquisa. com a multiplicação. Hi contém o resto. A chave é descobrir o valor para subtrair. o quociente também precisa mudar: −7 ÷ +2 :Quociente = −3 Reescrevendo nossa fórmula básica para calcular o resto: Resto = (Dividendo − Quociente × Divisor) = −7 − (−3 × +2) = −7 − (−6) = −1 Assim. o algoritmo de divisão com sinal nega o quociente se os sinais dos operandos foram opostos e faz com que o sinal do resto diferente de zero corresponda ao dividendo. Com a divisão binária. Um valor comum hoje é 4 bits. usando uma pesquisa numa tabela baseada nos bits mais significativos do dividendo e do resto. que pode deslocar para a esquerda ou para a direita e uma ALU de 32 bits que soma ou subtrai. Divisão no MIPS Você já pode ter observado que o mesmo hardware sequencial pode ser usado para multi- plicação e divisão nas Figuras 3. Existem técnicas para produzir mais de um bit do quociente por etapa. Divisão mais rápida Usamos muitos somadores para agilizar a multiplicação. não importa quais sejam os sinais do divisor e do quociente. existe somente uma única opção. −7 ÷ +2 :Quociente = −3. Ela conta com as etapas subsequentes para corrigir escolhas erradas. 3. Esses algoritmos utilizam 6 bits do resto e 4 bits do divisor para indexar uma tabela que determina a opção para cada etapa. Como poderíamos esperar do algoritmo anterior. O único requisito é um registrador de 64 bits. tanto para multiplicação quanto para divisão. O montador MIPS permite que as instruções de . Esse comportamento anômalo é evitado seguindo-se a regra de que o dividendo e o resto devem ter os mesmos sinais. o MIPS possui duas instruções: divide (div) e divide unsigned (divu). O motivo é que precisamos saber o sinal da diferença antes de po- dermos realizar a próxima etapa do algoritmo. o MIPS utiliza os registradores Hi e Lo de 32 bits.Resto = −1 Assim. A técnica de divisão SRT tenta descobrir vários bits do quociente por etapa. se −(x + y) ≠ (−x ) ÷ y a programação seria um desafio ainda maior. Logo.4 Divisão 195 Verificando os resultados: 7 = 3 × 2 + (+1) = 6 + 1 Se você mudar o sinal do dividendo. é que o valor absoluto do quociente mudaria dependendo do sinal do dividendo e do divisor! Logicamente.6 e 3. Calculamos as outras combinações seguindo a mesma regra: +7 ÷ −2 :Quociente = −3. Para lidar com inteiros com sinal e inteiros sem sinal.8 mostra o que pode acontecer se a tabela es- tiver incorreta. A falácia apresentada na Seção 3. poderíamos calcular os 32 produtos parciais imediatamente. e Lo contém o quociente após o término da instrução de divisão. A linguagem de máquina do MIPS aparece no Guia de referência rápida. gerando as instruções mflo ou mfhi para colocar o resultado desejado em um registrador de uso geral.13  Arquitetura MIPS revelada até aqui. no início do livro. Resumo O suporte de hardware comum para multiplicação e divisão permite que o MIPS ofereça um único par de registradores de 32 bits usados tanto para multiplicar quanto para dividir. mas esta seção acrescentou os registradores Hi e Lo para dar suporte à multiplicação e à divisão. FIGURA 3. A memória e os registradores da arquitetura MIPS não estão incluídos por questões de espaço.196 Capítulo 3  Aritmética Computacional divisão especifiquem três registradores. A Figura 3.13 resume os acréscimos à arquitetura MIPS das duas últimas seções. . 1. mas foi maior do que poderíamos representar com um inteiro de 32 bits com sinal.0dec × 10−9 (segundos em um nanossegundo) 3. Como a base não é 10.5   Ponto flutuante direção errada. Um número na notação científica que não tem que apresenta números com um único dígito à esquerda do ponto 0s à esquerda do ponto decimal é chamado de número normalizado. também precisamos de ponto flutuante Aritmética um novo nome para o ponto decimal. as linguagens de programação admitem números com frações.1dec × 10-8 e 10. a divisão também pode resultar em um cálculo impróprio: divisão por 0. A velocidade não o leva a lugar algum se você estiver na 3. 1. o número não representou uma fração pequena. é chamada ponto flutuante números em que o ponto binário não é fixo. A linguagem de programação C utiliza o nome float para esses números. que é o modo normal decimal.15576dec × 109 (segundosem um século típico) Observe que. é explorado ainda mais nos exercícios. também não possui 0s à esquerda do ponto podemos mostrar números binários em notação científica: decimal. mas 0. Em binário. Ele simplesmente soma o dividendo ao resto deslocado na etapa seguinte. de modo que o software precisa determi. Esse algoritmo de divisão sem restauração.0 bin × 2−1 Para manter um número binário na forma normalizada. que admite tais números. o ponto binário funcionará bem. porque representa os números em que o ponto binário não é fixo. como acontece para os inteiros. Alguns computadores distinguem esses dois eventos hardware/ anômalos. pois (r + d) x 2 – d = r x 2 + d x 2 – d = r x 2 + d.0dec × 10-10 não estão.000000001dec ou1. O software MIPS precisa verificar o divisor para descobrir a divisão por 0 e software também o overflow. Provérbio americano Indo além de inteiros com e sem sinal. Somente uma base de 2 atende à nossa necessidade. Detalhamento:  um algoritmo ainda mais rápido não soma imediatamente o divisor se o resto for negativo. xxxxxxxx bin × 2 yyyy .000dec ou 3.155. como o escrevemos. precisamos de uma base que possamos aumentar ou diminuir exatamente pelo número de bits que o número precisa ser deslocado para ter um dígito diferente de zero à esquerda do ponto decimal.14159265…dec (pi) 2. normalizado  Um número na notação de ponto flutuante que Assim como podemos mostrar números decimais em notação científica. os números são representados como um único dígito diferen- te de zero à esquerda do ponto binário. Um terceiro algoritmo. o formato é 1. que são chamados reais na matemática.0dec × 10-9 está em notação científica normalizada. computacional que representa os A aritmética computacional. 3. A notação alternativa para os dois últimos números é chamada notação científica. que tem um notação científica  Uma notação único dígito à esquerda do ponto decimal. Aqui estão alguns exemplos de números reais: 3. Interface nar se o quociente é muito grande. é chamado algoritmo de divisão sem o retorno esperado. Assim como na notação científica. que usa um clock por etapa. Além do overflow. Por exemplo. no último caso. Ele reduz em média um terço de operações aritméticas. o algoritmo aqui apresentado é chamado de divisão com restauração.760.5  Ponto flutuante 197 Instruções de divisão MIPS ignoram o overflow.71828…dec (e) 0. que não salva o resultado da subtração se ele for negativo. e as operações sobre palavras de 32 bits. as pessoas chamam esse evento de underflow. significa que você precisa tirar um bit de um para acrescentar um bit ao outro. o valor colocado no campo de expoente. bom projeto exige um bom compromisso. caber no campo de expoente. Ela simplifica a troca de dados. simplifica os algoritmos aritméticos de ponto flutuante. para simplificar a notação. e aumenta a precisão dos números que podem ser armazenados em uma palavra. Representação em ponto flutuante Um projetista de uma representação em ponto flutuante precisa encontrar um compromis- fração  O valor. doubles são indicadas como aritmética de ponto flutuante com precisão dupla. pois os 0s desnecessários são substituídos por dígitos reais à direita do ponto binário. interrupções por overflow podem ocorrer na arit- Uma situação em que um expoente mética de ponto flutuante e também na aritmética de inteiros. um aritmética de ponto flutuante. como vemos a seguir. Assim. bem como o restante do número. em que s é o sinal do número de ponto flutuante (1 significa negativo). extraordinário é diferente de infinito. os dois eventos poderiam resultar caber no campo de expoente. pois o sinal possui um bit separado do res- tante do número. esse número é chamado double.198 Capítulo 3  Aritmética Computacional (Embora o computador represente o expoente na base 2. colocado no campo de fração. In- felizmente. o rela- cionamento exato com esses campos será explicado em breve. Conforme nosso guia de projetos do Capítulo 2 nos lembra. Essa situação ocorre quando o expoente negativo é muito grande para caber no campo de expoente. Frações quase tão pequenas quanto 2. expoente é o valor do campo de expoente em 11 bits. Essa troca é entre a precisão e o intervalo: aumentar o tamanho da fração melhora a precisão da expoente  No sistema de fração.) Esses tamanhos escolhidos de expoente e fração dão à aritmética do computador MIPS um intervalo extraordinário. em que s ainda é o sinal do número. mostramos o expoente em decimal. Assim como underflow (ponto flutuante) Uma os programadores desejarão saber quando calcularam um número muito grande para ser situação em que um expoente representado. em um programa com respostas incorretas. ponto flutuante representado em A representação de um número em ponto flutuante com precisão dupla utiliza duas uma única palavra de 32 bits. Em C.) Uma notação científica padrão para os números reais no formato normalizado oferece três vantagens. Para distinguir do overflow. por saber que os números sempre estarão nessa forma. geralmente entre 0 so entre o tamanho da fração e o tamanho do expoente. enquanto aumentar o tamanho do expoente aumenta o intervalo de números que representação numérica da podem ser representados. de modo que ainda é possível que os overflow (ponto flutuante)  números sejam muito grandes. Observe que overflow aqui positivo torna-se muito grande para significa que o expoente é muito grande para ser representado no campo de expoente. que incluem números em ponto flutuante. também desejarão saber se a fração diferente de zero que estão calculando negativo torna-se muito grande para tornou-se tão pequena que não pode ser representada. pois um tamanho de palavra fixo e 1. precisão dupla  Um valor de ponto Uma maneira de reduzir as chances de underflow ou overflow é oferecer outro formato flutuante representado em duas que tenha um expoente maior.0dec × 1038 podem ser representados em um computador. A representação de um número em ponto flutuante MIPS aparece a seguir.0dec × 10-38 e números quase tão grandes quanto 2. o ponto precisão simples  Um valor de flutuante com precisão simples é o nome do formato anterior. expoente é o valor do campo de expoente com 8 bits (incluindo o sinal do expoente) e fração é o número de 23 bits. O ponto flutuante também oferece um novo tipo de evento excepcional. os números em ponto flutuante estão no formato (−1)S × F × 2E F envolve o valor no campo de fração e E envolve o valor no campo de expoente. 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 s expoente fração 1 bit 8 bits 23 bits Em geral. Essa representação é chamada sinal e magnitude. . (Logo veremos que o MIPS faz algo ligeiramente mais sofisticado. e fração é o número de 52 bits na fração. palavras MIPS. Os números em ponto flutuante normalmente são múltiplos do tamanho de uma pala- vra. 14  Codificação IEE 754 dos números de ponto flutuante. que será explicado em detalhes mais adiante. e fração quando queremos dizer o número de 23 ou 52 bits. (Para os que são matematicamente treinados. o programa imprimirá um símbolo de infinito. 3. de modo que o hardware não lhe acrescente um 1 inicial. o software pode definir o resultado para um padrão de bits que represente +∞ ou –∞. Se numerarmos os bits da fração da esquerda para a direita de s1. então o valor é (− (−1)S × (1 + (s1 × 2−1 ) + (s2 × 2−2 ) + (s3 × 2−3 ) + (s4 × 2−4 ) + …) × 2E A Figura 3. 24 bits de largura na precisão simples (1 implícito e fração de 23 bits) e 53 bits de extensão na precisão dupla (1 + 52). ele recebe o valor de expoente reservado 0. Essa informação também é encon- trada na coluna 4 do Guia de Instrução Rápida no início deste livro. Esses formatos vão além do MIPS. na realidade. encontrado em praticamente todo computador inventado desde 1980. 00…00bin representa 0. Logo. Para colocar ainda mais bits no significando. Esse padrão melhorou bastante tanto a facilidade de portar programas de ponto flutuante quanto a qualidade da aritmética computacional. usamos o termo significando a fim de representar o número de 24 ou 53 bits que é 1 mais a fração. em consequência do significando maior.14 mostra as codificações dos números de ponto flutuante IEEE 754. . s3. sua principal vantagem é sua maior precisão. em vez de interromper em uma divisão por 0. Quando o programador imprime os resultados. Para ser exato. Um bit de sinal separado determina o sinal. a representação do restante dos números usa a forma de antes. Eles fazem parte do padrão de ponto flutuante IEEE 754. Assim. o IEEE 754 deixa implícito o bit 1 inicial dos números binários normalizados. Os números desnormalizados são descritos no Detalhamento na página 270. o maior expoente é reservado a esses símbolos especiais. Embora a precisão dupla não aumente o in- tervalo do expoente. Ou- tros recursos do IEEE 754 são símbolos especiais para representar eventos incomuns. s2. e E especifica o valor no campo de expoente. Por exemplo.0dec × 10–308 e quase tão grandes quanto 2.) FIGURA 3. Como 0 não possui um 1 inicial.5  Ponto flutuante 199 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 s expoente fração 1 bit 11 bits 20 bits fração (continuação) 32 bits A precisão dupla do MIPS permite números quase tão pequenos quanto 2. …. com o 1 oculto sendo acrescentado: (−1)S × (1 + Fração) × 2E em que os bits da fração representam um número entre 0 e 1. a finalidade do infinito é formar o fechamento topológico dos reais. o número tem.0dec × 10308. para determinar o valor real. O expoente deslocado significa que o valor representado por um número em ponto flutuante é. . como 0/0. na realidade: (−1)S × (1 + Fração) × 2(Expoente−Bias) A faixa de números de precisão simples é. . per- mitindo um teste rápido de menor que. um expoente negativo se parecerá com um número grande. Esse símbolo é NaN. pois os números com expoentes maiores são maiores do que os números com expoentes menores. precisa representar o expoente mais negativo como 00 … 00bin e o mais positivo como 11 … 11bin.) O valor 1. de modo que –1 é representado pelo padrão de bits do valor –1 + 127dec ou 126dec = 0111 1110bin. de Not a Number (não é um número). O número –0. portanto.00000000000000000000000 bin × 2−126 até ±1. . ou a subtração entre infinito e infinito. então.) Colocar o expoente antes do significando simplifica a ordenação dos números de ponto flutuante usando instruções de comparação de inteiros. Expoentes negativos impõem um desafio à ordenação simplificada. Representação de ponto flutuante Mostre a representação binária IEEE 754 para o número –0.11111111111111111111111bin × 2+127 Vamos mostrar a representação. A notação desejável.200 Capítulo 3  Aritmética Computacional O IEEE 754 até mesmo possui um símbolo para o resultado de operações inválidas. Se usarmos o com- plemento de dois ou qualquer outra notação em que os expoentes negativos têm um 1 no bit mais significativo do campo de expoente. Por exemplo. em vez do complemento de dois. A finalidade dos NaNs é permitir que os programadores adiem alguns testes e decisões para outro momento no programa. sem sinal. desde ±1. quando for conveniente. com a inclinação (bias) sendo o número subtraído da representação normal. 1. e +1 é representado por 1 + 127 ou 128dec = 1000 0000bin. . pois essa notação é basicamente sinal e magnitude. especialmente para ordenação. Essa convenção é chamada notação deslocada. desde que os dois ex- poentes tenham o mesmo sinal.75dec em precisão sim- EXEMPLO ples e dupla. maior que ou igual a 0. O IEEE 754 usa um bias de 127 para a precisão simples.75dec também é RESPOSTA −3 / 4 dec ou − 3 / 2dec 2 .0bin × 2-1 seria representado como 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . Esse desejo é o motivo pelo qual o sinal está no bit mais significativo. (Isso é um pouco mais complicado do que uma ordenação simples de inteiros. (Lembre-se de que o 1 à esquerda do ponto é implícito no significando. Os projetistas do IEEE 754 também queriam uma representação de ponto flutuante que pudesse ser facilmente processada por comparações de inteiros.0bin × 2+1 seria semelhante a um número binário menor 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . 75dec. o campo de expoente contém 129 e o campo de fração contém 1 × 2–2 = 1/4. portanto.5  Ponto flutuante 201 Ele também é representado pela fração binária −11bin / 2dec 2 ou − 0.25. é 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1 0 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 bit 8 bits 23 bits A representação em precisão dupla é (−1)1 × (1 + .1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 bin ) × 2(1022−1023) 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1 0 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 bit 11 bits 20 bits 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 bits Agora.1bin × 2−1 A representação geral para um número de precisão simples é (−1)S × (1 + Fração) × 2(Expoente−127) Quando subtraímos o bias 127 do expoente de –1. 25) × 2(129−127) = −1 × 1.11bin Em notação científica. o resultado é (−1)1 × (1 + . O bit de sinal é 1. ou 0. 25 × 4 = −5. .1bin × 2–1. 25 × 22 = −1. vamos experimentar na outra direção. na notação científica normalizada. RESPOSTA (−1)S × (1 + Fração) × 2(Expoente-Bias) = (−1)1 × (1 + 0. 3.1000 0000 0000 0000 0000 000 bin ) × 2(126−127) A representação binária de precisão simples de 0. o valor é −0. Convertendo ponto flutuante binário para decimal Que número decimal é representado por este float de precisão simples? EXEMPLO 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . Usando a equação básica.0 . . ele é −1.11bin × 20 e.  Como pressupomos que o significando só pode ter quatro dígitos de extensão (ex- cluindo o sinal). Mainframes IBM recentes admitem IEEE 754 além do formato hexa. Adição em ponto flutuante Vamos somar os números na notação científica manualmente. para ilustrar os problemas na adição em ponto flutuante: 9. mas. depois da adição. Etapa 1. nas figuras.01610dec × 101 O número da direita é a versão que desejamos. Etapa 4. na realidade: 0. alguns computadores antes do padrão IEEE 754 usavam uma base diferente de 2. Em seu núcleo. Etapa 3. os dígitos hexadecimais significam que até 3 bits precisam ser removidos do significando. Sempre que o expoente é aumentado ou diminuído. Detalhamento:  em uma tentativa de aumentar o intervalo sem remover bits do significando.016dec 10‚015dec A soma é 10. Essa soma não está na notação científica normalizada. mas é preciso que haja manutenção extra para lidar com os expoentes e normalizar o resultado. os computadores mainframe IBM 360 e 370 usam a base 16. Suponha que só possamos armazenar quatro dígitos decimais do significando e dois dígitos decimais do expoente. de modo que precisamos ajustá-la: 10. Por exemplo. temos de arredondar o número. 9.999dec × 101.0015dec × 102 Assim. Esse exemplo mostra o deslocamen- to para a direita.016dec × 101 Etapa 2.015dec × 101 = 1. temos de verificar o overflow ou underflow – ou seja.  Em seguida. o número é.1610dec × 100 = 0. Assim. temos de alinhar o ponto decimal do número que possui o menor expoente. daremos os algoritmos para a adição e multiplicação em ponto flutuante. Contudo. Obtemos isso observando que existem várias representações de um número em ponto flutuante não normalizado na notação científica: 1. Em nosso algoritmo que aprendemos .610dec × 10-1. se um número fosse positivo e o outro negativo. o que leva a problemas surpreendentes na precisão da aritmética de ponto flutuante. binária. Logo. precisamos de uma forma do número menor. Para poder somar esses números corretamente. temos de verificar se o expoente ainda cabe em seu campo. os números de base 16 “normalizados” podem ter até 3 bits à esquerda do ponto em 0s! Logo. eles utilizam operações inteiras correspondentes nos significan- dos. oferecemos uma derivação intuitiva dos algoritmos em decimal. e depois uma versão mais detalhada.015dec × 101. é possível que a soma tenha muitos 0s iniciais. Primeiro. pois seu expoente combina com o expoente do maior número.999dec × 101 + 1.202 Capítulo 3  Aritmética Computacional Nas próximas seções. só podemos representar quatro dígitos deci- mais. que combine com o expoente maior. exigindo deslocamentos à esquerda. a primeira etapa desloca o significando do menor número à direita até que seu expoente corrigido combine com o do maior número. ajustando o expoente de acordo. 1. Como mudar o expoente no IBM em um significa deslocar o significando em 4 bits. de modo que. vem a adição dos significandos: 9‚999dec + 0.610dec × 10−1 = 0. podemos ter de deslocar a soma para colocá-la na forma normalizada. após o deslocamento.610dec × 10–1. 0015dec × 102 é arredondado para quatro dígitos no significando. O número 1. mas se o arredondamento fizer com que a soma fique não normalizada. As etapas 1 e 2 são semelhantes ao exemplo que discutimos: FIGURA 3. temos de repetir a etapa 3. como ao somar 1 a uma sequência de 9s.15 mostra o algoritmo para a adição binária de ponto flutuante que acompa- nha este exemplo em decimal.15  Adição de ponto flutuante. 3. sendo necessário realizar a etapa 3 novamente. O caminho normal é executar as etapas 3 e 4 uma vez. passando para 1. Observe que. as regras truncam o número se o dígito à direita do ponto desejado estiver entre 0 e 4 e somamos 1 ao dígito se o número à direita estiver entre 5 e 9.002dec × 102 pois o quarto dígito à direita do ponto decimal estava entre 5 e 9. a soma não pode mais ser normalizada.5  Ponto flutuante 203 na escola. A Figura 3. se não tivermos sorte no arredondamento. . (O expoente deslocado seria – 4 + 127.4375 dec em binário usando o algoritmo da EXEMPLO Figura 3.111bin × 2−1 Etapa 2. O significando do número com o menor expoente (-1.001bin × 2−1 Etapa 3. então 1.5 dec e –0.0625dec Essa soma é o que esperaríamos da soma de 0.000 bin × 2−4 = 0.0111bin = −0. o menor e o maior expoente deslocado não reservado.000 bin × 2−4  soma já cabe exatamente em 4 bits. forçando uma verificação de overflow ou underflow.11bin × 2-2) é deslocado para a direita até seu expoente combinar com o maior número: −1.110 bin × 2−2 = −0. o expoente máximo é 127. verificando overflow ou underflow: 0. O teste de overflow e underflow na etapa 3 depende da precisão dos operandos.16 esboça a organização básica do hardware para a adição de ponto flutuante. supondo que mantemos 4 bits de precisão: 0. . vejamos a versão binária dos dois números na notação científica normali- RESPOSTA zada. o padrão de todos os bits um no expoente é reservado para indicar valores e situações fora do escopo dos números de ponto flutuante normais (veja a Seção “Detalhamento” na página 270). Essa soma é.0001bin = 1 / 2dec 4 = 1 /16dec = 0. A Figura 3.000 bin × 2−4 C omo 127  ≥ 04 ≥ –126.  Some os significandos: 1.1bin = 0. Os limites para precisão dupla são 1023 e –1022.  Normalize a soma. Muitos computadores dedicam o hardware para executar operações de ponto flutuante o mais rápido possível. Adição de ponto flutuante em decimal Tente somar os números 0. não existe overflow ou underflow.100 bin × 2−3 = 1.001bin × 2−1 = 0.010 bin × 2−2 = 0.000 bin × 2−1 + (−0.0001000 bin = 0.) Etapa 4. ou 123. Além disso.0111bin × 20 = −1. e o expoente mínimo é –126. Lembre-se de que o padrão de todos os bits zero no expoente é reservado e usado para a representação de ponto flutuante de zero. de modo que não há mudança nos bits A em razão do arredondamento.  Arredonde a soma: 1.000 bin × 2−1 −0. Assim.1bin × 20 = 1.4375dec. 4375dec = −7 /16dec = −7 / 2dec4 = −0. Primeiro.110 bin × 2−2 Agora. A etapa 3 normaliza os resultados. que está entre 1 e 254. para a precisão simples.15.111bin × 2−1 ) = 0.5dec a –0.204 Capítulo 3  Aritmética Computacional ajustar o significando do número com o menor expoente e depois somar os dois significan- dos.5dec = 1 / 2 dec = 1 / 21dec = 0. seguimos o algoritmo: Etapa 1. que pode exigir normalização novamente para produzir o resultado final. desloca a soma para a esquerda ou para a direita e incrementa ou decrementa o expoente. Essa diferença controla os três multiplexadores. assim .5  Ponto flutuante 205 FIGURA 3. As etapas da Figura 3. de cima para baixo. Multiplicação em ponto flutuante Agora que já explicamos a adição em ponto flutuante. O menor significando é deslocado para a direita. 3. eles selecionam o maior expoente. e depois os significandos são somados usando a ALU grande. Ao contrário da adição. Primeiro. então. o significando do menor número e o significando do maior número. cria o resultado final. o expoente de um operando é subtraído do outro usando a ALU pequena para determinar qual é maior e quanto.16  Diagrama de bloco de uma unidade aritmética dedicada à adição em ponto flutuante.15 correspondem a cada bloco.110dec × 1010 × 9. então. Começamos multiplicando os números decimais em notação científica na mão: 1. Etapa 1. Suponha que possamos armazenar apenas quatro dígitos do significando e dois dígitos do expoente.200dec × 10–5. para obtermos o mesmo resul- V tado: 10 + 127 = 137. O arredondamento. calculamos o expoente do produto simplesmente somando os expoentes dos operandos: Novoexpoente = 10 + (−5) = 5  amos fazer isso com os expoentes deslocados. da esquerda para a direita. vamos experimentar a multiplicação em ponto flutuante. e –5 + 127 = 122. A etapa de normalização. pois estamos somando os biases e também os expoentes: Novoexpoente = (10 + 127) + (−5 + 127) = (5 + 2 × 127) = 259 De acordo com isso. Logo.021dec × 106 O sinal da soma no algoritmo de adição foi determinado pela adição dos signifi- candos. para obter a soma deslocada correta quando somamos números deslocados. o sinal é positivo. A a fim de colocá-lo no formato normalizado. temos de subtrair o bias da soma: Novoexpoente = 137 + 122 − 127 = 259 − 127 = 132 = (5 + 127) e 5 é. Consideramos que o significando tem apenas quatro dígitos de largura (excluindo o sinal). O underflow pode ocorrer se os dois operandos forem pequenos – ou seja.212 × 105. de modo que devemos arredondar o número. o sinal do produto é determinado pelos sinais dos operandos. 212dec × 105 = 1. somando 1 ao expoente.  Este produto não está normalizado. caso contrário. . na realidade. O número 1. Etapa 4. se ambos tiverem expoentes negativos grandes. porém.206 Capítulo 3  Aritmética Computacional Novoexpoente = 137 + 122 = 259  sse resultado é muito grande para o campo de expoente de 8 bits. O sinal do produto depende dos sinais dos operandos originais. Etapa 2. de modo que E há algo faltando! O problema é com o bias. 212000dec S upondo que só possamos manter três dígitos à direita do ponto decimal. é negativo. Se forem iguais. após a multiplicação.0212dec × 106 é arredondado para quatro dígitos no significando. o expoente que calculamos inicialmente. Nesse ponto.021dec × 106 Etapa 5. o produto é 10.0212dec × 106  ssim. o produto é +1. na multiplicação. para 1. vem a multiplicação dos significandos: 1‚110dec × 9‚200dec 0000 0000 2220 9990 10212000dec  xistem três dígitos à direita do ponto decimal para cada operando. Etapa 3. de modo que precisamos normalizá-lo: 10. o produto pode ser deslocado para a direita um dígito. de modo E que o ponto decimal é colocado seis dígitos a partir da direita no significando do produto: 10. podemos verificar o overflow e o underflow.  Em seguida. seguida por uma etapa de normalização opcional. somando os expoentes deslocados. em busca de overflow ou underflow. definimos o bit de sinal como 1 se os sinais dos operandos forem diferentes (produto negativo) ou como 0 se forem iguais (produto positivo). O tamanho do expoente é verificado. mais uma vez verificamos o tamanho do expoente. e depois o produto é arredondado. 3.17  Multiplicação em ponto flutuante. Finalmente. . como mostra a Figura 3. temos de repetir a etapa 3. mas se o arredondamento fizer com que a soma fique desnormalizada. está a multiplicação de significandos. Se o arredondamento causar mais normalização. O caminho normal é executar as etapas 3 e 4 uma vez. Começamos calculando o novo expoente do produto.17.5  Ponto flutuante 207 Mais uma vez. subtraindo um bias para obter o resultado apropriado. FIGURA 3. a multiplicação de números binários em ponto flutuante é muito semelhante às etapas que acabamos de concluir. Em seguida. não existe overflow ou underflow. verificamos o produto para ter certeza de que está normalizado e depois verificamos o expoente em busca de overflow ou underflow. Em binário.d) j Subtração simples em ponto flutuante (sub.5dec e –0.4375 dec . a tarefa é multiplicar 1.d) .208 Capítulo 3  Aritmética Computacional Multiplicação em ponto flutuante em decimal EXEMPLO Vamos tentar multiplicar os números 0. RESPOSTA Etapa 1.110bin × 2–2. Instruções de ponto flutuante no MIPS O MIPS admite os formatos de precisão simples e dupla do padrão IEEE 754 com estas instruções: j Adição simples em ponto flutuante (add.s) e adição dupla (add.5 dec e –0. na realidade. o produto é −1.s) e subtração dupla (sub. Logo. para verificar nossos resultados: −1. Etapa 3. Como os sinais dos operandos originais diferem. (Usando a representação deslocada.  Multiplicando os significandos: 1‚000 bin × 1‚110 bin 0000 1000 1000 1000 1110000 bin O produto é 1. de modo que é 1.110 bin × 2−3 Etapa 5.001110 bin = −0. 21875dec O produto entre 0. mas precisamos mantê-lo com 4 bits.110 bin × 2−3 = −0. usando as etapas na Figura 3. O produto já está normalizado e.000bin × 2–1 por –1.) Etapa 4.110bin × 2–3.21875dec.  Somando os expoentes sem bias: −1 + (−2) = −3 ou então.110 bin × 2−3 Convertendo para decimal.  O arredondamento do produto não causa mudança: 1.4375dec é. como 127 ≥ –3 ≥ –126. 254 ≥ 124 ≥ 1.110000bin × 2–3. torne o sinal do produto negativo.00111bin = −7/25dec = −7/32dec = −0. Agora. –0.17. usando a representação deslocada: (−1 + 127) + (−2 + 127) − 127 = (−1 − 2) + (127 + 127 − 127) = − 3 + 127 = 124 Etapa 2. de modo que o expoente cabe. . eles incluíram loads e stores separados para registradores de ponto flu- tuante: lwc1 e swc1 . menor que (lt).18 resume a parte de ponto flutuante da arquitetura MIPS revelada neste capítulo. 32 bits de F2 Um registrador de precisão dupla é. $f2… – usados para precisão simples ou precisão dupla. Semelhante à Figura 2.d) j Divisão simples em ponto flutuante (div.x($sp) # Lê número P. O maior impacto é criar um conjunto separado de instruções de transferência de dados para mover dados entre os registradores de ponto flutuante e a memória. ter o dobro da largura de banda de registrador. alguns computadores convertem todos os operandos dimensionados nos regis- tradores para um único formato inteiro.19. dependendo da condição de comparação. um par de registradores (par e ímpar) de precisão simples. e ser capaz de personalizar registradores para ponto flutuante. As- sim.s) e divisão dupla (div. $f1. O código do MIPS para carregar dois números de precisão simples da memória.d) j Comparação simples em ponto flutuante (c. menor ou igual (le).z($sp) # Armazena número P. com as adições para dar suporte ao ponto flutuante mostradas em destaque. 3. Os projetistas do MIPS decidiram acrescentar registradores de ponto flutuante separados – chamados $f0.s) e multiplicação dupla (mul. Como os programas hardware/ normalmente realizam operações com inteiros e operações com ponto flutuante sobre dados diferentes. somá-los e depois armazenar a soma poderia se parecer com isto: lwc1 $f4.x. Logo.$f4.$f6 # F2 = F4 + F6 precisão simples swc1 $f2. 32 bits em F4 lwc1 $f6.y($sp) # Lê número P. Os benefícios dos registradores de ponto flutuante separados são a existência do dobro dos registradores sem utilizar mais bits no formato da instrução. e um desvio de ponto flutuante então decide se desviará ou não. mostramos a codificação dessas instruções na Figura 3. na realidade.F. Os registradores base para transferências de dados de ponto flutuante continuam sendo registradores inteiros. o par de registradores $f2 e $f3 também forma o registrador de precisão dupla chamado $f2. A Figura 3.F. diferente (neq).x. maior que (gt) ou maior ou igual (ge) j Desvio verdadeiro em ponto flutuante (belt) e desvio falso (bc1f) A comparação em ponto flutuante define um bit como verdadeiro ou falso. a separação dos registradores só aumentará ligeiramente o número de software instruções necessárias para executar um programa. por exemplo.d).F. em que x pode ser igual (eq). Uma questão que os projetistas de computador enfrentam no suporte à aritmética de ponto flutuante é se devem utilizar os mesmos registradores usados pelas instruções com Interface inteiros ou acrescentar um conjunto especial de ponto flutuante. usando o número do registrador par como seu nome.s $f2. dependendo da condição. 32 bits em F6 add.19 no Capítulo 2.s) e comparação dupla (c.5  Ponto flutuante 209 j Multiplicação simples em ponto flutuante (mul. com conjuntos de registradores separados para inteiros e números de ponto flutuante. no início deste livro. Ver Apêndice B. para obter mais detalhes.210 Capítulo 3  Aritmética Computacional FIGURA 3.18  Arquitetura de ponto flutuante do MIPS revelada até aqui. Essa informação também é encontrada na coluna 2 do Guia de Instrução Rápida do MIPS. Seção B.10. . especificado na parte do meio da figura. lw se encontra na linha número 4 (100bin para os bits de 31-29 da instrução) e na coluna número 3 (011bin para os bits 28-26 da instrução).t) ou falso (bit 16 = 1 => bc1.c testa o estado verdadeiro (bit 16 = 1 => bc1. FlPt na linha 2 e coluna 1 (op = 010001bin) está definido na parte inferior da figura. de modo que rs = 10000) ou precisão dupla (f= d. O sublinhado indica que o campo é usado em outro lugar. o bit 16 da instrução determina se a instrução bc1. Por exemplo. 3. Essa notação indica o valor de um campo por linha e por coluna. determina se a operação é de precisão simples (f = s. de modo que o valor correspondente do campo op (bits 31-26) é 100011bin. .f). Essa informação também é encontrada na coluna 2 do Guia de Instrução Rápida do MIPS. de modo que rs = 10001).f na linha 0 e coluna 1 da seção inferior significa que o campo funct (bits 5-0 da instrução) é 000001bin e o campo op (bits 31-26) é 010001bin. com o Apêndice B abordando todas as instruções. De modo semelhante. sub. Por exemplo.5  Ponto flutuante 211 FIGURA 3. Observe que o campo rs de 5 bits. na parte superior da figura.19  Codificação de instruções de ponto flutuante do MIPS. As instruções em negrito são descritas nos Capítulos 2 neste capítulo. no início deste livro. Logo. assim. e depois retornamos: Agora. As duas primei- ras instruções carregam as constantes 5.212 Capítulo 3  Aritmética Computacional Compilando um programa C de ponto flutuante em código assembly do MIPS Vamos converter uma temperatura em Fahrenheit para Celsius: EXEMPLO Considere que o argumento de ponto flutuante fahr seja passado em $f12 e o resultado deva ficar em $f0. colocando o produto em $f0 como resultado de retorno. Vamos supor que X. Compilando um procedimento em C de ponto flutuante com matrizes bidimensionais no MIPS A maioria dos cálculos de ponto flutuante é realizada com precisão dupla.0/9. (Ao contrário dos registradores inteiros.) Qual é o código assembly do MIPS? Consideramos que o compilador coloca as três constantes de ponto flutuante na memó- RESPOSTA ria para serem alcançadas facilmente por meio do ponteiro global $gp.0 nos registradores de ponto flutuante: Depois. Vamos EXEMPLO realizar uma multiplicação de matrizes X = X + Y * Z.0 durante a compilação e guardariam uma única constante 5. Y e Z sejam matrizes quadradas com 32 elementos em cada dimensão. a divisão em tempo de execução. evitando.0 e depois a subtraímos de fahr ($f12): Finalmente.0/9. multiplicamos os dois resultados intermediários.0 por 9.0 e 9. carregamos a constante 32.) Em seguida. código comumente encontrado em programas científicos. . elas são divididas para que se obtenha a fração 5.0 na memória.0: (Muitos compiladores dividiriam 5. vamos realizar operações de ponto flutuante em matrizes. o registrador de ponto flutuante 0 pode conter um número. acumula a soma dos produtos de y[i][k] e z[k][j] nesse mesmo registrador. multiplicamos pelo tamanho de um elemento da matriz em bytes. para obter a que desejamos. Como 32 é uma potência de 2. para um par de registradores de ponto flutuante). multiplicamos o índice da primeira dimensão pelo tamanho da li- nha. lwc1 ou swc1. $a1 e $a2. podemos deslocar à esquerda por 3: Em seguida. Como o índice do loop é k.d e s. O corpo do procedimento começa salvando o valor de término do loop (32) em um registrador temporário e depois inicializando as três variáveis do loop for: Para calcular o endereço de x[i][j] precisamos saber como um array bidimen- sional de 32 × 32 é armazenado na memória. dando o endereço de x[i] [j]. Em vez disso. Assim. o compilador lê x[i][j] em um registrador fora do loop. Como cada elemento tem 8 bytes para a precisão dupla. respectivamente. e depois armazena a soma em x[i][j]. Qual é o código assembly do MIPS para o corpo do procedimento? Observe que x[i][j] é usado no loop mais interno. acrescentamos o segundo índice para selecionar o elemento j da linha desejada: Para transformar essa soma em um índice em bytes. e l. Assim. Como você poderia esperar. de modo que estão em $a0. 3. Mantemos o código mais simples. podemos usar um deslocamento em seu lugar: Agora. $s1 e $s2. o índice não afeta x[i][j]. e depois carregamos o número de precisão dupla x[i][j] em $f4: .d (que o montador trans- forma em um par de instruções de transferência de dados. Suponha que as variáveis inteiras estejam em $s0. somamos essa soma ao endereço base de x. seu layout é como se houvesse 32 arrays unidimensionais. usando as pseudoinstruções em assembly li (que carrega uma constante em um registrador). ou linhas. cada um com 32 elementos. a primeira etapa é pular os i “arrays unidimensionais”. de modo que podemos evitar a leitura e o armazenamento RESPOSTA de x[i][j] a cada iteração. ao terminar o loop mais interno.5  Ponto flutuante 213 Os endereços iniciais do array são parâmetros. 32. e depois acumulamos a soma em $f4. $f2. Se for 32. por sua vez. é usado pela linguagem C e muitas outras linguagens de programação. De modo semelhante. De modo semelhante. o final do loop mais interno.214 Capítulo 3  Aritmética Computacional As cinco instruções a seguir são praticamente idênticas às cinco últimas: calcular o endereço e depois ler o número de precisão dupla z[k][j]. Agora que carregamos todos os dados. precisamos armazenar em x[i][j] a soma acumulada em $f4. as cinco instruções a seguir são como as cinco últimas: calcular o endereço e depois carregar o número de precisão dupla y[i][k]. finalmente estamos prontos para realizar algumas operações em ponto flutuante! Multiplicamos os elementos de y e z locali- zados nos registradores $f18 e $f16.…. essas quatro instruções finais incrementam a variável de índice do loop do meio e do loop mais externo. O bloco final incrementa o índice k e retorna se o índice não for 32. Detalhamento:  Somente 16 dos 32 registradores de ponto flutuante do MIPS puderam ser usados originalmente para operações de precisão simples: $f0. $f4. usa a ordem colunas primeiro. A precisão dupla é calculada usando pares desses registradores. Os registradores de ponto flutuante com números ímpares só foram usados para carregar e armazenar a metade direita . pela qual o array é armazenado coluna por coluna. voltando no loop se o índice não for 32 e saindo se o índice for 32. ou seja. $f30. chamado ordem linhas primeiro. Detalhamento:  o layout do array discutido no exemplo. Fortran. o termo “coprocessador” reúne “acumulador” e “memória”. mas arredondar com precisão exige que o arredondamento  Método para hardware inclua bits extras no cálculo. Vamos fazer um exemplo decimal para ilustrar o valor desses dígitos extras.d e s. Detalhamento:  Java abarca o padrão IEEE 754 por nome em sua definição dos tipos de dados e operações de ponto flutuante Java. digamos. mas cada array pode ter seu próprio tamanho. Por exemplo. calculando uma recíproca de precisão extra.) Desde o início da década de 1990. F5 Detalhamento:  Outro motivo para que os registradores inteiros e de ponto flutuante sejam separados é que os microprocessadores na década de 1980 não possuíam transistores suficientes para colocar a unidade ponto flutuante no mesmo chip da unidade de inteiros. Nos exemplos anteriores. 3. não haveria oportunidade para arredondar. são aproximações para um número que não representam realmente. aproximação desejada. opcionalmente estava disponível como um segundo chip. respectivamente. F4 é equivalente a add. F2. outra técnica para aproveitar um multiplicador rápido é a iteração de Newton. ser representado no formato. que é a unidade de ponto flutuante.4. que não são admitidos explicita- mente em Java. e. portanto. o número mais próximo que pode tém dois bits extras à direita durante adições intermediárias. fomos vagos com rela. Assim. que é multiplicada pelo outro operando. Ela também precisaria verificar se a referência ao objeto não é nula. MIPS-32 acrescentou l. O arredondamento parece muito simples.d ao conjunto de instruções. ao contrário de vários arrays dimensionais em C. em geral. clara. F2. usados para melhorar a precisão do oferece vários modos de arredondamento para permitir que o programador selecione a arredondamento. descrita no Capítulo 5. . Aritmética de precisão Ao contrário dos inteiros. incluindo um novo cálculo de tamanho no final da linha. F3. o mente. os números de ponto flutuante. o código no primeiro exemplo poderia muito bem ter sido gerado para um método de classe que convertesse graus Fahrenheit em Celsius. que podem representar exatamente cada número entre o menor e o maior. Como os exemplos no Capítulo 2. 0 e 1. os microprocessadores têm integrado o ponto flutuante (e praticamente tudo o mais) no chip. F4. incluindo os registradores de ponto flutuante. em que uma única instrução resulta em duas operações paralelas de ponto flutuante sobre dois operandos de 32 bits dentro de registradores de 64 bits. As técnicas de iteração não podem ser arredondadas corretamente sem o cálculo de muitos bits extras. Esses chips aceleradores opcionais são chamados coprocessadores e explicam o acrônimo para os loads de ponto flutuante no MIPS: lwc1 significa “load word to coprocessor 1” (“leia uma palavra para o coprocessador 1”). Além de SRT. flutuante intermediário se encaixe no formato de ponto flutuante. dondamento.ps F0.5  Ponto flutuante 215 dos números de ponto flutuante de 64 bits. sempre man. chamados guarda e arre. O motivo é que existe uma variedade infinita guarda  O primeiro dos dois bits de números reais entre.s F0. por isso. Um chip TI soluciona esse problema. Assim. Detalhamento:  Conforme mencionamos na Seção 3. (O coprocessador 0 trata da memória virtual. mas. fazer com que o resultado de ponto ção ao número de bits que uma representação intermediária pode ocupar. MIPS-32 também acrescentou versões “simples emparelhadas” de todas as ins- truções de ponto flutuante. acelerar a divisão é mais complicado do que a multiplicação. o padrão IEEE 754 números de ponto flutuante. porém não mais do que 253 podem ser representados extras mantidos à direita durante com exatidão em ponto flutuante de precisão dupla. O melhor que podemos fazer é utilizar os cálculos intermediários de a representação de ponto flutuante próxima ao número real. ps F1. Java permite arrays de arrays. O IEEE 754. na qual a divisão é redefinida como a localização do zero de uma função para encontrar a recíproca 1/x. Logo. a unidade de ponto flutuante. uma versão Java desse segundo exemplo exigiria muito código de verificação para os limites de array. seguido por add. se cada resultado intermediário tivesse de ser truncado ao número de dígitos objetivo normalmente é encontrar exato. add. O segundo exemplo utiliza múltiplos arrays dimensionais. trunque. se for par. O IEEE 754 tem quatro modos de arredondamento: sempre arredondar para cima (para +∞). a fim de alinhar os RESPOSTA expoentes. o IEEE 754 garante que o computador utiliza o número que está dentro de meia ulp.50 dólares para cima. Esse modo é o mais utilizado. 2‚34 dec + 0‚02dec 2‚36dec A resposta é 2. Desde que não haja qualquer overflow.3656dec × 102. Um produto binário pode ter um bit 0 inicial. a multiplicação pode precisar de dois. O modo final determina o que fazer se o número estiver exatamente no meio. na realidade. Primeiro. truncar e arredondar para o próximo par. ele estaria menos significativos do significando defasado por 2 ulps. Arredondar a soma para cima com três dígitos significativos gera 2. Um modo mais imparcial seria arredondar para cima. Fazer isso sem dígitos de guarda e arredondamento remove dois dígitos do cálculo. e o único que o Java admite.34 dec × 102 . Isso desloca o dígito de guarda para o bit menos significativo do produto. Se o número ficou defasado em 2 nos bits menos significativos. deixando o bit de arredondamento para ajudar no arredondamento mais preciso do produto. de modo que 2. O IEEE 754 diz que. possivelmente para o benefício da Receita. dando nome ao arredondamento.216 Capítulo 3  Aritmética Computacional Arredondando com dígitos de guarda Some 2. na metade do tempo e arredondar para baixo na outra metade. Como o pior caso para o arredondamento seria quando o número real está a meio cami- nho entre duas representações de ponto flutuante. some um.37dec × 102. operação inválida. quere- mos que os valores de 0 a 49 arredondem para baixo e de 51 a 99 para cima. nesse caso. e depois sem eles. Detalhamento:  Embora o exemplo anterior. a etapa de normalização precisa deslocar o produto 1 bit à esquerda. precisasse apenas de um dígito extra. Arredonde para o número decimal mais próximo com três dígitos decimais significativos. podemos representar os dois dígitos menos significa- tivos quando alinharmos os expoentes. como se os resultados intermediários fossem calculados para precisão .56 dec × 10 0 a 2. sempre arredondar para baixo (para –∞).56dec × 100 torna-se 0. com 50 sendo o desempate. Como temos dígitos de guarda e arredondamento.36dec × 102. underflow ou exceções de entre o número real e o número que pode ser representado. a medida é denominada número de unidades na última casa. a soma é 2. temos de deslocar o número menor para a direita. Como temos dois dígitos para arredondar. Esse método sempre cria um 0 no bit menos significativo no caso de desempate. A Receita Federal americana sempre arredonda 0. logo. supondo que temos três dígitos decimais sig- EXEMPLO nificativos. a precisão no ponto flutuante normal- mente é medida em termos do número de bits em erro nos bits mais significativos do sig- unidades na última casa (ulp) O nificando. primeiro com dígitos guarda e arredondamento.0256dec × 102. A nova soma é. O objetivo dos bits de arredondamento extras é permitir que o computador obtenha os mesmos resultados. O dígito de guarda mantém 5 e o dígito de arredondamento mantém 6. arredondando no último dígito da soma anterior. se o bit menos significativo retido em um caso de meio do caminho for ímpar. A soma é 2‚3400dec + 0‚0256dec 2‚3656dec Assim. então. ou ulp (units in número de bits com erro nos bits the last place). 5  Ponto flutuante 217 infinita e depois arredondados. o significado da informação não pode ser determinado simples- mente examinando-se os bits. Isso foi acrescentado no IEEE 754 revisado (veja Seção 3. em vez de realizar dois arredondamentos — depois da multiplicação e após a adição — que aconteceria com instruções separadas. por exemplo. Eles podem representar inteiros com sinal. 3. O que é representado depende da instrução que opera sobre os bits na perspectiva palavra.10 no site). arredondamento além dos bits O sticky bit pode ser definido.345000…00. A principal diferença entre os números no computador e os números no mundo real é que os números no computador possuem tamanho limitado e.50 … 00dec e 0. Esta seção mostra que a aritmética computacional é finita e. por isso. O sticky bit seria definido. quando o menor número é de guarda e arredondamento.34ten × 102 no exemplo diferentes de zero à direita do bit de anterior.35. Detalhamento:  As arquiteturas PowerPC. Por exemplo. a representação de ponto flutuante do padrão IEEE 754 (−1)S × (1 + Fração) × 2(Expoente−Bias) é quase sempre uma aproximação do número real. o que aumenta a precisão da multiplicação adição. arredondamento. e os programadores às vezes precisam estar cientes das implicações dessa aproximação. a ins- trução de multiplicação adição pode realizar um único arredondamento após a adição. Obviamente. Suponha que somemos 5. inteiros sem sinal. Os sistemas computacionais precisam ter o cuidado de minimizar essa lacuna entre a aritmética computacional e a aritmética no mundo real.0050 a 2. estaríamos somando 0. consideraríamos que o número é igual a 2. arredondaríamos para 2. uma precisão limitada. Com o sticky bit para lembrar que o número é maior do que 2. ele é definido sempre que existem bits diferentes de zero à direita do bit de arredondamento. porque existem bits diferentes de zero à direita. é possível calcular um número muito grande ou muito pequeno para ser representado em uma palavra. Resumo A próxima seção “Colocando em perspectiva” reforça o conceito de programa armaze- nado do Capítulo 2. definido sempre que existem bits deslocado para a direita. pois os mesmos bits podem representar uma série de objetos.34.34. Sem o sticky bit para lembrar se quaisquer 1s foram deslocados. o padrão possui um terceiro bit além do bit de guarda e arredondamento. Os programadores precisam se lembrar desses limites e escrever programas de acordo. Mesmo com os bits de guarda e arredondamento. pode não combinar com a aritmética natural. Padrões de bits não possuem significado inerente. SPARC64 e AMD SSE5 oferecem uma única ins- trução que realiza multiplicação e adição sobre três registradores: a = a + (b × c).3450. números de ponto flutuante. durante a adição. Essas operações com um único arredondamento são chamadas multiplicação adição fundida. instruções e assim por Colocando em diante.345000…00 e arredondaríamos para o par mais próximo de 2. Esse sticky bit permite que o computador veja a diferença entre 0.01dec × 10-1 a 2. essa instrução permite um desempenho de ponto flutuante potencialmente mais alto para essa operação comum. com uma soma de 2. Para auxiliar nesse objetivo e arredondar para o par mais próximo. Igualmente importante é que. assim.50 … 01dec sticky bit  Um bit usado no ao arredondar. . mult. NaN 3.0000 0000 00 × 2-15 a ±1. ANDi.1111 1111 11 × 214. c.d Interface No capítulo anterior. ±1. subu.0 × 2-1074. ±1. Por exemplo. OR.d add. int ANDi. 1. slt. o IEEE permite números não normalizados (também conhecidos como denorms ou subnormals).s double double l. chamado underflow gradual. NaN 4.0 bin × 2−149 Para a precisão dupla. sltu.00000000000000000000000 bin × 2−126 mas o menor número não normalizado de precisão simples é 0.0000 0000 0 × 2-14 a ±1. slti unsigned — lw. sw. sltiu float float lwc1. sltu. div. c. sh. NOR.d. Logo. ANDi. mult. OR.d. ±0. sw. sb. lui addu.lt. c. div.le. ANDi. mas um significando diferente de zero.1111 1111 1 × 215. seu menor desempenho diminuiu a popularidade dos denorms no software de ponto flutuante portável. addi. addiu.0000 0000 00 × 20 a 1.218 Capítulo 3  Aritmética Computacional Transferências Tipo C Tipo Java de dados Operações int int lw. divu. ±1. AND.d. ±∞. lui addu. ORi. sub. Logo.eq. ORi. NaN Detalhamento:  Para acomodar comparações que possam incluir NaNs. mult. NOR.) Em uma tentativa de espremer cada bit de precisão de uma operação de ponto flutuante. ±∞. 0 2.lt.le.0 × 2-1022 a 1.1111 1111 11 × 231. OR. slti — char lh. divu. OR. ORi.1111 1111 11 × 215. seus programas poderão ser surpreendidos. slt. (Java não admite comparações não ordenadas. Além disso. addiu.00000000000000000000001bin × 2−126 . addiu.d. Observe que Java omite inteiros sem sinal. s. subu. . Embora as implementações de software sejam perfeitamente válidas. c.d.s.s. AND. lui addu. c. per- mitindo que o software complete a operação. o conjunto de instruções MIPS inteiro possui muitos tipos de comparações para dar suporte a NaNs. NOR.ou1. div. Eles permitem que um número diminua no significado até se tornar 0. A tabela anterior hardware/ mostra alguns dos tipos de dados C e Java junto com as instruções de transferência de software dados MIPS e instruções que operam sobre aqueles tipos que aparecem aqui e no Capítu- lo 2. mult. apresentamos as classes de armazenamento da linguagem de pro- gramação C (veja a seção Interface Hardware/Software da Seção 2. AND. subu. sub. muitos computadores causam uma exceção se um operando for não normalizado. lui add. sub.s. sltiu char — lb.7). o menor número normalizado positivo de precisão simples é 1. o padrão permite que alguns números sejam representados em forma não normalizada. Em vez de ter uma lacuna entre 0 e o menor número normalizado. Verifique você Suponha que houvesse um formato de ponto flutuante IEEE 754 de 16 bits com 5 bits de mesmo expoente.eq. ±0. mult. Eles têm o mesmo expoente que zero. Qual seria o intervalo provável de números que ele poderia representar? 1. a lacuna denorm vai de 1.d.s. ±∞. ±0. o padrão inclui ordenada e desordenada como opções para comparações. multu. c. ORi.0000 0000 00 × 2-14 a ±1.s.d. A possibilidade de um operando ocasional não normalizado tem dado dores de cabeça aos projetistas de ponto flutuante que estejam tentando criar unidades de ponto flutuante velozes. AND. NOR. div. swc1 add.s. se os programadores não esperarem os denorms. você pode considerar que existe um defeito na versão paralela.0dec que 1. e como a aritmética computacional tem precisão limitada. mesmo que não deem exatamente a mesma resposta que o código sequencial. dependendo da ordem das adições de ponto flutuante. como LAPACK e SCALAPAK.5dec × 1038. portanto. mais RESPOSTA um número pequeno.5dec × 1038 ) + 1. Essa técnica considera que a aritmética do computador não afeta os resultados quando passa de sequencial para paralelo. de modo que uma pergunta natural é “as duas versões geram a mesma resposta?”. abordada em diversos livros-texto voltados para esse assunto.5dec × 1038 é tão maior que 1. 3. É por isso que a soma de x.5dec × 1038 ) = 0.5dec × 1038. pois o número variável de processadores em cada execução faria com que as somas de ponto flutuante fossem calculadas em diferentes ordens.6  Paralelismo e aritmética computacional: associatividade 219  aralelismo e aritmética computacional: P 3. em que o escalonador do sistema operacional pode usar um número diferente de processadores. EXEMPLO Dada a grande faixa de números que podem ser representados em ponto flutuante.6  associatividade Os programas normalmente têm sido escritos primeiro para executarem sequencialmente antes de simultaneamente.0 ainda é 1. O campo que lida com essas ques- tões é a análise numérica. ocorrem problemas quando se somam dois números grandes de sinais opostos. .0 (x + y) + z = (−1.0.5dec × 1038 + 1. a adição de ponto flutuante não é associativa. Outro modo de dizer isso é que a adição de inteiros é associativa. que precisa ser localizado. y = 1. os programadores que escrevem código paralelo com números de ponto flutuante precisam verificar se os resultados são confiáveis. a adição de ponto flutuante não é associativa.000 processadores. Uma versão mais irritante dessa armadilha ocorre em um computador paralelo.5dec × 1038 + (1. dependendo do que outros programas estão executando em um computador paralelo.0 Portanto. suponha que x = -1. conforme veremos: x + ( y + z) = −1.0 ou 1. se você tivesse de somar um milhão de números. como os números de ponto flutuante são aproximações dos números reais.0 = (0. Ou seja. que foram validadas em suas formas sequencial e paralela.0.0) = −1.5dec × 1038.5dec × 1038 + 1.0 = 1.5dec × 1038 + (1. de modo que a adição de ponto flutuante não é associativa. Infelizmente. Essa suposição continua para inteiros no complemento de dois. Por exemplo. x + (y + z) ≠ (x + y) + z. 1. obteria os mesmos resultados usando 1 processador ou 1. Esses problemas são um motivo para a popularidade das bibliotecas numéricas. e. Ou seja. mesmo que o cálculo estoure. Se a resposta for não.5dec × 1038 + 1. Como os números de ponto flutuante possuem precisão limitada e resultam em apro- ximações dos resultados reais. O programador paralelo desavisado pode se confundir com seu programa obtendo respos- tas ligeiramente diferentes toda vez que for executada exatamente com o mesmo código e entrada idêntica.0dec ) + 1. e que todos estes sejam números de precisão simples. e z = 1. Testando a associatividade da adição de ponto flutuante Veja se x + (y + z ) = (x + y) + z. isso não é verdade para os números de ponto flutuante. Por causa desse dilema. y e z é 0. Antes de realizar a operação. embora tenha sido útil aos programadores de software matemático. (Na verdade. Outro novo recurso dessa arquitetura é que os operandos são mais largos na pilha de registradores do que são armazenados na memória e todas as operações são realizadas nessa precisão interna larga. em vez de contar com Hi e Lo separados como no MIPS. Essa precisão dupla estendida não é aceita pelas lingua- gens de programação. A arquitetura de ponto flutuante x86 é diferente de todos os outros computadores no mundo. As operações de ponto flutuante x86 podem ser divididas em quatro classes principais: 1. operações encontram operandos nos dois elementos do topo da pilha e stores podem retirar elementos da pilha. Instruções transcendentais. e os stores só podem mover do topo da pilha para a memória. Assim. Ao contrário do máximo de 64 bits no MIPS. Instruções de movimentação de dados. um conjunto completo de instruções de pilha é complementado por um conjunto limitado de instruções registrador-memória. Instruções aritméticas. Essa mistura é ainda um modelo registrador-memória restrito. pois os loads sempre movem dados para o topo da pilha enquanto incrementam o ponteiro do topo da pilha. as versões posteriores do conjunto de instruções MIPS incluíram instruções semelhantes. um operando pode estar na memória ou em um dos sete registradores do chip. incluindo load. divisão. subtração. multiplicação. 3. As instruções de transferência de dados também converterão automaticamente inteiros de 16 e 32 bits para ponto flutuante. load de constante e store 2.7  Vida real: ponto flutuante no x86 A arquitetura x86 possui instruções regulares de multiplicação e divisão que operam in- teiramente sobre os registradores normais. incluindo instruções para enviar o resultado ao processador de inteiros de modo que possa se desviar 4. A arquitetura de ponto flutuante do x86 O coprocessador de ponto flutuante Intel 8087 foi anunciado em 1980. Essa arquitetura estendeu o 8086 com cerca de 60 instruções de ponto flutuante. logaritmo e exponenciação . Os dados da memória podem ser números de ponto flutuante de 32 bits (precisão simples) ou de 64 bits (precisão dupla).) As diferenças principais são encontradas nas instruções de ponto flutuante. e ST(i) para representar o i-ésimo registrador abaixo do topo da pilha. para loads e stores de inteiros. Além de localizar operandos nos dois elementos do topo da pilha. raiz qua- drada e módulo absoluto 3. incluindo seno. os operandos de ponto flutuante x86 na pilha possuem 80 bits de largura. O problema ocorre se um desvio condicional compara com um número de ponto flutuante e os dois processadores seguem caminhos diferentes quando o bom senso sugere que eles deveriam seguir o mesmo caminho. a versão registrador-memória dessas instruções converterá o operando da memória para esse formato de 80 bits da Intel. abaixo do topo da pilha. e vice-versa. embora as duas respostas sejam consideradas precisas.220 Capítulo 3  Aritmética Computacional Detalhamento:  Uma versão sutil do problema de associatividade ocorre quando dois proces- sadores realizam um cálculo redundante que é executado em ordem diferente. A Intel proveu uma arquitetura de pilha com suas instruções de ponto flutuante: loads inserem números na pilha. de modo que eles recebem respostas ligeiramente diferentes. incluindo adição. A Intel complementou essa arquitetura de pilha com instruções e modos de endereçamento que permitem que a arquitetura tenha alguns dos benefícios do modelo registrador-memória. Comparação. A Intel usa a notação ST para in- dicar o topo da pilha. cosseno. Os números são convertidos automaticamente para o formato interno de 80 bits em um load e convertidos de volta para o tamanho apropriado em um store. A arquitetura de ponto flutuante Streaming SIMD Extension 2 (SSE2) da Intel O Capítulo 2 observa que. Nem todas as combinações sugeridas pela notação são fornecidas. Observe que obtemos ainda mais combinações quando incluímos os modos de operando para essas operações. As operações de memória reservam 2 bits para decidir se o operando é um ponto flutuante de 32 ou de 64 bits. Logo. ou um inteiro de 16 ou 32 bits. a Intel criou uma arquitetura de ponto flutuante mais tradicional como parte do SSE2. Isso inclui oito registradores de 64 bits que podem ser usados como operandos de ponto flutuante. 3. FSUBR. Como resultado. Usamos as chaves { } para mostrar variações opcionais das operações básicas: {I} significa que existe uma versão inteira da instrução. que movem dados para a memória ou para um dos registradores abaixo do topo da pilha. A comparação de ponto flutuante pode. em 2001. Os compiladores podem decidir usar os oito registradores SSE2 como FIGURA 3. FSUBP. A segunda coluna contém as operações aritméticas descritas anteriormente. {P} significa que essa variação retirará um operando da pilha após a operação. A primeira coluna mostra as instruções de transferência de dados. então. As três últimas operações na primeira coluna colocam constantes na pilha: pi. FSUBRP. O desempenho de ponto flutuante da família x86 tradicionalmente tem ficado atrás de outros computadores.20  As instruções de ponto flutuante do x86. incluindo registradores e operações de ponto flutuante com precisão dupla. não existe um pop (FI SUBP) ou um pop reverso (FISUBRP). Observe que as três últimas operam apenas no topo da pilha.21  As variações dos operandos para adição de ponto flutuante na arquitetura x86. Para as instruções de subtração de inteiros.0 e 0.7  Vida real: ponto flutuante no x86 221 A Figura 3. Como não existem instruções de desvio de ponto flutuante especiais. seguida por uma instrução SAHF a fim de definir os códigos de condição. FIGURA 3.0. ser testada por meio de instruções de desvio inteiras. A última coluna oferece as operações de ponto flutuante de mais alto nível.21 mostra as muitas opções para a adição de ponto flutuante. FI SUBR. e {R} significa o reverso da ordem dos operandos nessa operação. Esses mesmos 2 bits são usados em versões que não acessam a memória para decidir se o topo da pilha deve ser removido após a operação e se o topo da pilha ou um registrador inferior deve obter o resultado. As instruções de ponto flutuante são codificadas por meio do opcode ESC do 8086 e o especificador de endereço pós-byte (veja Figura 2. FISUB. operações F{I}SUB{R}{P} representam estas instruções encontradas no x86: FSUB. A Figura 3. 1. dando ao compilador um alvo diferente para as operações de ponto flutuante do que a arquitetura de pilha exclusiva. a Intel acrescentou 144 instruções à sua arquitetura.47). o resultado da comparação precisa ser transformado para a CPU de inteiros via instruções FSTSW. . A terceira coluna contém as instruções de comparação. seja para o registrador AX ou para a memória.20 mostra algumas das 60 operações de ponto flutuante. 1901 uma divisão de inteiros por uma potência de 2.8  Falácias e armadilhas que estamos falando. como parte do AMD64. a matemática pode ser definida como o assunto em que nunca sabemos do 3. {H} significa mover a metade alta (high) do operando de 128 bits. a Intel permite que vários operandos de ponto flutuante sejam encaixados em um único regis- trador SSE2 de 128 bits: quatro de precisão simples e dois de precisão dupla. e {L} significa mover a metade baixa (low) do operando de 128 bits. registradores de ponto flutuante. em que xi significa o bit na posição i. A Figura 3. Assim. e mem/xmm significa que o outro operando está na memória ou é um registrador SSE2. A AMD expandiu o número para 16. Lembre-se de que um número binário x. ou quatro operandos de 32 bits em um registrador de 128 bits. limitada da aritmética computacional e da precisão ilimitada da aritmética natural. xmm significa que um operando é um registrador SSE2 de 128 bits. um deslocamento à direita é o mesmo que Mathematics. representa o número …+ (x 3 × 23 ) + (x 2 × 22 ) + (x1 × 21 ) + (x 0 × 20 ) Deslocar os bits de x para a direita de n bits pareceria ser o mesmo que dividir por 2n. Usamos as chaves { } para mostrar variações opcionais das operações básicas: {SS} significa ponto flutuante de precisão Scalar Single. então as transferências de dados de 128 bits podem carregar e armazenar vários operandos por instrução. {PD} significa ponto flutuante de precisão Packed Double. suponha que queremos dividir –5dec por 4dec. Recent Falácia: assim como a instrução de deslocamento à esquerda pode substituir uma Words on the Principles of multiplicação de inteiros por uma potência de 2. o quociente seria –1dec. ou um operando de 64 bits em um registrador de 128 bits. O problema é com os inteiros com sinal. que a Intel passou a chamar de EM64T para seu uso. Por exemplo. Bertrand Russell. Além de manter um número de precisão simples ou de precisão dupla em um registrador. Essa arquitetura pode mais do que dobrar o desempenho em relação à arquitetura de pilha. A representação no complemento de dois para –5dec é 1111 1111 1111 1111 1111 1111 1111 1011bin De acordo com essa falácia. nem se o que estamos dizendo é As falácias e armadilhas aritméticas geralmente advêm da diferença entre a precisão verdadeiro. deslocar para a direita por dois deverá dividir por 4dec (22): 0011 1111 1111 1111 1111 1111 1111 1110 bin .22 resume as instruções SSE e SSE2. Esse formato de ponto flutuante compactado é aceito por operações aritméticas que podem operar simul- taneamente sobre quatro números de precisão simples (PS) ou dois de precisão dupla (PD). ou dois operandos de 64 bits em um registrador de 128 bits.22  As instruções de ponto flutuante SSE/SSE2 do x86. E isso é verdade para inteiros sem sinal. {U} significa que o operando de 128 bits é desalinhado na memória. Se os operandos podem ser organizados na memória como dados alinhados em 128 bits. {SD} significa ponto flutuante de precisão Scalar Double.222 Capítulo 3  Aritmética Computacional FIGURA 3. como aqueles encontrados em outros computadores. {A} significa que o operando de 128 bits é alinhado na memória. 1. na realidade. o resto parcial é ajustado em uma passada subsequente.23). A escolha é multiplicada pelo divisor e subtraída do resto a fim de gerar um novo resto. incluindo New York Times. em vez de colocar 0s à esquerda num deslocamento à direita. San Francisco Chronicle e Infoworld. esse resultado claramente está errado. mas não podemos comemorar.23  Uma amostra dos artigos de jornais e revistas de novembro de 1994. em vez de –1dec. As manchetes dos jornais de novembro de 1994 provam que essa afirmação é uma falácia (veja Figura 3. 0. –1. próximo. e eles otimizaram a PLA para retornar 0 no lugar de 2 nessas situa- FIGURA 3. 3. Falácia: somente os matemáticos teóricos se importam com a precisão do ponto flutuante. A escolha vem de uma tabela de pesquisa contendo –2.8  Falácias e armadilhas 223 Com um 0 no bit de sinal. Evidentemente. A seguir. que gera bits de quociente múltiplos por etapa. O valor criado pelo des- locamento à direita é. A Intel acabou tendo um custo de US$300 milhões para substituir os chips com defeito. O bug da divisão de ponto flutuante do Pentium chegou até mesmo à “Lista dos 10 mais” do David Letterman Late Show na televisão. Um deslocamento aritmético de 2 bits para a direita de –5dec produz 1111 1111 1111 1111 1111 1111 1111 1110 bin O resultado é –2dec. San Jose Mercury News. add immediate unsigned (addiu) é usada para somar constantes a inteiros com sinal quando não nos importamos com o overflow. de modo que os arquitetos do MIPS decidiram estender o sinal do campo imediato. se uma escolha anterior obtiver um resto muito grande. Apesar de seu nome. Uma solução seria ter um deslocamento aritmético à direita. . +1 ou +2. havia cinco elementos da tabela do 80486 que a Intel pensou que nunca poderiam ser acessados. Assim como a divisão sem restauração.073. está a história por trás das manchetes.822dec. Armadilha: a instrução MIPS add immediate unsigned (addiu) estende o sinal de seu campo imediato de 16 bits. usando os bits mais significativos do divisor e do dividendo para descobrir os 2 bits seguintes do quociente. e não –1dec. O Pentium usa um algoritmo de divisão de ponto flutuante padrão. que estende o bit de sinal.741. O MIPS não possui uma instrução de subtração imediata e os números negativos precisam de extensão de sinal. gerando 4. A Intel considera que um usuário realiza 1. estimando que 3 a 5 milhões de Pentiums seriam produzidos com o bug. ou do 4o ao 15o dígito decimal.2 milhões de divisões por dia. pelo diretor de operações e pelo presidente do comitê: “Nós. calculando por 15 minutos por dia. Mas nenhum microprocessador é totalmente perfeito. O símbolo Intel Inside significa que seu computador possui um microprocessador que não fica atrás de nenhum outro em qualidade e desempenho. Milhares de funcionários da Intel trabalham muito para garantir que isso aconteça. Até aqui. Depois de ligar para o suporte técnico da Intel e não receber uma posição oficial. Rapidamente surgiram os seguidores e alguns apontaram que até mesmo erros pequenos se tornam grandes ao multiplicar por grandes números: a fração de pessoas com uma doença rara vezes a população da Europa. por exemplo. j 12 de dezembro de 1994: a IBM Research Division discute o cálculo da Intel quanto à taxa de erros (você pode acessar esse artigo visitando www.000 anos.mkp.htm). assinado pelo presidente da Intel. j 5 de dezembro de 1994: a Intel afirma que a falha acontece uma vez em 27. A Intel estava errada: embora os 11 primeiros bits sempre fossem corretos. A seguir está um roteiro dos fatos que aconteceram referentes ao bug do Pentium: j Julho de 1994: a Intel descobre o bug no Pentium. Usuários de planilhas eletrônicas e processadores de textos não precisam se preocupar. O que aborreceu a muitos foi que os clientes foram solicitados a descrever sua aplicação à Intel. O Pentium “pode cometer erros no nono dígito. e não considera a distribuição aleatória de números. A IBM considera 5.000 anos para o usuário típico de planilha. um problema extremamente pequeno assumiu vida própria. queremos sinceramente pedir desculpas por nosso tratamento da falha recentemente publicada do processador Pentium. que logo foi seguido por outros jornais. verificar novamente e colocar o chip corrigido em produção. erros apareceriam ocasionalmente nos bits de 12 a 52. Como resultado. descobre o bug. só ouvimos falar de uma. calculando em vez disso as chances como uma em 100 milhões. j 22 de novembro de 1994: a Intel emite um comunicado oficial. poderiam produzir erros relacionados ao bug do Pentium com tanta frequência quanto uma vez a cada 24 dias. a IBM imediatamente deixa de enviar todos os computadores pessoais IBM baseados no Pentium.000 divisões por segundo. pelo diretor executivo. da Intel. … Talvez haja algumas dezenas de pessoas a quem isso afetaria. tecnicamente.com/books_catalog/cod/ links. A IBM afirma que os programas comuns de planilha. j 7 de novembro de 1994: o Electronic Engineering Times coloca a matéria em sua capa.224 Capítulo 3  Aritmética Computacional ções no Pentium. e depois apanha 9 milhões de dias. levariam meses para fazer a mudança. j 21 de dezembro de 1994: a Intel lança o seguinte comunicado. … Até mesmo a maioria dos engenheiros e analistas financeiros exige precisão apenas até a quarta ou quinta casa decimal. Thomas Nicely. ou 27. e depois a Intel decidiria se sua aplicação mereceria ou não um novo Pentium sem um bug de divisão. poderia levar a uma estimativa errada do número de pessoas doentes. j Setembro de 1994: um professor de matemática no Lynchburg College. O custo real para consertar o bug foi de várias centenas de milhares de dólares. ele posta sua descoberta na Internet. O que a Intel continua a acreditar é que. por 15 minutos. Embora a Intel mantenha . chamando-o de “glitch”. o que é um em 9 bilhões. apesar de a Intel ter deixado de explicar por que um cliente comum acessaria números de ponto flutuante aleatoriamente. … [Somente] matemáticos teóricos (com computadores Pentium comprados antes do verão) devem se preocupar”. A Intel planejou colocar os chips bons em produção em janeiro de 1995. Após os procedimentos normais de reparo do bug. na Virgínia. As coisas começam a acalmar. As coisas se aquecem novamente para a Intel.000 divisões por dia e multiplica a taxa de erro supondo que os números de ponto flutuante são aleatórios. Os analistas estimam que essa troca custou à Intel cerca de US$500 milhões. eles reconheceram publicamente o bug e ofereceram um reparo de software para contorná-lo – uma reação muito diferente da que aconteceu em 1994. Seria mais econômico ter consertado o bug em julho de 1994? Qual foi o custo para reparar o dano causado à reputação da Intel? E qual é a responsabilidade corporativa na divulgação de bugs em um produto tão utilizado e confiado como um microprocessador? Em abril de 1997. Para o crédito da Intel. . em que essa falha de divisão de ponto flutuante está corrigida. dessa vez. A Intel trocará a versão atual do processador Pentium por uma versão atualizada. fistp) encontram um número de ponto flutuante negativo que seja muito grande para caber em uma word de 16 ou 32 bits sendo convertida para inteiro. elas definem o bit errado na palavra de status FPO (exceção de precisão. sem qualquer custo. 3.8  Falácias e armadilhas 225 a qualidade da versão atual do processador Pentium. e os funcio- nários da Intel não receberam um bônus de Natal naquele ano. para qualquer proprietário que o solicite. durante toda a vida de seu computador”. Queremos resolvê-los. no lugar de exceção por operação inválida). Essa história nos faz refletir sobre alguns pontos. FIGURA 3. Essa informação também se encontra nas colunas 1 e 2 do Guia de Instrução Rápida do MIPS no início deste livro. Quando as instruções store de ponto flutuante para inteiro (fist. Este livro se concentra nas instruções da coluna da esquerda. reconhecemos que muitos usuários possuem problemas.24  O conjunto de instruções MIPS. outro bug de ponto flutuante foi revelado nos microprocessadores Pentium Pro e Pentium II. Com o passar dos anos. cada computador desktop vendido desde que este livro foi impresso pela primeira vez segue essas convenções. As instruções à direita são chamadas núcleo aritmético MIPS. A aritmética de ponto flutuante tem o desafio adicional de ser uma aproximação de números reais e é preciso tomar cuidado para garantir que o número selecionado pelo computador seja a representação mais próxima do número real.24 lista as instruções MIPS abordadas neste capítulo e no Capítulo 2. Com a explicação sobre aritmética computacional deste capítulo vem uma descrição de muito mais do conjunto de instruções do MIPS.226 Capítulo 3  Aritmética Computacional 3.25 estão as instruções que o processador MIPS executa que não se encontram na Figura 3. Chama- mos o conjunto de instruções da esquerda da figura de núcleo MIPS. 0. Todas as instruções listadas foram responsáveis por. A aritmética de inteiros binários com complemento de dois e a aritmética de ponto flutuante binário do padrão IEEE 754 são encontradas na grande maioria dos computadores vendidos hoje. Chamamos o conjunto completo de instrução de hardware de MIPS-32. No lado esquerdo da Figura 3. As duas figuras seguintes tentam es- clarecer isso. por meio do cálculo de números maiores ou menores do que os limites predefinidos. Por exemplo. À direita da Figura 3. Essas anomalias.24. embora os programadores e escritores de compilador possam utilizar MIPS-32 para ter um menu de opções mais rico. A aritmética computacional é distinguida da aritmética de lápis e papel pelas restrições da precisão limitada. A Figura 3. Subconjunto de instruções Inteiros Pt. Esse limite pode resultar em operações inválidas. A Figura 3. à medida que soluções que eram consideradas seguras nos computadores sequenciais precisam ser reconsideradas quando se tenta encontrar o algoritmo mais rápido para computadores paralelos. como mostra a tabela a seguir. Uma questão que gera confusão são as instruções explicadas neste capítulo versus as instruções executadas pelos chips MIPS versus as instruções aceitas pelos montadores MIPS. É a instrução que opera sobre os bits que determina seu significado. Núcleo do MIPS 98% 31% Núcleo aritmético do MIPS 2% 66% MIPS-32 restante 0% 3% . podem resultar em exceções ou interrupções. A recente passagem para o paralelismo acenderá a tocha na análise numérica novamente.25 estão as instruções aceitas pelo montador. a aritmética computacional tornou-se padronizada. e o núcleo de inteiros mais aritmético domina o ponto flutuante SPEC2006.26 indica a popularidade das instruções MIPS para os benchmarks de inteiro e de ponto flutuante SPEC2006. uma instrução e assim por diante. que não fazem parte do MIPS-32. O mesmo padrão de bits pode representar um inteiro com sinal. O Capítulo 4 discute as exceções com mais detalhes. Chamamos esse conjunto de instruções de PseudoMIPS. um inteiro sem sinal. chamadas “overflow” ou “underflow”. que ainda alcance um resultado correto. semelhantes a chamadas de sub-rotina não planejadas. Flut. as instruções do núcleo MIPS dominam a execução SCPEC2006 de inteiros. Os desafios da imprecisão e da representação limitada fazem parte da inspiração para o campo da análise numérica. um número de ponto flutuante. eventos de emergência. aumen- tando bastante a portabilidade dos programas. Observe que.2% das instruções executadas. pelo menos.9   Comentários finais Um efeito colateral do computador com programa armazenado é que os padrões de bits não possuem significado inerente. 25  Conjuntos de instruções MIPS-32 restantes e “pseudoMIPS”. .f). round (round.f/msub. 3. e tenha certeza de que compreender um computador que execute o núcleo MIPS lhe dará base suficiente para entender computadores com projetos ainda mais ambiciosos. Como podemos ver. vamos nos concentrar nas instruções do núcleo MIPS – o conjunto de instruções de inteiros. Para o restante do livro. o núcleo MIPS inclui as instruções MIPS mais comuns.9  Comentários finais 227 FIGURA 3. truncate (trunc. excluindo multiplicação e divisão – para facilitar a explicação do projeto do computador. MIPS-32 também possui instruções de PF para multiply e add/sub (madd.f). O sublinhado representa a letra a ser incluída para representar esse tipo de dados. ceiling (ceil.f).f) e reciprocal (recip. f significa instruções de ponto flutuante com precisão simples (s) ou dupla (d) e s significa versões com sinal e sem sinal (u).f). não aparecem aqui. 3. Ver Seção 3.10 no site. outros sistemas de numeração também foram muito populares quando se tratavam de computadores. Esta seção estuda a história do ponto flutuante desde von Neumann. pelo menos. mesmo que o rápido seja errado”. incluindo o es- W. Porém. O sistema de numeração octal (base 8) foi um deles. nunca ceda. nunca – em nada. nunca. As pseudoinstruções são convertidas em MIPS-32 antes da execução e.11   Exercícios importante ou insignificante – nunca ceda. A tabela a seguir mostra pares de números octais. Kahan. Nunca ceda. mais o raciocínio para a arquitetura de pilha de 80 bits para ponto flutuante do x86. A Lei de Gresham (“dinheiro ruim expulsa o bom”) para os computadores diria: “o rápido 3.26  Frequência das instruções MIPS para o benchmark de inteiros e ponto flutuante SPEC2000. portanto. seja grande ou pequeno. 3174 0522 b. discurso na Exercício 3. 1% das instruções estão incluídas na tabela.10   Perspectiva histórica e leitura adicional expulsa o lento.1 Harrow School. nunca.228 Capítulo 3  Aritmética Computacional FIGURA 3. 1992 forço surpreendentemente controvertido dos padrões do IEEE. 4165 1654 . 1941 O livro mostra como somar e subtrair números binários e decimais. Winston Churchill. A B a. Todas as instruções responsáveis por. 2 Hexadecimal (base 16) também é um sistema de numeração normalmente utilizado para representar valores nos computadores.2> Qual é a soma de A e B se eles representam números hexadecimais de 16 bits com sinal.1. Mostre seu trabalho. 7040 0444 b. 1446 672F b. A tabela a seguir também mostra pares de números octais. 3. 2460 4935 3. A B a. Repita considerando que ele esteja armazenado em formato de sinal e magnitude. Mostre seu trabalho.3 [10] <3.1. Mostre seu trabalho.2> O que é A – B se eles representam números hexadecimais de 16 bits sem sinal? O resultado deverá ser escrito em hexadecimal. 3.4 [5] <3. 3. 3. ele se tornou muito mais comum que octal. supondo que ele esteja sem sinal.2 [5] <3.2> Qual é a soma de A e B se eles representam números octais de 12 bits sem sinal? O resultado deverá ser escrito em octal. Mostre seu trabalho.1 [5] <3. Mostre seu trabalho. 3.2.11 Exercícios 229 3.3 [10] <3.1.4 [5] <3.2> O que é A – B se eles representam números octais de 12 bits sem sinal? O resultado deverá ser escrito em octal. 5ED4 07A4 3.2. Mostre seu trabalho. A tabela a seguir mostra pares de números hexadecimais. armazenados em formato de sinal e magnitude? O resultado deverá ser escrito em hexadecimal.2 [5] <3.1.5 [5] <3.6 [10] <3. supondo que ele é sem sinal.2> Qual é a soma de A e B se eles representam números octais de 12 bits com sinal armazenados em um formato de sinal e magnitude? O resultado deverá ser es- crito em octal.1. . A B a. A tabela a seguir também mostra pares de números hexadecimais.2> Converta A para um número decimal.1.1 [5] <3.2> O que é A – B se eles representam números octais de 12 bits com sinal armazenados em formato de sinal e magnitude? O resultado deverá ser escrito em octal. Na verdade. Mostre seu trabalho. A B a.2> Converta A em um número binário. 3. Mostre seu trabalho. 4365 3412 3. C352 36AE b.2. O que torna a base 8 (octal) um sistema de numeração atraente para representar valores nos computadores? Exercício 3. Repita considerando que ele está armazenado em formato de sinal e magnitude. 3.2> Converta A em um número decimal. Mostre seu trabalho.2> Qual é a soma de A e B se eles representam números hexadecimais de 16 bits sem sinal? O resultado deverá ser escrito em hexadecimal.2. armazenados em formato de sinal e magnitude? O resultado deverá ser escrito em hexadecimal. O resultado deverá ser escrito em decimal.5 [10] <3. A B a. O resultado deverá ser escrito em decimal. Usaremos os números na tabela a seguir. 3. 3.) A tabela a seguir mostra pares de números decimais.2> Suponha que A e B sejam inteiros decimais de 8 bits sem sinal. 102 44 3. underflow o nenhum deles? 3. 35 26 . ar- mazenados no formato de complemento de dois. Calcule A + B.3.6 [10] <3. 200 103 b. Calcule A . 62 12 b.4 Vejamos a multiplicação com mais detalhes.2> O que é A – B se eles representam números hexadecimais de 16 bits com sinal.1 [5] <3.B. Calcule A + B usando a aritmética por saturação. Mostre seu trabalho.B.2> Suponha que A e B sejam inteiros de 8 bits sem sinal.5 [5] <3. por exemplo. Mostre seu trabalho.3 O overflow ocorre quando um resultado é muito grande para ser representado com precisão dado um tamanho de palavra finito. Exercício 3. (O caso quando um resultado positivo é gerado pela adição de dois inteiros negativos também é considerado como underflow por muitos.2 [5] <3.3. armazenados em formato de magnitude de sinal. Calcule A . O underflow ocorre quando um número é muito pequeno para ser representado corretamente — um resultado negativo quando se realiza aritmética sem sinal. Calcule A . Mostre seu trabalho.3. arma- zenados em formato de magnitude de sinal.2> Converta A para um número binário.3. Existe overflow.230 Capítulo 3  Aritmética Computacional 3. 69 90 b. Mostre seu trabalho. A B a. 3.3.2> Suponha que A e B sejam inteiros decimais de 8 bits com sinal.6 [10] <3. Existe overflow.2> Suponha que A e B sejam inteiros decimais de 8 bits com sinal. underflow o nenhum deles? 3.2.2> Suponha que A e B sejam inteiros decimais de 8 bits com sinal. Existe overflow.2> Suponha que A e B sejam inteiros decimais de 8 bits com sinal. mas neste livro isso é considerado overflow.3 [5] <3. underflow ou nenhum deles? A tabela a seguir também mostra pares de números decimais. A B a. O resultado deverá ser escrito em decimal. O que torna a base 16 (hexa- decimal) um sistema de numeração atraente para representar valores em computadores? Exercício 3. Calcule A + B usando a aritmética por saturação.2. ar- mazenados no formato de complemento de dois. 247 237 3.B usando a aritmética por saturação.3.4 [10] <3. salvar os sinais originais e depois ajustar o valor final de forma apropriada. A B a. Exercício 3.4.6. Você deverá mostrar o conteúdo de cada registrador em cada etapa. usando a técnica descrita na Figura 3. Ele sempre pode ser um 0. gostaríamos de projetar multiplicadores que exijam menos tempo.5 se um inteiro tiver A bits de largura e cada etapa da .4. Muitas técnicas diferentes foram utilizadas para se realizar esse objetivo.3> Usando uma tabela semelhante à que mostramos na Figura 3.4. 3.4 ou no Exercício 3. 41 33 b.3> Ao deslocar um registrador um bit para a direita. 3.4.6. 4 3 ut b.3> Usando uma tabela semelhante à que mostramos na Figura 3.6 [60] <3. 60 26 3. 32 7 ut 3. calcule o produto dos números em complemento de dois com 6 bits A e B usando o hardware descrito na Figura 3. Usando uma tabela semelhante à que mostramos na Figura 3. Você poderá encontrar detalhes pesquisando a Web. calcule o produto de A e B usando o hardware descrito na Figura 3. as coisas precisam ser feitas de forma diferente se o multiplicador for negativo. e incluir a etapa necessária para produzir o resultado sinalizado corretamente. um modo de obter a resposta correta é converter o multiplicador e multiplicando para números positivos. 3.3> Escreva um programa na linguagem assembly MIPS para calcular o produto dos inteiros A e B sem sinal.7.4. A representa a largura de um inteiro em bits.4.3 [60] <3.5 [30] <3.4.4.7. existem várias maneiras de decidir qual será o novo bit entrando.3> Ao multiplicar números com sinal. pois preserva o sinal do número que está sendo deslocado).7. 3.5.4.3> Escreva um programa em linguagem assembly MIPS para calcular o produto dos inteiros com sinal A e B.4. ou o valor que já está no bit mais à esquerda pode simplesmente ser retido (chamado de deslocamento aritmético à direita. calcule o produto dos inteiros hexadecimais de 8 bits sem sinal A e B usando o hardware descrito na Figura 3.4 [30] <3.11 Exercícios 231 3.1 [20] <3.4 e 3. e B representa o número de unidades de tempo (ut) necessárias para realizar uma etapa de uma operação. Na tabela a seguir. Mostre o conteúdo de cada registrador a cada etapa. Observe que o algoritmo descrito no texto terá de ser modificado ligeiramente para que isso funcione — em particular. 3.4. Você deverá mostrar o conteúdo de cada registrador em cada etapa.7. A tabela a seguir mostra pares de números octais.1 [10] <3.3> Calcule o tempo necessário para realizar uma multiplicação usando a técnica dada nas Figuras 3. calcule o produto dos inteiros octais de 6 bits sem sinal A e B usando o hardware descrito na Figura 3. ou o bit entrando poderia ser aquele que está sendo empurrado pelo lado direito (transformando um deslocamento em uma rotação).5 Por muitos motivos. ou sempre um 1. Você deverá mostrar o conteúdo de cada registrador em cada etapa.5. A (largura em bits) B (unidades de tempo) a. Os deslocamentos à direita deverão ser feitos usando-se um deslocamento aritmético à direita.2 [20] <3. Usando uma tabela semelhante à que mostramos na Figura 3. Suponha que A e B estejam armazenados em formato de magnitude de sinal com 6 bits. Indique se você está usando a técnica dada no Exercício 3. podemos calcular 9 × 6 deslocando 6 para a esquerda três vezes e depois somando 6 a esse resultado. Solucione para cada caso. Ache uma descrição do algoritmo na internet e explique.6. armazenados em formato hexadecimal.3> Calcule o tempo necessário para realizar uma multiplicação usando a técnica descrita no texto (31 somadores empilhados verticalmente) se um inteiro tiver A bits de largura e um somador exigir B unidades de tempo.5. 33 55 b. 3.2 [20] <3. com base principalmente em realizar mais deslocamentos e menos operações aritméticas.6. por exemplo. 8a 6d 3. Suponha também que os registradores já foram inicializados (você está simplesmente contando quanto tempo é necessário para se realizar o próprio loop de multiplicação). A tabela a seguir mostra outros pares de números hexadecimais.6. A B a.6. usando o algoritmo de Booth.3 [60] <3. Se isso estiver sendo feito no hardware. 3.3> Mostre a melhor maneira de calcular A × B usando deslocamento e somas.3> Escreva um programa em linguagem assembly MIPS que realize uma multiplicação de inteiros com sinal usando deslocamento e somas.1 [20] <3.8. usando o enfoque des- crito em 3.232 Capítulo 3  Aritmética Computacional operação exigir B unidades de tempo.5. Suponha que A e B sejam inteiros de 8 bits em complemento de dois. Como 9 × 6. Exercício 3. na etapa 1a. pode ser escrito como (2 × 2 × 2 + 1) × 6. ao invés de deslocamentos e adições. A tabela a seguir mostra pares de números hexadecimais. Suponha que A e B sejam inteiros de 8 bits sem sinal.3> O algoritmo de Booth é outra técnica que reduz o número de operações aritméticas necessárias para realizar uma multiplicação. . F6 7F b.3 [20] <3. 3.6. uma melhoria possível é realizar um deslocamento e soma em vez de uma multiplicação real.1.6 Neste exercício. Mostre a melhor maneira de calcular A × B usando deslocamentos e adições/subtrações. A B a. eles terão de ser feitos um após o outro. 3. com detalhes. veremos algumas das outras maneiras de melhorar o desempenho da multiplicação. como ele funciona. Suponha que. uma adição sempre é realizada — ou o multiplicando será somado.5 [30] <3. Se isso estiver sendo feito no software. se A e B forem inteiros de 8 bits com sinal armazenados em formato de magnitude de sinal.2 [10] <3. os deslocamentos do multiplicando e do multiplicador podem ser feitos simultaneamente.3> Mostre o resultado passo a passo da multiplicação de A e B.6. se um inteiro tiver A bits de largura e um somador exigir B unidades de tempo. 3. ou então um 0 será somado.3> Calcule o tempo necessário para realizar uma multiplicação usando a técnica dada na Figura 3.3> Conforme discutimos no texto. 08 55 3. Esse algoritmo já existe há muitos anos e envolve identificar ciclos de 1s e 0s e realizar apenas deslocamentos durante os ci- clos.4 [30] <3. A B a.7. 3. Muitas referências a esses algoritmos são facilmente encontradas na Web. calcule A dividido por B usando o hardware descrito na Figura 3.5 [30] <3. (Dica: uma solução possível envolve o uso do fato de que a Figura 3. o divisor é somado de volta ao resto (res- taurando. Não se esqueça de incluir como você está calculando os sinais do quociente e do resto. Este algoritmo requer uma técnica ligeiramente diferente daquela mostrada na Figura 3.7. Suponha que A e B sejam inteiros com sinal. Suponha que A e B sejam inteiros de 6 bits sem sinal.4> Usando uma tabela semelhante à que mostramos na Figura 3.8 A Figura 3.11. 3. usando a técnica descrita na Figura 3. Você deverá pensar bem nisso.1 [20] <3. usando a técnica descrita na Figura 3.3 [60] <3. calcule A dividido por B usando o hardware descrito na Figura 3.4> Usando uma tabela semelhante à que mostramos na Figura 3. Suponha que A e B sejam inteiros de 6 bits sem sinal.6 [60] <3.9. pois quando subtrai o divisor do resto produz um resultado negativo.3> Escreva um programa em linguagem assembly MIPS para realizar a multiplicação de A e B usando o algoritmo de Booth. assim.12.12 implica que o registrador de resto pode ser deslocado em qualquer direção. Suponha que A e B sejam inteiros de 6 bits sem sinal.9.9. 75 47 3. 76 52 3. Você deverá mostrar o conteúdo de cada registrador em cada etapa. Exercício 3. A tabela a seguir mostra outros pares de números octais. 74 21 b.4> Escreva um programa em linguagem assembly MIPS para calcular A dividido por B.6. existem outros algoritmos que foram desenvolvidos para eliminar a adição extra. A B a. calcule A dividido por B usando o hardware descrito na Figura 3. Usaremos os números octais da tabela a seguir.4> Usando uma tabela semelhante à que mostramos na Figura 3.12.4> Escreva um programa na linguagem assembly MIPS para calcular A dividi- do por B.7.) 3.7. Você deverá mostrar o conteúdo de cada registrador em cada etapa. calcule A dividido por B usando o hardware descrito na Figura 3.11 Exercícios 233 3. Exercício 3.6 [60] <3.2 [30] <3. realizar um experimento ou dois. Você deverá mostrar o conteúdo de cada registrador em cada etapa. Você deverá mostrar o conteúdo de cada registrador em cada etapa.10.4 [30] <3.7 Vejamos a divisão com maiores detalhes. Não se esqueça de incluir como você está calculando os sinais do quociente e resto.11. Exploraremos esses algoritmos usando os pares de números octais na tabela a seguir. Suponha que A e B sejam inteiros de 6 bits com sinal em formato de magnitude de sinal.7. o valor).11. ou então vá à Web descobrir como fazer isso funcionar corretamente.4> Usando uma tabela semelhante à que mostramos na Figura 3. 3. Porém. .11. 3.12.10 descreve um algoritmo de divisão com restauração. Suponha que A e B sejam inteiros de 6 bits com sinal em formato de magnitude de sinal. 72 07 b.7. 3.9.11.8.” Este exercício examina as diferentes estratégias para realizar divisões. Suponha que A e B sejam inteiros de 6 bits com sinal.1 [30] <3.2 [60] <3. 27 06 b.11. . 54 12 3.9. Suponha que A e B sejam inteiros de 6 bits com sinal (magnitude de sinal). Você também pode escrever um programa para realizar as divisões nonperforming e nonrestoring. Suponha que A e B sejam inteiros de 6 bits com sinal (complemento de dois). Você deverá mostrar o conteúdo de cada registrador a cada etapa. 3. a.4> Descreva o algoritmo com detalhes.1 [30] <3. Exercício 3. Divisão por multiplicação recíproca 3. 3.8.2 [60] <3. Suponha que A e B sejam inteiros de 3 bits com sinal em complemento de dois. 3.8.9 A divisão é tão demorada e difícil que o guia do CRAY T3E Fortran Optimization afirma: “A melhor estratégia para divisão é evitá-la sempre que for possível. 37 15 3.4> Como o desempenho da divisão nonrestoring e nonperforming se comparam? Demonstre exibindo o número de etapas necessárias para calcular A dividido por B usando cada método.4 [30] <3.8.8.4> Escreva um programa em linguagem assembly MIPS para realizar uma divisão usando o algoritmo. Suponha que A e B sejam inteiros de 6 bits sem sinal. 26 05 b.5 [60] <3.3 [60] <3.4> Usando uma tabela semelhante à que mostramos na Figura 3.4> Escreva um programa em linguagem assembly MIPS para calcular A dividido por B usando a divisão nonperforming. Você deverá mostrar o conteúdo de cada registrador a cada etapa.234 Capítulo 3  Aritmética Computacional A B a. Divisão sem restauração b.4> Compare o desempenho da divisão com e sem restauração.4> Escreva um programa em linguagem assembly MIPS para calcular A dividido por B usando a divisão sem restauração. A tabela a seguir mostra outros pares de números octais. arma- zenados em formato de magnitude de sinal.6 [60] <3. calcule A dividido por B usando a divisão nonperforming.3 [60] <3.4> Use um fluxograma (ou um trecho de código de alto nível) para des- crever como o algoritmo funciona.4> Usando uma tabela semelhante àquela mostrada na Figura 3.9. Suponha que A e B sejam inteiros de 6 bits sem sinal.8. A B a. De- monstre exibindo o número de etapas necessárias para calcular A dividido por B usando cada método. 3. calcule A dividido por B usando a divisão sem restauração. 3. Você também pode escrever um programa para realizar as divisões com e sem restauração. 5> Escreva a representação binária do número decimal. 1.10. os cálculos de ponto flutuante eram tratados no software.11 Exercícios 235 Exercício 3.11.) Nenhum 1 oculto é utilizado.10 Em uma arquitetura de Von Neumann. que é semelhante ao IEEE 754. 3.25 b. a.5625 × 10–1 b. 9. 3. Em razão do uso de um 1 oculto. 0xC4630000 3. considerando o formato de precisão simples IEEE 754. outros formatos foram utilizados.2 [10] <3. e os 24 bits da direita são a mantissa armazenada como um número de complemento de dois.2 [20] <3. 3.5> NVIDIA tem um formato “metade”. 40625 3. se tivéssemos de representar o expoente no formato de complemento de dois. −1.356875 × 102 3. um padrão com apenas zeros na realidade seria o número 1! (Lembre-se de que qualquer coisa elevada à potência zero é 1 e. em vez da base 2.10. Porém. A tabela a seguir mostra números decimais.00 = 1.10.5> Que número decimal o padrão de bits representa se ele for um inteiro em complemento de dois? E um inteiro sem sinal? 3.1 [20] <3. A tabela a seguir mostra os padrões de bits expressos em notação hexadecimal. A tabela a seguir mostra números decimais.5 [10] <3. portanto. a.10. grupos de bits não possuem significados intrínsecos por si próprios. Compare o intervalo e a precisão desse padrão de 36 bits com os padrões IEEE 754 de precisão simples e dupla. 146987. 63. 3.3 [10] <3. exceto que tem apenas 16 bits de largura.11. o ex- . a. portanto.10. que instrução MIPS será executada? 3.1 [5] <3.5> Que número decimal o padrão de bits representa se ele for um número de ponto flutuante? Use o padrão IEEE 754.11 No padrão de ponto flutuante IEEE 754. 0x0C000000 b.10.5> Escreva a representação binária do número decimal. com 7 bits de expoente).5> Escreva a representação binária do número decimal considerando que ele foi armazenado usando-se o formato IBM de precisão simples (base 16.4 [10] <3. O bit mais à esquerda ainda é o bit de sinal. considerando o formato de precisão dupla IEEE 754. Essa técnica foi selecionada porque queremos que um ­padrão com apenas zeros seja o mais próximo de zero possível. O que um padrão de bits representa depende totalmente de como ele é utilizado. o expoente é armazenado em formato de “bias” (também conhecido como “Excess-N”).) Há muitos outros aspectos do padrão IEEE 754 que ajudam as unidades de ponto flutuante do hardware a trabalharem mais rapidamente.5> Se esse padrão de bits for colocado no Registrador de Instrução. Exercício 3.6 [10] <3. em muitas máquinas mais antigas.5> Escreva o padrão de bits binário considerando um formato semelhante ao empregado pelo DEC PDP-8 (12 bits da esquerda são o expoente armazenado como um número de complemento de dois. e. 2 (e também descrito no texto).2 (e também descrito no texto).5> Escreva um programa em linguagem assembly MIPS para calcular a soma de A e B. você pode realizar a multiplicação em formato legível aos humanos.236 Capítulo 3  Aritmética Computacional poente tem 5 bits de largura e é armazenado no formato Excess-16. porém.11. considerando que A e B sejam armazenados no formato NVIDIA de 16 bits descrito no Exercício 3. Compare o intervalo e a precisão desse padrão de 32 bits com o padrão IEEE 754 de precisão simples. em vez de usar as técnicas descritas nos Exercícios de 3. supondo que A e B sejam armazenados no formato NVIDIA de 16 bits descrito no Exercício 3.59375 × 10–2 8. 2. e arredonde para o par mais próximo.125 × 10–1 3. Qual é a precisão do seu resultado? Compare-o com o número que você obtém se realizar a multiplicação em uma calculadora. . seguida por outro campo de 16 bits que tinha nos 8 bits mais à esquerda uma extensão da mantissa (fazendo com que a mantissa tenha 24 bits de extensão) e os 8 bits mais à direita representando o expoente. –4.11.3953125 × 101 3.484375 × 101 1. Porém.11.6125 × 101 4.6 [60] <3. Comente sobre o intervalo e a precisão desse padrão de 16 bits com o padrão IEEE 754 de precisão simples. Mostre todas as etapas. Considere um bit de guarda.) Exercício 3. (Não se preocupe com os sticky bits nesta questão.5> Calcule o produto de A e B manualmente.4 [20] <3. A B a.11.5> Calcule a soma de A e B à mão. –8. Escreva sua resposta como um padrão de 16 bits e também como um número decimal.3. Mostre todas as etapas.5> Os Hewlett-Packard 2114.11. A B a.1 [30] <3. 3. Considere um bit de guarda.11. e arredonde para o par mais próximo. por um capricho interessante. Considere um bit de guarda. Que formato é mais fácil para um programador lidar? Compare-os com o formato IEEE 754. Assume-se que existe um 1 oculto.3 [20] <3. e a mantissa tem 10 bits de extensão. um bit de arredondamento e um sticky bit.4 a 3. 2115 e 2116 usavam um formato com os 16 bits mais à esquerda sendo a mantissa armazenada no formato de complemento de dois.1. Agora. 3. Nenhum 1 oculto é utilizado.2 (e também descrito no texto).150390625 × 10–1 b. A tabela a seguir mostra pares de números decimais. considerando que eles estejam armazenados usando o formato descrito no Exercício 3. supondo que estes estejam armazenados no formato NVIDIA de 16 bits descrito no Exercício 3. o expoente era armazenado em formato de magnitude de sinal com o bit de sinal no canto direito! Escreva o padrão de bits considerando esse formato. e arredonde para o par mais próximo. um bit de arredondamento e um sticky bit. 8. 3. A tabela a seguir apresenta pares de números decimais.11. um bit de arredondamento e um sticky bit.0546875 × 100 –1.5> Escreva um programa em linguagem de máquina do assembly MIPS para calcular a soma de A e B. Escreva o padrão de bits considerando uma versão modificada desse formato que utiliza um formato com excesso de 16 para armazenar o expoente.5 [60] <3.11.12 A multiplicação de ponto flutuante é ainda mais complicada e desafiadora que a adição de ponto flutuante. e ambas são mínimas se comparadas à divisão de ponto flutuante. como acontece no exemplo do texto.11.79931640625 × 10–1 b.12. Indique se existe overflow ou underflow. modifique o programa para calcular a soma considerando o formato descrito no Exercício 3.6. 5> Calcule A dividido por B manualmente.12.984375 × 10–1 3. 3. Livermore Loop 9 3.3 [60] <3.12. uma técnica para realizar divisão de ponto flutuante em um computador digital.5> Escreva um programa para calcular o produto de A e B.5 [60] <3. . A tabela a seguir identifica os kernels individuais do conjunto. vejamos a lei associativa.netlib.13. 3.11 Exercícios 237 3. Os Livermore Loops1 são um conjunto de kernels intensos de ponto flutuante tirados de programas científicos executados no Lawrence Livermore Laboratory. 1. considerando que eles sejam armazenados no formato IEEE 754.4375 × 10–1 1. considerando que eles sejam armazenados no formato descrito no Exercício 3. comparando o resultado decimal com o que você obtém usando uma calculadora. um bit de arredondamento e um sticky bit. Mostre todas as etapas necessárias para se chegar à sua resposta. descrito no Exercício 3. Não se esqueça de incluir referências às fontes que você utilizou. 3.84375 × 100 1. e arredonde para o par mais próximo. Livermore Loop 3 b.12.3. Indique se existe overflow ou underflow.11. isso nem sempre acontece quando se trabalha com números de ponto flutuante. A B a.96875 × 100 8.2 [60] <3. Mostre todas as etapas e escreva sua resposta em formato de ponto flutuante de 16 bits e em decimal. Primeiro. Contudo. 3. associativa e distributiva permanecem. considerando que A. (Lembre-se de que o IEEE 754 considera um bit de guarda.1. de arre- dondamento e um sticky bit. modifique o programa para calcular o produto considerando o formato descrito no Exercício 3. 3. Agora.46875 × 100 2.org/benchmark/livermore. B e C são armazenados no formato NVIDIA de 16 bits.2 e em decimal. e use-os se for necessário.5> Escreva o loop na linguagem assembly MIPS.5> Escreva um programa em linguagem assembly MIPS para calcular o produto de A e B.12.5> Descreva. 1 Você poderá encontrá-los em http://www. Escreva a resposta final em formato de ponto flutuante com 16 bits descrito no exercício 3. Considere um bit de guarda. Exercício 3.) 3.3203125 × 100 3.5.6 [60] <3.2.875 × 100 b. Que formato é mais fácil para um programador lidar? Compare-os com o formato IEEE 754.11. 3. Suponha que exista um bit de guarda. e arredonde para o par mais próximo. 8.13 As operações realizadas sobre inteiros de ponto fixo se comportam como se espera — as leis comutativa.625 × 101 –4.4 [30] <3.1921875 × 101 3.) A tabela a seguir mostra outros pares de números decimais.11. A tabela a seguir mostra conjuntos de números decimais.11.1 [20] <3. com detalhes.12.6> Calcule (A + B) + C manualmente. A B C a. um bit de arredondamento e um sticky bit.771 × 103 b. (Não se preocupe com os sticky bits nesta questão.  a.2 (e também descrito no texto). 3. 3. 3. Mostre todas as etapas e escreva sua resposta em formato de ponto flutuante de 16 bits e em decimal. Considere um bit de guarda.2.05625 × 102 b.3. B e C são armazenados no formato NVIDIA de 16 bits. 3.13.4 [30] <3.14. Mostre todas as etapas e escreva sua resposta em formato de ponto flutuante de 16 bits e em decimal.2.238 Capítulo 3  Aritmética Computacional 3.2 (e também descrito no texto).14.135 × 102 9. Considere um bit de guarda.2.34765625 × 10–3 1. Mostre todas as etapas e escreva sua resposta em formato de ponto flutuante de 16 bits e em decimal. 3.14.13. B e C são armazenados no formato NVIDIA de 16 bits.2 [20] <3. 3.1 e 3.1 e 3. 3. Considere um bit de guarda.6 [10] <3. e arredonde para o par mais próximo. B e C são armazenados no formato NVIDIA de 16 bits.3 [10] <3. Mostre todas as etapas.052734375 × 10–2 3. e arredonde para o par mais próximo.5.6> Com base nas suas respostas dos Exercícios 3. 3.2 (e também des- crito no texto).11.13.84375 × 10–1 3. 3. 3.13.666015625 × 100 1. 3.3.5.11. e arredonde para o par mais próximo.5.3.2. considerando que A. 3. 3.13. 3.11. descrito no Exercício 3.14 A lei associativa não é a única que nem sempre se mantém quando se lidam com números de ponto flutuante.5.6> Com base nas suas respostas dos Exercícios 3. considerando que A.6> Calcule A × (B + C) manualmente. 3.5.5.3. descrito no Exercício 3.1 [30] <3.6> Calcule A + (B + C) manualmente. (A × B) + (A × C) = A × (B + C)? . descrito no Exercício 3. A tabela a seguir mostra conjuntos de números decimais.2. e arredonde para o par mais próximo.5. um bit de arredondamento e um sticky bit. considerando que A. um bit de arredondamento e um sticky bit.13. B e C são armazenados no formato NVIDIA de 16 bits. um bit de arredondamento e um sticky bit.5.13.2 (e também descrito no texto). 3.2 (e também descrito no texto). 3.34765625 × 10–2 –4.13. 1.6> Calcule A × (B × C) manualmente. A B C a. descrito no Exercício 3. Existem outras coisas estranhas que também ocorrem.5.6> Com base nas suas respostas dos Exercícios 3.3 [10] <3. Mostre todas as etapas e escreva sua resposta em formato de ponto flutuante de 16 bits e em decimal. 3.4 e 3. 3. 3. 1.9760 × 104 –1.14. 3. um bit de arredondamento e um sticky bit.5 [30] <3.2 [30] <3.140625 × 102 –9. 3. e arredonde para o par mais próximo. Considere um bit de guarda. considerando que A. A B C a.3.11. descrito no Exercício 3.2.14. (A + B) + C = A + (B + C)? A tabela a seguir mostra outros conjuntos de números decimais. 3. 3.6> Calcule (A × B) + (A × C) manualmente. um bit de arredondamento e um sticky bit.6> (A × B) × C manualmente. 3.11.3. 3.48 × 102 6.9744 × 104 b.2 (e também descrito no texto).13.41796875 10–3 6. (A × B) × C = A × (B × C)? Exercício 3. B e C são armazenados no formato NVIDIA de 16 bits. considerando que A. e escreva sua resposta em formato de ponto flutuante de 16 bits e em decimal.2. Considere um bit de guarda. 3. –1/4 4 b. cada um consistindo em uma fração e um inteiro.4 [20] <3. Respostas das §3. mas eles não precisam ser binários. Números de base 15 usariam 0-9 e A-E.6> O que você obtém se somar A a si mesmo B vezes? Quanto é A × B? Eles são iguais? O que deveriam ser? 3.5.2 [10] <3. (Números de base 16 utilizam os símbolos 0-9 e A-F.) Suponha que existam 24 bits e você não precisa normalizar.3. em vez da base 2. 3. 3. 3. 3.15 Números binários são utilizados no campo de mantissa.4: página 269: 3. Seções “Verifique você mesmo” . (Escreva um programa para realizar esses cálculos.14.) Suponha que existam 24 bits e você não precisa normalizar.5. Essa representação é exata? Você consegue ver alguma vantagem no uso dessa técnica? §3.6> Escreva o padrão de bits na mantissa considerando um formato de ponto flutuante que usa números Binary Coded Decimal (base 10) na mantissa. A tabela a seguir mostra frações a serem representadas em diversos formatos de ponto flutuante. a. 3.11 Exercícios 239 A tabela a seguir mostra dois pares.15.4 [10] <3.4.2.5 [10] <3.2. em vez da base 2. Essa representação é exata? 3.6> Escreva o padrão de bits supondo que estamos usando números de base 15 na mantissa. cada uma com suas vantagens e desvantagens em particular.5. Essa representação é exata? 3. 3. A IBM usou números de base 16.2: página 229: 3. por exemplo.1 [10] <3. 1/10 3.) Exercício 3.14. Você consegue representar A com exatidão? 3.6> Escreva o padrão de bits na mantissa considerando um formato de ponto flutuante que usa números binários na mantissa (basicamente.15. Suponha que existam 24 bits e você não precisa normalizar. o que você esteve fazendo neste capítulo). 1/3 b.15. Suponha que existam 24 bits e você não precisa normalizar. Números de base 30 usariam 0-9 e A-T.6 [60] <3.5. 1/10 10 3. em alguns de seus formatos de ponto flutuante. (Números de base 16 utilizam os símbolos 0-9 e A-F.5. 3.5> Usando o formato de ponto flutuante IEEE 754.6> Escreva o padrão de bits supondo que estamos usando números de base 30 na mantissa. escreva o padrão de bits que representaria A. 3. Essa representação é exata? 3.15.5.14. 3.3 [10] <3. A B a. 3.6> O que você obtém se apanhar a raiz quadrada de B e depois multiplicar esse valor por si mesmo? O que você deveria obter? Faça isso para números de ponto flutuante com precisão simples e dupla. 3.3. Existem outras técnicas que também são possíveis. em vez da base 2. 6 Caminho de dados e controle usando Provérbio francês pipeline  276 4. 4 O Processador 4.3 Construindo um caminho de dados  248 Em um assunto importante. 4.5 Visão geral de pipelining  265 4.8 Hazards de controle  302 4.9 Exceções  309 .7 Hazards de dados: forwarding versus stalls  292 4. 4.1 Introdução  242 4.4 Um esquema de implementação simples  254 nenhum detalhe é pequeno.2 Convenções lógicas de projeto  245 4. 16 Exercícios 330 Os cinco componentes clássicos de um computador .14 Comentários finais  329 4.11 Vida real: o pipeline do AMD Opteron X4 (Barcelona)  325 4.10 Paralelismo e paralelismo avançado em nível de instrução  315 4.15 Perspectiva histórica e leitura adicional  330 4.12 Tópico avançado: uma introdução ao projeto digital usando uma linguagem de projeto de hardware para descrever e modelar um pipeline e mais ilustrações de pipelining  328 4.13 Falácias e armadilhas  328 4.4. AND. Examinando a implementação. 4. teremos a oportunidade de ver como o conjunto de instruções determina muitos aspectos da implementação e como a escolha de várias estratégias de implementação afeta a velocidade de clock e o CPI para o computador. j As instruções brench equal (beq) e jump (j).4 e 4.8 e 4. construímos o caminho de dados e a unidade de controle para duas implementações diferentes do conjunto de instruções MIPS. começando com uma sinopse altamente abstrata e sim- plificada nesta seção. tanto o tempo de ciclo de clock quanto o número de ciclos de clock por instrução são determinados pela implementação do processador. Ela também oferece várias outras ilustrações de como o hardware do pipelining é executado. nem inclui qualquer instrução de ponto flutuante. Tendências recentes são abordadas na Seção 4. O compilador e o conjunto de instruções. e a Se- ção 4.11 descreve o recente microprocessador AMD Opteron X4 (Barcelona). seguida de uma seção que desenvolve conceitos necessários para implementar conjuntos de instruções mais complexos.3. Entretanto. desde servidores de alto desempenho até microprocessadores de finalidade geral e processadores embutidos. Neste capítulo.5 apresentam os conceitos básicos do pipelining. Ela é seguida de uma seção que desenvolve um caminho de dados e constrói uma versão simples de um processador suficiente para implementar conjuntos de instruções como o MIPS. e depois como usar uma linguagem de projeto de hardware para descrever uma implementação em pipeline. que examinamos no Capítulo 2. Aqueles interessados em aprender como montar um processador também devem ler as Seções 4. os princípios básicos usados na criação de um caminho de dados e no projeto do controle são ilustrados. sub. . como os princípios Torne o caso comum mais rápido e A simplicidade favorece a regularidade. O corpo do capítulo descreve uma implementação MIPS otimizada e mais realista. j As instruções lógicas e aritméticas add. j As instruções de referência à memória load word (lw) e store word (sw). OR e slt.242 Capítulo 4  O Processador 4. as Seções 4. Para o leitor interessado em entender a interpretação de alto nível de instruções e seu impacto sobre o desempenho do programa. A implementação das outras instruções é semelhante. que acrescentamos depois. Uma implementação MIPS básica Analisaremos uma implementação que inclui um subconjunto do conjunto de instruções MIPS básico. Estas seções oferecem uma base suficiente para entender os conceitos de pipeline em um alto nível. a Seção 4.12 no site descreve como as linguagens de projeto de hardware e as ferramentas de CAD são usadas na implementação do hardware.2.6 serão úteis. tempo de ciclo de clock e CPI (ciclos de clock por instru- ção).7.10. Muitos dos princípios básicos de projeto apresentados no Capítulo 1 podem ser ilustrados considerando-se a implementação. Além disso.1   Introdução O Capítulo 1 explica que o desempenho de um computador é determinado por três fatores principais: contagem de instruções. Entretanto. Esse subconjunto não inclui todas as instruções de inteiro (por exemplo. multiply e divide estão ausentes). 4. Para os leitores interessados no projeto de hardware moderno. determinam a contagem de instruções necessária para um determinado programa. como o x86. Para os leitores que desejam um entendimento do processador e seu desempenho com mais profundidade. esta seção inicial e a Seção 4. Este capítulo contém uma explicação dos princípios e das técnicas usados na im- plementação de um processador.9. 4. shift. a maioria dos conceitos usados para implementar o subconjunto MIPS neste capítulo e no próximo envolvem as mesmas ideias básicas usadas para construir um amplo espectro de computadores. Uma instrução de referência à memória precisará acessá-la a fim de escrever dados para um load ou ler dados para um store. usando campos da instrução para selecionar os regis- tradores a serem lidos. as ações necessárias para com- pletar várias classes de instrução diferem. para cada uma das três classes de instrução (referência à memória. Uma unidade de controle. essas operações são direcionadas por linhas de controle que são definidas com base nos vários campos das instruções. focando as várias unidades funcionais e sua interconexão. e desvios). a ALU precisa realizar uma de várias operações. incluindo as instruções lógicas e aritméticas. A simplicidade e a regularidade do conjunto de instruções simplifica a implementação tornando semelhantes as execuções de muitas das classes de instrução. Por exemplo. O terceiro multiplexador – que determina se PC + 4 ou o endereço de destino do desvio é escrito no PC – é definido com base na saída zero da ALU. as ações necessárias para completar a instrução dependem da classe da instrução. Essa seleção normalmente é feita com um dispositivo chamado multiplexador. Para a instrução load word. essas linhas de dados não podem simplesmente ser interligadas. podemos ter de mudar o próximo endereço de instrução com base na comparação.1 Introdução 243 Uma sinopse da implementação No Capítulo 2 vimos instruções MIPS básicas. O banco de registradores precisa ser escrito em uma instrução load e em uma instrução lógica ou aritmética. as de referência à memória e as de desvio. Finalmente. A segunda omissão na Figura 4. O Apêndice C descreve o multiplexador. embora uma melhor denominação desse dispositivo seria seletor de dados. 4. usada para . A Figura 4. As instruções de referência à memória usam a ALU para o cálculo de endereço. Por exemplo. as ações são quase as mesmas. Por exemplo. Primeiro. Muito do que precisa ser feito para implementar essas instruções é igual. lógica e aritmética. Felizmente. Uma instrução lógica e aritmética precisa escrever os dados da ALU de volta a um registrador. precisamos adicionar um elemento que escolha dentre as diversas origens e conduza uma dessas origens a seu destino. 2.) Assim como os multiplexadores. independente da classe exata da instrução. Após essas duas etapas. que seleciona entre várias entradas com base na configuração de suas linhas de controle. é claro. Na prática.1 mostra os dados indo para uma determinada unidade. caso contrário. as instruções lógicas e aritméticas para a execução da operação e desvios para comparação. ela omite dois importantes aspectos da execução da instrução. usam a unidade lógica e aritmética (ALU) após a leitura dos registradores. Ler um ou mais registradores. para uma instrução de desvio. E. vindo de duas origens diferentes. Enviar o contador de programa (PC) à memória que contém o código e buscar a instrução dessa memória. precisamos ler apenas um regis- trador. as duas primeiras etapas são idênticas: 1. mas a maioria das outras instruções exige a leitura de dois registradores. como vimos no Capítulo 2. em vários lugares. os dados escritos no banco de registradores podem vir da ALU ou da memória de dados. (O Apêndice C descreve o projeto detalhado da ALU.2 mostra o caminho de dados da Figura 4. todas as classes de instrução. Após usar a ALU. exceto jump. seja qual for a instrução exata.1 é que várias das unidades precisam ser controladas de acordo com o tipo da instrução.1 com os três multiplexadores necessários acrescentados. e a segunda entrada da ALU pode vir de um registrador ou do campo imediato da instrução. Embora essa figura mostre a maioria do fluxo de dados pelo processador. Para cada instrução.1 mostra a visão em alto nível de uma implementação MIPS. o valor escrito no PC pode vir de dois somadores. o PC deve ser incrementado em 4 a fim de chegar ao endereço da próxima instrução. A Figura 4. As linhas de con- trole são definidas principalmente com base na informação tomada da instrução sendo executada. é usada para determinar como definir as linhas de controle para as unidades funcionais e dois dos multiplexadores. a Figura 4. a memória de dados precisa ler em um load e escrever em um store. que tem a instrução como uma entrada. bem como as linhas de controle para as principais unidades funcionais. Uma vez que os operandos tenham sido buscados. refinamos essa visão para preencher os detalhes. aumentemos o número das conexões entre unidades e. o resultado da ALU precisa ser escrito em um registrador.244 Capítulo 4  O Processador FIGURA 4. Os desvios exigem o uso da saída da ALU para determinar o próximo endereço de instrução. mostramos explicitamente quando as linhas que se cruzam estão conectadas pela presença de um ponto no local do cruzamento. cada instrução começa a execução em uma transição do clock e completa a execução na próxima transição do clock. eles podem ser operados de modo a calcular um endereço de memória (para um load ou store). Verifique Quantos dos cinco componentes clássicos de um computador – mostrados no início deste você mesmo capítulo – as Figuras 4. Se a instrução for uma instrução lógica ou aritmética. que vem da ALU (em que o offset do PC e do desvio são somados) ou de um somador que incrementa o PC atual em 4.2 contêm? . As linhas grossas interconectando as unidades funcionais representam barramentos. As Seções 4. que consistem em múltiplos sinais. o que exige que acrescentemos mais unidades funcionais.2. Embora seja mais fácil de entender.1 e 4. Se a operação for um load ou store.1  Uma visão abstrata da implementação do subconjunto MIPS mostrando as principais unidades funcionais e as principais conexões entre elas. veremos uma implementação em pipeline com todas as suas com- plexidades. Depois que a instrução é buscada. os registradores usados como operandos pela instrução são especificados por campos dessa instrução. O resultado da ALU ou memória é escrito de volta no banco de registradores.3 e 4. Após projetar o controle desse computador simples.4 descrevem uma im- plementação simples que usa um único ciclo de clock longo para cada instrução e segue a forma geral das Figuras 4. esse método não é prático. No restante do capítulo. Todas as instruções começam usando o contador de programa para fornecer o endereço de instrução para a memória de instruções. é claro. Nesse primeiro projeto. adicionemos uma unidade de controle a fim de controlar que ações são realizadas para diferentes classes de instrução. já que o ciclo de clock precisa ser esticado para acomodar a instrução mais longa. calcular um resultado aritmético (para uma instrução lógica ou aritmética) ou a comparação (para um desvio). realizar a comparação da instrução beq. Como as linhas de sinal podem se cruzar. incluindo as exceções. As linhas são usadas para guiar o leitor sobre como as informações fluem.1 e 4. o resultado da ALU é usado como um endereço com a finalidade de armazenar o valor de um registrador ou ler um valor da memória para um registrador. A regularidade e a simplicidade do conjunto de instruções MIPS significam que um simples processo de decodificação pode ser usado no sentido de determinar como definir as linhas de controle. sig. O multiplexador superior (“Mux”) controla que valor substitui o PC (PC + 4 ou o endereço de destino do desvio). provavelmente será útil ler o Apêndice C antes de continuar.2  A implementação básica do subconjunto MIPS incluindo as linhas de controle e os multiplexadores necessários. 4.1 e discutida no Apêndice C é um exemplo de elemento combinacional. As linhas de controle acrescentadas são simples e determinam a operação realizada pela ALU. Os elementos que operam nos valores dos dados são todos combinacionais. Esta seção examina algumas ideias básicas na lógica digital que usaremos em todo o capítulo. O multiplexador cuja saída retorna para o banco de registradores é usado para conduzir a saída da ALU (no caso de uma instrução lógica ou aritmética) ou a saída da memória de dados (no caso de um load) a ser escrita no banco de registradores. elemento operacional. um elemento combinacional sempre produz a mesma saída. As linhas de controle são mostradas em tons de cinza para que sejam vistas com mais facilidade. elemento combinacional Um nificando que suas saídas dependem apenas das entradas atuais. A ALU mostrada na Figura 4. como uma porta AND ou uma ALU. precisamos decidir como a implementação lógica do computador irá operar e como esse computador está sincronizado. se a memória de dados deve ler ou escrever e se os registradores devem realizar uma operação de escrita. . Finalmente. 4. Dada a mesma entrada. o multiplexador é controlado pela porta que realiza um AND da saída Zero da ALU com um sinal de controle que indica que a instrução é de desvio. Dado um con- junto de entradas.2  Convenções lógicas de projeto Para tratar do projeto de um computador.2  Convenções lógicas de projeto 245 FIGURA 4. o multiplexador da parte inferior é usado de modo a determinar se uma segunda entrada da ALU vem dos regis- tradores (para uma instrução lógica-aritmética OU um desvio) ou do campo offset da instrução (para um load ou store). ele sempre produz a mesma saída porque não possui qualquer armaze- namento interno. Se você tiver pouco ou nenhum conhecimento em lógica digital. Os elementos do caminho de dados na implementação MIPS consistem em dois tipos diferentes de elementos lógicos: aqueles que operam nos valores dos dados e os que contêm estado. Todos os elementos de estado. Um elemento de estado possui pelo menos duas entradas e uma saída. que determina quando o valor dos dados deve ser escrito. . poderíamos reiniciá-lo ou uma memória. consideraremos uma metodologia de sincronização acionada por por transição  Um esquema transição. um elemento de estado pode ser lido a qualquer momento. Ela é importante para especificar a sincronização das leituras e escritas porque. nossa implementação MIPS também usa dois outros tipos de elementos de estado: memórias e registradores. baixo. Uma metodologia de clocking tem o objetivo de garantir a previsibilidade. bem como os registradores. o termo ativar ou verdadeiro. são considerados acionados por transição. uma transição do clock. Em um sistema digital síncrono. seria como se o computador nunca tivesse perdido a energia. corresponder ao valor antigo. os elementos de estado e o clock estão intimamente relacio- nados. ao valor recém-escrito ou mesmo alguma combinação dos dois! Obviamente. pois. enquanto as saídas são valores que podem ser usados em um ciclo de clock seguinte. ativo  O sinal está logicamente alto. mas contêm estado. os projetos de computadores não podem tolerar essa imprevisibilidade. Além dos flip-flops. Chamamos esses elementos de ele- da memória. A Figura 4. Na Figura 4. o clock determina quando os elementos com estado escreverão valores no armazenamento interno. Como apenas os elementos de estado podem armazenar valores de dados. carregando os elementos de estado com os valores que continham antes de interrompermos a energia. o valor da leitura poderia e estáveis em relação ao clock. Além disso. se salvássemos e armazenássemos novamente os elementos de estado. a saída da unidade funcional representando os registradores depende dos números de registrador fornecidos e do que foi escrito nos registradores anteriormente. Usaremos o termo ativo para indicar um sinal que está logicamente alto. Uma metodologia de sincronização acionada por transição significa que quais- de clocking em que todas as mudanças de estado ocorrem quer valores armazenados em um elemento lógico sequencial são atualizados apenas em em uma transição do clock. O clock é usado para determinar quando se deve escrever no elemento de estado. Por exemplo. Os componentes lógicos que contêm estado também são chamados de sequenciais porque suas saídas dependem de suas entradas e do conteúdo do estado interno. A operação dos elementos combinatórios e sequenciais e sua construção são discutidas em mais detalhes no Apêndice C. um dos elementos de estado mais sim- ples logicamente é um flip-flop tipo D (veja o Apêndice C). quando os dados são válidos se um sinal fosse escrito ao mesmo tempo em que fosse lido. se desconectássemos o computador da tomada. que opera em um único ciclo de clock: todos os sinais precisam se propagar FIGURA 4. ou falso. incluindo a memória. Um elemento elemento de estado  Um elemento contém estado se tiver algum armazenamento interno. ambos aparecendo na Figura 4. ter alcançado um valor do qual não mudarão até após a transição do clock) antes que a transição ativa do clock faça com que o estado seja atualizado. como um registrador mentos de estado.1. Por exemplo.246 Capítulo 4  O Processador Outros elementos no projeto não são combinatórios. A saída de um elemento de estado fornece o valor escrito em um ciclo de clock anterior.3 mostra os dois elementos de estado em volta de um bloco de lógica com- binatória. Metodologia de clocking metodologia de clocking  Uma metodologia de clocking define quando os sinais podem ser lidos e quando podem O método usado para determinar ser escritos. que possui exatamente essas duas entradas (um valor e um clock) e uma saída. As entradas são valores escritos em um ciclo de clock anterior. para especificar que um sinal deve ser conduzido a logicamente alto. e desativar ou inativo inativo  O sinal está logicamente para representar o que é logicamente baixo.1. qualquer coleção de lógica combinatória precisa ter suas entradas vindo de um conjunto de elementos de estado e suas saídas escritas em um conjunto de elementos de estado. sincronização acionada Para simplificar. Quaisquer entradas em um único elemento precisam alcançar um valor estável (ou seja. As entradas necessárias são os valores dos dados a serem escritos no elemento e o clock. são exemplos de elementos de estado. as memórias de instruções e de dados.3  A lógica combinatória. não há qualquer feedback dentro de um único ciclo de clock. Além disso. já que as entradas no bloco de lógica combinatória não podem mudar exceto na transição de clock escolhida. Nossos projetos neste capítulo e no próximo se baseiam na metodologia de sincronização acionada por transição e em estruturas como a mostrada nesta figura. naturalmente. É claro que o ciclo de clock ainda precisa ser longo o suficiente para que os valores de entrada sejam estáveis quando a transição ativa do clock ocorrer. 1 representa logicamente alto e às vezes pode representar logicamente baixo. se um elemento de para seleção de multiplexador ou para direcionar a operação de uma estado não for atualizado em cada clock. Se o feedback fosse possível. sinal de controle  Um sinal usado to de estado é escrito em cada transição ativa de clock. esse projeto não poderia funcionar corretamente. Algumas vezes. Sempre que uma unidade tiver uma entrada ou saída diferente de 32 bits de extensão. com linhas mais grossas. rótulos nas linhas de barramento indicarão que estamos concatenando barramentos para formar um mais largo. 4.4 mostra um exemplo genérico. Para a arquitetura MIPS de 32 bits. um sinal de dados.2  Convenções lógicas de projeto 247 desde o elemento de estado 1. Não importa se consideramos que todas as escritas ocorrem na transição de subida do clock ou na transição de descida. bem como outras metodologias de sincronização. A Figura 4. . Detalhamento:  Há também uma versão de 64 bits da arquitetura MIPS e. Finalmente. Uma metodologia acionada por transição permite ler o conteúdo de um registrador. Nesses casos. O feedback não pode ocorrer dentro de um ciclo de clock devido à atualização acionada por transição do elemento de estado. No Apêndice C. já que essa é a extensão da maioria dos dados manipulados pelo processador. e o elemen. Por outro lado. às vezes. FIGURA 4. a maioria dos caminhos em sua implementação teria 64 bits de largura. por exemplo. quase todos esses elementos de estado e lógicos terão entradas e saídas contendo 32 bits de extensão. Tanto o sinal de clock quanto o sinal de controle de escrita são entradas. usamos os termos ativar e desativar porque. o realce indica um sinal de controle em oposição a um sinal que conduz dados. passando pela lógica combinatória e indo até o elemento 2 no tempo de um ciclo de clock. unidade funcional.4 funciona corretamente. Setas também são incluídas para ajudar a es- clarecer a direção do fluxo dos dados entre elementos. essa distinção se tornará mais clara enquanto avançarmos neste capítulo. que contém to de estado só é alterado quando o sinal de controle de escrita está ativo e ocorre uma informações operadas por uma transição do clock. e a lógica na Figura 4. desejaremos combinar vários barramentos para formar um barramento mais largo. Para simplificar. Verdadeiro ou falso: como o banco de registradores é lido e escrito no mesmo ciclo de Verifique clock. deixaremos isso claro. contrasta com sário. não mostraremos um sinal de controle de escrita quando um elemen. Com uma metodologia de sincronização acionada por transição. As figuras indicarão barra- mentos (que são sinais mais largos do que 1 bit). discutimos brevemente as outras limitações (como os tempos de setup e hold). O tempo necessário para os sinais alcançarem o elemento 2 define a duração do ciclo de clock. qualquer caminho de dados MIPS usando escritas acionadas por transição precisa você mesmo ter mais de uma cópia do banco de registradores. podemos querer obter um barramento de 32 bits combinando dois de 16 bits.4  Uma metodologia acionada por transição permite que um elemento de estado seja lido e escrito no mesmo ciclo de clock sem criar uma disputa que poderia levar a valores de dados indeterminados. um sinal de controle de escrita explícito é neces- unidade funcional. enviar o valor por meio de alguma lógica combinatória e escrever nesse registrador no mesmo ciclo de clock. executado. . isso não é difícil de incluir e o ignoramos em favor da simplicidade. precisaremos de um somador a fim de incrementar o PC para o e aritmética (ALU) e os somadores.5 para formar um caminho de dados que busca instruções e incrementa o PC de modo a obter o endereço da próxima instrução sequencial. Finalmente. Quando mos- usada para operar sobre os dados tramos os elementos do caminho de dados.3  Construindo um caminho de dados Uma maneira razoável de iniciar um projeto de caminho de dados é examinar os principais elemento do caminho de componentes necessários para executar cada classe de instrução MIPS.5b mostra um registrador. Como a memória de instruções apenas é lida. Essa classe de instrução inclui add. A Figura 4. sub.) O contador de pro- grama é um registrador de 32 bits que é escrito no final de cada ciclo de clock e. também mostramos seus sinais de controle. FIGURA 4. Na implementação MIPS. Os elementos de estado são a memória de instruções e o contador de programa. A memória de instruções só precisa fornecer acesso de leitura porque o caminho de dados não escreve instruções. é um registrador que contém o endereço da ins- de registradores. nós a tratamos como lógica combinatória: a saída em qualquer momento reflete o conteúdo do local especificado pela entrada de endereço.5a mostra o primeiro elemento de que precisamos: uma unidade de memó- processador. (Precisamos escrever na memória de instruções quando carregarmos o programa. que lê $t2 e $t3 e escreve em $t1. como na Figura 4. vamos considerar as instruções de formato R (veja a Figura 2. A fim de preparar para executar a próxima instrução.5  Dois elementos de estado são necessários para armazenar e acessar instruções. Agora. A Figura 4. e nenhum sinal de controle de leitura é necessário. precisamos começar buscando a instrução na memó- ria. pode ser construído a partir da ALU que descrevemos em detalhes no Apêndice C. OR e slt. AND. não precisa de um sinal de controle de escrita. como vimos no Capítulo 2. $t3. a unidade lógica trução atual. simplesmente interligan- contador de programa (PC) O registrador contendo o endereço do as linhas de controle de modo que o controle sempre especifique uma operação de da instrução do programa sendo adição. para indicar que ela se tornou permanentemente um somador e não pode realizar as ou- tras funções da ALU. que é combinatório. $t2. os elementos do caminho ria para armazenar as instruções de um programa e fornecer instruções dado um endere- de dados incluem as memórias de ço. O somador é uma ALU configurada para sempre realizar a adição das suas duas entradas de 32 bits e colocar o resultado em sua saída. que podemos chamar de contador de programa instruções e de dados. que foram apresentadas no Capítulo 2. Lembre-se de que um caso típico desse tipo de instrução é add $t1. Para executar qualquer instrução. 4 bytes depois. realizam uma operação na ALU com o conteúdo dos registradores e es- crevem o resultado em um registrador. que. Vamos começar dados  Uma unidade funcional olhando quais elementos do caminho de dados cada instrução precisa. Esse somador. Chamamos essas instruções de instruções tipo R ou instruções lógicas ou aritméticas (já que elas realizam operações lógicas ou aritméticas). Representaremos uma ALU desse tipo com o rótulo Add. Todas elas leem dois registradores. endereço da próxima instrução. portanto.20).248 Capítulo 4  O Processador 4.6 mostra como combinar os três elementos da Figura 4. também temos de incrementar o contador de programa de modo que aponte para a próxima instrução. o banco (PC). ou conter esses dados dentro de um A Figura 4.5. e um somador é necessário para calcular o endereço da próxima instrução. que precisa ser ativo para que uma escrita ocorra na transição do clock. A seguir. Para escrever uma palavra de dados.8 mostra esses dois elementos. com o campo offset de 16 bits com sinal contido na instrução. examinaremos o controle da ALU brevemente quando precisarmos saber como defini-lo. . precisaremos de duas entradas: uma para especificar o número do registrador a ser escrito e uma para fornecer os dados a serem escritos no registrador. considere as instruções MIPS load word e store word. precisaremos do banco de registradores e da ALU da Figura 4. A Figura 4. banco de registradores Um tradores em que qualquer registrador pode ser lido ou escrito especificando o número do elemento de estado que consiste em um grupo de registradores registrador no banco. Consequentemente. ler duas palavras de dados do banco de registradores e escrever uma palavra de dados no banco de registradores para cada instrução. enquanto a entrada de dados e os dois barramentos de saída de dados possuem 32 bits de largura cada um.7a mostra o resultado. Além disso. uma entrada de endereço e uma mais altos do item de dados maior entrada para os dados serem escritos na memória. o valor a ser armazenado também precisará ser lido do banco de registradores em que reside. Essas instruções calculam um endereço de memória somando o registrador de base. 4. que possuem o formato lw $t1. precisamos de um total de quatro entradas (três para números de registrador e uma para dados) e duas saídas (ambas para dados).3  Construindo um caminho de dados 249 FIGURA 4. que usa duas entradas de 32 bits e produz um resultado de 32 bits. precisamos de uma entrada no banco de registradores que especifique o número do registrador a ser lido e uma saída do banco de registradores que conduzirá o valor lido dos registradores. de destino. em $t1. Além disso. que é $t2. A fim de que cada palavra de dados seja lida dos registradores. A Figura 4. são controladas pelo sinal de controle de escrita. Os registradores de uso geral de 32 bits do processador são armazenados em uma estru- tura chamada banco de registradores. precisaremos que uma ALU opere nos valores lidos dos registradores. bem como um sinal de 1 bit se o resultado for 0. Um banco de registradores é uma coleção de regis. O banco de registradores contém o estado dos registradores do com- que podem ser lidos e escritos putador. do item de dados original nos bits portanto.offset_value($t2) ou sw $t1. Se a instrução for um load.7b mostra a ALU. que é $t1. precisaremos registrador a ser acessado. entretanto. O banco de registradores sempre gera como saída o conteúdo de quaisquer números de registrador que estejam nas entradas Registrador de leitura. o valor lido da memória precisará ser escrito no banco de registradores no registrador especificado. As escritas. A Figura 4. As entradas de número de registrador possuem 5 bits de largura para especificar um dos 32 registradores (32 = 25). e de uma unidade de memória da tamanho de um item de dados replicando o bit mais alto de sinal qual ler ou na qual escrever. A memória de dados precisa ser escrita com instruções store.7. O sinal de controle de quatro bits da ALU é descrito em detalhes no Apêndice C. precisaremos de uma unidade a fim de estender o sinal do campo offset de estender o sinal  Aumentar o 16 bits da instrução para um valor com sinal de 32 bits. ela tem sinais de controle de leitura e escrita. Se a instrução for um store.6  Uma parte do caminho de dados usada para buscar instruções e incrementar o contador do programa.offset_value($t2). fornecendo um número de Devido às instruções de formato R terem três operandos de registrador. A instrução buscada é usada por outras partes do caminho de dados. diferente do banco de registradores. além do banco de registradores e da ALU da Figura 4. os chips de memória padrão possuem um sinal “write enable” que é usado para escritas. são a unidade de memória de dados e a unidade de extensão de sinal. Ao contrário. enquanto as linhas com os valores de dados possuem 32 bits de largura. Consideramos que a memória de dados é acionada por transição para as escritas. o valor a ser escrito.8  As duas unidades necessárias para implementar loads e stores. elas serão omitidas. como veremos no Capítulo 5. As entradas com o número do registrador para o banco de registradores possuem todas 5 bits de largura. .7  Os dois elementos necessários para implementar operações para a ALU no formato R são o banco de registradores e a ALU. usando a ALU projetada no Apêndice C. embora apenas um deles possa ser ativado em qualquer clock específico. já que. O banco de registradores sempre gera como saídas os conteúdos dos registradores correspondentes às entradas Registrador de leitura nas saídas. enquanto o valor escrito estará disponível para uma leitura em um ciclo de clock subsequente. Na verdade. Em breve.250 Capítulo 4  O Processador FIGURA 4. O banco de registradores contém todos os registradores e possui duas portas para leitura e uma porta para escrita. nosso projeto pode ler e escrever sem problemas no mesmo registrador dentro de um ciclo de clock: a leitura obterá o valor escrito em um ciclo de clock anterior. uma escrita em um registrador precisa ser explicitamente indicada ativando o sinal de controle de escrita. até lá. Lembre-se de que as escritas são acionadas por transição. A unidade de memória é um elemento de estado com entradas para os endereços e os dados de escrita. que terá largura de 4 bits. Existem controles de leitura e escrita separados.9. usaremos a saída de detecção Zero da ALU para implementar desvios. ler o valor de um endereço inválido pode causar problemas.7.8 do Apêndice C para ver uma discussão mais detalhada de como funcionam os chips de memória reais. A unidade de extensão de sinal possui uma entrada de 16 bits que tem o seu sinal estendido para que um resultado de 32 bits apareça na saída (veja o Capítulo 2). A unidade de memória precisa de um sinal de leitura. nenhuma outra entrada de controle é necessária.8 do Apêndice C. O projeto dos bancos de registradores de várias portas é discutido na Seção C. FIGURA 4. de modo que todas as entradas de escrita (por exemplo. Embora o write enable não seja acionado por transição. A operação a ser realizada pela ALU é controlada com o sinal de operação da ALU. nosso projeto acionado por transição poderia facilmente ser adaptado para funcionar com chips de memória reais. quando discutiremos as exceções. Como as escritas no banco de registradores são acionadas por transição. Consulte a Seção C. e uma única saída para o resultado da leitura. A saída de overflow não será necessária até a Seção 4. o número do registrador e o sinal de controle de escrita) precisam ser válidas na transição do clock. já que a quantidade de “deslocamento” é constante. os operandos são iguais). j A arquitetura também diz que o campo offset é deslocado 2 bits para a esquerda de modo que seja um offset de uma palavra.3  Construindo um caminho de dados 251 A instrução beq possui três operandos. Na arquitetura o Capítulo 2) para os quais precisamos prestar atenção: MIPS. esse deslocamento aumenta a faixa efetiva do campo offset por um fator de quatro vezes.offset. Como calculamos PC + 4 (o endereço seguinte ao desvio. dizemos que o desvio é não tomado. o destino do desvio é dado pela soma do campo offset da j O conjunto de instruções especifica que a base para o cálculo do endereço de desvio instrução e o endereço da instrução é o endereço da instrução seguinte ao desvio. . que se torna o novo trução. Há dois detalhes na definição de instruções de desvio (veja desvio for tomado. desvio  O endereço especificado em um desvio. o desvios incondicionais são desvios endereço de destino do desvio se torna o novo PC e dizemos que o desvio é tomado. Se os tomados. precisaremos deslocar o campo offset de dois bits. o caminho de dados de desvio precisa de duas operações: calcular o endereço e o contador do programa (PC) de destino do desvio e comparar o conteúdo do registrador.9 que acompanha sequencialmente mostra a estrutura do segmento do caminho de dados que lida com os desvios. Para lidar com a última complicação. deslocados de 2 bits para a esquerda. dois registradores comparados para igualdade e um offset de 16 bits para calcular o endereço de destino do desvio relativo ao endereço endereço de destino do da instrução desvio. A unidade rotulada como Deslocamento de 2 à esquerda é simplesmente um direcionamento dos sinais entre entrada e saída que acrescenta 00bin à extremidade da direita do campo offset com sinal estendido. da próxima instrução) no caminho de dados para busca de instruções.$t2. e próxima instrução é a instrução que acompanha sequencialmente ou a instrução no endere. com base na saída Zero da ALU. nenhum hardware de deslocamento real é necessário. Para o desvio. o deslocamento irá descartar apenas “bits de sinal”. operandos não forem iguais. o PC incrementado deve substituir o PC atual (exatamente como para qualquer outra instrução normal). Para implementar essa ins. 4. nesse caso.9  O caminho de dados para um desvio usa a ALU a fim de avaliar a condição de desvio e um somador separado para calcular o destino do desvio como a soma do PC incrementado e os 16 bits mais baixos da instrução com sinal estendido (o deslocamento do desvio). desvio não tomado  Um desvio em que a condição de desvio é falsa Portanto. como veremos em breve.) A Figura 4. também precisamos determinar se a a condição de desvio é satisfeita. Todos os ço de destino do desvio. Quando a condição é verdadeira (isto é. desvio tomado  Um desvio em que Além de calcular o endereço de destino do desvio. o contador do programa (PC) se torna o destino do desvio. é fácil usar esse valor como a base para calcular o endereço de destino do desvio. A lógica de controle é usada para decidir se o PC ou o destino do desvio incrementado deve substituir o PC. Sua forma é beq $t1. FIGURA 4. Como sabemos que o offset teve o sinal dos seus 16 bits estendido. precisamos calcular o endereço de destino somando o campo offset estendido com contador do programa (PC) se o sinal da instrução com o PC. (Os desvios também afetam a se torna o endereço da instrução parte da busca de instrução do caminho de dados. independente de com um desvio normal. Quando a condição é falsa. Mais adiante. podemos enviar os dois operandos de registrador para a ALU com o conjunto de controle de modo a fazer uma subtração.7a a fim de fornecer os dois operandos (embora não precisemos escrever no banco de registradores). As instruções de acesso à memória também podem usar a ALU para fazer o cálculo do endereço. sabemos que os dois valores são iguais. um desvio atrasado primeiro executa a condição do desvio ser verdadeira ou falsa. ignoramos os desvios atrasados neste capítulo e implementamos uma instrução beq como não sendo atrasado. Para simplificar. Esse deslocamento é realizado simplesmente concatenando 00 ao offset do jump. muitos dos elementos podem ser compartilhados por diferentes fluxos de instrução.252 Capítulo 4  O Processador calcular o endereço de destino do desvio. como descrito no Capítulo 2. Construindo um caminho de dados EXEMPLO As operações do caminho de dados das instruções lógicas e aritméticas (ou tipo R) e das instruções de acesso à memória são muito semelhantes. que use um . Embora algumas unidades funcionais precisem ser duplicadas. desvio atrasado  Um tipo Detalhamento:  No conjunto de instruções MIPS. podemos combiná-los em um único caminho de dados e acrescentar o controle para completar a implementação. embora a segunda entrada seja o campo offset de 16 bits com sinal estendido da instrução. nós a estaremos usando apenas para implementar o teste de igualdade dos desvios. A motivação para os desvios atrasados surge de como o pipe- lining afeta os desvios (veja a Seção 4. precisamos de uma memória para instruções separada de uma memória para dados. Além disso. Para realizar a comparação. Para compartilhar um elemento do caminho de dados entre duas classes de instrução diferentes. As principais diferenças são as seguintes: j As instruções lógicas e aritméticas usam a ALU com as entradas vindas de dois registradores. Quando a condição é verdadeira. Embora a saída de Zero sempre sinalize quando o resultado é 0. talvez tenhamos de permitir múltiplas conexões com a entrada de um elemento usando um multiplexador e um sinal de controle para selecionar entre as múltiplas entradas. a comparação pode ser feita usando a ALU que projetamos no Apêndice C. j O valor armazenado em um registrador de destino vem da ALU (para uma ins- trução tipo R) ou da memória (para um load). e um somador.8). precisamos usar o banco de registradores mostrado na Figura 4. Isso significa que nenhum recurso do caminho de dados pode ser usado mais de uma vez por instrução e. os desvios são atrasados. Como essa ALU fornece um sinal de saída que indica se o resultado era 0. A instrução jump funciona substituindo os 28 bits menos significativos do PC pelos 26 bits menos significativos da instrução deslocados de 2 bits à esquerda.8. qualquer elemento necessário mais de uma vez precisa ser duplicado. exatamente como a da Figura 4. Criando um caminho de dados simples Agora que examinamos os componentes do caminho de dados necessários para as classes de instrução individualmente. portanto. Se o sinal Zero da ALU estiver ativo. mostraremos exatamente como conectar os sinais de controle da ALU para uso no caminho de dados. O caminho de dados mais sim- ples pode tentar executar todas as instruções em um único ciclo de clock. independente de a imediatamente seguinte ao desvio é condição de desvio ser verdadeira ou falsa. Então. Mostre como construir um caminho de dados para a parte operacional das ins- truções de acesso à memória e das instruções lógicas e aritméticas. isso significa de desvio em que a instrução que a instrução imediatamente posterior ao desvio é sempre executada. a execução se parece sempre executada. a instrução imediatamente posterior ao desvio na ordem sequencial antes de desviar para o endereço de destino do desvio. o caminho de dados de desvio inclui uma unidade de extensão de sinal. A Figura 4. Para criar um caminho de dados com apenas um único banco de registradores e uma única ALU. MemparaReg deve ser definido para fazer com que os dados da memória sejam enviados ao banco de registradores.11 mostra o caminho de dados que obtemos compondo as partes separadas. 4. Dois multiplexadores são necessários. A instrução de desvio usa a ALU principal para comparação dos registradores operandos. A unidade de controle precisa ser capaz de ler entradas e gerar um sinal de escrita para cada elemento de estado. Portanto. incluindo quaisquer multiplexadores necessários. FIGURA 4.9). O controle da ALU é diferente de várias maneiras e será útil projetá-lo primeiro.10. o caminho de dados das instruções tipo R e de acesso à memória (Figura 4.10 mostra a parte operacional do caminho de dados combinado.3  Construindo um caminho de dados 253 único banco de registradores e uma única ALU para manipular os dois tipos de ins- trução.10  O caminho de dados para as instruções de acesso à memória e as instruções tipo R. o controle seletor de cada multiplexador e o controle da ALU.8 acrescentando multiplexadores. podemos acrescentar a unidade de controle. você mesmo a. antes de projetarmos o restante da unidade de controle. . Este exemplo mostra como um único cami- nho de dados pode ser montado das partes nas Figuras 4. de modo que precisamos manter o somador da Figura 4. Agora que completamos este caminho de dados simples. podemos combinar todas as partes de modo a criar um caminho de dados sim- ples para a arquitetura MIPS incluindo um caminho de dados para busca de instruções (Figura 4. Agora. precisamos suportar duas origens diferentes para a segunda entrada da RESPOSTA ALU. bem como duas origens diferentes para os dados armazenados no banco de registradores.7 e 4.10) e o caminho de dados para desvios (Figura 4. I. como descrito no exemplo.9 a fim de calcular o endereço de destino do desvio. um multiplexador é colocado na entrada da ALU e outro na entrada de dados para o banco de registradores. A Figura 4. Qual das seguintes afirmativas é correta para uma instrução load? Consulte a Verifique Figura 4.6). Um multiplexador adicional é necessário para selecionar o endereço de instrução seguinte (PC + 4) ou o endereço de destino do desvio a ser escrito no PC. Essa implementação simples cobre as instruções load word (lw). b. O suporte para jumps será incluído mais tarde. Não precisamos nos importar com MemparaReg para loads. memórias diferentes são necessárias. sub. c. o processador opera em um ciclo e não pode usar uma memória de porta simples para dois acessos diferentes dentro desse ciclo.11  O caminho de dados simples para a arquitetura MIPS combina os elementos necessários para diferentes classes de instrução. c. veremos o que poderia ser considerado a implementação mais simples pos- sível do nosso subconjunto MIPS. os formatos dos dados e das instruções são diferentes no MIPS. porque: a. e. O controle da ALU A ALU MIPS no Apêndice C define as 6 combinações a seguir das nossas entradas de controle: . II. portanto. 4. O caminho de dados de ciclo único descrito conceitualmente nesta seção precisa ter memórias de instrução e dados separadas. ter memórias separadas é menos dispendioso.6. Os componentes vêm das Figuras 4. b. store word (sw). Este caminho de dados pode executar as instruções básicas (load-store word. MemparaReg deve ser definido para fazer com que o registrador de destino correto seja enviado ao banco de registradores. branch equal (beq) e as instruções lógicas e aritméticas add. desenvolveremos o projeto para incluir uma instrução jump (j).4  Um esquema de implementação simples Nesta seção.254 Capítulo 4  O Processador FIGURA 4. Construímos essa implementação simples usando o caminho de dados da última seção e acrescentando uma função de controle simples. 4.10.9 e 4. AND. OR e set on less than. Um multiplexador adicional é necessário para integrar os desvios. Pos- teriormente. operações da ALU e desvios) em um único ciclo de clock. a ALU precisa realizar uma das cinco ações (AND. subtract. (NOR é necessária para outras partes do conjunto de instruções MIPS não encon- tradas no subconjunto que estamos implementando. a ação da ALU desejada não depende do campo de código funct. nesse caso. Observe que quando o código de OpALU é 00 ou 01.12  A forma como os bits de controle da ALU são definidos depende dos bits de controle de OpALU e dos diferentes códigos de função para as instruções tipo R. Esse estilo de usar vários níveis de decodificação – ou seja. Essas otimizações são importantes. mostramos como definir as entradas do controle da ALU com base no controle OpALU de 2 bits e no código de função de 6 bits. pois a velocidade da unidade de controle normalmente é essencial para o tempo de ciclo de clock. que aparece na primeira coluna. a unidade de controle princi- pal gera os bits de OpALU. FIGURA 4. determina a definição dos bits de OpALU. Usar níveis múltiplos de controle pode reduzir o tamanho da unidade de controle principal. a ALU precisará realizar uma dessas cinco primeiras funções. OpALU indica se a operação a ser realizada deve ser add (00) para loads e stores. Podemos gerar a entrada do controle da ALU de 4 bits usando uma pequena unidade de controle que tenha como entradas o campo funct da instrução e um campo control de 2 bits. Na Figura 4. que chamamos de OpALU. .) Para as instruções load word e store word. a ALU precisa realizar uma subtração. então o código de função é usado para definir a entrada do controle da ALU. Veja o Apêndice C. Quando o valor de OpALU é 10. dependendo do valor do campo funct (ou function – função) de 6 bits nos bits menos significativos da instrução (veja o Capítulo 2). A saída da unidade de controle da ALU é um sinal de 4 bits que controla diretamente a ALU gerando uma das combinações de 4 bits mostradas anteriormente. Mais adiante neste capítulo. OR.12. usamos a ALU para calcular o endereço de memória por adição. são usados como entrada para o controle da ALU que gera os sinais reais para controlar a ALU – é uma técnica de implementação comum. add ou set on less than). O opcode. veremos como os bits de OpALU são gerados na unidade de controle principal. Usar várias unidades de controle menores também pode aumentar a velocidade da unidade de controle. 4. Para instruções tipo R. dizemos que “não nos importamos” (don’t care) com o valor do código de função e o campo funct é mostrado como XXXXXX. Para branch equal.4  Um esquema de implementação simples 255 Linhas de controle Função da ALU 0000 AND 0001 OR 0010 add 0110 subtract 0111 set on less than 1100 NOR Dependendo da classe de instrução. que. Todas as codificações são mostradas em binário. subtract (01) para beq ou determinada pela operação codificada no campo funct (10). então. Algumas entradas don’t care foram incluídas. independente do código funct. uma Figura 4.2 do Apêndice D. quando os bits de OpALU são 00. Nesse caso. Os termos don’t care podem ser especificados de diversas plo. em vez de mostrar as etapas finais aqui. Por exem- as entradas. Esse processo é completamente mecânico. veremos exemplos de outro tipo de termo don’t care. Projetando a unidade de controle principal Agora que descrevemos como projetar uma ALU que usa o código de função e um sinal de 2 bits como suas entradas de controle. mostrando quais deverão ser as saídas resultantes.13  A tabela verdade para os 4 bits de controle da ALU (chamados Operação). Apenas as entradas para as quais o controle da ALU é ativado são mostradas. em cada dessas combinações de entrada.11.256 Capítulo 4  O Processador Há várias maneiras diferentes de implementar o mapeamento do campo OpALU de 2 bits e do campo funct de 6 bits para os 3 bits de controle de operação da ALU. Como uma etapa no projeto dessa lógica. como OpALU não usa a codificação 11. (Essa prática possui uma desvantagem. podemos voltar a considerar o restante do con- trole. não nos interessamos pelos valores de algumas das entradas e termo don’t care  Um elemento de para mantermos as tabelas compactas. Em todo este capítulo. é útil criar uma tabela verdade para as com- binações interessantes do campo de código funct e dos bits de OpALU.) Como. também incluímos termos don’t care. Como apenas um pequeno número dos 64 valores possíveis do campo funct são de interesse e o campo funct é usado apenas quando os bits de OpALU são iguais a 10. é útil .2 do Apêndice D. As entradas são OpALU e o campo de código funct. como na primeira linha da tabela na Figura 4. ela pode ser otimizada e depois transformada em portas lógicas.13. Se você não estiver familiarizado com o conceito de termos don’t care. então. os dois primeiros bits (F5 e F4) dessas instruções são sempre 10. descrevemos o processo e o resultado na Seção D. Para começar esse processo. vamos identificar os campos de uma instrução e as linhas de controle necessárias para o caminho de dados construído na Figura 4. em vez de 10 e 01. como fizemos na tabela verdade  Pela lógica. Depois. eles são termos don’t care e são substituídos por XX na tabela verdade. as entradas do código funct serão don’t care nessa linha da tabela verdade. Por exemplo. usaremos essa prática de mos- trar apenas as entradas da tabela verdade que precisam ser declaradas e não mostrar as que estão zeradas ou que não nos interessam. Como a tabela verdade inteira é muito grande lógica listando todos os valores das (28 = 256 entradas) e não nos importamos com o valor do controle da ALU para muitas entradas e em seguida. Uma vez construída a tabela. podemos usar uma pequena lógica que reconhece o subconjunto dos valores possíveis e faz a definição correta dos bits de controle da ALU. sempre definimos o controle da ALU em 010.13. portanto. essa tabela verdade mostra como o controle da ALU de 3 bits é definido de representação de uma operação acordo com esses dois campos de entrada. a tabela verdade pode conter entradas 1X e X1. FIGURA 4. que dis- cutimos na Seção D. em muitos casos. Um termo uma função lógica em que a saída don’t care nessa tabela verdade (representado por um X em uma coluna de entrada) in- não depende dos valores de todas dica que a saída não depende do valor da entrada correspondente a essa coluna. quando o campo funct é usado. Portanto. A fim de entender como conectar os campos de uma instrução com o caminho de dados. mostramos apenas as entradas para as quais o controle da caso. ALU precisa ter um valor específico. veja o Apêndice C para obter mais informações. Além disso. maneiras. O campo address de 16 bits tem seu sinal estendido. O registrador rs é o registrador de base adicionado ao campo address de 16 bits de modo a formar o endereço de memória. Isso é verdade para as instruções tipo R. Já definimos como o sinal de controle OpALU funciona e é útil definir o que fazem os outros sete sinais de controle informalmente antes de determinarmos como definir esses sinais de controle durante a execução da instrução. O primeiro princípio de projeto do Capítulo 2 — a simplicidade favorece a regularidade — vale aqui na especificação do controle. a operação e o formato de uma instrução. precisaremos incluir um multiplexador a fim de selecionar que campo da instrução será usado para indicar o número de registrador a ser escrito. rt e rd. sub. acesso à memória e desvio) usam dois formatos de instrução diferentes. Usando essas informações. As instruções tipo R que implementamos são add. cada um deles requer uma única linha de controle. rt é o registrador de origem cujo valor deve ser armazenado na memória. Iremos opcode  O campo que denota nos referir a esse campo como Op[5:0].14 mostra esses formatos. A Figura 4. A função da ALU está no campo funct e é decodificada pelo projeto de controle da ALU da seção anterior. branch equal e store. OR e slt. ele está nas posições 20:16 (rt). está sempre contido nos bits 31:26.14  As três classes de instrução (tipo R.4  Um esquema de implementação simples 257 FIGURA 4. as instruções de desvio e as instruções de acesso à memória. Essas instruções possuem três registradores como operandos: rs.16 descreve a função dessas sete linhas de controle. O campo shamt é usado apenas para deslocamentos. examinar os formatos das três classes de instrução: as instruções tipo R. nas posições 25:21 e 20:16.15 mostra sete linhas de controle de um único bit mais o sinal de controle OpALU de 2 bits. AND. (c) Formato de instrução para branch equal (opcode = 4). Os campos rs e rt são origens e rd é o destino. Como todos os multiplexadores possuem duas entradas. também chamado opcode. (b) Formato de instrução para instruções load (opcode = 35dec) e store (opcode = 43dec). . load e store está sempre nas posições 15:0. rt é o registrador de destino para o valor lido. Os registradores rs e rt são os registradores de origem que são comparados para igualdade. o sinal de leitura para a memória de dados e os sinais de controle para os multiplexadores. os sinais de escrita para elementos de estado. além do bloco de controle da ALU. Portanto. j Os dois registradores a serem lidos sempre são especificados pelos campos rs e rt. A Figura 4. as quais possuem todas opcode 0. podemos acrescentar os rótulos de instrução e o multiplexa- dor extra (para a entrada Registrador para escrita do banco de registradores) no caminho de dados simples. j Offset de 16 bits para branch equal. é deslocado e somado ao PC para calcular o endereço de destino do desvio. Existem várias observações importantes sobre esses formatos de instrução em que nos basearemos: j Campo op. Para um load. A Figura 4.15 mostra essas adições. 4. nós o ignoraremos neste capítulo. As instruções jump usam outro formato. Com os loads. enquanto para uma instrução tipo R. A Figura 4. j Registrador de destino está em um de dois lugares. ele está nas posições 15:11 (rd). (a) Formato de instrução para instruções tipo R. j Registrador de base para as instruções load e store está sempre nas posições de bit 25:21 (rs). Com stores. que será discutido em breve. Agora que examinamos a função de cada um dos sinais de controle. Os sinais de controle ativos e os elementos do caminho de dados ativos são destacados em cada uma das figuras. essas etapas são ordenadas pelo fluxo da informação: .15  O caminho de dados da Figura 4. A unidade de controle pode definir todos menos um dos sinais de controle uni- camente com base no campo opcode da instrução.12.258 Capítulo 4  O Processador FIGURA 4. for verdadeira.18. Operação do caminho de dados Com as informações contidas nas Figuras 4.16 e 4.17. Essa linha de controle deve ser ativada se a instrução for branch on equal (uma decisão que a unidade de controle pode tomar) e a saída Zero da ALU. O bloco de controle da ALU também foi acrescentado.12 com todos os multiplexadores necessários e todas as linhas de controle identificadas. A Figura 4. mesmo se sua linha de controle não estiver destacada.16 e 4. como add $t1. Esses nove sinais de controle (sete da Figura 4. 1 ou don’t care (X) para cada um dos valores de opcode. vejamos como cada instrução usa o caminho de dados.19 mostra a operação do caminho de dados para uma instrução tipo R. já que ele é escrito uma vez no fim de cada ciclo de clock. essas informações seguem diretamente das Figuras 4. que chamamos Branch.18 descreve como os sinais de controle devem ser definidos para cada opcode. a lógica de controle de desvio determina se ele é escrito com o PC incrementado ou o endereço de destino do desvio. mostramos o fluxo das três classes de instrução diferentes por meio do caminho de dados. O PC não exige um controle de escrita. A Figura 4. usada para comparação de igualdade. precisaremos realizar um AND de um sinal da unidade de controle.$t3. que são os bits de opcode 31 a 26. As linhas de controle são mostradas em cor. podemos projetar a lógica da unidade de controle. 4. A exceção é a linha de controle OrigPC.17 mostra o caminho de dados com a unidade de controle e os sinais de controle. Embora tudo ocorra em um ciclo de clock. Antes de fazer isso. com o sinal Zero da ALU. Como a definição das linhas de controle depende apenas do opcode. Sinais de controle de vários bits são destacados se qualquer sinal constituinte estiver ativo.16 e dois para OpALU) podem agora ser definidos baseados nos seis sinais de entrada da unidade de controle. Para gerar o sinal OrigPC. definimos se cada sinal de controle deve ser 0.$t2. será útil definir a função de controle informalmente. porém. podemos pensar em qua- tro etapas para executar a instrução. Observe que um multiplexador cujo controle é 0 tem uma ação definida. A Figura 4. Nas próximas figuras. podemos ver como defini-los. Antes de tentarmos escrever um conjunto de equações ou uma tabela verdade para a unidade de controle. Observe que OrigPC é agora um sinal derivado.) FIGURA 4.4  Um esquema de implementação simples 259 FIGURA 4. descartamos o nome do sinal nas próximas figuras. a saída da porta AND controla a seleção do próximo PC. e um sinal de controle de 2 bits para a ALU (OpALU). .17  O caminho de dados simples com a unidade de controle. já que isso pode criar problemas de sincronização. OrigALU e MemparaReg).16  O efeito de cada um dos sete sinais de controle. (Veja o Apêndice C para obter mais detalhes sobre esse problema. Portanto. está ativo. O clock nunca vem externamente para um elemento de estado. o multiplexador seleciona a entrada correspondente a 1. o multiplexador seleciona a entrada 0. 4. LeMem e EscreveMem). um sinal de 1 bit usado na determinação de um possível desvio (Branch). para um multiplexador com duas entradas. em vez de um sinal vindo diretamente da unidade de controle. As saídas da unidade de controle consistem em três sinais de 1 bit usados para controlar multiplexadores (RegDst. Uma porta AND é usada de modo a combinar o sinal de controle de desvio com a saída Zero da ALU. Lembre-se de que todos os elementos de estado têm o clock como uma entrada implícita e que o clock é usado para controlar escritas. Quando o controle de bit 1 de largura. Caso contrário. três sinais para controlar leituras e escritas no banco de registradores e na memória de dados (EscreveReg. se o controle não estiver ativo. A entrada para a unidade de controle é o campo opcode de 6 bits da ins- trução. Esse tipo de don’t care precisa ser acrescentado pelo projetista. que é o campo funct. Para todas essas instruções. LeMem e EscreveMem são ativados para realizar o acesso à memória. A ALU opera nos dados lidos do banco de registradores. Quando o sinal de controle Branch é 0. Repare que o campo MemparaReg é irrelevante quando o sinal EscreveReg é 0: como o registrador não está sendo es- crito. FIGURA 4. Finalmente. OR e slt). já que ela envia os registradores rs e rt para a ALU. Os don’t care também podem ser adicionados a RegDst quando EscreveReg é 0. A primeira linha da tabela corresponde às instruções formato R (add. Dois registradores. da instrução) para gerar a função da ALU. O campo OpALU para um desvio é definido como uma subtração (controle da ALU = 01). sub. o PC é substituído pelo destino do desvio se a saída Zero da ALU também está ativa.$t3. os campos registradores de origem são rs e rt. e o campo registrador de destino é rd. uma vez que ele depende do conhecimento de como o caminho de dados funciona.18  A definição das linhas de controle é completamente determinada pelos campos opcode da instrução. Portanto. usada para testar a igualdade.260 Capítulo 4  O Processador FIGURA 4. A instrução branch é semelhante à operação no formato R. 3. AND. isso especifica como os sinais OrigALU e RegDst são definidos. A instrução é buscada e o PC é incrementado. A segunda e a terceira linhas dessa tabela fornecem as definições dos sinais de controle para lw e sw. . mas não escreve ou lê a memória de dados. o PC é incondicionalmente substituído por PC + 4. 2. O resultado da ALU é escrito no banco de registradores usando os bits 15:11 da ins- trução para selecionar o registrador de destino ($t1).$t2. usando o código de função (bits 5:0. As linhas de controle. $t2 e $t3. 1. uma instrução tipo R escreve em um registrador (EscreveReg = 1). são lidos do banco de registradores. e a unidade de con- trole principal calcula a definição das linhas de controle também durante essa etapa. caso contrário.19  O caminho de dados em operação para uma instrução tipo R como add $t1. Esses campos OrigALU e OpALU são ativados para realizar o cálculo do endereço. RegDst e EscreveReg são ativados para que um load faça o resultado ser armazenado no registrador rt. Além disso. as unidades do caminho de dados e as conexões que estão ativas aparecem destacadas. O campo OpALU para as instruções tipo R é definido como 10 a fim de indicar que o controle da ALU deve ser gerado do campo funct. 4. a entrada MemparaReg nas duas últimas linhas da tabela é substituída por X (don’t care). o valor dos dados na entrada Dados para escrita do banco de registradores não é usado. A soma da ALU é usada como o endereço para a memória de dados. 4.4  Um esquema de implementação simples 261 Da mesma forma. mas a saída da ALU é usada para determinar se o PC é escrito . Ela opera de forma muito parecida com uma instrução de formato R. A principal diferença seria que o controle da memória indicaria uma escrita em vez de uma leitura.19. da mesma maneira. Uma instrução store operaria de maneira muito semelhante.20 mostra as unidades funcionais ativas e as linhas de controle ativas para um load. Podemos pensar em uma instrução load como operando em cinco etapas (semelhante ao tipo R executado em quatro): FIGURA 4. as unidades do caminho de dados e as conexões ativas aparecem destacadas. Um valor de registrador ($t2) é lido do banco de registradores. 5. Uma instrução é buscada da memória de instruções e o PC é incrementado.offset. A Figura 4. offset($t2) em um estilo semelhante à Figura 4. como beq $t1. As linhas de controle.20  O caminho de dados em operação para uma instrução load. 3.$t2. A ALU calcula a soma do valor lido do banco de registradores com os 16 bits menos significativos com sinal estendido da instrução (offset). Os dados da unidade de memória são escritos no banco de registradores. como lw $t1. podemos ilustrar a execução de um load word. o registrador de destino é fornecido pelos bits 20:16 da instrução ($t1). a segunda leitura do valor de um registrador seria usada para os dados a serem armazenados e a operação de escrita do valor da memória de dados no banco de registradores não ocorreria. 4. Finalmente. 1. 2. podemos mostrar a operação da instrução branch-on-equal. Op [5:0]. Mostramos essa etapa final na Seção D. A função de controle pode ser definida precisamente usando o conteúdo da Figura 4. A ALU realiza uma subtração dos valores de dados lidos do banco de registradores. são lidos do banco de registradores.2 no Apêndice D. a saída Zero é usada na seleção do próximo contador de programa dentre os dois candidatos. Finalizando o controle Agora que vimos como as instruções operam em etapas.262 Capítulo 4  O Processador FIGURA 4.22 mostra a lógica na unidade de controle como uma grande tabela verdade que combina todas as saídas e que usa os bits de opcode como entradas. vamos acrescentar a instrução jump para mostrar como o caminho uma instrução é executada em um de dados básico e o controle podem ser estendidos ao lidar com outras instruções no único ciclo de clock. A Figura 4. O valor de PC + 4 é somado aos 16 bits menos significativos com sinal estendido (offset) deslocados de dois para a esquerda. e podemos implementá-la diretamente em portas lógicas implementação de ciclo de uma maneira automatizada. Portanto. e a entrada é o campo opcode de 6 bits. 2. O resultado Zero da ALU é usado para decidir qual resultado do somador deve ser armazenado no PC.21 mostra as quatro etapas da execução: 1. .18. As linhas de controle. conjunto de instruções. as unidades do caminho de dados e as conexões que estão ativas aparecem destacadas. Uma instrução é buscada da memória de instruções e o PC é incrementado. Após usar o banco de registradores e a ALU para realizar a comparação. 4. Uma implementação em que truções MIPS básico. vamos continuar com a im- plementação do controle. o resultado é o endereço de destino do desvio. podemos criar uma tabela verdade para cada uma das saídas com base na codificação binária dos opcodes. Ela especifica com- pletamente a função de controle.21  O caminho de dados em operação para uma instrução branch equal. As saídas são as linhas de controle. Dois registradores. único  Também chamada de Agora que temos uma implementação de ciclo único da maioria do conjunto de ins- implementação de ciclo de clock único. A Figura 4. com PC + 4 ou o endereço de destino do desvio. $t1 e $t2. 3. Estenda o caminho de dados EXEMPLO e o controle da Figura 4.) A parte inferior da tabela fornece as saídas. o PC de destino de um branch ou o PC de destino de um jump.4  Um esquema de implementação simples 263 FIGURA 4. (Lembre-se de que Op [5:0] corresponde aos bits 31:26 da instrução. Uma classe de instruções ausente é a da instrução jump. 4. uma vez que isso é suficiente para distinguir as instruções no formato R das instruções lw. Um sinal de controle adicional é necessário para o multiplexador adicional. j campo de 26 bits imediato da instrução jump. Os próximos 26 bits menos significativos desse endereço de 32 bits vêm do campo imediato de 26 bits na instrução. se parece um pouco com uma instrução branch. Portanto.23. chamado Jump. que é o campo op. j os bits 00bin. mas calcula o PC de destino de maneira diferente e não é condicional. Implementando jumps A Figura 4. . poderemos simplificar a tabela verdade usando don’t care na parte da entrada. Por exemplo. é ativado apenas quando a instrução é um jump – ou seja.24 mostra a adição do componente para jump à Figura 4. que pode ser o PC incrementado (PC + 4). já que o restante dos opcodes MIPS é usado em uma implementação completa. Os 4 bits superiores do endereço que deve subs- tituir o PC vêm do PC da instrução jump mais 4. podemos implementar um jump armazenando no PC a concatenação de: j os 4 bits superiores do PC atual + 4 (esses são bits 31:28 do endereço da instrução imediatamente seguinte).17 mostra a implementação de muitas das instruções vistas no Capítulo 2. Não tiramos vantagem dessa simplificação. A parte superior da tabela fornece combinações de sinais de entrada que correspondem aos quatro opcodes que determinam as definições de saída do controle. Um outro multiplexador é usado na seleção da origem para o novo valor do PC. podemos detectar uma instrução no formato R com a expressão Op5 • Op2. a saída EscreveReg é ativada para duas combinações diferentes das entradas. então.17. quando o opcode é 2. Esse sinal de controle. Se considerarmos apenas os quatro opcodes mostrados nessa tabela. Como RESPOSTA um branch. mostrada na Figura 4.17 para incluir a instrução jump.22  A função de controle para a implementação de ciclo único simples é completamente especificada por essa tabela verdade. Descreva como definir quaisquer novas linhas de controle. A Figura 4. sw e beq. Portanto. os 2 bits menos significativos de um endereço jump são sempre 00bin. A instrução jump. Embora o CPI seja 1 (veja o Capítulo 1). e. Entretanto. os primeiros computadores com conjuntos de instruções muito simples usavam essa tecnologia de implementação. que usa cinco unidades funcionais em série: a memória de instruções. um endereço de 32 bits. Um multiplexador adicional (no canto superior direito) é usado na escolha entre o destino de um jump e o destino de um desvio ou a instrução sequencial seguinte a esta. se tentássemos implementar a unidade de ponto . a memória de dados e o banco de registradores. a ALU. O endereço de destino para uma instrução jump é formado pela concatenação dos 4 bits superiores do PC atual + 4 com o campo endereço de 26 bits na instrução jump e pela adição de 00 como os dois bits menos significativos. Por que uma implementação de ciclo único não é usada hoje Embora o projeto de ciclo único funcionasse corretamente. assim.264 Capítulo 4  O Processador FIGURA 4. concatenando os 4 bits mais significativos do PC + 4 como os bits mais significativos. uma instrução load. depois. produzindo. FIGURA 4. Para ver o porquê disso.24  O controle e o caminho de dados simples são estendidos para lidar com a instrução jump. quase certamente. É claro. mas poderia ser considerado aceitável para esse conjunto de instruções pequeno. já que o ciclo de clock é muito longo. Esse caminho é. ele não seria usado nos projetos modernos porque é ineficiente.23  Formato de instrução para a instrução jump (opcode = 2). observe que o ciclo de clock precisa ter a mesma duração para cada instrução nesse projeto de ciclo único. o desempenho geral de uma im- plementação de ciclo único provavelmente será pobre. Historicamen- te. o ciclo de clock é determinado pelo caminho mais longo possível no processador. O ônus de usar o projeto de ciclo único com um ciclo de clock fixo é significativo. efetivamente adicionando 00 como os bits menos significativos. o banco de registradores. O endereço de destino do jump é obtido deslocando-se os 26 bits inferiores da instrução jump de 2 bits para a esquerda. Esse multiplexador é controlado pelo sinal de controle Jump. 2. de modo que mais trou- xas são terminadas por hora. Desde que haja recursos separados para cada estágio. 3. Hoje. mas. chamada pipelining. 4. colocar a trouxa de roupa seca na mesa e passar. a técnica de pipelining é praticamente universal. . Você consegue combinar alguns deles? Algum Verifique sinal de controle na figura pode ser substituído pelo inverso de outro? (Dica: leve em conta você mesmo os don’t care. Se estiver interessado em explorar a anatomia de um computador com pipeline.25. centrar nesta seção e depois pular para as Seções 4. Se você estiver interessado apenas no quadro geral. Veja os sinais de controle na Figura 4.9. 4. Quando a secadora terminar.11. O pipelining melhora a eficiência executando múltiplas instruções simultaneamente. então comece novamente com a próxima trouxa de roupa suja. você pode usar um sinal para o outro sem incluir um inversor? Nunca perca tempo. esse projeto de ciclo único decididamente não funcionaria bem. Quando seu colega terminar. Logo. não podemos usar técnicas de implementação que reduzem o atraso do caso comum. de montagem. a fim de ver uma introdução às técnicas de pipelining avançadas.6 a 4. Em seguida. veremos outra técnica de implementação. esta seção é uma boa introdução às Seções de 4. implementação em que várias Esta seção utiliza bastante uma analogia para dar uma visão geral dos termos e aspectos instruções são sobrepostas na execução. Uma implementação de ciclo único.) Nesse caso. quando temos muitas trouxas para lavar. podemos usar um pipeline para as tarefas. a técnica de pipelining não diminuiria o tempo para concluir uma trouxa de roupas. como mostra a Figura 4. mas não melhoram o tempo de ciclo de pior caso. começa a passar e dobrar a segunda. Colocar a trouxa de roupa suja na lavadora. Na próxima seção. Nesse ponto. move a trouxa de roupa molhada para a secadora e a próxima trouxa de roupa suja para a lavadora. Assim que a lavadora terminar com a primeira trouxa e ela for colocada na secadora. Qualquer um que tenha lavado muitas roupas intuitivamente já usou pipelining. o motivo pelo qual a técnica de pipelining é mais rápida para muitas trouxas é que tudo está trabalhando em paralelo.5  Visão geral de pipelining 265 flutuante ou um conjunto de instruções com instruções mais complexas. Quando a primeira trouxa estiver seca. Como precisamos considerar que o ciclo de clock é igual ao atraso de pior caso para todas as instruções. pedir ao seu colega de quarto para guardar as roupas.10 e 4. semelhante a uma linha da técnica de pipelining. e seja passada e guardada não é mais curto (o processo) para a técnica de pipelining. viola o nosso princípio básico de projeto do Capítulo 2 de tornar o caso comum mais rápido. portanto. a melhoria na vazão diminui o tempo total de conclusão do trabalho. você a coloca na tábua para começar a passar e dobrar. todas as etapas – denominadas estágios em pipelining – estão operando simultaneamente. Quando a lavadora terminar. 4. A técnica de pipelining melhora a vazão do sistema de lavanderia sem melhorar o tempo para concluir uma única trouxa. mas é muito mais eficiente por ter uma vazão muito mais alta.22. A técnica sem pipeline para lavar roupas seria 1. você carrega a lavadora com a segunda trouxa de roupa suja. você pede a seu colega para guardar a primeira remessa. O paradoxo da técnica de pipelining é que o tempo desde a colocação de uma única trouxa de roupa suja na lavadora até que ela esteja seca. colocar a trouxa de roupa molhada na secadora (se houver). deverá se con. utilizadas nos processadores mais recentes. como o AMD Opteron X4 (Barcelona) ou Intel Core. A técnica com pipeline leva muito menos tempo. que usa um caminho de dados muito semelhante ao caminho de dados de ciclo único.5  Visão geral de pipelining Provérbio americano Pipelining é uma técnica de implementação em que várias instruções são sobrepostas na pipelining  Uma técnica de execução. Quando terminar de passar. a secadora está com a terceira remessa e você coloca a quarta na lavadora. O formato das instruções MIPS permite que a leitura e a decodificação ocorram simultaneamente. secar. secadas.25  A analogia da lavagem de roupas para pipelining. passadas e guardadas. Esse efeito no início e no fim afeta o desempenho quando o número de tarefas não é grande em comparação com a quantidade de estágios do pipeline. no início e no final da carga de trabalho na versão com pipeline da Figura 4.5 horas. Escrever o resultado em um registrador. a lavanderia com pipeline é potencialmente quatro vezes mais rápida do que a sem pipeline: 20 trouxas levariam cerca de cinco vezes o tempo de uma trouxa. Executar a operação ou calcular um endereço. . quatro: lavar. então o ganho de velocidade devido à técnica de pipelining será igual ao número de estágios do pipeline. Assim. Ana. Beto. Se todos os estágios levarem aproximadamente o mesmo tempo e houver trabalho suficiente para realizar.25 porque mostramos apenas quatro trouxas. assim como agiliza a lavagem de roupas. então os estágios estarão cheios na maior parte do tempo e o aumento na vazão será muito próximo de 4.3 vezes na Figura 4. enquanto a lavagem com pipeline levaria apenas 3. Acessar um operando na memória de dados. As instruções MIPS normalmente exigem cinco etapas: 1. mas na realidade temos apenas um de cada recurso. Catarina e Davi possuem roupas sujas para serem lavadas. o pipeline MIPS que exploramos neste capítulo possui cinco estágios. enquanto 20 trouxas de lavagem sequencial levariam 20 vezes o tempo de uma trouxa. Observe que. Logo. 2. passar e guardar. O ganho foi de apenas 2. neste caso. O lavador. o pipeline não está completamente cheio. Ler registradores enquanto a instrução é decodificada.25. 4. O exemplo a seguir mostra que a técnica de pipelining agiliza a execução da instrução. 5. Os mesmos princípios se aplicam a processadores em que usamos pipeline para a execução da instrução. Se o número de trouxas for muito maior que 4. Mostramos o estágio do pipeline de diferentes trouxas com o passar do tempo mostrando cópias dos quatro recursos nessa linha de tempo bidimensional. A lavagem sequencial levaria oito horas para quatro trouxas de roupas. o passador e o guardador levam 30 minutos para sua tarefa.266 Capítulo 4  O Processador FIGURA 4. 3. o secador. Buscar instrução da memória. ela é lw – de RESPOSTA modo que o tempo exigido para cada instrução é 800ps. vamos criar um pipeline.27 compara a execução sem pipeline e com pipeline de três instruções load word. Se os estágios forem perfeitamente balanceados. Os tempos de operação para as principais unidades funcionais neste exemplo são de 200ps para acesso à memória. Neste exemplo. add (add). e no restante deste capítulo. vamos limitar nossa atenção a oito instruções: load word EXEMPLO (lw). O projeto de ciclo único precisa contemplar a instrução mais lenta – na Figura 4. um pipeline de cinco estágios é quase cinco vezes mais rápido. de 800ps. embora alguns estágios levem apenas 100ps. unidade de controle. AND (and). A Figura 4. store word (sw). subtract (sub). em que todas as instruções levam um ciclo de clock. 4. Compare o tempo médio entre as instruções de uma implementação em ciclo único.25. podemos converter a discussão sobre ganho de velocidade com a técnica de pipelining em uma fórmula. de modo que o ciclo precisa ser esticado para acomodar a instrução mais lenta. o ciclo de clock da execução com pipeline precisa ter o ciclo de clock no pior caso de 200ps. OR (or). com uma implementação com pipeline.26  Tempo total para cada instrução calculada a partir do tempo para cada componente. set-less-than (slt) e branch-on-equal (beq). Todos os estágios do pipeline utilizam um único ciclo de clock. Desse modo. O uso de pipeline ainda oferece uma melhoria de desempenho de quatro vezes: o tempo entre a primeira e a quarta ins- truções é de 3 × 200ps.26. a Figura 4. ou 600ps. Agora. embora algumas instruções possam ser tão rápidas quanto 500ps. Assim como na Figura 4. .400ps. o tempo entre a primeira e a quarta instrução no projeto sem pipeline é 3 × 800ns. ou 2. FIGURA 4. No modelo de ciclo único. 200ps para operação com ALU e 100ps para leitura ou escrita de registradores. acessos ao PC e unidade de extensão de sinal não possuem atraso. então o tempo entre as instruções no processador com pipeline – assumindo condições ideais – é igual a: Tempo entre as instruções com pipeline Tempo entre instruções pipeline = Número de estágios do pipeline Sob condições ideais e com uma grande quantidade de instruções.5  Visão geral de pipelining 267 Desempenho de ciclo único versus desempenho com pipeline Para tornar esta discussão concreta. de modo que ele precisa ser grande o suficiente para acomodar a operação mais lenta. cada instrução leva exatamente um ciclo de clock. o ganho de velocidade com a técnica de pipelining é aproximadamente igual ao número de estágios do pipeline. Esse cálculo considera que os multiplexadores.26 mostra o tempo exigido para cada uma das oito instruções. Assim como o projeto de ciclo único de clock precisa levar o tempo do ciclo de clock no pior caso. versus execução com pipeline (embaixo). Acrescentaríamos 1. O que aconteceria se aumentássemos o número de instruções? Poderíamos estender os valores anteriores para 1.002. cada instrução acrescenta 200ps ao tempo de execução total.000 ins- truções no exemplo com pipeline. consideramos que todos os estágios eram iguais.001. Neste caso.400ps. No exemplo sem pipeline.000 × 200ps + 1. Entretanto.000. Além do mais.00 200‚001‚400 ps 200 ps A técnica de pipelining melhora o desempenho aumentando a vazão de instruções. então o estágio da secadora definiria o tempo do estágio. Assim. ou 200. a técnica de pipelining envolve algum overhead. Usamos essa suposição por todo este capítulo. Ambas utilizam os mesmos componentes de hardware.000.400ps. Compare com a Figura 4. até mesmo nossa afirmação de uma melhoria de quatro vezes para nosso exemplo não está refletida no tempo de execução total para as três instruções: são 1. Naturalmente. e a leitura do banco de registradores ocorre na segunda metade. Consideramos que a escrita no banco de registradores ocorre na primeira metade do ciclo de clock.003 instruções. a razão entre os tempos de execução total para os programas reais nos processadores sem pipeline e com pipeline é próximo da razão de tempos entre as instruções: 800‚002‚400 ps 800 ps ≈ ≈ 4. o exemplo mostra que os estágios podem ser mal balanceados.000. de modo que o tempo de execução total seria 1. Os tempos de estágio do pipeline dos computadores são limitados pelo recurso mais lento. ou 800. isso acontece porque o número de instruções não é grande. cuja origem se tornará mais clara adiante. vemos um ganho de velocidade de quatro vezes no tempo médio entre as instruções. execução em ciclo único.400ps versus 2.000 × 800ps + 2.400ps. O tempo de execução total seria 1.268 Capítulo 4  O Processador FIGURA 4.000 instruções.000.400ps.27  Em cima. acrescentaríamos 1.26. e o ganho de velocidade será menor que o número de estágios do pipeline. pois os programas reais executam bilhões de instruções. Para a lavanderia. de 800ps para 200ps. sem pipeline. Sob essas condições ideais. em vez de diminuir o tempo de execução de uma instrução individual.25. cada uma exigindo 800ps. Além disso.000. o tempo por instrução no processador com pipeline será superior ao mínimo pos- sível. cujo tempo está listado na Figura 4. A fórmula sugere que um pipeline de cinco estágios deve oferecer uma melhoria de quase cinco vezes sobre o tempo sem pipeline de 800ps. .400ps. mas a vazão de instruções é a medida importante. Se a secadora fosse mais lenta. seja a operação da ALU ou o acesso à memória. ou um ciclo de clock de 160ps. os dados solicitados podem ser transferidos entre o processador e a memória em um único estágio do pipeline. a quarta instrução está buscando uma instrução dessa mesma memória. estão disponíveis. nosso pipeline poderia ter um hazard estrutural. as roupas que ficaram secas e estão prontas correto porque os dados necessários para serem passadas. As implementações recentes da arquitetura x86 na realidade traduzem instruções x86 em micro-operações simples. fracassaria. no qual as instruções variam de 1 byte a 17 bytes. Uma estratégia possível é pipeline. Em quarto lugar. todas as instruções MIPS têm o mesmo tamanho. e aquelas que acabaram de ser lavadas e estão prontas para secarem para executar a instrução ainda não deverão esperar. Ele significa que o hardware não pode hazard estrutural Uma ocorrência em que uma instrução admitir a combinação de instruções que queremos executar no mesmo ciclo de clock. Se o pipeline da Figura 4. Em um conjunto de instruções como o x86. . Essa simetria significa que o segundo estágio pode começar a ler o banco de registradores ao mesmo tempo em que o hardware está determinando que tipo de instrução foi lida. pois o cadora no lugar de lavadora e secadora separadas. ou se nosso colega estivesse ocupado hardware não admite a combinação com outra coisa e não pudesse guardar as roupas. Hazards estruturais O primeiro hazard é chamado hazard estrutural. Em terceiro lugar. estágio de memória e. suponha que tivéssemos uma única memória.) Em segundo lugar. no mesmo ciclo de clock em que a primeira instrução está acessando dados da memória. Se pudéssemos operar sobre os operandos na memória. projetado para execução com pipeline. Suponha que você tenha encontrado chamado hazard de dados do uma meia na mesa de passar para a qual não exista um par. estágio de execução. com os campos de registrador de origem localizados no mesmo lugar em cada instrução. veríamos que. o MIPS tem apenas alguns poucos formatos de instrução. podemos entender melhor o projeto do conjunto de instruções MIPS. a técnica de pipelining é muito mais desafiadora.5  Visão geral de pipelining 269 Projetando conjuntos de instruções para pipelining Mesmo com essa explicação simples sobre pipelining. no ciclo de clock apropriado. conforme discutimos no Capítulo 2. como na arquitetura x86. ser executada no ciclo de clock Obviamente. Hazards de dados Os hazards de dados ocorrem quando o pipeline precisa ser interrompido porque uma hazard de dados Também etapa precisa esperar até que outra seja concluída. Primeiro. o conjunto de instruções MIPS foi projetado para ser executado em um pipeline. executar em determinado ciclo de clock. e existem três tipos diferentes. Esses eventos são chamados hazards. Como dissemos. em vez de duas. Essa restrição significa que podemos usar o estágio de execução para calcular o endereço de memória e depois acessar a memória no estágio seguinte. os operandos precisam estar alinhados na memória. enquanto você está procurando. cuidadosamente pro. precisaríamos dividir o estágio 2. os estágios 3 e 4 se expandiriam para estágio de endereço. que se parecem com instruções MIPS e depois usam um pipeline de micro-operações no lugar das instruções x86 nativas! (Veja a Seção 4. Se os formatos de instrução do MIPS não fossem simétricos. Logo veremos a desvantagem dos pipelines mais longos. Sem duas memórias. Nosso pipeline.10. 4.27 tivesse uma quarta instrução. Um planejada não pode ser executada hazard estrutural na lavanderia aconteceria se usássemos uma combinação lavadora-se. resultando em seis estágios de pipeline. em seguida. Uma ocorrência em que uma instrução planejada não pode correr até o seu quarto e procurar em sua gaveta para ver se consegue encontrar o par. Essa restrição torna muito mais fácil buscar instruções no primeiro estágio do pipeline e decodificá-las no segundo estágio. não precisamos nos preocupar com uma única instrução de transferência de dados exigindo dois acessos à memória de dados. de instruções definidas para gramado. Hazards de pipeline Existem situações em pipelining em que a próxima instrução não pode ser executada no ciclo de clock seguinte. Logo. tornando muito fácil para os projetistas evitar hazards estruturais quando projetaram o pipeline. Contudo. os operandos em memória só aparecem em loads ou stores no MIPS. um hazard de dados poderia prejudicar o pipeline severamente. A Figura 4. com o desenho mostrando o banco de registradores sendo lido. semelhante ao pipeline da lavanderia. to.28  Representação gráfica do pipeline de instrução. a metade direita do ID é sombreada no segundo estágio porque o banco de registradores é lido. Para a sequência de código que falta a partir de buffers internos. significando que teríamos de acrescentar três bolhas ao pipeline. Por exemplo. e WB para o estágio write-back. O acréscimo de hardware extra para ter o item que falta antes do previs- programador ou na memória. semelhante em essência ao pipeline da lavanderia. Essas dependências acontecem com muita frequência. MEM para o estágio de acesso à memória. Aqui. com o desenho representando a ALU. os hazards de dados surgem quando uma instrução depende de uma anterior que ainda está no pipeline (um relacionamento que não existe realmente quando se lavam roupas). forwarding  Também chamado e o atraso simplesmente é muito longo para se esperar que o compilador nos tire desse bypassing. FIGURA 4. com a caixa representando a memória de instrução. Alinhe a cópia do caminho de dados para cada instrução. na Figura 4. mostre quais estágios do pipeline estariam conec- EXEMPLO tados pelo forwarding. Um método para dilema. Os símbolos para os cinco estágios: IF para o estágio de busca de instrução.25. assim que a ALU cria a soma para o add. EX para o estágio de execução. resolver um hazard de dados A solução principal é baseada na observação de que não precisamos esperar que a ins- utilizando o elemento de dados trução termine antes de tentar resolver o hazard de dados.29 mostra a conexão para o forwarding do valor em $s0 após o estágio de RESPOSTA execução da instrução add como entrada para o estágio de execução da instrução sub. Forwarding com duas instruções Para as duas instruções anteriores.25.270 Capítulo 4  O Processador Em um pipeline de computador. diretamente dos recursos internos. usamos símbolos representando os recursos físicos com as abreviações para estágios de pipeline usados no decorrer do capítulo. A ins- trução add não escreve seu resultado até o quinto estágio. MEM tem um fundo branco porque add não acessa a memória de dados. podemos fornecê-la como uma entrada chegue nos registradores visíveis ao para a subtração. os resultados não seriam satisfatórios. e o sombreamento da metade esquerda significa que ele é escrito nesse estágio. O sombreamento indica que o elemento é usado pela instrução. com a caixa representando a memória de dados. Logo. e a metade esquerda do WB é sombreada no quinto estágio. ID para o estágio de leitura de decodificação de ins- trução/banco de registradores. Logo. em vez de esperar que anterior. na Figura 4. com o desenho mostrando o banco de registradores sendo escrito. é chamado de forwarding ou bypassing. Use o desenho da Figura 4.28 para representar o caminho de dados durante os cinco estágios do pipeline. Embora pudéssemos contar com compiladores para remover todos esses hazards. . O sombreamento na metade direita do banco de registradores ou memória significa que o elemento é lido nesse estágio. suponha que tenhamos uma instrução add seguida imediatamente por uma instrução subtract que usa a soma ($ s 0): Sem intervenção. pois o banco de registradores é escrito. o que é impossível. Como podemos imaginar examinando hazard de dados no uso de a Figura 4. suponha que a primeira instrução fosse um load de $s0 em vez de um add.30. . Logo.29.7 mostra os detalhes do que realmente acontece no caso de um hazard. pois isso significaria voltar no tempo. O forwarding funciona muito bem e é descrito com detalhes na Seção 4. A conexão mostra o caminho do forwarding desde a saída do estágio EX de add até a entrada do estágio EX para sub. não pode haver um caminho de forwarding válido da saída do estágio de acesso à memória na primeira instrução para a entrada do estágio de execução da instrução seguinte. os dados desejados só estariam disponíveis depois do quarto estágio da load  Uma forma específica de primeira instrução na dependência.30  Precisamos de um stall até mesmo com forwarding quando uma instrução do formato R após um load tenta usar os dados. que é muito tarde para a entrada do terceiro estágio hazard de dados em que os dados solicitados por uma instrução load de sub. conhecido oficialmente como pipeline stall. Nessa representação gráfica dos eventos. na realidade. como mostra a Figura 4. se um stall será necessário. FIGURA 4. Veremos os stalls em outros lugares do pipeline. até mesmo com o forwarding.7. A Seção 4.5  Visão geral de pipelining 271 FIGURA 4. o caminho da saída do estágio de acesso à memória para a entrada do estágio de execução estaria ao contrário no tempo. Essa figura mostra um conceito requisitados por outra instrução. antes que a instrução de subtração seja lida e decodificada. 4. Sem o stall.29  Representação gráfica do forwarding. é uma simplificação. Essa figura. ele não pode impedir todos os stalls do pipeline. software que reordena o código para evitar stalls de pipeline no uso de load. Por exemplo. os caminhos de forwarding só são válidos se o estágio de destino estiver mais adiante no tempo do que o estágio de origem. teríamos de atrasar um estágio para um hazard ainda não estão disponíveis quando de dados no uso de load. Entretanto. substituindo o valor do registrador $s0 lido no segundo estágio de sub. pois não podemos saber.7 pipeline stall  Também chamado mostra como podemos tratar de casos assim. mas normalmente recebendo o apelido de bolha. Um stall iniciado a fim de resolver um hazard. A Seção 4. usando a detecção de hardware e stalls ou bolha. como este exemplo ilustra. Por exemplo. importante de pipeline. incluindo a dependência do primeiro add no primeiro lw e quaisquer hazards para instruções store. vindo da necessidade de tomar endereços de instrução não é o uma decisão com base nos resultados de uma instrução enquanto outras estão sendo que o pipeline esperava. Observe que o bypassing elimina vários outros hazards em potencial. ou seja. “Bypassing” vem de passar o Quando a instrução apropriada resultado pelo banco de registradores à unidade desejada. c = b + f. . Cada instrução MIPS escreve no máximo um resultado e faz isso no último estágio do pipeline.272 Capítulo 4  O Processador Reordenando o código para evitar pipeline stalls Considere o seguinte segmento de código em C: EXEMPLO a = b + e. O forwarding leva a outro detalhe da arquitetura MIPS. não pode ser executada no devido ciclo de clock de pipeline porque Hazards de controle a instrução buscada não é aquela necessária. Aqui está o código MIPS gerado para esse segmento. a sequência reordenada será com- pletada em dois ciclos a menos do que a versão original. As duas instruções add possuem um hazard. Detalhamento:  o nome “forwarding” vem da ideia de que o resultado é passado adiante a hazard de controle  Também chamado hazard de desvio partir de uma instrução anterior para uma instrução posterior. ou se precisarem escrever um resultado mais cedo na execução da instrução. O forwarding é mais difícil se houver vários resultados para encaminhar por instrução. além dos quatro mencionados anteriormente. supondo que todas as variáveis estejam na memória e sejam endereçáveis como offsets a partir de $t0: Encontre os hazards no segmento de código a seguir e reordene as instruções para evitar quaisquer pipeline stalls. o fluxo de O terceiro tipo de hazard é chamado hazard de controle. Subir a terceira instrução lw elimina os dois hazards: Em um processador com pipeline com forwarding. executadas. devido à respectiva dependência da RESPOSTA instrução lw imediatamente anterior. Observe que temos de começar a buscar a instrução após o desvio no próximo ciclo de clock. Na realidade. temos de esperar até o segundo estágio e examinar o uniforme seco para ver se precisamos ou não mudar as opções da lavadora. ou bolha. EXEMPLO A Figura 3. 4. pois ele só recebeu da memória a instrução de desvio! Assim como na lavanderia. Este exemplo considera que o desvio condicional é tomado. calcular o endereço de desvio e atualizar o PC durante o segundo estágio do pipeline (veja Seção 4.5  Visão geral de pipelining 273 Suponha que nosso pessoal da lavanderia receba a tarefa feliz de limpar os uniformes de um time de futebol. Como a roupa é muito suja. Em nosso pipeline de lavanderia. A tarefa de decisão equivalente em um computador é a instrução de desvio. o pipeline possivelmente não saberá qual deve ser a próxima instrução. Até mesmo com esse hardware extra. Contudo. A instrução lw. Como as outras instruções possuem um CPI de 1 e os desvios RESPOSTA tomaram um ciclo de clock extra para o stall. Essa opção conservadora certamente funciona. .8 para obter mais detalhes). o pipeline envolvendo desvios condicionais se pareceria com a Figura 4.27 no Capítulo 3 mostra que os desvios são 17% das instruções executadas no SPECint2006.31  Pipeline mostrando o stall em cada desvio condicional como solução para controlar os hazards. mas é lenta. e a instrução no destino do desvio é a ins- trução OR. Desempenho do “stall no desvio” Estime o impacto nos ciclos de clock por instrução (CPI) do stall nos desvios. após o desvio. Supo- nha que todas as outras instruções tenham um CPI de 1. O que fazer? Aqui está a primeira das duas soluções para controlar os hazards na lavanderia e seu equivalente nos computadores. mas não tão forte para desgastá-los antes do tempo. Vamos supor que colocamos hardware extra suficiente de modo que possamos testar registradores. temos de determinar se o detergente e a temperatura da água que selecionamos são fortes o suficiente para limpar os uniformes. FIGURA 4. es- perando até que o pipeline determine o resultado do desvio para saber de que endereço apanhar a próxima instrução. então veríamos um CPI de 1. Stall: Basta operar sequencialmente até que o primeiro lote esteja seco e depois repetir até você ter a fórmula correta.17 em relação ao caso ideal. portanto.31. um stall de 1. executada se o desvio não for tomado. Existe um stall de um estágio no pipeline. No entanto. fica em stall durante um ciclo de clock extra de 200ps antes de iniciar. o processo de criação de um stall é ligeiramente mais complicado.8. conforme veremos na Seção 4. o efeito sobre o desempenho é o mesmo que ocorreria se uma bolha fosse inserida.17 e. uma solução possível é ocasionar um stall no pipeline imediatamente após buscarmos um desvio. Os computadores realmente utilizam a previsão para tratar dos desvios. Em nossa analogia. então veríamos um atraso ainda maior se ocorresse um stall nos desvios.32  Prevendo que os desvios não serão tomados como solução para o hazard de con- trole. O custo dessa opção é muito alto para a maioria dos computadores utilizar. os uniformes escuros ou de que considera um determinado casa poderiam usar uma fórmula. Como provavelmente serão tomados e desviam para trás. Quando você estiver certo. fazem suas escolhas dependendo do comportamento de . mos prever como tomados os desvios para um endereço anterior.274 Capítulo 4  O Processador Se não pudermos resolver o desvio no segundo estágio. pelo menos durante o primeiro ciclo de clock imediatamente após o desvio. previsão de desvio  Um método Uma versão mais sofisticada de previsão de desvio teria alguns desvios previstos como de resolver um hazard de desvio tomados e alguns como não tomados. então basta prever que ela funcionará e lavar a segunda remessa enquanto espera que a primeira seque. A Figura 4. sempre podería- real. em vez de outra. quando estiver errado.31. No caso da programação. Conforme observamos na Figura 4. Entretanto. enquanto os uniformes claros ou de sair poderiam usar resultado para o desvio e prossegue a partir dessa suposição. no final dos loops existem desvios que voltam para o esperar para verificar o resultado início do loop. você terá de refazer a remessa que foi lavada enquanto pensa na decisão.32 mostra um exemplo assim. e isso motiva uma segunda solução para o hazard de controle: Prever: se você estiver certo de que tem a fórmula correta para lavar os uniformes. Previsores de hardware dinâmicos. Uma técnica simples é sempre prever que os desvios não serão tomados. ao contrário. Essas técnicas rígidas para o desvio contam com o comportamento estereotipado e não são responsáveis pela individualidade de uma instrução de desvio específica. Somente quando os desvios são tomados é que o pipeline sofre um stall. a inserção de uma bolha nesse padrão simplifica o que realmente acontece. como normalmente acontece para pipelines maiores. FIGURA 4. o pipeline prosseguirá a toda velocidade. O desenho superior mostra o pipeline quando o desvio não é tomado. A Seção 4.8 esclarecerá os detalhes. Essa opção não atrasa o pipeline quando você estiver correto. O desenho inferior mostra o pipeline quando o desvio é tomado. a instrução add antes do desvio na Figura 4. agora terá base suficiente para pular para a Seção 4. As soluções para controlar os hazards são descritas com mais detalhes na Seção 4. como o escalonamento superescalar e dinâmico.6.8). abordamos o conceito de pipelining usando o subconjunto de instruções MIPS da implementação de ciclo único.8 e aprender mais sobre soluções para hazards de desvio. Depois. resultando em previsores de desvio dinâmicos que podem prever os desvios corretamente. O delayed branch sempre executa a próxima instrução sequencial. e depois ver como as exceções são tratadas. pois o montador pode arrumar as instruções automaticamente para conseguir o comportamento de desvio desejado pelo programador. Como veremos mais adiante. se você estiver interessado em entender como a técnica de pipelining é implementada e os desafios de lidar com hazards.7.8. ajustando a próxima escolha dependendo do sucesso das escolhas recentes. 4. basta colocar uma remessa de roupas que não sejam de futebol na lavadora. Como alternativa. Em nossa analogia de lavanderia. Ela tem a vantagem substancial de que. Uma técnica comum para a previsão dinâmica de desvios é manter um histórico de cada desvio como tomado ou não tomado. diferente de programar um multiprocessador. essa solução funcionará bem. ler a Seção 4. Depois. mencionada anteriormente. e um desvio tomado muda o endereço da instrução que vem após essa instrução segura. que não é afetada pelo desvio. a previsão de desvio baseada em hardware normalmente é usada. com o desvio ocorrendo após esse atraso de uma instrução. ou pode ser executada sem stall ou forwarding: você mesmo . Chamado de delayed branch (desvio adiado) nos computadores. Em nossa analogia. Detalhamento:  Existe uma terceira técnica para o hazard de controle. Para cada sequência de código a seguir.5  Visão geral de pipelining 275 cada desvio. e podem mudar as previsões para um desvio durante a vida de um programa. pipelines mais longos aumentam o problema. a fim de esconder totalmente seu atraso. essa é a solução realmente usada pela arquitetura MIPS. Isso fica escondido do programador assembly do MIPS. Quando a escolha estiver errada. pode evitar stalls Verifique usando apenas forwarding. Como no caso de todas as outras soluções para controlar hazards. neste caso. e depois usar o comportamento passado recente para prever o futuro. na previsão dinâmica. poderá prosseguir para examinar o projeto de um caminho de dados com pipeline. Como os delayed branches são úteis quando os desvios são curtos. Nas próximas seções deste capítulo.10. devendo reiniciar o pipeline a partir do endereço de desvio apropriado. Em nosso exemplo. Seguindo nossa analogia. nenhum processador usa um delayed branch de mais de um ciclo. o controle do pipeline terá de garantir que as instruções após o desvio errado não tenham efeito.31 não o afeta. aumentando o custo do erro de previsão. você poderá usar esse conhecimento para explorar a implementação do forwarding e stalls na Seção 4. Resumo da visão geral de pipelining Pipelining é uma técnica que explora o paralelismo entre as instruções em um fluxo de instruções sequenciais. sempre que você tiver de tomar uma decisão sobre a lavanderia. O software MIPS colocará uma instrução imediatamente após a instrução de delayed branch. uma pessoa veria como o uniforme es- tava sujo e escolheria a fórmula. com uma precisão superior a 90% (veja Seção 4. temos de deixar de aceitar novas remessas para poder reiniciar a remessa prevista incorretamente. enquanto espera que os uniformes de futebol sequem. Você poderá. examinamos os problemas que a técnica de pipelining gera e o desempenho alcançável em certas situações. na Seção 4.11 examina os pipelines de microprocessadores recentes. a quantidade e o tipo de histórico mantido têm se tornado extensos. que não sejam afetadas pelo teste.10 apresenta conceitos avançados de pipelining. ela é fundamentalmente invisível ao programador. e pode ser movida para depois dele. explicado na Seção 4. indique se ela deverá sofrer stall. e a Seção 4.9. chamada decisão adiada. então. A Seção 4. Desde que você tenha roupas sujas suficientes. Para atrasos em desvios maiores. Se você quiser saber mais sobre o software e as implicações de desempenho da técnica de pipelining. que pode não ser totalmente implementada com pipeline. Caminho de dados e controle 4.10. seu desempenho. também chamado de latência. é mais fácil lidar com hazards de dados em programas de ponto flutuante porque a menor frequência de desvios e os padrões de acesso mais regulares permitem que o compilador tente escalonar instruções para evitar os hazards. A divisão de uma instrução em cinco estágios significa um pipeline de cinco estágios. que possuem acesso menos regular e envolvem um maior uso de ponteiros. Apesar disso. Colocando em A técnica de pipelining aumenta o número de instruções em execução simultânea perspectiva e a velocidade em que as instruções são iniciadas e concluídas. de dados e de controle continuam sendo importantes em pipelines simples e mais sofisticados. por sua vez. compreender o desempenho de um processador moderno com múltiplos dos programas problemas é algo complexo e exige a compreensão de mais do que apenas as questões que surgem em um processador com pipeline simples. portanto. o pipeline de cinco estágios ainda usa cinco latência (pipeline)  O número ciclos de clock para completar a instrução. A previsão de desvio.276 Capítulo 4  O Processador Sequência 1 Sequência 2 Sequência 3 Entendendo Fora do sistema de memória. Em geral. É mais difícil realizar essas otimizações em programas de inteiros.33 mostra o caminho de dados de ciclo único da Seção 4. Nos termos usados no Capítulo 4. que cos- tumam ter maiores frequências de desvio. que já precisam enfrentar hazards estruturais. e não o tempo de execução número de estágios entre duas instruções durante a execução.10. Por exemplo. enquanto os hazards de controle costumam ser um problema maior nos programas de inteiros. Para pipelines modernos. com cada parte possuindo um nome correspondente a um estágio da execução da instrução: . a de estágios em um pipeline ou o técnica de pipelining melhora a vazão de instruções. Assim. além de desvios menos previsíveis. A técnica de pipe- lining não reduz o tempo gasto para completar uma instrução individual. Conforme ve- o desempenho remos na Seção 4. significa que até cinco instruções estarão em execução durante qualquer ciclo de clock. o forwarding e os stalls ajudam a tornar um computador rápido enquanto ainda gera as respostas certas. Conforme veremos na Seção 4. a operação eficaz do pipeline normalmente é o fator mais im- portante para determinar o CPI do processador e. temos de separar o caminho de dados em cinco partes. existem técnicas de compilação e de hardware mais ambiciosas que reduzem as dependências de dados para o escalonamento. que.6   usando pipeline A Figura 4. os hazards estruturais.4 com os estágios de pipeline identificados. Os conjuntos de instruções podem simplificar ou dificultar a vida dos pro- jetistas do pipeline. ou latência das instruções individualmente. de controle e de dados. os hazards estruturais costumam girar em torno da unidade de ponto flutuante. Os hazards de dados podem ser gargalos de desempenho em programas de inteiros e de ponto flutuante. as roupas ficam mais limpas. mais secas e mais organizadas à medida que prosseguem na fila. e nunca se movem para trás. existem duas exceções para esse fluxo de informações da esquerda para a direita: j estágio de escrita do resultado. e a segunda ocasiona hazards de controle. que coloca o resultado de volta no banco de regis- tradores. as instruções e os dados em geral se movem da esquerda para a direita pelos cinco estágios enquanto completam a execução. Observe que a primeira seta da direita para a esquerda pode levar a hazards de dados. .6  Caminho de dados e controle usando pipeline 277 FIGURA 4. escolhendo entre o PC incrementado e o endereço de desvio do estágio MEM. mas são linhas de dados. esses cinco componentes correspondem aproximadamente ao modo como o caminho de dados é desenhado. IF (Instruction Fetch): Busca de instruções.) 1. que envia o resultado da ALU ou os dados da memória para a esquerda. Voltando à nossa analogia da lavanderia. no meio do caminho de dados. Entretanto. EX: Execução ou cálculo de endereço. ID (Instruction Decode): Decodificação de instruções e leitura do banco de regis- tradores.33  O caminho de dados da Seção 4. 2. WB (Write Back): Escrita do resultado. 4.17). usamos linhas coloridas para controle. 4. a fim de serem escritos no banco de registradores. 5. Os dados fluindo da direita para a esquerda não afetam a instrução atual. Cada etapa da instrução pode ser mapeada no caminho de dados da esquerda para a direita. MEM: Acesso à memória de dados. j a seleção do próximo valor do PC. (Normalmente. Na Figura 4. somente as ins- truções seguintes no pipeline são influenciadas por esses movimentos de dados reversos.4 (semelhante à Figura 4. As únicas exceções são a atualização do PC e a etapa de escrita do resultado.33. 3. mostrada em cores. consideramos que o banco de registradores é escrito na primeira metade do ciclo de clock e é lido durante a segunda metade. esta figura finge que cada instrução possui seu próprio caminho de dados e pinta cada parte de acordo com o uso. e assim por diante. usando linhas tracejadas no estágio ID.34  Instruções executadas usando o caminho de dados de ciclo único na Figura 4.34. Semelhante às Figuras de 4. o valor lido da memória de instruções precisa ser salvo em um registrador. como mostra a Figura 4. Todas as instruções avançam durante cada ciclo de clock de um regis- trador do pipeline para o seguinte.33. quando não estiver sendo lido.33. cada es- tágio é rotulado pelo recurso físico usado nesse estágio. de modo que precisamos colocar registradores sempre que existam linhas divisórias entre os estágios na Figura 4. permitindo que seja compartilhada por outras instruções durante os outros quatro estágios.27. a memória de instruções é usada durante apenas um dos cinco estágios de uma instrução. A fim de reter o valor de uma instrução individual para seus outros quatro estágios. e a metade direita não sombreada usando linhas tracejadas do estágio WB. Os registradores recebem os nomes dos dois estágios separados por esse registrador.34. Ao contrário daquelas figuras. Para manter a ordem de tempo correta. Retornando à nossa analogia da lavanderia. o registrador do pipeline entre os estágios IF e ID é chamado de IF/ID.34 mostra a execução das instruções na Figura 4.28 a 4. Em vez disso. exibindo seus caminhos de dados privados em uma linha de tempo comum. Esse uso dual é representado pelo desenho da metade esquerda não sombreada do banco de regis- tradores. Argumentos semelhantes se aplicam a cada estágio do pipeline.33 para mostrar os relacionamentos na Figura 4. Observe que não existe um registrador de pipeline no final do estágio de escrita do resultado (WB). poderíamos ter um cesto entre cada par de estágios contendo as roupas para a próxima etapa. IM representa a memória de instruções e o PC no estágio de busca da instrução. A Figura 4. A Figura 4. acrescentamos registradores para manter dados de modo que partes do caminho de dados pudessem ser compartilhadas durante a execução da instrução. quando ele não estiver sendo escrito. correspondendo às partes do caminho de dados na Figura 4. Reg significa banco de registradores e extensor de sinal no estágio de decodificação de instruções/leitura do banco de registradores (ID).33. assumindo a execução com pipeline. A Figura 4.35 mostra o caminho de dados usando pipeline com os registradores do pipeline destacados.278 Capítulo 4  O Processador Uma maneira de mostrar o que acontece na execução com pipeline é fingir que cada instrução tem seu próprio caminho de dados. Por exemplo. Todas as instruções precisam atualizar algum estado no processador – o . Como antes. esse caminho de dados estilizado divide o banco de registradores em duas partes lógicas: leitura de registradores durante a busca de registradores (ID) e registradores escritos durante a escrita do resultado (WB). Usamos uma versão estilizada do caminho de dados na Figura 4. Por exemplo.34 parece sugerir que três instruções precisam de três caminhos de dados. FIGURA 4.30. e depois colocar esses caminhos de dados em uma linha de tempo para mostrar seu relacionamento. 35  A versão com pipeline do caminho de dados na Figura 4. Os cinco estágios são os seguintes: 1. Mostramos um load primeiro porque ele ativa todos os cinco estágios.35. A Seção 4.6  Caminho de dados e controle usando pipeline 279 banco de registradores. . mas. o primeiro é rotulado com IF/ID porque separa os estágios de busca de instruções e decodificação de instruções. Essas páginas extras parecem exigir muito mais tempo para você entender. e qualquer instrução posterior que precise desses dados simplesmente lerá o registrador apropriado. Busca de instruções: a parte superior da Figura 4. enquanto o conteúdo dos registradores de pipeline pode ser descartado. no decorrer deste capítulo. As Figuras 4. destacamos a metade direita dos registradores ou memória quando estão sendo lidos e destacamos a metade esquerda quando estão sendo escritos.30. Por exemplo. Eles são rotulados pelos nomes dos estágios que separam. por exemplo. Vamos expandir esses registradores no decorrer deste capítulo. respectivamente. seu conteúdo precisa ser salvo quando ocorre uma exceção.38. Contudo. O PC pode ser considerado um registrador de pipeline: um que alimenta o estágio IF do pipeline.36 a 4. você poderia pensar no PC como correspondendo ao cesto que mantém a remessa de roupas sujas antes da etapa de lavagem.33. seja incrementando-o ou atribuindo a ele o endereço de destino de um desvio. Mostramos a abreviação da instrução lw com o nome do estágio do pipeline que está ativo em cada figura. o registrador IF/ID precisa ter 64 bits de largura. Os registradores do pipeline.36 mostra a instrução sendo lida da memória usando o endereço no PC e depois colocada no registrador de pipeline IF/ID. mostram as partes ativas do cami- nho de dados destacadas enquanto uma instrução de load passa pelos cinco estágios de execução do pipeline. por enquanto.7 descreve o que acontece quando existem hazards de dados entre instruções em um pipeline. Naturalmente. as sequências levam muito menos tempo do que parece. Mas não tema. assim. 4. memória ou o PC –. um registrador de pipeline separado é redundante para o estado que é atualizado. separam cada estágio do pipeline. Por exemplo. cada instrução atualiza o PC. Na analogia da lavanderia. FIGURA 4. apre- sentamos sequências de figuras para demonstrar a operação com o tempo. diferente dos registradores de pipeline sombreados na Figura 4. o PC faz parte do estado arquitetônico visível. Como nas Figuras de 4. nossa primeira sequência. pois precisa manter a instrução de 32 bits lida da memória e o endereço incrementado de 32 bits no PC. em cinza. ignore-as por enquanto. pois você pode compará-las e ver que mudanças ocorrem em cada ciclo do clock. Os registradores precisam ser grandes o suficiente para armazenar todos os dados correspondentes às linhas que passam por eles.28 a 4. os outros três registradores de pipeline contêm 128. 97 e 64 bits. Para mostrar como funciona a técnica de pipelining. uma instrução load colocará seu resultado em um dos 32 registradores. 28. mas simplifica o controle manter todos os três.2. O computador não tem como saber que tipo de instrução está sendo buscada. para que fique pronto para o próximo ciclo de clock.36  IF e ID: primeiro e segundo estágios do pipe de uma instrução.280 Capítulo 4  O Processador FIGURA 4.35 em destaque. Esse endereço incrementado também é salvo no registrador de pipeline IF/ID caso seja necessário mais tarde para uma instrução. de modo que precisa se preparar para qualquer instrução. . Como na Seção 4. o processador não sabe que instrução está sendo decodificada. com as partes ativas do caminho de dados da Figura 4. não há confusão quando se lê e escreve nos registradores. O endereço do PC é incrementado em 4 e depois escrito de volta ao PC. A convenção de destaque é a mesma utilizada na Figura 4. passando informações potencialmente necessárias pelo pipeline. como beq. de modo que estende o sinal da constante de 16 bits e lê os dois registradores para o registrador de pipeline ID/EX. pois o conteúdo só muda na transição do clock. Embora o load só precise do registrador de cima no estágio 2. Não precisamos de todos os três operandos. que tem seu sinal estendido para 32 bits.37 mostra que a instrução load lê o con- teúdo do registrador 1 e o imediato com o sinal estendido do registrador de pipeline ID/EX e os soma usando a ALU. 4. e os números dos dois registradores para leitura. Esse estágio ocorre antes que a instrução seja identificada. Aqui estão os cinco estágios do pipe da instrução store: 1.36 funciona para store e também para load. bem como a passagem da informação para os estágios posteriores. Busca de instruções: a instrução é lida da memória usando o endereço no PC e depois é colocada no registrador de pipeline IF/ID. 4.37  EX: o terceiro estágio do pipe de uma instrução load. O registrador é acrescentado ao imediato com sinal estendido.35 usadas neste estágio do pipe. Execução ou cálculo de endereço: a Figura 4. e a soma é colocada no registrador de pipeline EX/MEM. fornecendo o campo imediato de 16 bits. destacando as partes do caminho de dados da Figura 4. no meio da figura. A revisão de uma instrução store mostra a semelhança na execução da instrução. assim como o endereço no PC incrementado. 2.38 mostra a instrução load lendo a memória de dados por meio do endereço vindo do registrador de pipeline EX/MEM e carregando os dados no registrador de pipeline MEM/WB.38 mostra a etapa final: lendo os dados do registrador de pipeline MEM/WB e escrevendo-os no banco de registradores.36 mostra a parte relativa à instrução do registrador de pipeline IF/ID. Essa soma é colocada no registrador de pipeline EX/ MEM. Essa revisão da instrução load mostra que qualquer informação necessária em um es- tágio posterior do pipe precisa ser passada a esse estágio por meio de um registrador de pipeline. 3.6  Caminho de dados e controle usando pipeline 281 FIGURA 4. transferimos tudo o que possa ser necessário por qualquer instrução durante um ciclo de clock posterior. Acesso à memória: a parte superior da Figura 4. . Escrita do resultado: a parte inferior da Figura 4. Todos os três valores são armazenados no registrador de pipeline ID/EX. 5. Novamente. de modo que a parte superior da Figura 4. Decodificação de instruções e leitura do banco de registradores: A parte inferior da Figura 4. Decodificação de instruções e leitura do banco de registradores: a instrução no regis- trador de pipeline IF/ID fornece os números de dois registradores para leitura e estende o sinal do imediato de 16 bits. Nota: existe um bug nesse projeto. Esses três valores de 32 bits são armazenados no registrador de pipeline ID/EX. que foi consertado na Figura 4.282 Capítulo 4  O Processador FIGURA 4. A parte inferior da Figura 4.36 para instruções load também mostra as operações do segundo estágio para stores. . Em seguida.41. 2. destacando as partes do caminho de dados da Figura 4. os dados são lidos do registrador de pipeline MEM/WB e escritos no banco de registradores.38  MEM e WB: o quarto e quinto estágios do pipe de uma instrução load. pois é muito cedo para saber o tipo da instrução.35 usadas nesses estágios do pipe. Esses dois primeiros estágios são executados por todas as instruções. no meio do caminho de dados. A memória de dados é lida por meio do endereço no registrador de pipeline EX/MEM. e os dados são colocados no registrador de pipeline MEM/WB. nada acontece no estágio de escrita do resultado. Execução e cálculo de endereço: a Figura 4. A única maneira de disponibilizar os dados durante o estágio MEM é colocar os dados no registrador de pipeline EX/ MEM no estágio EX. ALU. Para a instrução store. pois as instruções posteriores já estão prosseguindo em velocidade máxima. não temos como acelerar essas ins- truções.40 mostra a última etapa do store. onde é armazenado na memória. Para essa instrução. Logo. precisamos passar um dos registradores lidos no estágio ID para o estágio MEM. esses componentes e seu con- trole podem ser associados a um único estágio do pipeline. memória de dados e porta para escrita de registradores – só pode ser usado dentro de um único estágio do pipeline. 5.6  Caminho de dados e controle usando pipeline 283 3. FIGURA 4. anteriormente neste capítulo). Embora não faça mal algum sempre escrever esse segundo registrador no registrador de pipeline EX/MEM. escrevemos o segundo registrador apenas em uma instrução store para tornar o pipeline mais fácil de entender. assim como armazenar o endereço efetivo em EX/MEM. Caso contrário. para passar algo de um estágio anterior do pipe a um estágio posterior.37. Acesso à memória: a parte superior da Figura 4. portas para leitura de registradores. 4. Logo. a informação é perdida quando a próxima instrução entrar nesse estágio do pipeline. Como cada instrução por trás do store já está em progresso.39 mostra a terceira etapa. o endereço efetivo é colocado no registrador de pipeline EX/MEM. A instrução store novamente ilustra que. Ao contrário do terceiro estágio da instrução load na Figura 4. . 4. caso contrário. Load e store ilustram um segundo ponto importante: cada componente lógico do caminho de dados – como memória de instruções.40 mostra os dados sendo escritos na memória. a informação precisa ser colocada em um registrador de pipeline. uma instrução passa por um estágio mesmo que não haja nada a fazer. Escrita do resultado: a parte inferior da Figura 4. teríamos um hazard estrutural (ver Seção “Hazards estruturais. Observe que o registrador contendo os dados a serem armazenados foi lido em um estágio anterior e armazenado no ID/EX.39  EX: o terceiro estágio do pipe de uma instrução store. o segundo valor do registrador é carregado no registrador de pipeline EX/MEM a ser usado no próximo estágio. Os dados foram colocados inicialmente no registrador de pipeline ID/EX e depois passados para o registrador de pipeline EX/MEM. Assim como store passou o conteúdo do registrador do ID/EX ao registrador de pipeline EX/MEM para uso no estágio MEM. qual instrução fornece o número do registrador de escrita? A instrução no registrador de pipeline IF/ID fornece o número do registrador de escrita. de modo que nada acontece no estágio 5. Outra . os dados são escritos na memória de dados para o store. Agora.40  MEM e WB: o quarto e quinto estágios do pipe de uma instrução store. Quando os dados são escritos na memória. precisamos preservar o número do registrador de destino da instrução load. Você conseguiu ver? Qual registrador é alterado no estágio final da leitura? Mais especificamente. load precisa passar o número do registrador de ID/ EX por EX/MEM ao registrador de pipeline MEM/WB. não há nada mais para a instrução store fazer. podemos descobrir um bug no projeto da instrução load. No quarto estágio.284 Capítulo 4  O Processador FIGURA 4. embora essa instrução ocorra consideravel- mente depois da instrução load! Logo. Observe que os dados vêm do registrador de pipeline EX/MEM e que nada é mudado no registrador de pipeline MEM/WB. para uso no estágio WB. e finalmente ao registrador MEM/WB. O número do registrador é passado do estágio do pipe ID até alcançar o registrador de pipeline MEM/WB. passando o número do registrador de escrita primeiro ao registrador ID/EX. Esse novo caminho aparece em destaque. A Figura 4.6  Caminho de dados e controle usando pipeline 285 maneira de pensar sobre a passagem do número de registrador é que. acrescentando mais 5 bits aos três últimos registradores de pipeline.38. de modo que cada registrador de pipeline contenha uma parte da instrução necessária para esse estágio e para os estágios posteriores. Veja na Seção 4.41  O caminho de dados em pipeline corrigido para lidar corretamente com a instrução load. . FIGURA 4.8 uma explicação de como fazer a instrução branch funcionar como esperado.42  A parte do caminho de dados na Figura 4.42 é um único desenho do caminho de dados correto. FIGURA 4.41 usada em todos os cinco estágios de uma instrução load. precisávamos preservar a instrução lida durante o estágio IF. A Figura 4. O número do registrador de escrita agora vem do registrador de pipeline MEM/WB junto com os dados. depois ao registrador EX/MEM. para compartilhar o caminho de dados em pipeline. 4.36 a 4. destacando o hardware utilizado em todos os cinco estágios da instrução load word nas Figuras de 4. O número do registrador é usado durante o estágio WB de modo a especificar o registrador a ser escrito.41 mostra a versão correta do caminho de dados. como a Figura 4.40. pois muitas instruções estão executando simultanea- mente em um único caminho de dados em cada ciclo de clock. Uma representação dos estágios do pipeline é colocada em cada parte do eixo de instruções. As instruções são listadas por ordem de execução. Os diagramas de pipeline de ciclo único de clock mostram o estado do caminho de dados inteiro durante um único ciclo de clock. mas não contêm todos os detalhes. semelhante ao pipeline da lavanderia. na Figura 4. Observe que a Figura 4.286 Capítulo 4  O Processador Representando pipelines graficamente Pipelining pode ser difícil de entender. Esse estilo de representação de pipeline mostra a execução completa das instruções em uma única figura. aqui. Por exemplo.28. enquanto a Figura 4.34. Ao contrário da Figura 4. . Para ajudar na compreensão.36 a 4. Os diagramas com múltiplos ciclos de clock são mais simples. ocupando os ciclos de clock apropriados. e diagramas de pipeline com único ciclo de clock.43 mostra o diagrama de pipeline com múltiplos ciclos de clock para essas ins- truções. Esses caminhos de dados es- tilizados representam os cinco estágios do nosso pipeline.43  Diagrama de pipeline com múltiplos ciclos de clock das cinco instruções. de cima para baixo. A Figura 4.44 mostra a versão mais tradicional do diagrama de pipeline com múltiplos ciclos de clock. mostramos os registradores de pipeline entre cada estágio. O tempo avança da esquerda para a direita na horizontal.25. existem dois estilos básicos de figuras de pipeline: diagramas de pipeline com múltiplos ciclos de clock.44 mostra a maneira tradicional de desenhar esse diagrama. considere esta sequência de cinco instruções: A Figura 4.43 mostra os recursos físicos utilizados em cada estágio. e normalmente todas as cinco instruções no FIGURA 4. mas um retângulo indicando o nome de cada estágio do pipe também funciona bem. A Figura 4. como as Figuras de 4. e os ciclos de clock se movem da esquerda para a direita.44 usa o nome de cada estágio. 44. pipeline são identificadas por rótulos acima de seus respectivos estágios do pipeline. mostrando o uso do caminho de dados em cada uma das instruções do pipeline no ciclo de clock designado.45  O diagrama com ciclo único de clock correspondente ao ciclo de clock 5 do pipeline das Figuras 4. Usamos diagramas de ciclo múltiplo de clock a fim de oferecer sinopses de situações de pipelining. 4.12 oferece mais ilustrações de diagramas de clock único se você quiser ver mais detalhes sobre a Figura 4. a Figura 4. FIGURA 4. Usamos esse tipo de figura para mostrar os detalhes do que está acontecendo dentro do pipeline durante cada ciclo de clock. Por exemplo. os diagramas com único ciclo de clock possuem mais detalhes e ocupam muito mais espaço para mostrar o mesmo número de ciclos de clock.44.45 mostra o diagrama com ciclo único de clock correspondente ao ciclo de clock 5 das Figuras 4.6  Caminho de dados e controle usando pipeline 287 FIGURA 4. uma figura com ciclo único de clock é uma fatia vertical de um diagrama com múltiplos ciclos de clock.44  Diagrama de pipeline com múltiplos ciclos de clock tradicional. . Os exercícios pedem que você crie esses diagramas para outras sequências de código. (A Seção 4.43. normalmente. Obviamente.43 e 4.43. para mostrar a operação do pipeline durante uma sequência de ciclos de clock.) Um diagrama de ciclo único de clock representa uma fatia vertical de um conjunto do diagrama com múltiplos ciclos de clock. Como você pode ver.43 e 4. com as cinco instruções da Figura 4. os desenhos aparecem em grupos. 9 removemos os óculos para revelar os hazards do mundo real. branches e instruções da ALU utilizem menos estágios do que os cinco necessários pela instrução load aumentará o desempenho do pipeline sob todas as circunstâncias. Você não pode fazer com que as instruções da ALU utilizem menos ciclos. podemos dividir as linhas de controle em cinco grupos. ID/EX.12. projeto simples. de acordo com o estágio do pipeline. EX/MEM e MEM/WB). Tentar permitir que algumas instruções utilizem menos ciclos não ajuda. devemos explorar um meio de tornar o pipeline mais longo.288 Capítulo 4  O Processador Verifique Um grupo de alunos discutia sobre a eficiência de um pipeline de cinco estágios quando você mesmo um deles apontou que nem todas as instruções estão ativas em cada estágio do pipeline. pois os registradores de pipeline também são es- critos durante cada ciclo de clock. Começamos com um é a diferença. de modo que não existem linhas de con- trole opcionais para definir. a operação da ALU e Dados da leitura 2 ou um imediato com sinal estendido para a ALU.7 a 4. . 2. Execução/cálculo de endereço: os sinais a serem definidos são RegDst. agora anterior. multiplexador do registrador destino e linhas de controle. de modo que existe alguma oportunidade de melhoria. Em particular. porém com ciclos mais curtos. o sistema de controle acrescentamos controle ao caminho de dados de um pipeline. Isso poderia melhorar o desempenho. Depois de decidir ignorar os efeitos dos hazards. o mesmo acontece em cada ciclo de clock. Essas funções são definidas nas Figuras 4. Quais delas estão corretas? 1. No computador 6600. Controle de um pipeline talvez ainda mais do que em qualquer computador Assim como acrescentamos controle ao caminho de dados simples na Seção 4.47 a 4. consideramos que o PC é escrito a cada ciclo de clock. mas os branches e jumps podem utilizar menos ciclos. pois a vazão é determinada pelo ciclo do clock. eles fizeram as quatro afirmações a seguir. de modo que as ins- truções utilizem mais ciclos.18. Em vez de tentar fazer com que as instruções utilizem menos ciclos de clock.48). Pelo mesmo argumento. Assim como ocorreu com a implementação com ciclo único. devido à escrita do resultado.17. 3. Design of a O primeiro passo é rotular as linhas de controle no caminho de dados existente. Reproduzimos as principais informações nas Figuras 4. A Computer: The Control Data Figura 4.47 e 4. OpALU e OrigALU (veja as Figuras 4. Decodificação de instruções/leitura do banco de registradores: como no estágio anterior. e não a vazão. 1. nas Seções de 4. A fim de especificar o controle para o pipeline. Busca de instruções: os sinais de controle para ler a memória de instruções e escrever o PC sempre são ativados. lógica de desvio. Permitir que jumps. 3. 4.46 mostra essas linhas. usamos a mesma lógica de controle da ALU. 1970 para o caminho de dados simples da Figura 4. Os sinais selecionam o registrador destino. 2. de modo que não existe nada de especial para controlar nesse estágio do pipeline.49 em uma única página de modo a facilitar o acompanhamento do restante do texto. 4. o número de estágios do pipe por instrução afeta a latência.3. Pegamos o máximo possível emprestado do controle 6600. de modo que não existe um sinal de escrita separado para o PC.16 e 4. que vê o problema por meio de óculos cor-de-rosa. não existem sinais de escrita para os registradores de pipeline (IF/ID. James Thornton. Como cada linha de controle está associada a um componente ativo em apenas um estágio do pipeline. só precisamos definir os valores de controle durante cada estágio do pipeline. que escreve o valor escolhido.12. FIGURA 4. e EscreveReg. FIGURA 4. respectivamente.6  Caminho de dados e controle usando pipeline 289 4. Lembre-se de que o OrigPC na Figura 4. já que a extensão do sinal deixa esses bits inalterados. Lembre-se de que esses 6 bits também são os bits menos significativos do campo imediato da instrução. 5.4.41 com sinais de controle identificados. Esse caminho de dados toma emprestado a lógica de controle para a origem do PC. LeMem e EscreveMem. de modo que o registrador de pipeline ID/EX pode fornecê-los a partir do campo imediato. Essa figura mostra como os bits do controle da ALU são definidos dependendo dos bits de controle OpALU e dos diferentes códigos de função para instruções tipo R. que decide entre enviar o resultado da ALU ou o valor da memória para o banco de registradores. Acesso à memória: as linhas de controle definidas nesse estágio são Branch. Escrita do resultado: as duas linhas de controle são MemparaReg. Esses sinais são definidos pelas instruções branch equal. a menos que o controle ative Branch e o resultado da ALU seja zero. 4.47  Uma cópia da Figura 4. . da Seção 4.48 seleciona o próximo endereço sequencial. o número do registrador destino e o controle da ALU.46  O caminho de dados em pipeline da Figura 4. Observe que agora precisamos do campo funct (código de função) de 6 bits da instrução no estágio EX como entrada para o controle da ALU. de modo que esses bits também precisam ser incluídos no regis- trador de pipeline ID/EX. load e store. Caso contrário.46. A função de cada um dos sete sinais de controle é definida.50 mostra que esses sinais de controle são usados no respectivo estágio do pipeline à medida que a instrução se move pelo pipeline. se o controle for desativado. o OrigPC é 0. o multiplexador seleciona a entrada 0. A Figura 4.16. O controle define o sinal Branch somente durante uma instrução beq.290 Capítulo 4  O Processador FIGURA 4. podemos usar os mesmos valores de controle de antes. podemos criar a infor- mação de controle durante a decodificação da instrução. caso contrário.18.49  Os valores das linhas de controle são iguais aos da Figura 4. A maneira mais simples de fazer isso é estender os registradores do pipeline de modo a incluir informações de controle. Se o sinal Branch e o sinal Zero da ALU estiverem ativos.47.49 tem os mesmos valores da Seção 4. FIGURA 4. A Figura 4. então OrigPC é 1. mas foram reorganizados em três grupos. o multiplexador seleciona a entrada corres- pondente a 1. Como a utilização de um pipeline no caminho de dados deixa inalterado o significado das linhas de controle. Quando um controle de 1 bit para um multiplexador bidirecional é ativado. mas agora as nove linhas de controle estão agrupadas por estágio do pipeline. A implementação do controle significa definir as nove linhas de controle desses valores em cada estágio. assim como o número do registrador destino para loads se move pelo pipeline da Figura 4. Observe que OrigPC é controlado por uma porta lógica AND na Figura 4. A Figura 4. ele é 0. Como as linhas de controle começam com o estágio EX. corres- pondentes aos três últimos estágios do pipeline.48  Uma cópia da Figura 4.51 mostra o caminho de dados . para cada instrução.4.41. As linhas de controle da ALU (OpALU) são definidas na segunda coluna da Figura 4. caso contrário. FIGURA 4. três são usadas durante o estágio MEM. e as linhas de controle restantes depois disso são passadas ao próximo estágio do pipeline. . Os valores de controle para os três últimos estágios são criados durante o estágio de decodificação de instruções e depois colocados no registrador de pipeline ID/EX. com os sinais de controle conectados às partes de controle dos regis- tradores de pipeline.46. com as cinco linhas de controle restantes passadas adiante para o registrador de pipeline EX/MEM.50  As linhas de controle para os três estágios finais. para uso no estágio WB.51  O caminho de dados em pipeline da Figura 4. As linhas de controle para cada estágio do pipe são usadas. e as duas últimas são passadas a MEM/WB. Observe que quatro das nove linhas de controle são usadas na fase EX.6  Caminho de dados e controle usando pipeline 291 FIGURA 4. 4. para manter as linhas de controle. o topo da Figura 4. quando uma instrução tenta usar um registrador em seu estágio EX. A Figura 4. ou nos ciclos de clock 4 e 5. com os registradores de pipeline estendidos e com as linhas de controle conectadas ao estágio apropriado. Assim. que muda durante o ciclo de clock 5. as instruções AND e OR receberiam o valor incorreto de 10! Usando esse estilo de desenho. que uma instrução anterior . a menos que a leitura ocorresse durante o ciclo de clock 5 ou posterior. de modo que esta fornece o que foi escrito.292 Capítulo 4  O Processador completo. consideramos apenas o desafio de forwarding para uma operação no estágio EX. Se o registrador $2 tivesse o valor 10 antes da instrução subtract e -20 depois dela. Conforme dissemos na Seção 4. Você 4.5. Como essa sequência funcionaria com nosso pipeline? A Figura 4. Agora é hora de retirarmos os óculos cor-de-rosa e examinarmos Galaxy. podemos executar esse segmento sem stalls se simplesmente os dados sofrerem forwarding assim que estiverem disponíveis para quaisquer unidades que precisam deles antes de es- tarem disponíveis para leitura do banco de registradores. O último hazard em potencial pode ser resolvido pelo projeto do hardware do banco de registradores: o que acontece quando um registrador é lido e escrito no mesmo ciclo de clock? Consideramos que a escrita está na primeira metade do ciclo de clock e a leitura está na segunda metade. Como acontece para muitas implementações dos bancos de registradores. (A Seção 4. Mesmo assim. na Seção 4. Douglas Adams. indicadas com realce: As quatro últimas instruções são todas dependentes do resultado no registrador $2 da primeira instrução. se quiser ver mais detalhes.5.45 eram independentes.52 mostra o valor do registrador $2. o resultado desejado está disponível no final do estágio EX ou no ciclo de clock 3. esses problemas se tornam aparentes quando uma linha de dependência retorna no tempo. o programador desejaria que -20 fosse usado nas instruções seguintes que se referem ao registrador $2. Assim.43 a 4.) Como assim por que teve de ser criado? É um bypass. vimos que os hazards de dados são obstáculos para a execução em pipeline. não temos hazard de dados nessa situação. 1979 o que acontece com os programas reais. quando a instrução sub escreve seu resultado. Como funciona o forwarding? Para simplificar o restante desta seção. Para demonstrar a execução dessa sequência de instruções em nosso pipeline atual. As instruções nas Figuras de 4. Isso significa que. respectivamente.52 mostra que os valores lidos para o registrador $2 não seriam o resultado da instrução sub. Vejamos uma sequência com muitas dependências. que pode ser uma operação da ALU ou um cálculo de endereço efetivo. Quando os dados são realmente necessários pelas instruções AND e OR? No início do estágio EX. The Os exemplos da seção anterior mostram o poder da execução em pipeline e como o Hitchhiker's Guide to the hardware realiza a tarefa. nenhuma delas usava os resultados calculados por qualquer uma das outras. as instruções que receberiam o valor correto de -20 são add e sw.12 contém mais exemplos de código MIPS executando em hardware com pipeline usando diagramas de clock simples.7  Hazards de dados: forwarding versus stalls precisa criar bypasses.52 ilustra a execução dessas instruções usando uma representação de pipeline com múltiplos ciclos de clock. e a instrução anterior está no estágio MEM.RegistradorRs = $2 . A primeira instrução escreve em $2. “ID/EX. MEM/WB.RegistradorRs 2b.$2.7  Hazards de dados: forwarding versus stalls 293 FIGURA 4.RegistradorRt 2a. à esquerda do ponto. Esse registrador é escrito no ciclo de clock 5. aquele da primeira porta de leitura do banco de registradores. de modo que o valor correto está indisponível antes do ciclo de clock 5. A primeira parte do nome. pretende escrever em seu estágio WB. e todas as instruções seguintes leem de $2.RegistradorRs” refere-se ao número de um registrador cujo valor se encontra no registrador de pipeline ID/EX.52  Dependências em pipeline em uma sequência de cinco instruções usando caminhos de dados simplificados para mos- trar as dependências. EX/MEM. Esse hazard pode ser detectado quando a instrução and está no estágio EX. Aquelas que precisam retornar no tempo são os hazards de dados do pipeline. 4. EX/MEM. Uma notação que nomeia os campos dos registradores de pipeline permite uma notação mais precisa das dependências.RegistradorRs 1b. entre o resultado de sub S2.RegistradorRd = ID/EX.$5.RegistradorRd = ID/EX.RegistradorRt O primeiro hazard na sequência da Seção 4. (Uma leitura de um registrador durante um ciclo de clock retorna o valor escrito no final da primeira metade do ciclo.$1. a segunda parte é o nome do campo nesse registrador. e “CC 1” no alto da figura significa o ciclo de clock 1. MEM/WB.RegistradorRd = ID/EX.) As linhas coloridas do caminho de dados do topo para os inferiores mostram as dependências.RegistradorRd = ID/EX.$3 e o primeiro operando de leitura de and $12. na realidade precisamos dos valores como entradas para a ALU. Por exemplo.RegistradorRd = ID/EX. Usando essa notação. de modo que este é o hazard 1a: EX/MEM.7 está no registrador $2. ou seja. quando ocorre tal escrita. Todas as ações dependentes são mostradas em cinza. é o nome do registrador de pipeline. os dois pares de condições de hazard são: 1a. Já temos o campo rt (bits 20-16). sub. A Figura 4. Uma solução é simplesmente verificar se o sinal EscreveReg estará ativo: examinando o campo de controle WB do registrador de pipeline durante os estágios EX e MEM. em vez de esperar pelo estágio WB para escrever no banco de registradores. podemos executar o pipeline em velocidade máxima na presença dessas dependências de dados. Antes .2). AND e OR. portanto. Como algumas instruções não escrevem em registradores. Assim. porque sw lê $2 no ciclo de clock depois que sub escreve $2. para determinar se os valores devem sofrer forwarding. A mudança é que a dependência começa por um registrador de pipeline.53 mostra as dependências entre os registradores de pipeline e as entradas da ALU para a mesma sequência de código da Figura 4.RegistradorRd ≠ 0 à segunda.52. às vezes. A Figura 4. é possível determinar se EscreveReg está ativo.55 mostra os valores das linhas de controle para os multiplexadores da ALU que selecionam os valores do banco de registradores ou um dos valores de forwarding. Não encaminhar os resultados destinados a $0 libera o programador assembly e o compilador de qualquer requisito para evitar o uso de $0 como destino. Se uma instrução no pipeline tiver $0 como seu destino (por exemplo. Assim. j Não existe hazard de dados entre sub e sw. os dados exigidos existem a tempo para as instruções posteriores. funcionam corretamente desde que acrescentemos EX/MEM. metade do problema está resolvido – mas ainda precisamos fazer o forwarding dos dados corretos. Se pudermos pegar as entradas da ALU de qualquer registrador de pipeline. então podemos fazer o forwarding dos dados corretos. Os outros hazards são RESPOSTA j sub-or é um hazard tipo 2b: MEM/WB. poderia haver forwarding indevidamente. queremos evitar o forwarding do seu valor possivelmente diferente de zero. essa política não é exata. Lembre-se de que o MIPS exige que cada uso de $0 como operando deve gerar um valor de operando 0.294 Capítulo 4  O Processador Detecção de dependência EXEMPLO Classifique as dependências nesta sequência da Seção 4. pois o banco de regis- tradores fornece os dados apropriados durante o estágio ID de add. Por enquanto. temos de passar os números dos registradores operandos do estágio ID por meio do registrador de pipeline ID/EX. Esse controle de forwarding estará no estágio EX porque os multiplexadores de for- warding da ALU são encontrados nesse estágio. Acrescentando multi- plexadores à entrada da ALU e com os controles apropriados. o sub-and é um hazard tipo 1a. A Figura 4.$1. sll $0. Agora que podemos detectar os hazards.54 mostra um detalhe da ALU e do registrador de pipeline antes e depois de acrescentar o for- warding. vamos considerar que as únicas instruções para as quais precisamos de forwarding são as quatro instruções no formato R: add.RegistradorRd = ID/EX.7: Conforme já mencionamos.Regis- tradorRd ≠ 0 à primeira condição de hazard e MEM/WB. As condições anteriores.RegistradorRt = $2 j As duas dependências em sub-add não são hazards. com os registradores de pipeline mantendo os dados para forwarding. e não apenas de ID/EX. tratamos de todo o forwarding. O “forwarding” do banco de registradores – ou seja. do forwarding. mas os valores vêm do banco de registradores. Esse caso faz o forwarding do resultado da instrução anterior para qualquer entrada da ALU.RegistradorRd é o destino de registrador para uma ins- trução da ALU (que vem do campo Rd da instrução) ou um load (que vem do campo Rt). Agora. Hazard EX: Observe que o campo EX/MEM. o registrador ID/EX não precisava incluir espaço a fim de manter o campo rs. Se a instrução anterior tiver de escrever no banco de registradores e o número do registrador de escrita combinar com o número do registrador de leitura das entradas . a leitura apanha o valor da escrita nesse ciclo de clock – é o motivo pelo qual o ciclo de clock 5 mostra o registrador $2 tendo o valor 10 no início e -20 no final do ciclo de clock. de modo que é possível fornecer as entradas para a ALU necessárias pela instrução AND e pela instrução OR fazendo forwarding dos resultados encontrados nos regis- tradores de pipeline. e não de um registrador de pipeline. exceto para o valor a ser armazenado por uma instrução store. Como no restante desta seção. vamos escrever as duas condições para detectar hazards e os sinais de controle para resolvê-los: 1. 4. Consideramos que o banco de registradores encaminha valores lidos e escritos durante o mesmo ciclo de clock. Logo.53  As dependências entre os registradores de pipeline se movem para a frente no tempo.7  Hazards de dados: forwarding versus stalls 295 FIGURA 4. rs (bits 25-21) é acrescentado a ID/EX. de modo que add não causa stall. Os valores nos registradores de pipeline mostram que o valor desejado está disponível antes de ser escrito no banco de registradores. Embaixo. omitindo os detalhes do caminho de dados completo.296 Capítulo 4  O Processador FIGURA 4. Observe que o campo ID/EX. desde que não seja o registrador 0. os multiplexadores foram expandidos para acrescentar os caminhos de forwarding. e não do registrador de pipeline EX/MEM.Regis- tradorRt aparece duas vezes. O hardware novo aparece em um destaque. A ou B da ALU. então direcione o multiplexador para pegar o valor. como o hardware de extensão de sinal. Hazard MEM: .54  Em cima estão a ALU e os registradores de pipeline antes da inclusão do forwarding. essa figura é um desenho estilizado. mas esse é um único sinal. 2. No entanto. Observe que esse mecanismo também funciona para instruções slt. e mostramos a unidade de forwarding. isso ignora o forwarding de um valor armazenado por uma instrução store. uma para conectar ao mux e uma para a unidade de forwarding. Como na discussão anterior. Como dissemos. Tal banco de registradores realiza outra forma de forwarding. 4. o controle para o hazard em MEM seria (com os acrés- cimos destacados): A Figura 4. . Uma complicação são os hazards de dados em potencial entre o resultado da instrução no estágio WB. Assim.7  Hazards de dados: forwarding versus stalls 297 FIGURA 4. Observe que o campo EX/MEM. o resultado da instrução no estágio MEM e o operando de origem da ins- trução no estágio ALU. não existe hazard no estágio WB porque consideramos que o banco de registradores fornece o resultado correto se a instrução no estágio ID ler o mesmo regis- trador escrito pela instrução no estágio WB.55  Os valores de controle para os multiplexadores de forwarding da Figura 4. o resultado sofre forwarding do estágio MEM. uma sequência de instruções lerá e escreverá no mesmo registrador: Nesse caso. pois o resultado no estágio MEM é o mais recente. RegistradorRd é o destino do registrador para uma instrução ALU (que vem do campo Rd da instrução) ou um load (que vem do campo Rt). ao somar um vetor de números em um único regis- trador.12 no site mostra dois trechos de código MIPS com hazards que causam forwarding. se você quiser ver mais exemplos ilustrados usando desenhos de pipeline de ciclo único. Por exemplo. O imediato com sinal que é outra entrada da ALU é descrito na Seção “Detalhamento” ao final desta seção. A Seção 4.56 mostra o hardware necessário para dar suporte ao forwarding para operações que utilizam resultados durante o estágio EX. mas isso ocorre dentro do banco de registradores.54. Contudo. um caso em que o forwarding não pode salvar o dia é Anônimo quando uma instrução tenta ler um registrador após uma instrução load que escreve no mesmo registrador. Se tivéssemos de redesenhar a Figura 4.57 mostra esse acréscimo. teríamos de acrescentar o forwarding para o estágio de acesso à memória. Além disso. Em comparação com o caminho de dados da Figura 4. Mas considere os loads imediatamente seguidos por stores. como o hardware de desvio e o hardware de extensão de sinal.53. Como elas utilizam apenas um valor de dados durante o es- tágio MEM. Algo precisa ocasionar um stall no pipeline para a combinação de load seguida por uma instrução que lê seu resultado.51. essa figura é um desenho mais estilizado. redefina sucesso. Deixamos essa modificação como um exercício para o leitor. não existe no caminho de dados da Figura 4. a entrada imediata com sinal para a ALU. necessária para loads e stores.5. Para essa opção. A Figura 4. os acréscimos são os multiplexadores para as entradas da ALU. A Figura 4. Conforme dissemos na Seção 4. pois os dados existem no registrador MEM/WB de uma instrução load em tempo para seu uso no estágio MEM de uma instrução store. Como o controle central decide entre registrador e imediato.56. e como a unidade de forwarding escolhe o registrador de pipeline para uma entrada de registrador para a ALU. substituindo as instruções sub e AND por lw e sw. a solução mais fácil é acrescentar um multiplexador 2:1 que es- colha entre a saída do multiplexador ForwardB e o imediato com sinal. Os dados ainda são lidos da memória no ciclo de clock 4. útil quando se realiza cópias da memória para a memória na arquitetura MIPS. . enquanto a ALU está realizando a operação para a instrução seguinte.56  O caminho de dados modificado para resolver os hazards via forwarding.58 ilustra o problema. veríamos que é possível evitar um stall.298 Capítulo 4  O Processador FIGURA 4. o forwarding é fácil. omitindo detalhes do caminho de dados completo. Detalhamento:  o forwarding também pode ajudar com hazards quando instruções store dependem de outras instruções. Se a princípio você não obteve Hazards de dados e stalls sucesso. precisamos acrescentar mais hardware de forwarding a fim de fazer com que as cópias de memória para memória se tornem mais rápidas. Como as cópias são frequentes. 4. essa combinação precisa resultar em um stall pela unidade de detecção de hazard. FIGURA 4. acrescentado para selecionar o imediato com sinal como uma entrada para a ALU. Como a dependência entre o load e a instrução seguinte (and) recua no tempo.54 mostra um multiplexador 2:1.7  Hazards de dados: forwarding versus stalls 299 FIGURA 4. esse hazard não pode ser resolvido pelo forwarding.58  Uma sequência de instruções em pipeline. . Logo.57  Uma visão de perto do caminho de dados da Figura 4. Se a condição permanecer. mas seu efeito é esticar o tempo das instruções AND e OR e atrasar a busca da instrução add. é como se você reiniciasse a lavadora com as mesmas roupas e deixasse a secadora continuando a trabalhar vazia.300 Capítulo 4  O Processador Logo. Esse trabalho repetido é um stall. o controle para a unidade de detecção de hazard é esta condição única: A primeira linha testa se a instrução é um load: a única instrução que lê a memória de dados é um load. Depois desse stall de um ciclo. de modo que pode inserir o stall entre o load e seu uso. a unidade de forwarding controla os multiplexadores da ALU a fim de substituir o valor de um registrador de uso geral pelo valor do registrador de pipeline apropriado.60 destaca as conexões do pipeline para a unidade de detecção de hazard e a unidade de forwarding. A unidade de detecção de hazard controla a escrita dos registradores PC e IF/ID mais o multiplexador que escolhe entre os valores de controle reais e 0s.) Se a instrução no estágio ID sofrer um stall. até que saia no final. Como podemos inserir esses nops. que causa stalling.49. precisamos de uma unidade de detecção de hazard. a metade do pipeline que começa nop  Uma instrução que não realiza com o estágio EX precisa estar fazendo algo. Esses valores de controle benignos são filtrados adiante em cada ciclo de clock com o efeito correto: nenhum registrador ou memória serão modificados se os valores forem todos 0. que não têm efeito algum: nops. a instrução ocasiona um stall de um ciclo de clock no pipeline. Assim como uma bolha de ar em um cano de água. vimos que a desativação de todos os nove sinais de controle (colocando-os em 0) nos estágios EX. ou nop. e todas as instruções começando com a instrução AND são atrasadas um ciclo. e os registradores no estágio ID continuarão a ser lidos usando os mesmos campos de ins- trução no registrador de pipeline IF/ID. Como antes. Retornando à nossa analogia favorita. As duas linhas seguintes verificam se o campo do registrador destino do load no estágio EX combina com qualquer registrador origem da instrução no estágio ID. caso contrário. além de uma unidade de forwarding. ilustrado por diagramas de pipeline com ciclo único de clock. se quiser ver mais detalhes. Neste exemplo. Desde que esses registradores sejam preservados. então as instruções na Figura 4. Verificando as instruções load. Evitar que essas duas instruções tenham progresso é algo feito simplesmente impedindo-se que o regis- trador PC e o registrador de pipeline IF/ID sejam alterados. o hazard força as instruções AND e OR a repetir no ciclo de clock 4 o que fizeram no ciclo de clock 3: AND lê registradores e decodifica. A Figura 4. assim como a secadora. A unidade de detecção de hazard insere um stall e desativa os campos de controle se o teste de hazard do uso do load for verdadeiro. perderíamos a instrução lida da memória. o que ela está fazendo é executar instruções operação para mudar de estado. uma bolha de stall retarda tudo o que está atrás dela e prossegue pelo pipe de instruções um estágio a cada ciclo.58 precisariam de outro ciclo de stall. podemos inserir uma bolha no pipeline alterando os campos de controle EX. A Figura 4. e OR é apanhado novamente da memória de instruções. então a instrução no estágio IF também precisa sofrer.59 mostra o que realmente acontece no hardware: a execução do slot do pipeline associado com a instrução AND transforma-se em um nop. . Ela opera durante o estágio ID.12. Identificando o hazard no estágio ID. MEM e WB do registrador de pipeline ID/EX para 0. Naturalmente. no site. A Seção 4. no pipeline? Na Figu- ra 4. contém um exemplo do código MIPS com hazards. (Se não houvesse forwarding. MEM e WB criará uma instrução que “não faz nada”. que atuam como bolhas. a lógica de forwarding pode lidar com a dependência e a execução prossegue. a instrução no estágio IF continuará a ser lida usando o mesmo PC. mostrando os dois multiplexadores para forwarding. . todas as dependências seguem à frente no tempo.7  Hazards de dados: forwarding versus stalls 301 FIGURA 4. mas seu estágio EX é atrasado até o ciclo de clock 5 (ao contrário da posição sem stall no ciclo de clock 4).60  Visão geral do controle em pipeline. a instrução or é apanhada no ciclo de clock 3. 4. Observe que a instrução and na realidade é buscada e decodificada nos ciclos de clock 2 e 3. e nenhum outro hazard acontece. a unidade de detecção de hazard e a unidade de forwarding. FIGURA 4. este desenho mostra a essência dos requisitos do hardware de forwarding. alterando a ins- trução and para um nop. Da mesma forma. Embora os estágios ID e EX tenham sido simplificados – a lógica de extensão de sinal imediato e de desvio estão faltando –. Após a inserção da bolha. mas seu estágio IF é atrasado até o ciclo de clock 5 (ao contrário da posição não atrasada no ciclo de clock 4). Uma bolha é inserida a partir do ciclo de clock 4.59  O modo como os stalls são realmente inseridos no pipeline. Uma instrução precisa ser buscada a cada ciclo de clock para sustentar o pipeline. esse atraso para determinar a instrução própria a ser buscada é chamado de hazard de controle ou hazard de desvio. sobre hazards de dados. A execução continua no destino do desvio. e se custar pouco descartar as instruções. Caso contrário. se movermos a execução do desvio para um estágio anterior do pipeline. as instruções que estão sendo buscadas e decodificadas precisam ser descartadas. simplesmente alteramos o controle para 0 no estágio ID e o deixamos prosseguir no pipeline. ID e EX do pipeline. também existem hazards de pipeline envolvendo desvios. assim como fizemos para o stall no hazard de dados no caso do load. Os projetistas observaram que muitos desvios contam apenas com testes simples .5. Reduzindo o atraso dos desvios Uma forma de melhorar o desempenho do desvio é reduzir o custo do desvio tomado. então.8  Hazards de controle Henry David Thoreau. A diferença é que também precisamos alterar as três instruções nos estágios IF. Detalhamento:  Com relação ao comentário anterior sobre a colocação das linhas de con- trole em 0 para evitar a escrita de registradores ou memória: somente os sinais EscreveReg e EscreveMem precisam ser 0. A Figura 4. Se o desvio for tomado. então menos ins- truções precisam sofrer flush. portanto.302 Capítulo 4  O Processador Colocando em Embora o compilador geralmente conte com o hardware para resolver depen- dências de hazard e garantir a execução correta. mas. Se os desvios não são tomados na metade das vezes.5. em nosso projeto. Esta seção sobre hazards de controle é mais curta do que as seções anteriores. Descartar instruções. Entretanto. continuar no fluxo sequencial das instruções. Até aqui. normalmente devido a um evento inesperado. que acabamos de examinar. consideramos que o próximo PC para um desvio é selecionado no estágio MEM. pipeline. 1854 Até aqui. Para cada mal que está batendo na raiz há milhares pendurados nos galhos. e ocorrem com menos frequência que os hazards de dados. enquanto os outros sinais de controle podem ser don’t care. significa que flush  Descartar instruções em um precisamos ser capazes de dar flush nas instruções nos estágios IF. Conforme mencionamos na Seção 4. que poderiam passar pelo pipeline com uma pequena penalidade no desvio. Veremos dois esquemas para resolver os hazards de controle e uma otimização para melhorar esses esquemas.61 mostra uma sequência de instruções e indica quando o desvio ocorreria nesse pipeline. Considere que o desvio não foi tomado Como vimos na Seção 4. como vimos na Seção 4. simplesmente alteramos os valores de controle para 0. Além disso. o compilador precisa com- perspectiva preender o pipeline a fim de alcançar o melhor desempenho. fazer um stall até que o desvio termine é muito lento.5. a decisão sobre o desvio não ocorra até o estágio MEM do pipeline. usamos esquemas mais simples. ID e EX quando o desvio atingir o estágio MEM. limitamos nossa preocupação aos hazards envolvendo operações aritméticas e transferências de dados. Logo. porque os hazards de controle são relativamente simples de entender. Walden. Para descartar instruções. não há nada tão eficiente contra os hazards de controle quanto o forwarding contra os hazards de dados. Uma melhoria comum ao stall do desvio é considerar que o desvio não será tomado e. stalls inesperados reduzirão o desempenho do código compilado. embora. essa otimização reduz ao meio o custo dos hazards de controle. ao contrário dos hazards de dados. A arquitetura do MIPS foi criada para dar suporte a desvios rápidos de ciclo único. para os stalls no uso de load. 4. 44. mas só será usado quando for necessário. Para branch equal. A parte fácil dessa mudança é subir com o cálculo do endereço de desvio. as três instruções sequenciais que seguem o branch serão buscadas e iniciarão sua execução. essa figura usa o caminho de dados não otimizado. naturalmente.61  O impacto do pipeline sobre a instrução branch. temos de decodificar a instrução. uma instrução separada. A parte mais difícil é a própria decisão do desvio. Mover o teste de desvio para o estágio ID implica hardware adicional de forwarding e detecção de hazard.) (igualdade ou sinal. Quando uma decisão de desvio mais complexa é exigida. Como a instrução branch decide se deve desviar no estágio MEM – ciclo de clock 4 para a instrução beq. Os números à esquerda da instrução (40. A igualdade pode ser testada primeiro realizando um OR exclusivo de seus respectivos bits e depois um OR de todos os resultados. é requisitada – uma situação semelhante ao uso de códigos de condição para os desvios (veja o Capítulo 2). Sem intervenção.31 considerou um hardware extra para reduzir o hazard de controle a um ciclo de clock. essas três instruções seguintes começarão a executar antes que o beq desvie para lw na posição 72. compararíamos os dois registradores lidos durante o estágio ID para ver se são iguais. possamos atribuir ao PC o endereço de destino do . Existem dois fatores que comprometem o procedimento: 1. (A Figura 4. o cálculo do endereço de destino do desvio será realizado para todas as instruções. teremos de fazer um forwarding dos resultados para a lógica do teste de igualdade que opera durante o estágio ID. a fim de implementar branch-on-equal (e seu inverso).8  Hazards de controle 303 FIGURA 4. que usa uma ALU para realizar uma comparação. Durante o estágio ID. Levar a decisão do desvio para cima exige que duas ações ocorram mais cedo: calcular o endereço de destino do desvio e avaliar a decisão do desvio. por exemplo) e que esses testes não exigem uma operação completa da ALU. mas podem ser feitos com no máximo algumas portas lógicas. anterior –. decidir se um bypass para a unidade de igualdade é necessário e completar a comparação de igualdade de modo que. 4. se a instrução for um desvio. …) são os endereços das instruções. Por exemplo. Já temos o valor do PC e o campo imediato no registrador de pipeline IF/ID. de modo que só movemos o somador do desvio do es- tágio EX para o estágio ID. visto que um desvio dependente de um resultado ainda no pipeline precisará funcionar corretamente com essa otimização. se uma instrução da ALU imediatamente antes de um desvio produz um dos operandos para a comparação no desvio. Os exercícios exploram os detalhes da implementação do caminho de forwarding e a detecção do hazard. possivelmente acoplada com a previsão baseada no compilador. em um pipeline agressivo. . acrescentamos uma linha de controle. Para o pipeline simples.304 Capítulo 4  O Processador desvio. dois ciclos de stall serão necessários. Diferente da RESPOSTA Figura 4. prevemos que os desvios não são tomados. que zera o campo de instrução do registrador de pipeline IF/ID. a saber. pois reduz a penalidade de um desvio a apenas uma instrução se o desvio for tomado. uma instrução que não possui ação e não muda estado algum. O forwarding para os operandos dos desvios foi tratado anteriormente pela lógica de forwarding da ALU. a penalidade do desvio aumenta em termos de instruções perdidas. com a questão múltipla (veja a Seção 4. Essa combinação significa que. chamada IF. pois o resultado do load aparece no final do ciclo MEM. Nesse caso. Por exemplo.10). Por extensão. Observe que os operandos-fonte de um desvio que sofreram bypass podem vir dos latches do pipeline ALU/MEM ou MEM/ WB. mas é necessário no início do ID do desvio. EXEMPLO considerando que o pipeline está otimizado para desvios que não são tomados e que movemos a execução do desvio para o estágio ID: A Figura 4. a penalidade do desvio aumenta quando medida em ciclos de clock. Apagar o registrador transforma a instrução buscada em um nop. mas a introdução da unidade de teste de igualdade no estágio ID exigirá nova lógica de forwarding. deverá ser adequada. 2. essa técnica.Flush. com cinco estágios. Previsão dinâmica de desvios Supor que um desvio não seja tomado é uma forma simples de previsão de desvios.62 mostra o que acontece quando um desvio é tomado. Para fazer um flush das instruções no estágio IF. Desvios no pipeline Mostre o que acontece quando o desvio é tomado nesta sequência de instruções. se um load for imediatamente seguido por um desvio condicional que está no resultado do load. um stall será exigido. Como os valores em uma comparação de desvio são necessários durante o estágio ID. mover a execução do desvio para o estágio ID é uma me- lhoria. aquela sendo buscada atualmente. Apesar dessas dificuldades. Com pipelines mais profundos. já que o estágio EX para a instrução da ALU ocorrerá depois do ciclo de ID do desvio. Da mesma forma. há somente uma bolha no pipeline para o desvio tomado. mas podem ser produzidos mais adiante no tempo. fazendo um flush no pipeline quando es- tivermos errados.61. é possível que ocorra um hazard de dados e um stall seja necessário. 62  O estágio ID do ciclo de clock 3 determina que um desvio precisa ser tomado. é discutível se o estágio ID no clock 4 deve ou não ser destacado.8  Hazards de controle 305 FIGURA 4.) um esquema de previsão estática provavelmente desperdiçará muito desempenho. (Como o nop na realidade é s11 $0. começar a buscar novas instruções desvios  Previsão de desvios a partir do mesmo lugar da última vez. é possível tentar prever o comportamento do desvio durante a execução do programa. Como mencionamos na Seção 4. usando desvios. informações em tempo de execução. com mais hardware.0. Uma técnica é pesquisar o endereço da instrução para ver se um desvio foi tomado previsão dinâmica de na última vez que essa instrução foi executada e.5. .$0. Essa técnica é chamada previsão dinâmica de durante a execução. de modo que seleciona 72 como próximo endereço do PC e zera a instrução buscada para o próximo ciclo de clock. 4. se foi. O ciclo de clock 4 mostra a instrução no local 72 sendo buscada e a única bolha ou instrução nop no pipeline como resultado do desvio tomado. as ins- truções previstas incorretamente são excluídas. o bit de previsão é invertido e armazenado de volta.63 mostra a máquina de estados finitos para um esquema de previsão de 2 bits. Caso contrário. uma previsão precisa estar errada duas vezes antes de ser alterada. Se o palpite estiver errado. os esquemas de previsão de 2 bits são utilizados com frequência. acessado com o endereço da instrução durante o estágio do pipe IF. podemos tornar o hazard de controle em um recurso. endereço da instrução de desvio Esse é o tipo de buffer mais simples. ou tabela de desvios  Também chamado histórico de desvios. Um buffer de previsão de desvios é uma pequena memória indexada tabela de histórico de desvios. quando ele não for tomado. . O ideal é que a previsão do sistema combine com a frequência de desvio tomado para esses desvios altamente regulares. Se a previsão for errada. O exemplo a seguir mostra esse dilema.5. como mostra a Figura 4. redefinindo o desvio. que tem os mesmos bits de endereço menos indicando se o desvio foi tomado significativos. que na arquitetura úteis. Para remediar esse ponto fraco. pois o desvio não foi tomado nessa iteração final. já que o desvio foi tomado nove vezes seguidas nesse ponto. e a sequência apropriada é buscada e executada. Um buffer de previsão de desvio pode ser implementado como um pequeno buffer especial. Em um esquema de 2 bits. A memória contém um pela parte menos significativa do bit que diz se o desvio foi tomado recentemente ou não. delay slot do desvio  O slot Os compiladores e os montadores tentam colocar uma instrução que sempre executa após o diretamente após a instrução de desvio no delay slot do desvio. não sabemos se a previsão é a correta – e que contém um ou mais bits ela pode ter sido colocada lá por outro desvio. Um delayed branch sempre executa a seguinte instrução. em vez de uma. a busca e a execução sequencial continuam. Qual é a exatidão da previsão para esse desvio. O erro de previsão na primeira iteração acontece porque o bit é invertido na execução anterior da última iteração do loop. correto. a exatidão da previsão para esse desvio tomado 90% do tempo é apenas de 80% (duas previsões incorretas contra oito corretas). mas a segunda instrução após o desvio será afetada pelo desvio. A previsão é apenas um palpite considerado recentemente ou não. depois não é tomado EXEMPLO uma vez. isso pode ser até mesmo no estágio ID. A tarefa do software é tornar as instruções sucessoras válidas e delayed branch. Esse esquema de previsão de 1 bit tem um problema de desempenho: mesmo que um desvio quase sempre seja tomado. provavelmente faremos uma previsão incorreta duas vezes. de modo que a busca começa na direção prevista.306 Capítulo 4  O Processador buffer de previsão de Uma implementação dessa técnica é um buffer de previsão de desvios. os bits de previsão são trocados.64 mostra as três maneiras como o delay slot do desvio pode ser escalonado. Detalhamento:  Conforme descrevemos na Seção 4. Uma pequena memória indexada pela parte menos significativa do endereço da instrução de desvio. pois o bit de previsão dirá “tomado”. supondo que o bit de pre- visão para o desvio permaneça no buffer de previsão? O comportamento da previsão de estado fixo fará uma previsão errada na primeira RESPOSTA e última iterações do loop.63. a busca começa a partir do destino assim que o PC for co- nhecido. na verdade. A Figura 4. Loops e previsão Considere um desvio de loop que se desvia nove vezes seguidas. MIPS é preenchido por uma As limitações sobre o escalonamento com delayed branch surgem de (1) as restrições instrução que não afeta o desvio. conforme mencionamos anteriormente. Assim. O erro de previsão na última iteração é inevitável. Se a instrução for prevista como tomada. sobre as instruções escalonadas nos delay slots e (2) nossa capacidade de prever durante a compilação se um desvio provavelmente será tomado ou não. Mas isso não afeta a exatidão. A Figura 4. em um pipeline de cinco estágios. FIGURA 4. queremos dizer que o trabalho é desperdiçado. mas o programa ainda será executado corretamente. o delay slot de desvio é escalonado a partir do destino do desvio. Em (a). Para cada par de quadros. a instrução de destino precisará ser copiada. como em um desvio de loop.64  Escalonando o delay slot do desvio. 4. um desvio que favoreça bastante a situação “tomado” ou “não tomado” – como muitos desvios fazem – será previsto incorretamente apenas uma vez. Com “OK”. normalmente.63  Os estados em um esquema de previsão de 2 bits. Esse é o caso. Nas sequências de código para (b) e (c).8  Hazards de controle 307 FIGURA 4. o quadro de baixo mostra o código escalonado. Para tornar essa otimização válida para (b) ou (c). o desvio pode ser escalonado a partir da sequência não tomada. incrementado quando a previsão é exata e decrementado em caso contrário. o delay slot é escalonado com uma instrução independente de antes do desvio. se $t4 fosse um registrador temporário não utilizado quando o desvio entrasse na direção inesperada. o quadro de cima mostra o código antes do escalonamento. . Essa é a melhor opção. por exemplo. Finalmente. Os 2 bits são usados para codificar os quatro estados no sistema. deve ser “OK” executar a instrução sub quando o desvio seguir na direção inesperada. A estratégia (b) é preferida quando o desvio é tomado com alta probabilidade. Em (b). e utiliza o ponto intermediário desse intervalo como divisão entre desvio tomado e não tomado. o uso de $s1 na condição de desvio impede que a instrução add (cujo destino é $s1) seja movida para o delay slot do desvio. Usando 2 bits em vez de 1. pois pode ser alcançada por outro caminho. O esquema de 2 bits é um caso geral de uma previsão baseada em contador. As estratégias (b) e (c) são usadas quando (a) não é possível. como em (c). Os delayed branches desvios  Uma estrutura que são uma técnica para eliminar essa penalidade. Assim. uma versão da arquitetura do conjunto de instruções MIPS tem duas novas instruções chamadas movn (move if not zero) e movz (move if zero). Outra técnica é usar uma cache para manter coloca em cache o PC de destino o contador de programa de destino ou instrução de destino. Usando essa analogia como um guia. Agora. Qual previsor é a melhor escolha para os seguintes desvios? . movn $8. o comportamento de desvio global pode ser imaginado como acrescentando determinado desvio e informações bits de índice adicionais para a previsão. o crescimento em transistores disponíveis por chip tornou a previsão dinâmica relativamente mais barata. Por exemplo. Logo. geram maior exatidão da simples. Verifique Considere três esquemas de previsão de desvios: desvio não tomado. Detalhamento:  um previsor de desvios nos diz se um desvio é tomado ou não. Um previsor correlato simples poderia ter dois previsores de 2 bits para cada desvio. Simul- taneamente. Ele normalmente é O esquema de previsão dinâmica de 2 bits usa apenas informações sobre um determinado organizado como uma cache com tags. começando com um caminho de dados de ciclo único e depois acrescentando regis- tradores de pipeline. previsão para o mesmo número de bits de previsão.$4 copia o conteúdo do registrador 11 para o registrador 8. Em vez de mudar o PC com um desvio condicional. mas ainda exige o cálculo do destino do desvio. Assim. juntos.65 mostra o caminho de dados e controle finais. detecção de hazard de dados. previsão de desvio e com flushing de instruções em exceções.$11. ela não faz nada. previsor de desvio que combina com a escolha entre os previsores feita com base em se o último desvio executado foi tomado o comportamento local de ou não. Assim. porém mais flexíveis. Suponha que a exatidão média da previsão do previsor dinâmico seja de 90%. o delayed branch perdeu popularidade em comparação com as técnicas mais dispendiosas. para cada desvio. Essas técnicas são chamadas de previsor previsor correlato Um correlato. Se a condição falha. o move atua como um nop. despachando múltiplas instruções por ciclo de clock (veja Seção 4. estamos prontos para outro hazard de controle: a questão complicada das exceções. os programas ARM poderiam ter menos desvios condicionais que os programas MIPS. tornando-o mais dispendioso desvio. Suponha que todos eles tenham penalidade zero quando preveem corretamente e 2 ciclos quando estão errados. desde que o valor no registrador 4 seja diferente de zero. explicamos o pipelining de instruções passo a passo. favorecendo qualquer um dos dois desvio e um mecanismo de seleção que escolhe qual previsor deve ser previsores que tenha sido mais preciso. Um seletor escolheria qual previsor usar para qualquer previsão dada. Um previsor de torneio típico poderia conter duas previsões para cada previsor de desvio de índice de desvio: uma baseada em informações locais e uma baseada no comportamento do torneio  Um previsor de desvios desvio global. Um de algum número recente de previsor de torneio utiliza vários previsores. usando um buffer de destino de ou a instrução de destino para desvios. caso contrário. mostrando princípios de pipelining em um ambiente do dia a dia. previsão tomada você mesmo e previsão dinâmica. o atraso do desvio torna-se maior e um único delay slot é insuficiente. A Figura 4. O seletor com múltiplas previsões para cada pode operar semelhantemente a um previsor de 1 ou 2 bits. globais sobre o comportamento Uma inovação mais recente na previsão de desvios é o uso de previsões de torneio. Resumo sobre pipeline Começamos na lavanderia. O conjunto de instruções ARM tem um campo de condição na maioria das instruções. Os pesquisadores notaram que o uso de informações sobre um desvio local e um do que um buffer de previsão comportamento global de desvios executados recentemente. buffer de destino de significando que os desvios tomados terão uma penalidade de um ciclo. Muitos microprocessadores avançados mais recentes usado para determinado desvio utilizam esses previsores rebuscados. caminhos de forwarding. um desvio.308 Capítulo 4  O Processador O delayed branch foi uma solução simples e eficaz para um pipeline de cinco estágios des- pachando uma instrução a cada ciclo de clock. os melhores resultados. qual previsor gera desvios executados. À medida que os processadores utilizam pipe- lines maiores.10). acompanhando. esse cálculo leva um ciclo. Detalhamento:  Uma maneira de reduzir o número de desvios condicionais é acrescentar instruções de move condicional. a instrução muda condicionalmente o registrador de destino do move. No pipeline de cinco estágios. 9   Exceções comportar [sequencialmente] não foi uma tarefa fácil. (Algumas arquiteturas utilizam o termo interrupção para todas as exceções. O mesmo mecanismo básico foi estendido para os dispositivos de E/S se co- Computer System: Project municarem com o processador. Um evento não o termo exceção para indicar qualquer mudança inesperada no fluxo de controle. pois o número de instruções Controle é o aspecto mais desafiador do projeto do processador: ele é a parte mais difícil em diversos estágios do de se acertar e a parte mais difícil de tornar mais rápida. Um desvio tomado com frequência de 70%.) .. Planning a aritmético. Por exemplo. Um desvio tomado com frequência de 5%. usamos o termo interrupção apenas quando detectar overflow. Stretch. pode ser muito grande. o evento é causado externamente. sem programado que interrompe a execução do programa. como o overflow Fred Brooks Jr. conforme veremos no Capítulo 6. usando interrupção. 4.65  O caminho de dados e controle final para este capítulo. em vez de um caminho de dados detalhado. usada para distinguir se a causa é interna ou externa. Uma das partes mais difíceis do processamento quando um controle é implementar exceções e interrupções — eventos diferentes dos desvios ou sinal de interrupção ocorre saltos. de modo que não contém o mux OrigALU da Figura 4. Observe que essa é uma figura estilizada. Fazer um computador com facilidades automáticas de interrupção de programa se 4.9 Exceções 309 FIGURA 4. nor- malmente usando o nome mais antigo interrupção para se referirem aos dois tipos de exceção  Também chamada eventos.51. Eles foram criados inicial. mente para tratar de eventos inesperados de dentro do processador. 2. 1962 Muitas arquiteturas e autores não fazem distinção entre interrupções e exceções. 1. Um desvio tomado com frequência de 95%.57 e os controles multiplexadores da Figura 4. Seguimos a convenção do MIPS. Aqui estão alguns exemplos mostrando se a situação é gerada internamente pelo processador ou se é gerada externamente: interrupção  Uma exceção que vem de fora do processador. o Intel x86 usa interrupção. que mudam o fluxo normal da execução da instrução. 3. retornaremos a esse assunto no Capítulo 5. além da instrução que a causou. ou terminar a execução do programa e informar um erro.310 Capítulo 4  O Processador Tipo de evento De onde? Terminologia MIPS Solicitação de dispositivo de E/S Externa Interrupção Chamar o sistema operacional do programa Interna Exceção do usuário Overflow aritmético Interna Exceção Usar uma instrução indefinida Interna Exceção Defeitos do hardware Ambos Exceção ou interrupção Muitos dos requisitos para dar suporte a exceções vêm da situação específica que causa a ocorrência de uma exceção. o sistema operacional pode terminar o pro- grama ou pode continuar sua execução. veremos mais de perto a questão da retomada da execução. Por para onde o controle é transferido é exemplo. definir os dois endereços de vetor de exceção a seguir: Tipo de exceção Endereço do vetor de exceção (emhexa) Instrução indefinida 8000 0000hexa Overflow aritmético 8000 0180hexa O sistema operacional sabe o motivo para a exceção pelo endereço em que ela é iniciada. que determina o tempo de ciclo de clock e.$1 como exemplo de exceção nas próximas páginas. que pode ser fornecer algum serviço ao programa do usuário. quando discutirmos sobre E/S. e entendermos melhor a motivação para as capacidades adicionais no mecanismo de exceção. lidamos com a implementação de controle de modo a detectar dois tipos de exceções que surgem das partes do conjunto de instruções e da implementação que já discutimos. e o sistema operacional precisa registrar o motivo para a exceção e pode realizar algum processamento limitado nessa . No Capítulo 5. Detectar condições excepcionais e tomar a ação apropriada normalmente está no per- curso de temporização crítico de um processador. Em uma interrupção vetorizada. bem como complicar a tarefa de corrigir o projeto. Existem dois métodos principais usados para comunicar o motivo de uma exceção. para acomodar os dois tipos de exceção listados anteriormente.$2. Como as exceções são tratadas em uma arquitetura MIPS Os dois tipos de exceções que nossa implementação atual pode gerar são a execução de uma instrução indefinida e um overflow aritmético. O da arquitetura MIPS é incluir um registrador de status (chamado registrador Cause). Consequentemente. A ação básica que o processador deve realizar quando ocorre uma exceção é salvar o endereço da ins- trução causadora no PC de Exceção (Exception Program Counter – EPC) e depois transferir o controle para o sistema operacional em algum endereço especificado. quando tratarmos de hierarquias de memória. as tentativas de acrescentar exceções a uma implementação com- plicada podem reduzir o desempenho significativamente. O sistema operacional pode então tomar a ação apropriada. interrupção vetorizada Uma Um segundo método é usar interrupções vetorizadas. o desempenho. Sem a devida atenção às exceções durante o projeto da unidade de controle. usando o EPC para determinar onde reiniciar a execução do programa. ele precisa conhecer o motivo da exceção. portanto. e no Capítulo 6. Para o sistema operacional tratar da exceção. interrupção para a qual o endereço o endereço ao qual o controle é transferido é determinado pela causa da exceção. que mantém um campo que indica o motivo da exceção. Usaremos o overflow aritmético na instrução add $1. poderíamos determinado pela causa da exceção. tomar alguma ação predefinida em resposta a um overflow. Os endereços são separados por 32 bytes ou oito instruções. Depois de realizar qualquer ação necessária devido à exceção. Nesta seção. 9 Exceções 311 sequência. pois funcionará como registrador de destino da instrução add. que envia 8000 0180hexa ao PC. Para dar flush na instrução em EX. (Esse registrador é necessário mesmo quando as exceções são vetorizadas. Devido ao planejamento cuidadoso. Um novo sinal de controle. a exceção de overflow é detectada durante o estágio EX. usamos o multiplexador já presente no estágio ID que zera os sinais de controle para stalls. de modo que a rotina de tratamento da exceção primeiro deve subtrair 4 do valor salvo. . com 10 representando uma instrução in- definida e 12 representando o overflow aritmético.) j Cause: Um registrador usado para registrar a causa da exceção. vimos como dar flush na instrução no es- tágio IF. desta vez. Este exemplo aponta um problema com as exceções: se não pararmos a execução no meio da instrução. que é o local da exceção para o overflow aritmético. Suponha que haja um campo de cinco bits que codifica as duas fontes de informação possíveis mencionadas anteriormente. A Figura 4. Quando lidamos com um desvio mal previsto. um único ponto de entrada para todas as exceções pode ser utilizado. com o único ponto de entrada sendo o endereço 8000 0180hexa. o programador não poderá ver o valor original do registrador $1 que ajudou a causar o overflow.Flush. (A implementação de exceções vetorizadas não é mais difícil. usamos um novo sinal. chamado EX.Flush. realiza um OR com o sinal de stall da Unidade de Detecção de Hazards a fim de dar flush durante o ID. Muitas exceções exigem que. A Figura 4. salvamos o endereço + 4. Na arquitetura MIPS. Vamos supor que estejamos implementando o sistema de exceção utilizado na arquitetura MIPS. logo.) Precisaremos acrescentar dois registradores adicionais à implementação MIPS: j EPC: Um registrador de 32 bits usado para manter o endereço da instrução afetada. Quando a exceção não é vetorizada. 4. por fim. Usaremos o mesmo mecanismo que usamos para os desvios tomados. fazendo com que novos multiplexadores zerem as linhas de controle. com- pletemos a instrução que causou a exceção como se ela fosse executada normalmente. Para começar a buscar instruções do local 8000 0180hexa. simplesmente acrescentamos uma entrada adicional ao multiplexador do PC. esse registrador tem 32 bits.66 mostra essas mudanças. Para dar flush nas instruções no estágio ID. embora alguns bits atualmente não sejam utilizados. incluindo o hardware de desvio e as acomodações neces- sárias para tratar das exceções. Assim como fizemos para o desvio tomado na seção anterior.Flush para impedir que a instrução no estágio EX escreva seu resultado no estágio WB. podemos usar o sinal EX. chamado ID. A etapa final é salvar o endereço da instrução problemática no Exception Program Counter (EPC). e o sistema operacional decodifica o registrador de status para encontrar a causa.66 mostra uma versão es- tilizada do caminho de dados. transformando-a em um nop. a exceção causa a desativação das linhas de controle. mas. suponha que haja um overflow aritmético em uma instrução add. Exceções em uma implementação em pipeline Uma implementação em pipeline trata exceções como outra forma de hazard de controle. temos de dar flush nas instruções que vêm após a instrução add do pipeline e começar a buscar instruções do novo endereço. Na realidade. O modo mais fácil de fazer isso é dar flush na instrução e reiniciá-la desde o início após a exceção ser tratada. Podemos realizar o processamento exigido para exceções acrescentando alguns regis- tradores e sinais de controle extras à nossa implementação básica e estendendo o controle ligeiramente. Por exemplo. um registrador Cause para registrar a causa da exceção. e um registrador PC de Exceção (Ex- ception Program Counter – EPC) para salvar o endereço da instrução que causou a exceção. e a primeira ins- trução do código de exceção é buscada. FIGURA 4. O ciclo de clock 7 mostra que o add e as instruções seguintes sofrem flush. o sinal de overflow da ALU é uma entrada para a unidade de controle. no multiplexador que fornece o novo valor do PC. A entrada 8000 0180hexa para o multiplexador é o endereço inicial para começar a buscar instruções no caso de uma exceção.67 mostra os eventos. começando com a instrução add no estágio EX. A Figura 4. com o valor 8000 0180hexa. . Embora não apareça. Observe que o endereço da instrução seguinte ao add é salvo: 4Chexa + 4 = 50hexa. e 8000 0180hexa é forçado para o PC.312 Capítulo 4  O Processador Exceção em um computador com pipeline Dada esta sequência de instruções EXEMPLO considere que as instruções a serem invocadas em uma exceção comecem desta forma: Mostre o que acontece no pipeline se houver uma exceção de overflow na instrução add. Os principais acréscimos incluem uma nova entrada.66  O caminho de dados com controles para lidar com exceções. O RESPOSTA overflow é detectado durante essa fase. 9 Exceções 313 FIGURA 4. 4. O overflow faz com que todos os sinais Flush sejam ativados perto do final desse ciclo de clock. Observe que as instruções AND e OR. . Embora não apareça. O ciclo de clock 7 mostra as instruções convertidas para bolhas no pipeline mais a busca da primeira instrução da rotina de exceção – sw $25. que estão antes do add.1000($0) – a partir do local da instrução 8000 0180hexa. o sinal de overflow da ALU é uma entrada para a unidade de controle. ainda completam. desativando os valores de controle (colocando-os em 0) para o add. salvando o endereço após o add no registrador EPC (4C + 4 = 50hexa).67  O resultado de uma exceção devido a um overflow aritmético na instrução add. O overflow é detectado durante o estágio EX do clock 6. que veremos no Capítulo 5. Além do mais. uma instrução indefinida é descoberta no estágio ID. Por exemplo. depois que a exceção for detectada. Uma interrupção ou exceção que está Detalhamento:  Embora o MIPS utilize o endereço de entrada de exceção 8000 0180hexa para sempre associada à instrução quase todas as exceções. definir um registrador para mostrar a causa da exceção. Logo. Na maioria das implementações MIPS. MIPS e a grande maioria dos computadores de hoje admitem interrupções precisas ou exceções precisas. e a chamada ao sistema operacional ocorre no estágio EX. o sistema operacional salva o estado do pro- grama. Uma dica importante é saber em que estágio do pipeline um tipo de exceção pode ocorrer. Solicitações de dispositivos de E/S e defeitos do hardware não estão associados a uma instrução específica. pipeline. Para uma solicitação de dispositivo de E/S ou uma chamada de serviço ao sistema operacional. O contrato do sistema operacional é examinar a causa da exceção e atuar de forma apropriada. pois essa tare- fa em geral pode não ser capaz de prosseguir até que a E/S termine. restaura o programa para continuar a execução. salvar o endereço da instrução problemática e depois desviar para um endereço previamente arranjado. As exceções são coletadas no registrador Cause em um campo de exceção pendente. O EPC captura o endereço das instruções interrompidas. usar o mecanismo utilizado para outras exceções funciona muito bem. o Capítulo 5 descreve essas exceções e seu tratamento com mais detalhes. várias exceções podem ocorrer simul- taneamente em um único ciclo de clock. uma vez que a mais antiga tenha sido atendida. o hardware ordena as exceções de modo que a instrução mais antiga seja interrompida. deixar que todas as instruções anteriores software terminem. o PC normalmente teria 58hexa no início interrupções ou exceções nos do ciclo de clock. No caso das solicitações do dispositivo de E/S. Interface O hardware e o sistema operacional precisam trabalhar em conjunto para que as exceções se comportem conforme o esperado. em algum ponto no futuro. É por isso que é funda- mental a capacidade de salvar e restaurar o estado de qualquer tarefa.9. embora a instrução com problema es- computadores em pipeline não teja no endereço 4Chexa. e o registrador Cause do MIPS registra todas as exceções possíveis em um ciclo de clock. Um dos usos mais importantes e frequentes das exceções é o tratamento de faltas de página e exceções de TLB. ele usa o endereço 8000 0000hexa de modo a melhorar o desempenho correta nos computadores em do tratador de exceção para exceções de falta de TLB (veja Capítulo 5). normalmente podemos escolher executar outra tarefa antes de retomar a tarefa que requisitou a E/S. realiza a tarefa desejada e. O que foi a causa da interrupção ou exceção. o desafio é associar uma exceção à instrução apropriada. (Um motivo é para dar suporte à memória virtual.) interrupção precisa Também chamada exceção precisa. Um processador com exceções imprecisas poderia colocar 58hexa no estão associadas à instrução exata EPC e deixar que o sistema operacional determinasse qual instrução causou o problema. A solução é priorizar as exceções de modo que seja fácil determinar qual será atendida primeiro. Para uma instrução indefinida. As precisas ou exceções imprecisas. o sistema operacional normalmente encerra o programa e retorna um indicador do motivo. de modo que o hardware possa interromper com base em exceções posteriores. Detalhamento:  A dificuldade de sempre associar a exceção correta à instrução correta nos computadores em pipeline levou alguns projetistas de computador a relaxarem esse requisito interrupção imprecisa Também em casos não críticos. Com cinco instruções ativas em qualquer ciclo de clock. de modo que a implementação possui alguma flexibilidade quanto ao momento de interromper o pipeline. dar flush em todas as instruções seguintes.314 Capítulo 4  O Processador Mencionamos cinco exemplos de exceções na tabela da Seção 4. O contrato do hardware normalmente é interromper hardware/ a instrução problemática no meio do caminho. No exemplo anterior. de modo que o software de ex- ceção precisa combinar a exceção à instrução. Alguns processadores são considerados como tendo interrupções im- chamada exceção imprecisa. . falha de hardware ou exceção por overflow aritmético. e veremos outros nos Capítulos 5 e 6. despacho múltiplo  Um esquema dora e secadora doméstica por. um microproces- sador de despacho múltiplo quádruplo de 4 GHz pode executar uma velocidade de pico de 16 bilhões de instruções por segundo e ter um CPI de 0. Se você quiser saber mais detalhes. principalmente quando os valores se tornam menores do que 1! Logo. S1  # overflow aritmético você mesmo 2. O primeiro é aumentar a profundidade do pipeline para sobrepor mais instruções. .10   em nível de instrução Esteja avisado de que esta seção é uma breve introdução de assuntos fascinantes. dinâmico  Uma técnica para mico. A desvantagem é o trabalho extra de manter todas as máquinas ocu- padas e transferir as trouxas de roupa para o próximo estágio do pipeline. pois existem mais operações sendo sobrepostas. $1  # instrução indefinida 3. digamos. ou um IPC de 4. Considerando um pipeline de cinco estágios. pois o ciclo de clock pode ser encurtado. XXX $1. Poderíamos. enxáguam e centrifugam. ou instrução por ciclo de clock. Às vezes. decisões são tomadas durante a execução pelo processador. de paralelismo em nível de instrução. $2. precisamos rebalancear as etapas restantes de modo que tenham o mesmo tamanho. no qual o material explicado nas próximas páginas é expandido para mais de 200 páginas (incluindo Apêndices)! A técnica de pipelining explora o paralelismo em potencial entre as instruções. $1  # erro de hardware   P  aralelismo e paralelismo avançado 4. Arquitetura de Computadores: uma abordagem quantitativa. as despacho múltiplo técnicas às vezes são chamadas de despacho múltiplo estático e despacho múltiplo dinâ. Disparar várias instruções por estágio permite que a velocidade de execução da ins- trução exceda a velocidade de clock ou. Uma lavanderia com despacho múltiplo substituiria nossa lava. poderíamos dividir nossa lavadora em três máquinas que lavam. Para ganhar o máximo de velocidade. as duas técnicas possuem outros nomes. Existem dois métodos principais para aumentar a quantidade em potencial instrução  O paralelismo entre as instruções.10  Paralelismo e paralelismo avançado em nível de instrução 315 Qual exceção deverá ser reconhecida primeiro nesta sequência? Verifique 1. usados mais comumente. O nome geral para essa técni- ca é despacho múltiplo.25 no melhor dos casos. hardware. add $1. sub $1. processador de despacho múltiplo Existem duas maneiras importantes de implementar um processador de despacho em que muitas decisões são múltiplo. durante a compilação) ou dinamicamente (ou seja. Como a divisão do trabalho indica se as decisões estão sendo feitas estaticamen- te (ou seja. porém avançados. durante a execução). nos processadores ou na lavanderia. normalmente existem despacho múltiplo estático Uma muitas restrições sobre os tipos das instruções que podem ser executadas simultaneamente técnica para implementar um e o que acontece quando surgem dependências. de forma alternativa. três lavadoras e três secadoras. deverá consultar nosso livro mais avançado. passar de um pipeline de quatro para seis estágios. então. implementar um processador de despacho múltiplo em que muitas que podem ser menos precisos ou mais restritivos. $2. no mesmo período. é útil inverter a métrica e usar o IPC. O desempenho é potencialmente maior. Entretanto. Outra técnica é replicar os componentes internos do computador de modo que ele possa iniciar várias instruções em cada estágio do pipeline. Usando nossa analogia da lavanderia e considerando que o ciclo da lavadora fosse maior do que os outros. 4. $2. Você também pelo qual múltiplas instruções são teria de recrutar mais auxiliares para passar e guardar três vezes a quantidade de roupas disparadas em 1 ciclo de clock. esse processador teria 20 instruções em execução em determinado momento. Esse paralelismo é chamado de paralelismo em nível de instrução (ILP – Instruction-Level paralelismo em nível de Parallelism). A quantidade de paralelismo sendo explorada é maior. quarta edição. Como veremos. que o CPI seja menor do que 1. Os microprocessadores mais potentes de hoje tentam despachar de três a oito instruções a cada ciclo de clock. como as etapas de uma lavadora tra- dicional. com a principal diferença sendo a divisão de trabalho entre o compilador e o tomadas pelo compilador antes da execução. mas o endereço que usa não é válido quando a especulação for incorreta. Por exemplo. esse processo é tratado correspondem a posições nos pelo menos parcialmente pelo compilador. O problema é complicado pelo fato de que. Na especulação por hardware. o proces- sador normalmente coloca os resultados especulativos em um buffer até que saiba que não são mais especulativos. se a instrução load não fosse especulativa. o hardware faz um flush nos buffers e executa novamente. por analogia. A dificuldade com a especulação é que ela pode estar erra- da. de modo a permitir que a execução comece para outras adivinha o resultado de uma instrução para removê-la como instruções que possam depender da instrução especulada. Na especulação em hardware. algumas ou todas as consequências dos hazards de dados e controle são tratadas es- taticamente pelo compilador. Empacotar as instruções em slots de despacho: como o processador determina das quais as instruções poderiam quantas instruções e quais instruções podem ser despachadas em determinado ciclo ser despachadas em determinado ciclo de clock. na realidade. O resultado é que ocorrerá uma exceção que não deveria ter ocorrido. Os mecanismos de recuperação usados para a especulação incorreta são bem diferen- tes. Lidar com hazards de dados e de controle: em processadores de despacho estático. usando técnicas que discutiremos mais adiante nesta seção. pudessem ser executadas mais cedo. especulação  Uma técnica pela Especulação é uma técnica que permite que o compilador ou o processador “adivinhem” qual o compilador ou processador as propriedades de uma instrução. e nenhuma pode afirmar ser perfeitamente pura. de clock? Na maioria dos processadores de despacho estático. então. o que permitiria que o load fosse executado antes do store. a exceção deveria ocorrer! Na especulação feita pelo compilador. Por exemplo. suponha que uma instrução load seja movida de uma maneira especulativa. que permite que tais exceções sejam ignoradas até que esteja claro que elas realmente devam ocorrer. Por exemplo. A implementação dessa capacidade de retro- cesso aumenta a complexidade. mas na sequência de instruções correta. de modo que as instruções após o desvio outras instruções. nos projetos de despacho dinâmico. cada técnica pega algo emprestado da outra. qualquer mecanismo de especulação deve incluir tanto um método para veri- ficar se a escolha foi certa quanto um método para retornar ou retroceder os efeitos das instruções executadas de forma especulativa. fazendo uma instrução passar por um desvio ou um load passar por um store. poderíamos es- uma dependência na execução de pecular a respeito do resultado de um desvio. as instruções são concluídas. 2. Embora as tenhamos descrito como técnicas distintas. No caso da especulação em software. isso blocos iniciais para um sprint. as exceções são simplesmente mantidas em um buffer até . Outro exemplo é que poderíamos especular que um store que precede um load não se refere ao mesmo endereço. normalmente é tratado durante a execução pelo processador. O conceito de especulação Um dos métodos mais importantes para localizar e explorar mais ILP é a especulação. Se a especulação estiver incorreta. o com- pilador pode usar a especulação para reordenar as instruções. O hardware do processador pode realizar a mesma transformação durante a execução.316 Capítulo 4  O Processador Existem duas responsabilidades principais e distintas que precisam ser tratadas em um pipeline de despacho múltiplo: slots de despacho  As posições 1. permitindo que o conteúdo dos buffers seja escrito nos registradores ou na memória. embora o compilador em geral já tenha tentado ajudar a melhorar a velocidade do despacho colocando as instruções em uma ordem benéfica. A especulação apresenta outro problema possível: especular sobre certas instruções pode gerar exceções que anteriormente não estavam presentes. Se a especulação estiver correta. Ao contrário. A especulação pode ser feita pelo compilador ou pelo hardware. esses problemas são evitados pelo acréscimo de suporte especial à especulação. Assim. o compilador normalmente insere instruções adicionais que verificam a precisão da especulação e oferecem uma rotina de reparo para usar quando a especulação tiver sido incorreta. a maioria dos processadores de despacho dinâmico tenta aliviar pelo menos algumas classes de hazards usando técnicas de hardware operando durante a execução. possui algumas vantagens. se uma instrução do par não puder ser usada. Além do mais. A Figura 4. Embora isso não seja estritamente necessário.68 mostra como as instruções aparecem enquanto entram no pipeline em pares. estático normalmente restringe o mix de instruções que podem ser iniciadas em determinado pelo processador. o pacote pode ser determinado estaticamente. com a parte da ALU ou desvio aparecendo primeiro. O despacho de duas instruções por ciclo exigirá a busca e a decodificação de 64 bits de instruções. Logo. antes de descrevermos o uso dessas técnicas separados. possivelmente com um nop em um slot. Assim. exigimos que ela seja substituída por um nop. pelo ções. Essa visão levou ao nome original para essa VLIW (Very Long Instruction técnica: VLIW (Very Long Instruction Word – palavra de instrução muito longa). Despacho múltiplo estático Todos os processadores de despacho múltiplo estático utilizam o compilador para ajudar no empacotamento de instruções e no tratamento de hazards. ou dinamicamente. o layout do despacho de instruções simultâneas é restrito para sim- plificar a decodificação e o despacho da instrução. Como um processador de despacho múltiplo compilador. as instruções sempre são despachadas em pares. é útil pensar no pacote de despacho como uma única instrução.68  Pipeline com despacho estático de duas instruções em operação. normalmente de código. manter as escritas de registrador no final do pipeline simplifica o tratamento de exceções e a manutenção de um modelo de exceção preciso. consideramos um proces- sador MIPS simples capaz de despachar duas instruções por ciclo. As res. como uma grande instrução com várias opera. exigiremos que as instruções sejam emparelhadas e alinhadas em um limite de 64 bits. . 4. Aqui. ciclo de clock. Em particular. Esse projeto é como aquele utilizado em alguns processadores MIPS embutidos. nesse ponto. As instruções da ALU e de transferência de dados são despachadas ao mesmo tempo. o que é chamado pacote de despacho. para serem independentes em uma ponsabilidades do compilador podem incluir previsão estática de desvios e escalonamento única instrução larga. vamos examinar as técnicas estática e dinâmica para a especulação. consideramos a mesma estrutura de cinco estágios utilizada para o pipeline de despacho único. Em muitos processadores de despacho múltiplo. Um exemplo: despacho múltiplo estático com a ISA do MIPS Para que você tenha uma ideia do despacho múltiplo estático. em um ciclo de clock. você pode pensar no conjunto de instruções despachadas em determinado ciclo de de instruções despachadas juntas clock.10  Paralelismo e paralelismo avançado em nível de instrução 317 que fique claro que a instrução que as causa não é mais especulativa e está pronta para terminar. e basicamente em todos os processadores VLIW. sendo que uma das instruções pode ser uma operação da ALU com inteiros e a outra pode ser um load ou um store. FIGURA 4. Essa visão é mais do que uma analogia. Word)  Um estilo de arquitetura de conjunto de instruções que A maioria dos processadores de despacho estático também conta com o compilador dispara muitas operações definidas para assumir alguma responsabilidade por tratar de hazards de dados e controle. a exceção é gerada. Em um processador de despacho pacote de despacho  O conjunto estático. permitindo várias operações em certos campos predefinidos. nesta seção. Vejamos uma versão simples do com muitos campos de opcode despacho estático de um processador MIPS. que se torna mais difícil em processadores de despacho múltiplo. é preciso haver muito esforço na decisão de quando a especulação é apropriada. Mais adiante. Como a especulação pode melhorar o desempenho quando realizada corretamente e diminuir o desempenho quando feita descuidadamente. para reduzir ou impedir todos os hazards. em processadores mais agressivos. e prossegue o tratamento normal da exceção. e também uma porta de escrita para uma operação da ALU e uma porta de escrita para um load. Sem esses recursos extras. nosso pipeline com despacho duplo seria atrapalhado pelos hazards estruturais. Suponha que a ALU inferior trate dos cálculos de endereço para transferências de dados e a ALU superior trate de todo o restante.69  Um caminho de dados com despacho duplo estático. Em um ciclo de clock.69). e outra ALU. Se o software precisa lidar com todos os hazards ou apenas tentar reduzir a fração de hazards entre pacotes de despacho separados. Claramente. e essa sobreposição adicional aumenta a perda de desempenho relativa aos FIGURA 4. esse processador com despacho duplo pode melhorar o desempenho por um fator de até 2. Como a ALU está presa à operação da ALU. também precisamos de um somador separado a fim de calcular o endereço efetivo para as transferências de dados. o compilador tem res- ponsabilidade completa por remover todos os hazards. mais duas portas de leitura e mais uma porta de escrita no banco de registradores.. Para emitir uma operação da ALU e uma operação de transferência de dados em paralelo. Em alguns projetos. o hardware detecta os hazards de dados e gera stalls entre dois pacotes de despacho. Ainda assumiremos a segunda técnica para esse exemplo. enquanto exige que o compilador evite todas as dependências dentro de um par de instruções. a primeira necessidade para o hardware adicional – além da lógica normal de detecção de hazard e stall – são portas extras no banco de registradores (veja Figura 4. podemos ter de ler dois registradores para a operação da ALU e mais dois para um store. Os acréscimos necessários para o despacho duplo estão destacados: outros 32 bits da memória de instruções. . escalonando o código e inserindo no-ops de modo que o código execute sem qualquer necessidade de detecção de hazard ou stalls gerados pelo hardware. um hazard geralmente força o pacote de despacho inteiro contendo a instrução dependente a sofrer stall. Em outros.318 Capítulo 4  O Processador Os processadores de despacho múltiplo estático variam no modo como lidam com hazards de dados e controle em potencial. Entretanto. fazer isso exige que o dobro de instruções seja superposto na execução. Mesmo assim. a aparência de haver uma única grande instrução com várias operações é reforçada. o que impede que uma ins. Além do mais.70  O código escalonado conforme apareceria em um pipeline MIPS com despacho duplo. no cálculo do CPI ou do IPC. Para explorar com efi- ciência o paralelismo disponível em um processador com despacho múltiplo. Consi- dere que os desvios são previstos. as instruções da ALU que não tiveram latência de uso no pipeline simples de cinco estágios agora possuem uma latência de uso de uma instrução. RESPOSTA Observe que apenas um par de instruções possui os dois slots utilizados. latência de uso  Número de ciclos trução use o resultado sem sofrer stall.8 versus o melhor caso de 0. Isso melhoraria o CPI. é preciso utilizar técnicas mais ambiciosas de escalonamento de compilador ou hardware. No pipeline com despacho duplo e cinco estágios.0. Os slots vazios são nops. .10  Paralelismo e paralelismo avançado em nível de instrução 319 hazards de dados e controle. de clock entre uma instrução load e uma instrução que pode usar o resultado de uma instrução load não pode ser usado no próximo ciclo de clock. Por exemplo. As três primeiras instruções possuem dependências de dados. ou um IPC de 1. em nosso pipeline simples de cinco estágios. São neces- sários quatro clocks por iteração do loop. Isso o resultado do load sem stall do significa que as duas instruções seguintes não podem usar o resultado do load sem sofrer pipeline. 4.5. stall. Escalonamento de código simples para despacho múltiplo Como este loop seria escalonado em um pipeline com despacho duplo estático para o MIPS? EXEMPLO Reordene as instruções para evitar o máximo de stalls do pipeline possível. e o des- pacho múltiplo estático requer que o compilador assuma essa função.25 versus 2. Observe que. pois os resultados não podem ser usados no load ou store emparelhados. não contamos quaisquer nops executados como instruções úteis.70 mostra o melhor escalonamento para essas instruções. de modo que os hazards de controle sejam tratados pelo hardware. obtemos o CPI decepcionante de 0. bem como as duas últimas. os loads possuem uma latência de uso de um ciclo de clock. em quatro clocks para executar cinco instruções. mas não o desempenho! FIGURA 4. A Figura 4. o loop terá quatro cópias de lw. suponha que o índice do loop seja um múltiplo de quatro.71 mostra o código desdobrado e escalonado. O custo dessa melhoria de desempenho é usar quatro registradores temporários em vez de um. parcialmente pela redução das instruções de controle de loop e parcialmente pela execução do despacho dual.$t0. o que gera um CPI de 8/14 = 0. O processo de renomeação elimina as dependências de que transporta um valor entre duas nome.4($s1). em que são feitas várias cópias do corpo do unrolling)  Uma técnica para loop. Considere como o código não desdobrado apareceria usando apenas $t0. addu $t0. chamado renomeação de regis- restante dos registradores é usado. enquanto preserva as verdadeiras dependências. apesar do uso de $t0. pela reutilização de um nome. além de um aumento significativo no tamanho do código. haverá mais ILP disponível pela sobreposição de instruções conseguir mais desempenho dos de diferentes iterações. Os slots vazios são nops.320 Capítulo 4  O Processador Uma técnica de compilador importante para conseguir mais desempenho dos loops é desdobramento de loop (loop o desdobramento de loop (loop unrolling).71  O código desdobrado e escalonado da Figura 4. mas essas sequências. em o compilador mova subsequentemente essas instruções independentes de modo a vez de uma dependência verdadeira escalonar melhor o código. É isso que é chamado de antide- antidependência Também pendência ou dependência de nome. que é uma ordenação forçada puramente pela chamada dependência de nome. para mas que poderiam levar a hazards em potencial ou impedir que o compilador es- remover antidependências. add e sw. Uma ordenação forçada reutilização de um nome. Para escalonar o loop sem quaisquer atrasos. O desdobramento e o escalonamento do loop com despacho dual nos deram um fator de melhoria de dois. FIGURA 4. calonasse o código de forma flexível. Como a primeira instrução no loop decrementa $s1 em 16. São necessários oito clocks para quatro iterações do loop. Durante o processo de desdobramento. Desdobramento de loop para pipelines com despacho múltiplo Veja como o trabalho de desdobramento do loop e escalonamento funciona no EXEMPLO exemplo anterior. em que são feitas várias cópias do corpo do loop e instruções de diferentes iterações são escalonadas juntas. A Figura 4.$s2 seguidas por sw t0. depois esse endereço menos 4. em vez de uma dependência de dados real. os endereços lidos são o valor original de $s1. mais um addi e um bne. instruções. na realidade são completamente independentes – nenhum valor de dados flui entre um par dessas instruções e o par seguinte. acontece que precisamos fazer quatro RESPOSTA cópias do corpo do loop. Haveria instâncias repetidas de lw $t0. loops que acessam arrays. Após o desdobramento. Depois de desdobrar e eliminar as instruções de overhead de loop desnecessárias. pelo compilador ou hardware.57. o compilador introduziu registradores renomeação de registradores O adicionais ($t1.0($s1). Observe agora que 12 das 14 instruções no loop são executadas como um par. menos 8 e menos 12. O objetivo desse processo. Para simplificar.$t2. . tradores. é eliminar dependências que não são dependências de dados verdadeiras. Renomear os registradores durante o processo de desdobramento permite que normalmente um registrador.70 conforme apareceria no pipeline MIPS com despacho duplo estático.$t3). ou dois clocks por iteração. existe uma diferença importante entre essa arquitetura superescalar simples e um processador VLIW: o código. (O Capítulo 5 explica as caches. e a recompilação foi necessária quando da mu- dança por diferentes modelos de processador. o código compilado sempre será executado corretamente. na memória. mais ou menos da mesma maneira como a lógica de forwarding faz em um pipeline es- calonado estaticamente. em outros processadores de despacho es- tático. programador. decodifica-as e envia cada instrução a uma unidade funcional correspondente para execução. discutiremos uma alternativa às dentro de uma unidade funcional estações de reserva utilizadas por muitos processadores recentes. Muitas arquiteturas superescalares estendem a estrutura básica das decisões de des- pacho dinâmico para incluir escalonamento dinâmico em pipeline. que estação de reserva  Um buffer mantêm os operandos e a operação. com isso. in- dependente da velocidade de despacho ou estrutura do pipeline do processador. também é usado para fornecer operandos. Quando o resultado for completado. Cada unidade funcional possui buffers. tente escalonar instruções para separar as dependências e. Mesmo com esse escalonamento de compilador. todos os seus operandos e a unidade funcional estiver pronta para executar. ele pode ser apanhado diretamente de lá. isso não tem acontecido. A combinação de operandos em buffers nas estações de reserva e os resultados no buffer de reordenação oferecem uma forma de renomeação de registradores. enquanto tenta evitar hazards e stalls. Considere a seguinte sequência de código: Embora a instrução sub esteja pronta para executar. 4. assim como . ela precisa esperar que lw e addu terminem primeiro. é garantido pelo hardware que será executado cor- retamente. melhorar a velocida- de de despacho de instruções.10  Paralelismo e paralelismo avançado em nível de instrução 321 Processadores com despacho múltiplo dinâmico Os processadores de despacho múltiplo dinâmico também são conhecidos como proces- sadores superescalares. O escalonamento escalonamento dinâmico em dinâmico em pipeline escolhe quais instruções serão executadas em determinado ciclo de pipeline  Suporte do hardware para clock. seguro armazenar os resultados na memória ou em um registrador. A Figura 4. seja ele escalonado ou não. Além do mais. o resultado será calculado. como em um pipeline normal. A primeira unidade busca ins. (Na próxima seção. as instruções são despachadas em ordem. Vamos começar com um exemplo simples de modificar a ordem de execução das instruções de modo a evitar stalls. Em alguns projetos VLIW. mas cons- tantemente de uma forma tão pouco eficiente que torna a compilação necessária.72 mostra o modelo. para um store. Nos processadores superescala. truções. impedimento de um hazard de dados. normal. superescalar  Uma técnica de res mais simples. pipelining avançada que permite que o processador execute mais de uma ou mais instruções podem ser despachadas em determinado ciclo de clock. possivelmente reordenando-as para evitar stalls.) Assim que o buffer tiver que mantém os operandos e a operação. e o processador decide se zero. dinamicamente até que seja mente chamado de buffer de reordenação. buffer que mantém resultados que mantém o resultado em um buffer até que seja seguro colocar o resultado no banco em um processador escalonado de registradores ou. Quando um resultado é submetido ao banco de registradores. O buffer na unidade de commit. decide quando é seguro liberar o várias unidades funcionais (uma dezena ou mais nos projetos de alto nível em 2008) e resultado de uma operação aos registradores e memória visíveis ao uma unidade de commit. motivo pelo qual os acessos à memória às vezes são muito lentos. o código seria executado corretamente em diversas implementações. ele será enviado a quaisquer estações buffer de reordenação O de reserva esperando por esse resultado em particular. conseguir um bom desempenho em tal processador ainda exige que o compilador selecionando-as durante a execução. chamados estações de reserva. o pipeline dinâmica ou fora de ordem que é dividido em três unidades principais: uma unidade de busca e despacho de instruções. Escalonamento dinâmico em pipeline unidade de commit  A unidade O escalonamento dinâmico em pipeline escolhe quais instruções serão executadas em em um pipeline de execução seguida. Nesses processadores. o que poderia exigir muitos ciclos de clock se a memória for lenta. bem como a unidade de commit.) O escalonamento dinâmico em pipeline permite que tais hazards sejam evitados total ou parcialmente. ou simplesmente superescalares. Obvia- uma instrução por ciclo de clock mente. o computador poderá apontar para a última instrução executada. Se um operando não estiver no banco de registradores ou no buffer de reordenação. Hoje. 2. Apesar de o front end (busca e despacho) e o back end (commit) do são buscadas. Conceitualmente. pipeline simples em ordem.72  As três unidades principais de um pipeline escalonado dinamicamente. a partir da unidade funcional. quando uma instrução com Para fazer com que os programas se comportem como se estivessem executando em um execução bloqueada não faz com que as instruções seguintes esperem. O nome da unidade funcional que produzirá o resultado é acompanhado. O processador execu- ta as instruções em alguma ordem que preserva a ordem do fluxo de dados do programa. o que permite que as dependências sejam acompanhadas. a cópia do registrador operando não é mais necessária. ele terá de estar esperando para ser produzido por uma unidade funcional. em que os resultados da execução se houver uma exceção. Para a instrução despachada. onde será colocado em um buffer até que todos os operandos e a unidade de execução estejam disponíveis. ele será copiado para a estação de reserva imediatamente. todos os pipelines es- calonados dinamicamente utilizam o commit em ordem. pois as instruções podem situação na execução em pipeline ser executadas em uma ordem diferente daquela em que foram apanhadas. . que estava aguardando. e a unidade de commit precisa escrever resultados nos registradores e na memória na ordem commit em ordem  Um commit de execução do programa. A etapa final da atualização do estado também é chamada de reforma ou graduação. Quando essa unidade por fim produz o resultado. pipeline executarem em ordem. ele é copiado diretamente para a estação de reserva. Essas etapas efetivamente utilizam o buffer de reordenação e as estações de reserva para implementar a renomeação de registradores. aquela utilizada pelo compilador em nosso exemplo anterior de desdobramento de loop. você pode pensar em um pipeline escalonado de forma dinâmica como uma análise da estrutura de fluxo de dados de um programa. se um de seus operandos estiver no banco de registradores ou no buffer de reordenação. a unidade de busca e decodificação de instruções precisa des- pachar instruções em ordem. execução fora de ordem Uma Esse estilo de execução é chamado de execução fora de ordem. Quando uma instrução é despachada. Para ver como isso funciona conceitualmente. e em pipeline sejam escritos no os únicos registradores atualizados serão aqueles escritos pelas instruções antes da instrução estado visível ao programador na mesma ordem em que as instruções que causa a exceção. anteriormente neste capítulo. Esse modo conservador é chamado de commit em ordem. e se houvesse uma escrita nesse regis- trador. o valor poderia ser reescrito. as unidades funcionais são livres para iniciar a execução sempre que os dados de que precisam estiverem disponíveis. considere as seguintes etapas: 1. sem passar pelos registradores. Logo.322 Capítulo 4  O Processador FIGURA 4. perspectiva de do compilador de encontrar e reduzir os efeitos de tais dependências. No entanto. o escalonamento dinâmico é estendido pela inclusão da especulação baseada em hardware. Prevendo a direção de um desvio. pode aumentar a quantidade de ILP que pode ser explorada. as falhas de cache (veja Capítulo 5) causam stalls imprevisíveis. escalonado dinamicamente. Um pi- peline especulativo.10  Paralelismo e paralelismo avançado em nível de instrução 323 Em geral. Como as instruções possuem um commit em ordem. como a latência do pipeline e a largura do despacho mudam de uma im- plementação para outra. Por exemplo. realizada pelo compilador ou pelo hardware. a forma de escalonar uma sequência de instruções dependentes é afetada tanto pela largura quanto pela latência do despacho. Terceiro. um processador escalonado dinamicamente pode continuar a buscar e executar instruções ao longo do caminho previsto. 4. A estrutura do pipeline afeta o número de vezes que um loop precisa ser desdobrado para evitar stalls e também o processo de renomeação de registradores feito pelo compilador. A especulação. pois o processador às vezes precisa esperar que uma dependência seja resolvida. o código antigo legado receberá grande parte do benefício de uma nova implementação sem a necessidade de recompilação. nem todos os stalls são o desempenho previsíveis. Na próxima seção. pois isso depende do comportamento previsto e real dos desvios. permitindo uma reordenação load-store e usando a unidade de commit para evitar a especulação incorreta. especialmente para resultados de desvios. as dependências de dados e controle nos programas oferecem um limite superior sobre o desempenho sustentado. enquan- to as técnicas centradas no hardware contam com extensões para o pipeline e mecanismos de despacho. As Colocando em técnicas centradas no software para a exploração do ILP contam com a capacida. você poderia perguntar por que um processador superescalar usaria o escalo- namento dinâmico. De modo semelhante. Em particular. Existem três motivos principais. A incorporação da es- peculação dinâmica para explorar mais ILP sem incorporar o escalonamento dinâmico restringiria significativamente os benefícios de tal especulação. embora se deva ter cuidado. Segundo. O escalonamento dinâmico permite que o hardware oculte a maioria desses detalhes. veremos o uso do escalonamento dinâmico com especulação no projeto do AMD Opteron X4 (Barcelona). ele não pode saber a ordem exata das instruções durante a compilação. . se o processador especula sobre resultados de desvio usando a previsão de desvio dinâmica. Primeiro. os usuários e os distribuidores de software não precisam se preocupar em ter várias versões de um programa para diferentes implementações do mesmo conjunto de instruções. Tanto a técnica de pipelining quanto a execução com despacho múltiplo aumen- tam a vazão máxima de instruções e a tentativa de explorar o paralelismo em nível de instrução (ILP). Dado que os compiladores também podem escalonar o código em torno das dependências Entendendo de dados. a melhor maneira de compilar uma sequência de código também muda. dos programas O escalonamento dinâmico permite que o processador oculte alguns desses stalls conti- nuando a executar instruções enquanto esperam que o stall termine. visto que a especulação incorreta provavelmente reduzirá o desempenho. sa- bemos se o desvio foi previsto corretamente ou não antes que quaisquer instruções do caminho previsto tenham seus resultados atualizados pelas unidades de commit. também pode admitir especulação nos endereços de load. Assim. são capazes de despachar várias instruções por clock. . o ILP adicional está dis- ponível. Alguns stalls do sistema de memória podem ser escondidos. os principais gargalos no desempenho surgem das dependências que não podem ser aliviadas. é muito difícil sustentar essa taxa de despacho. A Figura 4. software muito poucas aplicações podem sustentar mais do que duas instruções por clock. normalmente em uma estrutura chamada buffer de reordenação. o código que utiliza ponteiros. Agora que atingimos o muro da potência. seja em um buffer de store (veja Capítulo 5) ou no buffer de reordenação. dentro do pipeline. Em segundo lugar. e quando o store não for mais dependente de desvios previstos. Detalhamento:  Uma unidade de commit controla atualizações no banco de registradores e na memória. normalmente o compilador ou o hardware não sabe exatamente se uma dependência existe ou não e. Primeiro.73 mostra o número de estágios de pipeline. estamos vendo projetos com múltiplos processadores por chip em que os processadores não são tão profundamente dispostos em pipeline ou tão agressivamente especulativos quanto seus predecessores. as perdas no sistema da memória (o tópico do Capítulo 5) também limitam a capacidade de manter o pipeline cheio. Eficiência de potência e pipelining avançado A desvantagem do aumento da exploração do paralelismo em nível de instrução por meio do despacho múltiplo dinâmico e especulação é a eficiência de potência. embora os processadores mais simples não sejam tão rápidos quanto seus irmãos sofisticados. e a atualização real no banco de registradores ocorre depois. Outros processadores mantêm o resultado em buffer. Observe a queda nos estágios de pipeline e potência enquanto as empresas passam para projetos multicore. Embora pouca coisa possa ser feita sobre as verdadeiras dependências dos dados. A unidade de commit permite que o store escreva na memória a partir do buffer quando o buffer tiver um endereço e dados válidos.324 Capítulo 4  O Processador Interface Processadores modernos. reduzindo assim o paralelismo entre as ins- truções e a velocidade de despacho sustentada. A crença é que. mas geralmente eles faziam isso de modo muito ineficaz. Ao contrário. nível de especulação. Alguns processadores escalonados dinamicamente atualizam o banco de regis- tradores imediatamente durante a execução. largura do despacho. taxa de clock. seja em tempo de execução ou de compilação. usando registradores extras para implementar a função de renomeação e preservar a cópia mais antiga de um registrador até que a instrução atualizando o registrador não seja mais especulativa. por isso. cores por chip e potência de vários microprocessadores do pas- sado e recentes. Por exemplo. hardware/ apesar da existência de processadores com despacho de quatro a seis instruções por clock. a maior regularidade dos acessos a um array normalmente per- mite que um compilador deduza que não existem dependências. Stores na memória precisam ser colocados em buffer até o momento do commit. limitarão a capacidade de explorar o ILP. principalmente os que criam mais aliasing. infelizmente. mas quantidades limitadas de ILP também limitam a extensão à qual esses stalls podem ser escondidos. como parte do commit. eles oferecem melhor desempenho por watt. os desvios que não podem ser previstos com precisão. Cada inovação foi capaz de transformar mais transistores em desempenho. Em geral. Por exemplo. Existem dois motivos principais para isso. precisa considerar de forma conservadora que a dependência existe. de modo que podem oferecer mais desempenho por chip quando os projetos são restritos mais por potência do que por número de transistores. de alto desempenho. levará a dependências em potencial mais implícitas. De modo semelhante. mas a capacidade de o compilador ou o hardware encontrar ILP que possa estar bastante separado (às vezes pela execução de milhares de instruções) é limitada. Tanto AMD quanto Intel buscam as instruções x86 e as traduzem internamente para instruções tipo MIPS. Escalonamento dinâmico 6. Especulação 8. a você mesmo resposta pode ser “ambos”. Esses processadores. 1. Previsão de desvio 2. Despacho múltiplo 3. 4. Detalhamento:  Os acessos à memória se beneficiam das caches sem bloqueio. que con- tinuam a atender acessos da cache durante uma falta de cache (veja Capítulo 5). Esta seção focaliza o pipeline da operação RISC. porém. Renomeação de registradores Vida real: o pipeline do AMD Opteron X4 4. Os proces- sadores com execução fora de ordem precisam do projeto de cache para permitir que as ins- truções sejam executadas durante uma falha.73  Registro dos microprocessadores Intel e Sun em termos de complexidade de pipeline. . Indique se as técnicas ou componentes a seguir estão associados principalmente a uma Verifique técnica baseada em software ou hardware para a exploração do ILP. descrito no Capítulo 2. que o AMD chama de operações RISC (Rops) e a Intel chama de micro-operações.11  Vida real: o pipeline do AMD Opteron X4 (Barcelona) 325 FIGURA 4. Se os incluíssemos. capaz de sustentar uma taxa de execução de três operações RISC por ciclo de clock no AMD Opteron X4 (Barcelona). VLIW 4. Buffer de reordenação 9. As operações RISC são então executadas por um pipeline especulativo sofisticado. número de cores e potência. escalonado dinamicamente. os microprocessadores X86 em- pregam técnicas de pipelining sofisticadas. os pipelines do Pentium 4 seriam ainda mais profundos. Execução fora de ordem 7. ainda encaram o desafio de implementar o complexo conjunto de instruções x86. Superescalar 5. Em alguns casos.11     (Barcelona) Assim como a maioria dos computadores modernos. Os estágios de pipeline do Pentium 4 não incluem os estágios de commit. 36 operações de ponto flutuante/SSE e 44 loads e stores. A Figura 4. na realidade. Outra maneira de examinar o X4 é ver os estágios do pipeline pelos quais uma ins- trução típica passa. o bypass é feito marcando resultados e rastreando os operandos origem. dificultando a separação entre o caminho de dados e o pipeline. a cache e o banco de registradores. interconexão e controle. focalizando as estruturas principais unidades funcionais. registradores físicos (72 no X4). As extensas filas permitem que até 106 operações RISC estejam pendentes. como o pipeline é dinâmico. estes são os 32 registradores inteiros e 16 de processador (16 no caso da versão de 64 bits da arquitetura x86) para um conjunto maior de ponto flutuante. muitos engenheiros e pesquisadores microarquitetura  A organização adotaram o termo microarquitetura para se referirem à arquitetura interna detalhada de do processador. o despacho de instruções e o controle geral do pipeline se misturam. registradores da arquitetura Os Detalhamento:  o Opteron X4 usa um esquema para resolver antidependências e especula- registradores visíveis do conjunto ção incorreta.74  A microarquitetura do AMD Opteron X4. escalonados dinamica- mente. e não estático. Existe uma extensa rede entre as unidades funcionais para efetuar bypass. o projeto de unidades funcionais. com a primeira parte tratando do cálculo do endereço nas unidades da ALU para inteiros e a segunda parte responsável pela referência real à memória.75 mostra a estrutura do pipeline e o número típico de ciclos de clock gastos em cada estágio. o número de ciclos de clock varia devido à natureza do escalonamento dinâmico e também aos requisitos das operações RISC individuais. incluindo 24 operações de inteiros. A renomeação de registradores redefine explicitamente os registradores da arquitetura de um por exemplo. As unidades load e store.74 mostra a microarquitetura do X4. que utiliza um buffer de reordenação junto com a renomeação de registradores. Por causa disso. são separadas em duas partes. naturalmente.326 Capítulo 4  O Processador Quando consideramos o projeto de processadores sofisticados. de modo a permitir uma combinação quando um resultado é produzido para uma instrução que está em uma das filas e que precisa do resultado. O Opteron X4 utiliza a renomeação de registradores para FIGURA 4. A Figura 4. incluindo as um processador. . de instruções de um processador. sua para execução das operações RISC. no MIPS. O Opteron X4 combina um pipeline de 12 estágios e despacho múltiplo agressivo para Entendendo conseguir alto desempenho. j Dependências longas – normalmente causadas por instruções duradouras ou falhas de cache de dados. Isso fará com que o estado do proces- sador retorne à última instrução executada corretamente. . indicando qual regis- trador físico é a cópia mais atualizada de um registrador da arquitetura. fazendo com que o processador sofra stall. Também aparecem os principais buffers em que as operações RISC esperam. 4. o impacto das dependências de dados é reduzido. causando stalls. Mantendo baixas as latências para operações back-to-back.11  Vida real: o pipeline do AMD Opteron X4 (Barcelona) 327 FIGURA 4. j Desvios que são difíceis de se prever. com os três últimos podendo se aplicar de alguma forma a qualquer processador com pipeline de alto desempenho. j O uso de instruções x86 que não são mapeadas para algumas operações RISC simples. A fila de execução de ponto flutuante tem 17 estágios de extensão. As afirmações a seguir são verdadeiras ou falsas? Verifique 1. 4. O Opteron X4 utiliza o escalonamento dinâmico. Quais são os gargalos de desempenho o desempenho em potencial mais sérios para os programas executados nesse processador? A lista a seguir dos programas inclui alguns problemas de desempenho em potencial.75  O pipeline do Opteron X4 mostrando o fluxo do pipeline para uma instrução típica e o número de ciclos de clock para as principais etapas no pipeline de 12 estágios para operações RISC com inteiros. Registrando as reno- meações que ocorreram. mantendo o mapeamento correto entre os registradores da arquitetura e os registradores físicos. O pipeline de despacho múltiplo do Opteron X4 executa instruções x86 diretamente. O X4 usa menos da metade dos estágios de pipeline do Pentium 4 Prescott anterior (veja Figura 4. você mesmo 2. mas não a especulação.73). 3. causando stalls e reinícios mal previstos quando a especulação falha. j Atrasos de desempenho que surgem no acesso à memória (veja Capítulo 5). A renomeação de registradores exige que o processador mantenha um mapa entre os registradores da arquitetura e os registradores físicos. remover antidependências. A microarquitetura do Opteron X4 possui muito mais registradores do que o x86 requer. a renomeação de registradores oferece outra técnica para a recupe- ração no caso de especulação incorreta: basta desfazer os mapeamentos que ocorreram desde a primeira instrução especulada incorretamente. pode ser usada para descrever o controle do MIPS tanto comportamentalmente quanto em uma forma adequada para a síntese de hardware.328 Capítulo 4  O Processador T ópico avançado: uma introdução ao projeto 4. e os acréscimos ao modelo destacam as mudanças para encaminhamento. Muitas das dificuldades em pipelining surgem por causa das complicações do conjunto de instruções. Hoje. O bug só foi des- coberto quando alguém tentou montar um computador com aquele livro. Livros inteiros foram escritos sobre tais linguagens e seu uso no projeto digital. O modelo inicial ignora hazards. ele oferece uma série de modelos comportamentais em Verilog do pipeline de cinco es- tágios do MIPS. Com pipelines maiores. Nossos livros comprovam a sutileza da execução correta de um pipeline. hazard de dados e hazards de desvio. Armadilha: a falha em considerar o projeto do conjunto de instruções pode afetar o pipeline de forma adversa. no nível do conjunto de instruções. a lógica se tornava muito mais rápida do que a memória. à medida que a quantidade de transistores continuava a dobrar. a preocupação com a potência está levando a projetos menos agressivos. O fato de que o Verilog para descrever um pipeline como esse do Opteron X4 terá milhares de linhas é uma indicação da complexidade.12     digital usando uma linguagem de projeto de hardware para descrever e modelar um pipeline e mais ilustrações de pipelining O projeto digital moderno é feito por meio de linguagens de descrição de hardware e modernas ferramentas de síntese auxiliadas por computador. agora isso é redundante. que aparece no site. o escalonamento dinâmico em pipeline exigia muitos recursos e não era necessário para o alto ­desempenho. usando . oferecemos cerca de doze ilustrações usando a representação de pipeline gráfico com ciclo único para os leitores que quiserem ver mais detalhes sobre como os pipelines funcionam para algumas sequências de instruções MIPS. então as múltiplas unidades funcionais e os pipelines dinâmicos fizeram mais sentido. Esta seção. No início da década de 1990. no final da década de 1980. inicialmente no DEC VAX 8500. Depois. oferece uma breve introdução e mostra como uma linguagem de projeto de hardware. apesar de ter sido revisado por mais de 100 pessoas e testado nas salas de aula de 18 universidades. usando bibliotecas e síntese lógica. Quando o número de transistores no chip e a velocidade dos transistores tornaram um pipeline de cinco estágios a melhor solução. Verilog neste caso. Depois. Aqui estão alguns exemplos: j Tamanhos de instrução e tempos de execução muito variáveis podem causar dese- quilíbrio entre estágios do pipeline e complicar bastante a detecção de hazards em um projeto com pipeline. que podem criar projetos de hardware detalhados a partir de descrições. 4. mas. então o delayed branch (veja o primeiro “Detalhamento” da Seção “Previsão dinâmica de desvios”) foi uma solução simples para controlar os hazards. Esteja atento! Falácia: as ideias de pipelining podem ser implementadas independentes da tecnologia.13  Falácias e armadilhas Falácia: pipelining é fácil. a execução superescalar e a previsão dinâ- mica de desvios. Nosso livro avançado tinha um bug no pipeline em sua primeira edição. Esse problema foi contornado. A técnica de pipelining melhora a vazão.14  Comentários finais 329 o esquema de micropipeline que o Opteron X4 emprega hoje. a lei de Amdahl sugere que outra parte do sistema se torne o gargalo. Em uma tecnologia comparável. esses microprocessadores preservaram o modelo de programação sequencial. O pipelining foi apresentado como reduzindo o tempo de ciclo de clock do caminho de dados de ciclo único simples. mas por fim se chocaram com o muro da potência. j Modos de endereçamento sofisticados podem levar a diferentes tipos de problemas. que podem se tornar hazards. Noventa por cento da sabedoria consiste em ser 4. o overhead da tradução e a manutenção da correspondência entre as micro-operações e as instruções permanecem. Provérbio americano Como vimos neste capítulo. que exploram o paralelismo em níveis menos minuciosos (o as- sunto do Capítulo 7). Como dissemos no Capítulo 1. o VAX na média executa 2. Para sustentar os avanços no desempenho de processamento por meio de processadores paralelos. mas com um aumento na latência efetiva. Na Seção 4. ditando quais componentes podem ser usados no caminho de dados. O despacho de instrução múltiplo acrescenta um de execução inerente para uma instrução. A presença de dependências de dados e o controle. 4. para algumas instruções. vimos como o cami- nho de dados para um processador MIPS poderia ser construído com base na arquitetura e na decisão de criar uma implementação de ciclo único. O despacho múltiplo de instruções. resultando em uma simplificação dos pipelines em versões mais recentes das microarquiteturas. latência de instrução  O tempo em duração. Em outro exemplo. ambos no hardware e no software. focaliza claramente a redução dos ciclos de clock por instrução (CPI). Essa tendência também fez com que os projetistas reavaliassem as implicações de desempenho de potência de algumas invenções desde meados da década de 1990. de modo que o MIPS é mais rápido. Outros modos de endereçamento que exigem múltiplos acessos à memória complicam bastante o controle do pipeline e tornam difícil manter o pipeline fluindo tranquilamente. .3. Bhandarkar e Clark [1991] compararam o MIPS M/2000 e o DEC VAX 8700 contando os ciclos de clock dos benchmarks SPEC. e também se uma implementação de ciclo único sequer faz sentido. Esse gargalo é o assunto do próximo capítulo: o sistema de memória. a latência é semelhante. a tecnologia básica também afeta muitas decisões de projeto. Assim. hardware adicional ao caminho de dados para permitir que várias instruções sejam ini- ciadas a cada ciclo de clock. Os modos de endereçamento que atualizam registradores complicam a detecção de hazards. mas não o tempo de execução inerente (ou latência de instrução) das instruções. são as principais técnicas utilizadas para reduzir o impacto das dependências sobre o desempenho. A passagem para pipelines maiores. Naturalmente. em comparação. à técnica de ciclo único. embora o MIPS M/2000 execute mais instruções. despacho de instruções múltiplas e escalonamento dinâmico em meados da década de 1990 ajudou a sustentar os 60% de aumento anual de desempenho dos processadores que começou no início da década de 1980.7 vezes mais ciclos de clock.14  Comentários finais   sensato no tempo. tanto o caminho de dados quanto o controle para um proces- sador podem ser projetados começando com a arquitetura do conjunto de instruções e um conhecimento das características básicas da tecnologia. são as principais limitações para a exploração do paralelismo. Escalonamento e especulação. eles concluíram que. o conjunto de instruções mais recente do Alpha permitiu uma implementação cujo desempenho tem mais do que o dobro da velocidade do NVAX. a indústria foi forçada a testar multiprocessadores. Talvez o melhor exemplo seja o DEC Alpha e o DEC NVAX. A técnica de pipelining e o despacho múltiplo tentam explorar o paralelismo em nível de instrução. Naturalmente. Para os três problemas restantes neste exercício.1.1> Qual é o caminho crítico para uma instrução AND do MIPS? 4.2 para essa instrução? 4.1.3 [10] <4. além de desenvolvimentos importantes na tecnologia de compiladores que acompanha tudo isso. AND Rd.1. Os três problemas seguintes neste exercício referem-se à seguinte instrução: Instrução Interpretação a.1> Quais recursos (blocos) realizam uma função útil para essa instrução? 4. SW Rt. mas suas saídas não são usadas para essa instrução? Quais recursos não produzem saídas para ela? Diferentes unidades de execução e blocos de lógica digital possuem diferentes latências (tempo necessário para realizar seu trabalho). do custo e da complexidade que tal acréscimo introduz no caminho de dados e controle do processador. os superescalares mais antigos e o desenvolvimento de técnicas para execuções fora de or- dem e especulativas.2 [5] <4. Novas instruções podem ser acrescentadas a uma ISA existente. discute a história dos primeiros processadores em pipeline. que aparece no site. mas a decisão de fazer isso ou não depende.1 Diferentes instruções utilizam diferentes blocos de hardware na implementação básica de ciclo único.6 [10] <4.Rt Reg[Rd]=Reg[Rs] AND Reg[Rt] b.330 Capítulo 4  O Processador 4.1> Qual é o caminho crítico para uma instrução LD (load) do MIPS? 4.4 [5] <4. As latências dos blocos. 750ps 200ps 50ps 250ps 300ps 500ps 300ps 4. juntamente com o caminho crítico (latência mais longa) para uma instrução determinam a latência mínima dessa instrução. da Georgia Tech .1.1> Quais recursos (blocos) produzem saídas.Rs.16   Exercícios1 Exercício 4.2 só pode implementar algumas instruções.5 [5] <4.2 existem sete tipos de blocos principais.2 A implementação básica de ciclo único do MIPS na Figura 4. Na Figura 4. considere as seguintes latências de recurso: I-Mem Add Mux ALU Regs D-Mem Controle a.1. entre outras coisas.1> Qual é o caminho crítico para uma instrução BEQ do MIPS? Exercício 4. Os três primeiros problemas neste exercício referem-se a esta nova instrução: 1 Contribuição de Milos Prvulovic.1 [5] <4.Offs(Rs) Mem[Reg[Rs]+Offs]=Reg[Rt] 4.1. 200ps 70ps 20ps 90ps 90ps 250ps 40ps b. 4.15     Perspectiva histórica e leitura adicional Esta seção.1> Quais são os valores dos sinais de controle gerados pelo controle na Figura 4. 120ps.16 Exercícios 331 Instrução Interpretação a.2.2.3. e custos de 1000. Os três problemas res- tantes neste exercício referem-se a estas portas. considere que estamos começando com um caminho de dados da Figura 4. Controles mais simples +100ps para –400 para Controle O controle se torna mais Controle devagar.3. OR. 2000 e 500. NOT e elementos D. SEQ Rd.1.2. 4.2.1> Qual é o ganho de velocidade obtido acrescentando essa melhoria? 4. respectivamente. b. 350ps e 100ps. ALU.1> Que blocos existentes (se houver) podem ser usados para essa instrução? 4. 4.2 [10] <4. 100.Rs.3 Os problemas neste exercício referem-se ao seguinte bloco lógico: Bloco lógico a.2> Repita o Exercício 4. Mux. 200. LWI Rt. D-Mem e Controle têm latências de 400ps. 4.Rt Reg[Rd]=Valor booliano (0 or 1) de (Reg[Rs]==Reg[Rs]) b. latência e custos: . Use apenas AND. Pequeno Multiplexador (Mux) com quatro entradas de dados 8-bit b. apenas flip-flops ou ambos? 4. em que os blocos I-Mem.1> De que novos blocos funcionais (se houver) precisamos para essa instrução? 4. O custo e a latência da lógica digital dependem dos tipos de elementos lógicos básicos (portas) que estão disponíveis e das propriedades dessas portas.3 [10] <4.2 [20] <4. 30. Os três problemas restantes neste exercício referem-se à seguinte melhoria do processador: Melhoria Latência Custo Benefício a.Rd(Rs) Reg[Rt]=Mem[Reg[Rd]+Reg[Rs]] 4.1> De que novos sinais da unidade de controle (se houver) precisamos para dar suporte a essa instrução? Quando os projetistas de processador consideram uma melhoria possível no caminho de dados do processador. Add o multiplicador ao +300ps para ALU +600 para ALU Permite a adição da instrução ALU MUL e a execução de 5% menos instruções (o MUL não é mais emulado).1.1> Qual é o tempo de ciclo de clock com e sem essa melhoria? 4. 4. 200ps.2> Mostre como esse bloco pode ser implementado. 30ps. Regs.2. Pequeno ALU de 8-bit que pode realizar AND. 4. Add. 4.2. Exercício 4. OR ou NOT 4.6 [10] <4. mas com uma lógica mais barata.3.1 [5] <4.2> Esse bloco contém apenas lógica.2. a decisão normalmente depende da escolha de custo/desempenho.1> Compare a razão custo/desempenho com e sem essa melhoria.5 [10] <4. respectivamente. 100ps.3 [10] <4.1 [10] <4.1. 10.2.3. mas todas as portas AND e OR que você usa precisam ser portas de duas entradas. Nos três problemas a seguir.4 [10] <4. Compare o custo e a latência desses dois projetos otimizados. Para os três problemas restantes neste exercício. (((A OU B) E C) OU ((A OU C) (A E C) OU (B E C) OU (A OU B)) 4. Seu circuito deverá im- plementar diretamente a expressão dada (não reorganize a expressão para “otimizá-la”).1. 20ps 2 40ps 3 +30ps +1 80ps 9 4.6 [20] <4. 10ps 2 12ps 4 20ps 5 30ps 10 b.1. mas implemente o Sinal de controle 1 e o Sinal de controle 2 e tente “compartilhar” os circuitos entre as expressões sempre que for possível.1.2? 4. e que sua latência e custo são os seguintes: NOT AND de 2 entradas OR de duas entradas Elemento D Latência Custo Latência Custo Latência Custo Latência Custo a. deve-se utilizar as portas lógicas disponíveis para implementar um operador para o qual uma porta não está disponível.4. 4.4 [5] <4. qual é o tamanho (em portas) do caminho crítico no seu circuito do Exercício 4.3. 4.4. 10ps 2 12ps 4 +2ps +1 30ps 10 b.1. ao invés de separadamente? .2> Qual é o custo da sua implementação do Exercício 4.4.2> Que fração do custo foi salva no seu circuito do Exercício 4.6 [10] <4. (((A E B) XOR C) OU (A XOR C)) (A XOR B) OR (A XOR C) OU (A XOR B) b.2> Qual é a latência da sua implementação do Exercício 4.1? 4.3.1 [5] <4. usando portas NOT e portas AND. 4.2> Qual é o custo do seu circuito do Exercício 4. Os problemas neste exercício referem-se às seguintes expressões lógicas: Sinal de controle 1 Sinal de controle 2 a.4.4. Repita o Exercício 4.4.2? 4.4.3 [10] <4.3 im- plementando esses dois sinais de controle juntos.2> Qual é o tamanho do caminho crítico no seu circuito de 4.3. consideramos que os seguintes elementos básicos da lógica digital estão presentes.332 Capítulo 4  O Processador AND ou OR Cada entrada addl NOT Elemento D de 2 entradas para AND/OR Latência Custo Latência Custo Latência Custo Latência Custo a.3? 4.4.2 [10] Supondo que todas as portas possuem latências iguais.5 [10] <4. 4. 20ps 2 40ps 3 50ps 3 50ps 8 4.4.2> Quando múltiplas expressões lógicas são implementadas.3. OR e XOR de duas entradas.3.5 [5] <4.4.2> Mude o seu projeto para minimizar a latência.4 [10] <4.4. é possível reduzir o custo de implementação usando os mesmos sinais em mais de uma expressão. Exercício 4.3? 4.4 Ao implementar uma expressão lógica na lógica digital.2> Implemente a lógica para o sinal de controle 1. depois para mini- mizar o custo. 2> Crie um circuito com entradas de dados de 1 bit e saída de dados de 1 bit que realize essa operação em série.16 Exercícios 333 Exercício 4. começando com o bit menos significativo.1.1 [20] <4. Exercício 4.6 Os problemas neste exercício consideram que os blocos lógicos necessários para im- plementar o caminho de dados do processador têm as seguintes latências: I-Mem Add Mux ALU Regs D-Mem Extensão de sinal Shift-esq-2 a. Para este problema. mas agora projete um circuito que realiza essa operação 2 bits de cada vez.5. No restante deste exercício.1 e 4. 4.2> Qual é o tempo de ciclo para o circuito que você criou no Exercício 4.5.1? Quanto tempo é necessário para realizar a operação de 32 bits? 4. Add (X + Y) b.5.2> Compare as razões custo/benefício para os dois circuitos que você criou nos Exercícios 4.6 [5] <4. 4.5.5. Além das entradas de dados. No seu projeto.3 [10] <4.5.5 [10] <4.2> Qual é o tempo de ciclo para o circuito que você criou no Exercício 4.4 [10] <4.5. e depois para o circuito que você criou no Exercício 4. 200ps 70ps 20ps 90ps 90ps 250ps 15ps 10ps b. 4.2? Qual é ganho de velocidade obtido usando esse circuito em vez daquele do Exercício 4. OR e XOR.1 para uma operação de 32 bits? 4. um circuito AND serial é simplesmente uma porta AND.2. o desempenho de um circuito é o inverso do tempo necessário para realizar uma operação de 32 bits. o circuito tem uma entrada Clk (clock) e uma entrada “Start” que é definida como 1 somente no primeiro ciclo da operação. 50ps 1 100ps 2 90ps 2 120ps 3 160ps 2 O tempo dado para um elemento D é seu tempo de preparação. gerando os bits de saída um a um.2> Repita o Exercício 4.5 Este exercício tem por finalidade ajudá-lo a familiarizar-se com o projeto e a operação dos circuitos lógicos sequenciais. lhe damos o bit N de cada operando e obtemos o bit N do resultado. 4. 10ps 2 12ps 4 12ps 4 14ps 6 30ps 10 b.5.5. o circuito está processando operandos de entrada bit a bit.5.5. você pode usar elementos D e portas NOT.2.2 [20] <4. 750ps 200ps 50ps 250ps 300ps 500ps 100ps 0ps . AND.2> Calcule o custo para o circuito que você criou no Exercício 4.5. consideramos que os seguintes elementos básicos da lógica digital estão disponíveis. Por exemplo.5. no ciclo N. e que sua latência e custo são os seguintes: NOT AND OR XOR Elemento D Latência Custo Latência Custo Latência Custo Latência Custo Latência Custo a. Subtrair um (X–1) em complementos de dois 4.1.5. Os problemas neste exercício referem-se a esta operação da ALU: Operação da ALU a. Em uma implementação serial. A entrada de dados de um flip-flop precisa ter o valor correto do tempo de preparação antes da borda do clock (final do ciclo de clock) que armazena esse valor no flip-flop. discuta como as mudanças na latência indicada desse recurso afetam o tempo de ciclo do processador.3> Em que fração de todos os ciclos a memória de dados é utilizada? . considere as seguintes latências para blocos lógicos no caminho de dados: I-Mem Add Mux ALU Regs D-Mem Extensão de sinal Shift-esq-2 a.7.3> Qual é o tempo do ciclo de clock se o único tipo das instruções que precisamos dar suporte forem instruções da ALU (ADD.2.7.7.2 [10] <4.3> Repita o Exercício 4. Os três problemas restantes neste exercício referem-se ao seguinte bloco lógico (recurso) no caminho de dados: Recurso a. 750ps 200ps 50ps 250ps 300ps 500ps 100ps 0ps 4.3 [20] <4. considere que não existem stalls de pipeline e que o desmembramento das instruções executadas seja o seguinte: ADD ADDI NOT BEQ LW SW a.3 [10] <4. Suponha que as latências de outros recursos não mudem.3> Para que tipos de instruções (se houver) esse recurso está no caminho crítico? 4. e SW? Para os problemas restantes neste exercício.3> Qual é o tempo do ciclo de clock se só tivermos de dar suporte a ins- truções LW? 4. Exercício 4. AND.6 [10] <4. Shift-esq-2 b.)? 4. Para os problemas neste exercício.3> Se a única coisa que precisássemos fazer em um processador fosse buscar instruções consecutivas (Figura 4. Qual seria o tempo de ciclo para esse caminho de dados? 4.4 [10] <4.11.6.6.6. e como esses componentes são utilizados pelas instruções. qual seria o tempo do ciclo? 4. examinamos como as latências dos componentes individuais do caminho de dados afetam o tempo do ciclo de clock do caminho de dados inteiro.5 [20] <4.7. 20% 20% 0% 25% 25% 10% b.7 Neste exercício. 200ps 70ps 20ps 90ps 90ps 250ps 15ps 10ps b.334 Capítulo 4  O Processador 4.1 [10] <4. 30% 10% 0% 10% 30% 20% 4.4 [10] <4.2 [10] <4.6).1 [10] <4.3> Qual é o tempo do ciclo de clock se tivermos de dar suporte a instruções ADD. mas para um processador que só tem um tipo de instrução: desvio incondicional relativo ao PC.6.6. mas desta vez precisamos dar suporte apenas a desvios condicionais relativos ao PC.3> Supondo que só temos suporte para instruções BEQ e ADD.6.3> Que tipos de instruções exigem esse recurso? 4. LW.3> Considere um caminho de dados semelhante ao da Figura 4. Registradores 4. etc.6. BEQ. caso contrário.8. os defeitos nos materiais (por exemplo.7. bit 0 4. nenhuma falha 4. um fio da fonte de alimentação).5 [10] <4.16 Exercícios 335 4. 4.3. 4. 4.8.1 para uma falha stuck-at-1.8.3. 4. 4. 4. memórias e registradores) que determinaria se existe uma falha stuck-at-0 nesse sinal? 4. Isso é chamado de falha cross-talk.3> Se pudermos melhorar a latência de um dos componentes indicados do caminho de dados em 10%.1.7.1. o silício) e os erros de manufatura podem resultar em circuitos defeituosos.4> Se soubermos que o processador tem uma falha stuck-at-1 nesse sinal. Os problemas a seguir referem-se à seguinte falha: Falha a. e o sinal afetado sempre tem um valor lógico 0 ou 1.3. mas agora o teste é se o sinal de controle “Jump” tem essa falha. o processador ainda é utilizável? Para isso.6 [10] <4.2 [10] <4.24: Sinal a. entrada do Registrador Escrita. Torna-se 0 se o sinal do controle RegDs é 0.3 [60] <4. . Nesse caso.4> Repita o Exercício 4. Uma classe especial de falhas cross-talk é quando um sinal está conectado a um fio que tem um valor lógico constante (por exemplo. memórias e registradores.4> Vamos supor que o teste do processador seja feito preenchendo o PC.4 [10] <4.8 Quando os chips de silício são fabricados.5 [10] <4.3> Em que fração de todos os ciclos a entrada do circuito por extensão de sinal é necessária? O que esse circuito está fazendo nos ciclos em que sua entrada não é necessária? 4.8. temos uma falha stuck-at-0 ou stuck-at-1.8.8. Registradores. Um defeito muito comum é quando um fio afeta o sinal em outro. registradores e memórias de dados e instruções com alguns valores (você pode escolher quais valores). permitindo que uma única instrução seja executada e depois lendo o PC.8.3.8. resultado do ALU. que componente seria? Qual é o ganho de velocidade obtido por essa melhoria? Exercício 4. Você conseguiria usar um único teste para stuck-at-0 e stuck-at-1? Caso afirmativo. 4. se não. Você pode considerar que existe memória de instrução e memória de dados livre suficiente para tornar o programa maior e armazenar dados adicionais. explique por que não. Os problemas a seguir referem-se ao seguinte sinal da Figura 4. mas agora o teste é se o sinal de controle “MemRead” tem essa falha. Add unidade ao canto superior direito. 4. explique como.1 [10] <4. temos de poder converter qualquer programa que execute em um processador MIPS normal em um programa que funcione nesse processador.3.4> Repita o Exercício 4. bit 0 b.4> Repita o Exercício 4. Stuck-at-1 b. Esses valores são então examinados para determinar se uma falha em particular está presente. respectivamente. Você conseguiria criar um teste (valores para PC. Dica: o processador é utilizável se cada instrução “rompida” por essa falha puder ser substituída por uma sequência de instruções “funcionais” que conseguem o mesmo efeito. 24. desenhe o diagrama lógico para a parte da unidade de controle que implementa apenas o primeiro sinal. SLT R1.10 Neste exercício.3.8.2.2 [10] <4. Descreva uma série de testes para procurar essa falha em todas as saídas Mux (cada bit de saída de cada um dos cinco Muxes).6 [40] <4. SW.1.4> Qual é o valor da word de instrução? 4.4> Que sinal de controle na Figura 4. mas normalmente não em todos eles. e vice-versa.4> Qual é o número de registrador fornecido à entrada “Escrever regis- trador” do arquivo de registradores? Esse registro é realmente escrito? Diferentes instruções exigem que diferentes sinais de controle sejam ativados no caminho de dados. 4.R3 4.2.4> Para o caminho de dados da Figura 4.9.6 [20] <4. BEQ.4> Qual é o valor desses dois sinais para esta instrução? 4. 4.10. 750ps 200ps 50ps 250ps 300ps 500ps 100ps 5ps 70ps 4.1 [10] <4.R2.9 Neste exercício.24: Sinal de controle 1 Sinal de controle 2 a.24.9. quanto tempo a unidade de controle pode levar para gerar o sinal MemWrite? 4.9.4> Para evitar estender o caminho crítico do caminho de dados mostrado na Figura 4.336 Capítulo 4  O Processador 4.10.9. 4.2 [20] <4. Os problemas restantes neste exercício referem-se aos dois sinais de controle a seguir. Os problemas neste exercício referem-se à seguinte instrução MIPS: Instrução a.4> Repita o Exercício 4. examinamos como o tempo do ciclo de clock do processador afeta o projeto da unidade de controle.4> Qual é o número de registrador fornecido à entrada “Ler registrador 1” do arquivo de registradores? Esse registro é realmente lido? E “Ler registrador 2”? 4.5 [20] <4. Tente fazer isso com o mínimo possível de testes de única instrução. ADD e J (jump). Jump RegDst 4. da Figura 4. Considere que só precisamos dar suporte às instruções LW.3 [10] <4.24 tem mais slack e quanto tempo a unidade de controle tem para gerá-lo se quiser evitar estar no caminho crítico? . examinamos a operação do caminho de dados de ciclo único para deter- minada instrução. 4.5.-100(R16) b. Exercício 4. ALUSrc Branch b. 200ps 70ps 20ps 90ps 90ps 250ps 15ps 10ps 30ps b.8. Os problemas neste exercício consideram que os blocos lógicos usados para implementar o caminho de dados têm as seguintes latências: Extensão I-Mem Add Mux ALU Regs D-Mem Shift-esq-2 ALU Ctrl de sinal a.9. Exercício 4. SW R4.4> Usando um único teste descrito no Exercício 4.4 [20] <4. mas agora implemente esses dois sinais.9.1 [10] <4. podemos testar falhas em diversos sinais diferentes.9. 4> Qual sinal de controle na Figura 4.5 [20] <4. como fizemos no Exercício 4. 4. .3 [20] <4. mas o custo do processador inteiro aumentar em $1 para cada 5ps de melhoria de um único sinal de controle.16 Exercícios 337 4.5.10. Se você puder usar uma lógica mais lenta para implementar sinais de controle. em vez de pagar para agilizá-lo.2. que sinais de controle você agilizaria e por quanto maximizaria o desempenho? Qual é o custo (por processador) dessa melhoria de desempenho? 4. Os problemas restantes neste exercício consideram que a memória de dados contém apenas zeros e que os registradores do processador possuem os seguintes valores no início do ciclo em que a word de instrução anterior é apanhada: R0 R1 R2 R3 R4 R5 R6 R8 R12 R31 a. 00000000100000100000100000101010 4.2 [10] <4.4> Se o processador já for muito caro.4 [20] <4.11.24 é o mais crítico para ser gerado rapidamente e quanto tempo a unidade de controle tem para gerá-lo se quiser evitar estar no caminho crítico? Os problemas restantes neste exercício consideram que o tempo necessário pela unidade de controle para gerar sinais de controle individuais é o seguinte: RegDst Jump Branch MemRead MemtoReg OpALU MemWrite ALUSrc RegWrite a.4> Se você puder agilizar a geração dos sinais de controle.6 [30] <4. queremos minimizar seu custo sem torná-lo mais lento.24) para essa palavra de instrução? 4. 4. 10101100011000100000000000010100 b.4> Quais são os valores das entradas da unidade de controle da ALU para essa instrução? 4.4> Qual é o tempo do ciclo de clock do processador? 4. 0 1 2 –3 –4 10 6 8 2 –16 b.4> Quais são as saídas da unidade de extensão de sinal e salto “Shift left 2” (topo da Figura 4. 500ps 500ps 450ps 200ps 450ps 200ps 500ps 100ps 500ps b.10. quais sinais de controle você tornaria mais lentos e por quanto reduziria o custo do processador sem torná-lo mais lento? Exercício 4.3 [10] <4.10. economizando $1 do custo do processador para cada 5ps que acrescenta à latência de um único sinal de controle.10.10. examinamos detalhadamente como uma instrução é executada em um caminho de dados de ciclo único. Os problemas neste exercício referem-se a um ciclo de clock em que o processador busca a seguinte word de instrução: Word de instrução a.4 [10] <4.11.4> Qual é o novo endereço do PC após a execução dessa instrução? Des- taque o caminho através do qual esse valor é determinado. 0 256 –122 19 –32 13 –6 –1 16 –2 4.11. mostre os valores de sua saída de dados durante a execução dessa instrução e esses valores de registrador.4> Para cada Mux. 1100ps 1000ps 1100ps 800ps 1200ps 300ps 1300ps 400ps 1200ps 4.1 [5] <4.11.11 Neste exercício. 12 Neste exercício.12. podemos usar uma organização multiciclos.5 [10] <4.11.6 [10] <4. uma instrução só percorre os estágios que ela realmente precisa (por exemplo. 55% 15% 15% 15% 4.1 [5] <4. Compare os tempos do ciclo de clock e os tempos de execução com a organização em ciclo único.11.5> Qual é o tempo do ciclo de clock em um processador com e sem pipeline? 4.3 [10] <4. Exercício 4.5> Se você pudesse dividir um estágio do caminho de dados com pipeline em dois novos estágios. examinamos como o pipelining afeta o tempo do ciclo de clock do proces- sador. 45% 20% 20% 15% b.2 [10] <4. pois não precisa do estágio WB). Os problemas neste exercício referem-se a esta sequência de instruções: . quais são seus valores de entrada de dados? 4.12. qual é a utilização da porta de escrita de registrador da unidade “Registradores”? 4.5 [10] <4. que estágio você dividiria e qual é o novo tempo do ciclo de clock do processador? Os problemas restantes neste exercício consideram que as instruções executadas pelo processador são desmembradas da seguinte forma: ALU BEQ LW SW a. Os problemas neste exercício consideram que os estágios individuais do caminho de dados têm as seguintes latências: IF ID EX MEM WB a.12.5> Em vez de uma organização de ciclo único. Nessa organização. qual é a utilização da memória de dados? 4.12. 200ps 170ps 220ps 210ps 150ps 4.12.5> Qual é a latência total de uma instrução LW em um processador com e sem pipeline? 4. ST só ocupa quatro ciclos. em que cada instrução ocupa múltiplos ciclos. multiciclos e em pipeline.13 Neste exercício.5> Supondo que não haja stalls ou hazards.4 [10] <4. cada um com metade da latência do estágio original. examinamos como as dependências de dados afetam a execução no pipeli- ne básico de cinco estágios descrito na Seção 4.5> Supondo que não haja stalls ou hazards.5.6 [30] <4.12.338 Capítulo 4  O Processador 4.4> Para a ALU e as duas unidades de soma.4> Quais são os valores de todas as entradas para a unidade de “Regis- tradores”? Exercício 4. 250ps 350ps 150ps 300ps 200ps b. mas uma instrução termina antes que outra seja apanhada. 4.5> Para este problema.R3 OR R2.R2.13.R4 b. Os problemas restantes neste exercício consideram os seguintes tempos do ciclo de clock: Sem forwarding Com forwarding completo Apenas com forwarding ALU-ALU a.14.13.5 [10] <4.R1. b. 4. examinamos como os hazards de recursos.3 [10] <4.13.13.14 Neste exercício.2 [10] <4. Indique hazards e acrescente instruções NOP para eliminá-los.5> Indique as dependências e seu tipo. 250ps 300ps 290ps b.16 Exercícios 339 Sequência de instruções a. 4.-100(R6) LW R4.5> Acrescente instruções NOP a esse código para eliminar hazards se houver apenas forwarding ALU-ALU (nenhum forwarding do estágio MEM para EX).1 [10] <4.R2 4.1 [10] <4. haverá um hazard estrutural toda vez que precisarmos apanhar uma instrução no mesmo ciclo em que outra .5> Suponha que não haja forwarding nesse processador em pipeline.R4.13. 4. OR R1.5> Qual é o tempo de execução total dessa sequência de instruções sem forwarding e com forwarding completo? Qual é o ganho de velocidade obtido acres- centando-se forwarding completo a um pipeline que não tinha forwarding? 4.R4 OR R1. Os problemas neste exercício referem-se ao seguinte fragmento de código MIPS: Sequência de instruções a.13. Indique os hazards e acres- cente instruções NOP para eliminá-los.R1. 4.5> Suponha que haja forwarding completo. os hazards de controle e o projeto da ISA podem afetar a execução em pipeline. Se tivermos apenas uma memória (para instruções e dados).6 [10] <4.4 [10] <4.8(R16) ADD R5.5> Qual é o tempo de execução total dessa sequência de instruções apenas com forwarding ALU-ALU? Qual é o ganho de velocidade em relação a um pipeline sem forwarding? Exercício 4. SW R16. 180ps 240ps 210ps 4. suponha que todos os desvios sejam perfeitamente previstos (isso elimina todos os hazards de controle) e que nenhum slot de delay seja utilizado. essas instruções não precisam mais usar a ALU. que ganho de velocidade é obtido nessa sequência de instruções? 4.15.14.5> Considerando stall-on-branch e nenhum slot de delay. repita o cálculo de ganho de velocidade de 4. 150ps 200ps 200ps 20ps 100ps 4. Exercício 4. que ganho de velocidade é obtido nesse código se os resultados do desvio forem determinados no estágio ID.3.5 [10] <4. Quando EX e MEM são feitos em um único estágio. examinamos como a ISA afeta o projeto do pipeline.14.2 [10] <4. Para garantir o processo do forwarding. repita o cálculo de ganho de velocidade de 4.14. 200ps 120ps 150ps 190ps 100ps b. Como resultado. em relação à execução em que os resultados do desvio são determinados no estágio EX? Os problemas restantes neste exercício consideram que os estágios de pipeline individuais possuem as seguintes latências: IF ID EX MEM WB a. Mude esse código para acomodar essa ISA alterada. BEQM Rd.15.15 Neste exercício. Qual é o tempo de execução total dessa sequência de instruções no pipeline de cinco estágios que tem apenas uma memória? Vimos que os hazards de dados podem ser eliminados acrescentando NOPS ao código. a maior parte do trabalho pode ser feita em paralelo. o estágio EX/MEM resultante tem uma latência que é a maior das duas originais.Offs(Rs) if Rt=Mem[Offs+Rs] then PC=Rd 4.2 [20] <4. mas leve em conta a (possível) mudança no tempo do ciclo de clock.14.2. suponha que todos os desvios sejam perfeitamente previstos (isso elimina todos os hazards de controle) e que nenhum slot de delay seja utilizado. esse hazard sempre precisa ser resolvido em favor da instrução que acessa dados.6 [10] <4.5> Para este problema.15.Rt.3 [10] <4.5> Dadas essas latências de estágio de pipeline.340 Capítulo 4  O Processador instrução acessa dados. Suponha que a latência do estágio ID aumente em 50% e a latência do estágio EX diminua em 10ps quando a resolução do resultado do desvio é passada de EX para ID. mais 20ps necessários para o trabalho que poderia ser feito em paralelo. 4. Supondo que essa mudança não afete o tempo do ciclo de clock.5> Que novos sinais de controle precisam ser acrescidos ao seu pipeline do Exercício 4.1? . 4. Você conseguiria fazer o mesmo com esse hazard estrutural? Por quê? 4. Como resultado.14.14.5> Considerando stall-on-branch e nenhum slot de delay.4 [10] <4.5> Dadas essas latências de estágio em pipeline. Os problemas neste exercício referem-se à seguinte instrução nova: a. ADDM Rd. mas leve em conta a (possível) mudança no tempo do ciclo de clock.5> O que deverá ser mudado no caminho de dados em pipeline para acrescentar essa instrução à ISA do MIPS? 4.Rt+Offs(Rs) Rd=Rt+Mem[Offs+Rs] b.14.1 [20] <4. os es- tágios MEM e EX podem ser sobrepostos e o pipeline tem apenas quatro estágios. Se mudarmos as instruções load/store para usar um registrador (sem um offset) como endereço. qual é o novo tempo do ciclo de clock e tempo de execução dessa sequência de instruções se o cálculo de endereço de beq for passado para o estágio MEM? Qual é o ganho de velocidade decorrente dessa mudança? Suponha que a latência do estágio EX seja reduzida em 20ps e a latência do estágio MEM fique inalterada quando a resolução do resultado do desvio for passada de EX para MEM. que a substituição pode ser feita uma vez no número indicado de instruções originais. 3 40 1 4. como o AMD Barcelona.5> Qual é o ganho de velocidade alcançado com o acréscimo dessa nova instrução? No seu cálculo. Loop a. SW R16. 4. 4. 4.5. 4.3 [5] <4. O último problema neste exercício considera que cada uso da nova instrução substitui o número indicado das instruções originais.16. e quais registradores são realmente lidos? 4. e que.16. b. 4. 2 30 2 b.13> Dê um exemplo de onde essa instrução poderia ser útil e uma sequência de instruções MIPS existentes que são substituídas por essa instrução.11.15.16. .R1. Considere também que muitas iterações desse loop são executadas antes que o loop termine. Considere que a previsão de desvio perfeita é utilizada (sem stalls devido aos hazards de controle).1 [5] <4.2 [5] <4.6 [10] <4.15.4 [10] <4. 4. explique como ela seria executada em um processador moderno. toda vez que a nova instrução for executada.16 Os três primeiros problemas neste exercício referem-se à seguinte instrução MIPS: Instrução a.-100(R6) b. o número indicado de ciclos de stall extras será acrescentado ao tempo de execução do programa: Substitui Uma vez em cada Ciclos de stall extras a.5. OR R2.6> Que registradores precisam ser lidos.15.6> O que essa instrução faz nos estágios EX e MEM? Os três problemas restantes neste exercício referem-se ao loop a seguir.13> Se essa instrução já existir em uma ISA legada.3 [20] <4.16 Exercícios 341 4. que não existem slots de delay e que o pipeline possui suporte para forwarding completo.13> O suporte para essa instrução introduz novos hazards? Os stalls devidos aos hazards existentes se tornam piores? 4. considere que o CPI do programa original (sem a nova ins- trução) seja 1.5 [10] <4.6> Quando essa instrução é executada.15. o que é mantido em cada regis- trador localizado entre dois estágios do pipeline? 4. Exercício 4.5.R0 4. 6> A mudança no Exercício 4.17.5 [10] <4.6 [10] <4. o pipelining introduz registradores entre os estágios (Figura 4. Além disso.4 [10] <4.17.17. 4.17. e cada um deles gera uma latência adicional. em que porcentagem dos ciclos de clock o somador de desvio no estágio EX gera um valor que é realmente utilizado? 4.17. Qual é o tempo do ciclo de clock se isso for feito no caminho de dados de ciclo único e em pipeline? Suponha que a latência do novo estágio EX/MEM é igual à maior de suas latências.16.33 tem alguma latência. qual é o ganho de velocidade obtido com o pipelining de um caminho de dados de ciclo único? 4.4 [5] <4.5 [10] <4.6> Supondo que não haja stalls. em que EX e MEM são feitos em paralelo? . Mostre todas as instruções que estão no pipeline durante esses ciclos (não apenas aquelas da terceira iteração).1 [5] <4. Se isso for necessário para 50% dessas instruções. o que é armazenado no registrador IF/ID? Exercício 4. qual é o ganho de velocidade geral alcançado mudando do pipeline de cinco estágios para o pipeline de quatro estágios.342 Capítulo 4  O Processador 4.2 [5] <4.35).6> Com que frequência (como uma porcentagem de todos os ciclos) temos um ciclo em que todos os cinco estágios do pipeline estão realizando trabalho útil? 4. 200ps 120ps 150ps 190ps 100ps 15ps b. Os problemas restantes neste exercício assumem as seguintes latências para a lógica dentro de cada estágio do pipeline e para cada registrador entre dois estágios: IF ID EX MEM WB Registrador do pipeline a.17.6> No início do ciclo em que apanhamos a primeira instrução da terceira iteração desse loop. do ciclo em que apanhamos a primeira instrução dessa iteração até (mas não incluindo) o ciclo em que apanhamos a primeira instrução da iteração seguinte.5 exige que muitas instruções LW/SW existentes sejam convertidas para sequências de duas instruções.6 [10] <4. 150ps 200ps 200ps 200ps 100ps 15ps 4. com que frequência (porcentagem de todos os ciclos) realmente precisamos usar todas as três portas de registrador (duas leituras e uma escrita) no mesmo ciclo? 4.3 [5] <4. 40% 30% 25% 5% b. com que frequência (porcentagem de todos os ciclos) usamos a memória de dados? Cada estágio de pipeline na Figura 4.17.6> Supondo que não haja stalls.17 Os problemas neste exercício consideram que as instruções executadas por um processador em pipeline são repartidas da seguinte forma: ADD BEQ LW SW a.6> Podemos converter todas as instruções load/store em instruções baseadas em registrador (sem offset) e colocar o acesso à memória em paralelo com a ALU.16. 4. 60% 10% 20% 10% 4.6> Supondo que não haja stalls.16.6> Mostre um diagrama de execução de pipeline para a terceira iteração desse loop.6> Supondo que não haja stalls e que 60% de todos os desvios condicionais sejam tomados. e considere o seguinte tempo de ciclo de clock.4 [5] <4.18. 4.6.1 [10] <4.6> Para cada estágio do pipeline. de todas as instruções executadas em um processador. Qual seria um motivo a favor de fazer isso no estágio EX? Qual é o motivo contra fazer isso no estágio EX? Os problemas restantes neste exercício referem-se aos seguintes sinais da Figura 4. 2ª instrução que a segue. pois não podem resultar em hazards de dados. Consideramos que a escrita do registrador é feita na primeira metade do ciclo de clock e que as leituras do registrador são feitas na segunda metade do ciclo. 5% 20% 5% 10% 10% 10% b.6> Para cada um desses sinais. Qual é esse sinal? Esse é um paradoxo de retorno no tempo? Explique. LW R1.18.2 [10] <4.18.1 [10] <4. Além disso. considere que o CPI do processador é 1 se não houver hazards de dados. de modo que dependências “EX para 3ª” e “MEM para 3ª” não são contadas. Branch RegWrite 4. identifique o estágio do pipeline em que ele é gerado e o estágio em que ele é usado. OR R1. latência de ALU e latência de Mux: Tempo de ciclo Instrução Latência de ALU Latência de Mux de clock a. ou ambas).6> Para qual ou quais instruções MIPS esses dois sinais são definidos como 1? 4. 4.R6 200ps 170ps 25ps 4. EX para 1ª MEM para EX para 2ª MEM para EX para 1ª e Outras somente 1ª somente somente 2ª somente MEM para 2ª dependências RAW a.18.48: Sinal 1 Sinal 2 a.32(R2) 50ps 30ps 15ps b.7> Quanto tempo a unidade de controle tem para gerar o sinal de controle ALUSrc? Compare isso com uma organização de ciclo único.16 Exercícios 343 Exercício 4. ALUSrc PCSrc b.3 Qual é o valor do sinal PCSrc para essa instrução? Esse sinal é gerado cedo no es- tágio MEM (somente uma única porta AND).6 [10] <4. que fração dos ciclos estamos realizando stall devido aos hazards de dados? .18 Os três primeiros problemas neste exercício referem-se à execução da instrução a seguir no caminho de dados em pipeline da Figura 4.5 [5] <4.19 Esses problemas consideram que. quais são os valores dos sinais de con- trole ativados por essa instrução nesse estágio do pipeline? 4. O tipo de dependência de dados RAW é identificado pelo estágio que produz o resultado (EX ou MEM) e a instrução que consome o resultado (1ª instrução que segue aquela que produz o resultado.R5.19. a fração dessas instruções a seguir tem um tipo particular de dependência de dados RAW. 4.18. 4. Exercício 4.51.18.7> Se não usarmos forwarding. 20% 10% 15% 10% 5% 0% 4.6> Um desses sinais retorna pelo pipeline. 6 [20] <4.19. Repita o Exercício 4. todos os valores na memória de dados são 0s e que os regis- tradores de R0 a R3 têm os seguintes valores iniciais: .7> Vamos supor que não tenhamos recursos para ter Muxes de três entradas que são necessários para o forwarding completo.19. 150ps 100ps 120ps 150ps 140ps 130ps 120ps 100ps b.19. 4.20. 4. antes que qualquer um dos anteriores seja executado. mas desta vez determine quais das duas opções resulta em menor tempo por instrução.19.7> Se usarmos o forwarding completo (encaminhar todos os resultados que podem ser encaminhados).7> Qual seria o ganho de velocidade adicional (relativo a um processador com forwarding) se acrescentássemos o forwarding de retorno no tempo que elimina todos os hazards de dados? Suponha que o circuito de retorno no tempo ainda a ser inventado acrescente 100ps à latência do estágio EX de forwarding completo.7> Para as possibilidades de hazard e latências de estágio de pipeline indicadas.5 [10] <4.7> Repita o Exercício 4.7> Ache todos os hazards nessa sequência de instrução para um pipeline de cinco estágios com e depois sem forwarding. b.3.20.3 [10] <4.7> Encontre todas as dependências de dados nessa sequência de instrução.20. Temos de decidir se é melhor encaminhar apenas do registrador de pipeline EX/MEM (forwarding do próximo ciclo) ou apenas do registrador de pipeline MEM/WB (forwarding de dois ciclos). que fração dos ciclos estamos realizando stall devido aos hazards de dados? 4. estamos considerando uma divisão do estágio MEM em dois estágios. No estágio EX. Exercício 4. Qual das duas opções resulta em menos ciclos de stall de dados? Os três problemas restantes neste exercício referem-se às seguintes latências para estágios individuais do pipeline. as latências são dadas separadamente para um processador sem forwarding e um processador com diferentes tipos de forwarding. 300ps 200ps 300ps 350ps 330ps 320ps 290ps 100ps 4.2 [10] <4.3 [10] <4.2 para esse pipeline de seis estágios.7> Para reduzir o tempo do ciclo de clock.1 [5] <4. qual é o ganho de velocidade obtido acrescentando-se forwarding completo a um pipeline que não tinha forwarding? 4. Os três problemas restantes neste exercício consideram que.4 [10] <4.19.344 Capítulo 4  O Processador 4. 4.20 Os problemas neste exercício referem-se a estas sequências de instrução: Sequência de instrução a.20.19. EX (FW EX(FW EX (sem EX(FW IF ID apenas de apenas de MEM WB FW) completo) EX/MEM) MEM/WB) a. 4.2 [5] <4. para os cinco primeiros ciclos durante a execução desse código. 4. quais são os valores finais dos registradores após essa sequência de instrução? 4.21. especifique quais sinais são ativados em cada ciclo pelas unidades de detecção de hazard e forwarding na Figura 4.7> Se o processador tem forwarding.7> Se considerarmos que o forwarding será implementado quando projetarmos a unidade de detecção de hardware.4 [5] <4.16 Exercícios 345 R0 R1 R2 R3 a.1 [5] <4.4 [20] <4. explique por que cada sinal é necessário.5 [10] <4. mas depois nos esquecermos de realmente implementar o forwarding.3 [10] <4.2 [10] <4. insira nops para garantir a execução correta. 4. especifique quais sinais de saída ela ativa em cada um dos cinco primeiros ciclos durante a execução desse código. .21. mas nos esquecemos de implementar a unidade de detecção de hazard.6 [20] <4.7> Para o projeto descrito no Exercício 4. o que acontece quando esse código é executado? 4.7> Que valor é o primeiro a ser encaminhado e qual é o valor que ele redefine? 4. Exercício 4.7> Para a unidade de detecção de hazard do Exercício 4. que novas entradas e sinais de saída precisamos para a unidade de detecção de hazard da Figura 4. Os problemas neste exercício referem-se a estas sequências de instrução. detecção de hazard e projeto de ISA.21 Este exercício tem por finalidade ajudá-lo a entender o relacionamento entre forwarding.6 [10] <4.20.60? Usando essa sequência de instruções como um exemplo.7> Se não houver forwarding ou detecção de hazard.5 [10] <4. Sequência de instrução a. 4.21. Você pode considerar que o registrador R7 pode ser usado para manter valores temporários no seu código modificado.7> Se não houver forwarding. 4.21.5.7> Repita o Exercício 4.1.20.21.21.20.60. 0 4 63 3000 4.20.21. 4. e considere que ele é executado em um caminho de dados com pipeline em cinco estágios.7> Se houver forwarding. 4. 0 –1 31 1500 b.21. b. mas agora use nops somente quando um hazard não puder ser evitado alterando ou rearrumando essas instruções. acrescente nops a essa sequência de instrução de modo a garantir a execução correta apesar de faltar suporte para o forwarding.5. No código apresentado. além de requerer lógica adicional de forwarding e detecção de hazard. Compare a complexidade dessa nova unidade de forwarding com a complexidade da unidade de forwarding existente na Figura 4. Você pode considerar que o registrador $8 está disponível como um registrador temporário. descreva a lógica de detecção de hazard necessária para dar suporte à execução do desvio no estágio ID como na Figura 4. qual é o ganho de velocidade alcançado movendo-se a execução do desvio para o estágio ID? Explique sua resposta. Mude esse código para usar essa instrução de desvio em vez de BEQ.346 Capítulo 4  O Processador Exercício 4. No seu cálculo de ganho de velocidade.2 [10] <4.4 [10] <4.Label”.Label” e “BNEZ Rd.1. As instruções de desvio seriam “BEZ Rd. Essa técnica envolve um comparador dedicado no estágio ID.6 [10] <4. Juntamente com a precisão do previsor de desvio. 4.62.5 [10] <4. 4.1 [10] <4.22.8> Uma maneira de mover a resolução do desvio para um estágio anterior é não precisar de uma operação da ALU nos desvios condicionais.23 A importância de ter um bom previsor de desvio depende da frequência com que os des- vios condicionais são executados. b.22. isso . e haveria desvio se o registrador tivesse e não tivesse um valor 0. considere que a comparação adicional no estágio ID não afeta o tempo do ciclo de clock. supondo que não existam slots de delay e que os desvios sejam executados no estágio EX.22. respectivamente.8 descreve como a rigidez dos hazards de controle pode ser reduzida movendo-se a execução do desvio para o estágio ID. descreva o suporte para forwarding que precisa ser acrescentado para dar suporte à execução do desvio no estágio ID. hazards de controle e execução de desvio em um processador com pipeline. Neste exercício.8> Repita o Exercício 4.22. como mostra a Figura 4. forwarding completo e um previsor de desvio tomado: a.8> Usando como exemplo a primeira instrução de desvio no código apresentado.62.22. 4. essa técnica tem o potencial de aumentar a latência do estágio ID. Porém. e que uma instrução tipo R SEQ(set if equal) pode ser usada. Que tipo de hazard essa nova lógica deveria detectar? 4. 4. 4. consideramos que o código MIPS a seguir é executado em um processador com um pipeline em cinco estágios.22. A Seção 4.3 [20] <4. mas considere que os slots de delay sejam utilizados.8> Desenhe um diagrama de execução de pipeline para esse código. a instrução que vem após o desvio agora é a instrução do slot de delay para esse desvio.62.22. Exercício 4.22 Este exercício tem por finalidade ajudá-lo a entender o relacionamento entre slots de delay.8> Para o código apresentado.8> Usando como exemplo a primeira instrução de desvio no código apresentado. 8> Algumas instruções de desvio são muito mais previsíveis do que outras. 4. 45% 55% 85% b. 4. considere as seguintes precisões do previsor de desvio: Sempre tomado Sempre não tomado 2 bits a. NT. como a seguir: Tipo R BEQ JMP LW SW a. T. NT 4.23.16 Exercícios 347 determinará quanto tempo será gasto com stall devido a desvios mal previstos.8> Os ciclos de stall devidos a desvios mal previstos aumentam o CPI.24.23.63 (previsão não tomada). 4.23. considere o desmembramento das instruções dinâmicas em diversas categorias de instrução.3 [10] <4.24 Este exercício examina a precisão de vários previsores de desvios para o seguinte padrão repetitivo (como em um loop) de resultados do desvio: Resultados do desvio a. T.8> Qual é a precisão do previsor de dois bits para os quatro primeiros desvios nesse padrão. 40% 25% 5% 25% 5% b. qual é a precisão do previsor de 2 bits nos 20% restantes das instruções de desvio? Exercício 4.6 [10] <4. Qual é o CPI extra devido a desvios mal previstos com o previsor sempre tomado? Con- sidere que os resultados do desvio sejam determinados no estágio EX.8> Repita o Exercício 4.8> Repita o Exercício 4. T. 65% 35% 98% 4.24. supondo que o previsor comece no estado inferior esquerdo da Figura 4. 4.1 [10] <4. que ganho de velocidade seria obtido se pudéssemos converter metade das instruções de desvio de um modo que substituísse cada instrução de desvio por duas instruções da ALU? Suponha que instruções previstas correta e incorretamente tenham a mesma chance de serem substituídas. T. 60% 8% 2% 20% 10% Além disso.2 [5] <4.5 [10] <4.2 [10] <4.3 [10] <4.23.4 [10] <4.23. 4.23.1 para o previsor “sempre não tomado”.8> Qual é a precisão dos previsores sempre tomado e sempre não tomado para essa sequência dos resultados do desvio? 4. que sempre são previstos corretamente. 4. Se soubermos que 80% de todas as instruções de desvio executadas são desvios loop-back fáceis de prever.1 para o previsor de 2 bits.1 [5] <4.23.8> Qual é a precisão do previsor de dois bits se esse padrão for repetido indefinidamente? .8> Com um previsor de 2 bits. Neste exercício. NT.8> Com um previsor de 2 bits. T. 4.23. T b.24. que não existem hazards de dados e que nenhum slot de delay seja utilizado. que ganho de velocidade seria alcançado se pudéssemos converter metade das instruções de desvio de um modo que substitua uma instrução de desvio por uma instrução da ALU? Suponha que instruções previstas correta e incorretamente tenham a mesma chance de serem substituídas. 0x1000CB05 0x1000D230 0x1000d780 0x1000E230 00x100F254 b. especifique o estágio do pipeline em que ela é detectada.348 Capítulo 4  O Processador 4. Seu previsor deverá ter uma entrada que lhe diga qual foi o resultado real. 4.9> No tratamento de exceção com vetor. começar a prever perfeitamente esse padrão e seu oposto. 0x450064E8 0xC8203E20 0C8203E20 0x678A0000 0x00000010 4.8> Qual é a precisão do seu previsor do Exercício 4. Você pode considerar que os endereços desses handlers são conhecidos quando o proces- sador é projetado.3 [10] <4.25 Este exercício explora como o tratamento de exceção afeta o projeto do pipeline.4 [30] <4.24. 0 para não tomado) e nenhuma entrada que não seja o clock e o sinal de controle que indica que a instrução é um desvio condicional.8> Crie um previsor que alcance uma precisão perfeita se esse padrão for repetido indefinidamente.6 [15] <4.24.6 [20] <4. Dica: essa entrada permite que seu previsor determine qual dos dois padrões repetitivos ele recebe. 4.25. Seu previsor deverá ser um circuito sequencial com uma saída que oferece uma previsão (1 para tomado.25.4 [5] <4. mostre como a organização do pipeline deve ser mudada para ser capaz de tratar dessa exceção.5 [10] <4.3 usando esse pipeline modificado e o tratamento de exceção com vetor. mais cedo ou mais tarde (após um período de aquecimento durante o qual poderá fazer previsões erradas). descreva o que acontece no pipeline quando a primeira instrução causa a primeira exceção que você listou no Exercício 4. JUMP Label SW R5.R2. Mostre o diagrama de execução do pipeline do momento em que a primeira instrução é apanhada até o momento em que a primeira instrução do handler de exceção é concluída.9> Queremos simular o tratamento de exceção com vetor (descrito no Exercício 4.2 [10] <4.9> Que exceções cada uma dessas instruções pode disparar? Para cada uma dessas exceções.25.0(R1) b.25.Label LW R1. Os três problemas restantes neste exercício consideram que os handlers de exceção estão localizados nos endereços a seguir: Endereço de Instrução Endereço de Defeito do Overflow dados inválido indefinida instrução inválido hardware a. Mude o pipeline para implementar esse mecanismo de tratamento de exceção.9> Se houver um endereço de handler separado para cada exceção.25.1 [5] <4.8> Repita o Exercício 4. . 4.24.24.3? O que acontece se houver uma instrução inválida nesse endereço na memória de instrução? 4.5) em uma máquina que tem apenas um endereço de handler fixo.4 se ele receber um padrão repetitivo que é o oposto exato deste? 4.25. 4.0(R1) 4.25. Os três primeiros problemas neste exercício referem-se às duas instruções a seguir: Instrução 1 Instrução 2 a.9> Se a segunda instrução dessa tabela for apanhada logo após a instrução da primeira tabela.24. Repita o Exercício 4. Exercício 4.1. mas agora o seu previsor deverá ser capaz de. BNE R1.25.25.9> Qual é o endereço do handler de exceção no Exercício 4. a tabela de endereços do handler de exceção está na memória de dados em um endereço conhecido (fixo).5 [20] <4.4.25. R4.27 Este exercício examina como o tratamento de exceção interage com as instruções de desvio e load/store. Dica: esse código deverá identificar a exceção.26.9> Para cada estágio do pipeline.5 [20] <4. 4.9> Se uma exceção de overflow ocorrer uma vez para cada 100. Os três problemas restantes neste exercício consideram que os estágios do pipeline pos- suem as seguintes latências: IF ID EX MEM WB a.4 [10] <4. Os três primeiros problemas neste exercício referem-se à seguinte instrução MIPS que dispara uma exceção: Instrução Exceção a.9> Alguns dos sinais de controle gerados no estágio ID são armazenados no registrador ID/EX do pipeline. 4.26 Este exercício explora como o tratamento de exceção afeta o projeto da unidade de controle e o tempo do ciclo de clock do processador. Exercício 4.16 Exercícios 349 Escreva o código que deverá estar nesse endereço fixo.66 relacionados à exceção enquanto essa instrução passa por esse estágio do pipeline. usando essa instrução como um exemplo.1 [10] <4.Label” e estas latências de estágio do pipeline como exemplo. BNE R1.9> Podemos gerar sinais de controle de exceção em EX em vez de ID? Explique como isso funcionará ou por que não funcionará.26. qual é o ganho de velocidade geral se movermos a verificação do over- flow para o estágio MEM? Considere que essa mudança reduz a latência de EX em 30ns e que o IPC alcançado pelo processador em pipeline é 1 quando não existem exceções. Usando essa instrução como exemplo. 220ps 150ps 250ps 200ps 200ps b. 4.R5 Overflow aritmético 4.9> Supondo que cada Mux tenha uma latência de 40ps. Que sinal é o mais crítico? Exercício 4. b. 4.26. determine os valores dos sinais de controle da Figura 4. obter o endereço correto da tabela de vetor de exceção e transferir a execução para esse handler.26.3 [10] <4.R2.000 ins- truções executadas.2 [5] <4.26. . descreva a principal desvantagem dessa técnica. usando a instrução “BNE R4. SUB R2. e alguns vão diretamente para o estágio EX. determine o quanto da unidade de controle precisa gerar os sinais de flush.6 [10] <4.Label Endereço inválido de alvo b. 4.R5.26. Os problemas neste exercício referem-se à seguinte instrução de desvio e à instrução do slot de delay correspondente: Desvio e slot de delay a. Explique por que. 175ps 150ps 200ps 175ps 140ps 4.9> Podemos tornar o estágio EX mais rápido se verificarmos as exceções no estágio após aquela em que ocorre a condição excepcional. 1 [20] <4.27. e esse store acessar um endereço de dados inválido? 4. e que todos os registradores. 4. 4.9> Para a depuração.R11.R12 .4 [10] <4. considere que as variáveis são mantidas em registradores da seguinte forma. a instrução em “Label” for uma instrução inválida.27. R5 R6 R1 R2 R3 R10.9> Se o cálculo do endereço de load/store puder estourar. R2 R8 R9 R10 R11 R3. mas dessa vez considere que a instrução no slot de delay também causa uma exceção de erro de hardware quando está no estágio MEM. I J A B C Livre a. WADDR e WVAL.27. mas o slot de delay causar uma exceção? O que acontece após a execução do handler de exceção ter sido concluída? Os três problemas restantes neste exercício também se referem à seguinte instrução store: Instrução store a.27. com exceção daqueles indicados como Livre. SW R1. Queremos acrescentar dois novos registradores.3 [10] <4.27.350 Capítulo 4  O Processador 4. 4. SW R5.1.27. O processador deverá disparar uma exceção quando o valor igual a WVAL estiver para ser escrito no endereço WADDR.9> Qual é o valor do EPC se o desvio for tomado. Ao escrever código MIPS. comparamos o desempenho dos processadores de um despacho e proces- sadores de dois despachos.R4.5 [10] <4.9> Suponha que esse desvio seja corretamente previsto como tomado.9> Repita o Exercício 4. levando em conta as transformações do programa que podem ser feitas para otimizar para a execução em dois despachos.0(R1) 4.28 Neste exercício.6 [10] <4. Descreva o que é feito em cada estágio do pipeline para cada ciclo.9> O que acontece se o desvio for tomado. são usados para manter diversas variáveis. Como você mudaria o pipeline para implementar isso? Como essa instrução sw seria tratada pelo seu caminho de dados modificado? Exercício 4. mas depois a instrução em “Label” é uma instrução indefinida. a primeira instrução do handler de exceção for a instrução SW apresentada.-40(R15) b. b. de modo que não podem ser usados para nada mais. começando com o ciclo em que o desvio é decodificado até o ciclo em que a primeira instrução no handler de exceção é apanhada. é útil ser capaz de detectar quando um valor em particular é escrito em um endereço de memória específico.R5 b.27.2 [10] <4. podemos adiar a detecção da exceção de estouro para o estágio MEM? Use a instrução store indicada para explicar o que acontece. Os problemas neste exercício referem-se ao seguinte loop (escrito em C): Código C a. 5 [10] <4.4 [10] <4. 4. Suponha que o processador tenha previsão de desvio perfeita e possa buscar quaisquer duas instruções (não apenas instruções consecutivas) no mesmo ciclo.10> Se muitas (por exemplo.000 iterações do loop são executadas.000) iterações desse loop forem executadas. mas desta vez use seu código MIPS do Exercício 4.1 executado em um processador com dois despachos mostrado na Figura 4.28.2.1 para um despacho e dois despachos.5.16 Exercícios 351 4.2 [10] <4.28. e que um processador de dois despachos possa buscar duas instruções quaisquer no mesmo ciclo.2 [10] <4.10> Repita o Exercício 4. considere que o processador tenha previsões de desvio perfeitas.10> Rearrume o seu código do Exercício 4.28.000. três instruções load/store ou qualquer combinação dessas instruções.000.28. 4. Compare isso com o seu resultado para um processador de dois despachos do Exercício 4.10> Se o loop sair depois de executar apenas duas iterações. três desvios. e considere que 1. 4.000.28.28. da Figura 4. 1.29 Neste exercício.69. 1. mas as dependências de dados e controle ainda precisam ser tratadas corretamente. Observe que isso só remove uma restrição de recurso.1 para alcançar o me- lhor desempenho em um processador de dois despachos escalonado estaticamente. desenhe um diagrama de pipeline para o seu código MIPS do Exercício 4. sem rearrumar as instruções para conseguir melhor desempenho.3.6 [10] <4.000) iterações desse loop forem executadas.29.29. 4. suponha que qualquer combinação dos tipos de instrução possa ser executada no mesmo ciclo.3 [10] <4.28. Os problemas neste exercício referem-se ao loop a seguir: Loop a.29.1 [10] <4.2.69. 4. Assim como no Exercício 4. e a outra seja uma instrução não de memória. . uma das instruções a serem executadas em um ciclo possa ser de qualquer tipo.10> Traduza esse código C para instruções MIPS.1 [10] <4.10> Qual é o ganho de velocidade ao passar de um processador de um despacho para dois despachos da Figura 4. 4. b.69? Use o seu código do Exercício 4. as três instruções podem ser três operações da ALU.28.28. 4.1. determine a fração de todas as leituras de registrador que são úteis em um processador superescalar estático de dois despachos.10> Se muitas (por exemplo.28.28. Para simplificar o exercício.28. mas desta vez considere que. em um superes- calar de três despachos.28. Sua tradução deverá ser direta. 4. determine a fração de todas as leituras de registrador que são úteis em um processador superescalar estático de três despachos. por exemplo. no proces- sador de dois despachos.10> Repita o Exercício 4. consideramos a execução de um loop em um processador superescalar escalonado estaticamente. Exercício 4. 000).000.3 [10] <4. mas agora suponha que o processador de qua- tro despachos tenha 50 estágios de pipeline.4 em vez do código original com um processador em pipeline (um despacho)? Suponha que o loop tenha muitas iterações (por exemplo.10> Qual é o CPI obtido por um processador superescalar estático de dois despachos nesse programa? 4. Exercício 4. Suponha que o loop sempre execute um número par de iterações.30.4 [20] <4.6 [10] <4.4 [5] <4. 4. 4.29. supomos que um processador superescalar de N despachos possa executar quaisquer N instruções no mesmo ciclo. cujo previsor só pode tratar de um desvio por ciclo. independente de seus tipos. supomos que não existem stalls devidos a dependências de dados.2 [10] <4.30 Neste exercício.352 Capítulo 4  O Processador 4.6 <4.10> Para um processador superescalar estático de dois despachos com um pipeline clássico de cinco estágios. determine a fração de ciclos em que duas ou três portas de escrita de registrador são usadas em um processador superescalar estático de três despachos.10> Qual é o ganho de velocidade de usar o seu código do Exercício 4.000. 45% 4% 1% 30% 20% 4.4 em vez do código original com um processador superescalar estático de dois despachos? Suponha que o loop tenha muitas iterações (por exemplo.29.3 [10] <4.1 [5] <4.10> Repita o Exercício 4.10> Em um processador superescalar estático de dois despachos.30. supomos que cada instrução seja escolhida indepen- dentemente. Considere que cada um dos cinco estágios . sem considerar a instrução que a antecede ou sucede. que nenhum slot de delay é utilizado e que os desvios são executados no estágio EX do pipeline.30.10> Repita o Exercício 4.29.29. Segundo.5.30.4.000).10> Desdobre esse loop uma vez e escalone-o para um processador superescalar estático de dois despachos. 4. Que conclusão você pode chegar sobre a importância de uma boa previsão de desvio quando a largura da despacho do processador é aumentada? 4.30. que só tenha uma porta de escrita de registrador. fazemos várias suposições.5 [10] <4.10> Em um superescalar estático de dois despachos. supomos que as instruções executadas no programa são distribuídas da seguinte forma: BEQ previstas BEQ previstas ALU LW SW corretamente incorretamente a. 1. 40% 20% 5% 25% 10% b.5 [20] <4. que ganho de velocidade é obtido acrescentando a capacidade de prever dois desvios por ciclo? Considere uma política de stall-no-desvio para os desvios que o previsor não pode tratar.000. mas para um processador de quatro des- pachos.10> Qual é o ganho de velocidade do uso do seu código do Exercício 4. 1. Primeiro.30.000) iterações desse loop forem executadas.30.29.10> Se muitas (por exemplo. que ganho de velocidade é obtido acrescentando uma segunda porta de escrita de registrador? 4. Terceiro.29. que ganho de velocidade é obtido tornando a previsão de desvio perfeita? 4. Você pode usar os registradores de $10 a $20 quando alterar o código para eliminar dependências. 4. 1. Finalmente.30. 31. .31 Os problemas neste exercício referem-se ao loop a seguir. Instruções x86 Tradução tipo MIPS a. A memória de dados tem uma porta de leitura (para instruções no estágio MRD) e uma porta de escrita separada (para instruções no estágio WB). de modo que os únicos hazards com que você tem de se preocupar são hazards de recursos e hazards de dados. Além disso. subtrai esse valor do registrador eax e coloca o resultado de volta no registrador eax. e não para as primeiras e últimas iterações do loop. 4. 4. Se a operação precisar de um segundo valor de dados de origem. MRD realiza a leitura da memória. O último (normalmente segundo) operando da instrução indica o primeiro valor dos dados de origem e o destino.11> Que CPI seria obtido se a versão x86 desse loop for executada em um processador de um despacho com escalonamento estático e um pipeline de sete es- tágios? Os estágios do pipeline são IF. Você pode considerar que esse loop executa muitas iterações antes de terminar. b.2 [20] <4. ARD calcula o endereço do local de memória a ser lido. Observe que a maioria das instruções x86 nesse problema possui dois operandos cada. ID. Ao determinar o desempenho.11> Que CPI seria alcançado se a versão MIPS desse loop fosse executada em um processador de um despacho com escalonamento estático e uma pipeline de cinco estágios? 4. você pode considerar o suporte de encaminhamento total e previsão de desvio perfeita sem slots de delay. que é dado como código x86 e também como uma tradução MIPS desse código.eax” lê o local da memória apontado pelo registrador edx.16 Exercícios 353 originais seja desmembrado em dez novos estágios. EXE executa a operação e WB escreve o resultado no registrador ou na memória.1 [20] <4. Os estágios IF e ID são semelhantes àqueles no pipeline MIPS de cinco estágios. ARD. isso significa que você só precisa determinar qual seria o desempenho no “estado fixo”. A que conclusão você pode chegar sobre a im- portância da boa previsão de desvio quando a profundidade do pipeline do processador é aumentada? Exercício 4. MRD. “sub (edx).31. e que os desvios sejam executados no primeiro de dez novos estágios EX. EXE e WB. este é indicado pelo outro operando da instrução. Por exemplo. de modo que você só possa reordenar as instruções que não possuem dependências de dados.31. mas ainda não confirmadas) em determinado momento? .31. o resultado do desvio é resolvido pelas instruções buscadas depois do desvio errado ter sido descartado e o próximo ciclo do processador fará a busca no caminho correto. 4. Para as dependências de controle.2 [5] <4.11> Que CPI seria obtido se a versão MIPS desse loop fosse executada em um processador de um despacho com escalonamento dinâmico? Suponha que nosso processador não esteja realizando renomeação de registrador. renomeie a versão MIPS desse loop para eliminar o máximo de dependências de dados possível entre as instruções na mesma iteração do loop. Considere que o processador nunca sofreu stall por dados e dependências de recursos. usando seu novo código renomeado. 4.354 Capítulo 4  O Processador 4. 25 99% 4.31.31.31. quantas instruções de desvio pode-se esperar que estejam “em andamento” (já apanhadas.6 [20] <4. mas desta vez suponha que o proces- sador atribui um novo nome ao resultado de cada instrução à medida que essa instrução é decodificada. o processador utiliza a previsão de desvio e continua a fazer a busca no caminho de dados previsto.4.4 [20] <4. repita o Exercício 4. Desvios como % de todas Precisão da previsão de desvio as instruções executadas a. depois executa essas micro-operações em um pipeline de cinco estágios e um despacho com escalonamento estático.31. 4. e depois renomeia os registradores usados por instruções subsequentes para usar valores de registrador corretos. 30 20 4. 4.4.11> Quantas instruções espera-se que sejam executadas entre o momento em que um erro de previsão de desvio é detectado e o momento em que o próximo erro de previsão de desvio é detectado? Os problemas restantes neste exercício consideram a seguinte profundidade de pipeline e que o resultado do desvio é determinado no estágio de pipeline seguinte (contando a partir do estágio 1): Profundidade do pipeline Resultado do desvio conhecido no estágio a.3 [20] <4.11> Que CPI seria obtida se a versão x86 desse loop fosse executada em um processador que traduz essas instruções internamente para micro-operações tipo MIPS. Agora. Observe que o contador de instrução usado no cálculo do CPI para esse processador é o contador de instrução do x86. 15 12 b.11> Repita o Exercício 4.32.11> Em um processador de quatro despachos com esses parâmetros de pipeline.5 [30] <4. 25 95% b. como a busca e execução do número máximo de instruções por ciclo se existirem hazards de controle. Exercício 4.10.11> Supondo que existam muitos registradores livres à disposição. 4.32.10.1 [5] <4.32 Os problemas neste exercício consideram que os desvios representam as frações de todas as instruções executadas e a precisão da previsão de desvio apresentadas na tabela a seguir. Se o desvio foi previsto erronea- mente. ).11> Repita o Exercício 4.33.11> Se não houver erros de previsão de desvio e dependências de dados. Os problemas neste exercício referem-se a um processador com o seguinte número de estágios de pipeline e instruções emitidas por ciclo: Profundidade de pipeline Largura do despacho a. mas desta vez cada instrução executada tem uma dependência de dados RAW com a instrução que é executada logo em seguida.32. a menos que o problema especifique de outra forma.1 [10] <4. Para os três problemas restantes neste exercício.3 [5] <4.32.4 [10] <4. 10% 5 98% 1% 4.11> Qual é o ganho de velocidade obtido pela mudança do processador de quatro para oito despachos? Suponha que os processadores de oito e quatro despachos difiram apenas no número de instruções por ciclo.5. 30 8 4.11> Se tivermos a fração dada de instruções de desvio e precisão da previsão de desvio.4 [10] <4.33.32.11> Qual é o ganho de velocidade da execução de desvios um estágio antes em um processador de quatro despachos? 4.33 Este exercício explora como a previsão do desvio afeta o desempenho de um processador de despacho múltiplo com pipeline profundo. que porcentagem de todos os ciclos é gasta inteiramente apanhando instruções de caminho errado? Ignore o número da perda de desempenho. qual é a melhoria de desempenho esperada em relação a um processador de um despacho com um pipeline clássico de cinco estágios? Suponha que o tempo de ciclo de clock diminua em proporção ao número de estágios de pipeline. 4.11> Quantas instruções são apanhadas do caminho errado para cada erro de previsão de desvio em um processador de quatro despachos? 4.33. considere as estatísticas a seguir sobre qual porcentagem de instruções são desvios.16 Exercícios 355 4.11> Quantas portas de leitura de registrador o processador deverá ter para evitar quaisquer hazards de recursos devido a leituras de registrador? 4. 10% 9 96% 5% b.2. o forwarding permite que instruções consecutivas sejam executadas em ciclos back-to-back. 4. 4.32. estágio de resolução de desvio etc. precisão do previsor e perda de desempenho devido a erros de previsão de desvio: Desvios como uma fração Desvios Precisão Perda de todas as instruções executados do previsor de desempenho executadas no estágio a.33.2 [10] <4. e de outras maneiras sejam idênticas (profundidade de pipeline.32. 15 2 b.6 [10] <4. Você pode assumir que nenhum ciclo de stall é necessário.5 [10] <4. Exercício 4.33.11> Qual é o ganho de velocidade da execução dos desvios um estágio antes em um processador de oito despachos? Discuta a diferença entre esse resultado e o resultado do Exercício 4. .3 [10] <4. ou seja. 1.3 [10] <4.2 para o seu caminho de dados estendido do Exercício 4.5 (metade) em relação ao mesmo processador com um previsor de desvio ideal? Exercício 4. AND Rd.13.35 Este exercício tem por finalidade ajudá-lo a entender melhor o relacionamento entre o projeto de ISA e o pipelining.Rs. 4. 4.6 [10] <4.34 Este exercício tem por finalidade ajudá-lo a entender a discussão da falácia “Pipelining é fácil”. SW Rt. qual deverá ser nossa precisão da previsão de desvio? Ignore o número de precisão do previsor indicado. Exercício 4.Imm Reg[Rt]=Reg[Rs]+Imm 4.34.11> Qual deverá ser a precisão da previsão de desvio se quisermos ter um ganho de velocidade de 0.Rs.34.34. Os problemas neste exercício consideram que temos um processador em pipeline com despacho múltiplo com o seguinte número de estágios de pipeline.13> Descreva como estender o seu caminho de dados do Exercício 4.34.5 [20] <4. ADDI Rt. AND Rd.4.1? Observe que a exceção de ins- trução indefinida deverá ser ativada sempre que o processador encontrar qualquer outro tipo de instrução.34.34.13> Descreva um caminho de dados em pipeline para dar suporte apenas a essa instrução.13> Descreva os requisitos das unidades de forwarding e detecção de hazard para o seu caminho de dados do Exercício 4.13> O que precisa ser feito para dar suporte a exceções de instrução indefinidas no seu caminho de dados do Exercício 4. instruções remetidas por ciclo.33.34.Rt Reg[Rd]=Reg[Rs] AND Reg[Rt] b.1 de modo que também dê suporte a essa instrução.34. Seu caminho de dados estendido deverá ser criado para dar suporte apenas a instâncias dessas duas instruções.33.Rt Reg[Rd]=Reg[Rs] + Reg[Rt] b. da Seção 4.4 [10] <4.1 [10] <4.Offs(Rs) Mem[Reg[Rs]+Offs]=Reg[Rt] 4.Rs.34. Os dois problemas restantes neste exercício também se referem a esta instrução MIPS: Instrução Interpretação a. Seu caminho de dados deverá ser criado com a hipótese de que as únicas instruções que serão executadas são instâncias dessa instrução. Os quatro primeiros problemas neste exercício referem-se à seguinte instrução MIPS: Instrução Interpretação a. 4.2 [10] <4. . estágio em que os resultados do desvio são resolvidos e precisão do previsor de desvio.5 [10] <4. 4.11> Se quisermos limitar stalls devido a desvios mal previstos a não mais que determinada porcentagem do tempo de execução ideal (sem stalls).356 Capítulo 4  O Processador 4.13> Repita o Exercício 4.34. c.8.Offset(Rs) Mem[Reg[Rs]+offset]=Reg[Rt] Reg[Rs]=Reg[Rs]+4 b. 4.35.8. nenhuma instrução que esteja no mesmo estágio do pipeline que o desvio é apanhada do caminho errado.35.4 podem estar “em voo” dentro do pipeline desse processador? Dizemos que uma iteração está “em voo” quanto pelo menos uma de suas instruções foi apanhada e ainda não foi confirmada.7. Exercício 4. mas agora considere que 10% dos desvios executados têm todos os quatro slots de delay preenchidos com instrução útil. e 40% não têm instruções úteis em seus slots de delay.1 [5] <4. 4. 20% têm apenas três instruções úteis nos slots de delay (o quarto slot de delay é um nop).13> Repita o Exercício 4.35.35. considerando que nossa ISA requer apenas um slot de delay para cada desvio. Você pode considerar que as variáveis a.3 [10] <4.6 [10] <4. i e j são mantidas nos registradores r1.13> Repita o Exercício 4.16 Exercícios 357 Precisão Desvios Profundidade Largura do Desvios executados do previsor de como % de do pipeline despacho no estágio desvio instruções a.5 [10] <4. ou seja. 25 4 15 96% 15% 4.35.8.4 [10] <4. 4.35.35.36 Este exercício tem por finalidade ajudá-lo a entender melhor a última armadilha da Seção 4.4 para um processador que tem dois slots de delay para cada desvio.10. b. 30% têm apenas duas instruções úteis nos slots de delay.2.35.35. SWI Rt.Rd(Rs) Mem[Reg[Rd]+Reg[Rs]]=Reg[Rt] . b. r2. 4.8. 4. você também pode considerar que a instrução de desvio mal prevista sempre é a última instrução a ser apanhada em um ciclo.13 — deixar de considerar o pipelining no projeto do conjunto de instruções.13> Traduza este loop em C para instruções MIPS. 15 2 10 90% 25% b.13> Quantas iterações do seu loop do Exercício 4. Os quatro primeiros problemas neste exercício referem-se à seguinte nova instrução MIPS: Instrução Interpretação a. 4.13> Os hazards de controle podem ser eliminados acrescentando slots de delay de desvio. 4. 4. 4. 4. Para tornar seus cálculos mais fáceis. SWINC Rt.r3. Quantos slots de delay precisam acompanhar cada desvio se quisermos eliminar todos os hazards de controle neste processador? 4.2 [10] <4. Tente preencher os slots de delay com instruções não NOP sempre que possível. Os três problemas restantes neste exercício referem-se ao seguinte loop em C: a.r4 e r5.13> Qual é o ganho de velocidade que seria obtido usando quatro slots de delay de desvio para reduzir os hazards de controle neste processador? Considere que não existem dependências de dados entre as instruções e que todos os quatro slots de delay podem ser preenchidos com instruções úteis sem aumentar o número de ins- truções executadas. 4. 36. quais estruturas em qual estágio) que são necessárias para admitir diretamente (sem micro-operações) esta instrução.13> Repita o Exercício 4.36. Quando ADDM é traduzida. que ganho de velocidade é alcançado usando essa instrução no lugar de uma sequência de três instruções (LW.2 [10] <4.37 Este exercício explora algumas das escolhas envolvidas no pipelining. Exercício 4. 4.4 [10] <4. 4.3 [20] <4. Em um processador no qual ADDM foi acrescentada.358 Capítulo 4  O Processador 4. de alguma forma (mágica). como o tempo do ciclo de clock e a utilização dos recursos de hardware. e não a stalls acrescentados pela própria tradução de ADDM. estes problemas consideram o seguinte desmembramento de ciclos de clock.36.1 [10] <4.36.5 [10] <4.13> Traduza esta instrução para micro-operações MIPS. esse estágio extra pode ser removido e.6 [10] <4.3. discuta as mudanças no pipeline (quais estágios.13> Se quisermos acrescentar esta instrução à ISA do MIPS. b. mas agora considere que ADDM fosse aceita incluindo um estágio do pipeline. Os três primeiros problemas neste exercício referem-se ao código MIPS a seguir.11.13> Como você mudaria o pipeline MIPS de cinco estágios de modo a acrescentar suporte à tradução de micro-operação necessária para aceitar essa nova instrução? 4. sem criar hazards de recurso.37. metade dos stalls de dados existentes são eliminados. 4. 25% 20% 20% 10% 3% 10% 12% b. Observe que a eliminação do stall de dados só se aplica a stalls que existiam antes da tradução de ADDM. como resultado.13> Dado esse desmembramento dos ciclos de execução no processador com suporte direto à instrução ADDM. O código é escrito supondo-se que o proces- sador não utiliza slots de delay.36. 4. 4. a.1 [5] <4. 25% 10% 25% 20% 5% 10% 5% 4.14> Quais partes do caminho de dados de ciclo único são usadas por todas essas instruções? Quais partes são as menos utilizadas? . 4.13> Com que frequência você espera que essa instrução possa ser usada? Você acha que haveria justificativa se acrescentássemos essa instrução à ISA do MIPS? Os dois problemas seguintes neste exercício são referentes à inclusão de uma nova ins- trução ADDM à ISA. 4.11. aceita com um pipeline clássico de cinco estágios. ADD e depois SW)? Considere que a instrução ADDM é.5.36.36. segundo o qual a instrução termina nesse ciclo (ou qual stall está impedindo que uma instrução termine): ADD BEQ LW SW ADDM Stalls de controle Stalls de dados a. 70pJ 40pJ 40pJ 90pJ 100pJ 4. 200ps 70ps 20ps 90ps 90ps 250ps 15ps 10ps b.14> Repita o Exercício 4. 4. 4. 4.14> Qual é a utilização para a porta de leitura e de escrita da unidade de memória de dados? 4.3. 4. 4.5.37.37. 1 Leitura de Escrita de Leitura Escrita I-Mem Registrador Registrador de Mem D de Mem D a. 4.38 Este exercício explora a eficiência de energia e seu relacionamento com o desempenho.5 [10] <4.38. 4. compare os tempos de ciclo de clock do caminho de dados em pipeline de ciclo único e cinco estágios.1 [10] <4.14> Se custar $1 para reduzir a latência de um único componente do caminho de dados em 1ps. 4.4.2 [10] <4.14> Se a redução de energia é fundamental.2 [10] <4.37.3. qual seria o custo para reduzir o tempo de ciclo de clock em 20% no projeto de ciclo único e em pipeline? Exercício 4.6. 750ps 200ps 50ps 250ps 300ps 500ps 100ps 5ps 4.14> Dadas essas latências para elementos individuais do caminho de dados.3.14> Quanta energia é gasta para executar uma instrução ADD em um projeto de ciclo único e no projeto em pipeline com cinco estágios? 4. 4.38.6.5. 200ps 150ps 90ps 90ps 250ps b.16 Exercícios 359 4.6.37. 4.5.3 [10] <4. mas agora considere que só queremos dar suporte a instruções ADD.37. 4.6. Registradores e Memória de Dados. 4. Os problemas neste exercício consideram o consumo de energia a seguir para a atividade na Memória de Instrução. 4.14> Qual é a instrução MIPS no pior caso em termos do consumo de energia. 750ps 500ps 300ps 250ps 500ps . De quantos bits precisamos no total para os registradores de pipeline a fim de implementarmos o projeto em pipeline? Os três problemas restantes neste exercício consideram que os componentes do caminho de dados têm as seguintes latências: I-Mem Add Mux ALU Regs Mem D Extensão de sinal Shift-esq-2 a. 4. e qual é a energia gasta para executá-la? 4.6 [20] <4. Você pode considerar que os outros componentes do caminho de dados gastam uma quantidade de energia insignificante. como você mudaria o projeto em pipeline? Qual é a redução percentual na energia gasta por uma instrução LW após essa mudança? Registrador Leitura ou I-Mem Controle de leitura ou ALU escrita de escrita Mem D a.3 [10] <4.37.6. 4.3. 140pJ 70pJ 60pJ 140pJ 120pJ b.4 [10] <4.14> Suponha que já temos um projeto de ciclo único.38. fazemos suposições sobre como o consumo de energia muda se um estágio realizar seu trabalho mais lenta ou mais rapidamente do que isso.39.39.2 [10] <4.3 [10] <4.39 Os problemas neste exercício consideram que. 4.14> Repita o Exercício 4.39.14> Qual é o desempenho (em instruções por segundo)? 4.14> Podemos eliminar o sinal de controle MemRead e fazer com que a memória de dados seja lida em cada ciclo.4. é possível sacrificar alguma velocidade em um cir- cuito a fim de reduzir seu consumo de energia.6.14> Qual é o impacto das suas mudanças do Exercício 4. os ciclos do processador são gastos como na tabela a seguir. Suponha que possamos reduzir o consumo de energia por um fator de X (nova energia é 1/X vezes a energia antiga) se aumentarmos a latência por um fator de X (nova latência é X vezes a latência antiga). podemos ter MemRead = 1 permanentemente.6. ADD BEQ LW SW Stalls de controle Stalls de dados a.6. IF ID EX MEM WB a.38.2 para esse processador ajustado. durante uma execução do programa. 4.6. .14> Que estágios do pipeline você pode tornar mais lentos e por quanto.4 [10] <4. mas desta vez o objetivo é minimizar a energia gasta por instrução enquanto o tempo de ciclo de clock aumenta não mais do que 10%. 25% 20% 20% 10% 10% 15% b. podemos ajustar as latências dos estágios do pipeline para minimizar o consumo de energia sem sacrificar qualquer desempenho.39. O estágio gasta essa energia para realizar seu trabalho dentro da latência indicada. 200ps/75pJ 170ps/45pJ 220ps/100pJ 210ps/100pJ 150ps/35pJ 4. ou seja.5 [10] <4.6. 4.38. Qual é o efeito dessa mudança sobre a frequência de clock e consumo de energia? 4.6. 250ps/100pJ 350ps/45pJ 150ps/50pJ 300ps/150pJ 200ps/50pJ b. 4. Em vários dos problemas a seguir.39.6 [10] <4. sem afetar o tempo de ciclo de clock? 4.38.1 [10] <4.38. Observe que nenhuma energia é gasta no estágio MEM durante um ciclo em que não existe acesso à memória. Um ciclo é “gasto” em uma ins- trução se o processador concluir esse tipo de instrução nesse ciclo. Explique por que o processador ainda funciona corretamente após essa mudança. um ciclo é “gasto” em um stall se o processador não puder concluir uma instrução nesse ciclo devido a um stall.360 Capítulo 4  O Processador 4.14> Normalmente.39. Repita o Exercício 4. 4.3 sobre o desempenho? 4.4 [20] <4.14> Se uma unidade ociosa gasta 10% da potência que gastaria se estivesse ativa. Agora. 4. 4. 25% 10% 25% 20% 10% 10% Os problemas neste exercício também consideram que os estágios de pipeline individuais possuem latências e consumos de energia a seguir. De modo semelhante.39.14> Qual é a potência dissipada em watts (joules por segundo)? 4. ne- nhuma energia é gasta no estágio WB em um ciclo no qual não existe escrita de registrador.5 [10] <4. qual é a energia gasta pela memória de instrução em cada ciclo? Que por- centagem da energia geral gasta pela memória de instrução essa energia ociosa representa? Exercício 4. 2. Você não precisa de um inversor. 2. §4. Stall no resultado LW.10.6 [10] <4.5. Desvio e OpALU0 são idênticos. página 330: Sim. Seções “Verifique §4. Ambos. o restante está incorreto. MemtoReg e RegDst são opostos um do outro. página 343: 1. §4. Além disso. §4. Hardware. pois ela é executada logicamente antes das outras.1. 4. Memória.39. Previsão dinâmica. .12. 3. Hardware. Ambos.6. página 403: 1. 9.2. 7.6. página 303: 3 de 5: Controle. mas agora suponha que o consumo de energia seja reduzido por um fator de X2 quando a latência se torna X vezes maior.11. 4. página 383: 1. Previsão não tomada.4.9.16 Exercícios 361 4. Bypassing do primeiro resultado de ADD escrito em $t1. Ambos. página 4. página 307: falso. Nenhum stall ou bypassing é necessário. Software.39.12. §4. Hard- ware. página 4.12-5: A melhor resposta é a 2 (veja a Elaboração na página 371).2? §4. você mesmo” §4.3. 4. Caminho de dados.5. Ambos. §4. 6. II. C. página 315: I. Elementos de estado disparados na borda tornam a leitura e escrita simultâneas tanto possíveis quanto não ambíguas. Entrada e Saída estão Respostas das faltando.8. §4. 8. 2. Quais são as economias de potência em comparação com o que você calculou para o Exercício 4. 3.39.14> Repita o Exercício 4. §4. Previsão tomada. §4. página 358: Afirmações 2 e 4 estão corretas. 3. Hardware. basta usar o outro sinal e inverter a ordem das entradas para o multiplexador! §4. A.12-3: Afirmações 1 e 3 são ambas verdadeiras. página 404: Duas primeiras são falsas e duas últimas são verdadeiras. página 391: A primeira instrução. 5. 5 O ideal seria ter uma capacidade de memória infinitamente grande Grande e Rápida: a ponto de qualquer palavra Explorando a Hierarquia específica … estar imediatamente disponível. mas com acessibilidade 5. cada uma com 5.2 Princípios básicos de cache  368 de memórias.3 Medindo e melhorando o desempenho capacidade maior do que da cache  382 a anterior.1 Introdução  364 de construir uma hierarquia 5. H. W.4 Memória virtual  396 menos rápida. Goldstine e J. H.6 Máquinas virtuais  423 Preliminary Discussion of the Logical Design of an Electronic Computing Instrument.5 Uma estrutura comum para hierarquias de memória  417 A. 1946 . von Neumann  5. Burks. 5. … Somos … forçados de Memória a reconhecer a possibilidade 5. 12 Comentários finais  440 5.13 Perspectiva histórica e leitura adicional  441 5.5.9 Material avançado: implementando controladores de cache  434 5.11 Falácias e armadilhas  438 5.10 Vida real: as hierarquias de memória do AMD Opteron X4 (Barcelona) e Intel Nehalem  434 5.8 Paralelismo e hierarquias de memória: coerência de cache  430 5.14 Exercícios 441 Os cinco componentes clássicos de um computador .7 Usando uma máquina de estado finito para controlar uma cache simples  426 5. Por exemplo. no breve. j Localidade espacial (localidade no espaço): se um item é referenciado. os acessos sequenciais aos elementos de um array ou de um registro terão altos índices de localidade espacial. Antes de vermos como a ilusão é realmente criada. mas não há nada sobre o EDSAC. Há dois tipos diferentes de localidade: localidade temporal  O princípio j Localidade temporal (localidade no tempo): se um item é referenciado. Com isso. Então. você também percebeu que havia outro livro ao lado dele na es- dados com endereços próximos tenderão a ser referenciados em tante sobre computadores mecânicos. volta às estantes e procura um outro livro. . ele tenderá a ser ná-lo. mais tarde. Os acessos a dados também exibem uma localidade espacial natural. se um local plo. as instruções são acessadas sequencialmente. Você encontra um livro sobre os primeiros computadores britânicos. um programa não acessa todo o seu código ou dados ao mesmo tempo com igual probabilidade. então. então. são descritos nos livros encontrados. existe uma boa probabilidade de que muitos dos tópicos de que precisa possam ser encontrados neles. portanto. as instruções e os dados provavelmente são acessados de modo repetitivo. resolveu trazer também esse livro. Você está sentado em uma biblioteca examinando uma pilha de livros retirada das estantes. ele tenderá em que se um local de dados é a ser referenciado novamente em breve. Se você trouxe um livro à mesa para exami- referenciado. Por exemplo. então. referenciado novamente em breve. Veremos como a localidade espacial é usada nas hierarquias de memória um pouco mais adiante neste capítulo. os itens localidade espacial  O princípio cujos endereços estão próximos tenderão a ser referenciados em breve. Por exem- da localidade em que. Os tópicos deste capítulo ajudam os programadores a criar essa ilusão. Você descobre que vários computadores importantes. Com uma boa seleção de livros sobre a mesa à sua frente. mostrando altas quantidades de localidade temporal. encontrou algo útil. Como. a maioria dos programas contém loops e. ao trazer o livro sobre os primeiros computadores ingleses para pesquisar de dados é referenciado. Caso contrário. Assim como você não precisou acessar todos os livros da biblioteca ao mesmo tempo com igual probabilidade. Os livros sobre o mesmo assunto são colo- cados juntos na biblioteca para aumentar a localidade espacial. Assim como os acessos aos livros na estante exibem naturalmente a localidade. assim como seria impossível você colocar todos os livros da biblioteca em sua mesa e ainda encontrar o desejado rapidamente. a loca- lidade nos programas surge de estruturas de programa simples e naturais. você pode gastar mais do seu tempo apenas usando os livros na mesa sem voltar às estantes. Ter vários livros na mesa economiza seu tempo em comparação a ter apenas um livro e constantemente precisar voltar às estantes para devolvê-lo e apanhar outro. que fala sobre o EDSAC. os sobre o EDSAC. vamos considerar uma analogia simples que ilustra os princípios e mecanismos-chave utilizados. os programas mostram alta localidade espacial. O princípio da localidade diz que os programas acessam uma parte relativamente pequena do seu espaço de endereçamento em qualquer instante do tempo. sobre os quais precisa escrever. é provável que precise examiná-lo novamente em breve. exatamente como você acessou uma parte bastante pequena da coleção da biblioteca. em geral. Esse princípio da localidade sustenta a maneira como você fez seu trabalho na biblioteca e o modo como os programas funcionam. os programadores têm desejado quantidades ilimitadas de memória rápida. seria impossível tornar rápida a maioria dos acessos à memória e ainda ter memória grande nos computadores. Suponha que você fosse um estudante fazendo um trabalho sobre os importantes desenvolvimentos históricos no hardware dos computadores. qual. O mesmo princípio nos permite criar a ilusão de uma memória grande que podemos acessar tão rapidamente quanto uma memória muito pequena.364 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória 5.1   Introdução Desde os primeiros dias da computação. enquanto os níveis mais próximos do processador (caches) usam SRAM (Static Random Access Memory). A terceira tecnologia. usada para implementar o maior e mais lento nível na hierarquia. O objetivo é oferecer ao usuário o máximo de memória disponível na tecnologia mais barata. mas pode ser acessada como se fosse totalmente construída com a memória mais rápida. As memórias mais estrutura que usa múltiplos níveis rápidas são mais caras por bit do que as memórias mais lentas e.000ns 0. A memória flash substituiu os discos em muitos dispositivos embutidos. e todos os dados são armazenados no nível mais baixo.5ns 2000 a 5. conforme a distância da CPU aumenta.4.1  A estrutura básica de uma hierarquia de memória. Implementando o sistema de memória como uma hierarquia.5 a 2. os livros em sua mesa FIGURA 5. dom Access Memory).1 Introdução 365 Tiramos vantagem do princípio da localidade implementando a memória de um computador como uma hierarquia de memória. portanto.1 mostra que a memória mais rápida está próxima do processador e a memória mais lenta e barata está abaixo dele. portanto.20 a 2 Devido a essas diferenças no custo e no tempo de acesso.000 DRAM 50 a 70ns 20 a 75 Disco magnético 5. enquanto se fornece acesso na velocidade oferecida pela memória mais rápida. o usuário tem a ilusão de uma memória que é tão grande quanto o maior nível da hierarquia. A DRAM é mais barata por bit do que a SRAM. usando valores típicos em 2008: Tecnologia de memória Tempo de acesso típico US$ por GB em 2008 SRAM 0. os dados são organizados como uma hierarquia: um nível mais próximo do processador em geral é um subconjunto de qualquer nível mais distante.000.) O tempo de acesso e o preço por bit variam muito entre essas tecnologias. 5. A Figura 5.000. têm maior capacidade para a mesma quantidade de silício. são menores.9 do Apêndice C. veja Seção 6. veja Seção 6. como mostra a tabela a seguir. A memória principal é implementada por meio de DRAM (Dinamic Ran. existem três tecnologias principais usadas na construção das hierarquias de memórias e o tempo de acesso memória. embora seja substancialmente mais lenta.4. Por analogia. também aumentam. A diferença de preço ocorre porque a DRAM usa significativamente menos área por bit de memória e as DRAMs. . é vantajoso construir memória como uma hierarquia de níveis. e pode levar a um novo nível na hierarquia de armazenamento para computadores de desktop e servidor. (A memória flash é usada no lugar dos discos em muitos dispositivos embutidos. o tamanho das Hoje. Da mesma forma. Uma hierarquia de memória consiste em hierarquia de memória Uma múltiplos níveis de memória com diferentes velocidades e tamanhos. de memórias.000 a 20. a diferença de velocidade ocorre devido a diversos fatores descritos na Seção C. normalmente é o disco magnético. como os compiladores geram código e mesmo como as passar o bloco a quem o solicitou. acessado para recuperar o bloco com taxa de acertos  A proporção dos os dados requisitados. os níveis levam cada vez mais tempo para serem acessados. A penalidade de falha é o tempo de substituição de um tempo necessário para determinar bloco no nível superior pelo bloco correspondente do nível inferior. inclusive como o sistema operacional experimentou a falha. o tempo de apanhar outro livro das estantes e falha. memória. então. exatamente como poderíamos encontrar em uma hierarquia de bibliotecas de campus. isso é chamado um acerto (análogo a encontrar a informação em um dos livros em sua mesa). por sua vez. os conceitos usados para construir sistemas de memória a outro e inseri-lo no nível que afetam muitos outros aspectos de um computador. ria encontrados no nível superior.2 mostra que a unidade de informação mínima que pode estar presen- bloco (ou linha) A unidade te ou ausente na hierarquia de dois níveis é denominada um bloco ou uma linha. Além disso. a unidade de informação que está presente ou não é chamada de um bloco ou uma linha. você vai da sua mesa até as es- acessos à memória encontrados em tantes para encontrar o livro desejado. o sistema de memória é necessariamente um importante fator para se determinar o desempenho. o tempo de acerto será muito menor do que o tempo para acessar o necessário na busca de um bloco próximo nível na hierarquia. que. O nível inferior em uma hierarquia é. mas os dados são co- piados apenas entre dois níveis adjacentes ao mesmo tempo. O tempo de acerto é o tempo de acerto  O tempo tempo para acessar o nível superior da hierarquia de memória. estar presente ou ausente em uma Se os dados requisitados pelo processador aparecerem em algum bloco no nível superior. a requisição é chamada uma falha. O nível superior – o que está mais perto do processador – é menor e mais rápido (já que usa tecnologia mais cara) do que o nível inferior. colocá-lo na mesa). é um subconjunto de todas as bibliotecas do campus. aplicações usam o computador. É claro que. A confiança nas hierarquias de memória para obter FIGURA 5. Como o nível superior é menor e construído usando partes de memó- penalidade de falha  O tempo ria mais rápidas. transmiti-lo de um nível Como veremos neste capítulo. incluindo o para consultar os livros na mesa). o tempo para servir acertos e falhas é um aspecto importante. Uma hierarquia de memória pode consistir em múltiplos níveis. A taxa de falhas (1 – taxa de acertos) é a proporção dos acessos à memória não encontrados acessos à memória não encontrados no nível superior. Se os dados não forem encontrados no nível superior. o tempo necessário hierarquia de memória. como todos os programas gastam muito do seu tempo acessando a memória. Dentro de cada nível. de modo que podemos concentrar nossa atenção em apenas dois níveis. conforme nos afastamos do processador. em um nível da hierarquia de Como o desempenho é o principal objetivo de ter uma hierarquia de memória. cache. em mínima de informação que pode nossa analogia da biblioteca. mais o tempo para se o acesso é um acerto ou uma transferir esse bloco ao processador (ou. e depois gerencia a memória e a E/S. transferimos um bloco inteiro quando copiamos algo entre os níveis. Em geral. tar e apanhar um novo livro nas estantes. ela normalmente é usada como uma medida do desem- taxa de falhas  A proporção de penho da hierarquia de memória. (Continuando com nossa analogia. um bloco de informação seria um livro. . A Figura 5.) incluindo o tempo para acessar o bloco. de um nível inferior para um nível (O tempo para examinar os livros na mesa é muito menor do que o tempo para se levan- superior da hierarquia de memória. que inclui o tempo neces- necessário para acessar um nível da sário para determinar se o acesso é um acerto ou uma falha (ou seja.) A taxa de acertos é a fração dos acessos à memó- um nível da hierarquia de memória.2  Cada par de níveis na hierarquia de memória pode ser imaginado como tendo um nível superior e um nível inferior.366 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória formam um subconjunto da biblioteca onde você está trabalhando. que é o principal componente da penalidade de falha. Portanto. Como os sistemas de memória são essenciais para o desempenho. porém mais lentos. permite que o processador tenha um tempo de acesso determinado principalmente pelo nível 1 da hierarquia e ainda tenha uma memória tão grande quanto o nível n. As Colocando em hierarquias de memória tiram proveito da localidade temporal mantendo mais perspectiva próximos do processador os itens de dados acessados mais recentemente. Se a taxa de acertos for bastante alta.1 Introdução 367 desempenho tem indicado que os programadores (que costumavam pensar na memória como um dispositivo de armazenamento plano e de acesso aleatório) agora precisam entender as hierarquias de memória de modo a alcançarem um bom desempenho. alguns sistemas usam fita ou um servidor de arquivos numa rede local como os próximos níveis da hierarquia. As hierarquias de memória tiram proveito da localidade espacial movendo blocos consistindo em múltiplas palavras contíguas na memória para níveis superiores na hierarquia.18. Para mostrar como esse entendimento é importante. os projetistas de computadores têm dedicado muita atenção a esses sistemas e desenvolvido sofisticados mecanismos voltados a melhorar o desempenho do sistema de memória. Neste capítulo. vamos fornecer alguns exemplos. 5. Manter essa ilusão é o assunto deste capítulo. Os programas apresentam localidade temporal (a tendência de reutilizar itens de dados recentemente acessados) e localidade espacial (a tendência de referenciar itens de dados que estão próximos a outros itens recentemente acessados).3  Este diagrama mostra a estrutura de uma hierarquia de memória: conforme a dis- tância do processador aumenta. Os acessos de falha vão para os níveis mais baixos da hierarquia.3 mostra que uma hierarquia de memória usa tecnologias de memória menores e mais rápidas perto do processador. Essa estrutura. que são maiores. veremos as principais ideias conceituais. embora muitas simplificações e abstrações tenham sido usadas no sentido de manter o material praticável em tamanho e complexidade. como a Figura 5. FIGURA 5. a hierarquia de memória terá um tempo de acesso efetivo próximo ao tempo de acesso do nível mais alto (e mais rápido) e um tamanho igual ao do nível mais baixo (e maior). o tamanho também aumenta. Embora o disco local normalmente seja a parte inferior da hierarquia. Na maioria dos sistemas. os acessos de acerto no nível mais alto da hierarquia podem ser processados rapidamente. o que significa que os dados não podem estar presentes no nível i a menos que também estejam presentes no nível i + 1. . A Figura 5. com os mecanismos de operação apropriados. a memória é uma hierarquia verdadeira. A maneira mais simples de atribuir um local na cache para cada palavra da memória é atribuir um local na cache baseado no endereço da palavra na memória. Essa referência causa uma falha que força a cache a buscar Xn na memória e inseri-la na cache. começaremos a ver uma cache muito simples na qual cada requisição do processador é uma palavra e os blocos também consistem em uma única palavra. As caches apareceram inicialmente nos computadores de pesquisa no início da década de 1960 e nos computadores de produção mais tarde nessa mesma década. As caches tiram proveito da localidade temporal. X2. se estiver. X1. no Capítulo 4. Essa requisição resulta em uma falha.368 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Verifique você Quais das seguintes afirmações normalmente são verdadeiras? mesmo 1.3. antes e depois de requisitar um item de dados que não está inicialmente na cache. a cache contém uma coleção de referências recentes. como encontrá-lo? As res- postas a essas duas questões estão relacionadas. Olhando o cenário na Figura 5. embora permaneça o uso dominante da palavra cache. possui caches. Hoje. A maioria do custo da hierarquia de memória está no nível mais alto. 3. Cache: um lugar seguro para esconder ou guardar coisas. é fácil encontrar a palavra se ela estiver na cache. 4. e a palavra Xn é trazida da memória para a cache. todo computador de uso geral construído hoje. Se cada palavra pode ficar exatamente em um lugar na cache. Third College Em nosso exemplo da biblioteca. surgem duas perguntas a serem respondidas: como sabemos se o item de dados está na cache? Além disso. Em uma leitura. e o processador requisita uma palavra Xn que não está na cache. são simplesmente substituídas por caches. Nesta seção. dos servidores aos processadores embutidos de baixa capacidade. o valor retornado depende de quais blocos estão na cache.4  A cache. A maioria da capacidade da hierarquia de memória está no nível mais baixo.2  Princípios básicos de cache Dictionary of the American Language. (Os leitores que já estão familiarizados com os fundamentos de cache podem pular para a Seção 5.4. 2. Essa estrutura de cache é chamada FIGURA 5. a mesa servia como uma cache – um lugar seguro para Edition (1988) guardar coisas (livros) que precisávamos examinar. Webster's New World 5. então. As memórias no caminho de dados. Cache foi o nome escolhido para representar o nível da hierarquia de memória entre o processador e a memória prin- cipal no primeiro computador comercial a ter esse nível extra. . o termo também é usado para referenciar qualquer armazenamento usado para tirar proveito da localidade de acesso.… Xn-1. Antes de requisitar.4 mostra essa cache simples.) A Figura 5. imediatamente antes e após uma referência a uma palavra Xn que não está inicialmente na cache. a Figura 5. Como há oito palavras na cache. a cache pode ser acessada diretamente com os bits menos significativos.5 mostra como os endereços de memória entre 1dec (00001bin) e 29dec (11101bin) são mapeados para as posições 1dec (001bin) e 5dec (101bin) em uma cache diretamente mapeada de oito palavras. Os arquitetos omitem os bits de índice porque eles são redundantes. precisamos saber se a tag deve ser ignorada para essas entradas. Por exemplo.5  Uma cache diretamente mapeada com oito entradas mostrando os endereços das palavras de memória entre 0 e 31 que são mapeadas para os mesmos locais de cache. A tag precisa apenas conter a parte superior do endereço. na necessárias para identificar se o Figura 5. O mapeamento típico entre endereços e locais de cache para uma estrutura de cache em que cada cache diretamente mapeada é simples. Portanto. algumas entradas de cache podem ainda estar vazias. Também precisamos de uma maneira de reconhecer se um bloco de cache não possui informações válidas. uma requisitada. o módulo pode ser calculado simplesmente usando os log2 bits menos significativos (tamanho da cache em blocos). 10001bin e 11001bin são todos mapeados para a entrada 001bin da cache. 01001bin. um endereço X é mapeado para a palavra de cache X módulo 8. então. mapeadas usam o mapeamento (Endereçode bloco)módulo(Númerode blocos decache na cache) Se o número de entradas na cache for uma potência de dois. Por exemplo. Por exemplo. como na Figura 5. por definição. Ou seja. vez que. os log2(8) = 3 bits menos significativos são usados como o índice da cache. os endereços 00001bin. enquanto os endereços 00101bin. já que o campo índice com os três bits menos significativos do endereço sele. 01101bin. a cache não tem dados válidos. o campo índice de cada endereço precisa ter o mesmo valor. As tags contêm as tag  Um campo em uma tabela informações de endereço necessárias para identificar se uma palavra na cache corres.5. Mesmo após executar muitas instruções. quase todas as caches diretamente local da memória é mapeado exatamente para um local na cache. como podemos saber se os dados na cache correspondem a uma palavra requi- sitada? Ou seja. quando um processador é iniciado. usado para uma hierarquia de memória que contém as ponde à palavra requisitada.4. e os campos de tag não terão significado. como sabemos se uma palavra requisitada está na cache ou não? Res- pondemos a essa pergunta incluindo um conjunto de tags na cache. bloco associado na hierarquia ço na tag. Como cada local da cache pode armazenar o conteúdo de diversos locais diferentes da memória. corresponde a uma palavra ciona o bloco. 10101bin e 11101bin são todos mapeados para a entrada 101bin da cache. Assim. informações de endereço correspondente aos bits que não são usados como índice para a cache.2  Princípios básicos de cache 369 de mapeamento direto. O método FIGURA 5. precisamos apenas ter os dois bits mais significativos dos cinco bits de endere. assim. . 5. Por exemplo. já que cada local da memória é mapeado diretamente para um mapeamento direto Uma local exato na cache. especifica de modo único o endereço de memória da palavra contida no bloco de cache. já que as leituras não precisam mudar o conteúdo da cache. Após vermos os aspectos básicos de como as leituras funcionam e como as falhas de cache podem ser tratadas. apenas uma escolha do que substituir. incluindo a ação para cada referência. Se o bit não estiver ligado. Logo. Em uma cache diretamente mapeada. a legenda da Figura 5. os três bits menos significativos de um endereço fornecem o número do bloco: Endereço decimal Endereço binário Acerto ou falha Bloco de cache atribuído (onde da referência da referência na cache foi encontrado ou inserido) 22 10110bin falha (7. Acessando uma cache A seguir. A palavra no endereço 18 (10010bin) deve ser trazida para o bloco de cache 2 (010bin). Agora. ela precisa substituir a palavra no endereço 26 (11010bin). Em geral. usado para selecionar o bloco. Na oitava referência. há apenas um lugar para colocar o item recém-requisi- tado e. Essa situação é análoga a precisar de um livro da estante e não ter mais espaço na mesa para colocá-lo – algum livro que já esteja na sua mesa precisa ser devolvido à estante. j um índice de cache. Na arquitetura MIPS.6f) (10010bin mod 8) = 010bin 16 10000bin acerto (10000bin mod 8) = 000bin Como a cache está vazia. usado para ser comparado com o valor do campo tag da cache.6b) (10110bin mod 8) = 110bin 26 11010bin falha (7. várias das primeiras referências são falhas. A Figura 5. a manipulação de leituras é um pouco mais simples do que a manipu- lação de escritas. A Figura 5. Esse comportamento permite que uma cache tire proveito da localidade temporal: palavras recentemente acessadas substituem palavras menos referenciadas recentemente. o número total de entradas em uma cache diretamente mapeada será uma potência de dois. vamos nos concentrar em explicar como uma cache trata das leituras. não pode haver uma correspondência para esse memória que indica que o bloco associado na hierarquia contém bloco. juntamente com o conteúdo da tag desse bloco.6 mostra como o conteúdo da cache muda em cada falha. sabemos onde olhar na cache para cada endereço possível: os bits menos sig- nificativos de um endereço podem ser usados para encontrar a entrada de cache única para a qual o endereço poderia ser mapeado. dados válidos. que já está no bloco de cache 2 (010bin). Como o campo índice é usado como um endereço para acessar a cache e como um campo de n bits possui 2n valores.6c) (11010bin mod 8) = 010bin 22 10110bin acerto (10110bin mod 8) = 110bin 26 11010bin acerto (11010bin mod 8) = 010bin 16 10000bin falha (7. temos demandas em conflito para um bloco. portanto. O índice de um bloco de cache.370 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória bit de validade  Um campo nas mais comum é incluir um bit de validade indicando se uma entrada contém um ende- tabelas de uma hierarquia de reço válido.6d) (10000bin mod 8) = 000bin 3 00011bin falha (7. vemos uma sequência de nove referências da memória a uma cache vazia de oito blocos.6 descreve as ações de cada referência à memória. No restante desta seção.7 mostra como um endereço referenciado é dividido em: j um campo tag. Como há oito blocos na cache. uma vez que as palavras são alinhadas como . examinaremos os projetos de cache para computadores reais e detalharemos como essas caches manipulam as escritas.6e) (00011bin mod 8) = 011bin 16 10000bin acerto (10000bin mod 8) = 000bin 18 10010bin falha (7. e uma referência a 11010bin causará uma falha subsequente. As figuras mostram o conteúdo da cache após cada falha na sequência ter sido tratada. de forma equivalente. pois a cache inclui o armazenamento para os dados e as tags.6  O conteúdo da cache é mostrado para cada requisição de referência que falha. O campo tag conterá apenas a parte superior do endereço. O endereço completo de uma palavra contida no bloco de cache i com o campo tag j para essa cache é j × 8 + i ou. com todos os bits de validade (entrada V da cache) inativos (N). a entrada para o endereço 11010bin (26) precisa ser substituída. 5. o índice 010bin possui tag 10bin e corresponde ao endereço 10010bin. 10000bin (acerto) e 10010bin (falha). de modo que n bits são usados para o índice. múltiplos de 4 bytes. j Uma cache diretamente mapeada. os dois bits menos significativos de cada endereço especificam um byte dentro de uma palavra e. . j O tamanho da cache é 2n blocos. A cache inicialmente está vazia. O processador requisita os seguintes endereços: 10110bin (falha). com os campos índice e tag mostrados em binário para a sequência de endereços na página 372. O tamanho do bloco mencionado anteriormente era de uma palavra. 10110bin (acerto). mas normalmente é de várias palavras. Por exemplo. 10000bin (falha). Para as situações a seguir: j Endereços em bytes de 32 bits. 11010bin (falha).2  Princípios básicos de cache 371 FIGURA 5. portanto. 00011bin (falha). O número total de bits necessários para uma cache é uma função do tamanho da cache e do tamanho do endereço. 11010bin (acerto). Quando o endereço 10010bin (18) é referenciado. na cache f anterior. a concatenação do campo tag j e o campo índice i. são ignorados ao selecionar uma palavra no bloco. e dois bits são usados para a parte de byte do endereço o tamanho do campo de tag é 32 − (n + m + 2). 10 bits são usados para indexar a cache.7  Para esta cache. Se a tag e os 20 bits superiores do endereço forem iguais e o bit de validade estiver ligado. Assim. a parte inferior do endereço é usada para selecionar uma entrada de cache consistindo em uma palavra de dados e uma tag. Consideramos endereços de 32 bits neste capítulo. O número total de bits em uma cache diretamente mapeada é 2n × (tamanhodo bloco + tamanhodo tag + tamanhodocampode validade). Caso contrário. de modo que m bits são usados para a palavra dentro do bloco. Como a cache tem 210 (ou 1024) palavras e um tamanho de bloco de 1 palavra. Embora esse seja o tamanho real em bits. deixando 32 – 10 – 2 = 20 bits para serem comparados com a tag. a convenção de nomeação é excluir o tamanho da tag e do campo de validade e contar apenas o tamanho dos dados.7 é chamada de cache de 4 KB. . a requisição é um acerto na cache e a palavra é fornecida para o processador. Como o tamanho do bloco é 2m palavras (2m+5 bits) e precisamos de 1 bit para o campo de validade.372 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. j O tamanho do bloco é 2m palavras (2m+2 bytes). a cache na Figura 5. ocorre uma falha. Essa cache mantém 1024 palavras ou 4 KB. então. A tag da cache é comparada com a parte superior do endereço para determinar se a entrada na cache corresponde ao endereço requisitado. o número de bits nessa cache é 2n × (2m × 32 + (32 − n − m − 2) + 1) = 2n × (2m × 32 + 31 − n − m). considerando um endereço de 32 bits? EXEMPLO Sabemos que 16KB são 4K palavras. o tamanho de cache total é 210 × (4 × 32 + (32 − 10 − 2 − 2) + 1) = 210 × 147 = 147 Kbits ou 18. um bloco será retirado da cache antes que muitas de suas palavras . com 16 bytes por bloco. que é 32 – 10 – 2 – 2 bits. 5. esse bloco mapeia todos os endereços entre 1200 e 1215. mais um bit de validade.8.15 vezes o necessário apenas para o armazenamento dos dados. o número total de bits na cache é aproximadamente 1. ou 128 bits de RESPOSTA dados mais uma tag.4KB para uma cache de 16KB. Para essa cache.2  Princípios básicos de cache 373 Bits em uma cache Quantos bits no total são necessários para uma cache diretamente mapeada com 16KB de dados e blocos de 4 palavras. Para qual número de bloco o endereço em bytes 1200 é mapeado? EXEMPLO A fórmula foi vista no início da Seção 5. A taxa de falhas pode subir posteriormente se o tamanho de bloco se tornar uma fração significativa do tamanho de cache. há 210 blocos.2. Portanto. Na verdade. com um tamanho de bloco de 4 palavras (22). Blocos maiores exploram a localidade espacial para diminuir as taxas de falhas. Mapeando um endereço para um bloco de cache multipalavra Considere uma cache com 64 blocos e um tamanho de bloco de 16 bytes. o que equivale a 212 palavras e. O bloco é dado por (Endereçodo bloco)módulo(Númerode blocosdecache) RESPOSTA Em que o endereço do bloco é Endereçoem bytes Bytes por bloco Observe que esse endereço de bloco é o bloco contendo todos os endereços entre  Endereçoem bytes    × Bytes por bloco  Bytes por bloco  e  Endereçoem bytes    × Bytes por bloco + (Bytes por bloco − 1)  Bytes por bloco  Portanto. Cada bloco possui 4 × 32. Como mostra a Figura 5. o endereço em bytes 1200 é o endereço de bloco 1200 = 75 6 que é mapeado para o número de bloco de cache (75 módulo 64) = 11. Como resultado. aumentar o tamanho de bloco normalmente diminui a taxa de fa- lhas. uma vez que o número de blocos que pode ser armazenado na cache se tornará pequeno e haverá uma grande competição entre esses blocos. Um esquema ainda mais sofisticado é organizar a memória de modo que a palavra requisitada seja transferida da memória para a cache primeiro. além disso. a probabilidade de que o processador precise de outra palavra de um bloco de cache diferente antes que a transferência seja concluída é alta. O restante do bloco. o desempenho da cache. Muitos processadores usam essa técnica para acesso a instruções. podemos ser capazes de ocultar um pouco do tempo de transferência de modo que a penalidade de falha seja efetivamente menor. Explicando de outra forma: a localidade espacial entre as palavras em um bloco diminui com um bloco muito grande. ele precisará sofrer stall. Cada linha representa uma cache de tamanho diferente. começando com o endereço após a palavra requisitada e retornando para o início do bloco. os benefícios na taxa de falhas se tornam menores. Se o processador não puder acessar a cache de dados porque uma transferência está em andamento. então. A penalidade de falha é determinada pelo tempo necessário para buscar o bloco do próximo nível mais baixo na hierarquia e carregá-lo na cache. é simplesmente retomar a execução assim que a palavra requisitada do bloco seja retornada. com o sistema de memória entregando novas palavras de instrução em tempo. o tempo de transferência – e.8  Taxa de falhas versus tamanho de bloco. o processador poderá ser capaz de reiniciar sua operação quando a palavra requisitada for retornada. então. portanto. que será discutida em breve. em vez de esperar o bloco inteiro. se projetarmos a memória para transferir blocos maiores de forma mais eficiente.374 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. . portanto. Claramente. Discutiremos esse assunto na próxima seção. O método mais simples de fazer isso. Note que a taxa de falhas realmente sobe se o tamanho de bloco for muito grande em relação ao tamanho da cache. por conseguinte. chamado reinício precoce. é transferido. poderemos aumentar o tamanho do bloco e obter mais melhorias no desempenho da cache. diminuindo. Essa técnica normalmente é menos eficaz para caches de dados porque é provável que as palavras sejam requisitadas do bloco de uma maneira menos previsível. Naturalmente. Além disso. Detalhamento:  Embora seja difícil fazer algo sobre o componente de latência mais longo da penalidade de falha para blocos grandes. Um problema mais sério associado a apenas aumentar o tamanho de bloco é que o custo de uma falha aumenta. se o sistema de memória puder entregar uma palavra a cada ciclo de clock. a penalidade de falha – aumentará conforme o tamanho de bloco aumenta. esses dados são baseados no SPEC92. os traces do SPEC2000 levariam tempo demais se o tamanho de bloco fosse incluído. O tempo para buscar o bloco possui duas partes: a latência até a primeira palavra e o tempo de transferência para o restante do bloco. O resultado é que o aumento na penalidade de falha suplanta o decréscimo na taxa de falhas para grandes blocos. assim. o aumento na taxa de falhas começa a decrescer conforme os blocos se tornam maiores. a menos que mudemos o sistema de memória. (Esta figura é independente da associatividade. que é onde ela funciona melhor.) Infelizmente. Como os acessos a instruções são extremamente sequenciais. sejam acessadas. Enviar o valor do PC original (PC atual – 4) para a memória. A maneira mais simples de . 2. Se a cache atendida porque os dados não estão presentes na cache. mas ela é limitada pelas mesmas propriedades que limitam o reinício precoce. enquanto esperamos a memória. o conteúdo do registrador de instrução será inválido. O processamento de uma falha de cache cria um stall seme- lhante aos stalls de pipeline (Capítulo 4). então. escrevemos os dados apenas na cache de dados (sem alterar a memória principal). escrevendo os bits mais significativos do endereço (vindo da ALU) no campo tag e ligando o bit de validade. que exigiria salvar o estado de todos os registradores. Reiniciar a execução da instrução na primeira etapa. 5. Uma vez tendo o endereço. A falha de cache  Uma requisição de unidade de controle precisa detectar uma falha de cache e processá-la buscando os dados dados da cache que não pode ser requisitados da memória (ou. as falhas. em uma instrução store. exigem um trabalho maior. vamos ver como a unidade de controle lida com as falhas de cache. Instruir a memória principal a realizar uma leitura e esperar que a memória complete seu acesso. de uma cache de nível inferior). Es- peramos a memória responder (já que o acesso levará vários ciclos) e. Vejamos um pouco mais de perto como as falhas de instrução são tratadas.7). reportar um acerto. O controle da cache sobre um acesso de dados é basicamente idêntico: em uma falha. o endereço da instrução que gera uma falha de cache de instruções é igual ao valor do contador de programa menos 4. precisamos instruir a memória principal a realizar uma leitura. Tratando falhas de cache Antes de olharmos a cache de um sistema real. então. simplesmente suspendemos o processador até que a memória responda com os dados. desta vez encontrando-a na cache. (Descrevemos um controlador de cache na Seção 5. que fazem um stall nas perdas de cache. Processadores fora de ordem mais sofisticados podem permitir a execução de instruções enquanto se espera por uma falha de cache. dizemos que a cache e a memória estão inconsistentes. colocando os dados da memória na parte dos dados da entrada. pode ser um pouco mais rápida do que o reinício precoce. podemos definir as etapas a serem realizadas em uma falha de cache de instruções: 1. o que buscará novamente a instrução. Para colocar a instrução correta na cache. escrevemos as palavras na cache. podemos fazer um stall no processador inteiro. Modificar o controle de um processador para tratar um acerto é fácil. como oposto a uma interrupção. o mesmo método pode ser facilmente estendido para tratar falhas de dados. Se um acesso à ins- trução resultar em uma falha. a memória teria um valor diferente do valor na cache. chamada palavra requisitada primeiro. Escrever na entrada da cache. após a escrita na cache. Nes- se caso. 4. Como o contador do programa é in- crementado no primeiro ciclo de clock da execução. mas vamos considerar nesta seção os processadores em ordem. ou palavra crítica primeiro. Agora. no entanto. o computador continua usando os dados como se nada tivesse acontecido. O tratamento da falha de cache é feito com a unidade de controle do processador e com um controlador separado que inicia o acesso à memória e preenche novamente a cache. Tratando escritas As escritas funcionam de maneira um pouco diferente. basicamente congelando o conteúdo dos registradores temporários e visíveis ao programador.2  Princípios básicos de cache 375 Essa técnica. 3. Para uma falha de cache. Suponha que. como veremos. precisamos ser capazes de instruir o nível inferior na hierarquia de memória a realizar uma leitura. 0. Com um esquema de write-through. Implementar stores de modo realmente eficaz em uma cache que usa uma estratégia write-back é mais complexo do que em uma cache write-through. O bloco é apanhado da memória e depois a parte apropriada do bloco é sobrescrita. então haverá uma falha. Em uma cache write-back. descreveremos o tratamento de escritas em mais detalhes. suponha que 10% das instruções sejam stores. especialmente quando os proces- da hierarquia quando o bloco é sadores podem gerar escritas tão rápido ou mais rápido do que as escritas podem ser substituído. tratadas pela memória principal. Primeiro.5. os processadores normalmente aumentam a profundidade do buffer de escrita para além de uma única entrada. Nesses casos. A velocidade em que as escritas são geradas também pode ser menor do que a velocidade em que a memória pode aceitá-las. Essas escritas levarão muito tempo. Considere uma falha em uma cache write-through. se a velocidade em que a memória pode completar escritas for menor do que a velocidade em que o processador está gerando escritas. A estratégia mais comum é alocar um bloco no cache. a busca associada com a falha de escrita inicial pode ser desnecessária. Os e. entretanto. write-back  Um esquema que A alternativa para um esquema write-through é um esquema chamado write-back. Isso pode acontecer quando as es- critas ocorrem em bursts (ou rajadas). Se o buffer de escrita estiver cheio quando o processador atingir uma escrita. e stalls ainda podem ocorrer. Esse esquema é chamado write-through. cache e o próximo nível inferior da buscamos as palavras do bloco da memória. no manipula escritas atualizando qual. precisamos escrever o bloco novamente na memória se os dados na cache estiverem modificados e tivermos uma falha de cache. buffer de escrita  Uma fila que Uma solução para esse problema é usar um buffer de escrita (ou write buffer). Naturalmente. toda escrita faz com que os dados sejam escritos na memória principal. uma escrita na memória principal é concluída. depois. pois a memória tem o valor correto. Na Seção 5. que ar- contém os dados enquanto estão mazena os dados enquanto estão esperando para serem escritos na memória.376 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória manter consistentes a memória principal e a cache é sempre escrever os dados na memó- write-through  Um esquema em ria e na cache. escrevendo o bloco modificado no nível inferior esquemas write-back podem melhorar o desempenho. pois as escritas estão sendo geradas mais rápido do que o sistema de memória pode aceitá-las. que não é copiado no próximo nível da hierarquia da memória. talvez mais de 100 ciclos de clock de processador. o que se chama não alocar na escrita. descreveremos as caches de processadores reais e examinaremos como elas tratam leituras e escritas. mas não colocá-la no cache. a substituição do bloco no cache não é catastrófica. nenhuma quantidade de buffer pode ajudar. o novo valor é escrito apenas no bloco da cache. a entrada no buffer de escrita é liberada. quando ocorre uma escrita. Se simplesmente substituíssemos o bloco em uma instrução store antes de sabermos se o store teve acerto na cache (como poderíamos fazer para uma cache write-through). um esquema write-back é mais complexo de implementar do que um esquema write-through. . Uma cache write-through pode escrever os dados na cache e ler a tag. se a tag for diferente. chamado alocar na escrita. escrevemos a palavra na memória principal usando o endereço completo. reduzindo o desempenho por um fator maior que 10. Quando memória. hierarquia de memória. gastar 100 ciclos extras em cada escrita levaria a um CPI de 1. No restante desta seção. garantindo que os dados sejam sempre podemos substituir (sobrescrever) a palavra que causou a falha no bloco de cache. Se o CPI sem falhas de cache fosse 1. Para reduzir a ocorrência desses stalls. o processador precisará sofrer stall até que haja uma posição vazia no buffer de escrita. que as escritas sempre atualizam a O outro aspecto importante das escritas é o que ocorre em uma falha de dados. Detalhamento:  As escritas introduzem várias complicações nas caches que não estão presentes para leituras. o processador pode continuar a execução. e tornariam o processador consideravelmente mais lento. Por exemplo.0 + 100 × 10% = 11. Uma estratégia alternativa é atualizar a parte do bloco na memória. A motivação é que às vezes os programas escrevem blocos de dados. Embora esse projeto trate das escritas de maneira muito simples. Após escrever esperando para serem escritos na os dados na cache e no buffer de dados. Discutiremos aqui duas delas: a política nas falhas de escrita e a implementação eficiente das escritas em caches write-back. ele não oferece um desempenho muito bom. como quando o sistema operacional zera uma página de memória. Também consistentes entre os dois. O valores apenas no bloco da cache bloco modificado é escrito no nível inferior da hierarquia quando ele é substituído. Após o bloco ser buscado e colocado na cache. destruiríamos o conteúdo do bloco. Alguns computadores permitem que a política de alocação de escrita seja alterada com base em cada página. Como o cache é write-through. Por comparação. por questões didáticas. o processador gera uma falha de escrita para buscar o resto do bloco correspondente a esse endereço. A Figura 5. e o campo índice possui 8 bits de largura. as escritas sempre podem ser feitas em um ciclo. Considerando que outra falha não ocorra imediatamente.2  Princípios básicos de cache 377 Em uma cache write-back. Nesse caso. para eliminar o multiplexador. Próximo ao final do capítulo. permitindo que o store leve apenas um ciclo por meio de um pipeline de memória. como não podemos substituir o bloco. enquanto um campo de 4 bits (bits 5 a 2) é usado para indexar o bloco e selecionar a palavra do bloco usando um multiplexador de 16 para 1. mas começaremos com este exemplo simples. Considerando um acerto de cache. já que o bloco correto foi atualizado. Em casos como esse. mas real. Quando um buffer de store é usado. . o processador realiza a consulta de cache e coloca os dados no buffer de store durante o ciclo de acesso de cache normal. Lemos a tag e escrevemos a parte dos dados do bloco selecionado. os stores ou exigem dois ciclos (um ciclo para verificar um acerto seguido de um ciclo para efetivamente realizar a escrita) ou exigem um buffer de escrita para conter esses dados – na prática.9 mostra a organização da cache de dados do Intrinsity FastMATH. com o offset de bloco fornecendo os bits de endereço extras para a RAM grande de dados. a RAM grande possui 32 bits de largura e precisa ter 16 vezes o número de palavras como blocos na cache. Se a tag não corresponder. os novos dados são escritos do buffer de store para a cache no próximo ciclo de acesso de cache não usado. em uma cache write-through. as caches usam uma RAM grande separada para os dados e uma RAM menor para as tags. FIGURA 5. o buffer write-back é escrito novamente na memória. Muitas caches write-back também incluem buffers de escrita usados para reduzir a penalidade de falha quando uma falha substitui um bloco modificado. Depois. Na prática. o bloco modifi- cado é movido para um buffer write-back associado com a cache enquanto o bloco requisitado é lido da memória. essa técnica reduz à metade a penalidade de falha quando um bloco modificado precisa ser substituído. Se a tag corresponder ao endereço do bloco escrito. 5. Uma cache de exemplo: o processador Intrinsity FastMATH O Intrinsity FastMATH é um microprocessador embutido veloz que usa a arquitetura MIPS e uma implementação de cache simples. O campo tag possui 18 bits de largura. o processador pode continuar normalmente. examinaremos o projeto de cache mais complexo do AMD Opteron X4 (Barcelona).9  Cada cache de 16KB no Intrinsity FastMATH contém 256 blocos com 16 palavras por bloco. precisamos selecionar a palavra correta. ou 4K palavras.10  Taxas de falhas de instruções e dados aproximadas para o processador Intrinsity FastMATH para benchmarks SPEC2000. Ele possui um buffer de escrita de uma entrada.10 mostra as taxas de falhas para as caches de ins- truções e de dados. Entretanto. nós os escrevemos na cache e. a medida decisiva será o efeito do sistema de memória sobre o tempo de execução do pro- grama. com blocos de 16 palavras. o Intrinsity FastMATH oferece write-through e write-back. com uma tratando instruções e a outra usam uma instrução split e uma cache de dados para aumentar a largura de banda da cache. a palavra requisitada estará disponível nas linhas de dados.24%. são usadas caches de instruções e de dados separadas. Como existem 16 palavras no bloco desejado. Para escritas. então. os lemos para atender à requisição. semelhante ao discutido no Capí- tulo 4. FIGURA 5. . Cada cache possui 16KB. O endereço vem do PC (para uma instrução) ou da ALU (para dados). Essa taxa mais alta ocorre porque de memória é composto de duas a cache combinada não divide rigidamente o número de entradas que podem ser usadas por caches independentes que operam instruções daquelas que podem ser usadas por dados. Se a cache sinalizar falha. Se a cache sinalizar acerto. as etapas para uma requisição de leitura para qualquer uma das caches são as seguintes: 1.18%. A taxa de falhas combinada é a taxa de falhas efetiva para a combinação da cache de instruções de 16KB e da cache de dados de 16KB. (Lembre-se de que precisamos atualizar a cache de instruções quando ocorre uma falha. Um campo índice de bloco é usado para controlar o multiplexador (mostrado na parte inferior da figura). A taxa de falhas combinada é a taxa de falhas efetiva por referência para cada programa após considerar a frequência diferente dos acessos a instruções e a dados. Que taxas de falhas de cache são atingidas com uma estrutura de cache como a usada pelo Intrinsity FastMATH? A Figura 5.) Aqui estão taxas de falhas para caches do tamanho dos encontrados no processador In- trinsity FastMATH. Embora a taxa de falhas seja uma característica importante dos projetos de cache. As requisições de leitura para a cache são simples. deixando a cargo do sistema operacional decidir qual estratégia usar para cada aplicação. j Taxa de falhas efetiva da cache dividida: 3. Para satisfazer às demandas do pipeline sem stalls. sinais de controle separados serão necessários para ler e escrever em cada cache. Como existem caches de dados e de instruções separadas. 3. j Taxa de falhas da cache combinada: 3. que seleciona a palavra requisitada das 16 palavras do bloco indexado. cache dividida  Um esquema Detalhamento:  Uma cache combinada com um tamanho total igual à soma das duas caches em que um nível da hierarquia divididas normalmente terá uma taxa de acertos melhor. em breve veremos como a taxa de falhas e o tempo de execução estão relacionados. Quando está operando na velocidade de pico. e para uma cache combinada cujo tamanho é igual ao total das duas caches: j Tamanho total da cache: 32KB. Quando a memória retorna com os dados. tratando dados. Enviar o endereço à cache apropriada. muitos processadores em paralelo uma com a outra. enviaremos o endereço para a memória principal. Ela é obtida ponderando as taxas de falhas individuais de instruções e de dados pela frequência das referências a instruções e dados.378 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Esse processador possui um pipeline de 12 estágios.5. 2. o processador pode requisitar uma palavra de instrução e uma palavra de dados em cada clock. veja Seção 5. (Também pode haver menos falhas de conflito.) Portanto. que é construída com DRAMs. Portanto. e por isso usaremos o termo barramento.11a). (Co- mo veremos no Capítulo 6. essa tradição está mudando. Com uma largura de memória principal de duas palavras. isso permite acessos paralelos a todas as palavras do bloco. A terceira opção aumenta a largura de banda alargando a memória. Em vez de tornar todo o caminho entre a memória e a cache mais largo. Portanto. Vejamos em quanto essas outras duas opções melho- ram a penalidade de falha de 65 ciclos que veríamos para a primeira opção (Figura 5. Essa redução permite que tamanhos de bloco maiores sejam usados enquanto mantemos uma baixa penalidade de falhas. 5. o número de bytes transferidos por ciclo de clock de barramento para uma única falha seria 4×4 = 0‚25 65 A Figura 5. j 15 ciclos de clock de barramento de memória para cada acesso a DRAM iniciado. A largura de banda para uma única falha é. os chips de memória podem ser organizados em bancos para ler ou escrever múltiplas palavras em . logo suplanta a desvantagem de uma taxa de falhas um pouco maior. A segunda opção aumenta a largura de banda para a memória alargando a memória e os barramentos entre o processador e a memória. A velocidade desse barramento afeta a penalidade de falha.11 mostra três opções para projetar o sistema de memória. vimos que as DRAMs são projetadas com a principal ênfase no custo e na densidade.) A velocidade de clock do barramento geralmente é muito mais lenta do que a do processador. 0.48 (quase duas vezes maior) byte por ciclo de clock de barramento para uma memória que tem duas palavras de largura. Considere: j 1 ciclo de clock de barramento de memória para enviar o endereço. Essa constatação é outro lembrete de que não podemos usar a taxa de falhas como a única medida de desempenho de cache. semelhante àquela para um bloco menor. Projetando o sistema de memória para suportar caches As falhas de cache são satisfeitas pela memória principal. Os maiores custos dessa melhoria são o barramento mais largo e o possível aumento no tempo de acesso da cache devido ao multiplexador e à lógica de controle entre o processador e a cache. A vantagem de dobrar a largura de banda da cache. ainda pagamos um custo para transmitir cada palavra. a penalidade de falha cai de 65 ciclos de clock de barramento de memória para 1 + (2  15) + 2  1 = 33 ciclos de clock de barramento de memória. vamos definir um conjunto hipotético de tempos de acesso à memória. mas a tecnologia de interconexão real não importa neste capítulo. mas podemos evitar pagar o custo da latência de acesso mais de uma vez. diminuindo as partes do tempo de acesso e do tempo de transferência da penalidade de falha. então. suportando acessos a instruções e a dados simultaneamente. a penalidade de falha seria 1 + 4 × 15 + 4 × 1 = 65 ciclos de clock de barramento de memória. Se tivermos um bloco de cache de quatro palavras e um banco de DRAMs com a largura de uma palavra. Aumentar a largura da memória e do barramento aumentará a largura de banda da memória proporcionalmente. Embora seja difícil reduzir a latência para buscar a primeira palavra da memória. O processador normalmente é conectado à memória por meio de um barramento. Para entender o impacto das diferentes organizações de memória. j 1 ciclo de clock de barramento de memória para enviar uma palavra de dados. como mostra a Seção 5. A primeira delas segue o que temos considerado: a memória possui uma palavra de largura.3. e todos os acessos são feitos sequencialmente. mas não o barramento de interconexão.1.2  Princípios básicos de cache 379 A taxa de falhas da cache dividida é apenas ligeiramente pior. podemos reduzir a penalidade de falha se aumentarmos a largura de banda da memória para a cache. Na Seção 5. ou cerca de três vezes a largura de banda para a memória e barramento de uma palavra de largura. O nome significa que os dados são transferidos tanto na transição de subida quanto na transição de des- cida do clock. quadruplicando a largura de banda de escrita e gerando menos stalls em uma cache write-through. assim. um barramento e uma cache mais largos. 15 ciclos para que todos os quatro bancos acessem a memória e quatro ciclos para enviar as quatro palavras de volta à cache. Por exemplo. Os bancos também são valiosos nas escritas. com quatro bancos. Cada banco poderia ter uma palavra de largura para que a largura do barramento e da cache não precisassem mudar. (b) mostra uma memória.80 byte por clock. a DRAM interna é organizada em bancos de memória intercalados. Cada banco pode escrever independentemente. chamado de intercalação (interleaving). mas enviar um endereço para vários bancos permite que todos eles leiam simultaneamente.11  O principal método para obter largura de banda de memória mais alta é aumentar a largura física ou lógica do sistema de memória. conserva a vantagem de incorrer a latência de memória completa apenas uma vez. uma estratégia alternativa para escritas torna a intercalação ainda mais atraente. a lógica entre a cache e o processador consiste em um multiplexador usado em leituras e lógica de controle para atualizar as palavras apropriadas da cache nas escritas. Em (b). Como veremos. o dobro da largura de banda que se poderia esperar com base na velocidade de clock e na largura de dados. o tempo para obter um bloco de quatro palavras consistiria em um ciclo para transmitir o endereço e a requisição de leitura para os bancos. Essa é uma largura de banda efetiva por falha de 0.380 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. a largura de banda da memória é melhorada de duas maneiras. os fabrican- tes de DRAM fornecem um acesso em rajada aos dados de locais sequenciais na DRAM. Devido à onipresença das caches e ao desejo de tamanhos de bloco maiores. . Isso produz uma penalidade de falha de 1 + (1 × 15) + 4 × 1 = 20 ciclos de clock de barramento de memória. enquanto (c) mostra um barramento e uma cache mais estreitos com uma memória intercalada. um único tempo de acesso em vez de ler ou escrever uma única palavra em cada vez. Nesta figura. Para oferecer uma largura de banda tão grande. Esse esquema. O desenvolvimento mais recente são as DRAMs Double Data Rate (DDR). gerando. O projeto mais simples (a) usa uma memória na qual todos os componentes possuem uma palavra de largura. daí em diante. Detalhamento:  O modo de rajada para memória DDR também é encontrado nos barramentos de memória. 1995]. 5. A arquitetura interna das DRAMs e como essas otimizações são implementadas são descritos na Seção C. Essa capacidade muda significativamente o tempo de acesso. já que o tempo de acesso para bits na mesma linha é muito menor. Detalhamento:  Os chips de memória são organizados para produzir vários bits de saída. Resumo Começamos a seção anterior examinando a mais simples das caches: uma cache dire- tamente mapeada com um bloco de uma palavra. as DRAMs adicionaram clocks e são pro- priamente chamadas SDRAMs (Synchronous DRAMs). As DRAMs colocam uma linha de bits em um buffer. já que uma palavra pode estar localizada exatamente . embora seja frequentemente afetado por outros fatores. Elas não possuem localidade temporal e acessam arrays que são maiores do que a cache do computador sendo testado. normalmente de 4 a 32. adicionando pouco custo ao sistema enquanto atinge uma significativa me- lhoria na largura de banda. porém contínuas. dobrando aproximadamente a cada dois anos. o custo e o tempo de acesso das DRAMs mudaram através dos anos. mudando o endereço de coluna. Para melhorar a interface com os processadores. bits aleatórios podem ser acessados no buffer até o próximo acesso de linha.2  Princípios básicos de cache 381 A vantagem dessas otimizações é que elas usam os circuitos já presentes amplamente nas DRAMs. sendo que 16 era o mais comum em 2008. O buffer atua como uma SRAM. e w é a saída (ou a largura de cada local).9 do Apêndice C. As melhorias no tempo de acesso têm sido mais lentas. A Figura 5.12  Tamanho da DRAM aumentado por múltiplos de quatro aproximadamente uma vez a cada três anos até 1996 e. Ele mede o desempenho de longas operações de vetor.12 mostra como a densidade. tanto os acertos quanto as falhas são simples. A vantagem das SDRAMs é que o uso de clock elimina o tempo de sincronização entre a memória e o processador. como a disponibilidade e a demanda. e o custo quase acompanha as melhorias na densidade. As transferências em rajada permitem acessos repetidos ao buffer sem um tempo de acesso de linha. As DRAMs são organizadas logicamente como arrays retangulares. como o Intel Duo Core Front Side Bus. e o tempo de acesso é dividido em acesso de linha e acesso de coluna. onde d é o número dos locais endereçáveis (a profundidade). FIGURA 5. Nesse tipo de cache. Descrevemos a organização da RAM como d × w. O custo por gigabyte não está ajustado pela inflação. Detalhamento:  Um modo de medir o desempenho do sistema de memória por trás das ca- ches é o benchmark Stream [McCalpin. Essa técnica. uma cache precisa ter um tamanho de bloco maior do que uma palavra. ela se tornou comum nos computadores desktop vendidos por menos de US$500! O tempo de CPU pode ser dividido nos ciclos de clock que a CPU gasta executando o programa e os ciclos de clock que gasta esperando o sistema de memória. Os projetistas de DRAM melhoraram bastante a interface entre o processador e a memória. depois. discutiremos esse esquema mais detalhadamente em seções futuras.382 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória em um lugar e existe uma tag separada para cada palavra. Verifique você A velocidade do sistema de memória afeta a decisão do projetista sobre o tamanho do bloco de cache. A fim de manter a cache e a memória consistentes. a largura de banda da memória principal é aumen- tada de modo a transferir blocos de cache de maneira mais eficiente. O uso de um bloco maior diminui a taxa de falhas e melhora a eficiência da cache reduzindo a quantidade de armazenamento de tag em relação à quantidade de armazenamento de dados na cache. maior será o bloco de cache. Quanto maior for a largura de banda da memória. A alternativa ao write-through é um esquema write-back que copia um bloco de volta para a memória quando ele é substituído. menor será o bloco de cache. 4. um esquema de write-through pode ser usado. 3. Quanto mais curta for a latência da memória. Quanto mais curta for a latência da memória. desde então. A segunda técnica reduz a penalidade de falha acrescentando um nível adicional na hierarquia. 2. maior será o bloco de cache.3  da cache Nesta seção. Quanto maior for a largura de banda da memória. Embora um tamanho de bloco maior diminua a taxa de falhas. Normalmente. de modo que toda escrita na cache também faz com que a memória seja atualizada. Para evitar a perda de desempenho. blocos maiores poderiam facilmente levar a um desempenho menor. menor será o bloco de cache. ele também pode aumentar a penalidade de falha.000 em 1990. Para tirar vantagem da localidade espacial. apareceu inicialmente nos computadores de topo de linha sendo vendidos por mais de US$100. Os dois métodos comuns para fazer isso são tornar a memória mais larga e a intercalação. Portanto. Se a penalidade de falha aumentasse linearmente com o tamanho de bloco. chamada caching multinível. exploramos duas técnicas diferentes para melhorar o desempenho da cache. Uma delas focaliza o decréscimo da taxa de falhas reduzindo a probabilidade de dois blocos de memória diferentes disputarem o mesmo local da cache. começamos examinando como medir e analisar o desempenho da cache. a fim de au- mentar a largura de banda das transferências no modo rajada e reduzir o custo dos tama- nhos de bloco de cache maiores. Medindo e melhorando o desempenho 5. Quais dos seguintes princípios de projeto de cache normalmente são mesmo válidos? 1. consideramos que os custos do acesso à cache que são acertos são parte dos ciclos de execução normais da CPU. TempodeCPU = (ciclosdeclock deexecuçãoda CPU + Ciclosdeclock destallde memória) × Tempodeciclodeclock . Também limitamos a discussão a um modelo simplificado do sis- tema de memória. para obter mais informações sobre como lidar com escritas). e não apenas da frequência.5. Os esquemas write-back também possuem stalls potenciais extras surgindo da neces- sidade de escrever um bloco de cache novamente na memória quando o bloco é substituído. Se um sistema não atendesse a esse critério. ao contrário. e a previsão correta do desempenho normalmente exige simulações extremamente detalhadas do processador e do sistema de memória. que ocorrem quando o buffer de escrita está cheio ao ocorrer uma escrita. Felizmente. Para um esquema write-through. Na maioria das organizações de cache write-back. Nos processadores reais. os stalls gerados por leituras e escritas podem ser muito complexos. podemos combinar as leituras e escritas usando uma única taxa de falhas e a penalidade de falha: Acessosà memória Ciclosdeclock destallde memória = × Taxa defalhas × Penalidadedefalha Programa Também podemos fatorar isso como Instruções Falhas Ciclosdeclock destallde memória = × × Penalidadedefalha Programa Instrução Vamos considerar um exemplo simples para ajudar a entender o impacto no desempenho da cache sobre o desempenho do processador. os stalls do buffer de escrita serão pequenos e podemos ignorá-los. Assim.3  Medindo e melhorando o desempenho da cache 383 Os ciclos de clock de stall de memória vêm principalmente das falhas de cache. que normalmente exigem que busquemos o bloco antes de con- tinuar a escrita (veja a seção “Detalhamento” na Seção “Tratando escritas”. as penalidades de falha de leitura e escrita são iguais (o tempo para buscar o bloco da memória). Discutiremos mais o assunto na Seção 5. os ciclos de stall para escritas são iguais à soma desses dois fatores:  Leituras  Ciclosdestalldeescrita =  × Taxa defalhasdeescrita × Penalidadedefalha deescrita   Programa  + Stallsdo buffer deescrita Como os stalls do buffer de escrita dependem da proximidade das escritas. . a penalidade de falha nos ciclos de clock para uma leitura e a taxa de falhas de leitura: Leituras Ciclosdestallde leitura = × Taxa defalhasde leitura × Penalidadedefalha de leitura Programa As escritas são mais complicadas. temos duas origens de stalls: as falhas de escrita. 5. Os ciclos de clock de stall de memória podem ser definidos como a soma dos ciclos de stall vindo das leituras mais os provenientes das escritas: Ciclosdeclock destallde memória = Ciclosdestallde leitura + Ciclosdestalldeescrita Os ciclos de stall de leitura podem ser definidos em função do número de acessos de leitura por programa. quatro ou mais palavras) e uma memória capaz de aceitar escritas em uma velocidade que excede significativamente a frequência de escrita média em programas (por exemplo. por um fator de duas vezes). o projetista deveria ter usado um buffer de escrita mais profundo ou uma organização write-back. não é possível fornecer uma equação simples para calcular esses stalls. anteriormente neste capítulo. ele não seria bem projetado. e é isso que iremos considerar aqui. Se considerarmos que os stalls do buffer de escrita são insignificantes. nos sistemas com um buffer de escrita razoável (por exemplo. e os stalls do buffer de escrita. 44 = 5.44.00 × I A frequência de todos os loads e stores é de 36%. 44 × I O número total de ciclos de stall da memória é 2. nos lembra desse fato.44 I = 3. determine o quão mais rápido um processador executaria com uma cache perfeita que nunca falhasse. o que pode ser feito com um pipeline melhorado.00 I + 1. a Lei de Amdahl. Como não há mudança alguma na contagem de instruções ou na velocidade de clock. Portanto. mas o sistema de memória não? A quantidade de tempo gasto nos stalls da memória tomará uma fração cada vez maior do tempo de execução. O que acontece se o processador se tornar mais rápido. que examinamos no Capítulo 1. a taxa dos tempos de execução da CPU é TempodeCPU com stalls I × CPIstall × Ciclodeclock = TempodeCPU comcache perfeita I × CPIperfeita × Ciclodeclock CPIstall 5‚44 = = CPIperfeita 2 O desempenho com a cache perfeita é melhor por um fator de 5. podemos encontrar o número de ciclos de falha da memória para referências de dados: Ciclos de falha dedados = I × 36% × 4% × 100 = 1. e o sistema com a cache perfeita seria 4‚44 = 4‚44 vezes mais rápido 1 A quantidade de tempo de execução gasto em stalls da memória teria subido de 3‚44 = 63% 5‚44 para 3‚44 = 77% 4‚44 .44.44 = 4. Logo. então. O sistema com falhas de cache.44 I. Se um processador pos- sui um CPI de 2 sem qualquer stall de memória e a penalidade de falha é de 100 ciclos para todas as falhas. Isso é mais do que três ciclos de stall da memória por instrução. Suponha que aceleremos o computador do exemplo anterior reduzindo seu CPI de 2 para 1 sem mudar a velocidade de clock. Suponha que a frequência de todos os loads e stores seja 36%. teria um CPI de 1 + 3. O número de ciclos de falha da memória para instruções em termos da contagem RESPOSTA de instruções (I) é Ciclosde falha deinstrução = I × 2% × 100 = 2. o CPI com stalls da memória é 2 + 3.44/2 = 2. Alguns exemplos simples mostram como esse problema pode ser sério.72.384 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Calculando o desempenho da cache Suponha que uma taxa de falhas de cache de instruções para um programa seja de EXEMPLO 2% e que uma taxa de falhas de cache de dados seja de 4%. Suponha que as penalidades de perda de leitura e escrita sejam iguais e ignore outros stalls de escrita. O tempo médio de acesso à memória por instrução é TMAM = Tempo para um acerto + Taxa defalha × Penalidadedefalha RESPOSTA = 1 + 0. o aumento no tempo de acerto para uma cache maior pode dominar a melhoria na taxa de acertos. se o tempo de acerto aumentar. A fim de capturar o fato de que o tempo de acesso a dados para acertos e falhas afeta o desempenho. considerando acertos e falhas e a frequência dos diferentes acessos. Um aumento no tempo de acerto provavelmente acres- centa outro estágio ao pipeline. possivelmente causando um aumento no tempo de ciclo do processador. usamos um esquema de posicionamento simples: um bloco só pode entrar exatamente em um local na cache. esse esquema é chamado de mapeamento direto porque qualquer endereço de bloco na memória é diretamente mapeado para um único local no nível superior da hierarquia. exatamente como se sua mesa na biblioteca fosse muito grande (digamos. em algum ponto. quando colocamos um bloco na cache. Existe. já que podem ser necessários vários ciclos para um acerto de cache. 3 metros quadrados): você levaria mais tempo para localizar um livro. Como já dissemos. Embora vejamos em breve outros exemplos do que pode aumentar o tempo de acerto. Reduzindo as falhas de cache com um posicionamento de blocos mais flexível Até agora. algumas vezes. Embora seja mais complexo calcular o impacto de desempenho de um pipeline mais profundo. os projetistas às vezes usam tempo médio de acesso à memória (TMAM) como um modo de examinar os projetos de cache alternativos.05 falhas por instrução e um EXEMPLO tempo de acesso a cache (incluindo detecção de acerto) de 1 ciclo de clock. na .05 × 20 = 2ciclosdeclock ou 2 ns. o tempo total para acessar uma palavra do sistema de memória crescerá. aumentar a velocidade de clock sem mudar o sistema de memória também aumenta a perda de desempenho devido às falhas de cache. uma penalidade de falha de 20 ciclos de clock.3  Medindo e melhorando o desempenho da cache 385 Da mesma forma. um exemplo é aumentar o tamanho da cache.11). A próxima subseção discute organizações de cache alternativas que diminuem a taxa de falhas mas pode. Os exemplos e equações anteriores consideram que o tempo de acerto não é um fator na determinação do desempenho da cache. outros exemplos aparecem em Falácias e armadilhas (Seção 5. uma taxa de falha de 0. levando a uma redução no desempenho do processador. Uma cache maior pode ter um tempo de acesso maior. 5. Claramente. O tempo médio de acesso à memória é o tempo médio para acessar a memória. aumentar o tempo de acerto. ele é igual ao seguinte: TMAM = Tempo para um acerto + Taxa defalha × Penalidadedefalha Calculando o tempo médio de acesso à memória Ache o TMAM para um processador com tempo de clock de 1 ns. de cache associativa por conjunto de n vias. em que um bloco só pode ser posicionado exatamente em um local. em uma cache diretamente mapeada. Para tornar a pes- quisa exequível. e esse bloco é dado por (12 módulo 8) = 4. conforme as três políticas de posicionamento de bloco. Em uma cache associativa por conjunto de duas vias. existe um número fixo de locais (pelo menos dois) onde cada bloco pode um número fixo de locais (no ser colocado. determinado pelo campo índice. Para encontrar um determina- cache em que um bloco pode ser do bloco em uma cache totalmente associativa. No outro extremo está um esquema em que um bloco pode ser posicionado em qualquer cache totalmente local na cache. Por exemplo. Em uma cache associativa por conjunto  Uma cache que possui conjunto. ela é feita em paralelo com um comparador associado a cada entrada da cache. cada um consistindo em n blocos. então. um posiciona- mento associativo por conjunto combina o posicionamento diretamente mapeado e o posicionamento totalmente associativo: um bloco é diretamente mapeado para um con- junto e. Em uma cache totalmente . todas as tags de todos os elementos do conjunto precisam ser pesquisadas. toda uma faixa de esquemas para posicionamento de blocos. quisadas. o bloco de memória para o endereço de bloco 12 pode aparecer em qualquer um dos oito blocos de cache.386 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória verdade. há apenas um bloco de cache em que o bloco de memória 12 pode ser encontrado. Uma cache associativa por conjunto de n vias consiste em diversos conjuntos. No posicionamento diretamente mapeado. FIGURA 5. A faixa intermediária de projetos entre a cache diretamente mapeada e a cache total- cache associativa por mente associativa é chamada de associativa por conjunto.13  O local de um bloco de memória cujo endereço é 12 em uma cache com 8 blocos varia para posicionamento diretamente mapeado. uma cache associativa por conjunto com n locais para um bloco é chamado mínimo dois) onde cada bloco pode ser colocado. associativo por conjunto e totalmente associativo. uma correspondência é pesquisada em todos os blocos no conjunto. a Figura 5. Esse esquema é chamado de totalmente associativo porque um bloco na associativa  Uma estrutura de memória pode ser associado com qualquer entrada da cache. o bloco de memória pode estar em qualquer elemento do conjunto. pois um bloco pode estar posicionado em qualquer uma delas. Esses comparadores aumentam muito o custo do hardware. Portanto. haveria quatro conjuntos e o bloco de memória 12 precisa estar no conjunto (12 mod 4) = 0. o conjunto contendo um bloco de memória é determinado por (Númerodo bloco)módulo(Númerode conjuntos na cache) Como o bloco pode ser colocado em qualquer elemento do conjunto.13 mostra onde o bloco 12 pode ser posicionado em uma cache com oito blocos no total. e um bloco pode ser colocado em qualquer elemento desse conjunto. Lembre-se de que. todas as entradas da cache precisam ser pes- posicionado em qualquer local da cache. Em um extremo está o mapeamento direto. Em um posicionamento totalmente associativo. Cada bloco na memó- ria é mapeado para um conjunto único na cache. na prática. a posição de um bloco de memória é determinada por (Númerodo bloco)módulo(Númerode blocos na cache) Em uma cache associativa por conjunto. tornando o posicio- namento totalmente associativo viável apenas para caches com pequenos números de blocos. A Figura 5. 8. e a terceira cache é diretamente mapeada. O tamanho total da cache em blocos é igual ao número de conjuntos multiplicado pela as- sociatividade. e uma entrada pode residir em qualquer bloco dentro desse conjunto.14  Uma cache de oito blocos configurada como diretamente mapeada. Portanto. vamos determinar para qual bloco de cache cada endereço de bloco é mapeado: RESPOSTA . é um potencial aumento no tempo de acerto.14 mostra as possíveis estruturas de associa- tividade para uma cache de oito blocos. Podemos pensar em cada estratégia de posicionamento de bloco como uma variação da associatividade por conjunto. e cada conjunto possui um elemento. Uma cache é totalmente associativa.3  Medindo e melhorando o desempenho da cache 387 associativa. Uma cache diretamente mapeada é simplesmente uma cache associativa por conjunto de uma via: cada entrada de cache contém um bloco. Primeiro. 5. FIGURA 5. 0. Encontre o número de falhas para cada organização de cache. aumentar a associatividade diminui o número de conjuntos enquanto aumenta o número de elementos por conjunto. dada a seguinte sequência de endereços de bloco: 0. ele tem um conjunto com m blocos. O caso diretamente mapeado é mais fácil. Com oito blocos. uma cache associativa por conjunto de oito vias é igual a uma cache totalmente associativa. Uma cache totalmente associativa com m entradas é simplesmente uma cache associativa por conjunto de m vias. como mostra o próximo exemplo. A principal desvantagem. cada uma consistindo em quatro blocos de uma palavra cada. que veremos em mais detalhes em breve. Falhas e associatividade nas caches Considere três caches pequenas. associativa por conjunto de duas vias. uma segunda cache é associativa EXEMPLO por conjunto de duas vias. 6 e 8. A vantagem de aumentar o grau da associatividade é que ela normalmente diminui a taxa de falhas. associativa por conjunto de quatro vias e totalmente associativa. para uma cache de tamanho fixo. o bloco pode entrar em qualquer lugar e todas as tags de todos os blocos na cache precisam ser pesquisadas. Primeiro. usando uma entrada em branco para indicar que o bloco é inválido. A cache associativa por conjunto possui dois conjuntos (com índices 0 e 1) com dois elementos por conjunto. ele substitui o bloco 8. . ou seja. o bloco usado há mais tempo é substituído. As caches associativas por conjunto normalmente substituem o bloco menos recentemente usado dentro de um conjunto. o conteúdo da cache associativa por conjunto após cada referência se parece com o seguinte: Endereço do bloco Acerto Conteúdo dos blocos de cache após referência de memória associado ou falha Conjunto 0 Conjunto 0 Conjunto 1 Conjunto 1 0 falha Memória[0] 8 falha Memória[0] Memória[8] 0 acerto Memória[0] Memória[8] 6 falha Memória[0] Memória[6] 8 falha Memória[8] Memória[6] Observe que quando o bloco 6 é referenciado. (Discutiremos as regras de substituição mais detalhadamente em breve. precisamos de uma regra de substituição. vamos determinar para qual conjunto cada endereço de bloco é mapeado: Endereço do bloco Bloco de cache 0 (0 módulo 2) = 0 6 (6 módulo 2) = 0 8 (8 módulo 2) = 0 Já que temos uma escolha de qual entrada em um conjunto substituir em uma fa- lha. uma a menos do que a cache diretamente mapeada.) Usando essa regra de substituição. já que o bloco 8 foi referenciado menos recentemente do que o bloco 0. texto colorido para mostrar uma nova entrada incluída na cache para a referência associada e um texto normal para mostrar uma entrada existente na cache: Endereço do bloco Acerto Conteúdo dos blocos de cache após referência de memória associado ou falha 0 1 2 3 0 falha Memória[0] 8 falha Memória[8] 0 falha Memória[0] 6 falha Memória[0] Memória[6] 8 falha Memória[8] Memória[6] A cache diretamente mapeada gera cinco falhas para os cinco acessos. A cache associativa por conjunto de duas vias possui quatro falhas.388 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Endereço do bloco Bloco de cache 0 (0 módulo 4) = 0 6 (6 módulo 4) = 2 8 (8 módulo 4) = 0 Agora podemos preencher o conteúdo da cache após cada referência. três falhas é o melhor que podemos fazer porque três endereços de bloco únicos são acessados. vamos considerar a tarefa de encontrar um bloco em uma cache que é associativa por conjunto. a tag é usada para escolher o bloco por comparação com os blocos no conjunto selecionado. se tivéssemos 16 blocos. Repare que se tivéssemos oito blocos na cache. Quanta redução na taxa de falhas é obtida pela associatividade? A Figura 5. .15 mostra a melhoria para uma cache de dados de 64KB com um bloco de 16 palavras e mostra a associatividade mudando do mapeamento direto para oito vias. mas há pouca melhora adicional em passar para uma associatividade mais alta. O valor de índice é usado para selecionar o conjunto contendo o endereço FIGURA 5. Assim como em uma cache diretamente mapeada. Passar da associatividade de uma via para duas vias diminui a taxa de falhas em aproximadamente 15%. não haveria qualquer substituição na cache associativa por conjunto de duas vias (confira isso você mesmo). qualquer bloco de memória pode ser armazenado em qualquer bloco de cache.16 mostra como o endereço é decomposto. A tag de cada bloco de cache dentro do conjunto apropriado é verificada para ver se corres- ponde ao endereço de bloco vindo do processador. e ele teria o mesmo número de falhas da cache totalmente associativa. Até mesmo esse exemplo trivial mostra que o tamanho da cache e a associatividade não são independentes para a determinação do desempenho da cache. O índice é usado para selecionar o conjunto e. cada bloco em uma cache associativa por conjunto inclui uma tag de endereço que fornece o endereço do bloco. 5. depois. Localizando um bloco na cache Agora. Da mesma forma.3  Medindo e melhorando o desempenho da cache 389 A cache totalmente associativa possui quatro blocos de cache (em um único con- junto). Esses resultados para dez programas SPEC2000 são de Hennessy e Patterson [2003].15  As taxas de falhas da cache de dados para uma organização como o processador Intrinsity FastMATH para benchmarks SPEC2000 com associatividade variando de uma via a oito vias. todas as três caches teriam o mesmo número de falhas. com apenas três falhas: Endereço do bloco Acerto ou Conteúdo dos blocos de cache após referência de memória associado falha Bloco 0 Bloco 1 Bloco 2 Bloco 3 0 falha Memória[0] 8 falha Memória[0] Memória[8] 0 acerto Memória[0] Memória[8] 6 falha Memória[0] Memória[8] Memória[6] 8 acerto Memória[0] Memória[8] Memória[6] Para essa série de referências. O offset do bloco é o endereço dos dados desejados dentro do bloco.16  As três partes de um endereço em uma cache associativa por conjunto ou diretamen- te mapeada. FIGURA 5. A cache totalmente associativa possui o melhor desempenho. A Figura 5. existe apenas um conjunto. pesquisar as tags do conjunto. Em outras palavras. aumentar a associatividade aumenta o número de blocos por conjunto. cada aumento pelo dobro na associatividade diminui o tamanho do índice em 1 bit e aumenta o tamanho da tag em 1 bit.17 mostra que em uma cache associativa por conjunto de quatro vias. Se o tamanho de cache total for mantido igual. juntamente com um multiplexador de 4 para 1 a fim de escolher entre os quatro números possíveis do conjunto selecionado. depois. fazendo com que o elemento correspondente controle as saídas de dados.390 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória de interesse. A Figura 5. ambos em tempo e em hardware extra. que é o número de comparações simultâneas necessárias para realizar a pesquisa em paralelo: cada aumento por um fator de dois na associatividade dobra o número de blocos por conjunto e divide por dois o número de conjuntos. Como a velocidade é a essência da pesquisa. A saída permite que o sinal venha dos comparadores. e o endereço inteiro. é comparado com a tag de cada bloco. A saída dos comparadores é usada para selecionar os dados de um dos quatro blocos do conjunto indexado. Assim. Essa organização elimina a necessidade do multiplexador. FIGURA 5. O acesso de cache consiste em indexar o conjunto apropriado e. a cache inteira é pesquisada sem qualquer indexação. Em algumas implementações. Os custos de uma cache associativa são os comparadores extras e qualquer atraso pela neces- sidade de comparar e selecionar entre os elementos do conjunto. todas as tags no conjunto selecionado são pesquisadas em paralelo. excluindo o offset do bloco. Em uma cache diretamente mapeada. e acessamos a cache por meio da indexação. A escolha entre mapeamento direto. e todos os blocos precisam ser verificados em paralelo. Os comparadores determinam qual elemento do conjunto selecionado (se houver) corresponde à tag. Assim como em uma cache totalmente associativa. a saída permite que sinais nas partes de dados das RAMs de cache possam ser usados para selecionar a entrada no conjunto que controla a saída. associativo por conjunto ou totalmente associativo em qualquer hierarquia de memória dependerá do custo de uma falha em comparação com o custo da implementação da associatividade. pois a entrada pode estar apenas em um bloco. quatro comparadores são necessários. não há qualquer índice. e as tags de todos os blocos no conjunto precisam ser pesquisadas.17  A implementação de uma cache associativa por conjunto de quatro vias exige quatro comparadores e um multi- plexador de 4 para 1. apenas um único comparador é necessário. Portanto. usando um multiplexador com um sinal de seleção decodificado. uma pesquisa sequencial tornaria o tempo de acerto de uma cache associativa por conjunto muito lento. . Em uma cache totalmente associativa. A cache diretamente mapeada possui um mesmo RESPOSTA número de conjuntos e blocos e. associativas por conjunto de duas e quatro vias e totalmente associativas. Consequentemente. um endereço de 32 bits produz 32 – 4 = 28 bits para serem usados para índice e tag. que é o motivo pelo qual substituímos Memória(0) ao invés de foi usado há mais tempo. Conforme a associatividade aumenta. todos os blocos são candidatos à substituição. o bloco requisitado só pode entrar em exatamente uma posição. já que log2(4K) = 12. Memória(6) na Seção Falhas e associatividade nas caches. o bloco substituído é aquele que usado menos recentemente) Um não foi usado há mais tempo. e o número total de bits de tag é (28 – 10) × 4 × 1K = 72 × 1K = 72 Kbits. o maior tamanho e potência da CAM geralmente levam a uma associatividade por conjunto em duas vias e quatro vias sendo construída a partir de SRAMs padrão e comparadores. Para uma cache associativa por conjunto de quatro vias. Em um esquema LRU. existem 2K de conjuntos. uma escolha de qual bloco substituir. Em vez de fornecer um endereço e ler uma palavra como uma RAM. precisamos escolher entre os blocos do conjunto selecionado. um tamanho de bloco de EXEMPLO quatro palavras e um endereço de 32 bits. Cada grau de associatividade diminui o número de conjuntos por um fator de dois e.3  Medindo e melhorando o desempenho da cache 391 Detalhamento: Uma Content Addressable Memory (CAM) é um circuito que combina com- paração e armazenamento em um único dispositivo. Em uma cache associativa. a im- plementação do LRU se torna mais difícil. 12 bits de índice. O esquema mais comum é o LRU (Least Recently Used – usado menos recentemente). o número total de conjuntos é 1K. com oito vias em diante sendo construídas usando CAMs. . temos uma escolha de onde colocar o bloco requisitado e. Em 2008. 5. LRU (Least Recently Used – que usamos no exemplo anterior. Em uma cache totalmente associativa. o controle de quando os dois elementos foram usados pode ser implementado mantendo um único bit em cada conjunto e definindo o bit para indicar um elemento sempre que este é referenciado. na Seção 5. O exemplo associativo por conjunto anteriormente neste esquema de substituição em que o bloco substituído é aquele que não capítulo utiliza LRU. Para uma cache totalmente associativa. encontre o número total de conjuntos e o número total de bits de tag para caches que são diretamente mapeadas. Considerando uma cache de 4K blocos. Como existem 16 (=24) bytes por bloco. Em uma cache associativa por conjunto. portanto. você fornece os dados e a CAM verifica se tem uma cópia e retorna o índice da linha correspondente. Para uma cache associativa por conjunto de duas vias. e o número total de bits de tag é (28 – 11) × 2 × 2K = 34 × 2K = 68 Kbits. e a tag possui 28 bits. portanto. Tamanho das tags versus associatividade do conjunto O acréscimo da associatividade requer mais comparadores e mais bits de tag por bloco de cache. portanto.5. para uma cache associativa por conjunto de duas vias. As CAMs significam que os projetistas de cache podem proporcionar a implementação de uma associativa por conjunto muito mais alta do que se tivessem de construir o hardware a partir de SRAMs e comparadores. A substituição LRU é implementada monitorando quando cada elemento em um con- junto foi usado em relação aos outros elementos no conjunto. e o bloco ocupando essa posição precisa ser subs- tituído. diminui o número de bits usados para indexar a cache por um e aumenta o número de bits na tag por um. produzindo um total de 28 × 4K × 1 = 112K de bits de tag. veremos um esquema alternativo para substituição. há apenas um conjunto com blocos de 4K de blocos. o número total de bits de tag é (28 – 12) × 4K = 16 × 4K = 64 Kbits. Escolhendo que bloco substituir Quando uma falha ocorre em uma cache diretamente mapeada. logo. Essa cache de segundo nível normalmente está no mesmo chip e é aces- sada sempre que ocorre uma falha na cache primária. que será muito menor do que o tempo de acesso à memória principal.5%? A penalidade de falha para a memória principal é RESPOSTA 100 ns = 400ciclosdeclock ns 0‚25 ciclodeclock O CPI efetivo com um nível de cache é dado por CPI total = CPI básico + Ciclosde stall de memória por instrução Para o processador com um nível de cache. A penalidade da falha para um acesso à cache de segundo nível é 5 ns = 20ciclosdeclock ns 0‚25 ciclodeclock Se a falha for satisfeita na cache secundária. Para diminuir a diferença entre as rápidas velocidades de clock dos processadores modernos e o tempo relativamente longo necessário para acessar as DRAMs. a penalidade de falha para a cache de primeiro nível será o tempo de acesso à cache de segundo nível. incluindo todo o tratamento de falhas. Se a cache de segundo nível contiver os dados desejados.0. um acesso à memória principal será necessário.0 + Ciclosde stall de memória por instrução = 1. uma falha na cache primária (ou de primeiro nível) pode ser satisfeita pela cache secundária ou pela memória principal. Em que grau é significante a melhora de desempenho pelo uso de uma cache secundária? O próximo exemplo nos mostra.0 + 2% × 400 = 9 Com dois níveis de cache. Considere um tempo de acesso à memória principal de 100ns. Suponha que a taxa de falhas por instrução na cache primá- ria seja de 2%. Desempenho das caches multinível Suponha que tenhamos um processador com um CPI básico de 1.392 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Reduzindo a penalidade de falha usando caches multiníveis Todos os computadores modernos fazem uso de caches. e uma penalidade de falha maior será observada. Se a falha precisar ir à memória principal. Se nem a cache primária nem a secundária contiverem os dados. . então. essa será toda a penalidade de falha. O quão mais rápido será o processador se acrescentarmos uma cache secundária que tenha um tempo de acesso de 5ns para um acerto ou uma falha e que seja grande o suficiente de modo a reduzir a taxa de falhas para a memória principal para 0. considerando EXEMPLO que todas as referências acertem na cache primária e uma velocidade de clock de 4GHz. CPI total = 1. a penalidade de falha total será a soma do tempo de acesso à cache secundária e do tempo de acesso à memória principal. muitos microprocessadores suportam um nível adicional de cache. uma estrutura de cache de dois níveis permite que a cache primária se concentre em minimizar o tempo de acerto para produzir um ciclo de clock mais curto. A Figura 5.18(c) responde olhando as falhas de cache por item ordenado: o Quicksort possui muito menos falhas por item a ser ordenado. Como dis- semos na introdução. entender o comportamento da hierarquia de memória é vital para compreender o desempenho dos programas nos computadores atuais. a análise algorítmica padrão ignora o impacto da hierarquia de memória. bem como o tempo de acesso à memória principal (0. a cache primária de uma cache multinível normalmente é menor. o processador com a cache secundária é mais rápido por um fator de 9‚0 = 2‚6 3‚4 Como alternativa. Primeiro. O efeito dessas mudanças nas duas caches pode ser visto comparando cada cache com o projeto ótimo para um nível único de cache.5%) × 20 = 0. A classificação tem sido exaustivamente analisada para se encontrar algoritmos melhores: Entendendo Bubble Sort.5% × (20 + 400) = 2. a cache primá. A Figura 5. o Radix Sort possui uma vantagem algorítmica sobre o Quicksort dos programas em termos do número de operações. cache multinível  Uma hierarquia ria frequentemente usa um tamanho de bloco menor. o CPI total é a soma dos ciclos de stall dos dois níveis de cache e o CPI básico: CPI total = 1 + Stalls primários por instrução + Stalls secundários por instrução = 1 + 2% × 20 + 0.18(a). A soma. para uma cache de dois níveis. enquanto permite que a cache secundária focalize a taxa de falhas no sentido de reduzir a penalidade dos longos tempos de acesso à memória.5% × 400 = 1 + 0. Além disso.1. que precisam incluir o custo para acessar a cache secundária. Podemos ver que as linhas começam na mesma trajetória da Figura 5. 1. é novamente 3. em vez de apenas uma cache e a memória principal. No exemplo “Falhas e . a linha do Radix Sort diverge conforme os dados a serem orde- nados aumentam. À medida que velocidades de clock mais altas e a Lei de Moore permitem aos arquitetos compactarem todo o desempenho de um fluxo de instruções. Em comparação. já que o tempo de acesso da cache secundária é menos importante. para se adequar ao tamanho de cache de memória com múltiplos níveis menor e à penalidade de falha reduzida. para arrays grandes. As considerações de projeto para uma cache primária e secundária são significativamente diferentes porque a presença da outra cache muda a melhor escolha em comparação com uma cache de nível único.0 + 0. agora existem vários tipos diferentes de falhas e taxas de falhas correspondentes. Em especial. o desempenho te. Quicksort e assim por diante. Com um tamanho total maior. será maior do que em uma cache de nível único. Em comparação com uma cache de nível único.3) e as referências que vão à memória principal. Ela constantemente utili- za uma associatividade maior que a cache primária. a cache secundária normalmente de cache.18(b) mostra o tempo por chave em vez das instruções executadas. Infelizmente.3  Medindo e melhorando o desempenho da cache 393 Logo. a cache secundária pode usar um tamanho de bloco maior do que o apropriado com uma cache de nível único. dado o foco da redução de taxas de falha.4.3 + 2. Detalhamento:  Caches multiníveis envolvem diversas complicações. então. Decididamen. 4 Portanto. O que está ocorrendo? A Figura 5. 4 + 2.18(a) mostra as instruções executa- das por item pesquisado pelo Radix Sort em comparação com o Quicksort. poderíamos ter calculado os ciclos de stall somando os ciclos de stall das referências que acertam na cache secundária ((2% – 0. 5. mas.1). um uso correto da hierar- quia de memória é fundamental para a obtenção de um alto desempenho.0 = 3. A ideia básica das otimizações de cache é usar todos os dados em um bloco repetidamente antes de serem substituídos em uma falha. No exemplo anterior citado. Esses dados são de um artigo de LaMarca e Ladner [1996]. na cache secundária dividida pelo número de acessos. Embora os números mudassem para computadores mais novos. Como a cache primária filtra os acessos. Essa taxa de falhas é chamada de taxa taxa de falhas local  A fração das de falhas local da cache secundária. anteriormente neste capítulo. taxa de falhas local da cache secundária como: 0.18  Comparando o Quicksort e o Radix Sort por (a) instruções executadas por item ordenado.5%/2% = 25%! Felizmente. (b) tempo por item ordenado e (c) falhas de cache por item ordenado. foram criadas novas versões do Radix Sort que levam a hierarquia de memória em consideração. vimos a taxa de falhas da cache taxa de falhas global  A fração das primária e a taxa de falhas global – a fração das referências que falharam em todos os níveis de referências que falham em todos os cache.11). associatividade nas caches”. para readquirir suas vantagens logarítmicas (veja a Seção 5. podemos calcular a multiníveis. que é a taxa de todas as falhas níveis de uma cache multinível. Devido a esses resultados. a taxa de falhas local da cache secundária é que falham. a taxa de falhas global determina a frequência com que precisamos acessar a memória principal.394 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. usada em hierarquias muito mais alta do que a taxa de falhas global. especialmente referências a um nível de uma cache aqueles com boa localidade espacial e temporal. a ideia ainda permanece. . Há também uma taxa de falhas para a cache secundária. escolhido por indexação. pesquisam o espaço de parâmetros em tempo de execução de modo a encontrar a melhor combinação para um determinado computador. examinamos o uso dos esquemas de posicionamento associativos. algumas bibliotecas numéricas recentes parametrizam os seus algoritmos e. O desafio. portanto. As caches de primeiro nível são mais focalizadas na taxa de falhas. Uma regra é que o processador muitas vezes oculta a penalidade de falha para uma falha de cache L1 que acerta na cache L2. o desempenho é mais complexo. Somente vendo a execução do processador durante cada falha é que podemos ver se o processador sofre stall esperando os dados ou simplesmente encontra outro trabalho para fazer. Esses esquemas podem reduzir a taxa de falhas de uma cache permitindo um posicionamento mais flexível dos blocos dentro dela.3  Medindo e melhorando o desempenho da cache 395 Detalhamento:  Com processadores que usam execução fora de ordem (ver Capítulo 4). e as caches de segundo nível se preocupam mais com o tempo de acerto. O grau de associatividade que produz o melhor desempenho depende da tecnologia e dos detalhes da implementação. 5. mas são mais rápidas de serem acessadas. na associa- tividade. Essa técnica é chamada de autotuning. Para reduzir a taxa de falhas. As caches de primeiro nível são mais focalizadas no tempo de acerto. As caches associativas por conjunto são uma alternativa prática. é reduzir um desses fatores sem afetar significativamente os outros fatores críticos na hierarquia de memória. usamos falhas por instrução e esta fórmula: Ciclosde stall da memória Falhas = × (Latência de falha total – Latência de falha sobreposta ) Instrução Instrução Não há uma maneira geral de calcular a latência de falha sobreposta. e as caches de segundo nível se preocupam mais com a taxa de falhas. nos concentramos em três tópicos: o desempenho da cache. o uso da as- sociatividade para reduzir as taxas de falhas e o uso das hierarquias de cache multinível para reduzir as penalidades de falha. Finalmente. 2. como veremos na Seção 5. já que executam instruções durante a penalidade de falha. . O sistema de memória tem um efeito significativo sobre o tempo de execução do pro- grama. Qual das afirmações a seguir geralmente é verdadeira sobre um projeto com múltiplos Verifique você níveis de cache? mesmo 1. então. As caches associativas por conjunto apresentam taxas de falhas mais altas.5. Detalhamento:  O desafio do desempenho para algoritmos é que a hierarquia de memória varia entre diferentes implementações da mesma arquitetura no tamanho de cache. Os esquemas totalmente as- sociativos permitem que os blocos sejam posicionados em qualquer lugar. Em vez da taxa de falhas de instruções e da taxa de falhas de dados. mas também exigem que todos os blocos da cache sejam pesquisados para atender a uma requisição. as avaliações das hierarquias de memória para processadores com execução fora de ordem inevitavelmente exigem simulações do processador e da hierarquia de memória. Os custos mais altos tornam as caches totalmente associativas inviáveis. já que precisamos pesquisar apenas entre os elementos de um único conjunto. mas raramente oculta uma falha para a cache L2. no tamanho de bloco e no número de caches. O número de ciclos de stall de memória depende da taxa de falhas e da penalidade de falha. Resumo Nesta seção. Para fazer frente a essa variabilidade. examinamos as caches multiníveis como uma técnica para reduzir a penali- dade de falha permitindo uma cache secundária maior para tratar falhas na cache primária. chamada de memória física para distingui-la da memória virtual) e pelo armazenamento secundário. One-level storage permitir o compartilhamento seguro e eficiente da memória entre vários programas system. trata muitos acessos que falham na cache primária. que usa a memória principal como uma “cache” para armazenamento É claro que. mento de um programa contra outros programas. um com o outro. para permitir que vários programas compartilhem a mesma memória. Nesses casos. Como você pode bem imaginar. exatamente como uma cache contém apenas a parte ativa de um programa. Quatro décadas após sua invenção. Assim como na associatividade. Antigamente. dividiam os programas em partes e. virtual. Não podemos saber quais programas irão compartilhar a memória com outros pro- gramas quando os compilamos. intencionalmente durante a execução. preci- secundário. a memória depósito de nível único. então. As chamadas entre procedimentos em módulos diferentes de usuário. Historicamente. A segunda motivação para a memória virtual é permitir que um único programa do proteção  Um conjunto de usuário exceda o tamanho da memória principal. menos de dez ciclos de processador) contra o tempo de acesso à memória (normalmente mais de 100 ciclos de processador). . lendo ou um overlay que não estivesse carregado e que os overlays carregados nunca excederiam o escrevendo dados no outro. Na verdade. e a memória virtual nos permite compartilhar eficientemente o processador e a memória principal. gostaríamos de compilar cada programa para o seu próprio espaço de endereçamen- to – faixa distinta dos locais de memória acessível apenas a esse programa..4   Memória Virtual de memória e os tambores de discos aparecer para o Na seção anterior. Da mesma forma. Esse processo de tradução impõe a proteção do espaço de endereça- memória principal. cabia ao programador fazê-lo se adequar. A memória virtual implementa a tradução do espaço de endereçamento de um programa para os endereço físico  Um endereço na endereços físicos. Os overlays eram tradicionalmente organizados como módulos. as negociações de projeto entre o tamanho da cache secundária e seu tempo de acesso dependem de vários aspectos de implementação. Esses mecanismos também isolam o tamanho total da memória. 1962 e remover os transtornos de programação de uma quantidade pequena e limitada de memória principal. identificavam aquelas mutuamente exclusivas. os programas que compartilham a memória mudam dinamicamente enquanto estão sendo executados. Os programadores compartilhando processador. A memória virtual. com o programador garantindo que o programa nunca tentaria acessar ou não. que normalmente é 10 ou mais vezes maior do que a cache primária. levavam um módulo a se sobrepor a outro. memória ou dispositivos de E/S não Esses overlays eram carregados ou descarregados sob o controle do programa do usuário possam interferir. A memória principal precisa conter apenas as partes ativas dos muitos programas. normal- as transferências necessárias mente implementado com discos magnéticos. Essa técnica é chamada de memória ocorrendo automaticamente. A cache secundária. Devido a essa interação dinâ- mica. samos ser capazes de proteger os programas uns dos outros. …foi inventado um sistema para fazer a combinação entre os sistemas centrais 5. com principal pode agir como uma “cache” para o armazenamento secundário. o princípio da localidade possibilita a memória virtual e as caches. houve duas motivações principais para a memória virtual: Kilburn et al. o primeiro motivo é o que ainda predomina. se um programa se tornasse mecanismos para garantir que múltiplos processos muito grande para a memória. a penalidade de falha é aquela do tempo de acesso à cache secundária (em geral. vimos como as caches fornecem acesso rápido às partes recente- programador como um mente usadas do código e dos dados de um programa. criada para aliviar os programas dessa dificuldade. sistema operacional de um processo cada um contendo código e dados. essa responsabilidade era uma carga substancial para os programadores. gerencia automaticamente os dois níveis da hierarquia de memória representados pela memória principal (às vezes. Portanto. memória virtual  Uma técnica Considere um grupo de programas executados ao mesmo tempo em um computador. garantindo que um programa só possa ler e escrever as partes da memória principal atribuídas a ele.396 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória As caches de segundo nível se tornaram comuns quando os projetistas descobriram que o silício limitado e as metas de altas velocidades de clock impedem que as caches primárias se tornem grandes. 20 mostra a tradução do número de página virtual para um número de página física. mapeamento de endereço para um ria principal. em vez disso. Seção “Um lugar se- guro para os dados”). todos os sistemas de memória virtual em uso atualmente relocam o programa como um conjunto de blocos (páginas) de tamanho fixo. FIGURA 5. O processador gera endereços virtuais enquanto a memória é acessada usando endereços físicos. também é possível que uma página virtual esteja ausente da memória principal e não seja mapeada para um endereço físico. A Figura 5. traduzido por uma combinação de hardware e software para um endereço endereço virtual  Um endereço físico. A Figu. 5. O número de bits no campo offset de página determina o tamanho da página. os blocos de memória (chamados de páginas) são mapeados de um conjunto de endereços (chamados de endereços virtuais) em outro conjunto (chamado de endereços físicos). e uma falha da memória virtual é principal. a necessidade de encontrar um bloco contíguo de memória para alocar um programa. chamada de falta de página. endereço. A relocação mapeia os endereços virtuais usados por um programa para diferentes endereços físicos antes que os endereços sejam usados no acesso à memória.19 mostra a memória endereçada virtualmente com páginas mapeadas na memó. falta de página  Um evento que suas diferentes raízes históricas levaram ao uso de uma terminologia diferente. que. assim. os dois níveis de hierarquia de memória controlados pela memória é acessada. de modo que uma página virtual é realmente mapeada em uma página física. o processador produz um ende- reço virtual. residindo no disco em vez disso. Hoje. Ter um número de páginas virtuais maior do que as páginas físicas é a base para a ilusão de uma quantidade de memória virtual essencialmente ilimitada. chamada de mapeamento de blioteca. pode ser usado de modo a acessar a memória principal. virtual são as DRAMs e os discos magnéticos (veja o Capítulo 1. constitui a parte menos significativa. Um ocorre quando uma página acessada não está presente na memória bloco de memória virtual é chamado de página. Na memória virtual. Essa capacidade é usada para permitir que dois programas diferentes compartilhem dados ou código. Além disso. o sistema operacional só precisa encontrar um número suficiente de páginas na memória principal. por sua vez. eliminando. enquanto o offset de página. podemos pensar no tradução de endereço Também endereço virtual como o título de um livro e no endereço físico como seu local na bi.19  Na memória virtual. Se voltarmos à nossa analogia da biblioteca. A memória virtual também simplifica o carregamento do programa para execução fornecendo relocação. O número de páginas endereçáveis com o endereço virtual não precisa corresponder ao número de páginas endereçáveis com o endereço físico. Essa relocação nos permite carregar o programa em qualquer lugar na memória principal. As páginas físicas podem ser compartilhadas fazendo dois endereços virtuais apontarem para o mesmo endereço físico. O processo pelo qual um endereço virtual é mapeado a um endereço usado para acessar a memória. que corresponde a um local no espaço virtual e é traduzido pelo ra 5. o endereço é desmembrado em um número de página virtual e um offset de página. que não é alterado. Tanto a memória virtual quanto a memória física são desmembradas em páginas.4  Memória Virtual 397 Embora os conceitos aplicados na memória virtual e nas caches sejam os mesmos. . O número de página física constitui a parte mais significativa do endereço físico. Esse processo é chamado de mapeamento de endereço ou tradução de endereço físico quando a memória endereço. Naturalmente. Com a memória virtual. processadores de 32 bits já são pro- blemáticos. Além disso. Uma falta de página levará milhões de ciclos de clock para ser processada.1 mostra que a memória principal é aproximadamente 100.) Essa enorme penalidade de falha. visto que as escritas levam muito tempo. o software pode se dar ao luxo de usar algoritmos inteligentes para escolher como posicionar as páginas. leva a várias decisões importantes nos sistemas de memória virtual: j As páginas devem ser grandes o suficiente para tentar amortizar o longo tempo de acesso. a memória principal pode ter. dominada pelo tempo para obter a primeira palavra para tamanhos de página típicos. tradicionalmente é chamada de falta de página.000 vezes mais rápida do que o disco. 1GB.20  Mapeamento de um endereço virtual em um endereço físico. Tamanhos de 4KB a 16KB são comuns atualmente. j Organizações que reduzem a taxa de faltas de página são atraentes. As próximas subseções tratam desses fatores no projeto de memória virtual. . O número de páginas físicas permitido na memória é 218. j As faltas de página podem ser tratadas em nível de software porque o overhead será pequeno se comparado com o tempo de acesso ao disco. A principal técnica usada aqui é permitir o posicionamento totalmente associativo das páginas na memória. embora novos sistemas embutidos estejam indo na outra direção. Em vez disso. (A tabela na Seção 5. os sistemas de memória virtual usam write-back. no máximo. enquanto o espaço de endereço virtual possui 4GB. j O write-through não funcionará para a memória virtual. na memória virtual. já que o número de página física contém 18 bits. Nenhum programa único pode se beneficiar. Detalhamento:  Embora normalmente imaginemos os endereços virtuais como muito maio- res do que os endereços físicos. Para computadores servidores e desktops. já que mesmo pequenas reduções na taxa de falhas compensarão o custo desses algoritmos. mas um grupo de programas executados ao mesmo tempo pode se beneficiar de não precisar ser trocado para a memória ou de ser executado em processadores paralelos. Muitas escolhas de projeto nos sistemas de memória virtual são motivadas pelo alto custo de uma falha. para páginas de 1KB. Novos sistemas de desktop e servidor estão sendo desenvolvidos para suportar páginas de 32KB e 64KB. Portanto. o contrário pode ocorrer quando o tamanho de endereço do processador é pequeno em relação ao estado da tecnologia de memória. O tamanho de página é 212 = 4KB.398 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. que. que monitoram o uso de páginas. juntamente com o contador de programa e os registradores. 5. Se permitirmos que uma página virtual seja mapeada em qualquer página física. O principal mapeado para um endereço físico. discutiremos o assunto em mais detalhes em breve. um endereço consiste em duas partes: um número de segmento e um offset mapeamento de endereço de de segmento. que mapeia o espaço de endere. Cada programa possui sua própria tabela de páginas. precisamos salvar esse estado. A capacidade de usar um esquema de substituição inteligente e flexível reduz a taxa de faltas de página e simplifica o uso do posicionamento de páginas totalmente associativo.3. armazenada na çamento virtual desse programa para a memória principal. esse registrador é chamado de registrador de tabela de páginas. O software . Posicionando uma página e a encontrando novamente Em razão da penalidade incrivelmente alta decorrente de uma falta de página. de endereçamento. que usa blocos de tamanho fixo. Uma tabela de páginas é indexada pelo tabela de páginas  A tabela com as número de página do endereço virtual para descobrir o número da página física correspon. e uso da segmentação é suportar métodos de proteção mais avançados e compartilhar um espaço um offset de segmento. Se quisermos permitir que outro programa use o processador. O registrador de segmento é mapeado a um endereço físico e o offset é somado tamanho variável em que um para encontrar o endereço físico real. Muitas arquiteturas dividem o espaço de endereçamento em grandes blocos de tamanho fixo que simplificam a proteção entre o sistema operacional e os programas de usuário e aumentam a eficiência da paginação. então. A tabela. já que ela pode estar em qualquer lugar no nível superior da hierarquia. dos quais os programadores e compiladores precisam estar cientes. considere que a tabela de páginas esteja em uma área fixa e contígua da memória. Por exemplo. veremos que a tabela de páginas pode número da página física para essa página virtual se a página estiver conter entradas para páginas não presentes na memória. A paginação. o sistema operacional. Nos sistemas de memória virtual. Essas tentativas têm sido malsucedidas devido à dificuldade e ao ônus de desempenho inerentes a um endereço de duas partes. Em nossa analogia da biblioteca. Exatamente como o catálogo de cartões pode conter entradas para livros em cada entrada na tabela contém o outra biblioteca ou campus em vez da biblioteca local. o programa pode hardware/ continuar a execução. traduções de endereço virtual para dente. Como mencionamos na Seção 5. localizamos páginas usando uma tabela que indexa a memória. Há também um esquema de blocos de tamanho variável chamado segmentação. essa estrutura é cha- mada de tabela de páginas e reside na memória. uma verifica. Como o segmento pode variar em tamanho. endereço consiste em duas partes: um número de segmento. torna o limite entre o número de página e o offset invisível aos programadores e compiladores. páginas na memória. A fim de indicar o local da tabela de atualmente na memória. os projetistas reduzem a frequência das faltas de página otimizando seu posicionamento. segmentação  Um esquema de Na segmentação. memória. Frequentemente nos referimos a esse estado como um processo. esse mecanismo é muito mais simples do que a segmentação de tamanho de bloco variável e não é visível aos programas do usuário. normalmente é indexada a tabela de páginas corresponde a um mapeamento entre os títulos dos livros e os locais pelo número de página virtual. A tabela de páginas. a dificuldade em usar posicionamento totalmente as- sociativo está em localizar uma entrada.4  Memória Virtual 399 Detalhamento:  A discussão da memória virtual neste livro focaliza a paginação. pode escolher substituir qualquer página que desejar quando ocorrer uma falta de página. Mais tarde. físico em um sistema de memória virtual. para tentar escolher uma página que não será necessária por um longo tempo. A principal desvantagem da segmentação é que ela divide o espaço de endereço em partes logicamente separadas que precisam ser manipuladas como um endereço de duas partes: o número de segmento e o offset. após restaurar esse estado. Por enquanto. especifica Interface o estado de um programa. que é ção de limites é necessária para garantir que o offset esteja dentro do segmento. Os segmentos também têm sido usados como um método para estender o espaço de endereçamento sem mudar o tamanho da palavra do computador. o hardware inclui um registrador que aponta para o início da tabela de páginas. da biblioteca. por outro lado. Uma pesquisa completa é impraticável. A maioria dos livros de sistemas operacionais contém extensas discussões sobre a segmentação comparada com a paginação e sobre o uso da segmentação para comparti- lhar logicamente o espaço de endereçamento. o sistema operacional pode usar um sofisticado algoritmo e complexas estruturas de dados. Embora essas divisões normalmente sejam chamadas de “segmentos”. consequentemente. de modo que os espaços de endereço virtuais dos diferentes processos não colidam. a página está na memória e a entrada contém o número de página física. todos os dados que ele pode acessar na memória. a página não está presente na memória. exatamente como faríamos em uma cache. ou 4GB. Os bits extras seriam usados para armazenar informações adicionais que precisam ser mantidas página a página. que reside na memória. Cada processo possui sua própria tabela de páginas. e o espaço de endereçamento físico é 230 bytes. Consideramos um endereço de 32 bits. O espaço de endereçamento do processo. é definido pela sua tabela de páginas. Nessa figura. O bit de validade para cada entrada indica se o mapeamento é legal. o sistema operacional simplesmente carrega o registrador de tabela de páginas de modo a apontar para a tabela de páginas do processo que ele quer tornar ativo. já que dife- rentes processos usam os mesmos endereços virtuais. ou 4KB. o que irá iniciar a execução no valor salvo do contador de programa. O espaço de endereço virtual é 232 bytes. incluindo o contador de programa. Um bit de validade é usado em cada entrada de tabela de páginas. caso contrário.400 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória processo é considerado ativo quando está de posse do processador. O endereço inicial da tabela de páginas é dado pelo ponteiro da tabela de páginas. FIGURA 5. ou um milhão de entradas. Se ele estiver desligado. .21 usa o registrador de tabela de páginas. a página não está presente na memória principal e ocorre uma falta de página. O sistema operacional pode tornar um processo ativo carregando o estado do processo. ela normalmente seria arredondada para 32 bits a fim de facilitar a indexação. Se o bit estiver ligado. ele é considerado inativo. Em vez de salvar a tabela de páginas inteira. o uso de tabelas de páginas separadas também fornece proteção de um processo contra outro.21  A tabela de páginas é indexada pelo número de página virtual para obter a parte correspondente do endereço físico. Se o bit estiver desligado. Embora a entrada de tabela de páginas mostrada aqui só precise ter 19 bits de largura. Como veremos em breve. como a proteção. que permite uma memória principal de até 1GB. O sistema operacional é responsável por alocar a memória física e atualizar as tabelas de páginas. O número de entradas na tabela de páginas é 220. o tamanho de página é 212 bytes. A Figura 5. e. o endereço virtual e a tabela de páginas indicada para mostrar como o hardware pode formar um endereço físico. a tabela de páginas fornece o número de página física (ou seja. Esse espaço do disco é chamado de área de swap. em um endereço de disco especificado. a tabela de endereços de página física e endereços de página de disco. ocorre uma falta de página. é neces- sário monitorar o local no disco de cada página em um espaço de endereçamento virtual. O sistema operacional precisa receber o controle. o sistema operacional também área de swap  O espaço no cria uma estrutura para registrar onde cada página virtual está armazenada no disco. é armazenada em duas estruturas de dados separadas. Nesse momento. em um sistema de memória virtual. .22 mostra a organização quando uma única tabela contém o número de página física ou o endereço de disco. Se o bit de validade estiver desligado. Se o bit de validade estiver ligado. Essa transferência é feita pelo mecanismo de exceção. porque precisamos manter os endereços de disco de todas as páginas. Voltando à nossa analogia da biblioteca. ele precisa encontrar a página no próximo nível da hierarquia (geralmen- te o disco magnético) e decidir onde colocar a página requisitada na memória principal. Precisamos ir ao catálogo e consultar o livro. As tabelas du- plas se justificam. Faltas de página Se o bit de validade para uma página virtual estiver desligado. 5. mesmo que elas estejam atualmente na memória principal. que é o próximo nível na hierarquia. a página reside atualmente apenas no disco. A Figura 5. que abordaremos posteriormente nesta seção. embora sendo logicamente uma única tabela. FIGURA 5.4  Memória Virtual 401 Como a tabela de páginas contém um mapeamento para toda página virtual possível. Quando o sistema operacional obtém o controle. Lembre-se de que as páginas na memória principal e as páginas no disco são idênticas em tamanho. Da mesma forma. o índice usado para acessar a tabela de páginas consiste no endereço de bloco inteiro. de dados auxiliar indexada da mesma maneira que a tabela de páginas. em parte. O endereço virtual por si só não diz imediatamente onde está a página no disco. O número de página virtual é usado para indexar a tabela de páginas. que é o número de página virtual. não podemos encontrar o local de um livro nas estantes apenas sabendo seu título. Na terminologia da cache. nenhuma tag é necessária. Como não sabemos de antemão quando uma página na memória será escolhida para ser substituída. o sistema operacional normalmente cria o espaço no disco para todas as páginas de um processo no momento em que ele cria o processo.22  A tabela de páginas mapeia cada página na memória virtual em uma página na memória principal ou em uma página armazenada em disco. o endereço inicial da página na memória) correspondente à página virtual. obter um endereço para o local nas estantes. Em muitos sistemas. disco reservado para o espaço de Essa estrutura de dados pode ser parte da tabela de páginas ou pode ser uma estrutura memória virtual completo de um processo. Usando o passado para prever o futuro. Como queremos minimizar o número de faltas de página. podemos calcular o tamanho total da tabela de páginas: 232 Númerodeentradas da tabela de páginas = 12 = 220 2 Tamanhoda tabela de páginas = 220 entradasda tabela de páginas bytes × 22 = 4 MB entrada da tabela de página Ou seja. Um campo periodicamente os bits de referência e. As cinco técnicas a seguir visam a reduzir o armazenamento máximo total necessário. Como alternativa. O sistema operacional procura a página usada menos recentemente. se todas as páginas na memória principal estiverem em uso. Caso você esteja curioso. a hardware/ maioria dos sistemas operacionais aproxima a LRU monitorando que páginas foram software e que páginas não foram usadas recentemente. entradas precisarão ser . os sistemas operacionais seguem o esquema de substituição LRU (Least Recently Used – usado menos recentemente). Detalhamento: Com um endereço virtual de 32 bits. páginas de 4KB e 4 bytes por entrada da tabela de páginas. que é ligado sempre que uma página é acessada. alguns computadores fornecem um bit de referência ou bit bit de referência Também de uso. e se houver centenas de programas rodando. depois. precisaríamos usar 4MB da memória para cada programa em execução em um dado momento. Quando ocorre uma falta de página. Para ajudar o sistema operacional a estimar as páginas LRU. Se esse bit não for fornecido pelo hardware. o sistema operacional precisa escolher uma página para substituir. que por esse cálculo precisaríamos de 252 palavras? Diversas técnicas são usadas no sentido de reduzir a quantidade de armazenamento neces- sária para a tabela de páginas.402 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória O sistema operacional também cria uma estrutura de dados que controla quais processos e quais endereços virtuais usam cada página física. que mencionamos na Seção 5. Interface Implementar um esquema de LRU completamente preciso é muito caro. e essas tabelas controlando a memória estão na memória. o sistema operacional pode selecionar uma página que está entre as referenciadas esquemas de substituição. os detalhes dessa aparente contradição serão explicados em breve. fazendo a suposição de que uma página que não foi usada por um longo período é menos provável de ser usada do que uma página acessada mais recentemente. a maioria dos sistemas operacionais tenta escolher uma página que supostamente não será necessária no futuro próximo. menos recentemente (detectadas tendo seu bit de referência desligado). Essa quantidade não é ruim para um único programa.3. A técnica mais simples é manter um registrador de limite que restrinja o tamanho da tabela de páginas para um determinado processo. o sistema operacional é apenas outro processo. cada um com sua própria tabela de página? E como devemos tratar endereços de 64 bits. Mas. o sistema operacional precisará encontrar outra maneira de estimar que páginas foram acessadas. os registra para que ele possa determinar que é ligado sempre que uma que páginas foram tocadas durante um determinado período. pois requer atualizar uma estrutura de dados a cada referência à memória. Se o número de página virtual se tornar maior do que o conteúdo do registrador de limite. As páginas substituídas são escritas na área de swap do disco. O sistema operacional limpa chamado de bit de uso. bem como minimizar a memória principal dedicada às tabelas de páginas: 1. Com essas informações página é acessada e que é usado para implementar LRU ou outros de uso. que cresce em unidades de páginas. cada segmento pode ter a metade do tamanho do espaço de endereçamento. Devido à essa dualidade. O bit mais significativo de um endereço normalmente determina que segmento – e. é conveniente dividir a tabela de páginas e deixá-la crescer do endereço mais alto para baixo. Essa técnica permite que a tabela de páginas cresça à medida que um processo consome mais espaço. essa forma de segmentação é invisível ao programa de aplicação. A forma como esses problemas são resolvidos é um tema muito detalhado e. embora os segmentos sejam invisíveis ao usuário. usando os bits mais significativos do endereço. Essa estrutura é chamada de tabela de páginas invertida. Diferente do tipo de segmentação abordado na seção “Detalhamento” da Seção 5. a tabela de páginas só será maior se o processo estiver usando muitas páginas do espaço de endereçamento virtual. às vezes. Embora isso pareça complicado.4. Esse tipo de segmentação é usado por muitas arquiteturas. A fim de reduzir a memória principal real consumida pelas tabelas de páginas. o próximo conjunto de bits mais significativos é usado para indexar a tabela de páginas indicada pela entrada da tabela de segmentos. É claro que o processo de consulta é um pouco mais complexo com uma tabela de páginas invertida porque não podemos mais simplesmente indexar a tabela de páginas. 5. inclusive MIPS. A prin- cipal desvantagem desse esquema é que ele não funciona bem quando o espaço de endereçamento é usado de uma maneira esparsa e não como um conjunto contíguo de endereços virtuais.4  Memória Virtual 403 incluídas na tabela de páginas. 3. Essa técnica exige que o espaço de endereçamento se expanda apenas em uma direção. a maioria dos sistemas modernos também permite que as tabelas de páginas sejam paginadas. esse esquema funciona usando os mesmos conceitos básicos da memória virtual e simplesmente permite que as tabelas de páginas residam no espaço de endereçamento virtual. altamente específico ao processador. Entretanto. Outro método para reduzir o tamanho da tabela de páginas é aplicar uma função de hashing no endereço virtual de modo que a estrutura de dados da tabela de páginas precise ser apenas do tamanho do número de páginas físicas na memória principal. O primeiro nível mapeia grandes blocos de tamanho fixo do espaço de endereçamento virtual. A tradução de endereços ocorre primeiramente olhando na tabela de segmentos. sem precisar alocar a tabela de páginas inteira. Um registrador de limite para cada segmento especifica o tamanho atual do segmento. que precisam ser evitadas. chamados de segmentos. embora não para o sistema operacional. Se o endereço do segmento for válido. Isso significa que haverá duas tabelas de páginas separadas e dois limites separados. Esses esquemas são particularmente úteis com espaços de endereçamento muito grandes e em sistemas de software que exigem alocação não contígua. Múltiplos níveis de tabelas de páginas também podem ser usados no sentido de reduzir a quantidade total de armazenamento para a tabela de páginas. que tabela de páginas – deve ser usado para esse endereço. se estiver. talvez de 64 a 256 páginas no total. como uma série interminável de faltas de página. Cada entrada na tabela de segmentos indica se alguma página nesse segmento está alocada e. há alguns problemas pequenos mas cruciais. O uso de duas tabelas de páginas divide o es- paço de endereçamento em dois segmentos. A principal desvantagem desse mapeamento de dois níveis é o processo mais complexo para a tradução de endereços. em geral. Esses grandes blocos são. 2. aponta para uma tabela de páginas desse segmento. Assim. já que a maioria das linguagens exige duas áreas cujo tamanho seja expansível: uma área contém a pilha e a outra contém o heap. Em poucas palavras. e essa tabela de mapeamento de primeiro nível é chamada de tabela de segmentos. Permitir o crescimento apenas em uma direção não é o bastante. Esse esquema permite que o espaço de endereçamento seja usado de uma maneira esparsa (vários segmentos não contíguos podem estar ativos). assim como do endereço mais baixo para cima. 5. esses problemas são evitados colocando todas as tabelas de páginas no espaço de endereçamento do . portanto. 4. Como o segmento é especificado pelo bit de endereço mais significativo. pois as referências às palavras nessa página possuem localidade temporal e também espacial. o dobro do tempo: um acesso à memória para obter o endereço físico e um segundo acesso para obter os dados. A Figura 5. e os esquemas write-through podem ser usados. ela provavelmente será neces- sária novamente no futuro próximo. Como o tempo de transferência de disco é pequeno comparado com seu tempo de hardware/ acesso. O bit de modificação é ligado quando qualquer palavra em uma página é escrita. A TLB corresponde àquele pequeno pedaço de papel que normal- os mapeamentos de endereços mente usamos para registrar o local de um conjunto de livros que consultamos no catá- recentemente usados para evitar um acesso à tabela de páginas. realizando as escritas individuais para a página na memória e copiando a página novamente para o disco quando ela é substituída na memória. as escritas no próximo nível de hierarquia (disco) levam milhões de ciclos de clock de processador. embora mais eficiente do que transferir páginas individuais. Essa cache especial de tradução de endereços é tradicionalmen- TLB (Translation-Lookaside te chamada de TLB (translation-lookaside buffer). portanto. o bit de modificação indica se a página precisa ser escrita no disco antes que seu local na memória possa ser cedido a outra página. Logo. Para monitorar se uma página foi escrita desde que foi lida para a memória. Interface Um esquema write-back possui outra importante vantagem em um sistema de memória virtual. . nunca no disco. os sistemas de memória virtual precisam usar write-back. construir um buffer de escrita para permitir que o sistema escreva diretamente no disco seria impraticável. embora seria mais correto chamá-la Buffer)  Uma cache que monitora de cache de tradução. portanto. um bit de modificação (dirty bit) é acrescentado à tabela de páginas. Portanto. ainda é onerosa. cada acesso à memória por um programa pode levar. como o bit de modificação e o bit de referência.404 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória sistema operacional e colocando pelo menos algumas das tabelas de páginas para o sistema em uma parte da memória principal que é fisicamente endereçada e está sempre presente – e. O segredo para melhorar o desempenho de acesso é basear-se na localidade da referência à tabela de páginas. Se o sistema operacional escolher substituir a página. embora precisemos de um buffer de escrita para ocultar do processador a latência da escrita. que precisará incluir outros bits de status. copiar de volta uma página inteira é muito mais eficiente do que escrever palavras software individuais novamente no disco. uma página modificada normalmente é chamada de “dirty page”. Tornando a tradução de endereços rápida: a TLB Como as tabelas de páginas são armazenadas na memória principal. no mínimo. registramos o local de vários livros e usamos o pedaço de papel como uma cache da biblioteca. E quanto às escritas? A diferença entre o tempo de acesso à cache e à memória principal é de dezenas a centenas de ciclos. Quando uma tradução para um número de página virtual é usada. Assim. Em um sistema de memória virtual. logo. os processadores modernos incluem uma cache especial que controla as tradu- ções usadas recentemente. Uma operação write-back. em vez de pesquisar continuamente o catálogo inteiro. gostaríamos de saber se uma página precisa ser copiada de volta quando escolhemos substituí-la. em vez disso aces- saremos a TLB. Como não iremos mais acessar a tabela de páginas a cada referência.23 mostra que cada entrada de tag na TLB contém uma parte do número de página virtual. Em vez disso. e cada entrada de dados da TLB contém um número de página física. uma vez que as operações básicas são iguais nos dois casos. então. Depois que uma falha de TLB tiver ocorrido e a tradução faltando tiver sido recuperada da tabela de páginas. caso em que ocorre uma falta de página. Os mapeamentos da TLB são mostrados em destaque. as falhas de TLB serão muito mais frequentes do que as faltas de página verdadeiras. Se a página existir na memória. pode haver pouca diferença de desempenho entre os dois métodos. o processador chama o sistema operacional usando uma exceção. precisamos determinar se ela é uma falta de página ou simplesmente uma falha de TLB. com cuidado. copiar de volta essas entradas no momento da falha e não quando são escritas – é muito eficiente. Se a página não estiver presente na memória. 5. Na prática. nenhum campo tag é necessário. ou seja. Nesse caso. Em cada referência. Alguns valores comuns para uma TLB poderiam ser: j Tamanho da TLB: 16 a 512 entradas. Nesse caso. o processador pode tratar a falha de TLB lendo a tradução da tabela de páginas para a TLB e. Se ocorrer uma falha na TLB. Como a TLB possui muito menos entradas do que o número de páginas na memória principal. precisaremos selecionar uma entrada da TLB para substituir. ser usado na construção de uma entrada da TLB) ou indica que a página reside em disco. Se o processador estiver realizando uma escrita. então a falha de TLB indica apenas que a tradução está faltando. depois. o bit de modificação também é ligado. Como a tabela de páginas possui uma entrada para cada página virtual. ela não é uma cache. As falhas de TLB podem ser tratadas no hardware ou no software. O uso de write-back – ou seja. o número de página física é usado para formar o endereço e o bit de referência correspondente é ligado. Se não houver uma entrada correspondente na TLB para uma página. precisamos copiar esses bits de volta para a entrada da tabela de páginas quando substituirmos uma entrada. tentando a referência novamente. Como a TLB é uma cache. então a falha de TLB indica uma falta de página verdadeira. ela precisa ter um campo tag. . Alguns sistemas usam outras técnicas para aproximar os bits de referência e de modificação. Esses bits são a única parte da entrada da TLB que pode ser modificada. a tabela de páginas precisa ser examinada.4  Memória Virtual 405 FIGURA 5. j Tamanho do bloco: uma a duas entradas da tabela de páginas (geralmente 4 a 8 bytes cada uma). já que esperamos que a taxa de falhas da TLB seja pequena. consultamos o número de página virtual na TLB. Como os bits de referência e de modificação estão contidos na entrada da TLB.23  A TLB age como uma cache da tabela de páginas apenas para as entradas que mapeiam as páginas físicas. A tabela de páginas fornece um número de página física para a página (que pode. A TLB contém um subconjunto dos mapeamentos de página virtual para física que estão na tabela de páginas. Se tivermos um acerto. eliminando a neces- sidade de escrever na TLB exceto para carregar uma nova entrada da tabela em caso de falha. escolhida aleatoriamente. normalmente com pequena associatividade. O sistema operacional desempenha um importante papel na manutenção dessa hierarquia removendo o conteúdo de qualquer página da cache quando . muitos sistemas fornecem algum suporte para escolher aleatoriamente uma entrada a ser substituída. uma exceção é gerada. Cada entrada possui 64 bits de largura e contém uma tag de 20 bits (que é o número de página virtual para essa entrada de TLB). que abordaremos em breve. O sistema de memória usa páginas de 4KB e um espaço de endereçamento de 32 bits. A Figura 5. não podemos utilizar um algoritmo de software caro. Além do mais. portanto. o sistema operacional coloca o endereço físico da tabela de páginas na TLB.5 a 1 ciclo de clock j Penalidade de falha: 10 a 100 ciclos de clock j Taxa de falhas: 0. é totalmente associativa e é compartilhada entre as referências de instruções e de dados. além disso. A TLB do Intrinsity FastMATH Para ver essas ideias em um processador real. Para encontrar o endereço físico da página ausente. Esse bit impede que o programa escreva em páginas para as quais tenha apenas acesso de leitura.406 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória j Tempo de acerto: 0. de modo que os dados não podem estar na cache a menos que estejam presentes na memória principal. o número de página virtual tem 20 bits de largura. como as falhas de TLB são muito mais frequentes do que as faltas de página e. O hardware mantém um índice que indica a entrada recomendada a ser substituída. Uma falta de página verdadeira ocorre se a entrada da tabela de páginas não possuir um endereço físico válido. que trata a falha no software. precisam ser tratadas de modo mais econômico. vamos dar uma olhada mais de perto na TLB do Intrinsity FastMATH. res- pectivamente. Integrando memória virtual. o número de página física correspondente (também 20 bits). considerando que o código e a entrada da tabela de páginas estejam na cache de instruções e na cache de dados. (Veremos o código TLB MIPS posteriormente neste capítulo). O endereço físico é do mesmo tamanho do endereço virtual. Alguns sis- temas usam TLBs pequenas e totalmente associativas porque um mapeamento totalmente associativo possui uma taxa de falhas mais baixa. Usando um conjunto especial de instruções de sistema que podem atualizar a TLB. A exceção chama o sistema operacional. que indica o endereço inicial da tabela de páginas do processo ativo.25 mostra as etapas no processamento de uma requisição de leitura ou escrita. Como resultado. portanto. O bit de acesso de escrita faz parte do mecanismo de proteção.01% a 1% Os projetistas têm usado uma ampla gama de associatividades em TLBs. Com um mapeamento total- mente associativo. Outros sistemas usam TLBs grandes. pois é muito caro implementar um esquema de LRU de hardware. escolher a entrada a ser substituída se torna difícil. TLBs e caches Nossos sistemas de memória virtual e de cache funcionam em conjunto como uma hie- rarquia.5. Quando ocorre uma falha de TLB. o custo de um mapeamento totalmente associativo não é tão alto. como no alto da Figura 5. Existe uma complicação extra para requisições de escrita: o bit de acesso de escrita na TLB precisa ser verificado. como a TLB é pequena. o hardware MIPS salva o número de página da referência em um regis- trador especial e gera uma exceção.24. A TLB contém 16 entradas. enquanto a Figura 5. como para as falhas. Se o programa tentar uma escrita e o bit de acesso de escrita estiver desligado.24 mostra a TLB e uma das caches. Veremos os esquemas de substituição mais detalhadamente na Seção 5. Uma falha de TLB leva cerca de 13 ciclos de clock. um bit de modificação e outros bits de contabilidade. um bit de validade. a rotina de falha de TLB indexa a tabela de páginas usando o número de página do endereço virtual e o registrador de tabela de páginas. (Ver memórias endereçáveis por conteúdo na seção “Detalhamento” na seção “Localizando um bloco na cache”. Ao mesmo tempo. a tabela de páginas e a cache. o sistema operacional modifica as tabelas de páginas e a TLB de modo que uma tentativa de acessar quaisquer dados na página migrada gere uma falta de página. RAM de dados com o índice de cache concatenado com o offset de bloco.25 des- creve como tratar escritas. a Figura 5. O exemplo a seguir ilustra essas interações em mais detalhes. Embora a cache seja diretamente mapeada. um endereço virtual é traduzido pela TLB e enviado para a cache em que os dados apropriados são encontrados. uma referência pode falhar em todos os três componentes da hierarquia de memória: a TLB. No pior caso. já que a entrada desejada pode estar em qualquer lugar na TLB. Essa figura mostra a organização da TLB e a cache de dados considerando um tamanho de página de 4KB. Sob as circunstâncias ideais. mas estreita. Endereçando a longa.) Se o bit de validade da entrada correspondente estiver ligado. a TLB é totalmente associativa. 5.24  A TLB e a cache implementam o processo de ir de um endereço virtual para um item de dados no Intrinsity FastMATH. A implementação de uma TLB totalmente associativa exige que toda tag TLB seja comparada com o número de página virtual. o acesso será um acerto de TLB e os bits do número de página física acrescidos aos bits do offset de página formarão o índice usado para acessar a cache. Este diagrama focaliza uma leitura. selecionamos a palavra desejada no bloco sem um multiplexador 16:1. Repare que.9. as RAMs de tag e de dados são divididas. . recuperados e devolvidos ao processador. diferente da Figura 5.4  Memória Virtual 407 FIGURA 5. decide migrar essa página para o disco. Uma cache write-back requer que as escritas liguem um bit de modificação para o bloco de cache. diga se esse evento realmente pode ocorrer e sob que circunstâncias. Se a operação for uma escrita. uma referência de memória pode encontrar três tipos de falhas diferentes: uma falha de TLB. Se a TLB gerar um acerto. o que significa que os dados precisam estar presentes na memória. além disso.24. mas um acerto de cache só pode ocorrer após um acerto de TLB. RESPOSTA A Figura 5. que inclui uma TLB e uma EXEMPLO cache organizada como mostrado. Para uma leitura. a cache gera um acerto ou uma falha e fornece os dados ou causa um stall enquanto os dados são trazidos da memória. uma parte da entrada de cache é substituída por um acerto e os dados são enviados ao buffer de escrita se considerarmos uma cache write-through.408 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. uma falta de página e uma falha de cache. Operação geral de uma hierarquia de memória Em uma hierarquia de memória como a da Figura 5. .26 mostra as circunstâncias possíveis e se elas podem ou não surgir na prática.25  Processando uma leitura ou uma escrita direta na TLB e na cache do Intrinsity FastMATH. Para cada possibilidade. a cache pode ser acessada com o endereço físico resultante. Observe que um acerto de TLB e um acerto de cache são eventos independentes. Considere todas as combinações desses três eventos com uma ou mais ocor- rendo (sete possibilidades). A relação entre as falhas de TLB e as falhas de cache é examinada mais a fundo no exemplo a seguir e nos exercícios no final do capítulo. Uma falha de escrita é exatamente como uma falha de leitura exceto que o bloco é modificado após ser lido da memória. um buffer de escrita é carregado com o bloco inteiro apenas em uma falha de leitura ou falha de escrita se o bloco a ser substituído estiver com o bit de modificação ligado. Três dessas combinações são impossíveis e uma é possível (acerto de TLB. mas usam tags físicas. Essa ambiguidade cria um problema porque uma palavra o mesmo objeto é acessado por nessa página pode ser colocada na cache em dois locais diferentes. já que não é traduzida). dois ende. pode ocorrer na a diferentes endereços virtuais. já que a cache é acessada com um endereço virtual que não foi traduzido para um endereço físico. Quando a cache é acessada com um endereço virtual e páginas são compartilhadas entre programas (que podem acessá-las com diferentes endereços virtuais). mas na realidade ela endereçada  Uma cache tem 16KB. cada um correspondendo dois endereços. Isso tira a TLB do caminho crítico. As caches endereçadas mesma página física. Por exemplo. de modo que o Intrinsity FastMATH pode usar esse truque. 5. Para isso. a quantidade de tempo para acessar a memória.26  As possíveis combinações de eventos na TLB.4  Memória Virtual 409 FIGURA 5. o processador precisa traduzir o endereço para um endereço físico de modo que ele possa buscar o bloco de cache da memória principal. aliasing  Uma situação em que reços virtuais para a mesma página. esses acessos podem ser em pipeline. no entanto. . Quando ocorre uma falha de cache.24 considerou um tamanho de página de 4KB. Esses projetos. Nessa organização. Isso é chamado de cache virtualmente endereçada e usa tags que cache virtualmente são endereços virtuais. no sistema de memória virtual e na cache. completamente por endereços virtuais apresentam limitações de projeto na cache e na TLB para reduzir o aliasing ou exigem que o sistema operacional (e possivelmente o usuário) tome ações para garantir que o aliasing não ocorra. que é um endereço físico. o tamanho da cache e a associatividade. usando apenas a parte do offset de página do endereço. acerto de memória virtual. precisa acomodar um acesso de TLB e um acesso de cache. acesso de cache normal.26 considera que todos os endereços de memória são traduzidos para endereços físicos antes que a cache seja acessada. Uma conciliação comum entre esses dois pontos de projeto são as caches virtualmente indexadas (algumas vezes. Como alternativa. naturalmente. que são virtualmente indexados mas fisicamente rotulados. Essa ambiguidade permitiria que um programa escrevesse os memória virtual quando existem dois endereços virtuais para a dados sem que o outro programa soubesse que eles foram mudados. Nessas caches. é preciso endereçada por um endereço físico. mas nunca detectada. reduzindo a latência da cache. falha de cache). o processador pode indexar a cache com um endereço que seja completa ou parcialmente virtual. haver uma cuidadosa coordenação entre o tamanho de página mínimo. considerando um acerto de cache. a cache é fisica- mente indexada e fisicamente rotulada (tanto o índice quanto a tag de cache são endereços físicos em vez de virtuais). Nesse sistema. não existe qualquer problema de aliasing cache fisicamente nesse caso. o hardware de tradução de endereço (TLB) não é usado durante o com um endereço virtual em vez de um endereço físico. tentam unir as vantagens de desempenho das caches virtualmente indexadas às vantagens da arquitetura mais simples de uma cache fisicamente endereçada. A Figura 5. portanto. há a possibilidade de aliasing. O aliasing ocorre quando o mesmo objeto possui dois nomes – nesse caso. esse tipo de cache é virtualmente indexado e virtualmente endereçada  Uma cache acessada rotulado. Detalhamento: A Figura 5. hardware/ software 1. não desejamos que o programa de um aluno leia as notas enquanto elas estiverem na memória do processador. Portanto. . Também queremos evitar que um processo leia os dados de outro processo. garantindo que um processo do usuário só possa acessar o armazenamento fornecido pelo sistema operacional. embora vários processos estejam compartilhando a mesma memória principal. precisamos fornecer a capacidade de um processo proteger seus dados de serem lidos e escritos por outro processo. Como em qualquer outra exceção. caso contrário. um processo rebelde não pode escrever no espaço de endereçamento de outro processo do usuário ou no sistema operacional. que retorna ao modo usuário e desvia para o endereço no EPC. Usando esses mecanismos e armazenando as tabelas de páginas no espaço de endere- çamento do sistema operacional. e o processador é colocado no modo supervisor. Suportar pelo menos dois modos que indicam se o processo em execução é de usuário ou de sistema operacional. intencionalmente ou não. o sistema operacional usa instruções especiais que só estão disponíveis no modo supervisor. Para escrever esses elementos. que determina operacional. chamado de modo de kernel. (EPC). Uma vez que começamos a compartilhar a memória principal. o ponteiro para a tabela de páginas e a TLB. a memória principal será um poço de per- missividade! Lembre-se de que cada processo possui seu próprio espaço de endereçamento virtual. normalmente chamado de processo supervisor. No entanto. o sistema operacional pode mudar as tabelas de páginas enquanto impede que um processo do usuário as modifique. 3. Fornecer mecanismos pelos quais o processador pode passar do modo usuário para o modo supervisor e vice-versa. Por exem- plo. implementada como uma instrução instrução especial que transfere o especial (syscall no conjunto de instruções MIPS) que transfere o controle para um controle do modo usuário para um local dedicado no espaço de código supervisor. Sem esse nível de proteção. se o processador está no modo usuário ou supervisor. O mecanismo de proteção pre- cisa garantir que. Para retornar ao modo usuário da exceção. local dedicado no estágio de código supervisor. Isso inclui o bit de modo usuário/supervisor. o hardware precisa fornecer pelo menos três capacidades básicas resumidas a seguir. Colocar as tabelas de páginas no espaço de endereçamento protegido do sistema operacional satisfaz a ambos os requisitos. A primeira direção normalmente é consegui- chamada ao sistema Uma da por uma exceção de chamada ao sistema. Interface Para permitir que o sistema operacional implemente proteção no sistema de memória virtual. O bit de acesso de escrita na TLB pode proteger uma página de ser escrita.410 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Implementando proteção com memória virtual Uma das funções mais importantes da memória virtual é permitir o compartilhamento de uma única memória principal por diversos processos. chamando o mecanismo o contador de programa do ponto da chamada de sistema é salvo no PC de exceção de exceção no processo. um processo não será capaz de acessar os dados de outro. use a instrução return from exception (ERET). o sistema operacional precisa ser capaz de modificar as tabelas de páginas. se o sistema operacional mantiver as tabelas de páginas organizadas de modo que as páginas virtuais independentes mapeiem as páginas físicas separadas. O sistema operacional pode garantir segurança se ele impedir que o processo do usuário modifique suas pró- prias tabelas de páginas. É claro que isso exige que um processo de usuário seja incapaz de mudar o mapeamento da tabela de páginas. Fornecer uma parte do estado do processador que um processo de usuário pode executado é um processo do sistema ler mas não escrever. Um modo que indica que um processo 2. modo supervisor Também processo de kernel ou processo executivo. enquanto fornece proteção de memória entre esses processos e o sistema operacional. os vírus de computador seriam ainda mais comuns. de modo que um acerto de TLB ocorra apenas se o número de página e o identificador de processo corresponderem. Quaisquer bits que deter- minam os direitos de acesso a uma página precisam ser incluídos na tabela de páginas e na TLB. Infelizmente. A página não está presente na memória e precisamos transferir o controle para o sistema operacional a fim de lidar com uma falta de página. esse bit pode ser mudado apenas pelo sistema operacional. com uma inclui salvar o estado necessário TLB. P1. Se não houver uma TLB. a cache conterá dados do processo em execução. basta mudar o registrador de tabela de para permitir que um processo diferente use o processador. Uma alternativa comum é estender o espaço de endereçamento virtual acrescentando um identificador de processo ou identificador de tarefa. como o restante da tabela de páginas. uma variedade de solu- ções diferentes. Uma falha de TLB ocorre quando nenhuma entrada na TLB corresponde a um endereço virtual. a página correspondente não está na memória e temos uma falta de página em vez de uma . o tratamento de falhas de TLB e de faltas de página é mais com- plexo. O sistema operacional poderia usar o bit de proteção de escrita a fim de impedir que P1 escrevesse os dados. o sistema operacional precisa assisti-los. além disso. Esse problema ocorre porque os endereços virtuais usados por P1 e P2 são iguais e precisamos limpar a TLB a fim de evitar confundir esses endereços. exceto em raras ocasiões. leia uma página pertencente ao processo P2. descobriria que todas as suas entradas de TLB desapareceram e precisaria pagar falhas de TLB para recarregá-las. iremos procurar uma entrada na tabela de páginas para ser trazida para a TLB. ele é mantido em um registrador carregado pelo sistema operacional quando muda de processo. troca de contexto  Uma mudança ele precisa garantir que P2 não possa ter acesso às tabelas de páginas de P1 porque isso no estado interno do processador comprometeria a proteção. P1. P2 pediria ao sistema operacional para criar uma entrada na tabela de páginas para uma página virtual no espaço de endereço de P1 que aponte para a mesma página física que P2 deseja compartilhar. 5. Como saber qual dessas duas circunstâncias ocorreu? Quando processarmos a falha de TLB. Essa combinação elimina a necessidade de limpar a TLB.4  Memória Virtual 411 Quando os processos querem compartilhar informações de uma maneira limitada. como identificadores de processo. isso poderia ser bastante ineficiente. já que o acesso às informações de outro processo exige mudar a tabela de páginas do processo que está acessando. Problemas semelhantes podem ocorrer para uma cache. P2 poderia carregar apenas algumas entradas de TLB antes que o sistema operacional trocasse novamente para P1. se esse fosse o desejo de P2. Esses problemas surgem de diferentes maneiras para caches física e virtualmente endereçadas. são usadas para garantir que um processo obtenha seus próprios dados. o que páginas de modo que aponte para a tabela de páginas de P2 (em vez da de P1). processos fosse alta. O Intrinsity FastMATH possui um campo ID do espaço de endereçamento (ASID) de 8 bits para essa finalidade. O bit de acesso de escrita pode ser usado para restringir o compartilhamento apenas à leitura e. Se a entrada na tabela de páginas correspondente tiver um bit de validade que esteja desligado. então. Se a taxa de troca de atualmente executado. Por exemplo. 2. Detalhamento:  Quando o sistema operacional decide deixar de executar o processo P1 para executar o processo P2 (o que chamamos de troca de contexto ou troca de processo). já que. Tratando falhas de TLB e faltas de página Embora a tradução de endereços físicos para virtuais com uma TLB seja simples quando temos um acerto de TLB. O identificador de processo é concatenado com a parte da tag da TLB. digamos. A página está presente na memória e precisamos apenas criar a entrada de TLB ausente. em uma troca de processo. pois a tabela de páginas é acessada apenas em uma falha de TLB. Para per- mitir que outro processo. Uma falha de TLB pode indicar uma de duas possibilidades: 1. Esse pequeno campo identifica o processo que está atualmente sendo executado. precisamos limpar as entradas de TLB que pertencem a P1 – tanto para proteger os e retornar ao processo sendo dados de P1 quanto para forçar a TLB a carregar as entradas para P2. Uma falta de página será reconhecida em algum momento durante o ciclo de clock usado para acessar a memória. depois. o contador de programa da instrução que causou a falta de página precisa ser salvo. Uma complicação parecida surge nos stores. caso con- trário. dessa vez ele terá uma exceção de falta de página. Tratar uma falha de TLB ou uma falta de página requer o uso do mecanismo de exceção para interromper o processo ativo. salva o estado apenas suficiente para lhe permitir se recu- ocorrência de exceções durante intervalos antes que o processador perar se outra exceção ocorrer – a saber. necessário para evitar a O sistema operacional.27  Registradores de controle MIPS. ajudam com exceções. podemos simplesmente recuperar a entrada desejada. Interface Entre o momento em que começamos a executar o tratamento de exceção no sistema hardware/ operacional e o momento em que o sistema operacional salvou todo o estado do proces- so. executa novamente a instrução que causou a falha de TLB. pois ela exigirá apenas uma curta sequência de operações que copia uma entrada válida da tabela de páginas da memória para a TLB. se outra software exceção ocorresse quando estivéssemos processando a primeira exceção no sistema operacional. então. FIGURA 5. esse desastre fornecendo a capacidade de desabilitar e habilitar exceções. e isso poderia ser desastroso quando tentássemos reiniciar a instrução.0($1): o computador precisa ser capaz de impedir que o estágio de escrita do resultado do pipeline ocorra. Além disso. exceção. o sistema operacional se torna particularmente vulnerável. Considera-se que estes estejam no coprocessador 0. o processador liga um bit que desabilita todas as outras exceções. depois. e por isso são lidos com mfc0 e escritos com mtc0. Na reexecução. uma falha de TLB ou uma exceção de falta de página precisa ser sinalizada no final do mesmo ciclo de clock em que ocorre o acesso à memória. Por exemplo. os registradores do contador de programa de tenha seguramente salvado o estado exceção (EPC) e Cause. . habilitar exceção Também tornando impossível voltar para a instrução que causou a falta de página! Podemos evitar chamado de “habilitar interrupção”. de modo que o próximo ciclo de clock começará o processamento da exceção em vez de continuar a execução normal das instruções. a unidade de controle substituiria o contador de programa de exceção. Ele traz a entrada da tabela de páginas da memória e.27 mostra o restante. Por exemplo. retomar a execução do processo interrompido. Se a falta de página não fosse reconhecida nesse ciclo de clock. Uma falha de TLB pode ser tratada por software ou por hardware. considere a instrução lw $1. A fim de reiniciar a instrução após a falta de página ser tratada. EPC e Cause são dois dos registradores de controle especiais que necessário para a reinicialização. Se o bit de validade estiver ligado. Se a entrada da tabela de páginas indicar que a página não está na memória. isso normalmente é feito desativando a linha de controle de escrita para a memória. O MIPS tradicionalmente trata uma falha de TLB por software. transferir o controle ao sistema operacional e. a Figura 5. ele terá um acerto de TLB. Precisamos impedir que a escrita na memória realmente seja concluída quando há uma falta de página.412 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória simples falha de TLB. falhas de TLB e faltas de página. isso o processo responde ou não a uma poderia acontecer ao mesmo tempo em que o processador liga o bit de modo supervisor. Assim que uma Uma ação ou sinal que controla se exceção ocorre. uma instrução load poderia substituir um registrador. já que o conteúdo de $1 teria sido destruído. o contador de pro- grama de exceção (EPC) é usado para conter esse valor. Assim como no Capítulo 4. ele não poderia reiniciar corretamente a instrução. Para tornar essa indexação rápida. Consultar a entrada de tabela de páginas usando o endereço virtual e encontrar o local em disco da página referenciada. páginas. Portanto. que indica o endereço inicial da tabela de páginas do processo ativo. Uma vez que o sistema operacional conhece o endereço virtual que causou a falta de página. É claro que essa última etapa levará milhões de ciclos de clock de processador (assim como a segunda. reexecuta a instrução que causou a falta de página. software chamada para “tratar” uma la de páginas usando o número de página do endereço virtual e o registrador de tabela de exceção ou interrupção. o hardware do MIPS salva o número de página da referência em um registrador especial chamado BadVAddr e gera uma exceção. que trata a falha por software. 2. ele pode passar o controle do processador à vontade para outro processo. de modo que a exceção possa ser tratada e a instrução instrução reinicializável Uma possa ser continuada. Quando uma falha de TLB ocorre. Como cada instrução que pode retomar a execução após uma exceção ser instrução escreve apenas um item de dados e essa escrita ocorre no final do ciclo da ins. Como cada entrada de ta- bela de páginas possui uma palavra. 3. 3. se a página escolhida estiver com o bit de modificação ligado. 2. Vejamos o MIPS mais de perto. O controle é transferido para o endereço 8000 0000hexa (o local do handler da falha de TLB). Essas etapas assegu- ram que as exceções não façam com que o processador perca qualquer estado e. então. Lembre-se de . os últimos dois bits são 0. diferente das faltas de página de instruções. portan- to. o hardware do MIPS coloca tudo que você precisa no registrador especial Context: os 12 bits mais significativos têm o endereço da base da tabela de páginas e os próximos 18 bits têm o endereço virtual da página ausente. Essa instrução irá redefinir o processador do modo kernel para o modo usuário. Quando a leitura da página do disco está completa. sejam incapazes de reiniciar a execução da instrução interruptora. se a página substituída estiver com o bit de modificação ligado). o sistema operacional normalmente selecionará outro processo para executar no processador até que o acesso ao disco seja concluído. ela precisará ser escrita no disco antes que possamos definir uma nova página virtual para essa página física. as duas primeiras instruções copiam o registrador Context para o registrador temporário do kernel $k1 e. ele precisa completar três etapas: 1. bem como restaurar o contador de programa. Iniciar uma leitura de modo a trazer a página referenciada do disco para a página física escolhida. carregam a entrada de tabela de páginas desse endereço em $k1. As exceções de falta de página para acessos a dados são difíceis de implementar corre- tamente em um processador devido a uma combinação de três características: 1. Escolher uma página física a ser substituída. é relativamente fácil em uma arquitetura como o MIPS. Elas ocorrem no meio das instruções. 5. Após tratar a exceção. depois. portanto. acessa a página requisitada com sucesso e continua a execução. a instrução precisa ser reinicializada como se nada tivesse ocorrido. resolvida sem que a exceção afete o trução. Como o sistema operacional salvou o estado do processo. a rotina de falha de TLB indexa a tabe. o sistema operacional pode restaurar o estado do processo que causou originalmente a falta de página e executar a instrução que retorna da exceção. A exceção chama o sistema operacional. Tornar instruções reinicializáveis.4  Memória Virtual 413 O sistema operacional. pode habilitar novamente as exceções. O processo do usuário. A instrução não pode ser completada antes que a exceção seja tratada. e reinicializar a instrução no começo. A fim de handler  Nome de uma rotina de encontrar o endereço físico para a página ausente. então. podemos simplesmente impedir que a instrução seja concluída (não escrevendo) resultado da instrução. a falha de TLB possui um ponto de entrada especial que reduz a penalidade para uma falha de TLB. o sistema operacional sabe que será necessário um processamento extenso. esses endereços na parte inferior da memória física. não mapeada  Uma parte do chamada não mapeada (unmapped). Para evitar o problema de uma falta de página durante esse código de exceção de baixo nível. diferente de uma falha de TLB. Detalhamento:  Essa versão simplificada considera que o stack pointer (sp) é válido. o EPC contém o endereço virtual da página que gerou a falta. Random implementa uma substituição aleatória e. O hardware pode ter faltas de página. Note que salvamos e res- tauramos o estado no código MIPS. Se a entrada for inválida. Esse estado in- clui todos os registradores de uso geral e de ponto flutuante. deixando isso para os poucos handlers que precisam deles. A instrução tlbwr copia o registrador de controle EntryLo para a entrada de TLB selecionada pelo registrador de controle Random. Como a exceção para a entrada de TLB ausente é muito mais frequente do que uma falta de página. o EPC e o registrador Cause de exceção. ele trans- fere o controle para 8000 0180hexa. Uma falha de TLB leva cerca de 12 ciclos de clock. o MIPS possui um conjunto especial de instruções de sistema que atualiza a TLB. A seguir está o código MIPS para um handler de falha de TLB típico: Como mostrado anteriormente. Uma vez que o processo que gerou a falta de página tenha sido interrompido. . Esse é o endereço geral para exceção. ele salva todo o estado do processo ativo. Detalhamento:  O código na Figura 5. e o sistema operacional reconhece a falta de página.414 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória que $k0 e $k1 são reservados para uso do sistema operacional sem salvamento. o registrador de endereço de tabela de páginas. portanto. Como os handlers de exceção normalmente não usam os registradores de ponto flutuante.28 esboça o código MIPS de um handler de exceção. o sistema operacional coloca os pontos de entrada dos tratamentos de exceções e as pilhas de exceção na memória não mapeada. Portanto. Como a exceção é uma falta de página. um im- portante motivo dessa convenção é tornar rápido o handler de falha de TLB. MIPS traduz os endereços virtuais 8000 0000hexa a BFFF FFFFhexa para endereços físicos simples- mente ignorando os bits superiores do endereço virtual. O sistema operacional insere o código para o ponto de espaço de endereçamento que não entrada do tratamento de exceções e a pilha de exceção na memória não mapeada. é basicamente um contador de execução livre. A Figura 5. o MIPS separa uma parte do seu espaço de endereçamento que não pode ter faltas de página. um endereço diferente do handler de falha de TLB. o ponto de entrada geral não os salva.28 mostra a sequência de retorno da exceção do MIPS-32. Portanto. O endereço da instrução que gerou a falta está no EPC. O sistema operacional usa o registrador Cause de exceção a fim de diagnosticar a causa da exceção. tomando cuidado quando habilitamos e desabilitamos exceções. Esse método torna rápido o caso frequente de uma falha de TLB. O MIPS-I usa rfe e jr em vez de eret. Observe que o handler de falha de TLB não verifica se a entrada de tabela de páginas é válida. mas chamamos código C para tratar a exceção em particular. Se ela fosse uma falta de página de instruções. o endereço virtual que gerou a falta pode ser calculado examinando a instrução (cujo endereço está no EPC) para encontrar o registrador base e o campo offset. o sistema operacional carrega a TLB da tabela de páginas sem examinar a entrada e reinicializa a instrução. O endereço virtual que causou a falta de página depende se essa foi uma falta de ins- truções ou de dados. colocando. assim. ocorre outra exceção diferente. com uma pequena penalidade de desempenho para o raro caso de uma falta de página. caso contrário. A memória virtual permite que um único programa expanda seu espaço de endereçamento para além dos limites da memória principal. Em vez disso. como fazemos para instruções MIPS. Processar uma instrução pode gerar uma série de faltas de página no meio da instrução. Resumo Memória virtual é o nome para o nível da hierarquia de memória que controla a cache entre a memória principal e o disco. tornar as instruções reiniciáveis é muito mais difícil. é preciso haver uma coordenação cuidadosa e detalhada entre o código de tratamento de exceção no sistema operacional e o hardware. a instrução precisa ser interrompida e mais tarde continuada no meio de sua execução.4  Memória Virtual 415 FIGURA 5.28  Código MIPS para salvar e restaurar o estado em uma exceção. os processadores x86 possuem instruções de movimento em bloco que tocam em milhares de palavras de dados. as instruções normalmente não podem ser reiniciadas desde o início. Retomar uma instrução no meio de sua execução normalmente exige salvar algum estado especial. Por exemplo. Para que isso seja feito corretamente. 5. Detalhamento:  Para processadores com instruções mais complexas. Mais . Nesses processadores. processar a exceção e restaurar esse estado especial. que podem tocar em muitos locais de memória e escrever muitos itens de dados. Várias técnicas são usadas para reduzir a taxa de falhas: 1. Para garantir que os processos sejam protegidos uns dos outros. Um problema de desempenho mais comum são as falhas de TLB. como LRU e um bit de referência.25MB. A fim de tentar amenizar esse problema. O mapeamento entre endereços virtuais e endereços físicos. de uma maneira protegida. 2. o hardware do MIPS suporta . Por exemplo. Se seu programa realiza thrashing. portanto. Gerenciar a hierarquia de memória entre a memória principal e o disco é uma tarefa difícil devido ao alto custo das faltas de página. Como as gravações no disco são caras. que é implementado com uma tabela de páginas. As páginas são ampliadas para tirar proveito da localidade espacial e para reduzir a taxa de falhas. é um desastre quando ocorre. Entendendo Embora a memória virtual tenha sido criada para permitir que uma memória pequena aja como uma grande. A próxima seção aborda essa estrutura comum. as falhas de TLB normalmente são um problema para o Radix Sort. o que é implementado impedindo que programas de usuário alterem as tabelas de páginas. As caches. a diferença de desempenho entre o disco e a memória significa que se o desempenho um programa acessa rotineiramente mais memória virtual do que a memória física que dos programas possui. Uma opção mais complexa é reexaminar suas estruturas de dados e algoritmo para ver se você pode mudar a localidade e. Esse conjunto de páginas é informalmente chamado de working set. a memória virtual e as TLBs se baseiam em um conjunto comum de princípios e políticas. Por exemplo. é necessário que apenas o sistema operacional possa mudar as traduções de endereços. a memória virtual seria muito dispendiosa e a cache não teria sentido! Em vez disso. reduzir o número de páginas que seu programa usa simultaneamente. sua execução será muito lenta. embora raro. já que o processador pode acessar menos de um quarto de megabyte diretamente: 64 × 4KB = 0. O thrashing. Se um processador precisasse acessar uma tabela de páginas residente na memória para traduzir cada acesso. então. o que chamamos de thrashing. a memória virtual usa um esquema write-back e também monitora se uma página foi modificada (usando um bit de modificação) para evitar gravar páginas não alteradas novamente no disco. como a simplificação da alocação de memória. além da página de 4KB padrão. Os endereços são. a solução mais fácil é executá-lo em um computador com mais memória ou comprar mais memória para o computador. para escolher que páginas substituir.416 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória importante. um programa poderia facilmente ver uma alta taxa de falhas de TLB. a maioria das arquiteturas de computadores agora suporta tamanhos de página variáveis. 3. a memória virtual suporta o compartilhamento da memória principal entre vários processos simultaneamente ativos. Esse programa estaria continuamente trocando páginas entre a memória e o disco. uma TLB age como uma cache para traduções da tabela de páginas. é feito totalmente associativo para que uma página virtual possa ser colocada em qualquer lugar na memória principal. O compartilhamento controlado das páginas entre processos pode ser implementado com a ajuda do sistema operacional e dos bits de acesso na tabela de páginas que indicam se o programa do usuário possui acesso de leitura ou escrita à página. O mecanismo de memória virtual fornece tradução de endereços de um endereço virtual usado pelo programa para o espaço de endereçamento físico usado no acesso à memória. Como uma TLB pode tratar apenas de 32 a 64 entradas de página ao mesmo tempo. O sistema operacional usa técnicas. traduzidos do virtual para o físico usando as traduções na TLB. Essa tradução de endereços permite compartilhamento protegido da memória principal e oferece várias vantagens adicionais. do diretamente mapeado ao associativo por conjunto e ao totalmente associativo.5  de memória Agora você reconhece que os diferentes tipos de hierarquias de memória compartilham muita coisa em comum. Uma cache para uma memória principal. 16MB. Questão 1: onde um bloco pode ser colocado? Vimos que o posicionamento de bloco no nível superior da hierarquia pode utilizar diversos esquemas. Mais uma vez. Associe o elemento da hierarquia de memória à esquerda com a frase correspondente à direita. por exemplo. Cache L1 a. Cache L2 b. TLB d.5  Uma estrutura comum para hierarquias de memória 417 páginas de 16KB. 4. Uma cache para uma cache. Na prática. ele pode acessar mais memória dire- tamente sem falhas de TLB. o problema é fazer o sistema operacional permitir que os programas sele- cionem esses tamanhos de página maiores. 5. a solução mais complexa para reduzir as falhas de TLB é reexaminar as estruturas de dados e os algoritmos no sentido de reduzir o working set de páginas. Examinaremos essas políticas como uma série de questões que se aplicam entre quaisquer dos níveis de uma hierarquia de memória. muitas das políticas e recursos que determinam como uma hierarquia funciona são semelhantes em qualidade. Verifique você mesmo 1. se um programa usa grandes tamanhos de página. toda essa faixa de esquemas pode ser imaginada como variações em um .29 mostra como algumas características quantitativas das hierarquias de memória podem diferir. discutire- mos os aspectos operacionais comuns das hierarquias de memória e como determinar seu comportamento. Embora o intervalo de valores seja grande.29  Os principais parâmetros quantitativos do projeto que caracterizam os principais elementos da hierarquia de memória em um computador. Estes são valores típicos para esses níveis em 2008. 64MB e 256MB. 4MB. A Figura 5. 256KB. 2. 64KB. Uma cache para entradas de tabela de páginas. Embora muitos aspectos das hierarquias de memória difiram quantitativamente. Uma cache para discos. dada a importância dos acessos à memória para o desempenho e a frequência de falhas de TLB. 3. os tamanhos de bloco também crescem. à medida que as caches se tornam maiores para contornar maiores penalidades de falha. Como já dissemos. Memória principal c. No restante desta seção. embora usemos principalmente terminologia de caches por motivo de simplicidade. alguns programas com grandes working sets foram recriados com esse objetivo. Uma estrutura comum para hierarquias 5. Consequentemente. 1MB. FIGURA 5. isso ocorre parcialmente porque muitos dos valores que mudaram com o tempo estão relacionados. como já mencionado.418 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória esquema associativo por conjunto no qual o número de conjuntos e o número de blocos por conjunto variam: Nome do esquema Número de conjuntos Blocos por conjunto Mapeamento Direto Número de blocos na cache 1 Associativo por conjunto Número de blocos na cache Associatividade Associatividade (normalmente 2 a 16) Totalmente associativo 1 Número de blocos na cache A vantagem de aumentar o grau de associatividade é que normalmente isso diminui a taxa de falhas. a oportunidade de melhorar a taxa de falhas diminui e a melhoria absoluta na taxa de falhas da associativi- dade é reduzida significativamente. os benefícios de maior associatividade são menores (por exemplo. Conforme crescem os tamanhos de cache. A Figura 5. FIGURA 5. por sua vez. Embora o benefício de passar de associação por conjunto de uma via (mapeamento direto) para de duas vias seja significativo. já que isso determina o número de locais possíveis. Questão 2: como um bloco é encontrado? A escolha de como localizamos um bloco depende do esquema de posicionamento do bloco. que. Poderíamos resumir os esquemas da seguinte maneira: Associatividade Método de localização Comparações necessárias Mapeamento Direto Indexação 1 Associativo por conjunto Indexação do conjunto. a melhoria relativa da associatividade aumenta apenas ligeiramente. vejamos quanta melhoria é obtida. pesquisa entre os Grau de associatividade elementos Total Pesquisa de todas as entradas de cache Tamanho da cache Tabela de consulta separada 0 . são o custo mais alto e o tempo de acesso mais longo. A melhoria da taxa de falhas deriva da redução das falhas que disputam o mesmo local.30 mostra as taxas de falhas para diversos tamanhos de cache enquanto a associatividade varia de mapeamento direto para a associatividade por conjunto de duas vias. Examinaremos essas falhas mais detalhadamente em breve. A Figura 5.15 explica como esses dados foram coletados. como a perda geral de uma cache maior é menor. o que produz uma redução de 20% a 30% na taxa de falhas. Há ainda menos melhoria ao passar de quatro vias para oito vias. Antes. 1%-10% de melhoria passando de duas vias para quatro vias contra 20%-30% de melhoria passando de uma via para duas vias). pois a taxa de falhas básica de uma cache pequena é maior.30  As taxas de falhas da cache de dados para cada um dos oito tamanhos melhora à medida que a associatividade aumenta. é muito próximo das taxas de falhas de uma cache totalmente associativa. As caches menores obtêm um benefício absoluto muito maior com a associatividade. As possíveis desvantagens da associatividade. A associatividade total permite que softwares usem esquemas sofisticados de subs- tituição projetados para reduzir a taxa de falhas. Incluir a cache L2 no chip permite uma associatividade muito mais alta. o LRU normalmente é aproximado – por exemplo. Se a cache for associativa por conjunto. o LRU é muito oneroso de ser implementado para hierarquias com mais do que um pequeno grau de associatividade (geralmente. a tecnologia usada para implementar a cache e o papel vital do tempo de acesso na determinação do tempo de ciclo do processador. no qual o acesso combina indexação e a pesquisa de um conjunto pequeno. uma tabela de mapeamento separada (a tabela de páginas) é mantida para indexar a memória. A escolha da associatividade total para o posicionamento de página e da tabela extra é motivada pelos seguintes fatos: 1. ambos em termos de tempo e de hardware extra. como se a cache é on-chip. Nos sistemas de memória virtual. os sistemas de memória virtual quase sempre usam posicionamento totalmente associativo. precisamos decidir que bloco subs- tituir. o MIPS suporta substituição aleatória para falhas de TLB. depois.5  Uma estrutura comum para hierarquias de memória 419 A escolha entre os métodos mapeamento direto. Portanto. e o projetista não precisa se basear nos chips SRAM padrão como blocos de construção. Alguns sis- temas têm usado caches com mapeamento direto devido às suas vantagens no tempo de acesso e da simplicidade. O mapa completo pode ser facilmente indexado sem a necessidade de pesquisa e de qualquer hardware extra. já que as falhas são muito caras. usar um índice exige um acesso extra à memória. Essas escolhas de projeto dependem de muitos detalhes da implementação. 5. Mesmo para a associatividade por conjunto de quatro vias. precisamos escolher entre os blocos do conjunto. Questão 3: que bloco deve ser substituído em uma falha de cache? Quando uma falha ocorre em uma cache associativa. A associatividade total é benéfica. nos quais o custo dos comparadores não é grande e as melhorias da taxa de falhas absoluta são as melhores. O posicionamento associativo por conjunto é muitas vezes usado para caches e TLBs. Por exemplo. todos os blocos são candidatos à substituição. Além do armazenamento necessário para a tabela. monitorando qual par de blocos é o LRU (o que requer 1 bit) e. dois a quatro). A vantagem no tempo de acesso ocorre porque a localização do bloco requisitado não depende de uma comparação. talvez usando alguma assistência do hardware. É claro que a substituição é fácil em uma cache diretamente mapeada porque existe apenas um candidato. monitorando que bloco em cada par é o LRU (o que requer 1 bit por par). 2. Existem duas principais estratégias para substituição nas caches associativas por con- junto ou totalmente associativas: j Substituição aleatória: os blocos candidatos são selecionados aleatoriamente. Em uma cache totalmente associativa. j Substituição LRU (Least Recently Used): o bloco substituído é o que não foi usado há mais tempo. As caches totalmente associativas são proibitivas exceto para pequenos tamanhos. já que é oneroso controlar o uso das informações. Na prática. . 3. associativo por conjunto ou to- talmente associativo em qualquer hierarquia de memória dependerá do custo de uma falha comparado com o custo de implementar a associatividade. pois os tempos de acerto não são tão importantes. Os sistemas de memória virtual sempre usam write-back. pelas razões explicadas na Seção 5. algumas vezes. As principais vantagens do write-back são as seguintes: j As palavras individuais podem ser escritas pelo processador na velocidade em que a cache. j Quando blocos são escritos com write-back. o sistema pode fazer uso efetivo de uma transferência de alta largura de banda. cada vez mais caches estão usando uma estratégia write-back. pode aceitar. Como consequência. é aceitável aproximar essa informação. não a memória.420 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Para maior associatividade.2 usaram esse esquema. uma cache write-through precisaria usar um buffer de escrita. pode ser melhor do que as aproximações simples de LRU que são facilmente implementadas em hardware. Como as falhas são muito caras e relativamente raras. . em especial. para ser prática. em nível de software. j O write-through é mais fácil de ser implementado do que o write-back. Na verdade. a substituição aleatória. a taxa de falhas para as duas estratégias de substituição cai e a diferença absoluta se torna pequena. Conforme as caches se tornam maiores. o que significa que o esquema deve ser fácil de implementar. já que o bloco inteiro é escrito. O bloco modifi- cado é escrito no nível inferior da hierarquia apenas quando ele é substituído. j Write-back: as informações são escritas apenas no bloco da cache. o algoritmo de substituição está no hardware. Tanto write-back quanto write-through têm suas vantagens. Já vimos as duas opções básicas: j Write-through: as informações são escritas no bloco da cache e no bloco do nível inferior da hierarquia de memória (memória principal para uma cache). O write-through possui estas vantagens: j As falhas são mais simples e baratas porque nunca exigem que um bloco seja escrito de volta no nível inferior. Nas caches. para uma cache associativa por conjunto de duas vias. ou o LRU é aproximado ou a substituição aleatória é usada. Questão 4: o que acontece em uma escrita? Uma importante característica de qualquer hierarquia de memória é como ela lida com as escritas.1 vez mais alta do que a substituição LRU. a substituição aleatória possui uma taxa de falhas cerca de 1. As caches na Seção 5. já que mesmo uma pequena redução na taxa de falhas pode ser importante quando o custo de uma falha é enorme. Os bits de referência ou funcionalidade equivalente costumam ser fornecidos para facilitar que o sistema operacional monitore um conjunto de páginas usadas menos recentemente. Na memória virtual. j Diversas escritas dentro de um bloco exigem apenas uma escrita no nível inferior da hierarquia. A substituição aleatória é simples de construir em hardware e.4. alguma forma de LRU é sempre aproximada. embora. Em sistemas de memória virtual. até mesmo permitindo memórias física e logicamente mais largas. A taxa em que as escritas são geradas por um processador excederá a taxa em que o sistema de memória pode processá-las. apenas uma política write-back é viável devido à longa latência de uma escrita no nível inferior da hierarquia (o disco). que nunca esteve na cache. Como quando vários blocos competem pelo mesmo conjunto e que as falhas de conflito surgem diretamente da disputa pelo mesmo bloco de cache. aumentar são eliminados em uma cache a associatividade reduz as falhas de conflito. As falhas de capa. Uma falha de cache que ocorre em uma cache associativa por A Figura 5. Explicaremos as ideias falha compulsória Também em termos de caches. modelo dos três Cs  Um modelo de cache em que todas as falhas são classificadas em uma de três Os Três Cs: um modelo intuitivo para entender categorias: falhas compulsórias. junto ou diretamente mapeadas quando vários blocos disputam o mesmo conjunto. o bloco usado menos recentemente ou um bloco aleatório. a associatividade pode aumentar totalmente associativa do mesmo o tempo de acesso. chamada de falha de partida a frio. Nesta seção. total. mesmo tamanho. falha de conflito Também sociativa por conjunto que são eliminadas em uma cache totalmente associativa do chamada de falha de colisão. vamos examinar um modelo que esclarece as origens das falhas em uma hierarquia de memória e como as falhas serão afetadas por mudanças na hierarquia. mesmo com associatividade cidade ocorrem quando os blocos são substituídos e.5  Uma estrutura comum para hierarquias de memória 421 Embora as caches. As falhas de conflito são aquelas falhas em uma cache diretamente mapeada ou as. levando a um menor desempenho geral. as TLBs e a memória virtual inicialmente possam parecer muito diferentes. requisição.31 mostra como a taxa de falhas se divide nas três origens. Também são chamadas de falhas de partida a frio. pesquisa limitada (como em uma cache associativa por conjunto). recuperados. Nesse modelo. cache. depois. Questão 2: Como um bloco é encontrado? Resposta: Existem quatro métodos: indexação (como em uma cache diretamente mapeada). falha de capacidade  Uma falha j Falhas de capacidade: são falhas de cache causadas quando a cache não pode conter de cache que ocorre porque a todos os blocos necessários durante a execução de um programa. não pode conter todos os blocos necessários para satisfazer à j Falhas de conflito: são falhas de cache que ocorrem em caches associativas por con. todas as falhas são classificadas em uma de três categorias (os três Cs): Uma falha de cache causada pelo primeiro acesso a um bloco que j Falhas compulsórias: são falhas de cache causadas pelo primeiro acesso a um bloco nunca esteve na cache. Essas origens de conjunto ou diretamente mapeada falhas podem ser diretamente atacadas mudando algum aspecto do projeto da cache. 5. elas se baseiam nos mesmos dois princípios de localidade e Colocando em podem ser entendidos examinando como lidam com quatro questões: perspectiva Questão 1: Onde um bloco pode ser colocado? Resposta: Em um local (mapeamento direto). em alguns locais (associatividade por conjunto) ou em qualquer local (associatividade total). embora elas se apliquem diretamente a qualquer outro nível na hierarquia. pesquisa completa (como em uma cache totalmente associativa) e tabela de consulta separada (como em uma tabela de páginas). Essas falhas de cache também são chamadas de falhas de colisão. falhas de capacidade e falhas de o comportamento das hierarquias de memória conflito. Questão 4: Como as escritas são tratadas? Resposta: Cada nível na hierarquia pode usar write-through ou write-back. Entretanto. . tamanho. Questão 3: Que bloco é substituído em uma falha? Resposta: Em geral. 32. Em cada caso. Como já dissemos. Por isso. muitas das escolhas de projeto interagem. quando tornamos a cache maior. As falhas de capacidade podem facilmente ser reduzidas aumentando a cache. as caches de segundo nível têm se tornado constantemente maiores durante muitos anos. esse modelo é uma maneira útil de adquirir conhecimento sobre o desempenho dos projetos de cache. é mostrada para uma faixa de associatividades. Por exemplo. Essa combinação de efeitos positivos e negativos é o que torna o projeto de uma hierarquia de memória interessante. as caches de primeiro nível cresceram lentamente ou nem isso. a diferença na taxa de falhas incorrida por uma cache diretamente mapeada em relação a uma cache totalmente associativa do mesmo tamanho é dada pela soma das seções rotuladas como oito vias. quatro vias. A diferença entre oito vias e quatro vias é tão pequena que mal pode ser vista nesse gráfico. de uma via a oito vias.30. Esses dados são para os benchmarks de inteiro e ponto flutuante do SPEC2000 e são da mesma fonte dos dados na Figura 5.422 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. A parte do conflito. duas vias e uma via. Esse gráfico mostra a taxa de falhas total e seus componentes para uma faixa de tamanhos de cache. que depende do tamanho da cache. na verda- de.006% e não pode ser visto nesse gráfico. também precisamos ser cautelosos quanto ao aumento no tempo de acesso. A decomposição das falhas nos três Cs é um modelo qualitativo útil. Isso irá reduzir o número de referências necessárias para tocar cada bloco do programa uma vez. Apesar dessas deficiências. É claro que. que depende da associatividade e do tamanho da cache. e mudar uma característica de cache frequentemente afetará vários componentes da taxa de falhas. que pode levar a um desempenho geral mais baixo.31  A taxa de falhas pode ser dividida em três origens de falha. a seção rotulada como duas vias indica as falhas adicionais surgindo quando o cache possui associatividade de dois em vez de quatro. Colocando em A dificuldade de projetar hierarquias de memória é que toda mudança que me- lhore potencialmente a taxa de falhas também pode afetar negativamente o de- perspectiva sempenho geral. a principal maneira de um sistema de cache reduzir o número de falhas compulsórias é aumentando o tamanho do bloco. O próximo componente é a taxa de falhas de capacidade. a seção rotulada corresponde ao aumento na taxa de falhas que ocorre quando a associatividade é alterada do próximo grau mais alto para o grau de associatividade rotulado. porque o programa consistirá em menos blocos de cache. Portanto. O componente da falha compulsória é de 0. Como as falhas compulsórias são geradas pela primeira referência a um bloco. . aumentar demais o tamanho do bloco pode ter um efeito negativo sobre o desempenho devido ao aumento na penalidade de falha. Nos projetos de cache reais. como mostra a Figura 5. Não há um meio de reduzir as falhas compulsórias. Alguns exemplos são IBM VM/370. o que torna o overhead das VMs mais aceitável. ou hipervisor.6   Máquinas virtuais Uma ideia quase tão antiga relacionada à memória virtual é a das máquinas virtuais (VM — Virtual Machines).6  Máquinas virtuais 423 FIGURA 5. 5. Em uma plataforma convencional. Essas VMs são chamadas de (Operating) System Virtual Machines — máquinas virtuais do sistema (operacional). vários OSs compartilham os recursos do hardware. 5. Embora algumas VMs excutem diferentes ISAs na VM do hardware nativo. 3. estamos interessados nas VMs que oferecem um ambiente completo em nível de sistema. j As falhas na segurança e na confiabilidade dos sistemas operacionais padrão. consideramos que elas sempre correspondem ao hardware. mas. particionado ou . j O compartilhamento de um único computador entre muitos usuários não relacio- nados. Elas foram desenvolvidas inicialmente em meados da década de 1960. e seus recursos são compartilhados entre as VMs guest. O software que dá suporte às VMs é chamado de monitor de máquina virtual (VMM — Virtual Machine Monitor). VMware ESX Server e Xen. o VMM é o centro da tecnologia de máquina virtual. As máquinas virtuais do sistema apresentam a ilusão de que os usuários têm um compu- tador inteiro para si. Na redução de falhas. um único OS “possui” todos os recursos do hardware. Embora bastante ignoradas no domínio dos computadores monou- suários nas décadas de 1980 e 1990. elas recentemente ganharam popularidade devido a: j A importância crescente do isolamento e da segurança nos sistemas modernos. no nível da arquitetura de conjunto de instruções (ISA) binária. A plataforma de hardware básica é chamada de host. Quais das seguintes afirmativas (se houver) normalmente são verdadeiras? Verifique você 1. As caches totalmente associativas não possuem falhas de conflito. mesmo 2. com uma VM. j Os aumentos fantásticos na velocidade bruta dos processadores no decorrer das décadas. a associatividade é mais importante do que a capacidade. O VMM determina como mapear recursos virtuais a recursos físicos: um recurso físico pode ser de tempo compartilhado. incluindo uma cópia do sistema operacional.32  Dificuldades do projeto de hierarquias de memória. como a Java VM. Um único computador executa várias VMs e pode aceitar diversos sistemas operacionais (OSs) diferentes. e continuaram sendo uma parte importante da computação de mainframe no decorrer dos anos. Nesta seção. A definição mais geral das VMs inclui basicamente todos os métodos de emulação que oferecem uma interface de software padrão. o VMM precisa controlar praticamente tudo — acesso ao estado privilegiado. E/S. As VMs oferecem uma abstração que pode executar uma pilha de software completa. pois o OS raramente é chamado. que geralmente é executada no modo usuário.000 linhas de código. Embora nosso interesse aqui seja as VMs para melhorar a proteção. Para “virtualizar” o processador. incluindo até mesmo sistemas operacionais antigos. seja no sentido de balancear a carga ou sair do hardware com falha. O overhead é determinado pelo número de instruções que devem ser simuladas pelo VMM e por quanto tempo cada uma precisa simular. como o DOS. tradução de endereços. Os requisitos qualitativos são: j O software guest deverá se comportar em uma VM exatamente como se estivesse sendo executado no hardware nativo. o objetivo da arquitetura e do VMM é executar quase todas as instruções diretamente no hardware nativo. Os programas ligados ao processador em nível de usuário possuem overhead de virtualização zero. Para estar no controle. Uma implantação típica poderia ser algumas VMs executando OSs legados.424 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória ainda simulado no software. isso também garante que a execução de qualquer instrução privilegiada será tratada pelo VMM. a VMM suspenderia a VM guest atualmente em execução. Logo. exceto pelo comportamento relacionado ao desempenho ou limitações de recursos fixos compartilhados por múltiplas VMs. exceções e interrupções — embora a VM guest e o OS atualmente em execução estejam temporariamente utilizando-os. Em geral. Gerenciar o software. Um motivo para servidores múltiplos é ter cada aplicação executando com a versão compatível do sistema operacional em computadores separados. pois o processador geralmente está ocioso. o VMM precisa estar em um nível de privilégio mais alto que a VM guest. o custo da virtualização do processador depende da carga de trabalho. Outro exem- plo é que alguns VMMs admitem a migração de uma VM atual para um computador diferente. As cargas de trabalhos com uso intenso de E/S em geral usam intensamente o OS. salvaria seu estado. se a carga de trabalho com uso intenso de E/S também for voltada para E/S. e algumas testando a próxima versão do OS. como consideramos aqui. listados anteriormente: . Por exemplo. elas oferecem dois outros benefícios que são comercialmente significativos: 1. determina- ria qual VM guest será executada em seguida e depois carregaria seu estado. As VMs guest que contam com uma interrupção de temporizador recebem um temporizador virtual e uma interrupção de temporizador simulada pelo VMM. precisa isolar o estado dos guests um do outro e precisa proteger-se contra o software guest (incluindo os OSs guest). a parte de isolamento de um VMM possui talvez apenas 10. O VMM é muito menor que um OS tradicional. Requisitos de um monitor de máquina virtual O que um monitor de VM precisa fazer? Ele apresenta uma interface de software ao software guest. executando muitas chamadas do sistema e instruções privilegiadas. j O software guest não deverá alterar diretamente a alocação de recursos reais do sis- tema. 2. de modo que tudo é executado nas velocidades nativas. esperando pela E/S. pois essa separação pode melhorar a confiabilidade. Os requisitos básicos das máquinas virtuais do sistema são quase idênticos aos da memória virtual paginada. consolidando assim o número de servidores. Por outro lado. trataria da interrupção. o que pode resultar em um alto overhead de virtualização. o custo da virtualização do processador pode ser completamente ocultado. As VMs permitem que essas pilhas de software separadas sejam executadas independentemente enquanto compartilham o hardware. no caso de uma interrupção de um temporizador. quando as VMs guest executam a mesma ISA que o host. muitas executando a versão atual estável do OS. Gerenciar o hardware. Reduzir o custo da interrupção direcionando as interrupções para a VM apropriada sem chamar o VMM. Reduzir o custo da virtualização do processador. Ajustes semelhantes estão sendo feitos hoje para acomodar as máquinas virtuais. como as VMs foram consideradas para aplicações de servidor baseadas em desktop e PC apenas recentemente. outras medidas deverão ser tomadas. incluindo ARM e MIPS. Historicamente. e a arquitetura IBM 370 orgulhosamente ostenta esse rótulo. Então. um OS guest convencional é executado como um programa no modo usuário em cima do VMM. . que tinha sido anunciada apenas seis anos antes. todos os recursos do sistema precisam ser controláveis apenas por meio dessas instruções. aumentando assim a complexidade do VMM e reduzindo o desempenho da execução da VM. Na ausência desse suporte. os arquitetos tiveram de mudar a bem- sucedida arquitetura do conjunto de instruções do IBM 360. Em 2006. Proteção e arquitetura do conjunto de instruções Proteção é um esforço conjunto da arquitetura e dos sistemas operacionais. Um VMM precisa tomar precauções especiais para localizar todas as instruções problemáticas e garantir que elas se comportem corretamente quando executadas por um OS guest. Infelizmente. j Um subconjunto de instruções privilegiado. será relativamente fácil reduzir o número de instruções que devem ser executadas por um VMM e sua velocidade de simulação. o hardware mainframe IBM e o VMM exigiam três etapas para me- lhorar o desempenho das máquinas virtuais: 1. para dar suporte à memória virtual no IBM 370. se um OS guest tentar acessar ou modificar informações relacionadas aos recursos do hardware por meio de uma instrução privilegiada (por exemplo. Se você executar a instrução POPF no modo usuário. 5. lendo ou escrevendo o ponteiro da tabela de páginas). isso é um problema. 3. mas os arquitetos tiveram de modificar alguns detalhes desajeitados das arquiteturas de conjunto de instruções existentes quando a memória virtual se tornou popular.6  Máquinas virtuais 425 j Pelo menos dois modos de processador. Esses culpados incluem a x86 e a maioria das arquiteturas RISC. em vez de interceptá-la. Por exemplo. sistema e usuário. isso será interceptado pelo VMM. resultado em um trap se executado no modo usuário. O VMM poderá então efetuar as mudanças apropriadas nos recursos reais correspondentes. se qualquer instrução que tenta ler ou escrever essas informações sensíveis for interceptada quando executada no modo usuário. 2. conforme o OS guest espera. que está disponível apenas no modo do sistema. Por exemplo. o VMM poderá interceptá-la e dar suporte a uma versão virtual da informação sensível. Reduzir o custo de overhead da interrupção devido à virtualização. pois espera ver um flag IE alterado. a instrução POPF do x86 carrega os registradores de flag do topo da pilha para a memória. No modo do sistema. a maioria dos conjuntos de instruções foi criada sem a virtualização em mente. (Falta de) suporte da arquitetura do conjunto de instruções para máquinas virtuais Se as VMs forem planejadas durante o projeto da ISA. Portanto. Como um OS guest é executado no modo usuário dentro de uma VM. redu- zindo o custo da virtualização do processador. Como o VMM precisa garantir que o sistema guest só interaja com recursos virtuais. Um dos flags é o flag Interrupt Enable (IE). Será interessante ver quantas gerações de arquitetura e modificações do VMM serão necessárias para resolver todos os três pontos. ela muda o IE. Uma arquitetura que permite que a VM seja executada diretamente no hardware recebe o título de virtualizável. novas propostas da AMD e Intel tentaram resolver o primeiro ponto. ela simplesmente muda todos os flags exceto IE. j O tamanho do bloco é de 4 palavras (16 bytes ou 128 bits). A arquitetura da memória virtual é especificada ou por tabelas de página. Detectando todas as modificações na tabela de página do guest. como no IBM VM/370 e no x86. com certeza. o VMM precisa interceptar qualquer tentativa pelo OS guest de alterar sua tabela de páginas ou de acessar o ponteiro da tabela de páginas. e torna a memória real um nível separado. podemos implementar o controle para uma cache. Isso normalmente é feito protegendo as tabelas de página do guest e interceptando-se qualquer acesso ao ponteiro da tabela de páginas por um OS guest. Para que isso funcione. A última parte da arquitetura a ser virtualizada é a E/S. no Capítulo 4. Essa. à medida que cada OS guest em cada VM gerencia seu próprio conjunto de tabelas de página. Ela termina com a MEF de um controlador para essa cache simples. memória física e memória de máquina para indicar os mesmos três níveis.9 no site entra em mais detalhes. o VMM pode garantir que as entradas da tabela de página de sombra sendo usadas pelo hardware para traduções corresponda às do ambiente do OS guest. mostrando a cache e o controlador em uma nova linguagem de descrição de hardware. Em vez de pagar um nível extra de indireção em cada acesso à memória. outro desafio é a virtualização da memória virtual. e depois deixando para o VMM a tarefa de tratar da E/S real. A Seção 5. o segundo acontece naturalmente se o acesso ao ponteiro da tabela de páginas for uma operação privilegiada. além do suporte dos inúmeros drivers de dispositivo que são exigidos. Aqui estão as principais caracterís- ticas da cache: j Cache mapeada diretamente.7   para controlar uma cache simples Agora. com a exceção das páginas físicas corretas substituídas pelas páginas reais nas tabelas do guest. Detalhamento:  Além de virtualizar o conjunto de instruções. Outra dificuldade é o compartilhamento de um dispositivo real entre diversas VMs. devido ao número cada vez maior de dispositivos de E/S conectados ao computador e a crescente diversidade dos tipos de dispositivo de E/S. j Write-back usando alocação de escrita. o VMM separa as noções de memória real e física (que geralmente são tratadas como sendo sinônimas). Conforme observamos anteriormente. Logo. é a parte mais difícil da virtualização do sistema. (Alguns utilizam os termos memória virtual. especialmente se os diferentes OSs guest tiverem suporte no mesmo sistema de VM. e as tabelas de página do VMM mapeiam a memória real do guest para a memória física. o VMM man- tém uma tabela de páginas de sombra que é mapeada diretamente a partir do espaço de endereços virtuais do guest para o espaço de endereços físicos do hardware. A ilusão de VM pode ser mantida dando-se a cada VM versões genéricas de cada tipo de driver de dispositivo de E/S. assim como implementamos o controle para os caminhos de dados de único ciclo e em pipeline. ou pela estrutura de TLB. .426 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória e quanto tempo passará antes que as máquinas virtuais do século XXI sejam tão eficientes quanto os mainframes IBM e VMMs da década de 1970. Esta seção começa com uma definição de uma cache simples e depois uma descrição das máquinas de estado finito (MEF).) O OS guest mapeia a memória virtual para a memória real por meio de suas tabelas de página. como no MIPS. Usando uma máquina de estado finito 5. Uma cache simples Vamos projetar um controlador para uma cache simples. intermediário entre a memória virtual e a memória física. Os sinais entre o processador e a cache são: j 1 bit de sinal Read ou Write. . Observe que a interface para a memória não é um número fixo de ciclos. Uma máquina de estado finito conjunto de saídas ativas. j 32 bits de endereço. que normalmente são representadas graficamente. j 1 bit de sinal Ready. o controle é mais com. j 1 bit de sinal Valid. podemos agora calcular os campos de um endereço para a cache: j O índice da cache tem 10 bits. função lógica sequencial usamos um conjunto de tabelas verdade que especificava a configuração dos sinais consistindo em um conjunto de de controle com base na classe de instrução. e uma função de na sequência. j 1 bit de sinal Valid. j 32 bits de dados do processador à cache.(10 + 4) ou 18 bits. de modo que ela mantém 1024 blocos. Consideramos um controlador de memória que notificará a cache por meio do sinal Ready quando a leitura ou escrita na memória terminar. dizendo se existe uma operação de memória ou não. Fazer com que o bloco de cache combine com a largura da DRAM simplificou o projeto. dizendo se existe uma operação de cache ou não. A largura de memória extra geralmente é encontrada nos microprocessadores de hoje. possivelmente as entradas para um nitos. 5. j A cache inclui um bit de validade e um bit de modificação por bloco. Pela Seção 5. j O tamanho da tag tem 32 . o que nos permite controlar uma operação que pode utilizar múltiplos ciclos de clock. uma função plexo porque a operação pode ser uma série de etapas. A interface entre a memória e a cache tem os mesmos campos que entre o processador e a cache. pois o processador precisa esperar até que a cache tenha terminado a solicitação. j O offset do bloco tem 4 bits. j 128 bits de dados da memória à cache. O controle para uma cache de próximo estado que mapeia precisa especificar os sinais a serem definidos em qualquer etapa e a próxima etapa o estado atual e as entradas para um novo estado. j Endereços de byte de 32 bits. exceto que os campos de dados agora têm 128 bits de largura.2. Máquinas de estados finitos máquina de estados finitos Uma A fim de projetar a unidade de controle para o caminho de dados de único ciclo. Observe que essa é uma cache de bloqueio. j 1 bit de sinal Ready. saída que mapeia o estado atual e O método de controle multietapas mais comum é baseado em máquinas de estados fi. j 32 bits de dados da cache ao processador. dizendo que a operação da cache está completa. que lida com palavras de 32 bits ou 64 bits no processador. Aqui estão os sinais: j 1 bit de sinal Read ou Write. precisamos revisar as máquinas de estados finitos. j 128 bits de dados da cache à memória. entradas e saídas. enquanto o controlador da DRAM normalmente tem 128 bits. j 32 bits de endereço.7  Usando uma máquina de estado finito para controlar uma cache simples 427 j O tamanho da cache é de 16KB. dizendo que a operação de memória está completa. Antes de descrever o controlador de cache. Para uma cache. pois selecionam uma das entradas. De modo semelhante.) FIGURA 5. em vez de atuar como um don’t care. . Observe que.3. pode querer examinar o Apêndice C antes de prosseguir. as saídas dependem apenas do estado atual. determina tado também especifica um conjunto de saídas que são declaradas quando a máquina está o próximo estado de uma máquina de estados finitos.33 mostra como essa implementação poderia se parecer. As saídas da lógica combinacional são o estado atual e quaisquer entradas usadas para determinar o próximo estado. nesse estado. portanto. Nesse caso. Um exemplo simples de uma máquina de estados finitos aparece no Apêndice C. A implementação de uma máquina de estados finitos normalmente considera que todas as saídas que não estão declaradas explicitamente têm as declarações retiradas. cada es- entradas e o estado atual. a lógica de controle combinacional para uma máquina de estados finitos é implementada com uma ROM (Read-Only Memory) e uma PLA (Programmable Logic Array). dadas as de um novo estado. Uma máquina de estado finito pode ser implementada com um registrador tempo- rário que mantém o estado atual e um bloco de lógica combinatória que determina os sinais do caminho de dados a serem declarado e o próximo estado. na máquina de estado finito. As instruções função de próximo estado Uma são definidas por uma função de próximo estado. A Figura 5. sempre especificamos a definição de todos os controles multiplexadores com que nos importamos. a operação correta do caminho de dados depende do fato de que um sinal que não é declarado explicitamente tem a declaração retirada. A seção Detalhamento explica isso em minúcias. Na Seção C. Os controles multiplexadores são ligeiramente diferentes. as entradas são os bits de opcode do registrador de instrução. Quan- do implementamos a máquina de estado finito com lógica. Assim. (Veja também no Apêndice C uma descrição desses elementos lógicos. As saídas da lógica combinacional são o número do próximo estado e os sinais de controle a serem declarados para o estado atual.428 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória consiste em um conjunto de estados e instruções sobre como alterar os estados. e se você não estiver familiarizado com o conceito de uma máquina de estado finito. O Apêndice D descreve detalhadamente como a máquina de estados finitos é implementada usando essa es- trutura.33  Controladores da máquina de estados finitos normalmente são implementados com um bloco de lógica combinacional e um registrador para manter o estado atual. pode não exigir quaisquer portas lógicas. a definição de um controle como 0 pode ser o default e. na máquina de estados finitos utilizada neste capítulo. e não das entradas. Quando usamos uma máquina de estado finito para controle. sejam elas 0 ou 1. que mapeia o estado atual e as entradas função combinacional que. mas somente do estado atual. Uma parte tem a saída de controle e apenas a entrada de estado. j Ocioso: Esse estado espera uma solicitação de leitura ou escrita válida do processador. No Apêndice C. quando a implementação dessa máquina de estado finito é levada às portas lógicas. Sua característica identificadora é que a saída de- pende apenas do estado atual. Um estilo alternativo de máquina é uma máquina de Mealy. em situações em que existe uma diferença de um estado entre duas sequências de estados. j Comparar Tag: Como o nome sugere. a vantagem do tamanho pode ser vista com clareza. a máquina de Mealy pode unificar os estados. esse estado testa se a leitura ou escrita solicitada é um acerto ou uma falha. a caixa rotulada como lógica de controle combinacional pode ser dividida em duas partes. não dependem das en- tradas. em homenagem a George Mealy. é um acerto. A desvantagem em potencial de uma máquina de Moore é que isso pode exigir estados adicionais.34  Quatro estados do controlador simples. . Se ela for válida e a parte de tag do endereço combinar com a tag. Por exemplo. As máquinas de Moore possuem vantagens de implementação em potencial na velocidade e no tamanho da unidade de controle. Com uma máquina de Moore. As vantagens na velocidade ocorrem porque as saídas de controle. que são necessárias cedo no ciclo de clock.34 mostra os quatro estados do nosso controlador de cache simples: FIGURA 5. que move a MEF para o estado Comparar Tag. A máquina de Mealy permite que a entrada e o estado atual sejam usados para determinar a saída. em homenagem a Edward Moore. MEF para um controlador de cache simples A Figura 5. fazendo com que as saídas dependam das entradas. A parte de índice do endereço seleciona a tag a ser compa- rada.7  Usando uma máquina de estado finito para controlar uma cache simples 429 Detalhamento:  O estilo da máquina de estados finitos neste livro é chamado de máquinas de Moore. enquanto a outra tem apenas a saída do próximo estado. 5. Paralelismo e hierarquias de memória: 5. que. se o bloco nesse local tiver um valor de bit de modificação igual a 1. ele é incluído porque a tag é uma única memória. a comparação e acesso à cache são feitos em estados separados. Permanecemos nesse estado aguardando pelo sinal Ready da memória. A Seção 5. embora intuitivamente atraente. determina quando um valor escrito será retornado por uma leitura. A cache então escreveria o bloco modificado do buffer de escrita enquanto o processador está operando sobre os dados solicitados. define que valores podem ser retornados por uma leitura. poderíamos dizer que um sistema de memória é coerente se qualquer leitura de um item de dados retornar o valor escrito mais recentemente desse item de dados.430 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Ou os dados são lidos da palavra selecionada ou são escritos na palavra selecionada. Essa definição.8  coerência de cache Dado que um multiprocessador multicore significa múltiplos processadores em um único chip. Esse modelo simples facilmente poderia ser estendido com mais estados. ou para o estado Alocar. poderiam acabar vendo dois valores diferentes. possui mais detalhes sobre a MEF. é vaga e simples. a MEF retorna ao estado ocioso. embora pareça desnecessário. o bit de modificação é definido como 1. Embora pudéssemos ter ido para um novo estado para com- pletar a operação em vez de reutilizar o estado Comparar Tag. Essa definição simples contém dois aspectos diferentes do comportamento do sistema de memória. a MEF vai para o estado Comparar Tag. Por exemplo. a realidade é muito mais complexa. incluindo a atualização da palavra apropriada no bloco se o acesso foi uma escrita. no sentido de tentar melhorar o tempo do ciclo de clock. pois a visão da memória mantida por dois processadores diferentes é através de suas caches individuais. Normalmente. A Figura 5. Se for uma escrita. se for 0. O segundo aspecto. de modo que o processador não tenha de esperar por dois acessos à memória em uma falha de modificação. ambos críticos para escrever programas corretos de memória compartilhada.35 ilustra o problema e mostra como dois processadores diferentes podem ter dois valores diferentes para o mesmo local. j Write-Back: Esse estado escreve o bloco de 128 bits na memória usando o endereço composto da tag e do índice de cache. esses processadores provavelmente compartilham um espaço de endereçamento físico comum. também precisamos mudar os campos de validade e tag.9. . Quando a leitura da memória termina. para tentar me- lhorar o desempenho. j Alocar: O novo bloco é apanhado da memória. chamado consistência. Informalmente. no site. o estado Comparar Tag realiza a comparação e a leitura ou escrita dos dados de cache em um único ciclo de clock. Observe que um acerto de escrita também define o bit de validade e o campo de tag. Outra otimização seria acrescentar um buffer de escrita de modo que pudéssemos salvar o bloco de modificação e depois ler o novo bloco primeiro. para mudar o bit de modificação. Essa dificuldade geralmente é referenciada como o problema de coerência de cache. Uma falha primeiro atualiza a tag de cache e depois vai para o estado Write-Back. sem quaisquer precauções adicionais. a MEF vai para o estado Alocar. de modo que. mostrando o controlador completo em uma linguagem de descrição de hardware e um diagrama em blocos desse cache simples. e depois o sinal Cache Ready é definido. O caching de dados compartilhados gera um novo problema. Quando a escrita na memória termina. O primeiro aspecto. Se for um acerto e o bloco for válido. Continuamos nesse estado esperando pelo sinal Ready da memória. chamado de coerência. existe muita sobreposição. a cache de A e a memória contêm o novo valor. ela deverá ver o valor 1.35  O problema de coerência de cache para um único local da memória (X). as caches oferecem migração e replicação de itens de dados compartilhados: j Migração: Um item de dados pode ser movido para uma cache local e usado lá de uma forma transparente. e o processador P1 escreve no local X seguido por P2 escrevendo no local X. Assim. mas a cache de B não. lido e es- crito por dois processadores (A e B). Depois que o valor de X foi escrito por A. Também consideramos um cache write-through. se a CPU B armazena 2 na memória no endereço X após a etapa de tempo 3. claramente diríamos que a memória estava incoerente. 5. As escritas no mesmo local são serializadas. Se não serializássemos as escritas. por exemplo. 3. Por exemplo. ou seja. A necessidade de serialização de escrita é mais sutil. A primeira propriedade simplesmente preserva a ordem do programa — certamente esperamos que essa propriedade seja verdadeira nos processadores de 1 core. pode ser que algum processador veja a escrita de P2 primeiro e depois veja a escrita de P1.35. Assumimos inicialmente que nenhuma cache contém a variável e que X tem o valor 0. sempre retorna o valor escrito por P. Uma leitura por um processador ao local X que segue uma escrita por outro proces- sador a X retorna o valor escrito se a leitura e escrita forem suficientemente separadas no tempo e nenhuma outra escrita em X ocorrer entre os dois acessos. .8  Paralelismo e hierarquias de memória: coerência de cache 431 FIGURA 5. Uma leitura por um processador P para um local X que segue uma escrita por P a X. duas escritas no mesmo local por dois processadores quaisquer são vistas na mesma ordem por todos os processadores. um cache write-back acrescenta algumas complicações adicionais. na etapa de tempo 3. O modo mais simples de evitar essas dificuldades é garantir que todas as escritas no mesmo local sejam vistas na mesma ordem. A migração reduz a latência para acessar um item de dados compartilhado que está alocado remotamente e a demanda de largura de banda sobre a memória compartilhado. mas igualmente importante. sem escritas de X por outro processador ocorrendo entre a escrita e a leitura por P. Suponha que não serializássemos as escritas. se a CPU A tivesse de ler X após a etapa de tempo 3. A segunda propriedade define a noção do que significa ter uma visão coerente da memória: se um processador pudesse ler continuamente um valor de dados antigo. e se B ler o valor de X. precisamos de um mecanismo de modo que o valor 0 na cache da CPU B seja substituído pelo valor 1 após a CPU A armazenar 1 na memória no endereço X.35. Um sistema de memória é coerente se: 1. Assim. na Figura 5. essa propriedade é chamada serialização de escrita. Serializar as escritas garante que cada processador verá a escrita feita por P2 em algum ponto. porém semelhantes. na Figura 5. mantendo o valor escrito por P1 indefinidamente. os processadores nunca podem ler o valor no local X como 2 e mais tarde lê-lo como 1. 2. ele receberá 0! Vejamos primeiro a coerência. Esquemas básicos para impor a coerência Em um multiprocessador coerente com a cache. É essencial. mas é possível acompanhar a posse e forçar o write-back somente se o bloco for substituído. Para ver como esse protocolo garante a coerência. Sendo assim. O conteúdo da CPU e da memória mostra o valor após o processador e a atividade do barramento terem sido completados. Esse estilo de protocolo é chamado protocolo de invalidação de escrita. . Na próxima seção. mas também limita sua escalabilidade. O acesso exclusivo garante que não existe qualquer outra cópia de um item passível de leitura ou escrita quando ocorre a escrita: todas as outras cópias do item em cache são invalidadas. tanto o conteúdo da cache de B quanto o conteúdo de memória de X são atualizados. mas o processador que o possui é responsável por atualizar quaisquer outros processadores e memória quando muda o bloco ou o substitui. Acompanhar o estado de qualquer compartilhamento de um bloco de dados é essencial para implementar um protocolo coerente com a cache. simplifica o protocolo. A Figura 5. que ocorre quando um bloco se torna compartilhado. Isso requer a introdução de um estado adicional. As caches são todas acessíveis por algum meio de broadcast (um barramento ou rede). as caches fazem uma cópia do item de dados na cache local. Protocolos de snooping Um método para impor a coerência é garantir que um processador tenha acesso exclusivo a um item de dados antes de escrevê-lo. ela falha na cache. pois invalida as cópias em outras caches em uma escrita. Além disso. Consideramos que nenhuma cache mantém X inicialmente e que o valor de X na memória é 0. Um espaço em branco indica nenhuma atividade ou nenhuma cópia em cache. Os protocolos para manter coerência a múltiplos processadores são chamados de protocolos de coerência de cache. e esta é forçada a buscar uma nova cópia dos dados. Quando ocorre a segunda falha por B. oferecer suporte a essa migração e replicação. A replicação reduz a latência de acesso e a disputa por um item de dados compartilhado lido. exigimos que FIGURA 5. para o desempenho no acesso aos dados compartilhados. Cada cache que tem uma cópia dos dados de um bloco da memória física também tem uma cópia do status de compartilhamento do bloco. mas qualquer meio de comunicação que envia falhas de cache por broadcast a todos os processadores pode ser usado para implementar um esquema de coerência baseado em snooping. que indica que um bloco pode ser compartilhado. quando ocorre a leitura. a fim de determinar se eles têm ou não uma cópia de um bloco que é solicitado em um acesso ao barramento ou switch. O protocolo de coerência de cache mais comum é o snooping. chamado “owner” (proprietário).432 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória j Replicação: Quando os dados compartilhados estão sendo simultaneamente lidos. de modo que muitos multiprocessadores introduzem um protocolo de hardware que mantém caches coerentes. explicamos a coerência de cache baseada em snooping conforme im- plementada com um barramento compartilhado. mas nenhum estado centralizado é mantido. e todos os con- troladores monitoram ou vasculham o meio.36 mostra um exemplo de um protocolo de invalidação para um barramento de snooping com caches write-back em ação. Essa atualização de memória. considere uma escrita seguida por uma leitura por outro processador: como a escrita requer acesso exclusivo. a CPU A responde com o valor cancelando a resposta da memória. qualquer cópia mantida pelo processador de leitura precisa ser invalidada (daí o nome do protocolo). Para uma escrita.36  Um exemplo de um protocolo de invalidação atuando sobre um barramento de snooping para um único bloco de cache (X) com caches write-back. Esse broadcasting de todas as caches torna os protocolos de snooping simples de implementar. em que o status dos blocos compartilhados é distribuído. Blocos grandes também podem causar o que é chamado compartilhamento falso: compartilhamento falso Quando quando duas variáveis compartilhadas não relacionadas estão localizadas no mesmo duas variáveis compartilhadas bloco de cache. Detalhamento:  O problema da coerência de cache para multiprocessadores e E/S (ver Capítulo 6). tem diferentes características que afetam a solução apropriada. fazendo com que a cópia do outro processador seja invalidada. ele precisa obter uma nova cópia dos dados. mas força o processador a terminar uma escrita na ordem do programa. impedindo que qualquer outro proces- sador seja capaz de escrever simultaneamente. Em segundo lugar. Se. software sadores. Se dois processadores tentarem escrever os mesmos dados simultaneamente. se expandir para quantidades maiores de processadores. um deles vence a corrida. Para que o outro processador complete sua escrita. Fazemos as duas suposições a seguir. observe que não podemos exigir que uma leitura de X na Figura 5. em que múltiplas cópias de dados são um evento raro — a ser evitado sempre que possível —.8  Paralelismo e hierarquias de memória: coerência de cache 433 o processador escrevendo tenha acesso exclusivo. pois estes podem nem sequer ter saído do processador nesse ponto. 5. considere o caso do snooping em uma cache com um tamanho de bloco de oito palavras. Uma ideia interessante é que o tamanho do bloco desempenha um papel importante na Interface coerência da cache. Para ver por que. Os programadores e compiladores deverão dispor bloco inteiro é trocado entre os dados cuidadosamente para evitar o compartilhamento falso. uma escrita de X em um processador preceder uma leitura de X em outro proces- sador pouco antes. Essas restrições permitem que o processador reordene as leituras. Diferente da E/S. o processador não muda a ordem de qualquer escrita com relação a qualquer outro acesso à memória. embora os processadores estejam acessando variáveis diferentes. embora os processadores não relacionadas estão localizadas no mesmo bloco de cache e o estejam acessando variáveis diferentes. mas pode reduzir o tráfego entre as caches e. se um processador escreve no local X seguido pelo local Y. pode ser impossível garantir que a leitura retorne o valor dos dados es- critos. a questão de quando um valor escrito será visto também é importante. por exemplo. Portanto. A questão de exatamente quando um valor escrito deverá ser visto por um leitor é definido por um modelo de consistência de memória. esse protocolo também impõe a serialização da escrita. os processadores. A maioria dos protocolos troca blocos inteiros entre os proces.35 veja instantaneamente o valor escrito para X por algum outro processador. o bloco inteiro é trocado entre os processadores. um programa sendo executado em múltiplos processadores normalmente terá cópias dos mesmos dados em várias caches. A coerência baseada em diretório tem um overhead de implementação ligeiramente mais alto que o snooping. aumentando assim as demandas da largura de banda de coerência. Detalhamento:  Além do protocolo de coerência de cache baseado em snooping. portanto. um protocolo de coerência de cache baseado em diretório mantém o status de compartilhamento de um bloco de memória física em apenas um local. Essas duas condições significam que. embora semelhante em origem. com uma única palavra alternativamente escrita e lida hardware/ por dois processadores. Detalhamento:  Embora as três propriedades listadas no início desta seção sejam sufi- cientes para garantir a coerência. qualquer processador que vê o novo valor de Y também deve ver o novo valor de X. . Por exemplo. uma escrita não termina (e permite que ocorra a próxima escrita) até que todos os processadores tenham visto o efeito dessa escrita. Primeiro. que agora precisa conter o valor atualizado. chamado diretório. Este die de 13.37  Uma fotografia do die do processador Intel Nehalem com os componentes indicados. Os dois canais de memória de 128 bits são para a DRAM DDR3. Os quatro cores compartilham uma cache L3 de 8 MB. e a Figura 1. veremos a hierarquia de memória de dois microprocessadores modernos: o processador AMD Opteron X4 (Barcelona) e o Intel Nehalem. de modo que não existe um chip north bridge separado.37 mostra a fotografia do die do Intel Nehalem. Esta seção começa com uma descrição das máquinas de estados finitos e a implementação de um controlador de cache para uma cache de dados simples. assim como im- plementamos o controle para os caminhos de dados de único ciclo e caminhos de dados no Capítulo 4. o que reduz a latência para a memória principal. já que não existe necessidade de um barramento para uma cache secundária externa.  Vida real: as hierarquias de memória 5. e uma cache L2 de 512 KB. . O controlador de memória agora está no die. Ele contém quatro processadores que possuem.5 por 19.9   controladores de cache Esta seção no site mostra como implementar o controle para uma cache. incluindo uma descrição do controlador de cache em uma linguagem de descrição de hardware. caches de instrução privados de 32 KB e 32 LKB. como no Intel Clovertown. FIGURA 5. Depois.9 no Capítulo 1 mostra a fotografia do die do AMD Opteron X4. A Figura 5. Ambos possuem caches secundárias e caches terciárias no die do processador principal. Ambos possuem controladores de memória on-chip.10  do AMD Opteron X4 (Barcelona) e Intel Nehalem Nesta seção. ela entra nos detalhes do exemplo de um protocolo de coerência de cache e das dificuldades na implementação de tal protocolo.434 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Material avançado: implementando 5. Cada core também possui uma TLB de dois níveis.6 mm tem 731 milhões de transistores. cada um. Essa integração reduz o tempo de acesso às caches de nível inferior e também reduz o número de pinos do chip. O X4 implementa apenas 48 dos 64 bits possíveis do seu espaço virtual e 48 dos 64 bits possíveis do seu espaço de endereço físico.40 mostra o CPI. A Figura 5.39 mostra suas caches. taxas de falha por mil instruções para as caches L1 e L2. e acessos à DRAM por mil instruções para o Opteron X4 executando os benchmarks SPECint 2006. como descrito na Seção “Detalhamento” da Seção “Projetando o . com cada processador tendo suas próprias caches de instrução e dados L1 de 32 KB e sua própria cache L2 de 512KB. o endereço virtual é de 48 bits e o endereço físico é de 44 bits. Embora não tenhamos as falhas de L3 reais. Técnicas para reduzir as penalidades de falha Tanto o Nehalem quanto o AMD Opteron X4 possuem otimizações adicionais que per- mitem reduzir a penalidade de falha. A primeira delas é o retorno da palavra requisitada primeiro em uma falha. podemos deduzir a eficácia da cache L3 pela redução em acessos à DRAM versus falhas da L2. 5.38 resume os tamanhos de endereço e as TLBs dos dois processadores. O Nehalem tem três TLBs. O coeficiente de correlação entre o conjunto de CPIs e o conjunto de falhas de L1 por 1000 instruções é 0. e os quatro processadores compartilham uma única cache L3 de 8MB.10  Vida real: as hierarquias de memória do AMD Opteron X4 (Barcelona) e Intel Nehalem 435 As hierarquias de memória do Nehalem e do Opteron A Figura 5. O esquema de página grande evita o uso de um grande número de entradas para mapear um único objeto que está sempre presente. que são usadas para coisas como o sistema operacional ou no mapeamento de um buffer de quadro. Cada processador no X4 tem suas próprias caches de instrução e dados L1 de 64KB e sua própria cache L2 de 512KB. O Nehalem admite dois threads com suporte do hardware por core (veja Seção 7. FIGURA 5. O tamanho da palavra define o tamanho máximo do endereço virtual. O Nehalem tem uma estrutura semelhante. hmmer e bzip2 —.97. Observe que o CPI e as taxas de falha de cache são altamente correlacionados. Os dois processadores fornecem suporte a páginas grandes.5. A Figura 5. a maioria não se beneficia.38  Tradução de endereços e hardware TLB para o Intel Nehalem e o AMD Opteron X4. no Capítulo 7). Os quatro processadores compartilham uma única cache L3 de 2MB. Embora alguns programas se beneficiem bastante da cache L3 de 2MB — h264avc. Observe que o AMD Opteron X4 (Barcelona) possui quatro TLBs e que os endereços virtuais e físicos não precisam corresponder ao tamanho da palavra. mas um processador não precisa usar todos esses bits. 40  CPI. FIGURA 5. Observe que essa figura é para os mesmos sistemas e benchmarks da Figura 1. segundo nível e terceiro nível do Intel Nehalem e do AMD Opteron X4 2356 (Barcelona). Infelizmente. no Capítulo 1. Eles implementam dois tipos de não bloqueio. Acerto sob falha permite acertos de cache . chamada cache não bloqueante.436 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória FIGURA 5. está tratando uma falha anterior. Ambos permitem que o processador continue executando instruções que acessam a cache de dados durante uma falha de cache.39  Caches de primeiro nível.20. de modo que só temos acessos à DRAM para deduzir a eficácia da cache L3. é comumente usada quando os projetistas tentam referências a ela enquanto a cache ocultar a latência da falha de cache usando processadores com execução fora de ordem. os contadores de falhas da L3 não funcionaram nesse chip. taxas de falhas e acessos à DRAM para a hierarquia de memória do Opteron modelo X4 2356 (Barcelona) executando o SPECInt2006. sistema de memória para suportar caches”. Essa cache não bloqueante  Uma cache que permite que o processador faça técnica. O objetivo do primeiro deles é ocultar alguma latência de falha com outro trabalho. ou pela memória. Como os blocos de dados podem ser compartilhados entre diversos processadores na cache L3.11). a cache L3 fornece os dados diretamente para a cache L1. mas não em ambas. Uma grande dificuldade enfrentada pelos projetistas de cache é suportar processadores como o Nehalem e o Opteron X4. ela só remove o bloco de cache de L3 se nenhum outro processador a estiver compartilhando. Detalhamento:  Assim como o Opteron X4 não segue a propriedade convencional de inclusão. A sobreposição de uma grande fração dos tempos de falha para múltiplas falhas pendentes requer um sistema de memória de alta largura de banda. A cache pode ser multiporta. pois só mantém blocos deslocados de L1 (“vítimas”). Isso significa que uma cópia de todos os dados nas ca- ches de nível mais alto também pode ser encontrada nas caches de nível inferior. por sua vez. já que as células de RAM em uma memória multiporta precisam ser muito maiores do que as células de porta única. Os dois microprocessadores fazem uma pré-busca de instruções e possuem um mecanis- mo de pré-busca embutido no hardware para acessos a dados. Em contrapartida. A cache de dados L1 do Opteron X4 suporta duas leituras de 128 bits por ciclo de clock e tem oito bancos. O esquema alternativo é desmembrar a cache em bancos e permitir acessos múltiplos e independentes. As sofisticadas hierarquias de memória desses chips e a grande fração dos dies dedicada às caches e às TLBs mostram o significativo esforço de projeto despendido para tentar diminuir a diferença entre tempos de ciclo de processador e latência de memória. O Nehalem e a maioria dos outros processadores seguem a política de inclusão em sua hierarquia de memória. o que significa que um bloco de cache só pode ser encontrado nas caches de primeiro ou segundo níveis. A técnica é semelhante à memória principal intercalada (veja a Figura 5. só contendo blocos derramados de L2. Em vez de a memória alimentar a cache L2. Logo. enquanto falha sob acerto permite múltiplas falhas de cache pendentes. o protocolo da cache L3 reconhece se o bloco de cache está ou não sendo compartilhado ou usado somente por um único processador. Várias requisições podem ser suportadas na cache de primeiro nível por duas técnicas diferentes. . desde que sejam a bancos diferentes. que podem executar mais de uma instrução de aces- so à memória por ciclo de clock. Logo. mas for encontrada na cache L3. 5. a cache L3 é uma cache vítima para a cache L2. em uma falha da L1. alimenta a cache L1. as caches multiporta normalmente são muito caras. enquanto o objetivo do segundo é sobrepor a latência de duas falhas dife- rentes. Entretanto. ele também tem um relacionamento novo entre os níveis da hierarquia de memória. capaz de tratar múltiplas falhas em paralelo. a cache L2 pode ser chamada de cache vítima. Em sistemas desktop. ou um acerto de L3. Se uma falha de L1 não for encontrada na cache L2. quando um bloco é apanhado da L2 para a L1. o bloco substituído é enviado de volta à cache L2. a memória pode apenas ser capaz de tirar proveito limitado dessa capacidade. uma falha de L1 pode ser atendida por um acerto de L2. os processadores AMD seguem a política de exclusão em sua cache de primeiro e segundo níveis. Assim. Eles olham um padrão de falhas de dados e usam essas informações para tentar prever o próximo endereço a fim de começar a buscar os dados antes que a falha ocorra. permitindo mais de um acesso simultâneo ao mesmo bloco de cache. Detalhamento:  A cache L3 compartilhada do Opteron X4 nem sempre segue a exclusão. a cache L2 só mantém dados que foram expulsos da cache L1. De modo semelhante.10  Vida real: as hierarquias de memória do AMD Opteron X4 (Barcelona) e Intel Nehalem 437 adicionais durante uma falha. mas grandes servidores e multiprocessadores frequentemente possuem sistemas de memória capazes de tratar mais de uma falha pendente em paralelo. que. Essas técnicas geralmente funcionam melhor ao acessar arrays em loops. Logo. Isso poderia facilmente ser escrito como uma falácia: “Os programadores podem ignorar as hierarquias de memória ao escrever código.” Ilustramos com um exemplo usando multiplicação de matrizes. ele é mapeado no bloco (36 mod 8) = 4. Armadilha: ignorar o comportamento do sistema de memória ao escrever programas ou gerar código em um compilador. o endereço em bytes 36 é mapeado no bloco 1 da cache. O problema deve informar claramente a base do endereço. se o endereço 36 for um endereço em palavras. Aqui está o loop interno da versão da multiplicação de matrizes do Capítulo 3: . se tivermos uma cache diretamente mapeada de 32 bytes com um tamanho de bloco de 4 bytes.18.438 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória 5. Em que bloco o endereço em bytes 300 se encontra? Se dividirmos o endereço 300 em campos. precisamos considerar o tamanho do bloco. De modo semelhante. precisamos levar em conta o efeito de um endereçamento em bytes e blocos multipalavra ao determinar para qual bloco de cache um certo endereço é mapeado. bytes ou números de bloco. já que o endereço em bytes 36 é o endereço de bloco 9 e (9 mod 8) = 1. Lembre-se dessa armadilha ao realizar os exercícios. Por exemplo. Armadilha: esquecer-se de considerar o endereçamento em bytes ou o tamanho de bloco de cache ao simular uma cache. incluindo os autores (nos rascunhos anteriores) e ins- trutores que esquecem se pretendiam que os endereços estivessem em palavras. a hierarquia de memória pareceria ser menos vulnerável às falácias e armadilhas.11  Falácias e armadilhas Como um dos aspectos mais naturalmente quantitativos da arquitetura de um computador. Esse erro pega muitas pessoas. Começamos com uma armadilha que frequentemente pega estudantes em exercícios e exames. Suponha que te- nhamos uma cache com 256 bytes e um tamanho de bloco de 32 bytes. poderemos ver a resposta: O endereço em bytes 300 é o endereço de bloco  300   32  = 9 O número de blocos na cache é  256   32  = 8 O bloco número 9 cai no bloco de cache número (9 mod 8) = 1. Por outro lado. mas algumas levaram a grandes resultados negativos. Não só houve muitas falácias propagadas e armadilhas encontradas. para complementar a comparação de ordenações na Figura 5. então. Quando estamos simulando uma cache (manualmente ou por computador). Essa atitude laissez-faire causa problemas para os VMMs em todas essas arquiteturas. Muitos arquitetos nas décadas de 1970 e 1980 não tiveram o cuidado de garantir que todas as instruções lendo ou escrevendo informações relacionadas a informações de recurso de hardware fossem privilegiadas. incluindo o x86. Se a cache for associativa pelo menos em 2n vias. De uma perspectiva de marketing. portanto. avaliar a hierarquia de memória de forma independente usando o tempo médio de acesso à memória (veja página 387).11  Falácias e armadilhas 439 Quando executado com entradas que são matrizes de dupla precisão de 500 × 500. então. a única avaliação precisa da hierarquia de memória é simular o processador com execução fora de ordem juntamente com a hierarquia de memória. se ambos utilizarem caches L2 associativas com 16 vias. um programa paralelo sendo executado em 2n processadores ou threads pode facilmente alocar estruturas de dados a endereços que seriam mapeados para o mesmo conjunto de uma cache L2 compartilhada. quer por meio de um espaço de endereçamento de 32 bits não segmentado (também chamado de espaço de endereçamento plano). Se um processador é suspenso durante uma falha de cache. existe problema toda vez que uma linguagem de programação quer um endereço que seja maior do que um segmento. quer acrescentando 16 bits de segmento ao endereço de 16 bits existente. devido a falhas de conflito L2 — ao migrar de. um projeto de 16 cores para 32 cores. Armadilha: usar tempo médio de acesso à memória para avaliar a hierarquia de memória de um processador com execução fora de ordem. Durante a década de 1970. Infelizmente. foram revisados para oferecer endereços de 32 bits. os programadores poderiam enfrentar bugs de desempenho aparentemente misteriosos — na realidade. e. . então esses conflitos acidentais ficam ocultos pelo hardware do pro- grama. i (de modo que i seja o mais interno)! A única diferença é como o programa acessa a memória e o efeito resultante na hierarquia de memória. então. você pode calcular separada- mente o tempo de stall de memória e o tempo de execução do processador. acrescentar segmentos que fossem visíveis ao programador e que forçassem o programador e o compilador a decomporem programas em segmentos podia resolver o problema de endereçamento. acrescentar segmentos pode transformar todos os endereços em duas palavras — uma para o número do segmento e outra para o offset do segmento —. Se não. como índices para grandes arrays. o tempo de execução de CPU dos loops anteriores em uma CPU MIPS com uma cache secundária de 1MB foi aproximadamente metade da velocidade comparada a quando a ordem dos loops é alterada para k. que usamos aqui como um exemplo. ponteiros irrestritos ou parâmetros por referência. Os computadores. Se o processador continuar executando instruções e puder até sustentar mais falhas de cache durante uma falha de cache. digamos. 5. Armadilha: implementar um monitor de máquina virtual em uma arquitetura de conjunto de instruções que não foi projetada para ser virtualizável. Outras otimizações de compilador usando uma técnica chamada blocagem podem resultar em um tempo de execução que é outras quatro vezes mais rápido para esse código! Armadilha: ter menos associatividade em conjunto para uma cache compartilhada que o número de cores ou threads compartilhando essa cache. muitos programas ficaram tão grandes que nem todo o código e dados podiam ser endereçados apenas com um endereço de 16 bits. Armadilha: estender um espaço de endereçamento acrescentando segmentos sobre um espaço de endereçamento não segmentado. Além disso. Sem cuidados adicionais. j. causando problemas no uso dos endereços em registradores. como um registrador da tabela de descritores. o que não acontece para as VMs guest.41  Resumo de 18 instruções x86 que causam problemas para a virtualização [Robin e Irvine. j Verificam a proteção conforme requisitado pela arquitetura segmentada.41 descreve as 18 instruções que causam problemas para a virtualização [Robin e Irvine. sem causar uma interrupção. A verificação de proteção da arquitetura segmentada do x86 é a ruína do grupo inferior. 5. pois cada uma dessas instruções verifica o nível de privilégio implicitamente como parte da execução da instrução ao ler um registrador de controle. FIGURA 5. Uma alternativa para modificar o hardware é fazer pequenas modificações no sistema operacional de modo a evitar o uso de partes problemáticas da arquitetura. . e a verificação de proteção também falha. mas conside- ram que o sistema operacional está sendo executado no nível de privilégio mais alto. As duas classes gerais são instruções que: j Leem os registradores de controle no modo usuário. O Pacifica da AMD tem propostas semelhantes. mencionada anteriormente). O VMM Xen oferece um OS guest com uma abstração de máquina virtual que utiliza apenas as partes fáceis de virtualizar do hardware físico do x86. e o VMM Xen de fonte aberto é um bom exemplo. mas falha silenciosamente quando está no modo usuário. 2000]. em que o VMM é executado. As cinco primeiras instruções no grupo de cima permitem que um programa no modo usuário leia um registrador de controle. ser essencialmente a mesma nos computadores mais rápidos que nos computadores mais lentos e baratos. tanto AMD quanto Intel pro- puseram extensões à arquitetura de um novo modo. Para simplificar as implementações dos VMMs no x86.12  Comentários finais A dificuldade de construir um sistema de memória para fazer frente aos processadores mais rápidos é acentuada pelo fato de que a matéria-prima para a memória principal. o VT-x acrescenta 11 novas instruções para o x86. uma definição projetada do estado da VM. A instrução de “pop de flags” modifica um registrador de controle com informações sensíveis. DRAMs.440 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória A Figura 5. 2000]. O VT-x da Intel oferece um novo modo de execução para rodar VMs. Ao todo. Essa técnica é chamada de paravirtualização. A verificação considera que o OS precisa estar no nível de privilégio mais alto. instruções para trocar de VMs rapidamente e um grande conjunto de parâmetros para selecionar as circunstâncias em que um VMM precisa ser chamado. o que revela que o sistema operacional guest está sendo executado em uma máquina virtual (como POPF. Somente “Mover para/de registradores de segmento” (MOVE) tenta modificar o estado de controle. Embora esses níveis da hierarquia pareçam muito diferentes em termos quantitativos. 5. consideramos as hierarquias de memória para diversas aplicações. 5. ferência da memória. 1 Contribuição de Jichuan Chang. Windows e Linux. Essa otimização reduz significativamente o tráfego da memória para um kernel. Outra solução é o prefetching. mecanismos de proteção e máquinas virtuais.14 Exercícios 441 É o princípio da localidade que nos dá uma chance de superar a longa latência do acesso à memória — e a confiabilidade dessa técnica é demonstrada em todos os níveis da hierarquia de memória. os microprocessadores na Seção 7. podemos obter uma localidade – e. incluindo CTSS. A crescente importância da hierarquia de memória na determinação do desempenho do sistema significa que essa relevante área continuará a ser o foco de projetistas e pesquisadores ainda por vários anos. os parâmetros de projeto de uma cache de nível inferior são diferentes dos de uma cache de primeiro nível. Outra direção possível é recorrer à ajuda de software. O exemplo anterior. uso de instruções especiais que especificam o endereço do bloco. e conclui com uma breve história dos sistemas operacionais. MS-DOS. Em prefetching. MULTICS.11. uma cache de nível inferior realize alguma tarefa que possa ser útil para evitar futuras falhas. das linhas de atraso de mercúrio à DRAM. eles seguem estratégias semelhantes em sua operação e exploram as mesmas propriedades da localidade. Jacob Leverich. um bloco de dados é trazido para a cache prefetching  Uma técnica em que antes de ser realmente referenciado. futuro são colocados na cache pelo Uma terceira técnica utiliza instruções especiais cientes da cache. Esse método focaliza os programas orientados para loops que usam grandes arrays como a principal estrutura de dados. Uma é reorganizar o programa para melhorar sua localidade espacial e temporal. a invenção da hierarquia de memória. grandes problemas de álgebra linear são um exemplo típico. o que pode ser difícil para o software observar. Reestruturando os loops que acessam os arrays. UNIX. Por exemplo. listadas na tabela a seguir. quando estiver ociosa. como em uma cache de primeiro nível.14   Exercícios1  Exercício 5. pois o programa irá escrever o bloco inteiro. Muitos microprocessadores utilizam o prefetching de os blocos de dados necessários no hardware para tentar prever os acessos. que otimizam a trans. Controlar eficientemente a hierarquia de memória usando uma variedade de transformações de programa e recursos de hardware é um importante foco dos avanços dos compiladores. na Seção 5. BSD UNIX. Por exemplo. Primeiro. mostrou como poderia ser eficaz até mesmo uma simples mudança da estrutura de loop.13  Perspectiva histórica e leitura adicional Esta seção de história oferece um resumo das tecnologias de memória. um desempenho de cache – substancialmente melhor. 5.1 Neste exercício. como uma cache de segundo ou terceiro níveis será muito maior. uma cache de nível inferior não está constantemente sendo usada pelo processador. As caches multiníveis possibilitam o uso mais fácil de outras otimizações por dois motivos. portanto. Como veremos no Capítulo 7. Kevin Lim e Parthasarathy Ranganathan (todos da Hewlett-Packard) . Isso nos permite considerar fazer com que. é possível usar tamanhos de bloco maiores. Segundo. os sistemas de memória também são um importante tópico de projeto para processadores paralelos. Duas ideias diferentes estão sendo exploradas.10 do Capítulo 7 utilizam uma otimização que não apanha o conteúdo de um bloco da memória em uma falha de escrita. 1> Referências a quais variáveis exibem localidade espacial? . primeiro nomeie os sistemas cliente e servidor. veremos as propriedades de localidade de memória do cálculo de ma- triz.4 [10] <5. a.1.1 [5] <5.1.1> Quantos inteiros de 32 bits podem ser armazenados em uma linha de cache de 16 bytes? 5.1.5 [5] <5. Qual é o relacionamento entre o tamanho da cache e sua latência de acesso? 5.1> Quais são as unidades de transferências de dados entre as hierarquias? Qual é o relacionamento entre o local dos dados. Como o cache deve ser projetado para aliviar ou evitar esses problemas? Exercício 5.2 Neste exercício.3 [5] <5.2 [5] <5.6 [10] <5. 5.1.442 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória a.1> Crie uma hierarquia de memória para o sistema. o tamanho dos dados e a latência da transferência? 5.1 [10] <5.1.3 [15] <5.2.1. 5.1> Referências a quais variáveis exibem localidade temporal? 5. Onde as caches podem ser colocadas para agilizar o processo? 5. em que os elementos dentro da mesma linha são armazenados de forma contígua.2.1.1.1> Supondo que o cliente e o servidor estejam envolvidos no processo. O código a seguir é escrito em C.8> Dê um exemplo de quando a cache pode fornecer dados desatuali- zados. b. 5. esses cenários melhoram a localidade espacial e temporal? 5. Controle de versão de software b. Mostre o tamanho e a latência típicos em vários níveis da hierarquia. Fazer ligações no telefone 5.8> Agora.2 [10] <5. 5. Como a largura de banda pode ser melhorada? Qual será o custo dessa melhoria? 5.2> A largura de banda da comunicação e a largura de banda do processamento do servidor são dois fatores importantes a considerar quando se projeta uma hierarquia de memória.2.1. considerando múltiplos clientes acessando o servidor simul- taneamente. 61. O mesmo cál- culo também pode ser escrito a seguir em Matlab. 5. b. todos com um total de oito palavras de dados: C1 tem blocos de uma palavra. identifique o endereço binário.14 Exercícios 443 A localidade é afetada pela ordem de referência e pelo leiaute dos dados. supondo que a cache esteja inicialmente vazia.2> Para cada uma dessas referências. 111.5 [5] <5. 180. 61 5. a tag e o índice dado uma cache de mapeamento direto com 16 blocos de uma palavra. qual é o melhor projeto de cache? .2. 191. C2 tem blocos de duas palavras e C3 tem blocos de quatro palavras. 88.4 [10] <5. 5. identifique o endereço binário. indique se cada referência é um acerto ou uma falha. 143. 3.2 [10] <5.1> Quantas linhas de cache de 16 bytes são necessárias para armazenar todos os elementos de matriz de 32 bits sendo referenciados? 5.2. 62. 201.1 [10] <5.1> Referências a quais variáveis exibem localidade temporal? 5. 143.2> Para cada uma dessas referências. a.3 As caches são importantes para fornecer uma hierarquia de memória de alto desempenho aos processadores. 5. a. 14. 21. 2. a tag e o índice dado uma cache de mapeamento direto com blocos de duas palavras e um tamanho total de oito blocos. 133. e C1 tem um tempo de acesso de 2 ciclos. 253 b. supondo que a cache esteja inicialmente vazia. 5.3 [20] <5.6 [5] <5. Liste também se cada referência é um acerto ou uma falha.2. que projeto de cache é o melhor? Se o tempo de stall de falha é de 25 ciclos.3.3. A seguir está uma lista de 32 referências a endereços de memória de 32 bits. 181. Em termos de taxa de falhas. dadas como endereços de palavra.2. 190. 144. 43. 166. 166.3.3> Você está encarregado de otimizar um projeto de cache para as referências indicadas. Além disso. 44. Existem três projetos de cache de mapeamento direto possíveis.1> Referências a quais variáveis exibem localidade espacial? Exercício 5. 186. que difere da linguagem C armazenando elementos da matriz de forma contígua dentro da mesma coluna. C2 utiliza 3 ciclos e C3 utiliza 5 ciclos. 5. Dado esse tamanho total. Tag Índice Offset a.2> Qual é a razão entre o total de bits exigido para essa implementação de cache e os bits de armazenamento de dados? Desde que a alimentação esteja ligada. considerando um endereço de 32 bits. 5.2> Calcule o número total de bits necessários para a cache listada na tabela. Identifique uma solução possível que faria com que a cache listada na tabela tivesse uma taxa de falhas igual ou inferior à cache de 2KB.3. (Endereço de bloco[31:27] XOR Endereço de bloco[26:22]).6 [20] <5.4 Para um projeto de cache mapeada diretamente com endereço de 32 bits. A tabela a seguir lista parâmetros para diferentes projetos com mapeamento direto.3. ache o tamanho total da cache de mapeamento direto mais próxima com blocos de 16 palavras do mesmo tama- nho ou maior.2> Qual é o tamanho da linha de cache (em palavras)? 5. Explique por que a segunda cache. (Endereço do bloco) módulo (Número de blocos na cache). dados>. os bits de endereço a seguir são usados para acessar a cache.4. especificamente. . poderia oferecer desempenho mais lento do que a primeira cache. 5. Exercício 5.6 [15] <5.4 [15] <5.4. Se não for possível. com cada entrada válida representada como um registro de <índice.4 [10] <5. 32KB 4 palavras 2 ciclos 5. explique o motivo.2. Tamanho de dados da cache Tamanho de bloco da cache Tempo de acesso da cache a.4.3> Gere uma série de solicitações de leitura que possuem uma taxa de falhas em uma cache associativa em conjunto com duas vias de 2KB inferior à cache listada na tabela.2> Indique o estado final da cache. tag.5 [20] <5.2> Quantas entradas a cache possui? 5. considere uma função de indexação diferente.3 [5] <5. É possível usar isso para indexar uma cache mapeada diretamente? Se for. especificamente.2> Quantos blocos são substituídos? 5. as seguintes referências de cache endereçadas por byte são registradas. 32 KB 2 palavras 1 ciclo b.2> Qual é a razão de acerto? 5. 31-12 11-6 5-0 5.2> A fórmula apresentada na Seção 5. Supondo um endereço de 32 bits e 1024 blocos na cache.2 [5] <5.4. Endereço 0 4 16 132 232 160 1024 30 140 3100 180 2180 5.4. apesar de seu tamanho de dados maior. 5. Discuta as vantagens e desvantagens de uma solução desse tipo. explique por que e discuta quaisquer mudanças que poderiam ser necessárias na cache.444 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Existem muitos parâmetros de projeto diferentes que são importantes para o desempe- nho geral de uma cache.2 mostra o método típico para indexar uma cache mapeada diretamente. 31-10 9-5 4-0 b.3.4.1 [5] <5.5 [10] <5. 5.6 [5] <5.6.5. 5. 10. Considere os seguintes comportamentos do programa e da cache.5 [5] <5. ou seja.2. 5.5.30% 2% 64 5. L1 L2 a.2. bem como entre a cache L2 e a memória.5.5> Quais são as larguras de banda mínimas necessárias para alcançar o desempenho de CPI = 1. sem alocação de escrita Write-back.5. Write-through.5> Os buffers são empregados entre diferentes níveis de hierarquia da memória para reduzir a latência de acesso.2 [20] <5.1 [5] <5. 5.2 [5] <5.1> Recalcule a taxa de falhas quando o tamanho da linha de cache é de 16 bytes. Considere uma carga de trabalho de streaming de vídeo que acessa um conjunto de trabalho de 512KB sequencialmente com o fluxo de endereço a seguir: 0. com alocação de escrita.3> Considere um cache com mapeamento direto de 64KB com uma linha de 32 bytes. 250 100 0. 5. 5. 200 100 0. 14.2. quais são as larguras de banda mínimas de leitura e escrita necessárias para um CPI de 2? 5. mas não reutilizam grande parte dele. 64 bytes e 128 bytes. alocação de escrita 5.6 Aplicações de mídia que tocam arquivos de áudio ou vídeo fazem parte de uma classe de carga de trabalho chamada “streaming”. 5.5. 4.2. 2. alocação de escrita b. Write-through. quais são as larguras de banda mínimas de leitura e escrita (medidas em bytes-por-ciclo) necessárias para alcançar um CPI de 2? 5. considerando que 30% dos blocos de cache de dados substituídos são modificados. 16.5> Para uma cache write-back. Leituras de Escritas de Taxa de perdas Taxa de perdas Tamanho do dados por 1000 dados por 1000 da cache de da cache de bloco (byte) instruções instruções instruções dados a. Que tipo de localidade essa carga de trabalho está explorando? . considerando o componente envolvido e a possibilidade de substituir um bloco modificado. 5. 6.… 5.5? Exercício 5.6.30% 2% 64 b. suas combinações podem ser implementadas na cache L1 ou L2. 5. elas trazem grandes quantidades de dados.5 Lembre-se de que temos duas políticas de escrita e políticas de alocação de escrita.5> Descreva o procedimento de tratamento de uma falha de escrita em L1. descreva o procedimento de tratamento de uma falha de escrita em L1. 5. 8. considerando o componente envolvido e a possibilidade de substituir um bloco modificado.4 [5] <5. 5. com base no modelo 3C? 5.1 [5] <5.5> Para uma cache write-through. Para essa configuração dada.3 [20] <5. 5.5. 12.5> Para uma configuração de cache exclusiva multinível (um bloco só pode residir em uma das caches L1 e L2).14 Exercícios 445 Exercício 5. Qual é a taxa de falhas para esse fluxo de endereços? De que modo essa taxa de falhas é sensível ao tamanho da cache ou ao conjunto de trabalho? Como você categorizaria as falhas que essa carga de trabalho está experimentando. liste os possíveis buffers necessários entre as caches L1 e L2.5. alocação de escrita Write-back.2. com alocação de escrita.2. e a próxima linha de cache é pré-buscada. eles são considerados um acerto e movidos para a cache.6 [10] <5.3> Considerando que o tempo de acerto de L1 determina os tempos de ciclo para P1 e P2.1 [5] <5.62 ns b.3 [5] <5.6. considerando uma máquina de 1 CPI com uma média de 1.0% 0. ajude a encontrar o tamanho de bloco ideal dadas as seguintes taxas de falha para diversos tamanhos de bloco.446 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória 5.3 [10] <5.6.2 [5] <5.7.2> Qual é o tamanho de bloco ideal para uma latência de falha de 24 × B ciclos? 5. Normalmente. Qual é a taxa de falhas para esse stream de endereços? O tamanho do bloco de cache (B) pode afetar a taxa de falhas e a latência de falha.6. Um exemplo de prefetching é um buffer de fluxo que pré-busca linhas de cache sequencialmente adjacentes em um buffer separado quando determinada linha de cache é trazida. 8 16 32 64 128 a. Se os dados forem encontrados no buffer de prefetch. qual é o CPI total para cada um de P1 e P2? Que processador é mais rápido? Tamanho L2 Taxa de falhas L2 Tempo de acerto L2 a.3> Qual é o TMAM para cada um de P1 e P2? 5.90 ns b.6.0% 0. P1 e P2. Suponha que os acessos à memória principal utilizem 70ns e que os acessos à memória sejam 36% de todas as instruções. P1 16 KB 3. Considerando a seguinte tabela de taxa de falhas. quais são suas respectivas taxas de clock? 5. P1 2 KB 8.5% 1% b. 8% 7% 6% 5% 4% 5.9% 2.4 [10] <5.52 ns . veremos as diferentes maneiras como a capacidade afeta o desempenho geral.0 sem stalls de memória. 4% 3% 2% 1.4% 1. 8 MB 68% 23.3> Considerando um CPI base de 1. Tamanho L1 Taxa de falhas L1 Tempo de acerto L1 a.02 ns 5. 1 MB 95% 5. A tabela a seguir mostra dados para caches L1 relacionados a cada um dos dois processadores.7.2> Para uma latência de falha constante. o tempo de acesso da cache é proporcional à capacidade. qual é o tamanho de bloco ideal? Exercício 5.35 referências (a instruções e dados) por instrução.7 Neste exercício.2> Qual é o tamanho de bloco ideal para uma latência de falha de 20 × B ciclos? 5.66 ns P2 4 KB 6.7.5 [10] <5. Considere um buffer de stream de duas entradas e suponha que a latência da cache seja tal que uma linha de cache possa ser carregada antes que o cálculo na linha de cache anterior seja concluído.08 ns P2 32 KB 2.10> “Prefetching” é uma técnica que aproveita padrões de endereço previsíveis para trazer linhas de cache adicionais quando determinada linha de cache é acessada. 5.14 Exercícios 447 5.7.4 [10] <5.3> Qual é o TMAM para P1 com o acréscimo de uma cache L2? O TMAM é melhor ou pior com a cache L2? 5.7.5 [5] <5.3> Considerando um CPI base de 1,0 sem stalls de memória, qual é o CPI total para P1 com a adição de um cache L2 5.7.6 [10] <5.3> Que processador é mais rápido, agora que P1 tem uma cache L2? Se P1 é mais rápido, que taxa de falhas P2 precisaria em sua cache L1 para corresponder ao desempenho de P1? Se P2 é mais rápido, que taxa de falhas P1 precisaria em seu cache L1 para corresponder ao desempenho de P2? Exercício 5.8 Este exercício examina o impacto de diferentes projetos de cache, especificamente com- parando caches associativas com as caches mapeadas diretamente, da Seção 5.2. Para estes exercícios, consulte a tabela de streams de endereço mostrada no Exercício 5.3. 5.8.1 [10] <5.3> Usando as referências do Exercício 5.3, mostre o conteúdo final da cache para uma cache associativa em conjunto com três vias, com blocos de duas palavras e um tamanho total de 24 palavras. Use a substituição LRU. Em cada referência, identifique os bits de índice, os bits de tag, os bits de offset de bloco e se é um acerto ou uma perda. 5.8.2 [10] <5.3> Usando as referências do Exercício 5.3, mostre o conteúdo final da cache para uma cache totalmente associativa com blocos de uma palavra e um tamanho total de oito palavras. Use a substituição LRU. Para cada referência, identifique os bits de índice, os bits de tag, e se é um acerto ou uma perda. 5.8.3 [15] <5.3> Usando as referências do Exercício 5.3, qual é a taxa de perdas para uma cache totalmente associativa com blocos de duas palavras e um tamanho total de oito palavras, usando a substituição LRU? Qual é a taxa de perdas usando a substituição MRU (usado mais recentemente)? Finalmente, qual é a melhor taxa de perdas possível para essa cache, dada qualquer política de substituição? O caching multinível é uma técnica importante para contornar a quantidade limitada do espaço que uma cache de primeiro nível pode oferecer enquanto mantém sua velocidade. Considere um processador com os seguintes parâmetros: Taxa de perda global com cache de Taxa de perda global com cache de velocidade mapeada diretamente 2° nível, associativo em conjunto CPI base, sem stalls da memória 2° nível, mapeada diretamente Taxa de perdas da cache de 1° Tempo de acesso à memória Velocidade do processador velocidade associativa em Cache de segundo nível, Cache de segundo nível, conjunto com oito vias nível por instrução com oito vias principal a. 1,5 2GHz 100ns 7% 12 ciclos 3,5% 28 ciclos 1,5% b. 1,0 2GHz 150ns 3% 15 ciclos 5,0% 20 ciclos 2,0% 5.8.4 [10] <5.3> Calcule o CPI para o processador na tabela usando: 1) apenas uma cache de primeiro nível, 2) uma cache de mapeamento direto de segundo nível, e 3) uma cache 448 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória associativa em conjunto com oito vias de segundo nível. Como esses números mudam se o tempo de acesso da memória principal for dobrado? E se for cortado ao meio? 5.8.5 [10] <5.3> É possível ter uma hierarquia de cache ainda maior que dois níveis. Dado o processador anterior com uma cache de segundo nível mapeada diretamente, um projetista deseja acrescentar uma cache de terceiro nível que leve 50 ciclos para acessar e que reduzirá a taxa de falhas global para 1,3%. Isso ofereceria melhor desempenho? Em geral, quais são as vantagens e desvantagens de acrescentar uma cache de terceiro nível? 5.8.6 [20] <5.3> Em processadores mais antigos, como o Intel Pentium e o Alpha 21264, o segundo nível de cache era externo (localizado em um chip diferente) ao processador principal e à cache de primeiro nível. Embora isso permitisse grandes caches de segundo nível, a latência para acessar a cache era muito mais alta, e a largura de banda normalmente era menor, pois a cache de segundo nível trabalhava em uma frequência inferior. Suponha que uma cache de segundo nível de 512KB fora do chip tenha uma taxa de perdas global de 4%. Se cada 512KB adicionais de cache reduzisse as taxas de perdas globais em 0,7% e a cache tivesse um tempo de acesso total de 50 ciclos, que tamanho a cache deveria ter para corresponder ao desempenho da cache de segundo nível mapeada diretamente, listada na tabela? E ao desempenho da cache associativa em conjunto com oito vias? Exercício 5.9 Para um sistema de alto desempenho, como um índice B-tree para banco de dados, o tamanho de página é determinado principalmente pelo tamanho dos dados e pelo desempenho do disco. Suponha que, na média, uma página de índice B-tree esteja 70% cheio com entradas de tamanho fixo. A utilidade de uma página é sua profundidade de B-tree, calculada como log2(entradas). A tabela a seguir mostra que, para entradas de 16 bytes, um disco com dez anos de uso, uma latência de 10ms e uma taxa de transferência de 10MB/s, o tamanho de página ideal é de 16K. Utilidade da página ou profundidade Custo do acesso Tamanho de da B-tree (número de acessos ao disco à página de índice Utilidade/ página (KB) salvos) (ms) custo 2 6,49 (ou log2(2048/16 × 0,7)) 10,2 0,64 4 7,49 10,4 0,72 8 8,49 10,8 0,79 16 9,49 11,6 0,82 32 10,49 13,2 0,79 64 11,49 16,4 0,70 128 12,49 22,8 0,55 256 13,49 35,6 0,38 5.9.1 [10] <5.4> Qual é o melhor tamanho de página se as entradas agora tiverem 128 bytes? 5.9.2 [10] <5.4> Com base no Exercício 5.9.1, qual é o melhor tamanho de página se as páginas estiverem completas até a metade? 5.9.3 [20] <5.4> Com base no Exercício 5.9.2, qual é o melhor tamanho de página se for usado um disco moderno com latência de 3ms e uma taxa de transferência de 100MB/s? Explique por que os servidores futuros provavelmente terão páginas maiores. Manter páginas “frequentemente utilizadas” (ou “quentes”) na DRAM pode economizar acessos ao disco, mas como determinamos o significado exato de “frequentemente utilizadas” para determinado sistema? Os engenheiros de dados utilizam a razão de custo entre o acesso 5.14 Exercícios 449 à DRAM e ao disco para quantificar o patamar de tempo de reuso para as páginas quentes. O custo de um acesso ao disco é $Disco/acessos_por_segundo, enquanto o custo de manter uma página na DRAM é $DRAM_MB/tamanho_pag. Os custos típicos de DRAM e disco, e os tamanhos típicos de página de banco de dados em diversos pontos no tempo, são lis- tados a seguir: Custo da DRAM Tamanho da Custo do disco Taxa de acesso ao Ano ($/MB) página (KB) ($/disco) disco (acesso/seg) 1987 5000 1 15000 15 1997 15 8 2000 64 2007 0,05 64 80 83 5.9.4 [10] <5.1, 5.4> Quais são os patamares do tempo de reutilização para essas três gerações de tecnologia? 5.9.5 [10] <5.4> Quais são os patamares do tempo de reutilização se continuarmos usando o mesmo tamanho de página de 4K? Qual é a tendência aqui? 5.9.6 [20] <5.4> Que outros fatores podem ser alterados para continuar usando o mesmo tamanho de página (evitando assim a reescrita de software)? Discuta sua probabilidade com as tendências atuais de tecnologia e custo. Exercício 5.10 Conforme descrevemos na Seção 5.4, a memória virtual utiliza uma tabela de página para rastrear o mapeamento entre endereços virtuais e endereços físicos. Este exercício mostra como essa tabela precisa ser atualizada enquanto os endereços são acessados. A tabela a seguir é um stream de endereços virtuais vistos em um sistema. Considere páginas de 4KB, um TLB totalmente associativo com quatro entradas, e substituição LRU verdadeira. Se as páginas tiverem de ser trazidas do disco, incremente o próximo número de página maior. a. 4669, 2227, 13916, 34587, 48870, 12608, 49225 b. 12948, 49419, 46814, 13975, 40004, 12707, 52236 TLB Válido Tag Número da página física 1 11 12 1 7 4 1 3 6 0 4 9 Tabela de página Válido Página física ou no disco 1 5 0 Disco 0 Disco 1 6 1 9 1 11 0 Disco 450 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Válido Página física ou no disco 1 4 0 Disco 0 Disco 1 3 1 12 5.10.1 [10] <5.4> Dado o stream de endereços na tabela, e o estado inicial mostrado do TBL e da tabela de página, mostre o estado final do sistema. Indique também, para cada referência, se ela é um acerto no TLB, um acerto na tabela de página ou uma falta de página. 5.10.2 [15] <5.4> Repita o Exercício 5.10.1, mas desta vez use páginas de 16KB em vez de páginas de 4KB. Quais seriam algumas das vantagens de ter um tamanho de página maior? Quais são algumas das desvantagens? 5.10.3 [15] <5.3, 5.4> Mostre o conteúdo final do TLB se ele for associativo em conjunto com duas vias. Mostre também o conteúdo do TLB se ele for mapeado diretamente. Dis- cuta a importância de se ter um TLB para o desempenho mais alto. Como seriam tratados os acessos à memória virtual se não houvesse TLB? Existem vários parâmetros que afetam o tamanho geral da tabela de página. A seguir estão listados diversos parâmetros importantes da tabela de página. Tamanho do endereço Tamanho da entrada virtual Tamanho da página da tabela de página a. 32 bits 4KB 4 bytes b. 64 bits 16KB 8 bytes 5.10.4 [5] <5.4> Dados os parâmetros nessa tabela, calcule o tamanho total da tabela de página para um sistema executando cinco aplicações que utilizam metade da memória disponível. 5.10.5 [10] <5.4> Dados os parâmetros na tabela anterior, calcule o tamanho total da tabela de página para um sistema executando cinco aplicações que utilizam metade da memória disponível, dada uma técnica de tabela de página de dois níveis com 256 en- tradas. Suponha que cada entrada da tabela de página principal seja de 6 bytes. Calcule a quantidade mínima e máxima de memória exigida. 5.10.6 [10] <5.4> Um projetista de cache deseja aumentar o tamanho de uma cache de 4KB indexada virtualmente e marcada fisicamente com tags. Dado o tamanho de página listado na tabela anterior, é possível criar uma cache de 16KB com mapeamento direto, considerando duas palavras por bloco? Como o projetista aumentaria o tamanho dos dados da cache? Exercício 5.11 Neste exercício, examinaremos as otimizações de espaço/tempo para as tabelas de página. A tabela a seguir mostra parâmetros de um sistema de memória virtual. Endereço virtual DRAM física Tamanho da PTE (bits) instalada Tamanho da página (bytes) a. 43 16 GB 4 KB 4 b. 38 8 GB 16 KB 4 5.14 Exercícios 451 5.11.1 [10] <5.4> Para uma tabela de página de único nível, quantas entradas da tabela de página (PTE) são necessárias? 5.11.2 [10] <5.4> O uso de uma tabela de página multinível pode reduzir o consumo de memória física das tabelas de página apenas mantendo as PTEs ativas na memória física. Quantos níveis de tabelas de página serão necessários nesse caso? E quantas referências de memória são necessárias para a tradução de endereço se estiverem faltando no TLB? 5.11.3 [15] <5.4> Uma tabela de página invertida pode ser usada para otimizar ainda mais o espaço e o tempo. Quantas PTEs são necessárias para armazenar a tabela de página? Considerando uma implementação de tabela de hash, quais são os números do caso comum e do pior caso das referências à memória necessárias para atender a uma falta de TLB? A tabela a seguir mostra o conteúdo de uma TLB com quatro entradas. ID entrada Válido Página VA Modificado Proteção Página PA 1 1 140 1 RW 30 2 0 40 0 RX 34 3 1 200 1 RO 32 4 1 280 0 RW 31 5.11.4 [5] <5.4> Sob que cenários o bit de validade da entrada 2 seria definido como 0? 5.11.5 [5] <5.4> O que acontece quando uma instrução escreve na página VA 30? Quando uma TLB controlado por software seria mais rápido que uma TLB controlado por hardware? 5.11.6 [5] <5.4> O que acontece quando uma instrução escreve na página VA xxx? Exercício 5.12 Neste exercício, examinaremos como as políticas de substituição afetam a taxa de falhas. Considere uma cache associativa em conjunto com duas vias e quatro blocos. Você poderá achar útil desenhar uma tabela (como aquelas encontradas na seção “Falhas e associativida- de nas caches”, anteriormente neste capítulo) para solucionar os problemas neste exercício, conforme demonstramos nesta sequência de endereços “0, 1, 2, 3, 4). Endereço Conteúdo dos blocos de cache após referência do bloco de memória Acerto Bloco acessado ou falha expulso Conjunto 0 Conjunto 0 Conjunto 1 Conjunto 1 0 Falha Mem[0] 1 Falha Mem[0] Mem[1] 2 Falha Mem[0] Mem[2] Mem[1] 3 Falha Mem[0] Mem[2] Mem[1] Mem[3] 4 Falha 0 Mem[4] Mem[2] Mem[1] Mem[3] … Esta tabela mostra as sequências de endereços. Sequência de endereços a. 0, 2, 4, 8, 10, 12, 14, 16, 0 b. 1, 3, 5, 1, 3, 1, 3, 5, 3 452 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória 5.12.1 [5] <5.3, 5.5> Considerando uma política de substituição LRU, quantos acertos essa sequência de endereços exibe? 5.12.2 [5] <5.3, 5.5> Considerando uma política de substituição MRU (usado mais recentemente), quantos acertos essa sequência de endereços exibe? 5.12.3 [5] <5.3, 5.5> Simule uma política de substituição aleatória lançando uma moeda. Por exemplo, “cara” significa expulsar o primeiro bloco em um conjunto e “coroa” significa expulsar o segundo bloco em um conjunto. Quantos acertos essa sequência de endereços exibe? 5.12.4 [10] <5.3, 5.5> Que endereço deve ser expulso em cada substituição para ma- ximizar o número de acertos? Quantos acertos essa sequência de endereços exibe se você seguir essa política “ideal”? 5.12.5 [10] <5.3, 5.5> Descreva por que é difícil implementar uma política de subs- tituição de cache que seja ideal para todas as sequências de endereço. 5.12.6 [10] <5.3, 5.5> Considere que você poderia tomar uma decisão em cada referência de memória se deseja ou não que o endereço requisitado seja mantido em cache. Que impacto isso poderia ter sobre a taxa de falhas? Exercício 5.13 Para dar suporte às máquinas virtuais, dois níveis de virtualização de memória são neces- sários. Cada máquina virtual ainda controla o mapeamento entre o endereço virtual (VA) e o endereço físico (PA), enquanto o hipervisor mapeia o endereço físico (PA) de cada máquina virtual e o endereço de máquina (MA) real. Para acelerar esses mapeamentos, uma técnica de software chamada “paginação de shadow” duplica as tabelas de página de cada máquina virtual no hipervisor, e intercepta as mudanças de mapeamento entre VA e PA para manter as duas cópias coerentes. A fim de remover a complexidade das tabelas de página de shadow, uma técnica de hardware chamada tabela de página aninhada (ou tabela de página estendida) oferece suporte explícito a duas classes de tabelas de página (VA → PA e PA → MA) e pode percorrer essas tabelas apenas no hardware. Considere esta sequência de operações: (1) Criar processo; (2) Falha de TLB; (3) Falta de página; (4) Troca de contexto; 5.13.1 [10] <5.4, 5.6> O que aconteceria à sequência de operação indicada, para a tabela de página de shadow e a tabela de página aninhada, respectivamente? 5.13.2 [10] <5.4, 5.6> Considerando uma tabela de página de quatro níveis baseada na tabela de página guest e aninhada, quantas referências à memória são necessárias para atender a uma falha de TLB à tabela de página nativa versus aninhada? 5.13.3 [15] <5.4, 5.6> Entre a taxa de falha de TLB, latência de falha de TLB, taxa de falta de página e latência do tratador de falta de página, quais métricas são mais importantes para a tabela de página de shadow? Quais são importantes para a tabela de página aninhada? A tabela a seguir mostra parâmetros para um sistema de página por sombra. Falhas de TLB por Latência de falha Faltas de página por Overhead de shadowing por 1000 instruções de TLB NPT 1000 instruções falta de página 0,2 200 ciclos 0,001 30000 ciclos 5.14 Exercícios 453 5.13.4 [10] <5.6> Para um benchmark com CPI de execução nativo de 1, quais são os números de CPI se estiver usando tabelas de página de shadow versus NPT (considerando apenas o overhead de virtualização da tabela de página)? 5.13.5 [10] <5.6> Que técnicas podem ser usadas para reduzir o overhead induzido pelo shadowing da tabela de página? 5.13.6 [10] <5.6> Que técnicas podem ser usadas para reduzir o overhead induzido pelo NPT? Exercício 5.14 Um dos maiores impedimentos para o uso generalizado das máquinas virtuais é o overhead de desempenho ocasionado pela execução de uma máquina virtual. A tabela a seguir lista diversos parâmetros de desempenho e comportamento de aplicação. Acessos Tempo de privilegiados Impacto no Impacto no Acessos acesso de E/S do O/S desempenho desempenho de E/S (inclui tempo CPI por 10.000 de interceptar de interceptar por 10.000 para interceptar base instruções o O/S guest a VMM instruções o O/S guest) a. 1,5 120 15 ciclos 175 ciclos 30 1100 ciclos b. 1,75 90 20 ciclos 140 ciclos 25 1200 ciclos 5.14.1 [10] <5.6> Calcule o CPI para o sistema listado, supondo que não existem acessos à E/S. Qual é o CPI se o impacto do desempenho da VMM dobrar? E se for cortado ao meio? Se uma empresa de software da máquina virtual deseja obter uma degradação de desempenho de 10%, qual é a maior penalidade possível para interceptar a VMM? 5.14.2 [10] <5.6> Os acessos de E/S normalmente possuem um grande impacto sobre o desempenho geral do sistema. Calcule o CPI de uma máquina usando as características de desempenho anteriores, considerando um sistema não virtualizado. Calcule o CPI novamente, desta vez usando um sistema virtualizado. Como esses CPIs mudam se o sis- tema tiver metade dos acessos de E/S? Explique por que as aplicações voltadas para E/S possuem um impacto semelhante da virtualização. 5.14.3 [30] <5.4, 5.6> Compare as ideias da memória virtual e das máquinas virtuais. Como os objetivos de cada um se comparam: quais são os prós e contras de cada um? Liste alguns casos em que a memória virtual é desejada, e alguns casos em que as máquinas virtuais são desejadas. 5.14.4 [20] <5.6> A Seção 5.6 discute a virtualização sob a hipótese de que o sistema virtualizado esteja executando a mesma ISA do hardware subjacente. Porém, um uso pos- sível da virtualização é simular ISAs não nativas. Um exemplo disso é QEMU, que simula uma série de ISAs, como o MIPS, SPARC e PowerPC. Quais são algumas das dificuldades envolvidas nesse tipo de virtualização? É possível que um sistema simulado rode mais rápido do que em sua ISA nativa? Exercício 5.15 Neste exercício, exploraremos a unidade de controle de um controlador de cache para um processador com um buffer de escrita. Use a máquina de estados finitos encontrada na Figura 5.34 como ponto de partida para projetar suas próprias máquinas de estados finitos. 454 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Suponha que o controlador de cache seja para a cache de mapeamento direto descrita na Seção 5.7, mas você acrescentará um buffer de escrita com uma capacidade de um bloco. Lembre-se de que a finalidade de um buffer de escrita é servir como armazenamento temporário, de modo que o processador não precisa esperar por dois acessos à memória em uma falha modificada. Em vez de escrever de volta o bloco modificado antes de ler o novo bloco, ele coloca o bloco modificado no buffer e começa imediatamente a ler o novo bloco. O bloco modificado pode então ser escrito na memória principal enquanto o processador está trabalhando. 5.15.1 [10] <5.5, 5.7> O que deve acontecer se o processador emitir uma solicitação que acerta no cache enquanto um bloco está sendo escrito de volta na memória principal a partir do buffer de escrita? 5.15.2 [10] <5.5, 5.7> O que deve acontecer se o processador emitir uma solicitação que falha na cache enquanto um bloco está sendo escrito de volta à memória principal a partir do buffer de escrita? 5.15.3 [30] <5.5, 5.7> Crie uma máquina de estado finito para permitir o uso de um buffer de escrita. Exercício 5.16 A coerência da cache refere-se às visões de múltiplos processadores em determinado bloco de cache. A tabela a seguir mostra dois processadores e suas operações de leitura/escrita em duas palavras diferentes de um bloco de cache X (inicialmente, X[0] = X[1] = 0). P1 P2 a. X[0] + +;X[1] = 3; X[0] = 5;X[1]+ = 2; b. X[0] = 10;X[1] = 3; X[0] = 5;X[1]+ = 2; 5.16.1 [15] <5.8> Liste os valores possíveis do bloco de cache indicado para uma im- plementação correta do protocolo de coerência de cache. Liste pelo menos um valor possível do bloco se o protocolo não garantir coerência de cache. 5.16.2 [15] <5.8> Para um protocolo de snooping, liste uma sequência de operação válida em cada processador/cache para terminar as operações de leitura/escrita listadas anteriormente. 5.16.3 [10] <5.8> Quais são os números no melhor caso e no pior caso das falhas de cache necessários para terminar as instruções de leitura/escrita listadas? A coerência da memória refere-se às visões de múltiplos itens de dados. A tabela a seguir mostra dois processadores e suas operações de leitura/escrita em diferentes blocos de cache (A e B inicialmente 0). P1 P2 a. A = 1;B = 2; A+ = 2;B + +; C = B;D = A; b. A = 1;B = 2; A = 5;B + +; C = B;D = A; 5.16.4 [15] <5.8> Liste os valores possíveis de C e D para uma implementação que garante as suposições de consistência no início da Seção 5.8. 5.14 Exercícios 455 5.16.5 [15] <5.8> Liste pelo menos um par possível de valores para C e D se essas suposições não forem mantidas. 5.16.6 [15] <5.2, 5.8> Para diversas combinações de políticas de escrita e políticas de alo- cação de escrita, quais combinações tornam a implementação do protocolo mais simples? Exercício 5.17 Tanto o Barcelona quanto o Nehalem são multiprocessadores em um chip (CMPs), com diversas cores e suas caches em um único chip. O projeto da cache L2 no chip CMP possui opções interessantes. A tabela a seguir mostra as taxas de falhas e as latências de acerto para dois benchmarks com projetos de cache L2 privada versus compartilhada. Considere falhas de cache L1 uma vez a cada 32 instruções. Privada Compartilhada Falhas por instrução no benchmark A 0,30% 0,12% Falhas por instrução no benchmark B 0,06% 0,03% A próxima tabela mostra as latências de acerto. Cache privada Cache compartilhada Memória a. 5 20 180 b. 10 50 120 5.17.1 [15] <5.10> Qual projeto de cache é melhor para cada um desses benchmarks? Use dados para apoiar sua conclusão. 5.17.2 [15] <5.10> A latência da cache compartilhada aumenta com o tamanho do CMP. Escolha o melhor projeto se a latência da cache compartilhada dobrar. Como a largura de banda fora do chip torna-se o gargalo à medida que o número de cores CMP aumenta, escolha o melhor projeto se a latência da memória fora do chip dobrar. 5.17.3 [10] <5.10> Discuta os prós e os contras das caches L2 compartilhada versus privada para cargas de trabalho de único thread, multithreaded e multiprogramadas, e reconsidere-as se houver caches L3 no chip. 5.17.4 [15] <5.10> Considere que ambos os benchmarks têm um CPI base de 1 (cache L2 ideal). Se ter uma cache sem bloqueio melhora o número médio de falhas L2 concorrentes de 1 para 2, quanta melhoria de desempenho isso oferece sobre uma cache L2 comparti- lhada? Quanta melhoria pode ser obtida sobre a L2 privada? 5.17.5 [10] <5.10> Supondo que novas gerações de processadores dobrem o número de cores (núcleos) a cada 18 meses, para manter o mesmo nível de desempenho por core, quanta largura de banda fora do chip a mais é necessária para um processador em 2012? 5.17.6 [15] <5.10> Considerando a hierarquia de memória inteira, que tipos de otimi- zações podem melhorar o número de falhas simultâneas? Exercício 5.18 Neste exercício, mostramos a definição de um log de servidor Web e examinamos otimiza- ções de código para melhorar a velocidade de processamento do log. A estrutura de dados para o log é definida da seguinte forma: 456 Capítulo 5  Grande e Rápida: Explorando a Hierarquia de Memória Algumas funções de processamento em um log são: a. topK_sourceIP (int hour); b. browser_histogram (int srcIP); / /browsers of a given IP 5.18.1 [5] <5.11> Quais campos em uma entrada de log serão acessados para a função de processamento de log indicada? Considerando blocos de cache de 64 bytes e nenhum prefetching, quantas falhas de cache por entrada determinada função con- trai na média? 5.18.2 [10] <5.11> Como você pode reconhecer a estrutura de dados para melhorar a utilização da cache e a localidade do acesso? Mostre seu código de definição da es- trutura. 5.18.3 [10] <5.11> Dê um exemplo de outra função de processamento de log que preferiria um leiaute de estrutura de dados diferente. Se ambas as funções são importantes, como você reescreveria o programa para melhorar o desempenho geral? Suplemente a discussão com um trecho de código e dados. Para os problemas a seguir, use os dados de “Cache Performance for SPEC CPU2000 Benchmarks” (www.cs.wisc.edu/multifacet/misc/spec2000cache-data/) para os pares de benchmarks mostrados na tabela a seguir. a. apsi/facerec b. perlbmk/ammp 5.18.4 [10] <5.11> Para caches de dados de 64KB com associatividades de conjunto variadas, quais são as taxas de falhas desmembradas por tipos de falha (falhas frias, de capacidade e de conflito) para cada benchmark? 5.18.5 [10] <5.11> Selecione a associatividade de conjunto a ser usada por uma cache de dados L1 de 64KB compartilhada por ambos os benchmarks. Se a cache L1 tiver de ser mapeada diretamente, selecione a associatividade de conjunto para a cache L2 de 1MB. 5.18.6 [20] <5.11> Dê um exemplo na tabela de taxa de falhas em que a associatividade de conjunto mais alta aumenta a taxa de falhas. Construa uma configuração de cache e fluxo de referência para demonstrar isso. 5.14 Exercícios 457 §5.1: 1 e 4. (3 é falso porque o custo da hierarquia de memória varia por computador, mas Respostas das em 2008 o custo mais alto normalmente é a DRAM.) Seções “Verifique §5.2: 1 e 4: Uma penalidade de falha menor pode levar a blocos menores, pois você não você mesmo” tem tanta latência para amortizar, embora uma largura de banda de memória mais alta normalmente leve a blocos maiores, já que a penalidade de falha é apenas ligeiramente maior. §5.3: 1. §5.4: 1-a, 2-c, 3-c, 4-d. §5.5: 5, 2. (Tanto os tamanhos de bloco maiores quanto o prefetching podem reduzir as falhas compulsórias, de modo que 1 é falso.) 6 Armazenamento e outros tópicos de E/S Combinar largura de banda 6.1 Introdução  460 e armazenamento… permite 6.2 Confiança, confiabilidade e disponibilidade  462 acesso veloz e confiável às trovas 6.3 Armazenamento em disco  464 de conteúdo em expansão 6.4 Armazenamento flash  468 nos discos e… repositórios 6.5 Conectando processadores, memória e dispositivos de E/S  469 que se proliferam na Internet. 6.6 Interface dos dispositivos de E/S George Gilder.  com processador, memória e sistema The End is Drawing Nigh, 2000 operacional  473 6.7 Medidas de desempenho de E/S: exemplos de sistemas de disco e de arquivos  480 6.8 Projetando um sistema de E/S  482 6.9 Paralelismo e E/S: Redundant Arrays of Inexpensive Disks (RAID)  483 6.10 Vida real: servidor Sun Fire x4150  488 6.11 Tópicos avançados: redes  494 6.12 Falácias e armadilhas  494 6.13 Comentários finais  498 6.14 Perspectiva histórica e leitura adicional  498 6.15 Exercícios 499 Os cinco componentes clássicos de um computador 460 Capítulo 6  Armazenamento e outros tópicos de E/S 6.1   Introdução Embora os usuários possam se frustrar se seus computadores travarem e tiverem de ser reinicializados, eles ficam irados se seu sistema de armazenamento falhar e informações forem perdidas. Assim, a tolerância à confiabilidade é muito mais alta em relação ao armazenamento do que à computação. As redes também são planejadas para tratar falhas na comunicação, incluindo diversos mecanismos para detectar e recuperar-se de tais falhas. Logo, os sistemas de E/S geralmente colocam muito mais ênfase sobre a confiabilidade e o custo, enquanto os processadores e a memória focalizam o desempe- nho e o custo. Os sistemas de E/S também precisam planejar a facilidade de expansão e a diversidade de dispositivos, o que não é um problema para os processadores. A facilidade de expansão está relacionada à capacidade de armazenamento, que é outro parâmetro de projeto para os sistemas de E/S; os sistemas podem precisar de um limite inferior de capacidade de armazenamento a fim de cumprir seu papel. Embora o desempenho tenha um papel secundário para E/S, ele é mais complexo. Por exemplo, com alguns dispositivos, precisamos cuidar principalmente da latência de acesso, enquanto em outros a vazão é fundamental. Além do mais, o desempenho depende de muitos aspectos do sistema, de características dos dispositivos, da cone- xão entre o dispositivo e o resto do sistema, da hierarquia de memória e do sistema operacional. Todos os componentes, dos dispositivos de E/S individuais ao proces- sador e software de sistemas, afetarão a confiabilidade, a facilidade de expansão e o desempenho de tarefas que incluem E/S. A Figura 6.1 mostra a estrutura de um sistema simples com sua E/S. Os dispositivos de E/S são incrivelmente diversificados. Três características são úteis na organização dessa grande variedade: FIGURA 6.1  Uma coleção típica de dispositivos de E/S. As conexões entre os dispositivos de E/S, proces- sador e memória normalmente são chamadas de barramentos, embora o termo signifique fios paralelos compartilhados e a maioria das conexões de E/S hoje seja mais próxima de linhas seriais dedicadas. A comunicação entre os dispositivos e o processador utiliza interrupções e protocolos na interconexão, conforme veremos neste capítulo. A Figura 6.9 mostra a organização para um PC desktop. um teclado é um dispositivo de entrada usado por um humano com uma taxa de dados máxima de 10 bytes por segundo. vimos rapidamente quatro dispositivos de E/S importantes: mouses. Por exemplo. Em outro ambiente. O NITS cuida principalmente do processamento de uma grande quantidade de formulários em determinado momento. monitores gráficos.2  A diversidade de dispositivos de E/S. não pode ser lido) ou armazenamento (pode ser relido e normalmente reescrito). há uma seção de tópicos avançados sobre redes. de modo que 10 Mbits/seg = 10. que também são tratadas em outros livros. em muitas aplicações de multimídia. Nesses casos. No Capítulo 1. Neste capítulo. . e suas taxas de comunicação máximas. mas não pode ser usada para armazenamento. Quantas operações de E/S podemos realizar por unidade de tempo? A decisão sobre a melhor medida de desempenho pode depender do ambiente. discos e redes. É útil saber qual é a demanda máxima que o dispositivo pode gerar ao projetar um sistema de E/S. podemos nos importar principalmente com a vazão do sis- tema. a largura de banda de E/S será mais importante. a maioria das requisições de E/S é para fluxos de dados longos. Um exemplo desse ambiente poderia ser um escritório de processamento de impostos do National Income Tax Service (NITS). j Parceria: um humano ou uma máquina está na outra extremidade do dispositivo de E/S. As taxas de transferência dos dispositivos sempre são indicadas na base 10. seja alimentando a entrada de dados ou lendo-os na saída. 6.000. j Taxa de dados: a taxa de pico em que os dados podem ser transferidos entre o dis- positivo de E/S e a memória principal ou processador. Até mesmo a largura de banda de E/S pode ser medida de duas maneiras diferentes: 1.1 Introdução 461 j Comportamento: entrada (somente leitura). Os dispositivos de E/S podem ser distinguidos analisando se servem como dispositivos de entrada. seu parceiro de comunicação (pessoas ou outros computadores). No site. vamos nos aprofundar no armazena- mento e nos itens relacionados. Quantos dados podemos mover pelo sistema em determinado momento? 2. cada formulário de imposto é armazenado separadamente FIGURA 6. Por exemplo.000 bits/seg. e a largura de banda de transferência é a característica importante.2 mostra alguns dos dispositivos de E/S conectados aos computadores. As taxas de dados se espalham por oito ordens de grandeza. O modo como devemos avaliar o desempenho da E/S normalmente depende da apli- cação. podemos querer processar um número maior de acessos pequenos e não relacionados a um dispositivo de E/S. Observe que uma rede pode ser um dispositivo de entrada ou saída. saída ou armazenamento. Em alguns ambientes. saída (somente escrita. A Figura 6. servidores e computadores embutidos são sensíveis à confiabilidade e ao custo da E/S. no qual uma especificação de serviço é uma descrição combinada do comportamento esperado. a definição considerada padrão é a seguinte (Laprie. O último é o caso mais difícil de diagnosticar quando um sistema oscila entre os dois estados. especialmente no vasto mercado comercial para a computação. enquanto sistemas servidores focalizam mais a vazão e a facilidade de expansão dos dispositivos de E/S. importamo-nos principalmente com o tempo de resposta.2  Confiança. as três classes. Realização do serviço. e o sistema de E/S com a menor latência por acesso oferecerá o melhor tempo de resposta. Assim. mas um sistema de E/S que possa admitir a transferência simultânea de muitos arquivos pequenos pode ser mais barato e mais rápido para processar milhões de formulários de imposto. Em máquinas de monousuário. Um sistema orientado para transferência de arquivos grandes pode ser satisfatório. Resumindo. confiabilidade e disponibilidade Os usuários imploram por armazenamento confiável. sistemas de entrada de pedidos e acompanhamento de estoque. se você puder processar cada solicitação dos caixas eletrônicos rapidamente. na qual o serviço entregue é diferente do serviço especificado. servidores de arquivos e servidores Web. As falhas podem ser permanentes ou in- termitentes. Essa definição ocasiona dois termos relacionados: confiabilidade e disponibilidade. Após um considerável debate. Os usuários podem. Uma grande quantidade de aplicações. Nesses ambientes.462 Capítulo 6  Armazenamento e outros tópicos de E/S e é muito pequeno. Cada módulo possui um comportamento especificado ideal. 2. preocupamo-nos com o tempo usado para cada tarefa e quantas tarefas podemos processar em um segundo. O serviço entregue por um sistema é o seu comportamento real observado como percebido por outro(s) sistema(s) interagindo com os usuários desse sistema. Em outras aplicações. Interrupção do serviço. exige alta vazão e pouco tempo de resposta. muito da largura de banda. desktops. que. 6. As transições do estado 1 para o estado 2 são causadas por falhas. a questão é mais difícil do que consultar o dicionário. ou então o custo do computador por caixa eletrônico será muito alto. mas em muitos ambientes a maioria dos acessos será pequena. Alguns exemplos incluem caixas eletrônicos de banco. o tempo de res- posta é a principal característica do desempenho. as falhas permanentes são muito mais fáceis de diagnosticar. como você deve se lembrar. mas só pode lidar com uma pequena quantidade de requisições ao mesmo tempo. e as transições do estado 2 para o estado 1 são causadas por restaurações. requisições de E/S  Leituras ou Se as requisições de E/S forem extremamente grandes. Sistemas de desktop e sistemas embutidos se concentram mais no tempo de resposta e na diversidade dos dispositivos de E/S. não poderá dar suporte a muitos caixas eletrônicos. você precisa que uma especificação de referência do comportamento esperado seja capaz de determinar a confiança. mas como podemos definir isso? Na indústria de computação. como computadores desktop e laptops. Uma falha do sistema ocorre quando o comportamento real se desvia do comportamento especificado. então. . o tempo de resposta dependerá escritas em dispositivos de E/S. A quantidade de solicitações de caixas eletrônicos que você pode processar por hora não importa se cada uma exige 15 minutos – você ficará sem clientes! De modo semelhante. na qual o serviço é entregue conforme especificado. é o tempo total gasto para realizar uma tarefa em particular. 1985): Confiança de um sistema computacional é a qualidade do serviço entregue de modo que a confiança possa ser justificadamente depositada sobre esse serviço. ver um sistema alternando entre dois estados de serviço fornecido com relação à especificação deste: 1. 3 resume muitos documentos que coletaram dados sobre motivos para falhas de sistemas computacionais e sistemas de telecomunicações. . Qual é a causa das falhas? A Figura 6. que é simplesmente a porcentagem dos dispositivos que falhariam em um ano para determinado MTTF. 31-36) e por Patty Enriquez. mas eles em geral eram pequenos. Embora o MTBF seja muito utilizado. A Seção 6. A interrupção do serviço é medida como o tempo médio para o reparo (MTTR). permitindo que o componente seja substituído antes de falhar.2  Confiança. Logo. 2. como motivos ambientais para cortes de energia. a falha precisa ser definida em relação a um contexto. setembro–outubro de 1995. do tempo para a falha – de um ponto de referência. que ainda é muito citado. 6. e não apenas sinônimos de confiança. As duas linhas seguintes são de um artigo de Murphy e Gent. Quality and Reliability Engineering International 11:5. confiabilidade e disponibilidade 463 Confiabilidade é uma medida da realização contínua do serviço – ou. O tempo médio entre falhas (MTBF) é simplesmente a soma MTTF + MTTR.3  Resumo dos estudos dos motivos para falhas. Embora seja difícil coletar dados para deter- minar se os operadores são a causa dos erros. Logicamente. de forma equiva- lente. Logo. o que se aplica a falhas do hardware e do software. Uma falha em um componente pode não ocasionar uma falha do sistema. o termo falha é usado indicando falha de um componente. Previsão de falha: prever a presença e criação de falhas. Para esclarecer essa distinção. quase 20 anos após a coleta dos dados. As duas linhas iniciais vêm de um artigo clássico de Jim Gray [1990]. o tempo médio para a falha (MTTF) dos discos na Figura 6. 3. o que se aplica principal- mente a falhas do hardware.9 descreve as técnicas de RAID para tornar o armazenamento confiável por meio da tolerância a falhas. Tolerância a falhas: uso de redundância para permitir que o serviço cumpra com a especificação de serviço apesar da ocorrência de falhas. A disponibilidade é quantificada estaticamente como MTTF Disponibilidade = (MTTF + MTTR) Observe que a confiabilidade e a disponibilidade são medidas quantificáveis. abril de 1997. você pode melhorar a qualidade dos componentes ou projetar sistemas para que continuem a operação na presença de componentes que falharam. Aqui estão três maneiras de melhorar o MTTF: 1. As quinta e sexta linhas são estudos de dados de falhas do FCC sobre a rede telefônica pública dos Estados Unidos. Constantemente havia outras categorias. IEEE Computer 30:4. os operadores humanos são uma fonte de falhas significativa. Para aumentar o MTTF. Um termo relacionado é a taxa de falha anual (AFR). por Kuhn (“Sources of failure in the public switched telephone network”. Impedimento de falha: evitar a ocorrência da falha pela construção. que estudaram casos de cortes em sistemas VAX com o tempo (“Measuring system and software reliability using an automated data collection process”. 341-53). o MTTF normalmente é o termo mais apropriado.5 é uma medida de confiabilidade. esses estudos capturaram esses dados. Disponibilidade é uma medida da realização do serviço com relação à alternância entre os dois estados de realização e interrupção. Ganapath e Patterson [2003]. FIGURA 6. O estudo mais recente de três servidores de internet vem de Oppenheimer. como os operadores normalmente registram os motivos para as falhas. 3  Armazenamento em disco Como mencionamos no Capítulo 1. 2. o sistema operacional precisa direcionar o disco por um processo em três estágios. de modo que cada cabeça esteja sobre a mesma trilha de cada superfície. cabeça de leitura/gravação na trilha Os fabricantes de disco informam o tempo de seek mínimo. e o tempo de seek médio em seus manuais.000 concêntricos que compõem a a 50.096 bytes. as cabeças de leitura/escrita precisam ser movidas de modo que estejam sobre o local correto. ferramentas para detecção. assim. os discos magnéticos contam com um prato giratório coberto por uma superfície magnética e utiliza uma cabeça de leitura/escrita móvel para não volátil Dispositivo acessar o disco. Um disco magnético consiste em uma coleção de pratos os dados retêm seu valor mesmo (1-4). Verifique Quais das seguintes afirmações são verdadeiras sobre confiança? você mesmo 1. e o tempo para mover a cabeça até a trilha apropriada é chamado tempo de seek. O armazenamento em disco é não volátil – os dados permanecem mesmo de armazenamento em que quando a alimentação é removida. portanto. página C-66). A pilha de pratos gira a uma velo- quando a alimentação é removida. então todos os seus componentes estão realizando seu serviço esperado. O primeiro passo é posicionar a cabeça sobre a trilha apropriada. cada qual com duas superfícies de disco graváveis. mas com a introdução da ZBR (Zone Bit Recording – registro de bits por zona) no início da década de 1990. informações. mas. quantidade de informação lida ou escrita em um disco. chamados trilhas.000RPM e tem um diâmetro entre 2. O termo cilindro é usado para se referir a todas as trilhas sob as cabeças em determinado ponto para todas as superfícies. para ler e escrever informações. 3. Normalmente. O ZBR aumenta o número de bits nas trilhas externas e. mas a média está aberta a interpretações. . o mes- mo número de bits. existem de 10. diagnóstico e reparo de falhas podem ajudar a reduzir o tempo e reparar falhas ocasionadas por pessoas. pois ela depende da distância do seek. magnético. um gap. um gap.400 a 15. o tempo de seek médio real pode ser de apenas 25% a 33% do número anunciado. um setor é a menor a informação para esse setor incluindo o código de correção de erro (veja Apêndice C. Como vimos no Capítulo 1. A principal fonte de interrupções hoje é o software. Cada superfície do trilha  Um dos milhares de círculos disco é dividida em círculos concêntricos. dependendo da aplicação e do escalonamento das requisições de disco. Os dois primeiros são fáceis de medir. Essa localidade surge tanto por causa de acessos sucessivos ao mesmo arquivo quanto porque o sistema operacional tenta escalonar esses acessos juntos. é dividida em setores que contêm as superfície de um disco magnético. o tempo de seek máximo correta de um disco. A confiabilidade é uma medida quantitativa da realização contínua do serviço por um sistema. As cabeças de disco para cada superfície são conectadas e se movem em conjunto.5cm e 9cm. cada trilha pode ter de 100 a 500 setores. Os tempos de seek médios normalmente são anunciados como entre 3ms a 13ms. embora exista uma iniciativa para aumentar o tamanho do setor compõem uma trilha em um disco para 4. em vez de manter constante o espaçamento entre os bits. as unidades de disco passaram para um número variável de setores (portanto. devido à localidade das referências de disco. por sua vez. Para acessar dados.000 trilhas por superfície. 4. o número de setor do próximo setor. bits) por trilha. Originalmente. Os setores normalmente possuem setor  Um dos segmentos que 512 bytes de tamanho. e assim por diante. Cada trilha. software e hardware. Se um sistema estiver ativo. cidade entre 5. todas as trilhas tinham o mesmo número de setores e. Essa operação é seek  O processo de posicionar uma chamada seek. aumenta a capacidade da unidade. A disponibilidade é uma medida quantitativa da porcentagem de tempo em que um sistema está realizando seu serviço esperado. 6. A sequência gravada em mídia magnética é um número de setor. Os fabricantes decidiram calcular o tempo de seek médio como a soma do tempo para todos os seeks possíveis dividido pelo número de seeks possíveis. Por exemplo.464 Capítulo 6  Armazenamento e outros tópicos de E/S Diminuir o MTTR pode ajudar na disponibilidade tanto quanto aumentar o MTTF. A latência média para a informação desejada está a meio caminho ao redor do dis. o tempo da controladora.005 ms + 0.000RPM. é o tempo para transferir um bloco de bits.000RPM / 60   minuto  = 0‚0020 segundos = 2‚0 ms O último componente de um acesso ao disco. a taxa de trans. a resposta é 1. Usando o tempo de RESPOSTA seek médio anunciado. Uma controladora de discos normalmente trata do controle detalhado do disco e da transferência entre o disco e a memória. 0‚5rotação 0‚5rotação normalmente considerado metade Latência rotacional média = = do tempo de rotação. temos de esperar até o setor desejado girar sob a cabeça de leitura/escrita. 2 ms Observe que. 6.400RPM a 15. a maioria das transferências de disco possui o tamanho de múltiplos setores. A controladora acrescenta o componente final do tempo de acesso ao disco. Tempo de leitura do disco Qual é o tempo médio para ler ou escrever um setor de 512 bytes em um disco típico girando a 15. A única complicação é que a maioria dos controladores de disco possui uma cache interna que armazena setores enquanto eles passam. Suponha que o disco esteja ocioso.2ms. Hoje. Como os discos giram entre 5. 5400RPM   5400RPM/ 60 segundos   minuto  = 0‚0056 segundos = 5‚6 ms E 0‚5rotação 0‚5rotação Latência rotacional média = = 15. quando consideramos o tempo médio de seek medido.000RPM  segundos  15. o tempo de transferência. Esse tempo é chamado de latência rotacional ou atraso latência rotacional Também rotacional. as taxas de transferência da cache normalmente são maiores e poderiam chegar até 375MB/seg (3 Gbit/seg) em 2008. 2ms = 3.0 ms + 0. EXEMPLO ferência é de 100MB/seg e o overhead da controladora é de 0. .000RPM? O tempo de seek médio anunciado é de 4ms. chamada de atraso rotacional. O tempo médio para realizar uma operação de E/S consistirá nesses quatro tempos mais qualquer espera que ocorra porque outros processos estão utilizando o disco. a latência rotacional pode ser o maior componente do tempo de acesso. O tempo exigido para que o co. ao contrário do tempo médio de seek anunciado. da velocidade de rotação e da densidade de gravação de uma trilha.3  Armazenamento em disco 465 Quando a cabeça tiver atingido a trilha correta. O tempo de transferência é uma função do tamanho do setor. As taxas de trans- ferência em 2008 estavam entre 70 e 125MB/seg.000RPM 100 MB/seg Se o tempo médio de seek medido for 25% do tempo médio anunciado. que é o overhead que a controladora impõe na realização do acesso de E/S. de modo que não existe um tempo de espera. O tempo médio de acesso ao disco é igual ao Tempo médio de seek + Atraso rotacional médio + Tempo de transferência + Overhead da controladora.0 ms + 2. a latência rotacional média é entre setor desejado de um disco gire sob a cabeça de leitura/escrita. a resposta é 0‚5rotação 0‚5KB 4‚0ms + + + 0‚2 ms = 4‚0 + 2‚0 + 0‚005 + 0‚2 = 6‚2 ms 15. O Micropolis RD53 possui cinco pratos de 13. Essas caches permitem um acesso rápido aos dados lidos recentemente entre trans- . Ele foi fabricado em 1985. contendo quatro pratos de 35. Os blocos lógicos são ordenados em formato de serpentina por uma única superfície. O motivo para o desmem- bramento foi o aumento do nível das interfaces.5cm de diâmetro e armazenando 456MB. Detalhamento:  Essas interfaces de alto nível permitem que as controladoras de disco incluam caches.4. A Figura 6. essas interfaces de nível mais padrão para dispositivos de E/S. Em 2008.30 e US$5 por gigabyte.35cm. contendo 40MB. As supo- sições do modelo de setor-trilha-cilindro são que os blocos próximos estão na mesma trilha. na Figura 6. exigiram um microprocessador dentro de um disco. pois não existe tempo de seek. mas possuem apenas 8.3cm e armazena 85MB. O IBM 0361 também possui cinco pratos. os blocos no mesmo cilindro levam menos tempo para acessar. As interfaces inteligentes de nível mais Advanced Technology alto. O menor disco desta fotografia é o Integral 1820. Em 2008. O disco com diâmetro de 20cm vem da Fujitsu. da para dispositivos de E/S.5 mostra as características de quatro discos magnéticos. essa fotografia representa com precisão seus tamanhos físicos relativos.8cm mais denso tinha dois pratos e tinha 1TB no mesmo espaço. os preços geralmente variam entre US$0. o mesmo não ocorre com a sabedoria convencional sobre onde os números de bloco são encontrados.5cm. o que leva a Attachment (ATA)  Um conjunto otimizações de desempenho. Contudo.5cm contém 20MB e foi fabricado em 1992. e foi fabricado em 1990. como mostra a Figura 6. Esse disco de 1988 tem 320MB de capacidade. de comandos utilizado como Para aumentar a velocidade das transferências sequenciais. o disco de 8. Portanto. que é muito popular no PC.4  Seis discos magnéticos. e esse disco de 1984 armazena 130MB em seis pratos. ocasionando um aumento de densidade de aproximadamente 3000 vezes! O Conner CP 2045 possui dois pratos de 6. As densidades de disco têm continuado a aumentar há mais de 50 anos. não representam a melhor capacidade dos discos modernos desses mesmos diâmetros. Os discos da figura foram introduzidos há mais de 15 anos e. armadilha de considerar o modelo convencional de setor-trilha-cilindro.8cm de diâmetro. da interface e do desempenho. os blocos comandos usado como um padrão sequenciais podem estar em trilhas diferentes. alto organizam os discos mais como fitas do que como dispositivos de acesso aleatório.20 e US$2 por gigabyte. portanto.466 Capítulo 6  Armazenamento e outros tópicos de E/S FIGURA 6. variando em diâmetro de 35cm até 4. O maior dos discos é o DEC R81. e algumas trilhas são mais próximas que outras. Esse disco de um único prato de 4. dependendo do tamanho. O impacto dessa melhoria na densidade e na redução do tamanho físico de uma unidade de disco tem sido incríveis. Os objetivos de diferentes projetistas de discos têm levado a uma grande variedade de unidades disponíveis em determinado momento. Embora os discos permaneçam viáveis por um futuro previsível. esses discos de um único fabricante custavam entre US$0. como ATA e SCSI. Veremos um exemplo.19. No mercado mais amplo. tentando Small Computer Systems Interface (SCSI)  Um conjunto de capturar todos os setores que são gravados na mesma densidade de bits. Quais dos seguintes itens são verdadeiros sobre unidades de disco? Verifique 1. Observe que o MTTF cotado considera potência e temperatura normais. Elas utilizam write-through e não atualizam quando há falha na escrita. São necessárias horas para ler o conteúdo de um disco de alta capacidade sequen- cialmente. A taxa de transferência da cache é de 3-5 vezes mais rápida do que a taxa de transferência da superfície do disco.com a fim de obter mais informações sobre essas unidades. embora existam diferenças em desempenho em E/Ss por segundo devido à rotação mais rápida e tempos de seek mais rápidos para SAS.3  Armazenamento em disco 467 FIGURA 6.35cm de diâmetro. As três unidades mais à esquerda são para servidores e desktops. 3. Naturalmente. ou a versão serial da ATA (SATA). .35cm. Os tempos de vida do disco podem ser muito mais curtos se a temperatura e a vibração não forem controlados.89cm realizam mais E/Ss por segundo que os discos de 6. Elas normalmente também incluem algoritmos de prefetch para tentar antecipar a demanda. Veja o link da Seagate em www.seagate. você mesmo 2. Discos de 6. 4. 6. um barramento de E/S padrão para muitos sistemas. Discos de 8. enquanto a unidade mais à direita é para laptops. Os discos mostrados aqui são versões seriais da interface para SCSI (SAS). São necessários meses para ler o conteúdo de um disco de alta capacidade usando setores aleatórios de 512 bytes. O custo muito mais baixo por gigabyte da unidade de 8. mas é uma unidade de alto desempenho com a mais alta confiabilidade e tempo de seek mais rápido.8cm SATA ocorre principalmente devido ao mercado hipercompetitivo dos PCs. essas capacidades complicam a medida de desempenho do disco e aumentam a importância da escolha da carga de trabalho na comparação de discos.5  Características de quatro discos magnéticos de um único fabricante em 2008. As controladoras também utilizam uma fila de comandos que permite que o disco decida em que ordem irá realizar os comandos para maximizar o desempenho enquanto mantém o comportamento correto.35cm oferecem os mais altos índices de gigabytes por watt. A vida útil para esses discos é de cinco anos. Observe que a terceira unidade tem apenas 6. ferências solicitadas pelo processador. um barramento de E/S padrão para PCs. memória de bolha e memória holográfica. A primeira memória flash. sendo aleatoriamente endereçável. mas a latência é 100-1000 vezes mais rápida que o disco.6 utilizam flash NAND. Diferente dos discos e da DRAM. a memória flash NAND oferecia maior densidade de armazenamento. todos os produtos na Figura 6. câmeras digitais e players MP3. . A Figura 6. Como resultado. Há alguns anos. chamada flash NOR devido à semelhança da célula de armazenamento com uma porta NOR padrão. ele simula uma interface de disco. Quando uma nova tecnologia era entregue. pois a fiação necessária para os acessos aleatórios foi retirada.7). Essa técnica é chamada de nivelamento de desgaste.7 compara as principais características da memória flash NOR versus NAND. gasta menos energia e é mais resistente ao choque. Embora seu custo por gigabyte seja mais alto que os discos. ou cerca de 2 a 40 vezes mais alto que o disco e 5 a 10 vezes mais baixo que a DRAM.6 compara três produtos baseados em flash. O produto RiDATA imita uma interface de disco SATA de 2. trilhas lógicas e assim por diante. os bits da memória flash se desgastam (ver Figura 6. como qualquer memória. o custo da memória flash por gigabyte tem caído 50% por ano. Em 2008. a memória flash é popular nos dispositivos móveis em parte porque vem em capacidades menores. existe um grande mercado a pagar pelo investimento na melhoria da tecnologia de memória flash. mas assim como as tecnologias EEPROM. Por exemplo. Por seguir a interface ATA. o MP3 player iPod Shuffle da Apple era vendido por US$50 e mantinha 1GB. enquanto o disco menor é de 4GB e é vendido por mais do que o MP3 player inteiro. produtos de consumidor FIGURA 6. os discos rígidos de 1 polegada de diâmetro estão desaparecendo de alguns mercados de embutidos. a maioria dos produtos de flash NAND inclui um controlador para espalhar as escritas. o preço por gigabyte da flash era de $4 a $10 por gigabyte. Essa memória semicondutora é não volátil como os discos. era um concorrente direto com outras EEPROMs.6  Características de três produtos de armazenamento flash. mas a memória só podia ser lida e escrita em blocos.468 Capítulo 6  Armazenamento e outros tópicos de E/S 6. A fim de lidar com esses limites. Recentemente. O pacote padrão CompactFlash foi proposto pela Sandisk Corporation em 1994 para as placas PCMCIA-ATA de PCs portáteis. e ela é menor. Com o nivelamento de desgaste. e muitos falharam: memória CCD. O primeiro desafiador convincente é a memória flash. remapeando blocos que foram escritos muitas vezes para blocos menos utilizados. em 2008. A memória flash é um tipo de memória somente de leitura programável e eletricamente apagável (EEPROM).5 polegadas. incluindo comandos seek. os custos caíam proporcionalmente. os discos faziam avanços conforme já era previsto. e o produto desafiador ficava pouco atraente no mercado. A Figura 6.4   Armazenamento flash Muitos tentaram inventar uma tecnologia para substituir os discos. todos ficaram a desejar. Igualmente importante. A flash NAND é muito menos dispendiosa por gigabyte e muito mais comum que a flash NOR. devido à popularidade da memória flash nos telefones celulares. os diversos subsistemas precisam ter interfaces entre si. Porém. Estes dispositivos podem ler bytes e palavras de 16 bits apesar de seus tamanhos de acesso grandes. Combinando as duas ideias. MP3 players ou chaves de memória têm muito poucas chances de excederem os limites de escrita na flash. À medida que a capacidade aumenta e o custo por gigabyte continua a cair. Há também memórias flash disponíveis em tamanhos de disco padrão. Assim como a DRAM. Um barramento é um link de comunicação compartilhado. Durante muitos anos. para oferecer tempos de boot mais rápidos. isso tem sido feito com um barramento. Nos próximos anos. a não ser que o software de nível mais alto monitore o desgaste do bloco. mas são necessários. como mostra a Figura 6. mapeando as células de memória que foram manufaturadas incorretamente. parece que a memória flash competirá com sucesso com os discos rígidos para muitos dispositivos operados por bateria. mesmo 2. os primeiros laptops estão sendo vendidos com memória flash em vez de discos rígidos. será interessante ver se o desempenho mais alto e a eficiência de energia da memória flash gerarão oportunidades também nos mercados de desktop e servidor.5  e dispositivos de E/S Em um sistema computacional. Assim como os discos. memória e dispositivos de E/S 469 FIGURA 6. os controladores também podem melhorar o rendimento. câmeras digitais. a memória flash não perde informações se faltar energia. e os periféricos podem ainda ser . tamanho menor e maior vida da bateria. Definindo um único esquema de conexão. memória 6. novos dispositivos podem ser facilmente acrescentados. de modo que os laptops podem inicializar mais rapidamente e economizar energia. Conectando processadores. permitindo que os discos permaneçam ociosos com mais frequência. Os limites de escrita são um motivo para a memória flash não ser comum nos compu- tadores de desktop e servidor.6. 6. 4. Quais dos seguintes itens são verdadeiros sobre a memória flash? Verifique você 1. assim como o processador e os dispositivos de E/S. a memória flash é uma memória semicondutora. que utiliza um conjunto de fios para conectar diversos subsistemas. a um custo considerável. digamos. A largura de banda de leitura da flash NAND é semelhante ao disco. Por exemplo.7  Características da memória flash NOR versus NAND em 2008.5  Conectando processadores. As duas vantagens principais da organização do barramento são versatilidade e baixo custo. Esses controladores reduzem o desempenho em potencial da flash. a memória e o processador precisam se comunicar. O tempo de acesso de leitura da flash NOR é semelhante à DRAM. como telefones celulares. em 2008. os discos rígidos híbridos incluem. um gigabyte de memória flash. 3. Porém. o setor de computadores desenvolveu diversos padrões. barramento processador. a largura de banda desse barramento limita a vazão máxima da E/S. Logicamente. Quando a E/S tiver de passar por um único barramento. Além do mais. a necessidade de dar suporte a uma gama de dispositivos com latências e taxas de transferência de dados muito variáveis também torna o projeto do barramento desafiador. vista do processador: uma operação de entrada significa entrar dados do dispositivo para a memória. Uma transação inclui duas partes: enviar de operações pela interconexão que o endereço e receber ou enviar os dados. dos a eles. Os barramentos de E/S. Os barramentos processador-memória são curtos. vamos tentar usar os termos entrada e saída. A principal desvantagem de um barramento é que ele cria um gargalo de comuni- cação. velocidade. . em vez de focalizar exclusivamente os barramentos. essas redes estão gradualmente substituindo os barramentos em nossos sistemas. memória e rentes surgiram para funções especiais. como barramentos gráficos. e correspondente ao sistema de memória. A interconexão de E/S serve como um modo de expandir a máquina e conectar novos periféricos. Como é difícil trabalhar com muitos fios paralelos em alta velocidade devido a variações de clock e reflexão (veja Apêndice C).470 Capítulo 6  Armazenamento e outros tópicos de E/S movidos entre os sistemas computacionais que utilizam o mesmo tipo de barramento. Para facilitar isso. Como resultado dessa transição. Um padrão garante ao projetista do computador que os periféricos estarão disponíveis para uma nova máquina. na qual o processador os poderá ler. Outros barramentos com características dife- que processadores. processadores e memória. de modo podem ser extensos. O principal desafio é projetar um sistema de barramento capaz de atender às demandas do processador e também conectar grandes quantidades de dispositivos de E/S à máquina. de modo a maxi- e que é curto. geralmente de alta mizar a largura de banda memória-processador. dispositivos de E/S coexistam em Um motivo para o projeto de barramento ser tão difícil é que sua velocidade máxima um único barramento. passando de barramentos paralelos compartilhados para interconexões seriais ponto a ponto de alta velocidade com switches.8 resume as principais características dos cinco padrões de E/S dominantes: Firewire. que sempre são definidos do ponto de de barramento individuais. Os padrões servem como uma especificação para o fabricante de computador e para o fa- bricante de periféricos. e uma transação de es- iniciada por uma única solicitação crita escreve dados na memória. USB. serial ATA (SATA) e Serial Attached SCSI (SAS). ge- conecta processador e memória. ao contrário. PCI Express (PCIe). Assim. é limitada principalmente pelos fatores físicos: a extensão do barramento e o número de dispositivos. essa terminologia é confusa. Uma transação de leitura transfere dados da transportar dados. Os barramentos de E/S normalmente não realizam interface direta com a me- barramento backplane Um mória. Além disso. na qual o processador os es- creve. Uma transação é memória (para o processador ou para um dispositivo de E/S). os barramentos são eficazes porque um único conjunto de fios é compartilhado de várias maneiras. mas utilizam um barramento processador-memória ou um barramento barramento projetado para permitir backplane para a conexão com a memória. Os barramentos tradicionalmente são classificados como barramentos processador- memória  Um barramento que memória. ambas podendo definidas pelo que fazem com a memória. Esses limites físicos nos impedem de executar o barramento arbitrariamente rápido. esta seção foi revisada nesta edição para enfatizar o problema geral de conectar dispositivos de E/S. o setor está em transição. e garante ao montador do periférico que os usuários poderão se conectar ao seu novo equipamento. desde teclados a câmeras e discos. possivelmente limitando a vazão máxima de E/S. Fundamentos sobre conexão transação de E/S  Uma sequência Vamos considerar uma transação de E/S típica. podem ter muitos tipos de dispositivos conectados a eles e normal- a maximizar a largura de banda mente possuem uma grande faixa de largura de banda de dados dos dispositivos conecta- memória-processador. Para evitar e pode exigir várias operações isso. e uma operação de saída significa sair com dados para um dispositivo a partir da memória. ou barramentos de E/S. As transações de barramento normalmente são inclui uma solicitação e pode incluir uma resposta. ralmente de alta velocidade e correspondentes ao sistema de memória. A Figura 6. Eles conectam uma série de dispositivos aos computadores desktop. pode acomodar uma de clock ou sincronismo. grande variedade de dispositivos. barramentos assíncronos em que o emissor e o receptor só prosseguem para a próxima etapa quando as As interconexões de E/S dos processadores x86 duas partes concordarem que a etapa atual foi concluída. Entretanto. poderíamos ter um fixo para comunicação. Os barramentos tradicionais são síncronos. O processador se conecta a periféricos por meio de dois chips principais. protocolo de handshaking Uma te em uma série de etapas em que o emissor e o receptor prosseguem para a próxima série de etapas usadas para etapa apenas quando as duas partes concordarem. Primeiro. Por exemplo. A bridge sul conecta . 6.5  Conectando processadores. possivelmente a uma placa gráfica e ao chip da bridge sul. e o barramento pode ser estendido sem preocupação com problemas de variação um clock. Esse tipo de proto- colo pode ser implementado com facilidade em uma máquina de estados finitos peque- na. assíncrono utiliza um protocolo de handshaking. o barramento pode executar mais rapidamente. cada dispositivo no barramento precisa executar na mesma velocidade de clock.8 são assíncronos. para realizar uma leitura da memória. em vez de positivos. um barramento diferentes velocidades. clock. PCIe pode admitir leituras e escritas simultâneas. considerando uma divisão 50/50 de largura de banda de leitura versus escrita. devido a pro- blemas de variação de clock. relativo ao protocolo que transmite o endereço e comando de leitura no primeiro ciclo de clock. de Para coordenar a transmissão de dados entre o emissor e o receptor. os barramentos síncronos não podem ser longos se forem rápidos (veja Apêndice C). Como o protocolo é predeterminado e envolve pouca lógica. Isso significa que o barramento inclui barramento síncrono Um um clock nas linhas de controle e um protocolo fixo para comunicação que é relativo barramento que inclui um clock nas linhas de controle e um protocolo ao clock. e aquele conectado a ele é o hub controlador de E/S. O protocolo é implementado com um coordenar as transferências em conjunto adicional de linhas de controle. A linha de uso intencionado indica se ele foi projetado para ser usado com cabos externos ao computador ou apenas dentro do computador. memória e dispositivos de E/S 471 FIGURA 6. A bridge norte é basicamente um controlador de DMA. usando as linhas de controle para indicar o tipo de solicitação. chamado de bridge sul. Todos os exemplos da Figura 6. O chip próximo ao processador é o hub controlador da memória. normalmente chamado bridge norte. Esses problemas levaram a interconexões assíncronas. Segundo. Um protocolo de handshaking consis. os barra- mentos síncronos possuem duas grandes desvantagens.9 mostra o sistema de E/S de um PC tradicional.8  Principais características dos cinco padrões de barramento de E/S dominantes. A memória poderia então precisar responder com a palavra de dados no quinto clock. um protocolo de handshaking para coordenar o uso. com cabos curtos ou fio nas placas de circuito impresso. e a lógica da interface será pequena. Por não interconexão assíncrona Utiliza terem clock. que não utilizam clock. conectando o processador à memória. A Figura 6. as interconexões assíncronas podem acomodar uma grande variedade de dis. de modo que muitas publicações dobram a largura de banda por pista. temos de definir os protocolos de hardware e software a fim de controlar as transferências de dados entre os dispositivos de E/S e a memória. A Figura 6. um número cada vez maior de con- troladoras de E/S. poderá dobrar a largura de banda por link para PCIe. a bridge norte a diversos barramentos de E/S. Visto que a Lei de Moore continua a vigorar. e de modo que o processador especifique comandos aos dispositivos de E/S. Quais das seguintes afirmações são verda- você mesmo deiras: 1. Verifique Redes e barramentos conectam componentes. têm sido incorporadas por esses chip sets.472 Capítulo 6  Armazenamento e outros tópicos de E/S FIGURA 6. o AMD Opteron X4 e o Intel Nehalem incluem a bridge norte dentro do microprocessador.9). 2. que antes estavam disponíveis como placas opcionais conectadas aos barramentos de E/S. Por exemplo.9  Organização do sistema de E/S em um servidor Intel usando o chip set Intel 5000P. Acima desse nível básico. Essas interconexões de E/S oferecem conectividade elétrica entre os dispositivos de E/S.10 mostra três exemplos dos chip sets. pulando uma travessia de chip. Observe que a AMD engoliu o chip da bridge norte no Opteron e outros produtos. . e o chip da bridge sul do Intel 975 inclui uma controladora RAID (ver Seção 6. As redes e os barramentos de E/S são quase sempre padronizados. NVIDIA e outros fabricantes oferecem uma grande variedade de chip sets para conectar o processador ao mundo exterior. e também definem o protocolo de mais baixo nível para a comunicação. Se você considerar que leituras e escritas são metade do tráfego cada. Esses assuntos serão abordados na próxima seção. A Intel. As redes e os barramentos de E/S são quase sempre síncronos. reduzindo assim a quantidade de chips e a latência até a memória e placas gráficas. AMD. processadores e memória. Interface dos dispositivos de E/S com 6. memória e sistema operacional 473 FIGURA 6.6  processador. 2. Os sistemas de E/S normalmente usam interrupções (exceções geradas externamente) para comunicar informações sobre operações de E/S. o sistema operacional desempenha um papel importante no tratamento da E/S. pois estão no Intel Nehalem mais recente. Observe que as funções da bridge norte estão incluídas no microprocessador AMD. Isso ainda deixa várias outras tarefas que precisam ser realizadas para realmente fazer com que os dados sejam transferidos de um dispositivo para o espaço de endereçamento da memória de algum programa de usuário. Esta seção focaliza essas tarefas e responde a perguntas como estas: j Como uma solicitação de E/S de um usuário é transformada em um comando de dispositivo e comunicada ao dispositivo? j Como os dados são realmente transferidos de ou para um local da memória? j Qual é o papel do sistema operacional? Como veremos na resposta a essas perguntas.10  Dois chip sets de E/S da Intel e um da AMD. memória e sistema operacional Um protocolo de barramento ou de rede define como uma palavra ou bloco de dados devem ser comunicados em um conjunto de fios. Diversos programas usando o processador compartilham o sistema de E/S.6  Interface dos dispositivos de E/S com processador. atuando como interface entre o hardware e o programa que solicita a E/S. 6. Como as interrupções causam . As responsabilidades do sistema operacional surgem de três características dos sistemas de E/S: 1. Os dados precisam ser transferidos entre a memória e um dispositivo de E/S. registra os dados e os transmite . O controlador de dispositivos. 3. o sistema de memória ignora a operação. Em um sistema com dispositivos de E/S compartilhados. Para realizar essas funções em favor dos programas de usuário. vê a operação. Por exemplo. a proteção não poderia ser fornecida se os programas de usuário pudessem realizar E/S diretamente. pois exige o gerencia- mento de um conjunto de eventos simultâneos e porque os requisitos para o controle correto do dispositivo normalmente são muito detalhados Interface As três características dos sistemas de E/S anteriores levam a diversas funções diferentes que o sistema operacional precisa oferecer: hardware/ software j O sistema operacional garante que o programa de um usuário acessa apenas as partes de um dispositivo de E/S para as quais o usuário possui direitos. como uma busca em um disco. Esses comandos incluem não apenas operações como ler e escrever. atribuídas a dispositivos de E/S e leituras e escritas para esses Por exemplo. em que os dados serão interpretados como um comando. 2. O dispositivo precisa ser capaz de notificar o sistema operacional quando o dispositi- vo de E/S tiver completado uma operação ou tiver encontrado um erro. Leituras do espaço de endereçamento são e escritas para esses endereços são interpretadas como comandos aos dispositivos de E/S. Dois métodos são usados para ende- E/S mapeada em memória Um reçar o dispositivo: E/S mapeada em memória e instruções de E/S especiais. elas precisam ser tratadas pelo sis- tema operacional (SO). O controle de baixo nível de um dispositivo de E/S é complexo. Dando comandos a dispositivos de E/S Para dar um comando a um dispositivo de E/S. partes do espaço de endereçamento são atribuídas a dispositivos de E/S. assim como trata as exceções geradas por um programa. ele notificará o sistema operacional. coloca o endereço e os dados no barramento da memória.474 Capítulo 6  Armazenamento e outros tópicos de E/S uma transferência ao modo kernel ou supervisor. quando um disco completar uma busca. 3. o processador precisa ser capaz de endereçar o dispositivo e fornecer uma ou mais palavras de comando. Na E/S mapeada esquema de E/S em que partes em memória. Quando o processador comandos aos dispositivos de E/S. j O sistema operacional tenta oferecer acesso equilibrado aos recursos de E/S. Nas próximas seções. porém. além de escalonar acessos a fim de melhorar a vazão do sistema. o bloco sendo lido em uma leitura de disco precisa ser movido do disco para a memória. o sistema operacional não pode permitir que um programa leia ou escreva num arquivo no disco se o proprietário do arquivo não tiver acesso a esse programa. mas também outras operações a serem feitas no dispositivo. veremos como essas comunicações são realizadas. O sistema operacional precisa ser capaz de dar comandos aos dispositivos de E/S. Por exemplo. Por exemplo. j O sistema operacional oferece abstrações para acessar dispositivos fornecendo rotinas que tratam as operações de baixo nível dos dispositivos. porque o endereço indica uma parte do espaço de memória usado para E/S. j O sistema operacional trata as interrupções geradas pelos dispositivos de E/S. uma operação de escrita pode ser usada para enviar dados a um dispositivo endereços são interpretadas como de E/S. Três tipos de comunicação são necessários: 1. o sistema operacional precisa ser capaz de se comunicar com os dispositivos de E/S e impedir que o programa do usuário se comunique com os dispositivos de E/S diretamente. O dispositivo utiliza o endereço para determinar o tipo de comando. esperar até que a impressora ligue o bit pronto antes que possa colocar outro caractere no buffer. fazer uma leitura ou escrita de dados para cumprir uma solicitação do pro- grama normalmente exige várias operações de E/S separadas. A desvantagem do polling é que ele pode desperdiçar muito tempo de processador. O comando real pode ser transmitido pelas linhas de dados do barramento. O polling pode ser usado de várias maneiras diferentes. Além do mais. Como veremos. e um bit de erro. O processador está totalmente no controle e realiza todo o trabalho. emprega interrupções de E/S para indicar interrupção  Um esquema de E/S que emprega interrupções ao processador que um dispositivo de E/S precisa de atenção. Quando o dispositivo completar uma operação. e os dados podem ser fornecidos por uma escrita ou obtidos por uma leitura. os endereços são protegidos pela tradução de endereços. isso permite que o polling seja usado mesmo quando a taxa de E/S é um pouco maior. Os programas de usuário são impedidos de realizar operações de E/S diretamente. Essas instruções de E/S podem especificar o número do dispositivo e a palavra dedicada. usada para dar um de comando (ou o local da palavra de comando na memória). O registrador de status contém um bit de pronto. Tornando as instruções de E/S ilegais para serem executas quando fora do modo kernel ou su- pervisor. usada por quase todos E/S controlada por os sistemas pelo menos para alguns dispositivos. O processador precisa. e o processador deve vir e a necessidade de atender ao apanhar a informação. O processador também precisa verificar o bit de erro para determinar se houve um problema. A E/S controlada por interrupção. escrevendo ou lendo para selecionar endereços. Quando um dispositivo para indicar ao processador que deseja notificar o processador de que completou alguma operação ou que precisa de um dispositivo de E/S precisa de atenção. Cada byte de dados a ser impresso é colocado no registrador de dados. o que é útil para tempo real. memória e sistema operacional 475 ao dispositivo como um comando. O processador pode ler o registrador de status muitas vezes. uma simples impressora possui dois registradores de dispositivo de E/S – um para informações de status e um para dados a serem impressos. Detalhamento:  A alternativa à E/S mapeada em memória é usar instruções de E/S dedicadas instrução de E/S  Uma instrução no processador. na memória). Por exemplo. com duas distinções importantes: . ligado pela impressora quando ela tiver impresso um caractere. Uma interrupção de E/S é exatamente como as exceções vistas nos Capítulos 4 e 5. O polling é a forma polling  O processo de verificar mais simples para um dispositivo de E/S se comunicar com o processador. então. indicando que a impressora está com papel preso ou sem papel. o endereço codifica a identidade do dispositivo e o tipo de transmissão entre o processador e o dispositivo. é chamado de polling. isso faz com que o processador seja interrompido. O processador comunica o endere. pois o sistema operacional não oferece acesso ao espaço de endereçamento atribuído aos dispositivos de E/S e. ainda teremos de ler o status para determinar se ele teve sucesso. para descobrir que o dispositivo não completou uma operação de E/S comparativamente lenta. 6. os programas de usuário são impedidos de acessar os dispositivos diretamente. o processador pode ter de interrogar o status do dispositivo entre comandos individuais para determinar se o comando foi concluído com sucesso. dispositivo. Comunicação com o processador O processo de verificar periodicamente os bits de status para ver se é hora da próxima operação de E/S. como no exemplo anterior. levando à invenção de interrupções para notificar o processador quando um dispositivo de E/S exigir atenção do processador. ou que o mouse não saiu do lugar desde a última vez em que foi sondado. atenção. Cada uma dessas operações exige um acesso separado ao dispositivo de E/S. comando a um dispositivo de E/S e que especifica o número do ço do dispositivo por meio de um conjunto de fios normalmente incluídos como parte do barra- dispositivo e a palavra de comando mento de E/S. As aplicações embutidas de tempo real sondam os dispositivos de E/S porque as taxas de E/S são predeterminadas e isso torna o overhead da E/S mais previsível. (ou o local da palavra de comando Exemplos de computadores com instruções de E/S são os computadores Intel x86 e o IBM 370. Na realidade. O dispositivo de periodicamente o status de um dispositivo de E/S para determinar E/S simplesmente coloca a informação no registrador de status. A E/S mapeada em memória também pode ser usada para transmitir dados. O overhead em uma interface de polling foi reconhecido há muito tempo. pois os processadores são muito mais rápidos do que os dispositivos de E/S. Em qualquer evento. assim.6  Interface dos dispositivos de E/S com processador. e a Seção B. com dispositivos de alta velocidade associados às prioridades mais altas. em vez disso. Ou seja. Quando ocorre uma interrupção. Além do mais. em geral. . ele sabe a identidade do dis- positivo que causou a interrupção e pode interrogar imediatamente o dispositivo. Se o bit Inter- rupções habilitadas for 0. Essas prioridades indicam a ordem em que o processador deverá processar interrupções. quando o sistema operacional adquire o controle. Para dar suporte a níveis de prioridade para interrupções. permite que o processador seja focalizado nos programas em execução. Um mecanismo de interrupção elimina a necessidade de o processador sondar o dispositivo e. A arquitetura MIPS I mais antiga tinha três conjuntos aninhados de bits kernel/usuário e de bits de habilitação de interrupções para dar suporte a interrupções aninhadas. Como resultado. Uma interrupção de E/S é assíncrona com relação à execução da instrução.11  Os registradores Cause e Status.11 mostra os principais registradores. Pode haver várias prioridades de interrupção de E/S. um sistema pode usar interrupções vetorizadas ou um registrador de causa da exceção. de modo semelhante ao modo como o MIPS trata de falhas de TLB. Essa versão do registrador Cause corresponde à arquitetura MIPS-32.7 no Apêndice B contém mais detalhes sobre esses registradores. Isso é muito diferente de quaisquer exceções de falta de página ou exceções como overflow aritmético. Um bloqueio de interrupções mais refinado está disponível no campo de máscara de interrupções. as interrupções de E/S possuem prioridade menor do que as exceções internas. A Seção B. 2. a interrupção não é associada a qualquer instrução e não impede o término da ins- trução. é preciso haver um 1 no campo de máscara no bit dessa posição. Para habilitar a interrupção correspondente. gostaríamos de transmitir in- formações adicionais. Exceções geradas internamente e interrupções de E/S externas pos- suem prioridades. sistemas operacionais UNIX utilizam de quatro a seis níveis. como a identidade do dispositivo que gera a interrupção. as interrupções representam dispositivos que podem ter diferentes prioridades e cujas solicitações de interrupção possuem diferentes urgências associadas a elas. o MIPS oferece as primitivas que deixam o sistema operacional implementar a política. Quando o processador reconhece a interrupção. O registrador Status determina quem pode interromper o computador. o dispositivo pode enviar o endereço do vetor ou um campo de status para colocar no registrador de causa. Existe um bit na más- cara correspondente a cada bit no campo interrupções pendentes do registrador Cause. Níveis de prioridade de interrupção Para lidar com as diferentes prioridades dos dispositivos de E/S. A Figura 6. a maioria dos mecanismos de interrupção possui vários níveis de prioridade. como a identidade do dispositivo gerando a interrupção. Nossa unidade de controle só precisa verificar uma in- terrupção de E/S pendente no momento em que iniciar uma nova instrução. então ninguém poderá interromper. o sistema operacional pode encontrar o FIGURA 6. Além do fato de que uma interrupção de E/S ocorreu.476 Capítulo 6  Armazenamento e outros tópicos de E/S 1. Para comunicar informações ao processador.7 no Apêndice B oferece mais detalhes. Levantar e reduzir o IPL envolve mudanças no campo de máscara de interrupção do registrador Status. Entretanto. todas as interrupções são bloqueadas. 6. No IPL mais baixo. Podemos usar o processador para transferir dados entre um dispositivo e a memória com base no polling. Como os níveis de prioridade de interrupção (IPL – Interrupt Priority Levels) corres- pondem a esses mecanismos? O IPL é uma invenção do sistema operacional. Essas duas técnicas – polling e interrupções de E/S – formam a base para dois métodos de implementação da transferência de dados entre o dispositivo de E/S e a memória. São feitas cópias desses dois registradores usando a instrução mfc0 . Detalhamento:  Os dois bits menos significativos dos campos interrupções pendentes e máscara de interrupções são para interrupções de software. 7. Realize um AND lógico entre o campo interrupções pendentes e o campo máscara de interrupções para ver quais interrupções ativas poderiam ser as culpadas. Um outro mecanismo é fazer a transferência de dados controlada por interrupção. e cada processo recebe um IPL. Selecione a prioridade mais alta dessas interrupções. Nesse caso. veremos um outro mais adequado para dispositivos de maior desempenho ou coleções de dispositivos. A convenção do software é que a mais à esquerda seja a prioridade mais alta. 5. 8. Essas duas técnicas funcionam melhor com dispositivos de menor largura de banda. Salve o campo de máscara de interrupções do registrador Status. O Apêndice B mostra um handler de exceções para uma tarefa de E/S simples. 2. no IPL mais alto. A fim de permitir interrupções de prioridade mais alta. como a operação de E/S é controlada por interrupção. o sistema operacional simplesmente atua sobre outras tarefas enquanto os dados estão sendo lidos ou escritos no dispositivo. o processador carrega dados dos regis- tradores do dispositivo de E/S e os armazena na memória. coloque o bit interrupções habilitadas do registrador Cause em 1. memória e sistema operacional 477 motivo no campo de código de exceção do registrador Status: 0 significa que uma interrupção ocorreu. ele lê o status para verificar a ocorrência de erros. Em aplicações de tempo real. Aqui estão as etapas que precisam ocorrer no tratamento de uma exceção: 1. Ao contrário. . Depois de examinar esses dois esquemas. 3. Antes de restaurar o estado. Ele é ar- mazenado na memória do processo. o sistema operacional ainda transferiria dados em pequenos números de bytes de ou para o dispositivo. Eles normalmente são usados por interrupções de prioridade mais alta para deixar trabalho para interrupções de menor prioridade realizarem depois que o motivo imediato da interrupção for tratado. com outros valores para as exceções mencionadas no Capítulo 5. 4. Salve o estado do processador necessário para lidar com a interrupção. Isso permite restaurar o campo de máscara de interrupções. 6. nos quais estamos mais interessados em reduzir o custo do controlador de dis- positivo e interface do que oferecer uma transferência com largura de banda alta. Quando a interrupção de maior prioridade terminar. Chame a rotina de interrupção apropriada. que são de prioridade inferior. Se não houver. Quando o sistema operacional reconhece uma interrupção a partir do dispositivo.6  Interface dos dispositivos de E/S com processador. Transferindo os dados entre um dispositivo e a memória Vimos dois métodos diferentes que permitem que um dispositivo se comunique com o processador. as tarefas de prioridade inferior serão observadas e tratadas. todas as interrupções são permitidas. Tanto o polling quanto as transferências controladas por interrupção colocam o trabalho de mover dados e gerenciar a transferência sob a responsabilidade do processador. coloque o bit interrupções habilitadas do registrador Cause em 0. Mude o campo de máscara de interrupções para desativar todas as interrupções de prioridade igual ou inferior. a operação a realizar no dispositivo. O DMA inicia a operação no dispositivo e arbitra o acesso à interconexão. por uma sequência de escritas mapeadas em memória. O processador configura o DMA fornecendo a identidade do dispositivo. Usando esse mecanismo. O (DMA)  Um mecanismo que mecanismo de interrupção ainda é usado pelo dispositivo para a comunicação com o proces- oferece a um controlador de sador. os projetistas de computadores inventaram um mecanismo para desafogar o processador e fazer com que o controlador de dispositivo transfira dados diretamente de ou para a memória sem envolver o processador. O programa pode estar armazenado no processador de E/S. Para dispositivos com alta largura de banda. 2. o endereço de memória que é a origem ou o destino dos dados a serem transferidos e o número de bytes a transferir. por exemplo. o overhead ainda poderia ser intolerável. Naturalmente. Quando o último byte de uma solicitação de E/S tiver sido transmitido e a operação de E/S for concluída. Muitos controladores de DMA contêm alguma memória para permitir que eles tratem de modo flexível atrasos na transferência ou aqueles ocorridos na espera para se tornar o master. Por exemplo. interrogando o dispositivo de DMA ou examinando a memória. como discos rígidos. Detalhamento:  Para reduzir ainda mais a necessidade de interromper o processador e ocupá-lo no tratamento de uma solicitação de E/S que possa envolver a realização de várias operações reais. chamadas de programa de E/S. torna-se o master e direciona as leituras e escritas entre si mesmo e a memória. Quando a transferência de DMA termina. acesso direto à memória Esse mecanismo é chamado de acesso direto à memória (DMA – Direct Memory Access). pois isso poderia consumir uma grande fração do processador quando o disco estivesse transferindo. se usássemos esse método para transferir dados de ou para um disco rígido. Ao contrário do polling ou da E/S controlada por interrupção. 1. Esses processadores especializados executam uma série de operações de E/S. acessando o dispositivo e a memória para cada item de dados transferido. Usando caches. Assim. O controlador de DMA processador. que transfere dados entre memória ou para ela sem envolver o um dispositivo de E/S e a memória. as transferências consistem principalmente em blocos de dados relativamente grandes (centenas a milhares de bytes). ele transfere os dados. o controlador de E/S pode se tornar mais inteligente. o sistema operacional normalmente configura um programa de E/S que . Quando os dados estão disponíveis (do dispositivo ou da memória). Existem master  Uma unidade na três etapas em uma transferência de DMA: interconexão E/S que pode iniciar requisições de transferência. embora. independente do processador. sem incomodar o processador. a unidade de DMA pode completar uma transferência inteira. que pode então determinar. O dispositivo de DMA fornece o endereço de memória para a leitura ou a escrita. 3. o processador pode evitar ter de acessar a memória na maior parte do tempo. o DMA pode ser usado para realizar interface de um disco rígido sem consumir todos os ciclos de processador para uma única E/S. a unidade de DMA gera o próximo endereço de memória e inicia a próxima transferência. que pode ter milhares de bytes de tamanho. o sistema operacional poderá informar ao programa. mas somente no término da transferência de E/S ou quando ocorre um erro. A E/S controlada por interrupção libera o processador de ter de esperar por cada evento de E/S. Se a solicitação exigir mais de uma transferência. cada controlador de barramento de E/S normalmente terá um processador de DMA que trata de quaisquer transferências entre um dispositivo no barramento de E/S e a memória.478 Capítulo 6  Armazenamento e outros tópicos de E/S o sistema operacional poderá fornecer a próxima parte dos dados. em um sistema com um único barramento processador-memória e vários barramentos de E/S. O processador e o sistema operacional realizam todo o trabalho nesse processo. Ao usar um processador de E/S. ou pode estar armazenado na memória e ser buscado pelo processador de E/S. dispositivo a capacidade de transferir dados diretamente da O DMA é implementado com um controlador especializado. se o processador também estiver brigando pela memória. deixando assim a maior parte da largura de banda da memória livre para uso por dispositivos de E/S. Pode haver vários dispositivos de DMA em um sistema de computador. se a operação inteira foi concluída com sucesso. ele será atrasado quando a memória estiver ocupada realizando uma transferência de DMA. Controladores inteligentes normalmente são chamados de processadores de E/S (bem como controladores de E/S ou con- troladores de canal). o controlador interrompe o processador. Esses métodos têm a vantagem de liberar os ciclos do processador. ou problema de coerência (veja Capítulo 5). a ordem é polling. determinado sistema computacional pode escolher qual ponto nesse espectro é apropriado para os dispositivos de E/S se conectarem a ele. hardware/ cipal com o uso de um endereço físico em uma transferência de DMA é que a transferên. DMA e E/S controlada por interrupção. 6. Os processadores de DMA são processadores de uso especial (normalmente. Se uma solicitação de E/S cruzas- se um limite de página. vejamos rapidamente as medidas de desempenho deles na próxima seção. o valor de um local de memória visto pela unidade de DMA e pelo processador pode ser diferente. Como o processador de DMA realiza solicitações de memória diretamente à memória. Ao passar do polling para uma E/S controlada por interrupção e para uma interface de DMA. Acesso direto à memória e o sistema de memória Quando o DMA é incorporado a um sistema de E/S. Nesse sistema. Esses problemas normalmente são solucionados com uma combinação de técnicas de hardware e suporte do software. Vimos três métodos diferentes para transferir dados entre um dispositivo de E/S e a memória. além do tamanho e do endereço de transferência para quaisquer leituras ou escritas. quais afirmações são verdadeiras? Verifique você mesmo 1. busca as operações do pro- grama de E/S e interrompe o processador apenas quando o programa inteiro estiver completo. pois pode haver duas cópias de um item de dados: uma na cache e uma na memória. então os locais de memória para os quais ela estava sendo transferida não necessariamente seriam contíguos na memória virtual. Com DMA. Em termos de menor impacto na utilização do processador a partir de um único dispositivo de E/S. enquanto os processadores de E/S normalmente são implementados com microprocessadores de uso geral. Um método para permitir que o sistema inicie transferências de DMA que cruzam limites de página é fazer com que o DMA funcione em endereços virtuais. Se quisermos a menor latência para uma operação de E/S a um único dispositivo de E/S. O DMA também cria problemas para sistemas com caches. O processador de E/S. que executam um programa de E/S especializado. E/S controlada por interrupção e polling. Consequentemen- te. Essa diferença gera alguns problemas nos sistemas de memória virtual e em sis- temas com caches. Na avaliação das três maneiras de realizar E/S.6  Interface dos dispositivos de E/S com processador. de único chip e não programáveis). o DMA deverá funcionar com endereços virtuais Interface ou com endereços físicos? O problema óbvio com os endereços virtuais é que a unidade de DMA precisará traduzir os endereços virtuais em endereços físicos. 2. todos os acessos ao sistema de memória vêm do processador e. Antes de discutirmos o projeto dos sistemas de E/S. Sem DMA. As dificuldades de ter DMA em um sistema de memória virtual surgem porque as páginas possuem um endereço físico e um endereço virtual. e não pela cache do processador. Se alguns dos locais em que o DMA escreve estiverem na cache. existe outro caminho para o sistema de memória – que não passa pelo mecanismo de tradução de endereços ou pela hierarquia de cache. e o valor não foi escrito de volta. se a cache for write-back. o DMA poderá ler um valor diretamente da memória quando um valor mais novo estiver na cache. Considere uma leitura do disco que a unidade de DMA coloque diretamente na memória. a ordem é DMA. memória e sistema operacional 479 indica as operações de E/S a serem realizadas. se usarmos endereços físicos. a unidade . o relacionamento entre o sistema de memória e o processador muda. o processador receberá o valor antigo quando fizer uma leitura. prosseguem pela tradução de endereços e acesso à cache como se o processador gerasse as referências. software cia não pode cruzar com facilidade um limite de página. mudamos o peso do gerenciamento de uma operação de E/S do proces- sador para um controlador de E/S progressivamente mais inteligente. assim. O problema prin. Isso é chamado de problema de dados antigos. Por causa disso. De modo semelhante. Sua desvantagem é que eles aumentam o custo do sistema de E/S. então. Em um sistema com memória virtual. teremos de restringir todas as transferências de DMA para permanecerem dentro de uma página. provavelmente levando a uma variação maior no tempo de resposta. que executa a sequência inteira de transferências. Nesta seção. A invalidação do hardware para garantir coerência da cache é comum em sistemas multiprocessador. então. discutimos esse assunto com detalhes no Capítulo 5. a unidade de DMA não precisa se preocupar com o local das páginas virtuais envolvidas na transferência. damos alguns exemplos de medidas propostas para determinar o desempe- nho dos sistemas de disco. como alternativa. software O roteamento de toda a E/S pela cache é dispendioso e possui um grande impacto potencial negativo no desempenho do processador. como os discos são conectados. o sistema de memória. cada uma confinada dentro de uma única página física. Interface O problema de coerência para dados de E/S é evitado pelo uso de uma de três técnicas im- portantes. ele será relativamente pouco frequente. pois os dados de E/S raramente são usados de imediato e podem deslocar dados úteis de que um programa em execução precisa. Medidas de desempenho de E/S: exemplos 6. porque o de- sempenho da E/S depende de muitos aspectos do sistema e diferentes aplicações enfatizam diferentes aspectos do sistema de E/S. Antes de discutirmos esses benchmarks. precisamos explicar um ponto confuso sobre terminologia e unidades. Essa técnica exige uma pequena quantidade de suporte do hardware e provavelmente é mais eficiente se o software puder realizar a função de forma fácil e eficiente. alguns benchmarks restringem o tempo de resposta máximo a qualquer solicitação. Outra técnica é que o sistema operacional divida a transferência de DMA em uma série de transferências. o processador e o sistema de arquivos fornecido pelo sistema operacional. podemos aumentar a vazão em um disco agrupando solicitações que acessam locais próximos. embora uma vazão maior possa ser alcançada se tentarmos lidar com solicitações relacionadas juntas. tornando tais otimizações potencialmente problemáticas. Usando esse mapeamento. As trans- ferências. Embora a vazão seja maior. o sistema operacional ainda precisa cooperar não remapeando as páginas enquanto uma transferência de DMA que envolve essa página estiver em andamento. Uma técnica é rotear a atividade de E/S por meio da cache. A terceira técnica é oferecer um mecanismo de hardware para fazer o flush (ou invalidar) seletivamente às entradas de cache. O desempenho dos sistemas de E/S depende da velocidade em . Essa política aumentará o tempo de resposta para algumas solicitações. tornando impossível medir apenas um aspecto isoladamente. e a mesma técnica pode ser usada para E/S.7  de sistemas de disco e de arquivos Como devemos comparar sistemas de E/S? Essa é uma pergunta complexa. Como esse flush de grandes partes da cache só precisa acontecer nos acessos em bloco ao DMA. Além do mais. incluindo tecnologia de disco. um projeto pode fazer escolhas com- plexas entre tempo de resposta e vazão. tratar um pedido o mais cedo possível em geral minimiza o tempo de resposta. são encadeadas e entregues a um processador de E/S ou unidade de DMA inteligente. Por exemplo. Esses benchmarks são afetados por uma variedade de recursos do sistema. Qualquer que seja o método utilizado. O sistema operacional provê o mapeamento quando a E/S for iniciada. De acordo com isso. Uma se- gunda opção é ter o sistema operacional invalidando a cache seletivamente para uma leitura de E/S ou forçar a ocorrência de write-backs para uma escrita de E/S (normalmente chamado de flush de cache). Isso garante que as hardware/ leituras vejam o valor mais recente enquanto as escritas atualizam quaisquer dados na cache. o sistema operacional pode solicitar as transferências individualmente.480 Capítulo 6  Armazenamento e outros tópicos de E/S de DMA possui um pequeno número de entradas de mapa que oferecem mapeamento virtual para físico para uma transferência. Ilustramos esse erro na Seção 6. porque muitos acessos à E/S são para blocos de dados que possuem um tamanho que é uma potência de dois. ele testa o desempenho do sistema de E/S. o custo do sistema para um sistema de benchmark também precisa ser incluído. A velocidade de transferência depende da velocidade do clock.073. A taxa de transferência normalmente é cotada em GB/seg. Por exemplo. Diversos benchmarks de processamento de transações foram desenvolvidos. Além do Um tipo de aplicação que envolve o tratamento de pequenas mais.000. entre elas: garantir que as transações não são perdidas. em que a base 2 é utilizada (ou seja.12. . Benchmarks de E/S para sistema de arquivos e para Web Além de benchmarks de processador. Essas aplicações são muito críticas e sensíveis ao custo. convertendo com precisão uma das duas medidas. segundo.741. O TPC-H modela o apoio à decisão ocasional – as consultas não são relacionadas. O conjunto taxa de dados  Medida de mais conhecido de benchmarks é uma série desenvolvida pelo Transaction Processing desempenho de bytes por unidade Council (TPC). que simula a carga de trabalho de processamento de transações de uma firma de corretagem. de modo que o desempenho da vazão é medido apenas quando o limite do tempo de resposta é atendido. Além disso. Todos os benchmarks de TCP medem o desempenho em transações por segundo. Ele exercita o sistema de banco de dados e também o software básico do servidor Web.000.000 bytes). o tempo de respos.org. transações) que normalmente ao contrário da taxa de dados.tpc.824). taxa de E/S  A medida de desempenho das E/Ss por unidade bilidade em face da falha seja um requisito absoluto em tais sistemas. como leituras por ta e a vazão são fundamentais para criar sistemas econômicos. 1GB = 230 = 1. mas com requisitos importantes de tempo de resposta. Embora a confia. além do processador. essa diferença gera a necessidade de conversão entre a base 10 (1K = 1000) e a base 2 (1K = 1024). O TPC-W é um benchmark de aplicações baseadas na Web. que simula as atividades de um servidor Web transacional orientado a negócios. que normalmente é dada em GHz = 109 ciclos por segundo. de tempo. além de clientes postando dados ao servidor (veja Capítulo 1). tratar das transações rapidamente e minimizar o custo do processamento de cada transação. Finalmente. Os benchmarks TPC são descritos em www. SPECWeb é um benchmark de servidor Web que simula vários clientes solicitando páginas estáticas e dinâmicas de um servidor. tanto em termos de usuários quanto o tamanho do banco de dados ao qual as transações são aplicadas. o resultado é que os tempos de execução da consulta podem ser muito longos. o SPEC oferece um benchmark de servidor de arquivos (SPECSFS) e um benchmark de servidor Web (SPECWeb). características. Por causa disso. as velocidades de transação mais altas também estão associadas a sistemas maiores. as aplicações de TP tratam operações curtas (chamadas principalmente da taxa de E/S. de tempo. a maioria dos acessos de E/S é pequena. O TPC-App é um benchmark de servidor de aplicações e Web services. medida como o número de acessos ao disco por segundo. diferente da memória principal. O SPECSFS é um benchmark destinado a medir o desempenho do NFS (Network File System) usando um script de solicitações para servidores de arquivos. Benchmarks de E/S de processamento de transações Aplicações de processamento de transações (TP – Transaction Processing) envolvem um processamento de transações  requisito de tempo de resposta e uma medida de desempenho baseada na vazão. Além de aumentar a confusão. Para modelar sistemas do mundo real. Em vez de complicar todos os nossos exemplos. como GB/segundo O TPC-C. com o sistema As aplicações de processamento de atendendo a alguns requisitos de tempo de resposta e tratando de forma controlada certos transações normalmente possuem requisitos de tempo de resposta tipos de falhas. a capacidade de armazenamento precisa se expandir com o desempenho. Nos sistemas de E/S. os e uma medida de desempenho bancos normalmente utilizam sistemas de TP porque se preocupam com uma série de baseada na vazão das transações. SPECSFS é um benchmark orientado a vazão. 1GB = 109 = 1. GBs são medidos usando a base 10 (ou seja. medida como bytes de dados por segundo. 6. simula um ambiente de consulta complexo. incluindo disco e rede. ressaltamos aqui essa distinção e o fato de que tratar as duas medidas como se as unidades fossem idênticas produz um pequeno erro. e o conhecimento de consultas passadas não pode ser usado para otimizar futuras consultas. de TP geralmente envolvem mudanças em um banco de dados grande. eles incluem um requisito de tempo de resposta. inicialmente criado em 1992. As aplicações exigem tanto E/S quanto cálculo. permitindo comparações precisas de custo-desempenho.7  Medidas de desempenho de E/S: exemplos de sistemas de disco e de arquivos 481 que o sistema transfere dados. Logo. O mais recente é o TPC-E. Dependendo da carga de trabalho. As restrições de latência envolvem garantir que a latência para completar uma operação de E/S esteja limitada por uma certa quantidade. 4. em vez da latência. Faremos uma análise simples do sistema de E/S do servidor Sun Fire x4150 na Seção 6. 2.8  Projetando um sistema de E/S Existem dois tipos principais de especificação que os projetistas encontram nos sistemas de E/S: restrições de latência e restrições de largura de banda. determinar a latência de um sistema não carregado é relativamente fácil. Em vez de uma carga de trabalho padrão. Verifique As seguintes afirmativas são verdadeiras ou falsas? Ao contrário dos benchmarks de você mesmo processador. para mostrar como essa metodologia funciona. podem exigir que os dados definam a escala em tamanho ou número de usuários para conseguir os marcos de desempenho.10. nos controladores de E/S ou nos dispositivos. Encontrar o elo mais fraco no sistema de E/S. O modo mais fácil de entender essa metodologia é com um exemplo. existem exemplos de cinco cargas de trabalho que têm como finalidade simular aplicações comuns de sistemas de arquivos. Porém. concentram-se na vazão. 6. pois isso é fundamental para a aplicação ou porque o dispositivo precisa receber certo serviço garantido que impeça erros. Como alternativa. normalmente relatam o desempenho em termos de custo. o conhecimento do padrão de tráfego afeta o projeto e a análise. A técnica geral para projetar tal sistema é a seguinte: 1. que é o componente no caminho da E/S que restringirá o projeto. ele oferece uma linguagem que lhe permite descrever a carga de trabalho que você gostaria de executar nos seus sistemas de arquivos. um framework de benchmark do sistema de arquivos. Esse último problema de projeto é uma versão simplificada do primeiro. Da mesma forma.482 Capítulo 6  Armazenamento e outros tópicos de E/S O esforço SPEC mais recente é para medir a potência. os benchmarks de E/S: 1. o projetista pode receber um sistema de E/S parcialmente configurado e ser solicitado a balancear o sistema para manter a largura de banda máxima alcançável conforme ditado pela parte pré-configurada do sistema. Os dois tópicos estão além do escopo deste texto. incluindo nos processadores. o sistema pode ser descarregado. esse componente pode estar em qualquer lugar. Encontrar a latência média (ou a distribuição da latência) sob uma carga é um problema muito mais complexo. O SPECPower mede as caracterís- ticas de potência e desempenho de pequenos servidores. Esses problemas são resolvidos ou por teoria de filas (quando o comportamento das solicitações da carga de trabalho e os tempos de atendimento de E/S podem ser aproximados por distribuições simples) ou por simulação (quando o compor- tamento dos eventos de E/S é complexo). Nos dois casos. No caso simples. Os limites da carga de trabalho e de configuração podem ditar onde está localizado o elo mais fraco. 3. 2. 3. Configurar esse componente para sustentar a largura de banda exigida. Determinar os requisitos para o restante do sistema e configurá-los para dar suporte a essa largura de banda. A Sun recentemente anunciou o filebench. pois envolve rastrear o caminho da operação de E/S e somar as latências individuais. Projetar um sistema de E/S para atender a um conjunto de restrições de largura de banda dado uma carga de trabalho é o outro problema comum que os projetistas enfrentam. . e o projetista também precisa garantir que algum limite de latência seja realizado. o armazenamento em alto desempenho preferido eram discos grandes e dispendiosos.9  of Inexpensive Disks (RAID) A lei de Amdahl no Capítulo 1 nos lembra que é precipitado negligenciar a E/S nessa revolução paralela. a revolução paralela precisa chegar à E/S e também ao cálculo. dos quais 90 segundos é tempo de CPU e o restante é tempo de E/S. ou o esforço gasto paralelizando poderia ser gasto sempre que programas realizam E/S. Suponha EXEMPLO que o número de processadores dobre a cada dois anos. e o tempo de E/S não melhora. Essa passagem é uma boa escolha para processadores múltiplos . Acelerar o desempenho de E/S foi a motivação original dos arrays de disco (veja Seção 6. Logo. o que todos eles precisam fazer. No final dos anos 1980. mas os processadores per- manecem na mesma velocidade. a melhoria no tempo decorrido é de apenas 100 = 4‚7 21 e o tempo de E/S aumentou de 10% para 47% do tempo decorrido. o desempenho melhoria porque haveria mais cabeças de leitura. Um exemplo simples demonstra isso.14 no site). O argumento foi que.9  Paralelismo e E/S: Redundant Arrays of Inexpensive Disks (RAID) 483 Paralelismo e E/S: Redundant Arrays 6. como os maiores na Figura 6. Impacto da E/S sobre o desempenho do sistema Suponha que tenhamos um benchmark executado em 100 segundos de tempo de- corrido. subs- tituindo alguns discos grandes por muitos discos pequenos. O quanto mais rá- pido nosso programa será executado ao final de seis anos? Sabemos que Tempodecorrido = tempodeCPU + tempode E/S RESPOSTA 100 = 90 + tempode E/S Tempode E/S = 10 segundos Os novos tempos de CPU e os tempos decorridos resultantes são calculados na tabela a seguir. Após n anos Tempo de CPU Tempo de E/S Tempo decorrido % de tempo de E/S 0 ano 90 segundos 10 segundos 100 segundos 10% 2 anos 90 10 segundos 55 segundos 18% = 45 segundos 2 4 anos 45 10 segundos 33 segundos 31% = 23 segundos 2 6 anos 23 10 segundos 21 segundos 47% = 11 segundos 2 A melhoria no desempenho da CPU após seis anos é 90 =8 11 Porém. 6.4. poderia haver vantagens no custo.14 explicam a diferença entre RAID 3. a confiabilidade organização de discos que usa um array de discos pequenos e baratos foi o principal motivo para a popularidade geral do RAID. a taxa de falha subiria por um fator de pelo menos 50! A solução foi acrescentar redundância de modo que o sistema pudesse lidar com as falhas de disco sem perder informações. os autores numeraram os estágios do RAID. abreviado como RAID. mais importante que isso. Assim. FIGURA 6. A revolução paralela destacou para aumentar o desempenho e a a questão do desempenho original do RAID. As Figuras 6. substituindo uma única unidade por. mostrando discos de verificação extras por nível de RAID e empresas que utilizam cada nível. na potência e no espaço. De quanta redundância você precisa? Você precisa de informações extras para encon- trar as falhas? Importa como você organiza os dados e as informações de verificação extra nesses discos? O artigo que criou o termo deu uma resposta evolutiva a essas questões. confiabilidade e seus impactos sobre custo e desempenho. e eles ainda são usados hoje. Tendo muitos discos pequenos. O restante desta seção analisa as opções para confiabilidade.12  RAID para um exemplo de quatro discos de dados. Além do desempenho mais alto. A Figura 6. pois muitas cabeças de leitura/escrita significam que o sistema de armazenamento poderia dar suporte a muito mais acessos independentes. RAID 4 e RAID 5. Essa observação levou ao seu nome: array redundan- RAID (RedundantArrays te de discos pouco dispendiosos. Essas unidades menores e menos dispendiosas tinham menores valores de MTTF que as unidades grandes. pois discos menores geralmente são mais eficientes por gigabyte do que discos maiores.13 e 6.484 Capítulo 6  Armazenamento e outros tópicos de E/S também. começando com a solução mais simples. Para acompa- nhar a evolução. digamos. o custo da redun- dância extra para melhorar a confiabilidade é pequeno em relação a solução com alguns discos grandes. embora sua invenção fosse motivada pelo desempenho. . a confiabilidade era mais econômica se você construísse um array redundante de discos mais baratos. porém. porém mais dispendiosa. você poderia conseguir altas taxas de E/S por segundo e altas taxas de transferência de dados. of Inexpensive Disks) Uma Em retrospecto. Ou seja. 50 unidades pequenas.12 mostra a evolução e um exemplo de custo no número de discos de verificação extras. A falha no argumento foi que os arrays de disco poderiam tornar a confiabilidade muito pior. e também transferências grandes se espalhariam por muitos discos. 13. o sistema simples- mente vai ao “espelho” e lê seu conteúdo para obter a informação desejada. chamado espelhamento ou shado. Uma “escrita pequena” exigiria a . Pode parecer que cada escrita pequena exigiria que todos os outros discos fossem acessados para ler o restante das informações necessárias no recálculo da nova paridade. Paridade é um esquema desse tipo. Os leitores não acostumados com a paridade podem pensar no disco redundante como aquele com a soma de todos os dados dos outros discos. então você subtrai todos os dados nos discos bons do disco de paridade. espelhamento  Escrever dados wing. O espelhamen- to é a solução de RAID mais dispendiosa. No contexto do RAID. desempenho do que um único disco to do armazenamento. e RAID 0 normalmente está listado como uma das opções. chamado striping. A paridade é armazenada como blocos e associada a um conjunto de blocos de dados. mas gastar menos com armazenamento redundante. discos de dados ou blocos que compartilham um disco ou bloco taurar a informação perdida em uma falha. 6. permitindo que acessos independentes ocorram em paralelo. por exem- plo. Em RAID 3. normalmente repartem seus dados e podem não se preocupar com a confiabilidade tanto quanto. esses dados também são gravados em um disco redundante. algumas aplicações preferem acessos menores. striping  Alocação de blocos camente os acessos a vários discos. como multimídia e alguns códigos científicos. só precisamos acrescentar informações redundantes suficientes para res. um acesso pequeno vai para apenas um disco em um grupo de proteção. que simplifica o gerenciamen. força automati.9  Paralelismo e E/S: Redundant Arrays of Inexpensive Disks (RAID) 485 Nenhuma redundância (RAID 0) O simples espalhamento dos dados por vários discos. Como a informação de detecção de erro em cada setor é verificada nas leituras para ver se os dados estão corretos. como na Figura 6. RAID 3 é comum em aplicações com grandes conjuntos de dados. não iremos descrevê-lo aqui. para dos em um disco. que sempre existem duas cópias da informação. Em vez de ter uma cópia completa dos dados originais grupo de proteção  O grupo de para cada disco. muitos discos precisam ser lidos para determinar os dados que faltam. com um disco extra para manter as informações de verificação caso haja uma falha. desde que o acesso mínimo seja de um setor. mas eles acessam dados de formas diferentes. a informação restante deverá ser a informação que falta. A suposição por trás dessa técnica é a de que levar mais tempo para recuperar-se de uma falha. Leituras ou escritas vão para todos os discos de verificação comum. enquanto um acesso grande vai para todos os discos em um grupo de proteção. RAID 0 é um nome errado. cada acesso ia para todos os discos. Logo. Entretanto. muitos discos podem operar ao mesmo tempo. utiliza o dobro da quantidade de discos do RAID 0. Como RAID 2 caiu em desuso. pois não existe redundância. Isso também melhora o desempenho para acessos grandes. Se um disco falhar. Paridade intercalada por bloco (RAID 4) RAID 4 usa a mesma razão de discos de dados e discos de verificação do RAID 3. pois exige mais discos. Espelhamento (RAID 1) Esse esquema tradicional para tolerar falhas de disco. os níveis de RAID normalmente são deixados para o operador definir ao criar um sistema de armazenamento. digamos. Diferente de RAID 1. idênticos em vários discos. essas “leituras pequenas” a cada disco podem ocorrer de forma independente. Contudo. O striping por um conjunto de discos faz com que a logicamente sequenciais por discos separados para permitir maior coleção apareça ao software como um único disco grande. pois pode oferecer. As escritas são outro problema. Os sistemas de edição de vídeo. os bancos de dados. Sempre que os dados são grava. de modo aumentar a disponibilidade dos dados. o termo RAID 0 tornou-se muito utilizado. Quando um disco falha. Essa é a finalidade do RAID níveis 4 a 6. Código de detecção e correção de erros (RAID 2) RAID 2 utiliza um esquema de detecção e correção de erros que é mais utilizado para me- mórias (veja Apêndice C). onde n é o número de discos em um grupo de proteção. no grupo. é uma boa escolha. A paridade é simples- mente a soma módulo dois. Paridade intercalada por bit (RAID 3) O custo da disponibilidade mais alta pode ser reduzido para 1/n. de modo que não haja um único gargalo para escritas. comparar os dados antigos com os novos para ver quais bits mudam. e também permite escritas pequenas. Aumentar o tamanho do grupo de paridade aumenta as economias do atalho. a paridade associada a cada linha de blocos de dados não é mais restrita a um único disco. escritas grandes e leituras pequenas. em vez de acessar todos os discos. em RAID 5. P’). a informação de paridade pode ser es- palhada por todos os discos. desde que os blocos de paridade não estejam localizados no mesmo disco. A organização da paridade distribuída é RAID 5. Esse exemplo substitui três leituras de disco (D1. O ingênuo cálculo de paridade do RAID 4 à esquerda da figura lê os blocos D1. você lê a paridade antiga P e depois muda os bits correspondentes para formar P’. Temos de ler os dados antigos do disco sendo escrito. de modo que o disco de paridade é o gargalo para escritas back-to-back. que envolvem apenas dois discos. Em seguida. a pequena escrita envolve quatro acessos de disco a dois discos. ocupando assim o primeiro e terceiro discos. leitura dos dados antigos e da paridade antiga. ambas no quinto disco.13 mostra o atalho. Por exemplo.486 Capítulo 6  Armazenamento e outros tópicos de E/S FIGURA 6. ler a paridade antiga. P) e duas escritas de disco (D0’. RAID 5 utiliza o mesmo atalho. Como vemos na organização da direita. Essa organização é RAID 4. adicionando as novas informações e depois escrevendo a nova paridade no disco de paridade e os novos dados no disco de dados. bem como a quantidade de discos ocupados. que é um gargalo. A função lógica OR exclusivo faz exatamente o que queremos. D3) e duas escritas (D0’. alterar os bits correspondentes. (Caso você esteja questionando. O lado direito da Figura 6. Essa organização permite que várias escritas ocorram simultaneamente.13  Pequena atualização de escrita em RAID 4. acessa o segundo e quarto discos e. P’) envolvendo todos os discos para duas leituras de disco (D0. os novos dados D0’ vêm diretamente da CPU. D2. D2 e D3 antes de acrescentar o bloco D0’ para calcular a nova paridade P’.) O atalho RAID 4 à direita lê o valor antigo D0 e o compara com o novo valor D0’ para ver quais bits mudarão. A Figura 6. Essa figura considera que temos quatro blocos de dados e um bloco de paridade. Essa otimização para pequenas escritas reduz a quantidade de acessos ao disco.14 mostra como os dados são distribuídos no RAID 4 versus RAID 5. uma escrita no bloco 8 à direita também precisa acessar seu bloco de paridade P2. Paridade distribuída intercalada por bloco (RAID 5) RAID 4 aceita de forma eficiente uma mistura de leituras grandes. Para resolver o gargalo da escrita de paridade. Assim. implicando uma atualização no seu bloco de paridade P1. Quando uma correção de única falha não é suficiente. Uma segunda escrita no bloco 5. A ideia principal para reduzir esse overhead é que a paridade é simplesmente uma soma de informações. observando quais bits mudam quando escrevemos as novas informações. assim. a paridade pode ser generalizada . Essas mesmas escritas na organização à esquerda resultam em mudanças nos blocos P1 e P2. depois escrever os novos dados e a nova paridade. Uma desvantagem para o sistema é que o disco de paridade precisa ser atualizado em cada escrita. à direita. Redundância P + Q (RAID 6) Os esquemas baseados em paridade protegem contra uma única falha autoidentificável. poderia ocorrer simultaneamente com a escrita no bloco 8. de modo que os discos não estão envolvidos na sua leitura. só precisamos mudar os bits correspondentes no disco de paridade. pois tal dano devido ao ambiente provavelmente aconteceria em todos os discos no array. Segun. Embora os fabricantes de disco citem um MTTF muito alto para seus produtos.13 também funciona. Resumo de RAID RAID 1 e RAID 5 são bastante utilizados em servidores. o overhead do armazenamento é o dobro daquele do RAID 5. de modo que ocasionalmente poderão remover um disco bom no lugar do disco com defeito. existem questões sobre como a tecnologia de disco muda com o tempo. maiores as chances de outra falha que causará perda de dados. Distribuindo os blocos de paridade a todos os discos. Primeiro. a largura de banda do disco está crescendo mais lentamente que a capacidade do disco.14  Paridade intercalada por bloco (RAID 4) versus paridade distribuída intercalada por bloco (RAID 5). então. em componente defeituoso. uma construção ou uma instalação de rack ineficaz. o que. Se um array de disco em particular tiver sido sujeito a ciclos de temperatura devido a. em vez de quatro para atualizar as informações de P e Q. última análise. Como mostra a Figura 6. determina quais discos devem ser removidos. para evitar tornar os dados indisponíveis durante o reparo. mas o hot swapping de discos hot swapping  Substituição de um impõe demandas sobre o projeto físico e elétrico do array e as interfaces de disco. esses números estão sob condições nominais. Assim. do. para ter um segundo cálculo sobre os dados e outro disco de verificação de informações. as taxas de falha podem ser de três a seis vezes maior (veja a falácia pos- teriormente neste capítulo). Perceba que um operador humano que. os operadores são apenas humanos. um disco SATA de 1000GB . 6. Por exemplo. Além de projetar o sistema RAID para reparo. mas as falhas poderiam estar correlacionadas. digamos. RAIDs possuem redundância suficiente para permitir a operação contínua.9  Paralelismo e E/S: Redundant Arrays of Inexpensive Disks (RAID) 487 FIGURA 6. Esse segundo bloco de verificação permite a recuperação de uma segunda falha. exceto que agora existem seis acessos a disco. de modo que os dados podem reservas em standby Recursos ser reconstruídos imediatamente na descoberta da falha. Um ponto fraco dos sistemas RAID é o reparo. O operador pode. aumenta as chances de uma segunda falha. outra falha poderia ocorrer durante o reparo. Outro problema é que. componente de hardware enquanto o sistema está em execução. ocasionando uma falha de disco irrecuperável. de modo que o tempo de reparo afeta as chances de perder dados: quanto maior for o tempo de reparo. subs. a falha do sistema de ar-condicionado. algumas escritas pequenas podem ser realizadas em paralelo.3. O atalho de escrita pequena da Figura 6. por sua vez. alguns sistemas incluem reservas em standby. uma estimativa é de que 80% de discos nos servidores se encontrem em algum sistema RAID. O cálculo de confiabilidade RAID considera independência entre falhas de disco. Em vez de ter de esperar que o operador traga um disco bom. o array precisa ser designado de modo a permitir que os discos que falharam sejam substituídos sem ter de desligar o sistema. de hardware de reserva que podem imediatamente tomar o lugar de um tituir os discos que falharam sem tanta pressa. o tempo para reparo de um disco em um sistema RAID está aumentando. ou a sacudidas devido a um projeto. a própria aplicação faz cópias redundantes e é responsável por mantê-las coerentes e recuperar-se de falhas. mundos virtuais e outros. Você criaria quatro pares de discos – cada um organizado como RAID 1 – e depois faria striping dos dados nos quatro pares RAID 1? Como alternativa. Em vez do modelo tradicional do software vendido em um CD ou entregue pela Internet para ser instalado no seu compu- tador. Outros argumentos para preocupação com múltiplas falhas simultâneas são o aumento do número de discos nos arrays e o uso de discos SATA. Para grandes escritas. sem considerar interferência. processamento de documentos. estamos vendo uma revolução no modo como o software é entregue. que são mais lentos e têm maior capacidade que os discos tradicionais para empresa. e tornar essa unidade inteira o bloco de montagem. Para contornar ques- tões sobre confiabilidade. Ou seja. uma versão comum é incluir discos com o processador e a memória. Logo. quatro discos de dados para armazenar e oito discos físicos para usar. além dos aspectos tradicionais do custo e desempenho. RAID 3 (paridade intercalada por bit) possui a pior vazão. armazenamento de banco de dados. você criaria dois conjuntos de quatro discos – cada um organizado como RAID 0 – e depois espelharia as escritas nos dois conjuntos RAID 0? A terminologia RAID evoluiu para chamar o primeiro de RAID 1 + 0. ou RAID 10 (“espelhos com striping”) e o segundo de RAID 0 + 1 ou RAID 01 (“striping espelhado”). Dado que o RAID danificado provavelmente continuará a atender com dados. essas tendências levaram a um interesse cada vez maior na proteção contra mais de uma falha. RAID 1 (espelhamento) possui o mais alto overhead de disco de verificação. o RAID 6 está cada vez mais sendo oferecido como uma opção e sendo usado no setor. a recons- trução poderia ser bastante esticada. Como deverão ser os computadores se eles forem projetados para serem colocados nesses grandes centros de dados? Certamente não é preciso que todos tenham monitores e teclados. Suponha que você tivesse. digamos. outro problema é que a leitura de muito mais dados durante a reconstrução significa aumentar a chance de uma falha irrecuperável de leitura de mídia. Claramente.488 Capítulo 6  Armazenamento e outros tópicos de E/S poderia levar quase três horas para ser lido sequencialmente.10   Vida real: servidor Sun Fire x4150 Além da revolução no modo como os microprocessadores são construídos. a alternativa é o software como um serviço. portanto.000 deles em um centro de dados. O exemplo mais comum provavelmente seja a pesquisa na Web. que resultaria em perda de dados. 5 e 6? você mesmo 1. . mas existem serviços para edição e armazenamento de foto. 4 e 5 possuem a mesma vazão. 6. Verifique Quais das seguintes afirmações são verdadeiras sobre os níveis RAID 1. RAID 3. A questão relacionada é: como deverá ser o armazenamento em um centro de dados? Embora existam muitas opções. 4. Detalhamento:  Uma questão é como o espelhamento interage com o striping. 3. você vai à Internet para realizar seu trabalho em um computador que roda o software que você deseja usar para fornecer o serviço desejado. 3. Se você procurar. a eficiência no espaço e a eficiência na energia serão importantes se você tiver 10. Além de aumentar esse tempo. 2. Essa mudança levou à construção de grandes centros de dados para manter computa- dores e discos executando os serviços utilizados por milhões de usuários externos. prova- velmente poderá encontrar uma versão de serviço de quase todo programa que utiliza no seu computador desktop. 4. Os sistemas RAID contam com a redundância para conseguir a alta disponibilidade. e. Para pequenas escritas. ualberta.php. especificamente o rack utilizado para manter os computadores no centro de dados.45cm). O mais comum é o rack de 19 pole- gadas (48cm) de largura. o menor computador para montagem em rack é de 48cm de largura e 4. Este rack tem 42 servidores “caixa de pizza” 1U. Logo. Fonte: http://gchelpdesk.ca/news/07mar06/cbhd_news_07mar06. mas também são chamados de subrack ou sim- plesmente prateleira. O rack mais comum de 48cm tem 42 U de altura. Devido às suas dimensões. ou aproximadamente 187cm de altura. ou simplesmente unidade (U). Como o espaçamento tradicional entre os furos para conectar as prateleiras é de 1. que é 42 x 4. FIGURA 6. A Figura 6.10  Vida real: servidor Sun Fire x4150 489 A indústria de TI em grande parte concorda com alguns padrões no projeto físico dos computadores para o centro de dados. de montagem de rack. Os computadores projetados para o rack são chamados.45. 6.15  Um rack padrão de 48cm preenchido com 42 servidores 1U. preenchido com 42 servidores 1U. eles ganharam o apelido de caixas de pizza. normalmente chamados de computadores 1U ou servidores 1U.15 mostra um exemplo de um rack padrão. naturalmente. essa distância normalmente é chamada de unidade de rack. A profundidade da prateleira varia.75 polegadas (4. .45cm de altura. 35cm a 15. um exemplo de um servidor 1U. RAID 1. FIGURA 6.000 RPM.45cm de altura por 48cm de largura. espalhadas por 16 FBDIMMs de 4GB. No canto superior direito está um DVD e duas portas USB. j 3 portas PCI Express x8.66GHz.5 descreve os discos SAS no Sun Fire x4150. j 1 controlador RAID (admitindo RAID 0. .16  Frente e fundos do servidor 1U Sun Fire x4150. para permitir que o servidor continue operando apesar de falhas de um desses componentes. Para esclarecer o aviso sobre o projeto de um sistema de E/S na Seção 6. j 8 unidades de disco SAS de 73GB e 6. Ela tem fontes de alimentação e ventiladores redundantes.35cm podem ser substituídas da frente.9 e 6. j 64GB de DRAM DDR2-667. j 4 portas Ethernet 10/100/1000. As Figuras 6. RAID 5 e RAID 6). A figura de baixo rotula os itens na parte traseira do servidor. essa caixa 1U contém: j 8 processadores de 2.490 Capítulo 6  Armazenamento e outros tópicos de E/S A Figura 6.10 descrevem o chip set de E/S para o Intel 5345. j 4 portas USB 2. espalhados por dois soquetes (2 Intel Xeon 5345). As oito unidades de disco de 6.17 mostra a conectividade e larguras de banda dos chips da placa mãe. A Figura 6.0 externas e 1 interna. Configurado de forma máxima. As dimensões são 4. e a Figura 6.8.16 mostra o Sun Fire x4150. vamos realizar uma avaliação de desempenho simples para ver onde poderiam estar os gargalos de uma aplicação hipotética. j Cada processador sustenta 1 bilhão de instruções por segundo. Fonte: Figura 5 do “SUN FIRE™ X4150 AND X4450 SERVER ARCHITECTURE” (veja www. 6.000 instruções do usuário e 100. j O sistema operacional utiliza em média 100. de modo que RESPOSTA Taxa de E/S máxima de 1 processador = Taxa deexecuçãoda instrução 1 × 109 E/Ss = = 3‚333 Instruções por E/S (200 + 100) × 10 3 seg . Os três conectores PCIe permitem que placas x16 sejam conectadas. mas somente oferece oito pistas de largura de banda ao MCH. j A carga de trabalho consiste em leituras de 64KB. Cada E/S utiliza 200. Projeto do sistema de E/S Considere o seguinte sobre o Sun Fire x4150: EXEMPLO j O programa do usuário utiliza 200. Ache a taxa máxima de E/S sustentável para um Sun Fire x4150 totalmente carrega- do para leituras aleatórias e leituras sequenciais. Considere que as leituras sempre podem ser feitas em um disco ocioso.10  Vida real: servidor Sun Fire x4150 491 FIGURA 6.com/servers/x64/x4150/).sun. Vamos primeiro achar a taxa de E/S de um único processador.000 instruções do SO.17  Conexões lógicas e larguras de banda dos componentes no Sun Fire x4150.000 instruções por operação de E/S.000 instruções por operação de E/S. ignore conflitos de disco) e que o controlador RAID não é o gargalo. se houver um (ou seja. 000 leituras sequenciais por segundo. O link final na cadeia é o Front Side Bus que conecta o hub da bridge norte ao soquete Intel 5345. Na prática.333 IOPS. de modo que oito pistas podem realizar 2GB/segundo. O tempo por leitura aleatória de um único disco: Tempo por E / S nodisco = Busca + temporotacional + Tempode transferência 2‚9 64 KB = + 2‚0 ms + = 3‚3ms 4 ms 112 MB/seg Assim. muitas dessas simplificações poderiam não ser mantidas para aplicações críticas com uso intenso de E/S. vamos supor que ele seja apenas um quarto desse tempo.540 Bytes por E/S 64 × 103 segundo Existe um Front Side Bus por soquete. e oito discos realizam 2424 leituras aleatórias por segundo. Para leituras sequenciais. Quando os dados chegam à MCB. Dois soquetes com oito processadores podem realizar 26. de modo que o pico FSB dual é mais de 150. A largura de banda de uma FBDIMM DDR2 de 667MHz é de 5336MB/segundo. ele pode realizar 13.667 IOPS. Cada E/S transfere 64KB. cada disco pode completar 1000ms/3. de modo que Largura de banda do barramento 5‚3 × 109 E/Ss Taxa máx. mas a Seção 7.5. Logo. um Sun Fire x4150 totalmente configurado pode sustentar a largura de banda de pico dos oito discos.000 IOPS. e mais uma vez. eles precisam ser escritos na DRAM. o FSB não é um gargalo.000 leituras sequenciais de 64KB. Precisamos ver se os caminhos dos discos para a memória e os processadores são um gargalo.492 Capítulo 6  Armazenamento e outros tópicos de E/S Como um único soquete Intel 5345 tem quatro processadores.3ms ou 303 E/Ss por segundo.10 lhe sugere não obter mais de metade do pico. Cada pista de uma PCIe é de 250MB/segundo. Vamos começar com a interconexão PCI Express da placa RAID para chip da bridge norte. como normalmente acontece (veja Seção 6. que é 2424 leituras aleatórias por segundo ou 14. Vamos determinar os IOPS por disco para leituras aleatórias e sequenciais para o disco SAS de 6. Por esse motivo. Sua largura de banda de pico é de 10. . isso é apenas o tempo de transferência dividido pela largura de banda do disco: 112 MB/seg = 1750IOPS 64 KB Oito discos podem realizar 14.6GB/seg.3). Em vez de usar o tempo médio de busca do fabricante de disco.35cm descrito na Figura 6. Uma única DIMM pode executar 5336 MB / seg = 83‚375IOPS 64 KB A memória não é um gargalo mesmo com uma DIMM. executar uma carga de trabalho realista ou benchmark relevante normalmente é a única forma plausível de avaliar o desempenho da E/S.E/SdoFSB = = = 81. e temos 16 em um Sun Fire x4150 totalmente configurado. Observe o número significativo de suposições de simplificação que são necessárias para realizar este exemplo. Largura de banda PCI 2 × 109 E / Ss Taxa de E / S máxima da PCIe x8 = = = 31‚250 Bytes por E / S 64 × 103 segundo Até mesmo oito discos transferindo sequencialmente utilizam menos de metade do link PCIe x8. RESPOSTA riores.5. esses novos centros de dados se preo- cupam com a potência e o espaço. Pelos cálculos ante. Essa carga de trabalho excede uma potência de processamento do único soquete Intel E5345.7. com um desmembramento por cada componente. uma única memória DIMM pode admitir mais de 80. então o pico de potência poderia ser diferente enquanto executando aplicações diferentes. FIGURA 6.000 IOPS. A memória mínima do Sun Fire x4150 é de duas DIMMs.4 a 1.6 a 1.18. de modo que também podemos reduzir o número de soquetes Intel E5345 por um. Fonte: www. Avaliação de potência do sistema de E/S Reconfigure um Sun Fire x4150 para minimizar a potência. O sistema original pode desempenhar 14. supondo que a carga de trabalho no exemplo anterior seja a única atividade nesse servidor 1U. de modo que podemos economizar a potência (e custo) de 14 DIMMs de 4GB. Ainda precisamos de todos os discos e da controladora de disco. a potência total do sistema agora é: Potência Ociosa leituras aleatórias = 154 + 2 × 10 + 8 × 8 + 15 = 253 watts Potência Pico leituras aleatórias = 215 + 2 × 11 + 8 × 8 + 15 = 316 watts ou uma redução na potência por um fator de 1.000 leituras sequenciais de 64KB por segundo.18 mostra a potência ociosa e de pico exigida por um Sun Fire x4150 totalmente configurado. de modo que podemos economizar potência na memória. Vejamos as configurações alternativas do Sun Fire x4150 para economizar energia.18  Potência de pico e idle do Sun Fire x4150 totalmente configurado.333 IOPS. . A Figura 6.10  Vida real: servidor Sun Fire x4150 493 Conforme mencionamos no início desta seção. Esses experimentos vieram enquanto executando SPECJBB com 29 configurações diferentes. e o mes- mo número de DIMMs pode tratar dessa carga mais alta. precisamos de todos os oito discos e da controladora PCI RAID.sun. Um único soquete pode admitir 13. de modo que precisamos acrescentar um segundo. 6. além do custo e do desempenho.com/servers/x64/x4150/calc. EXEMPLO Para conseguir as 2424 leituras aleatórias de 64KB por segundo do exemplo anterior. Usando os números na Figura 6. Potência Ociosa leituras sequenciais = 154 + 22 + 2 × 10 + 8 × 8 + 15 = 275 watts Potência Pico leituras sequenciais = 215 + 79 + 2 × 11 + 8 × 8 + 15 = 395 watts ou uma redução na potência por um fator de 1. como TCP/IP. chamada taxa anual de falha (AFR).6% das unidades em seu terceiro ano. Se você substituísse os discos que falharam por um novo com as mesmas características de confiabilidade. redes locais. . A reivindicação é que. Eles descobriram que AFRs de 2% a 4% são comuns.200.000. e contam a quantidade que falha. de modo que os discos praticamente nunca falham. incluindo interligação de redes. e depois continua substituindo o disco a cada cinco anos – o tempo de vida planejado do disco.73%. o modelo OSI. Falácia: uma interconexão de 1GB/seg pode transferir 1GB de dados em 1 segundo.7% das unidades em seu primeiro ano subirem para 8. ou cerca de 140 anos. se muitos clientes (e seus bisnetos) fizessem isso para o próximo século.11. redes de longa distância.8%.000 discos ATA. o número que falharia por ano (8.000 discos ATA e SCSI que tinham uma cotação de MTTF de 1.11.12  Falácias e armadilhas   Falácia: o tempo médio para falha indicado para discos é 1. os fabricantes colocam milhares de discos em uma sala. 2007]. como IEEE 802. diferente de outros dispositivos de E/S. oferece uma visão geral dos tópicos e da terminologia.000 horas ou quase 140 anos.800 horas. Falácia: as taxas de falha de disco em campo combinam com suas especificações.000 a 1. Para esse grande MTTF fazer algum sentido. ou AFR de 0. Um segundo estudo de mais de 100. que tinham um valor AFR de aproxi- madamente 1. existem muitos livros e cursos sobre elas.494 Capítulo 6  Armazenamento e outros tópicos de E/S 6.200.760 horas) é 1.11  Tópicos avançados: Redes   As redes estão ganhando mais popularidade com o passar do tempo e.760horas/unidade Discos falhos = = 7‚3 1. 6. e redes sem fio. viu taxas de falha de 1.000 horas.5%. ou cerca de cinco a seis vezes a taxa especifi- cada [Pinheiro. As práticas de marketing atuais dos fabricantes de disco podem enganar os usuários.200. Considere 1. na média eles substituiriam um disco 27 vezes antes de uma falha. Uma medida mais útil seria a porcentagem de discos que falham. Um problema é que esse número é muito superior ao tempo de vida de um disco. famílias de protocolos. Dois estudos recentes avaliaram grandes coleções de discos para verificar o relacionamen- to entre os resultados em campo comparados com as especificações. normalmente três a cinco vezes as taxas especificadas [Schroeder e Gibson. Como esse MTTF é calculado? No início do processo. no site. Weber e Barroso. a AFR é 0. os colocam para trabalhar por alguns meses. que normalmente é cinco anos ou 43.000 discos com um MTTF de 1. Para os leitores que não fizeram nenhum curso nem leram livros sobre redes.000 horas e que os discos sejam usados 24 horas por dia.000unidades × 8. Eles calculam o MTTF como o número total de horas que os discos estiveram acumuladamente ativos dividido pelo número que falhou. como Ethernet. Um estudo foi de quase 100. 2007]. como ATM. Os fabricantes de disco estão come- çando a citar a AFR além do MTTB para dar aos usuários uma melhor intuição sobre o que esperar a respeito de seus produtos. esses fabricantes argumentam que o cálculo corresponde a um usuário que compra um disco.6% a 0.500.000horas/falha Explicando de uma forma alternativa. a Seção 6. Você precisa de ambos para reparar. não é possível oferecer essa função questionada como um recurso do próprio sistema de comunicação.824 = = 1‚073741824 ≈ 1‚07 segundo 109 1. Portanto. Um caso frequente dessa falácia é o uso de interfaces de E/S inteligentes que. pode ter uma latência pior do que uma atividade de E/S controlada pelo processador (embora. mas não aponta onde se encontra o problema. adulterando. desde que a verifi- cação fim a fim esteja disponível. comparando as listagens em papel e reparando o código manualmente! Se as somas de verificação tivessem sido calculadas e verificadas pela aplicação rodando nos sistemas na ponta. quando usados de forma correta. Apanhando emprestado o conceito religioso da “roda da reencarnação”. a segurança teria sido garantida. Qual é o significado dessa distinção? Se pudéssemos usar 100% do barramento para a transferência de dados. Como consequência. uma quantidade pequena do tempo de processador principal é substituída por uma quantidade maior de tempo do processador de E/S. 1GB/seg = 109 bytes/ seg). Com o tempo. se o processador for liberado suficientemente.000. 1GB = 230 bytes). eles. o desempe- nho cai quando o processador de E/S tem um desempenho muito inferior ao do proces- sador principal. cada qual acrescentando uma soma de verificação de um gateway para o seguinte. Existem muitos exemplos dessa armadilha pegando as pessoas.073. você ficaria satisfeito em conseguir 70% a 80% da largura de banda de pico. a vazão do sistema ainda possa aumentar). embora os processadores de E/S. esperando melhorar o desempenho sem uma análise cuidadosa. Os projetistas de estações de trabalho têm visto esses dois fenômenos repetidamente. Armadilha: mover funções da CPU para o processador de E/S. 6. Ela pode mostrar que algo está errado entre dois nós. o código.7.000 Armadilha: tentar oferecer recursos apenas dentro da rede versus fim a fim. observaram que eram apanhados em . o código-fonte de um sistema operacional era repetidamente passado pelo gateway. o tempo para transferir 1GB de dados em uma interconexão de 1GB/seg seria. A única solução foi corrigir os arquivos-fonte infectados. a definição de um gigabyte de armazenamento e um gigabyte por segundo de largura de banda não correspondem. o tempo para confirmar os sinais e os atrasos enquanto se espera para usar um barramento ocupado estão entre os motivos para você não poder usar 100% de um barramento. as medidas de largura de banda de E/S normalmente são cotadas em base 10 (ou seja. O tempo para enviar o endereço. Os programadores da aplicação assumiram a precisão garantida pela soma de verificação. O problema é fornecer em um nível inferior recursos que só podem ser cumpridos no nível mais alto.000. dessa forma. por fim. Para um barramento. Conforme discutimos na Seção 6. Um gateway tinha uma falha intermitente que trocava um par de bytes para cada milhão de bytes transferidos. satisfazendo assim apenas parcialmente à demanda da comunicação. você em geral não pode usar 100% de qualquer recurso do computador. As verificações intermediárias podem descobrir qual componente está errado. Myer e Sutherland [1968] escreveram um artigo clássico sobre a escolha entre com- plexidade e desempenho nos controladores de E/S. Reed e Clark [1984] explicam o argumento de fim a fim como A função em questão só pode ser especificada completa e corretamente com o conhecimento e a ajuda da aplicação que fica nas extremidades do sistema de comunicação. devido ao maior overhead para configurar uma requisição de E/S. certamente podem melhorar o desempenho. acreditando in- corretamente que a mensagem estava protegida enquanto armazenada na memória de cada gateway. Saltzer. enquanto 1GB de dados normalmente é uma medida na base 2 (ou seja. na realidade. Constantemente. Segundo. existe uma função útil para verificações intermediárias. No entanto.12  Falácias e armadilhas 495 Primeiro. Seu exemplo da armadilha foi uma rede no MIT que usava vários gateways.741. 230 1. pois as inovações nos discos precisam ajudar as fitas. para fazer sentido economicamente. trilhas e superfícies. com alguns recursos gráficos especiais. portanto. oferecem endereços de bloco lógicos para o sistema operacional hospedeiro. como ATA e SCSI. as cabeças de disco só precisam ler os pratos embutidos. Nesse mesmo espaço de tempo. Hoje. por si só. possuem registros de realização recentes melhores do que a fita. Porém. permitindo um tempo de recuperação instantâneo. e essa vantagem explica por que os discos estão melhorando muito mais rapidamente. eles são um pequeno mercado para fitas. no passado. o maior mercado levou os discos a melhorarem muito mais rapidamente do que as fitas. 2003]: . suponha que a carga de trabalho seja quatro leituras [Anderson. Falácia: os sistemas operacionais são o melhor local para programar acessos ao disco. o processador de vídeo ficou semelhante a um computador completo. As fitas magnéticas têm feito parte dos sistemas de computador tanto quanto os discos.496 Capítulo 6  Armazenamento e outros tópicos de E/S um loop de aumentar continuamente a potência de um processador de E/S até que ele precisasse do seu próprio coprocessador mais simples: Enfrentamos a tarefa começando com um esquema simples e depois acrescentando co- mandos e recursos que achamos que melhorariam o poder da máquina. uma única fita magnética poderia manter o conteúdo de muitos discos. De modo que. Como os discos são sistemas fechados. Os locais são selecionados de modo que os desastres não prejudiquem os dois locais. mas replicam os dados em nível de aplicação por diferentes locais. Um motivo para o mercado ser pequeno é que os proprietários de desktop geralmente não fazem backup de discos em fita. e assim. isso é uma falácia e uma armadilha. enquanto os desktops são um grande mercado para discos. ele pode reduzir as latências de rotação e de busca pelo reescalonamento. A alegação foi de que as fitas magnéticas precisam acompanhar os discos. as leitoras de fita precisam ler ou escrever a geração atual e anterior de fitas e precisam ler as quatro últimas gerações de fitas. E depois aconteceu uma coisa estranha. o preço por gigabyte de discos ATA caiu para menos do que o das fitas. esse era um meio de backup útil. Dada essa abstração de alto nível. descobrimos que o processo era tão frustrante que passamos a chamá-lo de “roda da reencarnação”. Foi então que descobrimos a verdade perturbadora. Entre 2000 a 2002.3. Sentimo-nos compelidos a acrescentar ao processador um segundo processador subsidiário que. Gradualmente. A diferença de custo-desempenho histórica entre discos e fitas é baseada em um disco selado. pois utilizam tecnologia semelhante aos discos e. o melhor que um SO pode fazer para tentar ajudar no desempenho é clas- sificar os endereços lógicos de bloco em ordem crescente. Na verdade. mas os spools removíveis de fita magnética significam que muitas fitas podem ser usadas por leitora e que elas podem ser muito longas. como o disco conhece o mapeamento real dos endereços lógicos na geometria física de setores. Por exemplo. Mais uma vez. Essa alegação foi importante porque as fitas eram um pequeno mercado e não poderiam dispor de um grande esforço de pesquisa e desenvolvimento separado. de modo que possuem alta capacidade. Como dissemos na Seção 6. Armadilha: usar fitas magnéticas para o backup de discos. algumas organizações retiraram as fitas. (Um tempo de recuperação longo é outra desvantagem séria da natureza serial das fitas magnéticas. com menor tempo de acesso do que o acesso sequencial à fita. o processador [de vídeo] tornava-se mais complexo… Finalmente. mas esses dois estão recebendo um investimento muito maior e. Os defensores da fita agora alegam que elas possuem requisitos de compatibilidade que não são impostos sobre os discos. historicamente têm seguido as mesmas melhorias na densidade. muitas empresas oferecendo software como serviço utilizam componentes baratos. Na verdade. usando redes e discos remotos para re- plicar os dados geograficamente. Projetar um processador de vídeo pode se tornar um processo cíclico sem fim. interfaces de nível mais alto. o disco muito mais popular era maior do que a maior fita. rotativo. por isso. começou a aumentar em complexidade.) Essa solução depende dos avanços na capacidade do disco e na largura de banda da rede. e por ser de 10 a 100 vezes mais barata por gigabyte do que os discos. Infelizmente. O barramento PCI de 32 bits. A Lei de Amdahl também nos lembra que a vazão de um sistema de E/S será limitada pelo componente de menor desempenho no caminho de E/S. Na prática. é difícil sustentar mais do que cerca de 80MB/seg para sistemas de memória reais. a reordenação poderia tornar isso pior.12  Falácias e armadilhas 497 Operação LBA inicial Tamanho Leitura 724 8 Leitura 100 16 Leitura 9987 1 Leitura 26 128 O hospedeiro poderia reordenar as quatro leituras por ordem de bloco lógico: Operação LBA inicial Tamanho Leitura 26 128 Leitura 100 16 Leitura 724 8 Leitura 9987 1 Dependendo do local relativo dos dados no disco. FIGURA 6. 33MHz. possui uma largura de banda de pico de cerca de 133MB/seg. mas as leituras programadas pelo SO exigem três rotações. rotulados com “fila ordenada pelo hospedeiro” e “fila ordenada pela unidade”. o overhead do software para iniciar a comunicação é ignorado. até mesmo para transferências longas. enquanto o segundo as completa em apenas três quartos de uma rotação (de Anderson [2003]).19  Exemplo mostrando acessos programados pelo SO versus disco. Por exemplo.19. O primeiro leva três rotações para completar as quatro leituras. essas medidas de largura de banda de pico em geral são baseadas em suposições irrealistas sobre o sistema ou não são alcançáveis. As leituras programadas pelo disco terminam em três quartos de uma rotação do disco. Muitos dos componentes de um sistema de E/S. 6. cotando o desempenho do barramento. desde os dispositivos até os contro- ladores e barramentos. como mostra a Figura 6. . são especificados por meio de suas larguras de banda de pico. a velocidade de transferência de pico às vezes é especificada usando um sistema de memória impossível de criar. Na prática. devido a outras limitações do sistema. Armadilha: usar uma taxa de transferência de pico de uma parte do sistema de E/S para fazer projeções de desempenho ou comparações de desempenho. Para sistemas em rede. 6. exigem confiabilidade e capacidade dos seus sistemas de E/S. As direções futuras da E/S incluem expandir o alcance das redes com e sem fio. Esses objetivos levam a esquemas bastante variados para interface de dispositivos de E/S. Lembre-se de que. embora o desempenho possa ajudar a vender um sistema de E/S. da dos programas memória e do dispositivo determinam a velocidade de transferência máxima do disposi- tivo ou para o dispositivo. medidos tanto em latência quanto em vazão. Entendendo O desempenho de um sistema de E/S. em parte devido às demandas crescentes para que toda a informação esteja na ponta dos seus dedos. a va- riedade de dispositivos de E/S aceitos. devido às limitações no número de operações de E/S simultâneas que ele pode admitir. a redundância e os mecanismos de correção de erros tornam-se mais e mais prevalentes enquanto ampliamos o sistema. Em geral. 2003]. As demandas de armazenamento e rede estão crescendo em velocidades sem precedentes. com quase todo dispositivo potencialmente tendo um endereço IP. Uma estimativa é que a quantidade de informação criada em 2002 foi de 5 exabytes – equivalente a 500. e o custo pode ser secundário. os usuários. custo. e essa quantidade total de informações no mundo dobrou nos últimos três anos [Lyman e Varian. o DMA com buffer provavelmente será o mecanismo de transferência dominante. Em outros casos.13   Comentários finais Os sistemas de E/S são avaliados em diversas características diferentes: confiança. o número máximo de dispositivos de E/S. em sua maioria. a world wide web e como a ethernet continua a triunfar sobre seus desafiantes. bancos de dados.14  Perspectiva histórica e leitura adicional A história dos sistemas de E/S é fascinante. De modo semelhante. memória flash. A Seção 6. Nos sistemas inferiores e interme- diários.14 oferece um breve histórico dos discos magnéticos. depende de todos os elementos no caminho entre o dispositivo e a memória. o sistema operacional é um gargalo. a internet. RAID. Como resultado. e a expansão do papel da memória flash nos sistemas de armazenamento. ser capaz de acessar os dados em um dispositivo de E/S a qualquer tempo (alta disponibilidade) torna-se mais importante quando os sistemas crescem. Em alguns casos. e desempenho. Nos sistemas de alto nível. a latência depende da latência do dis- positivo. o sistema operacional leva muito tempo para entregar uma solicitação de E/S de um programa de usuário a um dispositivo de E/S. a latência e a largura de banda podem ser ambos importantes. A largura de banda efetiva e a latência de resposta também dependem de outras requisições de E/S que podem causar disputa por algum recurso no caminho.000 cópias do texto da Biblioteca do Congresso dos Estados Unidos –. seja ele medido por largura de banda ou latência. incluindo o o desempenho sistema operacional que gera os comandos de E/S. . A largura de banda da interconexão. le- vando a uma alta latência. Vários caminhos para dispositivos de E/S com buffer limitado normalmente caracterizam sistemas de E/S de alto nível. Finalmente. o sistema operacional efetivamente limita a largura de banda de E/S. junto com qualquer latência imposta pelo sistema de memória ou barramentos.498 Capítulo 6  Armazenamento e outros tópicos de E/S 6. calcule os valores relacionados ao tempo de leitura e escrita para discos com as caracterís- ticas a seguir.2. estime sua taxa de dados. Explore as classificações de dispositivo para os seguintes dispositivos: a. da Universidade do Kansas. 6.1. Explore esses conceitos respondendo às perguntas sobre dispositivos com as métricas a seguir. . ou seja.1.2.1. 1 Contribuição de Perry Alexander.1> Para as interfaces identificadas no problema anterior.2 [5] <6.1> Para as interfaces identificadas no problema anterior. Usando as técnicas do Capítulo 6.3 [5] <6. Termostato automatizado 6. determine se a taxa de dados ou a taxa de operação é a melhor medida do desempenho.2 descreve diversos dispositivos de E/S em termos de seu comportamento.1.2> O que acontece à disponibilidade quando o MTTR se aproxima de 0. 6. um dispositivo é difícil de reparar? Isso significa que o dispositivo tem baixa disponibilidade? Exercício 6.1> Em relação aos dispositivos listados na tabela. essas classificações normalmente não oferecem uma imagem completa do fluxo de dados dentro de um sistema.2> O que acontece com a disponibilidade quando o MTTR se torna muito alto. 3 anos 1 dia b.1.15 Exercícios 499 6.1 [5] <6. Piloto automático b.3 [5] <6. 6. 6. Exercício 6. identifique as interfaces de E/S e classifique-as em termos de seu comportamento e parceria.2 [5] <6.2> Calcule o MTBF para cada um dos dispositivos na tabela. 6. 6. 7 anos 3 dias 6.1. Essa situação é real? 6. MTTF MTTR a. 6. parceria e taxa de dados.2> Calcule a disponibilidade para cada um dos dispositivos na tabela.2 Mean Time Between Failures (MTBF).1 A Figura 6.1 [5] <6. 6.4 [5] <61.3 Os tempos médio e mínimo para ler e escrever nos dispositivos de armazenamento são medições comuns usadas para comparar dispositivos.2.2. Mean Time To Replacement (MTTR) e Mean Time To Failure (MTTF) são medidas úteis para avaliar a confiabilidade e a disponibilidade de um recurso de armazenamento. Porém. 6.15  Exercícios1    Exercício 6. 000 40 MBytes/s 200 MBits/s 6. 6. a.3.4> Cada aplicação se beneficiaria de uma unidade FLASH em es- tado sólido. Diferentes situações exigem diferentes métricas. Exercício 6.3> Para cada disco na tabela. 6.3> Calcule o tempo médio para ler ou escrever um setor de 1024 bytes de cada disco listado na tabela.3 [10] <6.3. Especificamente.500 Capítulo 6  Armazenamento e outros tópicos de E/S Tempo de busca RPM Taxa de transferência Taxa de transferência da médio de disco controladora a. aumentar a velocidade de rotação do disco melhora o desempenho do sistema dado que o MTTF diminui? Explique sua resposta. se você pudesse fazer uma melhoria em qualquer aspecto do disco. diminuir o tamanho do setor durante leituras e escritas melhoraria o desempenho? Explique sua resposta.5 A memória FLASH é um dos primeiros competidores verdadeiros para as unidades de disco tradicionais. 6.2.1 [10] <6.500 90 MBytes/s 100 MBits/s b. dado que o custo é um fator de projeto? 6. a.4. Explore as implicações da memória FLASH respondendo as perguntas sobre as aplicações a seguir. 6.1 [5] <6. 6.5.4> Ao passarmos para unidades de estado sólido construídas de memória FLASH.2.3. 6. 6.2.4> Cada aplicação seria imprópria para uma unidade FLASH no estado sólido. o que escolheria? Se não houver um fator dominante.3> Para cada aplicação. 6. 6.4. dado que o custo NÃO é um fator de projeto? . determine o fator dominante ao desempe- nho. 6.3 [5] <6.2. aumentar a velocidade de rotação de disco melhora o desempenho? Explique sua resposta. 6. 6.2.2.2. 6. Sistema de controle de aeronaves b. Exercício 6.3. explique por quê.2 [10] <6. 7 ms 10. o projeto do sistema de armazenamento requer consideração de cenários de uso e também de parâmetros de disco.3> Para cada aplicação. 6. 10 ms 7.2. Central telefônica 6.3 [10] <6. Central telefônica 6. 6. o que mudará sobre os tempos de leitura de disco considerando que a taxa de transferência de dados permanece constante? 6.2 [10] <6. Explore diferenças no modo como os sistemas de armazenamento devem ser avaliados respondendo as perguntas sobre as aplicações a seguir.4 No fim. 6.3> Calcule o tempo mínimo para ler ou escrever um setor de 2048 bytes de cada disco listado na tabela.5.3> Para cada aplicação. Sistema de controle de aeronaves b.3.2. Vamos tentar avaliar sistematicamente os sistemas de disco.4.1 [5] <6.3.2 [5] <6.5. 8 Entre os tipos de barramento mais comuns utilizados na prática atualmente estão Fire- Wire (IEEE 1394). dando-lhes diferentes características.6.5> Selecione um barramento apropriado (FireWire. 6.1 [10] <6.15 Exercícios 501 Exercício 6. PCI ou SATA) para os periféricos listados na tabela.2.4> Calcule o tempo mínimo para leitura ou escrita de um setor de 512 bytes para cada memória FLASH listada na tabela.3. Identifique o que o controlador de barramento faz e onde o controle se encontra fisicamente.4> Calcule o tempo médio para leitura ou escrita de um setor de 1024 bytes para cada memória FLASH listada na tabela. a.2 [10] <6. 100 MB/s 90 MB/s 6. USB.8 as principais características de cada barramento. eles são implementados de diferentes maneiras.) 6.2.7.6. Isso é inesperado? Que fatores causam isso? Exercício 6. Coprocessador Gráfico 6.3 [5] <6. a.2. USB.4> A Figura 6.3. Explore as diferenças res- pondendo as perguntas de desempenho sobre os periféricos a seguir.2 [20] <6.5> Qual seria o tipo de barramento mais apropriado (síncrono ou assín- crono) para tratar das comunicações entre uma CPU e os periféricos listados na tabela? 6.6 Explore a natureza da memória FLASH respondendo as perguntas relacionadas a desempe- nho para memórias FLASH com as características a seguir.1 [5] <6. 120 MB/s 100 MB/s b.5> Use os recursos on-line ou de biblioteca e resuma a estrutura de comu- nicação para cada tipo de barramento. 6.7. 6. Explore as diferentes estruturas de barramento respondendo as perguntas sobre os barramentos e os periféricos a seguir.8. Mouse b. 6.2 [5] <6.1 [5] <6.6. 6. 6.5> Que problemas os barramentos longos e síncronos causariam para as conexões entre uma CPU e os periféricos listados na tabela? 6.8. Scanner 6. 6.7 A E/S pode ser realizada sincrônica ou assincronicamente. 6. Impressora b.3 [5] <6. (Veja na Figura 6. Embora todos os quatro sejam assíncronos. .6 mostra que os tempos de acesso de leitura e escrita da memória FLASH aumentam à medida que a memória FLASH se torna maior. 6.7.3. Taxa de transferência de dados Taxa de transferência da controladora a. Explique por que o barramento selecionado é apropriado. PCI e SATA.5> Que problemas os barramentos assíncronos causariam para as conexões entre uma CPU e os periféricos listados na tabela? Exercício 6. Identifique os comandos e sua interação com o dispositivo.5> Explique as limitações de cada um dos tipos de barramento. tratamento de interrupção.9. 6.1 [5] <6.6> Para as aplicações listadas na tabela.502 Capítulo 6  Armazenamento e outros tópicos de E/S 6. mapeamento de memória e comandos especiais de E/S.9.10. Cada aplicação na tabela seria apro- priada para a comunicação usando as técnicas de polling? Explique.5 [5] <6. a. 6.2 [5] <6. Os registradores Cause e Status juntos oferecem informações sobre a causa da interrupção e o status do sistema de tratamento da interrupção. Explique por que essas limitações precisam ser levadas em consideração quando se usa o barramento. Exercício 6. 6. 6. Identifique os locais de memória reservados e esboce seu conteúdo.4 [10] <6.1 [5] <6. se o polling for impróprio.6> O que acontece se o bit “interrupt enable” do registrador Cause não for definido no tratamento de uma interrupção? Que valor é assumido pela máscara de interrupção para realizar a mesma coisa? .9.3 [15] <6. Termostato automatizado 6. Res- ponda as perguntas sobre a comunicação com subsistemas de E/S para as aplicações a seguir usando combinações dessas técnicas.6> Descreva a comunicação controlada por interrupção. explique as técnicas controladas por interrupção que poderiam ser usadas. a.3 [10] <6.6> Descreva o polling do dispositivo.9. Para cada aplicação na tabela.6> Priorize as interrupções a partir dos dispositivos listados em cada linha da tabela.2 [10] <6. Piloto automático b. 6.10.6> Esboce como uma interrupção de cada um dos dispositivos listados na tabela seria tratada. Por que as interrupções de baixa prioridade são desabilitadas? Por que o registrador Status é salvo antes de desabilitar as interrupções? 6.6 define um processo de oito etapas para tratar das interrupções.9 A comunicação com dispositivos de E/S é alcançada por meio de combinações de polling.10 A Seção 6. Controlador de dados Ethernet Controlador do Mouse Reiniciar b.3 [10] <6.8.6> Faz sentido definir os subsistemas de E/S que usam uma combinação de mapeamento de memória e comunicação controlada por comando? Explique sua resposta. Explore o tratamento da interrupção respondendo as perguntas sobre as seguintes combinações de interrupções.6> Para as aplicações listadas na tabela. esboce um projeto para os coman- dos implementando a comunicação controlada por comando.10.4 [5] <6. o registrador Status é salvo e tudo além da interrupção de mais alta prioridade é desabilitado.6> Quando uma interrupção é detectada. Controlador do Mouse Desligamento Superaquecimento 6. esboce um projeto de comunicação mapeada na memória.10.9. 6. Exercício 6. Chat on-line 6.3 [10] <6. a.12. Computações matemáticas b. evitando a CPU por completo? 6. o desempenho da E/S é medido melhor usando o número de transações processadas? .7> Para cada aplicação na tabela.12. Enquanto o número de transações processadas domina o desempenho em algumas situações. Explore as im- plicações do DMA respondendo as perguntas sobre os periféricos a seguir. Controlador do mouse b. Controlador da ethernet 6. mas aumenta a complexidade das implementações do sistema de memória. cada interrupção tem seu próprio vetor de interrupção. Explore a avaliação do desempenho de E/S respondendo as perguntas para as aplicações a seguir.15 Exercícios 503 6.11.6> Em algumas implementações de tratamento de interrupção. Qual dos periféricos na tabela poderia gerar esses problemas? Como eles podem ser evitados? Exercício 6.6> Descreva os problemas que poderiam ocorrer quando se mistura DMA e memória virtual.7> Para cada aplicação na tabela. Em vez de um registrador Cause. a vazão de dados domina em outras.6> Dos periféricos listados na tabela. uma in- terrupção causa um salto imediato para um vetor de interrupção.2 [10] <6.2 [10] <6. qual se beneficiaria com o DMA? Que critérios determinam se o DMA é apropriado? 6.10. 6.1 [10] <6. O mesmo sistema de interrupção de prioridade pode ser implementado usando essa técnica? Existe alguma vantagem nessa técnica? Exercício 6.6> Dos periféricos listados na tabela.1 [5] <6.12. o desempenho da E/S domina o de- sempenho do sistema? 6. em que cada interrupção define um bit.10.11.4 [5] <6.6> A maioria dos sistemas de tratamento de interrupção é implementada no sistema operacional.5 [5] <6. Isso pode agilizar bastante o desempenho dos periféricos.11 Direct Memory Access (DMA) permite que os dispositivos acessem a memória diretamente em vez de utilizar a CPU. qual poderia causar problemas de coerência com o conteúdo da cache? Que critérios determinam se as questões de coerência devem ser enfocadas? 6. Que suporte do hardware poderia ser acrescentado de modo a tornar o tratamento de interrupção mais eficiente? Compare sua solução com o suporte de hardware em potencial para as chamadas de função.3 [5] <6. 6. um periférico pode simplesmente se comunicar com a memória diretamente. o desempenho da E/S é medido melhor usando a vazão de dados brutos? 6.6 [5] <6.7> Para cada aplicação na tabela.11.11. a.6> A CPU abre mão do controle da memória quando o DMA está ativo? Por exemplo.12 A métrica para desempenho de E/S pode variar bastante de uma aplicação para ou- tra. Cada linha na tabela a seguir mostra os valores dos blocos de dados e paridade.9> RAID 0 utiliza o striping para forçar o acesso paralelo entre muitos discos.13 Os benchmarks desempenham um papel importante na avaliação e seleção de dispositivos periféricos. F245 7453 DD25 AABB FEFE FEFF . eles devem exibir propriedades semelhante àquelas experimentadas por um dispositivo em uso normal.2 [5] <6. um bloco de paridade está associado a uma coleção de blocos de dados. defina as características que um conjunto de benchmarks deve exibir quando se avaliar um subsistema de E/S? 6. a.14. Para que os benchmarks sejam úteis. O nome Redundant Arrays of Inexpensive Disks implica em várias coisas sobre arrays RAID que exploraremos no contexto das atividades a seguir.504 Capítulo 6  Armazenamento e outros tópicos de E/S 6.15 RAID 3.1 [10] <6. Para cada uma das atividades listadas na tabela.13. o striping ajudará a alcançar melhor seus objetivos? 6.13. a. RAID 1 ajudará a conseguir melhor seus objetivos? 6. 7453 AB9C AABB 0098 549C 2FFF b. RAID 4 e RAID 5 utilizam o sistema de paridade para proteger blocos de dados. RAID 3 oferece disponibilidade de dados mais alta.7> Faz sentido avaliar um subsistema de E/S fora do sistema maior do qual ele faz parte? Exercício 6.9> Assim como RAID 1. Chat on-line 6.14. Novo D0 D0 D1 D2 D3 P a.7> Existe algum relacionamento entre as medidas de desempenho dos dois problemas anteriores e escolher entre o uso da comunicação por polling ou controlada por interrupção? E a escolha entre usar E/S mapeada pela memória ou controlada por comando? Exercício 6. Computações matemáticas de alta perfomance b. Serviços de video on-line 6.3 [5] <6. Cada uma das aplicações listadas na tabela se beneficiaria de RAID 3 em vez de RAID 1? Exercício 6. Explique a escolha entre RAID 1 e RAID 3. Computações matemáticas b.13. Por que o striping melhora o desempenho do disco? Para cada uma das atividades listadas na tabela.7> Usando recursos on-line ou de biblioteca.2 [15] <6.14 RAID está entre as técnicas mais comuns de paralelismo e redundância nos sistemas de armazenamento. como a redundância usando discos pouco dispendiosos pode resultar em um sistema com MTBF inferior? Use a definição matemática do MTBF para explicar sua resposta.7> Para cada aplicação na tabela.4 [5] <6. Especificamente. Explore os benchmarks e a seleção de dispositivo respondendo as perguntas sobre as aplicações a seguir.3 [5] <6. Por que os benchmarks padrão ajudam? 6.1 [5] <6. identifique um conjunto de benchmarks padrão para aplicações na tabela.9> RAID 1 espelha dados entre vários discos. conforme descritos na Figura 6.13.12. Supondo que discos pouco dispendiosos possuem MTBF mais baixo que os discos dispendiosos.14. Ignore os conflitos de disco e suponha que a controladora RAID não seja o gargalo. 6.2 [10] <6. 6.9> RAID 3 ou RAID 4 é mais eficiente? Existem motivos para RAID 3 ser preferível a RAID 4? 6. fazendo suposições semelhantes onde for necessário. escolher entre as alternativas pode ser difícil.1 [10] <6. DIMM ou o Front Side Bus apresenta um gargalo de E/S. Exercício 6.8.1 [15] <6. 6. Explore o processo de encontrar e avaliar servidores respondendo as perguntas sobre a aplicação a seguir. 6. mas o consumo de energia está se tornando cada vez mais importante.16. Instruções de Instruções Carga Velocidade programa/ do SO/Operação de Trabalho do processador Operações de E/S de E/S (KB lidos) (Instruções/Segundo) a. Repita para as configurações de 16.000 200. identifique as características de runtime para o sistema operacional.000 64 2 bilhões b.9> Calcule a nova paridade P’ para RAID 4 para as linhas a e b da tabela.4 [5] <6.16.8.2 [10] <6.9> Calcule a nova paridade P’ para RAID 3 para as linhas a e b da tabela.17. 200.4 [5] <6.15 Exercícios 505 6.16 O aparecimento de servidores Web para e-commerce. Servidor de banco de dados 6.9> RAID 4 e RAID 5 utilizam aproximadamente o mesmo mecanismo para calcular e armazenar a paridade para blocos de dados.000 128 3 bilhões 6.5 [5] <6. 6.16.10> Suponha que estejamos configurando um servidor Sun Fire x4150 conforme descrito na Seção 6. 6. Porém. 6. 6.10> Determine se o barramento PCI. Use os mesmos parâmetros e suposições usados na Seção 6.16. armazenamento on-line e comunica- ção tornou os servidores de disco aplicações fundamentais.8. 6.10> Explique por que os sistemas reais utilizam benchmarks ou aplicações reais para avaliar o desempenho real. Determine se uma configuração de oito discos apresenta um gargalo de E/S.16.10> Para a aplicação listada.10.1 [10] <6. A disponibilidade e a velocidade são medidas bem conhecidas para servidores de disco.15. .15. Por que isso acontece? Existe alguma situação em que RAID 4 e RAID 5 não seria mais eficiente do que RAID 3? Exercício 6. Siga a mesma técnica esboçada na Seção 6. Responda as perguntas sobre configuração e avaliação de servidores de disco com os parâmetros a seguir.10.000 150.3 [5] <6. 6.15. 6.8.3 [10] <6.8. Como RAID 5 difere de RAID 4 e para que aplicações RAID 5 seria mais eficiente? 6.15. 100.10> Ache a taxa de E/S sustentada máxima para leituras e escritas aleatórias. Escolha características que darão suporte à avaliação semelhante à que foi realizada para o Exercício 6.17 Determinar o desempenho de um único servidor com dados relativamente completos é uma tarefa fácil.9> As melhorias de velocidade do RAID 4 e RAID 5 crescem com relação a RAID 3 à medida que o tamanho do bloco protegido aumenta.15.10. ao comparar servidores de diferentes vendedores oferecendo dados diferentes. 4 e 2 discos. 3 [20] <6. visto que seu modelo de receita é baseado na disponibilidade do seu servidor? .19.4 [15] <6. avalie o servidor que você identificou no Exercício 6.12> Calcule a taxa de falha anual (AFR) para os discos na tabela.18.12> Repita o Exercício 6.17.8.2 com o Sun Fire x4150. A tabela a seguir oferece dados para diversas unidades de disco.17.12> Dados apenas os parâmetros do problema original.12> Suponha que a taxa de falha anual varie pelo tempo de vida dos discos na tabela anterior.2 [15] <6. visto que seu modelo de receita é baseado no número de anúncios atendidos? 6.19. 1.19. considere que o seu vendedor ofereça uma configuração RAID 0 que aumentará a vazão do sistema de armazenamento em 70% e uma configuração RAID 1 que reduzirá a AFR dos pares de discos por 2. Quantos discos seriam substituídos após sete anos de operação? E depois de dez anos? 6.12> Suponha que os discos com taxas de falha inferiores sejam mais dis- pendiosos. Exercício 6.2 para uma grande farm de discos operada por uma empresa de backup on-line. os discos estão disponíveis a um custo mais alto.17.2 [5] <6. 6.6 vezes o custo da solução original. que começará a dobrar sua taxa de falha no ano 8.200.8.16.16.10> Usando métricas semelhantes às que foram usadas no Capítulo 6 e no Exercício 6. 6.10> Com relação à aplicação listada anteriormente. Qual você escolheria? Os resultados da sua análise o surpreenderam? Especificamente. Antes de avaliar o servidor.1 [5] <6. 6.19. Suponha que o custo de cada solução é 1.9.12> Dado que sua empresa opera um mecanismo de busca global com uma grande farm de disco. encontre um servidor disponível no mercado que você acredita que seria apropriado para executar a aplicação. Especificamente.18.9.10> Identifique um conjunto de benchmark padrão que seria útil para comparar o servidor que você identificou no Exercício 6.512 1. O upgrading para RAID 0 ou RAID 1 faz sentido econômico. Número de unidades Horas/Unidade Horas/Falha a.3 [10] <6.250 8.200.19 Para os discos na tabela do Exercício 6.17.760 1. suponha que a AFR seja três vezes esse valor no primeiro mês de operação e o dobro a cada ano começando no quinto ano. você escolheria de outra forma diferente? 6. você recomen- daria fazer o upgrade para RAID 0 ou RAID 1. 6. 1.18. 6.000 10. Quanto mais você pagaria pelos discos se a sua intenção for mantê-los por 7 anos? E por 10 anos? Exercício 6.9.2 [10] <6.000 6. 6. 6.8.18.000 b.1 [10] <6.18 As medições e as estatísticas fornecidas pelos vendedores de armazenamento devem ser cuidadosamente interpretadas para se obter previsões significativas sobre o comportamento do sistema.3 [5] <6.506 Capítulo 6  Armazenamento e outros tópicos de E/S 6.17. 6. o upgrading para RAID 0 ou RAID 1 faz sentido econômico.2 em com- paração com o servidor Sun Fire x4150 avaliado no Exercício 6. ao invés do ano 5. supondo que os parâmetros individuais do disco permaneçam iguais aos da tabela anterior? 6. identifique motivos pelos quais ele foi selecionado. Especificamente. 6. 20. .10.20.20 A avaliação e a manutenção diárias dos sistemas operando no computador envolvem muitos dos conceitos discutidos no Capítulo 6. §6. Avalie o custo e a adequação para a aplicação usando parâmetros descritos no Capítulo 6.7: 1 e 2.12> Vendedores concorrentes para os sistemas que você identificou no Exercício 6. Selecione parâmetros de comparação usando propriedades da aplicação e também os requisitos especificados. 6.20. rodando simulações de bioinformática. Explore os detalhes da avaliação dos sis- temas explorando as perguntas a seguir.10.9: Todos são verdadeiros. Certifique-se de considerar as propriedades de grandes simulações ao realizar sua configuração.2 [20] <6. Identifique os benchmarks que você usará para determinar qual sistema é melhor à sua aplicação.1 [20] <6.4: Todos são verdadeiros (considerando que 40MB/s seja compatível com100MB/s). 6.12> Configure o Sun Fire x4150 para fornecer 10 terabytes de ar- mazenamento para um array de processadores de 1000 processadores. 6. 6.20.2: 2 e 3 são verdadeiros.3: 3 e 4 são verdadeiros. 6. Determine quanto tempo será necessário para colher dados suficientes e tomar a sua decisão.2 se ofereceram para permitir que você avalie seus sistemas no local. Seções “Verifique você mesmo” §6. pois a maioria dos benchmarks TPC inclui custo. Compare as capacidades de disco. Use a internet e recursos de biblioteca para identificar servidores em potencial. 6. Sua configuração deverá minimizar o consumo de potência enquanto enfatiza questões de vazão e disponibilidade para o array de discos. §6.15 Exercícios 507 Exercício 6.3 [15] <6. 6.20.10. §6.12> Recomende um sistema de backup e arquivamento de dados para o array de discos do Exercício 6. Respostas das §6.6: 1 e 2. §6. 3 é falso.1. fita e backup on-line.5: 1 é verdadeiro. §6. 7 Multicores. peixes melhores e clusters do que os que já foram pescados.3 Multiprocessadores de memória compartilhada  515 7. multiprocessadores Existem. 7.1 Introdução  510 7.2 A dificuldade de criar programas Provérbio irlandês com processamento paralelo  512 7.4 Clusters e outros multiprocessadores de passagem de mensagens  517 . no mar. 13 Comentários finais  553 7.10 Roofline: um modelo de desempenho simples  539 7. SIMD.8 Introdução às topologias de rede multiprocessador  534 7.11 Vida real: benchmarking de quatro multicores usando o modelo roofline  546 7.7. SPMD e vetor  524 7. MIMD.9 Benchmarks de multiprocessador  537 7.15 Exercícios 555 Organização de multiprocessador ou cluster .6 SISD.12 Falácias e armadilhas  552 7.5 Multithreading do hardware  521 7.14 Perspectiva histórica e leitura adicional  555 7.7 Introdução às unidades de processamento de gráficos  528 7. que sejam eficientes no desempenho e potência à medida que o número de cores por chip aumenta geometricamente. Alguns desses problemas podem ser tratados de forma simples. alguns projetos podem suportar operar mesmo com a ocorrência de quebras no hardware. O número de cores deverá dobrar a cada dois anos. As linhas da figura representam o hardware. vários processadores executando Usamos o termo programa de processamento paralelo para indicar um único programa programas independentes simultaneamente. sequencial e concorrente. usando um cluster composto de microprocessadores abrigados em muitos servidores ou PCs independentes. O grande desafio enfrentado pela indústria é criar hardware e software que facilite a escrita de programas de processamento paralelo. Assim. problema da potência significa que aumentos futuros no desempenho aparentemente microprocessador multicore Um virão de mais processadores por chip em vez de taxas de clock mais altas e CPI melhorado. Isso é o contrário do eficazes e menores pode oferecer melhor desempenho por watt ou por joule tanto no processador. O stanza 4. Como o software multiprocessador é escalável. os clusters podem servir a aplicações igualmente exigentes fora das ciências. multiprocessadores e clusters “Sobre as montanhas da lua.” Respondeu a sombra: “Se você procurar o Há muito tempo. Portanto. A Figura 7. Portanto. os processadores nor- único circuito integrado. grande quanto no pequeno. que tem apenas um. Essa visão dourada é a origem dos multiprocessadores. Por exemplo. Ao contrário. otimização e assim por diante. e essa classe de problemas tem sido usada para justificar muitos computa- paralelo  Um único programa que é executado em vários dores paralelos novos no decorrer das últimas décadas. Alto desempenho pode significar alta vazão para tarefas independentes. o sistema fornece serviço continuado com n – 1 processadores. “Eldorado”. Como dis- multiprocessador  Um sistema de semos no Capítulo 1. Logo. cluster  Um conjunto de computadores conectados por Além disso. geração de código. os multiprocessadores também podem melhorar a disponi- bilidade (veja Capítulo 6). Essas tarefas para- tarefa ou paralelismo em lelas são aplicações independentes. os arquitetos de computadores têm buscado o Eldorado do projeto de Eldorado!” computadores: criar computadores poderosos simplesmente conectando muitos compu- Edgar Allan Poe. cavalgue. pois programas sequenciais significa programas lentos. de modo que ainda existe muita confusão sobre a terminologia e o que ela significa. . servidores Web e bancos de dados. se um único processador falhar em um multiprocessador com n processadores. lo.1   Introdução corajosamente. ou paralelismo em nível de processo. que é executado em vários processadores simultaneamente. o software para multiprocessadores pre- cisa ser projetado para trabalhar com um número variável de processadores. que é serial ou paralelo. os programadores de sistemas operacionais normalmente pensam neles como programas concorrentes: processos em cooperação tratando de eventos de E/S devido a tarefas in- dependentes executando em um computador. os pro- gramadores de compiladores pensam neles como programas sequenciais: as etapas são análise léxica. a potência tornou-se o fator limitante para centros de dados e computador com pelo menos dois microprocessadores. e são um uso importante e comum dos computadores nível de processo Utilizar paralelos. Essa mudança repentina no projeto do microprocessador apanhou muitos de surpresa. parsing.510 Capítulo 7  Multicores.1 tenta esclarecer os termos serial. funciona como um único e grande Como dissemos no Capítulo 1. uma rede local (LAN) que como mecanismos de busca. microprocessador contendo vários Eles são chamados microprocessadores multicore e não microprocessadores multiproces- processadores (“cores”) em um sador. Essa técnica é contrária à execução de uma única tarefa em vários processadores. pelo vale das sombras. se o software puder utilizá-los com eficiência. Substituir grandes processadores ineficazes por muitos processadores processadores. os programadores que se preocupam com o desempenho precisam se tornar programadores paralelos. que é inerentemente sequencial ou concorrente. provavelmente para evitar redundância de nomeação. Há muito tempo existem problemas científicos que precisam de computadores muito programa de processamento mais rápidos. a melhor eficiência de potência se junta ao desempenho escalável no caso para os multiprocessadores. cavalgue 7. chamado paralelismo em nível de paralelismo em nível de tarefa. As colunas dessa figura representam o software. Veremos vários deles neste capítu- processadores simultaneamente. 1849 cliente pede tantos processadores quantos seu orçamento permitir e recebe uma quanti- dade correspondente de desempenho. Assim. tadores menores existentes. malmente são chamados cores em um chip multicore. paralelo. os multiprocessadores ganharam destaque porque o multiprocessador. ou seja. ou no hardware paralelo. As duas versões comuns dessas alternativas são chamadas microproces- sadores de memória compartilhada e clusters. A Seção 7.1 Introdução 511 FIGURA 7. não se esqueça das nossas in- cursões iniciais dos capítulos anteriores: j Capítulo 2. A Seção 7. As Seções 7. como um SO no mais recente Intel Xeon e5345 (Clovertown). chamado unidade de processamento de gráficos (GPU — Graphics Processing Unit). que é se todos os processadores nos sistemas contam ou não com um único endereço físico. o programador MATLAB escreve uma multiplicação de matriz pensando nela sequencialmente. da comunidade de hardware gráfico. um termo que geralmente é confundido com multiprocessamento. Na Seção 7. uma aplicação Verifique precisa ser concorrente. discutimos a dificuldade de se achar benchmarks paralelos. mas também fazer com que os programas concorrentes tenham alto desempe- nho nos multiprocessadores. j Capítulo 3. como os sistemas operacionais para o processador Intel Pentium 4. O motivo desses dois eixos da Figura 7.1 é que o software concorrente pode ser execu- tado no hardware serial. Além disso. Seção 3. em parte porque se baseia em uma concorrência semelhante nos programas.5 descreve então o multithreading. SIMD e vetor. Com essa distinção.6: Paralelismo e aritmética computacional: associatividade. na Seção 7. Por exemplo.9: Paralelismo e E/S: Redundant Arrays of Inexpensive Disks. Você poderia supor que o único desafio da revolução paralela é descobrir como fazer com que o software naturalmente sequencial tenha alto desempenho no hardware paralelo. Seção 6. porém introspectivo. ela descreve dois estilos de arquiteturas de conjunto de instruções que dão suporte à execução de aplicações sequenciais em hardware paralelo. Seção 4.4 descrevem as duas alternativas de uma característica fundamental do hardware paralelo. você mesmo . que ajuda no projeto de aplicações e também de arquiteturas. Antes de prosseguirmos ainda mais até o paralelismo.1. A próxima seção descreve por que é difícil criar programas eficientes para processamento paralelo. à medida que o número de processadores aumenta. j Capítulo 5. O mesmo acontece para o software sequencial. no restante deste capítulo usaremos programa de processamento paralelo ou software paralelo para indicar o software sequencial ou concorrente executando em hardware paralelo.9.10: Paralelismo e paralelismo avançado em nível de instrução.8: Paralelismo e hierarquias de memória: coerência de cache.6 descreve um esquema de clas- sificação mais antigo que na Figura 7.3 e 7. 7. Seção 2. Verdadeiro ou falso: para que se beneficie de um multiprocessador. O Apêndice A descreve as GPUs com mais detalhes.11.11: Paralelismo e sincronização de instruções. Terminamos com falácias e armadilhas e nossas conclusões sobre o paralelismo. A Seção 7. Seção 5. a saber.1  Categorização e exemplos de hardware/software do ponto de vista da concorrência e do paralelismo. j Capítulo 4. Em seguida. mas poderia executá-la serialmente no hardware do Pentium 4 ou em paralelo no hardware do Xeon e5345. j Capítulo 6.7 descreve um estilo de computador relativamente novo. usamos esse modelo para avaliar quatro computadores multicore recentes em dois kernels de aplicação. Essa seção é seguida por uma descrição de um modelo de desempenho novo e simples. Que fração da computação original pode ser sequencial? A Lei de Amdahl (Capítulo 1) diz que: RESPOSTA Tempodeexecuçãoapós melhoria = Tempodeexecuçãoafetado pela melhoria + Tempodeexecução nãoafetado Quantidadede melhoria Podemos reformular a lei de Amdahl em termos de speed-up versus o tempo de execução original: Tempo de execução antes Speed-up = Tempo de execução afetado (Tempode execução antes-Tempo de execução afetado) + 100 . Para essa analogia e para a programação paralela. Para ter sucesso. os desafios incluem escalonamento. as técnicas de projeto de processadores. especial- mente quando o número de processadores aumenta? No Capítulo 1. Na verdade. Outro perigo do desempenho seria que os repórteres gastariam muito tempo se comunicando entre si em vez de escrever suas partes do artigo. Por que é difícil escrever programas de multiprocessador que sejam rápidos. Ela nos lembra que mesmo as pequenas partes de um programa precisam estar em paralelo para que o programa faça bom proveito dos muitos cores. já que a programação é mais fácil. tiram vantagem do paralelismo em nível de instrução (ver Capítulo 4). Mas por que isso acontece? Por que os programas de processamento paralelo devem ser tão mais difíceis de desenvolver do que os programas sequenciais? A primeira razão é que você precisa obter um bom desempenho e eficiência do programa paralelo em um multiprocessador.512 Capítulo 7  Multicores. tempo para sincronização e overhead para a comunicação entre as partes. Nossa discussão no Capítulo 1 revela outro obstáculo. DESAFIO do speed-up Suponha que você queira alcançar um speed-up 90 vezes mais rápido com 100 proces- EXEMPLO sadores. balanceamento de carga. e o problema fica pior à medida que o número de processadores aumenta. a tarefa precisa ser dividida em oito partes de mesmo tamanho. como execução superescalar e fora de ordem. normalmente sem envolvimento do programador. usamos a analogia de oito repórteres tentando escrever um único artigo na esperança de realizar o trabalho oito vezes mais rápido. Tais inovações reduzem a necessidade de reescrever programas para multiprocessadores.2   com processamento paralelo A dificuldade com o paralelismo não está no hardware. é que muito poucos programas de aplicação importantes foram escritos para completar as tarefas mais cedo nos multiproces- sadores. você usaria um programa sequencial em um processador. É difícil escrever software que usa processadores múltiplos para completar uma tarefa mais rápido. pois senão alguns repórteres estariam ociosos enquanto esperam que aqueles com partes maiores terminem. O desafio é ainda maior quando aumenta o número de repórteres para um artigo do jornal e quanto aumenta o número de processadores para a programação paralela. já que os programadores poderiam não fazer nada e ainda assim seus programas sequenciais seriam executados mais rapidamente nos novos computadores. conhecido como a Lei de Amdahl. caso contrário. multiprocessadores e clusters A dificuldade de criar programas 7. Entretanto. DESAFIO do speed-up.1 = 0.5. a porcentagem sequencial só poderá ser 0. t.1%. EXEMPLO mensões 10 × 10. 7. o speed-up com 10 processadores é 110t/20t = 5. calcule os speed-ups supondo que as matrizes crescem para 100 por 100. O tempo de execução para 100 processadores é 100t Tempodeexecuçãoapós melhoria = + 10t = 11t 100 de modo que o speed-up com 100 processadores é 100t/11t = 10. simplificando a fórmula e resolvendo para a fração de tempo afetada: 90 × (1 − 0. para obter um speed-up de 90 com 100 processadores.99 × Fração de tempo afetada) = 1 90 − (90 × 0. e o tempo de execução afetado pela melhoria é considerado a fração do tempo de execução original: 1 Speed up = Fraçãode tempoafetada (1 − Fraçãode tempoafetada) + 100 Substituindo pela meta de um speed-up de 90 na fórmula anterior: 1 90 = Fraçãode tempoafetada (1 − Fraçãode tempoafetada) + 100 Então. ainda maior Suponha que você queira realizar duas somas: uma é a soma de duas variáveis es- calares e outra é uma soma matricial de um par de arrays bidimensionais. . então há 10 adições que não se beneficiam dos processadores paralelos e 100 adições RESPOSTA que se beneficiam.2  A dificuldade de criar programas com processamento paralelo 513 Essa fórmula normalmente é reescrita considerando-se que o tempo de execução antes é 1 para alguma unidade de tempo.999 Portanto. Que speed-up você obtém com 10 versus 100 processadores? Em seguida. o tempo de execução para 10 processadores é Tempodeexecuçãoapós melhoria = Tempodeexecuçãoafetado pela melhoria + Tempodeexecução nãoafetado Quantidadede melhoria 110t Tempodeexecuçãoapós melhoria = + 10t = 20t 10 Então. Se o tempo para um único processador é 110t. existem aplicações com um substancial paralelismo.99 × Fração de tempo afetada) = 1 90 − 1 = 90 × 0. Se considerarmos que o desempenho é uma função do tempo para uma adição.99 × Fração de tempo afetada Fração de tempo afetada = 89/89. com di. 514 Capítulo 7  Multicores. deverá fazer uma experiência com 100 vezes a quantidade de clientes.010t/1010t = 9. para o tamanho deste problema. então ele precisa realizar 2% × 10. Em vez disso. Como eles estão operando simultaneamente. e que temos P processadores. Este exemplo final mostra a importância do balanceamento de carga. podemos simplesmente calcular o tempo de execução como um máximo . M. Isso nos permite apresentar dois expansão forte Speed-up termos que descrevem maneiras de expandir. DESAFIO do speed-up: balanceamento DE CARGA Para conseguir o speed-up de 91 no problema maior. Esses exemplos mostram que obter um bom speed-up em um multiprocessador enquanto se mantém o tamanho do problema fixo é mais difícil do que conseguir um bom speed-up aumentando o tamanho do problema. o benchmark de banco de dados débito-crédito TPC-C (Capítulo 6) requer que você aumente o número de contas de cliente para conseguir um maior número de transações por minuto. mostrado anteriormente. multiprocessadores e clusters Assim. cada um dos 100 processadores teve 1% do trabalho a realizar. a memória por processador alcançado em um multiprocessador para a expansão forte é aproximadamente M/P. para esse tamanho de problema maior. Calcule em 2% e 5%. Ou seja.010t.000t Tempodeexecuçãoapós melhoria = + 10t = 1010t 10 de modo que o speed-up com 10 processadores é 10. seja o conjunto de trabalho na expansão fraca Speed-up memória principal. Por exemplo. O tempo de execução para 100 processadores é 10. consideramos que a carga foi balanceada perfeitamente.9. Expansão fraca significa que o tama- sem aumentar o tamanho do nho do problema cresce proporcionalmente com o aumento no número de processado- problema. obtemos cerca de 99% do speed-up em potencial com 10 processadores e mais de 90% com 100. mas somente 10% com 100. e os outros 99 compartilharão as 9800 restantes. Expansão forte significa medir o speed-up alcançado em um multiprocessador enquanto se mantém o tamanho do problema fixo. obtemos cerca de 55% do speed-up em po- tencial com 10 processadores. você pode argumentar em favor de qualquer uma dessas processadores. Assim. Em vez disso. O argumento é que não faz sentido pensar que determinada base de clientes de repente começará a usar caixas eletrônicos 100 vezes por dia só porque o banco adquiriu um computador mais rápido. Veja o que acontece quando aumentamos a matriz. ao aumento no número de Dependendo da aplicação. Vamos supor que o tamanho do problema. mostre o impacto sobre o speed-up se a carga de um processador for maior que todo o res- tante.000t = 10. Se um processador tem 2% da carga paralela. e para a expansão fraca ela é aproxima- enquanto se aumenta o tamanho do problema proporcionalmente damente M. O programa sequencial agora utiliza 10t + 10. técnicas de expansão.000t Tempodeexecuçãoapós melhoria = + 10t = 110t 100 de modo que o speed-up com 100 processadores é 10.010t/110t = 91. se você for demonstrar um sistema que pode funcionar 100 vezes o número de transações por minuto. com EXEMPLO 100 processadores. O tempo de execução para 10 processadores é 10. res.000 RESPOSTA ou 200 adições. Então. alguns acessos à memória são muito mais rápidos do que outros. que os acessos à memória principal Microprocessadores com único espaço de endereços podem ser de dois tipos. com todos os processadores capazes de acessar qualquer acesso uniforme à memória local da memória por meio de loads e stores. depen.  + 10t = 210t  99 1  O speed-up cai para 10. No segundo estilo. Esse exemplo demonstra o valor do balanceamento de carga. o que requer que o compartilhamento seja explícito.3  compartilhada Dada a dificuldade de reescrever programas antigos para que funcionem bem em hardware paralelo. quinas são chamadas multiprocessadores de acesso uniforme à memória (UMA). multiprocessador de memória processor) é aquele que oferece ao programador um único espaço de endereços físico para compartilhada (SMP) Um processador paralelo com um único todos os processadores. uma pergunta natural é o que os projetistas de computador podem fazer para simplificar a tarefa. Como você poderia es. Quando o espaço de endereços físico é comum — que normalmente acontece para chips multicore —. comunicação implícita com loads pendentes em seus próprios espaços de endereços virtuais. importa qual palavra é solicitada. e cinco vezes a carga em um processador reduz o speed-up por quase um fator de cinco. todas as variáveis de um programa podem ficar disponíveis a qualquer momento para qualquer processador.010t/210t = 48. Nessa técnica. então o hardware normalmente oferece coerência de cache para dar uma visão consistente da memória compartilhada (veja Seção 5. Verifique você mesmo Multiprocessadores de memória 7. mas as máquinas NUMA podem expandir rápidos do que outros. um espaço de endereços físico. acesso não uniforme à dendo de qual processador pede qual palavra. embora um termo mais preciso teria sido multiprocessador de espaço de endereços. pois apenas um único processador com o dobro da carga dos outros reduz o speed-up quase ao meio. os desafios de programação são mais difíceis para um multiprocessador NUMA de endereços único em que alguns acessos à memória são muito mais do que para um multiprocessador UMA. Se um processador tem 5% da carga. palavra.800t 200t  Tempodeexecuçãoapós melhoria = Max  . Essas máquinas são chamadas multi. apenas que podem ser executados em paralelo. O levam aproximadamente a mesma quantidade de tempo não importa primeiro leva aproximadamente o mesmo tempo para acessar a memória principal.2 mostra a organização clássica (UMA)  Um multiprocessador em de um SMP. não qual processador acessa e não importa qual processador o solicite e não importa qual palavra é solicitada. A alternativa é ter um espaço de endereços separado por processador. ele precisa realizar 500 adições:  9.8 do Capítulo 5. implicando na endereço compartilhado. Observe que esses sistemas ainda podem executar tarefas inde. multiprocessador com espaço perar. vamos des- crever essa opção na próxima seção. dependendo para tamanhos maiores.  + 10t = 510t  99 1  O speed-up cai ainda mais para 10.3  Multiprocessadores de memória compartilhada 515  9. Essas má.) Um multiprocessador de memória compartilhada (SMP – shared memory multi. Uma resposta para isso foi oferecer um único espaço de endereços físico que todos os processadores possam compartilhar. memória (NUMA)  Um tipo de processadores de acesso não uniforme à memória (NUMA).500t 500t  Tempodeexecuçãoapós melhoria = Max  . A Figura 7. e as NUMAs podem ter latência inferior para a memória de qual processador solicita qual próxima. . Os processadores se comunicam por meio de variáveis compartilhadas na memória. mesmo que todos compartilhem e stores.010t/510t = 20. 7. Verdadeiro ou falso: a expansão forte não está ligada à lei de Amdahl. de modo que os programas não precisem se preocupar com o local onde são executados. Somente um processador de cada vez pode adquirir o lock. Essa etapa se chama redução. por um processador de cada vez. e outros processadores interessados nos dados compartilhados precisam esperar até que o proces- lock  Um dispositivo de sincronização que permite sador original libere a variável. eles também precisam coordenar quando operarão sobre dados compartilhados. multiprocessadores e clusters FIGURA 7. Pn é o número que identifica o processador. depois. entre 0 e 99. um processador poderia começar a trabalhar nos dados antes que outro tenha sincronização  O processo de terminado.516 Capítulo 7  Multicores.2  Organização clássica de um multiprocessador de memória compartilhada. lhada. Neste exemplo. A Figura 7. uma estrutura de dados e retorna Dividimos para conquistar.000 números em um computador com multi- EXEMPLO processador com tempo de acesso à memória uniforme. até que tenhamos uma única soma final.11 do Capítulo 2 descreve as instruções para o acesso aos dados somente o locking no MIPS. Todos os processadores começam o programa executando um loop que soma seu subconjunto de números: redução  Uma função que processa A próxima etapa é fazer essas muitas somas parciais. Vamos considerar que temos 100 processadores. Um programa de processamento paralelo simples para um espaço de endereços compartilhado Suponha que queremos somar 100. já que existe uma única memória para essa máquina. Quando o compartilhamen- coordenar o comportamento to tem o suporte de um único espaço de endereços. Não alocamos os subconjuntos a um espaço de memória diferente. Uma técnica utiliza um lock para uma variável comparti- podem estar sendo executados em diferentes processadores. caso contrário. A primeira etapa novamente seria dividir o conjunto de números em subconjuntos do RESPOSTA mesmo tamanho. A Seção 2. Essa coordenação é chamada de sincronização. Como os processadores operando em paralelo normalmente compartilharão dados. um quarto soma pares das novas somas parciais e assim por diante. A metade dos processadores soma pares de somas parciais. apenas atribuímos endereços iniciais diferentes a cada processador. os dois processadores precisam ser sincronizados antes que o processador “consumidor” tente ler o resultado do local da memória escrito pelo . um único valor.3 ilustra a natureza hierárquica dessa redução. que parado para sincronização. é preciso haver um mecanismo se- de dois ou mais processos. ços privados. Se o emissor precisar de confirmação de que a mensagem chegou.4  Clusters e outros multiprocessadores de passagem de mensagens 517 processador “produtor”. Para todos os processadores cujo número i é menor que half. Esse multiprocessador alternativo precisa se comunicar por meio da passagem de mensagens explícita. mensagem  Uma rotina usada por um processador em máquinas a coordenação é embutida na passagem da mensagem. passagem de mensagens   lusters e outros multiprocessadores C Comunicação entre vários 7. que tradicionalmente é o nome desse estilo de rotina para receber computadores. caso contrário. e o processador receptor sabe quando uma men.4  de passagem de mensagens processadores enviando e recebendo informações explicitamente. você mesmo FIGURA 7. Desde que o sistema tenha rotinas para enviar e receber mensagens. adicione a soma produzida pelo processador número (i+half) à sua soma. Essa técnica tem sido experimentada. Aqui está o código (half também é privada): Verdadeiro ou falso: multiprocessadores de memória compartilhada não podem tirar Verifique proveito do paralelismo em nível de tarefa. deixando para o sistema operacional a tarefa de cuidar da comunicação.4 mos. o processador. Queremos que cada processador tenha sua própria versão da variável contadora de loop i. mas compartilhar um espaço de endereços virtuais comum. pois um processador sabe com memórias privadas para quando uma mensagem é enviada. um processador em máquinas com memórias privadas para passar uma tra a organização clássica de um multiprocessador com múltiplos espaços de endere- mensagem a outro processador. . de baixo para cima. A Figura 7. mas possui um alto overhead para oferecer uma abstração de memória compartilhada prática ao programador. rotina para enviar A técnica alternativa ao compartilhamento de um espaço de endereços é que cada mensagem  Uma rotina usada por processador tenha seu próprio espaço privado de endereços físicos.3  Os quatro últimos níveis de uma redução que soma os resultados de cada proces- sador. o consumidor pode ler o valor antigo dos dados. Detalhamento:  Uma alternativa ao compartilhamento do espaço de endereço físico seria ter espaços de endereços físicos separados. 7. aceitar uma mensagem de outro sagem chega. de modo que precisamos indicar que ela é uma variável “privada”. Esse ponto fraco é um dos motivos para a popularidade das máquinas virtuais (Capí- tulo 5). permitindo que um programa migre a partir de um hardware defeituoso. dados os custos muito mais altos. e eles ofereceram melhor desempenho de comunicação absoluta do que os clusters criados por meio de redes locais. Cada um executa uma cópia distinta do sistema operacional. as VMs possibilitam parar ou iniciar programas atomicamente. servidores de correio e servidores de arquivo — não exigem que o endereçamento compartilhado funcione bem. diferente do SMP da Figura 7. não importa se ele oferece endereços compartilhados ou passagem de mensagens. através de switches e formar um multiprocessador de passagem de mensagens. Observe que. Poucas aplicações poderiam justificar o desempenho de comunicação mais alto. O problema foi que eles eram muito mais caros. Algumas aplicações concorrentes funcionam bem em hardware paralelo. paralelismo e aplicações em nível de tarefa com pouca comunicação — como busca na web.2. clusters  Coleções de Logo. multiprocessadores e clusters FIGURA 7. e só precisa de uma única cópia do SO. tradicionalmente chamado de multiprocessador de passagem de mensagens. Outra desvantagem dos clusters é que os processadores em um cluster normalmente são conectados por meio da interconexão de E/S de cada computador. pois as VMs tornam os clusters mais fáceis de administrar. enquanto o custo de administrar um multiprocessador de memória compartilhada com n processadores é aproximadamente o mesmo que administrar uma única máquina. processador receptor poderá então enviar uma mensagem de confirmação para o emissor. A interconexão de memória tem largura de banda mais alta e latência mais baixa. Em particular.518 Capítulo 7  Multicores. Houve várias tentativas de construir computadores de alto desempenho com base em redes de passagem de mensagens de alto desempenho. Os clusters geralmente são coleções de computadores bá- por switches de rede padrão para sicos que são conectados entre si por sua interconexão de E/S. os clusters se tornaram o exemplo mais divulgado atualmente do computador computadores conectados por E/S de passagem de mensagens. enquanto os cores em um multiprocessador normalmente são conectados na interconexão de memória do computador. mas entre os nós processador-memória. Um último ponto fraco é o overhead na divisão de memória: um cluster de n máquinas tem n memórias independentes e n cópias do sistema operacional. Por exemplo. As VMs podem ainda migrar um programa de um computador em um cluster para outro sem interromper o programa. . permitindo um desempenho de comunicação muito melhor. Uma desvantagem dos clusters foi que o custo de administrar um cluster de n máquinas é cerca do mesmo que o custo de administrar n máquinas independentes. mas um multiproces- sador de memória compartilhada permite que um único programa utilize quase toda a memória no computador. Praticamente cada serviço da internet conta com clusters de servidores e switches básicos.4  Organização clássica de um multiprocessador com múltiplos espaços de endereços privados. o que simplifica as atualizações de software. cabos de rede padrão. a rede de interconexão não está entre as caches e a memória. A parte difícil é que cada soma parcial está localizada em uma unidade de execução diferente. EXEMPLO Quanto espaço a mais existe para os usuários com memória compartilhada? A razão da memória disponível para os programas do usuário no computador de memória compartilhada versus o cluster seria RESPOSTA 20 − 1 19 = ≈ 1‚ 25 5 × (4 − 1) 15 de modo que os computadores com memória compartilhada têm cerca de 25% mais espaço. Depois. envios e recepções continuam até haver uma única soma . Como esse computador possui múltiplos espaços de endereçamento. Um programa simples de processamento paralelo para passagem de mensagens Suponha que queremos somar 100.4  Clusters e outros multiprocessadores de passagem de mensagens 519 Eficiência da memória Suponha que um único processador de memória compartilhada tenha 20GB de memória principal. em que duas somas parciais são feitas. 7. e o SO ocupe 1GB. Essa etapa é simplesmente um loop que toda unidade de execução segue: ler uma palavra da memória local e adicioná-la a uma variável local: A última etapa é a redução que soma essas 100 somas parciais.000 números em um multiprocessador por pas- sagem de mensagens com 100 processadores.000 números envia os subconjuntos para cada um dos 100 nós de memória de processador. o primeiro passo é distribuir os 100 subconjuntos para cada uma das memórias locais. precisamos usar a rede de interconexão para enviar somas parciais e acumular a soma final. Em vez de enviar todas as somas parciais a um único processador. mais uma vez dividimos para conquistar. O processador RESPOSTA contendo os 100. metade dos processadores envia suas somas parciais para a outra meta- de dos processadores. Essas divisões. cinco computadores em cluster com 4GB cada. o que resultaria em acrescentar sequencialmente as somas. A próxima etapa é obter a soma de cada subconjunto. cada um com múltiplas memórias EXEMPLO privadas. Consequentemente. um quarto das unidades de execução (metade da metade) envia essa nova soma parcial para o outro quarto dos processadores (a metade da metade restante) para a próxima rodada de somas. Vamos refazer o exemplo de soma da seção anterior para ver o impacto das memórias privadas múltiplas e a comunicação explícita. Primeiro. A vantagem para os programadores é que software a comunicação é explícita. Seja Pn o número da unidade de execução. a emissão e recepção de mensagens é muito mais lenta. Já que o software de cluster é uma camada que roda sobre o sistema operacional executado em cada computador. de modo que podemos presumir que um processador receptor estará suspenso até receber uma mensagem. pois cada comunicação precisa ser identificada antecipadamente. A desvantagem para os programadores é que é mais difícil trans- portar um programa sequencial para um computador com passagem de mensagens.520 Capítulo 7  Multicores.8 do Capítulo 5). Existem diferenças de opinião quanto ao caminho mais curto para o alto desempenho. Se houver um número ímpar de nós. multiprocessadores e clusters de todos os números. . dados os prós e contras da comunicação implícita. em vez da memória compartilhada coerente com a cache. então. A limitação de memórias separadas para memória do usuário torna-se uma vantagem na disponibilidade do sistema. Interface Computadores que contam com a passagem de mensagens para a comunicação. é muito mais fácil desconectar e substituir uma máquina defeituosa. o que significa que existem menos surpresas de desempenho do que com a comunicação implícita nos computadores de memória compartilhada coerentes com a cache. o endereça- mento compartilhado significa que é difícil isolar um processador e substituí-lo sem um árduo trabalho por parte do sistema operacional. já que os processadores estão cientes da transmissão dos dados. e cada pro- cessador receptor recebe apenas uma mensagem. o que facilita o transporte.y) uma rotina que envia pela rede de interconexão para a unidade de execução número x o valor y e receive() a função que recebe um valor da rede para esse processador : Esse código divide todos os processadores em emissores ou receptores. Como um cluster consiste em computadores independentes conectados por meio de uma rede local. é muito mais fácil substituir uma máquina sem paralisar o sistema em um cluster do que em um SMP. Fundamentalmente. send(x. Na realidade. Portanto. ou o programa não funcio- nará. Uma otimização para balancear melhor o cálculo e a comunicação poderia ser o uso de menos nós recebendo muitas somas de outros processadores. o nó central não participa da emissão/ recepção. são muito mais fáceis para os projetis- hardware/ tas de hardware (veja Seção 5. Detalhamento:  Este exemplo considera implicitamente que a passagem de mensagens é tão rápida quanto a adição. send e receive podem ser usados como primitivas para sincronização e para comunicação. é definido de modo que esse nó seja o nó mais alto na próxima iteração. A memória compartilhada coerente com a cache permite que o hardware descubra quais dados precisam ser comunicados. O limite. Yahoo e outros possuem múltiplos centros de dados. Para permitir esse com. cada thread teria uma cópia separada do banco de registradores e do PC. Microsoft.5  Multithreading do hardware 521 Como os clusters são construídos por meio de computadores inteiros e redes indepen- dentes e escaláveis. ned prático. o hardware precisa suportar a capaci- dade de mudar para uma thread diferente com relativa rapidez. Uma importante vantagem do multithreading fine-grained é que ele pode ocultar as perdas de vazão que surgem dos stalls curtos e longos. Para tornar o multithreading fine-grai. Verdadeiro ou falso: diferentemente dos SMPs. Essa intercalação normalmente é feita de forma circular. a grade SETI@home operava em 257 TeraFLOPS. Em especial. A principal desvantagem do multithreading fine-grained é que ele torna mais lenta a execução das threads individuais. 7. o processador precisa ser capaz de trocar threads a cada ciclo de clock. que já suportam multiprogramação. A memória em si pode ser compartilhada por meio de mecanismos de memória virtual. e eles poderiam ser apanhados e ter boa utilidade se alguém desenvolvesse software que pudesse rodar nesses computadores e depois dar a cada PC uma parte independente do problema para atuar. Existem dois métodos principais de multithreading do hardware. após cada instrução. O primeiro exemplo foi o Search for ExtraTerrestrial Intelligence (SETI). Detalhamento:  Outra forma de computação em grande escala é a computação em grade. os computadores com passagem de Verifique você mensagens contam com locks para a sincronização. sem realizar nada de útil. Menor custo. saltando quais- sugere a comutação entre as threads quer threads que estejam suspensas nesse momento. o uso de múltiplos processadores nas empresas de serviço de internet tem sido muito bem-sucedido. maior eficiência de energia e a rápida e gradual ex- pansibilidade tornam os clusters atraentes para provedores de serviços para a world wide web. os computadores com passagem de mensagens precisam de múltiplas cópias do programa de processamento paralelo e do sistema operacional. uma troca de thread deve ser muito mais eficiente do que uma troca de processo. Mais de 5 milhões de usuários de computador em mais de 200 países se inscreveram para o SETI@ home e contribuíram coletivamente com mais de 19 bilhões de horas de tempo de proces- samento de computador. eBay. enquanto uma troca de thread pode ser instantânea. O multithreading multithreading fine-grained comuta entre threads a cada instrução. suspensa.5  Multithreading do hardware O multithreading do hardware permite que várias threads compartilhem as unidades multithreading do funcionais de um único processador de um modo sobreposto. e depois os programas que executam neles precisam se comunicar por redes de longa distância. já que uma thread que está pronta para ser executada sem stalls será atrasada por instruções de outras threads. que normalmente exige centenas a milhares de ciclos de processador. . 1. alta disponibilidade. já que as instruções de outras threads podem ser executadas quando uma thread é suspensa. o processador precisa duplicar o estado independente de cada thread. 7. Observou-se que milhões de PCs ficam ociosos em determinado momento. hardware  Aumentar a utilização de um processador trocando para partilhamento. resultando em execução intercalada fine-grained  Uma versão do multithreading do hardware que de várias threads. Verdadeiro ou falso: assim como os SMPs. Além disso. Logicamente. em que os computadores são espalhados por grandes áreas. esse isolamento também facilita expandir o sistema sem paralisar a aplicação que executa sobre o cluster. Google. Os mecanismos de busca que milhões de nós utilizamos todos os dias dependem dessa tecnologia. Ao final de 2006. A forma mais comum e exclusiva de computação em grade foi promovida pelo projeto SETI@home. outra thread quando uma thread é Por exemplo. mesmo 2. cada um com clusters de dezenas de milhares de processadores. deixan- do para o hardware a associação de slots de instrução e registradores renomeados com suas threads apropriadas. Essa mudança reduz a necessidade de tornar a comu- somente após eventos significativos.5 ilustra conceitualmente as diferenças na capacidade de um processador de explorar recursos superescalares para as configurações de processador a seguir. multithreading do hardware que sugere a comutação entre as threads como as falhas de cache de nível 2. A Figura 7. um importante stall. visto que só serão despachadas instruções de outras threads quando uma thread encontrar um stall oneroso. em que a reposição de pipeline é insignificante comparada com o tempo de stall. o paralelismo em nível de thread e o paralelismo em nível de instrução são explorados simultaneamente. pode deixar o processador inteiro ocioso. como apenas uma thread des- pacha instruções em um determinado ciclo de clock. Além disso. o multithreading coarse-grained sofre de uma grande desvantagem: é limitado em sua capacidade de sanar perdas de vazão. escalonada ralelismo de unidade funcional do que uma única thread efetivamente pode usar. j Um superescalar com simultaneous multithreading. o uso dos slots de despacho é limitado por uma falta de paralelismo em nível de instrução. Devido a esse overhead de inicialização. O princípio mais importante que motiva o SMT é para a microarquitetura de que os processadores de despacho múltiplo modernos normalmente possuem mais pa- despacho múltiplo. SMT não troca de recurso a cada ciclo. o pipeline precisa ser esvaziado ou congelado. e as limitações do paralelismo em nível de instrução significam que nem todos os slots de despacho serão utilizados. Esse método de multithreading comuta threads apenas em stalls onerosos. camente para explorar paralelismo em nível de thread ao mesmo tempo em que explora utilizando os recursos necessários o paralelismo em nível de instrução. como uma falha de cache de instruções. com múltiplas threads usando os slots de despacho . A parte inferior mostra como as quatro threads poderiam ser combinadas para serem executadas no processador de maneira mais eficiente usando três opções de multithreading: j Um superescalar com multithreading coarse-grained.522 Capítulo 7  Multicores. execução de uma thread individual. com a renomeação de registradores e o escalonamento dinâmico. multiprocessadores e clusters multithreading O multithreading coarse-grained foi criado como uma alternativa para o multithreading coarse-grained  Uma versão do fine-grained. Embora isso reduza o número de ciclos de clock completamente ociosos. Como um processador com multithreading coarse-grained despacha instruções por meio de uma única thread. j Um superescalar com multithreading fine-grained. o overhead de inicialização do pipeline ainda produz ciclos ociosos. No superescalar sem suporte a multithreading do hardware. No superescalar com multithreading coarse-grained. mas sempre está executando instruções de múltiplas threads. a resolução das dependências pode ser tratada pela capacidade de escalonamento dinâmico. simultaneous multithreading O simultaneous multithreading (SMT) é uma variação do multithreading do hard- (SMT)  Uma versão do ware que usa os recursos de um processador de despacho múltiplo escalonado dinami- multithreading que reduz o custo do multithreading. Entretanto. disso. especialmente de stalls mais curtos. Em um processador com multithreading coarse-grained. os longos stalls são parcial- mente ocultados pela comutação para outra thread que usa os recursos do processador. A parte superior mostra como quatro threads seriam executadas de forma independente em um superescalar sem suporte a multithreading. quando ocorre um stall. a intercalação de threads elimina quase todos os slots totalmente vazios. o multithreading coarse-grained é muito mais útil para reduzir a penalidade dos stalls de alto custo. tação de thread essencialmente gratuita e tem muito menos chance de tornar mais lenta a como uma falha de cache. No caso SMT. as limitações do paralelismo em nível de instrução ainda geram um número significativo de slots ociosos dentro de alguns ciclos de clock. Além dinamicamente. Essa limitação surge dos custos de inicialização de pipeline do multithreading coarse-grained. Como estamos contando com os mecanismos dinâmicos existentes. diversas instruções de threads independentes podem ser despachadas sem considerar as dependências entre elas. A nova thread que começa a ser executada após o stall precisa preencher o pipeline antes que as instruções consigam ser concluídas. Porém. Por exemplo. formas mais simples de multithreading sejam utilizadas.5  Multithreading do hardware 523 FIGURA 7. A dimensão horizontal representa a capacidade de despacho de instrução em cada ciclo de clock. Pode ser que os recursos subutilizados dos processadores fora de ordem possam ser reduzidos e. Os projetos multicore também compartilham recursos. portanto. o que provavelmente é mais eficaz para esconder a latência da memória do que tentar preencher slots de despacho não usados. Computadores fine-grained. As quatro threads no alto mostram como cada uma seria executada em um proces- sador superescalar padrão sem suporte a multithreading. Vamos concluir com três observações. levariam a mais perda na vazão para multithreading coarse.5  Como quatro threads usam os slots de despacho de um processador superescalar em diferentes métodos. portanto.11 é um exemplo de um retorno a microarquiteturas mais simples e. Na prática. . A dimensão vertical representa uma sequência dos ciclos de clock. sabemos que a barreira da potência está forçando um projeto em direção a processadores mais simples e mais eficientes em termos de potência em um chip. ao uso do multithreading fine-grained. Segundo. como em um SMT. Os efeitos de inicialização de pipeline adicionais para multithreading coarse. Uma caixa vazia (branco) indica que o slot de despacho correspondente está vago nesse ciclo de clock. outros fatores podem restringir o número de slots usados. trocam para outra thread em caso de falha.5 simplifique bastante a operação real desses processadores. Por exemplo. Os três exemplos embaixo mostram como elas seriam executadas juntas em três opções de multithreading. Os tons de cinza e preto correspondem a quatro threads diferentes nos processadores multithreading. O ideal é que o uso de slots de despacho seja limitado por desequilíbrios nas necessidades e na disponibilidade de recursos entre múltiplas threads. como o UltraSPARC T2. Por exemplo. dois proces- sadores poderiam compartilhar uma unidade de ponto flutuante ou uma cache L3. o microprocessador Sun UltraSPARC T2 (Niagara 2) na Seção 7. Embora a Figura 7. um desafio de desempenho importante é tolerar a latência decorrente das falhas de cache. ela ilustra as potenciais vantagens de desempenho em potencial do multithreading em geral e do SMT em particular. Uma terceira observação é que o objetivo do multithreading do hardware deve usar o hardware com mais eficiência compartilhando os componentes entre diferentes tarefas. 7. que não estão ilustrados nessa figura. o recente multicore Intel Nehalem suporta SMT com duas threads para melhorar a utilização do core. Primeiro. em um único ciclo de clock. pelo Capítulo 1. SPMD e vetor Outra categorização do hardware paralelo proposta na década de 1960 ainda está em uso atualmente. multiprocessadores e clusters Esse compartilhamento reduz alguns dos benefícios do multithreading em comparação com o oferecimento de mais cores não multithreaded. Computadores SIMD operam sobre vetores de dados. contando com ins- truções condicionais quando diferentes processadores deveriam executar diferentes seções SPMD  Single Program. possui fluxos de instruções e fluxos de dados múltiplos. FIGURA 7. 7. de programação MIMD convencional.6  SISD. e portanto cada unidade pode ter diferentes endereços de dados. Multiple Data streams. MIMD. Embora seja possível escrever programas separados que são executados em diferentes processadores em um computador MIMD e ainda trabalharem juntos para um objetivo grandioso e coordenado. isso é próximo do já conhecido SISD.6 mostra as categorias. Verifique 1. Do ponto de vista de um programador. processador de vetor ou de array. e um multiprocessador convencional único.1. escalonado dinamicamente. MISD e MIMD. a 64 ALUs. em termos da Figura 7. o inverso faz os processadores. de código. Multiple Data streams. Embora cada unidade esteja executando a mesma instrução. A Figura 7. Ela foi baseada no número de fluxos de instruções e no número de fluxos de SISD  ou Single Instruction stream. os programadores normalmente escrevem um único programa que executa em todos os processadores de um computador MIMD. cada unidade de execução tem seus próprios registradores de endereço. 2. Um multiprocessador. Assim. Assim. Um processador único fluxo de instruções e um único fluxo de dados. Um multiprocessador. um processador convencional tem um Single Data stream. em que um único Embora seja difícil oferecer exemplos de computadores úteis que sejam classificados programa é executado em todos como múltiplos fluxos de instruções e fluxo de instrução único (MISD).524 Capítulo 7  Multicores. Por exemplo. . Verdadeiro ou falso: o multithreading simultâneo utiliza threads para melhorar a utilização de recursos de um processador fora de ordem. dados. streams. mas é apenas o Multiple Data streams. muito mais sentido. SIMD. uma aplicação sequencial poderia ser compilada para executar em hardware serial organizado como um SISD ou em hardware paralelo que foi organizado como um SIMD. A mesma As virtudes do SIMD são que todas as unidades de execução paralelas são sincronizadas instrução é aplicada a muitos fluxos e todas elas respondem a uma única instrução que emana de um único contador de pro- de dados.6  Categorização de hardware e exemplos baseados no número de fluxos de instruções e fluxos de dados: SISD. SIMD. Essas duas categorias são abrevia- MIMD  ou Multiple Instruction das como SISD e MIMD. para formar 64 somas dentro de um único ciclo de clock. assim como em um grama (PC). respectivamente. SIMD  ou Single Instruction uma única instrução SIMD poderia acrescentar 64 números enviando 64 fluxos de dados stream. Verdadeiro ou falso: tanto o multithreading quanto o multicore contam com o você mesmo paralelismo para obter mais eficiência de um chip. Esse estilo é chamado Single Program Multiple Data (SPMD). O modelo modo normal de programar um computador MIMD. SIMD é mais fraco em instruções paralelismo em nível de case ou switch. Outra vantagem é o tamanho reduzido da memória do programa — SIMD só precisa de uma cópia do código que está sendo executado simultaneamente. uma arquitetura de vetor poderia ter 32 registradores de vetor. SIMD. Em vez de ter 64 ALUs realizando 64 adições simultaneamente. Um recurso importante das arquiteturas de vetor é um conjunto de registradores de vetor. o número de opcodes para instruções de multimídia explodia. como os antigos processadores de array. com os dados errados são desativadas.14 no site). mas duas interpretações do SIMD permanecem ativas hoje. Essa é novamente uma grande combinação com os problemas com muito paralelismo em nível de dados. e agora existem centenas de instruções SSE para realizar as combinações úteis (veja Capítulo 2). . A largura da operação e dos registradores é codificada no opcode dessas instruções de multimídia. você poderia considerar que um único componente de hardware seja uma ALU de 64 bits ou duas ALUs de 32 bits ou quatro ALUs de 16 bits ou oito ALUs de 8 bits. Por exemplo.6  SISD. é preciso haver muitos dados estruturados de forma idêntica. Essas instruções permitem que o hardware tenha muitas ALUs operando simultaneamente ou. e o MIMD com memória compartilhada precisará de múltiplas caches de instrução. em que cada unidade de execução precisa realizar uma operação dife. Elas foram acrescentadas para melhorar o desempenho dos programas de multimídia. que tem sido identificada de perto com os Cray Computers. cada um com 64 elementos de 64 bits. o que é chamado de paralelismo em nível de dados. mais hard- ware era acrescentado a essas extensões de multimídia. MIMD. Os chamados processadores de array que inspiraram a categoria SIMD desapareceram na história (veja Seção 7. que operam simultaneamente. e agora o SSE2 admite a execução simultânea de um par de números de ponto flutuante de 64 bits. enquanto os MIMDs com passagem de mensagem podem precisar de uma cópia em cada processador. SPMD e vetor 525 A motivação original por trás do SIMD foi amortizar o custo da unidade de controle por dezenas de unidades de execução. de modo que as unidades com dados corretos possam continuar. Assim. dependendo de quais dados ela tenha. ou oito elementos de dados de 8 bits. Essas situações basicamente executam em desempenho 1/n. À medida que a lei de Moore continuava. Loads e stores simplesmente possuem a largura da ALU mais larga. para o paralelis- mo funcionar no SIMD. onde n é o número de casos. particione uma ALU única e larga em muitas ALUs menores paralelas. colocá-los em ordem em um grande conjunto de registradores. Vetor Uma interpretação mais antiga e mais elegante do SIMD é a chamada arquitetura de vetor. A filosofia básica da arquitetura de vetor é coletar elementos de dados da memória. de modo equivalente. ou dois elementos de dados de 32 bits. SIMD funciona melhor quando lida com arrays em loops for. 7. Esse paralelismo a um custo muito baixo para dados inteiros estreitos foi a inspiração original das instruções MMX do x86. As unidades de execução independentes. e é a base das centenas de instruções MMX e SSE do microprocessador x86 (veja Capítulo 2). Logo. as arquiteturas de vetor colocaram a ALU em pipeline para obter bom desempenho com custo reduzido. Enquanto a largura de dados de registradores e operações crescia. SIMD no x86: extensões de multimídia A variação mais utilizada do SIMD encontra-se em quase todo microprocessador de hoje. de modo que o programador pode pensar na mesma instrução de transferência de dados como transferindo um único elemento de dados de 64 bits. dados  Paralelismo obtido operando-se sobre dados rente sobre seus dados. operar sobre eles sequencialmente nos registradores e depois escrever os resultados de volta para a memória. ou quatro elementos de dados de 16 bits. Os nomes lv e sv indicam load de vetor e store de vetor. mas com a letra “V” acrescentada. DAXPY significa Double precision a × X Plus Y.d). As instruções de vetor apanham como entrada um par de registradores de vetor (addv. o outro operando. e a é uma variável escalar de precisão dupla. As operações de vetor utilizam os mesmos nomes das operações MIPS. No segundo caso. é o endereço inicial do vetor na memória. (Esse exemplo é o chamado loop DAXPY.) Suponha que os endereços iniciais de X e Y estejam em $s0 e $s1. inicial- mente residentes na memória. Dada essa descrição curta. Essa redução ocorre tanto porque as operações de vetor trabalham sobre 64 elementos quanto porque as instruções de overhead que constituem quase metade do . Um operando é o registrador de vetor a ser car- regado ou armazenado. e carregam ou armazenam um vetor inteiro de dados de precisão dupla. Aqui está o código MIPS convencional para o DAXPY: RESPOSTA Aqui está o código MIPS de vetor para o DAXPY: Existem algumas comparações interessantes entre os dois segmentos de código nes- te exemplo. respectivamente.526 Capítulo 7  Multicores. que forma o loop interno do benchmark Linpack. o valor no registrador escalar é usado como a entrada para todas as operações — a operação addvs. A mais impressionante é que o processador de vetor reduz bastante a lar- gura de banda de instrução dinâmica. executando apenas seis instruções contra quase 600 para o MIPS. que é um registrador MIPS de uso geral.d somará o conteúdo de um registrador escalar a cada elemento em um registrador de vetor. Por exemplo. mostre o código MIPS convencional versus o código MIPS de vetor para Y = a × X +Y onde X e Y são vetores de 64 números de ponto flutuante com precisão dupla. multiprocessadores e clusters Comparando código de vetor com código convencional Suponha que estendamos a arquitetura do conjunto de instruções MIPS com ins- EXEMPLO truções de vetor e registradores de vetor. addv.d soma dois vetores de precisão dupla.d) ou um registrador de vetor e um regis- trador escalar (addvs. Porém. acrescentamos código de contabilidade para percorrer operações de vetor de tamanho total e tratar do restante. Quando os loops são mais curtos. j Como um loop inteiro é substituído por uma instrução de vetor cujo comportamento é predeterminado. SIMD. SPMD e vetor 527 loop no MIPS não estão presentes no código de vetor.d. Outra diferença importante é a frequência dos hazards de pipeline (Capítulo 4). MIMD. No código MIPS direto. Esse último processo é conhecido como strip mining (ou mineração a céu aberto). e cada s. No processador de vetor. e depois os elementos subsequentes fluirão tranquilamente pelo pipeline. e os projetistas são moti- vados a incluir unidades de vetor se o domínio da aplicação puder usá-las com frequência. 7. . j Arquiteturas e compiladores de vetor têm uma reputação de tornar muito mais fácil que os multiprocessadores MIMD escrever aplicações eficientes quando elas contêm paralelismo em nível de dados. Por esses motivos. Se os elementos do vetor forem todos adjacentes. e não uma vez para cada palavra do vetor. a grande diferença na largura de banda de instrução não pode ser reduzida. Detalhamento:  O loop no exemplo anterior combinou exatamente com o tamanho do vetor.6  SISD. então buscar o vetor de um conjunto de bancos de memória bastante intervalados funciona muito bem. j Usando uma instrução de vetor. cada add. Como você poderia esperar. de modo que o hardware não tem de verificar hazards de dados dentro de uma instrução de vetor. Assim.d. em vez de uma vez por elemento de vetor. Os stalls do pipeline podem ser reduzidos no MIPS usando desdobramento de loop (veja Capítulo 4). o custo da latência para a memória principal é visto apenas uma vez para o vetor inteiro. A redução de verificações pode economizar potência. o compilador ou programador indica que o cálculo de cada resultado no vetor é independente do cálculo de outros resultados no mesmo vetor. Neste exemplo. a frequência de stall do pipeline no MIPS será de aproximadamente 64 vezes maior do que no VMIPS.d precisa esperar por um mul. essa redução nas instruções buscadas e executadas economiza energia. os stalls do pipeline só são necessários uma vez por operação de vetor. j A economia na largura de banda da instrução e verificação de hazard mais o uso eficaz da largura de banda da memória dão às arquiteturas de vetor vantagens em potência e energia contra as arquiteturas escalares. e não uma vez para cada elemento dentro dos vetores. os hazards de controle que normalmente surgiriam do desvio do loop são inexistentes. as operações de vetor podem se tornar mais rápidas que uma sequência de operações escalares sobre o mesmo número de itens de dados.d precisa es- perar pelo add. as arquiteturas de vetor utilizam um registrador que reduz o tamanho das operações de vetor. Quando os loops são maiores. A largura de banda de busca e decodificação de instrução necessária é bastante reduzida. j O hardware só precisa verificar hazards de dados entre duas instruções de vetor uma vez por operando de vetor. Assim. cada instrução de vetor só gerará stall para o primeiro elemento em cada vetor. Vetor versus escalar As instruções de vetor possuem várias propriedades importantes em comparação com os arquivos convencionais de conjunto de instruções. que são chamadas arquiteturas escalares nesse contexto: j Uma única instrução de vetor especifica muito trabalho — isso é equivalente a executar um loop inteiro. j Instruções de vetor que acessam a memória possuem um padrão de acesso conhecido. Se haverá instruções load e store de vetor. Introdução às unidades de processamento 7. o número de elementos em uma operação de vetor não está no opcode. Isso significa que diferentes versões da arquitetura de vetor podem ser implementadas com um número diferente de elementos apenas mudando o conteúdo desse registrador e retendo. enquanto o vetor especifica dezenas de operações. os anúncios recentes da Intel sugerem que os vetores desempenharão um papel mais importante.7  de gráficos Uma justificativa importante para o acréscimo de instruções SIMD às arquiteturas existentes foi que muitos microprocessadores eram conectados a telas gráficas em PCs e estações de trabalho. . Ao contrário. Os vetores admitem os acessos “strided”. Verifique Verdadeiro ou falso: conforme exemplificamos no x86. Essa última largura é equivalente a 16 números de ponto flutuante de precisão dupla. e permitirá a eventual expansão para 1024 bits. A Advanced Vector Instructions (AVI) da Intel. fez sentido melhorar o proces- samento gráfico. de modo que é fácil fazer uma operação funcionar em 32 elementos de dados de 64 bits ou em 64 elementos de dados de 32 bits ou em 128 elementos de dados de 16 bits ou 256 elementos de dados de 8 bits. Além disso. e as instruções SIMD conseguiram alguns dos benefícios das ins- truções de vetor. Assim como as extensões de multimídia. um novo grande conjunto de opcodes é acrescentado toda vez que o tamanho do “vetor” muda na arquitetura da extensão de multimídia do x86. as extensões de multimídia podem você mesmo ser consideradas como uma arquitetura de vetor com vetores curtos que suportam apenas transferências sequenciais de dados de vetor. o vetor facilmente captura a flexibilidade nas larguras de dados. em que o hardware carrega cada n-ésimo elemento de dados na memória. em que o hardware encontra os endereços dos itens a serem carregados em um registrador de vetor. uma instrução de vetor especifica múltiplas operações. Geralmente. mas em um registrador separado. a entrada da Intel no mercado discreto de GPU para 2010 — apelidado de “Larrabee” — supostamente terá instruções de vetor. disponível em 2010. Também diferente das extensões de multimídia. expandirá a largura dos registradores SSE de 128 bits para 256 bits imediatamente. as arquiteturas de vetor são um meio muito eficaz de executar programas de processamento paralelo de dados. Detalhamento:  Dadas as vantagens do vetor. isso ainda não está claro. multiprocessadores e clusters Vetor versus extensões de multimídia Assim como as extensões de multimídia encontradas nas instruções SSE do x86. as extensões de multimídia normalmente especificam algumas poucas operações. portanto.528 Capítulo 7  Multicores. por que eles não são mais comuns fora da computação de alto desempenho? Havia preocupações sobre o estado maior para registradores de vetor aumentando o tempo de troca de contexto e a dificuldade de tratar das falhas de página nos loads e stores de vetor. Daí. Porém. são mais fáceis de evoluir com o tempo do que as extensões de multimídia na arquitetura x86. de modo que uma fração cada vez maior do tempo de proces- samento era usada para os gráficos. Porém. Detalhamento:  Outra vantagem das extensões de vetor e multimídia é que é relativamente fácil estender uma arquitetura de conjunto de instruções escalar com essas instruções para melhorar o desempenho das operações paralelas com dados. e acessos indexados. Diferente das extensões de multimídia. elas combinam melhor com a tecnologia de compilador do que extensões de multimídia. a compatibilidade binária. as transferências de dados não precisam ser contíguas. quando a lei de Moore aumentou o número de transistores disponíveis nos microprocessadores. como OpenGL e Microsoft's DirectX. consistindo em coordenadas (x. que poderiam ser acrescentadas às estações de trabalho. assim como os supercomputadores ofereceram um rico recurso de ideias para os microproces- sadores na busca por maior desempenho. Dado que a comunidade de gráficos e jogos teve objetivos diferentes da comunidade de desenvolvimento de microprocessador. a GPU evoluiu para executar muitos threads de programas sombreadores de vértice e pixel em paralelo. 7. (Outro exemplo é a arquitetura IBM Cell da Seção 7. que mais tarde entraram nos anúncios de televisão e depois nos filmes. Para renderizar milhões de pixels por frame rapidamente. Não importa se as GPUs realizam algumas tarefas mal ou que não realizem.7  Introdução às unidades de processamento de gráficos 529 Assim como a lei de Moore permitiu que a CPU melhorasse o processamento gráfico. ou GPUs. Essas placas gráficas de alto nível foram comuns na criação de imagens geradas por computador. consistindo em componentes de cor (vermelho. tanto em PCs quanto em consoles de jogos dedicados. em um sistema com uma CPU e uma GPU. y. como o PlayStation da Sony. geralmente da Silicon Graphics. e sombreamento ou renderização de fragmentos de pixels de primitivas geométricas. Os compiladores de linguagem são voltados para linguagens intermediárias padrão da indústria. na ponta estavam as placas gráficas caras. os controladores gráficos de vídeo tinham um alvo direcionado quando os recursos de processamento cresceram. O mercado de jogos em rápido crescimento encorajou muitas empresas a fazerem investimentos cada vez maiores no desenvolvimento de hardware gráfico mais rápido. Os video games por exemplo.) GPUs representam cada . junto com linguagens de sombreamento gráfico de alto nível. visto que. Esse papel lhes permitiu dedicar todos os seus recursos aos gráficos. a combinação CPU-GPU é um exemplo de multiprocessamento heterogêneo. verde. (Veja o Apêndice A para descobrir mais sobre vértices e pixels. azul. j Cada vértice pode ser desenhado independentemente. j O processamento gráfico envolve o desenho de vértices de primitivas de geome- tria 3D. alfa). em que nem todos os processadores são idênticos. a CPU pode realizá-las se for preciso. Assim. para permitir a criação de imagens com qualidade fotográfica. assim como na renderização de cada fragmento de pixel. Assim.11.) j As instruções de programação das GPUs são interfaces de programação de aplicação (APIs) de alto nível. que também foi projetada para acelerar gráficos 2D e 3D. desenham 20 a 30 vezes mais pixels que vértices. z. Uma força motriz importante para melhorar o processamento gráfico foi a indústria de jogos de computador. e esse feedback positivo levou o processamento gráfico a melhorar em um ritmo mais rápido do que o processamento de uso geral nos microprocessadores centrais. em vez de instruções de máquina. j Os tipos de dados gráficos são vértices. também permitiu que os chips do controlador gráfico de vídeo acrescentassem funções para acelerar gráficos 2D e 3D. ela evoluiu seu próprio estilo de processamento e terminologia. específicas para GPU. Quando os processadores gráficos aumentaram sua potência. Aqui estão algumas das principais características de como as GPUs se distinguem das CPUs: j GPUs são aceleradores que complementam uma CPU. de modo que não precisam ser capazes de realizar todas as tarefas de uma CPU. como linhas e triângulos. eles ganharam o nome Graphics Processing Units. para distingui-los das CPUs. Além do mais. Embora essas APIs e linguagens evoluam rapidamente para abranger novos recursos de GPU habilitados pela lei de Moore. Esse ambiente leva à inovação mais rápida em GPUs do que em CPUs. como C for Graphics (Cg) da NVIDIA e High Level Shader Language (HLSL) da Microsoft. O software de driver GPU gera instruções de máquina otimizadas. w). e pixels. a liberdade da com- patibilidade com a instrução binária permite que os projetistas de GPU explorem novas tecnologias sem temer que sejam seladas para sempre com a implementação de experimentos falhos. j Dada a confiança em muitos threads para oferecer boa largura de banda de memória. Finalmente. j A memória principal da GPU é assim orientada para largura de banda. em vez de latência. para a computação de uso geral. Além do mais. alguns a chamam de General Purpose GPUs. as memórias da GPU tradicionalmente têm tido memória principal menor que os microprocessadores convencionais. Em vez disso. Apesar disso. e ele não mostra a mesma localidade temporal que os dados nas principais aplicações. enquanto as CPUs tinham de 2 a 32GB. j As GPUs contam com um extenso paralelismo para obter alto desempenho. Além disso. j O conjunto de trabalho pode ter centenas de megabytes. Essas diferenças têm levado a diferentes estilos de arquitetura: j Talvez a maior diferença seja que as GPUs não contam com caches multinível para contornar a longa latência para a memória. im- plementando muitos processadores paralelos e muitos threads concorrentes.530 Capítulo 7  Multicores. j Diferente das CPUs. além de muitos threads. lembre-se de que. ou GPGPUs. eles desenvolveram linguagens de . as operações de precisão simples ainda serão de oito a dez vezes mais rápidas que a precisão dupla. mesmo nessas novas GPUs. Depois de cansar de tentar especificar seus problemas usando as APIs gráficas e linguagens de sombreamento de gráficos. multiprocessadores e clusters componente do vértice como um número de ponto flutuante de 32 bits.0 e 1. as GPUs podem acomodar muitos processadores paralelos. Em 2008. Logo. Embora as GPUs fossem projetadas para um conjunto mais estreito de aplicações. Ou seja. pois ela não é necessária nas aplicações gráficas. GPUs recentes estão voltadas para processadores idênticos de uso geral. de modo a oferecer mais flexibilidade na programação. Em 2008. mas as GPUs recentes agora representam cada componente como um número de ponto flutuante de precisão simples. não tem havido suporte para a aritmética de ponto flutuante com precisão dupla. Contudo. entre 0. entre o momento de uma solicitação de memória e o momento em que os dados chegam. foram anunciadas as primeiras GPUs a ter suporte para precisão dupla no hardware. as GPUs normalmente tinham 1GB ou menos. existe muito paralelismo em nível de dados nessas tarefas. Existem até mesmo chips de DRAM separados para GPUs que são mais largas e possuem largura de banda mais alta que os chips de DRAM para as CPUs. a GPU executa centenas ou milhares de threads que são independentes dessa solicitação. as GPUs recentes estão focalizando mais as instruções escalares para melhorar a facilidade de programação e a eficiência. as GPUs contavam com processadores heterogêneos de uso especial para oferecer o desempenho necessário a aplicações gráficas. Para distinguir esse estilo de uso das GPUs. j Dada a natureza de quatro elementos dos tipos de dados gráficos. você precisa incluir o tempo para transferir os dados entre a memória da CPU e a memória da GPU. as GPUs historica- mente possuem instruções SIMD. j No passado. alguns programadores questionaram se poderiam especificar suas aplicações em uma forma que lhes permitissem aproveitar o alto desempenho em potencial das GPUs.0. cada processador de GPU é altamente multithreaded. pois a GPU é um coprocessador. tornando-os mais semelhantes aos projetos multicore encontrados na computação principal. Cada um dos quatro componentes de pixel foi originalmente um inteiro não sinalizado de 8 bits. como as CPUs. as GPUs contam em ter threads suficientes para ocultar a latência para a memória. como nas CPUs. enquanto a diferença no desempenho para as CPUs seja limitada a benefícios na transferência de menos bytes no sistema de memória. devido ao uso de dados estreitos. uma linguagem de streaming para GPUs. que permite que o programador escreva programas em C para execução nas GPUs. As chamadas placa-mãe de GPU são integradas ao chip set da placa mãe. que a NVIDIA chama de multiprocessadores. como uma north bridge ou uma south bridge (Capítulo 6). Cada multiprocessador contém oito unidades de ponto flutuante de precisão simples multithreaded e unidades de processamento de inteiros. que a NVIDIA chama de processadores streaming. Quando você aprender os termos da GPU. Para ajudá-lo com essa transição ao novo vocabulário. como multithreading fine-grained e vetores. a maior versão é chamada de GeForce 8800 GTX. 345‚6 GFLOPs = seg. conforme sugerimos anteriormente. elas não apenas têm arquiteturas diferentes. As GPUs geralmente são oferecidas como uma família de chips em diferentes pontos de desempenho de preço. clock seg. verá as semelhanças nas técnicas apresentadas nas seções anteriores. Para ocultar a latência da memória. cada uma com 8 bytes de largura e com 128 MB de capacidade. mas também têm um conjunto de termos diferente. portanto. No início de 2008. 16 × 8 × 2 × 1. Um exemplo é Brook. embora com algumas restrições.35GFLOPs = seg. Os chips de GPUs baseadas em Tesla são oferecidas com algo entre 1 e 16 nós. O sistema de memória do 8800 GTX consiste em seis partições de 900MHz Graphics DDR3 DRAM. 1instr. O tamanho de memória local é. Um warp é a unidade de escalonamento.7  Introdução às unidades de processamento de gráficos 531 programação inspiradas em C para permitir que escrevam programas diretamente às GPUs. o desempenho máximo da multiplicação-adição de precisão sim- ples do chip 8800 GTX é: 8SPs 2FLOPs/instr. chamada Tesla. apresentamos uma rápida in- trodução aos termos e às ideias na arquitetura de GPU Tesla e no ambiente de programação CUDA. 768MB. O próximo passo na facilidade de programação do hardware e da linguagem de programação é a CUDA (Compute Unified Device Architecture) da NVIDIA. 0‚9 × 109 clocks 6 × 8 × 2 × 0‚9GB 86‚ 4GB 6× × × = = transf. Cada um dos 16 multiprocessadores do GeForce 8800 GTX tem um store local gerenciado por software com uma capacidade de 16KB mais 8192 registradores de 32 bits. 7. com todas sendo compatíveis em software.35GHz. seg. Como a arquitetura inclui uma instrução de multiplicação-adição de ponto flutuante com precisão simples. cada processador de streaming tem threads com suporte do hardware. e as threads ativas em um warp — até 32 — executam em . Cada grupo de 32 threads é chamado de warp. seg. A largura de banda de pico da memória GDDR3 é 8Bytes 2 transf. 1‚35 × 109 clocks 16 MPs × × × × MP SP clock seg. O uso de GPUs para a computação paralela está aumentando com sua crescente facilidade de programação. Um chip GPU discreto se encontra em uma placa separada conectada a um PC padrão através da interconexão PCI-Express. que tem 16 multiprocessadores e uma taxa de clock de 1. Introdução à arquitetura de GPU NVIDIA O Apêndice A contém muito mais detalhes sobre GPUs e apresenta minuciosamente a arqui- tetura de GPU da NVIDIA. Como as GPUs evoluíram em seu próprio am- biente. assim como o hardware T2 comuta entre threads para manter o core T2 ocupado. Cada multiprocessador Tesla consiste em oito processadores streaming.5 e 7. a arquitetura multithreaded lida com condições. permitindo que os threads tomem caminhos de desvio diferentes. Dessa forma. o melhor desempenho vem quando todas as 32 threads de um warp são executadas juntas em um padrão tipo SIMD. mostradas horizontalmente. pelos oito processadores de streaming e também segmentos de quatro ciclos de clock. Cada ciclo executa uma instrução para uma thread. multiprocessadores e clusters FIGURA 7. ou seja. descrito nas Seções 7.7  Comparando o único core de um Sun UltraSPARC T2 (Niagara 2) com um único multi- processador Tesla. O hardware junta as threads de volta em um warp totalmente ativo assim que os caminhos condicionais são concluídos.7 combina todos esses recursos e compara um multiprocessador Tesla com um core Sun UltraSPARC T2. Para obter o melhor desempenho. porém maiores. que aparecem verticalmente em blocos de quatro ciclos de clock. O core T2 é um único processador e usa multithreading com suporte do hardware. Em um estilo semelhante. paralelo no padrão SIMD. como mostra o eixo vertical. uma thread por ciclo. enquanto o Tesla pode realizar o multithread com o tempo e espaço. cada um executando oito threads paralelas por clock. A principal diferença é que o core T2 tem um processador que pode alternar as threads a cada ciclo de clock. Quando as threads de um warp tomam caminhos divergentes. Como dissemos. SIMT descobre dinamicamente quais threads de um warp podem executar a mesma instrução juntas. e quais threads independentes estão ociosas nesse ciclo. com oito threads. Ambos são multithreaded por hardware escalonando-se threads com o tempo. o hardware Tesla alterna entre warps para manter o multiprocessador Tesla ocupado. o warp executa sequencialmente os cami- nhos de código com algumas threads inativas. o hardware também examina os fluxos de endereço vindo de diferentes threads para tentar mesclar as solicitações individuais em menos transferências de bloco de memória.532 Capítulo 7  Multicores. . O core T2 contém apenas um único processador multithreaded. De modo semelhante. Contudo. o que faz com que as threads ativas sejam executadas de forma mais lenta. O multiprocessador Tesla usa multithreading de hardware fine-grained para escalonar 24 warps com o tempo. no sentido de aumentar o desempenho da memória. O multiprocessador Tesla contém oito processadores streaming e usa multithreading com suporte do hardware com 24 warps de 32 threads (oito processadores vezes quatro ciclos de clock). mostrado verticalmente. o UltraSPARC T2 escalona oito threads com suporte do hardware com o tempo. enquanto o Tesla pode comutar apenas a cada dois ou quatro ciclos de clock. que a arquitetura Tesla chama de Single-Instruction Multiple-Thread (SIMT). Um modo de comparar os dois é que o T2 só pode realizar multithread do processador com o tempo. A Figura 7. O T2 pode comutar a cada ciclo de clock. todos as 32 threads de um warp precisam ser executadas juntas em paralelo.11. sob a restrição de que os registradores por thread vezes threads por bloco de threads não ultrapasse os 8192 registradores por multiprocessador. os blocos de threads e warps com menos de 32 threads operam de modo menos eficiente do que os completos.7  Introdução às unidades de processamento de gráficos 533 enquanto a unidade de comutação mínima dos warps no microprocessador Tesla é de dois ciclos de clock por oito cores streaming. Grandes blocos de threads possuem melhor eficiência do que os pequenos. Cada grupo de 32 threads em um bloco de threads é empacotado em warps. Se fizer isso. Os programadores especificam o número de threads em um bloco de threads. mas o hardware tenta reunir os oito processadores streaming para que atuem no padrão SIMT quando múltiplos threads do mesmo warp podem estar executando juntos. 7. Ao contrário das arquiteturas de vetor. cada thread operaria em 1/16 do desempenho máximo de um warp completo de 32 threads executando em oito processadores streaming por quatro clocks. em vez de mensagens. e o número de blocos de threads que eles querem começar a executar na GPU. e eles podem ser tão pequenos quanto uma única thread. Se todos os 32 threads de um warp estivessem executando instruções independentes. A questão é como classificar cada um dos multiprocessadores Tesla e os oitos processadores principais que compõem um multi- processador Tesla. Um programa CUDA é um programa C/C + + unificado para um sistema de CPU e GPU heterogêneo. os projetistas acreditaram que existe pouca diferença de desempenho entre a comutação a cada dois ou quatro ciclos de clock. O Tesla visa o alto desempenho para o paralelismo em nível de dados. Quando os threads operam indepen- dentemente e seguem um caminho de execução independente. de modo que os progra­ madores podem pensar no multiprocessador Tesla como MIMD. O ambiente de programação CUDA também possui sua própria terminologia. eles são executados mais lentamente do que no padrão SIMT. O Tesla permite que o programador pense que o multiprocessador é um MIMD multithreaded de oito processadores streaming. Lembre-se de que já dissemos que o SIMD funcionou melhor com loops for e pior com instruções case e switch. Uma thread é um pedaço do programa para a GPU. Como Tesla é voltado para programas com muito paralelismo em nível de dados. O motivo para os programadores se importarem com os blocos de threads é que todos os threads no bloco de threads são escalonados para serem executados no mesmo multiprocessador. mas os programadores precisam ter o cuidado de escrever instruções de fluxo de controle que permitem que o hardware SIMT execute programas CUDA no padrão SIMD para oferecer o desempenho desejado. eles podem se comunicar por meio de loads e stores. e o hardware se tornou muito mais simples restringindo a frequência de comutação. Claramente. o escalonador também particiona o store local de 16KB dinamicamente entre os diferentes blocos de threads. com 16 multiprocessadores Tesla. enquanto facilita para os programadores lidarem com cases paralelos independentes em nível de thread. que contam com um compilador de vetoriza- ção para reconhecer o paralelismo em nível de dados em tempo de compilação e gerar . de modo que todos compartilham a mesma memória local. Um bloco de threads pode ter até 512 threads.6. Um escalonador de hardware tenta escalonar múltiplos blocos de threads por multi- processador quando for possível. contra cada ciclo de clock. Assim. pois todos os 32 threads de um warp compartilham uma única unidade de busca de instrução. o GeForce 8800 GTX. cada thread independente tem seu próprio PC efetivo. é um MIMD. Ele é executado na CPU e despacha o trabalho paralelo para a GPU. O compilador CUDA aloca registradores a cada thread. Assim. Esse trabalho consiste em uma transferência de dados da memória principal e um despacho de thread. Como dis- semos. Colocando as GPUs em perspectiva GPUs como a arquitetura Tesla da NVIDIA não se encaixam muito bem nas classificações anteriores dos computadores. como a Figura 7. atrasos causados pela disputa por uma parte da rede. e o switch aparece como um círculo colorido. o número de links em um switch que se conectam à rede. A primeira melhoria em relação a um barramento é uma rede que conecta uma sequência de nós: Essa topologia é chamada de anel. Outra obrigação da rede pode ser tolerância a falhas. As redes normalmente são desenhadas como gráficos. Assim. . e desempenho variável dependendo do padrão de comunicação. Por exemplo. algumas mensagens terão um salto por nós intermediários até que cheguem ao destino final. todos os links são bidirecionais. Verifique você Verdadeiro ou falso: GPUs contam com chips de DRAM gráficos para reduzir a latência mesmo da memória e. ou seja. nesta era de chips de potência limitada. GPUs Tesla não precisam de compiladores de vetorização. o tamanho dos links quando a rede é mapeada no chip. Essa categorização é uma indicação de que a GPU Tesla está ganhando terreno na arquitetura do computador. FIGURA 7. a largura (número de bits) por link. Nesta seção. a eficiência de potência das diferentes organizações pode superar outros aspectos. as implementações de hardware da arquitetura Tesla descobrem o paralelismo em nível de dados entre os threads em tempo de execução. portanto. O desempenho da rede também tem muitas faces. multiprocessadores e clusters instruções de vetor. e tornam mais fácil para o programador lidar com as partes do programa que não possuem paralelismo em nível de dados. Como alguns nós não são conectados diretamente. a informação pode fluir em qualquer direção. Ele inclui a latência em uma rede não carregada para enviar e receber uma mensagem. Finalmente. O nó processador-memória aparece como um quadrado preto. Esta seção revisa os prós e os contras de diferentes redes de multiprocessadores.8  multiprocessador Os chips multicore exigem que as redes nos chips conectem os cores. alguns cores podem ser adjacentes e outros podem estar no outro lado do chip. Introdução às topologias de rede 7. Os custos de rede incluem o número de switches.8 coloca as GPUs em uma classificação que compara o paralelismo em nível de instrução com o paralelismo em nível de dados e se ele é descoberto em tempo de compilação ou execução. a vazão em termos do número máximo de mensagens que podem ser transmitidas em determinado período de tempo. a Figura 7.8  Categorização de hardware das arquiteturas de processador e exemplos baseados em estático versus dinâmico e ILP versus DLP. pois os sistemas podem ter de operar na presença de componentes defeituosos. com cada arco do gráfico re- presentando um link da rede de comunicação. Todas as redes consistem em switches cujos links vão para os nós processador-memória e para outros switches. Para explicar melhor essa técnica exclusiva. aumentar o desempenho em aplicações gráficas.534 Capítulo 7  Multicores. 9 ilustra duas das topologias mais comuns. 7. Para as redes totalmente rede que conecta nós processador-memória fornecendo conectadas. A tremenda melhoria no desempenho das redes totalmente conectadas é anulada pelo enorme aumento no custo. e representa o melhor caso. a largura de banda de rede total é P × (P . surge a questão de onde desenhar a linha imaginária quando fizer o corte da máquina. Se um único link for tão rápido quanto o barramento. de modo que a resposta é escolher a divisão que gera o desempenho de rede mais pessimista. de links. Para a rede de anel apresentada. Tomamos a visão pessimista porque programas paralelos normalmente são limitados pelo elo mais fraco na cadeia de comunicação.1)/2. Depois você soma a largura de banda dos links A largura de banda entre duas partes iguais de um multiprocessador. A topologia de cubo n booliana é uma interconexão n-dimensional com 2n nós. n nós com o vizinho mais próximo. Como algumas topologias de rede não são simétricas. Como existem diversas topologias para escolher. cada uma com metade dos nós. entre cada nó. barramento. A avaliação do sucesso depende em grande parte da natureza da comunicação na carga de trabalho de programas paralelos executados na máquina. No outro extremo de um anel está a rede totalmente conectada. mas somente uma minoria foi utilizada em processadores paralelos comerciais. pode se referir à velocidade de um a largura de banda de rede total seria P vezes a largura de banda do link. As máquinas reais cons- tantemente acrescentam links extras a essas topologias simples para melhorar o desempe- nho e a confiabilidade. . vezes a largura de banda desse link. e é uma vez a largura de banda de link para o multiprocessador no pior caso. incluímos outra métrica que é mais próxima do pior caso: a largura de banda da corte. que é a largura de banda de cada link multiplicado pelo número rede  Informalmente. rede totalmente conectada Uma sador tem um link bidirecional com cada outro processador. em que cada proces. Esta é calculada dividindo-se a máquina em duas largura de banda de corte  partes.9  Topologias de rede que apareceram nos processadores paralelos comerciais. com P processadores. e os quadrados pretos representam nós processador-memória. Os círculos coloridos representam switches. Duas são comuns. Em outras palavras. Embora um switch tenha muitos links.8  Introdução às topologias de rede multiprocessador 535 Diferente de um barramento. o anel tem apenas o dobro da velocidade de um barramento no pior caso. que cruzam essa linha divisória imaginária. A largura de banda de corte de um anel é Essa medida é para uma divisão do duas vezes a largura de banda do link. Para balancear esse melhor caso. exigindo n links por switch (mais um para o processador) e. Isso inspira os engenheiros a inventarem novas topologias que estão entre o custo dos anéis e o desempenho das redes totalmente conectadas. A Figura 7. a taxa de transferência de pico de uma rede. geralmente apenas um vai para o processador. calcule todas as larguras de banda de corte e escolha a menor. essas topologias básicas têm sido suplementadas com arcos extras para melhorar o desempenho e a confiabilidade. e a largura de banda de corte um link de comunicação dedicado é (P/2)2. A primeira é a largura de largura de banda de banda de rede total. O número de topologias diferentes que foram discutidas nas diversas publicações seria difícil de contar. FIGURA 7. a largura de único link ou a taxa de transferência banda de rede total de um barramento é a largura de banda desse barramento. ou duas coletiva de todos os links na rede. Essa é uma métrica do pior caso. um anel é capaz de realizar muitas transferências simul- tâneas. mas é P vezes mais rápido no melhor caso. portanto. Constantemente. métricas de desempenho são necessárias a fim de distinguir esses projetos. ou 48 switches. em que n é o número de processadores. Os switches nesses desenhos são mais simples do que nos desenhos anteriores. o crossbar utiliza 64 switches contra 12 caixas de switch. qualquer nó se comunique com qualquer outro nó em uma passada pela rede. multiprocessadores e clusters FIGURA 7. Nesse caso. A caixa de switch em c pode passar A para C e B para D ou B para C e A para D. e fornece um pequeno switch em assim podem ser compactados de forma mais densa. O crossbar usa n2 switches. O crossbar. reduzindo assim a distância e aumen- cada nó. pois os links são unidirecionais. enquanto a rede Ômega usa 2n log2n das caixas de switch grandes. cada uma composta logicamente por quatro dos switches menores.10 não pode enviar uma mensagem de P0 a P6 ao mesmo tempo em comunique com qualquer outro nó que envia uma mensagem de P1 a P7. A distância de cada link afeta o custo de comunicação em uma alta taxa de clock — geralmente. Por exemplo.10 ilustra duas das organiza- memórias por meio do fornecimento ções multiestágio mais comuns. tando o desempenho. mas pode rede crossbar  Uma rede que ocorrer disputa entre as mensagens. Os tipos de redes multiestágio rede que conecta nós processadores de são tão numerosos quanto as redes de único estágio. pode aceitar qualquer combinação de mensagens entre os processadores. na rede Ômega. Essas redes normalmente são chamadas redes multiestágio para re- rede totalmente conectada Uma fletir as múltiplas etapas em que uma mensagem pode trafegar. Uma alternativa a colocar um processador em cada nó de uma rede é deixar apenas o switch rede multiestágio  Uma rede que em alguns desses nós. Os switches são menores que os nós processador-memória-switch. Uma rede totalmente conectada ou crossbar permite que de um link de comunicação dedicado entre cada nó.10  Topologias comuns de rede multiestágio para oito nós. dependendo do padrão de comunicação.536 Capítulo 7  Multicores. porém. Distâncias mais curtas também facilitam a atribuição de mais fios . em uma passada pela rede. quanto maior a distância. a permite que qualquer nó se rede Ômega na Figura 7. Implementando topologias de rede Esta análise simples de todas as redes nesta seção ignora considerações práticas importantes na construção de uma rede. enquanto a rede Ômega não pode. A Figura 7. os dados entram na parte de baixo e saem pelo link da direita. mais dispendioso é trabalhar em uma taxa de clock alta. Uma rede Ômega usa menos hardware do que a rede crossbar (2n log2n contra n2 switches). 9  Benchmarks de multiprocessador Como vimos no Capítulo 1. Você pode executar tantas cópias dos programas quantas desejar. em vez disso. A preocupação final é com a potência. A conclusão é que as topologias que parecem ser elegantes quando esboçadas em um quadro podem ser impraticáveis quando construídas em silício. j SPLASH e SPLASH 2 (Stanford Parallel Applications for Shared Memory) foram es- forços realizados por pesquisadores na Stanford University na década de 1990 para reunir um conjunto de benchmarks paralelo. Duas vezes por ano. Ele inclui kernels e aplicações. desde que calcule o resultado apro- priado. embora você deva ter cuidado ao comparar resultados para programas executando pro- blemas com diferentes tamanhos.org. se alguém mais ganhar. embora venha com dois conjuntos de dados. Os resultados afetam não apenas as vendas de sistemas comerciais. eles mereçam ganhar porque possuem um sistema genuinamente melhor. como SPEC CPU 2006 (veja Capítulo 1). deixando que o usuário escolha qualquer tamanho de problema. uma boa regra é que você não pode mudar o benchmark.6 representa uma pequena fração do código fonte do benchmark Linpack. Ou seja. Muitos benchmarks de multiprocessador seguem essas tradições. Assim.top500. pois a potência para conduzir por muitos fios a partir de um chip é menor se os fios forem curtos. os participantes querem ganhar a competição. A Figura 7. também descritos a seguir: j Linpack é uma coleção de rotinas de álgebra linear. Esse desejo leva a regras para garantir que os resultados do benchmark não sejam simplesmente truques de engenharia para esse benchmark. e existe uma única resposta apropriada. SPECrate executa muitas cópias do programa simultaneamente. Em vez de relatar o desempenho dos programas in- dividuais. Para evitar possíveis truques. ele mede o paralelismo em nível de tarefa. muitos benchmarks permitem pouca facilidade de expansão. 7. pois não há comunicação entre as tarefas. O código-fonte e os conjuntos de dados são fixos. Qualquer desvio dessas regras torna os resultados inválidos. O primeiro nessa lista é considerado pela imprensa como o computador mais rápido do mundo. Uma exceção comum é ser capaz de aumentar o tamanho do problema de modo que você possa executar o benchmark em sistemas com um número bem diferente de processadores. Problemas de potência podem forçar chips multicore a contarem com topologias de grade simples. Fios mais curtos também são mais baratos do que os mais longos. Outra limitação prática é que os desenhos tridimensionais precisam ser mapeados nos chips que são basicamente mídia bidimensional. mas também a reputação dos projetis- tas desses sistemas. mas. Esse benchmark requer expansão forte. Além do mais. de modo que essa novamente é uma forma de expansão fraca. e as rotinas para realizar a elimi- nação Gaussiana constituem o que é conhecido como benchmark Linpack. em vez de exigir muita facilidade. por exemplo. 7.11 é um resumo de vários benchmarks paralelos. avanços que melhoram o desempenho das aplicações reais. pois é uma forma altamente visível de tentar determinar qual sistema é melhor. mas eles também querem ter certeza de que.9  Benchmarks de multiprocessador 537 no link. A rotina DAXPY no exemplo da Seção 7. os 500 computadores com o desempenho Linpack mais rápido são publicados em www. sistemas de benchmarking sempre é um assunto delicado. mas é responsável pela maior parte do tempo de execução do benchmark. . além de muitos da comu- nidade de computação de alto desempenho. Logo. j SPECrate é uma métrica de vazão baseada nos benchmarks SPEC CPU. ele permite que o usuário reescreva o Linpack em qualquer formato e em qualquer linguagem. semelhante em objetivos ao conjunto de benchmarks SPEC CPU. Ele permite expansão fraca. eles consistem em cinco kernels. esses benchmarks podem ser reescritos. três contam com paralelismo em pipeline. Ela vem com uma biblioteca. Ela threads) e OpenMP (Open MultiProcessing). OpenMP  Uma API para multiprocessamento de memória j O recente conjunto de benchmarks PARSEC (Princeton Application Repository for Shared compartilhada em C. biblioteca e diretivas de runtime. e permitem Pthreads  Uma API do UNIX para expansão fraca.11  Exemplos de benchmarks paralelos.538 Capítulo 7  Multicores. Eles focalizam mercados emergentes e inclui diretivas de compilador. Oito contam com paralelismo de dados. Tomados da dinâmica de fluidos computacional. multiprocessadores e clusters FIGURA 7. definindo alguns poucos conjuntos de dados. que é executada em plataformas UNIX e Microsoft. C++ ou Memory Computers) consiste em programas multithreaded que usam Pthreads (POSIX Fortran. Assim como o Linpack. j Os benchmarks paralelos NAS (NASA Advanced Supercomputing) foram outra ten- tativa da década de 1990 de realizar o benchmark em multiprocessadores. mas as regras exigem que a linguagem de programação só possa ser C ou Fortran. e um com paralelismo não estruturado. uma consistem em nove aplicações e três kernels. . criar e manipular threads. Verdadeiro ou falso: a principal desvantagem com as técnicas convencionais de benchmarks Verifique para computadores paralelos é que as regras que garantem justiça também suprimem a você mesmo inovação. seria especialmente útil se tivéssemos um modelo sim- ples que oferecesse ideias para o desempenho de diferentes projetos. Mesmo assim.10  Roofline: um modelo de desempenho simples 539 O lado negativo dessas restrições tradicionais dos benchmarks é que a inovação é limi- tada principalmente a arquitetura e compilador. Estruturas de dados melhores. pois oferece ideias para o comportamento dos programas. mas lembre-se de que as aplicações reais são combinações de muitos kernels.9. a sabedoria convencional em arquitetura de computador levou a projetos de microprocessador seme- lhantes. Ele não é um modelo perfeito. redução de mapa e travessia de gráfico. Além do mais. Alguns exemplos são matrizes esparsas. O sistema poderia ganhar. pois isso geraria um resultado ilusório. pois ignora fatores potencialmente importantes. à medida que o número de cores por chip aumenta. mas os microprocessadores eram todos da mesma escola de projeto. Para que essa revolução tenha sucesso. o modelo 3Cs tem sido popular há 20 anos. além de novas arquiteturas e compiladores. algoritmo e linguagem de programação. precisamos encorajar a inovação em todos os níveis. por causa do algoritmo. na Figura 7. . Assim. uma falha pode ser atribuída à capacidade em um projeto e a uma falha de conflito em outra cache do mesmo tamanho. Roofline: um modelo de desempenho 7. digamos.10    simples Esta seção é baseada em um artigo de Williams e Patterson [2008]. ajudando arquitetos e programadores a melhorarem suas criações com base em concepções desse modelo. emissão de instrução superescalar. pois não existe sabedoria convencional sobre qual arquitetura tornará mais fácil escrever programas de processamento paralelo corretos. O modelo 3Cs do Capítulo 5 é uma analogia. Quase todo computador desktop e servidor utilizava caches. previsão de desvio e execução fora de ordem. A ideia dos padrões de projeto é que o desempenho de determinada aplicação é na realidade a soma ponderada de vários kernels que implementam esses padrões de projeto. Esses padrões de projeto são implementados por frameworks ou kernels. Embora essas orientações sejam compreensíveis quando os alicerces da computação são relativamente estáveis — como eram na década de 1990 e na primeira metade desta década —. Dada a diversidade crescente. 7. grade estruturada. Ele não precisa ser perfeito. Para descobrir esse modelo. Uma técnica recente foi defendida pelos pesquisadores na Universidade da Califórnia em Berkeley. o sistema com o solucionador de matriz esparsa mais rápido está livre para usar qualquer estrutura de dados. e não por causa do hardware ou do compilador. máquinas de estados finitos. ele possui algumas esquisitices. diretiva de alocação de bloco e diretiva de substituição de bloco. Os conjuntos de instruções variavam. pipelining. No passado. vamos começar com os 13 padrões de projeto de Berkeley. Além do mais. elas são indesejáveis no início de uma revolução. que executem de forma eficiente e se expandam à medida que o número de cores aumenta com o tempo. apenas criterioso. Eles identificaram 13 padrões de projeto que afirmam que será parte das aplicações do futuro. Veremos exemplos desses benchmarks na Seção 7.11. A passagem para multicore provavelmente significa que os microprocessadores se tornarão mais diversos. linguagens de programação e assim por diante geralmente não podem ser usados. como tamanho de bloco. um único fabricante provavelmente oferecerá diferentes números de cores por chip em diferentes pontos de preço ao mesmo tempo. elas esperam encorajar inovações em qualquer nível do sistema. Por exemplo. Vamos avaliar os kernels individuais aqui. Mantendo as definições em um alto nível. algoritmos. Um modo de encontrar o desempenho de pico da memória é o benchmark Stream. Logo. Para chips multicore. A Figura 7. Patterson. e não pa- ra cada kernel. o desempenho de pico em ponto flutuante é um limite sobre a velocidade desses kernels em determinado computador. O modelo roofline O modelo simples proposto reúne desempenho de ponto flutuante.13 mostra o modelo. o desempenho de pico em ponto flutuante é o desempenho de pico coletivo de todos os cores no chip. FIGURA 7. (Veja a seção Detalhamento na Seção “Projetando o sistema de memória para suportar caches”. pois coloca muito menos demanda sobre o sistema de memória. mostra a intensidade aritmética de vários dos padrões de projeto de Berkeley da Figura 7. . Observe que o gráfico é uma escala log-log. multiprocessadores e clusters Embora haja versões com diferentes tipos de dados.12 memória principal. especificada como o número de operações de ponto flu- tuante para executar o programa dividido pelo número de bytes acessados na memória principal [Williams.11. de modo que o desempenho de pico da memória pode ser definido pelo sistema de memória por trás das caches. que é feito uma vez para um computador. ponto flutuante é comum em várias implementações.0 GFLOPs/segundo. mas existem muitos kernels com intensidades aritméticas independentes do tamanho do problema. 2008]. As demandas no sistema de memória podem ser estimadas dividindo-se esse desempe- nho de pico em ponto flutuante pelo número médio de operações de ponto flutuante por byte acessado: OperaçõesdePF/Seg = Bytes/Seg OperaçõesdePF/Byte intensidade aritmética  A razão A razão entre operações de ponto flutuante por byte de memória acessada é chamada entre as operações de ponto de intensidade aritmética. Para os kernels nesse primeiro caso. intensidade arit- mética e desempenho da memória em um gráfico bidimensional [Williams. Se houvesse múltiplos microprocessadores no sistema. Alguns kernels possuem uma intensidade aritmética que se expande com o tamanho do problema. Ela pode ser calculada apanhando-se o número total de ope- flutuante em um programa e o rações de ponto flutuante para um programa dividido pelo número total de bytes de dados número de bytes de dados acessados por um programa a partir da transferidos para a memória principal durante a execução do programa. O eixo-X horizontal é a intensidade aritmética. Patterson. no Capítulo 5. O conjunto dos kernels que consideramos aqui não se encaixa em caches no chip.) A Figura 7.12  Intensidade aritmética.540 Capítulo 7  Multicores. variando de 1/8 FLOPs/DRAM acessados por byte a 16 FLOPs/DRAM acessados por byte. como Matrizes Densas. O eixo-Y vertical é o desempenho de ponto flutuante alcançável de 0. a expansão fraca pode levar a diferentes resultados.5 a 64. 2008]. O desempenho de pico em ponto flutuante pode ser encontrado usando as especificações de hardware mencionadas anteriormente. você multiplicaria o pico por chip pelo número total de chips. 13: GFLOPs/seg alcançável = Min(LBmemória de pico × Intensidadearitmética. então quase todo kernel poderá potencialmente atingir o desempenho máximo. A linha vertical pontilhada à direita representa o Kernel 2. Logo. Observe que o “ponto de cumeeira”. pois ela não varia por kernel. pois esse é um limite do hardware.) A linha vertical pontilhada à esquerda representa o Kernel 1. Patterson. Podemos desenhar uma linha horizontal mostrando o desempenho de pico em ponto flutuante do computador. 7. Na Figura 7. o que significa que por fim está limitado pela largura de banda da memória. Ela é limitada apenas computacionalmente a 16 GFLOPs/seg.) Para determinado kernel. Dada uma roofline de um computador. o desempenho real em ponto flutuante não pode ser maior que a linha horizontal. que tem uma intensidade aritmética de 4 FLOPs/byte. essa linha é a média das quatro. Este exemplo tem um desempenho de pico de 16 GFLOPs/seg e uma largura de banda de memória de pico de 16GB/seg do benchmark Stream. dependendo de sua intensidade aritmética. o que significa que o desempenho é com- putacionalmente limitado. você pode aplicá-la repetidamente. Podemos expressar os limites como uma fórmula para desenhar a linha no gráfico da Figura 7. em que os telhados diagonal e horizontal se encon- tram. A “roofline” define um limite superior no desempenho de um kernel.13  Modelo Roofline [Williams. Se desenhássemos uma linha vertical passando por esse ponto. oferece uma percepção interessante para o computador. . podemos desenhar uma terceira linha que mostre o desempenho máximo em ponto flutuante que o sistema de memória desse computador pode suportar para determinada intensidade aritmética. o desempenho do kernel nesse computador teria de ficar em algum lugar nessa linha. Obviamente. então somente os kernels com intensidade aritmética muito alta podem alcançar o desem- penho máximo desse computador. Se for muito longe à direita. e o kernel 1 é um exemplo do segundo. podemos encontrar um ponto no eixo X com base em sua intensidade aritmética. bytes/segundo é simplesmente uma linha diagonal em um ângulo de 45 graus nessa figura. Veremos exemplos de ambos em breve. ou atinge a parte inclinada do telado. (Esses dados são baseados no AMD Opteron X2 (Revision F) usando dual cores executando a 2GHz em um sistema dual socket. (Como o Stream na realidade tem quatro medições. Se for muito à esquerda. que tem uma intensidade aritmética de 0. o kernel 2 é um exemplo do primeiro. 2008]. Como poderíamos desenhar o desempenho de pico da memória? Como o eixo X é FLOPs/byte e o eixo Y é FLOPs/segundo. Ela é limitada pela largura de banda de memória a não mais que 8 GFLOPs/seg nesse Opteron X2. Desempenhode picoem ponto flutuante) As linhas horizontal e diagonal dão nome a esse modelo simples e indicam seu valor. Se pensarmos na intensidade aritmética como um poste que atinge o telhado.10  Roofline: um modelo de desempenho simples 541 FIGURA 7.13.5 FLOPs/byte. ou ele atinge a parte plana do telado. Além de dobrar o número de cores. e em que ordem? Para reduzir os gargalos computacionais. Esse equilíbrio é necessário ou porque o computador admite uma instrução multiplicação-adição unificada (veja a seção Detalhamento na Seção “Aritmética de precisão”. o ponto de cumeeira passa de 1 no Opteron X2 para 5 no Opteron X4. e não instruções de inteiros. está em preto. Para simplificar o projeto da placa.542 Capítulo 7  Multicores. que não é encontrada no Opteron X2. Suponha que seu programa esteja muito abaixo desse limite. e a roofline do Opteron X4 está colorida. Que otimizações você deverá realizar. A Figura 7. Como os dois sistemas que estamos comparando possuem taxas de clock semelhantes — 2.2GHz para o Opteron X2 versus 2.14 compara os modelos roofline para ambos os sistemas.3GHz para o Opteron X4 — o Opteron X4 tem mais de quatro vezes do desempenho de ponto flutuante de pico do Opteron X2 com a mesma largura de banda de DRAM. O Opteron X4 também tem uma cache L3 de 2MB. Logo. ou seus conjuntos de trabalho terão de caber nas caches do Opteron X4. O modelo roofline oferece um limite superior para o desempenho. Mix de operações de ponto flutuante. a mesma largura de banda de memória de pico. Como poderíamos esperar. eles usam o mesmo soquete. o Opteron X4 também tem o dobro do desempenho de pico em ponto flutuante por core: os cores do Opteron X4 podem emitir duas instruções SSE2 de ponto flutuante por ciclo de clock. os kernels precisam de uma in- tensidade aritmética maior que 1. O ponto de cumeeira maior do Opteron X4 significa que os kernels que eram computacionalmente limitados no Opteron X2 poderiam ser limitados pelo desempenho da memória no Opteron X4. FIGURA 7. Logo. para ver um ganho de desempenho na próxima geração. A roofline do Opteron X2. eles possuem os mesmos canais de DRAM e. no Capítulo 3) ou porque a unidade de ponto flutuante tem um número igual de somadores de ponto flutuante e multiplicadores de ponto flutuante. portanto. as duas otimizações a seguir podem ajudar a quase todo kernel: 1.14  Modelos roofline de duas gerações de Opterons. O melhor desempenho também requer que uma fração signi- ficativa do mix de instruções seja operações de ponto flutuante. O desempenho de pico em ponto flutuante para um computador normalmente exige um número igual de adições e multi- plicações quase simultâneas. . enquanto os cores do Opteron X2 emite no máximo uma. multiprocessadores e clusters Comparando duas gerações de Opterons O AMD Opteron X4 (Barcelona) com quatro cores é o sucessor do Opteron X2 com dois cores. que é a mesma que na Figura 7.11. 7. o desempenho mais alto exige manter muitas operações da memória no ato. e a otimização 4. Para as arquiteturas x86. que melhora o ILP. 2. A espessura da lacuna entre o teto e o próximo limite mais alto é a recompensa por tentar essa otimização. você já deverá ter ultrapas- sado todos os tetos abaixo. A roofline computacional pode ser encontrada nos manuais. O teto de memória exige a execução de experimentos em cada computador. de modo que os processadores raramente precisam acessar a memória dos outros chips. o Kernel 2 cai no trapezóide azul à direita. para ultrapassar o teto mais alto. todos poderão usar os resultados a fim de priorizar suas otimizações para esse computador. A intensidade aritmética de um kernel determina a região de otimização.16 combina os tetos da Figura 7. mostrando os tetos computacionais no gráfico superior e os tetos da largura de banda de memória no gráfico inferior. Essa otimização tenta alocar dados e as threads encarregadas de operar sobre esses dados no mesmo par memória-processador. também vêm dos manuais desse computador. as duas otimizações a seguir podem ajudar: 1. Embora os tetos mais altos não sejam rotulados com as duas otimizações. ele sugere começar com as otimizações 2 e 4. que sugere trabalhar apenas nas otimizações computacionais. Uma forma é desdobrando loops. Podemos pensar em cada uma dessas otimizações como um “teto” abaixo da roofline apropriada. Observe que as linhas verticais do Kernel 1 caem abaixo da otimização de desequilíbrio de ponto flutuante.10  Roofline: um modelo de desempenho simples 543 2. Observe que as otimizações computacionais e as otimizações de largura de banda da memória se sobrepõem para grande parte da intensidade aritmética. Para reduzir os gargalos da memória. Se um kernel caísse no triângulo cinza no canto inferior esquerdo.15 sugere que a otimização 2. sugere quais otimizações tentar. . isso está implícito nessa figura.15 acrescenta tetos ao modelo roofline da Figura 7.13. por sua vez. como o equilíbrio de ponto flutuante. Melhore o paralelismo em nível de instrução e aplique SIMD. tem um grande benefício para melhorar a largura de banda da memória nesse computador. Por exemplo. e a roofline de memória pode ser encontrada executando-se o benchmark Stream. O objetivo aqui é melhorar o código do compilador para aumentar o ILP. Se o sistema tiver múltiplos chips. o desempenho mais alto surge com a busca. Assim. que melhora a afinidade de memória. A maioria dos microprocessadores de hoje inclui um con- trolador de memória no mesmo chip com o microprocessador. A Figura 7. significando que você não pode ultrapassar um teto sem realizar a otimização associada. que. Os tetos computacionais. que é mais fácil de se fazer executando instruções de pré-busca do software.15 em um único gráfico. execução e commit de três a quatro instruções por ciclo de clock (veja Capítulo 4). Além do mais. a Figura 7. tem um grande benefício para melhorar a computação nesse computador.16 para indicar as diferentes estratégias de otimização. Três regiões são sombreadas de formas diferentes na Figura 7. O Kernel 1 cai no paralelogramo azul-cinza no meio. de modo que elas devem ser usadas sempre que possível. O segundo caso reduz o desempenho. A Figura 7. em vez de esperar até que os dados sejam exigidos pela computação. A boa notícia é que esse processo só precisa ser feito uma vez por computador. Afinidade de memória. de modo que a otimização 1 pode ser desnecessária. Para arquiteturas superescalares. e o restante requer que os acessos pela interconexão do chip acessem a DRAM que é local a outro chip. isso sugeriria tentar apenas otimizações de memória. pois quando alguém caracterizar os tetos de um computador. uma única instrução SIMD pode operar sobre pares de operandos de precisão dupla. Normalmente. que sugere tentar os dois tipos de otimização. para determinar a lacuna entre eles. isso significa que os mesmos endereços vão para a DRAM que é local a um chip. Pré-busca do software. O modelo roofline pode ajudar a decidir quais dessas otimizações serão realizadas e em que ordem. 544 Capítulo 7  Multicores, multiprocessadores e clusters FIGURA 7.15  roofline com tetos. O gráfico superior mostra os “tetos” computacionais de 8 GFLOPs/seg se o mix de operações de ponto flutuante estiver desequilibrado e 2 GFLOPs/seg se as otimizações para aumentar o ILP e o SIMD também estiverem faltando. O gráfico inferior mostra os tetos de largura de banda da memória de 11GB/ seg sem pré-busca de software e 4,8GB/seg se as otimizações de afinidade de memória também estiverem faltando. Até aqui, estivemos supondo que a intensidade aritmética é fixa, mas esse não é real­ mente o caso. Primeiro, existem kernels cuja intensidade aritmética aumenta com o tamanho do problema, como para os problemas Matriz Densa e N-body (veja Figura 7.12). Na realidade, esse pode ser o motivo para os programadores terem mais sucesso com a ex- pansão fraca do que com a expansão forte. Segundo, as caches afetam o número de acessos que vão para a memória, de modo que as otimizações que melhoram o desempenho da cache também melhoram a intensidade aritmética. Um exemplo é melhorar a localidade temporal desdobrando loops e depois agrupando instruções com endereços semelhantes. Muitos computadores possuem instruções de cache especiais, que alocam dados em uma cache, mas não preenchem primeiro os dados da memória nesse endereço, pois eles logo 7.10  Roofline: um modelo de desempenho simples 545 FIGURA 7.16  Modelo roofline com tetos, áreas sobrepostas sombreadas e os dois kernels da Figura 7.13. Os kernels cuja intensidade aritmética se encontra no trapezóide azul à direita deverão focalizar otimizações de computação, e os kernels cuja intensidade aritmética se encontra no triângulo cinza no canto inferior esquerdo devem focalizar otimizações de largura de banda de memória. Aqueles que se encontram no paralelogramo azul-cinza no meio precisam se preocupar com ambos. Quando o Kernel 1 cai no paralelogramo do meio, tente otimizar ILP e SIMD, afinidade de memória e pré-busca de software. O Kernel 2 cai no trapezoide à direita; portanto, tente otimizar ILP e SIMD e o equilíbrio das operações de ponto flutuante. serão modificados. Essas duas otimizações reduzem o tráfego da memória, movendo assim o poste da intensidade aritmética para a direita por um fator de, digamos, 1,5. Esse des- locamento para a direita poderia colocar o kernel em uma região de otimização diferente. A próxima seção usa o modelo roofline para demonstrar a diferença em quatro micro- processadores multicore recentes, para dois kernels de aplicação reais. Embora os exemplos anteriores mostrem como ajudar os programadores a melhorarem o desempenho, o modelo também pode ser usado por arquitetos para decidir onde eles otimizariam o hardware para melhorar o desempenho dos kernels que acreditam que serão importantes. Detalhamento:  Os tetos são ordenados de modo que os mais baixos são mais fáceis de oti- mizar. Logicamente, um programador pode otimizar em qualquer ordem, mas ter essa sequência reduz as chances de desperdiçar esforço em uma otimização que não possui benefício devido a outras restrições. Assim como o modelo 3Cs, desde que o modelo roofline ofereça percepções, um modelo pode ter esquisitices. Por exemplo, ele supõe que o programa tem balanceamento de carga entre todos os processadores. Detalhamento:  Uma alternativa ao benchmark Stream é usar a largura de banda bruta da DRAM como roofline. Enquanto as DRAMs definem um limite rígido, o desempenho real da memória normalmente está tão distante desse limite que não é tão útil como um limite superior. Ou seja, nenhum programa pode chegar perto desse limite. A desvantagem de usar o Stream é que uma programação muito cuidadosa pode exceder os resultados do Stream, de modo que a roofline da memória pode não ser um limite tão rígido quanto a roofline computacional. Ficamos com o Stream porque menos programadores serão capazes de oferecer mais largura de banda de memória do que o Stream descobre. Detalhamento:  Os dois eixos usados anteriormente eram operações de ponto flutuante por segundo e intensidade aritmética dos acessos à memória principal. O modelo roofline poderia ser usado para outros kernels e computadores cujo desempenho foi uma função de diferentes métricas de desempenho. 546 Capítulo 7  Multicores, multiprocessadores e clusters Por exemplo, se o conjunto de trabalho couber na cache L2 do computador, a largura de banda desenhada na roofline diagonal poderia ser largura de banda de cache L2, em vez da largura de banda da memória principal, e a intensidade aritmética no eixo X seria baseada em FLOPs por byte da cache L2 acessado. A linha de desempenho L2 diagonal subiria, e o ponto de cumeeira provavelmente se moveria para a esquerda. Como um segundo exemplo, se o kernel fosse classificado, os registros classificados por segundo poderiam substituir as operações de ponto flutuante por instrução no eixo X e a in- tensidade aritmética se tornaria registros por byte de DRAM acessado. O modelo roofline poderia ainda funcionar para um kernel com uso intenso de E/S. O eixo Y seria operações de E/S por segundo, o eixo X seria o número médio de instruções por operação de E/S, e a roofline mostraria a largura de banda de E/S de pico. Detalhamento:  Embora o modelo roofline apresentado seja para processadores multicores, ele certamente também funcionaria para um processador. Vida real: benchmarking de quatro 7.11    multicores usando o modelo roofline Dada a incerteza sobre a melhor maneira de proceder nessa revolução paralela, não é sur- presa que vejamos tantos projetos diferentes quantos chips multicore. Nesta seção, vamos examinar quatro sistemas multicore para dois kernels dos padrões de projeto da Figura 7.11: matriz esparsa e grade estruturada. (As informações nesta seção são de [Williams, Oliker, et al., 2007], [Williams, Carter, et al., 2008], [Williams and Patterson, 2008].) Quatro sistemas multicore A Figura 7.17 mostra a organização básica dos quatro sistemas, e a Figura 7.18 lista as principais características dos exemplos desta seção. Estes são todos sistemas de soquete dual. A Figura 7.19 mostra o modelo de desempenho roofline para cada sistema. O Intel Xeon e5345 (apelidado de “Clovertown”) contém quatro cores por soquete, empacotando dois chips dual core em um único soquete. Esses dois chips compartilham um barramento front side que é conectado a um chip set north bridge separado (ver Capítulo 6). Esse chip set north bridge admite dois barramentos front side e, portan- to, dois soquetes. Ele inclui o controlador de memória para as Fully Buffered DRAM DIMMs (FBDIMMs) de 667MHz. Esse sistema de soquete dual usa uma taxa de clock do processador de 2,33GHz e tem o mais alto desempenho de pico dos quatro exemplos: 75 GFLOPs. Porém, o modelo roofline na Figura 7.19 mostra que isso só pode ser obtido com intensidades aritméticas de 8 e acima. O motivo é que os barramentos front side duais interferem um com o outro, gerando largura de banda de memória relativamente baixa aos programas. O AMD Opteron X4 2356 (Barcelona) contém quatro cores por chip, e cada soquete tem um único chip. Cada chip tem um controlador de memória na placa e seu próprio caminho para a DRAM DDR2 de 667MHz. Esses dois soquetes se comunicam por links Hypertransport separados, dedicados, o que possibilita a criação de um sistema multichip “sem cola”. Esse sistema de soquete dual utiliza uma taxa de clock de proces- sador de 2,30GHz e tem um desempenho de pico de aproximadamente 74GFLOPs. A Figura 7.19 mostra que o ponto de cumeeira no modelo roofline está à esquerda do Xeon e5345 (Clovertown), em uma intensidade aritmética de aproximadamente 5 FLOPs por byte. O Sun UltraSPARC T2 5140 (apelidado de “Niagara 2”) é muito diferente das duas microarquiteturas x86. Ele usa oito cores relativamente simples por chip, com uma taxa de clock muito mais baixa. Também oferece multithreading fine-grained com oito threads 7.11  Vida real: benchmarking de quatro multicores usando o modelo roofline 547 FIGURA 7.17  Quatro multiprocessadores recentes, cada um usando dois soquetes para os processadores. Começando com o canto superior esquerdo, os computadores são: (a) Intel Xeon e5345 (Clovertown), (b) AMD Opteron X4 2356 (Barcelona), (c) Sun UltraSPARC T2 5140 (Niagara 2) e (d) IBM Cell QS20. Observe que o Intel Xeon e5345 (Clovertown) tem um chip north bridge separado, não encontrado nos outros microprocessadores. FIGURA 7.18  Características dos quatro multicores recentes. Embora o Xeon e5345 e o Opteron X4 tenham DRAMs com a mesma velocidade, o benchmark Stream mostra uma largura de banda de memória prática mais alta devido a ineficiências do barramento front side no Xeon e5345. por core. Um único chip tem quatro controladores de memória que poderiam impulsionar quatro conjuntos de FBDIMMs de 667MHz. Para juntar dois chips UltraSPARC T2, dois dos quatro canais de memória são conectados, deixando dois canais de memória por chip. Esse sistema de soquete dual tem um desempenho de pico de cerca de 22 GFLOPs, e o ponto de cumeeira é uma intensidade aritmética incrivelmente baixa, com apenas 1/3 FLOPs por byte. O IBM Cell QS20 novamente é diferente das duas microarquiteturas x86 e do UltraSPARC T2. Esse é um projeto heterogêneo, com um core PowerPC relativamente simples e com oito SPEs (Synergistic Processing Elements) que têm seu próprio conjunto de instru- ções exclusivo em estilo SIMD. Cada SPE também tem sua própria memória local, em 548 Capítulo 7  Multicores, multiprocessadores e clusters FIGURA 7.19  Modelo roofline para os multiprocessadores multicore na Figura 7.15. Os tetos são os mesmos que na Figura 7.13. Começando com o canto superior esquerdo, os computadores são: (a) Intel Xeon e5345 (Clovertown), (b) AMD Opteron X4 2356 (Barcelona), (c) Sun UltraSPARC T2 5140 (Niagara 2) e (d) IBM Cell QS20. Observe que os pontos de cumeeira para os quatro microprocessadores cruzam o eixo X nas intensidades aritméticas de 6, 4, 1/3 e 3/4, respectivamente. As linhas verticais tracejadas são para os dois kernels desta seção e as estrelas marcam o desempenho obtido para esses kernels após todas as otimizações. SpMV é o par de linhas verticais tracejadas à esquerda. Ele tem duas linhas porque sua intensidade aritmética melhorou de 0,166 para 0,255 com base nas otimizações de bloqueio de registrador. LBHMD são as linhas verticais tracejadas à direita. Ele tem um par de linhas em (a) e (b) porque uma otimização de cache pula o preenchimento do bloco de cache em uma falha quando o processador escreveria novos dados no bloco inteiro. Essa otimização aumenta a intensidade aritmética de 0,70 para 1,07. Essa é uma única linha a 0,70 em (c) porque o UltraSPARC T2 não oferece a otimização da cache. Essa é uma única linha a 1,07 em (d) porque o Cell possui store local carregado pelo DMA, de modo que o programa não busca dados desnecessários, como fazem as caches. vez de uma cache. Um SPE deve transferir dados da memória principal para a memória local, a fim de operar sobre ela e depois de volta à memória principal, quando é concluído. Ele usa DMA, que tem alguma semelhança com a pré-busca de software. Os dois soquetes são conectados por meio de links dedicados a comunicações multichip. A taxa de clock desse sistema é a mais alta dos quatro multicores em 3,2GHz, e usa chips de DRAM XDR, que normalmente são encontrados em consoles de jogos. Eles possuem muita largura de banda, mas pouca capacidade. Dado que a aplicação principal do Cell era de gráficos, ele tem desempenho em precisão simples muito mais alto do que o desempenho em precisão dupla. O desempenho de pico em precisão dupla dos SPEs no sistema de soquete dual é 29 GFLOPs, e o ponto de cumeeira da intensidade aritmética é 0,75 FLOPs por byte. 7.11  Vida real: benchmarking de quatro multicores usando o modelo roofline 549 Embora as duas arquiteturas x86 tivessem muito menos cores por chip que as ofertas da IBM e Sun no início de 2008, é exatamente aí que elas estão hoje. À medida que se es- pera que o número de cores dobre a cada geração da tecnologia, será interessante ver se as arquiteturas x86 fecharão a “lacuna de core” ou se IBM e Sun poderão sustentar um número maior de cores, dado que seu foco principal está nos servidores e não no desktop. Observe que essas máquinas utilizam técnicas muito diferentes para o sistema de memória. O Xeon e5345 usa uma cache L1 privada convencional e então pares de proces- sadores compartilham uma cache L2. Estes são conectados por meio de um controlador de memória fora do chip a uma memória comum por dois barramentos. Ao contrário, o Opteron X4 tem um controlador de memória separado e memória por chip, e cada core tem caches L1 e L2 privados. UltraSPARC T2 tem o controlador de memória no chip e quatro canais de DRAM separados por chip, e todos os cores compartilham a cache L2, que tem quatro bancos para melhorar a largura de banda. Seu multithreading fine-grained no topo de seu projeto multicore permite que ele mantenha muitos acessos à memória no ato. O mais radical é o Cell. Ele tem memórias privadas locais por SPE e usa DMA para transferir dados entre a DRAM conectada a cada chip e memória local. Ele sustenta muitos acessos à memória no ato tendo muitos cores e depois muitas transferências de DMA por core. Vejamos como esses quatro multicores em contraste funcionam nos dois kernels. Matriz esparsa O primeiro kernel de exemplo do padrão de projeto computacional de matriz esparsa é o Sparse Matrix-Vector multiply (SpMV). SpMV é comum na computação científica, modelagem econômica e recuperação de informações. Infelizmente, as implementações convencionais normalmente executam em menos de 10% do desempenho de pico dos processadores. Um motivo é o acesso irregular à memória, que você poderia esperar de um kernel trabalhando com matrizes esparsas. O cálculo é y = A× x onde A é uma matriz esparsa e x e y são vetores densos. Quatorze matrizes esparsas tomadas de uma série de aplicações reais foram usadas para avaliar o desempenho do SpMV, mas somente o desempenho mediano é relatado aqui. A intensidade aritmética varia de 0,166 antes de uma otimização de bloqueio de registrador para 0,250 FLOPs por byte depois disso. O código primeiro foi paralelizado para utilizar todos os cores. Dado que a intensidade aritmética baixa do SpMV esteve abaixo do ponto de cumeeira de todos os multicores na Figura 7.19, a maioria das otimizações envolveu o sistema de memória: j Pré-busca. Para obter o máximo dos sistemas de memória, as pré-buscas de software e hardware foram utilizadas. j Afinidade de memória. Essa otimização reduz os acessos à memória DRAM conectada ao outro soquete nos três sistemas que têm memória DRAM local. j Compactação de estruturas de dados. Como a largura de banda de memória provavel- mente limita o desempenho, essa otimização usa estruturas de dados menores para aumentar o desempenho — por exemplo, usando um índice de 16 bits em vez de um índice de 32 bits, e usando representações dos não zeros com uso mais eficiente do espaço nas linhas de uma matriz esparsa. A Figura 7.20 mostra o desempenho no SpMV para os quatro sistemas em comparação com o número de cores. (Os mesmos resultados são encontrados na Figura 7.19, mas é difícil comparar o desempenho quando se usa uma escala logarítmica.) Observe que, apesar de ter o desempenho de pico mais alto na Figura 7.18 e o desempenho de core isolado mais alto, o Intel Xeon e5345 tem o desempenho oferecido mais baixo dos quatro multicores. O Opteron X4 dobra seu desempenho. O gargalo do Xeon e5345 são os barramentos front side duais. Apesar da taxa de clock mais baixa, o número maior de cores simples do Sun 550 Capítulo 7  Multicores, multiprocessadores e clusters FIGURA 7.20  Desempenho do SpMV nos quatro multicores. UltraSPARC T2 supera os dois processadores x86. O IBM Cell tem o desempenho mais alto dos quatro. Observe que todos menos o Xeon e5345 se expandem bem com o número de cores, embora o Opteron X4 se expanda mais lentamente com quatro ou mais cores. Grade estruturada O segundo kernel é um exemplo do padrão de projeto de grade estruturada. Lattice-Boltzmann Magneto-Hydrodynamics (LBMHD) é comum para a dinâmica de fluido computacional; ele é um código de grade estruturada com uma série de etapas de tempo. Cada ponto envolve leitura e escrita de aproximadamente 75 números de ponto flutuante de precisão dupla e cerca de 1300 operações de ponto flutuante. Assim como SpMV, LBMHD tende a conseguir uma pequena fração do desempenho de pico nos processadores, devido à complexidade das estruturas de dados e da irregularidade dos padrões de acesso à memória. A razão entre FLOPs e bytes é muito maior, 0,70, em com- paração com menos de 0,25 no SpMV. Não preenchendo o bloco de cache da memória em uma perda de escrita quando o programa for sobrescrever o bloco inteiro, a intensidade sobe para 1,07. Todos os multicores menos o UltraSPARC T2 (Niagara 2) oferecem essa otimização de cache. A Figura 7.19 mostra que a intensidade aritmética do LBMHD é tão alta que as oti- mizações de largura de banda computacional e da memória fazem sentido em todos os multicores, menos o UltraSPARC T2, cujo ponto de cumeeira da roofline está abaixo do ponto do LBMHD. O UltraSPARC T2 pode alcançar a roofline usando apenas as otimi- zações computacionais. Além de colocar o código em paralelo, de modo que possa usar todos os cores, as otimizações a seguir foram usadas para LBMHD: j Afinidade de memória: Essa otimização novamente é útil pelos mesmos motivos mencionados anteriormente. j Minimização de perda de TLB: Para reduzir as perdas de TLB significativamente no LBMHD, use uma estrutura de arrays e combine alguns loops juntos em vez da técnica convencional de usar um array de estruturas. j Desdobramento e reordenação de loop: Para expor paralelismo suficiente e melhorar a utilização de cache, os loops foram desdobrados e depois reordenados para agrupar as instruções com endereços semelhantes. j SIMD: Os compiladores dos dois sistemas x86 não poderiam gerar bom código SSE, de modo que estes tiveram de ser escritos à mão em linguagem assembly. 7.11  Vida real: benchmarking de quatro multicores usando o modelo roofline 551 FIGURA 7.21  Desempenho do LBMHD nos quatro multicores. FIGURA 7.22  Desempenho de base versus totalmente otimizado dos quatro cores nos dois kernels. Observe a alta fração de desempenho totalmente otimizado oferecido pelo Sun UltraSPARC T2 (Niagara 2). Não existe coluna de desempenho de base para o IBM Cell, pois não existe como portar o código para os SPEs sem caches. Embora você possa executar o código no core do Power, ele tem um desempenho com uma ordem de grandeza a menos que o SPES, e por isso o ignoramos nesta figura. A Figura 7.21 mostra o desempenho dos quatro sistemas em comparação com o número de cores para LBMHD. Assim como o SpMV, o Intel Xeon e5345 tem a pior escalabilidade. Desta vez, os cores mais poderosos do Opteron X4 são superiores aos cores simples do UltraSPARC T2, apesar de ter metade do número de cores. Mais uma vez, o IBM Cell é o sistema mais rápido. Tudo menos o Xeon e5345 se expande bem com o número de cores, embora T2 e Cell se expandam mais tranquilamente do que o Opteron X4. Produtividade Além do desempenho, outra questão importante para a revolução da computação paralela é a produtividade, ou a dificuldade da programação de alcançar o desempenho. Para ilustrar as diferenças, a Figura 7.22 compara o desempenho simples com o desempenho totalmente otimizado para os quatro cores nos dois kernels. O mais fácil foi o UltraSPARC T2, devido à sua grande largura de banda de memória e seus cores fáceis de entender. O conselho para esses dois kernels no UltraSPARC T2 é simplesmente tentar obter código de bom desempenho do compilador e depois usar o máximo de threads possível. O único cuidado para outros kernels é que o UltraSPARC T2 pode cair na armadilha sobre garantir que a associatividade de conjunto combina com o número de threads de hardware (veja Seção 5.11, no Capítulo 5). Cada chip admite 64 threads de hardware, enquanto o cache L2 é associativo em conjunto com quatro vias. Essa divergência pode exigir a reestruturação de loops para reduzir as falhas por conflito. 552 Capítulo 7  Multicores, multiprocessadores e clusters O Xeon e5346 era considerado complexo porque não era fácil entender o comporta- mento de memória dos barramentos front side duais, era difícil entender como funcionava a pré-busca do hardware, assim como obter um bom código SIMD do compilador. O código C para ele e para o Opteron X4 são repletos de instruções intrínsecas envolvendo instruções SIMD para obter um bom desempenho. O Opteron X4 beneficiou-se da maioria dos tipos de otimizações, de modo que precisou de mais esforço que o Xeon e5345, embora o comportamento da memória do Opteron X4 fosse mais fácil de entender que o do Xeon e5345. O Cell forneceu dois tipos de desafios. Primeiro, as instruções SIMD do SPE eram difíceis de compilar, de modo que às vezes você precisava ajudar o compilador, inserindo instruções intrínsecas com instruções em linguagem assembly no código C. Segundo, o sis- tema de memória era mais interessante. Como cada SPE tem memória local em um espaço de endereço separado, você não poderia simplesmente transportar o código e começar a executar no SPE. Portanto, não há uma coluna de código base para o IBM Cell na Figura 7.22, e você precisava mudar o programa para emitir comandos de DMA e transferir dados entre o armazenamento local e a memória. A boa notícia é que o DMA desempenhou o papel de pré-busca de software nas caches, e o DMA é muito mais fácil de usar e conseguir um bom desempenho da memória. O Cell foi capaz de oferecer quase 90% da “roofline” de largura de banda de memória para esses kernels, em comparação com 50% ou menos para os outros multicores. Por mais de uma década 7.12   Falácias e armadilhas os analistas anunciam que a organização de Os muitos ataques ao processamento paralelo revelaram inúmeras falácias e armadilhas. um único computador Veremos três delas aqui. alcançou seus limites e que avanços verdadeiramente Falácia: a Lei de Amdahl não se aplica aos computadores paralelos. significantes só podem ser Em 1987, o diretor de uma organização de pesquisa afirmou que a Lei de Amdahl tinha sido feitos pela interconexão quebrada por uma máquina de multiprocessador. Para tentar entender a base dos relatos de uma multiplicidade de da mídia, vejamos a citação que nos trouxe a Lei de Amdahl [1967, p. 483]: computadores de tal modo que permita solução cooperativa... Uma conclusão bastante óbvia que pode ser tirada nesse momento é que o esforço Demonstrou-se a continuada despendido em conseguir altas velocidades de processamento paralelo é desperdiçado validade do método de se não for acompanhado de conquistas de mesmas proporções nas velocidades de processador único... processamento sequencial. Essa afirmação ainda deve ser verdadeira; a parte ignorada do programa deve limitar o Gene Amdahl, “Validity of the desempenho. Uma interpretação da lei leva ao seguinte princípio: partes de cada programa single processor approach to precisam ser sequenciais e, portanto, precisa haver um limite superior lucrativo para o achieving large scale computing número de processadores – digamos, 100. Mostrando speed-up linear com 1.000 proces- capabilities”, Spring Joint sadores, esse princípio se torna falso e, então, a Lei de Amdahl foi quebrada. Computer Conference, 1967 O método dos pesquisadores foi mudar a entrada para o benchmark: em vez de ir 1.000 vezes mais rápido, eles calcularam 1.000 vezes mais trabalho em tempo comparável. Para o algoritmo deles, a parte sequencial do programa era constante, independente do tamanho da entrada, e o restante era totalmente paralelo – daí, speed-up linear com 1.000 processadores. Não vemos razão para que a Lei de Amdahl não se aplique aos processadores paralelos. O que essa pesquisa salienta é um dos principais usos de computadores rápidos é executar problemas grandes, mas ter ciência de como os algoritmos escalam com o crescimento do tamanho do problema. Falácia: o desempenho de pico segue o desempenho observado. Por exemplo, a Seção 7.11 mostra que o Intel Xeon e5345, o microprocessador com o desempenho de pico mais alto, foi o mais lento dos quatro microprocessadores multicore para dois kernels. 7.13  Comentários finais 553 A indústria de supercomputadores usou essa métrica no marketing, e a falácia é enfatizada com as máquinas paralelas. Não apenas os marketeiros estão usando o desempenho de pico quase inatingível de um nó processador, mas eles também o estão multiplicando pelo número total de processadores, considerando speed-up perfeito! A lei de Amdahl sugere como é difícil alcançar qualquer um desses picos; multiplicar os dois multiplica os pecados. O modelo roofline ajuda a entender melhor o desempenho de pico. Armadilha: não desenvolver o software para tirar proveito de (ou otimizar) uma arqui- tetura de multiprocessador. Há um longo histórico de software ficando para trás nos processadores paralelos, pos- sivelmente porque os problemas do software são muito mais difíceis. Temos um exemplo para mostrar a sutileza dessas questões, mas existem muitos exemplos que poderíamos escolher! Um problema encontrado com frequência ocorre quando o software projetado para um processador único é adaptado a um ambiente multiprocessador. Por exemplo, o sistema operacional SGI protegia originalmente a tabela de página com um único lock, supondo que a alocação de página é pouco frequente. Em um processador único, isso não representa um problema de desempenho, mas em um multiprocessador, pode se tornar um gargalo de desempenho importante para alguns programas. Considere um programa que usa um grande número de páginas que são inicializadas quando começa a ser executado, o que o UNIX faz para as páginas alocadas estaticamente. Suponha que o programa seja colocado em paralelo, de modo que múltiplos processos aloquem as páginas. Como a alocação de página requer o uso da tabela de página, que é bloqueada sempre que está em uso, até mesmo um kernel do SO que permita múltiplas threads no SO será colocado em série se todos os processos tentarem alocar suas páginas ao mesmo tempo (que é exatamente o que poderíamos esperar no momento da inicialização!). Essa serialização da tabela de página elimina o paralelismo na inicialização e tem um impacto significativo sobre o desempenho paralelo geral. Esse gargalo de desempenho persiste até mesmo para o paralelismo em nível de tarefa. Por exemplo, suponha que divi- damos o programa de processamento paralelo em tarefas separadas e as executemos, uma tarefa por processador, de modo que não haja compartilhamento entre elas. (É exatamente isso o que um usuário fez, pois acreditava que o problema de desempenho era devido ao compartilhamento não intencional ou interferência em sua aplicação.) Infelizmente, o lock ainda coloca todas as tarefas em série — de modo que, até mesmo o desempenho da tarefa independente é fraco. Essa armadilha indica os tipos de bugs de desempenho sutis, porém significativos, que podem surgir quando o software é executado em multiprocessadores. Assim como muitos outros componentes de software essenciais, os algoritmos do SO e as estruturas de dados precisam ser repensadas em um contexto de multiprocessador. Colocar locks em partes menores da tabela de página efetivamente elimina o problema. Estamos dedicando todo o nosso desenvolvimento de 7.13   Comentários finais produto futuro aos projetos multicore. Acreditamos que esse seja um ponto de inflexão O sonho de construir computadores apenas agregando processadores existe desde os importante para a indústria. primeiros dias da computação. No entanto, o progresso na construção e no uso de proces- ... Essa não é uma corrida, é sadores paralelos eficientes tem sido lento. Essa velocidade de progresso foi limitada pelos uma mudança de mares na difíceis problemas de software bem como por um longo processo de evolução da arquitetura computação. dos multiprocessadores para melhorar a usabilidade e a eficiência. Discutimos muitos dos problemas de software neste capítulo, incluindo a dificuldade de escrever programas que Paul Otellini, Presidente da obtêm bom speed-up devido à Lei de Amdahl. A grande variedade de métodos arquite- Intel, Intel Developers Forum, tônicos diferentes e o sucesso limitado e a vida curta de muitas arquiteturas até agora se 2004. juntam às dificuldades de software. Abordaremos a história do desenvolvimento desses multiprocessadores na Seção 7.14, no site. 554 Capítulo 7  Multicores, multiprocessadores e clusters Como dissemos no Capítulo 1, apesar desse longo e sinuoso passado, a indústria da tecnologia de informação agora tem seu futuro ligado à computação paralela. Embora seja fácil apontar fatos para que esse esforço falhe como muitos no passado, existem motivos para termos esperança: j Claramente, o software como um serviço está ganhando mais importância, e os clus- ters provaram ser um modo muito bem-sucedido de oferecer tais serviços. Oferecen- do redundância em um nível mais alto, incluindo centros de dados geograficamente distribuídos, esses serviços têm oferecido disponibilidade 24 × 7 × 365 para os clientes no mundo inteiro. É difícil não imaginar que o número de servidores por centro de dados e o número de centros de dados continuarão a crescer. Certamente, esses centros de dados abraçarão projetos multicore, pois eles já podem usar milhares de processadores em suas aplicações. j O uso de processamento paralelo em domínios como a computação científica e de engenharia é comum. Esse domínio de aplicação possui uma necessidade quase ilimitada de mais computação. Ele também possui muitas aplicações com uma grande quantidade de paralelismo natural. Mais uma vez, os clusters dominam essa área de aplicação. Por exemplo, usando o relatório do Linpack 2007, os clus- ters representam mais de 80% dos 500 computadores mais rápidos. Entretanto, isso não tem sido fácil: programar processadores paralelos até para essas aplicações continua sendo um desafio. Ainda assim, esse grupo certamente também acolherá os chips multicore, pois novamente eles têm experiência com centenas a milhares de processadores. j Todos os fabricantes de microprocessador de desktop e servidor estão construindo multi- processadores para alcançar o desempenho mais alto, de modo que, diferente do passado, não existe um caminho fácil para o desempenho mais alto para aplicações sequenciais. Logo, os programadores que precisam de desempenho mais alto precisam colocar seus códigos em paralelo ou escrever novos programas de processamento paralelo. j Processadores múltiplos no mesmo chip permitem uma velocidade de comunicação muito diferente dos projetos de múltiplos chips, oferecendo latência muito mais baixa e largura de banda muito mais alta. Essas melhorias podem facilitar a oferta de bom desempenho. j No passado, os microprocessadores e os multiprocessadores estavam sujeitos a diferentes definições de sucesso. Ao escalar o desempenho do processador único, os arquitetos de microprocessador ficavam felizes se o desempenho com uma única thread subisse pela raiz quadrada da área de silício aumentada. Assim, eles fica- vam felizes com um desempenho sublinear em termos de recursos. O sucesso do multiprocessador era definido como um speed-up linear como função do número de processadores, supondo que o custo da compra ou o custo da administração de n processadores era n vezes o custo de um processador. Agora que o paralelismo está acontecendo no chip via multicore, podemos usar o microprocessador tradicional com sucesso na melhoria do desempenho sublinear. j O sucesso da compilação em tempo de execução just-in-time torna viável pensar no software adaptando-se para tirar proveito do número cada vez maior de cores por chip, o que oferece uma flexibilidade que não está disponível quando limitado a compiladores estáticos. j Diferente do passado, o movimento do código-fonte aberto tornou-se uma parte fundamental da indústria de software. Esse movimento é uma meritocracia, em que melhores soluções de engenharia podem ganhar a fatia de desenvolvedores em relação a questões legadas. Ele também alcança a inovação, convidando a mudança no software antigo e recebendo novas linguagens e produtos de software. Essa cultura aberta poderia ser extremamente útil nessa época de mudança rápida. 7.15 Exercícios 555 Essa revolução na interface de hardware/software talvez seja o maior desafio que esse campo encarou nos últimos 50 anos. Ela oferecerá muitas novas oportunidades de pesquisa e negócios dentro e fora do campo de TI, e as empresas que dominam a era do multicore podem não ser as mesmas que dominaram a era do processador único. Talvez você será um dos inovadores que aproveitará as oportunidades que certamente aparecerão nos tempos de incerteza mais adiante. 7.14  Perspectiva histórica e leitura adicional Esta seção no site oferece um histórico rico e geralmente desastroso dos multiprocessadores nos últimos 50 anos. 7.15   Exercícios1  Exercício 7.1 Primeiro, escreva uma lista das atividades diárias que você realiza normalmente em um fim de semana. Por exemplo, você poderia levantar da cama, tomar um banho, se vestir, tomar o café, secar seu cabelo, escovar os dentes etc. Lembre-se de distribuir sua lista de modo que tenha um mínimo de dez atividades. 7.1.1 <7.2> Agora considere qual dessas atividades já está explorando alguma forma de paralelismo (por exemplo, escovar vários dentes ao mesmo tempo em vez de um de cada vez, carregar um livro de cada vez para a escola em vez de colocar todos eles na sua mochila, e depois carregá-los “em paralelo”). Para cada uma de suas atividades, discuta se elas já estão sendo executadas em paralelo, mas se não, por que não estão. 7.1.2 <7.2> Em seguida, considere quais das atividades poderiam ser executadas si- multaneamente (por exemplo, tomar café e escutar as notícias). Para cada uma das suas atividades, descreva qual outra atividade poderia ser emparelhada com essa atividade. 7.1.3 <7.2> Para o Exercício 7.1.2, o que poderíamos mudar sobre os sistemas atuais (por exemplo, banhos, roupas, TVs, carros) de modo que pudéssemos realizar mais tarefas em paralelo? 7.1.4 <7.2> Estime quanto tempo a menos seria necessário para executar essas atividades se você tentasse executar o máximo de tarefas em paralelo possível. Exercício 7.2 Muitas aplicações de computador envolvem a pesquisa por um conjunto de dados e a clas- sificação dos dados. Diversos algoritmos eficientes de busca e classificação foram criados para reduzir o tempo de execução dessas tarefas tediosas. Neste problema, vamos considerar como é melhor colocar essas tarefas em paralelo. 1 Contribuição de David Kaeli, da Northeastern University 556 Capítulo 7  Multicores, multiprocessadores e clusters 7.2.1 [10] <7.2> Considere o seguinte algoritmo de busca binária (um algoritmo clás- sico do tipo dividir e conquistar) que procura um valor X em um array de N elementos A e retorna o índice da entrada correspondente: Suponha que você tenha Y cores em um processador multicore para executar BinarySearch. Supondo que Y seja muito menor que N, expresse o fator de speed-up que você poderia esperar obter para os valores e Y e N. Desenhe isso em um gráfico. 7.2.2 [5] <7.2> Em seguida, suponha que Y seja igual a N. Como isso afetaria suas con- clusões na sua resposta anterior? Se você estivesse encarregado de obter o melhor fator de speed-up possível (ou seja, expansão forte), explique como poderia mudar esse código para obter isso. Exercício 7.3 Considere o seguinte trecho de código em C: O código MIPS correspondente a esse fragmento é: As instruções têm as seguintes latências associadas (em ciclos): ADD.D L.D S.D DADDIU 4 6 1 2 7.15 Exercícios 557 7.3.1 [10] <7.2> Quantos ciclos são necessários para que todas as instruções em uma única iteração do loop anterior sejam executadas? 7.3.2 [10] <7.2> Quando uma instrução em uma iteração posterior de um loop de- pende do valor de dados produzido em uma iteração anterior do mesmo loop, dizemos que existe uma dependência carregada pelo loop entre as iterações do loop. Identifique as dependências carregadas pelo loop no código anterior. Identifique a variável de pro- grama dependente e os registradores em nível de assembly. Você pode ignorar a variável de indução de loop j. 7.3.3 [10] <7.2> O desdobramento de loop foi descrito no Capítulo 4. Aplique o des- dobramento de loop a esse loop e depois considere a execução desse código em um sistema de passagem de mensagem com memória distribuída com 2 nós. Suponha que usaremos a passagem de mensagem conforme descrito na Seção 7.4, na qual apresentamos uma nova operação send(x,y) que envia ao nó x o valor y, e uma operação receive( ) que espera pelo valor sendo enviado a ele. Suponha que as operações send gastem um ciclo para emitir (ou seja, outras instruções no mesmo nó podem prosseguir para o próximo ciclo), mas gastem 10 ciclos para serem recebidas no nó receptor. Operações receive provocam stall da execução no nó em que são executadas até que recebam uma mensagem. Produza um schedule para os dois nós; considere um fator de desdobramento de 4 para o corpo do loop (ou seja, o corpo do loop aparecerá quatro vezes). Calcule o número de ciclos necessários para que o loop seja executado no sistema de passagem de mensagens. 7.3.4 [10] <7.2> A latência da rede de interconexão desempenha um papel importante na eficiência dos sistemas de passagem de mensagens. Que velocidade a interconexão precisa ter a fim de obter qualquer speed-up com o uso do sistema distribuído descrito no Exercício 7.3.3? Exercício 7.4 Considere o seguinte algoritmo mergesort recursivo (outro algoritmo clássico para dividir e conquistar). Mergesort foi descrito inicialmente por John von Neumann em 1945. A ideia básica é dividir uma lista não classificada x de m elementos em duas sublistas de aproximadamente metade do tamanho da lista original. Repita essa operação em cada su- blista e continue até que tenhamos listas de tamanho 1. Depois, começando com sublistas de tamanho 1, faça o “merge” das duas sublistas em uma única lista classificada. A etapa do merge é executada pelo seguinte código: baunilha. Como isso afetaria suas conclusões na sua resposta anterior? Se você estivesse encarregado de obter o melhor fator de speed-up possível (ou seja. Exercício 7. expresse o fator de speed-up que você poderia esperar obter para os valores de Y e length(m).5 Você está tentando preparar três tortas de mirtilo. explique como poderia mudar esse código para obtê-lo. Passo 3: inclua os mirtilos aos poucos.2 [10] <7.4. Unte e polvilhe farinha na forma.2> Em seguida. bata com a batedeira a manteiga e o açúcar em velocida- de média até que a massa fique leve e macia. Acrescente ovos. Supondo que Y seja muito menor que length(m). batendo até ficar bem misturado. Desenhe isso em um gráfico. 7. Passo 2: em uma bacia grande. Leve ao forno 60 minutos.1 [5] <7.2> Suponha que você tenha Y cores em um processador multicore para executar o MergeSort. expansão forte). considere que Y é igual a length(m). Os ingredientes são os seguintes: 1 xícara de manteiga 1 xícara de açúcar 4 ovos grandes 1 colher de chá de extrato de baunilha 1/2 colher de chá de sal 1/4 colher de chá de noz moscada 1 1/2 xícaras de farinha de trigo 1 xícara de mirtilos A receita para uma única torta é a seguinte: Passo 1: pré-aqueça o forno a 160 °C.2> Sua tarefa é cozinhar três tortas da forma mais eficiente possível. sal e noz mos- cada. Supondo que você só tenha um forno com tamanho suficiente para conter uma torta. Bata até que tudo fique totalmente misturado. multiprocessadores e clusters 7. Espalhe uniformemente na forma da torta.1 [10] <7. uma bacia . 1/2 xícara por vez.5. 7.4. Reduza a velocidade da batedeira e acrescente farinha de trigo.558 Capítulo 7  Multicores. 4 [5] <7.2 b2. devida ao compartilhamento falso quando os elementos consecutivos que estão em sequência (ou seja.6. …. índice i) são atualizados. j i =1 para cada elemento i e j com 1 ≤ i ≤ m e 1 ≤ j ≤ p.5. Calcule o speed-up que esperaríamos obter em uma máquina de 4 cores.  . ignorando quaisquer problemas de memória. Identifique os gargalos para completar essa tarefa.6. Se atribuirmos C = AB. Identifique o paralelismo em nível de dados e o paralelismo em nível de tarefa no loop de preparação da torta.3> Como você consertaria o problema de compartilhamento falso que pode ocorrer? Exercício 7.5. j). Podemos expressar seu produto como uma matriz m × p indicada por AB(ou A · B). 7. a3. Suponha que as matrizes estejam dispostas na memória sequencialmente da seguinte forma: a1.1. j +…+ ai .1. 7.1 [10] <7. j = ∑ ai . e ci.1 b1. 7.j indicar a entrada em C na posição (i. agora que você tem esses recursos adicionais? 7. Vamos supor que tenhamos uma matriz m × n A e queiramos multiplicá-la por uma matriz n × p B.2> Suponha agora que você tenha três bacias. a2. O quanto o processo fica mais rápido.2 [5] <7.1. j + ai .2> Compare a tarefa de preparação da torta com o cálculo de três iterações de um loop em um computador paralelo. e que você tem um forno grande.5. Core 2: y = 2. uma forma de torta e uma batedeira.2> Agora suponha que você tem dois amigos que o ajudarão a cozinhar. Suponha que.3> Suponha que iremos calcular C em uma máquina de memória com- partilhada de único core e uma máquina com memória compartilhada de 4 cores. Como isso mudará o plano que você preparou no Exercício 7. Core 4: z = x + y. Exercício 7. 7. que possa acomodar todas as três tortas.1. prepare um plano para fazer as três tortas o mais rapidamente possível. três formas de torta e três batedeiras.5. Duas matrizes só podem ser multiplicadas se o número de colunas da primeira matriz for igual ao número de linhas na segunda.n bn.2 [10] <7. Agora.7 Considere as seguintes partes de dois programas diferentes rodando ao mesmo tempo em quatro processadores em um processador multicore simétrico (SMP).3> Repita o Exercício 7. queremos ver se podemos fazer o cálculo de C em paralelo.r br . tanto x quanto y sejam 0.6 A multiplicação de matriz desempenha um papel importante em diversas aplicações.6. a4. etc.3 [5] <7. supondo que as atualizações em C incorrem em uma falha de cache. Core 1: x = 2.3 [10] <7. Core 3: w = x + y + 1.1? 7. j = ai . então n ci .1.15 Exercícios 559 grande.6. antes que esse código seja executado. 7. 7.3> Para um mecanismo de coerência baseado em diretório. Para manter a coerência da memória. após o qual cada endereço escrito é lido por cada um dos três cores restantes.3 [20] <7. Além disso. depois da escrita. 7. Suponha também que o endereço em que os dados são escritos esteja inicialmente apenas na memória.3> Se tivermos P CPUs no sistema com T nós no sistema CC-NUMA. y e z? Para cada resultado possível. e mantivermos um byte de informação de coerência em cada bloco de cache.3> Quais são todos os valores resultantes possíveis de w. suponha que o bloco atualizado só esteja presente nas caches L1 do core para formar a escrita.1 e 7.9. Exercício 7.9 Considerando o sistema CC-NUMA descrito no Exercício 7.7. multiprocessadores e clusters 7.1 [10] <7. a quantidade de espaço de armazenamento é uma função do número de blocos de cache disponíveis em todas as caches). Cada core realizará a escrita. podemos acrescentar bits de status em cada bloco de cache.9. Se armazenarmos informações de coerência na cache. mas provido de uma cache de dados L2 compartilhada pelos quatro cores.9. .7. 7. e não em qualquer cache local.560 Capítulo 7  Multicores. elabore uma equação que expresse a quantidade de memória que estará presente em cada diretório.8 Em um sistema de memória compartilhada CC-NUMA. com cada CPU tendo C blocos de memória. cada uma mantendo uma cache de dados L1.1 [15] <7. O tamanho de cada diretório é uma função do tamanho do espaço compartilhado CC-NUMA (uma entrada é fornecida para cada bloco de memória local a um nó). A cache de dados L1 é store-through.2 [10] <7. explique como poderíamos chegar a esses resultados. descreva o tráfego entre nós que será gerado à medida que cada um dos quatro cores escreve em um endereço exclusivo. suponha que o sistema tenha quatro nós.2 [5] <7. Usando diretórios.8.3> Se cada entrada de diretório mantiver um byte de informação para cada CPU.3> Para um sistema que mantém coerência usando status de bloco baseado em cache. acrescentamos essa in- formação a cada cache em cada sistema (ou seja. descreva o tráfego entre nós gerado quando o mesmo padrão de código é executado. Você precisará examinar todas as intercalações possíveis das instruções.1 [10] <7. cada um com uma CPU de único core (cada CPU tem sua própria cache de dados L1 e cache de dados L2). só considerando o espaço usado para armazenar informações de coerência. as CPUs e a memória física são divididas entre os nós de computação. 7. ou podemos introduzir diretórios de memória dedicados. seguida por leituras por cada um dos 15 outros cores. com quatro cores por CPU.9. 7. x.2 [15] <7. se nosso sistema CC-NUMA tiver um total de S blocos de memória e o sistema tiver T nós.3> Como você poderia tornar a execução mais determinística. cada nó oferece uma tabela de hardware dedicada para gerenciar o status de cada bloco de memória que seja “local” a esse nó. embora a cache de dados L2 seja write-back. Suponha que o sistema tenha uma carga de traba- lho na qual uma CPU escreve em um endereço e todas as outras CPUs leiam os dados que são escritos. elabore uma equação que expresse a quantidade de memória que estará presente nas caches em um único nó do sistema para manter a coerência. de modo que somente um conjunto de valores seja possível? Exercício 7.8.9.2 supondo que cada CPU agora seja uma CPU multicore. Cada CPU possui caches locais.8. Não inclua o espaço de armazenamento de dados real consumido nessa equação.3> Repita os Exercícios 7. 7. precisamos acessar a memória uma vez a cada 100 ciclos. 7. suponha que somente uma única operação da memória possa estar ativa durante qualquer ciclo. Qual é a sequência de eventos que leva a esse problema? 7. Agora.9. Load/store local (ciclo) Load/store não local (ciclos) % acessos locais 25 200 20 Responda às perguntas a seguir supondo que os acessos à memória sejam distribuídos uniformemente pela aplicação.2 [10] <7. Exercício 7. e só pode usar os garfos do seu lado esquerdo e direito.3 [10] <7. Há uma tigela de macarrão no centro. Além disso.4> Podemos implementar as solicitações ao garçom como uma fila de solicitações ou como uma retentativa periódica de uma solicitação.9. 7.2 [10] <7.4> Descreva o cenário em que nenhum dos filósofos consegue comer (ou seja. Mas podemos garantir que trataremos de todos os filósofos de forma justa? Explique. o custo de acessar a memória não local pode limitar nossa capacidade de utilizar o multiprocessamento com eficiência. Com uma fila. Indique todas as suposições sobre a ordenação das operações de memória local versus não local.11. o filósofo precisa de dois garfos para comer. O resultado é que cada filósofo tem um garfo à sua esquerda e um garfo à sua direita. Além disso. não estão comendo. O problema geral é enunciado como filósofos sentados em volta de uma mesa redonda fazendo uma de duas coisas: comendo ou pensando. Um garfo é colocado entre cada filósofo.11 O problema do jantar dos filósofos é um problema clássico de sincronização e con- corrência.1 [10] <7.11. suponha que contratemos um garçom encarregado de atribuir garfos aos filósofos.3. O garçom tem co- nhecimento global de todos os garfos. Os filósofos não conversam entre si.3> Se. qual é o impacto sobre nossa aplicação? 7.3 [10] <7. Como isso afeta o tráfego do barramento? Explique.3> Se. 7. não estão pensando.15 Exercícios 561 7.3> Considere o sistema descrito no Exercício 7. agora assumindo que cada core escreve em dois bytes diferentes armazenados no mesmo bloco de cache. inanição). Devido à forma como se come macarrão. Quando eles estão comendo. na média. Ninguém pode pegar um garfo até que o garçom lhe diga que pode.3> Se. A tabela a seguir mostra os custos associados aos dados de acesso na memória local versus memória não local e a localidade da nossa aplicação expressa como a proporção de acesso que é local.10.10. na média. qual é o impacto sobre nossa aplicação? Exercício 7. e quando estão pensando. precisamos acessar a memória uma vez a cada 50 ciclos.10. se impusermos a diretriz de que os filósofos sempre solicitarão para apanhar seu garfo da esquerda antes de apanhar seu garfo da direita. O problema com o uso da . na média. as solicitações são tratadas na ordem em que são recebidas.4 [10] <7. qual é o impacto sobre nossa aplicação? 7.4> Descreva como podemos solucionar esse problema introduzindo o conceito de uma prioridade.11.1 [10] <7.10 Em um sistema CC-NUMA. 7. precisamos acessar a memória uma vez a cada 75 ciclos. então podemos garantir que o impasse (deadlock) será evitado. 7.11. para executar nessas CPUs.12 Considere as três organizações de CPU a seguir: CPU SS: Um microprocessador superescalar de dois cores que oferece capacidades de emissão fora de ordem em duas unidades funcionais (FUs).5> Suponha que você tenha uma CPU SS. e as instruções de qualquer uma ou ambas as threads podem ser emitidas para executar em qualquer ciclo. suponha que você tenha uma CPU MT. multiprocessadores e clusters fila é que podemos nem sempre ser capazes de atender ao filósofo cuja solicitação está no início da fila (devido à indisponibilidade de recursos). CPU SMT: Um processador SMT que permite que instruções de duas threads sejam executadas simultaneamente (ou seja.12. Somente uma única thread pode ser executada em cada core de cada vez. . a menos que observado de outra forma ou que encontrem um hazard.13 O software de virtualização está sendo agressivamente implantado para reduzir os custos de gerenciamento dos servidores de alto desempenho de hoje.562 Capítulo 7  Multicores. existem duas unidades funcionais). embora somente instruções de uma única thread possam ser emitidas em cada ciclo. CPU MT: Um processador multithreaded fine-grained que permite que instruções de duas threads sejam executadas simultaneamente (ou seja. em que uma fila é fornecida.3 [10]<7.5> Agora. Descreva um cenário com cinco filósofos. 7.4 [10] <7. o que inclui as seguintes operações: Thread X Thread Y A1 – leva 3 ciclos para executar B1 – leva 2 ciclos para executar A2 – sem dependências B2 – conflitos para uma unidade funcional com B1 A3 – conflitos para uma unidade funcional com A1 B3 – depende do resultado de B2 A4 – depende do resultado de A3 B4 – sem dependências e leva 2 ciclos para executar Suponha que todas as instruções utilizem um único ciclo para serem executadas. Quantos ciclos são neces- sários para executar essas duas threads? Quantos slots de emissão são desperdiçados devido a hazards? Exercício 7.12.1 [10]<7.2 [10]<7. Suponha que tenhamos duas threads.11. Empresas como VMWare. Quantos ciclos são necessários para executar essas duas threads? Quantos slots de emissão são desperdiçados devido a hazards? 7. existem duas unidades funcionais).5> Suponha que você tenha uma CPU SMT. mas o serviço não é concedido mesmo que haja garfos disponíveis para outro filósofo (cuja solicitação está mais profunda na fila) utilizar. Quantos ciclos são necessários para executar essas duas threads? Quantos slots de emissão são desperdiçados devido a hazards? 7. isso solucionará o problema des- crito no Exercício 7.4> Se implementarmos solicitações ao garçom repetindo periodicamente nossa solicitação até que os recursos estejam disponíveis.3? Explique. X e Y. Exercício 7.12. Um array sistólico é uma rede de pipeline ou “wavefront” de elementos de processamento de dados.15.1 [30] <7. Exercício 7. Isso exigirá que repensemos como os sistemas multicore e multiprocessador serão projetados no futuro para dar suporte ao compartilhamento das CPUs e memórias por diversos sistemas operacionais simultaneamente. tente programar o loop fornecido no Exercício 7.2 [15] <7. 7.14. Temos duas máquinas diferentes.13. Os arrays sistólicos com clock são computados em “lock-step”. é que uma camada hipervisora pode ser introduzida entre o hardware e o sistema operacional para permitir que vários sistemas operacionais compartilhem o mesmo hardware físico. mostre a sequência de instruções MIPS que você executaria em cada CPU.14 usando esse modelo MISD. Discuta quaisquer dificuldades que você encontrar.2 [20] <7. pois a execução é disparada pela chegada de dados. além de tratar os serviços normalmente tratados pelo sistema operacional (por exemplo.6> Discuta as semelhanças e diferenças entre uma máquina MISD e SIMD.5> Discuta quais mudanças podem ser necessárias nas plataformas de CPU multicore do futuro a fim de que sejam mais coerentes com as demandas de recursos impostas sobre esses sistemas. Cada um desses elementos não precisa de um contador de programa. O conceito geral. oito unidades funcio- nais SIMD paralelas). Compare o número de instruções executadas na máquina SIMD com a máquina MIMD. com cada processador realizando fases alternadas de computação e comunicação.13.15 Exercícios 563 Microsoft e IBM desenvolveram diversos produtos de virtualização. o multithreading pode desempenhar um papel eficaz para reduzir a competição por recursos de computação? Exercício 7.2 [10] <7.6> Para uma máquina MIMD com quatro CPUs. des- crito no Capítulo 5.14. Depois. A virtualização oferece uma visão abstrata do hardware subjacente ao sistema operacio- nal host e ao software de aplicação. 7. 7.14 Gostaríamos de executar o loop a seguir da forma mais eficiente possível. 7.15 Um array sistólico é um exemplo de uma máquina MISD. .15. Qual é o speed-up para essa máquina MIMD? 7. 7. Responda a essa pergunta em termos de paralelismo em nível de dados. Por exemplo.6> Considere as implementações propostas de um array sistólico (você pode encontrá-las na internet ou em publicações técnicas).6> Para uma máquina SIMD de largura 8 (ou seja. A camada hipervisora é então responsável por alocar recursos de CPU e memória.5> Selecione dois hipervisores no mercado hoje e compare como eles virtualizam e gerenciam o hardware subjacente (CPUs e memória). escreva um programa em assembly usando suas próprias extensões SIMD para o MIPS para executar o loop.1 [10] <7.1 [10] <7. 7. E/S). uma máquina MIMD e uma máquina SIMD. examinando o tempo de computação para a GPU e uma versão de CPU do seu programa para uma faixa de tamanhos de vetor. Atualmente. complete uma análise de desempenho do seu programa. A Intel também está saltando para essa arena com seu chip Larrabee. multiprocessadores e clusters Exercício 7. bn] é definido como: n a ⋅ b = ∑ ai bi = a1 b1 + a2 b2 +…+ an bn i =1 Submeta o código para cada programa que demonstra cada operação e verifica a exatidão dos resultados.S Mult. 7.com/object/cuda_get. Explique quaisquer resultados que você encontrar. Mas isso está mudando na arquitetura Fusion da AMD.…. vamos supor que todas as operações matemáticas sejam realizadas em números de ponto flutuante com precisão simples (vamos mudar o nome do loop para SAXP).17. Este é um exemplo de um sistema multiprocessador heterogêneo que es- peramos ver produzido comercialmente no futuro próximo.6 em assembly MIPS na GPU NVIDIA 8800 GTX descrita neste capítulo.1 [20] <7. A Intel está considerando o uso de sua tecnologia de interconexão QuickPath. escreva um programa CUDA para realizar o seguinte vetor de operações: 1. a2. Lembre-se de usar a versão “emurelês” (Emulation Mode) do código (você não precisará do hardware NVIDIA real para esse trabalho). Suponha que as instruções utilizem o seguinte número de ciclos para serem executadas. b2. 7.7> Usando o “template” de exemplo de SDK como ponto de partida.17. Loads Stores Add.1 [90] <7.17 Faça o download do CUDA Toolkit e SDK em www.S 5 2 3 4 7.18 A AMD recentemente anunciou que estarão integrando uma unidade de processamento gráfica com seus cores x86 em um único pacote.7> Descreva como você construirá warps para o loop SAXP explorar os oito cores fornecidos em um único multiprocessador. Atualmente a comunicação deve ser realizada entre chips de CPU e GPU discretos.2 [90] <7. 16) para facilitar a intercomunicação. Exercício 7.564 Capítulo 7  Multicores.7> Se você tiver hardware GPU disponível. o plano é usar múltiplos canais PCI express (pelo menos. Um dos principais pontos de projeto será permitir a comunicação de dados rápida entre a CPU e a GPU.nvidia.html.…. an] e b = [b1. a . embora com diferentes clocks para cada um dos cores. Exercício 7. Crie os programas de exemplo fornecidos no SDK e confirme se eles rodarão no emulador.b (subtração vetor-vetor) 2.16. Nesse problema. a · b (produto pontual de vetor) O produto pontual de dois vetores a = [a1.16 Suponha que queiramos executar o loop DAXP mostrado na Seção 7. . 21 Ao realizar cálculos sobre matrizes esparsas. 7. A linha i da matriz original se estende de A(IA(i)) até A(IA(i + 1) − 1).1 [15] <7.7> Compare a largura de banda e latência associadas a essas duas tecno- logias de interconexão.19.15 Exercícios 565 7. que mostra uma topologia de interconexão de cubo n de ordem 3. normalmente encontrada nas operações de matriz.20 O benchmarking é um campo de estudo que envolve identificar cargas de trabalho representativas para rodar em plataformas de computação específicas a fim de poder comparar objetivamente o desempenho de um sistema com outro.1 [60] <7.8> Compare a resiliência a falha do cubo n com uma rede de interconexão totalmente conectada. 7. vamos comparar duas classes de benchmarks: o benchmark Whetstone CPU e o pacote de benchmark PARSEC. Como resultado.19. O terceiro array.9> O que é inerentemente diferente entre essas duas classes de carga de trabalho quando executadas nesses sistemas multicore? 7. de modo que também tem tamanho R.21.2 [60] <7. Desenhe uma comparação da confiabilidade como uma função do número de links que podem falhar para as duas topologias.9> Considere a matriz esparsa X a seguir e escreva o código C que armazenaria esse código no Yale Sparse Matrix Format. 7. Selecione um programa do PARSEC. As matrizes esparsas não possuem a localidade espacial no fluxo de dados.2 [10] <7.9. Um recurso atraente de uma topologia de rede de interconexão de cubo n é sua capacidade de sustentar links partidos e ainda oferecer conectividade. Ele armazena uma matriz esparsa inicial m × n.18. mais um). Neste exercício. JA. . IA(i) contém o índice de A do primeiro elemento diferente de zero da linha i. Considere a execução de múltiplas cópias do Whetstone contra a execução do benchmark PARSEC em qualquer um dos sistemas descritos na Seção 7. Exercício 7. M.1 [10] <7.11. Todos os programas deverão estar disponíveis gratuitamente na internet. Também construímos um segundo array IA de tamanho m + 1 (ou seja. Exercício 7. 7. novas representações de matriz foram propostas. podemos construir um array A de tamanho R que contém todas as entradas diferentes de zero de M (na ordem da esquerda para a direita e de cima para baixo). a latência na hierarquia de memória torna-se um fator muito importante.8> Desenvolva uma equação que calcule quantos links no cubo n (onde n é a ordem do cubo) podem falhar e ainda podemos garantir que um link não partido existirá para conectar qualquer nó no cubo n. 7. que interconecta oito nós.20. 7. em formato de linha usando três arrays unidimensionais.10> Em termos do modelo roofline. Suponha que R indique o número de entradas diferentes de zero em M.19 Consulte a Figura 7. uma entrada por linha.20.1 [25] <7.9b. que dependência terão os resul- tados que você obtiver ao executar esses benchmarks na quantidade de compartilhamento e sincronização presente na carga de trabalho utilizada? Exercício 7. Uma das representações de matriz esparsa mais antigas é o Yale Sparse Matrix Format. contém o índice de coluna de cada elemento de A. 0.0. 3.7] Linha 5 [1. Suponha que nossos processadores executem nas seguintes frequências: CPU A CPU B CPU C 1 GHz 3 GHz 250 MHz A CPU A pode executar 2 instruções por ciclo. CPU B — Uma CPU inteira de único core rápida (ou seja.0.9> Em termos do espaço de armazenamento.0. e a CPU C pode executar 8 instruções (embora a mesma instrução) por ciclo. a CPU B pode executar 1 instrução por ciclo.0.21.0] Linha 4 [0. Começamos a ver algumas aparecendo no mercado de processamento embutido nos sistemas que contêm DSPs de ponto flutuante e CPUs de microcontrolador em um pacote de módulo multichip.0.0.0.9.1.21. 4. As CPUs A e B têm um conjunto de instruções semelhante a um processador MIPS. 99.22 Nos sistemas do futuro.0. calcule a quantidade de armazenamento usada para armazenar a matriz acima no Yale Sparse Matrix Format.9> Você consegue achar uma representação de matriz esparsa mais eficiente (em termos de overhead de espaço e computacional)? Exercício 7. [2.9> Realize a multiplicação de matriz da Matriz X pela Matriz Y mostrada a seguir. CPU C — Uma CPU de vetor lenta (com capacidade de ponto flutuante) que pode executar múltiplas cópias da mesma instrução por ciclo.1. Compare o tempo de execução do uso de uma representação sim- ples da matriz e do Yale Sparse Matrix Format. 1. Suponha que você tenha três classes de CPU: CPU A — Uma CPU multicore de velocidade moderada (com uma unidade de ponto flutuante) que pode executar múltiplas instruções por ciclo. esperamos ver plataformas de computação heterogêneas cons- truídas a partir de CPUs heterogêneas. Todas as três CPUs possuem a capacidade de realizar aritmética com inteiros. 3. multiprocessadores e clusters Linha 1[1. 3.0] Linha 3 [0.566 Capítulo 7  Multicores.3 [15] <7. 7. 7. supondo que cada elemento na matriz X tenha formato de ponto flutuante com precisão simples.2 [10] <7.2.0.0. A CPU C só pode realizar operações de soma e subtração de ponto flutuante.4 [15] <7. sem unidade de ponto flutuante) que pode executar uma única instrução por ciclo.0.1] 7. embora a CPU B não possa realizar aritmética de ponto flutuante diretamente.0] Linha 2 [0. 2] Coloque esse cálculo em um loop e meça o tempo de sua execução. 7.21. Suponha que todas as operações possam concluir sua execução em um único ciclo de latência sem quaisquer hazards.0. assim como loads e stores de . Não se esqueça de aumentar o número de vezes que esse loop é executado para obter uma boa resolução na sua medição do tempo. 11> Que tipo de instrução você acrescentaria à CPU de vetor C para obter o melhor desempenho? Exercício 7. §7. Verdadeiro. 7. Latência de transação média Taxa de processamento de transação máxima 1 ms 5000/seg 2 ms 5000/seg 1 ms 10.3: Falso.9: Verdadeiro. §7. Como o endereço compartilhado é um endereço físico. §7. Enviar e receber uma mensagem é uma sincronização implícita.11> Na média. você mesmo” §7.11> Descreva como você particionaria o problema nas três CPUs dife- rentes para obter o melhor desempenho.11> Se você passasse para um sistema de 8 cores. múltiplas tarefas em seus próprios espaços de endereço virtual podem executar bem em um multiprocessador de memória compartilhada.1 [10] <7.23. A tarefa em mãos é comparar duas matrizes X e Y.6: Verdadeiro. quantas transações/segundo o computador processará)? 7. O paralelismo em nível de tarefa pode ajudar as aplicações sequenciais e as Respostas das aplicações sequenciais podem ser criadas para executar em hardware paralelo. 7. §7.23. DIMMs de DRAM gráfica são apreciadas por sua largura de banda mais alta.23.2: Falso.22.5: 1.15 Exercícios 567 memória. embora Seções “Verifique isso seja mais difícil.1 [10] <7. Suponha também que cada instrução leve. uma quantidade de tempo fixa para ser processada.2 [10] <7. responda às seguintes perguntas: 7. 2.23 Suponha que um sistema de computador quad-core possa processar transações de banco de dados em uma taxa de estado constante de solicitações por segundo. na média. §7. §7.11> Discuta por que raramente obtemos esse tipo de speed-up simples- mente aumentando o número de cores. limitaria a expansão.1: Falso. 7. Verdadeiro. A expansão fraca pode compensar uma parte serial do programa que. que contêm cada uma 1024 × 1024 elementos de ponto flutuante.000/seg Para cada um dos pares na tabela. o que aconteceria com a vazão do sistema (ou seja.7: Falso. .4: 1. §7. 2. A tabela a seguir mostra pares de latência de transação e taxa de processamento. Suponha que todas as CPUs tenham acesso à memória compartilhada e que a sincronização tenha custo zero. além de um modo de compartilhar dados. Verdadeiro. A saída deverá ser uma contagem dos índices numéricos em que o valor em X foi maior que o valor em Y.22.2 [10] <7. Falso.000/seg 2 ms 10.3 [10] <7. Provavelmente precisamos de inovação em todos os níveis da pilha de hardware e software para vencer a aposta da indústria na computação paralela. na forma ideal. quantas solicitações estão sendo processadas em deter- minado instante? 7. de outra forma. 1930s NVIDIA . A A P Ê N D I C E Gráficos e GPUs de computação John Nickolls Imaginação é mais Diretor de Arquitetura. importante que NVIDIA conhecimento. David Kirk Albert Einstein. On Science.  Cientista Chefe. a GPU mistura de processamento gráfico tem uma arquitetura gráfica e de computação unificada. os cálculos se tornaram mais precisos com o tempo. Um PC é um sistema um controlador VGA (Video Graphics Array). mereceu um novo nome além de controlador VGA. computador desktop e estação de trabalho. portanto. incluindo hardware para configuração e rasterização de triângulos (cortar triângulos em pixels in- dividuais) e mapeamento e sombreamento de textura (aplicar “decalques” ou padrões aos pixels e misturar cores). interfaces gráficas com o usuário.3 Programando GPUs  576 A.7 Vida real: o NVIDIA GeForce 8800  605 A. O termo GPU foi usado para indicar que o dis- positivo gráfico tornou-se um processador. otimizado para computação visual. Em 1997. Em 2000. imagens e vídeo. aplicações de representação visual e vídeo. jogos de vídeo.10 Comentários finais  629 A.A. um controlador de memória e gerador de vídeo conectado a alguma DRAM. Um controlador VGA era simplesmente heterogêneo CPU-GPU.5 Sistema de memória paralela  597 A. pois os processadores progra- máveis substituíram a lógica dedicada de função fixa enquanto mantinham a organização básica do pipeline gráfico 3D. laptop. e recentemente para ponto flutuante de precisão dupla. não havia algo do tipo GPU.4 Arquitetura de multiprocessador multithreaded  587 A. computação visual e exibição.1 Introdução  569 A.9 Falácias e armadilhas  626 A. Com o tempo. imagens e vídeo.11 Perspectiva histórica e leitura adicional  629 A. os controladores VGA estavam começando a incorporar algumas funções de aceleração tridimensional (3D). a gráfico (GPU)  Um processador otimizado para gráficos 2D e 3D.1   Introdução Este apêndice focaliza a GPU — a onipresente unidade de processamento gráfico em unidade de processamento cada PC.2 Arquiteturas de sistemas GPU  572 A. até ponto flutuante de precisão simples.8 Vida real: mapeando aplicações a GPUs  612 A. Na década de 1990. Para oferecer in. Em sua forma mais básica. o processador gráfico de único chip incorporou quase todos os detalhes do pipeline gráfico da estação de trabalho de alto nível tradicional e. Os gráficos em um PC eram realizados por processador. de gráficos. . computação visual Uma teração visual em tempo real com objetos calculados via gráficos. GPU gera gráficos 2D e 3D. altamente multithreaded. Além disso. imagens e vídeo que habilitam sistemas operacionais baseados vídeo. que serve como um processador e computação. progredindo da aritmética indexada até inteiros e ponto flutuante. a tecnologia de semicondutor avançou suficientemente para que mais funções pudessem ser acrescentadas ao controlador VGA.6 Aritmética de ponto flutuante  601 A. A GPU moderna que descrevemos aqui é um multiprocessador altamente paralelo. em janelas. as GPUs tornaram-se mais programáveis. que lhe permite interagir visualmente com os gráfico programável e uma plataforma de computação paralela escalável. PCs e consoles objetos computados através de jogo combinam uma GPU com uma CPU para formar sistemas heterogêneos. Breve histórico da evolução da GPU sistema heterogêneo  Um sistema combinando diferentes tipos de Há quinze anos. A computação visual em uma GPU moderna combina o processamento gráfico e a computação paralela em novas maneiras. certamente não é o único. vértice e pixel é executado no mesmo tipo de processador. como C e C + +. Juntos. Ela subs- titui grandes seções do modelo tradicional de pipeline gráfico de hardware sequencial por elementos programáveis para programas de geometria. um array de processadores agora pode ser montado com muito poucos processadores. Mais cores de processador programável aumentam a vazão total do sistema. Por fim. é um processador com- plementar. com centenas de cores e milhares de threads. é possível criar de definições de função e estrutura de dados que fornece uma interface aceleração de hardware eficaz das funções de processamento gráfico definidas pelas APIs. fez sentido mesclar diferentes elementos de pipeline programáveis em um array unificado de muitos processadores programáveis. A duplicação frequente do desempenho da GPU possibilita novas aplicações. Tendências gráficas da GPU GPUs e seus drivers associados implementam os modelos OpenGL e DirectX do proces- samento gráfico. OpenGL é um padrão aberto para a programação gráfica 3D. o que dobra o desempenho da geração anterior nas aplicações existentes. Essa unificação permite uma escalabilidade incrível. O melhor desempenho para muitas aplicações vem do uso da CPU e da GPU. para uma biblioteca de funções. Unificar os processadores também oferece balanceamento de carga bastante eficaz. agora multicore. Na geração de GPUs GeForce 8-series. Na outra ponta do espectro. A CPU. para a GPU manycore maciçamente paralela. Esse é um dos motivos (além de aumentar a densidade do dispositivo) para que novas GPUs estejam sendo desenvolvidas a cada 12 a 18 meses. GPU evolui para processador paralelo escalável GPUs evoluíram funcionalmente de controladores VGA fisicamente conectados. e um ambiente de programação foi criado no sentido de permitir que as GPUs fossem programadas usando linguagens conhecidas. disponível para a maioria dos computadores.A-570 Apêndice A  Gráficos e GPUs de computação GPUs tornaram-se processadores programáveis maciçamente paralelos. Essa inovação torna a GPU um processador totalmente de uso geral. Como essas interfaces de aplicação (API)  Um conjunto programação de aplicação (APIs) possuem comportamento bem definido. uma porta aberta para aplicações de processamento paralelo inteiramente novas sobre GPUs predominantes de alto desempenho. esses dois tipos de processadores compreendem um sistema multiprocessador heterogêneo. programável e de muitos cores. pois todas as funções podem ser executadas nos mesmos processadores. incluindo Direct3D para gráficos 3D. Recentemente. vértice e pixel. de capa- cidade limitada. Este apêndice o ajudará a entender como e quando dividir melhor o trabalho entre esses dois processadores cada vez mais paralelos. DirectX é uma série de interfaces de programação de interface de programação de multimídia da Microsoft. pois qualquer função de processamento pode usar o array de processadores inteiro. conhecido como computação visual. para processadores paralelos programáveis. A interseção de processamento gráfico e computação paralela convida um novo paradigma para gráficos. Sistema heterogêneo Embora a GPU seja discutivelmente o processador mais paralelo e mais poderoso em um PC típico. que permitem que novos algoritmos gráficos sejam implementados. o processamento de geometria. Essa evolução prosseguiu alte- rando o pipeline gráfico lógico (baseado em API) para incorporar elementos programáveis e também tornando os estágios de pipeline de hardware básicos menos especializados e mais programáveis. instruções de processador e hardware de memória foram acrescentadas para dar suporte a linguagens de programação de uso geral. apesar de ainda ter alguns benefícios e limitações especiais. que não eram possíveis anteriormente. . antes de tudo serial. tation on GPU (GPGPU). e pipeline gráfico. na realidade. A GPU pode executar programas de sombreamento gráfico para o aspecto gráfico da GPU. Jogos são construídos sobre a capacidade de processamento de gráficos 3D. que são “primos de primeiro grau” dos gráficos. CUDA plataforma de programação paralela para GPUs e CPUs multicore. A. A grande quantidade de poder de processamento de ponto flutuante no array de processadores GPU é muito atraente para solucionar problemas não gráficos. Embora os processadores de suporte da GPU sejam unificados. múltiplos dados). A arquitetura do proces- sador de suporte da GPU é exposta de duas maneiras: primeiro. Computação GPU é o termo criado para usar a GPU para computação através de uma Computação GPU  Usar uma linguagem de programação paralela e API. e também executar programas de thread em CUDA. de uma linguagem de programação paralela e API. O modelo de programação CUDA tem um estilo de CUDA  Um modelo de programação software SPMD (Single-Program Multiple Data – único programa. As GPUs são eficazes em gráficos 2D e 3D. de modo que CUDA é um ambiente para escrever programas para todo o sistema de compu- tador heterogêneo. GPU unifica gráficos e computação Com o acréscimo de CUDA e computação GPU às capacidades da GPU. Isso é contrário à técnica mais antiga da General Purpose compu. mente programe em C ou C + +. com suporte a uma série de tarefas de processamento. Deixar de oferecer esse desempenho da aplicação seria fatal. para processar geometria. vértices e pixels. e combinar esses usos nas aplicações de computação visual. como um array de processadores altamente paralelos e programáveis em C/C + + com CUDA. OpenGLTM e DirectXTM. mas levando em conta uma execução escalável. De fato. A GPU é. acessando o poder de processamento da GPU através das APIs gráficas. sem usar a API gráfica tradicional e o modelo GPU para computação através de pipeline de gráfico. O escopo original de uma GPU era “tudo com pixels”. Aplicações de computação visual da GPU A computação visual inclui os tipos tradicionais de aplicações gráficas além de muitas aplicações novas. implementando as APIs gráficas programáveis. o modelo de programação para a computação mais geral deverá expressar diretamente o forte paralelismo. que de uma API gráfica tradicional permite que o programador evite a API gráfica e interfaces gráficas da GPU e simples. não é necessário que todos os programas de thread SPMD sejam iguais. Essa é uma tada por muitas threads em paralelo nos múltiplos processadores da GPU.1 Introdução A-571 Por que CUDA e computação GPU? Esse array de processadores uniforme e escalável convida a um novo modelo de progra- mação para a GPU. no paralelo escalável e linguagem qual um programador escreve um programa para uma thread que é instanciada e execu. As GPUs são excelentes em gráficos e computação visual. uma arquitetura de multiprocessador versátil. mas nem tanto para problemas menores e menos regulares. Dado o grande grau de paralelismo e a faixa de escalabilidade do array de processadores para aplicações gráficas. que envolve programar a GPU usando uma API gráfica e pipe- line gráfico para realizar tarefas não gráficas. Em geral. computação de uso geral através lela escalável e plataforma de software para a GPU e outros processadores paralelos. baseada em C/C + +. mas com computação regular e/ou estrutura de dados. pois realizam muito trabalho paralelo. agora é possível usar a GPU como um processador gráfico e um processador de computação ao mesmo tempo. mas agora ele in- clui muitos problemas sem pixels. . GPGPU  Usar uma GPU para Compute Unified Device Architecture (CUDA) é um modelo de programação para. pois essa é a finalidade para a qual elas foram projetadas. As GPUs também são excelentes em muitas aplicações de vazão de uso geral. também oferece uma facilidade para programar também múltiplos cores de CPU. em especial os grandes. pois foram projetadas especificamente para essas aplicações. além de ter muita estrutura de problema regular. Gráficos 2D e 3D utilizam a GPU em seu “modo gráfico”. elas são uma boa combinação para os problemas paralelos de dados (veja Capítulo 7). e segundo. controladora de interrupção. com respectivos subsistemas de memória. conhecido como VGA (Video Graphics Array). usando CUDA para programar a GPU no modo de computação. Os subsistemas gráficos com elementos de processamento embutidos (GPUs) não existiam no panorama do PC de 1990. Agora. também por meio de PCI-Ex- a ponto. a GPU está conectada ao chip set.0 de 16 pistas. do sistema. LAN). Arquitetura heterogênea de sistema CPU-GPU Uma arquitetura heterogênea de sistema de computação usando uma GPU e uma CPU pode ser descrita em um nível alto por duas características principais: primeiro. o programa será eficiente. essas GPUs podem ser programadas para implementar um pipeline virtual diferente. as GPUs e CPUs podem configurável de pistas e largura de banda. De modo semelhante. o que es- timulará novas técnicas de computação visual. que foi conectado ao barramento PCI. . O processamento de vídeo. controladora de DMA. o processamento de imagens é simplesmente outro programa de array paralelo de dados. A bridge norte (veja Capítulo 6) contém interfaces com alta largura de banda. acessar a memória um do outro. embora com menos largura de banda disponível que seu acesso às memórias conectadas mais diretamente. As primeiras GPUs implementavam apenas APIs gráficas específicas. com uma CPU da Intel. que usa links ponto com uma CPU da AMD. memória e barramento PCI. Os links têm um número press. na Figura A.2. Estas são carac- terizadas por uma GPU (GPU discreta) e CPU separadas. Dis- cutimos as configurações do sistema. quantos subsistemas funcionais e/ou chips são usados e quais são suas tecnologias de interconexão e topologia. a GPU não poderia acelerar sua tarefa.2. todas as aplicações agora são possíveis. com a mesma largura de banda disponível. vemos a GPU conectada por meio de PCI-Express (PCIe) Uma um link PCI-Express 2. A. Se não. Isso era maravilhoso se a API aceitasse as operações que você queria fazer. Na medida em que o acesso aos dados for regular e existir boa localidade. A maior oportunidade para aplicações de computação visual sobre GPUs é “romper o pipeline gráfico”. quais subsistemas de memória estão disponíveis a esses subsistemas funcionais. a bridge norte ou a controladora de memória é integrada ao mesmo die que a CPU. e segundo.2. conectando a CPU. o processamento de imagem é uma aplicação muito boa para GPUs.2  Arquiteturas de sistemas GPU Nesta seção. Veja no Capítulo 6 uma base sobre os sistemas de E/S e chip sets do PC. Nos dois casos. o processamento de imagens e vídeo são aplicações im- portantes para as GPUs. Na Figura A. embora com um desempenho muito alto. A Figura A.2a. A bridge sul contém interfaces e dispositivos legados: barramento ISA (áudio. com o advento da computação da GPU e CUDA. Nesse sistema. a exibição foi controlada por um subsistema de framebuffer sim- ples. especialmente a codificação e a decodificação (compactação e descompactação de acordo com alguns algoritmos padrão) é muito eficiente.2 ilustra duas configurações comuns em uso atualmente.A-572 Apêndice A  Gráficos e GPUs de computação Além dos gráficos 2D e 3D. pois a funcionalidade inicial da GPU era imutável. simplesmente escrevendo-se um programa CUDA para descrever a computação e o fluxo de dados que se deseja.1 é um diagrama em blocos de alto nível de um PC legado. Usando CUDA.2. Estes podem ser implementados usando as APIs gráficas ou como programas computacionais. Na prática. Assim. hora/ contador. analisamos as arquiteturas de sistemas GPU em uso comum hoje em dia. O PC histórico (por volta de 1990) A Figura A. No caso do sistema da AMD.2b. para oferecer uma taxa de transferência máxima interconexão de E/S padrão de 16GB/s (máximo de 8GB/s em cada direção). interfaces de programação padrão e uma arquitetura interna básica da GPU. funções e serviços da GPU. por volta de 1990. . FIGURA A. Veja no Capítulo 6 uma explicação dos componentes e interconexões nesta figura.1  PC histórico.2.2.2  Arquiteturas de sistemas GPU A-573 FIGURA A. A controladora VGA controla a exibição gráfica da memória do framebuffer. A.2  PCs contemporâneos com CPUs Intel e AMD. Um exemplo é o sistema multi-GPU NVIDIA SLI (Scalable Link Interconnect).3.3  Pipeline lógica gráfica. as GPUs são conectadas a uma CPU por meio da PCI-Express. um sistema pode ser reimplementado muitas vezes para explorar processos de manufatura com silício mais avançados. Os sistemas de console são projetados para serem entregues com desempenho e funcionalidade idênticas por um es- paço de tempo que pode durar cinco anos ou mais.2. Interfaces e drivers de GPU Em um PC de hoje. As GPUs podem acessar sua própria memória local física e a memória física do sistema da CPU usando ende- reços virtuais que são traduzidos por uma MMU na GPU. O kernel do sistema operacional gerencia as tabelas de página da GPU. O Capítulo 5 explica como as caches mantêm coerência em um espaço de endereço compartilhado.A-574 Apêndice A  Gráficos e GPUs de computação Unified Memory Architecture Uma variação de baixo custo desses sistemas. Esses sistemas têm GPUs com desempenho relativamente baixo. Mapeando o pipeline gráfico a processadores de GPU unificados A Figura A. geometria e pixel). enquanto a memória da GPU dedicada oferece alta largura de banda e baixa latência. e os blocos de função fixa aparecem com fundo branco. usa apenas memória do sistema da CPU. . Uma página física do sistema pode ser acessada usando transações PCI-Express coerentes ou não coerentes. A próxima categoria de sistema integra a GPU com a bridge norte (Intel) ou chipset (AMD) com e sem memória gráfica dedicada. penho alcançado é limitado pela largura de banda disponível da memória do sistema e latência aumentada do acesso à memória. nor- malmente duas a quatro trabalhando em paralelo. e assim oferecer capacidade constante a custos ainda mais baixos. um sistema Unified Memory Architec- (UMA)  Uma arquitetura de ture (UMA). Os sistemas de console não precisam ter seus subsistemas expandidos e atualizados da forma como os sistemas de PC fazem. como o Sony PlayStation 3 e o Microsoft Xbox 360 são semelhantes às arquiteturas de sistemas do PC. programas e dados à GPU por meio largura de banda do barramento PCI original para um slot de única de um driver de dispositivo gráfico otimizado para a GPU em particular. Uma variação do sistema de alto desempenho utiliza múltiplas GPUs conectadas. determinadas por um atributo na tabela de página da GPU. pois seu desem- sistema comum. em vez de padronizados. existem múltiplos espaços de endereço.4 mostra como o pipeline lógico compreendendo estágios programáveis independentes separados é mapeado em um array físico distribuído de processadores. As AGP  Uma versão estendida do gerações anteriores usavam AGP. Sua finalidade principal era conectar os subsistemas gráficos nos sistemas de PC. Pipeline lógico gráfico O pipeline lógico gráfico é descrito na Seção A.2. placa. Com CPUs e GPUs. destacando os estágios programáveis importantes (estágios de sombreamento de vértice. A Figura A.3 ilustra os principais es- tágios de processamento. omitindo a memória da GPU do sistema em que a CPU e a GPU compartilham uma memória de sistema.2. FIGURA A. 2006] ou Direct3D [Microsoft DirectX Specification] que usam a GPU que fornecia até oito vezes a como um coprocessador. descritas anteriormente. de modo que os principais barramentos internos do sistema tendem a ser customizados. As APIs enviam comandos. A CPU pode acessar a memória local da GPU através de um intervalo de endereços (também chamado de abertura) no espaço de endereços PCI-Express. As aplicações gráficas chamam funções de API OpenGL barramento de E/S PCI original. Consoles de jogos Sistemas de console. projetado para jogos de alto desempenho e estações de trabalho. Os estágios de sombreamento programável estão sombreados. [Segal e Akeley. Durante esse tempo. com suas telas encadeadas em forma de margarida. mais do orçamento de transistores por chip é dedicado à computação. Os processadores se conectam a quatro partições de DRAM com 64 bits de largura por meio de uma rede de interconexão. operações de rastreio. e programas de cálculo executam nos mesmos processadores. anti-aliasing. geometria e pixel executam nas SMs unificadas e seus cores SP. diferente das GPUs anteriores. Ele tem uma arquitetura unificada em que os programas gráficos tradicionais para o sombreamento de vértice. A Figura A. duas unidades de função especial (SFUs). Como as regiões de filtro do suporte normalmente se sobrepõem para solicitações de textura sucessivas. organizados como 14 multiproces- sadores streaming (SM) multithreaded. A arquitetura de array do processador é escalável para configurações de GPU menores e maiores. Array de processadores Um array de processador GPU unificado contém muitos cores de processador. que tinham processadores separados dedicados a cada tipo de processamento. Essa é a arquitetura Tesla básica implementada pelo NVIDIA GeForce 8800. uma pequena cache de textura L1 de streaming é eficaz para reduzir o número de solicitações ao sistema de memória. e o fluxo de dados do pipeline gráfico lógico recircula pelos processadores. compactação.2. escalando o número de multiprocessadores e o número de partições de memória. O array de processadores se conectam com processadores de operação de . A. GPUs manycore possuem um objetivo de projeto arquitetônico diferente. focalizado na execução de muitas threads paralelas eficientemente em muitos cores de processador.2.2. vamos focalizar aqui os processadores programáveis. Em comparação com CPUs multicore. Usando muitos cores mais simples e otimizando para o comportamento paralelo de dados entre os grupos de threads.4  Pipeline lógico mapeado nos processadores físicos. e menos às caches no chip e overhead. O array de processador programável é altamente integrado com processadores de função fixa para filtragem de textura.5 mostra sete clusters de dois SMs compartilhando uma unidade de textura e uma cache L1 de textura.2  Arquiteturas de sistemas GPU A-575 FIGURA A. A Figura A. Elas unificam o processamento do sombreamento de vértice. Cada SM tem oito cores SP. uma unidade de instrução multithreaded e uma memória compartilhada. decodificação de vídeo e processamento de vídeo de alta defini- ção. caches de instrução e constante. rasterização. exibição. geometria e pixel e a computação paralela nos mesmos processadores. Embora os processadores de função fixa excedam significativamente os processadores programáveis mais genéricos em termos de desempenho absoluto. custo ou potência. Cada core de SP é altamente multithreaded. Os estágios de sombreamento pro- gramável são executados no array dos processadores unificados.5 mostra uma GPU com um array de 112 cores de processador streaming (SP). normalmen- te organizados em multiprocessadores multithreaded. Arquitetura unificada básica da GPU As arquiteturas unificadas da GPU são baseadas em um array paralelo de muitos proces- sadores programáveis. restringido por um orçamento de área. descompactação. con- trolando 96 threads concorrentes e seu estado no hardware. A unidade de textura gera resultados filtrados ao SM dado um conjunto de coordenadas em um mapa de textura. chegando a centenas de cores de processador e dezenas de milhares de threads simultâneos em 2008.3   Programando GPUs Programar GPUs de multiprocessador é qualitativamente diferente de programar ou- tros multiprocessadores. os cores são altamente multithreaded.5  Arquitetura unificada básica da GPU. rastreio (ROP). diferentes produtos de GPU implementam quantidades bastante variadas de processadores e threads. independente de quantas threads paralelas ela executa ou quantos cores de processador paralelos ela tenha. caches de textura L2. GPU de exemplo com 112 cores de processador streaming (SP) organizados em 14 multiproces- sadores streaming (SMs). As GPUs continuam a aumentar seu paralelismo.2. Os processadores se conectam com quatro partições DRAM com 64 bits de largura por meio de uma rede de interconexão. gráficos. Como resultado. dobrando-o aproximadamente a cada 12 a 18 meses.A-576 Apêndice A  Gráficos e GPUs de computação FIGURA A. Ela tem a arquitetura Tesla básica de um NVIDIA GeForce 8800. memórias DRAM externas e memória do sistema por meio de uma rede de interconexão da largura da GPU. como CPUs multicore. caches de instrução e constante. uma unidade de instrução multithreaded e uma memória compartilhada. os usuários esperam que aplicações de jogos. imagens e cálculo funcionem em qualquer GPU. A. os modelos de programação de GPU e os programas de aplicação são projetados para se expandirem transparentemente a uma grande extensão de paralelismo. As GPUs oferecem duas ou três ordens de grandeza de paralelismo de thread e dados que as CPUs. Cada SM tem oito cores SP. e eles esperam que GPUs mais caras (com mais threads e cores) rodem as aplicações mais rapida- mente. Para transpor a grande faixa de preço e desempenho dos diferentes segmentos de mercado. duas unidades de função especial (SFUs). A força motriz por trás do grande número de threads e cores paralelos em uma GPU é o desempenho gráfico em tempo real – a necessidade de renderizar cenas 3D complexas . Mesmo assim. segundo a lei de Moore [1965] de aumento da densidade do circuito integrado e pela melhoria na eficiência arquitetônica. O número de processadores e o número de memórias podem se expandir para projetar sistemas de GPU balanceados para diferentes segmentos de desempenho e mercado. transparentemente à aplicação. Pipeline gráfico lógico A Figura A. Cada estágio de pipeline gráfico é mapeado no hardware de GPU ou em um processador de GPU. 2006]. . os blocos de função fixa estão em branco e os objetos da memória estão em cinza. Esse paradigma simples surgiu a partir das APIs gráficas e linguagens de sombreamento que descrevem como sombrear um vértice ou um pixel.3.3. De modo correspondente. Cada estágio processa um vértice.3  Programando GPUs A-577 com alta resolução em taxas de frames interativas. e continuam a se desenvolver rapidamen- te com os avanços do hardware de GPU. se expandem transparentemente por uma grande faixa de paralelismo de hardware. permite que aplicações de computação paralela em geral aproveitem grandes números de threads paralelas e se ex- pandam para qualquer número de cores de processador paralelos. Os es- tágios de sombreamento programável estão em azul. uma das interfaces de programação de multimídia DirectX da Microsoft. Nesses modelos de programação escaláveis. A API e pipeline lógico oferecem uma infraestrutura de FIGURA A. Depois ela descreve as GPUs de programação para aplicações de computação visual e cálculo paralelo em geral usando a linguagem C e o modelo de programação CUDA. foi proposto originalmente e definido pela Silicon Graphics Incorporated. um consórcio do setor.1 ilustra o pipeline gráfico lógico Direct3D 10. Eles definem um pipeline de processamento gráfi- co lógico que é mapeado no hardware de GPU e processadores. A.1  Pipeline gráfico Direct3D 10. 2006]. Os programas. Esta seção descreve rapidamente as GPUs de programação para aplicações gráficas de tempo real usando APIs gráficas e linguagens de programação. é definido e desenvolvido ainda mais pela Microsoft e seus parceiros. Ele continuou sendo um paradigma eficaz à medida que as GPUs rapidamente aumentaram seu paralelismo e desempenho desde o final dos anos 90. são projetados para explorar grandes graus de paralelismo por meio de muitas threads paralelas independentes e expandir para qualquer número de cores de processador. definida pela Microsoft e seus parceiros. OpenGL. um padrão aberto. [Kessenich. o programador escreve código para uma única thread. 2006]) é algo gerenciado pela Khronos. O modelo de programação paralela escalável CUDA. Direct3D  Uma API gráfica volvimento e extensão contínua do padrão OpenGL ([Segal e Akeley. Existem duas APIs gráficas padrão principais: OpenGL e Direct3D. e a GPU executa milhares de instâncias de thread em paralelo. a pelo menos 60 frames por segundo. de modo semelhante. Programando gráficos em tempo real As APIs desempenharam um papel importante no desenvolvimento rápido e bem-sucedido das GPUs e processadores. um padrão de fato. assim. OpenGL e Direct3D são estruturados de modo semelhante. juntamente com modelos de programação e linguagens para os estágios de pipeline programáveis. Direct3D [Blythe. primitivo geométrico ou pixel em um padrão de fluxo de dados de streaming. OpenGL  Uma API gráfica de padrão aberto. os modelos de programação escaláveis das linguagens de som- breamento gráfico. O desen. como Cg (C para gráficos) e HLSL (High-Level Shading Language). OpenGL tem uma estrutura de pipeline gráfico semelhante. Os programas de sombrea- mento de geometria operam sobre primitivos geométricos (como linhas e triângulos) defi- nidos por múltiplos vértices. primitivos e pixels em paralelo. Os programas de sombreamento de vértice mapeiam a posição dos vértices gráficos. Sombreamentos (e GPUs) utilizam aritmética de ponto flutuante para todos os cálculos de cor de pixel. e filtradas com coordenadas imagens e dados. y. w) e calcula uma posição de tela em ponto flutuante (x. z. produz resultados independentes e não tem efeitos colaterais. decalques. memória e infra- estrutura para os programas de sombreamento que processam cada fragmento de vértice. Os usuários programam todas as três threads gráficas com uma linguagem de alto nível dirigida comum. funções. y. cor ou orientação. mas estão longe de ser linguagens de computação de uso geral: atualmente não possuem acesso à memória geral. Os sombreamentos de pixel utilizam bastante as pesquisas amostradas e filtradas em textura  Um array 1D. alterando-os ou gerando primitivos adicionais. A API gráfica e o pipeline gráfico oferecem objetos de entrada. a E/S é implícita.A-578 Apêndice A  Gráficos e GPUs de computação fluxo de dados de streaming e canalização para os estágios de sombreamento programável. interpolação e acesso e filtragem de textura. pois cada uma trabalha sobre dados independentes. que pode descartar um fragmento de pixel oculto ou substituir a profundidade do pixel pela profundidade do fragmento. alfa (RGBA) de ponto flutuante para a imagem renderizada em sua posição de imagem (x. primitivo ou pixel. muitas instâncias de programa podem ser executadas em paralelo. e realiza uma operação de combinação de cores. usando coordenadas de ponto flutuan- que admite pesquisas amostradas te interpoladas. azul. Programas de sombreamento gráfico sombreamento  Um programa que opera sobre dados gráficos. HLSL e Cg consideram que os programas residem dentro de um pipeline gráfico lógico. trigonometria. como threads paralelas independentes. que processam diferentes quantidades de vértices. O estágio de processamento de operações de rastreio (ou misturador de interpoladas. Para todos os três tipos de sombreamentos gráficos. sombras e alta faixa dinâmica. saída. A aplicação 3D envia à GPU uma sequência de vértices agrupados em primitivos geométricos – pontos. Sombreamentos utilizam acessos à textura para mapas. O programa de sombrea- mento de geometria executa o processamento por cada primitivo e pode adicionar ou remover primitivos. linhas. Vértices. . do sombreamento de vértice entra com uma posição de vértice em ponto flutuante (x. O programa de sombreamento de vértice executa o proces- samento por cada vértice. z). E/S de arquivo e recursão. HLSL (High-Level Shading Language) e Cg (C para gráficos) normal- mente são usadas. incluindo a interpolação de parâmetros por fragmento. Elas possuem sintaxe tipo C e um rico conjunto de funções de biblioteca para operações de matriz. que corresponde ao pipeline linguagem de renderização de gráfico lógico. 2D ou 3D grandes arrays 1D. verde. a fim de eliminar arte- fatos visíveis enquanto calcula a faixa extrema de valores de contribuição de pixel encon- trados na renderização de cenas com iluminação complexa. portanto. uma thread modelo de programação de fluxo de dados ou streaming. triângulos e polígonos. 2D ou 3D. e. e sombras complexas. alterando sua posição. primitivos e pixels independentes ainda permitem que o mesmo programa gráfico seja executado em GPUs de tamanhos diferentes. y) da amostra do pixel. O montador de entrada coleta vértices e primitivos. Normalmente. Aplicações gráficas de tempo real utilizam muitos programas de sombreamento diferentes como um vértice ou um fragmento para modelar o modo como a luz interage com diferentes materiais e renderizar iluminação de pixel. incluindo a transformação da posição 3D do vértice em uma posição de tela e acendendo o vértice para determinar sua cor. texturização e colora- ção. ponteiros. que combina a cor do frag- mento com a cor do pixel e escreve o pixel com a cor combinada. O programa de sombreamento de pixel realiza o processamento por fragmento. calculando uma contribuição de cor vermelho. As linguagens de shading (ou sombreado) são baseadas em um linguagem de shading Uma modelo de programação de fluxo de dados ou streaming. chamadas texturas. normalmente com um do triângulo na tela. Assim. A unidade de configuração e o rasterizador geram fragmentos de pixel (fragmentos são contribuições em potencial aos pixels) que são cobertos por um primitivo geométrico. saída) realiza teste de profundidade do buffer Z e teste de estêncil. mostrados em azul. programas gráficos se expandem transparen- temente às GPUs com diferentes quantidades de paralelismo e desempenho. Os sombrea- mentos de fragmento de pixel “sombreiam” um pixel cada. Para cada busca de textura. e depois interpola o resultado final com a aritmética de filtragem em ponto flutuante. O sombreamento pesquisa a cor nas duas imagens de textura: um acesso de textura 2D para a cor da superfície e um acesso de textura 3D em um mapa de cubo (seis imagens correspondentes às faces de um cubo) para obter a cor do mundo exterior correspondente à direção de reflexão. Para cada thread de pixel. que implementa a técnica de renderização de “mapeamento de ambiente”. Embora esse programa de sombreamento tenha apenas três linhas. e pode simplesmente atribuir um valor ao parâmetro de saída COLOR para que seja passado adiante. esse som- breamento recebe cinco parâmetros. y) implícita. a maior parte dos threads executa programas de som- breamento de pixel. Os outros três parâmetros “uniformes” não variam de uma instância de pixel (thread) para a seguinte. e um vetor de ponto flutuante 3D dando a reflexão da direção da visão a partir da superfície. cada primitivo e cada fragmento de pixel. Exemplo de sombreamento de pixel Considere o seguinte programa sombreamento de pixel Cg. ou função de interpolação linear. a cor de ponto flutuante final com quatro componentes (vermelho. de modo a ser misturado com um pixel em uma posição (x. A GPU multithreaded executa milhares dessas threads peso leve de sombrea- mento de pixel Cg em paralelo. um sombreamento de fragmento de pixel pode esperar que as coordenadas de texto geométrica normal e múltipla tenham sido interpoladas a partir dos valores de vértice por estágios de função fixa anteriores. e iluminação e sombras complexas exigem razões ainda maiores entre threads de sombreamento de pixel e vértice. geometria ou pixel para cada vértice. Nos video games.3  Programando GPUs A-579 Por exemplo. necessárias para amostrar a cor da superfície. . o subsistema de textura da GPU faz diversos acessos à memória para amostrar cores da imagem nas vizinhanças das coordenadas de amostragem. pois normalmente existem de 10 a 20 vezes ou mais fragmentos de pixel do que vértices. A. verde. incluindo coordenadas da imagem de textura em ponto flutuante 2D. alfa) é calculada usando uma média ponderada chamada “lerp”. O hardware da GPU cria uma nova thread independente para executar um programa de sombreamento de vértice. O modelo de programação de sombreamento gráfico impulsionou a arquitetura de GPU a executar de modo eficiente milhares de threads fine-grained independentes em muitos cores paralelos do processador. ele ativa muito hardware da GPU. Depois. intercalando-as profundamente para ocultar a busca de textura e latência de memória. azul. Programando aplicações de computação paralela CUDA. o programa de sombreamento de pixel modela três camadas de pele separadas. elas atraíram aplicações altamente paralelas além dos gráficos tradicionais. cada uma com comportamento de espalhamento de subsuperfície exclusivo. Brook e CAL são interfaces de programação para GPUs que são focadas na com- putação paralela dos dados.2  Imagem renderizada pela GPU. Ele executa 1400 instruções para renderizar os componentes de cor vermelho. mas essa técnica GPGPU normalmente era esquisita e limitadora. em vez de gráficos. Para que a pele tenha profundidade e translucidez visual. pois a luz salta muito antes de emergir novamente. são modeladas para oferecer à pele profundidade e translucidez visual. Cg oferece um rico conjunto de tipos de dados úteis. O sombreamento Cg compilado executa 1400 instruções para calcular a cor de um pixel de pele.3. Nesse sombreamento complexo. O espalhamento pode ser modelado por uma convolução ofuscante em um espaço de “textura” aplainado. azul e alfa de cada fragmento de pixel da pele. o acesso a esse poder estava disponível apenas formulando uma aplicação como um algoritmo de renderização de gráficos. com o vermelho sendo ofuscado mais que o verde. Inicialmente. A pele real parece muito diferente da tinta de cor da carne. três camadas de pele separadas. que a GPU implementa como uma única thread.3. cada uma com comportamento exclusivo de espalhamento da subsuperfície. e o azul ofuscado menos.A-580 Apêndice A  Gráficos e GPUs de computação FIGURA A. funções de biblioteca e construções de linguagem para expressar técnicas de renderização variadas. verde. Cg focaliza a visão do programador de um único vértice ou primitivo ou pixel. Como as GPUs desenvolveram um desempenho de ponto flutuante superior e largura de banda de memória streaming muito alta para gráficos em tempo real. o programa de sombreamento é dimensionado transparentemente para explorar o paralelismo de thread nos processadores disponíveis.2 mostra a pele renderizada por um sombreamento de pixel de fragmento. Sendo específica da aplicação. Mais recentemente. A Figura A. o modelo de programação CUDA forneceu um modo muito mais fácil de explorar a largura de banda escalável de ponto flutuante e memória de alto desempenho das GPUs com a linguagem de programação C. Brook é uma . CAL (Compute Abstraction Layer) é uma interface de linguagem assembler de baixo nível para GPUs da AMD. desenvolvida pela NVIDIA [2007]. Com o novo modelo. A. o programador divide um array de dados de resultado grande em blocos e divide ainda mais cada bloco em elementos. Decomposição do problema paralelo de dados Para mapear grandes problemas de cálculo de modo eficaz a uma arquitetura de proces- samento altamente paralela. CUDA.3. A decomposição paralela em dois níveis é mapeada naturalmente para a arquitetura da GPU: multiprocessadores paralelos calculam blocos de resultado. O modelo de programação CUDA é descrito a seguir.3 mostra uma decomposição de um array de dados de resultado em uma grande de blocos 3 × 2. em que cada bloco é decomposto ainda mais em um array 5 × 3 de elementos. e threads paralelas calculam elementos de resultado. O programa calcula cada bloco de resultado com um array de threads paralelas fine-grained. [2004]. particularmente GPUs. Por exemplo. Programação paralela escalável com CUDA O modelo de programação paralela escalável CUDA estende as linguagens C e C + + para explorar grandes graus de paralelismo para aplicações gerais em multiprocessadores altamente paralelos. Buck. Garland e Skadron [2008]. é uma extensão às linguagens C e C + + para a programação paralela escalável de GPUs manycore e CPUs multicore. A Figura A. e os elementos dentro de cada bloco sejam calculados em paralelo. adaptado de um artigo de Nickolls. o programador ou compilador decompõe o problema em muitos problemas pequenos. A experiência inicial com CUDA mostra que muitos programas sofisticados podem ser prontamente expressos com algumas FIGURA A. executando aplicações de cálculo de alto desempenho além de aplicações gráficas.3  Decompondo os dados de resultado em uma grade de blocos de elementos a serem calculados em paralelo. dividindo cada grade de resultado em blocos de resultado coarse-grained. O programador escreve um programa que calcula uma sequência de grades de dados de resultado. particionando o trabalho entre threads. de modo que os blocos de resultado possam ser calculados independentemente em paralelo. que podem ser calculados independentemente em paralelo. de modo que cada uma calcule um ou mais elementos de resultado. que podem ser solucionados em paralelo. a GPU excede em cálculo paralelo de dados e vazão.3  Programando GPUs A-581 linguagem de streaming adaptada para BPUs por Buck et al.3. . 1.). os blocos de threads e grades podem ter uma. Por conveniência.. CUDA admite blocos de threads contendo até 512 threads. modelos da física e computação visual. que executam que podem cooperar entre si através da sincronização de barreira e através do acesso o mesmo programa de thread e compartilhado ao espaço de memória privado do bloco. que podem ser solucionados independentemente em paralelo. dentro do seu bloco de threads. Múltiplos níveis de threads.3. duas ou três dimensões. Os programas em CUDA disparam kernels paralelos com a sintaxe es- tendida de chamada de função: kernel <<< dimGrid. pesquisa.4 e A. respectivamente. número de blocos que compreendem a grade. aninhados dentro do paralelismo de dados coarse-grained e paralelismo de tarefas. O especificador de declaração _global_ indica que o procedimento é um ponto de entrada do kernel. .. As abstrações orientam o programador a dividir o problema em subproblemas grosseiros. classificação. O modelo CUDA também se aplica a outras arquiteturas de processamento paralelo de memória compartilhada. O programador kernel  Um programa ou função escreve um programa serial que chama kernels paralelos. Dimensões não especificadas são um por default. grade  Um conjunto de blocos de threads que executam o mesmo Ao chamar um kernel. onde dimGrid e dimBlock são vetores de três elementos do tipo dim3. que podem ser funções simples para uma thread. threadIdx. Como um exemplo muito simples de programação paralela. 2008]. O modelo de programação se ex- pande transparentemente para quantidades maiores de cores de processador: um programa CUDA compilado é executado em qualquer número de processadores. portanto.4 mostra o código C para realizar esse cálculo em um processador serial e em paralelo. PCs. dentro de sua grade.z. incluindo CPUs multicore [Stratton. podem ser resultado. Esse é o chamado kernel SAXPY. paralelas.. Um kernel é executado em paralelo a um conjunto de threads executado por muitas threads. Essas aplicações se expandem transparentemente para centenas de cores de processador e milhares de threads simultâneas. acessadas por meio dos campos de índice . . química computacional. O programador organiza essas threads em uma hierarquia de blocos de threads bloco de threads  Um conjunto de e grades de blocos de threads.7) executam programas CUDA em C. memória e sincronização oferecem paralelismo de dados fine-grained e paralelismo de threads. dimBlock >>> (.x. suponha que recebamos dois vetores x e y de n números de ponto flutuante cada. Como a NVIDIA lançou o modelo CUDA em 2007.A-582 Apêndice A  Gráficos e GPUs de computação a­ bstrações facilmente entendidas. Uma grade é um conjunto de podem cooperar para calcular um blocos de threads que podem ser executadas independentemente e. executadas em paralelo.. bloc- kIdx. e que queiramos calcular o resul- tado de y = ax + y para algum valor escalar a. 2. O paradigma CUDA CUDA é uma extensão mínima das linguagens de programação C e C + +. e se encontram facilmente em laptops. Cada grade recebe um número de thread ID exclusivo. projetado para ser ou programas completos. blockDim-1.. A Figura A. CUDA oferece três abstrações principais – uma hierarquia de grupos de threads. álgebra linear. usando CUDA. As GPUs NVIDIA com a arquitetura gráfica e de computação unificada Tesla (descrita nas Seções A. memórias compartilhadas e sincronismo de barreira –.. . e depois em partes mais minuciosas. solucionadores de matriz esparsa. que oferecem uma estrutura paralela clara ao código C convencional para uma thread da hierarquia. que especificam as dimensões da grade em blocos e as dimensões dos blocos em threads. definido pela bib de álgebra linear BLAS. Um bloco de threads é um conjunto de threads simultâneas threads simultâneas. incluindo processamento de dados sísmicos.y e . estações de trabalho e servidores. e cada bloco de threads recebe um número de block ID exclusivo.. numerado com 0.lista de parâmetros. o programador especifica o número de threads por bloco e o programa do kernel. e somente o sistema de runtime precisa saber a quantidade física de processadores. os desenvolvedores rapidamente criaram programas paralelos escaláveis para uma grande faixa de aplicações. que podem ser solucionadas em paralelo. Threads paralelas CUDA substituem o loop serial C — cada thread calcula o mesmo resultado como uma iteração do loop. ele geralmente é fácil de escrever e mais simples do que escrever código paralelo para operações de vetor. Na Figura A. Comparando as versões serial e paralelo desse código. essas threads as threads no bloco de threads também têm garantias de ver todas as escritas na memória realizadas pelas threads no cheguem à barreira. elas residirão juntas no mesmo processador ou multiprocessador físico. as threads em um bloco podem se comunicar entre si es- crevendo e lendo a memória compartilhada por bloco em uma barreira de sincronização. Assim. evitamos a necessidade de qualquer sincronização entre as threads ao escrever resultados na memória. Isso representa um padrão bastante comum.3  Programando GPUs A-583 FIGURA A. barreira de sincronização  Threads esperam em uma barreira seco. escalo- namento e término de thread é tratado para o programador pelo sistema subjacente. O paralelismo é determinado clara e explicitamente especificando-se as dimensões de uma grade e seus blocos de threads ao iniciar um kernel.3.3. As threads de um bloco são executadas simultaneamente e podem sincronizar em uma barreira de sincronização chamando o _syncthreads () intrín. Esses loops podem ser transformados matematicamente em kernels paralelos: cada iteração do loop se torna uma thread independente. A execução paralela e o gerenciamento de threads é automático. Assim. e depois realiza o cálculo desejado nos elementos de vetor correspondentes.4. A. Toda criação. Na verdade. bloco antes da barreira. uma GPU com arquitetura Tesla realiza todo o gerenciamento de threads direta- mente no hardware. Cada thread individual calcula um índice de elemento de sua thread e IDs de bloco. Depois de passar pela barreira.4  Código sequencial (em cima) em C versus código paralelo (embaixo) em CUDA para SAXPY (veja Capítulo 7). Porém. . Isso garante que nenhuma thread no bloco possa prosseguir até que todas as threads de sincronização até que todas em um bloco tenham chegado à barreira. O texto de um kernel CUDA é simplesmente uma função C para uma thread sequencial. Atribuindo uma única thread a cada elemento de saída. Como as threads em um bloco podem compartilhar memória e sincronizar por meio de barreiras. vemos que elas são muito semelhantes. O código serial consiste em um loop em que cada iteração é independente de todas as ­outras. disparamos uma grade de n threads que atribui uma thread a cada elemento dos vetores e coloca 256 threads em cada bloco. O código paralelo calcula n resultados com n threads organizados em blocos de 256 threads. A memória compartilha deverá ser uma memória de baixa latência perto de cada processador. tornando o modelo CUDA expansível por um número sem qualquer acesso interveniente. Para gerenciar essa virtualização do elemento de processamento e oferecer escalabili- dade. A vir- tualização em threads e blocos de threads permite decomposições intuitivas do problema. por bloco de threads e por aplicação. Os kernels podem ser executados em um dispositivo fisicamente separado. o código do kernel normalmente inicializará os dados nas variáveis compartilhadas.5 diagrama os níveis aninhados das threads. enquanto a memória global reside na DRAM rá- pida da placa gráfica. Por ter o mesmo tempo de vida do seu bloco de threads correspondente. além memória compartilhada  de frames de pilha e derramamento de registrador. visível a todas as threads do bloco. memória local  Memória local por Cada thread tem uma memória local particular.A-584 Apêndice A  Gráficos e GPUs de computação o número de blocos de threads pode ser muito superior ao número de processadores. com uma barreira implícita entre os kernels. dados recursos de hardware suficientes. Ele também permite que o mesmo programa CUDA se expanda para números bastante variáveis de cores de processador. em paralelo ou em série. Ela mostra ainda os níveis correspondentes de compartilhamento de memória: memórias locais. esses espaços de memória as threads. a aplicação precisa usar cudaMemcpy() para Single-Program Multiple Data copiar dados entre o espaço alocado e a memória do sistema host. qualquer de cores. Ele também ajuda a evitar a possibilidade de deadlock. para variáveis particulars da thread. Threads SPMD executa em um número fixo de threads. e cada kernel que todas as threads executam o mesmo programa. correspondem a memórias fisicamente separadas: a memória compartilhada por bloco é uma RAM no chip com baixa latência. Em uma GPU na arquitetura Tesla. o CUDA requer que os blocos de threads possam ser executados independentemen- te. Grades independentes podem ser executadas simul- taneamente. garantindo assim que todos os blocos da primeira grade terminem antes do início de qualquer bloco da segunda grade. semelhante a uma cache L1. como cudaMalloc() e cudaFree(). O .3. do bloco. pois o número de blocos pode ser ditado pelo tamanho dos dados sendo processados. ela pode oferecer comunicação de alto desempenho e compartilhamento de dados entre as threads de um bloco de threads. CUDA é mais flexível que a maioria das normalmente são coordenados com realizações do modelo SPMD. compartilhadas e globais para o compartilhamento de dados por thread. compartilhada ria compartilhada. compartilhada por todas shared_ e _device_ . Consequentemente. pois cada chamada do kernel cria dinamicamente uma nova sincronização de barreira. Diferentes blocos não têm meios de comunicação direta. embora possam coordenar suas operação de memória atividades usando operações de memória atômicas na memória global visível a todas as atômica  Uma sequência de threads – incrementando atomicamente os ponteiros de fila. Os programas memória global  Memória por declaram variáveis na memória compartilhada e global com os qualificadores de tipo _ aplicação. Os blocos de threads de grades sequencialmente dependentes se comunicam por meio da memória global. blocos de threads e grades dos blocos de threads. Porém. Uma aplicação pode executar múltiplas grades de forma dependente ou independente. que tem o mesmo tempo de vida por todas as threads do bloco. privativa à thread. usando-a para ler entrada e escrever resultados. Deverá ser possível executar os blocos em qualquer ordem. (SPMD)  Um estilo de modelo O modelo de programação CUDA é semelhante em estilo ao conhecido modelo single- de programação paralela em program multiple data (SPMD) — ele expressa paralelismo explicitamente. Grades dependentes são executadas sequencialmente. Um programa gerencia o espaço da memória global visível aos kernels por meio de chamadas ao runtime CUDA. O modelo CUDA utiliza a memória local thread. em vez do número de processadores no sistema. bem como por uma série de arquiteturas paralelas. A Figura A. Esse requisito operações de leitura. como é o caso quando os kernels são executados na GPU. modificação de independência permite que os blocos de threads sejam escalonados em qualquer ordem e escrita de memória que termina por qualquer número de cores. Finalmente. Cada bloco de thread tem uma memó- Memória por bloco. por exemplo. As threads podem acessar dados de vários espaços da memória durante sua execução. calculará usando variáveis compartilhadas e copiará os resultados da memória compartilhada para a memória global. O modelo de programação de threads CUDA virtualiza os processadores e dá ao programador a flexibilidade de paralelizar em qualquer granularidade que seja mais conveniente. grade com o número correto de blocos de thread e threads para essa etapa da aplicação. Portanto. que não se encaixam nos registradores da thread. dependente. todas as threads têm acesso à mesma memória global. Restrições Por eficiência. em que cada bloco de threads 2D consiste em 5 × 3 threads. Como CUDA exige que os blocos de threads sejam independentes e . A Figura A. a arquitetura GPU Tesla implementa gerenciamento de hardware e escalonamento de threads e blocos de threads. o código instancia o kernelF em uma grade 2D de 3 × 2 blocos. ele instancia kernelG em uma grade 1D de quatro blocos de threads 1D com seis threads cada. Os blocos de threads independentes de uma grade expres- sam paralelismo de dados coarse-grained. Um kernel é simplesmente código C para uma thread da hierarquia. e para simplificar sua implementação. pois as barreiras de sincronização de thread operam sobre todas as threads do bloco. Para permitir que os programas CUDA sejam exe- cutados em qualquer número de processadores. A memória local por thread é particular à thread. A.6 mostra um exemplo de uma sequência de código CUDA tipo SPMD.5  Níveis de granularidade aninhados — thread. O paralelismo de tarefa pode ser expresso no nível de bloco de threads. compartilhado e global. programador pode usar um grau de paralelismo conveniente para cada kernel. A memória global por aplicação é compartilhada por todas as threads. Depois. as dependências entre os blocos de threads dentro da mesma grade de kernel não são permitidas — os blocos precisam ser executados independentemente. não de dentro de um kernel paralelo.3. o modelo de programação CUDA tem algumas restrições. Threads e blocos de threads só podem ser criados chamando-se um kernel paralelo. As threads simultâneas de um bloco de threads expressam paralelismo de dados fine- grained e paralelismo de thread. Junto com a independência exigida dos blocos de threads. Como kernelG depende dos resultados de kernelF. Grades independentes expressam o paralelis- mo de tarefas coarse-grained. bloco de threads e grade — possuem níveis de compartilhamento de memória correspondentes – local. mas é difícil de expressar dentro de um bloco de threads. A memória compartilhada por bloco é compartilhada por todas as threads do bloco.3.3  Programando GPUs A-585 FIGURA A. Primeiro. eles são separados por uma barreira de sincronização entre kernels. que introduz um overhead mínimo em runtime. em vez de ter de projetar todas as fases do cálculo para usar o mesmo número de threads. isso possibilita executar programas CUDA com um scheduler sim- ples. De fato. Problemas com uso intenso de cálculo. uma barreira de sincronização entre kernels. grandes o suficiente para precisar de um aumento de desempenho da GPU. A recursão é pouco atraente em um kernel maciçamente paralelo. normalmente são implementados melhor usando paralelismo de dados aninhado em vez da recursão explícita. pois oferecer espaço de pilha para as dezenas de milhares de threads que podem estar ativas exigiria quantidades substanciais de memória.6  Sequência de kernel F instanciado em uma grade 2D de blocos de threads 2D. seguida por kernel G em uma grade 1D de blocos de threads 1D. por exemplo). permite que os blocos sejam executados em qualquer ordem. Para dar suporte a uma arquitetura de sistema heterogênea combinando uma CPU e uma GPU. a combinação dos resultados gerados por múltiplos blocos em geral precisa ser feita iniciando um segundo kernel em uma nova grade de blocos de threads (embora os blocos de threads possam coordenar suas atividades usando operações de memória atômicas na memória global visível a todas as threads — incrementando atomicamente os ponteiros de fila. amortizam o overhead melhor do que os problemas pequenos. os programas CUDA precisam copiar dados e resultados entre a memória do host e a memória do dispositivo. Algoritmos seriais que normalmente são expressos usando recursão.A-586 Apêndice A  Gráficos e GPUs de computação FIGURA A. . como o quicksort. O overhead da interação CPU-GPU e transferências de dados é minimizado usando-se mecanismos de transferência em bloco por DMA e interconexões velozes. Chamadas de função recursivas atualmente não são permitidas em kernels CUDA.3. cada uma com seu próprio sistema de memória. descrito na Seção A. j Cálculo intenso de ponto flutuante (ou inteiro). as GPUs implementam números es- caláveis de multiprocessadores — na verdade. e programas CUDA descrevem como calcular um resultado individual. j Escalabilidade: Um programa precisa aumentar automaticamente seu desempenho quando receber processadores adicionais.4  Arquitetura de multiprocessador multithreaded A-587 Implicações para a arquitetura Os modelos de programação paralela para gráficos e computação têm feito com que a arquitetura da GPU seja diferente da arquitetura da CPU. enquanto a GPU ou plataforma de computação de um entusiasta em jogos tem dezenas deles. Multithreading maciço Processadores GPU são altamente multithreaded para alcançar vários objetivos: j Cobrir a latência de loads da memória e buscas de textura da DRAM. a unidade de instrução multithreaded e a RAM de memória compartilhada. j Suporte para cálculos com alta vazão. em vez de vários processadores independentes? O paralelismo dentro de cada multiprocessador oferece alto desempenho localizado e admite multithreading extenso para os modelos de programação paralela fine-grained descritos na Seção A. Os principais aspectos dos pro- gramas da GPU impulsionando a arquitetura de processador da GPU são: j Uso extenso do paralelismo de dados fine-grained: Programas de sombreamento des- crevem como processar um único pixel ou vértice. Por questão de eficiência de espaço e potência.7 executa até 768 threads). A. As threads individuais de um bloco de threads são executadas juntas dentro de um multiprocessador para compartilhar dados. cada multiprocessador é altamente multithreaded para executar muitas threads de sombreamento de vértice e pixel fine-grained de forma eficiente. e executa até 512 threads (o SM descrito na Seção A. . incluindo a cache de instruções. j Admitir modelos de programação de cálculo paralelo fine-grained. Uma GPU básica de qualidade tem dois a quatro multiprocessadores.3. Por que usar um multiprocessador. j Admitir modelos de programação de sombreamento gráfico paralelo fine-grained. as GPUs são multiprocessadores compostos de multiprocessadores. uma versão simplificada do multiprocessador streaming (SM) Tesla da NVIDIA. sem recompilação. Arquitetura de multiprocessador A. O projeto de multiprocessador ­multithreaded que descrevemos aqui tem oito cores de processador escalares em uma arquitetura altamente acoplada.7. Além do mais. Esta seção examina a arquitetura de um multiprocessador multithreaded desse tipo. a 60 frames por segundo. o multiprocessador compartilha unidades grandes e complexas entre oito cores de processador. j Virtualizar os processadores físicos como threads e blocos de threads para oferecer escalabilidade transparente. Uma GPU precisa criar e executar milhões desses programas de thread por frame.4   multithreaded Para lidar com diferentes segmentos do mercado. j Simplificar o modelo de programação paralelo para escrever um programa serial para uma thread. j Modelo de programação altamente encadeado: Um programa de thread de som- breamento processa um único pixel ou vértice. e um programa de thread CUDA pode gerar um único resultado. Variáveis CUDA declaradas como __shared__ residem na memória compartilhada. e pode executar um caminho de código independente. Para mapear a carga de trabalho da pipeline gráfica lógica através dos múltiplos tempos do multiprocessador.6GHz em diferentes produtos de GPU.1. normalmente 16 a 64 registradores escalares de 32 bits por thread. um programa CUDA é um programa em C para uma única thread.4. uma cache de instrução. e sincronização de barreira rápida efetivamente dão suporte ao paralelismo bastante fine-grained. O compilador otimiza a alocação do registrador para balancear o custo do spilling de registradores versus o custo de menos threads. permitindo que cada SP execute até 64 threads de sombreamento de pixel para cobrir . como as CPUs. Os programas de sombreamento de pixel normalmente utilizam 16 ou menos registradores. como mostra a Seção A. Arquitetura de multiprocessador Um multiprocessador gráfico e de computação unificado executa programas de sombrea- mento de vértice. Uma solicitação de busca geralmente requer uma latência de acesso completa da DRAM mais a latência de interconexão e buffering. A memória compartilhada de 16KB mantém buffers de dados gráficos e dados de computação compartilhados. cada thread da GPU tem seus próprios registradores privados. geometria e fragmento de pixel. Programas gráficos e de computação instanciam muitas threads paralelas para renderizar imagens complexas e calcular grandes arrays de resultado. A criação de threads peso leve. De modo semelhante.2GHz a 1. primitivo e pixel independentes das linguagens de sombreamento gráfico e o modelo de programação de única thread do CUDA C/C + +. Os programas declaram sua demanda de registrador. Cada core de SP em pipeline executa uma instrução escalar por thread por clock. O multithreading ajuda a cobrir a latência com computação útil — enquanto uma thread está esperando que um load ou busca de textura termine. Cada core do SP contém unidades aritméticas escalares de inteiros e ponto flutuante que executam a maioria das instruções. uma unidade de instrução multithreaded. contador de programa e estado de execução de thread. e programas de computação paralelos. o multiprocessador de exemplo consiste em oito cores de pro- cessador escalar (SP). apesar da longa latência de memória vista pelas threads individuais. duas unidades de função especial (SFU). cada um com um grande arquivo de registrador (RF) multithreaded.2. e as cargas de trabalho chegam e saem independentemente da execução da thread. Como mostra a Figura A. O SP pode executar simultaneamente muitas threads que usam alguns registradores ou menos threads que usam mais registradores. threads de vértice. que calcula um resultado. escalonamento de threads com overhead zero. Cada core SP tem um arquivo de registrador (RF) grande de 1024 registradores de uso geral de 32 bits. pois as GPUs normalmente têm pequenos caches streaming em vez de grandes ca- ches do conjunto de trabalho. que varia de 1. Threads simultâneas dentro de blocos de threads podem sincronizar em uma barreira com uma única instrução. uma cache constante apenas de leitura e uma memória compartilhada. Os modelos de programação paralela fine-grained oferecem literalmente milhares de threads independentes que podem manter muitos processadores ocupados. Para dar suporte ao modelo de programação de vértice. O SP é multithreaded por hardware. cada multi- processador executa simultaneamente múltiplos programas de thread diferentes e diferentes tipos de programas de sombreamento. divididos entre suas threads atribuídas. memória por thread particular. o multiprocessador da GPU é multithreaded por hardware — ele controla e executa centenas de threads simultâneas no hardware sem overhead de escalonamento. geometria e pixel possuem buffers de entrada e saída independente. Para executar de modo eficiente centenas de threads leves simultâneas. o processador pode executar outra thread. Um programa gráfico de sombreamento de vértice ou pixel é um programa para uma única thread que processa um vértice ou um pixel. Para balancear dinamicamente o vértice de deslocamento e cargas de trabalho do thread de sombreamento de pixel. aceitando até 64 threads.A-588 Apêndice A  Gráficos e GPUs de computação A latência da busca de memória e textura podem exigir centenas de clocks de proces- sador. rede de interconexão e uma memória compartilhada multibanco. e usa a interface de memória para instruções de load e store da memória externa. paralelas surgindo de um tear. em threads de pixel e threads de cálculo abundantes. A fotografia na Figura A. Os blocos de threads consistem em um ou mais warps. e instruções atômicas de acesso. chamados warps. duas unidades de função especial (SFUs). Oito cores SP possuem um grande arquivo de registrador (RF) multithreaded cada. unidade de emissão de instrução multithreading.4  Arquitetura de multiprocessador multithreaded A-589 FIGURA A. que limita esse programa de kernel a 256 threads por bloco de threads nesse multiprocessador de exemplo. Essas instruções podem ser executadas simultaneamente com as instruções nos SPs. a primeira aplica uma instrução a múltiplas tecnologia de thread paralela. Single-Instruction Thread (SIMT).1  Multiprocessador multithreaded com oito cores de processador escalar (SP). controla. Single-Instruction Multiple-Thread (SIMT) Para controlar e executar centenas de threads rodando diversos programas diferentes de modo eficaz. O acesso à memória compartilhada usa uma rede de interconexão de baixa latência entre os processadores SP e os bancos de memória compartilhada. Esse multiprocessador de exemplo utiliza um tamanho de warp  O conjunto de threads warp SIMT de 32 threads.4. O multiprocessador executa instruções de busca de textura na unidade de textura por meio da interface de textura. A SFU é descrita mais adiante. cache constante. Programas CUDA compilados normalmente precisam de 32 registradores por thread. escalona e executa threads simultâneas em grupos de Multiple-Thread (SIMT) Uma arquitetura de processador que threads paralelas. As SFUs em pipeline executam instruções de thread que calculam funções especiais e interpolam atributos de pixel dos atributos de vértice primitivos. buscas de textura de longa latência. instrução juntas em uma nho de warp de 32 threads paralelas. Ele cria. em vez do seu máximo de 512 threads. executando quatro threads em cada um dos oito cores SP por paralelas que executam a mesma quatro clocks. e compartilham uma cache de instrução. O multiprocessador Tesla SM descrito na Seção A.2 mostra um warp de threads threads independentes em paralelo. limitando cada SP a 32 threads. o multiprocessador emprega uma arquitetura Single-Instruction Multiple. A. . executando quatro threads por core SP por eficiência arquitetura SIMT.7 também usa um tama. Essas instruções podem executar simultaneamente com instruções nos SPs. O termo warp é originado da tecelagem.4. as threads convergem para o mesmo caminho de execução. cada core do processador escalar SP executa uma instrução por quatro threads individuais de um warp usando quatro clocks. No momento da emissão de cada instrução. e não apenas a múltiplas pistas de dados.2  Escalonamento de warp multithreaded SIMT. a execução serializa para cada caminho de desvio tomado. e a unidade de instrução SIMT emite uma instrução a um warp de threads paralelas independentes por eficiência. threads individuais podem ser inativas devido ao desvio ou previsão independente. que aplica uma instrução a múltiplas pistas de dados.4. A arquitetura de processador SIMT é semelhante ao projeto Single-Instruction Multiple Data (SIMD). semelhante ao modo como um processador superescalar encontra o paralelismo em nível de instrução entre as instruções em tempo de execução. refletindo a razão 4:1 das threads de warp aos cores. o escalonador pode selecionar um warp diferente a cada vez. Uma instrução SIMT é enviada por broadcast de forma síncrona às threads paralelas ativas de um warp. Nesse multiprocessador. um total de 512 threads. O processador SIMT encontra o paralelismo em nível de dados entre as threads em tempo de execução. Como os warps são independentes. . a unidade de instrução multithreaded da arquitetura SIMT seleciona um warp que está pronto para executar sua próxima instrução. e quando todos os caminhos terminam. Se as threads de um warp divergirem por meio de um desvio condicional dependente dos dados. Uma instrução para um processador SIMD controla um vetor de múltiplas pistas de dados juntas. depois emite essa instrução às threads ativas do warp. enquanto uma instrução para um processador SIMT controla uma thread individual. um bloco de código if-else divergente é 50% eficiente.A-590 Apêndice A  Gráficos e GPUs de computação FIGURA A. O escalonador seleciona um warp pronto e emite uma instrução sincronamente às threads paralelas compondo o warp. Threads paralelas individuais compondo um warp são do mesmo tipo e começam juntas no mesmo endereço de programa. Para caminhos de mesmo tamanho. mas de outras maneiras são livres para se desviar e executar independentemente. O multiprocessador utiliza uma pilha de sin- cronização de desvio para gerenciar threads independentes que divergem e convergem. Um processador SIMT observa eficiência e desempenho plenos quando todas as threads de um warp tomam o mesmo caminho de execução. Esse multiprocessador SIMT de exemplo controla um pool de 16 warps. mas difere porque SIMT aplica uma instrução a múltiplas threads independentes em paralelo. O pipeline do processador utiliza vários clocks de latência para concluir cada instrução.0 por core de processador. Para cargas de trabalhos gráficos. O controlador do multiprocessador empacota os quads de pixel em um warp. incluindo a unidade de textura. caminho de acesso à memória e caminhos de E/S. geometria.4  Arquitetura de multiprocessador multithreaded A-591 Diferentes warps são executadas independentemente em velocidade plena. latências de instrução de até 32 ciclos podem ser escondidas de uma thread sequencial individual. bem como código paralelo de dados para muitas threads coordenadas. Durante cada ciclo de escalonamento. A. Execução e divergência de warp SIMT A técnica SIMT de escalonar warps independentes é mais flexível que o escalonamento de arquiteturas GPU anteriores. SIMT permite que os programa- dores escrevam código paralelo em nível de thread para threads individuais independentes. Um warp compreende threads paralelos do mesmo tipo: vértice. ele cria e gerencia três . O projeto SIMT compartilha a unidade de busca e emissão de instrução eficientemente por threads paralelos de um warp. porém. permitindo que execute warps de vértice e pixel simultaneamente. pois seus warps são muito mais estreitos que a largura SIMD das GPUs anteriores. com poucos warps ativos. O escalonador de instruções precisa selecionar um warp a cada quatro clocks para emitir uma instrução por clock por thread. O controlador aceita solicitações de trabalho e dados de entrada. Se o número de warps ativos vezes os clocks por warp ultrapas- sar a latência do pipeline. Uma ins- trução de warp emitida executa como quatro conjuntos de oito threads por quatro ciclos do processador de vazão. pixel ou cálculo. o programador pode basicamente ignorar os atributos de execução SIMT dos warps. Porém. GPUs SIMT são muito mais eficientes e flexíveis no código de desvio do que as GPUs an- teriores. equivalente a um IPC de 1. A priorização precisa considerar tipo de warp. o programador pode ignorar a latência do pipeline. e arbitra o acesso aos recursos compartilhados.4. pois existem quatro pistas de thread por core de processador. tipo de instrução e o desejo de ser imparcial para todos os warps ativos. Como os warps são independentes. Na prática. a profundidade do pipeline do processador torna-se visível e pode causar stall dos processadores. Esse multiprocessador unificado escalona e executa múltiplos tipos de warp simultanea- mente. mas deve ser considerado na estrutura de código quando se projeta por desempenho de pico. Para esse multiprocessador.2. Para a exatidão do programa. Seu escalonador de warp opera em menos do que a taxa de clock do processador. Um problema de projeto desafiador é implementar o escalonamento de warp com overhead zero para uma mistura dinâmica de diferentes programas de warp e tipos de programa. isso é semelhante ao papel das linhas de cache nos códigos tradicionais: o tamanho da linha de cache pode ser seguramente ignorado quando se projeta por exatidão. como mostra a Figura A. sem levar em conta se estão executando caminhos de código comuns ou desconexos. O escalonador usa um scoreboard de dependência de registrador para qualificar warps cujas threads ativas estão prontas para executar uma ins- trução. melhorias de desempenho substanciais podem ser observadas cuidado-se para que o código raramente exija que as threads em um warp divirjam. Um bloco de threads compreende um ou mais warps. um schedule round-robin de oito warps tem um período de 32 ciclos entre instruções sucessivas para o mesmo warp. A unidade básica de processamento de sombreamento do fragmento de pixel é o quad de pixel 2 por 2. as únicas dependências estão entre ins- truções sequenciais do mesmo warp. Se o programa puder manter 256 threads ativos por multiprocessador. mas requer um warp completo de threads ativas para obter eficiência de desempenho completa. Como resultado. Em comparação com as arquiteturas de vetor SIMD. implementado como quatro threads de sombreamento de pixel. ele seleciona um warp para executar uma instrução de warp SIMT. Gerenciando threads e blocos de threads O controlador do multiprocessador e a unidade de instrução gerenciam threads e blocos de threads. Ele prioriza todos esses warps prontos e seleciona o que possui mais alta prioridade para emissão. array de thread cooperativo O controlador cria arrays de thread cooperativos (CTAs). quantidades antes de iniciar o CTA. Porém. que são então otimizadas e traduzidas para microinstruções GPU binárias. e múltiplas instruções PTX possam se desdobrar em uma microinstrução binária. Instruction Set Architecture (ISA) A thread ISA descrita aqui é uma versão simplificada da arquitetura Tesla PTX ISA. de modo que um programa CTA começa a executar imediatamente no de- sempenho total do multiprocessador. Depois. As instruções de textura continuam sendo baseadas em vetor. Cada um dos tipos de trabalho gráfico possui caminhos independentes de entrada e saída.A-592 Apêndice A  Gráficos e GPUs de computação tipos de threads gráficas simultaneamente: vértice. enquanto os programas de sombreamento de pixel calculam vetores de cor (vermelho. O pro- de GPU implementa um bloco de grama declara as capacidades exigidas. dife- rente das arquiteturas de instrução de vetor da GPU anteriores. que implementam blocos (CTA)  Um conjunto de threads de threads CUDA como um ou mais warps de threads paralelos. Além dos threads e calcular um resultado. azul. A definição do conjunto de instruções PTX (execução paralela de thread) da NVIDIA [2007] oferece uma ISA de destino estável para compiladores. o controlador desempacota os resultados e libera os registradores e recursos do warp. instruções de vetor Direct3D ou instruções escalares PTX). y. Ele cria um CTA quan- que executa o mesmo programa de thread e pode cooperar para do pode criar todos os warps CTA e alocar todos os recursos CTA. alfa). Instruções escalares PTX são traduzidas quase um para um com microinstruções binárias escalares. O controlador monitora quando todas as threads de um CTA saíram. reúne ins- truções quando for viável e otimiza pontos de divergência e convergência de desvio SIMT. um conjunto de instruções escalar baseado em registrador compreendendo funções de ponto . dele cria warps CTA na taxa de escalonamen- to de warp. Instruções de thread Os processadores de thread SP executam instruções escalares para threads individuais. Programas CUDA C/C + + têm código predominantemente escalar por thread. Ele acumula e empacota cada um desses tipos de trabalho de entrada em warps SIMT de threads paralelas executando o mesmo programa de thread. z. o controlador inicia um warp somente quando ele pode alocar o contador de registrador solicitado para as threads do warp. geometria e pixel. O otimizador prontamente expande as instruções de vetor Direct3D para múltiplas microinstruções binárias escalares. Um CTA registradores. Instruções escalares são mais simples e amigáveis a compilador. mas isso complicava o hardware de es- calonamento e também o compilador. Os programas de vértice geralmente calculam vetores de posição (x. em vez de paralelizar os quatro componentes de vetor dentro de um pixel. tomando um vetor de coordenada de origem e retornando um vetor de cor filtrada. O otimizador elimina o código morto. Como as instruções intermediárias em nível de assembler utilizam registradores virtuais. GPUs anteriores empregavam empacotamento de vetor (por exemplo. o otimizador analisa as dependências de dados e aloca registradores reais. Com efeito. w). que executavam instruções de vetor de quatro componentes para cada programa de sombreamento de vértice ou pixel. um CTA requer a alocação de memória compartilhada e barreiras. e libera os recursos compartilhados do CTA e seus recursos de warp. e o controlador espera até que possa alocar essas threads CUDA. combinar subvetores de trabalho para ganhar eficiência). Ele aloca um warp livre. e oferece compatibilidade por várias gerações de GPUs com arquiteturas de microinstrução binária em evolução. aloca registradores para as threads de warp e inicia a execução do warp no multiprocessador. Cada programa declara sua demanda de registrador por thread.. gráficos de alto nível e compiladores de linguagem de computação geram instruções intermediárias em nível de assembler (por exemplo. a arquitetura SIMT paraleliza por 32 threads de pixel independentes. e é cada vez mais difícil ocupar totalmente até mesmo dois componentes de uma arquitetura de vetor de quatro componentes de GPU legada. Quando todas as threads do warp terminam. Para dar suporte a múltiplas GPUs com diferentes formatos de microinstrução binária. embora algumas instruções PTX se expandam para múltiplas microinstruções binárias. os programas de sombreamento estão se tornando maiores e mais escalares. verde. . A. b. a. veja detalhes na especificação NVIDIA PTX [2007]. controle de fluxo.type d. a. acesso à memória e operações de textura.3  Instruções básicas de thread da GPU PTX.4  Arquitetura de multiprocessador multithreaded A-593 flutuante.type é um destes: FIGURA A. O formato da instrução é: opcode. A Figura A. inteiro. b. especiais.3 lista as instruções de thread PTX GPU básicas. onde d é o operando de destino. de conversão. c são operandos de origem.4. c. lógicas. e .4. . Instruções de acesso à memória A instrução tex busca e filtra amostras de textura de arrays de textura 1D. Outras instruções também podem ter predicados em um registrador de predicado verdadeiro ou falso. . instruções PTX com inteiros de 64 bits e lógicas são traduzidas para duas ou mais microinstruções binárias. Para dar suporte às necessidades de cálculo e da linguagem C/C + +. . . ver Seção A. o proces- sador de operações de rastreio a mistura com a cor do pixel em sua posição de pixel atribuída (x. que realizam operações de 32 bits. Para cálculo. . st.s64 Ponto flutuante 16.b8. ld. As instruções aritméticas PTX operam sobre tipos de ponto flutuante. exit de thread e bar. operandos de predicado são valores boolianos de 1 bit. mas são uma nova capacidade significativa nas GPUs da arquitetura Tesla. as instruções load/store acessam três espaços de leitura/escrita que im- plementam os espaços de memória CUDA correspondentes na Seção A. As instruções têm predicados iniciando-as com @p ou @!p. Programas de cálculo utilizam a instrução de sincronização de barreira rápida bar.b32. 32 e 64 bits .s16. 16. 16.sync (sincronização de barreira).6. até 128 bits no total. 32 e 64 bits . As instruções de função especial da GPU são limitadas a ponto flutuante de 32 bits. As buscas de textura geralmente utilizam coordenadas de ponto flutuante interpoladas para endereçar uma textura.shared . sync para sincronizar threads dentro de um bloco CTA/thread que se comunica um com o outro por meio da memória compartilhada e global.u16. As instruções load/store da memória são comuns nos processadores.u64 Inteiro com sinal 8. Quando uma thread de sombreamento de pixel gráfico calcula sua cor de fragmento de pixel.u8. 2D e 3D na memória por meio do subsistema de textura.global . y) e escreve a cor final na memória. Instruções de memória e textura transferem escalares ou vetores de dois a quatro componentes. pois GPUs anteriores forneciam apenas a textura e os acessos de pixel exigidos pelas APIs gráficas. . 32 e 64 bits . A instrução de desvio condicional @p bra target usa um registrador de predicado p (ou !p) definido anteriormente por uma instrução setp de comparação e definição de predicado. .u32.s32.f64 Operandos de origem são valores escalares de 32 bits ou 64 bits nos registradores. . GPUs recentes admitem ponto flutuante de precisão dupla com 64 bits.A-594 Apêndice A  Gráficos e GPUs de computação Tipo Especificador .global .f16.local e st.3: j Memória local para dados temporários endereçáveis por thread (implementada na DRAM externa) j Memória compartilhada para acesso de baixa latência aos dados compartilhados por threads em cooperação no mesmo bloco CTA/thread (implementada na SRAM no chip) j Memória global para grandes conjuntos de dados compartilhados por todas as threads de uma aplicação de cálculo (implementada na DRAM externa) As instruções load/store da memória ld. a ISA PTX Tesla implementa as instruções load/store da memória.tipo Bits não tipados 8. ld. compartilhado e local. Elas utilizam endereçamento de inteiros por byte.b16. Instruções PTX especificam o comportamento de um thread.s8. 32 e 64 bits .f32. st. shared. 16. Nas GPUs atuais.local acessam os espaços de memória global. . onde p é um registrador de predicado. .b64 Inteiro sem sinal 8. . um valor imediato ou uma constante. As instruções de fluxo de controle de thread são branch condicional. call e return de função. para determinar se a thread apanha o desvio ou não. com aritmética de registrador mais endereço de offset para facilitar as otimizações de código convencionais do compilador. inteiro com sinal e inteiro sem sinal de 32 e 64 bits. exceto para store na memória. . Destinos são registradores. or. exchange e cas (compare-and-swap). ajuda a cobrir a latência de carga para uso da memória local e global implementada na DRAM externa. profundidade e textura. Quando uma thread executar uma instrução bar. Ele executa todas as operações fundamentais de ponto flutuante. incluindo valores not-a-number (NaN) e infinito. incluindo add. A função de sincronização intrínseca gera uma única instrução bar. As threads esperam em uma barreira no escalonador de threads SIMT de modo que não consumam quaisquer ciclos de processador enquanto esperam.4  Arquitetura de multiprocessador multithreaded A-595 Para melhorar a largura de banda da memória e reduzir o overhead. A junção de solicitações de memória oferece um aumento de desempenho significativo em relação a solicitações separadas de threads individuais. ela incrementa o contador de chegada de thread da barreira e o escalonador marca a thread como esperando na barreira.4.sync . O core SP também implementa todas as instruções PTX aritméticas.4.f32.u32. incluindo operações com inteiros add.3. Sincronização de barreira para comunicação de threads O sincronismo rápido de barreira permite que programas CUDA se comuniquem frequen- temente por meio de memória compartilhada e memória global. Quando todas as threads CTA chegarem. O SP limpa os operandos des- normalizados da entrada para zero-com-sinal-preservado. Porém. xor. de comparação. seguida por uma adição com arredondamento-para-par-mais-próximo.sync. de raiz quadrada recíproca e de chave. mul. mad. . f32. min.op. A.f32 e sept. o contador da barreira é igual ao contador terminal esperado. O agrupamento de threads em warps SIMT de 32 threads reduz a dificuldade de sin- cronização por um fator de 32. que calcula aproximações de ponto flutuante de 32 bits para funções transcendentais recíprocas.3. max.f32. and.f32 realiza uma multiplicação truncada. A operação de multiplicação- adição de ponto flutuante mad. conversão e lógicas com inteiros de 32 e 64 bits na Figura A. as instruções load/ store locais e globais juntam solicitações de thread paralelas individuais a partir do mesmo warp SIMT em uma única solicitação de bloco de memória quando os endereços caem no mesmo bloco e atendem critérios de alinhamento. Streaming Processor (SP) O processador streaming (SP) multithreaded é o principal processador de instruções de thread no multiprocessador. min. juntamente com o suporte para muitas solicitações de carga pendentes. simplesmente chamando _syncthreads(). As operações de ponto flutuante add e mul empregam o arredondamento-para-par-mais- próximo do IEEE como modo de arredondamento padrão. As operações de adição e multiplicação em ponto flutuante são compatíveis com o padrão IEEE 754 para números de PF em precisão simples. max.f32 (floating compare and set predicate). implementar a sin- cronização de barreira rápida entre até 512 threads por bloco de threads CUDA é um desafio. como parte de cada etapa de comunicação entre threads. A grande contagem de threads do multiprocessador. Seu arquivo de registradores (RF) oferece 1024 registradores escalares de 32 bits para até 64 threads. facilitando reduções paralelas e gerenciamento de estruturas de dados paralelas. Special Function Unit (SFU) Certas instruções de thread podem ser executadas nas SFUs. A SFU implementa as instruções de função es- pecial da Figura A.f32 (floating multiply-add). simultaneamente com outras instruções de thread executando nos SPs. Ela também implementa interpolação de atributo planar em ponto flutuante para sombreamentos de pixel. Os resultados com underflow da faixa de expoentes da saída de destino são limpos para zero-com-sinal-preservado após o arredondamento. ofere- cendo interpolação precisa de atributos como coordenadas de cor. e o escalonador libera todas as threads esperando na barreira e continua executando threads. As GPUs mais recentes da arquitetura Tesla também oferecem eficientes operações de memória atômicas na memória com as instruções atom. em vez de forçar o programador a expressá-lo como instruções de vetor SIMD. Uma máquina SIMT executa um warp de 32 threads de forma síncrona quando as threads tomam o mesmo caminho de execução. chamada SIMT (Single-Instruction Multiple-Thread) para enviar uma instrução por broadcast. pois é multithreaded por hardware com sincronização de barreira de hardware. O multiprocessador SIMT impõe pouco overhead. Veja mais detalhes sobre aritmética de SFU na Seção A. Juntar oito cores de processador streaming em um multiprocessador e depois im- plementar um número escalável desses multiprocessadores cria um multiprocessador de dois níveis composto de multiprocessadores. Apesar disso.A-596 Apêndice A  Gráficos e GPUs de computação Cada SFU em pipeline gera um resultado de função especial de ponto flutuante de 32 bits por ciclo. as duas SFUs por multiprocessador executam instruções de função es- pecial em um quarto da taxa de instrução simples dos oito SPs. ao em vez de um vetor de dados SIMD de quatro ou mais pistas de dados. O mesmo programa de thread pode oferecer operações fine-grained e coarse-grained. O modelo de programação CUDA explora a hierarquia de dois níveis oferecendo threads individuais para cálculos paralelos fine- grained. como SSE x86. com base nas aproximações minimax avançadas. as CPUs com instruções de vetor SIMD precisam usar dois modelos de programação diferentes para oferecer operações fine-grained e coarse-grained: threads paralelas coarse-grained nos diferentes cores. o multiprocessador SIMT pode executar threads individuais independentemente. É mais simples e mais produtivo desenvolver código de única thread escalar que o código de vetor. aumentando a taxa de cálculo máxima para 50%. enquanto o hardware SIMD requer que o software expresse o paralelismo de dados explicitamente em cada instrução de vetor. e o multiprocessador SIMT executa o código com eficiência tipo SIMD. A vantagem é significativa. Comparando com outros multiprocessadores Em comparação com as arquiteturas de vetor SIMD. A precisão da função estima intervalos de 22 a 24 bits de mantissa. a SFU da arquitetura Tesla emprega interpolação quadrática. Cada thread executa seu fluxo de instruções em um dos oito cores do processador streaming (SP). raiz quadrada recíproca. Ao contrário. que são multithreaded para até 64 threads. e instruções de vetor SIMD para o paralelis- mo de dados fine-grained. As SFUs também executam a instrução de multiplicação mul. Ele utiliza uma variação da arquitetura SIMD e multithreading.6. Conclusão sobre multiprocessador multithreaded O multiprocessador da GPU de exemplo baseado na arquitetura Tesla é altamente mul- tithreaded. espalhando a superfície e o custo de uma unidade de instrução pelas 32 threads de um warp e pelos oito cores de processador streaming. 2x e sin/cos. executando um total de até 512 threads peso leve simultaneamente para dar suporte a sombreamentos de pixel fine-grained e threads CUDA. Por avaliação funcional. de forma eficiente. Programas gráficos e CUDA utilizam threads para expressar paralelismo de dados fine-grained em um programa por thread. Isso permite que sombreamentos gráficos e threads CUDA expressem um paralelismo bastante fine-grained. SIMT oferece o desempenho do SIMD junto com a produtividade do multithreading. pois os programas e as instruções SIMT simples- mente descrevem o comportamento de uma única thread independente. para aproximar as funções recíprocas. o multiprocessador SIMT possui eficiência tipo SIMD. e oferecendo grades de blocos de thread para operações paralelas coarse-grained. O hardware SIMT encontra paralelismo de dados entre threads independentes. enquanto permite que cada thread se desvie e seja executada independentemente. em vez de sempre executá-las juntas em grupos síncronos. evitando a necessidade de codificar explicitamente os vetores SIMD do código para condições de aresta e divergência parcial. para threads com uma mistura de instruções adequada. para um warp de 32 threads paralelas. embora possa executar cada thread independentemente quando elas divergirem. .f32 simultaneamente com os oito SPs. log2x. a demanda de largura de banda no sistema de memória é enorme. o GeForce 8800 pode processar 32 pixels por clock.5  Sistema de memória paralela A-597 A ISA PTX é uma ISA escalar de load/store baseada em registrador. e o próprio array de memória compreende muitos chips DRAM para fornecer a largura total do barramento de dados. as instruções de hardware podem evoluir rapidamente sem atrapalhar compiladores e ferramentas de software que geram instruções PTX. Alta vazão (eficiência de utilização) e latência curta estão fundamentalmente em conflito. que é invisível à aplicação e oportunista. j As GPUs buscam usar cada ciclo disponível para transferir dados de e para o array de memória. Operações de escrita e blend (ler-modifica- escrever) de pixel. leituras de mapa de textura. Considerações sobre DRAM As GPUs precisam levar em consideração as características exclusivas da DRAM. os sistemas de memória da GPU têm as seguintes carac- terísticas: j Eles são amplos. existe uma demanda de 28 bytes vezes 32 pixels = 896 bytes por clock. as GPUs especificamente não visam minimizar a latência ao sistema de memória. além de leituras de dados de vértice e atributo de objeto. As cargas de trabalhos gráficos exigem taxas de trans- ferência muito altas de e para a memória. As DRAMs impõem uma série de requisitos de temporização em seu processador de controle. e cada linha contém um número de bits na potência de dois (normalmen- te. para um caso típico. Para fornecer esses requisitos. Para conseguir isso. j Caches e estruturas de junção de trabalho são usadas para reduzir a quantidade de tráfego fora do chip necessário e garantir que os ciclos gastos movendo-se dados são usados o mais totalmente possível.2. de quatro a oito). j Eles são rápidos. mas. Por exemplo. Assim. Como as instruções PTX são otimizadas e traduzidas para microinstruções binárias para uma GPU específica. em que cada banco inclui um número de linhas na potência de 2 (normalmente. Assim. Normalmente. a 600MHz. j Técnicas de compactação são utilizadas. das quais o programador precisa estar ciente.5  Sistema de memória paralela Fora a própria GPU. quanto sem perdas. leituras e escritas de buffer em profundidade. tanto com perdas. A. 8192). por volta de 16.5. significando que existe um grande número de pinos para transmitir dados entre a GPU e seus dispositivos de memória. A.384). significando que técnicas de sinalização agressivas são usadas para maximizar a taxa de dados (bits/segundo) por pino. DRAMs síncronas Double-Data Rate (DDR) transferem dados nas arestas de subida e descida do clock de interface (veja Capítulo 5). uma vez ativados. compreendem a maior parte do tráfego da memória. Nitidamente. uma média de dois ou três texels de quatro bytes cada são lidos para gerar a cor do pixel. As GPUs modernas são altamente paralelas. os bits dentro dessa linha são acessíveis aleatoriamente com um novo endereço de coluna a cada quatro clocks. Cada pixel normalmente requer uma leitura e escrita de cor e uma leitura e escrita de profundidade de um pixel de 4 bytes. o subsistema de memória é o determinante mais importante do desempenho de um sistema gráfico. dezenas de ciclos são exigidos para ativar uma linha. uma . Por exemplo. como mostramos na Figura A. Chips de DRAM são arrumados internamente como múltiplos bancos (normalmente. que descreve a execução de uma única thread. A-598 Apêndice A  Gráficos e GPUs de computação DRAM DDR com clock de 1GHz transfere dados a 2 gigabits por segundo por pino de dados. Diferentes estágios do pipeline gráfico lógico possuem cada um seus próprios streams de solicitação: busca de atributo de comando e vértice. Con- sidere o caso de uma cache de textura. as GPUs experimentam taxas de acerto mais próximas de 90% e. normalmente existem múltiplas unidades independentes para oferecer a vazão paralela. Caches As cargas de trabalho da GPU normalmente possuem conjuntos de trabalho muito grandes – na ordem de centenas de megabytes para gerar um único frame gráfico. Assim. não é prático construir caches em chips grandes o suficiente para manter qualquer coisa próxima do conjunto de trabalho inteiro de uma aplicação gráfica.9% ou mais). a largura de banda total é 2 × 4 × 4 × 64 = 2048 bits por clock. todas operando independentemente. portanto. O projeto precisa cuidar para que nenhuma solicitação em particular espere muito tempo. Uma unidade de textura comum pode avaliar duas interpolações bilineares para cada um dos quatro pixels por ciclo de clock. Uma solução é que o controlador de memória da GPU mantenha heaps separadas de tráfego voltado para diferentes bancos de DRAM. embora seja bom para a localidade de linha de DRAM e. e esperem até que um tráfego suficiente para determinada linha da DRAM esteja pendente antes de ativar essa linha e transferir todo o tráfego ao mesmo tempo. portanto. conforme visto pelos solicitantes cujas solicitações gastam tempo esperando por outras. precisam lidar com muitas falhas durante a execução. e uma GPU pode ter muitas dessas unidades de textura. e leitura-escrita de profundidade e cor de pixel. Isso naturalmente favorece um arranjo multibanco e/ou multiporta de arrays SRAM. cada um compreendendo um controlador de memória totalmente independente e um ou dois dispositivos de DRAM que são totalmente e exclusivamente possuídos por essa partição. todas as unidades de processamento geram endereços de memória em um . Os subsistemas de memória da GPU são arrumados como múltiplas partições de me- mória. Caches da GPU precisam oferecer largura de banda muito alta aos seus clientes. Cada interpolação bilinear requer quatro texels separados. O número de partições de memória é projetado para balancear o número de processadores e outros solicitadores de memória. uma GPU precisa prosseguir com falhas e acertos misturados. os endereços são intercalados detalhadamente por todas as partições de memória. Cada texel de 64 bits separado é endereçado independentemente. Observe que acumular solicitações pendentes. Embora uma CPU possa ser razoavelmente projetada para interromper enquanto espera por uma falha de cache rara. Em cada estágio lógico. DRAMs DDR gráficas normalmente possuem 32 pinos de dados bidirecionais. Estas são solicitadores de memória independentes. Essa é uma divergência natural do padrão de referência preferido pelas DRAMs. portanto. Para conseguir o melhor balanceamento de carga e. existe um número enorme de solicitações não correlacionadas durante a execução. No GeForce 8800. ou então algumas unidades de processamento podem “morrer de fome” esperando por dados e por fim fazer com que os processadores vizinhos se tornem ociosos. MMU GPUs modernas são capazes de traduzir endereços virtuais para endereços físicos. de modo que oito bytes podem ser lidos ou escritos a partir da DRAM por clock. As GPUs internamente possuem um grande número de geradores de tráfego de memó- ria. Diferente das CPUs. busca e load/store de textura de sombreamento. Enquanto as CPUs podem assumir taxas de acerto de cache muito altas (99. leva a uma latência média mais longa. aproximar o desempenho teórico de n partições. É mais comum ter quatro componentes de 16 bits. O caminho de intercalação da partição em geral é um bloco de algumas centenas de bytes. Chamamos isso de arquitetura de cache streaming. para o uso eficiente do barramento de dados. Quando vistas no sistema de memória. de modo que a cache precisa tratar de 32 endereços exclusivos por clock. e cada texel poderia ser um valor de 64 bits. Memória compartilhada A memória compartilhada por CTA só é visível às threads que pertencem a esse CTA. todas as 16 threads poderiam acessar um endereço diferente . Para cálculo. é prático criar estruturas de memória com largura de banda muito alta no chip para dar suporte às demandas de leitura/escrita de cada multiprocessador streaming. Para a discussão a seguir. Cada multiprocessador streaming contém oito processadores de thread físicos. pode residir no chip. As leituras e escritas na memória solicitadas por diferentes threads são desordenadas. De fato. Espaços de memória Conforme apresentado na Seção A. Como o espaço de endereço é distribuído uniformemente entre todas as partições de memória. um programador não sabe a ordem relativa em que os CTAs são exe- cutados. A memória compartilhada. de modo que 16 threads de solicitações de memória comparti- lhada precisam ser tratados em cada clock. 16 bancos são suficientes para manter a vazão. Dentro de um CTA. portanto. em CUDA. a memória compartilhada é bastante acoplada ao multiprocessador streaming. Primeiro. o hardware lê as tabelas de página da memória local para responder a falhas em favor de uma hierarquia de buffers lookaside de tradução espalhados entre os processadores e mecanismos de renderização. pois visa a comunicação entre diferentes CTAs (blocos de threads) em diferentes grades. assumimos GPUs da arquitetura Tesla da NVIDIA. Uma unidade de gerenciamento de memória realiza tradução de endereço de virtual para físico. Para os padrões de acesso comuns. a instrução de sincronização de barreira bar. que são estendidos para um endereço virtual de 40 bits acrescentando um offset de 40 bits. e a memória compartilhada só ocupa armazenamento a partir do momento em que um CTA é criado até o momento em que ele termina. Como cada thread pode gerar seus próprios endereços. CUDA expõe diferentes espaços de memória para permitir que o programador armazene valores de dados de uma forma que seja ideal para o desempenho. As threads também podem usar as operações atômicas da memória descritas na Seção A. a memória compartilhada é montada usando-se 16 bancos SRAM endereçáveis independentemente.3. ela não é local a qualquer multiproces- sador de streaming (SM) físico isolado. mas a ordem dos acessos a diferentes endereços pode não ser preservada. as entradas da tabela de página da GPU especificam o algoritmo de compactação para cada página. as instruções de thread de load e store utilizam endereços de byte com 32 bits. por exemplo. neces- sária para referências à memória global. A. Memória global A memória global é armazenada na DRAM externa. mas casos patológicos são possíveis. Além dos bits da página física.4 para coordenar o trabalho na memória que elas compartilham. cada processador de thread pode processar dois threads de instruções.sync pode ser usada para obter ordenação de memória estrita entre as threads do CTA. é preciso haver um caminho de leitura/escrita de qualquer multiprocessador streaming para qualquer partição da DRAM. os muitos CTAs que referenciam um local na memória global podem não estar executando na GPU ao mesmo tempo.5  Sistema de memória paralela A-599 espaço de endereço virtual de 40 bits. Os tamanhos de página variam de 4 a 128 kilobytes. por projeto. o tráfego da memória compartilhada não precisa competir com a largura de banda limitada fora do chip. Segundo. a ordem das leituras e escritas na memória para o mesmo endereço é preservada. e os endereços normalmente são exclusivos. A instrução de thread membar oferece uma operação de barreira/cerca de memória que valida os acessos anteriores à memória e os torna visíveis a outras threads antes de prosseguir. Na verdade. Essa técnica tem muitos benefícios. Os programas com threads veem um modelo de ordenação de memória relaxado. O acesso à memória global por diferentes threads (e diferentes processadores) não tem garantias de ter consistência sequencial. Durante um ciclo de memória compartilhada. Dentro de uma thread. Diversos formatos são definidos. texturas 1D (lineares) e 3D (volume) também estão disponíveis. Um programa de cálculo referencia uma textura usando uma instrução tex. Para melhorar a largura de banda da memória e reduzir o overhead. Para dar suporte a grandes alocações de memória local (lembre-se de que a alocação total é a alocação por thread vezes o número de threads ativas). um pixel pode ser definido como quatro componentes inteiros RGBA de 8 bits. de modo que é exigida uma rede de in- terconexão de 16 por 16. Alguns programas usam buscas de textura como um modo de manter a memória global em cache. Os ope- randos incluem um identificador para nomear a textura. A cache constante é projetada para enviar valores escalares por broadcast às threads em cada warp. Como normalmente a maioria ou todas as threads em um warp SIMT leem do mesmo endereço na memória constante. 2 ou 3 coordenadas. a memória local é alocada na DRAM externa. ou quatro componentes de ponto flutuante de 16 bits. Memória de textura A memória de textura mantém grandes arrays de dados somente de leitura. as instruções load/ store globais juntam solicitações de thread paralelas individuais a partir do mesmo warp em uma única solicitação de bloco de memória quando os endereços caem no mesmo . e 1. com base na dimensionalidade da textura. dependendo do formato da superfície. Memória local A memória local por thread é a memória particular visível apenas a uma única thread. Superfícies Superfície é um termo genérico para um array unidimensional. Acesso de load/store As instruções load/store com endereçamento de byte inteiro permitem a escrita e com- pilação de programas em linguagens convencionais. uma única pesquisa de endereço por clock é suficiente. como C e C + +.A-600 Apêndice A  Gráficos e GPUs de computação em um banco de SRAM. Um kernel de programa não precisa conhecer o tipo da superfície. elas são bem adequadas a serem mantidas em cache no chip. Buscas de textura são mantidas em cache em uma hierarquia de cache streaming proje- tada para otimizar a vazão das buscas de textura de milhares de threads simultâneas. bidimensional ou tridi- mensional de valores de pixel e um formato associado. Ela é armazenada na DRAM externa e mantida em cache no SM. Embora a memória global e a local por thread residam fora do chip. Embora as texturas sejam normalmente imagens bidimensionais (arrays 2D de valores de pixel). Coordenadas não inteiras invocam uma interpolação ponderada bilinear dos quatro valores mais próximos (para uma textura 2D) antes que o resultado seja retornado ao programa. Uma instrução tex converte seus valores de resultado como ponto flutuante. Memória constante A memória constante é somente de leitura para um programa rodando no SM (ela pode ser escrita por meio de comandos à GPU). Deverá ser possível rotear uma solicitação a partir de qualquer pista de thread para qualquer banco de SRAM. As coordenadas de ponto flutuante incluem uma parte fracionária que especifica um local de amostra normalmente entre os locais de texel. por exemplo. Programas CUDA utilizam instruções load/store para acessar a memória. As texturas para computação têm os mesmos atributos e capacidades das texturas usadas com gráficos 3D. e um programa pode calcular endereços na memória local. A memória local é arquitetonicamente maior que o arquivo de registrador da thread. A aritmética de ponto flutuante das primeiras GPUs foi sucedida por ponto flutuante de 16 bits. Alguma lógica de função fixa dentro de uma GPU.6  Aritmética de ponto flutuante As GPUs hoje realizam a maioria das operações aritméticas nos cores de processador programáveis usando operações de ponto flutuante de 32 bits com precisão simples compatíveis com IEEE 754 (veja Capítulo 3). além de mistura de cores. comparação. O padrão também especifica um formato de ponto flutuante de armazenamento bi- nário de 16 bits. GPUs recentes também oferecem instruções de ponto flutuante de 64 bits com precisão dupla compatível com IEEE 754. meia precisão. GPUs da arquitetura Tesla NVIDIA compreendem um array de processador streaming (SPA). Os controladores de ROP e memória cooperam para implementar compactação de cor e profundidade sem perda (até 8:1) para reduzir a largura de banda externa. que realiza todos os cálculos programáveis da GPU. seguida por adição.2. ROP Como podemos ver na Figura A. fração de 10 bits de textura e mistura de pixel em meia precisão dentro da unidade de filtragem de textura e um bit de inteiro implícito. ciente.6  Aritmética de ponto flutuante A-601 bloco e atendem aos critérios de alinhamento. multiplicação-adição. ponto flutuante que realiza uma truções de ponto flutuante normalmente oferecem modificadores de operando de origem operação composta: multiplicação para negação e valor absoluto. máximo. continua a usar os formatos numéricos proprietários. e um sistema de memória escalável. ponto flutuante binário de 16 bits. junto com o suporte para muitas solicitações de load pendentes. que compreende controle de DRAM externa e Raster Operation Processors (ROPs) de função fixa. A grande quantidade de threads. Unidades ROP também realizam operações atômicas na memória. A. GPUs e a linguagem de sombreamento Cg empregam o meia precisão  Um formato de formato de dados estreito de 16 bits para armazenamento e movimentação de dados efi. expoente de 5 bits. Aritmética básica As operações comuns de ponto flutuante com precisão simples em cores programáveis da GPU incluem adição. Formatos aceitos O padrão IEEE 754 para aritmética de ponto flutuante [2008] especifica formatos básicos e de armazenamento. O formato de arquivo de imagem de alta faixa dinâ- mica OpenEXR.5. Cada ROP é responsável por testes e atualizações de profundidade e estêncil. mínimo. GPUs realizam muitos cálculos de filtragem com 1 bit de sinal. Juntar solicitações de memória pequenas em solicitações de bloco maiores oferece um aumento de desempenho significativo sobre solicitações separadas. . desenvolvido pela Industrial Light and Magic [2003]. As ins. que realizam operações de buffer de frame de cor e profundidade diretamente na memória. Cada unidade ROP é emparelhada com uma partição de memória específica. multiplicação. multiplicação-adição (MAD)  Uma instrução única em definição de predicado e conversões entre números inteiros e de ponto flutuante. ponto flutuante binário de 32 e 64 bits. As GPUs usam dois dos formatos básicos para computação. A. ajuda a cobrir a latência de load-para-uso para a memória local e global implementada na DRAM externa. usa o formato de metade idêntico para valores de componente de cor em aplicações de imagens de compu- tador e desenho animado. depois ponto flutuante de 32 bits compatível com IEEE 754. e a unidade de operações de rastreio. embora mantendo alta faixa dinâmica. 24 bits e 32 bits. Partições ROP são alimentadas a partir dos SMs por meio de uma rede de interconexão. normalmente chamados de precisão simples e precisão du- pla. como hardware de filtragem de textura. A unidade de função especial (SFU) introduzida na (SFU)  Uma unidade de hardware Seção A. Isso a torna diferente da instrução de multiplicação-adição fundida. Os m bits superiores Xu são usados para consultar um conjunto de três tabelas de pesquisa para retornar três coeficientes de palavra finita C0. C1 e C2. e mais adiante nesta seção. Podemos resumir o método de interpolação quadrática SFU. raiz quadrada recíproca. As estatís- ticas de função de exemplo aparecem na Figura A. Para aumentar a vazão da instrução em ponto flutuante.A-602 Apêndice A  Gráficos e GPUs de computação As operações de adição e multiplicação em ponto flutuante da maioria das GPUs atualmente são compatíveis com o padrão IEEE 754 para números de PF de precisão simples. seno. A operação de multiplicação-adição de ponto flutuante realiza multiplicação de PF com truncamento.6. Esses coeficientes são usados para aproximar determinada função f(X) no intervalo Xu <= X < Xu + 2−m avaliando a expressão: f(X) = C 0 + C1 X 1 + C 2 X 12 A precisão de cada função estima os intervalos de 22 a 24 bits significativos. Instruções de interpolação de atributo oferecem geração eficiente de atributos de pixel. GPUs normalmente limpam operandos de origem desnormalizados para zero preservado por sinal. sem exigir que o escalonador de ins- trução despache duas instruções separadas. 2x. e Xl é a parte inferior. e eles limpam resultados que passam por underflow da faixa de expoente de saída de destino para zero preservado por sinal após o arredondamento.1  Estatísticas de aproximação de função especial. FIGURA A. Para um operando de entrada binário X com significando de n bits. contendo m bits. . incluindo recíproco.4 calcula funções especiais e interpola atributos planares [Oberman e Siu. contendo n-m bits.1. Existem vários métodos para avaliar funções especiais no hardware. Mostrou-se que a interpolação quadrática baseada em Enhanced Minimax Approximations é um método muito eficiente para aproximar funções no hardware. Instruções de função especial incluem cosseno. Ela oferece duas operações de ponto flutuante em um ciclo de emissão. mas o cálculo não é fundido e trunca o produto antes da adição. o significando é dividido em duas partes: Xu é a parte superior. as GPUs normalmente utilizam uma instrução de multiplicação-adição composta (mad). derivados da unidade de função especial avaliação da equação do plano. logaritmo binário. recíproco e raiz quadrada recíproca. dis- cutida no Capítulo 3. ex- ponencial binário. 2005]. seno e cosseno. Para a unidade de função especial (SFU) do NVIDIA GeForce 8800. interpolação de atributo e filtragem de textura. Cada função a ser aproximada requer um conjunto exclusivo de tabelas. As operações de adição e multiplicação de PF utilizam o arredondamento-para-par-mais-próximo como o modo de arredondamento default. incluindo not-a-number (NaN) e valores infinitos. seguida por adição de PF com arredondamento-para-para-mais-próximo. log2x.6. que calcula funções especiais e interpola atributos planares. Aritmética especializada As GPUs oferecem hardware para acelerar o cálculo de função especial. Esses atributos precisam ser interpolados no espaço de tela (x. Exemplos de atributos são coordenadas de cor. mapa de MIP  Uma frase em Latin multum in parvo. usadas para aumentar a velocidade de 5. além de suas instruções convencionais IEEE de ponto flutuante com precisão simples. renderização e reduzir artefatos. Um mapa de MIP contém imagens pré-calculadas 4. para muitas aplicações de GPU. espaço pequeno. Calcular a fração de interpolação trilinear. B e C são parâmetros de interpolação associadas a cada atributo U. y) conforme a necessidade. O valor de determinado atributo U em um plano (x. ou muito em um 3. A. contudo. a biblioteca de matemática CUDA oferece uma função de precisão completa e uma função rápida com a precisão da instrução SFU. profundidade e textura.6  Aritmética de ponto flutuante A-603 O padrão IEEE 754 especifica requisitos de arredondamento exato para divisão e raiz quadrada. a vazão de cálculo mais alta é mais importante do que a precisão até o último bit. e a latência é otimizada para balancear atraso e área. Os parâmetros de interpolação A. Em pipeline. Os principais atributos normalmente são especificados para vértices de primitivos que compõem uma cena a ser renderizada. Outra operação aritmética especializada em uma GPU é a interpolação de atributo. com uma SFU compartilhada por quatro cores do SP. Dada a necessidade para um avaliador de função e um interpolador de atributo em um processador de sombreamento de pixel. Calcular o nível de detalhe para identificar o nível de mapa MIP com textura correta. o GeForce 8800 Ultra emite cerca de 500 GFLOPS de cálculo de ponto flutuante em formato próprio para instruções de mapeamento de textura. a vazão das funções especiais é menor que as operações de adição e multiplicação em ponto flutuante. Como um exemplo. y). a compatibilidade exata não é exigida. Para as funções especiais da SFU. para determinar os valores dos atributos em cada local de pixel. O mapeamento de textura requer uma quantidade significativa de cálculo de ponto flutuante para a operação em velocidade plena. t) para o nível de mapa de MIP selecionado. Realizar operação de filtragem sobre os texels. As duas funções usam uma operação de soma de produtos para interpolar resultados. t) para o pixel de tela atual (x. Escalar endereço de textura (s. 2. grande parte feita em meia precisão com 16 bits. e o número de termos a ser resumido nas duas funções é muito semelhante. Ao contrário. consulte Foley e van Dam [1995]. onde s e t são números de ponto flutuante de precisão simples. 6. as CPUs normalmente têm uma vazão significativamente menor para funções semelhantes. de diferentes resoluções. uma única SFU que realiza as duas funções por eficiência poderá ser projetada. B e C são todos representados como números de ponto flutuante de precisão simples. Desempenho O hardware aritmético de adição e multiplicação em ponto flutuante utiliza pipelines em sua totalidade. A vazão em um quarto de velocidade para as funções especiais é o desempenho típico nas GPUs modernas. Operações de textura Mapeamento e filtragem de textura é outro conjunto principal de operações aritméticas de ponto flutuante especializadas em uma GPU. y) = A u x + Bu y + C u onde A. Em vez disso. . Receber endereço de textura (s. As operações usadas para mapeamento de textura incluem: 1. y) pode ser expresso usando-se equações de plano na forma: U(x. para essas aplicações. Acessar memória e recuperar os texels desejados (elementos de textura). Para obter mais detalhes sobre mapeamento e filtragem de textura. além da própria operação FMA.6. . A instrução FMA também permite implementações de software eficientes de divisão e raiz quadrada arredondadas exatamente. como a Tesla T10P. conforme discutimos no Capítulo 3.2. A operação FMA realiza uma multiplicação de ponto flutuante seguida por uma adição. Dupla precisão GPUs mais recentes. os significandos de A e B são multiplicados para formar um produto de 106 bits. com os resultados mantidos na forma de carry-save (salvar vai-um). envolvendo o acúmulo de produtos. também admitem operações de precisão dupla IEEE 754 com 64 bits no hardware.A-604 Apêndice A  Gráficos e GPUs de computação como divisão e raiz quadrada. O hardware de in- terpolação de atributo normalmente utiliza pipelines em sua totalidade. O padrão de ponto flutuante IEEE 754 de 2008 inclui es- pecificação para a operação fundida de multiplicação-adição reunida (FMA). incluindo produtos de ponto. Em paralelo. As operações aritméticas de ponto flutuante padrão em precisão dupla incluem adição. evitando a necessidade de uma unidade de divisão ou raiz quadrada no hardware. A arquitetura de uma unidade FMA de precisão dupla permite o suporte para número desnormalizado em velocidade plena nas entradas e saídas. multiplicação de matriz e avaliação polinomial. embora com resultados mais exatos. Uma unidade FMA de precisão dupla no hardware implementa adição.2 mostra um diagrama em blocos de uma unidade FMA. As operações de multiplicação e adição fundidas retêm precisão total nos cálculos intermediários.6. multiplicação e conversões com 64 bits. multiplicação e conversões entre diferentes formatos de ponto flutuante e inteiro. Como podemos ver na Figura A. o somando de 53 bits C é condicionalmente invertido e alinhado ao produto de 106 bits. Hardware para implementar A × B + C em ponto flutuante para precisão dupla.6. A Figura A. Esse comportamento permite cálculos de ponto flutuante mais precisos. Os resultados de soma e vai-um do produto de 106 bits são somados FIGURA A. com um único arredondamento. para permitir sombreamentos de pixel em velocidade plena.2  Unidade fundida de multiplicação-adição (FMA) com precisão dupla. 1 contém 128 cores de processador streaming (SP) organizados como 16 multiprocessadores streaming (SMs).7  Vida real: o NVIDIA GeForce 8800 O NVIDIA GeForce 8800 GPU. . A saída do carry-save é então somada em um somador carry-propagate (propagar vai-um) para produzir um resultado não arredondando na forma não redundante. SMs. Dois SMs compartilham uma unidade de textura em cada cluster textura/processador (TPC). Nickolls.7. O resultado complementado é normalizado.1  Arquitetura unificada de gráficos e cálculo da GPU NVIDIA Tesla. FIGURA A. estações de trabalho e servidores. Um array de oito TPCs compõe o array de processador streaming (SPA). introduzido em novembro de 2006.7  Vida real: o NVIDIA GeForce 8800 A-605 com o somando alinhado por um somador carry-save (CSA) com 161 bits de largura.4 e em Lindholm. desktops. arrumados em oito clusters de textura/processador (TPC). A. Esse GeForce 8800 tem 128 cores de processador streaming (SP) em 16 multiprocessadores streaming (SM). que também admite aplicações de cálculo paralelo escritas em C usando o modelo de programação paralela CUDA. A. partições de DRAM e outras unidades. Os processadores se conectam a seis partições DRAM com 64 bits de largura por meio de uma rede de interconexão. Outras GPUs implementando a arquitetura Tesla variam o número de cores SP. e depois é arredondado para caber dentro do formato de destino. Oberman e Montrym [2008]. de complemento de dois. Uma família de GPUs da arquitetura Tesla enfoca as diferentes necessidades dos laptops. é um projeto de proces- sador unificado de vértice e pixel. que executa todos os programas de sombreamento gráfico e programas de cálculo. Array de processador streaming (SPA) A GPU GeForce 8800 mostrada na Figura A. O resultado é recomplementado condicionalmente.7. de modo a retornar um resultado na forma de magnitude com sinal. Essa é a primeira implementação da arquitetura unificada de gráficos e cálculo descrita na Seção A. pixels e arrays de threads de cálculo para os TPCs no SPA. O montador de entrada coleta primitivos geométricos (ponto. Os TPCs executam programas de sombreamento de vértice e geometria e programas de cálculo. A rede também direciona solicitações de leitura de memória de textura do SPA para a DRAM e lê dados da DRAM por uma cache de nível 2 de volta ao SPA. arbitrando a unidade de textura compartilhada. geometria ou pixel quad.7. A unidade de textura processa uma instrução de textura para um vértice. As origens da instrução de textura são FIGURA A. duas SFUs e uma memória compartilhada.A-606 Apêndice A  Gráficos e GPUs de computação A unidade de interface host se comunica com a CPU host por meio do barramento PCI-Express. O controlador de geometria mapeia o pipeline de vértice gráfico lógico em recirculação nos SMs físicos. cami- nho de load/store e caminho de E/S. um controlador SM (SMC). triângulos). . linhas.2  Cluster de textura/processador (TPC) e um multiprocessador streaming (SM). O SMC atende a três cargas de trabalhos gráficos simultaneamente: vértice. Cada SM tem oito cores de processador streaming (SP).7. dois multi- processadores streaming (SMs) e uma unidade de textura. direcionando todo atributo de primitivo e vértice e fluxo de topologia no TPC.2. Os pixels sombreados são enviados pela rede de interconexão para serem processados pelas unidades ROP. como mostra a Figura A. Os dados geométricos de saída são enviados ao bloco viewport/ clip/setup/raster/zcull para serem rasterizados em fragmentos de pixel. geometria e pixel. O SMC controla múltiplos SMs. Os blocos de distribuição de trabalho despacham vértices. que são então redistribuídos de volta ao SPA para a execução de programas de sombreamento de pixel. ou quatro threads de cálculo por ciclo. verifica a consistência do comando e realiza a mudança de contexto. Cluster de textura/processador (TPC) Cada TPC contém um controlador de geometria. O SM escalona e executa diversos tipos de warp simultaneamente. as instruções load/store acessam três espaços de memória de leitura-escrita: memória local para dados por thread.4. pelas threads do CTA. A. privados. ela flui acertos misturados com falhas sem gerar stalls. temporários. O SM executa arrays de threads cooperativos (CTAs) como múltiplos warps simultâneos que acessam uma região de memória compartilhada alocada dinamicamente para o CTA. para um máximo de 36 GFLOPS por SM. algumas unidades não de caminho de dados do SM operam com metade da taxa de clock do SP.5GHz.4. o escalonador pode manter ambas totalmente ocupadas. apanhando um vetor de coordenadas de origem e retornando um vetor de cores filtrado. As unidades SP e SFU executam instruções independentemente. pixel ou cálculo. Para executar de forma eficiente centenas de threads paralelas enquanto executa vários programas diferentes. O clock do GeForce 8800 Ultra trabalha com cores SP e SFUs a 1. e memória global para dados compartilhados por todas as threads. O conjunto de instruções baseado em registrador inclui todas as instruções de arit- mética de ponto flutuante e inteiro. load/ store de memória e instruções de textura listadas na tabela de instruções PTX da Figura A. duas SFUs. Cada thread tem seu próprio estado de execução de thread e pode executar um caminho de código independente.7  Vida real: o NVIDIA GeForce 8800 A-607 coordenadas de textura. que facilita reduções paralelas e gerenciamento paralelo da estrutura de dados. controle de fluxo. geometria e fragmento de pixel e programas de cálculo paralelos. memória compartilhada para dados por CTA de baixa latência. Um scoreboard qualifica cada warp para emitir cada ciclo. compartilha a unidade de busca e emissão de instrução SM eficientemente por 32 threads. Para otimizar a eficiência de potência e área. geometria. que executa programas de sombreamento de vértice. uma cache de instrução. o tipo de instrução e a “imparcialidade” para todos os warps sendo executados no SM. lógicas. anteriormente descrito na Seção A. O SM consiste em oito cores de processador de thread SP. Ele executa instruções escalares para threads individuais. diferente das arquiteturas anteriores de instrução de vetor da GPU. As instruções load/store da memória utilizam endereçamento de byte inteiro com aritmética de endereço de registrador-mais-offset. Ele controla e executa até 768 threads simultâneos no hardware com overhead de escalonamento zero. Conjunto de instruções Threads executam instruções escalares. As GPUs da arquitetura Tesla mais recente implementam operações de memória atômicas de PTX. Um warp consiste em até 32 threads do mesmo tipo — vértice.3. uma unidade de busca e emissão de instrução multithreaded (emissão MT). A unidade de textura utiliza pipelines em profundidade. O projeto SIMT. A cada ciclo de emis- são. e as saídas são amostras ponderadas. transcendentais. mas requer um warp completo de threads ativas para eficiência de desempenho plena. o SM é multithreaded por hardware. Uma instrução de warp emitida é executada como quatro conjuntos de 8 threads por quatro ciclos de processador. Embora contenha uma cache streaming para capturar a localidade da filtragem. O es- calonador de instrução prioriza todos os warps prontos e seleciona um com a prioridade mais alta para emissão. uma cache de constante somente de leitura e uma memória compartilhada de leitura/escrita com 16KB. e emitindo instruções entre elas em ciclos alternados. As instruções escalares são mais simples e amigáveis do compilador. Multiprocessador streaming (SM) O SM é um multiprocessador gráfico e de cálculo unificado. A priorização considera o tipo de warp. Para cálculos. Os programas de cálculo utilizam a instrução rápida de sincronização de barreira bar. . o escalonador seleciona um dos 24 warps para executar uma instrução de warp SIMT. normalmente uma cor de ponto flutuante com quatro componentes (RGBA). As instruções de textura permanecem baseadas em vetor. sync para sincronizar threads dentro de um CTA que se comunicam entre si por meio da memória compartilhada e global. O processador utiliza o pipeline por completo. incluindo not-a-number (NaN) e infinito.6.4). envia o pixel sobrevivente e dados associados ao ROP. em paralelo. Processador de operações de rastreio (ROP) e o sistema de memória Cada ROP é emparelhado com uma partição de memória específica. O SMC monta pixels sobreviventes em warps para serem processados por um SM rodando o sombreamento de pixel atual.A-608 Apêndice A  Gráficos e GPUs de computação Processador streaming (SP) O core SP multithreaded é o processador de threads principal. e. O algoritmo de antialiasing de amostragem de cobertura (CSAA) calcula e armazena a cobertura Boo- leana em até 16 amostras e compacta informações redundantes de cor. apresentado na Seção A. que gera equações de aresta para o rasterizador. ROPs admitem processamento com profundidade de taxa dupla quando as escritas de cor são desativadas. Os primitivos sobreviventes então vão para a unidade de configuração. rejeitando os pedaços de pixels se forem conservadoramente conhecidos como ocultados pelos pixels desenhados anteriormente. comparação. 2x e sin/cos em um resultado por ciclo. profundidade e estêncil no footprint da memória e uma largura de banda de quatro ou oito amostras para melhorar o desempenho. os ROPs realizam teste e atualizações de profundidade e estêncil. O core SP também implementa todas as instruções PTX de aritmética com inteiros. Suas operações de adição e multiplicação em ponto flutuante são compatíveis com o padrão IEEE 754 para números de PF com precisão simples. profundidade e textura em quatro amos- tras por ciclo. então. Conforme descrevemos na Seção A. As operações de adição e multiplicação utilizam o arredondamento-para-par-mais-próximo do IEEE como modo de arredondamento padrão. raiz quadrada recíproca. ela utiliza a interpolação quadrática com base nas aproximações minimax avançadas para aproximar as funções de recíproco. Seu arquivo de registradores oferece 1024 registradores escalares de 32 bits para até 96 threads (mais threads que o SP de exemplo da Seção A. dependendo do estado atual. Para cada fragmento de pixel emitido por um programa de sombreamento de pixel. Unidade de função especial (SFU) A SFU admite cálculo de funções transcendentais e interpolação de atributo planar. A SFU também admite interpolação de atributo de pixel como coordenadas de cor. que gera informações de cobertura e valores de profundidade detalhados. e depois trans- formam os vértices em espaço de tela (pixel). log2x. e a latência é otimizada para balancear atraso e área. Rasterização Primitivos de geometria dos SMs entram em sua ordem de entrada round-robin original no bloco viewport/clip/setup/raster/zcull. O suporte para antialiasing inclui até 16 multisampling e supersampling. Um estágio de rasterização coarse gera todos os pedaços de pixels que estão pelo menos parcialmente dentro do primitivo. O teste de profundidade e atualização pode ser realizado antes do sombreamento de fragmento. mistura de cores e atualizações. As unidades de viewport e clip cortam os primitivos até o frustum da view e até quaisquer planos de corte do usuário ativados. ou depois.4. conversão e lógicas de 32 e 64 bits. O SMC. A taxa de rejeição é de até 256 pixels por clock. . A compactação de cores sem perda (até 8:1) e a compactação de profundidade (até 8:1) são usadas para reduzir a largura de banda da DRAM. Cada ROP tem uma taxa máxima de quatro pixels por clock e admite formatos HDR de ponto flutuante com 16 e 32 bits. A unidade zcull mantém uma superfície z hierárquica. Os pixels que sobrevivem ao zcull vão então para o estágio de rasterização fina. O desempenho da CPU era medido usando a Intel Math Kernel Library (MKL) 10. A Figura A.5 compara o desempenho FFT de precisão simples complexo em 1D de um GeForce 8800 GTX a 1.4 compara as taxas em GFLOPS sobre a fatoração de matriz para uma GPU com uma CPU quad-core.8GHz (apelidado de “Harpertown”. de modo que uma rede de interconexão roteia solicitações e respostas.1 e FFTs de decimação-em-frequência com raiz 16 1D em lote. protocolos. Desempenho de FFT Fast Fourier Transforms são usadas em muitas aplicações.35GHz e um máximo correspondente de 518 GFLOPS. O desempenho . para um pico de operação teórico de 576 GFLOPS. gerando uma largura de banda de cerca de 16GB/s por partição. Variar o número de SMs. o problema de fatoração torna-se tão grande que SGEMM pode aproveitar o paralelismo da GPU e contornar o sistema CPU-GPU e overhead de cópia. As três seções seguintes comparam o desempenho de uma GPU GeForce 8800 com uma CPU multicore em três aplicações diferentes — álgebra linear densa. O desempenho da GPU foi medido usando a biblioteca NVIDIA CUFFT 2. Como a ordem de matriz aumenta além de 200 para 400. TPCs. oferecendo mais escalabilidade. em até 1. Desempenho O GeForce 8800 Ultra usa 1.3 compara as taxas em GFLOPS sobre a multiplicação matriz- matriz densa SGEMM para uma GPU GeForce 8800 GTX com uma CPU quad-core. ou 96GB/s. QR e Cholesky. A Figura A.7  Vida real: o NVIDIA GeForce 8800 A-609 O barramento de dados da memória DRAM é de 384 pinos. O código da CPU utiliza a biblioteca MKL 10. densidades de dispositivo e larguras de barramento de dados. enquanto a fatoração QR alcançou 192 GFLOPS. A. Grandes transformações e transformações multidimensionais são particionadas em lotes de transformações 1D menores. Desempenho da álgebra linear densa Os cálculos de álgebra linear densa são fundamentais em muitas aplicações. ROPs.7. A interconexão de link escalável (SLI) conecta múltiplas GPUs. Como a multiplicação matriz-matriz SGEMM e as rotinas BLAS3 semelhantes são o centro do trabalho na fatoração de matriz. Os controladores de memória admitem uma grande faixa de taxas de clock de DRAM. seu desempenho define um limite superior na taxa de fatoração.0GHz.3 vezes a CPU quad-core.0 FFT com quatro threads. Solicitações de textura e load/store podem ocorrer entre qualquer TPC e qualquer partição de memória. Escalabilidade A arquitetura unificada Tesla é projetada por escalabilidade. cerca de 60% da taxa de multiplicação-adição máxima do GeForce 8800 GTX. datado de final de 2007). A multiplicação matriz-matriz SGEMM de Volkov alcança 206 GFLOPS.7.35GHz (datado de final de 2006) com uma série Intel Xeon E5462 quad-core a 2. Cada partição admite protocolos de taxa de dados dupla DDR2 e GDDR3 orientado a gráficos.5GHz de clock nos cores do processador de threads SP e SFUs. O GeForce 8800 GTX tem um clock de processador de 1. A Figura A. Volkov e Demmel [2008] apresentam resultados de desempenho de GPU e CPU para multiplicação matriz-matriz densa com precisão simples (a rotina SGEMM) e fatorações de matriz LU. caches e partições de memória oferece o equilíbrio certo para alvos de desempenho e custo nos segmentos de mercado da GPU. cerca de 4. organizados em seis partições independentes de 64 pinos cada. transformações de Fourier rápidas e classificação.7. Os programas e bibliotecas da GPU são código C CUDA compilado.0 da Intel multithreading com precisão simples para aproveitar instruções SSE e múltiplos cores. incluindo todos os tempos de transferência de dados CPU-GPU. As linhas azuis são um Intel Core2 Quad Q6600 a 2. Intel MKL 10. As linhas pretas são um NVIDIA GeForce 8800 GTX a 1.35GHz. Intel MKL 10.1. . As linhas pretas são um GeForce 8800 GTX a 1.35GHz usando o código SGEMM de Volkov (agora no NVIDIA CUBLAS 2. Linux com 64 bits. Adaptado da Figura 7 de Volkov e Demmel [2008].3  Taxas de desempenho da multiplicação matriz-matriz densa SGEMM.0) em matrizes na memória GPU. Linux de 64 bits. O gráfico mostra as taxas em GFLOPS de precisão simples obtidas na multiplicação de matrizes N × N quadradas (linhas sólidas) e matrizes N × 64 e 64 × N (linhas tracejadas).67GHz. CUDA 1. Windows XP conectado a um Intel Core2 Duo E6700 a 2. FIGURA A.0.4GHz.A-610 Apêndice A  Gráficos e GPUs de computação FIGURA A.7.7. Adaptado da Figura 6 de Volkov e Demmel [2008].4GHz.4  Taxas de desempenho de fatoração de matriz densa.0 em matrizes na memória da CPU. O gráfico mostra taxas GFLOPS obtidas em fatorações de matriz usando a GPU e usando apenas a CPU. As linhas azuis são um Intel Core2 Quad Q6600 quad-core a 2. cache L2 de 6MB. e cada chip tem uma cache L2 de 4MB. 1600 FSB. A. diversos algoritmos de classificação bem conhecidos podem ser eficientemente colocados em paralelo para rodar em na GPU. Assim. Nessa faixa.8GHz (apelidado “Harpertown”). Red Hat Linux. com tamanho de lote 224/n.7  Vida real: o NVIDIA GeForce 8800 A-611 FIGURA A. Dos dois códigos radix sort baseados na CPU. Intel MKL 10. O gráfico compara o desempenho das FFTs complexas no local unidimensional em lote. e a expansão paralela é correspondentemente mais difícil de obter.5  Desempenho de vazão Fast Fourier Transform. a classificação requer uma coordenação muito mais substancial entre as threads paralelas.7. um foi implementado usando apenas o conjunto de instruções escalares e o outro utiliza rotinas de linguagem assembly cuidadosamente ajustadas. 4GB de memória. [2008] detalham o projeto de algoritmos de classificação em CUDA. ambos datando do início de 2007.35GHz com um Intel Xeon E5462 quad-core de 2.6 compara o desempenho da classificação paralela de um GeForce 8800 Ultra com um sistema Intel Clovertown de oito cores. o número de operações por transformação foi tomado como 5n log2n. O próprio gráfico mostra a taxa de classificação alcançada — definida como o número de elementos classificados dividido pelo tempo a classificar — para um intervalo de tamanhos de sequência. Fica aparente por esse gráfico que a radix sort da GPU alcançou a taxa de classificação mais alta para todas as sequências de elementos de 8K e maiores. Satish et al. O algo principal sendo estudado é o radix sort. Para determinar a taxa em GFLOPS. onde n é o tamanho da transformação. A Figura A. que tiram proveito das instruções de vetor SSE2 SIMD. . em um GeForce 8800 GTX de 1. Apesar disso. Cada soquete contém um módulo multichip com chips Core2 gêmeos. e os resultados que eles informam para radix sort são resumidos a seguir. Os cores da CPU são distribuídos entre dois soquetes físicos. a carga de trabalho para cada tamanho de transformação foi 128MB. Desempenho da classificação Ao contrário das aplicações que discutimos. da vazão da CPU e GPU foi medido usando-se FFTs em lote. Todas as rotinas de classificação foram projetadas para classificação pares de chave-valor em que chaves e valores são inteiros de 32 bits.0.7. embora o procedimento parralel_sort() baseado no Quicksort fornecido pelos Threading Building Blocks da Intel também seja incluído por comparação. Uma matriz esparsa n × n é aquela em que o número de entradas diferentes de zero m é somente uma pequena fração do total. provavelmente devido à fraca localidade de cache de suas permutações globais. Este gráfico compara as taxas de classificação para implementações de radix sort paralelas em um GeForce 8800 Ultra a 1. Esta seção apresenta exemplos de mapeamento de aplicações de cálculo paralelo es- caláveis à GPU usando CUDA. assim como as aplicações gráficas 3D expandem transparentemente seu paralelismo a GPUs com quantidades bas- tantes variadas de cores. A multiplicação de vetor de matriz esparsa (SpMV) é um bom exemplo de um bloco de montagem importante que pode ser paralelizado diretamente usando as abstrações fornecidas pelo modelo CUDA. A. simplificam a escrita de solucionadores iterativos. As representações em matriz esparsa buscam .8  Vida real: mapeando aplicações a GPUs O advento das CPUs multicore e GPUs manycore significa que os principais chips de processador agora são sistemas paralelos. Os kernels que discutimos a seguir.6 vezes mais rápida que a rotina baseada no Quicksort e aproximadamente duas vezes mais rápida que as rotinas radix sort. Além do mais. O desafio é desenvolver aplicações importantes de cálculo visual e cálculo de alto desempenho que expandam transparentemente seu paralelismo para aproveitar o número cada vez maior de cores de processador.7. O desempenho da radix sort da CPU varia bastante. como o método de gradiente conjugado.A-612 Apêndice A  Gráficos e GPUs de computação FIGURA A.5GHz e um sistema de oito cores Intel Core2 Xeon E5345 a 2. seu paralelismo continua a se expandir com a lei de Moore. mesmo quando as estruturas de dados envolvidas não são sim- ples grades regulares. ela é na média 2. quando combinados com as rotinas de vetor CUBLAS fornecidas.6  Desempenho da classificação paralela. todas usando os oito cores da CPU dis- poníveis. Matrizes esparsas Uma grande variedade de algoritmos paralelos pode ser escrita em CUDA de uma maneira razoavelmente simples.33GHz. Calcular o produto total é então simplesmente uma questão de percorrer todas as linhas e calcular o resultado para essa linha usando multiply_row().8. . Finalmente.8. as entradas para a linha i em Aj e Av se estendem do índice Ap[i] até. O código para esse kernel aparece na Figura A. temos uma condicional que só avalia o produto de uma linha se o índice da linha estiver dentro dos limites da matriz (isso é necessário porque o número de linha n não precisa ser um múltiplo do tamanho de bloco usado na partida do kernel). Como é muito comum que uma matriz esparsa n × n contenha apenas n = O(n) elementos diferentes de zero. existem apenas dois pontos de diferença.1 mostra um exemplo da representação CSR de uma matriz simples.8. Uma das representações mais comuns para as matrizes esparsas não estruturadas gerais é a representação da linha esparsa compactada (CSR). o índice row para cada thread é calculado a partir dos índices de bloco e thread atribuídos a cada thread. Os m elementos diferentes de zero da matriz A são armazenados em ordem principal de linha em um array Av.8.8  Vida real: mapeando aplicações a GPUs A-613 armazenar apenas os elementos diferentes de zero de uma matriz. Simplesmente espalhamos o loop em csrmul_serial() por muitas threads paralelas. Isso significa que Ap[0] sempre será 0 e Ap[n] sempre será o número de elementos diferentes de zero na matriz.1  Matriz de linha esparsa compactada (CSR). eliminando o loop for. A. mas não incluindo.2  Código serial em C para uma única linha de multiplicação de vetor de matriz esparsa. A Figura A. Cada thread calculará exatamente uma linha do vetor de saída y. Um segundo array Aj registra o índice de coluna correspondente para cada entrada de Av.3. Dada uma matriz A em formato CSR e um vetor x. Primeiro. Segundo. Esse algoritmo pode ser traduzido para um kernel CUDA paralelo muito facilmente. isso representa uma economia substancial no espaço de armazenamento e tempo de proces- samento.8. podemos calcular uma única linha do produto y = Ax usando o procedimento multiply_row() mostrado na Figura A. Observe que ele se parece exatamente com o loop serial usado no procedimento csrmul_serial(). um array Ap de n + 1 elementos registra a extensão de cada linha nos arrays anteriores. FIGURA A.8.2. como no código serial em C mostrado na Figura A. FIGURA A. Na realidade. o índice Ap[i+1].4. 8. não é exclusivo do modelo CUDA. por diversos sis- temas de programação paralelos. Esses loops podem ser colocados em paralelo facilmente pela simples atribuição de uma ou mais iterações do loop a cada thread paralela.3  Código serial para multiplicação de vetor de matriz esparsa. a partida desse kernel se parecerá com isto: O padrão que vemos aqui é muito comum. FIGURA A. O algoritmo serial original é um loop cujas interações são independentes uma da outra. Essa estratégia geral de decompor cálculos em blocos de trabalho independente. de uma forma ou de outra. e mais especificamente desmembrar iterações de loop independentes. Supondo que as estruturas de dados da matriz já tenham sido copiadas para a memória do dispositivo de GPU.A-614 Apêndice A  Gráficos e GPUs de computação FIGURA A. . incluindo OpenMP e Threading Building Blocks da Intel. Essa é uma técnica comum utilizada.4  Versão CUDA da multiplicação de vetor de matriz esparsa.8. O modelo de programação fornecido pelo modelo CUDA torna a expressão desse tipo de paralelismo particularmente simples. reordenação de matriz e bloqueio de registrador. para uma coleção de ma- trizes Laplacianas derivadas de malhas de superfície triangulada 3D. Desdobraremos o loop multiply_row() e buscaremos os elementos de x da cache sempre que for possível. Em muitos casos comuns. também conhecido como soma de prefixo paralela. até mesmo esse uso muito simples da memória compartilhada retorna uma melhoria de desempenho de cerca de 20% nas matrizes representativas derivadas de malhas de superfície 3D. ainda é interessante examinar o desempenho comparativo até mesmo desses kernels simples. 2. ele é relativamente pequeno. quatro e oito cores da máquina. uma pequena memória no chip. com latência muito baixa. [2007] em algumas arquiteturas multicore diferentes. Varredura e redução O scan paralelo. . respectivamente.8. correspondentes a speed-ups paralelos de 3. a n-1 ] . . No contexto da multiplicação de matriz esparsa. apresentadas por Sengupta. et al. em vez de uma cache de hardware implicitamente ativa.8  Vida real: mapeando aplicações a GPUs A-615 Caching na memória compartilhada Os algoritmos SpMV esboçados aqui são muito simples. O paralelismo desse kernel com a construção parrallel_for fornecida pelo Threading Building Blocks da Intel produz speed-ups paralelos de 2. como a busca de Ap[row+1] a partir de uma thread adjacente.. Esses são kernels muito simples. e particularmente quando a matriz foi reordenada.5. . cuja finalidade é ilustrar as técnicas básicas na escrita de programas CUDA. No exemplo mostrado anteriormente. os kernels csrmul_kernel() e csrmul_cached() alcançam taxas de processamento de aproximadamente 772 e 920 milhões de valores diferentes de zero por segundo. em vez de buscá-lo novamente da memória. Modificações usando memória compartilhada podem ser vistas na Figura A. O bloco de threads processando as linhas de i a j carregará de x[i] a x[j] nessa memória compartilhada. 1990].5. incluindo desdobramento de loop. as linhas usando x[i] serão linhas próximas da linha i. Portanto. em vez de como conseguir o máximo de desempenho. Como a arquitetura Tesla oferece uma memória compartilhada no chip controlada explicitamente.3 rodando em dois. o kernel csrmul_serial() roda em aproximadamente 202 milhões de valores diferentes de zero processados por segundo. Diversas avenidas de otimização possíveis estão disponíveis. Embora isso possa impor algum peso de desenvolvimento adicional para o programador. é um dos blocos de montagem mais importantes para os algoritmos paralelos de dados [Blelloch. Em um GeForce 8800 Ultra. observamos que várias linhas de A podem usar um elemento de array em particular x[i]. podemos implementar um esquema de caching simples e esperar alcançar algum benefício no desempenho. [2007]. Um modo importante de fazer isso é usar memória compartilhada como uma cache gerenciada pelo software para manter dados reutilizados com frequência. A. Em um processador Intel Core2 Xeon E5335 a 2GHz. é muito comum incluir esse tipo de otimização.1 e 2. Um dos recursos arquitetônicos importantes expostos pelo modelo CUDA é a presença da memória compartilhada por bloco. A dis- ponibilidade de uma memória controlada explicitamente no lugar de uma cache implícita também tem a vantagem de que políticas de caching e prefetching podem ser ajustadas especificamente às necessidades da aplicação. Os kernels paralelos também podem ser reimplementados em termos de operações scan paralelas com dados.6 vezes em relação do desempenho serial de um único core da CPU. Tirar proveito dessa memória pode oferecer melhorias de desempenho substanciais. O código resultante aparece na Figura A. Existem diversas otimizações que podem ser feitas nos códigos da CPU e GPU que podem melhorar o desempenho.8 a 4. Dada uma sequência a e n elementos: [a 0 . A memória compartilhada também pode ser usada para fazer outras otimizações. a1 .8. e os benefícios em potencial do desempenho podem ser substanciais. Apesar disso.0. várias delas exploradas por Williams et al. e um operador associativo binário ⊕ .A-616 Apêndice A  Gráficos e GPUs de computação FIGURA A.5  Versão de memória compartilhada da multiplicação de vetor de matriz esparsa..(a 0 ⊕ a 1 ). se consideramos ⊕ como o operador de adição normal. ⊕) = [a 0 ..8. então aplicar scan ao array de entrada a = [317 0 416 3] produzirá esta sequência de somas parciais: scan(a.. ⊕ a n −1 )] Como exemplo. +) = [3 411111516 22 25] . a função scan calcula a sequência: scan(a...(a 0 ⊕ a1 ⊕ .. ao FIGURA A. FIGURA A. A incorporação apenas dos elementos anteriores geraria um operador de scan exclusivo. a linha final do diagrama). vemos que ele incorpora todos os valores de entrada até ele mesmo. A principal observação é que. As arestas destacadas em azul mostram a forma dessa árvore de somatório para o elemento final. As folhas dessa árvore são todas elementos iniciais. também conhecido como operação de soma de prefixo. vemos que ela realiza O(n) adições. Ela realiza log2n iterações de um loop coletando somas parciais. A. Examinando a implementação serial.7  Modelo CUDA para plus-scan paralelo.8  Vida real: mapeando aplicações a GPUs A-617 Essa operação de scan é um scan inclusivo. As linhas indicam o local do qual os dados estão sendo buscados. que ilustra o caso simples para n = 8 threads e elementos.6. Para entender a ação desse loop. Cada nível do diagrama representa um passo do loop.8. e assim por diante. Uma implementação de seu algoritmo em CUDA aparece na Figura A. podemos imaginar a soma de pares de elementos consecutivos em paralelo. como mostra a Figura A.6  Modelo para plus-scan serial. Embora simples. esse algoritmo não é tão eficiente quanto gostaríamos. A implementação paralela. A implementação serial dessa operação é extremamente simples.8. no sentido de que o elemento i da sequência de saída incorpora o elemento ai da entrada. À primeira vista. considere a Figura A. Ela é simplesmente um loop que se repete uma vez pela sequência inteira. . Por exemplo. inclusive. Para cada elemento da saída (ou seja. estamos livres para mudar a ordem em que os elementos são somados. Porém. Ela considera que o array de entrada x[] terá exatamente um elemento por thread do bloco de threads. como a adição é associativa. estamos montando uma árvore de somatório pelos elementos da entrada.8.8. pode parecer que essa operação é inerentemente serial.7.8. Um esquema simples para fazer isso vem de Hillis e Steele [1989]. e depois a soma dessas somas parciais. Voltando a partir de qualquer elemento da saída.8. ela pode realmente ser implementada em paralelo eficientemente. Poderíamos simplesmente usar um algoritmo de scan para realizar esse cálculo. esse array deverá ser armazenado na . Ao final este loop. em vez de uma sequência de todas as somas de prefixo retornadas por scan. temos de combinar as somas parciais de todos os blocos na grade.8  Referências de dados de varredura paralelos baseados em árvore. O código na Figura A. cada thread simplesmente carrega um elemento da sequência de entrada (ou seja.9 mostra o código para calcular uma redução usando a adição. Nesse exem- plo. existem outras técnicas para implementar scan que são eficientes ao trabalho. de modo semelhante ao algoritmo de scan acima. pois realiza mais trabalho que a implementação serial para calcular o mesmo resultado. Esse é o problema da redução paralela. contrário. Os detalhes sobre técnicas de implementação mais eficientes e a extensão desse procedimento por bloco a arrays multiblocos são fornecidos por Sengupta.8. realiza O(n log n) adições.8. mas a redução geralmente pode ser implementada de forma mais eficiente que o scan. Uma estratégia para seria fazer com que cada globo escreva sua soma parcial em um segundo array e depois iniciar o kernel de redução novamente. Ele aceita como entrada um array values contendo um inteiro de 32 bits para cada thread do bloco. Uma alternativa mais atraente admitida pela arquitetura de GPU Tesla é usar o primitivo atomicAdd(). ela inicialmente soma uma subsequência de comprimento 1).8. O loop nesse kernel monta implicitamente uma árvore de somatório sobre os elementos de entrada. queremos que a thread 0 contenha a soma de todos os elementos carregados inicialmente pelas threads de seu bloco. Radix sort Uma aplicação importante das primitivas de scan é na implementação de rotinas de classificação.A-618 Apêndice A  Gráficos e GPUs de computação FIGURA A. um primitivo de leitura-modificação-escrita atômico admitido pelo subsistema de memória. Esse grau de mistura de dados entre as threads seria proibitivamente caro se fosse feito na memória global fora do chip. [2007]. et al. A redução paralela é um primitivo essencial para a programação paralela e realça a importância da memória compartilhada por bloco e barreiras de baixo custo para tornar eficiente a cooperação entre as threads. Isso elimina a necessidade de arrays temporários adicionais e partidas de kernel repetidas. a thread 0 contém a soma de todos os valores carregados por esse bloco. Feliz- mente.10 implementa um radix sort de inteiros por um único bloco de threads. Ao final da redução. Em alguns casos. ela não é eficiente ao trabalho. A Figura A. Por eficiência. podemos só estar interessados em calcular a soma de todos os elemen- tos em um array. Por esse motivo. Se quisermos que o valor final do local apontado por total contenha o total de todos os elementos no array. repetindo o processo até que tenhamos reduzido a sequência a um único valor. 8.8. esse particionamento deverá ser estável. A implementação de um procedimento de particionamento é uma aplicação simples do scan. mas isso não é exigido para que a classificação ocorra corretamente. Essa é uma implementação muito simples do radix sort. A thread i mantém o valor xi e precisa calcular o índice de saída correto para es- crever esse valor. A. A .8  Vida real: mapeando aplicações a GPUs A-619 FIGURA A. Uma estratégia semelhante pode ser aplicada para implementar um kernel de radix sort que classifica um array de tamanho grande. O código CUDA para partition_by_bit() aparece na Figura A. memória compartilhada por bloco. em vez de apenas um array de um bloco. ela precisa calcular (1) o número de threads j < i para as quais o bit designado é 1 e (2) o número total de bits para os quais o bit designado é 0. Ela considera a disponibilidade de um procedimento partition_by_bit() que dividirá o array indicado de modo que todos os valores com um 0 no bit designado chegarão antes de todos os valores com 1 nesse bit.9  Implementação CUDA de plus-reduction. FIGURA A.8. Para fazer isso.11. Para produzir a saída correta.10  Código CUDA para radix sort. Satish. várias simplificações foram propostas na geração de algoritmos O(n log n) e O(n). . simulação de fluxo de fluido turbulento. etapa fundamental continua sendo o procedimento de scan. com a única perda de precisão vindo das operações de hardware de ponto flutuante. Um exemplo é uma simulação astrofísica em que cada corpo representa uma estrela individual. com excelente desempenho de GPU — o algoritmo all-pairs N-body. Aplicações N-body em uma GPU1 Nyland. Harris e Garland [2008] fornecem detalhes para a realização de radix sorts sobre arrays grandes de forma eficiente. somando para cada corpo. e os corpos atraem gravitacionalmente uns aos outros. em que a simulação N-body é usada para calcular forças ele- trostáticas e van der Waals. Para contornar esse custo alto. O algoritmo all-pairs N-body calcula a força total em cada corpo no sistema pelo cálculo da força de cada par no sistema.8. que é muito grande para os sistemas com mais de 106 corpos. Esse é um componente demorado de muitas aplicações científicas. porém útil. devamos dobrar o buffer do array de valores em vez de fazer o particionamento no local. “Fast N-Body Simulation with CUDA”. Harris e Prins [2007]. e iluminação global em gráficos de computador. Outros exemplos são desdobramento de proteína. Capítulo 31 de GPU Gems 3.A-620 Apêndice A  Gráficos e GPUs de computação FIGURA A. quando um cálculo é particionado por múltiplos kernels. 1 Adaptado de Nyland. Simulações N-body calculam a evolução de um sistema de corpos em que cada corpo interage continuamente com cada outro corpo. A desvantagem é sua complexidade de cálculo O(n2). Muitos cientistas consideram esse método como o mais preciso. Harris e Prins [2007] descrevem um kernel de cálculo simples. embora.11  Código CUDA para particionar dados com base em cada bit. como parte do radix sort. Dada uma lista de corpos interagindo (um sistema inteiro ou um subconjunto). Quando todas as forças são calculadas. ele continua a ser importante. O código do cálculo de força serial usa dois loops for aninhados interagindo por pares de corpos. O loop interno chama uma função que calcula a força por cada par. mas não é eficiente. e o loop interno percorre todos os corpos.8  Vida real: mapeando aplicações a GPUs A-621 alguns exemplos são o algoritmo de Barnes-Hut. O loop externo é substituído por uma grade de kernel CUDA que dispara N threads. Entre dois corpos indexados por i e j. o Fast Multipole Method e o somatório Particle-Mesh-Ewald. O loop externo seleciona o corpo para o qual a força total está sendo calculada. assim. A conversão para CUDA.13. . um para cada corpo. pois ignora recursos arquitetônicos importantes. enquanto a atualização é O(n). Otimização para execução da GPU O código CUDA mostrado está funcionalmente correto. converte o loop externo serial para um kernel por thread. a memória compartilhada pode ser usada para evitar FIGURA A. calcule a força e a soma para cada corpo. o vetor força 3D é: mi m j rij fij = G 2 × rij rij A magnitude da força é calculada no termo da esquerda. Os dois kernels terminam armazenando a aceleração total em um array global usado para calcular os novos valores de posição e velocidade em uma etapa subsequente.12 e na Figura A. O cálculo das forças tem complexidade O(n2). pois o cálculo da força sobre cada corpo é independente do cálculo em todos os outros corpos. A. O código para as versões serial e paralela aparece na Figura A. as posições e velocidades dos corpos podem ser atualizadas. calcule a força corpo-corpo usando a física elementar. O melhor desempenho pode ser alcançado com três otimizações principais.12  Código serial para comparar todas as forças por par em N corpos. Matemática N-body Para a simulação gravitacional. enquanto a direção é calculada à direita (vetor unidade apontando de um corpo para o outro). O kernel CUDA calcula uma ID de thread global para cada thread. como em muitos outros exemplos. substituindo a variável repetidora do loop externo serial. o cálculo é simples: para todos os pares de interações. depois soma a força a uma soma acumulada. Quando as forças totais são calculadas.8. elas são usadas para atualizar a posição e a velocidade de cada corpo.8. Primeiro.8. Para calcular as forças em paralelo. em que cada thread calcula a força total sobre um único corpo. atribuímos uma thread a cada corpo. A versão serial tem dois loops for aninhados. com base na posição e velocidade anterior. Todos os métodos rápidos ainda contam com o método all-pais como um kernel para o cálculo preciso de forças de curta duração. Mudamos as dimensões do bloco de threads de (p. 1). A função chamada accel_on_one_body() requer algumas mudanças para admitir essa otimização. Segundo. o desempenho no 8800 GTX salta por 110% quando N = 1024 (uma thread alcança 90 GFLOPS. Cada iteração do loop externo carrega p posições sucessivas na memória compartilhada (uma posição por thread). resultados parciais podem ser armazenados na memória compartilhada. Muitos esforços de pesquisa que contam com cálculos N-body focalizam em um N pequeno (para longos tempos de simulação).15 mostra a degradação de desempenho para problema com pequenos valores de N (N < 4096) no GeForce 8800 GTX. Otimizamos o código mostrado anteriormente para que cada uma das p threads em um bloco de threads carregue uma posição na memória compartilhada (para um total de p posições). O uso da memória compartilhada reduz a largura de banda de memória exigida para menos de 10% da largura de banda total que a GPU pode sustentar (usando menos de 5GB/s). cada thread pode então realizar p interações (usando os dados na memória compartilhada). tornando-o um alvo para nossos esforços de otimização.14. q. O uso de duas ou quatro threads por corpo leva a grandes melhorias para um N pequeno. o desdobramento de loop reduz o overhead com o loop.A-622 Apêndice A  Gráficos e GPUs de computação FIGURA A. em que quatro alcançam 190 GFLOPS). Usando múltiplas threads por corpo A Figura A. eliminando solicitações de memória redundantes entre as threads. na faixa de 32 a 128). Quando todas as threads tiverem carregado um valor na memória compartilhada. Alocando as threads adicionais dentro do mesmo bloco de threads. 1) para (p.13  Código de thread CUDA para calcular a força total em um único corpo. A solução é alocar mais threads por corpo.8. Isso é repetido N/p vezes para completar o cálculo de força para cada corpo. Nossa suposição para explicar o desempenho mais baixo foi que simplesmente não havia trabalho suficiente para manter a GPU ocupada quando N é pequeno.15. Uma segunda sincronização é necessária para garantir que novos valores não sejam carregados na memória compartilhada antes de todas as threads. O loop que anteriormente percorria todos os corpos agora salta pela dimensão de bloco p. leituras de memória idênticas entre as threads. O código modificado aparece na Figura A. os q resultados parciais podem ser coletados e somados para calcular o resultado final. em vez de es- perar os acessos à memória. Como um exemplo. o uso de múltiplas threads por corpo melhora o desempenho para valores pequenos de N. em que q threads dividem o trabalho de um único corpo em partes iguais. Terceiro. o que reduz o número de solicitações à memória por um fator de p (normalmente. completando os cálculos de força com os dados atuais. como aconteceria sem o uso da memória compartilhada.8.8. O desempenho para valores variados de N aparece na Figura A. Quando todos os cálculos de força forem feitos. O desempenho cai . As threads se sincronizam e depois p cálculos da força são calculados por cada thread.8. 1. garantido por _syncthreads(). Usando memória compartilhada A memória compartilhada pode manter um subconjunto de posições de corpo. como uma cache. Essa otimização mantém a aplicação ocupada realizando cálculo. Os aumentos de desempenho aparecem na Figura A. mas por fim contrai uma penalidade no desempenho à medida que N cresce. o problema precisa ser maior para alcançar desempenho pleno (o pico de 9600 fica em torno de 2048 corpos.8. podemos ver o desempenho das GPUs como alto e médio. Na Figura A.15  Medidas de desempenho da aplicação N-body em um GeForce 8800 GTX e um GeForce 9600. de modo que só usamos essa otimização para N menores que 4096.80GHz (cerca de 30% do 8800). Para um N pequeno. FIGURA A. A.16. mais de uma thread por corpo pode melhorar o desempenho significativamente.384 corpos).15 e A. enquanto o 8800 não alcança seu máximo até 16.8. junto com as melhorias alcançadas usando múltiplas threads por corpo.8. O desempenho de pico é 242 GFLOPS.8. Para uma GPU com mais processadores.14  Código CUDA para calcular a força total em cada corpo. ligeiramente em um N grande. usando memória compartilhada para melhorar o desempenho.8. O desempenho na GPU mais rápida varia de 90 a pouco menos de 250 GFLOPS.8. O 8800 tem 128 processadores de stream a 1.8  Vida real: mapeando aplicações a GPUs A-623 FIGURA A. Comparação de desempenho O desempenho do código N-body aparece nas Figuras A.15.15 para uma GPU com 128 processadores e uma GPU menor com 64 processadores com clock a dois terços da velocidade. .35GHz. enquanto o 9600 tem 64 a 0. pois a CPU requer apenas metade dos cálculos para gerar o mesmo resultado (usando a otimização de que as forças em um par de corpos são iguais em força e opostas em direção).8. que um compilador pode explorar. O gráfico mostra o desempenho N-body de precisão simples usando CPUs Core2 da Intel. pois sua precisão é muito baixa para ser comparável. em que o desempenho melhora em 24%. um desktop.384 na CPU X9775. 2 As instruções SSE do x86 de raiz quadrada recíproca (RSQRT*) e recíproca (RCP*) não foram consideradas. As CPUs da Intel são um Extreme X9775 a 3.0. indicados por seu número de modelo de CPU.2 GHz.A-624 Apêndice A  Gráficos e GPUs de computação A Figura A. o código exige 6-16 segundos.66GHz (apelidado de “Wolfdale”).16  Medidas de desempenho no código N-body em uma CPU. O desempenho na CPU geralmente independe do tamanho do problema. CUDA expõe paralelismo e localidade. um E8200 a 2.83GHz (apelidado de “Yonah”). e nos processadores Core2 mais antigos e no processador Pentium IV. como linguagem de progra- mação. único core) levou mais de 3 segundos por frame para rodar o mesmo código que roda a uma taxa de frame de 44 Hz em uma GPU GeForce 8800. permitindo que operações de divisão e raiz quadrada sejam executadas quatro vezes mais rápido que as CPUs Intel anteriores. As CPUs da Intel utilizam muitos ciclos para instruções de divisão e raiz quadrada com precisão simples. permitindo que o compilador faça melhor uso da unidade de vetor SSE em um único core. O tempo de execução para o código N-body rodando em uma CPU recente da Intel (Penryn X9775 a 3. O cálculo da força por par requer 20 operações de ponto flutuante.97 e 7. compreendendo principalmente instruções de adição e multiplicação (algumas das quais podem ser combinadas usando-se uma instrução de multiplicação-adição).94 em dois. em que ele supera o código C + + em 24%. desenvolvemos um kernel de cálculo que melhora o desempenho da GPU por CPUs multicore por um fator de até 157.2 a 2 GFLOPS. expõe paralelismo. nas quais alcança expansão quase perfeita em um sistema de oito cores com N = 4096 (razões de 2.2 FIGURA A. Observe a drás- tica redução no desempenho em GFLOPS (mostrado em GFLOPS no eixo y). respectivamente). A versão Penryn da arquitetura Core 2 é particularmente interessante para cálculos de N-body com seu divisor de 4 bits. demonstrando o quão mais rápida é a GPU em comparação com a CPU. uma CPU de laptop de 2007. O gráfico também mostra os resultados da execução da versão CUDA do código (usando o compilador CUDA-for-CPU) em um único core da CPU. Como uma linguagem de programação.2GHz (apelidado de “Penryn”). 3. O desempenho da CPU é cerca de 1% da GPU. O gráfico também mostra os resultados da compilação da versão CUDA do código para uma CPU. Resultados Com um esforço modesto. A versão CUDA do código N-body também é naturalmente mapeada para CPUs multicore (com grades de blocos). na faixa de 0. Em CPUs anteriores ao Penryn. CPU anterior ao Penryn. . e um T2400 a 1. CUDA. exceto para um desempenho anomalamente baixo quando N = 16. Temos de dividir o aumento aparente no desempenho ao meio. permanecendo quase constante pela grande gama de tamanhos de problema.8. mas também existem instruções de divisão e raiz quadrada para normalização de vetor. Como a GPU pode agilizar o código tanto assim? A resposta exige uma inspeção nos detalhes arquitetônicos. o tempo é de cerca de 25 segundos.16 mostra um código quase idêntico (C + + versus CUDA) rodando em CPUs Core2 da Intel. quatro e oito cores. Isso oferece aos cientistas uma imagem visual incrível. em comparação com mais de 40 instruções de uma série de compiladores de CPU x86. e podemos exibir interativamente 16K corpos interagindo a 44 frames por segundo.8. o algoritmo all-pairs N-body emite mais de 240 GFLOPS de desempenho. como redução de ruído. muito rápidos ou muito lentos). Acoplamos a simulação N-body da GPU com uma exibição gráfica do movimento. A. mais espaço de regis- trador e um compilador eficiente se combinam para explicar a melhoria de desempenho dramático do código N-body entre a CPU e a GPU. Também disponível em www3.8. Order Number: 248966-016. A configuração inicial é uma FIGURA A. com seu divisor de 4 bits mais rápido. Isso per- mite que eventos astrofísicos e biofísicos sejam exibidos e navegados em taxas interativas.17 mostra uma exibição de série de tempo de uma simulação astrofísica de 16K corpos. mas ainda é significativamente mais lento que uma única GPU. Finalmente.3 Além do mais. Ele tem um arquivo de registradores maior (por thread) e memória compartilhada que pode ser acessada como um operando de instrução. Maior paralelismo. com cada corpo atuando como uma galáxia.pdf. em comparação com menos de 2 GFLOPS nos processadores sequenciais recentes. veja na Seção A. exibindo imediatamente seus efeitos sobre a dinâmica do sistema. damping e técnicas de integração. 3 Intel Corporation. as limitações na capacidade de registrador levam a muitas instruções MOV no código x86 (supostamente de/para a cache L1). . podemos parametrizar muitas configurações. Novembro de 2007. execução mais rápida de instruções complexas. A compilação e execução da versão CUDA do código em uma CPU demonstra que o programa se expande bem para CPUs multicore. o GeForce 8800 executa uma instrução de thread de raiz quadrada recíproca em quatro clocks.intel.17  Doze imagens capturadas durante a evolução de um sistema N-body com 16.6 a precisão da função especial. A Figura A. Em um GeForce 8800. Além disso. Intel 64 and IA-32 Architectures Optimization Reference Manual. Ao contrário. melhorando suas percepções sobre sistemas de outra forma invisíveis (muito grandes ou pequenos.com/design/processor/ manuals/248966.384 corpos.8  Vida real: mapeando aplicações a GPUs A-625 embora isso tenha melhorado na família de CPUs Penryn mais recente. permitindo-lhes criar melhores modelos dos fenômenos físicos. o compilador CUDA emite 15 instruções para uma interação do loop. Embora Moore fizesse a previsão inicial em 1965. Gordon Moore [1965] previu que essa progressão ofereceria aproximadamente duas vezes o número de transistores para o mesmo custo de manufatura a cada ano. Em aplicações gráficas.4. A execução é mais eficiente se os acessos individuais de load/store da thread também puderem ser reunidos em acessos em bloco. um warp de 32 threads) seja executado mais eficientemente quando os PCs para as threads são os mesmos. com o tempo. pode haver vários grupos de programas de vértice. Uma GPU não possui tal restrição para acessos a registrador ou memória. Contudo. A redução do tamanho do transistor historicamente teve outros benefícios. ele provou ser muito coerente. memória particular da thread. o código CUDA para essa aplicação está disponível no SDK CUDA. Na verdade. O modelo de execução de thread é MIMD com sincronização de barreira e otimizações SIMT. Cada thread da GPU tem seus próprios registradores escalares. ID de thread. como menor potência por transistor e velocidades de clock mais rápidas em potência constante. Assim. tanto que muitas pessoas acham que o crescimento do desempe- nho do processador de duas vezes a cada 18-24 meses é a lei de Moore. Os projetistas de microprocessador gastam alguns dos novos transistores nos cores do processador. A lei de Moore descreve uma expectativa de que. Falácia: GPUs são apenas multiprocessadores de vetor SIMD.9  Falácias e armadilhas As GPUs evoluíram e mudaram tão rapidamente que surgiram muitas falácias e armadilhas. Ela não é um limite da “velocidade da luz” para qualquer outra taxa. A lei de Moore é simplesmente uma taxa. em www. execução independente. juntamente com a mistura de galáxias com o tempo. Um fenômeno de interesse para os astrofísicos é o agrupamento que ocorre. caminho de desvio e contador de programa eficaz. Embora um grupo de threads (por exemplo.A-626 Apêndice A  Gráficos e GPUs de computação concha esférica de corpos girando em torno do eixo z. Abordamos algumas delas aqui. Os programas de cálculo também podem executar diferentes programas simultaneamente em diferentes warps. programas de pixel e programas de geometria rodando no array multiprocessador simultaneamente. porém. a execução é mais eficiente se os warps de threads acessarem blocos de dados locais. à medida que a tecnologia de semicondutores avança e os transistores se tornam menores. os acessos à memória/registrador para diferentes threads precisam ser alinhados em um padrão de vetor regular.com/CUDA. Porém. não é. estado de execução da thread. Para o leitor interessado. os multiprocessadores não são puramente SIMD. dado um custo de manufatura constante. e realizando o pipelining para mais .nvidia. quando havia apenas 50 componentes por circuito integrado. memória e outros componentes. Saindo ainda mais de um modelo SIMD puro. Em outras palavras. Por algum tempo. descrito na Seção A. a execução dessas threads não é puramente SIMD ou vetor. GPUs pos- suem um modelo de programação em estilo SPMD. Em uma arquitetura de vetor puramente SIMD. os projetistas de CPU usaram os transistores extras para aumentar o desempenho do processador em uma taxa semelhante à lei de Moore. pois um programador pode escrever um único programa que é executado em múltiplas instâncias de thread com múltiplos dados. o número de transistores aumentará exponencialmente. isso não é necessário. isso não é estritamente necessário. Falácia: o desempenho da GPU não pode ficar mais rápido do que a lei de Moore. além de poder endereçar a memória independentemente. melhorando a arquitetura e o projeto. e mais tarde o revisou para dobrar a cada dois anos. o custo de manufatura por transistor cairá exponencialmente. uma GPU SIMT pode executar mais de um warp de threads simultaneamente. A. ela é Single- Instruction Multiple-Thread (SIMT). Essa generosidade crescente de transistores é usada por arquiteturas de chip para criar processadores. É fácil chegar à falsa con- clusão de que as GPUs são simplesmente multiprocessador de vetor SIMD. as GPUs são iguais a quaisquer outros processadores compatíveis com IEEE 754. Quarto. aumentando a eficiência do processamento. memórias mais largas. conforme a maioria das aplicações exige. E talvez mais rápido. Para atender as demandas do desenvolvedor de software gráfico expressas nas interfaces e requisitos de desempenho/ recursos das APIs gráficas. As GPUs. O restante dos novos transistores é usado para oferecer mais cache e tornar o acesso à memória mais rápido. compactação de dados e caches melhores. elas não podem fazer cálculos gerais. portanto. Assim. a precisão dupla roda mais lentamente que a velocidade de precisão simples. As GPUs são processadores completos de Turing. de modo que a taxa da lei de Moore claramente pode ser excedida gastando-se mais para chips maiores com mais transistores. cerca de cinco a dez vezes mais lenta. A. Falácia: GPUs não podem executar programas de ponto flutuante com precisão dupla com rapidez. As GPUs modernas realizam praticamente todos os cálculos em aritmética de ponto flutuante IEEE com precisão simples. aritmética de ponto fixo. de modo que podem executar qualquer programa que uma CPU pode executar. mais rápidos. Cg e HLSL. pelo menos na família de processadores da arquitetura Tesla. Por um pequeno custo adicional. Falácia: a GPUs exibem gráficos 3D. ultrapassando a taxa da lei de Moore. os projetistas de GPU colhem os frutos da lei de Moore diretamente pela aplicação de exponencialmente mais transistores na montagem de processadores mais paralelos e. Falácia: GPUs não computam ponto flutuante corretamente. Hoje. os projetistas de GPU utilizam quase nenhum dos novos transistores para oferecer mais cache. A combinação dessas quatro técnicas historicamente tem permitido que o desempenho da GPU dobre regularmente. E isso não é muito rápido de forma alguma. embora talvez não tão bem. Hoje. As GPUs são criadas para exibir gráficos 3D e também gráficos e vídeo 3D. e estão começando a usar também a precisão dupla. como o tratamento de números desnormalizados e o oferecimento de exceções de . usando memórias mais rápidas. Terceiro. esses processadores são programados por meio das APIs gráficas e com linguagens de programação gráfica misteriosas (GLSL. uma GPU pode admitir ponto flutuante com precisão dupla além de ponto flutuante com precisão simples. que permite que os programadores desenvolvam programas de aplicação gerais usando a linguagem C e logo C + +. adicionaram a precisão dupla. em OpenGL e Direct3D). As GPUs progrediram da representação aritmética indexada (tabelas de pesquisa para cores) para inteiros de 8 bits por componente de cor. as GPUs não implementam alguns dos recursos específicos descritos no pa- drão. os projetistas de GPU podem melhorar a arquitetura com o tempo. O limitador de taxa mais desafiador parece ser o sistema de memória. a lei de Moore considera custo constante. Segundo. As GPUs ficam mais rápidas por quatro mecanismos. realizam o processamento de ponto flu- tuante com precisão simples em um nível prescrito pelo padrão de ponto flutuante IEEE 754. recentemente. e não mostra sinais de diminuição de velocidade significativa. em termos de precisão. as GPUs se tornaram processadores de ponto flutuante progra- máveis maciçamente paralelos. a maioria dos transistores é usada para melhorar os cores do processador e acrescentar mais cores do processador. Pelo custo adicional incremental. No domínio gráfico. foi demonstrada em aplicações gráficas por aproximadamente dez anos. Primeiro.9  Falácias e armadilhas A-627 velocidade de clock. De fato. o desempenho da precisão dupla pode ser aumentado com relação à precisão simples em estágios. os sistemas de memória da GPU aumentaram sua largura de banda efetiva em um ritmo quase comparável à taxa de processamento. as GPUs não podiam executar programa algum de ponto flutuante com precisão dupla. No passado. mas a inovação competitiva também está avançando isso rapidamente. não há nada que impeça os arquitetos de GPU de exporem os cores de processador paralelo a programadores sem a API gráfica ou as linguagens gráficas misteriosas. ponto flutuante com precisão simples e. a família de GPUs da arquitetura Tesla expõe os processadores por meio de um ambiente de software conhecido como CUDA. Porém. Ao contrário. Essa taxa. a cada 12 a 18 meses mais ou menos. CUDA deliberadamente deixa dados na GPU entre as partidas para dar suporte a isso. se os acessos à memória forem espalhados e não correlacionados entre as threads. Algumas CPUs têm usado o multithreading para tolerar a latência. A CPU. serão limitados pela transferência de entradas à GPU e a saída de retorno do cálculo. de modo que é evitada esforçando-se para executar na cache. as etapas de transferência de dados de e para o dispositivo podem limitar o desempenho dos algoritmos com a complexidade O(n) (com uma pequena quantidade de trabalho por dado). A memória externa está dis- tante do processador. sem o uso de threads (por meio de funções assíncronas da GPU). Alguns exemplos são processamento de vídeo. Assim. Consequentemente. compactação/descompactação de dados e até mesmo cálculos simples. O modelo de programação CUDA admite a alocação de trabalho a uma ou mais GPUs junto com o uso continuado da CPU. Segundo. Se a próxima instrução não estiver pronta ou os dados exigidos para essa instrução não estiverem disponíveis. Cada thread pode tolerar alguma quantidade de latência da memória. a instrução não poderá ser executada e o processador emite um stall. A estratégia da GPU é que diferentes cores da GPU sejam projetados para executar muitas threads simultaneamente. Para executar em velocidade total. a GPU admite as operações simultâneas de copy-in. A taxa de transferência mais alta em relação ao barramento PCIe é aproximadamente 48GB/segundo quando são usadas transferências de DMA. roteamento de rede. de modo que os dados podem ser enviados para dentro e fora do dispositivo enquanto ele está calculando.A-628 Apêndice A  Gráficos e GPUs de computação ponto flutuante precisas. Por fim. de modo que é relativamente simples manter todas as GPUs e uma CPU trabalhando simultaneamente para solucionar problemas ainda mais rapidamente. Porém. mas em conjunto executa as threads de uma maneira mais eficiente. copy-out e cálculo. Armadilha: só use mais threads para cobrir latências de memória maiores. Os cores da CPU normalmente são projetados para executar uma única thread em velocidade total. pois outras threads podem executar. tente deixar os dados na GPU pelo máximo de tempo possível. até mesmo as múltiplas threads não serão capazes de cobrir a latência. multiplicação-adição fundida e suporte para número desnormalizado para precisão dupla. oferece arredondamento IEEE completo. Falácia: algoritmos O(n) são difíceis de aumentar a velocidade. a GPU Tesla T10P. Não importa como a GPU é rápida no processamento de dados. de modo que exige muitos ciclos de execução desperdiçados para apanhar dados da memória. a armadilha é que. as demandas do conjunto de trabalho do programa podem ser maiores que qualquer cache. você precisa ter threads suficientes. mas o número de threads por core geralmente tem sido limitado a um pequeno número. Outra forma de dizer isso é que uma GPU executa cada thread lentamente. como matemática com grandes vetores. cada instrução e seus dados precisam estar disponíveis quando for o momento para essa instrução executar. introduzida recentemente. melhorando o desempenho ao atribuir um subconjunto do trabalho a cada um. pelo contrário. Primeiro. o sistema de memória será cada vez mais lento na resposta a cada soli- citação individual. e ligeiramente menor para transferências não DMA. Além disso. e as threads precisam ser bem comportadas em termos de localidade do acesso à memória. . mas apenas uma instrução de qualquer thread de uma vez. em vez de mover os dados para lá e para cá em diferentes etapas de um algoritmo complicado. A desvantagem disso é que múltiplas threads são necessárias para cobrir a latência da memória. A latência da memória é longa. Problemas de exemplo. Há três maneiras de contornar o custo de transferência de dados. tem velocidades de acesso típicas de 8-12GB/segundo para a memória do sis- tema. como a adição em vetor. para a estratégia de trabalho “só usar mais threads” para cobrir a latência. tratando o sistema como uma plataforma de computação heterogênea. A terceira sugestão é usar a CPU e a GPU juntas. Esse modelo é útil para qualquer stream de dados que possa ser processado enquanto eles chegam. as CPUs exigem grandes caches locais para continuar executando sem stalling. Em algum ponto. Ela acompanha a evolução da GPU desde pipelines de função fixa até os processadores gráficos programáveis. Agradecimentos Este apêndice é o trabalho de vários autores sobre NVIDIA. que aparece no site. CUDA está evoluindo rapidamente na direção da funcionalidade plena do C/C + +. incluindo GPUs e CPUs. além de aumentar a largura de banda de thread e memória disponível para os programas. analisa a história das unidades de processamento gráfico (GPUs) em tempo real programáveis desde o início dos anos 80 até hoje.10 Comentários finais As GPUs são processadores maciçamente paralelos e se tornaram bastante utilizados. APIs gráficas e modelos de programação provavelmente se adaptarão às capacidades de computação paralela e modelos CUDA. principalmente aumentando o número de processadores. A arquitetura da GPU continuará a se adaptar aos padrões de uso de gráficos e outros programadores de aplicação. Massimiliano Fatica. As GPUs continuarão a se expandir para incluir mais poder de processamento através de cores de processador adicionais. com perspectivas sobre computação de GPU. O paralelismo da GPU continuará a se expandir segundo a lei de Moore. à medida que diminuíram de preço por duas ordens de grandeza e aumentaram o desempenho também por duas ordens de grandeza. não apenas para gráficos 3D. Somente os modelos de programação paralela que podem se expandir prontamente para centenas de cores de processador e milhares de threads terão sucesso no suporte a GPUs e CPUs manycore. o modelo de programação CUDA usa um estilo SPMD (Single-Program Multiple Data). . acompanhando o modo como os programas CUDA já utilizam funções intrínsecas de textura para realizar pesquisas de textura usando a instrução de textura e unidade de textura da GPU. Os modelos de programação paralela para GPUs estão se tornando mais flexíveis.11   Perspectiva histórica e leitura adicional Esta seção. A. John Montrym. Seu modelo de threading no estilo SPMD é escalável. somente as aplicações que tiverem muitas tarefas paralelas em grande parte independentes serão aceleradas pelas arquiteturas manycore maciçamente paralelas. Impulsionada por essas mudanças nos modelos de programação. os modelos de programação precisam evoluir para incluir a programação de sistemas manycore heterogêneos. computação visual e GPUs escaláveis. Por exemplo. A. sucinto e facilmente aprendido. Além disso. Doug Voorhies. Erik Lindholm. a arquitetura de GPU. Paulius Micikevicius. e é um modelo conveniente. para expressar grandes quantidades de paralelismo. Lars Nyland. está se tornando mais flexível e mais programável. executando um programa com muitas threads paralelas. gráficos unificados e processadores de cálculo. As unidades de função fixa da GPU estão se tornando acessíveis a partir de programas em geral. Essa ampla aplicação foi possibilitada pela evolução de dispositivos gráficos nos processadores programáveis. Stuart Oberman e Vasily Volkov. por sua vez. tanto para gráficos quanto para a computação paralela.11   Perspectiva histórica e leitura adicional A-629 A. Somos gratos às contribuições significativas de Michael Garland. mas também para muitas outras aplicações. O modelo de programação de aplicação gráfica para GPUs normalmente é uma API como DirectX™ ou OpenGL™. Para uma computação de uso geral. Além disso. 1927 .  Whitney v. Microsoft Louis Brandeis. livre expressão. Larus justificar sozinho a supressão da Microsoft Research. Link-editores O receio do insulto sério não pode e o Simulador SPIM James R. B A P Ê N D I C E Montadores. California. Os montador  Um programa montadores oferecem uma representação mais amigável do que os 0s e 1s de um compu.5 Uso da memória  643 B. Os humanos. Além disso.1 ilustra como um programa é montado. Este apêndice descreve o processo pelo qual um programa legível ao ser humano é traduzido para um formato que um computador pode executar.1   Introdução Codificar instruções como números binários é algo natural e eficiente para os computado- res.3 Link-editores  642 B. o assembly permite que os programadores utilizem rótulos para identificar e nomear palavras parti- culares da memória que mantêm instruções ou dados.12 Exercícios 691 B. as macros. Outra ferramenta. As versões UNIX. . referência que exige mais tecas. compilados e montados de forma independente. de modo que as pessoas possam ler e lembrar-se deles. O código em um módulo não pode ser executado quando contém referências não informações de um arquivo externo resolvidas para rótulos em outros arquivos-objeto ou bibliotecas.1 Introdução  631 B.9 SPIM  659 B. Outra faceta são as facilidades de programa- ção que aumentam a clareza de um programa. e locais são uma faceta dessa representação. escritos. um simulador que executa programas MIPS. As pessoas leem e escrevem símbolos (palavras) muito melhor do que longas sequências de dígitos. A Figura B. discutidas na macro  Uma facilidade Seção B. Um programa também pode usar rotinas pré-escritas fornecidas em uma biblioteca de programa. oferece algumas dicas sobre a escrita de programas em assembly e explica como executar esses programas no SPIM.B. definindo novas operações.8 Entrada e saída  658 B. Windows e Mac OS X do simulador SPIM estão disponíveis no site. Nomes simbólicos para operações uma instrução para a versão binária. pois as instruções do computador podem ser representadas de muitas maneiras.2. de combinação e substituição de padrões que oferece Um montador lê um único arquivo-fonte em assembly e produz um arquivo-objeto com um mecanismo simples instruções de máquina e informações de trabalho que ajudam a combinar vários arquivos. como opcodes (códigos de operação) e especificadores de regis- tradores. permitem que um programador estenda o assembly. ocorrem comumente.1. A maioria de instruções utilizada dos programas consiste em vários arquivos – também chamados de módulos – que são com frequência.10 Assembly do MIPS R2000  663 B. Uma ferramenta chamada montador traduz do assembly para instruções binárias.2 Montadores  636 B. O Capítulo 2 mostrou que não precisamos escolher entre números e palavras. Um módulo normal- referência não resolvida Uma mente contém referências a sub-rotinas e dados definidos em outros módulos e em biblio. para estar completa.4 Carga  643 B. porém. O assembly é mais legível do que a linguagem de máquina porque A representação binária utilizada utiliza símbolos no lugar de bits. o que simplifica a escrita e a leitura de programas. Os símbolos no assembly nomeiam padrões de bits que para a comunicação dentro de um sistema computacional.6 Convenção para chamadas de procedimento  645 B. Assembly é a representação simbólica da codificação binária – linguagem de máquina – linguagem de máquina  de um computador. têm muita dificuldade para entender e manipular esses números. e os computadores podem executar os números binários equivalentes.7 Exceções e interrupções  654 B.11 Comentários finais  690 B. para nomear uma sequência objeto em um programa. que traduz uma versão simbólica de tador. Os humanos podem escrever e ler símbolos. Por exemplo. você poderia usar as tabelas de formato de opcode e instrução do Capítulo 2 para traduzir as instruções em um programa simbólico. e não por um rótulo simbólico. Os nomes diretiva do montador Uma que começam com um ponto. de máquina. Nomes seguidos por um sinal de dois-pontos. link-editor  Também chamado chamada link-editor. que dizem ao montador como traduzir um programa.1. combina uma coleção de arquivos-objeto e biblioteca em um arqui- linker. mas ainda é difícil de acompanhar. que combina programas Para ver a vantagem do assembly. pois os locais da memória são indicados por seus endereços.1. em vez de padrões de bits.4 mostra o assembly que rotula endereços de memória com nomes mne- mônicos.1  O processo que produz um arquivo executável. Um programa de sistema vo executável. que um computador pode executar.data e . mas não produzem instruções como traduzir um programa. considere a sequência de figuras mostrada a seguir. que é link-editado a outros arquivos e bibliotecas para um arquivo executável.1. Link-editores e o Simulador SPIM FIGURA B.1. são mas não produz instruções de máquina. No entanto.3. FIGURA B. como str: ou main:. semelhante à Figura B. são diretivas do monta- operação que diz ao montador dor. esse assembly ainda é difícil de acompanhar. pois muitas operações simples são exigidas para realizar tarefas simples e porque a falta de construções de fluxo de controle do assembly oferece poucos palpites sobre a operação do programa. MIPS executa.B-632 Apêndice B  Montadores. sempre começa rótulos que denominam o próximo local da memória. Essa forma de rotina é muito mais fácil de ler. a maioria dos programas em assembly (exceto por uma óbvia falta de comentários). pois as operações e os operandos estão escritos com símbolos. A Figura B. Um montador traduz um arquivo em assembly para um arquivo-objeto.1. Esse programa é tão legível quanto com um ponto. Com esforço considerável. . por exemplo. A maior parte dos programadores prefere ler e escrever dessa forma. em linguagem de máquina montados independentemente e todas contendo uma pequena sub-rotina que calcula e imprime a soma dos quadrados dos resolve todos os rótulos indefinidos inteiros de 0 a 100. .2 mostra a linguagem de máquina que um computador em um arquivo executável. A Figura B.2  Código em linguagem de máquina MIPS para uma rotina que calcula e imprime a soma dos quadrados dos inteiros entre 0 a 100.globl. data indica que elas contêm dados.1 Introdução B-633 FIGURA B.align 2 significa que o próximo item deverá estar em um limite da palavra. o código para a rotina não rotula regis- tradores ou locais de memória. Ao contrário. alto nível em que um programa é fonte. . . nem inclui comentários.globl main declara que main é um símbolo global.1.align n indica que os itens nas linhas seguintes devem ser alinhados em um limite de 2n bytes.1. Entretanto. Em geral. As outras formas do programa foram produzidas por um compilador C e um montador.6). . .1. em vez de construído com desvios. mas sem comentários. FIGURA B. e a saída do compilador é sua linguagem destino. . a rotina em C é a única que escrevemos.3  A mesma rotina escrita em assembly. Finalmente. pois as variáveis possuem nomes mnemônicos e o loop é explícito. B. A linguagem de alto nível é chamada de linguagem.1. escrito originalmente. Um compilador traduz um programa escrito em uma linguagem de alto nível (como C ou Pascal) para um programa equivalente em linguagem-fonte  A linguagem de linguagem de máquina ou assembly. .4  A mesma rotina escrita em assembly com rótulos. o assembly desempenha duas funções (ver Figura B. Na verdade. Logo.text indica que as linhas seguintes contêm instruções.5 é mais curta e mais clara. que deverá ser visível ao código armazenado em outros arquivos.asciiz armazena na memória uma string terminada em nulo. . a rotina em C na Figura B. Os comandos que começam com pontos são diretivas do montador (ver páginas A-34 a A-35). A primeira é como uma linguagem de saída dos compiladores. Hoje. porém. como verificação de tipos e fluxo de controle estruturado. podem tornar os programas assembly mais curtos. em que a maior parte de um programa é escrita em uma linguagem de alto nível e seções fundamentais são escritas em assembly. ou para explorar recursos do hardware que não possuem correspondentes nas linguagens de alto nível. Por exemplo. Embora este apêndice dê destaque ao assembly do MIPS. Quando usar o assembly O motivo principal para programar em assembly. Apesar disso. é chamado de computador embutido. reduzir o tamanho de um programa. como os freios de um carro. como um carro. a programação assembly na maioria das outras máquinas é muito semelhante. Os programas normalmente gastam a maior parte do seu tempo execu- tando uma pequena fração do código-fonte do programa.5  A rotina escrita na linguagem de programação C. Um programador assembly. nem oferecem ao assembly as vantagens das linguagens de alto nível. mas não mudam o processo de montagem de um programa. a maioria dos programadores utiliza uma linguagem de alto nível e raramente ou nunca vê as instruções que um computador executa. As outras instruções e os modos de endereçamento nas máquinas CISC. Esse tipo de computador precisa responder rápida e previsivelmente aos eventos no mundo exterior. Essa função costumava ser a dominante.1. de modo que caiba em menos chips de memória.1. Essa observação é exatamente o princípio da localidade em que as caches se baseiam (veja Seção 5. em vez de outra linguagem de alto nível. Como um compilador introduz incerteza sobre o custo de tempo das operações. 1 milissegundo após um sensor detectar que um pneu está derrapando. como o VAX. por outro lado.6  O assembly é escrito por um programador ou é a saída de um compilador. . o assembly ainda é importante para a escrita de programas em que a velocidade ou o tamanho são fundamentais. FIGURA B. Link-editores e o Simulador SPIM FIGURA B. aproveita os pontos fortes das duas linguagens. no Capítulo 5). possui mais controle sobre as instruções executadas. reduz o custo do computador embutido. Uma técnica híbrida. devido a memórias maiores e compi- ladores melhores. em aplicações embutidas. Além disso. A outra função do assembly é como uma linguagem para a escrita de programas.B-634 Apêndice B  Montadores.1. os programadores podem achar difícil garantir que um programa em linguagem de alto nível responderá dentro de um intervalo de tempo definido – digamos. Um computador incorporado em outro dispositivo. é que a velocidade ou o tamanho de um programa têm extrema importância. imagine um computador que controla um mecanismo qualquer. discutida no Capítulo 1. Entretanto. Desvantagens do assembly O assembly possui muitas desvantagens. Isso significa que os programadores são aproximadamente x vezes mais produtivos em uma linguagem de alto nível. precisam ser criados a partir de desvios e jumps.1. de modo que a única alternativa de um programador é o assembly. Em programas mais complexos. pois o leitor precisa recriar cada construção de nível mais alto a partir de suas partes. essa parte do programa pode se tornar mais rápida com melhores estruturas de dados ou algoritmos. mesmo depois que o computador for substituído por máquinas mais novas.1. Infelizmente.4 possui 31 linhas. mais rápidas e mais econômicas. às vezes. onde x é o fator de expansão do assembly. significa que as arquiteturas se tornam obsoletas. Outra desvantagem é que os programas em assembly são maiores do que os programas equivalentes escritos em uma linguagem de alto nível. a razão entre o assembly e a lin- guagem de alto nível (seu fator de expansão) pode ser muito maior do que o fator de três nesse exemplo. a vantagem de um programador sobre um compilador tornou-se difícil de manter.5 possui 11 linhas de extensão. por exemplo. Outra vantagem importante do assembly está na capacidade de explorar instruções especializadas. os programadores em geral consideram vários procedimentos simultaneamente enquanto escrevem seu código. até mesmo entre os limites dos procedimentos. estudos empíricos mostraram que os programadores escrevem quase o mesmo número de linhas de código por dia em assembly e em linguagens de alto nível. Os idiomas de programação comuns. A rápida evolução dos computadores. Os compiladores costumam ser melhores do que os programadores na produção uniforme de código de máquina de alta qualidade por um programa inteiro. não podem determinar se um loop de programa pode ser substituído por uma única instrução. Um programa em assembly permanece firmemente ligado à sua arquitetura original. programas maiores são mais difíceis de ler e entender e contêm mais bugs. e cada instância de uma instrução pode ser ligeiramente diferente. os programadores podem fazer um programa ser executado com mais rapidez. Hoje. Computadores muito antigos ou especializados não possuem um compilador. Os compiladores compilam cada procedimento isoladamente e precisam seguir convenções estritas governando o uso dos registradores nos limites de procedimento. Para aumentar o problema. que argumentam fortemente contra seu uso generalizado. Por exemplo. O último motivo para usar assembly é que não existe uma linguagem de alto nível dis- ponível em um computador específico. Retendo valores comumente usados nos registradores. os programadores entendem os algoritmos e o comportamento de um pro- grama em um nível mais profundo do que um compilador e podem investir esforço e engenhosidade consideráveis melhorando pequenas seções do programa. veja a Figura B. na maior parte dos casos. No entanto. Os compiladores. instruções de cópia de string ou combinação de padrões. Os programas resultantes são difíceis de ler. o programa em C da Figura B.4 e responda a estas perguntas: que tipo de loop é utilizado? Quais são seus limites inferior e superior? . B. pois as técnicas de compilação melhoram e os pipelines das máquinas aumentaram de complexidade (Capítulo 4). Por exemplo. o programador que escreveu o loop pode substituí-lo facilmente por uma única instrução. Em muitos casos. Em particular. melhorias de desempenho significativas só são obtidas com a recodificação de uma parte crítica de um programa em assembly. Talvez sua principal desvantagem seja que os programas escritos em assembly são inerentemente específicos à máquina e precisam ser reescritos para serem executados em outra arquitetura de computador.1 Introdução B-635 O perfil do programa mede onde um programa gasta seu tempo e pode localizar as partes de tempo crítico de um programa. Contudo. enquanto o programa em assembly da Figura B.1. O assembly realça esse problema. devido à sua completa falta de es- trutura. Essa melhoria não é necessariamente uma indicação de que o compilador da linguagem de alto nível falhou. como instruções if-then e loops. Um rótulo que se tos ou dados em outros arquivos. O processo de tradução possui duas etapas principais. nomes ge- está definido. pois rótulo local  Um rótulo que se são referenciados a partir de muitos arquivos em um programa. algumas aplicações embutidas são escritas em uma linguagem de alto nível. Todavia. que é a rotina da biblioteca que imprime valo- res. A segunda etapa é traduzir cada instrução assembly combinando os equivalentes numéricos dos opcodes. como resolver endereços e codificar instruções como números binários. funções estáticas em C. Ela também contém dois rótulos locais – loop e str – visíveis apenas dentro do seu arquivo em assembly. Esses compiladores executam muito mais rapidamente do que aqueles que invocam um montador como parte da compilação.B-636 Apêndice B  Montadores. rótulo externo  Também chamado Um arquivo-objeto normalmente não pode ser executado porque referencia procedimen- rótulo global. Rótulos locais e globais Considere o programa na Figura B. Na verdade. usado dentro do arquivo em que que só podem ser chamadas por outras funções no mesmo arquivo.4 poderiam ser referenciados a partir de outro arquivo? RESPOSTA Somente os rótulos globais são visíveis fora de um arquivo. de modo que o único rótulo que poderia ser referenciado por outro arquivo é main. em vez de contar com um montador. A sub-rotina possui um rótulo externo (global) EXEMPLO main. os rótulos são locais por padrão e precisam ser declarados como globais explicitamente. Na diferentes daquele em que está definido. especificadores de registradores e rótulos em uma instrução válida. o montador produz um arquivo de saída.1. Como vemos na Figura B. referenciado a partir de arquivos Um rótulo é local se o objeto só puder ser usado dentro do arquivo em que está definido. dados e informações de manutenção. essas considerações levaram o Departamento de Defesa. Isso aumenta bastante o custo da escrita de um programa em assembly e torna muito difícil verificar a exatidão desse tipo de programa. Finalmente.4. B.1.2   Montadores Um montador traduz um arquivo de instruções em assembly para um arquivo de instruções de máquina binárias e dados binários. Rótulos locais ocultam refere a um objeto que só pode ser nomes que não devem ser visíveis a outros módulos – por exemplo. a rotina também contém uma referência não resolvida a um rótulo externo printf. rados pelo compilador – por exemplo. Além disso. que precisam ser muito confiáveis. Os programas em assembly são maiores e mais difíceis de escrever e ler do que os programas em linguagem de alto nível. um compilador que gera linguagem de máquina precisa realizar muitas tarefas que um montador normalmente trata. uma nova linguagem de alto nível para a escrita de sistemas embutidos. que contém as instruções de máquina. chamado de arquivo-objeto. Link-editores e o Simulador SPIM Detalhamento:  Os compiladores podem produzir linguagem de máquina diretamente. A escolha é entre velocidade de compilação e simplicidade do compilador. de modo que o compilador não precisa produzir nomes exclusivos em cada arquivo. maior parte dos montadores.1. A primeira etapa é encontrar locais de memória com rótulos. Quais rótulos na Figura B. Detalhamento:  Apesar dessas considerações.1. de modo que o relacionamento entre os nomes simbólicos e endereços é conhecido quando as instruções são traduzidas. . Um rótulo é externo (também chamado global) se o refere a um objeto que pode ser objeto rotulado puder ser referenciado a partir de arquivos diferentes de onde está definido. As sub-rotinas e variáveis globais exigem rótulos externos. um nome para a instrução no início de um loop – são locais. a desenvolver a Ada. Muitas dessas aplicações são programas grandes e complexos. que paga por muitos sistemas embutidos complexos. como essa.1.2 Montadores B-637 Como o montador processa cada arquivo em um programa individual e isoladamente. Acompa- das palavras de memória que nhando os tamanhos das instruções. referência à frente  Um rótulo cia à frente. uma vírgula e o símbolo loop. O montador depende de outra ferramenta. a linha ble $t0. O montador auxilia o link-editor.5 do Capítulo 2. força um montador a traduzir um programa em duas etapas: usado antes de ser definido. Java e C. O montador novamente examina cada linha no arquivo. os programas precisam implementar todo o fluxo de controle com go tos. até mesmo os rótulos locais apresentam um desafio interessante a um montador. números e caracteres de pontuação individuais. como aquelas no MIPS. Ao contrário dos nomes na maioria das linguagens de alto nível. são palavras. ele não sabe onde a palavra rotulada com str está locali- zada ou mesmo se str rotula uma instrução ou um dado. oferecendo listas de rótulos e referências não resolvidas. No entanto. resolvendo os rótulos externos. Além disso. na Figura B. como BASIC. Por outro lado. Por exemplo. No exemplo. exigem apenas um exame superficial. Um montador não reclama sobre referências não resolvidas porque o rótulo correspondente provavelmente estará definido em outro arquivo. trução entrará.4. adição de inteiro ou ponto flutuante) a um valor. O montador utiliza as informações na tabela de símbolos durante uma segunda passada pelo arquivo. que.100. A primeira passada de um montador lê cada linha de um arquivo em assembly e a divide em suas partes componentes. As instruções e as palavras de dados que referenciam um símbolo externo definido em outro arquivo não podem ser completamente montadas (elas não estão resolvidas) porque o endereço do símbolo não está na tabela de símbolos. calcula quantas palavras de memória ocupará a instrução na linha atual. um progra- mador precisa aplicar as operações apropriadas (por exemplo. O monta- dor realiza um cálculo semelhante para estabelecer o espaço exigido para instruções de dados. os rótulos em assembly podem ser usados antes de serem definidos. é que o assembly oferece apenas alguns tipos simples de dados e fluxo de controle. A possibilidade de uma referên. o montador pode determinar onde a próxima ins. Quando o montador atinge o final de um arquivo assembly. O montador. na realidade. um montador precisa examiná-la em detalhes. o especificador de registrador $t0 . para combinar uma coleção de arquivos-objeto e bibliotecas em um arquivo executável. o montador registra em sua tabela de símbolos tabela de símbolos  Uma tabela o nome do rótulo e o endereço da palavra de memória que a instrução ocupa. a tabela de símbolos registra o local de cada rótulo definido no arquivo. Essas partes. B. ele só sabe os endereços dos rótulos locais. que faz a correspondência entre os nomes dos rótulos e os endereços então.loop contém seis lexemas: o opcode ble . as instruções ocupam. instruções de tamanho fixo. Sua principal diferença das lin- Colocando guagens de alto nível. Os dois fatores tornam a pro- gramação em assembly para qualquer máquina – MIPS ou 80x86 – mais difícil e passível de erro do que a escrita em uma linguagem de alto nível. Se a linha contém uma instrução. Os programas em assembly não em perspectiva especificam o tipo de valor mantido em uma variável. No exemplo. O assembly é uma linguagem de programação. produz o código de máquina. em assembly. uma vírgula. o número 100. Para calcular o tamanho de uma instrução de tamanho variável. . o montador combina as representações binárias de seu opcode e operandos (especificadores de registradores ou endereço de memória) em uma instrução válida. primeiro encontre todos os rótulos e depois produza as instruções. quando o montador vê a instrução la. o ró- tulo str é usado pela instrução la antes de ser definido. Se uma linha começa com um rótulo. O processo é semelhante ao usado na Seção 2. como aquelas no VAX. chamadas lexemas. Em vez disso. o link-editor. Quando o montador vê inicialmente um rótulo não resolvido em uma instrução de desvio. endereço absoluto  O endereço j A tabela de símbolos associa endereços a rótulos externos no arquivo de origem e lista real na memória de uma variável referências não resolvidas. Essas informações de relocação são necessárias porque o montador não sabe quais locais da memória um procedimento ou parte de dados ocupará depois de ser link-editado com o restante do programa. Os procedimentos e dados de um arquivo são armazenados em uma parte contígua da memória.B-638 Apêndice B  Montadores.2. O montador volta e corrige sua representação binária para binária (possivelmente incompleta) de cada instrução em uma passada incorporar o endereço do rótulo.2. usados pelo programa vidas a rótulos em outros arquivos. Esse requisito pode limitar o tamanho dos programas que podem ser montados. O montador também passa algumas entradas da tabela de símbolos para o link-editor. O processo é complicado por máquinas com diversos tipos de desvios que se espalham por di- ferentes intervalos de instruções. . Formato do arquivo-objeto Os montadores produzem arquivos-objeto. além de informações adicionais para ajudar a link-editar partes de um programa. de modo que um depurador possa descobrir quais endereços de instrução correspondem às linhas em um arquivo de origem e imprimir as estruturas de dados em formato legível. ele precisa usar o maior desvio possível ou arriscar ter de voltar e reajustar muitas instruções para criar espaço para um desvio maior. Em sua passada pelo arquivo. Em particular. Essas referências precisam mudar se partes do pro- e palavras de dados que dependem grama forem movidas na memória. o montador consulta essa tabela para encontrar todas as instruções que contêm o montador tem uma representação uma referência à frente ao rótulo. ching. resolvidas. ou rotina. segmento de dados  O segmento de um objeto ou arquivo executável j O segmento de dados contém uma representação binária dos dados no arquivo de do UNIX que contém uma origem. de modo que as instruções possam sofrer backpat- indefinidos.1): j O cabeçalho do arquivo-objeto descreve o tamanho e a posição das outras partes do segmento de texto  O segmento arquivo. Essas rotinas podem ser não executáveis devido a referências não no arquivo de origem. FIGURA B. Se a instrução referencia um rótulo ainda para instruções de máquina. Um montador do UNIX produz um arquivo-objeto com seis seções distintas. informações de relocação  j As informações de relocação identificam instruções e palavras de dados que depen- O segmento de um arquivo-objeto do UNIX que identifica instruções dem de endereços absolutos. mas o montador não sabe onde essa memória es- tará localizada. Contudo. em que não definido. o montador precisa registrar quais símbolos externos são definidos em um arquivo e quais referências não resolvidas ocorrem em um arquivo. Um arquivo-objeto no UNIX contém seis seções distintas (veja Figura B. esse processo em duas etapas pode ser feito em uma passada pelo arquivo assembly com uma técnica conhecida backpatching  Um método como backpatching. Link-editores e o Simulador SPIM Detalhamento:  Se a velocidade de um montador for importante. de um arquivo-objeto do UNIX que contém o código em linguagem j O segmento de texto contém o código em linguagem de máquina para rotinas no de máquina para as rotinas arquivo de origem. O montador produz um arquivo-objeto que contém uma representação binária do pro- grama e dos dados.1  Arquivo-objeto. isso exige que um montador mantenha uma representação bi- para preencher rótulos previamente nária inteira de um programa na memória. o montador monta uma representação bi- para traduzir do assembly nária (possivelmente incompleta) de cada instrução. Os dados também podem estar incompletos devido a referências não resol- representação binária dos dados inicializados. de endereços absolutos. j As informações de depuração contêm uma descrição concisa da maneira como o pro- grama foi compilado. O backpatching agiliza o assembly porque o montador só lê por um programa e depois retorna sua entrada uma vez. 2 Montadores B-639 Detalhamento:  Por conveniência.15. que um montador traduz para binário. Um montador pode traduzir caracteres para sua representação binária muito mais rapidamente e com mais precisão do que um ser humano. que contém uma entrada descrevendo cada instrução ou palavra de dados no arquivo que referencia um endereço absoluto. No MIPS.10. somente as instruções call. Diretiva de string Defina a sequência de bytes produzida por esta diretiva: EXEMPLO RESPOSTA .4. os montadores consideram que cada arquivo começa no mesmo endereço (por exemplo.1. O montador produz informações de relocação. Por exemplo. a diretiva armazena caracteres da string na memória. e não como números binários. não precisam ser relocadas. load e store da sub-rotina referenciam endereços absolutos. B. Facilidades adicionais Os montadores oferecem diversos recursos convenientes que ajudam a tornar os programas em assembly mais curtos e mais fáceis de escrever.asciiz é mais fácil de ler porque representa caracteres como letras. descreve a codificação ASCII para os caracteres): A diretiva . como desvios. Outras diretivas de layout são descritas na Seção B. as diretivas de layout de dados permitem que um programador descreva os dados de uma maneira mais concisa e natural do que sua representação binária. Compare essa linha com a alternativa de escrever cada caractere como seu valor ASCII (a Figura 2. As diretivas de layout de dados especificam os dados em um formato legível aos seres humanos. mas não mudam fundamentalmente o assembly. Na Figura B. no Capítulo 2. posição 0) com a expectativa de que o link-editor reposicione o código e os dados quando receberem locais na memória. As instruções que usam endereçamento relativo ao PC. No entanto. e a diretiva . suponha que um programador precise imprimir muitos números. elas não causam uma chamada e um retorno de sub-rotina quando o programa é executado. As macros. Em vez de digitar repetidamente as mesmas instruções toda vez que forem usadas. diferente das sub-rotinas. Entretanto. que oferece um mecanis- mo simples para nomear uma sequência de instruções usada com frequência. Link-editores e o Simulador SPIM As macros são uma facilidade de combinação e troca de padrão. como as sub-rotinas. print_int.text diz ao montador para armazenar as instruções em seu segmento de texto. um programador chama a macro e o montador substitui a chamada da macro pela sequência de instruções correspondente. escrito sem macros. Uma alternativa é introduzir uma macro. Um programador poderia imprimir o inteiro no registrador $7 com as seguintes instruções: A diretiva . Depois dessa troca. A rotina de biblioteca printf aceita uma string de formato e um ou mais valores para imprimir como seus argumentos. pois uma chamada de macro é substituída pelo corpo da macro quando o programa é montado. permitem que um programador crie e nomeie uma nova abstração para uma operação comum. a impressão de muitos números dessa maneira é tediosa e produz um programa extenso.data diz ao montador para armazenar a string no segmento de dados do programa. Macros EXEMPLO Como um exemplo. a montagem resultante é indistinguível do pro- grama equivalente.B-640 Apêndice B  Montadores. para imprimir um inteiro: . difícil de ser entendido. Em vez de manter esses programas em arquivos separados – o que complica bastante o reparo de bugs no código comum –. por que os montadores para sis- temas UNIX nunca ou quase nunca as oferecem? Um motivo é que a maioria dos programadores nesses sistemas escreve programas em linguagens de alto nível. um processador de macro de uso geral – podem oferecer macros e montagem condicional para programas em assembly. que são instruções fornecidas Interface por um montador mas não implementadas no hardware. Se as macros e a montagem condicional são tão úteis.7. parâmetro formal Uma Quando a macro é expandida. Por exemplo. Muitas pseudoinstruções também poderiam ser simuladas com macros. ou m4. pois pode usar um registrador dedicado ($at) e é capaz de otimizar o código gerado. o argumento de uma chamada é substituído pelo pa. a Seção 2. os programadores normalmente mesclam as versões em um único arquivo. variável que é o argumento de um procedimento ou macro. o pré-processador C. des. o quando a macro é expandida. Depois. de modo que a macro expande para Para o que a chamada print_int($a0) se expande? RESPOSTA Esse exemplo ilustra uma desvantagem das macros. . Esse recurso é particularmente útil quando várias versões de um programa diferem por um pequeno valor. o argumento é $t0. que acham mais conveniente repetir o código do que definir macros. Um programador que utiliza essa macro precisa estar ciente de que print_int utiliza o registrador $a0 e por isso não pode imprimir corretamente o valor nesse registrador. como C. print_int($t0).2 Montadores B-641 A macro possui um parâmetro formal. A maior parte do código assembly é produzida por compiladores. o que permite que um programador inclua ou exclua grupos de instruções quando um programa é montado. $arg. râmetro formal em todo o corpo da macro. no Capítulo 2. o montador MIPS torna a programação em as- sembly mais fácil sem complicar o hardware. mas o montador MIPS pode gerar um código melhor para essas ins- truções. O Capítulo 2 contém muitos exem- plos de como o montador MIPS sintetiza pseudoinstruções e modos de endereçamento do hardware/ conjunto de instruções de hardware do MIPS. digamos. Estendendo o conjunto de instruções. de modo que a macro se expande para o código Em uma segunda chamada em print_int. o montador substitui a chamada substituída por esse argumento pelo corpo recém-expandido da macro. O código particular a uma versão é montado condicionalmente. montam condicionalmente partes de código. Outro motivo é que outras ferramentas no UNIX – como cpp. que nomeia o argumento da macro. Alguns montadores também implementam pseudoinstruções. Detalhamento:  Os montadores. B. software creve como o montador sintetiza a instrução blt a partir de duas outras instruções: slt e bne. Na primeira chamada em print_int. de modo que possa ser excluído quando outras versões do pro- grama forem montadas. é importante pontuar. argumento é $7. 3. As referências não combinadas significam que um símbolo foi usado. Referências não resolvidas nesse estágio do processo de link-edição não necessariamente significam que um programador cometeu um erro. A primeira tarefa de um link-editor é garantir que um programa não contenha rótulos indefinidos. a compilação separada necessita da etapa adicional de link-edição para combinar os arquivos-objeto de módulos separados e consertar suas referências não resolvidas. Ele realiza três tarefas: j Pesquisa as bibliotecas de programa para encontrar rotinas de biblioteca usadas pelo programa.1  O link-editor pesquisa uma coleção de arquivos-objeto e bibliotecas de programa para encontrar rotinas usadas em um programa. o link-editor pesquisa as bibliotecas de programa do sistema para encontrar sub-rotinas e estruturas de dados predefinidas que FIGURA B. Link-editores e o Simulador SPIM B. Depois de combinar os símbolos no programa. O link-editor combina os símbolos externos e as referências não resolvidas a partir dos arquivos de um programa.3   Link-editores compilação separada Dividir A compilação separada permite que um programa seja dividido em partes que são armaze- um programa em muitos arquivos. arquivo pode ser compilado e montado independente de outros arquivos.3. j Determina os locais da memória que o código de cada módulo ocupará e realoca suas instruções ajustando referências absolutas. mas não definido em qualquer lugar do programa. Cada arquivo contém uma coleção logicamente relacionada cada qual podendo ser compilado de sub-rotinas e estruturas de dados que formam um módulo de um programa maior. .1). Um sem conhecimento do que está nos outros arquivos. A ferramenta que mescla esses arquivos é o link-editor (veja Figura B. de modo que as mudanças em um módulo não exigem a recompilação do programa inteiro. Um símbolo externo em um arquivo resolve uma referência de outro arquivo se ambos se referirem a um rótulo com o mesmo nome. O programa poderia ter referenciado uma rotina de biblioteca cujo código não estava nos arquivos-objeto passados ao link- editor.B-642 Apêndice B  Montadores. j Resolve referências entre os arquivos. nadas em arquivos diferentes. combina-as em um único arquivo executável e resolve as referências entre as rotinas em arquivos diferentes. Conforme já discutimos. Copia argumentos passados ao programa para a pilha. alocam e liberam memória.5).4   Carga Um programa que link-edita sem um erro pode ser executado. 5. e realizam operações numéricas. todas as referências absolutas precisam ser relocadas para refletir seu verdadeiro local. Esse espaço de endere- çamento é grande o suficiente para manter os segmentos de texto e de dados. 2. Copia instruções e dados do arquivo executável para o novo espaço de endereçamento. Se todas as referências externas forem resolvidas. O link-editor produz um arquivo executável que pode ser executado em um computador. junto com um segmento de pilha (veja a Seção B.5). Um programa que referencia um símbolo não resolvido que não está em qualquer biblioteca é errôneo e não pode ser link-editado. Para iniciar um programa. 4. B.5  Uso da memória B-643 o programa referencia. Lê o cabeçalho do arquivo executável para determinar o tamanho dos segmentos de texto e de dados. Quando o programa usa uma rotina de biblioteca. Essa nova rotina. pode depender de outras rotinas de biblioteca. Cria um novo espaço de endereçamento para o programa. Como o link-editor possui informações de relocação que identificam todas as referências relocáveis. a maioria dos registradores é apagada. a rotina de partida termina o programa com a chamada do sistema exit. Inicializa os registradores da máquina. o programa reside em um arquivo no armazenamento secundário. 6. que copia os argumentos do programa da pilha para os registradores e chama a rotina main do programa. Essas seções descrevem um conjunto de convenções seguido em muitos sistemas MIPS. 3. o sistema operacional realiza as seguintes etapas: 1. Em geral. mas o stack pointer precisa receber o endereço do primeiro local da pilha livre (veja a Seção B. Essas seções tratavam principalmente de como os pro- gramadores assembly utilizam o hardware do MIPS. Normalmente.5  Uso da memória As próximas seções elaboram a descrição da arquitetura MIPS apresentada anteriormente no livro. Se a rotina main retornar. Antes de ser executado. o link-editor em seguida determina os locais da memória que cada módulo ocupará. exceto que não contém referências não resolvidas ou informações de relocação. Desvia para a rotina de partida. Outras bibliotecas contêm rotinas para acessar bancos de dados ou manipular janelas de terminal. Quando o link-editor coloca um módulo na me- mória. o hardware não . por sua vez. de modo que o link-editor continua a buscar outras rotinas de biblioteca até que nenhuma referência externa esteja não resolvida ou até que uma rotina não possa ser encontrada. o montador não poderia saber onde as instruções ou os dados de um módulo seriam colocados em relação a outros módulos. As bibliotecas básicas contêm rotinas que leem e escrevem dados. B. ele pode eficientemente localizar e remendar essas referências. Os capítulos anteriores focalizaram principalmente o hardware e seu relaciona- mento com o software de baixo nível. como um disco. o kernel do sistema operacional traz o programa para a memória e inicia sua execução. Em sistemas UNIX. B. Em sua maior parte. Como os arquivos foram montados isolada- mente. esse arquivo tem o mesmo formato de um arquivo-objeto. o link-editor extrai o código da rotina da biblioteca e o incorpora ao segmento de texto do programa. O link-editor atribui ob- jetos estáticos a locais no segmento de dados e resolve referências a esses objetos.1). no Capítulo 2). 0x800 é 8000hexa ou 32. exemplo. Interface Como o segmento de dados começa muito acima do programa. as instruções load e store não podem referenciar diretamente os objetos de dados com seus hardware/ campos de offset de 16 bits (veja Seção 2. são necessárias duas instruções: (O 0x antes de um número significa que ele é um valor hexadecimal. Por exemplo. Link-editores e o Simulador SPIM impõe essas convenções.5. acima do segmento de texto. Em vez disso. pois podem ser referencia- das a qualquer momento durante a execução de um programa. de modo que as instruções load e store podem usar seus campos de 16 bits com sinal para acessar os primeiros 64KB do segmento de dados estático. os sistemas MIPS normalmente dedicam um registrador ($gp) como um ponteiro global para o segmento de dados es- tático. as variáveis globais são alocadas estaticamente. um ponteiro global torna os locais de endereçamento entre 10000000hexa- 10010000hexa mais rápidos do que outros locais do heap. é o segmento de dados.B-644 Apêndice B  Montadores. próxima do início do espaço de endereçamento (começando no endereço 400000hexa). pois essas variáveis possuem locais fixos e se ajustam melhor do que outros dados globais.768dec. Os sistemas baseados em processadores MIPS normalmente dividem a memória em três partes (veja Figura B. FIGURA B. Por exemplo. dividido ainda da memória que contém dados mais em duas partes. no endereço 10000000hexa.) Para evitar repetir a instrução lui em cada load e store. dados estáticos  A parte A segunda parte. Com esse ponteiro global. em C. O compilador MIPS normal- mente armazena variáveis globais nessa área. . Os dados estáticos (começando no endereço 10000000hexa) contêm cujo tamanho é conhecido pelo objetos cujo tamanho é conhecido pelo compilador e cujo tempo de vida – o intervalo compilador e cujo tempo de vida durante o qual um programa pode acessá-los – é a execução inteira do programa.5. como arrays. Por é a execução inteira do programa. Esse registrador contém o endereço 10008000hexa. de modo que o software escrito por diferentes pessoas possa atuar junto e fazer uso eficaz do hardware MIPS.5.1  Layout da memória. que mantém as instruções do programa. é o segmento de texto. A primeira parte. podemos reescrever o exemplo como uma única instrução: Naturalmente. para carregar a software palavra no segmento de dados no endereço 10010020hexa para o registrador $v0. elas representam um acordo entre os programadores para seguirem o mesmo conjunto de regras. um compilador precisa saber quais registradores pode usar e quais são reserva- dos para outros procedimentos. são alocados pelo programa enquanto ele é executado. Para compilar um procedimento em particular. Como o dos registradores Também nome sugere.6  Convenção para chamadas de procedimento As convenções que controlam o uso dos registradores são necessárias quando os procedimen- tos em um programa são compilados separadamente. da memória usada por o tamanho máximo da pilha de um programa não é conhecido antecipadamente. reside no topo do espaço de ende. em vez chamada convenção para chamadas de procedimento.8. o segmento de pilha do programa. $k0 (26) e $k1 (27) são reservados para o montador e o sis- tema operacional e não devem ser usados por programas do usuário ou compiladores. registrador salvo pelo callee Um têm valores de longa duração os quais devem ser preservados entre as chamadas. O compilador nativo do MIPS utiliza uma convenção mais complexa. A instrução jal escreve no registrador $ra (31) o endereço de retorno de uma chamada de procedimento. uma chamada de procedimento. Assim como os dados dinâmicos. de regras impostas pelo hardware. que controla o uso dos registradores A convenção para chamadas descrita nesta seção é aquela utilizada pelo compilador gcc. que faz com que o sistema operacional acrescente mais páginas ao espaço de endereçamento virtual do programa (veja Seção 5. segmento de pilha  A parte reçamento virtual (começando no endereço 7fffffffhexa). no Capítulo 5) imediatamente acima do segmento de dados dinâmico. convenção para uso ções para uso dos registradores ou convenções para chamadas de procedimento. Conforme indica a seta para cima na figura. . a maioria dos compiladores e programadores Um protocolo de software tenta seguir essas convenções estritamente. Como um compilador não pode prever quanta memória um programa alocará. pois sua violação causa bugs traiçoeiros. registrador salvo pela rotina sendo chamada. Contudo. 3) são usados para retornar valores das funções. j Os registradores $a0—$a3 (4-7) são usados para passar os quatro primeiros argu- mentos às rotinas (os argumentos restantes são passados na pilha). O regis- trador $0 contém o valor fixo 0. um programa para manter frames de chamada de procedimento. j Os registradores $s0—$s7 (16-23) são registradores salvos pelo callee. que man. 24. j Os registradores $t0 —$t9 (8-15.6  Convenção para chamadas de procedimento B-645 Imediatamente acima dos dados estáticos estão os dados dinâmicos. No entanto. Esses dados.4. e eles podem crescer para usar o espaço de endereços inteiro de um programa. que aponta para o último local na pilha. Essa divisão de três partes da memória não é a única possível. convenções seguidas pelo software. o sistema operacional expande a área de dados dinâmica para atender à demanda. por procedimentos. em direção ao segmento de dados. As regras para usar os registradores são chamadas de conven. em sua maior parte. B. a rotina de biblioteca malloc localiza e retorna um novo bloco de memória. que é ligeiramente mais rápida. Esses dois regis- tradores são explicados na próxima seção. essas regras são. À me. dida que o programa coloca valores na pilha. O registrador $fp (30) é o frame pointer. numerados de 0 a 31. Os registradores $v0 e $v1 (2. ela possui duas características importantes: os dois segmentos dinamicamente expansíveis são bastante distantes um do outro. A CPU do MIPS contém 32 registradores de uso geral. j O registrador $sp (29) é o stack pointer. como seu nome sugere. no Capítulo 2). Nos programas C. registrador salvo pelo caller Um usados para manter quantidades temporárias que não precisam ser preservadas registrador salvo pela rotina que faz entre as chamadas (veja Seção 2. 25) são registradores salvos pelo caller. B. A terceira parte. malloc expande a área dinâmica com a chamada do sistema sbrk. o sistema operacional expande o segmento de pilha para baixo. j Os registradores $at (1). j O registrador $gp (28) é um ponteiro global que aponta para o meio de um bloco de 64K de memória no segmento de dados estático. os programadores frame de chamada de procedimento  Um bloco assembly precisam implementar explicitamente cada chamada e retorno de procedimento. Essa memória é usada para di- a um procedimento versas finalidades: como argumentos.6.B-646 Apêndice B  Montadores. Contudo. de memória usado para manter A maior parte da manutenção associada a uma chamada gira em torno de um bloco de valores passados memória chamado frame de chamada de procedimento. Os programadores que escrevem em uma linguagem de alto nível (como C ou Pascal) nunca veem os detalhes de como um procedimento chama outro. pois o compilador cuida dessa manutenção de baixo nível. . usaremos os nomes em vez de números de registrador. Chamadas de procedimento Esta seção descreve as etapas que ocorrem quando um procedimento (caller) invoca outro procedimento (callee).1  Registradores do MIPS e convenção de uso. $sp para o stack pointer – refletem os usos intencionados na convenção de chamada de procedi- mento. pode modificar mas que o caller j Para salvar registradores que um procedimento pode modificar. j Para oferecer espaço para variáveis locais a um procedimento. locais a um procedimento. mas que o caller não não deseja que sejam alterados.1 lista os registradores e descreve seus usos intencionados. e fornecer espaço para variáveis deseja que sejam alterados. a fim de salvar registradores que um procedimento j Para manter valores passados a um procedimento como argumentos. FIGURA B. Ao descrever essa convenção. Link-editores e o Simulador SPIM As abreviações e os nomes de duas letras para esses registradores – por exemplo.6. A Figura B. ela precisa realizar as seguintes etapas para configurar seu frame de pilha: 1. O stack pointer ($sp) aponta para a última palavra do frame. que desvia para a primeira instrução do callee e salva o endereço de retorno no registrador $ra. A Figura B. Salvar os registradores salvos pelo callee no frame. que aponta para a última palavra do frame. e o stack pointer ($sp). Salvar registradores salvos pelo caller.2  Layout de um frame de pilha. 3. o caller coloca os argumentos da chamada de procedimento em locais padrões e invoca o callee para fazer o seguinte: 1. 2. primeiro a sair (LIFO – Last-In. Um callee precisa salvar os valores desses registradores ($s0—$s7. Essa convenção entra em ação em três pontos durante uma chamada de procedimento: imediatamente antes de o caller invocar o callee. As etapas a seguir descrevem a convenção de chamada utilizada na maioria das máquinas MIPS. as chamadas e retornos de procedimento seguem uma ordem estrita do tipo último a entrar. O frame pointer ($fp) aponta para a primeira palavra do frame de pilha do procedimento em execução. $fp e $ra) antes de alterá-los. motivo pelo qual esses blocos de memória às vezes são chamados frames de pilha. ele deverá salvar seu valor antes da chamada. Executar uma instrução jal (veja Seção 2.6. Antes que uma rotina chamada comece a executar. Alocar memória para o frame.2 mostra um frame de pilha típico. 2. de modo que o quinto argumento é o primeiro armazenado na pilha. um argumento no frame de pilha pode ser lido para o registrador $v0 com a instrução Um frame de pilha pode ser construído de muitas maneiras diferentes. O frame consiste na memória entre o frame pointer ($fp). pois o caller espera . subtraindo o tamanho do frame do stack pointer. First-Out). Por exemplo. Na maioria das linguagens de programação. Os quatro primeiros argumentos são passados em registradores.8 do Capítulo 2). O procedimento chamado pode usar esses registradores ($a0—$a3 e $t0—$t9) sem primeiro salvar seu valor. Se o caller es- pera utilizar um desses registradores após uma chamada. o caller e o callee precisam combinar a sequência de etapas.6  Convenção para chamadas de procedimento B-647 FIGURA B. Na primeira parte. Quaisquer argumentos restantes são colocados na pilha e aparecem no início do frame de pilha do procedimento chamado. Passar argumentos. Por convenção. porém. assim que o callee começa a executar e imediatamente antes de o callee retornar ao caller. que aponta para a primeira palavra do frame. O procedimento que está executando utiliza o frame pointer para acessar rapidamente os valores em seu frame de pilha. B. de modo que o frame pointer aponta para cima do stack pointer. de modo que essa memória pode ser alocada e liberada como uma pilha. A pilha cresce para baixo a partir dos endereços de memória mais altos. os quatro primeiros argumentos são passados nos registradores $a0—$a3.6. 3. Retorne desviando para o endereço no registrador $ra. 2. o registrador $ra só precisa ser salvo se o callee fizer uma chamada.B-648 Apêndice B  Montadores. Durante uma cha- mada. em arquiteturas load-store. Exemplo de chamada de procedimento Como exemplo. o caller não pode usar esses registradores para valores temporários de curta duração. hardware/ Os registradores salvos pelo caller são usados para manter valores de longa duração. como MIPS. o callee retorna ao caller executando as seguintes etapas: 1. procedimentos Detalhamento:  Uma linguagem de programação que não permite procedimentos recursivos – recursivos  Procedimentos que procedimentos que chamam a si mesmos direta ou indiretamente. os registradores salvos pelo callee são usados para manter quantidades de curta duração. que são utilizados. Finalmente. Interface A convenção de uso dos registradores do MIPS oferece registradores salvos pelo caller e pelo callee. que não persistem entre as chamadas. o indiretamente através de uma frame de cada procedimento pode ser alocado estaticamente. 3. um procedimento pode estar ativa ao mesmo tempo. Link-editores e o Simulador SPIM encontrar esses registradores inalterados após a chamada. coloque o valor retornado no regis- trador $v0. Além disso. Esses registradores só são salvos durante uma chama- da de procedimento se o caller espera utilizar o registrador. Restaure todos os registradores salvos pelo callee que foram salvos na entrada do procedimento. Todavia. O registrador $fp é salvo para cada procedimento que aloca um novo frame de pilha. Se o callee for uma função que retorna um valor. Os outros registradores salvos pelo callee. pois somente uma invocação de cadeia de chamadas. Por outro lado. como software variáveis de um programa do usuário. também precisam ser salvos. Remova o frame de pilha somando o tamanho do frame a $sp. a recursão é uma técnica de programação valiosa. As versões mais antigas de Fortran proibiam a recursão porque frames alocados estaticamente produziam código mais rápido em algumas máquinas mais antigas. que permite que uma única instrução load ou store acesse valores no frame. considere a rotina em C . No entanto. Em uma linguagem não recursiva. 4. os frames de pilha podem ser muito rápidos porque o registrador frame pointer aponta diretamente para o frame de pilha ativo. como valores imediatos em um cálculo de endereço. por meio de uma cadeia de chamam a si mesmos direta ou chamadas – não precisa alocar frames em uma pilha. Estabelecer o frame pointer somando o tamanho do frame de pilha menos 4 a $sp e armazenando a soma no registrador $fp. pois os dois tipos de registradores são vantajosos em circunstâncias diferentes. . seu frame de pilha precisa ter duas palavras a mais (lembre-se de que o stack pointer é mantido alinhado em um limite de double palavra). a rotina main cria seu frame de pilha e salva os dois registradores salvos pelo callee que serão modificados: $fp e $ra. depois de imprimir o fatorial. Primeiro. Esse frame mínimo pode manter quatro registradores de argumento ($a0—$a3) e o endereço de retorno $ra. ela precisa restaurar os registradores que salvou e remover seu frame de pilha: A rotina de fatorial é semelhante em estrutura a main. chama a rotina de fatorial e lhe passa o único argumento 10. preenchidos até um limite de double palavra (24 bytes). main retorna. Entretanto. fact é uma rotina recursiva que calcula n! multiplicando n vezes (n – 1)!. fact também salva seu argumento ($a0 ). Além de salvar $ra e $fp . × 1).6  Convenção para chamadas de procedimento B-649 que calcula e imprime 10! (o fatorial de 10. ela cria um frame de pilha e salva os registradores salvos pelo callee que serão usados por ela. Na entrada. Depois que fact retorna.. O código assembly para essa rotina ilustra como os programas manipulam frames de pilha. O frame é maior do que o exigido para esses dois registradores. então. pois a convenção de chamada exige que o tamanho mínimo de um frame de pilha seja 24 bytes. A rotina main. 10! = 10 × 9 × . primeiro. main chama a rotina de biblioteca printf e lhe passa uma string de formato e o resultado retornado de fact: Finalmente. que ela usará para a chamada re- cursiva: . Como main também precisa salvar o $fp. B. cujo frame de pilha vem em seguida na pilha.6. Caso contrário.B-650 Apêndice B  Montadores. mainexecuta primeiro. a rotina é chamada recursivamente para calcular fact(n-1) e multiplica esse valor por n: Finalmente. Ele testa se o argumento é maior do que 0. a rotina de fatorial restaura os registradores salvos pelo callee e retorna o valor no registrador $v0: Pilha em procedimentos recursivos A Figura B.3 mostra a pilha na chamada fact(7). main chama fact(10). Se o argumento for maior do que 0. de EXEMPLO modo que seu frame está mais abaixo na pilha. Cada invocação chama fact recursivamente para calcular o próximo fatorial mais inferior. a rotina retorna o valor 1. Os frames de pilha fazem um parale- . Link-editores e o Simulador SPIM O núcleo da rotina fact realiza o cálculo do programa em C. mas é um programa altamente recursivo que ilustra a convenção de chamada do MIPS. B. isso complica a geração do código. $s8. RESPOSTA Detalhamento:  A diferença entre o compilador MIPS e o compilador gcc é que o compilador MIPS normalmente não usa um frame pointer. criado por Ikuo Takeuchi. . Essa função não calcula nada de útil. Contudo. Qual é a aparência da pilha quando a cha- mada a fact(10) retorna?  FIGURA B. cujo valor pode mudar durante a execução de um procedimento se os valores forem colocados na pilha.6  Convenção para chamadas de procedimento B-651 lo com a ordem LIFO dessas chamadas. que é um benchmark bastante utilizado.3  Frames da pilha durante a chamada de fact(7). porque um procedimento precisa acessar seu frame de pilha com $sp. Outro exemplo de chamada de procedimento Como outro exemplo. Essa mudança salva algumas das instruções na chamada de procedimento e sequência de retorno. considere a seguinte rotina que calcula a função tak. de modo que esse registrador está disponível como outro registrador salvo pelo callee.6. Se y<x. ela desvia para o rótuloL1. então ela executa o corpo da rotina. Link-editores e o Simulador SPIM O código assembly para esse programa está logo em seguida. A função agora prepara argumentos para a segunda chamada recursiva. pela última vez. que contém quatro chamadas recursivas. A função utiliza registradores salvos pelo callee. A rotina. o resultado dessa chamada recursiva é salvo no registrador $s0. que aparece a seguir. o que inclui várias chamadas que potencialmente poderiam modificar registradores.B-652 Apêndice B  Montadores. primeiro. pois a rotina pode fazer chamadas que precisam usar os registradores $a0—$a2 e $ra . precisamos ler. Nas instruções a seguir. . pois eles mantêm valores que persistem por toda a vida da função. A primeira chamada usa quase os mesmos argumentos da progenitora: Observe que o resultado da primeira chamada recursiva é salvo no registrador $s3. o valor salvo do primeiro argumento a partir desse registrador. então. Se não. inicia a execução testando se y<x. No entanto. A função tak primeiro salva seu endereço de retorno no frame de pilha e seus argumentos nos registradores salvos pelo callee. de modo que pode ser usado mais tarde. Depois da chamada. e depois pega o resultado calculado (7) e o imprime usando a chamada ao sistema do SPIM para imprimir inteiros: . estamos prontos para a chamada recursiva final. B. o resultado da função está em $v0.6  Convenção para chamadas de procedimento B-653 Depois de três chamadas recursivas mais internas. e o controle desvia para o epílogo da função. Esse código no rótulo L1 é a consequência da instrução if-then-else. que restaura os registradores salvos e retorna o resultado da função a quem chamou. Ele apenas move o valor do argumento z para o registrador de retorno e entra no epílogo da função. O código a seguir é o epílogo da função. A rotina main chama a função tak com seus argumentos iniciais. o registrador EPC contém o endereço da instrução executada quando a exceção ocorreu. O ou interrupção. Um bit de máscara 1 per- mite que as interrupções nesse nível parem o processador. Contudo. que tratava exceções de forma ligeiramente diferente. o EPC aponta para a instrução de branch ou jump e o bit BD é ligado no registrador Cause. Após uma exceção.B-654 Apêndice B  Montadores. pois as mudanças são limitadas aos campos dos registradores Status e Cause e à substituição da instrução rfe pela instrução eret.0 em diante. o handler de exceção precisa procurar a instrução problemática em EPC + 4. No entanto. Quando esse bit está ligado. Quando o valor no registrador Count for igual ao valor no registrador Compare. Se a exceção foi causada por uma interrupção externa. Nesse caso. que é o que o SPIM implementa na Versão 7. a cada 10 milissegundos) enquanto o SPIM está executando.1 mostra o subconjunto dos campos do registrador Status implementados pelo simulador SPIM do MIPS. um handler de exceção retoma o programa corretamente.9 do Capítulo 4 descreve o mecanismo de exceção do MIPS. que o SPIM não modela. O registrador Count é um timer que incrementa em uma taxa fixa (como padrão. retornando à instrução no EPC. o SPIM oferece os seguintes registradores do coprocessador 0: Nome do Número registrador do registrador Uso BadVAddr 8 endereço de memória em que ocorreu uma referência de memória problemática Count 9 temporizador Compare 11 valor comparado com o temporizador que causa interrupção quando combinam Status 12 máscara de interrupções e bits de habilitação Cause 13 tipo de exceção e bits de interrupções pendentes EPC 14 endereço da instrução que causou a exceção Config 16 configuração da máquina Esses sete registradores fazem parte do conjunto de registradores do coprocessador 0. como resultado de uma exceção registra as informações de que o software precisa para lidar com exceções e interrupções. Link-editores e o Simulador SPIM B. simulador SPIM do MIPS não implementa todos os registradores do coprocessador 0.7.7  Exceções e interrupções A Seção 4. ocorre uma interrupção de hardware com nível de prioridade 5. . chamada coprocessador 0. Um bit de máscara 0 desativa as interrupções nesse nível. de qualquer forma. A conversão de programas a partir dessas versões para execução no MIPS-32 não deverá ser difícil. que responde a ex- ceções causadas por erros durante a execução de uma instrução e a interrupções externas tratamento de interrupção Um causadas por dispositivos de E/S. exceto quando a instrução problemática está no delay slot de um branch ou jump. o registrador BadVAddr contém o endereço do local de memória referenciado.1 Nos processadores MIPS. ela liga seu bit de interrupção 1 Esta seção discute as exceções na arquitetura MIPS-32. Esta seção descreve o tratamento de interrupção e exceção trecho de código executado com mais detalhes. uma parte da CPU. As versões anteriores do SPIM implementaram a arquitetura MIPS-I. O campo interrupt mask contém um bit para cada um dos seis níveis de interrupção de hardware e dois de software. Eles são acessados pelas instruções mfc0 and mtc0. então a instrução não terá iniciado a execução. pois muitos não são úteis em um simulador ou fazem parte do sistema de memória. A Figura B. Se a instrução que causou a exceção fez um acesso à memória. Quando uma interrupção chega. Todas as outras exceções são causadas pela execução da instrução no EPC. Se for 0. O bit de branch delay é 1 se a última exceção ocorreu em uma instrução executada no slot de retardo de um desvio. Os bits de interrupções pendentes tornam-se 1 quando uma interrupção é gerada em determinado nível de hardware ou software.7. elas estão inibidas.7.7  Exceções e interrupções B-655 FIGURA B. mesmo que o bit de máscara esteja desligado.2 mostra o subconjunto dos campos do registrador Cause que o SPIM implementa. O bit de modo do usuário é 0 se o processador estiver funcionando no modo kernel e 1 se estiver funcionando no modo usuário. A Figura B. O registrador de código de exceção descreve a causa de uma exceção por meio dos seguintes códigos: Número Nome Causa da exceção 00 Int interrupção (hardware) 04 AdEL exceção de erro de endereço (load ou busca de instrução) 05 AdES exceção de erro de endereço (store) 06 IBE erro de barramento na busca da instrução 07 DBE erro de barramento no load ou store de dados 08 Sys exceção de syscall 09 Bp exceção de breakpoint 10 RI exceção de instrução reservada 11 CpU coprocessador não implementado 12 Ov exceção de overflow aritmético 13 Tr trap 15 FPE ponto flutuante . ela interromperá o processador quando seu bit de máscara for habilitado mais tarde. Quando uma interrupção está pendente. pois o proces- sador SPIM não implementa o modo kernel. B.1  O registrador Status. as interrupções são desativadas e o EPC não é atualizado se outra exceção ocorrer. mas é colocado em 1 depois que ocorre uma exceção. mas deve ser reiniciado quando o handler termina. No SPIM.2  O registrador Cause.7. Quando esse bit é 1. Se o bit interrupt enable for 1. esse bit é fixado em 1. FIGURA B. Esse bit impede que um handler de exceção seja incomodado por uma interrupção ou exceção. pendente no registrador Cause. O bit de nível de exceção normalmente é 0. as interrupções são permitidas. pois a segunda exceção gravaria sobre valores salvos durante a primeira exceção. O sistema operacional processa essas solicitações e retoma o processo.s) usado pelo simulador SPIM. Em vez disso. pois não pode acessar a memória sem usar $at) e dois locais da memória (save0 e save1). Se tiver sido. que é a parte da CPU que trata das exceções. que é usado em pseudoins- EXEMPLO truções no código do handler. Esse código examina a causa da exceção e desvia para um ponto apropriado no sistema operacional. Elas em geral fazem com que o sistema operacional mova dados de ou para um dispositivo de E/S e retome o processo interrompido. no endereço 80000180hexa (no espaço de endereçamento do kernel. Os registradores Cause e EPC não fazem parte do conjunto de registradores da CPU. depois salva $a0 e $a1. Link-editores e o Simulador SPIM Exceções e interrupções fazem com que um processador MIPS desvie para uma parte do código. Um processo que causa um erro. Observe que o handler de exceção não precisa salvar os registradores $k0 e $k1. pois a causa da exceção poderia ter sido uma referência de memória que usou um valor incorreto (como 0) no stack pointer. é terminado pelo sistema operacional. a exceção é ignorada. O sistema operacional responde a uma exceção terminando o processo que causou a exceção ou realizando alguma ação. dois locais não seriam suficientes. não do usuário). Por outro lado. como a execução de uma instrução não implementada. Handler de exceções O handler de exceção primeiro salva o registrador $at. como faltas de página. são solicitações de um processo para o sistema operacional realizar um serviço. chamada handler de exceção. como trazer uma página do disco. como faria uma rotina comum. O handler de exceção. então. Se a própria rotina de exceção pudesse ser interrompida. o handler de exceção armazena esses regis- tradores em um registrador de handler de exceção ($k1. A instrução mfc0 $k0. pois os programas do usuário não deveriam usar esses registradores. de modo que o problema não surge. O handler de exceção não pode armazenar os valores antigos a partir desses registradores na pilha. Esse código é seme- lhante ao handler de exceção (exceptions. . O último tipo de exceções são interrupções de dispositivos externos. move os registradores Cause e EPC para os regis- tradores da CPU. Em vez disso. que mais tarde utiliza para passar argumentos. outras exceções.B-656 Apêndice B  Montadores. Entretanto. o handler chama print_excp para imprimir uma mensagem. O han- dler de exceção usa o valor do registrador Cause para testar se a exceção foi causada por uma interrupção (ver a tabela anterior). O código no exemplo a seguir é um handler de exceção simples. eles são registradores no coprocessador 0. $13 move o registrador 13 do coprocessador 0 (o registrador Cause) para o registrador da CPU $k0. esse handler de exceção simples termina a execução antes de permitir interrupções. Se a exceção não foi uma interrupção. que invoca uma rotina para imprimir uma mensagem a cada exceção (mas não interrupções). a fim de não reexecutar a instrução que falhou e causar a mesma exceção novamente. se a instrução que causou a exceção estivesse em um delay slot de uma instrução de desvio (veja Capítulo 4). . a próxima instrução a executar pode não ser a instrução seguinte na memória. de modo a permitir que exceções subsequentes mudem o registrador EPC. ele executa a instrução eret (retorno de exceção).7  Exceções e interrupções B-657 Antes de retornar. o retorno de um handler de exceção é mais complexo. o handler de exceção apaga o registrador Cause. que retorna à instrução apontada pelo EPC. Esse handler de exceção retorna à instrução após aquela que causou a exceção. O handler de exceção não pode sempre desviar para a instrução após o EPC. Depois. $a1 e $at. e restaura os registradores $a0. reinicia o regis- trador Status para ativar interrupções e limpar o bit EXL. B. Por exemplo. Detalhamento:  Em processadores MIPS reais. Além disso. eles aparecem no terminal do SPIM ou na janela de console. mas. Link-editores e o Simulador SPIM B.B-658 Apêndice B  Montadores.8.PCSpim pode ativar a E/S mapeada em memória por meio de um flag de linha de comando ou pela caixa de diálogo “Settings” (configurações). Somente alguns bits desses registradores são realmente utilizados. O transmissor exibe caracteres no vídeo. O receptor lê caracteres digitados no teclado. e ele muda de 1 para 0 quando o caractere é lido do registrador Receiver Data.8  Entrada e saída O SPIM simula um dispositivo de E/S: um console mapeado em memória em que um programa pode ler e escrever caracteres. O bit de pronto muda de 0 a 1 quando um caractere é digitado no teclado. como mostra a Figura B.1  O terminal é controlado por quatro registradores de dispositivo. Os outros sempre são lidos como 0s e as escritas são ignoradas. o SPIM conecta seu próprio terminal (ou uma janela de console separada na versão xspim do X-Windows ou na versão PCSpim do Windows) ao processador. cada um deles parecendo com uma posição de memória no endereço indicado. que os caracteres digitados no teclado não são ecoados automaticamente no monitor. Um programa controla o terminal com quatro registradores de dispositivo mapeados em memória. em vez disso.8. Para usar a E/S mapeada em memória (ver a seguir). . As duas unidades são completamente independentes. o spim ou o xspim precisam ser iniciados com o flag —mapped_io. Somente dois de seus bits são realmente usados. se o programa MIPS escreve caracteres no terminal. O bit de pronto é apenas de leitura: tentativas de sobrescrevê-lo são ignoradas. FIGURA B. por exemplo. o terminal é novamente conectado ao SPIM para que você possa digitar comandos do SPIM. isso significa que um caractere chegou do teclado.1. Isso significa. Um programa MIPS executando no SPIM pode ler os caracteres que você digita. O registrador Receiver Control está na posição ffff0000hexa. mas ainda não foi lido do registrador Receiver Data. porque você digitou Control-C ou porque o programa atingiu um ponto de interrupção). Quando o programa para de executar (por exemplo. Em vez disso. Uma exceção a essa regra é Control-C: esse caractere não é passado ao programa. um programa ecoa um caractere lendo-o do receptor e escrevendo-o no transmissor. O bit 0 é chamado “pronto”: se for 1. faz com que o SPIM pare e retorne ao modo de comando. “Mapeado em memória” significa que cada registrador aparece como uma posição de memória especial. O dispositivo de terminal consiste em duas unidades independentes: um receptor e um transmissor. Quando um programa está executando. Quando um valor é escrito nesse local. O registrador Transmitter Data só deverá ser escrito quando o bit de pronto do registrador Transmitter Control for 1. O SPIM mede o tempo em instruções executadas. O terceiro registrador de dispositivo de terminal é o registrador Transmitter Control (no endereço ffff0008hexa). Esse bit pode ser lido e escrito por um programa. Isso significa que o transmissor não fica pronto novamente até que o processador execute um número fixo de instruções. Os programas executados nas versões anteriores do SPIM e que não usavam exceções deverão ser executados sem modificação nas versões mais recentes do SPIM. Por exemplo. O bit 0 é chamado de “pronto” e é apenas de leitura. Os programas que usavam exceções exigirão pequenas mudanças. Esse bit permanece sendo 0 até passar tempo suficiente para transmitir o caractere para o terminal. depois. se você deixar a máquina executar. Essa arquitetura é quase um subconjunto apropriado da arquitetura MIPS-32. O SPIM é um sistema autocontido para executar programas do MIPS. Todavia. o terminal solicita uma interrupção no nível de hardware 1 sempre que um caractere é digitado e o bit de pronto se torna 1. Se você interromper a máquina e examinar o bit de pronto.0) implementaram a arquitetura MIPS-1 utilizada nos proces- sadores MIPS R2000 originais.2 O nome do SPIM é simplesmente MIPS ao contrário. O SPIM pode ler e executar os arquivos em assembly. O interrupt enable inicialmente é 0. para que a interrupção afete o processador. seus oito bits menos significativos (ou seja. A leitura do registrador Receiver Data reinicia o bit de pronto no registrador Receiver Control para 0. . que são aceitas pelo SPIM. o bit de pronto no registrador Transmitter Control é retornado para 0. Somente os dois bits menos significativos desse registrador são usados. sem caches e apenas os coprocessador 0 e 1. Todos os outros bits contêm 0s. depois que o transmissor começa a escrever um caractere. o bit de pronto do transmissor torna-se 0 por um tempo.15. B. Computadores reais exigem tempo para enviar caracteres a um console ou terminal. Se esse bit for 1. no Capítulo 2) são enviados para o console. Os oito bits menos significativos desse registrador contêm o último caractere digitado no teclado. Ele contém um depurador e oferece alguns serviços de forma semelhante ao 2 As primeiras versões do SPIM (antes da 7. B. as interrupções também precisam estar ativadas no registrador Status (veja Seção B. sendo que a diferença é a maneira como as exceções são tratadas. Esse registrador é apenas de leitura e muda apenas quando um novo caractere é digitado no teclado. um caractere ASCII como na Figura 2. Eles se comportam de modo semelhante aos bits correspondentes no registrador Receiver Control. O registrador de dispositivo final é o registrador Transmitter Data (no endereço ffff000chexa).7). o transmissor estará pronto para aceitar um novo caractere para saída. O segundo registrador de dispositivo de terminal é o registrador Receiver Data (no endereço ffff0004hexa).9   SPIM SPIM é um simulador de software que executa programas em assembly escritos para processadores que implementam a arquitetura MIPS-32. especificamente o Release 1 dessa arquitetura com um mapeamento de memória fixo. O MIPS-32 também in- troduziu aproximadamente 60 novas instruções. mas o caractere não é enviado). O valor nesse registrador é indefinido se o registrador Receiver Control for 0. Se esse bit for colocado em 1. o transmissor ainda está ocupado escrevendo o caractere anterior. e não em tempo de clock real. o bit por fim mudará de volta para 1. o bit de pronto se torna 1 novamente. as escritas no registrador Transmitter Data são ignoradas (as escritas parecem ter sucesso. Contudo. O bit 1 é “interrupt enable” e pode ser lido e escrito. Se o transmissor não estiver pronto. então o terminal solicita uma interrupção no nível de hardware 0 sempre que o transmissor estiver pronto para um novo caractere e o bit de pronto se torna 1. Todos os outros bits do registrador Receiver Control não são utilizados.9 SPIM B-659 O bit 1 do registrador Receiver Control é o “interrupt enable” do teclado. Esses retardos de tempo são simulados pelo SPIM. Se ele for colocado em 1 por um programa. ele não mudará. Se for 0. Quando o registrador Transmitter Data é escrito. Como eles são implementados em software. pois podem detectar mais erros e oferecer uma interface melhor do que um computador real. a instrução imediatamente após o desvio é executada. ou apenas coletar dados. que aparecem como instruções reais nos programas em assembly. Esse computador virtual parece ter branches e virtual que parece ter desvios loads não delayed e um conjunto de instruções mais rico do que o hardware real. O e loads não delayed e um conjunto montador reorganiza instruções para preencher os delay slots. Por exemplo. depure e execute programas MIPS simples. SPIM é muito mais lento do que um computador real (100 ou mais vezes). são sintetizados comparando-se os dois registradores e desviando quando o resultado da comparação é verdadeiro (diferente de zero).B-660 Apêndice B  Montadores. não em silício. porém. pois essa é a máquina que a maioria dos programadores achará útil. Entretanto. seguimos a convenção dos programadores (e compiladores) assembly do MIPS. por causa dos delayed branches. Uma boa parte da complexidade da programação é resultante de instruções delayed. O MIPS sabiamente escolheu ocultar essa complexidade fazendo com que seu monta- máquina virtual  Um computador dor implemente uma máquina virtual. como aquele que desvia quando um registrador é maior do que outro. Muitos detalhes nunca deverão preocupá-lo. No segundo ciclo. seu baixo custo e grande disponibilidade não têm comparação com o hardware real! Uma pergunta óbvia é: por que usar um simulador quando a maioria das pessoas pos- sui PCs que contêm processadores executando muito mais rápido do que o SPIM? Um motivo é que o processador nos PCs são 80x86s da Intel. cuja arquitetura é muito menos regular e muito mais complexa de entender e programar do que os processadores MIPS. o SPIM simula a máquina virtual mais rica. . o SPIM também pode simular os desvios e loads delayed no hardware real. O computador virtual de instruções mais rico do que o hardware real. que deverá permitir que você carregue. Introdução ao SPIM O restante deste apêndice é uma introdução ao SPIM e ao Assembly R2000 do MIPS. o hardware do MIPS só oferece instruções para desvio quando um registrador é igual ou diferente de 0. Esta seção começa com um tutorial rápido sobre o uso do SPIM. Como padrão. também oferece pseudoinstruções. que normalmente utilizam a máquina estendida como se estivesse implementada em silício. Todavia. que não faz nada. A arquitetura do MIPS pode ser a síntese de uma máquina RISC simples e limpa. os simuladores podem ser examinados e facilmente modificados para acrescentar novas instruções. Ela também pode ser um nop (nenhuma operação). criar novos sistemas. O hardware. Um delayed branch exige dois ciclos para executar (veja as seções “Detalhamentos” do Capítulo 4). Além disso. Simulação de uma máquina virtual Uma arquitetura MIPS básica é difícil de programar diretamente. de modo que a instrução imediatamente após um load não pode usar o valor (veja Seção 4. não sabe nada a respeito de pseudoinstruções. Essa dificuldade é tolerável. como os multiprocessadores. Essa instrução pode realizar um trabalho útil que normalmente teria sido feito antes do desvio. pois esses computadores foram projetados para serem programados em linguagens de alto nível e apresentam uma interface criada para compiladores. Link-editores e o Simulador SPIM sistema operacional. os simuladores são uma ferramenta útil no estudo de computadores e dos programas neles executados. os simuladores podem oferecer um ambiente melhor para a programação em assembly do que uma máquina real. Finalmente. porém. os delayed loads exigem dois ciclos para trazer um valor da memória. A seguir. Ao fazer isso. o grande volume de informações às vezes poderá obscurecer o fato de que o SPIM é um programa simples e fácil de usar. descrevemos a máquina virtual e só mencionamos rapidamente os recursos que não pertencem ao hardware real. delayed loads e modos de endereçamento restritos. Outros desvios condicionais. de modo que o montador as traduz para sequências equivalentes de instruções de máquina reais. De modo semelhante.2 do Capítulo 4). em vez de programadores assembly. byte 0. em uma máquina little-endian. Além disso. em um Intel 80x86. o spim pode fazer tudo que seus primos mais sofisticados fazem. Por exemplo. O SPIM não simula caches ou a latência da memória. o SPIM é little-endian. A única constante é a versão mais simples. o SPIM é big-endian. nem reflete com precisão os atrasos na operação de ponto flutuante ou nas instruções de multiplicação e divisão. Por exemplo. Recursos surpreendentes Embora o SPIM fielmente simule o computador MIPS. a palavra seria Byte # 3 2 1 0 O SPIM opera com duas ordens de bytes. em uma máquina big-endian. o que deveria causar exceções em uma máquina real. Apesar da falta de uma interface sofisticada. B. Se você executar o spim em um computador com UNIX ou Linux. spim e as opções da linha de comandos do SPIM estão neste CD (clique em Software). 3 resultaria em uma palavra de memória contendo Byte # 0 1 2 3 enquanto. chamada spim . As versões do SPIM para UNIX e Windows estão neste CD (clique em Tutoriais). e certas coisas não são idênticas a um computador real. a diretiva . A ordem de bytes do SPIM é a mesma ordem de bytes da máquina utilizada para executar o simulador. PCspim. xspim é um programa mais fácil de aprender e usar do que o spim. pressiona a tecla Enter (ou Return) e o spim executa seu comando. Os processadores MIPS podem operar com a ordem de bytes big-endian ou little-endian. Ordem de bytes Os processadores podem numerar os bytes dentro de uma palavra de modo que o byte com o número mais baixo seja o mais à esquerda ou o mais à direita. que é um programa controlado por linha de comandos. as instruções de ponto flutuante não detectam muitas condições de erro. o SPIM é um simulador. 2. A convenção usada por uma máquina é considerada sua ordem de bytes. A outra versão sofisticada se chama PCspim e roda no Microsoft Windows. As diferenças mais óbvias são que a tem- porização da instrução e o sistema de memória não são idênticos. Ele opera como a maioria dos programas desse tipo: você digita uma linha de texto. 1. as instruções que encontra são diferentes daquelas do programa-fonte. deverá primeiro dar uma olhada no tutorial sobre PCspim neste CD.9 SPIM B-661 O SPIM vem em diferentes versões para diferentes tipos de sistemas. Os tutoriais (em inglês) sobre xspim. Outra surpresa (que também ocorre na máquina real) é que uma pseudoinstrução se ex- pande para várias instruções de máquina. pois seus comandos sempre são visíveis na tela e porque ele continuamente apresenta os registradores e a memória da máquina. Quando você examina a memória passo a passo. . Se você for executar o spim em um PC com o Microsoft Windows. Existem dois primos sofisticados do spim. A correspondência entre os dois conjuntos de instruções é muito simples. pois o SPIM não reorganiza as ins- truções para preencher delay slots. deverá ler o tutorial (em inglês) sobre xspim (clique em Tutoriais). enquanto em um Macintosh ou Sun SPARC. A versão que roda no ambiente X-Windows de um sistema UNIX ou Linux é chamada xspim. executado em uma janela de console. o código a seguir imprime “the answer=5”: A chamada ao sistema print_int recebe um inteiro e o imprime no console.print_ float imprime um único número de ponto flutuante. e print_string recebe um ponteiro para uma string terminada em nulo. As chamadas ao sistema read_int. que ele escreve no console. por meio da instrução de chamada ao sistema (syscall). print_double imprime um nú- mero de precisão dupla. para valores de ponto flutuante). até o caractere de newline.1  Serviços do sistema. Para requisitar um serviço.9. Os caracteres após o número são FIGURA B. .1) no registrador $v0 e os argumentos nos registradores $a0—$a3 (ou $f12.9. Por exemplo.B-662 Apêndice B  Montadores. inclusive. As chamadas ao sistema que retornam valores colocam seus resultados no registrador $v0 (ou $f0 para resultados de ponto flutuante). read_float e read_double leem uma linha inteira da entrada. Link-editores e o Simulador SPIM Chamadas ao sistema O SPIM oferece um pequeno conjunto de serviços semelhantes aos oferecidos pelo sistema operacional. um programa carrega o código da chamada ao sistema (veja Figura B. Ela lê até n – 1 caracteres para um buffer e termina a string com um byte nulo. Se menos de n – 1 caracteres estiverem na linha atual. O SPIM simula a maior parte dos aspectos dessa unidade.10  Assembly do MIPS R2000 B-663 ignorados. B. Por exemplo. read_string possui a mesma semântica da rotina de biblioteca do UNIX fgets. produzindo uma ou mais instruções antes que o load ou o store calculem um endereço complexo. Modos de endereçamento O MIPS é uma arquitetura load-store.10. e novamente termina a string com nulo. Uma quantidade está alinhada se seu endereço de memória for um múltiplo do seu tamanho em bytes. lwr. O coprocessador 0 trata de exceções e interrupções. As instruções de cálculo operam apenas sobre os valores nos regis- tradores. B. que usa a soma do c imediato e do registrador rx como endereço. write e close são as chamadas da biblioteca padrão do UNIX.exit2 termina o programa SPIM. No entanto. print_char e read_char escrevem e leem um único caractere. o MIPS oferece algumas instruções para manipular dados não alinhados (lwl. como números de ponto flutuante (veja Figura B. O SPIM simula dois coprocessadores. Detalhamento:  O montador MIPS (e SPIM) sintetiza os modos de endereçamento mais complexos. A máquina pura oferece apenas um modo de endereçamento de memória: c(rx). suponha que o rótulo table referenciasse o local de memória 0 × 10000004 e um programa tivesse a instrução .8). Aviso: os programas que usam essas syscalls para ler do terminal não deverão usar E/S mapeada em memória (ver Seção B. read_string lê até o caractere de new- line. A máquina virtual oferece os seguintes modos de endereçamento para instruções load e store: Formato Cálculo de endereço (registrador) conteúdo do registrador imm imediato imm (registrador) imediato + conteúdo do registrador rótulo endereço do rótulo rótulo ± imediato endereço do rótulo + ou – imediato rótulo ± imediato (registrador) endereço do rótulo + ou – (imediato + conteúdo do registrador) A maior parte das instruções load e store opera apenas sobre dados alinhados. exit interrompe o programa que o SPIM estiver executando. um objeto halfword precisa ser armazenado em endereços pares e um objeto palavra (word) precisa ser armazenado em endereços que são múltiplos de quatro. O coprocessador 1 é a unidade de ponto flutuante. sbrk retorna um ponteiro para um bloco de memória contendo n bytes adicionais. open.10  Assembly do MIPS R2000   Um processador MIPS consiste em uma unidade de processamento de inteiros (a CPU) e uma coleção de coprocessadores que realizam tarefas auxiliares ou operam sobre outros tipos de dados. read.1). o que significa que somente instruções load e store acessam a memória. Portanto. inclusive. swl e swr). e o argumento de exit2 torna-se o valor retornado quando o próprio simulador SPIM termina. respectivamente. ). Os identificadores são uma sequência de caracteres alfanuméricos. Final- mente. Rótulos são declarados por sua colocação no início de uma linha e seguidos por um sinal de dois-pontos.1  CPU e FPU do MIPS R2000. A segunda instrução acrescenta o conteúdo do registrador $a1 ao endereço parcial do rótulo. símbolos _ e pontos (. Sintaxe do montador Os comentários nos arquivos do montador começam com um sinal de sharp (#). Os opcodes de instrução são palavras reservadas que não podem ser usadas como identificadores. que é o registrador que o montador reserva para seu próprio uso. que não começam com um número. a instrução load utiliza o modo de endereçamento de hardware para adicionar a soma dos bits menos significativos do endereço do rótulo e o offset da instrução original ao valor no registrador $at.B-664 Apêndice B  Montadores.10. Link-editores e o Simulador SPIM FIGURA B. por exemplo: . O montador traduziria essa instrução para as instruções A primeira instrução carrega os bits mais significativos do endereço do rótulo no regis- trador $at. Tudo desde esse sinal até o fim da linha é ignorado. kdata.sdata).. Logo.rdata e ..word. itens subsequentes são armazenados a partir do endereço end. os itens subsequentes são armazenados a partir do endereço end. wn Armazena as n quantidades de 32 bits em palavras de memória sucessivas.align n Alinha o próximo dado em um limite de 2n bytes. 256 e 0x100 indicam o mesmo valor.extern sym tamanho Declara que o dado armazenado em sym possui tamanho bytes de extensão e é um rótulo global.globl sym Declara que o rótulo sym é global e pode ser referenciado a partir de outros arquivos. Se o argumento opcional end estiver presente.sat at A primeira diretiva impede que o SPIM reclame sobre instruções subsequentes que utilizam o registrador $at. os programadores precisam ter muito cuidado ao deixar valores nesse registrador. .double d1..space n Aloca n bytes de espaço no segmento atual (que precisa ser o segmento de dados no SPIM). Por exemplo.. .double até a próxima diretiva . . .10  Assembly do MIPS R2000 B-665 Os números estão na base 10 por padrão.. . mais adiante)..data <end> Itens subsequentes são armazenados no segmento de dados. No SPIM. .ktext<end> Itens subsequentes são colocados no segmento de texto do kernel. No SPIM.. .data.float f1.align 0 desativa o alinhamento automático das diretivas . . hn Armazena as n quantidades de 16 bits em halfwords sucessivas da memória..kdata<end> Itens de dados subsequentes são armazenados no segmento de dados do kernel. fn Armazena os n números de precisão simples em ponto flutuante nos locais de memória sucessivos.set noat e .. O SPIM não distingue as várias partes do segmento de dados (.word. .asciiz str Armazena a string str na memória e a termina com nulo..word w1. . . As strings são delimitadas com aspas (“).ascii str Armazena a string str na memória..half h1.byte b1.float e . . os itens subsequentes são armazenados a partir do endereço end.data ou . Essa diretiva permite que o montador armazene o dado em uma parte do segmento de dados que é acessado eficientemente por meio do registrador $gp . B.. .text<end> Itens subsequentes são colocados no segmento de texto do usuário.. . mas não a termina com nulo. .. Se eles forem precedidos por 0x..dn Armazena os n números de precisão dupla em ponto flutuante em locais de memória sucessivos..half. Caracteres especiais nas strings seguem a convenção da linguagem C: j nova linha \n j tabulação \t j aspas \” O SPIM admite um subconjunto das diretivas do montador do MIPS: . esses itens só podem ser instruções ou palavras (ver a diretiva . os itens subsequentes são armazenados a partir do endereço end. .word a seguir). serão inter- pretados como hexadecimais.. Se o argumento opcional end estiver presente. . A segunda diretiva reativa a advertência. Se o argumento opcional end estiver presente.. Como as pseudoinstruções se expandem para o código que usa o registrador $at. . Se o argumento opcional end estiver presente.align 2 alinha o próximo valor em um limite da palavra... esses itens só podem ser instruções ou palavras (ver a diretiva . bn Armazena os n valores em bytes sucessivos da memória. . . então as operações estão no último campo com f = d.2 explica como uma instrução MIPS é codificada em um número binário. respectivamente.10. 18 e 19. a operação é especificada em outro lugar: se z = 0. O texto no topo de uma FIGURA B. . Esse campo op especifica completamente a operação do MIPS. “1”. 18 ou 19. Se rs = 17 e z = 1. 17. as operações são especificadas no quarto campo (bits 4 a 0). se z = 1. então as operações são no último campo com f = s.B-666 Apêndice B  Montadores. Essas operações são determinadas pelos outros campos. 17. O segundo campo (rs) usa “z” para indicar “0“. identificados por ponteiros. “2” ou “3” se op = 16. Os valores de cada campo aparecem à sua esquerda. o opcode j possui um valor 2 no campo opcode. Os números na margem esquerda são valores para um campo.2  Mapa de opcode do MIPS. 1. Por exemplo. Cada coluna contém codificações de instrução para um campo (um grupo de bits contíguo) a partir de uma instrução. Se rs = 16. 16. Link-editores e o Simulador SPIM Codificando instruções do MIPS A Figura B.10. exceto para 6 valores de op: 0. A primeira coluna mostra os valores na base 10 e a segunda mostra a base 16 para o campo op (bits 31 a 26) na terceira coluna. O último campo (funct) utiliza “f ” para indicar “s” se rs = 16 e op = 17 ou “d” se rs = 17 e op = 17. o montador e o SPIM traduzem uma forma mais geral de uma instrução (por exemplo. Adição (com overflow) Adição (sem overflow) Coloca a soma dos registradores rs e rt no registrador rd. As instruções reais indicam os campos em sua representação binária. . $a0. as diferentes instruções de ponto flutuante são especificadas pelos bits 0-5. Essa instrução começa com 6 bits em 0. alguns grupos de instruções utilizam campos adicionais para distinguir instruções relacionadas. Outro campo comum é imm16. 0x55). de modo que o próximo campo é um especificador de registrador de 5 bits chamado rs. Esse é o mesmo registrador que é o segundo argumento no assembly simbólico à esquerda dessa linha. addi $v1. que é um número imediato de 16 bits. Os especificadores de registradores começam com um r. mas omitem a informação de codificação de instrução. O tamanho de cada campo em bits é o pequeno número abaixo do campo. No entanto. rdest e rsrcl são registradores. e src2 é um registrador ou um valor imediato. Por exemplo. Instruções aritméticas e lógicas Valor absoluto Coloca o valor absoluto do registrador rsrc no registrador rdest. Por exemplo. add $v1. Os dois tipos de instruções podem ser distinguidos facilmente. Por exemplo: Multiplicação (sem overflow) Nas pseudoinstruções. Em geral. 0x55) para uma forma especializada (por exemplo. em: Adição (com overflow) a instrução add consiste em seis campos. o campo op está contido nos bits 26-31 de uma instrução. Formato de instrução O restante deste apêndice descreve as instruções implementadas pelo hardware MIPS real e as pseudoinstruções fornecidas pelo montador MIPS. $a0. As setas a partir da primeira coluna mostram quais opcodes utilizam esses campos adicionais. Esse campo codifica a maioria das instruções.10  Assembly do MIPS R2000 B-667 coluna nomeia um campo e especifica quais bits ele ocupa em uma instrução. As pseudoinstruções seguem aproximadamente as mesmas convenções. B. Por exemplo. o resultado é 32. o restante não será es- pecificado pela arquitetura MIPS e dependerá da convenção da máquina em que o SPIM é executado. Deixa o quociente no registrador e o resto no registrador hi. Contar uns iniciais Contar zeros iniciais Conta o número de uns (zeros) iniciais da palavra no registrador rs e coloca o resultado no registrador rd. . AND Coloca o AND lógico dos registradores rs e rt no registrador rd. Se uma palavra contém apenas uns (zeros). Observe que. AND imediato Coloca o AND lógico do registrador rs e o imediato estendido com zeros no registrador rt. Divisão (com overflow) Divisão (sem overflow) Divide o registrador rs pelo registrador. Link-editores e o Simulador SPIM Adição imediato (com overflow) Adição imediato (sem overflow) Coloca a soma do registrador rs e o imediato com sinal estendido no registrador rt. se um operando for negativo.B-668 Apêndice B  Montadores. Multiplicação (com overflow) Multiplicação sem sinal (com overflow) Coloca os 32 bits menos significativos do produto do registrador rsrcl e src2 no regis- trador rdest. Multiplicação Multiplicação sem sinal Multiplica os registradores rs e rt. Deixa a palavra menos significativa do produto no registrador lo e a palavra mais significativa no registrador hi. B.10  Assembly do MIPS R2000 B-669 Divisão (com overflow) Divisão (sem overflow) Coloca o quociente do registrador rsrcl pelo src2 no registrador rdest. Multiplicação (sem overflow) Coloca os 32 bits menos significativos do produto de rs e rt no registrador rd. Multiplicação adição Multiplicação adição sem sinal Multiplica os registradores rs e rt e soma o produto de 64 bits resultante ao valor de 64 bits nos registradores concatenados lo e hi. . Negar valor (com overflow) Negar valor (sem overflow) Coloca o negativo do registrador rsrc no registrador rdest. NOR Coloca o NOR lógico dos registradores rs e rt para o registrador rd.B-670 Apêndice B  Montadores. OR Coloca o OR lógico dos registradores rs e rt no registrador rd. Link-editores e o Simulador SPIM Multiplicação subtração Multiplicação subtração sem sinal Multiplica os registradores rs e rt e subtrai o produto de 64 bits resultante do valor de 64 bits nos registradores concatenados lo e hi. OR imediato Coloca o OR lógico do registrador rs e o imediato estendido com zero no registrador rt. Resto . NOT Coloca a negação lógica bit a bit do registrador rsrc no registrador rdest. B.10  Assembly do MIPS R2000 B-671 Resto sem sinal Coloca o resto do registrador rsrc1 dividido pelo registrador rsrc2 no registrador rdest. Shift lógico à esquerda Shift lógico à esquerda variável Shift aritmético à direita Shift aritmético à direita variável Shift lógico à direita Shift lógico à direita variável Desloca o registrador rt à esquerda (direita) pela distância indicada pelo shamt imediato ou pelo registrador rs e coloca o resultado no registrador rd. Rotate à esquerda Rotate à direita Gira o registrador rsrc1 à esquerda (direita) pela distância indicada por rsrc2 e coloca o resultado no registrador rdest. Observe que o argumento rs é ignorado para sll. sra e srl. . Observe que se um operando for negativo. o resto não é especificado pela arquitetura MIPS e depende da convenção da máquina em que o SPIM é executado. Load imediato Move o imediato imm para o registrador rdest. Link-editores e o Simulador SPIM Subtração (com overflow) Subtração (sem overflow) Coloca a diferença dos registradores rs e rt no registrador rd. Os bits menos significativos do registrador são colocados em 0. . Instruções para manipulação de constantes Load superior imediato Carrega a halfword menos significativa do imediato imm na halfword mais significativa do registrador rt. OR exclusivo Coloca o XOR lógico dos registradores rs e rt no registrador rd.B-672 Apêndice B  Montadores. XOR imediato Coloca o XOR lógico do registrador rs e o imediato estendido com zeros no regis- trador rt. caso contrário. coloca-o em 0. Instruções de comparação Set se menor que Set se menor que sem sinal Coloca o registrador rd em 1 se o registrador rs for menor que rt . 10  Assembly do MIPS R2000 B-673 Set se menor que imediato Set se menor que imediato sem sinal Coloca o registrador rt em 1 se o registrador rs for menor que o imediato estendido com sinal. e em 0 caso contrário. Set se maior que Set se maior que sem sinal Coloca o registrador rdest em 1 se o registrador rsrc1 for maior que rsrc2. Set se menor ou igual Set se menor ou igual sem sinal Coloca o registrador rdest em 1 se o registrador rsrc1 for menor ou igual a rsrc2. Set se igual Coloca o registrador rdest em 1 se o registrador rsrcl for igual a rsrc2. B. . e em 0 em caso contrário. e em 0 caso contrário. e em 0 caso contrário. Set se maior ou igual Set se maior ou igual sem sinal Coloca o registrador rdest em 1 se o registrador rsrc1 for maior ou igual a rsrc2. e em 0 caso contrário. B-674 Apêndice B  Montadores. uma instrução desvia para um rótulo. O SPIM implementa essas instruções. O SPIM não simula esse delay slot. que não executa a instrução no delay slot do desvio se o desvio não for tomado. Instruções de desvio As instruções de desvio utilizam um campo offset de instrução de 16 bits com sinal. Link-editores e o Simulador SPIM Set se diferente Coloca o registrador rdest em 1 se o registrador rsrc1 não for igual a rsrc2. No MIPS-32. e o montador calcula a distância entre o desvio e a instrução destino. elas poderão ser removidas em versões subsequentes da arquitetura. Os delayed branches afetam o cálculo de offset. Branch se for igual Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs for igual a rt. Em vez disso. os offsets normalmente não são especificados como números. No código assembly. a variável provável de beq é beql). logo. Não use essas instruções. elas podem desviar 215 – 1 instruções (não bytes) para frente ou 215 instruções para trás. que não transferem o controle até que a ins- trução após o desvio (seu “delay slot”) tenha sido executada (veja Capítulo 4). pois precisam ser calculados em relação ao endereço da instrução do delay slot (PC + 4). Se cc for omitido da instrução. Em processadores MIPS reais. . que é quando o desvio ocorre. e em 0 caso contrário. a menos que os flags —bare ou —delayed_branch sejam especificados. Branch co-processador falso Branch co-processador verdadeiro Desvia condicionalmente pelo número de instruções especificado pelo offset se o flag de condição de ponto flutuante numerado como cc for falso (verdadeiro). as instruções de desvio são delayed branches. A instrução jump contém um campo de endereço de 26 bits. mas elas não são descritas daqui por diante. o flag de código de condição 0 é assumido. todas as instruções de desvio condicional reais (não pseudo) têm uma variante “provável” (por exemplo. Branch Desvia incondicionalmente para a instrução no rótulo. Branch se for menor que zero Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs for menor que 0. Salva o endereço da próxima instrução no registrador 31. Branch se for menor e link Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs for menor que 0. Branch se for diferente Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs não for igual a rt. Branch se for maior que zero Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs for maior que 0. Salva o endereço da próxima instrução no registrador 31. B. Branch se for menor ou igual a zero Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs for menor ou igual a 0. Branch se for maior ou igual a zero e link Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs for maior ou igual a 0.10  Assembly do MIPS R2000 B-675 Branch se for maior ou igual a zero Desvia condicionalmente pelo número de instruções especificado pelo offset se o regis- trador rs for maior ou igual a 0. . . Branch se não for igual a zero Desvia condicionalmente para a instrução no rótulo se o registrador rsrc não for igual a 0.B-676 Apêndice B  Montadores. Branch se for maior Branch se for maior sem sinal Desvia condicionalmente para a instrução no rótulo se o registrador rsrc1 for maior do que src2. Branch se for menor Branch se for menor sem sinal Desvia condicionalmente para a instrução no rótulo se o registrador rsrc1 for menor do que src2. Branch se for menor ou igual Branch se for menor ou igual sem sinal Desvia condicionalmente para a instrução no rótulo se o registrador rsrc1 for menor ou igual a rsrc2. Branch se for maior ou igual Branch se for maior ou igual com sinal Desvia condicionalmente até a instrução no rótulo se o registrador rsrc1 for maior ou igual a rsrc2. Link-editores e o Simulador SPIM Branch se for igual a zero Desvia condicionalmente para a instrução no rótulo se rsrc for igual a 0. gera uma exceção de Trap. Salva o endereço da próxima instrução no registrador $ra. gera uma exceção de Trap. gera uma exceção de Trap. Salva o endereço da próxima instrução no registrador rd (cujo default é 31). Trap se for igual imediato Se o registrador rs for igual ao valor de imm com sinal estendido. B. Jump-and-link registrador Desvia incondicionalmente para a instrução cujo endereço está no registrador rs. Jump registrador Desvia incondicionalmente para a instrução cujo endereço está no registrador rs. . Jump-and-link Desvia incondicionalmente para a instrução no destino. Instruções de trap Trap se for igual Se o registrador rs for igual ao registrador rt.10  Assembly do MIPS R2000 B-677 Instruções de jump Jump Desvia incondicionalmente para a instrução no destino. Trap se não for igual Se o registrador rs não for igual ao registrador rt. gera uma exceção de Trap. . gera uma exceção de Trap. Link-editores e o Simulador SPIM Trap se não for igual imediato Se o registrador rs não for igual ao valor de imm com sinal estendido. gera uma exceção de Trap.B-678 Apêndice B  Montadores. gera uma exceção de Trap. Trap se for maior ou igual Trap sem sinal se for maior ou igual Se o registrador rs for maior ou igual ao registrador rt. Trap se for maior ou igual imediato Trap sem sinal se for maior ou igual imediato Se o registrador rs for maior ou igual ao valor de imm com sinal estendido. Trap se for menor Trap sem sinal se for menor Se o registrador rs for menor que o registrador rt. gera uma exceção de Trap. Trap se for menor imediato Trap sem sinal se for menor imediato Se o registrador rs for menor do que o valor de imm com sinal estendido. B. Load word Carrega a quantidade de 32 bits (palavra) no endereço para o registrador rt. Load word coprocessador 1 Carrega a palavra no endereço para o registrador ft da unidade de ponto flutuante. Load word à esquerda . A halfword tem sinal estendido por lh. Load halfword Load halfword sem sinal Carrega a quantidade de 16 bits (halfword) no endereço para o registrador rt. mas não por lbu. Load byte Load byte sem sinal Carrega o byte no endereço para o registrador rt. mas não por lhu. O byte tem sinal estendido por lb.10  Assembly do MIPS R2000 B-679 Instruções load Load endereço Carrega o endereço calculado – não o conteúdo do local – para o registrador rdest. Store halfword Armazena a halfword baixa do registrador rt no endereço. A halfword tem extensão de sinal por ulh. Load halfword não alinhada Load halfword sem sinal não alinhada Carrega a quantidade de 16 bits (halfword) no endereço possivelmente não alinhado para o registrador rdest. Load Linked Carrega a quantidade de 32 bits (palavra) no endereço para o registrador rt e inicia uma operação ler-modificar-escrever indivisível. que falhará se outro processador escrever no bloco que contém a palavra carregada. . mas não ulhu. a operação de armazenamento condicional sempre tem sucesso. Essa operação é concluída por uma instrução de armazenamento condicional (sc). Load doubleword Carrega a quantidade de 64 bits no endereço para os registradores rdest e rdest+1. Load word não alinhada Carrega a quantidade de 32 bits (palavra) no endereço possivelmente não alinhado para o registrador rdest. Instruções store Store byte Armazena o byte baixo do registrador rt no endereço. Como o SPIM não simula processadores múltiplos. Link-editores e o Simulador SPIM Load word à direita Carrega os bytes da esquerda (direita) da palavra do endereço possivelmente não alinhado para o registrador rt.B-680 Apêndice B  Montadores. Store doubleword Armazena a quantidade de 64 bits nos registradores rsrc e rsrc+1 no endereço. Store double coprocessador 1 Armazena o valor de ponto flutuante da dupla palavra nos registradores ft e ft +1 do coprocessador de ponto flutuante em endereço. Store word não alinhada Armazena a palavra do registrador rsrc no endereço possivelmente não alinhado. O registrador ft precisa ser um número par. Store word coprocessador 1 Armazena o valor de ponto flutuante no registrador ft do coprocessador de ponto flu- tuante no endereço.10  Assembly do MIPS R2000 B-681 Store word Armazena a palavra do registrador rt no endereço. . Store word à esquerda Store word à direita Armazena os bytes da esquerda (direita) do registrador rt no endereço possivelmente não alinhado. B. Store halfword não alinhada Armazena a halfword baixa do registrador r s r c no endereço possivelmente não alinhado. Move do coprocessador 0 . Instruções para movimentação de dados Move Move o registrador rsrc para rdest. Move de hi Move de lo A unidade de multiplicação e divisão produz seu resultado em dois registradores adicionais. divisão e resto que fazem com que essa unidade pareça operar sobre os registradores gerais movem o resultado depois que o cálculo terminar. As pseudoinstruções de multiplicação. Se essa operação indivisível tiver sucesso. Move o registrador hi (lo) para o registrador rd. Move para hi Move para lo Move o registrador rs para o registrador hi (lo). Como o SPIM não simula diversos processadores. a instrução sempre tem sucesso. hi e lo. Se a operação indivisível falhar porque outro processador escreveu em um local no bloco contendo a palavra endereçada. a palavra da memória será modificada e o registrador rt será colocado em 1. essa instrução não modifica a memória e escreve 0 no registrador rt.B-682 Apêndice B  Montadores. Essas instruções movem os valores de e para esses registradores. Link-editores e o Simulador SPIM Store condicional Armazena a quantidade de 32 bits (palavra) no endereço rt para a memória no endereço e completa uma operação ler-modificar-escrever indivisível. Se cc for omitido da instrução. Move condicional zero Move o registrador rs para o registrador rd se o registrador rt for 0. Move o registrador rd em um co-processador (registrador fs na FPU) para o regis- trador rt da CPU.10  Assembly do MIPS R2000 B-683 Move do coprocessador 1 Os co-processadores têm seus próprios conjuntos de registradores. Move condicional em caso de FP verdadeiro Move o registrador da CPU rs para o registrador rd se o flag de código de condição da FPU número cc for 1. Move para coprocessador 0 Move para coprocessador 1 Move o registrador da CPU rt para o registrador rd em um coprocessador (registrador fs na FPU). o flag de código de condição 0 será assumido. Essas instruções movem valores entre esses registradores e os registradores da CPU. Move condicional em caso de FP falso Move o registrador da CPU rs para o registrador rd se o flag de código de condição da FPU número cc for 0. B. Se cc for omitido da instrução. A unidade de ponto flutuante é o co-processador 1. Move double do coprocessador 1 Move os registradores de ponto flutuante frsc1 e frsrc1 +1 para os registradores da CPU rdest e rdest+1. o bit de código de condição 0 é assumido. Move condicional diferente de zero Move o registrador rs para o registrador rd se o registrador rt não for 0. . s.s e s. Esse coprocessador tem seus próprios registradores. Os valores são movidos para dentro e para fora desses registradores uma palavra (32 bits) de cada vez pelas instruções lwc1. Nas pseudoinstruções a seguir. descritos anteriormente. l. converte para um valor de ponto fixo de 32 bits e coloca a palavra resultante no registrador fd. descritas a seguir. numerados de 0 a 7.B-684 Apêndice B  Montadores.d. $f2). fdest é um registrador de ponto flutuante (por exemplo.s. Link-editores e o Simulador SPIM Instruções de ponto flutuante O MIPS possui um coprocessador de ponto flutuante (número 1) que opera sobre números de ponto flutuante de precisão simples (32 bits) e precisão dupla (64 bits). Como esses registradores possuem apenas 32 bits. . que são alterados por instruções de comparação e testados por instruções de desvio (bclf ou bclt) e instruções move condicionais. ou pela pseudoinstruções l. que são numerados de $f0 a $f31. dois deles são necessários para manter dou- bles. de modo que somente registradores de ponto flutuante com números pares podem manter valores de precisão dupla. Teto de ponto flutuante para word Calcula o teto do double (single) de ponto flutuante no registrador fs. Nas instruções reais a seguir. O coprocessador de ponto flutuante também possui 8 flags de código de condição (cc). mtc1 e mfc1ou um double (64 bits) de cada vez por ldc1 e sdc1. Adição de ponto flutuante double Adição de ponto flutuante single Calcula a soma dos doubles (singles) de ponto flutuante nos registradores fs e ft e a coloca no registrador fd. os bits 21-26 são 0 para precisão simples e 1 para precisão double.d. Valor absoluto de ponto flutuante double Valor absoluto de ponto flutuante single Calcula o valor absoluto do double (single) de ponto flutuante no registrador fs e o coloca no registrador fd. swc1. Comparação menor ou igual double Comparação menor ou igual single Compara o double (single) de ponto flutuante no registrador fs com aquele no ft e coloca o flag de condição de ponto flutuante cc em 1 se o primeiro for menor ou igual ao segundo. o flag de código de condição 0 é assumido. o flag de código de condição 0 é assumido.10  Assembly do MIPS R2000 B-685 Comparação igual double Comparação igual single Compara o double (single) de ponto flutuante no registrador fs com aquele em ft e coloca o flag de condição de ponto flutuante cc em 1 se forem iguais. Converte single para double Converte integer para double Converte o número de ponto flutuante de precisão simples ou inteiro no registrador fs para um número de precisão dupla (simples) e o coloca no registrador fd. . Comparação menor que double Comparação menor que single Compara o double (single) de ponto flutuante no registrador fs com aquele no ft e coloca o flag de condição de ponto flutuante cc em 1 se o primeiro for menor que o segundo. Se o cc for omitido. o flag de código de condição 0 é assumido. B. Se o cc for omitido. Se cc for omitido. Link-editores e o Simulador SPIM Converte double para single Converte integer para single Converte o número de ponto flutuante de precisão dupla ou inteiro no registrador fs para um número de precisão simples e o coloca no registrador fd. Converte double para integer Converte single para integer Converte o número de ponto flutuante de precisão dupla ou simples no registrador fs para um inteiro e o coloca no registrador fd.B-686 Apêndice B  Montadores. Carrega double de ponto flutuante Carrega single de ponto flutuante Carrega o número de ponto flutuante de precisão dupla (simples) em address para o registrador fdest. . Piso de ponto flutuante para palavra Calcula o piso do número de ponto flutuante de precisão dupla (simples) no registrador fs e coloca a palavra resultante no registrador fd. Divisão de ponto flutuante double Divisão de ponto flutuante single Calcula o quociente dos números de ponto flutuante de precisão dupla (simples) nos registradores fs e ft e o coloca no registrador fd. Move condicional de ponto flutuante double se verdadeiro Move condicional de ponto flutuante single se verdadeiro Move o double (single) de ponto flutuante do registrador fs para o registrador fd se o flag do código de condição cc for 1. o flag do código de condição 0 será assumido. Se o cc for omitido. Move condicional de ponto flutuante double se falso Move condicional de ponto flutuante single se falso Move o número de ponto flutuante de precisão dupla (simples) do registrador fs para o registrador fd se o flag do código de condição cc for 0. B. Se o cc for omitido. . o flag de código de condição 0 é assumido. Move ponto flutuante double condicional se não for zero Move ponto flutuante single condicional se não for zero Move o número de ponto flutuante double (single) do registrador fs para o registrador fd se o registrador rt do processador não for 0.10  Assembly do MIPS R2000 B-687 Move ponto flutuante double Move ponto flutuante single Move o número de ponto flutuante de precisão dupla (simples) do registrador fs para o registrador fd. Arredondamento de ponto flutuante para palavra Arredonda o valor de ponto flutuante double (single) no registrador fs. Raiz quadrada de double . Multiplicação de ponto flutuante double Multiplicação de ponto flutuante single Calcula o produto dos números de ponto flutuante double (single) nos registradores fs e ft e o coloca no registrador fd. converte para um valor de ponto fixo de 32 bits e coloca a palavra resultante no registrador fd. Negação double Negação single Nega o número de ponto flutuante double (single) no registrador fs e o coloca no registrador fd. Link-editores e o Simulador SPIM Move ponto flutuante double condicional se for zero Move ponto flutuante single condicional se for zero Move o número de ponto flutuante double (single) do registrador fs para o registrador fd se o registrador rt do processador for 0.B-688 Apêndice B  Montadores. converte para um valor de ponto fixo de 32 bits e coloca a palavra resultante no registrador fd.10  Assembly do MIPS R2000 B-689 Raiz quadrada de single Calcula a raiz quadrada do número de ponto flutuante double (single) no registrador fs e a coloca no registrador fd. B. Instruções de exceção e interrupção Retorno de exceção Coloca em 0 o bit EXL no registrador Status do coprocessador 0 e retorna à instrução apontada pelo registrador EPC do coprocessador 0. Store de ponto flutuante double Store de ponto flutuante single Armazena o número de ponto flutuante double (single) no registrador fdest em address. Subtração de ponto flutuante double Subtração de ponto flutuante single Calcula a diferença dos números de ponto flutuante double (single) nos registradores fs e ft e a coloca no registrador fd. . Truncamento de ponto flutuante para palavra Trunca o valor de ponto flutuante double (single) no registrador fs. melhor ainda. See MIPS Run. verificação de tipo e construções de controle – e o controle completo sobre as instruções que um computador executa. Além do mais. . o custo desse nível de atenção são programas em assembly maiores. Reading. mais demorados para escrever e mais difícil de manter do que os programas em linguagem de alto nível. No entanto.B-690 Apêndice B  Montadores. Finalmente. mas ainda é a referência padrão sobre compiladores. and Tools. como o tempo de resposta ou o tamanho do programa. A Exceção 1 é reservada para o depurador. temos testemunhado uma tendência em direção a aplicações cada vez mais complexas. no caso de processadores que executam várias instruções ao mesmo tempo. Grandes aplicações são escritas por equipes de programadores e exigem recursos de modularidade e verificação semântica fornecidos pelas linguagens de alto nível. exigem que um programador preste muita atenção a cada instrução. que não apenas são mais rápidos. [1999]. Res- trições externas sobre algumas aplicações.9. B. Os compiladores modernos produzem código comparável ao melhor código escrito manualmente – e. A primeira tendência é em direção à melhoria dos compiladores. MA: Addison-Wesley. Compilers: Principles. Além disso. a rápida evolução dos computadores modernos favorece os programas em linguagem de alto nível que não estejam presos a uma única arquitetura. Break Causa a exceção código. A segunda tendência é a introdução de novos processadores.11  Comentários finais   A programação em assembly exige que um programador escolha entre os recursos úteis das linguagens de alto nível – como estruturas de dados. Ligeiramente desatualizado e faltando a cobertura das arquiteturas modernas. Leitura adicional Aho.1) fornecido pelo SPIM. Sweetman. às vezes. Ullman [1985]. Sethi e J. D. San Francisco CA: Morgan Kaufmann Publishers. B. três tendências estão reduzindo a necessidade de escrever programas em assembly. Nop Não faz nada. caracterizadas por interfaces gráficas complexas e muito mais recursos do que seus predecessores. Link-editores e o Simulador SPIM Chamada ao sistema O registrador $v0 contém o número da chamada ao sistema (veja Figura B. Techniques. também são mais difíceis de programar manualmente. R. mas.. escreva e teste um programa que leia três in- teiros e imprima a soma dos dois maiores desses três. escreva e teste um programa de calculadora que leia inteiros repetidamente e os adicione a um acumulador. B. B. B. Use as chamadas do sistema do SPIM descritas nas páginas B-43 e B-45. Um problema sério com esse handler é que ele desativa as interrupções por um longo tempo. que não possa ser interrompido mas que ative as interrupções o mais rápido possível. pdf/getDownload) B. a menos que a instrução que causou a exceção esteja no delay slot de um desvio.2 [20] <§B. B.5 [15] <§B.9> Usando o SPIM.7 [5] <§B.00. pdf/getDownload) MIPS32™ Architecture for Programmers Volume II: The MIPS-32 Instruction Set (http://mips.00. a próxima instrução será o alvo do desvio.9> Usando o SPIM.4 [25] <§B.com/content/Documentation/MIPSDocumentation/ProcessorArchitecture/ ArchitectureProgrammingPublicationsforMIPS32/MD00086-2B-MIPS32BIS-AFP-02.3 [5] <§B. B.7 contém código para um handler de exceção muito simples.5> A Seção B. que cumpra os mesmos objetivos.7> O handler de exceção simples sempre desvia para a instrução após a exceção.6 [5] <§B. Nesse caso.com/content/Documentation/MIPSDocumentation/ProcessorArchitecture/ ArchitectureProgrammingPublicationsforMIPS32/MD00082-2B-MIPS32INT-AFP-02.7> A Seção B.7> É seguro que um programa do usuário utilize os registradores $k0 ou $k1? B. A documentação detalhada sobre a arquitetura MIPS-32 está disponível na Web: MIPS32™ Architecture for Programmers Volume I: Introduction to the MIPS-32 Architecture (http://mips.9.1 [5] <§B. Você pode usar o critério de desempate que desejar. Isso funciona bem. Escreva um handler de exceção melhor.5 descreveu como a memória é dividida na maioria dos sis- temas MIPS. detalhada e envolvente sobre o conjunto de instruções do MIPS e a programação em assembly nessas máquinas. pdf/getDownload) MIPS32™ Architecture for Programmers Volume III: The MIPS-32 Privileged Resource Architecture (http://mips.12  Exercícios   B.com/content/Documentation/MIPSDocumentation/ProcessorArchitecture/ ArchitectureProgrammingPublicationsforMIPS32/MD00090-2B-MIPS32PRA-AFP-02. Proponha outra maneira de dividir a memória.00.12 Exercícios B-691 Uma introdução completa. Escreva um handler melhor. B. . Use as chamadas do sistema do SPIM descritas na Seção B. que use o registrador EPC para determinar qual instrução deverá ser executada após a exceção. imprimindo a soma nesse ponto. Isso significa que as interrupções de um dispositivo de E/S rápido podem ser per- didas. O programa deverá parar quando receber uma entrada 0.6> Reescreva o código para fact utilizando menos instruções. todos os discos estão no pino 1.9 [25] <§B. testando se cada um deles é primo. O programa em C a seguir pode ser usado como uma base para a escrita do seu pro- grama em assembly: . Por exemplo. se o usuário informou “728”. por sua vez. até o disco 1 no topo. Imprime os 100 primeiros números primos. Inicialmente.8 [5] <§B.9> Escreva e teste um programa em assembly do MIPS para calcular e imprimir os 100 primeiros números primos. Teste seus programas executando-os no SPIM. Link-editores e o Simulador SPIM B.10 [10] <§§B. Um número n é primo se ele só puder ser dividido exatamente por ele mesmo e por 1. B. e assim por diante. 2 e 3) e n discos (o número n pode variar. O objetivo é mover todos os discos para o pino 2. existe uma restrição: não é possível colocar um disco maior em cima de um disco menor. e assim por diante.) O problema consiste em três pinos (1. o programa deverá imprimir os nomes dos dígitos dos inteiros por extenso. os valores típicos poderiam estar no intervalo de 1 a 8).9> Usando o SPIM. que. Se o inteiro não for positivo. escreva e teste um programa recursivo para solucionar um problema matemático clássico.B-692 Apêndice B  Montadores. O disco 1 é menor que o disco 2. começando com o disco n na parte inferior. o disco superior de qualquer um dos três pinos para o topo de qualquer um dos outros dois pinos. o programa deverá terminar com a mensagem “Entrada inválida”. com o disco n sendo o maior. (Isso exigirá o uso de frames de pilha para admitir a recursão. o disco n – 1 acima dele. a saída deverá ser “Sete Dois Oito”. ou seja. escreva e teste um programa que leia um inteiro positivo usando as chamadas do sistema do SPIM.6. j main() percorre os inteiros. delimitados por exatamente um espaço.9> Usando o SPIM. Além do mais. B. Duas rotinas deverão ser implementadas: j testa_primo (n) retorna 1 se n for primo e 0 se n não for primo. Você só pode mover um disco de cada vez. denominado Torres de Hanói. é menor que o disco 3. B. caso contrário. 136 496–497 diagrama de blocos de unidade aritmética. definição. A-603 caches. 424 de controle ponteiro para variáveis automáticas. 209. 436 otimizado. 181–185 hierarquias de memória. 132 binária. 185 técnicas de redução de penalidade de falta. A-570 desenvolvimento de software com discos. controle. A-627–A-628 algoritmos de classificação. algoritmo. 131 velocidade. 15 desempenho da taxa de transferência adição sem sinal. 219 Application Binary Interface (ABI). 409 desempenho LBMHD. 326 lógicas. 181–185 armazenamento AMD Opteron X4 (Barcelona). 546 precisão dupla. A-604. 130–132 B-684–B-685 pipeline. 409 hardware. 61 hardware TLB. 325–327 registrador-registrador. A-601–A-603 abstrações características. 298 hierarquias de memória. 132 instruções. instruções. 496 instruções. na pilha. Ver ASCII avaliação de processador fora de ordem. 320 definição. A-601 definição. 81–82. 551 cálculos. 186–191 subconjunto de equação de desempenho. 257 subtração. 257 aritmética. 34–39. 209. B-667 ilustração. 464 693 . 5 desempenho SpMV. 497 Advanced Technology Attachment (ATA). 250 de memória. 325 semelhanças do MIPS. 436 especializada. binária. 131 Ver também aritmética 436–437 armadilhas adição de ponto flutuante. 202–203 AND. bloco de controle. 327 formatos. 328–329 definição. 182 microarquitetura. 189 caminho de dados de desvio. 142 algoritmo de divisão. 551 campo de condição. A-601 não volátil. 494. arquitetura Ver também ALU controle. 255. 242 aritmética de multimídia. etapas. A-574 Arithmetic Logic Unit (ALU) endereços de word sequenciais. 495–496 bits. 547 loads e stores em bloco. 255 divisão. 546 formatos admitidos. 130–132 acertos de cache. 39 testando a associatividade. 435 características. operação. ALU. 204 AMD64. 203. 439–441 na heap. 550 campo imediato de 12 bits. 553 AGP. B-684–B-685 antidependência. Índice remissivo A cache L3 compartilhado. 296 extensão do espaço de endereços. ALUOp. B-668 439 ilustração. 468–469 benchmark de potência SPEC. 256 ponto flutuante. taxas de falta e acessos à DRAM. 252 GPUs. 182 ignorando o comportamento do sistema All-pairs N-body. 191–197 simulando cache. movendo funções para processador de E/S. 179–228 142 ALU. instrução. 13–15 definição. 439 algoritmo de multiplicação. 15 desempenho básico versus totalmente ARM. 36–38 aritmética de ponto flutuante (GPUs). 183–184 disco. 94 243 496 Alpha. 435 acessos de disco pelo sistema operacional. 437–441 aliasing. 193 antes do forwarding. 435–437 compare e desvio condicional. 181–182 ilustração de pipeline. 132 add (Add). 94–97 uso de instrução de referência de memória. 132–133 adição. 308 acrônimos. 254 para multimídia. 248 implementação de VMM. 438 alocação de espaço para valores de registrador. transferência de dados. 437 operações de textura. unidades pipelining. 202–205. 437–438 Ver também Arithmetic Logic Unit (ALU) multiplicação. 203 Annual Failure Rate (AFR). 197–219 Ver também falácias sinal de controle. 130–133 acerto sob perda. 202–205 tradução de endereço. American Standard Code for Information associatividade. 495 gráficos. 133 operandos. A-620 operações em formato R. 494 backups de fita magnética. 183–184 40–41 bits. 13. 325. A-601 flash. 133 ponto flutuante. 181–185 provisão de recurso da rede. 182 Application Programming Interfaces (APIs) de pico. 439 205 Interchange. A-603 interface de hardware/software. 202 registradores arquiteturais. 548 modos de endereçamento. A-627 princípio. A-578 multiprocessadores. 464–467 benchmark de CPU SPEC. 127 entrada imediata com sinal. 465. 462. 13 CPI. 38–39 básica. 131 significandos. modelo roofline. 437 desempenho. 254–256 adição. 325 com dígitos de guarda. B-638 locais de posicionamento. 71 conclusão. 470 criação. A-584 definição. 217 gerenciamento de threads/blocos de aumentando. 391 arquivos executáveis. 321. B-638–B-639 definição. B-634–B-635 modificados. slots informação de depuração. 369 threads. 111 bits tempo de busca. 36–38 buffers de escrita ponteiros versus. 111 padrões. 100 bit mais significativo não volátil. A-584 produção do link-editor. 391–392 válidos. 2. 465–467 representação de caractere. 113 E/S. 253 373–374 thread. 41 loads/stores. 366 (SFUs). 215–216 array de processador. tamanho de tag versus. 255. 324. 126 segmento de texto. 424–425 bancos de registradores. 533 definição. 465 ilustração. 250 B exploração de localidade espacial. 113 processador-memória. 78–79 referência. 210 guarda. 465 número binários versus. 402 densidades. 475 endereçamento. 391–392 bits menos significativos instruções de thread. 471. B-661 bytes modos IEEE. B-637 definição. 387–389 definição. 419–420 cálculo de endereço de desvio. 404 ordem. 113. 404 ilustração. 387. 70 ISA. 41 backups. 72–73 bloco básico. 539 buffer de frame. 383 bits. B-661 . A-596 associatividade sinal. 113 multiprocessador. 538 buffer de renovação de rastreio. B-630 benchmark de servidor de arquivos (SPECFS). A-592–A-595 teste de adição de ponto flutuante. 219 bits sticky. 537 escalonamento. 480–482 definição. linguagem definição. 215 big-endian. 97 bit de referência. 464 definição. 15. 469 posicionamento flexível. 145 backpatching. 85–86 multithreading massivo. 12 tabela de símbolos. 61. 385–389 arquivos de registradores barramento processador-memória. 215 SPEC CPU. 475 características. 469 seleção de substituição. 537 definição. 217 arquitetura de multiprocessador quando utilizar. 389–391 proteção. 537–539 Bubble Sort. A-592–A-595 barramento backplane. B-663–B-690 erro. 464 linguagens de alto nível versus. 470 taxa de perda. A-588–A-589 atalho de negação. 308 link-edição. 113. 417–418 mantendo. 417 sticky. mapeando endereços para. 475 arquitetura de GPU unificada. 114–116 multicores. A-591 cabeçalho. 385 estratégias de posicionamento. 87 blocos processador streaming (SP). 133 história. 369 SIMT. 66. 306 informação de relocação. 469 compartilhamento de memória. 111 definição. 7. A-596 aumentando o grau. A-596 calculando. 464 MIPS. A-582 arquivos-objeto. 418–419 arquitetura do conjunto de instruções definição. instrução. B-634–B-635 prontos. B-635–B-636 ALUOp. 36 branch delay. 546 buffers de reordenação. 374 únicos. 537–539 stalls. B-630 481 gerenciando. 78–79. 469 blocos de thread. 215 bit de modificação. 387 ARM. 369 latência de rotação. 113 paralelos. 217 Stream. 539 buffers de armazenamento. A-575 programas. B-636 benchmarks bolhas. suporte para máquina virtual. A-585 arquivos fonte. 128 SPECrate. 69 setores. 301 formato. definição. 385 definição. 113 NAS paralelo. 248. 217 bit de erro. 425–426 balanceamento de carga. 7 armazenamento não volátil. 253 barramentos. A-575–A-576 produção. 265 dados válidos. 97 bit de validade.694 Índice remissivo armazenamento de disco. 113 Linpack. 130–133 estratégias de substituição. 98 bit de sinal. 217 multiprocessador. 481 sincronização. 391 definição. 12 arrays PARSEC. 38–39 cache write-back. 217 trilhas. 589tunidades de função especial Average Memory Access Time (AMAT). 385 encontrando. 472 usados menos recentemente (LRU). B-638 benchmark de servidor Web (SPECWeb). 496 localizando na cache. A-575–A-576 ponto flutuante. B-630 busca-e-incremento atômico. 475 multithreaded. 374 definição. 71 interfaces. A-587–A-588 atalho de verificação de limites. ordem de byte. 464 Assembly. 465 símbolos. B-630 backplane. 248 barramento síncrono. 66. A-592 em caches. 464 desvantagens. A-595 atraso no pior caso. 8 arredondamento. 467 definição. A-591 conjunto. 514–515 multiword. 377 procedimentos para definir como zero. 376 arredondamento SPLASH/SPLASH. 262 segmento de dados estático. A-587 traduzindo para linguagem de máquina. 531–552 branch-on-equal. 66 preciso. 464–467 ASCII bit de pronto. 754. 216 bibliotecas de programas. 325 dimensão múltipla. B-643 síncronos. 127–130 SPEC power. 256 tempo de transferência. 402 comparação de multiprocessador. 252–254 compilando loops while na. 373 Ver também caminhos de dados MIPS. 408 local de bloco da memória. 376. 420 branch-on-equal. 89 Cg. 420 em operação para instrução definição. 130 faltas. 393 nos estágios da instrução load. 382. 419 unidade de controle. 420 equação de desempenho clássica. 385 operações. 409 definição. 247–254 atraso no pior caso. 370 buffers de escrita. 62–63 definição. 22. linguagem caches de mapeamento direto tratamento de exceção. 64–65 local de bloco de memória. B-654 locais. 283 tempo. 410 write-through. 22 não bloqueantes. 12 localizando blocos. 387 caminhos de dados de ciclo único hierarquia de tradução. 262 carga. 77 divisão. 24 multinível. 386 carga. 382. 251. 325. 97 fisicamente marcadas. 373. 252 convenção. 409 desvio. 420 representação ASCII. 370 definição. 254 número de registradores. 373 desempenho. 265 duas vias. 260 ciclos de clock definição. Ver circuitos integrados (ICs) caches associativos em conjunto. B-643 FSM para controlar. 385 caracteres fisicamente endereçadas. 93 Ver também caches com sinais de controle conectados. 387 operação. 259 compilando. 377 co-processor 0. 16 inconsistentes. 375 caches write-back caso comum rápido. 376. 392–393 campos campo de tag. 247 C. 393 partes de endereço. 391 pipeline. 258–262 definição. A-579–A-580 simulando. B-655 esvaziando. 393. reduzindo. 62 partes de endereço. 285 associativas em conjunto. 116 GPU. criando. 419 para arquitetura MIPS. 378 caches sem bloqueio. B-661–B-663 virtualmente marcadas. 25–26. 26–28 memória virtual e integração de TLB. 368–382 caches divididas. 368. 264 stall de memória. 389 caminhos de dados em pipeline. 12 preservação por. 385 montagem. compilando no MIPS. 379–382 linha de controle. 260 dois níveis de caching. 408 estratégias de substituição em bloco. 385 únicos. 91 centros de dados. 370 penalidade de falta. 396 instrução store. 436 instrução load. 375–377 caches totalmente associativas registrador de Status. 311 algoritmos de classificação. 377. 386 ilustração. 249 ciclos de clock de stall da memória. 112 ilustração. 387–389 complicações. 93 virtualmente indexadas. 382 projeto de sistema de memória. 23 406–409 caixas de pizza. 419 em Java. 84–85 escolha. 308 bits. 385 para instruções tipo R. 391 único ciclo. 377 Central Processor Unit (CPU) Intrinsity FastMATH. B-646 virtualmente endereçadas. 437–438 caminho de dados de desvio chamadas de procedimento tamanho. 420 para instrução de salto. B-647–B-653 vazias. Índice remissivo 695 C quádruplas. 409 dois despachos estáticos. 409 corrigidos. 370. 436 registrador Cause. 64 estratégias de substituição de bloco. 288 acessando. 392–395 cálculo de execução/endereço tempo do sistema. 75 controlador de disco. 409 escolha. 291 caches. 369 definição. 274 n-vias. 372 ALU. 393 campo de condição. 479 definição. 127 comparador único. 382. 393. 389–391 stalls. 395–396 MIPS. 370 execução de instrução. Ver também caches medições de tempo. 387. 376. 252 chamadas do sistema. 277 atribuição. 277 tradução para linguagem assembly do número total de bits. 389 para resolução de hazard via forwarding. 276–288 variáveis. 420 definição. B-654. 22 primárias. 409 flash. A-598 Ver também caches cartões de memória removíveis baseados em ilustração do conteúdo. 276–288 Ver também caches projeto. 378 com sinais de controle. 100–101 fisicamente indexadas. B-661 Ver também blocos em operação para instrução load. 23 escolha. 261 chips. 385 vantagens. 251 exemplos. B-645–B-653 totalmente associativas. 370–374 caches endereçadas fisicamente. 377–378 complexidade. exemplo. 89. 389 carregadores. 288 Ver também processadores resumo. 387–389 para instruções de busca. 253. 279 associatividade. 386 para instruções de memória. 371 caches virtualmente endereçados. 393 . 281 tempo do usuário. 377. 368. 382 callee. 396 caller. 253 ciclos de clock por instrução (CPI). programa shader de pixel. 278 tarefa de compilação com registradores. 383 local de bloco da memória. 143 índice. 382. 467 resumo. 426–434 perdas. 318 código. 297 um nível de caching. 370 caminhos de dados frame. 489 tempo de execução. 383 falhas. 23. 285 bits necessários. 392–395 definição. 2 secundárias. 385 caches multinível ilustração. B-655 escritas. B-662 write-back. 76–77 definição. 383 desempenho. 13. 22–23 mapeadas diretamente. B-654. 368 Ver também caches nomes. 385–386 em operação para instrução tipo R. 288–292 Ver também chips específicos computadores terminando. 288. 74 caches. 432 reduzindo o overhead. A-571–A-572 ALU. 111 atualizações de instrução. 225 decodificando linguagem de máquina. 143 dados estáticos comparações. 11 kernels. matriz. 517 aritmética. B-644 operandos constantes. A-582 código de correção. 33 template paralela plus-scan. A-582. 77 definição. 458 linhas de controle. 320 . A-582–A-585 esquemas de imposição. 430 definição. 509 desktop. 17 princípio do computador. A-569 pipeline. 87 conjunto de trabalho. 320 loops while. 431 design. 209–214 contadores de programa (PCs). 144. 12 A-580–A-585 problema. instruções de atribuição. 488 definição. 430. 432 computadores laptop. 432 comunicação. 295 criação de desvio. 17–18 sincronização de barreira. 518 embutidos. 322 ilustração. 2–4 ilustração do esboço. B-636 controladores de disco desdobramento de loop complemento a um. B-667 revolução da informação. 31 instruções move. A-571. A-571 instrução de ponto flutuante. 308 dependências em pipeline. 269 A-580. 79 CUDA. B-682–B-683 organização de componente. migração. 320 A-613 tempo. A-582 consistência. ambiente de programação SDK. 320 Compressed Sparse Row (CSR). ambiente de programação. 85–86 confiabilidade. 141 protocolos. 78. 106 C. 60. 254–256 circuitos integrados (ICs) definição. 520 componentes. 293 Just In Time (JIT). 264 processo de manufatura. 513–514 B-634–B-635.696 Índice remissivo ciclos de stall de escrita. 180. 4 programação paralela escalável com. 2 controle em pipeline. 485 computadores desktop hierarquias de grupos de threads. 293 procedimentos. 32 codificação princípios. 292 função. B-634 Cooperative Thread Arrays (CTAs). A-591 co-processadores laptop. 383 aplicações visuais. 8800. 410. A-582 if-then-else. B-632 mudando com desvio condicional. 289 organização. 211 representação da instrução. 383 computação GPU controle ciclos de stall de leitura. 2 desenvolvimento. 465 para pipelines de despacho múltiplo. A-580. 391 desafio de speed-up. 84–85 x86. 308 data race. 92–93 consoles de jogo. 288–292 definição. 279 entre registradores de pipeline. 288 desvantagens. 416 definição. 510. 141 servidores. 249 sequência. 74–80 abstrações de chave. A-595 replicação. 433 MIPS-32. B-634 memórias compartilhadas. 9. 111. A-596 475–475 conceito de programa armazenado. crescimento. controladores de canal. B-654 medida de projeto. 294 definição. 89. 215 montagem em rack. 26. 89. A-586 protocolo snooping. 533. linguagem. 16. 143 dependências procedimentos recursivos. 75 ilustração. 462 dados dinâmicos. 549 princípios. 316–317 incrementando. 27 entre registradores de pipeline e entradas programas de ponto flutuante. 302 isolamento. 262 clusters aplicações. A-570 desafio. thread. 433 balanceando a carga. 247 inserção de bolha. 130 projeto para pipelining. Ver programas. 5 paradigma. 84 definição. A-582. 227 dependência de nome. 320 especulação. 42 cores definição. 301 definição. 111 ARM. 512–515 otimização. 247. 9 número por chip. 80 D Compact Disks (CDs). 430–433 computadores embutidos memória compartilhada por bloco. 109 compartilhamento falso. 433 Compute Unified Device Architecture. 60 commit na ordem. 294 compiladores. A-574 detecção. 94 compare e swap atômicos. 514–515 produção de linguagem de máquina. 9. 10 Ver também controle overhead na divisão da memória. 62–63 NVIDIA GeForce. 83 Pseudo MIPS. A-615 coerência. A-595 threads. A-619 código de máquina. 79 compactação de estrutura de dados. A-582 instrução MIPS. 227 decisão adiada. 12 copy back. 309 custo. 2 implementação plus-reduction. 467 definição. 412 nome. A-582 código de função. 179–228 especificando. 84–85. 275 compilação MIPS. C. A-607 decomposição do problema paralelo de dados. A-617 comandos para dispositivos de E/S. 431. 247 da ALU. A-571 instrução x86. 19 (GPUs) para instrução de salto. 465 renomeação de registrador. 119 Content Addressable Memory (CAM). 107. 35 Ver também Graphics Processing Units forwarding. 92–93 contador de instruções. definição. Ver write-back co-processador 0. 7 exceção. 432 requisitos da aplicação. B-644 com sinal versus sem sinal. 478 problema maior. 86 conjuntos de instruções segmento. A-586 coerência de cache. 2 definição. 518 classes de aplicação. A-612. 130 controladores de cache. 34 computação visual. 2. 2–4. 432–433 CUDA. 381 impacto sobre desempenho do processador. 192 solicitações. 192 processamento de transação. 20–22 alterando o contador de programa com. 288 Dynamically Linked Libraries (DLLs). 192 componentes. 19–29 pipelines de cinco estágios. 381 desempenho de classificação. tempo de resposta. síncrona (SDRAM). B-668–B-669 Ver também benchmarks . 480–481 terminando. B-658 processadores. 252 discos rígidos híbridos. B-658 adiados. 87. 461 definição. 308 tempos de acesso. 275. 286 velocidade. 16 desempenho da cache. 498 suposição. buffers. 475 escalonamento de código. 192 medindo. 88 DRAM síncrona (SRAM). 479 endereçamento. 192 definição. B-658–B-659 vazão. 209. 468 padrões. 192 equação clássica da CPU. 481–482 limitações de escalonamento. 12 calculando. 250 discos magnéticos. 314 arredondamento com. 485 crescimento de capacidade. A-611–A-612 reduzindo. 251 definição. Ver também desvios condicionais divisor. 473 destino do desvio diretivas de leiaute de dados. 461. 16 elementos afetando. 22 implementação. 492. 16. versão melhorada. 320–322 Direct Memory Access (DMA) E/S controlada por interrupção. 478 uso. 195 armazenando. 481–482 definição. 479 E/S. 193 transações. 191–197 taxa. 15 instruções. Índice remissivo 697 desempenho. 83 divisor. 19–20 solução do hazard de controle. 314. desvio tomado cabeça de leitura-escrita. 35 definição. 286 GPU. 382–396 clock. A-577 chip sets. 194 Web. 16 medidas de desempenho. 496 desvio não tomado definição. 470 pipeline. 317 múltiplos dispositivos. 28 ilustração. A-597–A-598 383–384 ilustração. 302 discos rígidos impacto no desempenho do sistema. 477 definição. 381 razão. 216 E desdobramento de loop. 306. subindo. 379 throughput. 16 largura de banda. 28 endereçamento relativo ao PC. 480–482 condição. 252. 84 disponibilidade. 478 E/S mapeada na memória estático. A-611–A-612 286 tamanho. 302 dispositivos de entrada. 118 despacho múltiplo. 308 mais rápida. 193–195 E/S. 316. 22 compilando if-then-else em. resto. 87 hardware. 304 dividendo. 21 Digital Video Disks (DVDs). 475 pacotes de despacho. 83 Dynamic Random Access Memory (DRAM). Ver bits tardio. 498 execução no estágio ID. 471 criação de compilador. 23–25 em loops. 28 Ver também desvios ponto flutuante. 251 tecnologia. 316. 483–488 decisão. 382 tempo de acerto. 103 Double Data Rate RAMs (DDRRAMs). 77 dicing. 382 desempenho do programa definição. 314–322 dígitos de guarda definição. 286 Double Date Rate (DDR). B-632 475–476 endereços. 306 instruções. 302 diâmetros. 304 divisão. 35 116–117 desempenho máximo de ponto flutuante. B-686 CPU. 83 algoritmo. 17 direções futuras. 103–105 dispositivos de saída. 381 relativo. 117. 533 dígitos binários. 275 operandos. 15 483–484 definição. 16 desempenho. 15 mapeada na memória. 26–28 308 SRT. 385 diagramas de pipeline de único ciclo de clock. 320 definição. 323 Direct3D. 498 desvios ilustração. 22–23 definição. 22–23 desvios condicionais quociente. 304 365. 308 diretivas do montador. 195–197 avaliando. 195 instrução. 478. 316 transferências. benchmarks. 21 desviosem pipeline. 252 hardware. 103 termo. 475 desvio igual. B-639 comunicação do processador. 215 dinâmico. 319 configuração. 83 don't cares melhorando. 302–305. 20. 26 diagramas de pipeline de múltiplo ciclo de custo. 192 480–481 desvios adiados. 459 endereço de destino. 192–193 sistema de arquivos. 480. 17 versão da link-edição de procedimento despacho de threads. 20 detecção de erro. 20 usando equação. 286 definição. 540 dies. 85 dividendo. 286 largura de banda externa. entendendo. 493 incondicionais. 478. 10 problema de coerência. 384 cinco instruções. 462 paralelismo. 21 desvios incondicionais. 132 Ver também aritmética medição de tempo. 10 sistemas. 475 redução de custo. Ver discos rígidos controlada por interrupção. 317–320 definição. definição. 302 discos óticos controladores. 25–26 ARM. 475. 304 com sinal. 256 programa. 302–305 no MIPS. 117 desempenho relativo. 197–198 endereçamento por deslocamento. 376 interrupções versus. 404 na implementação em pipeline. 283 prioridades. 493 escalonamento de pipeline dinâmico. 414 281. 393 modos x86. 396. 376. 248 esquemas. 321 fraco. 309–310 combinacionais. 322 transferindo. 377 imprecisas. 247. 246 estendendo. 310 base. no esquema de previsão de 2 bits. 376 na arquitetura MIPS. 105 definição. 102–109 baseada em hardware. 317 complexidade do desempenho. 472 especulação baseada em hardware. 397 Ethernet. 105 problemas. 136. 281 vetor versus. 482–483 entradas. 476–477 mapeando. 322 expansão forte. 377 instruções. 306 definição. 103. 516–517 tipos de evento. 411 determinando o reinício. 460 base. 461 imediatos de 32 bits. 387 definição. 317 exemplo de shader de pixel. 322 exclusive OR (XOR). 105 espelhamento. B-655–B-656 elo mais fraco. 65 instrução load. 316 definição. 105 especulação baseada em hardware. 105 especulação. 439 exception enable. B-672 intermediário. 416 motivos. 399 extensão de sinal. 72 linha de controle. 105 mecanismo de recuperação. dispositivos endereços instrução store. 321 detectando.698 Índice remissivo E/S. 322 definição. tratamento da hierarquia de memória. 439 resultado devido a estouro na instrução clock. 439 definição. 375–377 PC. 497 espaço. 313 compartilhamento. 66 linha de controle. 325 registrador. 183 definição. 410. 398 detecção de exceção de overflow. 311–314 elementos de estado tratamento. 17. 311 endereçamento virtual. 514 endereçamento de registradores. 482 buffer de reordenação. 485 expansão saltos e desvios. 420 precisas. 247 espaço de endereços. 288 interfaces. 313 elementos cache write-through. 103. 256 instruções load. 105 definição. 247 físico único. E/S. 183. estação de reserva. 471–473 mapeamento. 397 EX. 477–478 endereços virtuais estágio do cálculo de execução ou endereço. 397 de banco de registradores múltiplos caminhos. 470 definição. 459 memória. 397 linha de controle. 475 byte. 246 expoentes. 279 expansibilidade. 183. 399 add. 498 definição. 98 105 estágio de acesso à memória extensões de multimídia endereço de retorno. 288 transferências. 313 248 espaço de endereços plano. 310 entradas. 105 componentes lógicos. 514 endereçamento intermediário. 515 endereçamento de base. instruções. 310–311 elementos combinacionais. interconexões causando falhas de página. 66 estágio de busca de instrução diversidade. 412 lógica combinacional. 18 processadores x86. 245 memória virtual. 396 instrução load. 528 . 498 definição. 291 comandos. 517 instrução store. 185 deslocamento. 461 endereços físicos. 89 instrução load. 515 105 estado expansão fraca. 281 avaliação de potência. 66. operandos de buffering. 310 474 unidade de commit. 497 unidades primárias. 515 Exception Program Counters (EPCs). 283 função. 316 execução fora de ordem modos do MIPS. B-689 caminho de dados. 252 não mapeado. 415 atalho. 102–109 instrução store. 252 complicações. 250 endereçamento pseudodireto. 321 associação. estágio E/S. 460 definição. 313 exemplo de projeto. 246. 415 taxa de transferência máxima. 283 características. 321 tratamento. 283 desempenho. 311 organização. 311 projeto. instruções store. 514. 312 Memory (EEPROM). 414 estágio de decodificação de instrução/leitura leituras/escritas. 105 especificação. 309–314. 247. 245 custo. 468 cache write-back. 109 imediatos de 32 bit. 491–493 conceito. 247 plano. 103–105 estações de reserva forte. 310–311 estado. sistemas tamanho. 515. 311 Electrically Erasable Programmable Read-Only escritas exemplo de computador em pipeline. 283 ilustração. 412 armazenando/acessando instruções. 321 estágio para salvar/restaurar. 316–317 exclusão mútua. 105 exceção. 317 processadores. A-579–A-580 relativo ao PC. 279 número máximo. 73–74 endereçamento relativo ao PC. 322 pseudodireto. 321 estouro. 473–479 virtuais. salvando/restaurando. 414 copiando. 376. 310 elementos do caminho de dados ID (ASID). 514. 397–398. 498 321–322 exceções. 105 desempenho. 322 caminho de dados com controles para história. 472. 310 responsabilidades do sistema operacional. 411 captura de endereço. 138 implementação. 246 compartilhado. 273 flexível. 436 estruturais. 365 operações da ALU. A-572–A-574 previsão de desvio dinâmico. A-629 desempenho de cache. 275 ciclos de clock de stall da memória. 494–495 para implementação de único ciclo. 77 modo gráfico. A-626–A-628 hazards estruturais. 8. A-572–A-576 previsão de desvio como solução. 292–302 tempo médio para (MTTF). 413 computação geral. 272–275. 385–389 aplicações N-body. 292–302 definição. 269 endereço virtual causando. 552–553 caminho de dados para resolução de deslocamento à direita. 94 fluxo de instruções da esquerda para a direita. 424 falhas funções de controle hazard de dados de uso de load. 199 procedimentos de suporte. A-627 técnica de decisão adiada. 262 controle. 528–534 soluções. 142 definição. 552 múltiplos resultados. 427 virtualizável. 529 forwarding. 368–382 definição. 273 substituição de bloco. 398. 293 handlers de interrupção. 132 resumo. 269 falta sob falta. 197. B-639–B-641 tipo J. 77 memória principal. 141 multiplexadores. 7–9 141–142 representação gráfica. A-574 redução branch delay. 411–416 definição. A569 hierarquias de memória 278 interfaces de programação. 462. A-627 uso de load. A-569 stalls. A-570 Ver também hazards Fast Fourier Transforms (FFT). A-628 com duas instruções. 414 como aceleradoras. 100 GPUs. A-571 heap definição. 317 definição. 437–445 formato de instrução tipo J. B-654 desempenho. 296 linguagem. A-571 desafios de projeto. 387 General Purpose GPUs (GPGPUs). 375 unificadas. A-577 definição. 530. arquiteturas do sistema. 421 interfaces e drivers. 421 implicações. 75 pipeline gráfico lógico. 530 falácias tipo R. 39 ALU antes. 512. A-571 hazards de desvio. 302 motivos para. 302 capacidade. 77 sistema de memória paralela. 269–272. 413 comercial. 423 formatos de instrução paralelismo. 366 formato-I. 529. 417–423 instrução de salto. 463 definindo. 298 cache associativo em conjunto. 496 General Purpose (GPGPUs). 419–420 aritmética de ponto flutuante. 496 gráficos de tempo real. 302–309 cache totalmente associativa. 269. 269–275 taxas de disco. 376 grades. 258 hazards. Ver hazards de controle Filebench. 308–309 na cache write-through. A-629 tipo I. A-580. 298–301 Ver também memória virtual dobrando o desempenho. 366 formato R. 257 tendências gráficas. 302 reduzindo com posicionamento de bloco Graphics Processing Units (GPUs). 269 perda de TLB. 269–272. 296 H desempenho de pico. 427 hardware virtualizável. 533–534 diagrama de estrutura. 269–270 handlers importância da compatibilidade binária controle. A-620–A-626 stalls de pipeline como solução. 292–302 para acesso a dados. 272 como camada hierárquica. A-576–A-586 estrutura. 60–63 MTTF. A-571 alocando espaço. 257 mapeando aplicações. 16 definição. 302 tratamento. 141 Ver também computação GPU baixa utilização usa pouca potência. 271. 283 fitas magnéticas. A-602–A-603 bloco (ou linha). 306–308 compulsórias. 297 halfwords. 389 gigabytes. 34. 77. 530. A-596–A-600 facilidades. 302 tratamento. 263 programando. 198. 250 memória. registradores de pipeline antes. 328 função do próximo estado. 375 A-601. A-577–A-578 estrutura comum. 530 definição. 463. 494 frações. A-571 hazards de controle. A-580 armadilhas. 269. 223 x86. 283 faltas de cache G forwarding. 222–223 hazard. 462 Fused-Multiply-Add (FMA). 366 . A-582 simplicidade. 103 interpolação de atributo. suposição de desvio não tomado. 94–97 histórico de uso. 530. 132 perspectiva. 272–275. 414 instruções poderosas significam maior funcionamento. 530–533 hazards de dados. 292–302 definição. A-626–A-627. 494 A-604 definição. Índice remissivo 699 F MIPS. A-574 múltiplo. 494–495 definição. 421 GPU. 88–97 pipelining. 217. história. 481 falácias e armadilhas. 297 hardware lei de Amdahl. 401 arquitetura NVIDIA. 269. 375 pipeline lógico gráfico. 530 definição. 103 software de driver. 382–396 ARM. dados. 16 geração GeForce série. 382 heterogêneas. 424 taxas de falha de disco. A-575–A-576 resumo de pipeline. 271. A-570 adição imediata sem sinal. 397 caches multinível. 302–309 tempo médio entre (MTBF). A-609 evolução. 612t–683f caches. 530 dependência de. operação. A-586 processadores estáticos de despacho conflito. 302–305 etapas. 272. 387–389 Ver também pipelining cache de mapeamento direto. 270 operações. 6 linguagem assembly para desempenho. 367 definição. 40 forwarding. 294 definição. 275 faltas de página. 248–249 identificadores de tarefa. B-685 hot-swapping. 100 campos. B-685–B-686 instrução de salto versus. verificação. 260 IEEE. B-677 identificadores de processo. B-679–B-680 comparação. 551 OR exclusivo. 302. 264 ID. 262 vetor. 89. 263 instruções load. MIPS. 361–546 desvio. B-672–B-674 estágio MEM. B-689 otimizado. 228 instruções de comparação. 313 B-682–B-683 paralelismo. 266–267 tomada de decisão. 413 formato de instrução. 754. 263 execução de desvio. 87 operandos caminho de dados em pipeline. B-684–B-685 variância. B-689 ilustração. 78 instruções de deslocamento. 182. A-594–A-595 operandos. 98 . 396–416 E/S. 103 subtração. 199. 67 acesso à memória. 261 informação de relocação. 249 ponto flutuante. 87. 302 explorando. 86 interligadas. 265 Ver também instruções aritméticas. B-639 lógicas. 58–178 MIPS. 395 load. 308 parâmetros de projeto quantitativos. B-685 halfword sem sinal. bloco. 546 negação. 411 salto. B-670 negação. 280 básicas. 100 comparação. padrão de ponto flutuante. 257 desempenho. B-668–B-669 instruções de manipulação de constante. B-667–B-672 conversão. B-667 instruções cientes da cache. 103 conversão. B-674–B-676 load half. 550 ponto flutuante (x86). B-686–B-687 movimentação de dados. 441 instruções de conversão. 66 add imediato. B-672 memória virtual. 282 busca. 278 instruções de movimento condicional. 487 lógicas aritméticas. 411 sequência de pipeline. B-685–B-686 manipulação de constante. B-671 caminho de dados para. 248–249 store. 65 If. 200 shift. B-672 subtração. estágio reiniciáveis. operação geral. 548 referência à memória. B-689 instruções de movimentação de dados. 60 instruções de desvio. 110 adição. 300 raiz quadrada. A-601 penalidade. 66 definição. 304 representação no computador. 67 Ver também instruções detalhes. B-688–B-689 definição. B-686–B-687 definição. 98 instruções. B-685–B-686 lista. 313 inclusão. B-667–B-672 compilando. B-679–B-680 adição. 547 ponto flutuante. 430–433 fluxo da esquerda para a direita. 263 instrução store. B-680–B-682 definição. 263 ponto flutuante. 74–80 implementando. 65. 111 cientes da cache. 63 A-595 estágio IF. A-592. 280 assembly. B-672 divisão. 66 implementação de único ciclo thread. 285 informação de depuração. 83 definição. B-677–B-679 pipeline. B-689–B-690 desempenho SpMV. B-688–B-689 pares de nível. 416 lista. B-671 instrução de desvio versus. A-592 offset. 80.700 Índice remissivo hierarquias de memória (cont. 217 sinais eletrônicos. 366 introdução. 298 caminho de dados em operação para. 252 modelo roofline. A-593 instruções de jump. 67 função de controle. B-684–B-690 valor absoluto. 110–111 instruções de transferência de dados If-then-else. 437 divisão. A-594– estágio ID. B-674–B-676 registrador de base. 221 truncamento. 308 load. B-686 I move condicional. 263–265 x86. 133 índice fora dos limites. 75 múltiplos níveis. 67. 262 tipo R. B-672–B-674 impacto do pipeline. 527 instruções load não uso da. 7. 83–88 Ver também ponto flutuante store condicional. B-688 características. 551 PTX. 98 como words. 65 instruções de trap. 83–88 Ver também instruções execução sem pipeline versus execução com transferência de dados. 190. B-679–B-680 codificação. 268 trap. B-638. 280 retomando. 417 imediatas. 209–211. 441 estágio EX. 74 instruções de tomada de decisão. 133–141 acesso. B-684 LBMHD performance. 304. B-638 instruções aritméticas caminho de dados na operação. B-674–B-676 exceções. 549 nop. 395 load ligado.) desvio condicional. 260 modos de arredondamento. B-689 desempenho básico versus totalmente operações lógicas. 25–26 instruções de flushing. 408 flushing. 60 lista. 243 controle e caminho de dados. B-687–B-688 IBM Cell QS20 multiplicação. B-671–B-672 load. 80–83 store. B-684–B-690 tempo de execução de programa. 130–133 instruções de acesso à memória. 83 store. 304 sem sinal. 248 com sinal. 85–86 lista. 63 definição. 75 instruções de conjunto. 110. B-671 load byte sem sinal. 282 bloco básico. B-669 multiplicação. B-672–B-674 estágio WB. 248. 102. 60 instruções de ponto flutuante. 280 resto. 302. 366 exceção e interrupção. instruções. 475 instruções de máquina. B-670. 67 desempenho com pipeline versus. 182. B-677 instruções de tipo R. B-677–B-679 instruções imediatas. 281 ARM. B-682–B-683 move. 302 load upper immediate. 67 instruções de negação. 551 latência ilustração da função. 119 orientadas a objeto. 118 definição. 310 otimizações. Ver blocos Ver também instruções store linhas de controle instruções por ciclo de clock (IPC). 477 linguagem de máquina loops. 100–101 linguagens orientadas a objeto mapeando aplicações. 406 traduzindo linguagem assembly MIPS para. 389 SRAM. 113–116. A-582. 257 TLB hardware for. B-642–B-643 básico versus totalmente otimizado memória. 380. 127 definição. 367 interrupções precisas. B-689 (LBMHD). 100–101 linguagens de programação mapa de MIP. 114–116 ilustração. 435 cache L2. 365 definição. A-612–A-626 Java Virtual Machine (JVM). A-582 busca de instrução. 549 tendência. 318. 426–430 Just In Time (JIT). compilando. 434 L decodificação de instrução/leitura de banco hierarquias de memória. 364 instruções. A-602–A-603 latência de uso espacial. 288 435–437 largura de banda no caminho de dados. 548 restrições. 288 caches. 309–310 latência rotacional. 319 load word. 311 definição. 546 rede. 12 interpretando. 546 largura de banda de bisseção. ordem de bytes. 12 objetivos. 408 MIPS. 412 falácia. 104–105 definição. A-603 hierarquia de tradução. 435 bisseção. 210 previsão. 40 locks. 306 processamento de leitura. 119. 276 Linpack. 552 combinacional. 380 arquivos executáveis. 113. 367 exceções versus. 7. 79 while. A-628 linkagem de arquivos objeto. 65. 106 desvios condicionais. 127 TLB. 130 variáveis. 84–85 taxas de perda de dados. 378. 378 definição. 246 definição. B-643 características. 465 localidade espacial. 476–477 Lei de Gresham. 367 interrupções definição. 13 loops for. processador. 291 instruções reiniciáveis. 436 configuração. B-640 caracteres. 75. 546 valores. 258. 130 mapas de bits. 247 Interrupt Priority Levels (IPLs). 311 performance. 64 armazenamento. 382 link-editores. 11 intensidade aritmética. 313 Lattice Boltzmann Magneto-Hydrodynamics definição. 546 pipeline. 364–365. 260 Intel Nehalem definição. 251 K linhas. 550 instrução. B-630 definição. 465 little-endian. 535 etapas. 498 write-back. B-643 desempenho do SpMV. 288 tradução de endereço. 11. 365. 84 377–378 decodificação. 8 uso. 377 ponto flutuante. 12 strings. 528. 117–119 linguagens de shading. 39 lógica interrupt enable. 554 Ver também Java controladores. A-578 objetivo. 470 latência de instrução. 374 precisas. B-632 macros Java benefícios. 260 foto do processador. 247 mais altos. 314 kernels acesso à memória. B-640–B-641 bytecode. 379. 103 caches. B-630 for. 535 três estágios finais. 364. 113 desempenho do LBMHD. Índice remissivo 701 unidade para implementação. A-586 ativadas. 289 Intel Threading Building Blocks. B-632 linguagens de alto nível. 219 execução/cálculo de endereço. 540 rotacional. 183. 318 princípio. 113. 114–116 desempenho. 118 importância. 313 lei de Amdahl. 512 tendência. 313 corolário. 365 vetorizadas. iniciando. 291 Intel Xeon e5345 externa à DRAM. LAPACK. 384. 364–365 imprecisas. 435–437 de registradores. 549–551 exploração de bloco grande. 537 modelo roofline. offset de desvio. 364 interrupções imprecisas. 130 máquinas de estados finitos (FSMs). 382 uso. 550–551 localidade temporal. 329 usando. B-630 algoritmos de classificação. 117 Ver também linguagens específicas definição. 516 interrupções vetorizadas. 128 processamento write-through. 482 Liquid Crystal Displays (LCDs). 7–9. 429 . 78–79 M J linguagem fonte. 535 definição. 127 definição. 310 uma instrução. 313 definição. 413 CUDA. 8 teste. 367 tipos de evento. 84–85 Intrinsity FastMATH. 119. A-615 E/S. 551 definição. 8 exemplo. 551 memória. 364. 408 ilustração. 228 componentes. 319 temporal. 477 Lei de Moore. 67 interconexão assíncrona. 68 programas. 288 técnicas de redução de penalidade de falha. 626t–683f lógica combinacional. compiladores. 9 definição. 329 localidade interpolação de atributos. B-661 intercalação. 190 Mean Time To Failure (MTTF). A-612–A-614 endereços físicos. 429 caching. anatomia. 246. 65–66 definição. B-667–B-672 máquinas virtuais (VMs). 78. 60. A-599 B-672 melhoria do desempenho. 109. atômica. 404 modos de endereçamento. 227 arquivo objeto. 468–469 metodologia de clocking.) por CTA. 317–320 ponto flutuante. 242–244 GPU. 131 memória implementação da proteção. B-641 volátil. 11 CUDA. B-630 stalls. 113 secundária. 412 meia precisão. 72 metodologia de clocking disparada Ver também MIPS espaços. máquinas. B-638 bancos de SRAM. conjunto de instruções básico. A-600 endereços de memória. 61. 96 co-processadores. 409–411 sintaxe do assembler. A-622 despacho múltiplo estático. 550 integração. B-682–B-683 n-body. 246. 144. 429 definição. 424 nivelamento de desgaste. B-630. B-644 estáticos. 381 milhões de instruções por segundo (MIPS). 404 registradores de controle. Ver memória principal exceções. 15 compilando atribuição C complexa tabela de símbolos. A-600 compilando instruções de atribuição C Moore. 391 resumo. 145 montagem de código condicional. B-663 para controlador de cache simples. B-640–B-641 uso. 247 MIPS. A-615 para. 246–247 arquitetura. estilo. 325 módulos. 12. 397 linguagem de máquina. 549. B-636–B-641 SDRAM. 16. 79 instruções. largura de banda. B-672–B-674 benefícios. 463 memória secundária. 15 núcleo aritmético. 406–409 suporte a diretiva do assembler. B-682–B-683 definição. 427 memória física. 468–469 formatos de instrução. 432 montadores. 242–244 definição. B-663–B-664 operandos. 243 eficiência. 427 memória de textura. 397. 385 alocação de memória para programa função. B-663 detalhes. A-585. 61 falácias. 76–77 macros. 62 mouse. B-630 principal. B-660 NOR. 326 modos de endereçamento. CAM. 195–197 definição. A-599 divisão. B-638. 196 global. 410 não volátil. 468 instruções aritméticas. 398 ilustração da implementação. 15 instruções de salto. 462 Ver também memória multiplicação. 379. A-585. B-682–B-683 memória de baixa latência. 7. 396–397 MIPS. B-644–B-645 classes de instruções. 228. 462. 421 local. 13. 468 instruções de desvio. 132. 18–19 e dados. 396 pseudo. B-636 tecnologias para criação. 424 memória não volátil. 113 sistema paralelo. ilusão. B-667 Moore. conjunto de instruções. B-663–B-664 Mean Time Between Failures (MTBF). 15 migração. 245 constante. B-660 memória primária. 246 modelo de consistência de memória. 468 FPU. 113. B-637 memória compartilhada para.702 Índice remissivo máquinas de estados finitos (FSMs) (cont. 247 mix de instruções. 380 métodos 433 layout. 75 Mealy. A-600 microarquiteturas modo kernel. 379. 368–396 motivações. A-585. 15. 112–113. caminho de dados para. 12 virtualização. 365. 424–425 definição. A-599 por transição. 416 228 compartilhada. 426 memória global. máquina. 60. A-615 conjunto de instruções. 401 semelhanças do ARM. 462. 243–244 endereços. 310–311 Mealy. 429 tabelas de página. 41 aceitação de número. A-585 mecanismo. A-600 campos. 396–416 codificação de instrução. 78–79. 226 avaliações. instruções. B-666 matrizes esparsas. 518 memória volátil. core flash. 429 memória constante. 246 conjunto de instruções. 423–426 EEPROM. B-677–B-679 simulação. 416 B-664–B-667 cache. 225 move. 15 MIPS-32. B-639 textura. 227 Mean Time To Repair (MTTR). 397 mapeamento de instrução assembly. 381 Ver também páginas visão abstrata. A-596–A-600 MIPS. A-585 convenções de registrador. 429 memória flash. 468 instruções de comparação. A-600 tradução de endereço. 16. 107. A-600 instruções de ponto flutuante. A-599 definição. B-644 modelo dos três Cs. 425 memória local. 426 subconjunto. B-674–B-676 definição. A-600 102–109 função do próximo estado. 226. 484 memória virtual. 15 mapa de opcode. 396. 253 por previsibilidade. 94 informação de relocação. A-585 CPU. 396–416 operandos. B-667–B-672 suporte à arquitetura do conjunto de memória principal. 62–63 velocidade. B-667 pseudoinstruções. Ver memória principal instruções lógicas. 427 Ver também memória endereçamento para imediatos de 32 bits. 242–243 DRAM. 463 escritas. B-663–B-690 definição. B-641 virtual. A-585. 397. B-687–B-688 . 15. 28 instruções. 494 definição. 468 instruções de manipulação de constante. B-664–B-667 afinidade. 209–211 para melhoria da proteção. A-585. 530 disparada por transição. A-601 faltas de página. 66 implementação. 15 visão geral. 404–406 implementação. A-599–A-600 segmentação. 429 características. 15 AMD Opteron X4 (Barcelona). 546 sinal e magnitude. 217 operandos constantes. 533 coarse-grained. 522 conjunto de instruções. A-623–A-624 NVIDIA. 70 MIPS. mais rápida. A-577 Ver também aritmética níveis de prioridade. 71 em comparações. 187–189 Streaming Processor Array (SPA). 81–82. A-607 hardware. 537–539 NOT. 65–66 características. 191 Newton. 516 operações multiprocessador Tesla. 187 GPU. 209 fine-grained. implementando. 187 NAS (NASA Advanced Supercomputing). 218 ocorrência frequente. 186–191 Special Function Unit (SFU). 82–83. 31. 521–524 números desnormalizados. A-611–A-612 multiplicação de ponto flutuante. A-588–A-589. 515 números binários constante. 300 atômicas. 133 memória compartilhada. B-688 resultados. A-620 O operandos. 68–74 memória. 74. 68 Ver também instruções . 523 desempenho. B-669 n-body Texture/Processor Cluster (TPC). 71 divisão. 530–533 multiplicando. simulação. 68–74 shifts. 80–83 benchmarks. 5. A-609 etapas. 215 OpenGL. 511. 243 multithreading simultâneo (SMT). 547 conversão de números binários para. definição. A-622 ponto flutuante. 205–207. 82. A-608 multiplicação. B-667–B-672 passagem de mensagens. 257 paralelismo em nível de thread. 190 matemática. 189 slots de despacho não usados. 468 hardware. 197 definição. 517–521 notação imparcial. 523 processador streaming. 86 multicore. 471 lógicas. A-605–A-612 controles. 522 números não sinalizados. 260 rápida. 521. 187 otimização. 515–517 para reais. 75–76 operandos. 76 imediatos de 32 bits. 31 conversão para números hexadecimais. 207 definição. 523 definição. A-602 instruções. 192 multiprocessadores multicore. NOR. 76 Multiple Instruction Single Data (MISD). 521–522 estatísticas de aproximação de função ilustração. 510 desnormalizados. iteração. 187 nivelamento de desgaste. operação. 532 nops. 468 operação de memória atômica. 219 (MIMD). 5. A-585 multiplicando. 525 fine-grained. arquitetura de GPU. 136–140 A-596 north bridge. 512 especial. 187 Nonuniform Memory Access (NUMA). 189 N Streaming Multiprocessor (SM). A-622 definição. 65 definição. 510 notação científica AND. 63–68 (SMP). 202 MIPS. 182 multithreading coarse-grained. 82–83. 68 instruções aritméticas. 523 algoritmo all-pairs N-body. 190. 521–524 rasterização. 80–83 definição. A-620 A-606–A-607 multiplicador. 67–68 espaço único de endereços físicos. 510 tratando como sem sinal. 80–83 organização. 75–76 definição. A-625 definição. 511 decimais. 524 definição. A-608 significandos. 188 uso da memória compartilhada. A-605 instruções. 71 somando. 516 conversão para números decimais. 87 multiplicação. 63 546–552 números com sinal. B-671 operações lógicas. 516 com sinal. 521–522 números hexadecimais. 555 números NOT. 553–554 definição. 521. 210 organização do sistema. 205 hardware. 515–517 sem sinal. A-624–A-626 opcodes primeiro algoritmo. 521–522 definição. 206–208 multithreading. A-607 no caminho de dados. valores de controle. 82. A-609 binária. 524 desempenho na classificação. 68 multiprocessadores de memória compartilhada hexadecimais. 132 sincronização. 253 simultâneo. 522–524 NVIDIA GeForce. 190 algoritmo all-pairs. 67–68 mudança de projeto. 427 multithreading fine-grained. A-608 multiplicação-adição (MAD). 522–524 cálculos de álgebra linear densa. 521. 61 definição. 68–74 controle de seletor. 197 ARM. 205–206 coarse-grained. B-670 inteiros do x86. 60–63 arquitetura multithreaded. 68 OR. 80 multiprocessadores computador versus mundo real. 510 binários. B-671 UMA. memória flash. 539 definição de linha de controle. B-670 perspectiva histórica. B-668 desempenho. 98 deslocamento. 68–74 compilação quando na memória. 75 multiplexadores opções. Índice remissivo 703 Multiple Instruction Multiple Data multithreading do hardware. 68. A-625 no MIPS. 8800. B-671 software. 522–524 ROP. 110 multiprocessadores NOR. 257 produto. 511. 297 definição. 187 dois soquetes. 187 comparação de desempenho. 517 somando números. 523 desempenho FFT. operação. hardware. 476–477 OpenMP (Open MultiProcessing). A-609 forwarding. 77. 547 números decimais ponto flutuante. A-587–A-588 escalabilidade. 205–209 suporte. A-609 multiplicação com sinal. 102–103 benchmarking com modelo roofline. A-601 simultâneo (SMT). 539 multiplicador. 509. 82. 521 conversão de números binários para. A-608 assinada. 515 ASCII versus. 200 NOR. 89. A-629 estágio de execução e cálculo de endereço. 198 tarefa. 286–288 underflow. 210 benefícios de desempenho. 182 determinação. 200 PARSEC (Princeton Application Repository for resumo. 127–130 definição. 269 representação binária. 421 arquitetura SSE2. 404 pipeline lógico gráfico. 212–214 multicore. 198 223–225 ponteiros de frame. 539 tempo de execução. 94 saturação. 324 impacto da instrução de desvio. 281. 328 potência relativa. 198 E/S. 283 GPU. 31. 397 AMD Opteron X4 (Barcelona). 183–184 perdas compulsórias. 269. 269–275 representação. 210 Ver também memória virtual diagramas de único ciclo de clock. 94 codificação de instruções. 42 definição. 33 estágio de decodificação de instrução overflow. 214 nível de dados. 209–211 posicionando. 222 paralelismo de tarefas. B-650–B-651 desvio. 374 frame. 272–275 definição. 215–216 pilhas cálculos imediatos. 397 pipelines formato empacotado. 93 ocorrência. 397 procedimentos recursivos. 524 estágios. 29 Ver também paralelismo falácias. 12 compilador.704 Índice remissivo OR. 209–214 multithreading. 220–222 paralelismo. 486 alocando espaço. 317 linguagem assembly. 265 relativa. 89 desafios. formato de ponto flutuante. redundância. 317 para argumentos. 70. padrão IEEE. B-641 hazards de dados. 276 subtração. 93 subtração. 485 melhoria de desempenho. 198 nível de processo. 89 paralelismo de threads. A-604. 267 precisão dupla paralelismo em nível de tarefa. 279. 209 modificadas. 276 Ver também precisão simples intercalada por bit. 201 disco. 30 exploração. 510 latência. 283 no x86. 197 perdas de conflito. 435–437 globais. 510 hazards de controle. 404 estágio de acesso à memória. 275 Ver também precisão dupla Shared Memory Computers). 441 hazards estruturais. 328–329 potência paralelismo em nível de dados. 525 gargalos de desempenho. 366 aumentando. 130 PCI-Express (PCIe). 399 despacho duplo estático. 324–325 paralelismo em nível de instrução (ILP) benefícios. A-585 armadilha. 314–325 estágio de busca de instrução. 216 thread. 325–327 frequência de instrução MIPS. A-627 paridade. 311–314 taxa de clock e. 314 definição. 199. A-604 paravirtualização. 283 operandos. 517–521 placas-mãe. 211 Packed. 486–487 projeto do conjunto de instruções. 222 definição. 226 definição. 267 registradores. 524 estágio de write-back. 91 ponto flutuante. 283 precisão. A-586 sequência de instruções. 302 sinal e magnitude. 298 unidades. 530. 91 dígitos de guarda. 30 paralelismo em nível de processo. 201 pacotes de despacho. 31. 222 P petabytes. 283 bidimensionais. 283 programas. 215 P + Q. 398 diagramas de múltiplos ciclos de clock. A-585 pipelining. 510 representação gráfica. 217 páginas modificadas. 324–325 eficiência. reduzindo. 209 nível de tarefa. 197–202 nível de instrução. 327–328 divisão. 324 exceções. 392–395 arrays versus. 441. 286 linguagem de máquina. 210 tamanho. 228 offset. 399 push. 517 visão geral. aumentando. 130 penalidade de falta ponteiros overflow caches multinível. 265 natureza crítica. 510 fórmula de speed-up. 485 hazards. 82. 486 instruções de execução simultânea. A-575 forma. A-586 analogia da lavanderia. 430–433 281. 525 avançado. 324 representação. compilando. 265 pop. 485–486 paradoxo. 421 ponteiros globais. 483–488 e leitura de arquivo de registrador. 126 definição. A-573 polling. 214 definição. 94 exceções. 71 Pentium. 265–276 otimização multiprocessadores. 314–322 279. operação. 286 multiplicação e adição reunidas. 209 localizando. 421 ponto flutuante. procedimento com matrizes hierarquias de memória. 402 pipeline de projeto digital. 182 perdas de capacidade. 276 ordem principal de linha. 269 precisão simples intercalada por bloco. 279–281. 314. 31. 269–272 FMA. 276 prefetching. 198 número físico. 219 GPUs e. pilha. jogada de moralidade do bug. 281. 128 detecção. 265 definição. 197 páginas pop. 311 técnicas de redução. 397 cinco estágios. 215–216 LRU. 198 parâmetros formais. 265–276 variação de operandos no x86. 267. 222 número virtual. 754. 89 conversão binário para decimal. 198 definição. 475 manual. B-671 passagem de mensagens vazão. 89. 549 . 270. 198 intercalada por bloco distribuído. 2 arredondamento. 200 emissão múltipla. 288 instruções MIPS. 306 instruções. 136 previsão de estado fixo. 112 definição. 536 swap. 308 despacho duplo. 120–125 512–515 redes. 111–119 redes multiestágio. A-592. 88 Java. desafios. A-608 usando. 525–528 protocolo de handshaking. 487 invocação de clone. 306 processadores. 100 definição. 307 Ver também processadores definição. 316–317 CUDA. 306 controle. 375 streaming. Índice remissivo 705 previsão processadores de vetor. 31 previsão de desvio estática. 308 despacho múltiplo dinâmico. 17–18. 484 316. 433 estado fixo. 308 especulação. 484–488 definição. 100 caminho de dados. 192 correlação. 18 compilando procedimento recursivo 516–517 multiestágios. 396 RAID 1 + 0. código. A-618 exemplo. instruções. 512–515 Ver também redes para definir arrays em zero. 111–119 redes crossbar. B-647–B-649 conjuntos de instruções de pipeline. A-593 estática. 306 despacho múltiplo estático. A-618–A-620 previsores de desvio de torneio. iniciando. 91 linguagem assembly. unidade de controle principal. A-576. A-601. 99. 488 conjuntos de instruções. 88 iniciando. 527 protocolos de invalidação de escrita. A-618–A-620 primeira word crítica. 525–528 A-601 compilando. 317–320 proteção RAID 0. A-595 push previsão de desvio dinâmica. 424 RAID 3. 393 implementação. 96. B-689 aninhados. 91–93 tecnologias para criação. 321–322. 269 (RAID). 32 Quicksort. 535 procedimentos aninhados. 536 recursivos. 320–322 definição. 485 processadores de despacho múltiplo estático. 471 desvio dinâmico. 308 despacho múltiplo. A-620 previsores de hardware dinâmicos. 239–329 loops. 526 protocolo snooping. 306. 274 superescalar. 553 totalmente conectadas. 187 GeForce. 485 Ver também despacho múltiplo VMs para. 485 . 393. 143 Redundant Arrays of Inexpensive Disks procedimentos recursivos. 119–120 dificuldade na criação. 306 extensões de multimídia. 275 escalonamento de pipeline. 128 traduzindo. 244–247 definição. 9. 393. 88–97 superescalar. processadores. 316 R precisão. 12 quantidade de deslocamento. A-608 cópia de string. 117–119 redes locais (LANs) folha. 8800. 527 conjunto de instruções. 316 Radix sort. 320. 96. 528 pseudo MIPS loops. 316. 247 redução. 531. 432. B-647–B-649 programas de processamento paralelo. 226 previsão de desvio processadores dinâmicos de despacho pseudoinstruções buffers. 12 Q Ver também hazards de controle como cores. 394. 531. 317 comunicação de E/S com. 493 pilha. 485 hazards de controle. 306 escalares versus. 409–411 RAID 2. 91 hierarquia de memória. 98–100 programas rasterização. 327–328 cálculo. 317 processadores streaming. A-595 Disks procedimentos. A-578 vantagens. 539 dinâmica. 256–262 popularidade. 536 mostrando. 227 precisão. 18–19 Raster Operation (ROP). 423 controlador PCI. 89 buffer de previsão de desvio. A-601 RAID. 518–519 remotas (WANs). 91 definição. 274. 317–320 definição. 274 execução fora de ordem. redes totalmente conectadas. locais (LANs). 112 como solução do hazard de controle. 320 Pthreads (POSIX threads). 94 processamento paralelo. 535. B-650–B-651 lógico. 512–515 largura de banda. 91–93 para espaço de endereços compartilhado. 92–93 produto. 321–322 resumo. 432–433 esquema de 2 bits. compilando. 317 função fixa. 317 implementando. 394 previsores de desvio definição. 306. 306–308 comparação de código convencional. 17 definição. 482–483 ilustração de exemplo. 275. 92–93 para passagem de mensagens. 317–320 torneio. 317 grupo. 18 frames. mostrando ligação de VLIW. 517 Ver também procedimentos comprometimentos. 522 raiz quadrada. instruções. 306 caminho de dados. 375 ROP. 318 informação. 12 quociente. 485 RAID 1. B-647 digital. 510 crossbar. A-608 definição. Ver Redundant Arrays of Inexpensive primeira word requisitada. 306–308 Ver também despacho múltiplo PTX. 536 procedimentos de folha programas de shader gráficos. 536 sort. A-605 definição. 8800. 89 vetor. 77 previsor de correlação. 535. 111 definição. A-576. A-601 procedimento aninhado. 306 GeForce. 493–494 strcpy. 484 Ver também procedimentos sistema de E/S. 306–308 array (SPA). 18 definição. 314. 308 crescimento do desempenho. 325. 307 múltiplo. 91 uso. 91 projeto redução paralela. 536 etapas de execução. 475–476 quad words. 485 com MIPS ISA. 316. 64 servidores memória compartilhada. 71 significandos. 214 589t–651f primitivos. RISCs controle. 431–432 espaços de memória. embutidas. B-636 Single-Instruction Multiple-Thread (SIMT). A-596 spilling. B-659 saturação. 311. 295. B-655 benchmarking de multicores com. 541 sinais desativados. 198 base. A-578 (RAID) (cont. 64–65 ilustração. 96 Opteron. 74 lingote de cristal. 545 definição. A-599 variáveis. rotina. 524 pipeline. B-671 vetor de dados. B-655 IBM Cell QS20. 258. 476. 246 registrador de controle do receptor. B-646 segmentação. 311. 546 overhead. 257. 246 B-659 Set Computer (RISC). A-582 destino. B-654 RISC. 33 convenções MIPS. 136 custo e capacidade. 376 acesso de load/store. 294. 90 exemplo de pixel. B-659 send message. 525. 109 definição. 64. 298 definição. 41 não resolvidas. 74 rótulos sincronização de desbloqueio. 202 resumo. 143 ilustração. 34 referências absolutas. 294. A-578 RAID 4. 113 atalho de extensão de sinal. 487 representação em complemento a dois. A-601 temporários.706 Índice remissivo Redundant Arrays of Inexpensive Disks dependências. 432 adição. B-659 definição. 398 execução e divergência de warp. 548 barreira. 66 Ver também RISCs de desktop e servidor memória global. 295 aritmética de ponto flutuante. B-630. 34 caches. 400 seletores de dados. 64 sem alocação de escrita. 2 memória constante. A-600 registradores de base. A-578 RAID 6. 247 registrador salvo pelo caller. B-642 definição. A-595 compilando a atribuição C com. 545 caminhos de dados em pipeline. 90 semicondutores. 477. 524. 464 memória local. 257 campos. 244 sistema de memória paralelo. B-645 com ceilings. 279 externos. B-642 resto arquitetura de vetor. 199 absolutas. B-659 Ver RISCs de desktop e servidor. A-590 Receiver Control. A-584 especificação numérica. B-658. 72–73 como tecnologia básica de hardware. 258 registradores desempenho de pico da memória. B-636 vantagem. A-596 definição. 73–74 silício forward. B-646 segmento de dados. 546–552 bits múltiplos. A-589 Receiver Data. definição. 542 unlock. B-636 sincronização de lock. A-598 Transmitter Control. 64. A-600 antes do forwarding. Reduced Instruction desativados. 279 globais. Status. ponto flutuante. B-658. 63–64 S arquitetura de processador. B-638 overhead. B-636 Single Instruction Single Data (SISD). B-645 Single-Program Multiple Data (SPMD). B-654. 325 desempenho de ponto flutuante máximo. B-645 com dois kernels. 71 wafers. 320 SCALAPAK. 183–184 escalonamento de warp multithreaded. A-595 mapeando. 192 no x86. B-645. modelo. A-598–A-599 . A-599 registradores de pipeline setores. reduzindo. 548 lock. ativados. B-655 segmento de texto. 410 sinais registrador contador. A-596–A-600 tempo de ciclo de clock. 325 definição. multiplicação. 113 regra. 288 registrador salvo pelo callee. 485–486 registradores temporários. sinal e magnitude. renomeando. 517 para comunicação de threads. 34 referências de forwarding. 296. 296 shaders MMU. 539–546 ALUOp. 476. 477. 543 sincronização de barreira. 462 533 link-editores e. 246 arquiteturais. 487 SIMD (Single Instruction Multiple Data). B-655 instruções. 517 considerações de DRAM. A-597–A-598 Transmitter Data. B-646 kernel intensivo de E/S. 486 replicação. 219 A-590 salvo pelo callee. 516 contador. A-579–A-580 RAID 5. 541 definição. 525 campos. 66 540 sincronização. B-636 atalho de negação. 249 rotina receber mensagem. 205 referências 70. 247. A-600 registradores arquiteturais. 257 Sun UltraSPARC T2.) seleção de unidade de forwarding. 259 ilustração. 525–528 registrador Cause. B-654. 66 simplicidade. 2 memória de textura. 34 referências não resolvidas reservas em standby. A-582. 311 restrição de alinhamento. 544. 109 metade direita. 477 com áreas sobrepostas sombreadas. B-630 restaurações. gerações. A-599–A-600 x86. 476 roofline. arquiteturas sinais de controle registrador de status. 109–111 Cause. 548 definição. A-591 salvo pelo caller. 477 retorno de exceção (ERET). 63 roofline computacional. 375 gráficos. 545 efeito. 70 definição. 109 convenção de uso. 486 reinício antecipado. 78. A-584. 259 registrador de dados do receptor. 476 definição. 298 locais. 109 metade esquerda. 67 segmento de pilha. B-638 A-585 tabela de página. B-654 Intel Xeon e5345. B-659 serialização da escrita. 15 solução para hazards de controle. servidor. 100–101 tags B-664–B-667 representação. 491 sistemas operacionais evitando com reordenação de código. A-615 estágio EX. A-601 ajuste. 553 definição. 321. B-659 Streaming Multiprocessor (SM). 119 Ver também procedimentos definição. A-572–A-574 stalls do pipeline. 190 uso de load. 511 271–272 supercomputadores. 402–404 GeForce. 121–123 store. 124 compilando com. 532 encapsulamento. 488 arquitetura. A-614. A-614 estágio IF. 546 software buffer de escrita. 481 unidade para implementar. 100 níveis. A-602 ponteiros. B-661 strings definição. 181–182 tail call. 182 superfícies. 280 versão de memória compartilhada. 113. A-607 VMM. 251 ilustração. 488. 120 preservando registradores. somadores carry save. 298–301 potência ociosa e máxima. 389 versões. 133 código do corpo. 298–301 superescalares software de sistemas. procedimento. 123 store word. uso de load. 399 SPECPower. versão. instruções Swap. 551 camadas. B-661 arquitetura de ponto flutuante. 494 stalls. A-614 estágio ID. 96 537–539 instruções. espaço. 13 superfícies. 121 definição. 36–38 lista. 383 ilustração. 67. 209. 120. 419 benchmark de potência. Ver previsão SPEC estágio WB. 257 definição. B-661–B-663 Stream. benchmark. 219 tabelas de página. B-671–B-672 taxa de acerto. 547 multiprocessador. ilustração de posterior/anterior. 493 disco. 400 SPIM. 271 conexões lógicas e larguras de banda. A-569 definição. 485 localizando bloco. B-680–B-682 tabelas de página. 549. 67 completo. A-612. 400 SPECratio. 465. 302 subtrilhas. 401 código para o corpo. 119–120 definição. 2 sistemas. Índice remissivo 707 ROP. em Java. 120–125 Static Random Access Memories (SRAMs) opções de multithreading. 284 de desvio. 280 T CUDA. 550 driver GPU. 402 Special Function Units (SFUs). 511 memória. 546 402–404 definição. 401 SPLASH/SPLASH 2 (Stanford Parallel subtração. 301 Sun UltraSPARC T2 (Niagara 2). 320 software paralelo. A-608 spilling de registradores. 523. procedimento. Sparse Matrix-Vector Multiply (SpMV). binária. 67 swap. A-596 definição. B-660 striping. 8800. 98 par bits de controle. B-637. 181–186 tamanho. 298 System Performance Evaluation Cooperative. B-660 definição. 6 hazards de dados. 256 suporte a diretivas do montador MIPS. 222 tabelas verdade recursos. B-659–B-663 Ver também procedimentos técnicas de redução de armazenamento. 124 bloco. 271–272 Sun Fire x4150. A-601 chamada de procedimento. 124–125 condicional. 89 ponto flutuante. B-661 Streaming SIMD Extension 2 (SSE2) tabelas de símbolos. detalhes. 182 Ver também Graphics Processing Units definição. 67 Ver também procedimentos south bridge. 404 definição. 98 memória principal. 38–39 ponto flutuante. B-689 atualizando. 402 SPECrate. 120 acesso. 522 alocação de registrador. 119–120 passando parâmetros. 284 tabelas de histórico de desvio. 490 armadilha de escalonamento do acesso ao 271–272 memória mínima. 91 overflow. 488–493 definição. 271 desempenho SpMV. 550 como serviço. 283 código serial. 383 desempenho. A-616 estágio MEM. 302 características. 271–272 definição. modelo roofline. 493 definição. 546 discos. 496–497 hazards de dados. B-661 subnormais. A-601 alocação de registradores. procedimento. 6 como solução para hazard de controle. 121 procedimento completo. 399 SPEC2006. 90 procedimento de folha. 510 evitando com reordenação de código. 471 dependência de instrução. 391–392 Applications for Shared Memory). 100 registrador. B-689–B-690 (GPUs) valores. 301 definição. 426 iniciação. 273 desempenho do LBMHD. 530 esquema write-back. 228 registrador de base. 36 Strcpy. B-638 ordem de byte. 273 básico versus totalmente otimizado Small Computer Systems Interface (SCSI). 366 . chamadas do sistema. 302 321–322 Sort. 98 definição. A-601 stack pointers número negativo. 255 simulação de máquina virtual. 6 inserção. 369 velocidade. 548 paralelo. 91 Ver também aritmética sistemas heterogêneos. 537 Ver também instruções load indexando. buffers benchmark de CPU. 6 inserção em pipeline. 385 escalonamento de pipeline dinâmico. A-570 stalls de uso de load. 99 invertidas. B-680–B-682 Ver SPEC 550. 110–111 definição. 414 saída. 18 handler. 374 Translation-Lookaside Buffer (TLB). 67 Ver também Translation-Lookaside Buffer conexões de pipeline. 93 LCD. 276 Video Graphics Array (VGA). A-602. A-589 latências de memória. B-656–B-657 vazão sincronização de barreira. 300 store. 405 no controle de atualização. 300 quad. 19 estáticas. 393 Intel Nehalem. thrashing. 537 definição. 414 unidades de controle. 64 problema. A-615 suporte de hardware do computador. 416 Ver também Arithmetic Logic Unit (ALU) duplas. 34 gerenciando. 34 criação. 93 locais. A-594 Ver também TLB. 109 Very Large-Scale Integrated (VLSI). 34 threads para implementação de load/store. 515 potência. 321 while. 418 TLB para. 550 ilustração. 20 tempo de acerto retorno dos. 84–85 warps. A-618 instruções de thread de GPU. 34 CUDA. 24 U processadores. 93 melhoria. processador. A-596 rank. A-628 buffer. 480 AMD Opteron X4. Ver Mean Time commit. 12 Intrinsity FastMATH. 65 ponto de entrada. A-592–A-595 valores típicos. 406 baseada em árvore. tempo de leitura de disco. Transmitter Control. 19 Very Long Instruction Word (VLIW) como medida de desempenho válida. 64 taxas de perda globais. 405 definição. 324 requisitos. 244 Ver também redes minimização. 23. 323 desempenho de cache. 536–537 A-574 frequência comutada como função da.708 Índice remissivo taxa de clock topologias de rede. 439–441 Time To Failure (MTTF) unidades na melhoria do desempenho. 480–481 global. 2 definição. 393 definição. linguagem C. 11 integração. 425 tempo médio para reparo. 100 atitude laissez-faire. loops. projetando. 254–255 tabelas de página. 378 Transaction Processing Council (TPC). 216 definição. detecção de hazard. 385 troca atômica. 435 usado menos recentemente (LRU) taxa de transferência máxima. tempo de busca. definição. 366 trilhas. 488. 404–406 páginas. 393 definição. 244. 256–262 acessando. 497 definição. 136 (TLB) funções. 462 alfabetos de exemplo. A-592–A-595 unidades de commit warps. 480 classe de armazenamento. 411 circuitos. 488. 416 A-608 wafers. 405 registrador. 404 variáveis estáticas. 378 Transaction Processing (TP) V definição. 489 dies. 34 ISA. 424 tempo médio para falha. 422 404–406 linguagem de programação. 298 load. B-655 definição. B-658 despacho múltiplo. 30 multiestágios. 317 pipelining. 41 definição. 93 telas gráficas ilustração. 465 alfabetos. 22. 404–406 cache repartido. 404 tipo. 420 taxas de falta rápida. 19 tempo de execução tubos de vácuo. 440 tempo médio entre falhas (MTBF). A-617 A-594–A-595 Transmitter Data. 29 tradução de endereço multiprocessadores. 64 tamanho de bloco versus. controladores. 321. 324 definição. A-615 instruções aritméticas. 321 Wide Area Networks (WANs) TLB. 101 definição. 516 taxa de dados. 464 pipelining. 424 To Repair (MTTR) controle. 21 Unicode Virtual Machine Monitors (VMMs) tempo de transferência. 317 CPU. registrador. 464 troca de contexto. 402 cache de dados. 411–416 unidades de detecção de hazard. 397 definição. 67 . 323 definição. 93 origens de falta. 198 A-569 tempo de resposta. 489 yield. 65. 406–409 varredura paralela. A-618 Telsa PTX ISA. 216 Texture/Processor Cluster (TPC). 23 implementando. A-591 unidades de avaliação. 298. A-596. 531. 276. B-659 modelo CUDA. 375 associatividades. 259 words ocorrência. A-593 tratadores de exceção. 534–537 Uniform Memory Access (UMA). A-595 definição. 411 principais. 515–516. 465 underflow. 366 benchmarks de E/S. 251 defeitos. 100 implementando. registrador. falhas. A-615 instruções de acesso à memória. 435 estratégia de substituição de bloco. 480 variáveis Intrinsity FastMATH. A-589 definição. 426 terabytes. falhas inclusiva. 391 taxas de falhas locais. 393 transistores. 300 W A-606–A-607 função especial (SFUs). 20. Ver Mean definição. 254–255 definição. B-659 varredura paralela baseada em árvore. 136 tratamento. A-585 ponto flutuante. 525 Ver também caches instruções de ponto flutuante. 220–222 divergência de tag. 133–136 registradores. 141 definição. caches endereço. 136–140 vantagens. 281 X86. 136 X instruções/funções típicas. 140–141 modos de endereçamento de dados. 136 377 formatos de instrução. 138 write-through. 141 operações típicas. 141 SIMD. 283 codificação de instruções. 133–141 linha de tempo histórica. estágio interconexões de E/S. 471–473 instrução load. 376. 420 crescimento do conjunto de instruções. 291 codificação do especificador do primeiro 136. linha de controle. Índice remissivo 709 words duplas. 141 operações com inteiros. 137 . 143 ponto flutuante. 133–136 instrução store. 140 write-back. 420 conclusão. 221 tipos de instruções. evolução.


Comments

Copyright © 2024 UPDOCS Inc.