
/**
 * Test different channel shuffle implementation for CNN ShuffleNet.
 *
 * @see {@link https://jsperf.com/colorfulcakechen-cnn-channel-shuffle}
 */


// concat-reshape-transpose-reshape-split
function by_ConcatReshapeTransposeReshapeSplit( dataTensor3dArray ) {
  tf.tidy( () => {
    let groupCount = dataTensor3dArray.length;
    let lastAxisId = dataTensor3dArray[ 0 ].rank - 1;

    let dataTensor3d = tf.concat( dataTensor3dArray, lastAxisId );
 
    let [ h, w, c ] = dataTensor3d.shape;
    let newChannelCount = c / groupCount;

    let x = dataTensor3d.reshape( [ h, w, groupCount, newChannelCount ] );
    x = x.transpose( [ 0, 1, 3, 2 ] );
    x = x.reshape( [ h, w, c] );

    x = x.split( groupCount, lastAxisId );
  });
}

// concat-gather
function by_ConcatGather( dataTensor3dArray ) {
}

// split-split-concat-concat
function by_SplitSplitConcatConcat( dataTensor3dArray ) {
}


let height = 10; // image height
let width = 15;  // image width
let depth = 12;  // image channel count

let valueCount = height * width * depth;

let groupCount = 2; // Split the data into how many groups.

let dataTensor3dArray = tf.tidy( () => {
  let dataTensor1d = tf.linspace(0, valueCount - 1, valueCount);
  let dataTensor3d = dataTensor1d.reshape( [ height, width, depth ] );
  return dataTensor3d.split( groupCount, dataTensor3d.rank - 1 );  // Along the last axis.
});


globalThis.dataTensor3d = dataTensor3d;

globalThis.cnnShuffle_by_ConcatReshapeTransposeReshapeSplit = by_ConcatReshapeTransposeReshapeSplit();
globalThis.cnnShuffle_by_ConcatGather = by_ConcatGather();
globalThis.cnnShuffle_by_SplitSplitConcatConcat = by_SplitSplitConcatConcat();

@@ -147,17 +147,16 @@
 e%7D%0A */%0A%0A
-%0A
 // conca
@@ -194,27 +194,24 @@
 it%0Afunction 
-by_
 ConcatReshap
@@ -258,16 +258,23 @@
 y ) %7B%0A  
+return 
 tf.tidy(
@@ -686,24 +686,31 @@
  c%5D );%0A%0A    
+return 
 x = x.split(
@@ -775,52 +775,973 @@
 ion 
-by_ConcatGather( dataTensor3dArray ) %7B%0A%7D%0A%0A//
+ConcatGather( dataTensor3dArray ) %7B%0A  tf.tidy( () =%3E %7B%0A    let groupCount = dataTensor3dArray.length;%0A    let lastAxisId = dataTensor3dArray%5B 0 %5D.rank - 1;%0A%0A    let dataTensor3d = tf.concat( dataTensor3dArray, lastAxisId );%0A%0A    // shuffle and split by gather (one operation achieves two operations).%0A    let shuffledSplitedArray = shuffledChannelIndicesArray.map( ( shuffledChannelIndices, i ) =%3E %7B%0A      return dataTensor3d.gather( shuffledChannelIndices, lastAxisId );%0A    %7D);%0A%0A    return shuffledSplitedArray;%0A  %7D);%0A%7D%0A%0A// split-split-concat-concat%0Afunction by_SplitSplitConcatConcat( dataTensor3dArray ) %7B%0A%7D%0A%0A%0A%0A// Test concat-reshape-transpose-reshape-split%0Afunction by_ConcatReshapeTransposeReshapeSplit( dataTensor3dArray ) %7B%0A  tf.tidy( () =%3E %7B%0A    ConcatReshapeTransposeReshapeSplit( dataTensor3dArray );%0A  %7D);%0A%7D%0A%0A// Test concat-gather%0Afunction by_ConcatGather( dataTensor3dArray ) %7B%0A  tf.tidy( () =%3E %7B%0A    ConcatGather( dataTensor3dArray );%0A  %7D);%0A%7D%0A%0A// Test
  spl
@@ -2137,16 +2137,17 @@
 lueCount
+ 
 );%0A  let
@@ -2308,16 +2308,470 @@
 s.%0A%7D);%0A%0A
+// Shuffled channel indices (One dimension) for by_ConcatGather()%0AglobalThis.shuffledChannelIndicesArray = tf.tidy( () =%3E %7B%0A  let channelIndices = tf.linspace( 0, depth - 1, depth );%0A  let lastAxisId = channelIndices.rank - 1;%0A%0A  let newChannelCount = depth / groupCount;%0A%0A  let x = channelIndices.reshape( %5B groupCount, newChannelCount %5D );%0A  x = x.transpose( %5B 1, 0 %5D );%0A  x = x.reshape( %5B depth %5D );%0A%0A  return x.split( groupCount, lastAxisId );%0A%7D);%0A%0A%0A
 %0AglobalT
@@ -2778,32 +2778,37 @@
 his.dataTensor3d
+Array
  = dataTensor3d;
@@ -2806,16 +2806,21 @@
 Tensor3d
+Array
 ;%0A%0Agloba

Update jsPerf_CNNChannelShuffle.js