1 comentários

 
GN⁺ 2023-12-04
Comentários do Hacker News
  • Olhando para a história das gerações ARM usadas pelo Raspberry Pi, surpreende como o chip era antigo
    Mesmo em 2014, quando o Raspberry Pi B+ saiu, o núcleo ARM1176 usado era de 2003, então já tinha 11 anos
    Por isso, não é estranho que, ao compilar em outra plataforma, como um Raspberry Pi mais recente, seja necessário especificar flags de arquitetura para gerar código compatível
    Mas, se nem ao compilar no próprio Raspberry Pi B+ a arquitetura correta for usada por padrão, isso parece um erro de configuração nos padrões da distribuição

    • Pelo que me lembro, o Pi original usava chips que sobraram de TV boxes
      Produtos desse tipo quase nunca colocam mais desempenho de computação do que o necessário, por causa do preço
    • Desde o início, era um produto pensado para ser um computador de baixo custo
    • Na verdade, não foi compilado no B+
      O texto diz que “peguei um binário do host de build, um Pi 4B muito mais rápido, e tentei executá-lo nesse dispositivo antigo, resultando em illegal instruction”
      Isso é parecido com tentar executar em um PC antigo com Windows XP um .EXE compilado no Windows 11 com o MSVC mais recente
      Provavelmente a distribuição do Pi inteira rodando no Pi 4B também não funcionaria no B+, e até o kernel pode ter sido compilado da mesma forma
  • Acho que o texto ou o artigo não deixa isso claro, mas isso não é um bug?
    Procurei bugs do LLVM e encontrei algo que parecia quase o mesmo problema, mas era um bug de 2012 e já estava fechado. Pelos últimos comentários, parecia que talvez não tivesse sido corrigido de fato, mas só dei uma olhada rápida e posso ter entendido errado
    https://github.com/llvm/llvm-project/issues/13989
    Revendo, no fim do texto ele diz que, ao passar explicitamente o alvo, o programa gerado funciona. Então parece uma espécie de bug de configuração; no Unix, eu esperaria que o alvo padrão fosse o processador atual, mas não tenho certeza
    O bug que linkei parece ter sido um problema em que o compilador gerava código errado mesmo quando o alvo era configurado corretamente; felizmente, não parece ser esse o caso agora

    • Isso mesmo. O bug linkado era que, mesmo dizendo ao compilador para mirar em armv6, ele emitia instruções armv7
      O problema da Rachel foi resolvido ao informar ao compilador que o alvo era armv6, então aquele bug já foi corrigido e parece ser separado deste problema
    • Claro que é um bug, mas parece que o autor, em vez de reportá-lo, preferiu escrever um post com um título meio caça-cliques e terminar com “muito estranho”
  • O banco de dados em que trabalho, o ClickHouse, se esforça bastante para manter compatibilidade com hardware bem antigo
    O binário ARM padrão exige Armv8.2, de 2016, e pode ser usado nos modelos a partir do Raspberry Pi 2. O binário x86 roda em hardware por volta de 2010 que tenha SSE4.2 e instruções pclmul* para CRC rápido
    Também compilamos binários para sistemas com apenas Armv8.0 e SSE2, mas não os testamos em CI. O script de instalação rápida baixa e descompacta o binário adequado para o host de destino
    No geral, acho difícil equilibrar compatibilidade retroativa com o aproveitamento dos recursos de CPU das gerações AArch64 mais recentes
    https://en.wikipedia.org/wiki/AArch64
    Havia um número surpreendente de instituições com orçamento apertado, por exemplo universidades de países emergentes, e usuários hobbystas sem condições de atualizar hardware
    Tecnicamente, era bem incômodo o fato de as flags de CPU em /proc/cpuinfo nem sempre corresponderem às flags -march= passadas ao compilador. Por exemplo, aparecem de formas diferentes, como "lrcpc" e "rcpc"
    Para fazer isso funcionar corretamente, na prática é preciso manter dois conjuntos de flags

    • Nesse caso, acho que seria melhor para todos oferecer várias builds, para que os clientes possam escolher a mais próxima da própria arquitetura
  • O problema provavelmente é que o alvo configurado mudou no pacote clang-13 atual do bookworm
    Especificamente, no bullseye e no clang-11, o alvo padrão é armv6k-unknown-linux-gnueabihf, enquanto no bookworm e no clang-13 é arm-unknown-linux-gnueabihf
    Ou talvez o padrão dessa configuração de build tenha mudado no próprio LLVM

  • Não parece ter sido uma mudança intencional
    Como comentários próximos mencionaram /etc/env.d/gcc, é bem possível que seja a forma como ele lê informações do ambiente
    O triple padrão deve ser algo como arm-unknown-linux se o clang não encontrar nem receber informações mais específicas, mas parece que o mecanismo que informa um alvo mais específico quebrou
    Isso pode significar que não há um buildbot ARMv6, ou que há um buildbot, mas nele a configuração implícita ainda funciona corretamente
    O LLVM é um cross-compiler realmente bom. Dá para compilar de qualquer alvo para qualquer alvo sem grandes problemas
    O Clang é menos atraente que isso. Se ele foi compilado com suporte ao alvo e se você conseguir informar corretamente para qual alvo compilar, provavelmente lida com isso do jeito certo. Mesmo neste texto, o palpite estava errado, mas, ao receber mais informações, ele funcionou corretamente
    A situação das bibliotecas de runtime é pior. Mesmo que você compile para um alvo como armv4, ainda precisa encontrar a libc correspondente etc., e talvez precise informar ao compilador onde ficam essas bibliotecas e headers; nessa parte, os detalhes ainda não são claros

    • A maioria das distribuições e compiladores praticamente abandonou o suporte a ARMv6 alguns anos atrás
      Passei por um problema parecido ao compilar binários para um NAS antigo da Synology
    • Por que o Clang teria que ler informações de /etc/env.d/gcc?
  • clang/clang++ lêem as flags de alvo e o perfil em /etc/env.d/gcc, e cabe ao sistema operacional manter isso corretamente
    Nesse sistema operacional, parece que essa manutenção não foi feita direito
    Meu SBC ARM com Gentoo, baseado na arquitetura ainda mais antiga armv4, continua rodando bem mesmo com as atualizações recentes de gcc/clang
    grep CTARGET /etc/env.d/gcc -r
    /etc/env.d/gcc/armv4tl-softfloat-linux-gnueabi-11.3.0:CTARGET="armv4tl-softfloat-linux-gnueabi"

    • /etc/env.d é um diretório específico do Gentoo que define variáveis de ambiente padrão das sessões de usuário
      O Clang não tem um recurso para ler esse diretório, então não se deve presumir que ele exista em outras distribuições
      É apenas que a configuração de compilador do Gentoo lê a variável de ambiente CTARGET para escolher o alvo, e o Gentoo usa /etc/env.d para definir esse valor
  • O texto não diz se é Debian ou Raspbian nem, se for Debian, se é o port armel ou armhf
    Sem essa informação, não faz muito sentido discutir para qual conjunto de instruções o LLVM compila. Isso depende da configuração de alvo nativo do LLVM
    Como referência, o llvm-toolchaim-snapshot do Debian ainda oferece suporte a armel, que usa ARMv5T como baseline. No entanto, atualmente há um bug separado na biblioteca OpenMP do LLVM que impede a compilação de ter sucesso

    • O estranho é que o próprio binário do Clang foi compilado com um conjunto de instruções compatível com o Pi B+, mas, na prática, não mira um conjunto de instruções compatível com o Pi B+
      Isso é realmente estranho. Como não é para ser usado como cross-compiler, em teoria host e alvo deveriam ser iguais
      A imagem provavelmente é Raspbian. Não vejo motivo para não presumir isso
  • Seria útil saber a saída do comando dpkg-architecture e o conteúdo do arquivo /etc/os-release
    Sem isso, fica difícil fazer um comentário útil

  • O título infelizmente é sensacionalista
    Isto é uma mudança no alvo padrão, e o clang ainda consegue compilar binários para o Pi B+
    Basta especificar explicitamente a arquitetura. Então acho melhor mudar um pouco o título para deixar mais claro que se trata de uma mudança na configuração padrão

    • Se, mesmo compilando na própria máquina-alvo, ele não consegue gerar binários para essa máquina-alvo, não me parece tão sensacionalista assim
  • Achei interessante porque, ao depurar por que um programa não roda em ARM, parece que a abordagem é mais ou menos essa
    Tenho uma build Linux do Unity que não roda dentro de um contêiner, e mesmo passando a flag amd64 ao executar o Docker, o Unity mono tenta fazer uma chamada de sistema indisponível
    Encontrei um contorno e ainda não depurei. Ativei o modo de desenvolvimento e mudei as configurações de build para não usar mono
    Algum dia quero voltar a investigar isso para aprender mais