Resumo *
1. Introdução *
2. Orientação a objetos e IA *
3. Arquiteturas Abordadas *
3.1 SOAR (Smalltalk On A RISC) *
Figura 1 - Os 2 tipos de dados suportados no SOAR *
Figura 2 - Instruções SOAR *
Figura 3 - Chamadas de subrotinas no SOAR *
Figura 4 - O apontador contém o endereço do objeto
alvo *
Figura 5 - Topologia básica (mesh hexagonal) *
Figura 6 - Organização hierárquica do FAIM-1
*
Figura 7 - Estrutura do Hectogon *
Figura 8 - Decodificação de instruções
*
Figura 9 - Formato de Instruções da COM *
Figura 10 - Diagrama da Máquina COM *
Figura 11 - Representação dos dados *
Quadro 1 - Máquinas para processamento de Linguagens OO.
*
Quadro 2 - Sumário das Máquinas OO *
Desde o lançamento do projeto de computadores de quinta geração no Japão e outros similares nos Estados Unidos e Europa, têm se questionado o paradigma de computação utilizado e o modelo das máquinas existentes. Aplicações de Inteligência Artificial demandam por formas eficientes de representar e manipular o conhecimento, principalmente através de computação simbólica.
A orientação a objetos fornece algumas características interessantes ao desenvolvimento de aplicações de IA, principalmente a hierarquia de classes, abstração e encapsulamento de dados, troca de mensagens e também facilidade de manutenção de programas. No entanto, linguagens como Smalltalk eram restritas a poucas plataformas de hardware na década de 80, devido ao limitado poder de processamento da maioria das máquinas existentes.
Neste contexto, este trabalho tem o objetivo de apresentar algumas máquinas
utilizadas no processamento de aplicações escritas em linguagens
orientadas a objetos, e que contribuíram de alguma forma à
incorporação de novos conceitos ou estruturas de hardware
para melhorar o desempenho de aplicações orientadas a objetos,
sobretudo àquelas destinadas à IA.
Palavras-chave
Arquiteturas especiais de computadores, Orientação a objetos,
IA
Aplicações numéricas convencionais podem ser expressas através de algoritmos que são executados de maneira eficiente e com uma boa estimativa de desempenho nos computadores comercialmente disponíveis. Este fato sem dúvida está ligado à natureza da aplicação, às técnicas e ferramentas utilizadas para resolver os problemas (algoritmos, linguagens de programação, compiladores) e também à plataforma de hardware que se adapta bem à esse tipo de tarefa.
Entretanto, existem aplicações cujos requisitos de tratamento contrastam com a maioria dos problemas numéricos, expondo a deficiência das estruturas existentes nos computadores atuais para realizá-las de forma eficiente. As aplicações de IA são um bom exemplo, pois são caracterizadas pelo processamento simbólico, computações não determinísticas, execução dinâmica, grande potencial para processamento paralelo e distribuído, gerenciamento de conhecimento, características evolutivas dos sistemas.
As Linguagens de programação imperativas convencionais são inadequadas para programação de IA devido à sua ineficiência no processamento simbólico e de padrões e a inaceitável complexidade de programação. Linguagens específicas para IA são fortemente declarativas, possuem construções de suporte ao processamento simbólico, representação de informação através de listas, uso de recursão como o único mecanismo de controle. Na década de 80 os paradigmas de linguagens mais utilizados em IA foram linguagens funcionais, lógicas e orientadas a objetos, com o desenvolvimento de algumas linguagens híbridas. Estas linguagens se diferenciam pelo poder de expressão, facilidade de implementação, habilidade de expressar paralelismo e de incluir conhecimento heurístico [WAH 87].
A taxonomia de máquinas apresentada em [HWA 87], classifica as arquiteturas de computadores para IA em 3 grandes classes: máquinas baseadas em linguagens, máquinas baseadas no conhecimento e máquinas de interface inteligente. Ainda segundo esta taxonomia, o conceito de objetos pode ser usado para expressar o conhecimento, enquadrando as máquinas baseadas em objetos na classe de arquiteturas baseadas na representação e manipulação do conhecimento.
A programação orientada a objetos é baseada no encapsulamento dos dados, juntamente com os métodos que os manipulam, formando uma entidade uniforme denominada objeto, permitindo ainda agrupar entidades logicamente relacionadas em classes. Algumas das principais máquinas para processamento de linguagens orientadas a objetos estão relacionadas no quadro 1.
Atualmente, linguagens orientadas a objetos são utilizadas em diversas áreas da computação, não se restringindo somente à Inteligência Artificial. Entretanto, muitas das linguagens ditas orientadas a objetos como C++, agregam características existentes em linguagens baseadas em procedimentos como C e Pascal, e excluíram muitos dos conceitos encontrados em linguagens como Smalltalk, na qual a programação é totalmente baseada em objetos. Esta tendência permite que essas linguagens consigam um melhor desempenho nas arquiteturas de computadores atuais, em detrimento de muitas das características interessantes da orientação a objetos.
| Nome e Empresa | Arquitetura e Linguagem | Paradigma de Execução |
|
iAPX 432, Intel Corp. |
Multiprocessador baseado em barramento compartilhado; para Ada e linguagens orientadas a objeto puras |
Modelo stack e também baseado em 3 endereços |
| SOAR*, UC Berkeley | Monoprocessador para Smalltalk | Avaliação de expressões baseado em registradores com checagem de tipos usando tags |
| FAIM-1*, Fairchild, Palo Alto, Calif. | Multiprocessador com interconexão mesh hexagonal; executa a linguagem OIL | Modelo stack com hardware paralelo dedicado à checagem de tags |
| Dragon, Xerox, Palo Alto, Calif. | Multiprocessador com barramento compartilhado; suporta Cedar, Interlisp e Smalltalk | Executa instruções stack e memória-memória. |
| Sword32*, Univ. de Tokyo | Sistema multiprocessador baseado em barramento compartilhado; para execução de Smalltalk | Modelo stack emulador de máquina virtual |
| COM*, California Institute of Technology | Monoprocessador para Smalltalk | Instruções de três endereços |
| AI-32*, Hitachi, Japan | processador escravo microprogramado que suporta Smalltalk e outras linguagens. | Modelo stack com tags para operandos. |
| PicoJava, Sun Microsystems, Inc. | Microprocessador que suporta bytecodes da máquina virtual linguagem Java | Modelo stack com opcodes específicos as tipos de dados; utiliza folding de instruções. |
Entretanto, como citado acima algumas arquiteturas foram propostas para o processamento eficiente de linguagens orientadas a objetos, sobretudo àquelas destinadas a aplicações de IA na década de 80. Portanto, este trabalho têm o objetivo de discutir as principais estruturas propostas para elevar o desempenho de máquinas para linguagens OO através da apresentação de algumas dessas arquiteturas.
O texto esta organizado da segundo a seguinte estrutura: a seção
2 apresenta a orientação em perspectiva à inteligência
artificial, a seção 3 relaciona algumas máquinas para
o processamento de programas escritos em linguagens baseadas em objetos
e seção 5 encerra o texto apresentando as conclusões.
A inteligência artificial foi vista como uma área de pesquisa
durante décadas. Porém, aplicações de IA comerciais
começaram a ser disponibilizadas nos anos 80, sobretudo sistemas
especialistas e de processamento de linguagem natural. Este último
com menos sucesso devido à sua extrema dificuldade. Segundo Tello
em [TEL 89], as oito áreas da IA no final da década de 80
eram:
Muitas aplicações de IA se caracterizam por serem sistemas baseados no conhecimento. Portanto, há uma grande importância em conceber formas adequadas de representar o conhecimento. Outro componente importante nestes sistemas é a máquina de inferência, que consiste em um programa que torna "executável" o conhecimento armazenado, fazendo com que os dados tenham características ativas, ao invés de dados passivos.
Diversos paradigmas e linguagens foram propostas para representar e manipular adequadamente o conhecimento em aplicações de IA. Dentre os paradigmas propostos, podemos citar o lógico, funcional e também o orientado a objetos. Em função de diversas linguagens ditas orientadas a objetos (C++, Java), atualmente sejam utilizadas para o desenvolvimento de aplicações convencionais, pode-se questionar a sua adequabilidade a problemas de IA. Entretanto, linguagens como Smalltalk (puramente orientada a objetos) ou OIL (mescla de paradigmas) apresentam muitas diferenças com relação a linguagens como C++, e eram consideradas mais adequadas para implementar aplicações de IA.
Características interessantes de linguagens como Smalltalk são a modularidade do programa, abstração de dados e classificação hierárquica dos objetos. O conceito de herança é útil na representação do conhecimento quando há uma implícita hierarquia de classes e para evitar replicação de informações. Uma discussão mais detalhada sobre as diferenças entre a programação em IA e a programação convencional, podem ser encontrados em [TEL 89] e [RAM 87]. Um exemplo de sistemas de IA que utilizam o conceito de orientação a objetos são aqueles cuja representação do conhecimento se baseia em frames [RAM 87].
Algumas razões para utilizar a orientação a objetos na implementação de máquinas de inferência são: eliminação de código redundante, evolução facilitada sem grande esforço de re-escrita de código, e permitir múltiplas instâncias da máquina de inferência sendo executadas ao mesmo tempo. O projeto e implementação de uma máquina de inferência utilizando orientação a objetos pode ser encontrada em [TEL 89].
Durante a década de 80 diversos projetos surgiram com o intuito de conceber máquinas que executassem eficientemente linguagens orientadas a objetos, dadas as vantagens que poderiam ser alcançadas mediante a utilização das mesmas. O quadro 1 relaciona as principais máquinas que agregavam estruturas para elevar o desempenho da execução de programas escritos em linguagens orientadas a objetos, sobretudo Smaltalk.
Entretanto, as máquinas abordadas neste trabalho serão
basicamente: SOAR de Berkeley, FAIM-1 da Fairchild, Sword32 da Universidade
de Tokyo, COM da Caltech e AI32 da Hitachi. Estas máquinas são
apresentadas sucintamente dando ênfase nas estruturas de hardware
que se destacam pelo objetivo de ganhar desempenho, dadas as características
das linguagens OO. O iAPX 432 e a máquina Dragon da Xerox não
serão abordados, dada à dificuldade de reunir informações
suficientes para inclui-las a tempo. Quanto ao processador PicoJava da
Sun informações mais detalhadas podem ser encontradas em
[ITO 98].
3.1 SOAR (Smalltalk On A RISC)
A linguagem Smalltalk-80 é orientada a objetos, dinâmica e é definida em termos de uma máquina virtual que executa instruções de pilha denominados bytecodes. A linguagem Smalltalk foi concebida num esforço de obter um ambiente de programação altamente produtivo, oferecendo características interessantes como:
No projeto SOAR uma das razões para o ganho de desempenho era a compilação de bytecodes Smalltalk para o conjunto de instruções SOAR. Portanto, o compilador atuava como um tradutor de bytecodes de arquitetura stack para instruções de load/store e registrador-registrador do estilo RISC.
Como comentado acima, em operações Smalltalk os tipos dos operandos podem variar, portando devem ser checados em tempo de execução. As implementações existentes até então, usavam microcódigo ou software para checar tipos antes de realizar operações como adição penalizando o desempenho obtido. Em geral, tags podem ser checados pelo hardware para descobrir erros em um programa. Entretanto, no projeto SOAR, os tags tinham a finalidade de elevar o desempenho através da previsão de tipos, permitindo iniciar uma operação e checar o tag para confirmar a previsão de forma simultânea.

