[clfft] 17/128: Precallback - Added few Google Test test cases

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Oct 22 14:54:33 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch master
in repository clfft.

commit 2a3e9bb0745d60391cda50f846a6d64e32a05448
Author: Pradeep <pradeep.rao at amd.com>
Date:   Tue Aug 18 11:49:52 2015 +0530

    Precallback - Added few Google Test test cases
---
 src/tests/CMakeLists.txt                |   1 +
 src/tests/accuracy_test_common.h        |  88 ++++++++++++++++++++
 src/tests/accuracy_test_precallback.cpp | 143 ++++++++++++++++++++++++++++++++
 src/tests/buffer.h                      |  23 +++++
 src/tests/cl_transform.h                |  80 +++++++++++++++++-
 src/tests/fftw_transform.h              |  17 ++++
 src/tests/test_constants.h              |  50 +++++++++++
 7 files changed, 401 insertions(+), 1 deletion(-)

diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 88904b5..d08ead6 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -27,6 +27,7 @@ set( clFFT.Test.Source
 	 accuracy_test_pow5.cpp
 	 accuracy_test_mixed_radices.cpp
 	 accuracy_test_random.cpp
+	 accuracy_test_precallback.cpp
 	 gtest_main.cpp
 	 ${PROJECT_SOURCE_DIR}/client/openCL.misc.cpp
 	 c-compliance.c
diff --git a/src/tests/accuracy_test_common.h b/src/tests/accuracy_test_common.h
index 428bd8b..159cde4 100644
--- a/src/tests/accuracy_test_common.h
+++ b/src/tests/accuracy_test_common.h
@@ -119,6 +119,94 @@ void complex_to_complex( data_pattern pattern, direction::direction_t direction,
 
 /*****************************************************/
 /*****************************************************/
+// complex to complex transform with precallback
+// dimension is inferred from lengths.size()
+// tightly packed is inferred from strides.empty()
+template< class T, class cl_T, class fftw_T >
+void precallback_complex_to_complex( data_pattern pattern, direction::direction_t direction,
+	std::vector<size_t> lengths, size_t batch,
+	std::vector<size_t> input_strides, std::vector<size_t> output_strides,
+	size_t input_distance, size_t output_distance,
+	layout::buffer_layout_t in_layout, layout::buffer_layout_t out_layout,
+	placeness::placeness_t placeness, bool hasUserDatatype = false,
+	T scale = 1.0f )
+{
+	clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
+		input_strides.empty() ? NULL : &input_strides[0],
+		output_strides.empty() ? NULL : &output_strides[0],
+		batch, input_distance, output_distance,
+		cl_layout(in_layout), cl_layout(out_layout),
+		cl_placeness(placeness) );
+
+	fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2c );
+
+	//initialize input
+	if( pattern == sawtooth )
+	{
+		test_fft.set_input_to_sawtooth( 1.0f );
+		reference.set_data_to_sawtooth( 1.0f );
+	}
+	else if( pattern == value )
+	{
+		test_fft.set_input_to_value( 2.0f, 2.5f );
+		reference.set_all_data_to_value( 2.0f, 2.5f );
+	}
+	else if( pattern == impulse )
+	{
+		test_fft.set_input_to_impulse();
+		reference.set_data_to_impulse();
+	}
+	else if( pattern == erratic )
+	{
+		test_fft.set_input_to_random();
+		reference.set_data_to_random();
+	}
+	else
+	{
+		throw std::runtime_error( "invalid pattern type in complex_to_complex()" );
+	}
+
+	// if we're starting with unequal data, we're destined for failure
+	EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
+
+	//set precallback values
+	if (hasUserDatatype)
+	{
+		test_fft.set_precallback_complex_userdatatype();
+	}
+	else
+	{
+		test_fft.set_precallback_complex();
+	}
+	reference.set_precallback_complex();
+
+	if( direction == direction::forward )
+	{
+		test_fft.set_forward_transform();
+		test_fft.forward_scale( scale );
+
+		reference.set_forward_transform();
+		reference.forward_scale( scale );
+	}
+	else if( direction == direction::backward )
+	{
+		test_fft.set_backward_transform();
+		test_fft.backward_scale( scale );
+
+		reference.set_backward_transform();
+		reference.backward_scale( scale );
+	}
+	else
+		throw std::runtime_error( "invalid direction in complex_to_complex()" );
+
+	reference.transform();
+	test_fft.transform();
+
+	EXPECT_EQ( true, test_fft.result() == reference.result() );
+}
+
+/*****************************************************/
+/*****************************************************/
 // dimension is inferred from lengths.size()
 // tightly packed is inferred from strides.empty()
 // input layout is always real
