Nota!Primeiramente gostaria de dizer que este tutorial não é só meu! Ele é de todos os amigos e colegas que participam do tópico do Hqxriven sobre o
Kernel Omnislash (Unofficial) - Aprendendo a voar sem segredos!!!
Vários colegas contribuíram para este tutorial, gostaria de agradecer aos colegas: Buli, MSXManiac , 4d4c47, Gunss, cesargcomp, vampire_thunder e Hqxriven! Minhas sinceras desculpas se esqueci de alguém que tenha contribuído direta ou indiretamente com esse tutorial e que não tenha o seu nick aqui divulgado! É só falar que eu corrijo!
Esse tutorial não foi feito pensando em usuários iniciantes! Ele também faz uso maciço, se não quase que exclusivo, da linha de comando! Portanto se não gosta do bom e velho terminal, pare por aqui!!!!
O que eu fiz foi juntar muita informação que estava espalhada no tópico do Hqxriven do kernel Ominislash! Coisas que eu e os colegas acima citados fomos descobrindo e testando ao longo do tópico do kernel Omnislash! Portanto este tutorial não serve e nem quer substituir o tópico do Hqxriven! Ele atende a pedidos insistentes dos participantes do tópico do Hqxriven que pediam essas informações reunidas em um só lugar!
Se qualquer colega do fórum quiser acrescentar ou corrigir qualquer informação do tutorial abaixo, por favor esteja a vontade para o fazer!
Então vamos deixar de conversa fiada e partir para o que interessa!!!
1- Introdução!Para quem gosta de ter o máximo de desempenho possível do seu sistema operacional já deve ter se perguntado qual o motivo de uma distribuição ser mais rápida que outras! Foi a resposta de uma pergunta como essa que levou a existência do tópico do Hqxriven! Mas ainda não satisfeito, eu me perguntava qual o motivo de ao utilizarmos opções de otimizações para o kernel para um processador que não era o meu, ter um desempenho maior do que quando usava as opções para o meu processador? Este tópico é a reposta dessa minha pergunta! O que eu tentarei a seguir é fazer o resumo da síntese de um assunto bastante amplo e complexo, mas que vale a pena ser relatado para que você tenha um melhor entendimento do que estará fazendo com os comandos a seguir!
Os desenvolvedores do Kernel Linux e de grandes distribuições tem uma tarefa muito ingrata na hora de fazer um kernel ou sistema que funcione bem não importa qual seja a sua configuração! Na tentativa de fazer com que o kernel Linux funcione numa variedade muito ampla de processadores, afinal ele não sabe em que modelo ou marca de fabricante de processador o kernel vai funcionar, o desenvolvedor é obrigado a tomar medidas que façam com que o kernel funcione desde de um 286 a um Core i7 de última geração! Ou seja, estamos cobrindo quase 30 anos de história de processadores! E vocês sabem o que apenas um ano representa em matéria de desenvolvimento de processadores!
Distribuições mais modernas que visam apenas processadores mais recentes já não possuem compatibilidade com processadores com mais de 11 anos de idade! Mesmo assim isso representa um período gigantesco em matéria de novas tecnologias e instruções embutidas no processador! O resultado é o uso de configurações genéricas no kernel para que ele possa funcionar numa miríade de modelos e marcas de processadores! Se você acha que apenas AMD e Intel fazem processadores pesquise mais um pouco sobre o assunto!
Se você tiver curiosidade, visite as páginas da Intel ou AMD e procure ler a respeito das instruções de otimização que cada processador tem embutida dentro dele! Para começar, pesquise sobre instruções SSE! Se o kernel não for capaz de reconhecer alguma instrução do processador ou precisar de uma instrução que não está disponível no processador em questão ele simplesmente não "liga"! Um exemplo prático disso foi o que ocorreu com o nosso amigo vampire_thunder na tentativa da instalação do Ubuntu 10.10 em um K6-II 500! O kernel do Ubuntu 10.10, voltado para processadores com menos de 10 anos de idade, não "ligou" com um k6-II 500 por ele não ter suporte as instruções cmov!!! Com isso o vampire teve que usar o Ubuntu 10.04 que ainda dá suporte a processadores tão velhos!
Então agora você já deve estar passando o cartão ou você já deve estar se fazendo algumas perguntas! Para que o kernel funcione no maior número possível de processadores os desenvolvedores removem as instruções de otimização dos processadores mais novos para que o kernel funcione num processador do arco da velha? Sim, é isso mesmo o que acontece!!!! Então quer dizer que o meu novíssimo Phenon X6 ou Core i7 rodam muito aquém de sua capacidade máxima? Sim, é isso mesmo o que ocorre!!!
Mas nem tudo está perdido! Se você costuma compilar o seu kernel esse problema pode ser evitado e você poderá retirar cada gota do desempenho de seu caro processador! Mesmo que ele seja um Pentium 4 ou o Atom! Essas alterações são feitas nas instruções passadas para o
GCC ( GNU Compiler Collection) na hora de compilar o seu kernel! Em distribuições feitas para serem compiladas, como o Arch Linux e o Gentoo, seus usuários já estão acostumados com isso! Inclusive o Arch Linux e o Gentoo trazem ainda mais opções de compilações das que mostradas a seguir! Lembre-se, o Ubuntu não é uma distribuição para ser compilada! Ela foi feita para usar os pacotes .deb já prontos pela equipe da Canonical! O que vamos fazer é ter o melhor de dois mundos! A praticidade de não ter que compilar um sistema inteiro mas sim compilar apenas a parte principal e maior responsável pelo desempenho do sistema! Se você quiser tirar cada gota máxima de desempenho do seu sistema inteiro, sugiro que mude de distribuição! Passe a usar o Arch Linux ou o Gentoo!!!
2- Entendo as alterações do GCCTudo começou com uma simples pergunta: Qual o motivo do meu sistema com Core i7 desempenhar melhor quando eu colocava o kernel para ser otimizado para Pentium 4 do que para Core2? Você que está acostumado a compilar o kernel Linux sabe da suma importância de acertar o processador no Menuconfig do kernel para o desempenho ideal! Por isso essa pergunta me deixava com um elefante atrás da orelha!!!
Mas antes da resposta a essa pergunta vamos entender o que é o GCC!
Segundo a Wikipedia:
O GNU Compiler Collection (chamado usualmente por GCC) é um conjunto de compiladores de linguagens de programação produzido pelo projecto GNU. É software livre distribuído pela Free Software Foundation (FSF) sob os termos da GNU GPL, e é um componente-chave do conjunto de ferramentas GNU. É o compilador padrão para sistemas operativos UNIX e Linux e certos sistemas operativos derivados tais como o Mac OS X. Originalmente suportava somente a linguagem de programação C e era designado GNU C Compiler (compilador C GNU). Com o tempo ganhou suporte às linguagens C++, Fortran, Ada, Java e Objective-C, entre outras.Depois de muita pesquisa e leitura, descobri o seguinte: Segundo a documentação do GCC, na teoria, deveríamos ter melhor desempenho ao se colocar a arquitetura correta do processador na hora de compilar! O problema é que isso vale mais para distros feitas para serem compiladas como Arch Linux e o Gentoo! Essas duas distros possuem um arquivo de configuração onde dentro dele estão contidas todas as instruções na hora de compilar qualquer coisa no sistema! O Debian/Ubuntu não possuem tal coisa! Nem vou falar do apt-build pois este não conta para compilar kernel!
Como ia dizendo, na documentação do GCC existe a opção de ativar as otimizações do seu processador! Como no Ubuntu não temos o mesmo arquivo de configuração do Gentoo ou do Arch Linux, faremos as alterações diretamente nos arquivos do fonte do Kernel! Nós vamos alterar a linha do
CFLAGS (para o C) e o
CXXFLAGS (para o C++) e todas as linhas que contiverem as opções
"march",
"mtune" e
"mcpu" nos arquivos que importam do fonte do kernel!
Desde a versão 4.3 do GCC existe a opção
mtune que ajuda na ativação de instruções para processadores x86! Ou seja, ela ajuda de forma
"genérica"! Apesar de obsoleta nas versões mais recentes do GCC essa opção ainda é utilizada por questões de compatibilidade! Para um melhor aproveitamento na ativação das instruções dos processadores foi criada a opção
march que ativa instruções específicas para o seu processador! Mesmo assim fica difícil saber qual opção utilizar sendo tantos os modelos e variações nas instruções dos processadores! Para facilitar a nossa vida os desenvolvedores criaram a opção
"march=native" que verifica em qual processador o código vai ser compilado e ativa todas as instruções deste processador em questão!
Para entender um pouco mais, ao se usar o
"mtune" a compilação irá otimizar o código para o processador, mas ele não usa as otimizações específicas das instruções do mesmo! Ao se utilizar a opção
"march", ele usa as otimizações específicas das instruções do processador! E mais, ao se usar a opção "march" implica em dizer que o mtune vai seguir o "march", mas o contrário não é verdadeiro!
Embolou o meio de campo?
Fica fácil entender com um exemplo!
Se eu colocar mtune = core2, quer dizer que o código a ser compilado vai usar otimizações para o Core2, mas por compatibilidade e segurança ele não vai usar instruções específicas, vai usar instruções genéricas nas instruções! Aí vai depender do desenvolvedor, ele pode colocar a i386 se quiser nas instruções, mas ao que tudo indica, eles usam a nocona (que foi o primeiro pentium 4 com instruções 64bits). A nocona possui: Pentium4 com extensões 64-bit , MMX, SSE, SSE2 e SSE3!
Se eu usar march = Core2, quer dizer que ele vai usar as instruções específicas do Core2 ( extensões 64-bit, MMX, SSE, SSE2, SSE3 e SSSE3), ou seja, se o seu processador não suportar tais instruções, o kernel não "liga"!!! Ao usar o march = Core2 implica em dizer que o mtune também será Core2! Passaram o cartão agora?
Resumindo:
mtune = código otimizado, sem instruções do processador otimizadas!march = código e instruções do processador otimizadas de acordo com a arquitetura do processador selecionada! Eu só tive essa luz no fim do túnel porque eu achei um fórum de programadores em C e um Canadense deu uma explicação matadora que eu não tinha lido em canto nenhum ainda!
Leiam o que o cyberfish diz:
mtune=... does NOT affect the instruction sets used, or machines the executable is run on.
For that (eg, enabling SSE), you'll need march=....
If you do march=core2 for example (on a new GCC), it will use all the instruction sets available to Core 2 CPUs. march=x also sets mtune=x. The executable won't run on older CPUs.
If you ONLY use mtune=core2, it will generate code that runs the best on a Core 2, but will still only use instructions available to all x86 CPUs (eg, no SSE), hence it will still run on old CPUs, just a little slower.
As a real world example, I think a few years ago some Linux distribution decides to use -march=pentium3 -mtune=pentium4, or something like that. That means, the code is guaranteed to run on a P3, but optimized for a P4, since they predict most people will be running for a P4.
If you don't use any flag, GCC will assume -march=i386 (lowest x86).
If you want GCC to use all instruction sets on your CPU, and optimize for your CPU (because, for example, the code will only be run on your machine), you can do -march=native (which also sets mtune=native). Only available in newer GCC (it was introduced in 4.3 or 4.4 I THINK).
-m32 and -m64 are only for generating 32-bit code on a 64-bit machine, or generating 64-bit code on a 32-bit machine, respectively. GCC defaults to 32-bit on 32-bit, and 64-bit on 64-bit.
O tópico é este aqui:
http://cboard.cprogramming.com/c-programming/127502-%5Bgcc%5D-compiling-generic-x86-architecture-2.htmlE quanto ao kernel? Tudo indica que ao usar o menuconfig estamos alterando apenas o mtune e não o march!!!! Pois o sistema já foi construído! É uma distro binária! Com o gentoo e o arch linux não, o "normal" deles é você construir o sistema inteiro!
Para bular tal limitação no Ubuntu é que vamos alterar os arquivos do Makefile do kernel! O arquivo Makefile é um dos que contém as instruções para compilar o código do kernel!
Essa dica foi dada por outro usuário do fórum internacional do Ubuntu, o tópico é este aqui:
http://ubuntuforums.org/showthread.php?t=15795053- Colocando a mão na massa! Já sei, você está ansioso para colocar isso tudo em prática! Mas espere só mais um pouco! É que você pode ter dúvida em que momento da preparação para compilar o kernel você vai executar os comandos e alterações abaixo!
Você pode continuar o seu tutorial habitual, como o do Hqxriven. Baixe o fonte do kernel que você for usar, descompacte-o, aplique os patchs que você assim desejar, faça as alterações do menuconfig/xconfig que você pretende e só então realize as alterações sugeridas abaixo antes de efetivamente dar os comandos para compilar o kernel! Descobri que assim as chances de erros são bem menores!
A primeira coisa a saber é quais as opções colocar na linha do CFLAGS do Makefile do diretório raiz do fonte do kernel!
Atenção, se a sua versão do GCC for muita antiga o comando abaixo não funcionará, portanto você terá que migrar para uma versão do GCC mais recente!
Por falar em GCC, sempre procure usar a versão mais recente do GCC se quiser extrair o máximo de desempenho de processadores modernos! Aqui mesmo no Fórum eu já coloquei um tuto de como alterar a versão do GCC do Ubuntu e o Alyscom mostra lá que existe um PPA para as versões do GCC mais recentes também! Contudo, pode haver erro ao compilar o kernel numa versão moderna do GCC e você for utilizar esse kernel em um sistema com GCC mais antigo!!! Então cuidado! Para não correr riscos o ideal é usar um sistema com a mesma versão do GCC em que o kernel foi compilado!
Para saber o que vai ser alterado use o comando abaixo na máquina em questão:
$cc -march=native -E -v - </dev/null 2>&1 | grep cc1
Como exemplo eu vou colocar a saída do comando do meu Core i7:
galactus@galactus-mint ~ $ cc -march=native -E -v - </dev/null 2>&1 | grep cc1
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/cc1 -E -quiet -v - -D_FORTIFY_SOURCE=2 -march=core2 -mcx16 -msahf -mpopcnt -msse4.2 --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=256 -mtune=core2 -fstack-protector
A parte em negrito é a que interessa para melhorar o desempenho! As opções
-D_FORTIFY_SOURCE=2 e
-fstack-protector servem para melhorar a segurança da memória contra ataques de segurança! Se decidir colocar essas opções na linha do CFLAGS, lembre-se de ativar a opção
fstack-protector no menuconfig do Kernel!!!!
Como podem ver o comando mostra a versão do GCC do meu sistema, que no exemplo acima usa o GCC 4.4.5, mostra que vai otimizar o processador para sua família correta "core2", ativa todas as suas instruções específicas deste processador com o -msse4.2, passa parâmetros específicos para otimizar a memória cache L1 e L2 do processador além de outras opções de otimização que vocês podem pesquisar na documentação do GCC!
De posse dessas informações, procure o arquivo Makefile na seguinte pasta (você também pode alterar os arquivos da pasta de link simbólico "linux"):
/usr/src/linux-2.6.XX/Makefile
A linha que vamos alterar está por volta da 232!
O arquivo original deve ser parecido com este:
# SHELL used by kbuild
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi ; fi)
HOSTCC = gcc
HOSTCXX = g++
HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTCXXFLAGS = -O2
A linha em negrito é a que interessa!
A linha modificada deve ficar assim:
# SHELL used by kbuild
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi ; fi)
HOSTCC = gcc
HOSTCXX = g++
HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -march=native -mcx16 -msahf -mpopcnt -msse4.2 --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=256 -mtune=generic
HOSTCXXFLAGS = -O2
Dicas:- Acrescente a opção
-pipe para acelerar a compilação
- Se estiver compilando um kernel 64bits não precisa colocar a opção
-fomit-frame-pointer, ela já é padrão em compilações de kerneis 64bits
- Altere a opção
-march=nomedafamíliadoprocessador para
-march=native- Se usar a versão do
GCC 4.5.1 para baixo, na opção -mtune use
-mtune=generic, assim o desempenho é maior! Do
GCC 4.5.2 em diante, use a saída original do comando acima! No meu caso foi -mtune=core2!
- Não use a opção
-03! Permaneça com a
-02!
Essas são as principais alterações a fazer! Se não quiser mexer nas demais pastas, tudo bem! Se quiser extrair um pouco mais, continue lendo!
Agora encontre as seguintes pastas listadas abaixo com as linhas onde você provavelmente vai encontrar as opções march, mtune ou mcpu!
A dica é do 4d4c47:
/usr/src/linux-2.6.xx/arch/x86/boot/compressed/Makefile - linha 12
/usr/src/linux-2.6.xx/arch/x86/boot/Makefile - linha 63
/usr/src/linux-2.6.xx/arch/x86/kernel/acpi/realmode/Makefile - linha 35
/usr/src/linux-2.6.xx/arch/x86/Kconfig.cpu - linha 300
/usr/src/linux-2.6.xx/arch/x86/Makefile - linhas 53, 54, 57, 58, 59, 60
/usr/src/linux-2.6.xx/arch/x86/Makefile_32.cpu - linhas 5, 7, 9, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 43, 46, 47, 63
Especial atenção para o arquivo Makefile_32.cpu! Aí está a opção para otimzação do seu processador!!!!
Em todos os arquivos acima listados, altere todas as opções ativas de
-march=xx para
-march=native, de
-mtune=xx para
-mtune=generic (se usar a versão do GCC 4.5.1 para baixo) ou para -
mtune=nomedafamíliadoprocessador que a saída do comando mostrou se usar a versão do GCC 4.5.2 em diante, e
mcpu para
-mcpu=native!
De novo o colega 4d4c47 trás a dica: depois de tudo isso, comece a compilação ( pra ver se tá compilando com march=native mesmo, abra um outro terminal e execute após 2 minutos de compilação:
ps ax | grep gcc | grep march )
E só!!!
4- O que eu ganho com isso tudo?Ao realizar essas alterações você terá um kernel compilado otimizado especificamente para o seu processador, com todas as instruções que estão embutidas nele ativas, com sua memória cache otimizada entre outras opções! O resultado é um sistema muito mais ágil, principalmente nas operações que envolvem Áudio, Vídeo, animações flash, navegação na internet e diminui o consumo do processador, então sua conta de energia vai ser menor e sua bateria de notebook vai durar mais! Na hora de chamar um programa pela segunda vez a resposta é mais rápida também!