No caso trivial, os dois operandos são do tipo inteiro e o resultado correto esta disponível após um ciclo de relógio. Porém, quando algum dos operandos não é do tipo inteiro, o SOAR aborta a operação e provoca um desvio para rotina que efetuará as computações adequadas para aquele tipo de dado. Como pode ser observado na figura 1, os dados no SOAR possuem um bit (tag) indicando se o dado é do tipo inteiro, ou um apontador para a estrutura de dado contendo a informação.
As instruções de desvio condicional também foram influenciados pela checagem dinâmica de tipos exigida por Smalltalk. Basicamente há duas formas clássicas de se implementar desvios condicionais: instruções de comparação explícitas ou códigos de condição. Esta última técnica permite economizar uma instrução quando a condição depende da comparação do resultado da operação anterior e zero. Entretanto, não é possível aplicá-la desde que em Smalltalk o tipo do resultado pode variar. Desde que 32 bits não seriam suficientes para codificar uma instrução do tipo compare-and-brach, SOAR utiliza uma instrução do tipo compare-and-skip.
Como o sistema Smalltalk-80 ser baseado em uma máquina virtual de arquitetura estilo stack, cada instrução compreende de um a três bytes, correspondendo em geral a cada token do programa fonte. Esta abordagem apresenta algumas vantagens como simplificação do compilador e depurador, e portabilidade alcançada pela implementação de emuladores. Entretanto, a decodificação requer uma estrutura de hardware adicional e toma uma quantidade de tempo maior, e instruções de alto nível requerem múltiplos ciclos para executar e exigem uma unidade de controle dedicada.
A filosofia RISC busca um conjunto de instruções ortogonal, razão pelo qual os projetistas do SOAR abandonaram a abordagem baseada em bytecodes da máquina virtual. Portanto, cada instrução SOAR ocupa 32 bits e a maioria toma um ciclo de relógio para executar, com exceção das instruções de load/store e return que tomam 2 ciclos.

