Crossing your arms relieves pain

20 maio

Now that’s a very strange suggestion. Nevertheless, it makes sense.
Give it a read, share your thoughts!

AOC – Pipeline II

12 maio

Arquitetura e Organização de Computadores

Pipeline II

Na continuação de Pipeline, vou explicar o que são e como tratar os Hazards de Pipeline.

Hazards

Hazards são, como vimos no fim do post Pipeline I, situações que impedem o pipeline de continuar sua execução natural ou o fazem perder performance por computar incorretamnete. Existem três tipos de Hazards, são eles:

  • Hazards Estruturais
  • Hazards de Dados
  • Hazards de Controle

1. Estruturais

Hazards Estruturais acontecem quando duas ou mais instruções sobrepostas no pipeline tentam usar o mesmo recurso de hardware ao mesmo tempo. Por exemplo se um processador possui memória compartilhada entre dados e instruções, em um momento em que o estágio MEM (referência à memória) e o estágio IF (busca uma instrução) ficam sobrepostos no pipeline, ocorre um hazard estrutural.

Isso pode ser simplesmente resolvido com o uso de bolhas no pipeline. Isso significa dizer que:

# É possível inserir “bolhas” (instruções sem operações) no pipeline e atrasar a execução da instrução atual até que o operando requerido seja computado corretamente e escrito no registrador. Esse método diminui a eficiência do pipeline, que é totalmente o oposto da idéia do próprio pipeline, mas mesmo assim, é uma estratégia válida porque reduz o custo de memória quase que pela metade em uma máquina que suporta acesso à memória e à instruções a cada estágio do pipeline para evitar o hazard, por exemplo.

2. De Dados

Hazards de Dados acontecem quando uma instrução depende no resultado de uma instrução anterior de modo que a primeira instrução ainda não computou esse resultado. Como por exemplo:

ADD R1, R2, R4         ; Instrução 1
SUB R4, R5, R1          ; Instrução 2
AND R6, R1, R7         ; Instrução 3
OR R8, R1, R9            ; Instrução 4
XOR R10, R1, R1  1   ; Instrução 5
(Instruções de processadores da arquitetura RISC, onde Rn são registradores)

Nesse caso, R1 só é escrito no último estágio de execução da instrução 1, mas já é usado no segundo estágio da instrução 2. Veja:

ADD R1, R2, R3 IF ID EX MEM  WB
SUB R4, R5, R1 IF ID EX MEM WB

A tabela acima ilustra bem essa situação no caso RAW. O estágio de Decodificação (ID) da instrução SUB precisa do valor de R1, mas esse valor não vai ser computado até o estágio WB (Writeback), onde a instrução ADD faz escrita no registrador.

Existem três tipos de Hazards de Dados:
– Imaginem duas instruções 1 e 2. 

  • RAW (Read After Write – Leitura depois da escrita): Também chamado de Hazard de Dependência, ocorre quando a instrução 2 usa o resultado da instrução 1 que ainda não foi calculado ou buscado.Isso ocorre porque mesmo que a instrução 2 venha depois da instrução 1, no pipeline ela é executada simultaneamente, como no nosso exemplo da tabela acima.Outro exemplo:

     SUB R1, R2, R3  ; Instrução 1
    ADD R4, R1, R3  ; Instrução 2

  • WAR (Write After Read – Escrita depois da leitura) : Também chamado de Hazard de Anti Dependência, ocorre em pipelines de tamanho variável, quando a instrução 2 escreve no registrador antesque a instrução 1 o leia. Por exemplo:

    SUB R4, R1, R3  ; Instrução 1
    ADD R1, R2, R3  ; Instrução 2

    SUB R4, R1, R3 IF  …  …  ID
    ADD R1, R2, R3 IF ID EX MEM WB

    A tabela acima ilustra essa situação bem, onde por algum motivo a instrução 1 levou mais ciclos de clock para realizar a leitura para os registradores, mas a instrução 2 realizou escrita nesse registrador antes.

  • WAW (Escrita depois de escrita) : Também chamado de Hazard de Output, ocorre apenas em pipelines que escrevem em mais de um estágio ou permitem que uma instrução continue sua execução mesmo quando uma instrução anterior está parada (vamos ver o que são instruções ‘paradas’ logo abaixo).

     SUB R1, R4, R3  ; Instrução 1
    ADD R1, R2, R3  ; Instrução 2

    SUB R1, R1, R3 IF ID  …  …  WB
    ADD R1, R2, R3 IF ID EX MEM WB

    A tabela acima mostra como o hazard ocorre. Por algum motivo a instrução 1 levou mais ciclos de clock para terminar, enquanto isso a instrução 2 executou todos seus estágios, incluindo o de escrita. O problema é que a instrução 2 está executando a operação em um registrador que ainda não foi escrito pela instrução 1.

