2
0
mirror of https://github.com/boostorg/compute.git synced 2026-01-24 17:52:37 +00:00
Files
compute/test/test_transform.cpp
Denis Demidov 5d77bbebee Global setup for OpenCL context in tests
refs kylelutz/compute#9

device, context, and queue are initialized statically in `context_setup.hpp`.
With this change all tests are able to complete when an NVIDIA GPU is in
exclusive compute mode.

Side effect of the change:
Time for all tests to complete reduced from 15.71 to 13.03 sec Tesla C2075.
2013-04-19 14:53:59 +04:00

291 lines
9.7 KiB
C++

//---------------------------------------------------------------------------//
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://kylelutz.github.com/compute for more information.
//---------------------------------------------------------------------------//
#define BOOST_TEST_MODULE TestTransform
#include <boost/test/unit_test.hpp>
#include <boost/compute/lambda.hpp>
#include <boost/compute/system.hpp>
#include <boost/compute/function.hpp>
#include <boost/compute/functional.hpp>
#include <boost/compute/algorithm/transform.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/iterator/counting_iterator.hpp>
#include "context_setup.hpp"
namespace bc = boost::compute;
BOOST_AUTO_TEST_CASE(transform_int_abs)
{
int data[] = { 1, -2, -3, -4, 5 };
bc::vector<int> vector(data, data + 5);
BOOST_CHECK_EQUAL(vector[0], 1);
BOOST_CHECK_EQUAL(vector[1], -2);
BOOST_CHECK_EQUAL(vector[2], -3);
BOOST_CHECK_EQUAL(vector[3], -4);
BOOST_CHECK_EQUAL(vector[4], 5);
bc::transform(vector.begin(),
vector.end(),
vector.begin(),
bc::abs<int>());
BOOST_CHECK_EQUAL(vector[0], 1);
BOOST_CHECK_EQUAL(vector[1], 2);
BOOST_CHECK_EQUAL(vector[2], 3);
BOOST_CHECK_EQUAL(vector[3], 4);
BOOST_CHECK_EQUAL(vector[4], 5);
}
BOOST_AUTO_TEST_CASE(transform_float_sqrt)
{
float data[] = { 1.0f, 4.0f, 9.0f, 16.0f };
bc::vector<float> vector(data, data + 4);
BOOST_CHECK_EQUAL(float(vector[0]), 1.0f);
BOOST_CHECK_EQUAL(float(vector[1]), 4.0f);
BOOST_CHECK_EQUAL(float(vector[2]), 9.0f);
BOOST_CHECK_EQUAL(float(vector[3]), 16.0f);
bc::transform(vector.begin(),
vector.end(),
vector.begin(),
bc::sqrt<float>());
BOOST_CHECK_CLOSE(float(vector[0]), 1.0f, 1e-4);
BOOST_CHECK_CLOSE(float(vector[1]), 2.0f, 1e-4);
BOOST_CHECK_CLOSE(float(vector[2]), 3.0f, 1e-4);
BOOST_CHECK_CLOSE(float(vector[3]), 4.0f, 1e-4);
}
BOOST_AUTO_TEST_CASE(transform_float_clamp)
{
float data[] = { 10.f, 20.f, 30.f, 40.f, 50.f };
bc::vector<float> vector(data, data + 5);
BOOST_CHECK_EQUAL(float(vector[0]), 10.f);
BOOST_CHECK_EQUAL(float(vector[1]), 20.f);
BOOST_CHECK_EQUAL(float(vector[2]), 30.f);
BOOST_CHECK_EQUAL(float(vector[3]), 40.f);
BOOST_CHECK_EQUAL(float(vector[4]), 50.f);
bc::transform(vector.begin(),
vector.end(),
vector.begin(),
clamp(bc::_1, 15.f, 45.f));
BOOST_CHECK_EQUAL(float(vector[0]), 15.f);
BOOST_CHECK_EQUAL(float(vector[1]), 20.f);
BOOST_CHECK_EQUAL(float(vector[2]), 30.f);
BOOST_CHECK_EQUAL(float(vector[3]), 40.f);
BOOST_CHECK_EQUAL(float(vector[4]), 45.f);
}
BOOST_AUTO_TEST_CASE(transform_add_int)
{
int data1[] = { 1, 2, 3, 4 };
bc::vector<int> input1(data1, data1 + 4);
int data2[] = { 10, 20, 30, 40 };
bc::vector<int> input2(data2, data2 + 4);
bc::vector<int> output(4);
bc::transform(input1.begin(),
input1.end(),
input2.begin(),
output.begin(),
bc::plus<int>());
BOOST_CHECK_EQUAL(output[0], 11);
BOOST_CHECK_EQUAL(output[1], 22);
BOOST_CHECK_EQUAL(output[2], 33);
BOOST_CHECK_EQUAL(output[3], 44);
bc::transform(input1.begin(),
input1.end(),
input2.begin(),
output.begin(),
bc::multiplies<int>());
BOOST_CHECK_EQUAL(output[0], 10);
BOOST_CHECK_EQUAL(output[1], 40);
BOOST_CHECK_EQUAL(output[2], 90);
BOOST_CHECK_EQUAL(output[3], 160);
}
BOOST_AUTO_TEST_CASE(transform_pow4)
{
float data[] = { 1.0f, 2.0f, 3.0f, 4.0f };
bc::vector<float> vector(data, data + 4);
BOOST_CHECK_EQUAL(float(vector[0]), 1.0f);
BOOST_CHECK_EQUAL(float(vector[1]), 2.0f);
BOOST_CHECK_EQUAL(float(vector[2]), 3.0f);
BOOST_CHECK_EQUAL(float(vector[3]), 4.0f);
bc::vector<float> result(4);
bc::transform(vector.begin(),
vector.end(),
result.begin(),
pown(bc::_1, 4));
BOOST_CHECK_CLOSE(float(result[0]), 1.0f, 1e-4);
BOOST_CHECK_CLOSE(float(result[1]), 16.0f, 1e-4);
BOOST_CHECK_CLOSE(float(result[2]), 81.0f, 1e-4);
BOOST_CHECK_CLOSE(float(result[3]), 256.0f, 1e-4);
}
BOOST_AUTO_TEST_CASE(transform_custom_function)
{
float data[] = { 9.0f, 7.0f, 5.0f, 3.0f };
bc::vector<float> vector(data, data + 4);
const char source[] =
"float pow3add4(float x){ return pow(x, 3.0f) + 4.0f; }";
bc::function<float (float)> pow3add4 =
bc::make_function_from_source<float (float)>("pow3add4", source);
bc::vector<float> result(4);
bc::transform(vector.begin(),
vector.end(),
result.begin(),
pow3add4);
BOOST_CHECK_CLOSE(float(result[0]), 733.0f, 1e-4);
BOOST_CHECK_CLOSE(float(result[1]), 347.0f, 1e-4);
BOOST_CHECK_CLOSE(float(result[2]), 129.0f, 1e-4);
BOOST_CHECK_CLOSE(float(result[3]), 31.0f, 1e-4);
}
BOOST_AUTO_TEST_CASE(extract_vector_component)
{
int data[] = { 1, 2,
3, 4,
5, 6,
7, 8 };
bc::vector<bc::int2_> vector(reinterpret_cast<bc::int2_ *>(data),
reinterpret_cast<bc::int2_ *>(data) + 4,
context);
BOOST_CHECK_EQUAL(vector[0], bc::int2_(1, 2));
BOOST_CHECK_EQUAL(vector[1], bc::int2_(3, 4));
BOOST_CHECK_EQUAL(vector[2], bc::int2_(5, 6));
BOOST_CHECK_EQUAL(vector[3], bc::int2_(7, 8));
bc::vector<int> x_components(4, context);
bc::transform(vector.begin(),
vector.end(),
x_components.begin(),
bc::vector_component<bc::int2_, 0>());
BOOST_CHECK_EQUAL(x_components[0], 1);
BOOST_CHECK_EQUAL(x_components[1], 3);
BOOST_CHECK_EQUAL(x_components[2], 5);
BOOST_CHECK_EQUAL(x_components[3], 7);
bc::vector<int> y_components(4, context);
bc::transform(vector.begin(),
vector.end(),
y_components.begin(),
bc::vector_component<bc::int2_, 1>());
BOOST_CHECK_EQUAL(y_components[0], 2);
BOOST_CHECK_EQUAL(y_components[1], 4);
BOOST_CHECK_EQUAL(y_components[2], 6);
BOOST_CHECK_EQUAL(y_components[3], 8);
}
BOOST_AUTO_TEST_CASE(transform_pinned_vector)
{
int data[] = { 2, -3, 4, -5, 6, -7 };
std::vector<int> vector(data, data + 6);
bc::buffer buffer(context,
vector.size() * sizeof(int),
bc::buffer::read_write | bc::buffer::use_host_ptr,
&vector[0]);
bc::transform(bc::make_buffer_iterator<int>(buffer, 0),
bc::make_buffer_iterator<int>(buffer, 6),
bc::make_buffer_iterator<int>(buffer, 0),
bc::abs<int>(),
queue);
void *ptr = queue.enqueue_map_buffer(buffer,
bc::command_queue::map_read,
0,
buffer.size());
BOOST_VERIFY(ptr == &vector[0]);
BOOST_CHECK_EQUAL(vector[0], 2);
BOOST_CHECK_EQUAL(vector[1], 3);
BOOST_CHECK_EQUAL(vector[2], 4);
BOOST_CHECK_EQUAL(vector[3], 5);
BOOST_CHECK_EQUAL(vector[4], 6);
BOOST_CHECK_EQUAL(vector[5], 7);
queue.enqueue_unmap_buffer(buffer, ptr);
}
BOOST_AUTO_TEST_CASE(transform_popcount)
{
using boost::compute::uint_;
uint_ data[] = { 0, 1, 2, 3, 4, 45, 127, 5000, 789, 15963 };
bc::vector<uint_> input(data, data + 10, context);
bc::vector<uint_> output(input.size(), context);
bc::transform(
input.begin(),
input.end(),
output.begin(),
bc::popcount<uint_>(),
queue
);
queue.finish();
BOOST_CHECK_EQUAL(uint_(output[0]), uint_(0));
BOOST_CHECK_EQUAL(uint_(output[1]), uint_(1));
BOOST_CHECK_EQUAL(uint_(output[2]), uint_(1));
BOOST_CHECK_EQUAL(uint_(output[3]), uint_(2));
BOOST_CHECK_EQUAL(uint_(output[4]), uint_(1));
BOOST_CHECK_EQUAL(uint_(output[5]), uint_(4));
BOOST_CHECK_EQUAL(uint_(output[6]), uint_(7));
BOOST_CHECK_EQUAL(uint_(output[7]), uint_(5));
BOOST_CHECK_EQUAL(uint_(output[8]), uint_(5));
BOOST_CHECK_EQUAL(uint_(output[9]), uint_(10));
}
// generates the first 25 fibonacci numbers in parallel using the
// rounding-based fibonacci formula
BOOST_AUTO_TEST_CASE(generate_fibonacci_sequence)
{
using boost::compute::uint_;
boost::compute::vector<uint_> sequence(25, context);
const char nth_fibonacci_source[] =
"inline uint nth_fibonacci(const uint n)\n"
"{\n"
" const float golden_ratio = (1.f + sqrt(5.f)) / 2.f;\n"
" return floor(pown(golden_ratio, n) / sqrt(5.f) + 0.5f);\n"
"}\n";
boost::compute::function<uint_(const uint_)> nth_fibonacci =
boost::compute::make_function_from_source<uint_(const uint_)>(
"nth_fibonacci", nth_fibonacci_source);
boost::compute::transform(
boost::compute::make_counting_iterator(uint_(0)),
boost::compute::make_counting_iterator(uint_(sequence.size())),
sequence.begin(),
nth_fibonacci,
queue
);
queue.finish();
BOOST_CHECK_EQUAL(uint_(sequence[0]), 0);
BOOST_CHECK_EQUAL(uint_(sequence[1]), 1);
BOOST_CHECK_EQUAL(uint_(sequence[2]), 1);
BOOST_CHECK_EQUAL(uint_(sequence[5]), 5);
BOOST_CHECK_EQUAL(uint_(sequence[9]), 34);
BOOST_CHECK_EQUAL(uint_(sequence[15]), 610);
BOOST_CHECK_EQUAL(uint_(sequence[24]), 46368);
}
BOOST_AUTO_TEST_SUITE_END()