Uma arquitetura que utiliza tags e não possui microcódigo
exige que o compilador mescle instruções de inspeção
e manipulação dos tags e as demais instruções.
Cada instrução SOAR possui um bit que habilita ou desabilita
a checagem dos tags (indicado por % no assembly). No modo "untagged" os
bits de tag são tratados como dados, permitindo que programas escritos
em linguagens convencionais como C possam executar no SOAR. Os dois formatos
de instrução do SOAR podem ser observados na figura 2.
3.1.3 Chamadas de procedimento eficientes
Smalltalk explora ao extremo a modularidade dos programas através da utilização de subrotinas. Portanto, os programas escritos em Smalltalk possuem uma alta taxa de chamadas à subrotinas. Além disso, estas chamadas são mais complexas, por duas razões:

O banco de registradores do SOAR possui 32 registradores. Quando sua capacidade é excedida, o SOAR invoca uma rotina em software para salvar o conteúdo dos registradores em memória. Entretanto, para acelerar esse processo existem instruções especiais que podem transferir 8 registradores em apenas nove ciclos (um ciclo de busca de instrução e 8 de acesso a dados). O SOAR também pode inicializar todos os registradores de uma janela através da instrução return, que realiza esta tarefa em paralelo com o cálculo do endereço de retorno, deixando os registradores inicializados para a próxima chamada.
Uma terceira técnica para reduzir o overhead associado às
chamadas de subrotinas é armazenar o endereço destino obtido
na consulta da tabela de endereços no próprio fluxo de instruções,
dispensando novas consultas (Figura 3). Porém, esta técnica
não permite o uso de código reentrante e o chaveamento de
processos deve ser evitado. As instruções SOAR de call e
jump possuem um bit para especificar se é seguro realizar o chaveamento
de processo, permitindo o uso de interrupção por software
necessário para implementação de sistemas operacionais.
Em Smalltalk-80, os objetos são pequenos (56 bytes para o SOAR) e voláteis. O gerenciamento do armazenamento dessas estruturas de dados são gerenciadas através do uso de três técnicas, que estão descritas sucintamente a seguir.

