#ifndef AI2_BINARY_CONVOLUTION_H #define AI2_BINARY_CONVOLUTION_H /** @file binary_convolution.h * @brief Routines related for approximating convolutions using binary operations * * @author Carlo C. del Mundo (carlom) * @date 05/23/2016 */ #include #include #include #include #include #include #include #include #include #include "common.h" typedef struct { int batch; // number of filter batches int c; // channels, z int h; // height, y int w; // width, x int stride; int pad; int px; // padded x (use this for striding in padded input and output arrays) int py; // padded y (use this for striding in padded input and output arrays) int wx; int wy; float *input; // input values BINARY_WORD *binary_input; float *weights; // weight or filter values BINARY_WORD *binary_weights; float *output; // output values BINARY_WORD *binary_output; float *alpha; // we assume alpha is calculated at the beginning of initialization float *beta; // we assume beta is given to us float *new_beta; // we calculate the new beta for the next layer struct ai2_bin_conv_layer *next; } ai2_bin_conv_layer; /** @brief Performs a binary convolution using XNOR and POPCOUNT between input and weights * * @param output A 2D real-valued plane to store the outputs * @param input A 2D binary-valued plane that holds the inputs * @param weights A 2D binary-valued plane that holds the weights * @param ix the input's x dimension * @param iy the input's y dimensions * @param wx the weight's x dimension * @param wy the weight's y dimension * @param pad the amount of padding applied to input. (ix+2*pad is the x dimension of the input * @param stride NOP. TODO: implement stride. the stride between sliding windows * @return the count of all overlapping set bits between the two volumes. */ void ai2_bin_conv2D(float *output, const BINARY_WORD *input, const BINARY_WORD *weights, int ix, int iy, int wx, int wy, int pad, int stride); /** @brief Performs a binary dot product (XNOR and POPCOUNT) for two equal sized volumes. * * @param a A 3D binary tensor * @param b A 3D binary tensor * @param vdim the dimensionality of the data. Note: we pack 32 elements in the Z element. * @return the count of all overlapping set bits between the two volumes. */ int ai2_bin_dp(BINARY_WORD *a, BINARY_WORD *b, dim3 vdim); /** @brief Calculates the alpha plane given an alpha volume. * * Each point in the yz alpha plane * is the average sum of the absolute value of all elements in the z-direction. * * Pre-conditions: * alpha_volume is an array of size x*y*z. * alpha_plane is an array of size x*y. * alpha_volume (x,y,z) is transposed to (z,x,y). * * @param alpha_plane The 2D real-valued output plane * @param alpha_volume The 3D real-valued output volume * @param vdim the dimensionality of alpha_volume. */ void ai2_calc_alpha(float *alpha_plane, float *alpha_volume, dim3 vdim); /** @brief Wrapper function for generating the beta scaling factor */ void ai2_calc_beta(float *beta_plane, float *beta_volume, dim3 vdim); /** @brief Set the bit in a binary word */ void ai2_bitset(BINARY_WORD *bword, unsigned int position); /** @brief Checks that the bit is set in a binary word */ int ai2_is_set(BINARY_WORD bword, unsigned int position) ; /** @brief Converts a 3D float tensor into a 3D binary tensor. * * The value of the ith element in the binary tensor is the sign * of the ith element in the floating tensor. * * @param binary_vol the binary tensor * @param real_vol the real tensor * @param vdim the size of the 3D tensor */ void ai2_flt_to_bin(BINARY_WORD *binary_vol, float *real_vol, dim3 vdim) ; /** @brief Converts a 3D binary tensor into a 3D float tensor. * * The ith float element will be '1' if the ith binary element is '1'. * Otherwise, the float element will be '-1'. * * @param real_vol the output real tensor * @param binary_vol the input binary tensor * @param vdim the dimension of both binary_vol and real_vol */ void ai2_bin_to_flt(float *real_vol, BINARY_WORD *binary_vol, dim3 vdim); /** @brief Performs a pointwise matrix multication between two 2D tensors * @param output A 2D real-valued plane to store the outputs * @param input A 2D binary-valued plane that holds the inputs * @param N the number of elements between the arrays */ void ai2_pointwise_mul_mm(float *output, const float *input, int N); /** @brief Performs a tiled pointwise matrix multiplication between two 2D tensors * * Pre-conditions: wx < ix, and wy < iy * * @param output A 2D real-valued plane of size ix, iy * @param alpha A 2D binary-valued plane of size wx, wy * @param ix the output's x dimension * @param iy the output's y dimensions * @param wx the alpha's x dimension * @param wy the alpha's y dimension * @param pad how many cells are padded, adds 2*pad to the borders of the image */ void ai2_pointwise_mul_mm_2d(float *output, const float *alpha, int ix, int iy, int wx, int wy, int pad); // -------------------------------------- // SETTER FUNCTIONS // -------------------------------------- /** @brief Safe function to set the float input of a conv_layer */ void ai2_setFltInput(ai2_bin_conv_layer *layer, float *new_input); /** @brief Safe function to set the binary input of a conv_layer */ void ai2_setBinInput(ai2_bin_conv_layer *layer, BINARY_WORD *new_input); /** @brief Safe function to set the binary weights of a conv_layer */ void ai2_setFltWeights(ai2_bin_conv_layer *layer, float *new_weights); /** @brief Safe function to set the binary weights of a conv_layer */ void ai2_setBinWeights(ai2_bin_conv_layer *layer, BINARY_WORD *new_weights); /** @brief Safe function to set the binary outputs of a conv_layer */ void ai2_setFltOutput(ai2_bin_conv_layer *layer, float *new_output); /** @brief Safe function to set the binary outputs of a conv_layer */ void ai2_setBinOutput(ai2_bin_conv_layer *layer, BINARY_WORD *new_output); /** @brief Safe function to set the alpha of a conv_layer */ void ai2_setFltAlpha(ai2_bin_conv_layer *layer, float *new_alpha); /** @brief Safe function to set the beta of a conv_layer */ void ai2_setFltBeta(ai2_bin_conv_layer *layer, float *new_beta); /** @brief Safe function to set the new_beta of a conv_layer */ void ai2_setFltNewBeta(ai2_bin_conv_layer *layer, float *new_new_beta); // -------------------------------------- // GETTER FUNCTIONS // -------------------------------------- /** @brief Safe function to get the float outputs of a conv_layer */ float * ai2_getFltOutput(ai2_bin_conv_layer *layer); /** @brief 3D tranpose from (x,y,z) to (z,y,x) * @return a new pointer with the transposed matrix */ void ai2_transpose3D(float *data, dim3 d); /** @brief Checks if a float is a whole number (e.g., an int) */ int ai2_isFloatWhole(float f); /* @brief Allocates all memory objects in an ai2_bin_conv_layer * b - batches (number of filter batches) * c - input channels * ix - input width * iy - input height * wx - weight/filter width * wy - weight/filter height * s - stride between sliding windows * pad - the amount of padding */ ai2_bin_conv_layer ai2_make_bin_conv_layer(int b, int c, int ix, int iy, int wx, int wy, int s, int pad); /* @brief Safe deallocation of all memory objects in an ai2_bin_conv_layer */ void ai2_free_bin_conv_layer(ai2_bin_conv_layer *layer); /* @brief Given real-valued filter data and a conv layer, performs a forward pass */ void ai2_bin_forward(ai2_bin_conv_layer *layer); #endif