Parallel programming has been around since the 1960s with the four-processor Illiac IV (and maybe longer), but cheap silicon and networking now give millions of people access to parallel computers containing anywhere from a handful to thousands of processors.
I see three main areas of parallel programming that are entering the mainstream, differentiated by their distance from the CPU chip and the amount of parallelism they offer:
- "Cloud computing," where thousands of computers cooperate through the internet to compute a result. Google's proprietary MapReduce framework is the standard bearer for this, but there are open source alternatives like Hadoop and QtConcurrent.
- Graphic processing units (GPUs), which use hundreds of processing engines to offload general computational work from the CPU. Nvidia's CUDA Toolkit and AMD/ATI's CTM are competing frameworks that support each company's particular chipset.
- Multicore CPUs that divide their workload between two to eight identical computing cores. Intel and AMD provide the multicore CPUs that most people are using today.
In this article, I'll concentrate on programming multicore CPUs. There are a growing number of libraries/frameworks for programming multicore architectures (Data Distribution Service, Message Passing Interface, and Concurrency and Coordination Runtime), but I chose Threading Building Blocks (TBB) for the following reasons:
- It's open source, so I can see how it works.
- It's free, so there is no economic barrier to its expansion.
- There's a commercial version, so there may be consulting work to be had.
- It's backed by Intel, so there's some technical and marketing muscle behind it.
- It's on version 2.0, so it has survived the infant mortality phase.
Of course, other frameworks can make many of these same claims. But I had to make a choice and get started, and not sit around waiting for a clear winner. Even if I make the wrong choice, hopefully most of the techniques I learn will be transferable to other frameworks.
In the sections that follow, I'll describe how I set up the tools to use TBB on Windows and used them to create a simple parallel program.
Setting Up TBB
The first thing I did was to download the TBB documentation and the Commercial Aligned Release. I unpacked the source archive (tbb20_014oss_src.tar.gz) into the directory C:\llpanorama\TBB (it isn't particular about the directory where it is installed). Then I unpacked the Windows binaries (tbb20_014oss_win.tar.gz) and copied the ia32 subdirectory into the top level of the source directory. (There is also a directory for 64-bit Windows, em64t, if you are using that.)
To build TBB and create applications, I downloaded and installed the free Visual C++ 2005 Express Edition (including the Graphical IDE). Since building TBB requires it, I also downloaded and installed the Microsoft Assembler.
By default, the Express Edition only supports .NET applications. Since I wanted to build Win32 applications (rebuilding TBB also requires this), I installed the Microsoft Platform SDK for Windows Server 2003 R2. [Note: to be able to follow the instructions in this article exactly, make sure you download the "Windows Server 2003 R2" version of the Platform SDK. I used this version because it's the version that was specifically designed for use with Visual Studio 2005. If you install the newer "Windows SDK for Windows Server 2008 and .NET Framework 3.5," then you'll have to modify the SDK-related instructions below accordingly.]
So that the Express Edition can find the SDK, I modified the VCProjectEngine.Dll.Express.Config file located in the \vc\vcpackages subdirectory of the Express Edition to include the executable, include, and library directories for my SDK installation. Here's my edited VCProjectEngine.Dll.Express.Config file (long lines have been broken into multiple lines to fit on this page):
<?xml version="1.0" encoding="utf-8"?> <VCPlatformConfigurationFile Version="8.00" > <Platform Name="VCProjectEngine.dll" Identifier="Win32" > <Directories Include="$(VCInstallDir)include;$(VCInstallDir)PlatformSDK\include; $(FrameworkSDKDir)include; C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include" Library="$(VCInstallDir)lib;$(VCInstallDir)PlatformSDK\lib; $(FrameworkSDKDir)lib;$(VSInstallDir);$(VSInstallDir)lib; C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib" Path="$(VCInstallDir)bin;$(VCInstallDir)PlatformSDK\bin; $(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools; $(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop; $(FrameworkSDKDir)bin;$(FrameworkDir)$(FrameworkVersion);$(VSInstallDir); C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin;$(PATH)" Reference="$(FrameworkDir)$(FrameworkVersion)" Source="$(VCInstallDir)crt\src" /> </Platform> </VCPlatformConfigurationFile>
As the Using Visual C++ 2005 Express with the Microsoft Platform SDK page states, as an alternative to editing the VCProjectEngine.Dll.Express.Config file you can specify these paths by launching Visual C++ Express Edition, selecting Options, and editing the "Project and Solutions VC++ Directories" settings.
Then I changed the corewin_express.vsprops file in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults so that the line
AdditionalDependencies="kernel32.lib"
becomes
AdditionalDependencies="kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib"
To enable the Win32 Windows Application type in the Win32 Application Wizard of the Express Edition, I commented out lines 441-444 in the the AppSettings.htm file located in %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\:
// WIN_APP.disabled = true; // WIN_APP_LABEL.disabled = true; // DLL_APP.disabled = true; // DLL_APP_LABEL.disabled = true;
Finally, before starting the Express Edition, I deleted the vccomponents.dat file located in the %USERPROFILE%\Local Settings\Application Data\Microsoft\VCExpress\8.0 directory.
In addition to using the Express Edition GUI, I wanted to use the compiler from the command line. I modified the PATH, INCLUDE, and LIB variables in the C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\vsvars32.bat file to include the required Platform SDK paths, as shown below:
@set PATH=C:\Program Files\Microsoft Visual Studio 8\Common7\IDE; C:\Program Files\Microsoft Visual Studio 8\VC\BIN; C:\Program Files\Microsoft Visual Studio 8\Common7\Tools; C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin; C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727; C:\Program Files\Microsoft Visual Studio 8\VC\VCPackages; C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin; %PATH% @set INCLUDE=C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE; C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include; %INCLUDE% @set LIB=C:\Program Files\Microsoft Visual Studio 8\VC\LIB; C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\lib; C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib; %LIB%
I also installed MinGW make (version 3.80) on my system so I could run the TBB makefile. I renamed the executable to make.exe and added the mingw32\bin path to my system PATH environment variable, so I could just enter "make" at a command prompt to launch my builds.
After all that was installed and patched together, I opened a Visual Studio 2005 command prompt window, went to the C:\llpanorama\TBB\tbb20_014oss_src directory, and issued the commands:
C:> vsvars32.bat C:> make
The first command initialized all the environment variables for the command-line version of the compiler. The second started the build process for the TBB libraries, which compiled and ran a suite of test programs. This completed without any errors, so I figured I'd set up everything correctly.
Next, I read the Getting Started Guide for TBB. First I created a new system environment variable, TBB20_INSTALL_DIR, and set it to the location where I installed TBB (C:\llpanorama\TBB\tbb20_014oss_src in my case). I also added my ia32\vc8\bin directory to my system PATH so that all the TBB DLLs would be found as needed.
The Getting Started Guide describes how to build the sub_string_finder example application. Rather than type all that in, I just jumped to the directory for this example at ...\tbb20_014oss_src\examples\GettingStarted\sub_string_finder\vc8. Double-clicking the sub_string_finder.sln file brought up the Express Edition window. I built the sub_string_finder project and ran it successfully.