Author Topic: Multithreading: Parallel processing of strings  (Read 2549 times)

0 Members and 1 Guest are viewing this topic.

Charles Pegge

  • Guest
Multithreading: Parallel processing of strings
« on: June 15, 2011, 11:15:52 PM »

This is a test rig where 3 threads process strings at the same time. String corruption is guaranteed unless the string concatenation procedure is fully reentrant.

I found that the string function processing up to 7 calls at the same time. - can't explain why but the strings come out clean at the end :)

Code: OxygenBasic
  1.  
  2.  
  3.  
  4.   '================================================
  5.  'MULTIPLE THREADS WITH SYNC FOR STRING PROCESSING
  6.  '================================================
  7.  
  8.   #define NULL     0
  9.   #define FALSE    0
  10.   #define TRUE     1
  11.   #define IGNORE   0           'Ignore signal
  12.  #define INFINITE 0xFFFFFFFF  'Infinite timeout
  13.  
  14.   #define __in
  15.   #define __out
  16.   #define __in_opt
  17.   #define __out_opt
  18.   #define __in_ecount(nCount)
  19.  
  20.   #define MAX_THREADS 3
  21.  
  22.   'Sample custom data structure for threads to use.
  23.  'This is passed by void pointer so it can be any data type
  24.  'that can be passed using a single void pointer (LPVOID).
  25.  '
  26.  type dtype sys val1,val2
  27.  
  28.   typedef sys   HANDLE,SIZE_T
  29.   typedef void  *LPVOID, *LPSECURITY_ATTRIBUTES, *LPTHREAD_START_ROUTINE
  30.   typedef dword *LPDWORD
  31.  
  32.   '--------------------------------
  33.  extern stdcall lib "kernel32.dll"
  34.   '================================
  35.  
  36.   sys Sleep(sys msec)
  37.  
  38.   HANDLE CreateThread
  39.   (
  40.     __in_opt  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  41.     __in      SIZE_T dwStackSize,
  42.     __in      LPTHREAD_START_ROUTINE lpStartAddress,
  43.     __in_opt  LPVOID lpParameter,
  44.     __in      DWORD dwCreationFlags,
  45.     __out_opt LPDWORD lpThreadId
  46.   )
  47.  
  48.  
  49.   DWORD WaitForMultipleObjects
  50.   (
  51.     __in DWORD nCount,
  52.     __in_ecount(nCount) CONST HANDLE *lpHandles,
  53.     __in BOOL bWaitAll,
  54.     __in DWORD dwMilliseconds
  55.   )
  56.  
  57.  
  58.  
  59.   BOOL CloseHandle
  60.   (
  61.     __in HANDLE hObject
  62.   )
  63.  
  64.  
  65.   end extern
  66.  
  67.   sys eventA,eventB,MaxSimult
  68.   sys busy,entries
  69.   string cr=chr(13)+chr(10)
  70.   string tab=chr(10)
  71.   bstring s[8]<=("String A:" cr,"string B:" cr,"string C:" cr)
  72.  
  73.  
  74.   '-----------------------
  75.  function append(sys i,c)
  76.   '=======================
  77.  'do
  78.  '  if busy then inc eventB : sleep 1 : else busy=1 : exit do
  79.  'end do
  80.  '
  81.  inc entries
  82.   '
  83.  'add asci char to indexed string
  84.  '
  85.  sys a,b,le,p
  86.   p=@s
  87.   mov ecx,i
  88.   dec ecx
  89.   shl ecx,2 'array index
  90.  add ecx,p
  91.   mov a,ecx 'bstring location
  92.  mov ecx,[ecx]
  93.   mov eax,[ecx-4]
  94.   mov le,eax
  95.   add le,1
  96.   b=getmemory le
  97.   copy b,*a,le
  98.   mov ecx,b
  99.   add ecx,le
  100.   dec ecx
  101.   mov al,c
  102.   mov [ecx],al
  103.   freememory *a
  104.   *a=b
  105.   '
  106.  dec entries
  107.   if entries then inc eventB
  108.   if maxSimult<entries then MaxSimult=entries
  109.   busy=0
  110.   '
  111.  end function
  112.  
  113.   '-------------------------------------------
  114.  function ThreadA( dtype*pd ) as sys external
  115.   '===========================================
  116.  finit
  117.   sys i=65,j
  118.   do
  119.     append 1,i
  120.     inc eventA
  121.     inc i
  122.     sleep 1
  123.     if i>90 then i=65 : inc j : if j=4 then exit do
  124.   end do
  125.   return 10
  126.   end function
  127.  
  128.   '-------------------------------------------
  129.  function ThreadB( dtype*pd ) as sys external
  130.   '===========================================
  131.  finit
  132.   sys i=97,j
  133.   do
  134.    append 2,i
  135.    inc eventA
  136.     inc i
  137.     sleep 1
  138.     if i>122 then i=97 : inc j : if j=4 then exit do
  139.   end do
  140.   return 0
  141.   end function
  142.  
  143.   '-------------------------------------------
  144.  function ThreadC( dtype*pd ) as sys external
  145.   '===========================================
  146.  finit
  147.   sys i=48,j
  148.   do
  149.     append 3,i
  150.     inc eventA
  151.     inc i
  152.     sleep 1
  153.     if i>57 then i=48 : inc j : if j=8 then exit do
  154.   end do
  155.   return 0
  156.   end function
  157.  
  158.  
  159.   #define MAX_THREADS 3
  160.  
  161.   LPTHREAD_START_ROUTINE FunArray[MAX_THREADS]<=(&ThreadA,&ThreadB,&ThreadC)
  162.  
  163.  
  164.   '--------------
  165.  function main()
  166.   '==============
  167.  
  168.   dtype  tdata[MAX_THREADS]
  169.   dword  dwThreadIdArray[MAX_THREADS]
  170.   HANDLE hThreadArray[MAX_THREADS]
  171.   sys    i
  172.  
  173.   'Create MAX_THREADS worker threads.
  174.  '----------------------------------
  175.  
  176.   for i=1 to MAX_THREADS
  177.     '
  178.    'Generate some unique data for each thread to work with.
  179.    '------------------------------------------------------
  180.    '  
  181.    tdata[i].val1=i : tdata[i].val2=i+100
  182.     '
  183.    'Create the thread to begin execution on its own.
  184.    '------------------------------------------------
  185.    '
  186.    hThreadArray[i] = CreateThread
  187.     (
  188.     byval NULL,              'default security attributes
  189.    0,                       'use default stack size  
  190.    byval FunArray[i],       'thread function
  191.    tdata[i],                'argument to thread function
  192.    0,                       'use default creation flags
  193.    dwThreadIdArray[i]       'returns the thread identifier
  194.    )
  195.     '
  196.    'print "ThreadID: " dwThreadIdArray[i]
  197.    '
  198.    'Check the return value for success.
  199.    'If CreateThread fails, terminate execution.
  200.    'This will automatically clean up threads and memory.
  201.    '
  202.  next 'End of main thread creation loop.
  203.  '
  204.  'print "All threads up and running"
  205.  '
  206.  do
  207.     if busy then sleep 1 else busy=1 : exit do
  208.   end do
  209.   '
  210.  '
  211.  'Wait until all threads have terminated.
  212.  '---------------------------------------
  213.  '
  214.  WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE)
  215.   '
  216.  'Close all thread handles and free memory allocations.
  217.  '-----------------------------------------------------
  218.  '
  219.  for i=1 to MAX_THREADS
  220.     CloseHandle( hThreadArray[i] )
  221.   next
  222.   '
  223.  return 0
  224.   '
  225.  end function 'main
  226.  
  227.   main()
  228.  
  229.   print s[1] cr s[2] cr s[3] cr cr "String Ops: " EventA cr+
  230.   "Total Parallel Encounters: " EventB cr+
  231.   "Max string operations in parallel: " MaxSimult
  232.   '
  233.  frees s[1]
  234.   frees s[2]
  235.   frees s[3]
  236.  
  237.  

