 	memory_limit += zRank == 0 ? 0 : (zRank * 2 + 4);
 	memory_limit += xRank * 6;
 	memory_limit += MAX_RANK; // special case, needed roughtly in one pase
+
+	return memory_limit;
+}
+
+dim3 getBetterDimensions(int numTads, int tadLength, int xRank, int yRank, int zRank, int dimensionLength, int elementSize, int reduction) {
+	int num_blocks = nd4j::math::nd4j_min<int>(numTads, blockLimit);
+	int num_threads = nd4j::math::nd4j_min<int>(tadLength, maxThreads);
+
+	// since we use shared memory as fast memory for some cases - we need to count that in
+	int memory_limit = getBaseMemorySize(xRank, yRank, zRank);
 
 	// at this momen we've stored all required information for things. time to count in reduction multipliers
 	int reduction_per_block;

			0,
			shape::rank(resultShapeInfoPointer),
			dimensionLength,
			sizeof(double),
			8
	);

	reduceFloat<<<launchDims.x,launchDims.y,launchDims.z, *stream>>>(

	return dim3(num_blocks,num_threads, 3000);
}

int getBaseMemorySize(int xRank, int yRank, int zRank) {
	int memory_limit = 256;

	if (xRank == 0) xRank = 2;