O FAIM-1 era um sistema destinado ao processamento simbólico de aplicações de inteligência artificial. O objetivo principal deste projeto era obter uma arquitetura escalável à uma configuração capaz de obter um desempenho de duas a três ordens de magnitude sobre as arquiteturas convencionais. Considerou-se ainda neste projeto, fatores como programabilidade, desempenho, extensibilidade, tolerância a falhas e um custo compatível com a tecnologia existente.
A arquitetura do FAIM-1 foi concebida para ser uma máquina de
alto desempenho para a avaliação de programas escritos na
linguagem concorrente OIL (Our Intermediate Language), e suportar um estilo
de multiprocessamento distribuído embutido no sistema operacional
[HON 87].
OIL é uma linguagem de programação de alto nível, concorrente e de natureza simbólica. O projeto desta linguagem foi influenciada pelas diversas linguagens existentes utilizadas na implementação de programas de IA. Basicamente, são três os estilos de programação suportados por OIL: orientado a objetos, lógica e funcional. Seus projetistas argumentavam que complexas aplicações de IA, poderiam requerer os três estilos de programação.
Um programa OIL é constituído de um conjunto de objetos que se comunicam através da troca de mensagens. Objetos consistem de informações de estado (variáveis) e diversos ports usados para troca de mensagens (recebidos segundo uma política de fila). Um comportamento é associado a cada port, descrevendo a resposta do objeto a uma determinada mensagem. Objetos atômicos de OIL podem ser dos tipos logical (escritos de forma declarativa semelhante a algumas versões paralelas do Prolog) e procedural (descritos de forma imperativa como alguns dialetos de Lisp).
Para suportar chamadas de rotinas de forma distribuída e sincronização de processos paralelos, subconjuntos de ports podem ser agrupados em entries. Quando todos os ports de um entry possuem uma mensagem, então o comportamento associado a este entry é dito fireable. Os componentes lógicos são usados para expressar buscas não determinísticas dirigida por padrões, enquanto componentes funcionais são usados para especificação de algoritmos seqüenciais, exibindo um comportamento determinístico.
O funcionamento de um componente lógico é baseado na manipulação de uma cadeia de metas, e a produção de uma lista de soluções (em geral, diversas soluções por meta). Ao contrário, um componente funcional aceita uma seqüência de chamadas à funções e produz uma lista de mensagens (geralmente, uma resposta para cada chamada de função).
Ao programador são fornecidos flexíveis e poderosos recursos de programação, como os chamados pragmas, que podem descrever o comportamento esperado de um fragmento de código em tempo de execução, permitindo por exemplo uma melhor alocação de recursos e consequentemente afetar o desempenho do programa. Na realidade os pragmas podem ser utilizados para 3 finalidades: estimar a probabilidade de um desvio ser tomado em uma decisão, estimar o tamanho de estruturas de dados dinâmicas e tomar decisões sobre a alocação de recursos.
Programas escritos em OIL são compilados em código objeto
em uma máquina Lisp hospedeira. Este código é depois
enviado para execução no FAIM-1. Decisões de como
proceder a alocação de cada objeto é realizado durante
a fase de compilação denominada alocação de
recursos. Isto permite balancear o hardware de execução paralela
e o custo de comunicação em tempo de execução.
A arquitetura do FAIM-1 consiste de diversos elementos de processamento independentes, chamados Hectogons, interconectados por uma mesh hexagonal. Portanto, os elementos de processamento podem se comunicar diretamente com até 6 elementos adjacentes.

A figura 5 ilustra a topologia básica, na qual as linhas pontilhadas completam as conexões. Este tipo de interconexão resulta em um simples algoritmo de roteamento. As conexões "extra-hexágono" permitem a comunicação com dispositivos de I/O ou com outros hexágonos.