diff --git a/src/tests/accuracy_test_precallback.cpp b/src/tests/accuracy_test_precallback.cpp
new file mode 100644
index 0000000..a617017
--- /dev/null
+++ b/src/tests/accuracy_test_precallback.cpp
@@ -0,0 +1,143 @@
+/* ************************************************************************
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ************************************************************************/
+
+#include <gtest/gtest.h>
+#include<math.h>
+
+#include "test_constants.h"
+#include "fftw_transform.h"
+#include "cl_transform.h"
+#include "typedefs.h"
+#include "accuracy_test_common.h"
+#include <stdexcept>
+#include <vector>
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+class accuracy_test_precallback_single : public ::testing::Test {
+protected:
+	accuracy_test_precallback_single(){}
+	virtual ~accuracy_test_precallback_single(){}
+	virtual void SetUp(){}
+	virtual void TearDown(){
+	}
+};
+
+class accuracy_test_precallback_double : public ::testing::Test {
+protected:
+	accuracy_test_precallback_double(){}
+	virtual ~accuracy_test_precallback_double(){}
+	virtual void SetUp(){}
+	virtual void TearDown(){
+	}
+};
+
+namespace precallback
+{
+// *****************************************************
+// *****************************************************
+template< class T, class cl_T, class fftw_T >
+void precallback_1D_forward_in_place_complex_interleaved_to_complex_interleaved()
+{
+	std::vector<size_t> lengths;
+	lengths.push_back( normal2 );
+	size_t batch = 1;
+	std::vector<size_t> input_strides;
+	std::vector<size_t> output_strides;
+	size_t input_distance = 0;
+	size_t output_distance = 0;
+	layout::buffer_layout_t in_layout = layout::complex_interleaved;
+	layout::buffer_layout_t out_layout = layout::complex_interleaved;
+	placeness::placeness_t placeness = placeness::in_place;
+	direction::direction_t direction = direction::forward;
+
+	data_pattern pattern = impulse;
+	precallback_complex_to_complex<T, cl_T, fftw_T>( pattern, direction, lengths, batch, input_strides, output_strides, input_distance, output_distance, in_layout, out_layout, placeness );
+}
+
+TEST_F(accuracy_test_precallback_single, precallback_1D_forward_in_place_complex_interleaved_to_complex_interleaved)
+{
+	try { precallback_1D_forward_in_place_complex_interleaved_to_complex_interleaved< float, cl_float, fftwf_complex >(); }
+	catch( const std::exception& err ) { handle_exception(err);	}
+}
+
+TEST_F(accuracy_test_precallback_double, precallback_1D_forward_in_place_complex_interleaved_to_complex_interleaved)
+{
+	try { precallback_1D_forward_in_place_complex_interleaved_to_complex_interleaved< double, cl_double, fftw_complex >(); }
+	catch( const std::exception& err ) { handle_exception(err);	}
+}
+
+// *****************************************************
+// *****************************************************
+template< class T, class cl_T, class fftw_T >
+void precallback_1D_forward_in_place_complex_planar_to_complex_planar()
+{
+	std::vector<size_t> lengths;
+	lengths.push_back( normal2 );
+	size_t batch = 1;
+	std::vector<size_t> input_strides;
+	std::vector<size_t> output_strides;
+	size_t input_distance = 0;
+	size_t output_distance = 0;
+	layout::buffer_layout_t in_layout = layout::complex_planar;
+	layout::buffer_layout_t out_layout = layout::complex_planar;
+	placeness::placeness_t placeness = placeness::in_place;
+	direction::direction_t direction = direction::forward;
+
+	data_pattern pattern = impulse;
+	precallback_complex_to_complex<T, cl_T, fftw_T>( pattern, direction, lengths, batch, input_strides, output_strides, input_distance, output_distance, in_layout, out_layout, placeness );
+}
+
+TEST_F(accuracy_test_precallback_single, precallback_1D_forward_in_place_complex_planar_to_complex_planar)
+{
+	try { precallback_1D_forward_in_place_complex_planar_to_complex_planar< float, cl_float, fftwf_complex >(); }
+	catch( const std::exception& err ) { handle_exception(err);	}
+}
+
+TEST_F(accuracy_test_precallback_double, precallback_1D_forward_in_place_complex_planar_to_complex_planar)
+{
+	try { precallback_1D_forward_in_place_complex_planar_to_complex_planar< double, cl_double, fftw_complex >(); }
+	catch( const std::exception& err ) { handle_exception(err);	}
+}
+
+// *****************************************************
+// *****************************************************
+template< class T, class cl_T, class fftw_T >
+void precallback_1D_forward_in_place_complex_to_complex_userdatatype()
+{
+	std::vector<size_t> lengths;
+	lengths.push_back( normal2 );
+	size_t batch = 1;
+	std::vector<size_t> input_strides;
+	std::vector<size_t> output_strides;
+	size_t input_distance = 0;
+	size_t output_distance = 0;
+	layout::buffer_layout_t in_layout = layout::complex_interleaved;
+	layout::buffer_layout_t out_layout = layout::complex_interleaved;
+	placeness::placeness_t placeness = placeness::in_place;
+	direction::direction_t direction = direction::forward;
+
+	data_pattern pattern = impulse;
+	precallback_complex_to_complex<T, cl_T, fftw_T>( pattern, direction, lengths, batch, input_strides, output_strides, input_distance, output_distance, in_layout, out_layout, placeness, true );
+}
+
+TEST_F(accuracy_test_precallback_single, precallback_1D_forward_in_place_complex_to_complex_userdatatype)
+{
+	try { precallback_1D_forward_in_place_complex_to_complex_userdatatype< float, cl_float, fftwf_complex >(); }
+	catch( const std::exception& err ) { handle_exception(err);	}
+}
+
+}
\ No newline at end of file
diff --git a/src/tests/buffer.h b/src/tests/buffer.h
index 7fef025..50fc5a5 100644
--- a/src/tests/buffer.h
+++ b/src/tests/buffer.h
@@ -598,6 +598,29 @@ public:
 		return !( *this == other_buffer );
 	}
 
