9/28/2016

CUDA, GPGPU, Parallel communication pattern 5 -> Map, Gather, Scatter, Stencil, Transpose

1. Map : Tasks read from and write to specific data elements.


2. Gather : each calculation gathers input data elements together from different places to compute an output result.


3. Scatter : tasks compute where to write output


4. stencil


5. transpose



quiz


->
*out[i] = pi * in[i]
There is a 1-to-1 correspondence between the output and the input, so that's clearly an Map operation.

*out[i+j*128] = in[j+i*128];
i, j is reorder the array, so this is Transpose operation

*out[i-1] += pi * in[i]; out[i+1] += pi * in[i]
the value of calculation is placing the into a couple of different places in the output.
So Scatter operator

*out[i] = (in[i] + in[i-1] + in[i+1])* pi/3.0f;
every thread is writing a single location in the output array, and it's reading from multiple places in the input array, locations that it computes.
this looks very much like a stencil operation since it's reading from a local neighborhood, but because " if(i%2) ", it's not writing into every location.




image captured from UdaCity

9/23/2016

To run an external file to ShellExecute and kill processes. in MFC (and window active by PID or process handle)




Firstly, Check executing process to make by me.
And If process exist made by me, kill after check that saved PID is same.
"TerminateProcess" function used for kill process.
...
...
if (m_Manual_shell_hadle != NULL)
 {
  unsigned int tmp_pid = GetProcessId(m_Manual_shell_hadle); // retrieve PID
  //It comes under the pid value to the storage handle. Take on only kill pid is the same as the saved pid.
  if (tmp_pid == m_Manual_shell_pid)
  {
   TerminateProcess(m_Manual_shell_hadle, 1); //kill process
   m_Manual_shell_hadle = NULL;

   return 1; //sucess
  }
  
 }
 m_Manual_shell_hadle = NULL;
return 0; //not found
...
...


And, execute external file.

..
...
 SHELLEXECUTEINFO ShExecInfo = { 0 };
 ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
 ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
 ShExecInfo.hwnd = this->m_hWnd;
 ShExecInfo.lpVerb = NULL;
        ShExecInfo.lpFile = TargetPath; //external file name
 ShExecInfo.lpParameters = NULL; //aguments
 ShExecInfo.lpDirectory = NULL;
 ShExecInfo.nShow = SW_SHOW;
 ShExecInfo.hInstApp = NULL;

ShellExecuteEx(&ShExecInfo); //execute 

  //save pid and handle
  m_Manual_shell_pid = GetProcessId(ShExecInfo.hProcess); // retrieve PID
  m_Manual_shell_hadle = ShExecInfo.hProcess;

...
...


"m_Manual_shell_pid, m_Manual_shell_hadle" is our member variable.


and one more thing, if we want to window activating or taking to top on screen, using hwnd, to use below function.
///
::BringWindowToTop(hwnd);
 ::SetActiveWindow(hwnd);
 ::SetForegroundWindow(hwnd);
 ::ShowWindow(hwnd, SW_SHOWNORMAL);
 ::UpdateWindow(hwnd);
///

But to use these functions, we have to know hwnd value to active window.
We just know HANDLE value, then we can get Process id, that PID using GetProcessId and then
we can know hwnd using by this pid.

this is little complex, we should use callback function this -> EnumWindows(...)
The usage is like that,

firstly, make own function -> EnumWindowsProcMy
And call EnumWindows and then get hwnd.
see example code

HWND g_HWND = NULL;
BOOL CALLBACK EnumWindowsProcMy(HWND hwnd, LPARAM lParam)
{
 DWORD lpdwProcessId;
 GetWindowThreadProcessId(hwnd, &lpdwProcessId);
 if (lpdwProcessId == lParam)
 {
  g_HWND = hwnd;
  return FALSE;
 }
 return TRUE;
}


int CSomeClass::ActiveManualWindowIfAlive()
{

        if (m_Manual_shell_hadle != NULL)
 {
  unsigned int tmp_pid = GetProcessId(m_Manual_shell_hadle); // retrieve PID
  if (tmp_pid == m_Manual_shell_pid)
  {
   g_HWND = NULL;
   EnumWindows(EnumWindowsProcMy, m_Manual_shell_pid);
   if (g_HWND != NULL)
   {
    ::BringWindowToTop(g_HWND);
    return 1;
   }

  }
  
 }

 return 0;

}



Thank you.