mirror of
https://github.com/amd/blis.git
synced 2026-05-11 17:50:00 +00:00
- Add missing axpby and xpby operations (plus test cases). - Add special case for scal2v with alpha=1. - Add restrict qualifiers. - Add special-case algorithms for incx=incy=1.
2253 lines
87 KiB
C
2253 lines
87 KiB
C
/*
|
|
|
|
BLIS
|
|
An object-based framework for developing high-performance BLAS-like
|
|
libraries.
|
|
|
|
Copyright (C) 2014, The University of Texas at Austin
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
- Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
- Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
- Neither the name of The University of Texas at Austin nor the names
|
|
of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
#include "blis.h"
|
|
#include "test_libblis.h"
|
|
|
|
|
|
// Global variables.
|
|
char libblis_test_binary_name[ MAX_BINARY_NAME_LENGTH + 1 ];
|
|
|
|
char libblis_test_parameters_filename[ MAX_FILENAME_LENGTH + 1 ];
|
|
char libblis_test_operations_filename[ MAX_FILENAME_LENGTH + 1 ];
|
|
|
|
char libblis_test_pass_string[ MAX_PASS_STRING_LENGTH + 1 ];
|
|
char libblis_test_warn_string[ MAX_PASS_STRING_LENGTH + 1 ];
|
|
char libblis_test_fail_string[ MAX_PASS_STRING_LENGTH + 1 ];
|
|
|
|
char libblis_test_store_chars[ NUM_OPERAND_TYPES ][ MAX_STORE_VALS_PER_TYPE + 1 ];
|
|
|
|
char libblis_test_param_chars[ NUM_PARAM_TYPES ][ MAX_PARAM_VALS_PER_TYPE + 1 ];
|
|
|
|
|
|
|
|
int main( int argc, char** argv )
|
|
{
|
|
test_params_t params;
|
|
test_ops_t ops;
|
|
|
|
// Initialize libblis.
|
|
bli_init();
|
|
|
|
// Initialize some strings.
|
|
libblis_test_init_strings();
|
|
|
|
// Parse the command line parameters.
|
|
libblis_test_parse_command_line( argc, argv );
|
|
|
|
// Read the global parameters file.
|
|
libblis_test_read_params_file( libblis_test_parameters_filename, ¶ms );
|
|
|
|
// Read the operations parameter file.
|
|
libblis_test_read_ops_file( libblis_test_operations_filename, &ops );
|
|
|
|
// Test the utility operations.
|
|
libblis_test_utility_ops( ¶ms, &ops );
|
|
|
|
// Test the level-1v operations.
|
|
libblis_test_level1v_ops( ¶ms, &ops );
|
|
|
|
// Test the level-1m operations.
|
|
libblis_test_level1m_ops( ¶ms, &ops );
|
|
|
|
// Test the level-1f operations.
|
|
libblis_test_level1f_ops( ¶ms, &ops );
|
|
|
|
// Test the level-2 operations.
|
|
libblis_test_level2_ops( ¶ms, &ops );
|
|
|
|
// Test the level-3 micro-kernels.
|
|
libblis_test_level3_ukrs( ¶ms, &ops );
|
|
|
|
// Test the level-3 operations.
|
|
libblis_test_level3_ops( ¶ms, &ops );
|
|
|
|
// Finalize libblis.
|
|
bli_finalize();
|
|
|
|
// Return peacefully.
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_utility_ops( test_params_t* params, test_ops_t* ops )
|
|
{
|
|
libblis_test_randv( params, &(ops->randv) );
|
|
libblis_test_randm( params, &(ops->randm) );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_level1v_ops( test_params_t* params, test_ops_t* ops )
|
|
{
|
|
libblis_test_addv( params, &(ops->addv) );
|
|
libblis_test_axpbyv( params, &(ops->axpbyv) );
|
|
libblis_test_axpyv( params, &(ops->axpyv) );
|
|
libblis_test_copyv( params, &(ops->copyv) );
|
|
libblis_test_dotv( params, &(ops->dotv) );
|
|
libblis_test_dotxv( params, &(ops->dotxv) );
|
|
libblis_test_normfv( params, &(ops->normfv) );
|
|
libblis_test_scalv( params, &(ops->scalv) );
|
|
libblis_test_scal2v( params, &(ops->scal2v) );
|
|
libblis_test_setv( params, &(ops->setv) );
|
|
libblis_test_subv( params, &(ops->subv) );
|
|
libblis_test_xpbyv( params, &(ops->xpbyv) );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_level1m_ops( test_params_t* params, test_ops_t* ops )
|
|
{
|
|
libblis_test_addm( params, &(ops->addm) );
|
|
libblis_test_axpym( params, &(ops->axpym) );
|
|
libblis_test_copym( params, &(ops->copym) );
|
|
libblis_test_normfm( params, &(ops->normfm) );
|
|
libblis_test_scalm( params, &(ops->scalm) );
|
|
libblis_test_scal2m( params, &(ops->scal2m) );
|
|
libblis_test_setm( params, &(ops->setm) );
|
|
libblis_test_subm( params, &(ops->subm) );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_level1f_ops( test_params_t* params, test_ops_t* ops )
|
|
{
|
|
libblis_test_axpy2v( params, &(ops->axpy2v) );
|
|
libblis_test_dotaxpyv( params, &(ops->dotaxpyv) );
|
|
libblis_test_axpyf( params, &(ops->axpyf) );
|
|
libblis_test_dotxf( params, &(ops->dotxf) );
|
|
libblis_test_dotxaxpyf( params, &(ops->dotxaxpyf) );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_level2_ops( test_params_t* params, test_ops_t* ops )
|
|
{
|
|
libblis_test_gemv( params, &(ops->gemv) );
|
|
libblis_test_ger( params, &(ops->ger) );
|
|
libblis_test_hemv( params, &(ops->hemv) );
|
|
libblis_test_her( params, &(ops->her) );
|
|
libblis_test_her2( params, &(ops->her2) );
|
|
libblis_test_symv( params, &(ops->symv) );
|
|
libblis_test_syr( params, &(ops->syr) );
|
|
libblis_test_syr2( params, &(ops->syr2) );
|
|
libblis_test_trmv( params, &(ops->trmv) );
|
|
libblis_test_trsv( params, &(ops->trsv) );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_level3_ukrs( test_params_t* params, test_ops_t* ops )
|
|
{
|
|
libblis_test_gemm_ukr( params, &(ops->gemm_ukr) );
|
|
libblis_test_trsm_ukr( params, &(ops->trsm_ukr) );
|
|
libblis_test_gemmtrsm_ukr( params, &(ops->gemmtrsm_ukr) );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_level3_ops( test_params_t* params, test_ops_t* ops )
|
|
{
|
|
libblis_test_gemm( params, &(ops->gemm) );
|
|
libblis_test_hemm( params, &(ops->hemm) );
|
|
libblis_test_herk( params, &(ops->herk) );
|
|
libblis_test_her2k( params, &(ops->her2k) );
|
|
libblis_test_symm( params, &(ops->symm) );
|
|
libblis_test_syrk( params, &(ops->syrk) );
|
|
libblis_test_syr2k( params, &(ops->syr2k) );
|
|
libblis_test_trmm( params, &(ops->trmm) );
|
|
libblis_test_trmm3( params, &(ops->trmm3) );
|
|
libblis_test_trsm( params, &(ops->trsm) );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_read_ops_file( char* input_filename, test_ops_t* ops )
|
|
{
|
|
FILE* input_stream;
|
|
|
|
// Attempt to open input file corresponding to input_filename as
|
|
// read-only/binary.
|
|
input_stream = fopen( input_filename, "rb" );
|
|
libblis_test_fopen_check_stream( input_filename, input_stream );
|
|
|
|
// Begin reading operations input file.
|
|
|
|
// dimensions n_param operation
|
|
|
|
// Section overrides
|
|
libblis_test_read_section_override( ops, input_stream, &(ops->util_over) );
|
|
libblis_test_read_section_override( ops, input_stream, &(ops->l1v_over) );
|
|
libblis_test_read_section_override( ops, input_stream, &(ops->l1m_over) );
|
|
libblis_test_read_section_override( ops, input_stream, &(ops->l1f_over) );
|
|
libblis_test_read_section_override( ops, input_stream, &(ops->l2_over) );
|
|
libblis_test_read_section_override( ops, input_stream, &(ops->l3ukr_over) );
|
|
libblis_test_read_section_override( ops, input_stream, &(ops->l3_over) );
|
|
|
|
// Utility operations
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 0, &(ops->randv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 0, &(ops->randm) );
|
|
|
|
// Level-1v
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->addv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->axpbyv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->axpyv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->copyv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->dotv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->dotxv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 0, &(ops->normfv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->scalv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->scal2v) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 0, &(ops->setv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->subv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 1, &(ops->xpbyv) );
|
|
|
|
// Level-1m
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->addm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->axpym) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->copym) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 0, &(ops->normfm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->scalm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->scal2m) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 0, &(ops->setm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 1, &(ops->subm) );
|
|
|
|
// Level-1f
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->axpy2v) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->dotaxpyv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MF, 2, &(ops->axpyf) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MF, 2, &(ops->dotxf) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MF, 4, &(ops->dotxaxpyf) );
|
|
|
|
// Level-2
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 2, &(ops->gemv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_MN, 2, &(ops->ger) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->hemv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->her) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->her2) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->symv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 2, &(ops->syr) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->syr2) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->trmv) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_M, 3, &(ops->trsv) );
|
|
|
|
// Level-3 micro-kernels
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_K, 0, &(ops->gemm_ukr) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_NO_DIMS, 1, &(ops->trsm_ukr) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_NOID, BLIS_TEST_DIMS_K, 1, &(ops->gemmtrsm_ukr) );
|
|
|
|
// Level-3
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_GEMM, BLIS_TEST_DIMS_MNK, 2, &(ops->gemm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_HEMM, BLIS_TEST_DIMS_MN, 4, &(ops->hemm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_HERK, BLIS_TEST_DIMS_MK, 2, &(ops->herk) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_HER2K, BLIS_TEST_DIMS_MK, 3, &(ops->her2k) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_SYMM, BLIS_TEST_DIMS_MN, 4, &(ops->symm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_SYRK, BLIS_TEST_DIMS_MK, 2, &(ops->syrk) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_SYR2K, BLIS_TEST_DIMS_MK, 3, &(ops->syr2k) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_TRMM, BLIS_TEST_DIMS_MN, 4, &(ops->trmm) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_TRMM3, BLIS_TEST_DIMS_MN, 5, &(ops->trmm3) );
|
|
libblis_test_read_op_info( ops, input_stream, BLIS_TRSM, BLIS_TEST_DIMS_MN, 4, &(ops->trsm) );
|
|
|
|
// Output the section overrides.
|
|
libblis_test_output_section_overrides( stdout, ops );
|
|
|
|
// Close the file.
|
|
fclose( input_stream );
|
|
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_read_params_file( char* input_filename, test_params_t* params )
|
|
{
|
|
FILE* input_stream;
|
|
char buffer[ INPUT_BUFFER_SIZE ];
|
|
char temp[ INPUT_BUFFER_SIZE ];
|
|
int i;
|
|
|
|
// Attempt to open input file corresponding to input_filename as
|
|
// read-only/binary.
|
|
input_stream = fopen( input_filename, "rb" );
|
|
libblis_test_fopen_check_stream( input_filename, input_stream );
|
|
|
|
// Read the number of repeats.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->n_repeats) );
|
|
|
|
// Read the matrix storage schemes to test. We should have at most three:
|
|
// 'r' for row-major, 'c' for column-major, and 'g' for general strides.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%s ", temp );
|
|
|
|
params->n_mstorage = strlen( temp );
|
|
if ( params->n_mstorage > MAX_NUM_MSTORAGE )
|
|
{
|
|
libblis_test_printf_error( "Detected too many matrix storage schemes (%u) in input file.\n",
|
|
params->n_mstorage );
|
|
}
|
|
strcpy( params->storage[ BLIS_TEST_MATRIX_OPERAND ], temp );
|
|
|
|
// Read the vector storage schemes to test. We should have at most four:
|
|
// 'r' for row vectors with unit stride, 'c' for column vectors with unit
|
|
// stride, 'i' for row vectors with non-unit stride, and 'j' for column
|
|
// vectors with non-unit stride.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%s ", temp );
|
|
|
|
params->n_vstorage = strlen( temp );
|
|
if ( params->n_vstorage > MAX_NUM_VSTORAGE )
|
|
{
|
|
libblis_test_printf_error( "Detected too many vector storage schemes (%u) in input file.\n",
|
|
params->n_vstorage );
|
|
}
|
|
strcpy( params->storage[ BLIS_TEST_VECTOR_OPERAND ], temp );
|
|
|
|
// Read whether to mix all storage combinations.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->mix_all_storage) );
|
|
|
|
// Read the general stride "spacing".
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->gs_spacing) );
|
|
|
|
// Overwrite the existing storage character arrays with the sets provided.
|
|
strcpy( libblis_test_store_chars[BLIS_TEST_MATRIX_OPERAND],
|
|
params->storage[BLIS_TEST_MATRIX_OPERAND] );
|
|
strcpy( libblis_test_store_chars[BLIS_TEST_VECTOR_OPERAND],
|
|
params->storage[BLIS_TEST_VECTOR_OPERAND] );
|
|
|
|
// Read the datatypes to test. We should have at most four: 's', 'd', 'c',
|
|
// and 'z'.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%s ", temp );
|
|
|
|
params->n_datatypes = strlen( temp );
|
|
if ( params->n_datatypes > MAX_NUM_DATATYPES )
|
|
{
|
|
libblis_test_printf_error( "Detected too many datatype requests (%u) in input file.\n",
|
|
params->n_datatypes );
|
|
}
|
|
|
|
for( i = 0; i < params->n_datatypes; ++i )
|
|
{
|
|
if ( temp[i] == 's' ) params->datatype[i] = BLIS_FLOAT;
|
|
else if ( temp[i] == 'd' ) params->datatype[i] = BLIS_DOUBLE;
|
|
else if ( temp[i] == 'c' ) params->datatype[i] = BLIS_SCOMPLEX;
|
|
else if ( temp[i] == 'z' ) params->datatype[i] = BLIS_DCOMPLEX;
|
|
|
|
params->datatype_char[i] = temp[i];
|
|
}
|
|
|
|
// Read the initial problem size to test.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->p_first) );
|
|
|
|
// Read the maximum problem size to test.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->p_max) );
|
|
|
|
// Read the problem size increment to test.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->p_inc) );
|
|
|
|
// Read whether to enable 3mh.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_3MH ]) );
|
|
|
|
// Read whether to enable 3m3.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_3M3 ]) );
|
|
|
|
// Read whether to enable 3m2.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_3M2 ]) );
|
|
|
|
// Read whether to enable 3m1.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_3M1 ]) );
|
|
|
|
// Read whether to enable 4mh.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_4MH ]) );
|
|
|
|
// Read whether to enable 4m1b (4mb).
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_4M1B ]) );
|
|
|
|
// Read whether to enable 4m1a (4m1).
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->ind_enable[ BLIS_4M1A ]) );
|
|
|
|
params->ind_enable[ BLIS_NAT ] = 1;
|
|
|
|
// Read the requested error-checking level.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->error_checking_level) );
|
|
|
|
// Read the requested course of action if a test fails.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%c ", &(params->reaction_to_failure) );
|
|
|
|
if ( params->reaction_to_failure != ON_FAILURE_IGNORE_CHAR &&
|
|
params->reaction_to_failure != ON_FAILURE_SLEEP_CHAR &&
|
|
params->reaction_to_failure != ON_FAILURE_ABORT_CHAR )
|
|
{
|
|
libblis_test_printf_error( "Invalid reaction-to-failure character code (%c) in input file.\n",
|
|
params->reaction_to_failure );
|
|
}
|
|
|
|
// Read whether to output in matlab format.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->output_matlab_format) );
|
|
|
|
// Read whether to output to files in addition to stdout.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%u ", &(params->output_files) );
|
|
|
|
// Close the file.
|
|
fclose( input_stream );
|
|
|
|
// Output the parameter struct.
|
|
libblis_test_output_params_struct( stdout, params );
|
|
}
|
|
|
|
|
|
void libblis_test_read_section_override( test_ops_t* ops,
|
|
FILE* input_stream,
|
|
int* override )
|
|
{
|
|
char buffer[ INPUT_BUFFER_SIZE ];
|
|
|
|
// Read the line for the section override switch.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%d ", override );
|
|
}
|
|
|
|
|
|
void libblis_test_read_op_info( test_ops_t* ops,
|
|
FILE* input_stream,
|
|
opid_t opid,
|
|
dimset_t dimset,
|
|
unsigned int n_params,
|
|
test_op_t* op )
|
|
{
|
|
char buffer[ INPUT_BUFFER_SIZE ];
|
|
char temp[ INPUT_BUFFER_SIZE ];
|
|
int i, p;
|
|
|
|
// Initialize the operation type field.
|
|
op->opid = opid;
|
|
|
|
// Read the line for the overall operation switch.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%d ", &(op->op_switch) );
|
|
|
|
// Read the line for the sequential front-end/micro-kernel interface.
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%d ", &(op->front_seq) );
|
|
|
|
op->n_dims = libblis_test_get_n_dims_from_dimset( dimset );
|
|
op->dimset = dimset;
|
|
|
|
if ( op->n_dims > MAX_NUM_DIMENSIONS )
|
|
{
|
|
libblis_test_printf_error( "Detected too many dimensions (%u) in input file to store.\n",
|
|
op->n_dims );
|
|
}
|
|
|
|
//printf( "n_dims = %u\n", op->n_dims );
|
|
|
|
// If there is at least one dimension for the current operation, read the
|
|
// dimension specifications, which encode the actual dimensions or the
|
|
// dimension ratios for each dimension.
|
|
if ( op->n_dims > 0 )
|
|
{
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
|
|
for ( i = 0, p = 0; i < op->n_dims; ++i )
|
|
{
|
|
//printf( "buffer[p]: %s\n", &buffer[p] );
|
|
|
|
// Advance until we hit non-whitespace (ie: the next number).
|
|
for ( ; isspace( buffer[p] ); ++p ) ;
|
|
|
|
//printf( "buffer[p] after: %s\n", &buffer[p] );
|
|
|
|
sscanf( &buffer[p], "%d", &(op->dim_spec[i]) );
|
|
|
|
//printf( "dim[%d] = %d\n", i, op->dim_spec[i] );
|
|
|
|
// Advance until we hit whitespace (ie: the space before the next number).
|
|
for ( ; !isspace( buffer[p] ); ++p ) ;
|
|
}
|
|
}
|
|
|
|
// If there is at least one parameter for the current operation, read the
|
|
// parameter chars, which encode which parameter combinations to test.
|
|
if ( n_params > 0 )
|
|
{
|
|
libblis_test_read_next_line( buffer, input_stream );
|
|
sscanf( buffer, "%s ", temp );
|
|
|
|
op->n_params = strlen( temp );
|
|
if ( op->n_params > MAX_NUM_PARAMETERS )
|
|
{
|
|
libblis_test_printf_error( "Detected too many parameters (%u) in input file.\n",
|
|
op->n_params );
|
|
}
|
|
if ( op->n_params != n_params )
|
|
{
|
|
libblis_test_printf_error( "Number of parameters specified by caller does not match length of parameter string in input file. strlen( temp ) = %u; n_params = %u\n", op->n_params, n_params );
|
|
}
|
|
|
|
strcpy( op->params, temp );
|
|
}
|
|
else
|
|
{
|
|
op->n_params = 0;
|
|
strcpy( op->params, "" );
|
|
}
|
|
|
|
// Initialize the "test done" switch.
|
|
op->test_done = FALSE;
|
|
|
|
// Initialize the parent pointer.
|
|
op->ops = ops;
|
|
|
|
// Disable operation if requested.
|
|
if ( op->op_switch == DISABLE_ALL )
|
|
{
|
|
op->front_seq = DISABLE;
|
|
}
|
|
}
|
|
|
|
|
|
void libblis_test_output_section_overrides( FILE* os, test_ops_t* ops )
|
|
{
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "--- Section overrides ---\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "Utility operations %d\n", ops->util_over );
|
|
libblis_test_fprintf_c( os, "Level-1v operations %d\n", ops->l1v_over );
|
|
libblis_test_fprintf_c( os, "Level-1m operations %d\n", ops->l1m_over );
|
|
libblis_test_fprintf_c( os, "Level-1f operations %d\n", ops->l1f_over );
|
|
libblis_test_fprintf_c( os, "Level-2 operations %d\n", ops->l2_over );
|
|
libblis_test_fprintf_c( os, "Level-3 micro-kernels %d\n", ops->l3ukr_over );
|
|
libblis_test_fprintf_c( os, "Level-3 operations %d\n", ops->l3_over );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf( os, "\n" );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_output_params_struct( FILE* os, test_params_t* params )
|
|
{
|
|
int i;
|
|
//char int_type_size_str[8];
|
|
gint_t int_type_size;
|
|
ind_t im;
|
|
cntx_t cntx_s;
|
|
cntx_t* cntx = &cntx_s;
|
|
|
|
// If bli_info_get_int_type_size() returns 32 or 64, the size is forced.
|
|
// Otherwise, the size is chosen automatically. We query the result of
|
|
// that automatic choice via sizeof(gint_t).
|
|
/*
|
|
if ( bli_info_get_int_type_size() == 32 ||
|
|
bli_info_get_int_type_size() == 64 )
|
|
sprintf( int_type_size_str, "%d", ( int )bli_info_get_int_type_size() );
|
|
else
|
|
sprintf( int_type_size_str, "%d", ( int )sizeof(gint_t) * 8 );
|
|
*/
|
|
if ( bli_info_get_int_type_size() == 32 ||
|
|
bli_info_get_int_type_size() == 64 )
|
|
int_type_size = bli_info_get_int_type_size();
|
|
else
|
|
int_type_size = sizeof(gint_t) * 8;
|
|
|
|
// Output some system parameters.
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "--- BLIS library info -------------------------------------\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "version string %s\n", bli_info_get_version_str() );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "--- BLIS configuration info ---\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "integer type size (bits) %d\n", ( int )int_type_size );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "SIMD number of registers %d\n", ( int )bli_info_get_simd_num_registers() );
|
|
libblis_test_fprintf_c( os, "SIMD size (bytes) %d\n", ( int )bli_info_get_simd_size() );
|
|
libblis_test_fprintf_c( os, "SIMD alignment (bytes) %d\n", ( int )bli_info_get_simd_align_size() );
|
|
libblis_test_fprintf_c( os, "Max stack buffer size (bytes) %d\n", ( int )bli_info_get_stack_buf_max_size() );
|
|
libblis_test_fprintf_c( os, "Page size (bytes) %d\n", ( int )bli_info_get_page_size() );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "memory alignment (bytes) \n" );
|
|
libblis_test_fprintf_c( os, " stack address %d\n", ( int )bli_info_get_stack_buf_align_size() );
|
|
libblis_test_fprintf_c( os, " obj_t address %d\n", ( int )bli_info_get_heap_addr_align_size() );
|
|
libblis_test_fprintf_c( os, " obj_t stride %d\n", ( int )bli_info_get_heap_stride_align_size() );
|
|
libblis_test_fprintf_c( os, " pool block addr %d\n", ( int )bli_info_get_pool_addr_align_size() );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "BLAS compatibility layer \n" );
|
|
libblis_test_fprintf_c( os, " enabled? %d\n", ( int )bli_info_get_enable_blas2blis() );
|
|
libblis_test_fprintf_c( os, " integer type size (bits) %d\n", ( int )bli_info_get_blas2blis_int_type_size() );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "CBLAS compatibility layer \n" );
|
|
libblis_test_fprintf_c( os, " enabled? %d\n", ( int )bli_info_get_enable_cblas() );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "floating-point types s d c z \n" );
|
|
libblis_test_fprintf_c( os, " sizes (bytes) %7u %7u %7u %7u\n", sizeof(float),
|
|
sizeof(double),
|
|
sizeof(scomplex),
|
|
sizeof(dcomplex) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "--- BLIS default implementations ---\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "level-3 implementations s d c z\n" );
|
|
libblis_test_fprintf_c( os, " gemm %7s %7s %7s %7s\n",
|
|
bli_info_get_gemm_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_gemm_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_gemm_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_gemm_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " hemm %7s %7s %7s %7s\n",
|
|
bli_info_get_hemm_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_hemm_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_hemm_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_hemm_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " herk %7s %7s %7s %7s\n",
|
|
bli_info_get_herk_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_herk_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_herk_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_herk_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " her2k %7s %7s %7s %7s\n",
|
|
bli_info_get_her2k_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_her2k_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_her2k_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_her2k_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " symm %7s %7s %7s %7s\n",
|
|
bli_info_get_symm_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_symm_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_symm_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_symm_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " syrk %7s %7s %7s %7s\n",
|
|
bli_info_get_syrk_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_syrk_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_syrk_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_syrk_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " syr2k %7s %7s %7s %7s\n",
|
|
bli_info_get_syr2k_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_syr2k_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_syr2k_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_syr2k_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " trmm %7s %7s %7s %7s\n",
|
|
bli_info_get_trmm_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_trmm_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_trmm_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_trmm_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " trmm3 %7s %7s %7s %7s\n",
|
|
bli_info_get_trmm3_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_trmm3_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_trmm3_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_trmm3_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " trsm %7s %7s %7s %7s\n",
|
|
bli_info_get_trsm_impl_string( BLIS_FLOAT ),
|
|
bli_info_get_trsm_impl_string( BLIS_DOUBLE ),
|
|
bli_info_get_trsm_impl_string( BLIS_SCOMPLEX ),
|
|
bli_info_get_trsm_impl_string( BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
|
|
//bli_ind_disable_all();
|
|
|
|
bli_ind_oper_enable_only( BLIS_GEMM, BLIS_NAT, BLIS_SCOMPLEX );
|
|
bli_ind_oper_enable_only( BLIS_GEMM, BLIS_NAT, BLIS_DCOMPLEX );
|
|
|
|
libblis_test_fprintf_c( os, "--- BLIS native implementation info ---\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, " c z \n" );
|
|
libblis_test_fprintf_c( os, "complex implementation %7s %7s\n",
|
|
bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_SCOMPLEX ),
|
|
bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
|
|
bli_gemmnat_cntx_init( cntx );
|
|
|
|
libblis_test_fprintf_c( os, "level-3 blocksizes s d c z \n" );
|
|
libblis_test_fprintf_c( os, " mc %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MC, cntx ) );
|
|
libblis_test_fprintf_c( os, " kc %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_KC, cntx ) );
|
|
libblis_test_fprintf_c( os, " nc %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_NC, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, " mc maximum %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MC, cntx ) );
|
|
libblis_test_fprintf_c( os, " kc maximum %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_KC, cntx ) );
|
|
libblis_test_fprintf_c( os, " nc maximum %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NC, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, " mr %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MR, cntx ) );
|
|
libblis_test_fprintf_c( os, " nr %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_NR, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, " mr packdim %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MR, cntx ) );
|
|
libblis_test_fprintf_c( os, " nr packdim %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_FLOAT, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DOUBLE, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NR, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "micro-kernel types s d c z\n" );
|
|
libblis_test_fprintf_c( os, " gemm %7s %7s %7s %7s\n",
|
|
bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ),
|
|
bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ),
|
|
bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ),
|
|
bli_info_get_gemm_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " gemmtrsm_l %7s %7s %7s %7s\n",
|
|
bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ),
|
|
bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ),
|
|
bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ),
|
|
bli_info_get_gemmtrsm_l_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " gemmtrsm_u %7s %7s %7s %7s\n",
|
|
bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ),
|
|
bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ),
|
|
bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ),
|
|
bli_info_get_gemmtrsm_u_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " trsm_l %7s %7s %7s %7s\n",
|
|
bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ),
|
|
bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ),
|
|
bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ),
|
|
bli_info_get_trsm_l_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " trsm_u %7s %7s %7s %7s\n",
|
|
bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_FLOAT ),
|
|
bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_DOUBLE ),
|
|
bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_SCOMPLEX ),
|
|
bli_info_get_trsm_u_ukr_impl_string( BLIS_NAT, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
|
|
bli_gemmnat_cntx_finalize( cntx );
|
|
|
|
libblis_test_fprintf_c( os, "--- BLIS induced implementation info ---\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
|
|
for ( im = 0; im < BLIS_NAT; ++im )
|
|
{
|
|
if ( params->ind_enable[ im ] == 0 ) continue;
|
|
|
|
bli_ind_oper_enable_only( BLIS_GEMM, im, BLIS_SCOMPLEX );
|
|
bli_ind_oper_enable_only( BLIS_GEMM, im, BLIS_DCOMPLEX );
|
|
|
|
libblis_test_fprintf_c( os, " c z \n" );
|
|
libblis_test_fprintf_c( os, "complex implementation %7s %7s\n",
|
|
bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_SCOMPLEX ),
|
|
bli_ind_oper_get_avail_impl_string( BLIS_GEMM, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
|
|
bli_gemmind_cntx_init( im, cntx );
|
|
|
|
libblis_test_fprintf_c( os, "level-3 blocksizes c z \n" );
|
|
libblis_test_fprintf_c( os, " mc %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MC, cntx ) );
|
|
libblis_test_fprintf_c( os, " kc %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_KC, cntx ) );
|
|
libblis_test_fprintf_c( os, " nc %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NC, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, " mc maximum %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MC, cntx ) );
|
|
libblis_test_fprintf_c( os, " kc maximum %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_KC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_KC, cntx ) );
|
|
libblis_test_fprintf_c( os, " nc maximum %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NC, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NC, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, " mr %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_MR, cntx ) );
|
|
libblis_test_fprintf_c( os, " nr %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_NR, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, " mr packdim %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_MR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_MR, cntx ) );
|
|
libblis_test_fprintf_c( os, " nr packdim %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_SCOMPLEX, BLIS_NR, cntx ),
|
|
( int )bli_cntx_get_blksz_max_dt( BLIS_DCOMPLEX, BLIS_NR, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "micro-kernel types c z\n" );
|
|
libblis_test_fprintf_c( os, " gemm %7s %7s\n",
|
|
bli_info_get_gemm_ukr_impl_string( im, BLIS_SCOMPLEX ),
|
|
bli_info_get_gemm_ukr_impl_string( im, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " gemmtrsm_l %7s %7s\n",
|
|
bli_info_get_gemmtrsm_l_ukr_impl_string( im, BLIS_SCOMPLEX ),
|
|
bli_info_get_gemmtrsm_l_ukr_impl_string( im, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " gemmtrsm_u %7s %7s\n",
|
|
bli_info_get_gemmtrsm_u_ukr_impl_string( im, BLIS_SCOMPLEX ),
|
|
bli_info_get_gemmtrsm_u_ukr_impl_string( im, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " trsm_l %7s %7s\n",
|
|
bli_info_get_trsm_l_ukr_impl_string( im, BLIS_SCOMPLEX ),
|
|
bli_info_get_trsm_l_ukr_impl_string( im, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, " trsm_u %7s %7s\n",
|
|
bli_info_get_trsm_u_ukr_impl_string( im, BLIS_SCOMPLEX ),
|
|
bli_info_get_trsm_u_ukr_impl_string( im, BLIS_DCOMPLEX ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
|
|
bli_gemmind_cntx_finalize( im, cntx );
|
|
}
|
|
|
|
bli_ind_disable_all();
|
|
|
|
// We use hemv's context because we know it is initialized with all of the fields
|
|
// we will be outputing.
|
|
bli_hemv_cntx_init( cntx );
|
|
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "--- BLIS misc. other info ---\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "level-2 cache blocksizes s d c z \n" );
|
|
libblis_test_fprintf_c( os, " m dimension %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_M2, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_M2, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_M2, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_M2, cntx ) );
|
|
libblis_test_fprintf_c( os, " n dimension %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_N2, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_N2, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_N2, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_N2, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "level-1f fusing factors s d c z \n" );
|
|
libblis_test_fprintf_c( os, " axpyf %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_AF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_AF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_AF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_AF, cntx ) );
|
|
libblis_test_fprintf_c( os, " dotxf %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_DF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_DF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_DF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_DF, cntx ) );
|
|
libblis_test_fprintf_c( os, " dotxaxpyf %7d %7d %7d %7d\n",
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_FLOAT, BLIS_XF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DOUBLE, BLIS_XF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_SCOMPLEX, BLIS_XF, cntx ),
|
|
( int )bli_cntx_get_blksz_def_dt( BLIS_DCOMPLEX, BLIS_XF, cntx ) );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf( os, "\n" );
|
|
|
|
bli_hemv_cntx_finalize( cntx );
|
|
|
|
// Output the contents of the param struct.
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "--- BLIS test suite parameters ----------------------------\n" );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf_c( os, "num repeats per experiment %u\n", params->n_repeats );
|
|
libblis_test_fprintf_c( os, "num matrix storage schemes %u\n", params->n_mstorage );
|
|
libblis_test_fprintf_c( os, "storage[ matrix ] %s\n", params->storage[ BLIS_TEST_MATRIX_OPERAND ] );
|
|
libblis_test_fprintf_c( os, "num vector storage schemes %u\n", params->n_vstorage );
|
|
libblis_test_fprintf_c( os, "storage[ vector ] %s\n", params->storage[ BLIS_TEST_VECTOR_OPERAND ] );
|
|
libblis_test_fprintf_c( os, "mix all storage schemes? %u\n", params->mix_all_storage );
|
|
libblis_test_fprintf_c( os, "general stride spacing %u\n", params->gs_spacing );
|
|
libblis_test_fprintf_c( os, "num datatypes %u\n", params->n_datatypes );
|
|
libblis_test_fprintf_c( os, "datatype[0] %d (%c)\n", params->datatype[0],
|
|
params->datatype_char[0] );
|
|
for( i = 1; i < params->n_datatypes; ++i )
|
|
libblis_test_fprintf_c( os, " [%d] %d (%c)\n", i, params->datatype[i],
|
|
params->datatype_char[i] );
|
|
libblis_test_fprintf_c( os, "problem size: first to test %u\n", params->p_first );
|
|
libblis_test_fprintf_c( os, "problem size: max to test %u\n", params->p_max );
|
|
libblis_test_fprintf_c( os, "problem size increment %u\n", params->p_inc );
|
|
libblis_test_fprintf_c( os, "test induced complex \n" );
|
|
libblis_test_fprintf_c( os, " 3mh? %u\n", params->ind_enable[ BLIS_3MH ] );
|
|
libblis_test_fprintf_c( os, " 3m3? %u\n", params->ind_enable[ BLIS_3M3 ] );
|
|
libblis_test_fprintf_c( os, " 3m2? %u\n", params->ind_enable[ BLIS_3M2 ] );
|
|
libblis_test_fprintf_c( os, " 3m1? %u\n", params->ind_enable[ BLIS_3M1 ] );
|
|
libblis_test_fprintf_c( os, " 4mh? %u\n", params->ind_enable[ BLIS_4MH ] );
|
|
libblis_test_fprintf_c( os, " 4m1b (4mb)? %u\n", params->ind_enable[ BLIS_4M1B ] );
|
|
libblis_test_fprintf_c( os, " 4m1a (4m1)? %u\n", params->ind_enable[ BLIS_4M1A ] );
|
|
libblis_test_fprintf_c( os, "test native complex? %u\n", params->ind_enable[ BLIS_NAT ] );
|
|
libblis_test_fprintf_c( os, "error-checking level %u\n", params->error_checking_level );
|
|
libblis_test_fprintf_c( os, "reaction to failure %c\n", params->reaction_to_failure );
|
|
libblis_test_fprintf_c( os, "output in matlab format? %u\n", params->output_matlab_format );
|
|
libblis_test_fprintf_c( os, "output to stdout AND files? %u\n", params->output_files );
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf( os, "\n" );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_output_op_struct( FILE* os, test_op_t* op, char* op_str )
|
|
{
|
|
dimset_t dimset = op->dimset;
|
|
|
|
libblis_test_fprintf_c( os, "test %s seq front-end? %d\n", op_str, op->front_seq );
|
|
|
|
if ( dimset == BLIS_TEST_DIMS_MNK )
|
|
{
|
|
libblis_test_fprintf_c( os, "%s m n k %d %d %d\n", op_str,
|
|
op->dim_spec[0], op->dim_spec[1], op->dim_spec[2] );
|
|
}
|
|
else if ( dimset == BLIS_TEST_DIMS_MN )
|
|
{
|
|
libblis_test_fprintf_c( os, "%s m n %d %d\n", op_str,
|
|
op->dim_spec[0], op->dim_spec[1] );
|
|
}
|
|
else if ( dimset == BLIS_TEST_DIMS_MK )
|
|
{
|
|
libblis_test_fprintf_c( os, "%s m k %d %d\n", op_str,
|
|
op->dim_spec[0], op->dim_spec[1] );
|
|
}
|
|
else if ( dimset == BLIS_TEST_DIMS_M ||
|
|
dimset == BLIS_TEST_DIMS_MF )
|
|
{
|
|
libblis_test_fprintf_c( os, "%s m %d\n", op_str,
|
|
op->dim_spec[0] );
|
|
}
|
|
else if ( dimset == BLIS_TEST_DIMS_K )
|
|
{
|
|
libblis_test_fprintf_c( os, "%s k %d\n", op_str,
|
|
op->dim_spec[0] );
|
|
}
|
|
else if ( dimset == BLIS_TEST_NO_DIMS )
|
|
{
|
|
// Do nothing.
|
|
}
|
|
else
|
|
{
|
|
libblis_test_printf_error( "Invalid dimension combination.\n" );
|
|
}
|
|
|
|
if ( op->n_params > 0 )
|
|
libblis_test_fprintf_c( os, "%s operand params %s\n", op_str, op->params );
|
|
else
|
|
libblis_test_fprintf_c( os, "%s operand params %s\n", op_str, "(none)" );
|
|
|
|
libblis_test_fprintf_c( os, "\n" );
|
|
libblis_test_fprintf( os, "\n" );
|
|
}
|
|
|
|
|
|
|
|
char* libblis_test_get_string_for_result( double resid,
|
|
num_t dt,
|
|
thresh_t* thresh )
|
|
{
|
|
char* r_val;
|
|
|
|
if ( resid > thresh[dt].failwarn ) r_val = libblis_test_fail_string;
|
|
else if ( resid > thresh[dt].warnpass ) r_val = libblis_test_warn_string;
|
|
else r_val = libblis_test_pass_string;
|
|
|
|
return r_val;
|
|
}
|
|
|
|
|
|
|
|
param_t libblis_test_get_param_type_for_char( char p_type )
|
|
{
|
|
param_t r_val;
|
|
|
|
if ( p_type == 's' ) r_val = BLIS_TEST_PARAM_SIDE;
|
|
else if ( p_type == 'u' ) r_val = BLIS_TEST_PARAM_UPLO;
|
|
else if ( p_type == 'e' ) r_val = BLIS_TEST_PARAM_UPLODE;
|
|
else if ( p_type == 'h' ) r_val = BLIS_TEST_PARAM_TRANS;
|
|
else if ( p_type == 'c' ) r_val = BLIS_TEST_PARAM_CONJ;
|
|
else if ( p_type == 'd' ) r_val = BLIS_TEST_PARAM_DIAG;
|
|
else
|
|
{
|
|
r_val = 0;
|
|
libblis_test_printf_error( "Invalid parameter character.\n" );
|
|
}
|
|
|
|
return r_val;
|
|
}
|
|
|
|
|
|
|
|
operand_t libblis_test_get_operand_type_for_char( char o_type )
|
|
{
|
|
operand_t r_val;
|
|
|
|
if ( o_type == 'm' ) r_val = BLIS_TEST_MATRIX_OPERAND;
|
|
else if ( o_type == 'v' ) r_val = BLIS_TEST_VECTOR_OPERAND;
|
|
else
|
|
{
|
|
r_val = 0;
|
|
libblis_test_printf_error( "Invalid operand character.\n" );
|
|
}
|
|
|
|
return r_val;
|
|
}
|
|
|
|
|
|
|
|
unsigned int libblis_test_get_n_dims_from_dimset( dimset_t dimset )
|
|
{
|
|
unsigned int n_dims;
|
|
|
|
if ( dimset == BLIS_TEST_DIMS_MNK ) n_dims = 3;
|
|
else if ( dimset == BLIS_TEST_DIMS_MN ) n_dims = 2;
|
|
else if ( dimset == BLIS_TEST_DIMS_MK ) n_dims = 2;
|
|
else if ( dimset == BLIS_TEST_DIMS_M ) n_dims = 1;
|
|
else if ( dimset == BLIS_TEST_DIMS_MF ) n_dims = 1;
|
|
else if ( dimset == BLIS_TEST_DIMS_K ) n_dims = 1;
|
|
else if ( dimset == BLIS_TEST_NO_DIMS ) n_dims = 0;
|
|
else
|
|
{
|
|
n_dims = 0;
|
|
libblis_test_printf_error( "Invalid dimension combination.\n" );
|
|
}
|
|
|
|
return n_dims;
|
|
}
|
|
|
|
|
|
|
|
unsigned int libblis_test_get_n_dims_from_string( char* dims_str )
|
|
{
|
|
unsigned int n_dims;
|
|
char* cp;
|
|
|
|
cp = dims_str;
|
|
|
|
for ( n_dims = 0; *cp != '\0'; ++n_dims )
|
|
{
|
|
//printf( "n_dims = %u\n", n_dims );
|
|
while ( isspace( *cp ) )
|
|
{
|
|
//printf( "current char: _%c_", *cp );
|
|
++cp;
|
|
}
|
|
|
|
while ( isdigit( *cp ) )
|
|
{
|
|
//printf( "current char: _%c_", *cp );
|
|
++cp;
|
|
}
|
|
}
|
|
//printf( "n_dims finally = %u\n", n_dims );
|
|
|
|
return n_dims;
|
|
}
|
|
|
|
|
|
|
|
dim_t libblis_test_get_dim_from_prob_size( int dim_spec,
|
|
unsigned int p_size )
|
|
{
|
|
dim_t dim;
|
|
|
|
if ( dim_spec < 0 ) dim = p_size / bli_abs(dim_spec);
|
|
else dim = dim_spec;
|
|
|
|
return dim;
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_fill_param_strings( char* p_spec_str,
|
|
char** chars_for_param,
|
|
unsigned int n_params,
|
|
unsigned int n_param_combos,
|
|
char** pc_str )
|
|
{
|
|
unsigned int pci, pi, i;
|
|
unsigned int* counter;
|
|
unsigned int* n_vals_for_param;
|
|
|
|
// Allocate an array that will store the number of parameter values
|
|
// for each parameter.
|
|
n_vals_for_param = ( unsigned int* ) malloc( n_params * sizeof( unsigned int ) );
|
|
|
|
// Fill n_vals_for_param[i] with the number of parameter values (chars)
|
|
// in chars_for_param[i] (this is simply the string length).
|
|
for ( i = 0; i < n_params; ++i )
|
|
{
|
|
if ( p_spec_str[i] == '?' ) n_vals_for_param[i] = strlen( chars_for_param[i] );
|
|
else n_vals_for_param[i] = 1;
|
|
}
|
|
|
|
// Allocate an array with one digit per parameter. We will use
|
|
// this array to keep track of our progress as we canonically move
|
|
// though all possible parameter combinations.
|
|
counter = ( unsigned int* ) malloc( n_params * sizeof( unsigned int ) );
|
|
|
|
// Initialize all values in c to zero.
|
|
for ( i = 0; i < n_params; ++i ) counter[i] = 0;
|
|
|
|
for ( pci = 0; pci < n_param_combos; ++pci )
|
|
{
|
|
// Iterate backwards through each parameter string we create, since we
|
|
// want to form (for example, if the parameters are transa and conjx:
|
|
// (1) nn, (2) nc, (3) cn, (4) cc, (5) tn, (6) tc, (7) hn, (8) hc.
|
|
for ( i = 0, pi = n_params - 1; i < n_params; --pi, ++i )
|
|
{
|
|
// If the current parameter character, p_spec_str[pi] is fixed (ie: if
|
|
// it is not '?'), then just copy it into the parameter combination
|
|
// string. Otherwise, map the current integer value in c to the
|
|
// corresponding character in char_for_param[pi].
|
|
if ( p_spec_str[pi] != '?' )
|
|
pc_str[pci][pi] = p_spec_str[pi];
|
|
else
|
|
pc_str[pci][pi] = chars_for_param[ pi ][ counter[pi] ];
|
|
}
|
|
|
|
// Terminate the current parameter combination string.
|
|
pc_str[pci][n_params] = '\0';
|
|
|
|
// Only try to increment/carryover if this is NOT the last param
|
|
// combo.
|
|
if ( pci < n_param_combos - 1 )
|
|
{
|
|
// Increment the least-most significant counter.
|
|
counter[ n_params - 1 ]++;
|
|
|
|
// Perform "carryover" if needed.
|
|
carryover( &counter[ n_params - 1 ],
|
|
&n_vals_for_param[ n_params - 1 ],
|
|
n_params );
|
|
}
|
|
}
|
|
|
|
// Free the temporary arrays.
|
|
free( counter );
|
|
|
|
// Free the array holding the number of parameter values for each
|
|
// parameter.
|
|
free( n_vals_for_param );
|
|
}
|
|
|
|
|
|
|
|
void carryover( unsigned int* c,
|
|
unsigned int* n_vals_for_param,
|
|
unsigned int n_params )
|
|
{
|
|
if ( n_params == 1 ) return;
|
|
else
|
|
{
|
|
if ( *c == *n_vals_for_param )
|
|
{
|
|
*c = 0;
|
|
*(c-1) += 1;
|
|
carryover( c-1, n_vals_for_param-1, n_params-1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_op_driver( test_params_t* params,
|
|
test_op_t* op,
|
|
iface_t iface,
|
|
char* op_str,
|
|
char* p_types,
|
|
char* o_types,
|
|
thresh_t* thresh,
|
|
void (*f_exp) (test_params_t*, // params struct
|
|
test_op_t*, // op struct
|
|
iface_t, // iface
|
|
num_t, // datatype (current datatype)
|
|
char*, // pc_str (current param string)
|
|
char*, // sc_str (current storage string)
|
|
unsigned int, // p_cur (current problem size)
|
|
double*, // perf
|
|
double* ) ) // residual
|
|
{
|
|
unsigned int n_mstorage = params->n_mstorage;
|
|
unsigned int n_vstorage = params->n_vstorage;
|
|
unsigned int n_datatypes = params->n_datatypes;
|
|
unsigned int p_first = params->p_first;
|
|
unsigned int p_max = params->p_max;
|
|
unsigned int p_inc = params->p_inc;
|
|
unsigned int mix_all_storage = params->mix_all_storage;
|
|
unsigned int reaction_to_failure = params->reaction_to_failure;
|
|
|
|
num_t datatype;
|
|
char dt_char;
|
|
|
|
char* p_spec_str;
|
|
unsigned int n_params;
|
|
char** chars_for_param;
|
|
unsigned int n_param_combos;
|
|
char** pc_str;
|
|
|
|
char s_spec_str[ MAX_NUM_OPERANDS + 1 ];
|
|
unsigned int n_operands;
|
|
char** chars_for_storage;
|
|
unsigned int n_store_combos;
|
|
char** sc_str;
|
|
|
|
unsigned int p_cur, pi;
|
|
unsigned int dt, indi, pci, sci, i, j, o;
|
|
|
|
double perf, resid;
|
|
char* pass_str;
|
|
char* ind_str;
|
|
char blank_str[32];
|
|
char funcname_str[64];
|
|
char dims_str[64];
|
|
char label_str[128];
|
|
unsigned int n_spaces;
|
|
unsigned int n_dims_print;
|
|
|
|
FILE* output_stream = NULL;
|
|
|
|
|
|
// If output to files was requested, attempt to open a file stream.
|
|
if ( params->output_files )
|
|
libblis_test_fopen_ofile( op_str, iface, &output_stream );
|
|
|
|
// Set the error-checking level according to what was specified in the
|
|
// input file.
|
|
if ( params->error_checking_level == 0 )
|
|
bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING );
|
|
else
|
|
bli_error_checking_level_set( BLIS_FULL_ERROR_CHECKING );
|
|
|
|
// Obtain the parameter specification (filter) string.
|
|
p_spec_str = op->params;
|
|
|
|
// Figure out how many parameters we have.
|
|
n_params = strlen( p_types );
|
|
|
|
if ( strlen( p_types ) != strlen( p_spec_str) )
|
|
{
|
|
libblis_test_printf_error( "Parameter specification string from input file does not match length of p_types string.\n" );
|
|
}
|
|
|
|
// Allocate an array that stores pointers to the sets of possible parameter
|
|
// chars for each parameter.
|
|
chars_for_param = ( char** ) malloc( n_params * sizeof( char* ) );
|
|
|
|
// Set the values in chars_for_param to the appropriate string addresses.
|
|
for ( i = 0; i < n_params; ++i )
|
|
{
|
|
param_t param_type = libblis_test_get_param_type_for_char( p_types[i] );
|
|
chars_for_param[i] = libblis_test_param_chars[ param_type ];
|
|
}
|
|
|
|
// Compute the total number of parameter combinations to test (which is
|
|
// simply the product of the string lengths of chars_for_param[i].
|
|
for ( i = 0, n_param_combos = 1; i < n_params; ++i )
|
|
{
|
|
if ( p_spec_str[i] == '?' )
|
|
n_param_combos *= strlen( chars_for_param[i] );
|
|
}
|
|
|
|
// Allocate an array of parameter combination strings, one for each
|
|
// parameter combination that needs to be tested.
|
|
pc_str = ( char** ) malloc( n_param_combos * sizeof( char* ) );
|
|
for ( i = 0; i < n_param_combos; ++i )
|
|
pc_str[i] = ( char* ) malloc( ( n_params + 1 ) * sizeof( char ) );
|
|
|
|
// Fill the parameter combination strings in pc_str with the parameter
|
|
// combinations called for by the parameter string p_spec_str.
|
|
libblis_test_fill_param_strings( p_spec_str,
|
|
chars_for_param,
|
|
n_params,
|
|
n_param_combos,
|
|
pc_str );
|
|
|
|
|
|
|
|
// Figure out how many operands we have.
|
|
n_operands = strlen( o_types );
|
|
|
|
// If we are testing a micro-kernel, unconditionally disable the
|
|
// "mix all storage" option.
|
|
if ( iface == BLIS_TEST_SEQ_UKERNEL )
|
|
mix_all_storage = DISABLE;
|
|
|
|
// Determine the total number of storage schemes.
|
|
if ( mix_all_storage )
|
|
{
|
|
// Fill storage specification string with wildcard chars.
|
|
for ( i = 0; i < n_operands; ++i )
|
|
s_spec_str[i] = '?';
|
|
s_spec_str[i] = '\0';
|
|
|
|
// Allocate an array that stores pointers to the sets of possible
|
|
// storage chars for each operand.
|
|
chars_for_storage = ( char** ) malloc( n_operands * sizeof( char* ) );
|
|
|
|
// Set the values in chars_for_storage to the address of the string
|
|
// that holds the storage chars.
|
|
for ( i = 0; i < n_operands; ++i )
|
|
{
|
|
operand_t operand_type = libblis_test_get_operand_type_for_char( o_types[i] );
|
|
chars_for_storage[i] = libblis_test_store_chars[ operand_type ];
|
|
}
|
|
|
|
// Compute the total number of storage combinations to test (which is
|
|
// simply the product of the string lengths of chars_for_storage[i].
|
|
for ( i = 0, n_store_combos = 1; i < n_operands; ++i )
|
|
{
|
|
if ( s_spec_str[i] == '?' )
|
|
n_store_combos *= strlen( chars_for_storage[i] );
|
|
}
|
|
|
|
// Allocate an array of storage combination strings, one for each
|
|
// storage combination that needs to be tested.
|
|
sc_str = ( char** ) malloc( n_store_combos * sizeof( char* ) );
|
|
for ( sci = 0; sci < n_store_combos; ++sci )
|
|
sc_str[sci] = ( char* ) malloc( ( n_operands + 1 ) * sizeof( char ) );
|
|
|
|
|
|
// Fill the storage combination strings in sc_str with the storage
|
|
// combinations called for by the storage string p_spec_str.
|
|
libblis_test_fill_param_strings( s_spec_str,
|
|
chars_for_storage,
|
|
n_operands,
|
|
n_store_combos,
|
|
sc_str );
|
|
}
|
|
else // if ( !mix_all_storage )
|
|
{
|
|
// Only run combinations where all operands of either type (matrices
|
|
// or vectors) are stored in one storage scheme or another (no mixing
|
|
// of schemes within the same operand type).
|
|
unsigned int n_mat_operands = 0;
|
|
unsigned int n_vec_operands = 0;
|
|
|
|
for ( o = 0; o < n_operands; ++o )
|
|
{
|
|
operand_t operand_type
|
|
= libblis_test_get_operand_type_for_char( o_types[o] );
|
|
if ( operand_type == BLIS_TEST_MATRIX_OPERAND ) ++n_mat_operands;
|
|
else if ( operand_type == BLIS_TEST_VECTOR_OPERAND ) ++n_vec_operands;
|
|
}
|
|
|
|
// We compute the total number of storage combinations based on whether
|
|
// the current operation has only matrix operands, only vector operands,
|
|
// or both.
|
|
if ( n_vec_operands == 0 )
|
|
{
|
|
n_store_combos = n_mstorage;
|
|
n_vstorage = 1;
|
|
}
|
|
else if ( n_mat_operands == 0 )
|
|
{
|
|
n_store_combos = n_vstorage;
|
|
n_mstorage = 1;
|
|
}
|
|
else
|
|
{
|
|
n_store_combos = n_mstorage * n_vstorage;
|
|
}
|
|
|
|
sc_str = ( char** ) malloc( n_store_combos * sizeof( char* ) );
|
|
|
|
for ( j = 0; j < n_mstorage; ++j )
|
|
{
|
|
for ( i = 0; i < n_vstorage; ++i )
|
|
{
|
|
sci = j*n_vstorage + i;
|
|
|
|
sc_str[ sci ]
|
|
= ( char* ) malloc( ( n_operands + 1 ) * sizeof( char ) );
|
|
|
|
for ( o = 0; o < n_operands; ++o )
|
|
{
|
|
unsigned int ij;
|
|
operand_t operand_type
|
|
= libblis_test_get_operand_type_for_char( o_types[o] );
|
|
|
|
if ( operand_type == BLIS_TEST_MATRIX_OPERAND ) ij = j;
|
|
else ij = i;
|
|
|
|
sc_str[sci][o] = params->storage[ operand_type ][ij];
|
|
}
|
|
sc_str[sci][n_operands] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Output a heading and the contents of the op struct.
|
|
libblis_test_fprintf_c( stdout, "--- %s ---\n", op_str );
|
|
libblis_test_fprintf_c( stdout, "\n" );
|
|
libblis_test_output_op_struct( stdout, op, op_str );
|
|
|
|
// Also output to a matlab file if requested (and successfully opened).
|
|
if ( output_stream )
|
|
{
|
|
// For file output, we also include the contents of the global
|
|
// parameter struct. We do this per operation so that the parameters
|
|
// are included in each file, whereas we only output it once to
|
|
// stdout (at the end of libblis_test_read_parameter_file()).
|
|
libblis_test_output_params_struct( output_stream, params );
|
|
|
|
libblis_test_fprintf_c( output_stream, "--- %s ---\n", op_str );
|
|
libblis_test_fprintf_c( output_stream, "\n" );
|
|
libblis_test_output_op_struct( output_stream, op, op_str );
|
|
}
|
|
|
|
|
|
// Loop over the requested storage schemes.
|
|
for ( sci = 0; sci < n_store_combos; ++sci )
|
|
{
|
|
// Loop over the requested datatypes.
|
|
for ( dt = 0; dt < n_datatypes; ++dt )
|
|
{
|
|
datatype = params->datatype[dt];
|
|
dt_char = params->datatype_char[dt];
|
|
|
|
// Build a commented column label string.
|
|
libblis_test_build_col_labels_string( params, op, label_str );
|
|
|
|
// Output the column label string.
|
|
libblis_test_fprintf( stdout, "%s\n", label_str );
|
|
|
|
// Also output to a matlab file if requested (and successfully
|
|
// opened).
|
|
if ( output_stream )
|
|
libblis_test_fprintf( output_stream, "%s\n", label_str );
|
|
|
|
// Start by assuming we will only test native execution.
|
|
ind_t ind_first = BLIS_NAT;
|
|
dim_t ind_last = BLIS_NAT;
|
|
|
|
// If the operation is level-3, and the datatype is complex,
|
|
// then we iterate over all induced methods.
|
|
if ( bli_opid_is_level3( op->opid ) &&
|
|
bli_is_complex( datatype ) ) ind_first = 0;
|
|
|
|
// Loop over induced methods (or just BLIS_NAT).
|
|
for ( indi = ind_first; indi <= ind_last; ++indi )
|
|
{
|
|
// If the current induced method is native execution, OR
|
|
// if the current induced method is implemented (for the
|
|
// operation being tested) AND it was requested, then we
|
|
// enable ONLY that method and proceed. Otherwise, we
|
|
// skip the current method and go to the next method.
|
|
if ( indi == BLIS_NAT ) { ; }
|
|
else if ( bli_ind_oper_is_impl( op->opid, indi ) &&
|
|
params->ind_enable[ indi ] == 1 ) { ; }
|
|
else { continue; }
|
|
|
|
bli_ind_oper_enable_only( op->opid, indi, datatype );
|
|
|
|
// Query the implementation string associated with the
|
|
// current operation and datatype. If the operation is
|
|
// not level-3, we will always get back the native string.
|
|
ind_str = bli_ind_oper_get_avail_impl_string( op->opid, datatype );
|
|
|
|
// Loop over the requested parameter combinations.
|
|
for ( pci = 0; pci < n_param_combos; ++pci )
|
|
{
|
|
// Loop over the requested problem sizes.
|
|
for ( p_cur = p_first, pi = 1; p_cur <= p_max; p_cur += p_inc, ++pi )
|
|
{
|
|
f_exp( params,
|
|
op,
|
|
iface,
|
|
datatype,
|
|
pc_str[pci],
|
|
sc_str[sci],
|
|
p_cur,
|
|
&perf, &resid );
|
|
|
|
// Remove the sign of the residual, if there is one.
|
|
resid = bli_fabs( resid );
|
|
if ( resid == -0.0 ) resid = 0.0;
|
|
|
|
// Query the string corresponding to the residual's
|
|
// position relative to the thresholds.
|
|
pass_str = libblis_test_get_string_for_result( resid,
|
|
datatype,
|
|
thresh );
|
|
|
|
// Build a string unique to the operation, datatype,
|
|
// parameter combination, and storage combination being
|
|
// tested.
|
|
libblis_test_build_function_string( BLIS_FILEDATA_PREFIX_STR,
|
|
indi,
|
|
ind_str,
|
|
op_str,
|
|
dt_char,
|
|
n_param_combos,
|
|
pc_str[pci],
|
|
sc_str[sci],
|
|
funcname_str );
|
|
|
|
// Compute the number of spaces we have left to fill given
|
|
// length of our operation's name.
|
|
n_spaces = MAX_FUNC_STRING_LENGTH - strlen( funcname_str );
|
|
fill_string_with_n_spaces( blank_str, n_spaces );
|
|
|
|
// Print all dimensions to a single string.
|
|
libblis_test_build_dims_string( op, p_cur, dims_str );
|
|
|
|
// Count the number of dimensions that were printed to the string.
|
|
n_dims_print = libblis_test_get_n_dims_from_string( dims_str );
|
|
|
|
// Output the results of the test. Use matlab format if requested.
|
|
if ( params->output_matlab_format )
|
|
{
|
|
libblis_test_fprintf( stdout,
|
|
"%s%s( %3u, 1:%u ) = [%s %7.3lf %8.2le ]; %c %s\n",
|
|
funcname_str, blank_str, pi, n_dims_print + 2,
|
|
dims_str, perf, resid,
|
|
OUTPUT_COMMENT_CHAR,
|
|
pass_str );
|
|
|
|
// Also output to a file if requested (and successfully opened).
|
|
if ( output_stream )
|
|
libblis_test_fprintf( output_stream,
|
|
"%s%s( %3u, 1:%u ) = [%s %7.3lf %8.2le ]; %c %s\n",
|
|
funcname_str, blank_str, pi, n_dims_print + 2,
|
|
dims_str, perf, resid,
|
|
OUTPUT_COMMENT_CHAR,
|
|
pass_str );
|
|
}
|
|
else
|
|
{
|
|
libblis_test_fprintf( stdout,
|
|
"%s%s %s %7.3lf %8.2le %s\n",
|
|
funcname_str, blank_str,
|
|
dims_str, perf, resid,
|
|
pass_str );
|
|
|
|
// Also output to a file if requested (and successfully opened).
|
|
if ( output_stream )
|
|
libblis_test_fprintf( output_stream,
|
|
"%s%s %s %7.3lf %8.2le %s\n",
|
|
funcname_str, blank_str,
|
|
dims_str, perf, resid,
|
|
pass_str );
|
|
}
|
|
|
|
// If we need to check whether to do something on failure,
|
|
// do so now.
|
|
if ( reaction_to_failure == ON_FAILURE_SLEEP_CHAR )
|
|
{
|
|
if ( strstr( pass_str, BLIS_TEST_FAIL_STRING ) == pass_str )
|
|
libblis_test_sleep();
|
|
}
|
|
else if ( reaction_to_failure == ON_FAILURE_ABORT_CHAR )
|
|
{
|
|
if ( strstr( pass_str, BLIS_TEST_FAIL_STRING ) == pass_str )
|
|
libblis_test_abort();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
libblis_test_fprintf( stdout, "\n" );
|
|
|
|
if ( output_stream )
|
|
libblis_test_fprintf( output_stream, "\n" );
|
|
}
|
|
}
|
|
|
|
|
|
// Free the array that stored pointers to the sets of possible parameter
|
|
// chars for each parameter.
|
|
free( chars_for_param );
|
|
|
|
// Free the parameter combination strings and then the master pointer.
|
|
for ( pci = 0; pci < n_param_combos; ++pci )
|
|
free( pc_str[pci] );
|
|
free( pc_str );
|
|
|
|
// Free the storage combination strings and then the master pointer.
|
|
for ( sci = 0; sci < n_store_combos; ++sci )
|
|
free( sc_str[sci] );
|
|
free( sc_str );
|
|
|
|
|
|
// If the file was opened (successfully), close the output stream.
|
|
if ( output_stream )
|
|
libblis_test_fclose_ofile( output_stream );
|
|
|
|
|
|
// Mark this operation as done.
|
|
op->test_done = TRUE;
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_build_function_string( char* prefix_str,
|
|
ind_t method,
|
|
char* ind_str,
|
|
char* op_str,
|
|
char dt_char,
|
|
unsigned int n_param_combos,
|
|
char* pc_str,
|
|
char* sc_str,
|
|
char* funcname_str )
|
|
{
|
|
sprintf( funcname_str, "%s_%c%s", prefix_str, dt_char, op_str );
|
|
|
|
// If the method is non-native (ie: induced), append a string
|
|
// identifying the induced method.
|
|
if ( method != BLIS_NAT )
|
|
sprintf( &funcname_str[strlen(funcname_str)], "%s", ind_str );
|
|
|
|
// We check the string length of pc_str in case the user is running an
|
|
// operation that has parameters (and thus generally more than one
|
|
// parameter combination), but has fixed all parameters in the input
|
|
// file, which would result in n_param_combos to equal one. This way,
|
|
// the function string contains the parameter string associated with
|
|
// the parameters that were fixed.
|
|
if ( n_param_combos > 1 || strlen(pc_str) > 0 )
|
|
sprintf( &funcname_str[strlen(funcname_str)], "_%s_%s", pc_str, sc_str );
|
|
else
|
|
sprintf( &funcname_str[strlen(funcname_str)], "_%s", sc_str );
|
|
|
|
if ( strlen( funcname_str ) > MAX_FUNC_STRING_LENGTH )
|
|
libblis_test_printf_error( "Function name string length (%d) exceeds maximum (%d).\n",
|
|
strlen( funcname_str ), MAX_FUNC_STRING_LENGTH );
|
|
|
|
}
|
|
|
|
|
|
void libblis_test_build_dims_string( test_op_t* op,
|
|
dim_t p_cur,
|
|
char* dims_str )
|
|
{
|
|
unsigned int i;
|
|
|
|
// For level-1f experiments with fusing factors, we grab the fusing
|
|
// factor from the op struct. We do something similar for micro-kernel
|
|
// calls.
|
|
if ( op->dimset == BLIS_TEST_DIMS_MF )
|
|
{
|
|
//sprintf( &dims_str[strlen(dims_str)], " %5u %5u",
|
|
sprintf( dims_str, " %5u %5u",
|
|
( unsigned int )
|
|
libblis_test_get_dim_from_prob_size( op->dim_spec[0],
|
|
p_cur ),
|
|
( unsigned int ) op->dim_aux[0] );
|
|
}
|
|
else if ( op->dimset == BLIS_TEST_DIMS_K )
|
|
{
|
|
//sprintf( &dims_str[strlen(dims_str)], " %5u %5u %5u",
|
|
sprintf( dims_str, " %5u %5u %5u",
|
|
( unsigned int ) op->dim_aux[0],
|
|
( unsigned int ) op->dim_aux[1],
|
|
( unsigned int )
|
|
libblis_test_get_dim_from_prob_size( op->dim_spec[0],
|
|
p_cur ) );
|
|
}
|
|
else if ( op->dimset == BLIS_TEST_NO_DIMS )
|
|
{
|
|
//sprintf( &dims_str[strlen(dims_str)], " %5u %5u",
|
|
sprintf( dims_str, " %5u %5u",
|
|
( unsigned int ) op->dim_aux[0],
|
|
( unsigned int ) op->dim_aux[1] );
|
|
}
|
|
else // For all other operations, we just use the dim_spec[] values
|
|
// and the current problem size.
|
|
{
|
|
// Initialize the string as empty.
|
|
sprintf( dims_str, "%s", "" );
|
|
|
|
// Print all dimensions to a single string.
|
|
for ( i = 0; i < op->n_dims; ++i )
|
|
{
|
|
sprintf( &dims_str[strlen(dims_str)], " %5u",
|
|
( unsigned int )
|
|
libblis_test_get_dim_from_prob_size( op->dim_spec[i],
|
|
p_cur ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// % dtoper_params_storage m n k gflops resid result
|
|
void libblis_test_build_col_labels_string( test_params_t* params, test_op_t* op, char* l_str )
|
|
{
|
|
unsigned int n_spaces;
|
|
char blank_str[64];
|
|
|
|
strcpy( l_str, "" );
|
|
|
|
if ( op->n_params > 0 )
|
|
{
|
|
sprintf( &l_str[strlen(l_str)], "%c %s_%s", OUTPUT_COMMENT_CHAR,
|
|
BLIS_FILEDATA_PREFIX_STR,
|
|
"<dt><op>_<params>_<stor>" );
|
|
}
|
|
else // ( n_params == 0 )
|
|
{
|
|
sprintf( &l_str[strlen(l_str)], "%c %s_%s", OUTPUT_COMMENT_CHAR,
|
|
BLIS_FILEDATA_PREFIX_STR,
|
|
"<dt><op>_<stor> " );
|
|
}
|
|
|
|
if ( params->output_matlab_format ) n_spaces = 11;
|
|
else n_spaces = 1;
|
|
|
|
fill_string_with_n_spaces( blank_str, n_spaces );
|
|
|
|
sprintf( &l_str[strlen(l_str)], "%s", blank_str );
|
|
|
|
if ( op->dimset == BLIS_TEST_DIMS_MNK ||
|
|
op->dimset == BLIS_TEST_DIMS_MN ||
|
|
op->dimset == BLIS_TEST_DIMS_MK ||
|
|
op->dimset == BLIS_TEST_DIMS_M ||
|
|
op->dimset == BLIS_TEST_DIMS_K ||
|
|
op->dimset == BLIS_TEST_DIMS_MF ||
|
|
op->dimset == BLIS_TEST_NO_DIMS )
|
|
sprintf( &l_str[strlen(l_str)], " %5s", "m" );
|
|
|
|
if ( op->dimset == BLIS_TEST_DIMS_MNK ||
|
|
op->dimset == BLIS_TEST_DIMS_MN ||
|
|
op->dimset == BLIS_TEST_DIMS_K ||
|
|
op->dimset == BLIS_TEST_DIMS_MF ||
|
|
op->dimset == BLIS_TEST_NO_DIMS )
|
|
sprintf( &l_str[strlen(l_str)], " %5s", "n" );
|
|
|
|
if ( op->dimset == BLIS_TEST_DIMS_MNK ||
|
|
op->dimset == BLIS_TEST_DIMS_MK ||
|
|
op->dimset == BLIS_TEST_DIMS_K )
|
|
sprintf( &l_str[strlen(l_str)], " %5s", "k" );
|
|
|
|
sprintf( &l_str[strlen(l_str)], "%s", " gflops resid result" );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_build_filename_string( char* prefix_str,
|
|
char* op_str,
|
|
char* funcname_str )
|
|
{
|
|
sprintf( funcname_str, "%s_%s.m", prefix_str, op_str );
|
|
}
|
|
|
|
|
|
|
|
void fill_string_with_n_spaces( char* str, unsigned int n_spaces )
|
|
{
|
|
unsigned int i;
|
|
|
|
// Initialze to empty string in case n_spaces == 0.
|
|
sprintf( str, "%s", "" );
|
|
|
|
for ( i = 0; i < n_spaces; ++i )
|
|
sprintf( &str[i], " " );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_mobj_create( test_params_t* params, num_t dt, trans_t trans, char storage, dim_t m, dim_t n, obj_t* a )
|
|
{
|
|
dim_t gs = params->gs_spacing;
|
|
dim_t m_trans = m;
|
|
dim_t n_trans = n;
|
|
dim_t rs_g;
|
|
dim_t cs_g;
|
|
|
|
// Apply the trans parameter to the dimensions (if needed).
|
|
bli_set_dims_with_trans( trans, m, n, m_trans, n_trans );
|
|
|
|
// In case of general strides, use the general stride spacing specified by the
|
|
// user to create strides with a column-major tilt.
|
|
rs_g = gs * 1;
|
|
cs_g = gs * m_trans;
|
|
|
|
if ( storage == 'c' ) bli_obj_create( dt, m_trans, n_trans, 0, 0, a );
|
|
else if ( storage == 'r' ) bli_obj_create( dt, m_trans, n_trans, n_trans, 1, a );
|
|
else if ( storage == 'g' ) bli_obj_create( dt, m_trans, n_trans, rs_g, cs_g, a );
|
|
else
|
|
{
|
|
libblis_test_printf_error( "Invalid storage character: %c\n", storage );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_pobj_create( bszid_t bmult_id_m, bszid_t bmult_id_n, invdiag_t inv_diag, pack_t pack_schema, packbuf_t pack_buf, obj_t* a, obj_t* p, cntx_t* cntx )
|
|
{
|
|
// Start with making p and alias to a.
|
|
bli_obj_alias_to( *a, *p );
|
|
|
|
// Then initialize p appropriately for packing.
|
|
bli_packm_init_pack( inv_diag,
|
|
pack_schema,
|
|
BLIS_PACK_FWD_IF_UPPER,
|
|
BLIS_PACK_FWD_IF_LOWER,
|
|
pack_buf,
|
|
bmult_id_m,
|
|
bmult_id_n,
|
|
a,
|
|
p,
|
|
cntx );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_vobj_create( test_params_t* params, num_t dt, char storage, dim_t m, obj_t* x )
|
|
{
|
|
dim_t gs = params->gs_spacing;
|
|
|
|
// Column vector (unit stride)
|
|
if ( storage == 'c' ) bli_obj_create( dt, m, 1, 1, m, x );
|
|
// Row vector (unit stride)
|
|
else if ( storage == 'r' ) bli_obj_create( dt, 1, m, m, 1, x );
|
|
// Column vector (non-unit stride)
|
|
else if ( storage == 'j' ) bli_obj_create( dt, m, 1, gs, gs*m, x );
|
|
// Row vector (non-unit stride)
|
|
else if ( storage == 'i' ) bli_obj_create( dt, 1, m, gs*m, gs, x );
|
|
else
|
|
{
|
|
libblis_test_printf_error( "Invalid storage character: %c\n", storage );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_init_strings( void )
|
|
{
|
|
strcpy( libblis_test_pass_string, BLIS_TEST_PASS_STRING );
|
|
strcpy( libblis_test_warn_string, BLIS_TEST_WARN_STRING );
|
|
strcpy( libblis_test_fail_string, BLIS_TEST_FAIL_STRING );
|
|
|
|
strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_SIDE], BLIS_TEST_PARAM_SIDE_CHARS );
|
|
strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_UPLO], BLIS_TEST_PARAM_UPLO_CHARS );
|
|
strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_UPLODE], BLIS_TEST_PARAM_UPLODE_CHARS );
|
|
strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_TRANS], BLIS_TEST_PARAM_TRANS_CHARS );
|
|
strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_CONJ], BLIS_TEST_PARAM_CONJ_CHARS );
|
|
strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_DIAG], BLIS_TEST_PARAM_DIAG_CHARS );
|
|
|
|
strcpy( libblis_test_store_chars[BLIS_TEST_MATRIX_OPERAND], BLIS_TEST_MSTORE_CHARS );
|
|
strcpy( libblis_test_store_chars[BLIS_TEST_VECTOR_OPERAND], BLIS_TEST_VSTORE_CHARS );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_sleep( void )
|
|
{
|
|
int i;
|
|
|
|
libblis_test_printf_infoc( "Resuming in " );
|
|
for ( i = SECONDS_TO_SLEEP; i > 0; --i )
|
|
{
|
|
libblis_test_printf_info( "%d ", i );
|
|
sleep(1);
|
|
}
|
|
libblis_test_printf_info( "\n" );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_abort( void )
|
|
{
|
|
abort();
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_fopen_ofile( char* op_str, iface_t iface, FILE** output_stream )
|
|
{
|
|
char filename_str[ MAX_FILENAME_LENGTH ];
|
|
|
|
if ( iface == BLIS_TEST_MT_FRONT_END )
|
|
bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED );
|
|
|
|
// Construct a filename string for the current operation.
|
|
libblis_test_build_filename_string( BLIS_FILE_PREFIX_STR,
|
|
op_str,
|
|
filename_str );
|
|
|
|
// Open the output file (overwriting a previous instance, if it exists)
|
|
// for writing (in binary mode).
|
|
*output_stream = fopen( filename_str, "wb" );
|
|
|
|
// Check the output stream and report an error if something went wrong.
|
|
libblis_test_fopen_check_stream( filename_str, *output_stream );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_fclose_ofile( FILE* output_stream )
|
|
{
|
|
fclose( output_stream );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_fopen_check_stream( char* filename_str,
|
|
FILE* stream )
|
|
{
|
|
// Check for success.
|
|
if ( stream == NULL )
|
|
{
|
|
libblis_test_printf_error( "Failed to open file %s. Check existence (if file is being read), permissions (if file is being overwritten), and/or storage limit.\n",
|
|
filename_str );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_read_next_line( char* buffer, FILE* input_stream )
|
|
{
|
|
char temp[ INPUT_BUFFER_SIZE ];
|
|
|
|
// We want to read at least one line, so we use a do-while loop.
|
|
do
|
|
{
|
|
// Read the next line into a temporary buffer and check success.
|
|
if ( fgets( temp, INPUT_BUFFER_SIZE-1, input_stream ) == NULL )
|
|
{
|
|
if ( feof( input_stream ) )
|
|
libblis_test_printf_error( "Error reading input file: encountered unexpected EOF." );
|
|
else
|
|
libblis_test_printf_error( "Error (non-EOF) reading input file." );
|
|
}
|
|
}
|
|
// We continue to read lines into buffer until the line is neither
|
|
// commented nor blank.
|
|
while ( temp[0] == INPUT_COMMENT_CHAR || temp[0] == '\n' ||
|
|
temp[0] == ' ' || temp[0] == '\t' );
|
|
|
|
// Save the string in temp, up to first white space character, into buffer.
|
|
//sscanf( temp, "%s ", buffer );
|
|
strcpy( buffer, temp );
|
|
|
|
//printf( "libblis_test_read_next_line() read: %s\n", buffer );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_fprintf( FILE* output_stream, char* message, ... )
|
|
{
|
|
va_list args;
|
|
|
|
// Initialize variable argument environment.
|
|
va_start( args, message );
|
|
|
|
// Parse the received message and print its components.
|
|
libblis_test_parse_message( output_stream, message, args );
|
|
|
|
// Shutdown variable argument environment and clean up stack.
|
|
va_end( args );
|
|
|
|
// Flush the output stream.
|
|
fflush( output_stream );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_fprintf_c( FILE* output_stream, char* message, ... )
|
|
{
|
|
va_list args;
|
|
|
|
fprintf( output_stream, "%c ", OUTPUT_COMMENT_CHAR );
|
|
|
|
// Initialize variable argument environment.
|
|
va_start( args, message );
|
|
|
|
// Parse the received message and print its components.
|
|
libblis_test_parse_message( output_stream, message, args );
|
|
|
|
// Shutdown variable argument environment and clean up stack.
|
|
va_end( args );
|
|
|
|
// Flush the output stream.
|
|
fflush( output_stream );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_printf_info( char* message, ... )
|
|
{
|
|
FILE* output_stream = stdout;
|
|
va_list args;
|
|
|
|
// Initialize variable argument environment.
|
|
va_start( args, message );
|
|
|
|
// Parse the received message and print its components.
|
|
libblis_test_parse_message( output_stream, message, args );
|
|
|
|
// Shutdown variable argument environment and clean up stack.
|
|
va_end( args );
|
|
|
|
// Flush the output stream.
|
|
fflush( output_stream );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_printf_infoc( char* message, ... )
|
|
{
|
|
FILE* output_stream = stdout;
|
|
va_list args;
|
|
|
|
fprintf( output_stream, "%c ", OUTPUT_COMMENT_CHAR );
|
|
|
|
// Initialize variable argument environment.
|
|
va_start( args, message );
|
|
|
|
// Parse the received message and print its components.
|
|
libblis_test_parse_message( output_stream, message, args );
|
|
|
|
// Shutdown variable argument environment and clean up stack.
|
|
va_end( args );
|
|
|
|
// Flush the output stream.
|
|
fflush( output_stream );
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_printf_error( char* message, ... )
|
|
{
|
|
FILE* output_stream = stderr;
|
|
va_list args;
|
|
|
|
fprintf( output_stream, "%s: *** error ***: ", libblis_test_binary_name );
|
|
|
|
// Initialize variable argument environment.
|
|
va_start( args, message );
|
|
|
|
// Parse the received message and print its components.
|
|
libblis_test_parse_message( output_stream, message, args );
|
|
|
|
// Shutdown variable argument environment and clean up stack.
|
|
va_end( args );
|
|
|
|
// Flush the output stream.
|
|
fflush( output_stream );
|
|
|
|
// Exit.
|
|
exit(1);
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_parse_message( FILE* output_stream, char* message, va_list args )
|
|
{
|
|
int c, cf;
|
|
char format_spec[8];
|
|
unsigned int the_uint;
|
|
int the_int;
|
|
double the_double;
|
|
char* the_string;
|
|
char the_char;
|
|
|
|
// Begin looping over message to insert variables wherever there are
|
|
// format specifiers.
|
|
for ( c = 0; message[c] != '\0'; )
|
|
{
|
|
if ( message[c] != '%' )
|
|
{
|
|
fprintf( output_stream, "%c", message[c] );
|
|
c += 1;
|
|
}
|
|
else if ( message[c] == '%' && message[c+1] == '%' ) // handle escaped '%' chars.
|
|
{
|
|
fprintf( output_stream, "%c", message[c] );
|
|
c += 2;
|
|
}
|
|
else
|
|
{
|
|
// Save the format string if there is one.
|
|
format_spec[0] = '%';
|
|
for ( c += 1, cf = 1; strchr( "udefsc", message[c] ) == NULL; ++c, ++cf )
|
|
{
|
|
format_spec[cf] = message[c];
|
|
}
|
|
|
|
// Add the final type specifier, and null-terminate the string.
|
|
format_spec[cf] = message[c];
|
|
format_spec[cf+1] = '\0';
|
|
|
|
// Switch based on type, since we can't predict what will
|
|
// va_args() will return.
|
|
switch ( message[c] )
|
|
{
|
|
case 'u':
|
|
the_uint = va_arg( args, unsigned int );
|
|
fprintf( output_stream, format_spec, the_uint );
|
|
break;
|
|
|
|
case 'd':
|
|
the_int = va_arg( args, int );
|
|
fprintf( output_stream, format_spec, the_int );
|
|
break;
|
|
|
|
case 'e':
|
|
the_double = va_arg( args, double );
|
|
fprintf( output_stream, format_spec, the_double );
|
|
break;
|
|
|
|
case 'f':
|
|
the_double = va_arg( args, double );
|
|
fprintf( output_stream, format_spec, the_double );
|
|
break;
|
|
|
|
case 's':
|
|
the_string = va_arg( args, char* );
|
|
//fprintf( output_stream, "%s", the_string );
|
|
fprintf( output_stream, format_spec, the_string );
|
|
break;
|
|
|
|
case 'c':
|
|
the_char = va_arg( args, int );
|
|
fprintf( output_stream, "%c", the_char );
|
|
break;
|
|
}
|
|
|
|
// Move to next character past type specifier.
|
|
c += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_parse_command_line( int argc, char** argv )
|
|
{
|
|
bool_t gave_option_g = FALSE;
|
|
bool_t gave_option_o = FALSE;
|
|
int opt;
|
|
char opt_ch;
|
|
|
|
// Copy the binary name to a global string so we can use it later.
|
|
strncpy( libblis_test_binary_name, argv[0], MAX_BINARY_NAME_LENGTH );
|
|
|
|
// Process all option arguments until we get a -1, which means we're done.
|
|
while( (opt = bli_getopt( argc, argv, "g:o:" )) != -1 )
|
|
{
|
|
// Explicitly typecast opt, which is an int, to a char. (Failing to
|
|
// typecast resulted in at least one user-reported problem whereby
|
|
// opt was being filled with garbage.)
|
|
opt_ch = ( char )opt;
|
|
|
|
switch( opt_ch )
|
|
{
|
|
case 'g':
|
|
libblis_test_printf_infoc( "detected -g option; using \"%s\" for parameters filename.\n", bli_optarg );
|
|
strncpy( libblis_test_parameters_filename,
|
|
bli_optarg, MAX_FILENAME_LENGTH );
|
|
gave_option_g = TRUE;
|
|
break;
|
|
|
|
case 'o':
|
|
libblis_test_printf_infoc( "detected -o option; using \"%s\" for operations filename.\n", bli_optarg );
|
|
strncpy( libblis_test_operations_filename,
|
|
bli_optarg, MAX_FILENAME_LENGTH );
|
|
gave_option_o = TRUE;
|
|
break;
|
|
|
|
case '?':
|
|
libblis_test_printf_error( "unexpected option '%c' given or missing option argument\n", bli_optopt );
|
|
break;
|
|
|
|
default:
|
|
libblis_test_printf_error( "unexpected option chararcter returned from getopt: %c\n", opt_ch );
|
|
}
|
|
}
|
|
|
|
if ( gave_option_g == FALSE )
|
|
{
|
|
libblis_test_printf_infoc( "no -g option given; defaulting to \"%s\" for parameters filename.\n", PARAMETERS_FILENAME );
|
|
|
|
// Copy default parameters filename into its global string.
|
|
strncpy( libblis_test_parameters_filename,
|
|
PARAMETERS_FILENAME, MAX_FILENAME_LENGTH );
|
|
}
|
|
|
|
if ( gave_option_o == FALSE )
|
|
{
|
|
libblis_test_printf_infoc( "no -o option given; defaulting to \"%s\" for operations filename.\n", OPERATIONS_FILENAME );
|
|
|
|
// Copy default operations filename into its global string.
|
|
strncpy( libblis_test_operations_filename,
|
|
OPERATIONS_FILENAME, MAX_FILENAME_LENGTH );
|
|
}
|
|
|
|
// If there are still arguments remaining after getopt() processing is
|
|
// complete, print an error.
|
|
if ( bli_optind < argc )
|
|
{
|
|
libblis_test_printf_error( "Encountered unexpected non-option argument: %s\n", argv[ bli_optind ] );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void libblis_test_check_empty_problem( obj_t* c, double* perf, double* resid )
|
|
{
|
|
if ( bli_obj_has_zero_dim( *c ) )
|
|
{
|
|
*perf = 0.0;
|
|
*resid = 0.0;
|
|
}
|
|
}
|
|
|