I'm using an older version of Parrot (0.2.2) so I can use threads.
It seems that Parrot on Solaris doesn't ever use more than one processor.
The program attached should create argv[1] number of threads, and
divide up over both of them argv[2] - ie perfect linear speedup.
I've got a dual-processor Xeon (a real one, not this hyperthreaded stuff)
and I indeed get speedup:
tonic(19)% time ./parrot /common/tmp/jon/thread_test.pir 1 500000000
<...>
18.870u 0.010s 0:18.93 99.7% 0+0k 0+0io 534pf+0w
tonic(20)% time ./parrot /common/tmp/jon/thread_test.pir 2 500000000
<...>
19.360u 0.030s 0:09.93 195.2% 0+0k 0+0io 534pf+0w
tonic(21)%
However, on a Solaris machine that has 8 CPUs, we get no speedup:
pinot(6)% time ./parrot-solaris /common/tmp/jon/thread_test.pir 1 50000000
<...>
9.69u 0.05s 0:09.77 99.6%
pinot(7)% time ./parrot-solaris /common/tmp/jon/thread_test.pir 2 50000000
<...>
9.08u 0.09s 0:09.19 99.7%
pinot(8)% time ./parrot-solaris /common/tmp/jon/thread_test.pir 4 50000000
<...>
9.28u 0.07s 0:09.38 99.6%
pinot(9)% time ./parrot-solaris /common/tmp/jon/thread_test.pir 8 50000000
<...>
9.67u 0.03s 0:09.74 99.5%
Is there some way we can check to see if Parrot is actually creating more than
one thread? Is it some sort of crazy green-thread issue?
Thanks,
-Erik
# Basic shared array program for parrot
.sub _main
.param pmc argv
.sym int threadIncs
.sym pmc threads
.sym pmc child
.sym pmc Inc_array
.local pmc increment_pass
.local pmc seed_param
.local int i, value, seed
.local pmc temp
.local int tmp
.local int offset
.local int numThreads
.local pmc logtmlib
.local pmc DoBreakpoint
.local string parameter
parameter = shift argv
parameter = shift argv
numThreads = parameter
parameter = shift argv
#numThreads = 1
threadIncs = parameter
threadIncs = threadIncs/numThreads
init_array:
Inc_array = global "increment_array" # get function pointer
# setup an array to hold threads
threads = new .FixedPMCArray
threads = 50
# Set the number of increments to do in each thread
increment_pass = new .Integer
increment_pass = threadIncs
seed = 54433
seed_param = new .Integer
i = 0
create_Thread:
child = new ParrotThread # basically new thread
.sym pmc New_thread
find_method New_thread, child, "thread3"
seed_param = seed
increment_pass = increment_pass
.pcc_begin
.arg Inc_array
.arg increment_pass
.arg seed_param
.invocant child
.nci_call New_thread
.pcc_end
threads[i] = child
inc i
if i < numThreads goto create_Thread
i = 0
# Join and wait on threads
_join_thread:
.sym int tid
.sym pmc Thread_join
child = threads[i]
tid = threads[i]
find_method Thread_join, child, "join"
.pcc_begin
.arg tid
.nci_call Thread_join
.pcc_end
threads[i] = child
inc i
if i < numThreads goto _join_thread
#DoBreakpoint()
i = 0
tmp = 0
_main_print_loop:
tmp = tmp + value
print value
print " "
inc i
if i < 100 goto _main_print_loop
print "\n"
print tmp
print "\n"
.end
# The code to exectute in the thread
.sub increment_array
.param pmc sub
.param pmc increments
.param pmc seed_param
.local int i, tmp, value, numIncs, rand, index
.local int temp
numIncs = increments
i = 0
s_loop:
inc i
if i < numIncs goto s_loop
i = 0
.end
> Hi -
>
> I'm using an older version of Parrot (0.2.2) so I can use threads.
>
> It seems that Parrot on Solaris doesn't ever use more than one
> processor.
[ ... ]
> Is there some way we can check to see if Parrot is actually creating
> more than
> one thread? Is it some sort of crazy green-thread issue?
There are AFAIK some issues with solaris (but I don't know the details)
It might need a different threading lib or some additional init code to
create 'real' threads.
> Thanks,
>
> -Erik
leo
> There are AFAIK some issues with solaris (but I don't know the
> details) It might need a different threading lib or some additional
> init code to create 'real' threads.
>
You just have to know how they implement pthreads, which is
weasel-worded in POSIX and
allows Solaris much divergence from what you expect. It's the LWP versus
full-fledged process
thing.
--
Jack J. Woehr # "I never played fast and loose with the
PO Box 51, Golden, CO 80402 # Constitution. Never did and never will."
http://www.well.com/~jax # - Harry S Truman
I've got it to work now, thanks to Joe Wilson who gave me the last clue.
I turned on pthreads in configure:
perl Configure.pl --ccflags=":add{ -pthreads -D_REENTERANT }" --linkflags=":add{ -pthreads }"
and I changed the definitino of CREATE_THREAD_JOINABLE:
# define THREAD_CREATE_JOINABLE(t, func, arg) do {\
pthread_attr_t attr; \
int rc = pthread_attr_init(&attr); \
assert(rc == 0); \
rc = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); \
assert(rc == 0); \
rc = pthread_setconcurrency(8); \
assert(rc == 0); \
pthread_create(&t, NULL, func, arg); \
} while(0)
The default to attrsetsope on Solaris is SCOPE_PROCESS, the default on Linux
is SCOPE_SYSTEM.
I'm on Solaris 8, and without the call to pthread_setconcurrency, I only ran
one thread at a time. Starting in Solaris 9, pthread_setconcurrency doesn't
do anything. (I don't have a Solaris 9 SMP I can test on to see if parrot
uses multiple processors concurrently without the call to set_concurrency.
My runtimes get about twice as fast every time I add a processor. I'm not sure
what the minimal set of calls I need to add are - the setconcurrency was the
last thing I tried, and once I added it in things started working - I don't
know if that means I can remove my other changes and things will still work,
I'll do that experiment later.
-Erik
> I've got it to work now, thanks to Joe Wilson who gave me the last
> clue.
Great.
> I turned on pthreads in configure:
> perl Configure.pl --ccflags=":add{ -pthreads -D_REENTERANT }"
> --linkflags=":add{ -pthreads }"
Have a look at config/init/hints/solaris.pm to make this change more
permanent.
Also having some SOLARIS_VERSION define (for below) if it's solaris
would be good I presume.
> and I changed the definitino of CREATE_THREAD_JOINABLE:
For a final patch you could include some #ifdef SOLARIS_VERSION == foo
to just include necessary extensions.
> -Erik
leo
>> and I changed the definitino of CREATE_THREAD_JOINABLE:
>
>
> For a final patch you could include some #ifdef SOLARIS_VERSION == foo
> to just include necessary extensions.
Doesn't look like there's anything Solaris-specific here. Other
non-Linux OSes will need the same changes (FreeBSD supports both
SCOPE_SYSTEM and SCOPE_PROCESS, for example), will they not?
--
http://www.velocityvector.com/ | http://glmiller.blogspot.com/
http://www.classic-games.com/ |
The hand ain't over till the river.