Skip to content

Commit 05afa5f

Browse files
committed
Use thread-local storage for global program cache
1 parent df1698f commit 05afa5f

File tree

8 files changed

+76
-5
lines changed

8 files changed

+76
-5
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ compiler:
44
- clang
55
before_install:
66
- sudo apt-get update -qq
7-
- sudo apt-get install -qq fglrx=2:8.960-0ubuntu1 opencl-headers libboost-chrono1.48-dev libboost-date-time1.48-dev libboost-test1.48-dev libboost-system1.48-dev libboost-filesystem1.48-dev libboost-timer1.48-dev libboost-program-options1.48-dev python-yaml lcov libopencv-dev
7+
- sudo apt-get install -qq fglrx=2:8.960-0ubuntu1 opencl-headers libboost-chrono1.48-dev libboost-date-time1.48-dev libboost-test1.48-dev libboost-system1.48-dev libboost-filesystem1.48-dev libboost-timer1.48-dev libboost-program-options1.48-dev libboost-thread1.48-dev python-yaml lcov libopencv-dev
88
- gem install coveralls-lcov
99
script:
1010
- mkdir -p build
1111
- cd build
12-
- cmake -DBOOST_COMPUTE_BUILD_TESTS=ON -DBOOST_COMPUTE_BUILD_EXAMPLES=ON -DBOOST_COMPUTE_BUILD_BENCHMARKS=ON -DBOOST_COMPUTE_USE_OFFLINE_CACHE=ON -DBOOST_COMPUTE_ENABLE_COVERAGE=ON -DBOOST_COMPUTE_HAVE_OPENCV=ON -DCMAKE_CXX_FLAGS="-Wall -pedantic -Werror -Wno-variadic-macros -Wno-long-long -Wno-shadow" ..
12+
- cmake -DBOOST_COMPUTE_BUILD_TESTS=ON -DBOOST_COMPUTE_BUILD_EXAMPLES=ON -DBOOST_COMPUTE_BUILD_BENCHMARKS=ON -DBOOST_COMPUTE_USE_OFFLINE_CACHE=ON -DBOOST_COMPUTE_ENABLE_COVERAGE=ON -DBOOST_COMPUTE_HAVE_OPENCV=ON -DBOOST_COMPUTE_THREAD_SAFE=ON -DCMAKE_CXX_FLAGS="-Wall -pedantic -Werror -Wno-variadic-macros -Wno-long-long -Wno-shadow" ..
1313
- make -j8
1414
- ./example/list_devices
1515
- ctest --output-on-failure

CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ if(${BOOST_COMPUTE_USE_CPP11})
1818
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
1919
endif()
2020

21+
# thread-safety options
22+
option(BOOST_COMPUTE_THREAD_SAFE "Compile with BOOST_COMPUTE_THREAD_SAFE defined" OFF)
23+
if(${BOOST_COMPUTE_THREAD_SAFE})
24+
add_definitions(-DBOOST_COMPUTE_THREAD_SAFE)
25+
if(${BOOST_COMPUTE_USE_CPP11})
26+
add_definitions(-DBOOST_COMPUTE_HAVE_THREAD_LOCAL)
27+
endif()
28+
endif()
29+
2130
# optional third-party libraries
2231
option(BOOST_COMPUTE_HAVE_EIGEN "Have Eigen" OFF)
2332
option(BOOST_COMPUTE_HAVE_OPENCV "Have OpenCV" OFF)

doc/faq.qbk

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,18 @@ which provides a std::vector-like interface to a region of host-memory and can
129129
be used directly with all of the Boost.Compute algorithms.
130130

131131

132+
[h3 Is Boost.Compute thread-safe?]
133+
134+
The low-level Boost.Compute APIs offer the same thread-safety guarantees as
135+
the underyling OpenCL library implementation. However, the high-level APIs
136+
make use of a few global static objects for features such as automatic program
137+
caching which makes them not thread-safe by default.
138+
139+
To compile Boost.Compute in thread-safe mode define `BOOST_COMPUTE_THREAD_SAFE`
140+
before including any of the Boost.Compute headers. By default this will require
141+
linking your application/library with the Boost.Thread library.
142+
143+
132144
[h3 How can I contribute?]
133145

134146
We are actively seeking additional C++ developers with experience in

example/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ if (${BOOST_COMPUTE_USE_OFFLINE_CACHE})
3131
set(EXAMPLE_BOOST_COMPONENTS ${EXAMPLE_BOOST_COMPONENTS} system filesystem)
3232
endif()
3333