Para resolver os Hazards de Dados, existem algumas opções também:

  • Forwarding – Para resolver os problemas de dependência, foi criada uma técnica chamada de Forwarding, onde um novo circuito é adicionado ao pipeline. É como um barramento que corta caminho através do pipeline. Apesar da necessidade de adicionar um novo circuito ao hardware, funciona bem por ser bem mais rápido transferir um dado via hardware do que esperar um estágio do pipeline terminar de executar para então preparar os dados para a próxima instrução que depende deles.
  • Reordenação de Código – O problema é evitado usando um compilador ‘inteligente’ que reordena o código em assembly para evitar esses tipos de dependência. Não é muito comum, pois o compilador deve ter informações detalhadas da estrutura e do ‘rítmo’ de execução do pipeline no qual o hazard ocorreria. Esse tipo de compilador é chamado de Compilador Dependente de Hardware.
  • Inserção de Bolhas – Como vimos nos Hazards de Estrutura, inserimos uma bolha no pipeline para atrasar a execução da instrução, ganhando tempo para a instrução posterior. Nesse caso é um método de última opção que pode ser usado quando forwarding ou o auxílio de um compilador especial não estiver disponível ou não for suportado pelo hardware.

3. De Controle

Como vimos no último post de AOC (Pipeline I), um dos mais comuns problemas de pipeline são os de desvio de fluxo. Esses problemas são os Hazards de Controle e são causados por desvios e outras instruções que alteram o PC (Program Counter).

Recapitulando um pouco, é comum em Hazards de Controle acontecerem em situações como:

MOV AX, 10h      ; Instrução 1
CMP AX, BX         ; Instrução 2
    JAE  9f                  ; Instrução 3
SUB AX, 5h           ; Instrução 4
9: ADD SP, 8          ; Instrução 15
Até a instrução 3, o processador não sabe qual instrução deve executar a seguir, por isso, geralmente continua o fluxo normal da instrução 4 e adiante. Porém, caso o jump da instrução 3 seja feito, todas as instruções buscadas entre o primeiro estágio de pipeline da instrução 3 até o fim do estágio de execução são removidas do pipeline e o processador deve então pôr a instrução 15 no pipeline para executa-la, ficando ocioso por um tempo significante. Esse tempo em que fica ocioso é chamado de penalidade de desempenho.
Mostrando de novo a ilustração dessa situação:

Desvio Condicional e Penalidade de Desempenho

Hazards de Controle podem ser tratados dos seguintes modos:
  • Inserção de bolha – Insere-se uma bolha no pipeline até que seja computado se o desvio vai ser tomado ou não.
  • Nunca tomar o desvio – Como foi mostrado em nosso exemplo, assume-se que o desvio nunca é tomado e a execução sempre ocorre naturalmente. Caso no fim do pipeline da instrução o desvio seja tomado, ocorre a penalidade de desempenho.
  • Sempre tomar o desvio – Nessa abodagem, o pipeline sempre assume que o desvio vai ser tomado e já começa a agendar as instruções posteriores ao desvio sem saber se ele na verdade vai ser tomado ou não.