Code: [Select]
String A:
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
string B:
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
string C:
01234567890123456789012345678901234567890123456789012345678901234567890123456789

String Ops: 288
Total Parallel Encounters: 272
Max string operations in parallel: 4

Charles

kryton9

  • Guest
Re: Multithreading: Parallel processing of strings
« Reply #1 on: June 16, 2011, 12:13:21 AM »
All magic to me...  someday I will understand :)

Charles Pegge

  • Guest
Re: Multithreading: Parallel processing of strings
« Reply #2 on: June 18, 2012, 08:28:21 AM »
Since this example was posted, Oxygen no longer uses a static string concatenator. Each procedure has its own local concatenator, safe to use in multiple threads.

Here is a simpler example, running three threads at the same time.

Code: OxygenBasic
  1.  
  2.   '========================
  3.  'RUNNING MULTIPLE THREADS
  4.  '========================
  5.  
  6.   library "kernel32.dll"
  7.   sys   CreateThread (sys lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, *lpThreadId)
  8.   dword WaitForMultipleObjects(sys nCount,*lpHandles, bWaitAll, dwMilliseconds)
  9.   bool  CloseHandle(sys hObject)
  10.   void  Sleep(sys dwMilliSeconds)
  11.   library ""
  12.  
  13.   % INFINITE 0xFFFFFFFF  'Infinite timeout
  14.  
  15.   function RunAll(sys n,*funs)
  16.   '==============================
  17.  '
  18.  sys  hThread[64], id[64], i
  19.   '
  20.  for i=1 to n
  21.     hThread[ i ] =  CreateThread 0,0,funs[ i ],i,0,id[ i ]
  22.   next
  23.   '
  24.  WaitForMultipleObjects n, hThread, 1, INFINITE
  25.   '
  26.  '
  27.  for i=1 to n
  28.     CloseHandle hThread[ i ]
  29.   next
  30.   '
  31.  end function
  32.   '
  33.  'THREADS
  34.  '=======
  35.  '
  36.  '
  37.  string cr=chr(13)+chr(10)
  38.   string tab=chr(10)
  39.   string s[8]<=("String A:" cr,"string B:" cr,"string C:" cr)
  40.   '
  41.  '-------------------------------------------
  42.  function ThreadA( sys n ) as sys external
  43.   '===========================================
  44.  finit
  45.   sys i=65,j
  46.   do
  47.     s[n]+=chr(i)
  48.     inc i
  49.     sleep 1
  50.     if i>90 then i=65 : inc j : if j=4 then exit do
  51.   end do
  52.   return 0
  53.   end function
  54.  
  55.   '-------------------------------------------
  56.  function ThreadB( sys n ) as sys external
  57.   '===========================================
  58.  finit
  59.   sys i=97,j
  60.   do
  61.     s[n]+=chr(i)
  62.     inc i
  63.     sleep 1
  64.     if i>122 then i=97 : inc j : if j=4 then exit do
  65.   end do
  66.   return 0
  67.   end function
  68.  
  69.   '-------------------------------------------
  70.  function ThreadC( sys n ) as sys external
  71.   '===========================================
  72.  finit
  73.   sys i=48,j
  74.   do
  75.     s[n]+=chr(i)
  76.     inc i
  77.     sleep 1
  78.     if i>57 then i=48 : inc j : if j=8 then exit do
  79.   end do
  80.   return 0
  81.   end function
  82.  
  83.  
  84.   '====
  85.  'TEST
  86.  '====
  87.  '
  88.  sys threads[3]={@ThreadA, @ThreadB, @ThreadC}
  89.   RunAll 3,threads
  90.   print s[1] cr s[2] cr s[3] cr
  91.  
  92.  

Charles

kryton9

  • Guest
Re: Multithreading: Parallel processing of strings
« Reply #3 on: June 18, 2012, 11:44:30 AM »
Thanks for the update. Great I got lots of cool stuff to look at tonight, thanks again!