From 0ee13afc4429411de9a05ba4c2ff8a580784b568 Mon Sep 17 00:00:00 2001 From: Gunes Bayir Date: Wed, 7 Feb 2024 15:34:45 +0000 Subject: Remove CKW prototype and Template Writer Gpu code in dynamic fusion is now written by stable CKW. We do not need CKW protoype and the older writer implementation, i.e. TemplateWriter. It also removes the need for the flag -DACL_INTERNAL_TEST_CKW_IN_DF to compile and test dynamic fusion operator. Resolves: COMPMID-6715 Signed-off-by: Gunes Bayir Change-Id: I9f9453311e79d9be612bd4754240d832f98503e8 Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/11116 Benchmark: Arm Jenkins Tested-by: Arm Jenkins Reviewed-by: Jakub Sujak Comments-Addressed: Arm Jenkins --- .../validation/dynamic_fusion/gpu/Integration.cpp | 10 +- .../dynamic_fusion/gpu/cl/DepthwiseConv2d.cpp | 10 +- tests/validation/dynamic_fusion/gpu/cl/MatMul.cpp | 3 +- tests/validation/dynamic_fusion/gpu/cl/Pool2d.cpp | 3 +- tests/validation/dynamic_fusion/gpu/cl/Reshape.cpp | 14 +- tests/validation/dynamic_fusion/gpu/cl/Softmax.cpp | 184 +++++++++++---------- 6 files changed, 116 insertions(+), 108 deletions(-) (limited to 'tests') diff --git a/tests/validation/dynamic_fusion/gpu/Integration.cpp b/tests/validation/dynamic_fusion/gpu/Integration.cpp index 80dcaa8f90..453983c077 100644 --- a/tests/validation/dynamic_fusion/gpu/Integration.cpp +++ b/tests/validation/dynamic_fusion/gpu/Integration.cpp @@ -63,7 +63,7 @@ namespace validation TEST_SUITE(CL) TEST_SUITE(INTEGRATION) TEST_SUITE(DYNAMIC_FUSION) -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Conv2d is not ported to ckw yet. COMPMID-6259 + TEST_CASE(Conv2d, framework::DatasetMode::ALL) { /* Computation: @@ -156,7 +156,7 @@ TEST_CASE(Conv2d, framework::DatasetMode::ALL) 0.001f); /**< Tolerance value for comparing reference's output against implementation's output for floating point data types */ validate(CLAccessor(t_dst), ref_t_dst_nchw, tolerance_f32); } -#endif // ACL_INTERNAL_TEST_CKW_IN_DF + TEST_CASE(Add_Output_Add_Output, framework::DatasetMode::ALL) { /* Computation: @@ -368,8 +368,9 @@ TEST_CASE(Add_Output_Add_Cast_Cast_Output, framework::DatasetMode::ALL) validate(CLAccessor(t_out_1), ref_t_out_1, tolerance_cast_f32); } -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Conv2d is not ported to ckw yet. COMPMID-6259 -TEST_CASE(Conv2d_Sigmoid_DepthwiseConv2d_Mul, framework::DatasetMode::ALL) +/// TODO: COMPMID-6593 : This integration test fails with CKW backend. +/// It was not enabled for CKW before, therefore went unnoticed. +TEST_CASE(Conv2d_Sigmoid_DepthwiseConv2d_Mul, framework::DatasetMode::DISABLED) { // (tensor0) // | @@ -580,7 +581,6 @@ TEST_CASE(Conv2d_Sigmoid_DepthwiseConv2d_Mul, framework::DatasetMode::ALL) constexpr RelativeTolerance tolerance(0.001f); validate(CLAccessor(tensor6), ref_mul_dst_nchw, tolerance); } -#endif // ACL_INTERNAL_TEST_CKW_IN_DF TEST_SUITE(Invalid_Fusion_Should_Fail) TEST_CASE(Multiple_Complex_Ops_0, framework::DatasetMode::ALL) diff --git a/tests/validation/dynamic_fusion/gpu/cl/DepthwiseConv2d.cpp b/tests/validation/dynamic_fusion/gpu/cl/DepthwiseConv2d.cpp index 40e1ea8929..2f8c639cea 100644 --- a/tests/validation/dynamic_fusion/gpu/cl/DepthwiseConv2d.cpp +++ b/tests/validation/dynamic_fusion/gpu/cl/DepthwiseConv2d.cpp @@ -290,7 +290,7 @@ FIXTURE_DATA_TEST_CASE(RunLarge, { validate(CLAccessor(_target), _reference, tolerance_f16); } -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Do not include this test as dilation not supported yet in DepthwiseConv2d CKW kernel + TEST_SUITE(Dilation) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuDepthwiseConv2dFixture, @@ -313,7 +313,6 @@ FIXTURE_DATA_TEST_CASE(RunLarge, validate(CLAccessor(_target), _reference, tolerance_f16); } TEST_SUITE_END() // Dilation -#endif // ACL_INTERNAL_TEST_CKW_IN_DF TEST_SUITE_END() // W3x3 TEST_SUITE(Generic) @@ -336,7 +335,7 @@ FIXTURE_DATA_TEST_CASE(RunLarge, { validate(CLAccessor(_target), _reference, tolerance_f16, tolerance_num); } -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Do not include this test as dilation not supported yet in DepthwiseConv2d CKW kernel + TEST_SUITE(Dilation) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuDepthwiseConv2dFixture, @@ -359,7 +358,6 @@ FIXTURE_DATA_TEST_CASE(RunLarge, validate(CLAccessor(_target), _reference, tolerance_f16, tolerance_num); } TEST_SUITE_END() // Dilation -#endif // ACL_INTERNAL_TEST_CKW_IN_DF TEST_SUITE_END() // Generic TEST_SUITE_END() // FP16 @@ -385,7 +383,6 @@ FIXTURE_DATA_TEST_CASE(RunLarge, validate(CLAccessor(_target), _reference, tolerance_f32); } -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Do not include this test as dilation not supported yet in DepthwiseConv2d CKW kernel TEST_SUITE(Dilation) FIXTURE_DATA_TEST_CASE(RunSmall, @@ -409,7 +406,6 @@ FIXTURE_DATA_TEST_CASE(RunLarge, validate(CLAccessor(_target), _reference, tolerance_f32); } TEST_SUITE_END() // Dilation -#endif // ACL_INTERNAL_TEST_CKW_IN_DF TEST_SUITE_END() // W3x3 TEST_SUITE(Generic) @@ -445,7 +441,6 @@ FIXTURE_DATA_TEST_CASE(RunLargeKernelSize, validate(CLAccessor(_target), _reference, tolerance_f32); } -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Do not include this test as dilation not supported yet in DepthwiseConv2d CKW kernel TEST_SUITE(Dilation) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuDepthwiseConv2dFixture, @@ -468,7 +463,6 @@ FIXTURE_DATA_TEST_CASE(RunLarge, validate(CLAccessor(_target), _reference, tolerance_f32); } TEST_SUITE_END() // Dilation -#endif // ACL_INTERNAL_TEST_CKW_IN_DF TEST_SUITE_END() // Generic TEST_SUITE_END() // FP32 TEST_SUITE_END() // Float diff --git a/tests/validation/dynamic_fusion/gpu/cl/MatMul.cpp b/tests/validation/dynamic_fusion/gpu/cl/MatMul.cpp index 96b79679c3..82d66ca6ce 100644 --- a/tests/validation/dynamic_fusion/gpu/cl/MatMul.cpp +++ b/tests/validation/dynamic_fusion/gpu/cl/MatMul.cpp @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifdef ACL_INTERNAL_TEST_CKW_IN_DF + #include "tests/AssetsLibrary.h" #include "tests/CL/CLAccessor.h" #include "tests/datasets/LargeMatMulDataset.h" @@ -333,4 +333,3 @@ TEST_SUITE_END() // CL } // namespace validation } // namespace test } // namespace arm_compute -#endif // ACL_INTERNAL_TEST_CKW_IN_DF diff --git a/tests/validation/dynamic_fusion/gpu/cl/Pool2d.cpp b/tests/validation/dynamic_fusion/gpu/cl/Pool2d.cpp index e537826c71..be816b32b3 100644 --- a/tests/validation/dynamic_fusion/gpu/cl/Pool2d.cpp +++ b/tests/validation/dynamic_fusion/gpu/cl/Pool2d.cpp @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifdef ACL_INTERNAL_TEST_CKW_IN_DF + #include "arm_compute/dynamic_fusion/sketch/gpu/operators/GpuPool2d.h" #include "tests/CL/CLAccessor.h" @@ -217,4 +217,3 @@ TEST_SUITE_END() // CL } // namespace validation } // namespace test } // namespace arm_compute -#endif // ACL_INTERNAL_TEST_CKW_IN_DF diff --git a/tests/validation/dynamic_fusion/gpu/cl/Reshape.cpp b/tests/validation/dynamic_fusion/gpu/cl/Reshape.cpp index 43617fe1be..a1495cf014 100644 --- a/tests/validation/dynamic_fusion/gpu/cl/Reshape.cpp +++ b/tests/validation/dynamic_fusion/gpu/cl/Reshape.cpp @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Do not include this test if ACL_INTERNAL_TEST_CKW_IN_DF and the op has not been ported to ckw + #include "tests/CL/CLAccessor.h" #include "tests/datasets/ReshapeLayerDataset.h" #include "tests/framework/datasets/Datasets.h" @@ -82,7 +82,7 @@ using DynamicFusionGpuReshapeLayerFixture = TEST_SUITE(F32) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuReshapeLayerFixture, - framework::DatasetMode::ALL, + framework::DatasetMode::DISABLED, combine(datasets::SmallReshapeLayerDataset(), framework::dataset::make("DataType", DataType::F32))) { @@ -94,7 +94,7 @@ TEST_SUITE_END() // F32 TEST_SUITE(F16) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuReshapeLayerFixture, - framework::DatasetMode::ALL, + framework::DatasetMode::DISABLED, combine(datasets::SmallReshapeLayerDataset(), framework::dataset::make("DataType", DataType::F16))) { @@ -106,7 +106,7 @@ TEST_SUITE_END() // F16 TEST_SUITE(U8) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuReshapeLayerFixture, - framework::DatasetMode::ALL, + framework::DatasetMode::DISABLED, combine(datasets::SmallReshapeLayerDataset(), framework::dataset::make("DataType", DataType::U8))) { @@ -118,7 +118,7 @@ TEST_SUITE_END() // U8 TEST_SUITE(S8) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuReshapeLayerFixture, - framework::DatasetMode::ALL, + framework::DatasetMode::DISABLED, combine(datasets::SmallReshapeLayerDataset(), framework::dataset::make("DataType", DataType::S8))) { @@ -130,7 +130,7 @@ TEST_SUITE_END() // S8 TEST_SUITE(S16) FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionGpuReshapeLayerFixture, - framework::DatasetMode::ALL, + framework::DatasetMode::DISABLED, combine(datasets::SmallReshapeLayerDataset(), framework::dataset::make("DataType", DataType::S16))) { @@ -145,5 +145,3 @@ TEST_SUITE_END() // CL } // namespace validation } // namespace test } // namespace arm_compute - -#endif // ACL_INTERNAL_TEST_CKW_IN_DF diff --git a/tests/validation/dynamic_fusion/gpu/cl/Softmax.cpp b/tests/validation/dynamic_fusion/gpu/cl/Softmax.cpp index b7cb6bace6..8f5a1ed14a 100644 --- a/tests/validation/dynamic_fusion/gpu/cl/Softmax.cpp +++ b/tests/validation/dynamic_fusion/gpu/cl/Softmax.cpp @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef ACL_INTERNAL_TEST_CKW_IN_DF // Do not include this test if ACL_INTERNAL_TEST_CKW_IN_DF and the op has not been ported to ckw + #include "arm_compute/core/Types.h" #include "arm_compute/dynamic_fusion/sketch/gpu/operators/GpuSoftmax.h" @@ -46,62 +46,70 @@ namespace validation RelativeTolerance tolerance_f16(half(0.2)); RelativeTolerance tolerance_f32(0.001f); +using framework::dataset::make; + +/// TODO: COMPMID-6713 +/// Softmax is not implemented in CKW. Therefore, the tests are DISABLED. +/// Enable the tests when Softmax is implemented in CKW. + TEST_SUITE(CL) TEST_SUITE(DYNAMIC_FUSION) TEST_SUITE(SOFTMAX) // *INDENT-OFF* // clang-format off -DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip( - framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U), 1, DataType::F32), // Mismatching data types - TensorInfo(TensorShape(27U, 13U), 1, DataType::F32), // Mismatching shapes - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::S32), // Unsupported data type - TensorInfo(TensorShape(32U, 13U), 1, DataType::F16), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - - }), - framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(27U, 13U), 1, DataType::F16), - TensorInfo(TensorShape(27U, 11U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::QASYMM16), // Unsupported data type - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), - - })), - framework::dataset::make("beta", { 1.0, - 2.0, - 2.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - })), - framework::dataset::make("axis", { - 0, - 0, - 1, // Invalid as axis != 0 - 0, - 0, - 0, - -3, // Invalid as axis != 0 - 2, // Invalid as axis != 0 - 1, // Invalid as axis != 0 - -1, // Invalid as axis != 0 - })), - framework::dataset::make("Expected", { false, false, false, true, false, false, false, false, false, false})), - input_info, output_info, beta, axis, expected) +DATA_TEST_CASE(Validate, framework::DatasetMode::DISABLED, + zip( + make("InputInfo", { + TensorInfo(TensorShape(27U, 13U), 1, DataType::F32), // Mismatching data types + TensorInfo(TensorShape(27U, 13U), 1, DataType::F32), // Mismatching shapes + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::S32), // Unsupported data type + TensorInfo(TensorShape(32U, 13U), 1, DataType::F16), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + }), + make("OutputInfo",{ + TensorInfo(TensorShape(27U, 13U), 1, DataType::F16), + TensorInfo(TensorShape(27U, 11U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::QASYMM16), // Unsupported data type + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + TensorInfo(TensorShape(32U, 13U), 1, DataType::F32), + }), + make("beta", { + 1.0, + 2.0, + 2.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + }), + make("axis", { + 0, + 0, + 1, // Invalid as axis != 0 + 0, + 0, + 0, + -3, // Invalid as axis != 0 + 2, // Invalid as axis != 0 + 1, // Invalid as axis != 0 + -1, // Invalid as axis != 0 + }), + make("Expected", { false, false, false, true, false, false, false, false, false, false})), + input_info, output_info, beta, axis, expected) { // Create a new workload sketch CLCompileContext cl_compile_ctx = CLKernelLibrary::get().get_compile_context(); @@ -122,33 +130,39 @@ using DynamicFusionSoftmaxLayerFixture = DynamicFusionSoftmaxValidationFixture, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SoftmaxLayerSmallShapes(), - framework::dataset::make("DataType", DataType::F32)), - framework::dataset::make("Beta", { 1.0f, 2.0f })), - framework::dataset::make("Axis", { 0 })), - framework::dataset::make("is_log", {false, true}))) +FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::DISABLED, + combine( + datasets::SoftmaxLayerSmallShapes(), + make("DataType", DataType::F32), + make("Beta", { 1.0f, 2.0f }), + make("Axis", { 0 }), + make("is_log", {false, true}))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f32); } -FIXTURE_DATA_TEST_CASE(RunLarge, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::SoftmaxLayerLargeShapes(), - framework::dataset::make("DataType", DataType::F32)), - framework::dataset::make("Beta", { 1.0f, 2.0f })), - framework::dataset::make("Axis", { 0 })), - framework::dataset::make("is_log", {false, true}))) +FIXTURE_DATA_TEST_CASE(RunLarge, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::DISABLED, + combine( + datasets::SoftmaxLayerLargeShapes(), + make("DataType", DataType::F32), + make("Beta", { 1.0f, 2.0f }), + make("Axis", { 0 }), + make("is_log", {false, true}))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f32); } -FIXTURE_DATA_TEST_CASE(Run4D, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::SoftmaxLayer4DShapes(), - framework::dataset::make("DataType", DataType::F32)), - framework::dataset::make("Beta", { 1.0f, 2.0f })), - framework::dataset::make("Axis", { 0 })), - framework::dataset::make("is_log", {false, true}))) +FIXTURE_DATA_TEST_CASE(Run4D, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::DISABLED, + combine( + datasets::SoftmaxLayer4DShapes(), + make("DataType", DataType::F32), + make("Beta", { 1.0f, 2.0f }), + make("Axis", { 0 }), + make("is_log", {false, true}))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f32); @@ -156,33 +170,39 @@ FIXTURE_DATA_TEST_CASE(Run4D, DynamicFusionSoftmaxLayerFixture, framework TEST_SUITE_END() // FP32 TEST_SUITE(FP16) -FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SoftmaxLayerSmallShapes(), - framework::dataset::make("DataType", DataType::F16)), - framework::dataset::make("Beta", { 1.0f, 2.0f })), - framework::dataset::make("Axis", { 0 })), - framework::dataset::make("is_log", {false, true}))) +FIXTURE_DATA_TEST_CASE(RunSmall, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::DISABLED, + combine( + datasets::SoftmaxLayerSmallShapes(), + make("DataType", DataType::F16), + make("Beta", { 1.0f, 2.0f }), + make("Axis", { 0 }), + make("is_log", {false, true}))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); } -FIXTURE_DATA_TEST_CASE(RunLarge, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::SoftmaxLayerLargeShapes(), - framework::dataset::make("DataType", DataType::F16)), - framework::dataset::make("Beta", { 1.0f, 2.0f })), - framework::dataset::make("Axis", { 0 })), - framework::dataset::make("is_log", {false, true}))) +FIXTURE_DATA_TEST_CASE(RunLarge, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::DISABLED, + combine( + datasets::SoftmaxLayerLargeShapes(), + make("DataType", DataType::F16), + make("Beta", { 1.0f, 2.0f }), + make("Axis", { 0 }), + make("is_log", {false, true}))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); } -FIXTURE_DATA_TEST_CASE(Run4D, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::SoftmaxLayer4DShapes(), - framework::dataset::make("DataType", DataType::F16)), - framework::dataset::make("Beta", { 1.0f, 2.0f })), - framework::dataset::make("Axis", { 0 })), - framework::dataset::make("is_log", {false, true}))) +FIXTURE_DATA_TEST_CASE(Run4D, DynamicFusionSoftmaxLayerFixture, framework::DatasetMode::DISABLED, + combine( + datasets::SoftmaxLayer4DShapes(), + make("DataType", DataType::F16), + make("Beta", { 1.0f, 2.0f }), + make("Axis", { 0 }), + make("is_log", {false, true}))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); @@ -197,5 +217,3 @@ TEST_SUITE_END() // CL } // namespace validation } // namespace test } // namespace arm_compute - -#endif // ACL_INTERNAL_TEST_CKW_IN_DF -- cgit v1.2.1