Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

threading branch #13410

Merged
merged 66 commits into from
Oct 30, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
5cdc03b
Merging threads branch.
kpamnany Jan 19, 2015
6cfe327
Fix for the parallel for form.
kpamnany Jan 27, 2015
8c98205
Change LLVM_GIT_URL_LLVM to use "https:" instead of "git@", since some
Feb 13, 2015
65c9d89
inlining improvement that helps #10527
JeffBezanson Mar 18, 2015
0afad35
fix merge mistake in fix for #10527
JeffBezanson Mar 18, 2015
6c7e175
Cosmetic change to bring closer to master: __JL_THREAD -> JL_THREAD
Mar 27, 2015
1db03d2
More cosmetic changes to bring closer to master.
Mar 27, 2015
4ee059e
Bring tasking up to version in master branch.
Apr 1, 2015
72de07b
Merge branch 'adr/snapshot' of https://github.com/JuliaLang/julia int…
Apr 8, 2015
766c608
Fix Relocation and CodeModel.
Apr 8, 2015
8673d74
Merge branch 'adr/snapshot' of https://github.com/JuliaLang/julia int…
Apr 10, 2015
6311538
Use https://github.com/JuliaLang/llvm.git -b kf/tlsrebase5
Apr 10, 2015
7aadf02
Resolve merge of base/inference.jl
Apr 13, 2015
fbfd8e9
Some whitespace fixes
Keno Apr 13, 2015
4a2d2cc
Affinity fix for threads. Multi-threaded workloads.
kpamnany Apr 13, 2015
0f17e69
Lattice-Boltzmann 3D workload.
kpamnany Jun 5, 2015
3f4afe0
Minor updates & fixes to multithreaded workloads.
kpamnany Jun 18, 2015
4573cdb
Seed MT differently on each proc
ViralBShah Jun 28, 2015
a14a8b5
Merge branch 'adr/threading' of https://github.com/JuliaLang/julia in…
vtjnash Aug 31, 2015
9604d75
remove compiler overrides
vtjnash Sep 1, 2015
2f0d759
for TLS variables, need to call dlsym rather than & to get the addres…
vtjnash Sep 2, 2015
ac027dc
reduce cruft from codegen init
vtjnash Sep 2, 2015
236c5e4
makefile fixes to build on darwin
vtjnash Sep 2, 2015
1a0ddf3
put GC barrier back
JeffBezanson Sep 2, 2015
0152ea1
remove accidental double-init of jlexc_var
vtjnash Sep 2, 2015
a715b4e
fix gc-verify code to work with threading
vtjnash Sep 2, 2015
c0983e0
more gc fixes and cleanup
vtjnash Sep 2, 2015
4df1fe2
some 0.4 updates to threads code; get test-threads passing again
JeffBezanson Sep 2, 2015
3fd7aca
fix another translation error in the gc-verify code
vtjnash Sep 2, 2015
2fc8d97
syncronize contentious gc state
vtjnash Sep 3, 2015
67a93b9
synchronize type caches
JeffBezanson Sep 3, 2015
b29089c
synchronize add_finalizer. fixes #10718
JeffBezanson Sep 3, 2015
95f22cf
add JULIA_ENABLE_THREADING guard block around all threading-specific …
vtjnash Sep 3, 2015
8b69400
slightly reduce overhead in jl_threading_run
JeffBezanson Sep 3, 2015
cc71a4a
fixup for jn/threading build
vtjnash Sep 3, 2015
707e81f
fix a `return` that needs to be `continue` with the function body wra…
JeffBezanson Sep 3, 2015
87f9a9c
fix build of gc.c when threads are disabled
JeffBezanson Sep 3, 2015
cf70bc9
mark all thread stacks in GC
JeffBezanson Sep 4, 2015
3a86a98
hoist loads of constant closed variables
JeffBezanson Sep 4, 2015
c129d1e
Atomics.
Sep 11, 2015
0f49b2f
@nany exported; was already defined
Sep 18, 2015
6eab323
Reduce default number of threads to 4.
Sep 18, 2015
f3402da
Refactor threading stuff into Base.Threads
Sep 18, 2015
66bf7be
fix whitespace script to not get confused by glob expansion, and whit…
vtjnash Oct 1, 2015
a113dd3
Merge remote-tracking branch 'origin/master' into jn/threading
vtjnash Oct 1, 2015
0921b94
set a min target architecture of pentium4 to require support for sse2…
vtjnash Oct 1, 2015
f68130c
Uint => UInt deprecation
vtjnash Oct 1, 2015
5203429
get threads test passing without threading support
vtjnash Oct 1, 2015
74f906f
add support for llvm < v3.6 to atomics
vtjnash Oct 1, 2015
49d582b
correct size of uv_mutex on windows (& everywhere)
vtjnash Oct 1, 2015
2cc1371
Style: 4-spaced.
Oct 2, 2015
e6a8b1e
work around a gcc register allocation error
vtjnash Oct 5, 2015
db59e7a
fix minor makefile grievances
vtjnash Oct 5, 2015
a56a3bc
Merge remote-tracking branch 'origin/master' into jn/threading
vtjnash Oct 5, 2015
89636aa
Updated license.
Oct 6, 2015
f5da3f8
Fix atomics.jl on llvm-svn
Keno Oct 7, 2015
407b00a
Added credits.
Oct 7, 2015
8d840bd
Change Lock to AbstractLock and fix compile error
Oct 7, 2015
b3b22e8
Fixes for MSVC build
tkelman Oct 9, 2015
f54fbb2
Merge remote-tracking branch 'origin/master' into jn/threading
vtjnash Oct 19, 2015
4282ba2
use llvm-config directly to always determine the real llvm-version
vtjnash Oct 19, 2015
79da037
Licensing: added note for LBM3D.
Oct 26, 2015
7723bd2
Threads: make it easier to turn on threads
Oct 26, 2015
d164587
remove duplicated NOINLINE defines
tkelman Oct 27, 2015
173cd22
Threads: add enable threading flag correctly
Oct 27, 2015
eaf6115
Threads: use the correct flags and conditional
Oct 28, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@ else
DISABLE_ASSERTIONS := -DNDEBUG
endif

