Basic for Experts
Paralelismo


  Os computadores que possuem apenas um processador, como o MSX, normalmente executam uma tarefa, programa, sub-rotina etc por vez.
  Hoje em dia, é inimaginável termos um computador que rode só uma aplicação por vez, como por exemplo, um browser ativo e um editor de texto aguardando o término da execução do browser. Até mesmo o mouse não pode esperar a execução completa de um aplicativo qualquer, sob pena de perdermos o controle sobre o sistema.
  A computação paralela visa o estudo e implementação de sistemas, que são capazes de gerenciar e executar vários programas "ao mesmo tempo". Entretanto, executar dois ou mais programas realmente "ao mesmo tempo" não é possível, quando se tem somente um processador.
  A solução então é dividir a execução de cada programa em "fatias", e alternar a execução de cada um no processador. Como os dois (ou mais) caminham sempre, dão a impressão de estar rodando "ao mesmo tempo".
  Para atingir tal fim, é necessário dispor de um terceiro programa, responsável por gerenciar e dividir o processador para cada um dos programas que se deseje rodar em paralelo.

  O esquema a seguir apresenta como dois programas P1 e P2 rodam sequencialmente e em paralelo.
 Sequencial     Paralelo

  +------+      +------+   
  |      |      |  P1  |   ↓ Tempo
  |  P1  |      +------+
  |      |      |  P2  |
  |      |      +------+
  +------+      |  P1  |
  |      |      +------+
  |  P2  |      |  P2  |
  |      |      +------+
  +------+      |  P1  |
                +------+

  O MSX ativa uma interrupção a cada 1/60 segundos, conforme visto no capítulo do temporizador. Essa interrupção será utilizada de tempo em tempo para chamar o gerenciador e trocar a sub-rotina em execução para a outra sub-rotina, e assim, ficar alternando entre elas.

  O capítulo do temporizador possui um programa que desenha um círculo na tela, ponto a ponto. Deste modo, vamos aproveitar esse programa para testar o paralelismo. A idéia aqui é criar uma nova sub-rotina de desenho de círculo, que desenha outro círculo em posição diferente do primeiro.


  Código Sequencial

  O código sequencial irá desenhar os dois círculos, sendo que um de cada vez.
10 SCREEN 2
100 ' Desenho 1
110 P1=90 : P2=60
120 FOR AA=0 TO 6.4 STEP 0.2
130 P3=60+COS(AA)*30 : P4=60-SIN(AA)*30
140 LINE(P1,P2)-(P3,P4),15
150 P1=P3 : P2=P4
160 NEXT AA
200 ' Desenho 2
210 Q1=150 : Q2=120
220 FOR AB=0 TO 6.4 STEP 0.2
230 Q3=120+COS(AB)*30 : Q4=120-SIN(AB)*30
240 LINE(Q1,Q2)-(Q3,Q4),15
250 Q1=Q3 : Q2=Q4
260 NEXT AB
270 GOTO 270

  É importante ter o nome das variáveis diferentes nas duas sub-rotinas, para que não haja confusão quando houver o paralelismo.


  Código em Paralelo

  O objetivo agora é modificar o programa anterior, de forma que as sub-rotinas "Desenho 1" e "Desenho 2" sejam alternadas durante uma determinada fração de tempo.
  A instrução INTERVAL-GOSUB será utilizada para chamar a sub-rotina que faz o gerenciamento de troca de sub-rotinas, a cada 2 segundos.
  Foi visto no capítulo extra de pilhas que o GOSUB-RETURN e o FOR-NEXT escrevem dados na pilha, e que estes servem para o interpretador Basic se orientar. Então, não basta somente trocar a sub-rotina em execução. Há a necessidade de modificar a pilha, de forma que a informação de cada sub-rotina seja a correta.
  Desse modo, temos que salvar o contexto da pilha tanto para o GOSUB, como para o FOR, e modificá-los na pilha, quando houver a troca de sub-rotina.

  O programa que desenha os círculos "ao mesmo tempo" é apresentado a seguir. Rode-o em um MSX 1, 2 ou 2+.
10 SCREEN 2
20 R=0
30 DEFINT C
40 DIM CG(2,4)
50 DIM CF(2,25)
60 GOTO 200
70 ON INTERVAL=120 GOSUB 310
80 INTERVAL ON
100 ' Desenho 1 (R=0)
110 P1=90 : P2=60
120 FOR AA=0 TO 6.4 STEP 0.2
125 CF(0,0)=&H82
130 P3=60+COS(AA)*30 : P4=60-SIN(AA)*30
140 LINE(P1,P2)-(P3,P4),15
150 P1=P3 : P2=P4
160 NEXT AA
165 CF(0,0)=0
170 GOTO 170
200 ' Desenho 2 (R=1)
205 GOSUB 500
210 Q1=150 : Q2=120
220 FOR AB=0 TO 6.4 STEP 0.2
225 CF(1,0)=&H82
230 Q3=120+COS(AB)*30 : Q4=120-SIN(AB)*30
240 LINE(Q1,Q2)-(Q3,Q4),15
250 Q1=Q3 : Q2=Q4
260 NEXT AB
265 CF(1,0)=0
270 GOTO 270
300 ' Tratamento de interrupção
310 INTERVAL OFF
320 T=PEEK(&HF6B1)+PEEK(&HF6B2)*256
330 NR = (R + 1) MOD 2
340 FOR I=3 TO 6
350 CG(R,I-3)=PEEK(T+I)
360 POKE T+I, CG(NR,I-3)
370 NEXT I
380 FOR I=7 TO 31
390 IF CF(R,0)<>0 THEN CF(R,I-7) = PEEK(T+I)
400 IF CF(NR,0)<>0 THEN POKE T+I,CF(NR,I-7)
410 NEXT I
420 R=NR
430 INTERVAL ON
440 RETURN
500 ' Pega contexto de Desenho 2
510 T=PEEK(&HF6B1)+PEEK(&HF6B2)*256
520 FOR I=3 TO 6
530 CG(1,I-3) = PEEK(T+I)
540 NEXT I
550 RETURN 70

  Os dois cículos não desenham exatamente ao mesmo tempo, mas uma parte de cada um vai sendo desenhada na tela alternadamente.
  Ao executar o programa, observa-se que o tempo de desenho para os dois círculos aumentou em relação ao desenho seqüencial. Este tempo extra é conseqüẽncia do tratamento da interrupção e da troca de contexto, necessária ao funcionamento do programa.

  Os principais passos do programa são:
  Dicas:

  Considerações Finais

  O paralelismo demonstrado nesse capítulo tem somente objetivo de apresentar o conceito, visto que ele é muito pesado para rodar uma linguagem interpretada como o Basic do MSX.
  Entretanto, ele foi brilhantemente implementado em linguagem de máquina Z-80 no sistema operacional SymbOS, por Jörn Mika. Como prova disso, podemos observar várias aplicações rodando ao mesmo tempo em diferentes janelas.

  Obviamente, para desenhar dois círculos ao mesmo tempo na tela como efeito de animação, basta colocar o comando de desenho de cada círculo no mesmo laço FOR.



MARMSX/CURSOS/Basic