+	void operator*=( buffer<T> & other_buffer )
+	{
+		if( is_interleaved() )
+		{
+			T* base_ptr = _the_buffers[interleaved].ptr();
+
+			for( size_t batch = 0; batch < batch_size(); batch++ )
+					for( size_t z = 0; z < length(dimz); z++ )
+						for( size_t y = 0; y < length(dimy); y++ )
+							for( size_t x = 0; x < length(dimx); x++ )
+							{					
+								size_t real_index = index(x, y, z, batch);
+								size_t imag_index = real_index + 1; // the imaginary component immediately follows the real
+
+								*( base_ptr + real_index ) *= other_buffer.real(x, y, z, batch);
+								if (!(this->is_real() || other_buffer.is_real()))
+								{
+									*( base_ptr + imag_index ) *= other_buffer.imag(x, y, z, batch);
+								}
+							}
+		}
+	}
+
 	/*****************************************************/
 	// strides and distance are those of the output (that is, the new hermitian buffer)
 	void change_real_to_hermitian( const size_t* strides_in, const size_t distance_in )
diff --git a/src/tests/cl_transform.h b/src/tests/cl_transform.h
index 776a318..2edf28d 100644
--- a/src/tests/cl_transform.h
+++ b/src/tests/cl_transform.h
@@ -131,7 +131,7 @@ private:
 
 	buffer<T> input;
 	buffer<T> output;
