Arquiteturas exóticas que os comitês de padrões se preocupam

Eu sei que os padrões C e C ++ deixam muitos aspectos da implementação da linguagem definidos apenas porque se houver uma arquitetura com outras características, seria muito difícil ou impossível escrever um compilador padrão em conformidade para isso.

Eu sei que 40 anos atrás, qualquer computador tinha sua própria especificação única. No entanto, não conheço nenhuma arquitetura usada hoje em que:

  • CHAR_BIT != 8
  • signed não é complemento de dois (eu ouvi que o Java teve problemas com este).
  • Ponto flutuante não é compatível com IEEE 754 (Editar: eu quis dizer “não na codificação binária IEEE 754”).

A razão pela qual estou perguntando é que muitas vezes eu explico às pessoas que é bom que o C ++ não determine quaisquer outros aspectos de baixo nível, como tipos de tamanhos fixos . É bom porque ao contrário de ‘outras linguagens’ torna seu código portátil quando usado corretamente (Edit: porque ele pode ser portado para mais arquiteturas sem requerer emulação de aspectos de baixo nível da máquina, como por exemplo aritmética de complemento de dois em sinal + arquitetura de magnitude) . Mas me sinto mal por não poder apontar para nenhuma arquitetura específica.

Então a questão é: quais arquiteturas exibem as propriedades acima?

uint*_t s são opcionais.

Dê uma olhada neste aqui

Servidores Unisys ClearPath Dorado

oferecendo compatibilidade com versões anteriores para pessoas que ainda não migraram todos os seus softwares Univac.

Pontos chave:

  • Palavras de 36 bits
  • CHAR_BIT == 9
  • um complemento
  • Ponto flutuante não IEEE de 72 bits
  • espaço de endereço separado para código e dados
  • endereçado à palavra
  • nenhum ponteiro de pilha dedicado

Não sei se eles oferecem um compilador C ++, mas eles poderiam .


E agora um link para uma edição recente de seu manual C apareceu:

Manual de Referência de Programação do Compilador C da Unisys

A Seção 4.5 possui uma tabela de tipos de dados com 9, 18, 36 e 72 bits.

tamanho e intervalo de tipos de dados no compilador USC C

Nenhuma de suas suposições se aplica a mainframes. Para começar, não conheço um mainframe que use o IEEE 754: a IBM usa o ponto flutuante da base 16 e ambos os mainframes da Unisys usam a base 8. As máquinas da Unisys são um pouco especiais em muitos outros aspectos: Bo mencionou o 2200 arquitetura, mas a arquitetura MPS é ainda mais estranha: palavras marcadas em 48 bits. (Se a palavra é um ponteiro ou não depende de um bit na palavra.) E as representações numéricas são projetadas de modo que não haja distinção real entre ponto flutuante e aritmética integral: o ponto flutuante é a base 8; ele não requer normalização e, ao contrário de todos os outros pontos flutuantes que eu vi, ele coloca o decimal à direita da mantissa, ao invés da esquerda, e usa magnitude assinada para o expoente (além da mantissa). Com os resultados, um valor de ponto flutuante integral tem (ou pode ter) exatamente a mesma representação de bit que um inteiro de magnitude assinado. E não há instruções aritméticas de ponto flutuante: se os expoentes dos dois valores forem ambos 0, a instrução faz aritmética integral, caso contrário, ela faz aritmética de ponto flutuante. (Uma continuação da filosofia de marcação na arquitetura.) O que significa que, enquanto int pode ocupar 48 bits, 8 deles devem ser 0, ou o valor não será tratado como um inteiro.

A conformidade total com IEEE 754 é rara em implementações de ponto flutuante. E enfraquecer a especificação nesse sentido permite muitas otimizações.

Por exemplo, o subnorm suporta diferenças entre x87 e SSE.

Otimizações como fusão de multiplicação e adição, que eram separadas no código-fonte, alteram ligeiramente os resultados também, mas é uma boa otimização em algumas arquiteturas.

Ou na conformidade x86 rígida do IEEE pode exigir que determinados flags sejam configurados ou transferências adicionais entre registradores de ponto flutuante e memory normal para forçá-lo a usar o tipo de ponto flutuante especificado em vez de seus floats internos de 80 bits.

E algumas plataformas não têm flutuações de hardware e, portanto, precisam imitá-las no software. E alguns dos requisitos do IEEE 754 podem ser caros de implementar em software. Em particular, as regras de arredondamento podem ser um problema.

Minha conclusão é que você não precisa de arquiteturas exóticas para entrar em situações em que nem sempre quer garantir a conformidade estrita do IEEE. Por esse motivo, poucas linguagens de programação garantem a conformidade estrita do IEEE.

Eu encontrei este link listando alguns sistemas onde CHAR_BIT != 8 . Eles incluem

alguns DSPs da TI têm CHAR_BIT == 16

Chip BlueCore-5 (um chip Bluetooth da Cambridge Silicon Radio) que tem CHAR_BIT == 16 .