# Threads
ifeq ($(JULIA_THREADS), 1)
LLVM_VER := svn
LLVM_GIT_URL_LLVM := https://github.com/JuliaLang/llvm.git -b jn/tls37
endif

# Compiler specific stuff

ifeq ($(USEMSVC), 1)
Expand Down Expand Up @@ -405,10 +411,6 @@ CC_BASE := $(shell echo $(CC) | cut -d' ' -f1)
CXX_BASE := $(shell echo $(CXX) | cut -d' ' -f1)
endif

ifeq ($(LLVM_VER),svn)
JCXXFLAGS += -std=c++11
endif

JFFLAGS := -O2 $(fPIC)
ifneq ($(USEMSVC),1)
CPP := $(CC) -E
Expand Down Expand Up @@ -602,7 +604,7 @@ JCFLAGS += -fsigned-char

LLVM_ASSERTIONS=1
#LLVM_FLAGS+="--with-float=hard --with-abi=aapcs-vfp"
LLVM_VER:=3.6.1
LLVM_VER:=3.7.0

override USE_BLAS64:=0
override OPENBLAS_DYNAMIC_ARCH:=0
Expand Down Expand Up @@ -654,7 +656,6 @@ endif # LLVM_CONFIG undefined

ifeq ($(USE_SYSTEM_LLVM), 1)
JCPPFLAGS+=-DSYSTEM_LLVM
LLVM_VER := $(shell $(LLVM_CONFIG) --version)
endif # SYSTEM_LLVM

ifeq ($(BUILD_OS),$(OS))
Expand Down Expand Up @@ -844,6 +845,11 @@ JCPPFLAGS += -D_WIN32_WINNT=0x0502
UNTRUSTED_SYSTEM_LIBM := 1
endif

# Threads
ifeq ($(JULIA_THREADS), 1)
JCPPFLAGS += -DJULIA_ENABLE_THREADING
endif

# Intel VTune Amplifier
ifeq ($(USE_INTEL_JITEVENTS), 1)
JCPPFLAGS += -DJL_USE_INTEL_JITEVENTS
Expand Down
2 changes: 1 addition & 1 deletion base/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ else
endif
@echo "const libfftw_name = \"$(LIBFFTWNAME)\"" >> $@
@echo "const libfftwf_name = \"$(LIBFFTWFNAME)\"" >> $@
@echo "const libllvm_version = \"$(LLVM_VER)\"" >> $@
@echo "const libllvm_version = \"$$($(LLVM_CONFIG_HOST) --version)\"" >> $@
@echo "const VERSION_STRING = \"$(JULIA_VERSION)\"" >> $@
@echo "const TAGGED_RELEASE_BANNER = \"$(TAGGED_RELEASE_BANNER)\"" >> $@
@echo "const SYSCONFDIR = \"$(sysconfdir_rel)\"" >> $@
Expand Down
60 changes: 60 additions & 0 deletions base/atomics.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license

using Base.Intrinsics: llvmcall

import Base: setindex!, getindex

export
Atomic,
atomic_cas!,
atomic_xchg!,
atomic_add!, atomic_sub!,
atomic_and!, atomic_nand!, atomic_or!, atomic_xor!,
atomic_max!, atomic_min!, atomic_umax!, atomic_umin!