-
+	
 	size_t number_of_data_points;
 	T _forward_scale, _backward_scale;
 	cl_uint commandQueueFlags;
@@ -618,6 +618,84 @@ public:
 	}
 
 	/*****************************************************/
+	void set_precallback_complex() {
+		cl_int status = 0;
+		clfftPrecision precision;
+		clfftGetPlanPrecision( *plan_handle, &precision );
+
+		char* precallbackstr;
+		
+		if (input.is_interleaved() )
+		{
+			precallbackstr = (precision == CLFFT_SINGLE) ? STRINGIFY(MULVAL) : STRINGIFY(MULVAL_DP);
+		}
+		else if (input.is_planar())
+		{
+			precallbackstr = (precision == CLFFT_SINGLE) ? STRINGIFY(MULVAL_PLANAR) : STRINGIFY(MULVAL_PLANAR_DP);
+		}
+
+		//precallback user data
+		buffer<T> userdata( 	static_cast<size_t>(dimension),
+					input.lengths(),
+					input.strides(),
+					input.batch_size(),
+					input.distance(),
+					layout::real,
+					_placeness
+					);
+
+		userdata.set_all_to_random_data(lengths[0], 10);
+		
+		// make the new buffer
+		const size_t bufferSizeBytes = userdata.size_in_bytes( );
+
+		cl_mem userdataBuff = clCreateBuffer( context.get( ), CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, bufferSizeBytes, userdata.real_ptr(), &status);
+		OPENCL_V_THROW( status, "Creating Buffer ( ::clCreateBuffer() )" );
+
+		//Register the callback
+		OPENCL_V_THROW (clFFTSetPlanCallback(*plan_handle, "mulval", precallbackstr, NULL, 0, PRECALLBACK, userdataBuff), "clFFTSetPlanCallback failed");
+	}
+
+		/*****************************************************/
+	void set_precallback_complex_userdatatype() {
+		cl_int status = 0;
+
+		char* precallbackstr = STRINGIFY(MULVAL_UDT);
+
+		size_t totalPts = input.total_number_of_points_including_data_and_intervening();
+
+		buffer<T> temp( 	static_cast<size_t>(dimension),
+					input.lengths(),
+					input.strides(),
+					input.batch_size(),
+					input.distance(),
+					layout::real,
+					_placeness
+					);
+
+		temp.set_all_to_random_data(lengths[0], 10);
+
+		std::vector<USER_DATA> userdata(totalPts);
+		size_t the_index;
+		for( size_t batch = 0; batch < input.batch_size(); batch++) 
+			for( size_t z = 0; z < input.length(dimz); z++) 
+				for( size_t y = 0; y < input.length(dimy); y++) 
+					for( size_t x = 0; x < input.length(dimx); x++) 
+					{
+						the_index = ( input.stride(dimx) * x + input.stride(dimy) * y + input.stride(dimz) * z + input.distance() * batch );
+
+						userdata[the_index].scalar1 = temp.real(x, y, z, batch);
+						userdata[the_index].scalar2 = 1;
+					}
+
+		cl_mem userdataBuff = clCreateBuffer(context.get( ), CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(USER_DATA) * totalPts, (void*)&userdata[0], &status);
+		OPENCL_V_THROW( status, "Creating Buffer ( ::clCreateBuffer() )" );
+
+		//Register the callback
+		OPENCL_V_THROW (clFFTSetPlanCallback(*plan_handle, "mulval", precallbackstr, STRINGIFY(STRUCT_USERDATA), 0, PRECALLBACK, userdataBuff), "clFFTSetPlanCallback failed");
+	}
+
+	/*****************************************************/
 	bool device_list_has_devices() {
 		return !device_id.empty();
 	}