Desses três métodos de tratamento dos Hazards de Controle, o mais comum, assim como pra qualquer outro hazard é o uso de bolhas. Nesse caso o pipeline é parado até que seja computado o estágio de decisão de fluxo, evitando quaisquer tipos de penalidades e perdas maiores de desempenho.
Bom, é isso aí, acabamos então o assunto de hazards de pipeline. Qualquer coisa, só deixar um comentário!
Até!

AOC02 – CISC & RISC

12 maio

Arquitetura e Organização de Computadores

Arquiteturas CISC e RISC

A aula de hoje foi entrando mais a fundo nos detalhes das arquiteturas CISC e RISC, um assunto muito interessante e cheio de coisas, então vou pular os rodeios e ir direto ao ponto.

CISC – Complex Instruction Set Computer

Ou, traduzindo para o português: Computador de Conjunto Complexo de Instruções “é uma arquitetura de processadores capaz de executar centenas de instruções complexas diferentes sendo assim, extremamente versátil” – trecho da descrição da arquitetura no Wikipédia.

CISC é a arquitetura usada pelos processadores da família Intel x86, presente na maioria (se não, em grande parte) dos computadores pessoais hoje em dia e é bem provável que o seu seja um desses também.

De modo geral, a filosofia da arquitetura é que hardware sendo mais rápido que software, os processadores deveriam ter conjuntos de instruções mais poderosos, permitindo aos programadores fazer bem mais coisas com menos linhas de código, se aproximando mais à linguagens de alto nível.

Uma visão geral da arquitetura CISC:

  • Necessidade:
    Os processadores devem ser capazes de executar operações complexas para se aproximar mais das instruções de linguagens de programação de alto nível. Com o crescimento das linguagens de alto nível como C, FORTRAN ou ALGOL no fim da década de 70 e início da década de 80, os desenvolvedores de compiladores começaram a ter muita dificuldade em manter uma boa performance e simplicidade do código gerado em assembly para os programas escritos nessas linguagens de alto nível por causa de suas instruções mais complexas.
  • Problema:
    Essa distância entre as instruções de linguagem de máquina existentes na arquitetura de processadores da época e as instruções complexas das linguagens de alto nível gerou uma distância entre as duas que ocasionava em maior necessidade de uso do processador para executar os programas. Esse distância é chamada de gap semântico e é um grande problema da arquitetura CISC existente até nos dias de hoje, pois a capacidade de processamento do processador deve aumentar de acordo com a complexidade das linguagens de alto nível.
  • Solução:
    Para diminuir o gap semântico, os arquitetos de processadores tiveram que além de criar instruções mais complexas, utilizar uma micro programação nos processadores CISC, isto é, criar uma camada de microcódigo a nível de hardware na qual as instruções complexas em Assembly serão traduzidas e então executadas. Essas operações em microcódigo, porém, nem sempre tornavam o processador mais rápido, mas pelo contrário, em algumas situações como onde não era necessário o uso de instruções complexas, essa camada de microcódigo poderia gerar mais ciclos de execução para uma instrução simples. Outra situação é que os processadores CISC possuem um número limitado de registradores de propósito geral. Nos x86 da Intel são apenas 4 (AX, BX, CX e DX) e a memória RAM é constantemente usada em operações, o que além de ser mais lento (visto que os registradores estão dentro do próprio processador, diferente da memória RAM) requer vários modos de endereçamento para as instruções fazendo com que seus tamanhos nem sempre sejam iguais e tornando o trabalho do decodificador um bocado mais difícil – e lento.

    Vale notar então que a “solução” de utilizar instruções complexas e uma camada de microcódigo acabou por gerar novos problemas.

  • Vantagens:
    Com as instruções complexas, algumas instruções em uma linguagem de alto nível poderia traduzir para exatamente uma instrução em Assembly, reduzindo a dificuldade para escrever compiladores, aumentando a compactação de código, facilitando o processo de debug, aumentando a eficiência de programas escritos em linguagens de alto nível e com isso diminuindo seus custos, tamanhos e complexidades.
  • Desvantagens:
    Em alguns casos, o uso de mais instruções simples era mais eficiente do que usar menos instruções complexas, pelo fato de o microcódigo gerar novos ciclos de execução e o decodificador ter mais dificuldade para decodificar as instruções. Sem contar com o uso de operandos de memória, que podem causar hazards estruturais prevenindo a execução de instruções paralelas no pipeline.

