分類彙整: Programming

Unity: Awake and Start

Adopt from

[1] http://unity3d.com/learn/tutorials/modules/beginner/scripting/awake-and-start

Both Awake() and Start() will be called once in the lifetime of a script on a GameObject even when you disable and re-enable the script.

The sequence of the function calls is difference. Awake() is invoked before Start().

Awake() is called when the script is loaded so it is a good place to set up the references between scripts and initialization. Start() will then be immediately called once the script component is enabled. Therefore, you can delay any part of initialization when it is really needed.

How to: Debug in Mixed Mode

Adopted from:

[1] http://msdn.microsoft.com/en-us/library/kbaht4dh.aspx

[2] http://msdn.microsoft.com/en-us/library/fz5w87ad.aspx

Introduction

A mixed-mode application is any application that combines native code (C++) with managed code (such as Visual Basic, Visual C#, or C++ that runs on the common language runtime) [2]. Debugging mixed-mode applications is largely transparent in Visual Studio; it is not too different from debugging a single-mode application [2].

Why do you debug in mixed mode?[1]

Debugging in both managed and native code is also known as mixed-mode debugging. There are two scenarios for doing so, depending on whether the DLL or the application is written in native code:

  1. The calling application that calls your DLL is written in native code. In this case your DLL is managed, and both managed and native debuggers must be enabled to debug both. You can check this in the <Project> Property Pages dialog box. How you do this depends on whether you start debugging from the DLL project or the calling application project.
  2. The calling application that calls your DLL is written in managed code and your DLL is written in native code.

How to enable mixed-mode debugging?[1]

  1. In Solution Explorer, select the project.
  2. On the View menu, click Property Pages.
  3. In the <Project> Property Pages dialog box, expand the Configuration Properties node, and then select Debugging.
  4. Set Debugger Type to Mixed.

Linking a C++ DLL of a Solution in Visual Studio 2012

References

[1] http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix

[2] http://stackoverflow.com/questions/17350521/error-lnk2019-unresolved-external-symbol-in-visual-studio

[3] http://stackoverflow.com/questions/8735918/c-lnk2019-unresolved-external-symbol

[4] http://stackoverflow.com/questions/4489441/why-when-is-declspec-dllimport-not-needed

[5] http://msdn.microsoft.com/en-us/library/a90k134d.aspx

Introduction

If you use Visual Studio to include your own dynamic library for the first time, most of you will encounter this lengthy error:

Error 12 error LNK2019: unresolved external symbol "public: ..."

When you search "visual studio c++ LNK2019: unresolved external symbol" in StackOverflow, the system returns nearly 1000 questions. As you can see, some of them are even marked as duplicated. In fact, existing answers in the previous posts do contain the procedure to solve this error if you are quite familar with C++ development. But it is too implicit for many newcomers to understand. This post will give you a step-by-step guide to solve this problem.

Problem Settings

ProjectDll (say in MySolution\ProjectDll) which implements the library functions

ProjectApp (say in MySolution\ProjectApp) which contains the functions that use the library

And compile with errors LNK2019.

Step 1: Verify the ProjectDll as a DLL project

In Solution Explorer,

1a. Right click ProjectDll –> Properties

1b. Configuration Properties –> General –> Configuration Type –> Dynamic Library (.dll)

 

Step 2: Mark and export the functions/classes/data to the library

2a. Create a header file, say CommonHeader.h in ProjectDll project

//CommonHeader.h

#ifdef _PROJDLL_EXPORTS
#define _PROJDLL_API __declspec(dllexport)
#else
#define _PROJDLL_API __declspec(dllimport)
#endif

The reason using __declspec(dllexport) and __declspec(dllimport) can be found in [4] and [5].

2b. Mark all the required functions/classes/data which have to be exposed

And don't forget to #include "CommonHeader.h" only in the corresponding header(*.h) files.

For example,

In MySystem.h in ProjectDll

class MySystem{..}  ------> class _PROJDLL_API MySystem{..}

extern double GlobalVarA; ------> extern _PROJDLL_API double GlobalVarA;

2c. We need to define the symbol _PROJDLL_EXPORTS to activate __declspec(dllexport) only for this project. However, as the CommonHeader.h will be shared with ProjectApp, we cannot add #define _PROJDLL_EXPORTS in the header files used by another project. One way is to do this in compilation option

Configuration Properties –> C/C++ –> Preprocessor –> Preprocessor Definitions –> Add _PROJDLL_EXPORTS

 

Step 3: Build the libary

3a. Right click ProjectDll –> Build

Notice a .dll file and a .lib file in In the same window, MySolution\Debug\ directory.

 

Step 4: Set the Dependencies

4a. In Solution Explorer, right click ProjectDll and open Project Dependencies with the following settings:

Projects: ProjectDll

Depends on: ProjectApp

After this, modifications on ProjectDll will lead to recompilation of ProjectApp.

 

Step 5: Include necessary files when compiling ProjectApp

5a. Right click ProjectApp –> Common Properties –> Add New Reference… –> Add the ProjectDll project

5b. In the same window, Configuration Properties –> C/C++ –> General –> Additional Include Directories –> [Directory of the header files of ProjectDll in MySolution\ProjectDll]

5c. In the same window, Configuration Properties –> Linker –> Input –> Additional Dependencies –>  [.lib file of ProjectDll in MySolution\Debug$$

 

Step 6: Compile ProjectApp

Right click ProjectApp –> Build

OR

Right click ProjectApp –> Set as StartUp Project

Press Build in the Toolbar

 

You need to repeat the above steps for Release mode, probably with a different directory of *.lib file. Of course you can use All Configurations next time when making these settings. Readers should also find the reasons behind these settings from online documents and forums.

Thread Divergence

Adopted from

[1] Programming Massively Parallel Processors: A Hands-on Approach by David B. Kirk and Wen-mei W. Hwu

Background

In Single Instruction Multiple Data (SIMD) architecture, all threads in the same wrap execute the same instruction. However, these threads may in different control flow when working their data. The SIMD hardware needs to execute the same instruction for multiple passes to cope with these divergent paths by keeping the threads independently executed. For example, an if-then-else construct can produce two different paths for the threads. Extra cost will also be incurred in other constructs, such as for-loop or decision conditions on threadIdx values.

An Example of a Thread Divergence Problem: Reduction Algorithm

A reduction algorithm computes a single value from an array of values. You will encounter this kind of algorithm when performing a summary, such as averaging and summing up the given values, or tournament selection. Although sequential algorithm works efficiently in linear time to the number of elements introduced, parallel execution is still favourable due to a large number of elements.

Consider the following kernel function (wasting at least half of the threads in a block) on sum reduction.

Algorithm 1

__shared__ float partialSum[]

unsigned int t = threadIdx.x;

for (unsigned int stride=1; stride<blockDim.x; stride *=2){

    __syncthreads();

    if (t % (2*stride) ==0)

        partialSum[t] += partialSum[t+stride]; //Absorb the neighbour of the right

}

 

    Threads
Iter stride 0 1 2 3 4 5 6 7 8 9 10 11
0   1 4 2 2 4 2 5 2 3 1 4 6
1 1 5   4   6   7   4   10  
2 2 9       13       14      
3 4 22               14      
4 8 36                      

Given N elements, time complexity is N/2+N/4+N/8+…+1=N-1=O(N)

There is an issue of thread divergence in the above algorithm. The first iteration of the loop, some threads will execute a different path due to the condition on threadIdx.x. In the worst case, two passes will be needed for each iteration for the threads in the same wrap.

Solution

Algorithm 2

__shared__ float partialSum[]

unsigned int t = threadIdx.x;

for (unsigned int stride=blockDim.x/2; stride>1; stride /=2){

    __syncthreads();

    if (t < stride)

        partialSum[t] += partialSum[t+stride]; //Absorb the neighbour of the right

}

    Threads
Iter stride 0 1 2 3 4 5 6 7 8 9 10 11
0   1 4 2 2 4 2 5 2 3 1 4 6
1 8 4 5 6 8 4 2 5 2    
2 4 8 7 11 10            
3 2 19 17                  
4 1 36                      

A if-then statement still remains in the loop but we claimed there is a performance difference between Algorithm 1 and Algorithm 2. The hint is the positions of threads between those executing in different control paths.

Suppose the size of a warp 4 (32 in reality), all the threads in warps 0-1 (corresponding to thread 0-7) executes the same control path, there is no thread divergence in iteration 1 in these wraps. Similarly, this happens in iteration 2. However, when the number of threads is less than the size of warp, thread divergence occurs again in iteration 3 and iteration 4. But when the problem is large, the number iterations with thread divergence accounts for a small constant number of iteration, i.e. log2(size of a warp) (at least after log2(blockDim.x)-log2(size of a warp) iterations for thread divergence to occur ideally).

Conclusion

In this article, we studied how the thread divergence affects the design of algorithm running on GPGPU. Design of algorithm needs to match with the underlying hardware architecture in order to fully utilize the computational resources.

Eclipse Launch Configuration

Sometimes, the application has to be invoked with some arguments for other execution options to suit different purposes. For example, Internet Explorer supported the following options

(adopt from http://msdn.microsoft.com/en-us/library/ee330728(v=VS.85).aspx)

iexplore.exe [ [ -embedding ] [ -extoff ] [ -framemerging ] [ -k ] [ -noframemerging ] [ -nohangrecovery ] [ -private ] ] [ URL ]

If you are going to develop your program in Eclipse and want to test your application with different options, you may follow the instructions below.

  1. Open your project in Eclipse.
  2. In Project Explorer, find your project.
  3. Right-click and select Properties and then Properties Windows appears.
  4. In the menu on the left, click Run/Debug Settings.
  5. On the right, select a Launch configuration (by default there is at least one)
  6. Press Edit to change the configuration

As you can see, there are a number of configurations but we only focus on the settings in the Arguments tab.

  1. In the Arguments tab, input your arguments for the program. Each line is for one argument.
  2. If you do not want to use the default Working directory, unchecked Use default. This is useful if you want to open a file that is in the same directory as the executable. Suppose the executable named MyApp1. To specify the directory,
    1. For C++ project, very often, we change it from ${workspace_loc:MyApp1} to ${workspace_loc:MyApp1/Debug}
    2. For Java project, very often,  we change it from ${workspace_loc:MyApp1} to ${workspace_loc:MyApp1/bin}

Python: Install pip on Windows

References

[1] http://www.pip-installer.org/en/latest/

[2] http://pypi.python.org/pypi/pip#downloads

[3] http://pypi.python.org/pypi/setuptools#downloads

[4] http://stackoverflow.com/questions/4750806/how-to-install-pip-on-windows


Python allows developers to install packages. pip is a tool for installing and managing Python packages. To install pip, you can follow the steps below:

Install setuptools

  1. Download setuptools [http://pypi.python.org/pypi/setuptools#downloads]
  2. Open the installer to install setuptools

Install pip

  1. Download pip-1.2.x.tar.gz (e.g. pip-1.2.1.tar.gz)[http://pypi.python.org/pypi/pip#downloads]
  2. Upzip the pip-1.2.x.tar.gz to a folder, e.g. C:\Downloads\pip-1.2.x
  3. Assume the folder is at C:\Downloads\pip-1.2.x
    cd "C:\Downloads\pip-1.2.x"
  4. Install pip
    C:\Python27\python.exe setup.py install

Update environment variable

Refer to http://www.helpwithwindows.com/WindowsXP/howto-04.html

  1. Add path C:\Python27
  2. Add path C:\Python27\Scripts
  3. Reopen the command prompt

Use pip

For example, we want to install the networkx package [http://networkx.lanl.gov/]

pip install networkx

Warning message of g++ in MinGW

References

[1] http://stackoverflow.com/questions/10191063/mingw-g-gives-warnings-in-wrong-language-german-instead-of-english

[2] localization - Non-localized version of MinGW- - Stack Overflow


Introduction

In MinGW, although localization on the g++ compiler makes the warning and error message "user-friendly", it can be troublesome. It was found that the Eclipse CDT message parser can only identify the English word "warning" as warning, while the "warning" in other languages (such as 警告) are regarded as error message. Therefore, every time you want to compile the code in Eclipse, you receive the error message dialog, which is annoying. To solve this problem, you may ask the Eclipse team to make the parser be able to recognize different languages. However, the faster way is to solve this problem is to add an environment variable in your Windows system.

Syndrome

C:\Users\_____\src>g++ -O0 -g3 -fsyntax-only -Wall -c
-fmessage-length=0 -o "src\\GrammarBook.o" "..\\src\\GrammarBook.cpp"
..\\src\\GrammarBook.cpp: In member function 「void GrammarBook::LoadContentToGrammar(Grammar&, char*)」:
..\\src\\GrammarBook.cpp:163:16: 警告:未使用的變數 「newG」

Solution[1]

Control Panel -> System -> Advanced System Settings -> Environment Variables... -> System variables -> New.. -> Variable: LC_ALL, Value: en_US.UTF-8

If you are successful, the message becomes

C:\Users\_____\src>g++ -O0 -g3 -fsyntax-only -Wall -c
-fmessage-length=0 -o "src\\GrammarBook.o" "..\\src\\GrammarBook.cpp"
..\\src\\GrammarBook.cpp: In member function 'void GrammarBook::LoadContentToGrammar(Grammar&, char*)':
..\\src\\GrammarBook.cpp:163:16: warning: unused variable 'newG'

F#: Introduction

Adapt from

[1] http://www.tryfsharp.org/Tutorials.aspx

[2] http://www.tryfsharp.org/Tutorials/QuickLanguageOverview/Section0.html

[3] http://www.tryfsharp.org/Tutorials/QuickLanguageOverview/Section1.html

[4] http://www.tryfsharp.org/Tutorials/QuickLanguageOverview/Section2.html

[5] http://www.tryfsharp.org/Tutorials/QuickLanguageOverview/Section3.html

[6] http://msdn.microsoft.com/en-us/library/dd233154.aspx


The Rise of F#

F# is a programming language that provides support for functional programming in addition to traditional object-oriented and imperative (procedural) programming. F# is a first-class member of the .NET Framework languages and retains a strong resemblance to the ML family of functional languages [6].

Features

  • fully type checked at compile time (eliminating many kinds of run-time error)
  • a compiled language (which delivers good performance)
  • combines its functional nature with the imperative paradigm, with the object-oriented paradigm, and with the concurrent paradigm
  • integrates with the .NET Framework and other implementations of the CLI (Common Language Infrastructure) (asynchronous and parallel class libraries is supported)

Example – First program

let x = 7
let y = 6
let z = (float 6.0)

let s = "life the universe and everything"
printfn "The answer to %A is %A" s (x*y)

Key takeaway

  1. A
    let

    statement is not an assignment statement but is used to associate a name with a value. In functional programming, such an association is called a binding. The new binding simply hides the old one if the binding already exists.

  2. There is no declarations. The name
    x

    does represent an

    int

    value but it does not need to be declared as

    int

    because the type can be easily deduced from its associated value

    7

    . Whenever datatypes can be inferred from the code, they can be omitted. The complete form is shown in let

    z = (float 6.0)

    .

  3. printfn

    is a built-in function for outputting lines of text; it is modelled after the

    printf

    function of C. The

    printfn

    function recognizes many of the same formatting codes as

    printf

    in C; however

    <strong>%A</strong>

    is an extra one which works with any datatype.

  4. Function calls are written in this format -- the function name, followed by the arguments which are separated by white space. (No comma and brackets)

Example – Association statement and assignment statement

[Incorrect-Error: Duplicate definition of value 'n']

let n = 2
let n = n + 1
printfn "n = %A" n

[Incorrect-Give "n = 2"]

let n = 2
n = n + 1
printfn "n = %A" n

[Incorrect-Give "n = 2"]

let mutable n = 2
n = n + 1
printfn "n = %A" n

[Correct-Give "n = 3"]

let mutable n = 2
n <- n + 1
printfn "n = %A" n

The associatation statement binds n to a value, which is not mutable. However, mutable variable is required to do the assignment of value. If an assignment statement is really needed, F# does provide it by a special operator (the left arrow

&lt;-

).

Example – Indentation and broken a line of code

[Version 1]

let AVeryLongVariableName = 1
let AnotherLongVariableName = 2
let variableNumberOne = AVeryLongVariableName + AnotherLongVariableName

[Version 2]

let variableNumberOne =

AVeryLongVariableName +

AnotherLongVariableName

[Version 3]

let variableNumberOne = (AVeryLongVariableName

+ AnotherLongVariableName)

[Version 4]

let variableNumberOne =

AVeryLongVariableName + AnotherLongVariableName

All four versions are identical. Indentation matters in F# code. It is used instead of a statement terminator (such as the semicolon in C, C# or Java code) and instead of statement grouping symbols (such as the left and right brace characters in C, C# or Java) to indicate where a F# language construct begins and ends.

Adding GSL Library on Eclipse with the help from MinGW

  1. Download MinGW installer from the official website http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/mingw-get-inst/
  2. Install MinGW with the latest version
  3. Follow the instruction on the guide Getting Started http://mingw.org/wiki/Getting_Started so as to download and set up the gcc and g++ compiler
  4. Download and unzip GSL library source from the offical website ftp://ftp.gnu.org/gnu/gsl/
  5. Copy the GSL source folder to the MinGW installation path, for example, C:\MinGW\msys\1.0\home, which is equivalent to /home in the GNU system
  6. Read the INSTALL in GSL source folder. If you want to have a quick set up, read the instruction under "The simplest way to compile this package is"
  7. Write the code which invokes function in GSL by following the example of GSL in the offical web site

    http://www.gnu.org/software/gsl/manual/html_node/Compiling-and-Linking.html

    http://www.gnu.org/software/gsl/manual/html_node/Linking-programs-with-the-library.html

  8. Download Eclipse IDE for C/C++ Developers (includes Incubating components) from the offical website. http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers-includes-incubating-components/indigor
  9. Unzip and open the eclipse.exe inside.
  10. Follow the instruction to do the initial set up for the IDE.
  11. After that, start a new project and choose MinGW as the toolchain for the project. Then click finish.
  12. Right click your project in the Project Explorer then click Properties.
  13. We need to construct the commands as shown in the GSL example with the steps. below.
  14. Under C/C++ Build –> Settings –> GCC C++ Compiler –> Includes, add the following paths: (supposing your MinGW installation path is C:\MinGW)
    "C:\MinGW\include"
    "C:\MinGW\msys\1.0\local\include"
    "C:\MinGW\msys\1.0\local\include\gsl"
    "C:\MinGW\msys\1.0\include"
    "C:\MinGW\lib\gcc\mingw32\4.5.2\include"
  15. Repeat the previous step under C/C++ Build –> Settings –> GCC C Compiler –> Includes
  16. In MinGW C++ Linker –> Libraries –> Libraries (-l), add the followings:
    gsl
    gslcblas
    m
  17. In MinGW C++ Linker –> Libraries –> Library search path (-L), add the foolowing paths:
    "C:\MinGW\msys\1.0\lib"
    "C:\MinGW\msys\1.0\local\lib"
  18. Create a new C++ file and copy the example of GSL to the editor.
  19. Click Run Configuration, add a new configuration under C/C++ Application and press OK
  20. Rebuild the whole project to see the results

    Debugging in Android - 001

    Observation

    Cannot see new views(e.g. RadioGroup) after the textbox(i.e. edittext) while running my app with the following XML layout.

    Code

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="5dp">
       
        <EditText
            android:id="@+id/edittext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
       
       
        <RadioGroup android:id="@+id/people_radioGroup"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content">
          <RadioButton android:id="@+id/radio_red"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Red" />
          <RadioButton android:id="@+id/radio_blue"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Blue" />
        </RadioGroup>  
       
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Country" />
        <AutoCompleteTextView android:id="@+id/autocomplete_country"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"/>

    </LinearLayout>

    More Details

    API Level: 8

    Orientation: Vertical

    Solution

    The line

    android:orientation="horizontal"

    is incorrect.

    It should be

    android:orientation="vertical"

    for veritcal orientation.