Tutorial Windows* 8: Escrevendo uma Aplicação Multithreaded para a Windows Store* usando a biblioteca Intel® Threading Building Blocks.

Publicado:03/06/2013   Última atualização:03/06/2013

É sabido que a API das aplicações Windows Store não disponibiliza algumas funções comuns para trabalhar com Threads, como a CreateThread e aquelas que trabalham com chaves TLS (Thread-local storage). Esta é mais uma grande oportunidade para migrar o seu desenvolvimento de aplicações de um paralelismo baseado em threads para um paralelismo baseado em tarefas. Este post demonstra as instruções passo-a-passo para escrever um exemplo que usa paralelismo e que pode passar pela validação do Windows App Certification Kit (WACK). Esse exemplo pode ser expandido para suportar clientes para jogos online e muito mais. Além disso como o Intel® Threading Building Blocks (Intel® TBB, threadingbuildingblocks.org) é usado para implementar paralelismo, a engine de cálculo paralelo pode ser facilmente portada para outras plataformas mobile ou desktop. 

Siga os passos abaixo para criar uma aplicação Windows Store simples usando a biblioteca TBB que consegue ser aprovada no WACK.

Requisitos para execução do tutorial:

- Visual Studio 2012

- GNU Make (http://gnuwin32.sourceforge.net/packages/make.htm)

1) Faça o download do código fonte da release desenvolvimento mais recente em http://threadingbuildingblocks.org/download#development-releases

2) Descompacte o código fonte em algum diretório de sua escolha. Para facilitar, iremos utilizar o diretório < C:\tbb_dev_src >.

3) Abra o arquivo <DIRETÓRIO_TBB>\include\tbb\machine\msvc_ia32_common.h e procure o seguinte trecho de código (linha 170):

extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); #define __TBB_Yield()  SwitchToThread()

Altere esse trecho de código para:

#if !__TBB_WIN8UI_SUPPORT extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); #define __TBB_Yield()  SwitchToThread() #else #include<thread> #define __TBB_Yield()  std::this_thread::yield() #endif

Essa alteração será incorporada em releases futuros da biblioteca TBB. 

4) Verifique se o GNU make (versão 3.81 ou maior) está na variável de ambiente %PATH% e caso não esteje disponível, adicione manualmente ou utilize o instalador disponível no seguinte link: http://gnuwin32.sourceforge.net/downlinks/make.php

5) Abra o "VS2012 x86 Native Tools Command Prompt" e navegue até o diretório aonde o código fonte foi descompactado usando o comando cd <DIRETÓRIO_TBB>. No caso do diretório utilizado no artigo, < cd C:\tbb_dev_src >

6) Execute o comando < make tbb tbbmalloc target_ui=win8ui target_ui_mode=production > para compilar a biblioteca TBB

7) Após compilar o projeto, os binários estarão disponíveis no diretório <DIRETÓRIO_TBB>\build\windows_ia32_cl_vc11_release

8) Abra o Visual Studio 2012 e crie um novo projeto "File -> New -> Project" e selecione o template "Visual C++ -> Windows Store -> Blank App" com o nome que desejar. O tutorial irá utilizar o nome TbbWindowsStore:

9) Abra as propriedades do projeto (através do menu "Project -> <Nome_Projeto> Properties..." ou clique com o botão direito no projeto e selecione "Properties")

10) Altere a opção "Configuration" para "All Configurations" para aplicarmos as configurações para os binários de release e debug.

11) Adicione o diretório <DIRETÓRIO_TBB>\include na propriedade "C\C++ -> Additional Include Directories" conforme a figura abaixo (atenção para os separadores ;):

12) Adicione o diretório com os binários do TBB (<DIRETÓRIO_TBB>\build\windows_ia32_cl_vc11_release) na propriedade "Linker -> Additional Library Directory" conforme a figura abaixo e clique em "Apply" e em "OK" em seguida

13) Adicione os arquivos tbb.dll e tbbmalloc.dll (disponíveis em <DIRETÓRIO_TBB>\build\windows_ia32_cl_vc11_release) ao projeto (através do menu "Project -> Add Existing Item" ou clicando com o botão direito no projeto e selecionando a opção "Add -> Existing Item")

14) Selecione as duas DLLs no "Solution Explorer" e altere a propriedade "Content" de ambos para o valor "True", permitindo que ambos sejam carregados quando a aplicação for iniciada ou sob demanda.

15) Abra o arquivo "MainPage.xaml.cpp" e adicione a seguinte linha de codigo logo após os includes:

#include "tbb/tbb.h"

16) Compile ("Build -> Build Solution") e execute o projeto em modo de release para verificar se tudo foi configurado corretamente. Caso o programa inicie normalmente, tudo está ok.

17) Abra o arquivo "MainPage.xaml" e adicione dois botões e altere as seguintes propriedades:

- "Name" para "btnSR" e "btnDR", respectivamente

- "Content" para "Simple Reduction" e "Deterministic Reduction", respectivamente