O tamanho de cada hexágono é determinado pelo número
de processadores contido em cada lado do hexágono. A escalabilidade
pode ainda ser alcançada organizando o FAIM-1 de forma hierárquica,
através de múltiplos hexágonos, como demonstra a figura
6, onde 133 elementos de processamento estão conectados.
Cada Hectogon pode ser visto como um elemento de processamento homogêneo da arquitetura do FAIM-1, que se caracteriza por ser um sistema multiprocessador de memória compartilhada, altamente concorrente e de média granulosidade. Internamente os hectogons são compostos de diversos subsistemas, como pode ser observado na figura 7.
O desempenho do sistema, depende da taxa de processadores ativos, a
eficiência da comunicação, do total de processadores
e também do desempenho de cada processador. Internamente cada hectogon
é composto por:
A maior porção do paralelismo explorado pelo FAIM-1 é
tipo OU. O paralelismo do tipo E só é explorado quando suas
cláusulas são independentes e as checagens de consistência
complexas não são necessárias. A técnica de
balanceamento de carga é predominantemente estático, com
limitado suporte ao balanceamento dinâmico devido ao seu overhead
[HWA 89].
3.3 COM (Caltech Object Machine)
O projeto da máquina COM tinha o objetivo de obter alto desempenho
na execução das linguagens orientadas a objetos que utilizam
o conceito de late biding. Seus projetistas utilizavam principalmente duas
técnicas para alcançar esta meta: alocação
de contexto eficiente e um buffer de tradução para instruções
(translation lookaside buffer). A proposta destas estruturas de hardware
era baseada na necessidade de novos mecanismos a serem incorporados aos
processadores von Newmann convencionais, altamente penalizados na execução
de linguagens orientadas a objetos. Diversos outros projetos, como por
exemplo das máquinas Xerox Dorado e SOAR, inspiraram o projeto da
COM [KAJ 85].
3.3.1 Novos conceitos incorporados na Arquitetura
Os projetistas da máquina COM utilizaram o conceito de "instruções abstratas" como método para interpretar instruções de máquina. Neste esquema, o opcode e a classe determinam qual instrução deve ser executada, dando ainda a informação se a instrução é primitiva ou definida.
Entretanto, a decodificação de uma instrução
é muito mais complexa e lenta se realizada por software. Entretanto,
o mecanismo ITLB (Instruction Translation Lookaside Buffer) pode diminuir
o overhead da utilização desta técnica. Cada entrada
na ITLB contem 3 campos: uma chave composta pelo opcode e um conjunto de
classes; um bit que indica se o método é primitivo ou definido;
e um campo que indica o resultado de uma unidade funcional ou uma porção
de código, dependendo do bit descritor do método. A figura
8 apresenta a estrutura do ITLB.

Portanto a decodificação de instruções era realizada em 3 etapas. Primeiro o opcode e a classe de cada operando constituíam uma chave, através do qual uma memória associativa realizava a busca da entrada correspondente. Caso tal chave fosse encontrada a decodificação era imediata, caso contrário era utilizado a técnica padrão de "method lookup", comum na execução de programas escritos em Smalltalk.
Os projetistas da máquina COM também propuseram um método para eliminar o conhecido problema de objetos pequenos, que leva ao dilema de optar por um número de maior segmentos ou por segmentos maiores. Utilizando a técnica o endereço por ponto flutuante, na qual cada endereço possui um "expoente" e uma "mantissa" onde exp = é lg manù . O expoente codifica na realidade o tamanho do offset representado pela mantissa.
A máquina COM utiliza uma memória provida de tags de 4 bits usados para identificar os tipos primitivos: unintialized , small integer, floating point, atom, instruction and object pointer. Um tag de 16 bits é armazenado no contexto para indicar a classe de um objeto que será utilizado no processo de method lookup.
O mecanismo de alocação de contextos utiliza o tamanho
fixo de 32 palavras para os contextos. Métodos que necessitem mais
de 32 palavras podem alocar espaço adicional fora da pilha. Entretanto,
como em programas orientados a objetos em geral os métodos são
menos exigentes quanto ao tamanho dos contextos, esta restrição
é justificada. Uma cache de contextos associativa por conjuntos
é utilizada para acesso eficiente aos contextos. Outro mecanismo
interessante é o gerenciamento da cache, que começa a mover
os contextos à medida que a cache vai atingindo seu limite máximo
e copia-os de volta quando metade da cache está livre. Este mecanismo
possui função semelhante às janelas de registradores
adotadas no projeto SOAR.
A máquina COM incorporava não somente as características destacadas na seção 3.3.1, mas também uma série de características bem conhecidas para suportar a execução eficiente de programas orientados a objetos. A memória da máquina COM possuía tags para identificar os diferentes tipos de objetos. A velocidade de processamento era atribuída principalmente ao suporte em hardware para o processo de method lookup e para permitir acesso e alocação de contextos.
O mecanismo de endereçamento na máquina COM era bem sofisticado, possuindo 3 espaços de endereçamento: espaço virtual (espaço de endereçamento local a um grupo de processos), espaço absoluto (espaço de nomes global, onde existe um identificador único para cada objeto), e espaço físico (endereçamento em dispositivos físicos). A resolução de nomes é feita através da tradução do espaço virtual para o espaço absoluto. A alocação de recursos era tratada através da tradução do espaço absoluto para o espaço físico. Processos como o garbage collector utilizam o espaço de endereçamento absoluto. Completo suporte em hardware para tradução dos 3 tipos de endereçamento estão disponíveis na máquina COM, bem como um ATLB (Address Translation Lookaside Buffer).

