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

É 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.

Теги:
Пожалуйста, обратитесь к странице Уведомление об оптимизации для более подробной информации относительно производительности и оптимизации в программных продуктах компании Intel.
Возможность комментирования русскоязычного контента была отключена. Узнать подробнее.