type Atomic{T<:Integer}
value::T
Atomic() = new(zero(T))
Atomic(value) = new(value)
end

Atomic() = Atomic{Int}()

atomicintsmap = Dict(Int8 => "i8", UInt8 => "i8",
Int16 => "i16", UInt16 => "i16",
Int32 => "i32", UInt32 => "i32",
Int64 => "i64", UInt64 => "i64",
Int128 => "i128", UInt128 => "i128")

unsafe_convert{T}(::Type{Ptr{T}}, x::Atomic{T}) = convert(Ptr{T}, pointer_from_objref(x))
setindex!{T}(x::Atomic{T}, v) = setindex!(x, convert(T, v))

for (typ, lt) in atomicintsmap
rt = VersionNumber(Base.libllvm_version) >= v"3.6" ? "$lt, $lt*" : "$lt*"
@eval getindex(x::Atomic{$typ}) =
llvmcall($"""
%rv = load atomic volatile $rt %0 monotonic, align $WORD_SIZE
ret $lt %rv
""", $typ, Tuple{Ptr{$typ}}, unsafe_convert(Ptr{$typ}, x))
@eval setindex!(x::Atomic{$typ}, v::$typ) =
llvmcall($"""
store atomic volatile $lt %1, $lt* %0 monotonic, align $WORD_SIZE
ret void
""", Void, Tuple{Ptr{$typ},$typ}, unsafe_convert(Ptr{$typ}, x), v)
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
llvmcall($"""
%rv = cmpxchg $lt* %0, $lt %1, $lt %2 acq_rel monotonic
%bv = extractvalue { $lt, i1 } %rv, 1
ret i1 %bv
""", Bool, Tuple{Ptr{$typ},$typ,$typ}, unsafe_convert(Ptr{$typ}, x), cmp, new)
for rmwop in [:xchg, :add, :sub, :and, :nand, :or, :xor, :max, :min, :umax, :umin]
rmw = string(rmwop)
fn = symbol("atomic_", rmw, "!")
@eval $fn(x::Atomic{$typ}, v::$typ) =
llvmcall($"""
%rv = atomicrmw volatile $rmw $lt* %0, $lt %1 acquire
ret $lt %rv
""", $typ, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
end
end

15 changes: 14 additions & 1 deletion base/cartesian.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Cartesian

export @nloops, @nref, @ncall, @nexprs, @nextract, @nall, @ntuple, @nif
export @nloops, @nref, @ncall, @nexprs, @nextract, @nall, @nany, @ntuple, @nif

### Cartesian-specific macros

Expand Down Expand Up @@ -98,6 +98,19 @@ function _nall(N::Int, criterion::Expr)
Expr(:&&, conds...)
end

# Check whether any of variables i1, i2, ... satisfy criterion
macro nany(N, criterion)
_nany(N, criterion)
end

function _nany(N::Int, criterion::Expr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests for @nany?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add a couple, but I can't find tests for any of the existing macros in Cartesian.

if criterion.head != :->
error("Second argument must be an anonymous function expression yielding the criterion")
end
conds = [Expr(:escape, inlineanonymous(criterion, i)) for i = 1:N]
Expr(:||, conds...)
end

macro ntuple(N, ex)
_ntuple(N, ex)
end
Expand Down
138 changes: 138 additions & 0 deletions base/locks.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a base/lock.jl. Shouldn't the two be merged?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I'm working on the interaction between threads and tasks, which is also needed for I/O. When that is properly designed, these will get merged.


export SpinLock, Mutex, init_lock!, destroy_lock!, lock!, trylock!, unlock!

abstract AbstractLock

# Test-and-test-and-set spin locks are quickest up to about 30ish
# contending threads. If you have more contention than that, perhaps
# a lock is the wrong way to synchronize.
type TatasLock <: AbstractLock
handle::Atomic{Int}
TatasLock() = new(Atomic{Int}(0))
end

typealias SpinLock TatasLock

function lock!(l::TatasLock)
while true
if l.handle[] == 0
p = atomic_xchg!(l.handle, 1)
if p == 0
return 0
end
end
# TODO: pause
end
end

function trylock!(l::TatasLock)
if l.handle[] == 0
return atomic_xchg!(l.handle, 1)
end
return 1
end

function unlock!(l::TatasLock)
l.handle[] = 0
return 0
end


# Recursive test-and-test-and-set lock. Slower.
type RecursiveTatasLock <: AbstractLock
ownertid::Atomic{Int16}
handle::Atomic{Int}
RecursiveTatasLock() = new(0, Atomic{Int}(0))
end

typealias RecursiveSpinLock RecursiveTatasLock

function lock!(l::RecursiveTatasLock)
if l.ownertid[] == threadid()
return 0
end
while true
if l.handle[] == 0
p = atomic_xchg!(l.handle, 1)
if p == 0
l.ownertid[] = threadid()
return 0
end
end
# TODO: pause
end
end

function trylock!(l::RecursiveTatasLock)
if l.ownertid[] == threadid()
return 0
end
if l.handle[] == 0
p = atomic_xchg!(l.handle, 1)
if p == 0
l.ownertid[] = threadid()
end
return p
end
return 1
end

function unlock!(l::RecursiveTatasLock)
if l.ownertid[] != threadid()
return 1
end
l.ownertid[] = 0
l.handle[] = 0
return 0
end


# These are mutexes from libuv, which abstract pthread mutexes and
# Windows critical sections. We're doing some error checking (and
# paying for it in overhead), but regardless, in some situations,
# passing a bad parameter will cause an abort.

# TODO: how defensive to get, and how to turn it off?
# TODO: how to catch an abort?

const UV_MUTEX_SIZE = ccall(:jl_sizeof_uv_mutex, Cint, ())

type Mutex <: AbstractLock
ownertid::Int16
handle::Array{Int8}
Mutex() = (m = new(zero(Int16), zeros(Int8, UV_MUTEX_SIZE));
ccall(:uv_mutex_init, Void, (Ptr{Void},), m.handle);
finalizer(m, (x -> ccall(:uv_mutex_destroy, Void, (Ptr{Void},), x.handle)));
m)
end

function lock!(m::Mutex)
if m.ownertid == threadid()
return 0
end
ccall(:uv_mutex_lock, Void, (Ptr{Void},), m.handle)
m.ownertid = threadid()
return 0
end

function trylock!(m::Mutex)
if m.ownertid == threadid()
return 0
end
r = ccall(:uv_mutex_trylock, Cint, (Ptr{Void},), m.handle)
if r == 0
m.ownertid = threadid()
end
return r
end

function unlock!(m::Mutex)
if m.ownertid != threadid()
return Base.UV_EPERM
end
m.ownertid = 0
ccall(:uv_mutex_unlock, Void, (Ptr{Void},), m.handle)
return 0
end

3 changes: 3 additions & 0 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ include("deprecated.jl")
include("docs/helpdb.jl")
include("docs/basedocs.jl")

# threads
include("threads.jl")

function __init__()
# Base library init
reinit_stdio()
Expand Down
89 changes: 89 additions & 0 deletions base/threadingconstructs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license

export threadid, maxthreads, nthreads, @threads

threadid() = Int(ccall(:jl_threadid, Int16, ())+1)
maxthreads() = Int(unsafe_load(cglobal(:jl_max_threads, Cint)))
nthreads() = Int(unsafe_load(cglobal(:jl_n_threads, Cint)))

function _threadsfor(forexpr)
fun = gensym("_threadsfor")
lidx = forexpr.args[1].args[1] # index
lf = forexpr.args[1].args[2].args[1] # first
ll = forexpr.args[1].args[2].args[2] # last
lbody = forexpr.args[2] # body
quote
function $fun()
tid = threadid()
# divide loop iterations among threads
len, rem = divrem($(esc(ll))-$(esc(lf))+1, nthreads())
# not enough iterations for all the threads?
if len == 0
if tid > rem
return
end
len, rem = 1, 0
end
# compute this thread's range
f = $(esc(lf)) + ((tid-1) * len)
l = f + len - 1
# distribute remaining iterations evenly
if rem > 0
if tid <= rem
f = f + (tid-1)
l = l + tid
else
f = f + rem
l = l + rem
end
end
# run this thread's iterations
for $(esc(lidx)) = f:l
$(esc(lbody))
end
end
ccall(:jl_threading_run, Void, (Any, Any), $fun, ())
end
end

function _threadsblock(blk)
fun = gensym("_threadsblock")
esc(quote
function $fun()
$blk
end
ccall(:jl_threading_run, Void, (Any, Any), $fun, ())
end)
end

function _threadscall(callexpr)
fun = callexpr.args[1]
esc(quote
ccall(:jl_threading_run, Void, (Any, Any), $fun, $(Expr(:call, Core.svec, callexpr.args[2:end]...)))
end)
end

macro threads(args...)
na = length(args)
if na != 2
throw(ArgumentError("wrong number of arguments in @threads"))
end
tg = args[1]
if !is(tg, :all)
throw(ArgumentError("only 'all' supported as thread group for @threads"))
end
ex = args[2]
if !isa(ex, Expr)
throw(ArgumentError("need an expression argument to @threads"))
end
if is(ex.head, :for)
return _threadsfor(ex)
elseif is(ex.head, :block)
return _threadsblock(ex)
elseif is(ex.head, :call)
return _threadscall(ex)
else
throw(ArgumentError("unrecognized argument to @threads"))
end
end

Loading