É isso aí, amanhã termino o post com um resumo da arquitetura RISC.
Talvez dê alguma editada aqui e adicione mais alguma coisa, também.

Até!

EDA01

10 maio

Estruturas de Dados I

Algoritmos de Ordenação pt.2*

*Bom, esse sendo o primeiro post de Estruturas de Dados, vou fazer como disse que faria. Passar o resumo da matéria atual e pouco a pouco, fazer posts com resumos das matérias já vistas.

Hoje vi a segunda parte dos algoritmos de ordenação. Os métodos sofisticados ou algoritmos eficientes.

Os que vimos até agora foram:

  • Shell Sort
  • Merge Sort
  • Quick Sort
Shell Sort

Shell Sort é um algoritmo de ordenação sofisticado ou eficiente. Um algoritmo simples de entender, relativamente rápido de processar e fácil de implementar.

Seu nome vem de Donald Shell, que o criou em 1959 com a idéia de dividir um grande vetor de dados em vetores menores, ordenando-os e fazendo isso novamente para ter um único vetor praticamente ordenado e então trabalhar em cima dele, que seria mais prático e rápido. O algoritmo de Shell Sort em si mesmo não ordena nada, mas aumenta a eficiência de outros algoritmos de ordenação (como o da inserção e seleção, que serão vistos no próximo post de EDA), o que definitivamente faz sentido quando se entende como ele funciona.

Princípios básicos:

  • O Shell Sort se baseia em uma variável chamada de incremento de sequência, ou incremento de shell, que é dado por e ao decorrer da execução do algoritmo, é decrementada até 1.
  • Utilizando o incremento de shell, o algoritmo compara elementos distantes em um vetor, em vez de comparar os adjacentes.
  • No algoritmo, a ordenação é realizada em vários passos, usando uma sequência de valores do incremento de shell <h1, h2, h3…hN> onde começando por hN selecionamos apenas os valores que estão hN elementos distantes um do outro, então ordenamos esses elementos com algum algoritmo de ordenação simples como bolha, seleção ou inserção. Deste modo, apenas os elementos selecionados serão ordenados, os outros são todos ignorados.

    Fig. 1 - Shell Sort com hN = 4

    A Fig. 1 é um exemplo de como são selecionados os elementos do vetor usando a variável incremento de shell. Sempre selecionamos os elementos que estão hN elementos distantes um do outro. O segundo ciclo (h2) da figura mostra bem isso. Notem que os valores selecionados foram sempre de 2 em 2, pois h2 = 2.

  • Como escolher valores para h?
    Existem vários modos de escolher valores para h baseados em estudos de eficiência, você pode até escolher os valores que quiser, apesar de ser altamente não recomendável por questões de eficiência. O método de seleção de valores para h proposto por Donald Shell foi h = n/2 onde n é o número de elementos do vetor, mas já foi provado que sua eficiência é baixa. O que vimos hoje foi o da sequência de Donald Knuth, explicado como:

    h = 3*h+1
    E a sequência gerada: 1, 4, 13, 40, 121, 364, 1093, 3280…

    Partindo de h = 1[*] precisamos do maior valor possível que seja menor que o número de elementos no vetor, então basta calcular:

    h1 = 3*1+1 = 4
    h2 = 3*4+1 = 13
    h 3 = 3*13+1 = 40
    etc.

    Para decrementar os  valores de h até h=1 podemos usar a fórmula inversa:
    h = (h-1)/3
    …3280, 1093, 364, 121, 40, 13, 4, 1.

  • [*] O valor mais baixo possível de h sempre deve ser 1, para que seja possível comparar elementos adjacentes. Veja a Fig. 1 novamente e note que o último passo da ordenação é h = 1, que faz a comparação e ordenação dos elementos adjacentes
  • Exemplificando:
    Se ainda não deu pra entender bem, veja assim:
    hN= valor mais alto na fórmula que seja menor que o número de elementos no vetor.
    Por ex: Para um vetor de 20 elementos, hN = 13 pois 3*13+1 = 40 que é maior que 20.Ou ainda, em C:

        /* tamanho é o número de elementos no nosso
         * vetor fictício */
        int tamanho = 20, h = 1;  
    
        while(h < tamanho) {
            h = 3*h+1;
        }
        /* ao final desse laço, h valerá 13, já que como
         * vimos no exemplo acima, o próximo resultado da
         * equação seria 40, que não iria satisfazer a
         * condição h < tamanho. */