O conjunto de instruções da máquina COM foi projetada
para ser regular e facilitar a introdução de execução
pipeline. Todas as instruções são de 32 bits de tamanho
e contém de zero ou três operandos. Portanto, uma instrução
de 3 operandos pode substituir em torno de 2 instruções do
tipo stack da máquina virtual Smalltalk-80. Os formatos das palavras
de instrução são apresentadas na figura 9. As instruções
podem ser classificadas em: aritméticas, múltipla precisão,
lógica e de acesso a bits, comparações, movimento
de dados, acesso a tags, de controle (jumps).

Como pode ser observado na figura 10, a interpretação das instruções são realizadas em 5 etapas:
O Sword32 foi um microprocessador de 32 bits com 4K palavras de memória
para microinstruções, uma grande pilha e mecanismos para
emular bytecodes Smalltalk eficientemente. A motivação para
concepção deste processador, derivou de estudos sobre a viabilidade
da utilização de Smalltalk como linguagem principal de desenvolvimento
de sistemas no núcleo de pesquisas do departamento de Engenharia
Matemática da Universidade de Tokyo. Através desses estudos
comprovou-se que além de Smalltalk apresentar diversas características
de interesse, esta linguagem sofria de problemas de desempenho, limitando
sua utilização à poucas plataformas de hardware [SUZ
84].
3.4.1 Características da Arquitetura
Para fornecer um ambiente com um bom tempo resposta à interação e superar o problema de limitação de memória, foi usado uma técnica de garbage collection chamada transaction. Não há suporte especial em hardware para efetuar este processo, a não ser o fato de que o programa foi implementado na maioria em micro-código.
A referência à objetos em geral é feita através de apontadores, cuja implementação pode variar de sistema para sistema. Por exemplo, o SOAR utiliza apontadores com o endereço absoluto para os objetos, o Dolphin (máquina da Xerox) utiliza índices para uma tabela contendo o endereço dos objetos e o Sword32 adotou uma solução intermediária, fazendo referência aos objetos através do endereço efetivo dentro de uma tabela de endereços para objetos.