diff --git a/src/tests/fftw_transform.h b/src/tests/fftw_transform.h
index 8768648..9936b21 100644
--- a/src/tests/fftw_transform.h
+++ b/src/tests/fftw_transform.h
@@ -440,6 +440,23 @@ public:
 		input = other_buffer;
 	}
 
+	void set_precallback_complex()
+	{
+		//precallback user data
+		buffer<T> userdata( 	input.number_of_dimensions(),
+					input.lengths(),
+					input.strides(),
+					input.batch_size(),
+					input.distance(),
+					layout::real ,
+					cl_placeness(placeness::in_place)
+					);
+		
+		userdata.set_all_to_random_data(_lengths[0], 10);
+
+		input *= userdata;
+	}
+
 	/*****************************************************/
 	void clear_data_buffer()
 	{
diff --git a/src/tests/test_constants.h b/src/tests/test_constants.h
index b281da4..cc39769 100644
--- a/src/tests/test_constants.h
+++ b/src/tests/test_constants.h
@@ -23,6 +23,56 @@
 #include <string>
 #include <stdexcept>
 
+#define MULVAL float2 mulval(__global void* in, uint offset, __global void* userdata)\n \
+				{ \n \
+				float scalar = *((__global float*)userdata + offset); \n \
+				float2 ret = *((__global float2*)in + offset) * scalar; \n \
+				return ret; \n \
+				}
+
+#define MULVAL_UDT float2 mulval(__global void* in, uint offset, __global void* userdata)\n \
+				{ \n \
+				__global USER_DATA *data = ((__global USER_DATA *)userdata + offset); \n \
+				float scalar = data->scalar1 * data->scalar2; \n \
+				float2 ret = *((__global float2*)in + offset) * scalar; \n \
+				return ret; \n \
+				}
+
+#define MULVAL_DP double2 mulval(__global void* in, uint offset, __global void* userdata)\n \
+				{ \n \
+				double scalar = *((__global double*)userdata + offset); \n \
+				double2 ret = *((__global double2*)in + offset) * scalar; \n \
+				return ret; \n \
+				}
+
+#define MULVAL_PLANAR float2 mulval(__global void* inRe, __global void* inIm, uint offset, __global void* userdata)\n \
+				{ \n \
+				float scalar = *((__global float*)userdata + offset); \n \
+				float2 ret; \n \
+				ret.x = *((__global float*)inRe + offset) * scalar; \n \
+				ret.y = *((__global float*)inIm + offset) * scalar; \n \
+				return ret; \n \
+				}
+
+#define MULVAL_PLANAR_DP double2 mulval(__global void* inRe, __global void* inIm, uint offset, __global void* userdata)\n \
+				{ \n \
+				double scalar = *((__global double*)userdata + offset); \n \
+				double2 ret; \n \
+				ret.x = *((__global double*)inRe + offset) * scalar; \n \
+				ret.y = *((__global double*)inIm + offset) * scalar; \n \
+				return ret; \n \
+				}
+
+#define STRUCT_USERDATA typedef struct USER_DATA  \
+					   {  \
+						float scalar1;  \
+						float scalar2;  \
+						} USER_DATA; 
+STRUCT_USERDATA
+
+#define CALLBCKSTR(...) #__VA_ARGS__
+#define STRINGIFY(...) 	CALLBCKSTR(__VA_ARGS__)
+
 enum { REAL=0, IMAG=1 };
 enum { dimx=0, dimy=1, dimz=2 };
 enum fftw_dim { one_d=1, two_d=2, three_d=3 };

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/clfft.git



More information about the debian-science-commits mailing list