Até agora pode estar parecendo complicado, mas na verdade vamos ver que o algoritmo Shell Sort é bem simples analisando sua implementação em C abaixo:
void shellSort(int *vet, int tamanho) {  

//Cria variáveis auxiliares
    int i , j , valor;

//Cria a variável h que será usada para selecionar
//os grupos de valores do vetor 
    int h = 1;
    do {

//Aqui como usamos do/while, pegamos o valor 40
//como último valor aceito, não 13. 
//Vamos entender o porquê disso mais pra baixo.
        h = 3*h+1;
    } while(h < tamanho);
    do {

//Aqui dividimos o incremento de shell para montar
//os grupos de valores que serão ordenados. Depois de
//todos os valores de h serem ordenados, dividimos h
//novamente e ordenamos pares mais próximos, até que
//h = 1 e os pares adjacentes sejam ordenados.
        h /= 3;
//É aqui que a comparação e a ordenação acontecem:
        for(i = h; i < tamanho; i++) {

//Valor vai receber o h-ésimo elemento do vetor
            valor = vet[i];

//j vai ser o índice do elemento que será comparado
//com valor. Ex: Na primeira iteração do laço:
//Se h = 13 e i = 13 então j = 0 pois j = 13 - 13.
//Então vet[13] será comparado com vet[0], então com
//vet[1] e etc. até i < tamanho e h será dividido
//novamente para selecionar um novo grupo de elementos
//em uma distância menor e os ordenará.
            j = i - h;

//Aqui é feita a troca de lugares entre os elementos,
//Seguindo o nosso exemplo, se vet[13] < vet[0],
//então vet[13] recebe o valor de vet[0].
            while (j >= 0 && valor < vet[j]) {
                vet[j + h] = vet[j]; //vet[13] recebe vet[0]
                j -= h; //Aqui se j = 0 e h = 13, j = -13.
            }

//Para que aqui, vet[0] receba o valor de vet[13]
            vet[j + h] = valor;
        }

//E a validação de h > 1 é feita para que quando
//a última ordenação h1 for feita, o programa termine.
    } while( h > 1);
}
E para fixar, um exemplo final para analisar:
Exemplo de Shell Sort

Fig. 2 - Shell Sort em sequência 8-4-2-1

Na Fig. 2 foram escolhidas potências de 2 para h, o que não proporciona uma das melhores performances, mas é um bom exemplo para entender as seleções de elementos e ordenações.
Bom, como esse post já ficou muito grande, vou pôr o Merge Sort e o Quick Sort em outro post de continuação.
E é isso aí, qualquer pergunta ou correção, só falar nos comentários!

AOC – Pipeline I

7 maio

AOC?

Para evitar grandes títulos, ao decorrer dos posts, vou procurar utilizar siglas em vez dos nomes completos das disciplinas, mas os escrevendo por extenso no cabeçalho dos posts.

Então, começando:

Arquitetura e Organização de Computadores

Pipeline

Então, se você é da área, provavelmente já ouviu falar em Pipeline. Na aula de hoje aprendi o que é o Pipeline, conheci seus hazards e suas estratégias te otimização.

Em poucas palavras:

  • O que é? Pipeline é a implementação de uma técnica para otimizar o processador .
  • Como? O Pipeline é baseado em cliclos de clock para processar uma instrução. Cada instrução é quebrada em um número N de passos cada um guardando um valor que será usado como input no próximo passo. No Pipeline, essas instruções são sobrepostas de modo que a cada ciclo do clock, um passo de cada instrução seja executado (Fig. 1), evitando deixar componentes do processador ociosos. A performance do processador é aumentada proporcionalmente ao número de passos em que as instruções são quebradas.