34+
if(${BOOST_COMPUTE_THREAD_SAFE} AND NOT ${BOOST_COMPUTE_USE_CPP11})
35+
set(EXAMPLE_BOOST_COMPONENTS ${EXAMPLE_BOOST_COMPONENTS} thread)
36+
endif()
37+
3438
find_package(Boost 1.48 REQUIRED COMPONENTS ${EXAMPLE_BOOST_COMPONENTS})
3539
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
3640

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//---------------------------------------------------------------------------//
2+
// Copyright (c) 2013-2014 Kyle Lutz <[email protected]>
3+
//
4+
// Distributed under the Boost Software License, Version 1.0
5+
// See accompanying file LICENSE_1_0.txt or copy at
6+
// http://www.boost.org/LICENSE_1_0.txt
7+
//
8+
// See http://kylelutz.github.com/compute for more information.
9+
//---------------------------------------------------------------------------//
10+
11+
#ifndef BOOST_COMPUTE_DETAIL_GLOBAL_STATIC_HPP
12+
#define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC_HPP
13+
14+
#include <boost/compute/config.hpp>
15+
16+
#ifdef BOOST_COMPUTE_THREAD_SAFE
17+
# ifdef BOOST_COMPUTE_HAVE_THREAD_LOCAL
18+
// use c++11 thread local storage
19+
# define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(type, name, ctor) \
20+
thread_local type name ctor;
21+
# else
22+
// use thread_specific_ptr from boost.thread
23+
# include <boost/thread/tss.hpp>
24+
# define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(type, name, ctor) \
25+
static ::boost::thread_specific_ptr< type > BOOST_PP_CAT(name, _tls_ptr_); \
26+
if(!BOOST_PP_CAT(name, _tls_ptr_).get()){ \
27+
BOOST_PP_CAT(name, _tls_ptr_).reset(new type ctor); \
28+
} \
29+
static type &name = *BOOST_PP_CAT(name, _tls_ptr_);
30+
# endif
31+
#else
32+
// no thread-safety, just use static
33+
# define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(type, name, ctor) \
34+
static type name ctor;
35+
#endif
36+
37+
#endif // BOOST_COMPUTE_DETAIL_GLOBAL_STATIC_HPP

include/boost/compute/detail/program_cache.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <boost/compute/context.hpp>
2121
#include <boost/compute/program.hpp>
2222
#include <boost/compute/detail/lru_cache.hpp>
23+
#include <boost/compute/detail/global_static.hpp>
2324

2425
namespace boost {
2526
namespace compute {
@@ -66,7 +67,7 @@ inline boost::shared_ptr<program_cache> get_program_cache(const context &context
6667
{
6768
typedef lru_cache<cl_context, boost::shared_ptr<program_cache> > cache_map;
6869

69-
static cache_map caches(8);
70+
BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(cache_map, caches, (8));
7071

7172
boost::shared_ptr<program_cache> cache = caches.get(context.get());
7273
if(!cache){

perf/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ if (${BOOST_COMPUTE_USE_OFFLINE_CACHE})
66
set(PERF_BOOST_COMPONENTS ${PERF_BOOST_COMPONENTS} filesystem)
77
endif()
88

9+
if(${BOOST_COMPUTE_THREAD_SAFE} AND NOT ${BOOST_COMPUTE_USE_CPP11})
10+
set(PERF_BOOST_COMPONENTS ${PERF_BOOST_COMPONENTS} thread)
11+
endif()
12+
913
find_package(Boost 1.48 REQUIRED COMPONENTS ${PERF_BOOST_COMPONENTS})
1014
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
1115

test/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ include_directories(../include)
33
set(BOOST_COMPONENTS unit_test_framework)
44

55
if (${BOOST_COMPUTE_USE_OFFLINE_CACHE})
6-
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} system filesystem)
7-
add_definitions(-DBOOST_COMPUTE_USE_OFFLINE_CACHE)
6+
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} system filesystem)
7+
add_definitions(-DBOOST_COMPUTE_USE_OFFLINE_CACHE)
8+
endif()
9+
10+
if(${BOOST_COMPUTE_THREAD_SAFE} AND NOT ${BOOST_COMPUTE_USE_CPP11})
11+
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} thread)
812
endif()
913

1014
find_package(Boost 1.48 REQUIRED COMPONENTS ${BOOST_COMPONENTS})

0 commit comments

Comments
 (0)