Após alterar as propriedades o arquivo "MainPage.xaml" ficará parecido com isso:

<Page     x:Class="TbbWindowsStore.MainPage"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:TbbWindowsStore"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d">     <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">         <Button x:Name="btnSR" Content="Simple Reduction" HorizontalAlignment="Left" Margin="34,40,0,0" VerticalAlignment="Top" Height="81" Width="686"/>         <Button x:Name="btnDR" Content="Deterministic Reduction" HorizontalAlignment="Left" Margin="34,160,0,0" VerticalAlignment="Top" Height="81" Width="686"/>     </Grid> </Page>

18) Selecione o botão "btnSR" e dentro de suas propriedades clique no botão em forma de raio para ver os eventos associados ao botão. Clique duas vezes sobre o campo "Click" para criar e associar um evento de clique para o botão.

19) Abra o arquivo MainPage.xaml.cpp e adicione o código abaixo ao evento criado no passo anterior:

void TbbWindowsStore::MainPage::btnSR_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) {     int N=1000000;     float fr = 1.0f/(float)N;     float sum = tbb::parallel_reduce(         tbb::blocked_range<int>(0,N), 0.0f,         [=](const tbb::blocked_range<int>& r, float sum)->float {             for( int i=r.begin(); i!=r.end(); ++i )                 sum += fr;             return sum;     },         []( float x, float y )->float {             return x+y;     }     );       btnSR->Content="Press to run Simple Reduction. The result is " + sum.ToString();  }

20) Repita os dois passos anteriores para o botão "btnDR", adicionando o seguinte código para o evento associado a ele:

void TbbWindowsStore::MainPage::btnDR_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) {     int N=1000000;     float fr = 1.0f/(float)N;     float sum = tbb::parallel_deterministic_reduce(         tbb::blocked_range<int>(0,N), 0.0f,         [=](const tbb::blocked_range<int>& r, float sum)->float {             for( int i=r.begin(); i!=r.end(); ++i )                 sum += fr;             return sum;     },         []( float x, float y )->float {             return x+y;     }     );       btnDR->Content="Press to run Deterministic Reduction. The result is " + sum.ToString(); }

21) Após criar os eventos para os botões, o arquivo "MainPage.xaml" ficará parecido com o seguinte código:

<Page     x:Class="TbbWindowsStore.MainPage"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:TbbWindowsStore"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d">     <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">         <Button x:Name="btnSR" Content="Simple Reduction" HorizontalAlignment="Left" Margin="34,40,0,0" VerticalAlignment="Top" Height="81" Width="686" Click="btnSR_Click"/>         <Button x:Name="btnDR" Content="Deterministic Reduction" HorizontalAlignment="Left" Margin="34,160,0,0" VerticalAlignment="Top" Height="81" Width="686" Click="btnDR_Click"/>     </Grid> </Page>

22) Compile e rode o programa novamente conforme passo 16. Caso tudo funcione corretamente, use o "Resource Monitor" do "Task Manager" ("Performance -> Open Resource Monitor") para observar as curvas de utilização do processador quando clicar nos botões. 

Sugestão: Para ver curvas maiores, você pode ajustar o valor da variável N, conforme no exemplo abaixo que alterei para observar as curvas em um Core i5:

void TbbWindowsStore::MainPage::btnDR_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) {     int N=10000000;     float fr = 1.0f/(float)N;     float sum = tbb::parallel_deterministic_reduce(         tbb::blocked_range<int>(0,N), 0.0f,         [=](const tbb::blocked_range<int>& r, float sum)->float {             for( int i=r.begin(); i!=r.end(); ++i )                 sum += fr;             return sum;     },         []( float x, float y )->float {             return x+y;     }     );       btnDR->Content="Press to run Deterministic Reduction. The result is " + sum.ToString(); }

24) Agora será possível validar sua aplicação utilizando o Windows App Certification Kit (WACK) e ter sua aplicação aprovada. Para obter mais informações de como utilizar o WACK, visite seguinte link: Testing your app with the Windows App Certification Kit

* Other names and brands may be claimed as the property of others.

Informações de produto e desempenho

1

Os compiladores da Intel podem ou não otimizar para o mesmo nível de microprocessadores não Intel no caso de otimizações que não são exclusivas para microprocessadores Intel. Essas otimizações incluem os conjuntos de instruções SSE2, SSE3 e SSSE3, e outras otimizações. A Intel não garante a disponibilidade, a funcionalidade ou eficácia de qualquer otimização sobre microprocessadores não fabricados pela Intel. As otimizações que dependem de microprocessadores neste produto são destinadas ao uso com microprocessadores Intel. Algumas otimizações não específicas da microarquitetura Intel são reservadas para os microprocessadores Intel. Consulte os Guias de Usuário e Referência do produto aplicáveis para obter mais informações sobre os conjuntos de instruções específicos cobertos por este aviso.

Revisão do aviso #20110804