Os inteiros no Sword32 tem 31 bits devido ao uso de um tag que o diferencia dos apontadores como pode ser observado na figura 11. A codificação direta do valor inteiro permite acelerar o processamento, pois não é necessário efetuar a consulta à tabela de objetos. O acesso à memória pode ser feita através de instruções de load/store de 8 ou 32 bits.
Nos sistemas Smalltalk em geral se utiliza um sistema de cache para acelerar o processo de method lookup. O Sword32 utiliza uma técnica chamada method cache com algumas modificações. O método original consiste de uma tabela hash global, na qual as chaves são o identificador da mensagem e a classe do receptor, e os valores são o índice de um método ou primitiva. No Sword32 os valores contidos na tabela são o endereços do primeiro bytecode (método) ou do microcódigo (primitiva), permitindo uma aceleração da execução. Um tag é utilizado no bit mais significativo da palavra de endereço da instrução para indicar se corresponde à um bytecode (valor 0) ou uma microinstrução (valor 1).
Para permitir chamadas rápidas à métodos, o Sword32 provê amplo suporte à troca de contexto através de uma grande pilha dentro do chip (128 palavras) e 32 registradores de propósito geral. No Sword32 até 8 contextos podem estar armazenados simultaneamente na pilha.
A parte operativa do Sword32 foi projetada de maneira simples e possui
apenas 2 estágios de pipeline (busca de instrução
e acesso a operandos/operação/write-back). Nenhum suporte
especial em hardware está disponível para a busca de instruções,
sendo de responsabilidade do microprogramador garantir que a busca não
ocorra enquanto uma instrução de acesso à memória
esteja sendo realizada.
O ganho de desempenho proposto no projeto do Hitachi AI32 originava-se da otimização de instruções complexas e freqüentes como checagem dinâmica de tipos, chamadas à subrotinas e o gerenciamento de memória. Para melhorar o desempenho destas operações eram utilizados grandes bancos de registradores intra-chip, grande capacidade em EPROM para armazenar microinstruções, engenhosos mecanismos de despacho de instruções e manipulação de tags.
O objetivo era obter um microprocessador capaz de executar eficientemente
programas escritos em linguagens orientadas a objetos e outras linguagens
destinadas à IA, através do uso de microprogramas adequados.
O projeto do AI32 pela Hitachi foi influenciado pelo Sword32 desenvolvido
pela Universidade de Tokyo. Basicamente, as diferenças incorporadas
no AI32 se concentram na estrutura do datapath, o método de acesso
ao banco de registradores, mecanismos de manipulação de tag
e codificação das micro-instruções.
3.5.1 Características da arquitetura
O AI32 foi projetado para ser um processador escravo, operando sob a supervisão da MPU (Micro Processing Unit) hospedeira, ambas acessando o mesmo espaço de endereçamento. O AI32 compõe-se de 5 unidades principais: unidade de sequenciamento das microinstruções, unidade de controle de barramento, unidade de execução, 2 bancos de registradores.
A unidade de sequenciamento é composta por uma grande EPROM (4K palavras de 64 bits) para o armazenamento das microinstruções, mecanismos de despacho de instruções e manipulação de tags. A unidade de execução possui uma ULA e um barrel-shifter. Cada banco de registradores possui 256 palavras de 32-bits de memória RAM e uma unidade aritmética privada com registradores de endereço. Cada unidade é controlada independentemente por um campo da microinstrução [KAW 86].
Programas escritos em linguagens orientadas a objetos são traduzidas em seqüências de macro-instruções, os quais são executados através de microinstruções pelo AI32. No AI32, o contexto da chamada de métodos é armazenado na pilha de execução e é chamada "contexto volátil".
O datapath do AI32 foi projetado para alcançar bom desempenho com recursos limitados. Os dois grandes banco de registradores provém maior eficiência na transferência de dados, explorando a localidade dos mesmos. A estratégia de separar os registadores em dois bancos é uma questão tecnológica, pois o aumento do número de registradores eleva o tempo de propagação. O datapah é de 32 bits e as operações realizadas são: ler 2 operandos dos bancos de registradores, realizar operações de ULA ou shift e armazenar o resultado da operação nos latches de saída. Dados da memória podem ser lidos a partir dos registradores AOR (Address Output Register), DIR (Data Input Register) e DOR (Data Output Register).
Na realidade a seqüência de micro-instruções é determinada por um campo de 12 bits NMA (Next Micro-Address) para eliminar a necessidade de uma unidade complexa para determinar a seqüência de microinstruções. Esta técnica diminui a quantidade de instruções de desvio explícitas, numerosas devido ao compartilhamento de grandes porções do micro-código.
Cada apontador possui um bit de tag (bit menos significativo) para indicar
seu tipo. Caso este bit tenha o valor 1, significa que corresponde à
uma referência a um objeto, se o valor for 0, o apontador é
tratado como um valor do tipo inteiro. Na realidade, esta arquitetura não
apresenta inovações muito significativas, recorrendo à
microprogramação para a execução de linguagens
orientadas a objetos.
Durante o texto pudemos observar diversas técnicas e estruturas de hardware utilizadas para melhorar o desempenho na execução de programas escritos em orientadas a objetos, principalmente Smalltalk. Basicamente os projetos procuram explorar 3 grandes gargalos das aplicações orientadas a objetos: passagem de mensagens, grande exigência de memória, e troca de contexto.
Foram diversas as formas com que os projetistas tentaram contornar os problemas encontrados: uso de grande quantidade de registradores, pilhas, instruções virtuais, memória virtual, memória associativa, inline cache e method cache, ITLB, novos modos de endereçamento, janelas de registradores, dentre outras. Muitas destas técnicas parecem não ser grande novidade, mas na época foram motivo de grande inovação e discussão.
Pode-se observar ainda que os projetistas seguiram 3 linhas de projeto distintas: maciço uso de microcódigo, uso de monoprocessador RISC e uso de um multiprocessador para explorar o paralelismo. Cada uma delas privilegia um fator, seja ele desempenho, simplicidade, velocidade de implementação, ou tão somente dar suporte adequado à linguagem alvo. Por exemplo, o uso maciço de microcódigo se deve ao fato de suportar as instruções da máquina virtual da linguagem diretamente, primando por portabilidade. A linguagem OIL, por tentar incorporar os 3 paradigmas mais utilizados em IA possui grande quantidade de paralelismo a ser explorado e um tratamento adequado das troca de mensagem.
O ponto chave desempenho não foi abordado de forma quantitativa,
não constando gráficos ilustrativos de speed-up obtidos por
cada máquina. Este fato se deve por diversos motivos: os dados constantes
nos documentos pesquisados estão desatualizados, não há
uma padronização efetiva da metodologia de benchmark entre
os projetos, não existe uma análise comparativa de desempenho
de muitas máquinas da época, muitos dos projetos não
explicitavam o tipo de tecnologia utilizada na implementação
das máquinas.
|
|
|||||
| SOAR | FAIM-1 | COM | Sword32 | AI32 | |
| Interface com a Linguagem |
|
|
|
|
|
| Arquitetura |
|
|
|
|
|
| Ponteiro de Objeto |
|
|
|
|
|
| Tabela de Objetos |
|
|
|
|
|
| Garbage Collector |
|
|
|
|
|
| Instrução |
|
|
|
|
|
| Method lookup |
|
|
|
|
|
| Tags |
|
|
|
|
|
| Alocação de Contexto |
|
|
|
|
|
Ressalta-se porém, que durante o texto procurou-se abordar cada
máquina de forma resumida, atendo-se aos pontos mais importantes
de cada uma. Muitas dos detalhes foram omitidos por simplicidade atendo-se
principalmente às estratégias utilizadas por cada projeto
no atendimento aos requisitos citados acima. Um resumo das características
das máquinas é apresentado no quadro 2.
Um ponto mais filosófico é a questão das linguagens orientadas a objetos atuais produzirem programas razoavelmente eficientes. Programas escritos em linguagens como C++ são amplamente difundidos e podem ser utilizados em qualquer computador pessoal. Entretanto, o que devemos considerar é que muitas linguagens abandonaram a idéia de serem puramente orientadas a objetos em detrimento do desempenho a ser obtido nas máquinas convencionais. Em adição à este fato, também a tecnologia de implementação se alterou profundamente, permitindo que problemas de gerenciamento de memória fossem amenizados.
A grande pergunta a ser respondida é se linguagens orientadas a objeto necessitam realmente de suporte especial em hardware. Algumas discussões podem ser encontradas em [UNG 95], no qual Ungar argumenta que da linguagem SELF (tão orientada a objetos como Smalltalk-80) pode resultar em código objeto semelhante ao produzido a partir de C. Segundo Ungar, estes resultados foram obtidos com a utilização de técnicas sofisticadas de compilação, contradizendo trabalhos realizados no passado.
[HON 87] HON, Robert W. et al. The Architecture of FAIM-1. Computer, IEEE Computer Society, Vol. 20, N 1, January, 1987.
[ITO 98] ITO, Sérgio A. Arquitetura dos Processadores Java. Monografia apresentada como trabalho final da disciplina CMP 114. CPGCC-UFRGS, agosto de 1998.
[KAJ 85] KAJIYA, James T.; DALLY, Willian J. An Object Oriented Architecture. Proceedings of 12th Annual International Symposium on Computer Architecture. Massachusetts: IEEE Computer Society Press, 1985.
[KAW 86] KAWASAKI, Shumpei et al. Microprogrammable Processor for Object-Oriented Architecture. Proceedings of 13th Annual International Symposium on Computer Architecture. Tokyo: IEEE Computer Society Press, 1986.
[PAT 86] PATTERSON, David et al. Architecture of SOAR: Smalltalk on a RISC. Tutorial: Software-Oriented Computer Architecture. Washington: IEEE Computer Society Press, 1986.
[PAT 87] PATTERSON, David; UNGAR, David. What Price Smalltalk? Computer, IEEE Computer Society, Vol. 20, N 1, January, 1987.
[RAM 87] RAMAMOORTHY, C. V. et al.. Software Development Support for AI Programs. Computer, IEEE Computer Society, Vol. 20, N 1, January, 1987.
[SUZ 84] SUZUKI, Norihisa et al. Sword32: A Bytecode Emulating Microprocessor for Object-Oriented Languages. Procedings of the International Conference on Fifth Generation Computer Systems. Japan: ICOT, 1984.
[TEL 89] TELLO, Ernest R. Object-Oriented Programming for Artificial Inteligence. Addison-Wesley Publishing Company, Inc, 1989.
[UNG 87] UNGAR, David et al. Compiling Smalltalk-80 to a RISC. Proceedings of Second International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS II), California: IEEE Computer Society Press, 1987.
[UNG 95] UNGAR, David; URS Hölzle. Do object-oriented languages need special hardware support? ECOOP '95 Conference Proceedings. Springer Verlag Lecture Notes in Computer Science 952. p.253-282, Aug. 1995.
[WAH 87] WAH, Benjamin W. Guest Editor's Introduction: New Computers for Artificial Intelligence Processing. Computer, IEEE Computer Society, Vol. 20, N 1, January, 1987.
[HWA 87] HWANG, Kai et al. Computer Architectures for Artificial Intelligence Processing. Computer, IEEE Computer Society, Vol. 20, N 1, January, 1987.
[HWA 89] HWANG, Kai et al. Parallel Architectures for Implementing
Artificial Intelligence Systems. Parallel Processing for Supercomputers
& Artificial Intelligence. Cap. 7. Editors: Hwang and Degroot, McGraw-Hill,
1989.