Fig. 1 - Cada instrução possui 6 passos que são sobrepostos no Pipeline e executados a cada ciclo de clock de modo que a partir do 5o ciclo, a cada novo ciclo uma instrução é terminada.


Com mais detalhes:

Antes, vale a pena lembrar que:

Uma instrução em linguagem de montagem (Assembly) é formada por campos que guardam os dados necessários para a execução da instrução, geralmente apresentados como:

  • Opcode (Código de Operação) – Código que em Assembly é representado por um mnemônico, ou abreviações como ADD, MOV, STOR, etc. e indica a operação que vai ser executada, tanto quanto o modo de endereçamento de operandos utilizado.
  • N Campos de endereço – O número de campos de endereço dos operandos varia de acordo com a necessidade da operação. Geralmente de 0 a 3 operandos sendo eles o operando fonte, operando destino e dependendo da arquitetura do conjunto de instruções, uma referência à próxima instrução.
E que a CPU possui componentes internos como Buscador de Instruções, Decodificador de Instruções, Conjunto de Registradores e ULA(Unidade Lógica e Aritmética) para citar os mais comuns, com isso em mente podemos dizer que quando uma instrução é apresentada ao processador, ele ativa cada um desses componentes internos para realizar uma parte da execução dessa instrução. Esse processo é demonstrado na Fig. 2 abaixo:

Fig. 2 - Diagrama do Ciclo de Instrução

De acordo com a Fig. 2, vemos que para cada passo da execução de uma instrução apenas um componente da CPU é utilizado, deixando todos os outros componentes ociosos, e isso é um grande desperdício de processador. Para resolver esse problema, o Pipeline foi introduzido na organização dos processadores.

Como visto na Fig. 1, o Pipeline é dividido em estágios de acordo com o ciclo de instrução. O número de estágios varia dependendo do tipo de processador, em nosso caso são 6:

  • FI (Fetch Instruction) – Busca a próxima instrução e a armazena em um buffer.
  • DI (Decodificar Instrução) – Determina o opcode e os operandos que serão usados.
  • CO (Calcular Operandos) –  Calcula o endereço dos operandos de origem baseado na forma de endereçamento usada na instrução.
  • FO (Fetch Operands) – Busca cada operando da memória, de uma E/S (I/O) ou de um registrador.
  • EI – Executa a operação indicada na instrução.
  • WO (Write Operand) – Escreve o resultado na memória.
Desse modo, é possível sobrepor as instruções permitindo que a cada ciclo de clock o processador utilize todos seus componentes para executar cada estágio de diversas instruções ao mesmo tempo. Aumentando a performance do processador de modo que:
  • No estágio 1, a instrução é buscada e armazenada. Já no estágio 2 o Decodificador é ativado para interpretar a instrução, enquanto o estágio 1 está buscando uma nova instrução. Quando os estágios 1 e 2 terminam, o estágio 2 passa para o estágio 3 e começa a calcular os operandos, o estágio 1 passa para o estágio 2 e começa a decodificar a instrução recém adquirida e o estágio 1 busca uma nova instrução. Mantendo sempre os componentes responsáveis por cada estágio trabalhando. Isso monta a escada de execução mostrada na Fig. 1.
Agora que já entendemos o que é o Pipeline de instruções, algumas perguntas são feitas:
  1. Se no pipeline várias instruções são executadas ao mesmo tempo, como o processador sabe quais vão ser essas próximas instruções?
  • De modo geral, o pipeline carrega sempre a próxima instrução na sequência. Veja o trecho de código abaixo.
