#include using namespace Upp; #include using namespace af; static array A, B; static array dist_naive(array a, array b) { array dist_mat = constant(0, a.dims(1), b.dims(1)); for (int ii = 0; ii < a.dims(1); ii++) // Iterate through columns a for (int jj = 0; jj < b.dims(1); jj++) // Iterate through columns of b for (int kk = 0; kk < a.dims(0); kk++) // Get the sum of absolute differences dist_mat(ii, jj) += abs(a(kk, ii) - b(kk, jj)); return dist_mat; } static array dist_vec(array a, array b) { array dist_mat = constant(0, a.dims(1), b.dims(1)); for (int ii = 0; ii < a.dims(1); ii++) { // Iterate through columns a array avec = a(span, ii); for (int jj = 0; jj < b.dims(1); jj++) { // Iterate through columns of b array bvec = b(span, jj); dist_mat(ii, jj) = sum(abs(avec - bvec));// Get SAD using sum on the vector } } return dist_mat; } static array dist_gfor1(array a, array b) { array dist_mat = constant(0, a.dims(1), b.dims(1)); gfor (seq ii, a.dims(1)) { // GFOR along columns of a array avec = a(span, ii); for (int jj = 0; jj < b.dims(1); jj++) { // Itere through columns of b array bvec = b(span, jj); dist_mat(ii, jj) = sum(abs(avec - bvec));// Get SAD using sum on the vector } } return dist_mat; } static array dist_gfor2(array a, array b) { array dist_mat = constant(0, a.dims(1), b.dims(1)); gfor (seq jj, b.dims(1)) { // GFOR along columns of b array bvec = b(span, jj); for (int ii = 0; ii < a.dims(1); ii++) { // Iterate through columns of A array avec = a(span, ii); dist_mat(ii, jj) = sum(abs(avec - bvec));// Get SAD using sum on the vector } } return dist_mat; } static array dist_tile1(array a, array b) { int alen = a.dims(1); int blen = b.dims(1); array dist_mat = constant(0, alen, blen); for (int jj = 0; jj < blen; jj++) { // Iterate through columns of b // Get the column vector of b array bvec = b(span, jj); // shape of bvec is (feat_len, 1) // Tile avec to be same size as a array bvec_tiled = tile(bvec, 1, alen); // shape of bvec_tiled is (feat_len, alen) array sad = sum(abs(bvec_tiled - a)); // Get the sum of absolute differences // sad is row vector, dist_mat needs column vector dist_mat(span, jj) = sad.T(); // transpose sad and fill in dist_mat } return dist_mat; } static array dist_tile2(array a, array b) { int feat_len = a.dims(0); int alen = a.dims(1); int blen = b.dims(1); array a_mod = a; // Shape of a is (feat_len, alen, 1) array b_mod = moddims(b, feat_len, 1, blen); // Reshape b from (feat_len, blen) to (feat_len, 1, blen) array a_tiled = tile(a_mod, 1, 1, blen); // Tile both matrices to be (feat_len, alen, blen) array b_tiled = tile(b_mod, 1, alen, 1); // Do The sum operation along first dimension array dist_mod = sum(abs(a_tiled - b_tiled)); // Output is of shape (1, alen, blen) array dist_mat = moddims(dist_mod, alen, blen); // Reshape dist_mat from (1, alen, blen) to (alen, blen) return dist_mat; } static void bench_naive() {dist_naive(A, B);} static void bench_vec() {dist_vec(A, B);} static void bench_gfor1() {dist_gfor1(A, B);} static void bench_gfor2() {dist_gfor2(A, B);} static void bench_tile1() {dist_tile1(A, B);} static void bench_tile2() {dist_tile2(A, B);} void Vectorize_Bench() { printf("\nVectorize demo:"); // Do not increase the sizes // dist_naive and dist_vec get too slow at large sizes A = randu(3, 200); B = randu(3, 300); array d1 = dist_naive(A, B); array d2 = dist_vec (A, B); array d3 = dist_gfor1(A, B); array d4 = dist_gfor2(A, B); array d5 = dist_tile1(A, B); array d6 = dist_tile2(A, B); printf("\nMax. Error for dist_vec : %f", max(abs(d1 - d2))); printf("\nMax. Error for dist_gfor1: %f", max(abs(d1 - d3))); printf("\nMax. Error for dist_gfor2: %f", max(abs(d1 - d4))); printf("\nMax. Error for dist_tile1: %f", max(abs(d1 - d5))); printf("\nMax. Error for dist_tile2: %f", max(abs(d1 - d6))); printf("\n"); printf("\nTime for dist_naive: %2.2fms", 1000 * timeit(bench_naive)); printf("\nTime for dist_vec : %2.2fms", 1000 * timeit(bench_vec )); printf("\nTime for dist_gfor1: %2.2fms", 1000 * timeit(bench_gfor1)); printf("\nTime for dist_gfor2: %2.2fms", 1000 * timeit(bench_gfor2)); printf("\nTime for dist_tile1: %2.2fms", 1000 * timeit(bench_tile1)); printf("\nTime for dist_tile2: %2.2fms", 1000 * timeit(bench_tile2)); }