E, claro, há uma pergunta sobre o Stack Overflow: quais plataformas têm algo diferente de 8 bits?

Quanto aos sistemas não complementares de dois, há uma leitura interessante em comp.lang.c ++. Moderated . Resumindo: existem plataformas que têm um complemento ou representação de sinal e magnitude.

Tenho quase certeza de que os sistemas VAX ainda estão em uso. Eles não suportam o ponto flutuante IEEE; eles usam seus próprios formatos. O Alpha suporta os formatos de ponto flutuante VAX e IEEE.

As máquinas de vetores Cray, como o T90, também têm seu próprio formato de ponto flutuante, embora os sistemas Cray mais recentes utilizem o IEEE. (O T90 que usei foi descomissionado há alguns anos; não sei se algum deles ainda está em uso ativo.)

O T90 também teve / tem algumas representações interessantes para pointers e inteiros. Um endereço nativo só pode apontar para uma palavra de 64 bits. Os compiladores C e C ++ possuíam CHAR_BIT == 8 (necessário porque ele rodava o Unicos, um tipo de Unix, e precisava interoperar com outros sistemas), mas um endereço nativo só podia apontar para uma palavra de 64 bits. Todas as operações em nível de byte foram sintetizadas pelo compilador e um void* ou char* armazenou um deslocamento de byte nos 3 bits mais altos da palavra. E eu acho que alguns tipos inteiros tinham bits de preenchimento.

Mainframes IBM são outro exemplo.

Por outro lado, esses sistemas específicos não precisam necessariamente impedir mudanças no padrão de linguagem. Cray não demonstrou nenhum interesse particular em atualizar seu compilador C para C99; presumivelmente a mesma coisa aplicada ao compilador C ++. Pode ser razoável reforçar os requisitos para implementações hospedadas, como a exigência de CHAR_BIT == 8, o formato IEEE de ponto flutuante, se não a semântica completa, e o complemento de 2 sem preenchimento de bits para números inteiros assinados. Os sistemas antigos poderiam continuar a suportar padrões de linguagem anteriores (o C90 não morreu quando o C99 foi lançado) e os requisitos poderiam ser mais frouxos para implementações independentes (sistemas embarcados), como os DSPs.

Por outro lado, pode haver boas razões para os sistemas futuros fazerem coisas que seriam consideradas exóticas hoje em dia.

CHAR_BITS

De acordo com o código fonte do gcc :

CHAR_BIT é 16 bits para arquiteturas 1750a , dsp16xx .
CHAR_BIT é de 24 bits para a arquitetura dsp56k .
CHAR_BIT é de 32 bits para arquitetura c4x .

Você pode encontrar mais facilmente fazendo:

 find $GCC_SOURCE_TREE -type f | xargs grep "#define CHAR_TYPE_SIZE" 

ou

 find $GCC_SOURCE_TREE -type f | xargs grep "#define BITS_PER_UNIT" 

se CHAR_TYPE_SIZE estiver definido adequadamente.

Conformidade com IEEE 754

Se a arquitetura de destino não suportar instruções de ponto flutuante, o gcc pode gerar fallback de software que não é o padrão compatível por padrão. Mais do que, opções especiais (como -funsafe-math-optimizations que também desativa a preservação de sinais para zeros) podem ser usadas.

A representação binária IEEE 754 era incomum nas GPUs até recentemente, veja Paranoia de ponto flutuante da GPU .

EDIT: foi levantada uma questão nos comentários se o ponto flutuante da GPU é relevante para a programação usual do computador, não relacionado a charts. Claro que sim! A maior parte da coisa de alto desempenho industrialmente computada hoje é feita em GPUs; a lista inclui AI, mineração de dados, redes neurais, simulações físicas, previsão do tempo e muito mais. Um dos links nos comentários mostra por que: uma vantagem de ponto flutuante de ordem de grandeza das GPUs.

Outra coisa que gostaria de acrescentar, que é mais relevante para a questão do OP: o que as pessoas fizeram 10-15 anos atrás quando o ponto flutuante da GPU não era IEEE e quando não havia APIs como o OpenCL ou CUDA de hoje para programar GPUs? Acredite ou não, os primeiros pioneiros da computação GPU conseguiram programar GPUs sem uma API para fazer isso ! Eu conheci um deles na minha empresa. Eis o que ele fez: ele codificou os dados que precisava para calcular como uma imagem com pixels representando os valores em que estava trabalhando e usou o OpenGL para executar as operações de que precisava (como “gaussian blur” para representar uma convolução com distribuição normal , etc), e decodificou a imagem resultante de volta em uma matriz de resultados. E isso ainda foi mais rápido do que usar CPU!

Coisas desse tipo fizeram com que a NVidia finalmente tornasse seus dados internos binários compatíveis com o IEEE e introduzisse uma API orientada para computação, em vez de manipulação de imagens.

Intereting Posts