MOV AL, 1h             ; Instrução 1
MOV EAX,  [EBX]  ; Instrução 2
SUB AH, AL             ; Instrução 3
Cada instrução é carregada no pipeline na ordem de sequência. A instrução 1, depois a 2, depois a 3. E isso funciona muito bem, se assumirmos que cada instrução sempre vai passar por todos os 6 estágios do pipeline, o que nem sempre acontece. Uma instrução de LOAD, por exemplo, não tem resultado e não precisa do último estágio WO (para escrever um resultado na memória). Além disso, supõe-se que todos estágios podem ser executados em paralelo e que não haverão conflitos de memória. De todos os possíveis problemas que podem aparecer no pipeline, se destaca um: desvios condicionais.
Como o pipeline busca a próxima instrução n+1 antes que a instrução anterior n termine de executar, o que acontece quando a instrução n é um desvio condicional?
MOV AX, 10h      ; Instrução 1
CMP AX, BX         ; Instrução 2
    JAE  9f                  ; Instrução 3
SUB AX, 5h           ; Instrução 4
9: ADD SP, 8          ; Instrução 15
No trecho de código acima temos um exemplo de desvio condicional, onde se a comparação na instrução 3 for verdadeira, o programa é desviado para a instrução 15, como demonstrado na Fig. 3.

Fig. 3 - Desvio Condicional e Penalidade de Desempenho

Em uma situação como essa, no início na execução da instrução 3, o processador não tem nenhuma maneira de saber se o desvio será tomado ou não, então as instruções da sequência são executadas e ao fim da execução da instrução 3, se o desvio for tomado, todas as instruções entre 3 e 15 são removidas do pipeline e nenhuma instrução é executada entre os tempos t8 e t12. Isso é chamado de penalidade de desempenho.

Outras situações que resultam em perda de desempenho do pipeline ocorrem quando o pipeline ou alguma parte dele, precisa parar porque alguma condição não permite que ele continue. Essas ‘paradas’ são chamadas de bolhas e essas situações que causam de perda de desempenho no pipeline, o impedem de prosseguir ou o fazem computar incorretamente são chamadas de Hazards do Pipeline e são divididos em três tipos que serão detalhados no próximo post de AOC. Os três tipos de hazards são: recurso, dados e controle.

Até a próxima!

Let the fun begin!

7 maio

Olá!

Caderno Geek?” você se pergunta.

Sim. E que tipo de blog é esse?

Caderno Geek foi o nome mais apropriado em que consegui pensar para o blog que nada mais vai ser que o caderno de rabiscos, matérias e devaneios de um geek desenvolvedor de software, aspirante a cientista da computação e estudante do curso. Principalmente, caderno com resumos das disciplinas vistas em aula, em todos os dias de aula (tendo começado em Maio, meio do semestre letivo, tentarei pouco a pouco atualizar o conteúdo com resumos das aulas passadas, mas dando foco nas correntes).

A idéia surgiu com meu outro blog, SciFy, onde faço clips[1] de notícias, artigos e publicações sobre ciência e tecnologia e comento sobre tais. De qualquer modo, a idéia veio quando percebi que fazendo pesquisas para comentar e explicar melhor os clips, acabava aprendendo muita coisa nova e que poderia usar isso com assuntos vistos em sala de aula tanto para rever esses assuntos quanto para repassar isso pra outros estudantes ou interessados. Logo, Caderno Geek é o caderno de muitas das disciplinas vistas no curso de Ciência da Computação. Espero que seja uma boa experiência tanto para mim como estudante e editor quanto para quem quer que se depare com o blog e se interesse pelo o que aqui tem(terá) escrito.

É isso aí. Qualquer coisa que tiver a acrescentar, não hesite em comentar!

And let the fun begin!

-Bernardo

[1] Clip ou Clipping – É um conceito criado pela empresa americana Clipmarks e usada em seus dois sites (Clipmarks e Amplify), permitindo seus usuários, com a ajuda de um plugin instalado no browser, selecionar texto, imagens e vídeos de qualquer página da internet e salva-los em forma de post de blog em poucos cliques, podendo o mesmo ser categorizado com tags e comentado pelo autor do clip e por leitores no site. Uma forma rápida de compartilhar fotos, artigos, notícias e vídeos na íntegra com o mundo todo e ferramenta a qual sou fã e recomendo a todos.