Skip to content

Commit

Permalink
Sorting algorithms take tuples of keys/values
Browse files Browse the repository at this point in the history
One will also has to explicitly specify the comparison function. Both
host and device variants of the comparison functor should take 2*n
arguments, where n is number of keys. First n arguments correspond to a
left set of keys, and second n arguments correspond to a right set of
keys. Here is an example that sorts values by a tuple of two keys:

    vex::vector<int>    keys1(ctx, n);
    vex::vector<float>  keys2(ctx, n);
    vex::vector<double> vals (ctx, n);

    struct {
        VEX_FUNCTION(device, bool(int, float, int, float),
                "return (prm1 == prm3) ? (prm2 < prm4) : (prm1 < prm3);"
                );
        bool operator()(int a1, float a2, int b1, float b2) const {
            return std::make_tuple(a1, a2) < std::tuple(b1, b2);
        }
    } comp;

    vex::sort_by_key(std::tie(keys1, keys2), vals);
  • Loading branch information
ddemidov committed Dec 5, 2013
1 parent 91c8db5 commit 7ed62da
Show file tree
Hide file tree
Showing 6 changed files with 1,233 additions and 420 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ endif ()
# Enable C++11 support, set compilation flags
#----------------------------------------------------------------------------
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wclobbered -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wsign-compare -Wtype-limits -Wuninitialized -Wunused-parameter -Wunused-but-set-parameter -Wno-comment")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wclobbered -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wsign-compare -Wtype-limits -Wuninitialized -Wunused-parameter -Wunused-but-set-parameter -Wno-comment -Wno-type-limits")
endif ()

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wsign-compare -Wtype-limits -Wuninitialized -Wunused-parameter -Wno-comment")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wsign-compare -Wtype-limits -Wuninitialized -Wunused-parameter -Wno-comment -Wno-tautological-compare")

option(USE_LIBCPP "Use libc++ with Clang" OFF)
if (USE_LIBCPP)
Expand Down
94 changes: 86 additions & 8 deletions tests/sort.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
#define BOOST_TEST_MODULE Sort
#include <algorithm>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/test/unit_test.hpp>
#include <vexcl/vector.hpp>
#include <vexcl/sort.hpp>
#include "context_setup.hpp"

BOOST_AUTO_TEST_CASE(sort_pairs)
BOOST_AUTO_TEST_CASE(sort_keys)
{
const size_t n = 1000 * 1000;

std::vector<float> k = random_vector<float>(n);
vex::vector<float> keys(ctx, k);

vex::sort(keys);
vex::copy(keys, k);

BOOST_CHECK( std::is_sorted(k.begin(), k.end()) );
}

BOOST_AUTO_TEST_CASE(sort_keys_vals)
{
const size_t n = 1000 * 1000;

Expand All @@ -19,13 +33,16 @@ BOOST_AUTO_TEST_CASE(sort_pairs)
BOOST_CHECK( std::is_sorted(k.begin(), k.end()) );

struct {
typedef bool result_type;

VEX_FUNCTION(device, bool(int, int),
"char bit1 = 1 & prm1;\n"
"char bit2 = 1 & prm2;\n"
"if (bit1 == bit2) return prm1 < prm2;\n"
"return bit1 < bit2;\n"
);
bool operator()(int a, int b) const {

result_type operator()(int a, int b) const {
char bit1 = 1 & a;
char bit2 = 1 & b;
if (bit1 == bit2) return a < b;
Expand All @@ -39,17 +56,78 @@ BOOST_AUTO_TEST_CASE(sort_pairs)
BOOST_CHECK(std::is_sorted(k.begin(), k.end(), even_first));
}

BOOST_AUTO_TEST_CASE(sort_keys)
BOOST_AUTO_TEST_CASE(sort_keys_tuple)
{
const size_t n = 1000 * 1000;

std::vector<float> k = random_vector<float>(n);
vex::vector<float> keys(ctx, k);
std::vector<int> k1 = random_vector<int> (n);
std::vector<float> k2 = random_vector<float>(n);

vex::sort(keys);
vex::copy(keys, k);
vex::vector<int> keys1(ctx, k1);
vex::vector<float> keys2(ctx, k2);

BOOST_CHECK( std::is_sorted(k.begin(), k.end()) );
struct {
typedef bool result_type;

VEX_FUNCTION(device, bool(int, float, int, float),
"return (prm1 == prm3) ? (prm2 < prm4) : (prm1 < prm3);"
);

result_type operator()(int a1, float a2, int b1, float b2) const {
return (a1 == b1) ? (a2 < b2) : (a1 < b1);
}
} less;

vex::sort(std::tie(keys1, keys2), less );
vex::copy(keys1, k1);
vex::copy(keys2, k2);

BOOST_CHECK( std::is_sorted(
boost::counting_iterator<size_t>(0),
boost::counting_iterator<size_t>(n),
[&](size_t i, size_t j) {
return std::make_tuple(k1[i], k2[i]) < std::make_tuple(k1[j], k2[j]);
} ) );
}

BOOST_AUTO_TEST_CASE(sort_keys_vals_tuple)
{
const size_t n = 1000 * 1000;

std::vector<int> k1 = random_vector<int> (n);
std::vector<float> k2 = random_vector<float>(n);
std::vector<long> v1 = random_vector<long> (n);
std::vector<short> v2 = random_vector<short>(n);

vex::vector<int> keys1(ctx, k1);
vex::vector<float> keys2(ctx, k2);
vex::vector<long> vals1(ctx, v1);
vex::vector<short> vals2(ctx, v2);

struct {
typedef bool result_type;

VEX_FUNCTION(device, bool(int, float, int, float),
"return (prm1 == prm3) ? (prm2 < prm4) : (prm1 < prm3);"
);

result_type operator()(int a1, float a2, int b1, float b2) const {
return (a1 == b1) ? (a2 < b2) : (a1 < b1);
}
} less;

vex::sort_by_key(std::tie(keys1, keys2), std::tie(vals1, vals2), less );

vex::copy(keys1, k1);
vex::copy(keys2, k2);

BOOST_CHECK( std::is_sorted(
boost::counting_iterator<size_t>(0),
boost::counting_iterator<size_t>(n),
[&](size_t i, size_t j) {
return std::make_tuple(k1[i], k2[i]) < std::make_tuple(k1[j], k2[j]);
} ) );
}


BOOST_AUTO_TEST_SUITE_END()
1 change: 1 addition & 0 deletions vexcl/backend/cuda/device_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct deleter_impl<char*> {
template <typename T>
class device_vector {
public:
typedef T value_type;
typedef CUdeviceptr raw_type;

/// Empty constructor.
Expand Down
4 changes: 2 additions & 2 deletions vexcl/backend/cuda/kernel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@ class kernel {

/// Adds an argument to the kernel.
template <class Arg>
void push_arg(Arg &&arg) {
void push_arg(const Arg &arg) {
char *c = (char*)&arg;
prm_pos.push_back(stack.size());
stack.insert(stack.end(), c, c + sizeof(arg));
}

/// Adds an argument to the kernel.
template <typename T>
void push_arg(device_vector<T> &&arg) {
void push_arg(const device_vector<T> &arg) {
push_arg(arg.raw());
}

Expand Down
1 change: 1 addition & 0 deletions vexcl/backend/opencl/device_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static const mem_flags MEM_READ_WRITE = CL_MEM_READ_WRITE;
template <typename T>
class device_vector {
public:
typedef T value_type;
typedef cl_mem raw_type;

device_vector() {}
Expand Down
Loading

0 comments on commit 7ed62da

Please sign in to comment.