Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Computacin Paralela
Contenido
RESUMEN................................................................................................................. 3
PALABRAS CLAVE.................................................................................................... 3
ABSTRACT................................................................................................................ 4
KEYWORDS.............................................................................................................. 4
1.
INTRODUCCIN................................................................................................5
2.
3.
OBJETIVOS........................................................................................................ 9
4.
DESARROLLO................................................................................................. 10
5.
CONCLUSIONES............................................................................................. 39
6.
REFERENCIAS................................................................................................. 40
7.
ANEXO............................................................................................................. 42
Resumen
Actualmente nos encontramos ante la disyuntiva de cmo seguir
incrementando la performance de los sistemas de computacin.
Estamos viendo grandes avances en la computacin paralela, la cual
se perfila como el nuevo paradigma a seguir, aportando una
performance superior a la de los sistemas tradicionales.
Pero la adopcin de este nuevo paradigma no es tan sencilla. Nos
enfrentamos ahora a la nueva complejidad propia de los algoritmos
paralelos.
Si bien el aumento de performance no es lineal a la cantidad de
procesadores, este nuevo enfoque de la computacin aporta mucha
mas capacidad a los sistemas actuales, imponindose como la nueva
solucin al problema de la escalabilidad.
Palabras Clave
Computacin, Arquitecturas, Programacin, Paralelo, Concurrente,
Algoritmos
Abstract
We are now faced with the dilemma of how to further enhance the
performance of computer systems.
We are seeing great advances in parallel computing, which is
emerging as the new paradigm to follow, providing superior
performance
to
that
of
traditional
systems.
But adoption of this new paradigm is not so simple. We are now facing
the new inherent complexity of parallel algorithms.
As will be seen, the performance increase is not linear to the number
of processors, but also see that this new approach provides much
more computing capability to the existing systems, emerging as the
new solution scalability.
Keywords
Computing,
Algorithms.
Architectures,
Programming,
Parallel,
Concurrent,
1.
Introduccin
2.
2.1
Resea histrica
Para encarar este cambio, hay que hacerlo desde varios frentes
simultneamente.
1
http://software.intel.com/en-us/intel-tbb/
http://research.microsoft.com/en-us/projects/tpl/
3
http://openmp.org/wp/
4
http://www.erlang.org/
5
http://clojure.org/
6
http://msdn.microsoft.com/en-us/devlabs/dd795202.aspx
7
http://en.wikipedia.org/wiki/Actor_model
2
3.
Objetivos
10
4.
Desarrollo
4.1
Arquitecturas Paralelas
Los sistemas SMP son aptos para gran cantidad de aplicaciones, entre
las cuales podemos mencionar a las que usan memoria compartida,
como los sistemas de soporte a la decisin, y los sistemas de
procesamiento de transacciones On-Line.
Dentro de esta categora podemos encontrar a las siguientes
maquinas comerciales:
HP 9000 Clase K, T y V
Sun UE6000 y E10000
DEC 8400
IMB RS/6000 J50 y R50 .
PRAM Model
Para el diseo de algoritmos paralelos se usa una variacin llamada
PRAM (Parallel Random Access Machine). Simplificando, son muchas
CPU conectados a memoria ilimitada, que es compartida por todos los
CPU.
Cuando se especifica un algoritmo PRAM se deben definir primero el
tipo de acceso a memoria.
Los 4 tipos disponibles son:
Parmetros de Acceso a memoria
Concurrent Read,
Concurrent Write (CRCW)
Concurrent Read, Exclusive
Write (CREW)
Exclusive Read, Concurrent
Write (ERCW)
Exclusive Read, Exclusive
Write (EREW)
Descripcin
Muchos threads pueden leer de la misma ubicacin
de memorial mismo tiempo y mltiples threads
pueden escribir en la misma posicin de memoria
al mismo tiempo.
Mltiples threads pueden leer de la misma posicin
de memoria al mismo tiempo y un solo thread
puede escribir en una determinada posicin de
memoria en un momento dado.
Un thread puede leer una posicin de memoria en
un tiempo determinado y muchos threads pueden
escribir en la misma posicin de memoria al mismo
tiempo.
Un thread puede leer una posicin de memoria en
un momento dado y un thread puede escribir una
posicin de memoria en un momento dado.
Arquitecturas NUMA
MPP (Massively
paralelo)
Parallel
Processing,
13
procesamiento
masivamente
Como
se
menciono
con
anterioridad,
el
procesamiento
simtricamente paralelo tiene las limitaciones propias de la memoria
compartida.
Para tratar de evitar estos problemas, se disearon las mquinas
masivamente paralelas.
Estas
maquinas
son
bsicamente
unidades
de
computo
independientes llamadas nodos, y poseen su propio procesador, su
propia memoria, sus canales I/O y una copia del sistema operativo.
Para comunicarse unas con otras utilizan un bus comn dedicado a
este propsito, y lo hacen mediante el pase de mensajes.
Bajo esta tcnica de pase de mensajes, los nodos son programados
para ejecutarse aisladamente, y se comunican con otros nodos
solamente cuando el programador lo explicita mediante alguna
sentencia concreta.
Estos mensajes contendrn la informacin que se desee compartir
entre los procesos, y sern enviados a travs de primitivas, pero la
responsabilidad del contenido del mensaje es exclusiva del
programador. De esta manera se libera el bus de comunicacin entre
nodos, ya que es utilizado nicamente cuando el programador as lo
requiere.
Ventajas y Desventajas
Este tipo de arquitectura es muy escalable y puede crecer hasta
cientos o miles de procesadores, de echo las supercomputadoras mas
poderosas del mundo son maquinas masivamente paralelas. Al no
tener la limitacin de un bus compartido de acceso a memoria, para
agrandar el sistema se pueden agregar tantos procesadores como se
necesite.
Pero esta fuerza de procesamiento no es sencilla de lograr. Programar
un sistema de estas caractersticas es una tarea extremadamente
14
SETI@HOME en http://setiathome.ssl.berkeley.edu/
FOLDING@HOME en http://folding.stanford.edu/
10
ORACLE SMP en http://www.oracle.com/global/es/products/middleware/application-grid.html
11
INFORMIX en http://www-01.ibm.com/software/data/informix/
9
15
16
Trabajo redundante
No importa como un algoritmo concurrente sea, siempre hay partes
que son seriales. Cuando el resultado de la computacin serial debe
ser compartido, se ejecuta en un procesador y se transmite el
resultado a los otros procesadores que requieren la informacin.
Transmitir esa informacin agrega overhead al tiempo de ejecucin.
En otro caso si los datos usados estn disponibles en los otros
procesadores, se pueden generar los resultados en cada procesador
sin necesidad de transmitir los resultados.
En el paralelismo de memoria compartida, los datos estn disponibles
por default.
4.2
4.3
requerimientos
del
multiprocesamiento.
software
incluyen
multithreading
Que es concurrencia?
Dos sucesos se dice que son concurrentes si se producen dentro del
mismo intervalo de tiempo.
Por ejemplo, dos tareas pueden ejecutarse concurrentemente en el
mismo segundo, pero con la ejecucin de cada tarea dentro de las
diferentes fracciones de segundo.
La primera tarea puede llevarse a cabo en la primera dcima de
segundo. La segunda tarea puede llevarse a cabo durante la prxima
dcima parte de segundo. Luego La primera tarea de ejecucin puede
comenzar de nuevo en la tercera dcima de segundo, etc.
Cada tarea puede alternar de ejecucin. Sin embargo, la duracin de
un segundo es tan corta que parece que ambas tareas se ejecutan de
forma simultnea.
Vamos a tratar con los desafos de la concurrencia en trminos de tres
categoras:
Software development
Software deployment
Software maintenance
Diez desafos de la concurrencia
1. Descomposicin del software en instrucciones o set de tareas
que se necesitan ejecutar simultneamente
2. Comunicacin entre 2 o ms tareas que se ejecutan en paralelo
3. Acceso o actualizacin concurrente de datos por 2 o ms tareas
4. Identificacin de las relaciones entre partes de las tareas en
ejecucin.
5. Controlar el uso de recursos para muchas tareas
6. Determinar el numero ptimos de tareas a ejecutar en paralelo
7. Crear un entorno de pruebas para simular los requerimientos y
condiciones del procesamiento paralelo
8. Recrear las excepciones del software para remover defectos
9. Documentar
y
comunicar
multiprocesamiento
diseos
que
contengan
10.
Implementar interfaces para que los compiladores y/o
Sistemas operativos soportes programacin paralela
24
Mecanismos de IPC
La especificacin
comunicacin
POSIX
soporta
25
mecanismos
bsicos
de
Archivos
Pipes
Memoria Compartida
Colas de mensajes
Sockets
Semforos
Deadlock
Es el bloqueo permanente de procesos del sistema, esperando por el
mismo recurso. Para tratar los deadlock existen 3 tecnicas principales
que son la deteccin, la prevencin y la prediccin.
Identificar las relaciones entre tareas que ejecutan concurrentemente
Synchronization Relationship
Start-to-start (SS)
Finish-to-start (FS)
Start-to-finish (SF)
Finish-to-finish (FF)
Descripcin
Una tarea no
arranque.
Una tarea no
inicie.
Una tarea no
termine.
Una tarea no
termine.
Que es un proceso
Un proceso es una unidad de trabajo creada por el sistema operativo.
Es necesario notar que proceso y programa no necesariamente son
26
Exclusin Mutua
Mantener y esperar
Sin expropiacin
29
Espera Circular
Algoritmos de Dekker
Para resolver el problema de la seccin critica
Solo est definido para 2 threads.
Hay mejores algoritmos como el de Lamport.
Mecanismos de sincronizacin
Hay recursos que solo permiten un nico acceso concurrente, o un
nmero limitado de accesos concurrentes, en estos casos es
necesario proteger el acceso a estos recursos, los mecanismos ms
conocidos son:
o Semaforos
o Readwrite locks
o Monitores
Estrategias para el uso de Thread
La estrategia determina la forma en que se va a emplear threading en
una aplicacin.
Modelo de Delegacin
En este modo un thread llamada jefe, crea a otros threads, llamados
trabajadores y le asigna una tarea a cada uno. El jefe debe esperar
hasta q todos los trabajadores completen su tarea para poder
continuar.
El propsito de un jefe es:
1. Crear todos los threads
2. Poner trabajo en la cola
3. Despertar a los trabajadores cuando exista trabajo para procesar
Los trabajadores:
1. Controlar los pedidos en la cola
2. Ejecutar la tarea asignada
3. Suspenderse si no hay mas tareas disponibles
Modelo Peer - to Peer
En este modelo todos los thread tienen las mismas responsabilidades,
un thread inicia al resto pero luego este se transforma en un
trabajador mas.
30
4.4
Modelos Tericos
Amdahls Law
Antes de hacer un algoritmo paralelo generalmente se estima cual va
a ser la mejora en eficiencia.
33
Gustafson-Barsiss Law
Una de las crticas al Amdahls Law es que a medida que el numero
de cores aumenta, tambin aumente la cantidad de datos manejados,
Amdahls Law asume una cantidad fija de datos que todos los cores
son usados.
Gustafson-Barsis Law tiene en cuenta un incremento en el tamao de
los datos en proporcin al incremento en el numero de cores.
Mientras que Amdahls Law es una herramienta para predecir la
cantidad de incremento de velocidad que se puede lograr
paralelizando un cdigo serial, Gustafson-Barsis Law es usada para
calcular el incremento de velocidad de un cdigo paralelo existente.
La formula es Speedup p + (1 p) s
Reglas para Generar algoritmos paralelos
34
Los patrones estn por todas partes, dando las mejores prcticas de
desarrollo de software y ayudando a sembrar nuevas generaciones de
desarrolladores con el conocimiento inmediato de direcciones
establecidas en una amplia gama de problemticas. Los patrones
representan repetidas soluciones comunes y exitosas (o en el caso
de anti-patrones, sin xito) que los desarrolladores han aplicado
varias veces en dominios particulares de arquitectura y
programacin. Con el tiempo, stas probadas prcticas los han
ayudado con nombres, altura y variaciones a proliferar en sus
aplicaciones e impulsar proyectos de muchos.
Los patrones no slo se manifiestan a nivel macro. Considerando que
los patrones de diseo cubren comnmente la estructura
arquitectnica o metodologas, la codificacin de patrones y la
construccin de mdulos tambin se manifiestan, en representacin
de formas tpicas de implementacin de un mecanismo
especfico. Estos patrones se han arraigado de forma tal que su uso a
diario en la codificacin se realiza con naturalidad sin siquiera pensar
en ello. Estos patrones representan soluciones a tareas comunes que
se encuentran en varias ocasiones.
Por supuesto, la bsqueda de buenos patrones bien puede ocurrir slo
despus de muchos intentos exitosos y fallidos de soluciones.
As, para nuevos espacios de problemas, puede tomar algn tiempo
para que stos ganen cierta reputacin. Ese es el lugar en donde hoy
se encuentra esta industria en lo que respecta a los patrones para la
programacin paralela. Si bien los desarrolladores en informtica de
35
por lo tanto precarga ese recurso de manera que est disponible para
el momento en que sea necesario. Si el sistema adivina
correctamente, el resultado final es la mejora percibida en la
perfomance.
Task<TResult> en el. NET Framework 4 hace que sea muy sencillo de
implementar este tipo de lgica. Cuando el sistema anticipa que el
resultado de un clculo particular puede ser necesario, pone en
marcha un Task<TResult> para calcular el resultado.
4.7
14
http://es.wikipedia.org/wiki/Distancia_de_Levenshtein
38
Figura 9. Calculo de PI
00:00:02.7953053: 3,14159265359043 - SerialPi - 0x
00:00:02.1307372: 3,14159265358999 - ParallelPi - 1,3118958546366x
00:00:01.1064297: 3,14159265358982 - ParallelPartitionerPi 1,92577729972361x
39
40
5.
Conclusiones
41
6.
Referencias
42
Programming
Wrox
ISBN:978-
43
Anexo
Codigo Fuente de los Ejemplos
Calculo de PI
using
using
using
using
using
System;
System.Collections.Concurrent;
System.Diagnostics;
System.Linq;
System.Threading.Tasks;
class Program
{
const int num_steps = 100000000;
static TimeSpan oldElapsed = TimeSpan.MaxValue;
/// <summary>Main method to time various implementations of computing
PI.</summary>
static void Main(string[] args)
{
while (true)
{
Time(() => SerialPi(), "SerialPi");
Time(() => ParallelPi(), "ParallelPi");
Time(() => ParallelPartitionerPi(), "ParallelPartitionerPi");
Console.WriteLine("----");
Console.ReadLine();
}
/// <summary>Times the execution of a function and outputs both the elapsed time
and the function's result.</summary>
static void Time<T>(Func<T> work, string name)
{
var sw = Stopwatch.StartNew();
var result = work();
TimeSpan elapsed =sw.Elapsed;
string speed = oldElapsed == TimeSpan.MaxValue ? "0x" :
oldElapsed.TotalSeconds / elapsed.TotalSeconds+ "x";
Console.WriteLine(elapsed + ": " + result + " - " + name + " - " + speed);
oldElapsed = elapsed;
}
/// <summary>Estimates the value of PI using a for loop.</summary>
static double SerialPi()
{
double sum = 0.0;
double step = 1.0 / (double)num_steps;
for (int i = 0; i < num_steps; i++)
{
double x = (i + 0.5) * step;
sum = sum + 4.0 / (1.0 + x * x);
}
return step * sum;
}
/// <summary>Estimates the value of PI using a Parallel.For.</summary>
static double ParallelPi()
44
Corrector Ortogrfico
using
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
System.IO;
System.Threading;
System.Diagnostics;
System.Threading.Tasks;
namespace SpellChecker
{
class Program
{
const int NUM_SUGGESTIONS = 10;
static List<string> _words = new List<string>(200000);
static int _maxWordLength;
static void Main(string[] args)
{
using (StreamReader reader = new StreamReader("english-words.95"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string word = line.Trim().ToLower();
if (!String.IsNullOrEmpty(word))
{
45
}
}
_words.Add(word);
if (word.Length > _maxWordLength) _maxWordLength = word.Length;
MakeSuggestions("helo", true);
MakeSuggestions("helo", false);
Console.ReadLine();
}
private static void MakeSuggestions(string text, bool sequential)
{
if (String.IsNullOrEmpty(text))
{
return;
}
// Time the operation and kick it of
Stopwatch sw = Stopwatch.StartNew();
Task.Factory.StartNew(() =>
{
List<string> results = null;
if (sequential)
{
var distanceMatrix = new int[_maxWordLength + 1, _maxWordLength + 1];
results = _words
.Select(word => new { Word = word, Distance =
LevenshteinDistance(word, text, distanceMatrix) })
.OrderBy(p => p.Distance)
.Take(NUM_SUGGESTIONS)
.Select(p => p.Word)
.ToList();
}
else
{
using (var distanceMatrix = new ThreadLocal<int[,]>(() => new
int[_maxWordLength + 1, _maxWordLength + 1]))
{
results = _words
.AsParallel()
.Select(word => new { Word = word, Distance =
LevenshteinDistance(word, text, distanceMatrix.Value) })
.TakeTop(p => p.Distance, NUM_SUGGESTIONS) // Or .OrderBy(p =>
p.Distance).Take(NUM_SUGGESTIONS)
.Select(p => p.Word)
.ToList();
}
}
sw.Stop();
return new { Results = results, Time = sw.Elapsed }; // Return both the
spelling suggestions and the elapsed time
}).ContinueWith(t =>
{
// Display the results
DisplayResult(sequential,t.Result.Results.Select((str, i) =>
string.Format("{0,2}. {1}", i + 1, str)),"Sec: " + t.Result.Time);
},TaskContinuationOptions.OnlyOnRanToCompletion);
}
46
+ cost;
substitution);
// Check for Transposition
if (i > 1 && j > 1 && (str1[str1Index] == str2[str2Index - 1]) &&
(str1[str1Index - 1] == str2[str2Index]))
{
scratchDistanceMatrix[i, j] = Math.Min(scratchDistanceMatrix[i, j],
scratchDistanceMatrix[i - 2, j - 2] + cost);
}
}
}
// Levenshtein distance is the bottom right element
return scratchDistanceMatrix[str1.Length, str2.Length];
}
Blend de Imgenes
partial class MainForm
{
47
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed;
otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.btnSequential = new System.Windows.Forms.Button();
this.btnParallel = new System.Windows.Forms.Button();
this.lblTime = new System.Windows.Forms.Label();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.pbInput1 = new System.Windows.Forms.PictureBox();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.pbInput2 = new System.Windows.Forms.PictureBox();
this.pbOutput = new System.Windows.Forms.PictureBox();
this.lblSpeedup = new System.Windows.Forms.Label();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbInput1)).BeginInit();
this.splitContainer2.Panel1.SuspendLayout();
this.splitContainer2.Panel2.SuspendLayout();
this.splitContainer2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbInput2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pbOutput)).BeginInit();
this.SuspendLayout();
//
// btnSequential
//
this.btnSequential.Enabled = false;
this.btnSequential.Location = new System.Drawing.Point(12, 12);
this.btnSequential.Name = "btnSequential";
this.btnSequential.Size = new System.Drawing.Size(75, 23);
this.btnSequential.TabIndex = 0;
this.btnSequential.Text = "Sequential";
this.btnSequential.UseVisualStyleBackColor = true;
this.btnSequential.Click
+=
System.EventHandler(this.btnBlendImages_Click);
//
// btnParallel
//
48
new
this.btnParallel.Enabled = false;
this.btnParallel.Location = new System.Drawing.Point(93, 12);
this.btnParallel.Name = "btnParallel";
this.btnParallel.Size = new System.Drawing.Size(75, 23);
this.btnParallel.TabIndex = 1;
this.btnParallel.Text = "Parallel";
this.btnParallel.UseVisualStyleBackColor = true;
this.btnParallel.Click += new System.EventHandler(this.btnBlendImages_Click);
//
// lblTime
//
this.lblTime.AutoSize = true;
this.lblTime.Location = new System.Drawing.Point(174, 17);
this.lblTime.Name = "lblTime";
this.lblTime.Size = new System.Drawing.Size(0, 13);
this.lblTime.TabIndex = 2;
//
// splitContainer1
//
this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)
((((System.Windows.Forms.AnchorStyles.Top
|
System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.splitContainer1.Location = new System.Drawing.Point(12, 41);
this.splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.pbInput1);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.splitContainer2);
this.splitContainer1.Size = new System.Drawing.Size(860, 269);
this.splitContainer1.SplitterDistance = 286;
this.splitContainer1.TabIndex = 3;
//
// pbInput1
//
this.pbInput1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pbInput1.Cursor = System.Windows.Forms.Cursors.Hand;
this.pbInput1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pbInput1.Location = new System.Drawing.Point(0, 0);
this.pbInput1.Name = "pbInput1";
this.pbInput1.Size = new System.Drawing.Size(286, 269);
this.pbInput1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pbInput1.TabIndex = 0;
this.pbInput1.TabStop = false;
this.toolTip1.SetToolTip(this.pbInput1, "Double-click to load new image");
this.pbInput1.DoubleClick
+=
new
System.EventHandler(this.pbInput_DoubleClick);
//
// splitContainer2
//
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
this.splitContainer2.Name = "splitContainer2";
//
// splitContainer2.Panel1
//
this.splitContainer2.Panel1.Controls.Add(this.pbInput2);
//
49
// splitContainer2.Panel2
//
this.splitContainer2.Panel2.Controls.Add(this.pbOutput);
this.splitContainer2.Size = new System.Drawing.Size(570, 269);
this.splitContainer2.SplitterDistance = 285;
this.splitContainer2.TabIndex = 0;
//
// pbInput2
//
this.pbInput2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pbInput2.Cursor = System.Windows.Forms.Cursors.Hand;
this.pbInput2.Dock = System.Windows.Forms.DockStyle.Fill;
this.pbInput2.Location = new System.Drawing.Point(0, 0);
this.pbInput2.Name = "pbInput2";
this.pbInput2.Size = new System.Drawing.Size(285, 269);
this.pbInput2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pbInput2.TabIndex = 1;
this.pbInput2.TabStop = false;
this.toolTip1.SetToolTip(this.pbInput2, "Double-click to load new image");
this.pbInput2.DoubleClick
+=
new
System.EventHandler(this.pbInput_DoubleClick);
//
// pbOutput
//
this.pbOutput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pbOutput.Dock = System.Windows.Forms.DockStyle.Fill;
this.pbOutput.Location = new System.Drawing.Point(0, 0);
this.pbOutput.Name = "pbOutput";
this.pbOutput.Size = new System.Drawing.Size(281, 269);
this.pbOutput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pbOutput.TabIndex = 1;
this.pbOutput.TabStop = false;
this.pbOutput.DoubleClick
+=
new
System.EventHandler(this.pbOutput_DoubleClick);
//
// lblSpeedup
//
this.lblSpeedup.Anchor = ((System.Windows.Forms.AnchorStyles)
((System.Windows.Forms.AnchorStyles.Top
|
System.Windows.Forms.AnchorStyles.Right)));
this.lblSpeedup.AutoSize = true;
this.lblSpeedup.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F,
System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblSpeedup.ForeColor = System.Drawing.Color.Green;
this.lblSpeedup.Location = new System.Drawing.Point(869, 17);
this.lblSpeedup.Name = "lblSpeedup";
this.lblSpeedup.Size = new System.Drawing.Size(0, 13);
this.lblSpeedup.TabIndex = 4;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(884, 322);
this.Controls.Add(this.lblSpeedup);
this.Controls.Add(this.splitContainer1);
this.Controls.Add(this.lblTime);
this.Controls.Add(this.btnParallel);
this.Controls.Add(this.btnSequential);
this.Name = "MainForm";
this.Text = "Blend Images";
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
50
this.splitContainer1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pbInput1)).EndInit();
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel2.ResumeLayout(false);
this.splitContainer2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pbInput2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pbOutput)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private
private
private
private
private
private
private
private
private
private
using
using
using
using
using
using
using
using
System.Windows.Forms.Button btnSequential;
System.Windows.Forms.Button btnParallel;
System.Windows.Forms.Label lblTime;
System.Windows.Forms.SplitContainer splitContainer1;
System.Windows.Forms.PictureBox pbInput1;
System.Windows.Forms.SplitContainer splitContainer2;
System.Windows.Forms.PictureBox pbInput2;
System.Windows.Forms.PictureBox pbOutput;
System.Windows.Forms.Label lblSpeedup;
System.Windows.Forms.ToolTip toolTip1;
System;
System.Collections.Concurrent;
System.Diagnostics;
System.Drawing;
System.Drawing.Imaging;
System.Threading.Tasks;
System.Windows.Forms;
Microsoft.Drawing;
namespace Microsoft.ParallelComputingPlatform.ParallelExtensions.Samples
{
public partial class MainForm : Form
{
private TimeSpan? _lastSequentialTime, _lastParallelTime;
public MainForm() { InitializeComponent(); }
private void pbInput_DoubleClick(object sender, EventArgs e)
{
// Get the PictureBox that caused this event
PictureBox pb = sender as PictureBox;
if (pb == null) return;
// Open a dialog to let the user select an image
using (var ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == DialogResult.OK)
{
// Store the new image into the PictureBox
Image newImage = new Bitmap(ofd.FileName);
Image oldImage = pb.Image;
pb.Image = newImage;
if (oldImage != null) oldImage.Dispose();
}
}
// Make sure the btns are enabled if they should be
51
52
53
}
});
sw.Stop();
}
else
{
// Blend the images sequentially
sw.Restart();
for(int j=0; j<height; j++)
{
PixelData* outPixel = fastOut.GetInitialPixelForRow(j);
PixelData* startPixel = fastStart.GetInitialPixelForRow(j);
PixelData* endPixel = fastEnd.GetInitialPixelForRow(j);
for (int i = 0; i < width; i++)
{
// Blend the input pixels into the output pixel
outPixel->R = (byte)((startPixel->R * blend) + .5 + (endPixel->R * (1 blend))); // .5 for rounding
outPixel->G = (byte)((startPixel->G * blend) + .5 + (endPixel->G * (1 blend)));
outPixel->B = (byte)((startPixel->B * blend) + .5 + (endPixel->B * (1 blend)));
outPixel++;
startPixel++;
endPixel++;
}
}
sw.Stop();
54