From 1bea8e1eacc68bcedbd3f207395bccf11011dae2 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 1 May 2020 09:34:23 -0300 Subject: [PATCH] New lightmapper -Added LocalVector (needed it) -Added stb_rect_pack (It's pretty cool, we could probably use it for other stuff too) -Fixes and changes all around the place -Added library for 128 bits fixed point (required for Delaunay3D) --- SConstruct | 7 + core/error_macros.h | 36 +- core/image.cpp | 4 + core/image.h | 2 + core/io/resource_format_binary.cpp | 24 +- core/io/resource_format_binary.h | 2 +- core/io/resource_importer.cpp | 2 +- core/local_vector.h | 246 + core/math/basis.cpp | 111 + core/math/basis.h | 1 + core/math/camera_matrix.cpp | 16 + core/math/camera_matrix.h | 1 + core/math/delaunay.h | 2 - core/math/delaunay_3d.h | 386 ++ core/math/geometry.cpp | 194 + core/math/geometry.h | 243 + core/math/plane.cpp | 4 + core/math/plane.h | 1 + core/math/r128.cpp | 2 + core/ustring.cpp | 16 +- core/ustring.h | 2 +- core/vector.h | 8 + drivers/vulkan/rendering_device_vulkan.cpp | 10 +- drivers/vulkan/rendering_device_vulkan.h | 2 + drivers/vulkan/vulkan_context.cpp | 9 + editor/editor_node.cpp | 16 +- .../resource_importer_layered_texture.cpp | 329 +- .../resource_importer_layered_texture.h | 34 +- editor/import/resource_importer_scene.cpp | 7 +- .../import/resource_importer_shader_file.cpp | 2 +- editor/import/resource_importer_texture.cpp | 121 +- editor/import/resource_importer_texture.h | 12 +- editor/node_3d_editor_gizmos.cpp | 339 +- editor/node_3d_editor_gizmos.h | 31 +- .../plugins/baked_lightmap_editor_plugin.cpp | 69 +- editor/plugins/baked_lightmap_editor_plugin.h | 7 +- editor/plugins/canvas_item_editor_plugin.cpp | 2 +- editor/plugins/node_3d_editor_plugin.cpp | 3 +- editor/plugins/texture_editor_plugin.cpp | 6 +- .../plugins/texture_layered_editor_plugin.cpp | 286 ++ .../plugins/texture_layered_editor_plugin.h | 95 + gles_builders.py | 64 + main/main.cpp | 8 +- main/tests/test_math.cpp | 53 +- modules/denoise/SCsub | 119 + modules/denoise/config.py | 6 + modules/denoise/denoise_wrapper.cpp | 34 + modules/denoise/denoise_wrapper.h | 8 + modules/denoise/lightmap_denoiser.cpp | 63 + modules/denoise/lightmap_denoiser.h | 57 + modules/denoise/register_types.cpp | 41 + modules/denoise/register_types.h | 32 + modules/denoise/resource_to_cpp.py | 70 + modules/lightmapper_rd/SCsub | 12 + modules/lightmapper_rd/config.py | 6 + modules/lightmapper_rd/lightmapper_rd.cpp | 1754 +++++++ modules/lightmapper_rd/lightmapper_rd.h | 229 + modules/lightmapper_rd/lm_blendseams.glsl | 117 + modules/lightmapper_rd/lm_common_inc.glsl | 92 + modules/lightmapper_rd/lm_compute.glsl | 657 +++ modules/lightmapper_rd/lm_raster.glsl | 170 + modules/lightmapper_rd/register_types.cpp | 64 + modules/lightmapper_rd/register_types.h | 37 + modules/tinyexr/image_saver_tinyexr.cpp | 16 +- modules/xatlas_unwrap/register_types.cpp | 1 + platform/uwp/export/export.cpp | 46 +- scene/3d/baked_lightmap.cpp | 1792 ++++--- scene/3d/baked_lightmap.h | 256 +- scene/3d/gi_probe.cpp | 2 +- scene/3d/lightmap_probe.cpp | 4 + scene/3d/lightmap_probe.h | 12 + scene/3d/lightmapper.cpp | 37 + scene/3d/lightmapper.h | 90 + scene/3d/visual_instance_3d.cpp | 93 +- scene/3d/visual_instance_3d.h | 36 +- scene/3d/voxelizer.cpp | 205 +- scene/register_scene_types.cpp | 18 +- scene/resources/mesh.cpp | 6 +- scene/resources/mesh.h | 6 +- scene/resources/texture.cpp | 523 +- scene/resources/texture.h | 166 +- scene/scene_string_names.cpp | 5 + scene/scene_string_names.h | 4 + servers/rendering/rasterizer.h | 63 +- .../rasterizer_rd/rasterizer_canvas_rd.cpp | 4 +- .../rasterizer_rd/rasterizer_effects_rd.cpp | 30 +- .../rasterizer_rd/rasterizer_effects_rd.h | 3 + .../rendering/rasterizer_rd/rasterizer_rd.cpp | 6 +- .../rendering/rasterizer_rd/rasterizer_rd.h | 7 +- .../rasterizer_scene_high_end_rd.cpp | 221 +- .../rasterizer_scene_high_end_rd.h | 36 +- .../rasterizer_rd/rasterizer_scene_rd.cpp | 173 +- .../rasterizer_rd/rasterizer_scene_rd.h | 10 +- .../rasterizer_rd/rasterizer_storage_rd.cpp | 566 +- .../rasterizer_rd/rasterizer_storage_rd.h | 93 +- ...render_pipeline_vertex_format_cache_rd.cpp | 8 +- .../render_pipeline_vertex_format_cache_rd.h | 9 +- .../rasterizer_rd/shader_compiler_rd.cpp | 5 + .../rendering/rasterizer_rd/shaders/copy.glsl | 29 +- .../rasterizer_rd/shaders/scene_high_end.glsl | 123 +- .../shaders/scene_high_end_inc.glsl | 58 +- .../shaders/screen_space_reflection.glsl | 2 +- .../screen_space_reflection_filter.glsl | 2 +- .../screen_space_reflection_scale.glsl | 2 +- .../rendering/rasterizer_rd/shaders/ssao.glsl | 2 +- .../rasterizer_rd/shaders/ssao_blur.glsl | 2 +- .../shaders/subsurface_scattering.glsl | 2 +- servers/rendering/rendering_device.cpp | 4 +- servers/rendering/rendering_device.h | 4 +- servers/rendering/rendering_device_binds.cpp | 15 +- servers/rendering/rendering_device_binds.h | 25 +- servers/rendering/rendering_server_raster.h | 39 +- servers/rendering/rendering_server_scene.cpp | 442 +- servers/rendering/rendering_server_scene.h | 13 +- .../rendering/rendering_server_wrap_mt.cpp | 2 +- servers/rendering/rendering_server_wrap_mt.h | 33 +- servers/rendering/shader_language.cpp | 29 +- servers/rendering/shader_language.h | 3 + servers/rendering_server.cpp | 12 +- servers/rendering_server.h | 49 +- thirdparty/oidn/.gitignore | 1 + thirdparty/oidn/common/barrier.h | 52 + thirdparty/oidn/common/exception.h | 45 + thirdparty/oidn/common/platform.cpp | 114 + thirdparty/oidn/common/platform.h | 131 + thirdparty/oidn/common/ref.h | 163 + thirdparty/oidn/common/tensor.cpp | 83 + thirdparty/oidn/common/tensor.h | 66 + thirdparty/oidn/common/thread.cpp | 297 ++ thirdparty/oidn/common/thread.h | 202 + thirdparty/oidn/common/timer.h | 49 + thirdparty/oidn/core/api.cpp | 408 ++ thirdparty/oidn/core/autoencoder.cpp | 519 ++ thirdparty/oidn/core/autoencoder.h | 116 + thirdparty/oidn/core/buffer.h | 75 + thirdparty/oidn/core/common.h | 133 + thirdparty/oidn/core/device.cpp | 205 + thirdparty/oidn/core/device.h | 78 + thirdparty/oidn/core/filter.cpp | 27 + thirdparty/oidn/core/filter.h | 52 + thirdparty/oidn/core/image.h | 111 + thirdparty/oidn/core/input_reorder.h | 232 + thirdparty/oidn/core/math.h | 78 + thirdparty/oidn/core/network.cpp | 434 ++ thirdparty/oidn/core/network.h | 112 + thirdparty/oidn/core/node.h | 142 + thirdparty/oidn/core/output_reorder.h | 126 + thirdparty/oidn/core/transfer_function.cpp | 95 + thirdparty/oidn/core/transfer_function.h | 201 + thirdparty/oidn/core/upsample.h | 92 + thirdparty/oidn/core/weights_reorder.h | 99 + .../oidn/include/OpenImageDenoise/oidn.h | 214 + .../oidn/include/OpenImageDenoise/oidn.hpp | 468 ++ .../oidn/include/OpenImageDenoise/version.h | 23 + thirdparty/oidn/mkl-dnn/LICENSE | 214 + thirdparty/oidn/mkl-dnn/include/mkldnn.h | 1771 +++++++ thirdparty/oidn/mkl-dnn/include/mkldnn.hpp | 2615 ++++++++++ .../oidn/mkl-dnn/include/mkldnn_debug.h | 98 + .../oidn/mkl-dnn/include/mkldnn_types.h | 1415 +++++ .../oidn/mkl-dnn/include/mkldnn_version.h | 32 + .../oidn/mkl-dnn/include/mkldnn_version.h.in | 32 + .../src/common/batch_normalization.cpp | 104 + .../src/common/batch_normalization_pd.hpp | 240 + .../oidn/mkl-dnn/src/common/c_types_map.hpp | 550 ++ thirdparty/oidn/mkl-dnn/src/common/concat.cpp | 86 + .../oidn/mkl-dnn/src/common/concat_pd.hpp | 211 + .../oidn/mkl-dnn/src/common/convolution.cpp | 200 + .../mkl-dnn/src/common/convolution_pd.cpp | 56 + .../mkl-dnn/src/common/convolution_pd.hpp | 348 ++ .../oidn/mkl-dnn/src/common/deconvolution.cpp | 188 + .../mkl-dnn/src/common/deconvolution_pd.hpp | 293 ++ .../oidn/mkl-dnn/src/common/eltwise.cpp | 84 + .../oidn/mkl-dnn/src/common/eltwise_pd.hpp | 161 + thirdparty/oidn/mkl-dnn/src/common/engine.cpp | 75 + thirdparty/oidn/mkl-dnn/src/common/engine.hpp | 119 + .../oidn/mkl-dnn/src/common/inner_product.cpp | 106 + .../mkl-dnn/src/common/inner_product_pd.cpp | 56 + .../mkl-dnn/src/common/inner_product_pd.hpp | 321 ++ thirdparty/oidn/mkl-dnn/src/common/lrn.cpp | 91 + thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp | 170 + .../oidn/mkl-dnn/src/common/math_utils.hpp | 280 + thirdparty/oidn/mkl-dnn/src/common/memory.cpp | 238 + thirdparty/oidn/mkl-dnn/src/common/memory.hpp | 63 + .../src/common/memory_desc_wrapper.cpp | 212 + .../src/common/memory_desc_wrapper.hpp | 400 ++ .../mkl-dnn/src/common/memory_tracking.hpp | 295 ++ .../oidn/mkl-dnn/src/common/mkldnn_debug.cpp | 131 + .../src/common/mkldnn_debug_autogenerated.cpp | 365 ++ .../oidn/mkl-dnn/src/common/mkldnn_thread.hpp | 115 + .../src/common/mkldnn_thread_parallel_nd.hpp | 277 + .../oidn/mkl-dnn/src/common/mkldnn_traits.hpp | 77 + thirdparty/oidn/mkl-dnn/src/common/nstl.hpp | 193 + .../oidn/mkl-dnn/src/common/pooling.cpp | 114 + .../oidn/mkl-dnn/src/common/pooling_pd.hpp | 238 + .../oidn/mkl-dnn/src/common/primitive.cpp | 103 + .../oidn/mkl-dnn/src/common/primitive.hpp | 76 + .../mkl-dnn/src/common/primitive_attr.cpp | 290 ++ .../mkl-dnn/src/common/primitive_attr.hpp | 183 + .../mkl-dnn/src/common/primitive_desc.cpp | 78 + .../mkl-dnn/src/common/primitive_desc.hpp | 174 + .../src/common/primitive_exec_types.cpp | 90 + .../src/common/primitive_exec_types.hpp | 68 + .../mkl-dnn/src/common/primitive_iterator.cpp | 89 + .../mkl-dnn/src/common/primitive_iterator.hpp | 79 + thirdparty/oidn/mkl-dnn/src/common/query.cpp | 59 + .../oidn/mkl-dnn/src/common/reorder.cpp | 68 + .../oidn/mkl-dnn/src/common/reorder_pd.hpp | 85 + thirdparty/oidn/mkl-dnn/src/common/rnn.cpp | 400 ++ thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp | 280 + .../oidn/mkl-dnn/src/common/scratchpad.cpp | 112 + .../oidn/mkl-dnn/src/common/scratchpad.hpp | 36 + .../oidn/mkl-dnn/src/common/shuffle.cpp | 72 + .../oidn/mkl-dnn/src/common/shuffle_pd.hpp | 121 + .../oidn/mkl-dnn/src/common/softmax.cpp | 68 + .../oidn/mkl-dnn/src/common/softmax_pd.hpp | 161 + thirdparty/oidn/mkl-dnn/src/common/stream.cpp | 46 + thirdparty/oidn/mkl-dnn/src/common/stream.hpp | 44 + thirdparty/oidn/mkl-dnn/src/common/sum.cpp | 79 + thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp | 143 + .../oidn/mkl-dnn/src/common/tag_traits.hpp | 200 + .../oidn/mkl-dnn/src/common/type_helpers.hpp | 348 ++ thirdparty/oidn/mkl-dnn/src/common/utils.cpp | 135 + thirdparty/oidn/mkl-dnn/src/common/utils.hpp | 370 ++ .../oidn/mkl-dnn/src/common/verbose.cpp | 665 +++ .../oidn/mkl-dnn/src/common/verbose.hpp | 62 + .../oidn/mkl-dnn/src/common/z_magic.hpp | 46 + .../oidn/mkl-dnn/src/cpu/cpu_barrier.cpp | 112 + .../oidn/mkl-dnn/src/cpu/cpu_barrier.hpp | 60 + .../src/cpu/cpu_batch_normalization_pd.hpp | 40 + .../src/cpu/cpu_batch_normalization_utils.cpp | 140 + .../src/cpu/cpu_batch_normalization_utils.hpp | 43 + .../oidn/mkl-dnn/src/cpu/cpu_concat.cpp | 51 + .../oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp | 41 + .../mkl-dnn/src/cpu/cpu_convolution_pd.hpp | 74 + .../mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp | 46 + .../oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp | 45 + .../oidn/mkl-dnn/src/cpu/cpu_engine.cpp | 324 ++ .../oidn/mkl-dnn/src/cpu/cpu_engine.hpp | 70 + .../mkl-dnn/src/cpu/cpu_inner_product_pd.hpp | 84 + .../oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp | 151 + .../oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp | 42 + .../oidn/mkl-dnn/src/cpu/cpu_memory.cpp | 277 + .../oidn/mkl-dnn/src/cpu/cpu_memory.hpp | 89 + .../oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp | 40 + .../oidn/mkl-dnn/src/cpu/cpu_primitive.hpp | 83 + .../oidn/mkl-dnn/src/cpu/cpu_reducer.cpp | 544 ++ .../oidn/mkl-dnn/src/cpu/cpu_reducer.hpp | 334 ++ .../oidn/mkl-dnn/src/cpu/cpu_reorder.cpp | 262 + .../oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp | 48 + .../oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp | 41 + .../oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp | 45 + thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp | 48 + .../oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp | 39 + .../src/cpu/gemm/f32/gemm_utils_f32.cpp | 372 ++ .../src/cpu/gemm/f32/gemm_utils_f32.hpp | 72 + .../gemm/f32/jit_avx512_common_gemm_f32.cpp | 2131 ++++++++ .../gemm/f32/jit_avx512_common_gemm_f32.hpp | 36 + .../src/cpu/gemm/f32/jit_avx_gemm_f32.cpp | 2705 ++++++++++ .../src/cpu/gemm/f32/jit_avx_gemm_f32.hpp | 37 + .../mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp | 346 ++ .../mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp | 36 + thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp | 280 + thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp | 58 + .../oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp | 86 + .../mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp | 206 + .../mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp | 28 + .../s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp | 1409 +++++ .../s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp | 38 + .../jit_avx512_core_gemm_s8u8s32_kern.cpp | 539 ++ .../jit_avx512_core_gemm_s8u8s32_kern.hpp | 101 + .../s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp | 290 ++ ...t_avx512_core_kernel_gemv_s8u8s32_kern.cpp | 411 ++ ...t_avx512_core_kernel_gemv_s8u8s32_kern.hpp | 64 + .../jit_avx512_core_u8_copy_an_kern.cpp | 819 +++ .../jit_avx512_core_u8_copy_at_kern.cpp | 2209 ++++++++ .../jit_avx512_core_u8_copy_bn_kern.cpp | 564 ++ .../jit_avx512_core_u8_copy_bt_kern.cpp | 501 ++ .../jit_avx512_core_u8_copy_sum_an_kern.cpp | 1283 +++++ .../jit_avx512_core_u8_copy_sum_at_kern.cpp | 3163 ++++++++++++ .../jit_avx512_core_u8_copy_sum_bn_kern.cpp | 821 +++ .../jit_avx512_core_u8_copy_sum_bt_kern.cpp | 647 +++ .../src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp | 116 + .../src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp | 38 + .../cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp | 180 + .../cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp | 37 + .../oidn/mkl-dnn/src/cpu/gemm_convolution.cpp | 307 ++ .../oidn/mkl-dnn/src/cpu/gemm_convolution.hpp | 250 + .../src/cpu/gemm_convolution_utils.cpp | 771 +++ .../src/cpu/gemm_convolution_utils.hpp | 66 + .../mkl-dnn/src/cpu/gemm_inner_product.cpp | 156 + .../mkl-dnn/src/cpu/gemm_inner_product.hpp | 157 + .../src/cpu/gemm_x8s8s32x_convolution.cpp | 740 +++ .../src/cpu/gemm_x8s8s32x_convolution.hpp | 266 + .../src/cpu/gemm_x8s8s32x_inner_product.cpp | 453 ++ .../src/cpu/gemm_x8s8s32x_inner_product.hpp | 166 + .../src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp | 674 +++ .../src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp | 110 + .../src/cpu/jit_avx2_1x1_convolution.cpp | 545 ++ .../src/cpu/jit_avx2_1x1_convolution.hpp | 344 ++ .../src/cpu/jit_avx2_conv_kernel_f32.cpp | 1501 ++++++ .../src/cpu/jit_avx2_conv_kernel_f32.hpp | 225 + .../mkl-dnn/src/cpu/jit_avx2_convolution.cpp | 410 ++ .../mkl-dnn/src/cpu/jit_avx2_convolution.hpp | 302 ++ .../cpu/jit_avx512_common_1x1_conv_kernel.cpp | 1255 +++++ .../cpu/jit_avx512_common_1x1_conv_kernel.hpp | 108 + .../cpu/jit_avx512_common_1x1_convolution.cpp | 816 +++ .../cpu/jit_avx512_common_1x1_convolution.hpp | 344 ++ .../src/cpu/jit_avx512_common_conv_kernel.cpp | 4539 +++++++++++++++++ .../src/cpu/jit_avx512_common_conv_kernel.hpp | 423 ++ ...avx512_common_conv_winograd_kernel_f32.cpp | 1163 +++++ ...avx512_common_conv_winograd_kernel_f32.hpp | 179 + .../src/cpu/jit_avx512_common_convolution.cpp | 1526 ++++++ .../src/cpu/jit_avx512_common_convolution.hpp | 302 ++ ...jit_avx512_common_convolution_winograd.cpp | 1215 +++++ ...jit_avx512_common_convolution_winograd.hpp | 318 ++ .../mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp | 853 ++++ .../mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp | 96 + .../jit_avx512_core_fp32_wino_conv_2x3.cpp | 1103 ++++ .../jit_avx512_core_fp32_wino_conv_2x3.hpp | 144 + .../jit_avx512_core_fp32_wino_conv_4x3.cpp | 1020 ++++ .../jit_avx512_core_fp32_wino_conv_4x3.hpp | 386 ++ ..._avx512_core_fp32_wino_conv_4x3_kernel.cpp | 2596 ++++++++++ ..._avx512_core_fp32_wino_conv_4x3_kernel.hpp | 291 ++ ..._avx512_core_u8s8s32x_wino_convolution.cpp | 1284 +++++ ..._avx512_core_u8s8s32x_wino_convolution.hpp | 128 + ...t_avx512_core_x8s8s32x_1x1_conv_kernel.cpp | 820 +++ ...t_avx512_core_x8s8s32x_1x1_conv_kernel.hpp | 131 + ...t_avx512_core_x8s8s32x_1x1_convolution.cpp | 292 ++ ...t_avx512_core_x8s8s32x_1x1_convolution.hpp | 159 + ...avx512_core_x8s8s32x_1x1_deconvolution.hpp | 140 + .../jit_avx512_core_x8s8s32x_conv_kernel.cpp | 1182 +++++ .../jit_avx512_core_x8s8s32x_conv_kernel.hpp | 239 + .../jit_avx512_core_x8s8s32x_convolution.cpp | 423 ++ .../jit_avx512_core_x8s8s32x_convolution.hpp | 115 + ...jit_avx512_core_x8s8s32x_deconvolution.cpp | 1034 ++++ ...jit_avx512_core_x8s8s32x_deconvolution.hpp | 237 + .../oidn/mkl-dnn/src/cpu/jit_generator.hpp | 773 +++ .../mkl-dnn/src/cpu/jit_primitive_conf.hpp | 481 ++ .../src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp | 677 +++ .../src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp | 104 + .../src/cpu/jit_sse42_1x1_convolution.cpp | 134 + .../src/cpu/jit_sse42_1x1_convolution.hpp | 96 + .../src/cpu/jit_sse42_conv_kernel_f32.cpp | 497 ++ .../src/cpu/jit_sse42_conv_kernel_f32.hpp | 93 + .../mkl-dnn/src/cpu/jit_sse42_convolution.cpp | 136 + .../mkl-dnn/src/cpu/jit_sse42_convolution.hpp | 103 + .../src/cpu/jit_transpose_src_utils.cpp | 1192 +++++ .../src/cpu/jit_transpose_src_utils.hpp | 145 + .../src/cpu/jit_uni_1x1_conv_utils.hpp | 327 ++ .../src/cpu/jit_uni_batch_normalization.cpp | 1407 +++++ .../src/cpu/jit_uni_batch_normalization.hpp | 100 + .../src/cpu/jit_uni_dw_conv_kernel_f32.cpp | 1302 +++++ .../src/cpu/jit_uni_dw_conv_kernel_f32.hpp | 253 + .../src/cpu/jit_uni_dw_convolution.cpp | 427 ++ .../src/cpu/jit_uni_dw_convolution.hpp | 266 + .../oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp | 1142 +++++ .../oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp | 193 + .../mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp | 949 ++++ .../mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp | 89 + .../oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp | 305 ++ .../oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp | 103 + .../src/cpu/jit_uni_lrn_kernel_f32.cpp | 1487 ++++++ .../src/cpu/jit_uni_lrn_kernel_f32.hpp | 183 + .../src/cpu/jit_uni_pool_kernel_f32.cpp | 699 +++ .../src/cpu/jit_uni_pool_kernel_f32.hpp | 192 + .../oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp | 264 + .../oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp | 182 + .../oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp | 1006 ++++ .../oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp | 127 + .../mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp | 313 ++ .../mkl-dnn/src/cpu/jit_utils/jit_utils.cpp | 115 + .../mkl-dnn/src/cpu/jit_utils/jit_utils.hpp | 32 + .../cpu/jit_utils/jitprofiling/LICENSE.BSD | 27 + .../src/cpu/jit_utils/jitprofiling/README.md | 1 + .../jit_utils/jitprofiling/ittnotify_config.h | 595 +++ .../jit_utils/jitprofiling/ittnotify_types.h | 94 + .../cpu/jit_utils/jitprofiling/jitprofiling.c | 293 ++ .../cpu/jit_utils/jitprofiling/jitprofiling.h | 673 +++ .../oidn/mkl-dnn/src/cpu/nchw_pooling.cpp | 317 ++ .../oidn/mkl-dnn/src/cpu/nchw_pooling.hpp | 147 + .../src/cpu/ncsp_batch_normalization.cpp | 382 ++ .../src/cpu/ncsp_batch_normalization.hpp | 160 + .../oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp | 392 ++ .../oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp | 210 + .../src/cpu/nspc_batch_normalization.cpp | 288 ++ .../src/cpu/nspc_batch_normalization.hpp | 169 + .../src/cpu/ref_batch_normalization.cpp | 265 + .../src/cpu/ref_batch_normalization.hpp | 127 + .../oidn/mkl-dnn/src/cpu/ref_concat.hpp | 97 + .../oidn/mkl-dnn/src/cpu/ref_convolution.cpp | 395 ++ .../oidn/mkl-dnn/src/cpu/ref_convolution.hpp | 194 + .../mkl-dnn/src/cpu/ref_deconvolution.cpp | 199 + .../mkl-dnn/src/cpu/ref_deconvolution.hpp | 502 ++ .../oidn/mkl-dnn/src/cpu/ref_eltwise.cpp | 297 ++ .../oidn/mkl-dnn/src/cpu/ref_eltwise.hpp | 168 + .../mkl-dnn/src/cpu/ref_inner_product.cpp | 285 ++ .../mkl-dnn/src/cpu/ref_inner_product.hpp | 159 + thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp | 252 + thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp | 136 + .../oidn/mkl-dnn/src/cpu/ref_pooling.cpp | 381 ++ .../oidn/mkl-dnn/src/cpu/ref_pooling.hpp | 119 + .../oidn/mkl-dnn/src/cpu/ref_shuffle.cpp | 153 + .../oidn/mkl-dnn/src/cpu/ref_shuffle.hpp | 111 + .../oidn/mkl-dnn/src/cpu/ref_softmax.cpp | 264 + .../oidn/mkl-dnn/src/cpu/ref_softmax.hpp | 186 + thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp | 101 + .../oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp | 90 + .../oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp | 180 + .../oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp | 170 + .../oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp | 143 + .../oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp | 113 + .../oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp | 191 + .../src/cpu/rnn/jit_uni_rnn_postgemm.hpp | 401 ++ .../oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp | 788 +++ .../oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp | 328 ++ .../oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp | 380 ++ .../oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp | 426 ++ .../oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp | 225 + .../oidn/mkl-dnn/src/cpu/simple_concat.cpp | 126 + .../oidn/mkl-dnn/src/cpu/simple_concat.hpp | 155 + .../oidn/mkl-dnn/src/cpu/simple_q10n.hpp | 98 + .../oidn/mkl-dnn/src/cpu/simple_reorder.hpp | 1022 ++++ .../oidn/mkl-dnn/src/cpu/simple_sum.cpp | 91 + .../oidn/mkl-dnn/src/cpu/simple_sum.hpp | 74 + .../oidn/mkl-dnn/src/cpu/wino_reorder.hpp | 376 ++ .../oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT | 47 + thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h | 2658 ++++++++++ .../mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h | 303 ++ .../mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h | 2017 ++++++++ .../oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h | 772 +++ thirdparty/oidn/weights/rtlightmap_hdr.tza | Bin 0 -> 5660131 bytes thirdparty/r128/r128.h | 2124 ++++++++ thirdparty/stb_rect_pack/stb_rect_pack.h | 629 +++ thirdparty/xatlas/xatlas.cpp | 1912 +++---- 434 files changed, 126122 insertions(+), 3384 deletions(-) create mode 100644 core/local_vector.h create mode 100644 core/math/delaunay_3d.h create mode 100644 core/math/r128.cpp create mode 100644 editor/plugins/texture_layered_editor_plugin.cpp create mode 100644 editor/plugins/texture_layered_editor_plugin.h create mode 100644 modules/denoise/SCsub create mode 100644 modules/denoise/config.py create mode 100644 modules/denoise/denoise_wrapper.cpp create mode 100644 modules/denoise/denoise_wrapper.h create mode 100644 modules/denoise/lightmap_denoiser.cpp create mode 100644 modules/denoise/lightmap_denoiser.h create mode 100644 modules/denoise/register_types.cpp create mode 100644 modules/denoise/register_types.h create mode 100644 modules/denoise/resource_to_cpp.py create mode 100644 modules/lightmapper_rd/SCsub create mode 100644 modules/lightmapper_rd/config.py create mode 100644 modules/lightmapper_rd/lightmapper_rd.cpp create mode 100644 modules/lightmapper_rd/lightmapper_rd.h create mode 100644 modules/lightmapper_rd/lm_blendseams.glsl create mode 100644 modules/lightmapper_rd/lm_common_inc.glsl create mode 100644 modules/lightmapper_rd/lm_compute.glsl create mode 100644 modules/lightmapper_rd/lm_raster.glsl create mode 100644 modules/lightmapper_rd/register_types.cpp create mode 100644 modules/lightmapper_rd/register_types.h create mode 100644 scene/3d/lightmap_probe.cpp create mode 100644 scene/3d/lightmap_probe.h create mode 100644 scene/3d/lightmapper.cpp create mode 100644 scene/3d/lightmapper.h create mode 100644 thirdparty/oidn/.gitignore create mode 100644 thirdparty/oidn/common/barrier.h create mode 100644 thirdparty/oidn/common/exception.h create mode 100644 thirdparty/oidn/common/platform.cpp create mode 100644 thirdparty/oidn/common/platform.h create mode 100644 thirdparty/oidn/common/ref.h create mode 100644 thirdparty/oidn/common/tensor.cpp create mode 100644 thirdparty/oidn/common/tensor.h create mode 100644 thirdparty/oidn/common/thread.cpp create mode 100644 thirdparty/oidn/common/thread.h create mode 100644 thirdparty/oidn/common/timer.h create mode 100644 thirdparty/oidn/core/api.cpp create mode 100644 thirdparty/oidn/core/autoencoder.cpp create mode 100644 thirdparty/oidn/core/autoencoder.h create mode 100644 thirdparty/oidn/core/buffer.h create mode 100644 thirdparty/oidn/core/common.h create mode 100644 thirdparty/oidn/core/device.cpp create mode 100644 thirdparty/oidn/core/device.h create mode 100644 thirdparty/oidn/core/filter.cpp create mode 100644 thirdparty/oidn/core/filter.h create mode 100644 thirdparty/oidn/core/image.h create mode 100644 thirdparty/oidn/core/input_reorder.h create mode 100644 thirdparty/oidn/core/math.h create mode 100644 thirdparty/oidn/core/network.cpp create mode 100644 thirdparty/oidn/core/network.h create mode 100644 thirdparty/oidn/core/node.h create mode 100644 thirdparty/oidn/core/output_reorder.h create mode 100644 thirdparty/oidn/core/transfer_function.cpp create mode 100644 thirdparty/oidn/core/transfer_function.h create mode 100644 thirdparty/oidn/core/upsample.h create mode 100644 thirdparty/oidn/core/weights_reorder.h create mode 100644 thirdparty/oidn/include/OpenImageDenoise/oidn.h create mode 100644 thirdparty/oidn/include/OpenImageDenoise/oidn.hpp create mode 100644 thirdparty/oidn/include/OpenImageDenoise/version.h create mode 100644 thirdparty/oidn/mkl-dnn/LICENSE create mode 100644 thirdparty/oidn/mkl-dnn/include/mkldnn.h create mode 100644 thirdparty/oidn/mkl-dnn/include/mkldnn.hpp create mode 100644 thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h create mode 100644 thirdparty/oidn/mkl-dnn/include/mkldnn_types.h create mode 100644 thirdparty/oidn/mkl-dnn/include/mkldnn_version.h create mode 100644 thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in create mode 100644 thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/concat.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/engine.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/engine.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/lrn.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/memory.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/memory.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/nstl.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/pooling.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/query.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/reorder.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/rnn.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/softmax.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/stream.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/stream.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/sum.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/utils.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/verbose.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/verbose.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h create mode 100644 thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h create mode 100644 thirdparty/oidn/weights/rtlightmap_hdr.tza create mode 100644 thirdparty/r128/r128.h create mode 100644 thirdparty/stb_rect_pack/stb_rect_pack.h diff --git a/SConstruct b/SConstruct index e866a4c998..0c91399a12 100644 --- a/SConstruct +++ b/SConstruct @@ -598,6 +598,13 @@ if selected_platform in platform_list: ) } ) + env.Append( + BUILDERS={ + "GLSL_HEADER": env.Builder( + action=run_in_subprocess(gles_builders.build_raw_headers), suffix="glsl.gen.h", src_suffix=".glsl" + ) + } + ) scons_cache_path = os.environ.get("SCONS_CACHE") if scons_cache_path != None: diff --git a/core/error_macros.h b/core/error_macros.h index 18c46c9e7d..83f92129a5 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -530,19 +530,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Prints `m_msg`. */ #define ERR_PRINT(m_msg) \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)) + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg) /** * Prints `m_msg` once during the application lifetime. */ -#define ERR_PRINT_ONCE(m_msg) \ - if (1) { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)); \ - first_print = false; \ - } \ - } else \ +#define ERR_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \ + first_print = false; \ + } \ + } else \ ((void)0) // Print warning message macros. @@ -553,21 +553,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ #define WARN_PRINT(m_msg) \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING) + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING) /** * Prints `m_msg` once during the application lifetime. * * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_PRINT_ONCE(m_msg) \ - if (1) { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ - first_print = false; \ - } \ - } else \ +#define WARN_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING); \ + first_print = false; \ + } \ + } else \ ((void)0) // Print deprecated warning message macros. diff --git a/core/image.cpp b/core/image.cpp index 6f18516ae1..ff8acc54af 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -3668,6 +3668,10 @@ Ref Image::duplicate(bool p_subresources) const { return copy; } +void Image::set_as_black() { + zeromem(data.ptrw(), data.size()); +} + Image::Image() { width = 0; diff --git a/core/image.h b/core/image.h index 5bd73fa677..07b4f49751 100644 --- a/core/image.h +++ b/core/image.h @@ -376,6 +376,8 @@ public: void set_pixelv(const Point2 &p_dst, const Color &p_color); void set_pixel(int p_x, int p_y, const Color &p_color); + void set_as_black(); + void copy_internals_from(const Ref &p_image) { ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object."); format = p_image->format; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 8c7559479b..e0fea143bb 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -337,10 +337,14 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case OBJECT_INTERNAL_RESOURCE: { uint32_t index = f->get_32(); + String path = res_path + "::" + itos(index); + if (use_nocache) { - r_v = internal_resources[index].cache; + if (!internal_index_cache.has(path)) { + WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data()); + } + r_v = internal_index_cache[path]; } else { - String path = res_path + "::" + itos(index); RES res = ResourceLoader::load(path); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); @@ -720,13 +724,15 @@ Error ResourceLoaderBinary::load() { if (!main) { + path = internal_resources[i].path; + + if (path.begins_with("local://")) { + path = path.replace_first("local://", ""); + subindex = path.to_int(); + path = res_path + "::" + path; + } + if (!use_nocache) { - path = internal_resources[i].path; - if (path.begins_with("local://")) { - path = path.replace_first("local://", ""); - subindex = path.to_int(); - path = res_path + "::" + path; - } if (ResourceCache::has(path)) { //already loaded, don't do anything @@ -769,7 +775,7 @@ Error ResourceLoaderBinary::load() { r->set_subindex(subindex); if (!main) { - internal_resources.write[i].cache = res; + internal_index_cache[path] = res; } int pc = f->get_32(); diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 0f8fc9445b..3c8d916c0a 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -68,10 +68,10 @@ class ResourceLoaderBinary { struct IntResource { String path; uint64_t offset; - RES cache; }; Vector internal_resources; + Map internal_index_cache; String get_unicode_string(); void _advance_padding(uint32_t p_len); diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 643df53f8c..9e22bdced7 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -91,7 +91,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy r_path_and_type.path = value; path_found = true; //first match must have priority } else if (assign == "type") { - r_path_and_type.type = value; + r_path_and_type.type = ClassDB::get_compatibility_remapped_class(value); } else if (assign == "importer") { r_path_and_type.importer = value; } else if (assign == "group_file") { diff --git a/core/local_vector.h b/core/local_vector.h new file mode 100644 index 0000000000..0b0ef6dfdc --- /dev/null +++ b/core/local_vector.h @@ -0,0 +1,246 @@ +/*************************************************************************/ +/* local_vector.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LOCAL_VECTOR_H +#define LOCAL_VECTOR_H + +#include "core/error_macros.h" +#include "core/os/copymem.h" +#include "core/os/memory.h" +#include "core/sort_array.h" +#include "core/vector.h" + +template +class LocalVector { +private: + U count = 0; + U capacity = 0; + T *data = nullptr; + +public: + _FORCE_INLINE_ void push_back(T p_elem) { + if (unlikely(count == capacity)) { + if (capacity == 0) { + capacity = 1; + } else { + capacity <<= 1; + } + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + + if (!__has_trivial_constructor(T) && !force_trivial) { + memnew_placement(&data[count++], T(p_elem)); + } else { + data[count++] = p_elem; + } + } + + void remove(U p_index) { + ERR_FAIL_UNSIGNED_INDEX(p_index, count); + for (U i = p_index; i < count; i++) { + data[i] = data[i + 1]; + } + count--; + if (!__has_trivial_destructor(T) && !force_trivial) { + data[count].~T(); + } + } + + void erase(const T &p_val) { + U idx = find(p_val); + if (idx >= 0) + remove(idx); + } + + void invert() { + + for (U i = 0; i < count / 2; i++) { + SWAP(data[i], data[count - i - 1]); + } + } + + _FORCE_INLINE_ void clear() { resize(0); } + _FORCE_INLINE_ void reset() { + clear(); + if (data) { + memfree(data); + data = nullptr; + capacity = 0; + } + } + _FORCE_INLINE_ bool empty() const { return count == 0; } + _FORCE_INLINE_ void reserve(U p_size) { + p_size = nearest_power_of_2_templated(p_size); + if (p_size > capacity) { + capacity = p_size; + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + } + + _FORCE_INLINE_ U size() const { return count; } + void resize(U p_size) { + + if (p_size < count) { + + if (!__has_trivial_destructor(T) && !force_trivial) { + for (U i = p_size; i < count; i++) { + data[i].~T(); + } + } + count = p_size; + } else if (p_size > count) { + + if (unlikely(p_size > capacity)) { + if (capacity == 0) { + capacity = 1; + } + while (capacity < p_size) { + capacity <<= 1; + } + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + if (!__has_trivial_constructor(T) && !force_trivial) { + for (U i = count; i < p_size; i++) { + memnew_placement(&data[i], T); + } + } + count = p_size; + } + } + _FORCE_INLINE_ const T &operator[](U p_index) const { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + return data[p_index]; + } + _FORCE_INLINE_ T &operator[](U p_index) { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + return data[p_index]; + } + + void insert(U p_pos, T p_val) { + ERR_FAIL_UNSIGNED_INDEX(p_pos, count + 1); + if (p_pos == count) { + push_back(p_val); + } else { + resize(count + 1); + for (U i = count; i > p_pos; i--) { + data[i] = data[i - 1]; + } + data[p_pos] = p_val; + } + } + + int64_t find(const T &p_val, U p_from = 0) const { + + for (U i = 0; i < count; i++) { + if (data[i] == p_val) { + return int64_t(i); + } + } + return -1; + } + + template + void sort_custom() { + + U len = count; + if (len == 0) + return; + + SortArray sorter; + sorter.sort(data, len); + } + + void sort() { + + sort_custom<_DefaultComparator>(); + } + + void ordered_insert(T p_val) { + + U i; + for (i = 0; i < count; i++) { + + if (p_val < data[i]) { + break; + }; + }; + insert(i, p_val); + } + + operator Vector() const { + Vector ret; + ret.resize(size()); + T *w = ret.ptrw(); + copymem(w, data, sizeof(T) * count); + return ret; + } + + Vector to_byte_array() const { //useful to pass stuff to gpu or variant + Vector ret; + ret.resize(count * sizeof(T)); + uint8_t *w = ret.ptrw(); + copymem(w, data, sizeof(T) * count); + return ret; + } + + _FORCE_INLINE_ LocalVector() {} + _FORCE_INLINE_ LocalVector(const LocalVector &p_from) { + resize(p_from.size()); + for (U i = 0; i < p_from.count; i++) { + data[i] = p_from.data[i]; + } + } + inline LocalVector &operator=(const LocalVector &p_from) { + resize(p_from.size()); + for (U i = 0; i < p_from.count; i++) { + data[i] = p_from.data[i]; + } + return *this; + } + inline LocalVector &operator=(const Vector &p_from) { + resize(p_from.size()); + for (U i = 0; i < count; i++) { + data[i] = p_from[i]; + } + return *this; + } + + _FORCE_INLINE_ ~LocalVector() { + + if (data) { + reset(); + } + } +}; + +#endif // LOCAL_VECTOR_H diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 87abf2dbc1..6218b7e248 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -878,3 +878,114 @@ Basis Basis::slerp(const Basis &target, const real_t &t) const { return b; } + +void Basis::rotate_sh(real_t *p_values) { + + // code by John Hable + // http://filmicworlds.com/blog/simple-and-fast-spherical-harmonic-rotation/ + // this code is Public Domain + + const static real_t s_c3 = 0.94617469575; // (3*sqrt(5))/(4*sqrt(pi)) + const static real_t s_c4 = -0.31539156525; // (-sqrt(5))/(4*sqrt(pi)) + const static real_t s_c5 = 0.54627421529; // (sqrt(15))/(4*sqrt(pi)) + + const static real_t s_c_scale = 1.0 / 0.91529123286551084; + const static real_t s_c_scale_inv = 0.91529123286551084; + + const static real_t s_rc2 = 1.5853309190550713 * s_c_scale; + const static real_t s_c4_div_c3 = s_c4 / s_c3; + const static real_t s_c4_div_c3_x2 = (s_c4 / s_c3) * 2.0; + + const static real_t s_scale_dst2 = s_c3 * s_c_scale_inv; + const static real_t s_scale_dst4 = s_c5 * s_c_scale_inv; + + real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] }; + + real_t m00 = elements[0][0]; + real_t m01 = elements[0][1]; + real_t m02 = elements[0][2]; + real_t m10 = elements[1][0]; + real_t m11 = elements[1][1]; + real_t m12 = elements[1][2]; + real_t m20 = elements[2][0]; + real_t m21 = elements[2][1]; + real_t m22 = elements[2][2]; + + p_values[0] = src[0]; + p_values[1] = m11 * src[1] - m12 * src[2] + m10 * src[3]; + p_values[2] = -m21 * src[1] + m22 * src[2] - m20 * src[3]; + p_values[3] = m01 * src[1] - m02 * src[2] + m00 * src[3]; + + real_t sh0 = src[7] + src[8] + src[8] - src[5]; + real_t sh1 = src[4] + s_rc2 * src[6] + src[7] + src[8]; + real_t sh2 = src[4]; + real_t sh3 = -src[7]; + real_t sh4 = -src[5]; + + // Rotations. R0 and R1 just use the raw matrix columns + real_t r2x = m00 + m01; + real_t r2y = m10 + m11; + real_t r2z = m20 + m21; + + real_t r3x = m00 + m02; + real_t r3y = m10 + m12; + real_t r3z = m20 + m22; + + real_t r4x = m01 + m02; + real_t r4y = m11 + m12; + real_t r4z = m21 + m22; + + // dense matrix multiplication one column at a time + + // column 0 + real_t sh0_x = sh0 * m00; + real_t sh0_y = sh0 * m10; + real_t d0 = sh0_x * m10; + real_t d1 = sh0_y * m20; + real_t d2 = sh0 * (m20 * m20 + s_c4_div_c3); + real_t d3 = sh0_x * m20; + real_t d4 = sh0_x * m00 - sh0_y * m10; + + // column 1 + real_t sh1_x = sh1 * m02; + real_t sh1_y = sh1 * m12; + d0 += sh1_x * m12; + d1 += sh1_y * m22; + d2 += sh1 * (m22 * m22 + s_c4_div_c3); + d3 += sh1_x * m22; + d4 += sh1_x * m02 - sh1_y * m12; + + // column 2 + real_t sh2_x = sh2 * r2x; + real_t sh2_y = sh2 * r2y; + d0 += sh2_x * r2y; + d1 += sh2_y * r2z; + d2 += sh2 * (r2z * r2z + s_c4_div_c3_x2); + d3 += sh2_x * r2z; + d4 += sh2_x * r2x - sh2_y * r2y; + + // column 3 + real_t sh3_x = sh3 * r3x; + real_t sh3_y = sh3 * r3y; + d0 += sh3_x * r3y; + d1 += sh3_y * r3z; + d2 += sh3 * (r3z * r3z + s_c4_div_c3_x2); + d3 += sh3_x * r3z; + d4 += sh3_x * r3x - sh3_y * r3y; + + // column 4 + real_t sh4_x = sh4 * r4x; + real_t sh4_y = sh4 * r4y; + d0 += sh4_x * r4y; + d1 += sh4_y * r4z; + d2 += sh4 * (r4z * r4z + s_c4_div_c3_x2); + d3 += sh4_x * r4z; + d4 += sh4_x * r4x - sh4_y * r4y; + + // extra multipliers + p_values[4] = d0; + p_values[5] = -d1; + p_values[6] = d2 * s_scale_dst2; + p_values[7] = -d3; + p_values[8] = d4 * s_scale_dst4; +} diff --git a/core/math/basis.h b/core/math/basis.h index 0261cf67c6..2924a0ddbd 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -159,6 +159,7 @@ public: bool is_rotation() const; Basis slerp(const Basis &target, const real_t &t) const; + void rotate_sh(real_t *p_values); operator String() const; diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 76321b0679..5d3ebc9f6d 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -33,6 +33,22 @@ #include "core/math/math_funcs.h" #include "core/print_string.h" +float CameraMatrix::determinant() const { + + return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] - + matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] + + matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] - + matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] + matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] + + matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] - matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] - + matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] + matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] + + matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] - matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] - + matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] + + matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] - matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] - + matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] + matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] + + matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] - + matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3]; +} + void CameraMatrix::set_identity() { for (int i = 0; i < 4; i++) { diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index c10193bc84..5420fa2984 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -47,6 +47,7 @@ struct CameraMatrix { real_t matrix[4][4]; + float determinant() const; void set_identity(); void set_zero(); void set_light_bias(); diff --git a/core/math/delaunay.h b/core/math/delaunay.h index 29f84210d2..6f19f3e58a 100644 --- a/core/math/delaunay.h +++ b/core/math/delaunay.h @@ -115,8 +115,6 @@ public: triangles.push_back(Triangle(p_points.size() + 0, p_points.size() + 1, p_points.size() + 2)); for (int i = 0; i < p_points.size(); i++) { - //std::cout << "Traitement du point " << *p << std::endl; - //std::cout << "_triangles contains " << _triangles.size() << " elements" << std::endl; Vector polygon; diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h new file mode 100644 index 0000000000..6280ec8071 --- /dev/null +++ b/core/math/delaunay_3d.h @@ -0,0 +1,386 @@ +#ifndef DELAUNAY_3D_H +#define DELAUNAY_3D_H + +#include "core/local_vector.h" +#include "core/math/aabb.h" +#include "core/math/camera_matrix.h" +#include "core/math/vector3.h" +#include "core/oa_hash_map.h" +#include "core/os/file_access.h" +#include "core/print_string.h" +#include "core/variant.h" +#include "core/vector.h" +#include "thirdparty/r128/r128.h" + +class Delaunay3D { + struct Simplex; + + enum { + ACCEL_GRID_SIZE = 16 + }; + struct GridPos { + Vector3i pos; + List::Element *E = nullptr; + }; + + struct Simplex { + + uint32_t points[4]; + R128 circum_center_x; + R128 circum_center_y; + R128 circum_center_z; + R128 circum_r2; + LocalVector grid_positions; + List::Element *SE = nullptr; + + _FORCE_INLINE_ Simplex() {} + _FORCE_INLINE_ Simplex(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d) { + points[0] = p_a; + points[1] = p_b; + points[2] = p_c; + points[3] = p_d; + } + }; + + struct Triangle { + uint32_t triangle[3]; + bool bad; + _FORCE_INLINE_ bool operator==(const Triangle &p_triangle) const { + return triangle[0] == p_triangle.triangle[0] && triangle[1] == p_triangle.triangle[1] && triangle[2] == p_triangle.triangle[2]; + } + + _FORCE_INLINE_ Triangle() { bad = false; } + _FORCE_INLINE_ Triangle(uint32_t p_a, uint32_t p_b, uint32_t p_c) { + if (p_a > p_b) + SWAP(p_a, p_b); + if (p_b > p_c) + SWAP(p_b, p_c); + if (p_a > p_b) + SWAP(p_a, p_b); + + bad = false; + triangle[0] = p_a; + triangle[1] = p_b; + triangle[2] = p_c; + } + }; + + struct TriangleHasher { + _FORCE_INLINE_ static uint32_t hash(const Triangle &p_triangle) { + uint32_t h = hash_djb2_one_32(p_triangle.triangle[0]); + h = hash_djb2_one_32(p_triangle.triangle[1], h); + return hash_djb2_one_32(p_triangle.triangle[2], h); + } + }; + + struct FPVal { + }; + + _FORCE_INLINE_ static void circum_sphere_compute(const Vector3 *p_points, Simplex *p_simplex) { + + // the only part in the algorithm where there may be precision errors is this one, so ensure that + // we do it as maximum precision as possible + + R128 v0_x = p_points[p_simplex->points[0]].x; + R128 v0_y = p_points[p_simplex->points[0]].y; + R128 v0_z = p_points[p_simplex->points[0]].z; + R128 v1_x = p_points[p_simplex->points[1]].x; + R128 v1_y = p_points[p_simplex->points[1]].y; + R128 v1_z = p_points[p_simplex->points[1]].z; + R128 v2_x = p_points[p_simplex->points[2]].x; + R128 v2_y = p_points[p_simplex->points[2]].y; + R128 v2_z = p_points[p_simplex->points[2]].z; + R128 v3_x = p_points[p_simplex->points[3]].x; + R128 v3_y = p_points[p_simplex->points[3]].y; + R128 v3_z = p_points[p_simplex->points[3]].z; + + //Create the rows of our "unrolled" 3x3 matrix + R128 row1_x = v1_x - v0_x; + R128 row1_y = v1_y - v0_y; + R128 row1_z = v1_z - v0_z; + + R128 row2_x = v2_x - v0_x; + R128 row2_y = v2_y - v0_y; + R128 row2_z = v2_z - v0_z; + + R128 row3_x = v3_x - v0_x; + R128 row3_y = v3_y - v0_y; + R128 row3_z = v3_z - v0_z; + + R128 sq_lenght1 = row1_x * row1_x + row1_y * row1_y + row1_z * row1_z; + R128 sq_lenght2 = row2_x * row2_x + row2_y * row2_y + row2_z * row2_z; + R128 sq_lenght3 = row3_x * row3_x + row3_y * row3_y + row3_z * row3_z; + + //Compute the determinant of said matrix + R128 determinant = row1_x * (row2_y * row3_z - row3_y * row2_z) - row2_x * (row1_y * row3_z - row3_y * row1_z) + row3_x * (row1_y * row2_z - row2_y * row1_z); + + // Compute the volume of the tetrahedron, and precompute a scalar quantity for re-use in the formula + R128 volume = determinant / R128(6.f); + R128 i12volume = R128(1.f) / (volume * R128(12.f)); + + R128 center_x = v0_x + i12volume * ((row2_y * row3_z - row3_y * row2_z) * sq_lenght1 - (row1_y * row3_z - row3_y * row1_z) * sq_lenght2 + (row1_y * row2_z - row2_y * row1_z) * sq_lenght3); + R128 center_y = v0_y + i12volume * (-(row2_x * row3_z - row3_x * row2_z) * sq_lenght1 + (row1_x * row3_z - row3_x * row1_z) * sq_lenght2 - (row1_x * row2_z - row2_x * row1_z) * sq_lenght3); + R128 center_z = v0_z + i12volume * ((row2_x * row3_y - row3_x * row2_y) * sq_lenght1 - (row1_x * row3_y - row3_x * row1_y) * sq_lenght2 + (row1_x * row2_y - row2_x * row1_y) * sq_lenght3); + + //Once we know the center, the radius is clearly the distance to any vertex + + R128 rel1_x = center_x - v0_x; + R128 rel1_y = center_y - v0_y; + R128 rel1_z = center_z - v0_z; + + R128 radius1 = rel1_x * rel1_x + rel1_y * rel1_y + rel1_z * rel1_z; + + p_simplex->circum_center_x = center_x; + p_simplex->circum_center_y = center_y; + p_simplex->circum_center_z = center_z; + p_simplex->circum_r2 = radius1; + } + + _FORCE_INLINE_ static bool simplex_contains(const Vector3 *p_points, const Simplex &p_simplex, uint32_t p_vertex) { + + R128 v_x = p_points[p_vertex].x; + R128 v_y = p_points[p_vertex].y; + R128 v_z = p_points[p_vertex].z; + + R128 rel2_x = p_simplex.circum_center_x - v_x; + R128 rel2_y = p_simplex.circum_center_y - v_y; + R128 rel2_z = p_simplex.circum_center_z - v_z; + + R128 radius2 = rel2_x * rel2_x + rel2_y * rel2_y + rel2_z * rel2_z; + + return radius2 < (p_simplex.circum_r2 - R128(0.00001)); + } + + static bool simplex_is_coplanar(const Vector3 *p_points, const Simplex &p_simplex) { + + Plane p(p_points[p_simplex.points[0]], p_points[p_simplex.points[1]], p_points[p_simplex.points[2]]); + if (ABS(p.distance_to(p_points[p_simplex.points[3]])) < CMP_EPSILON) { + return true; + } + + CameraMatrix cm; + + cm.matrix[0][0] = p_points[p_simplex.points[0]].x; + cm.matrix[0][1] = p_points[p_simplex.points[1]].x; + cm.matrix[0][2] = p_points[p_simplex.points[2]].x; + cm.matrix[0][3] = p_points[p_simplex.points[3]].x; + + cm.matrix[1][0] = p_points[p_simplex.points[0]].y; + cm.matrix[1][1] = p_points[p_simplex.points[1]].y; + cm.matrix[1][2] = p_points[p_simplex.points[2]].y; + cm.matrix[1][3] = p_points[p_simplex.points[3]].y; + + cm.matrix[2][0] = p_points[p_simplex.points[0]].z; + cm.matrix[2][1] = p_points[p_simplex.points[1]].z; + cm.matrix[2][2] = p_points[p_simplex.points[2]].z; + cm.matrix[2][3] = p_points[p_simplex.points[3]].z; + + cm.matrix[3][0] = 1.0; + cm.matrix[3][1] = 1.0; + cm.matrix[3][2] = 1.0; + cm.matrix[3][3] = 1.0; + + return ABS(cm.determinant()) <= CMP_EPSILON; + } + +public: + struct OutputSimplex { + uint32_t points[4]; + }; + + static Vector tetrahedralize(const Vector &p_points) { + + uint32_t point_count = p_points.size(); + Vector3 *points = (Vector3 *)memalloc(sizeof(Vector3) * (point_count + 4)); + + { + const Vector3 *src_points = p_points.ptr(); + AABB rect; + for (uint32_t i = 0; i < point_count; i++) { + Vector3 point = src_points[i]; + if (i == 0) { + rect.position = point; + } else { + rect.expand_to(point); + } + points[i] = point; + } + + for (uint32_t i = 0; i < point_count; i++) { + points[i] = (points[i] - rect.position) / rect.size; + } + + float delta_max = Math::sqrt(2.0) * 20.0; + Vector3 center = Vector3(0.5, 0.5, 0.5); + + // any simplex that contains everything is good + points[point_count + 0] = center + Vector3(0, 1, 0) * delta_max; + points[point_count + 1] = center + Vector3(0, -1, 1) * delta_max; + points[point_count + 2] = center + Vector3(1, -1, -1) * delta_max; + points[point_count + 3] = center + Vector3(-1, -1, -1) * delta_max; + } + + List acceleration_grid[ACCEL_GRID_SIZE][ACCEL_GRID_SIZE][ACCEL_GRID_SIZE]; + + List simplex_list; + { + //create root simplex + Simplex *root = memnew(Simplex(point_count + 0, point_count + 1, point_count + 2, point_count + 3)); + root->SE = simplex_list.push_back(root); + + for (uint32_t i = 0; i < ACCEL_GRID_SIZE; i++) { + for (uint32_t j = 0; j < ACCEL_GRID_SIZE; j++) { + for (uint32_t k = 0; k < ACCEL_GRID_SIZE; k++) { + GridPos gp; + gp.E = acceleration_grid[i][j][k].push_back(root); + gp.pos = Vector3i(i, j, k); + root->grid_positions.push_back(gp); + } + } + } + + circum_sphere_compute(points, root); + } + + OAHashMap triangles_inserted; + LocalVector triangles; + + for (uint32_t i = 0; i < point_count; i++) { + + bool unique = true; + for (uint32_t j = i + 1; j < point_count; j++) { + if (points[i].is_equal_approx(points[j])) { + unique = false; + break; + } + } + if (!unique) { + continue; + } + + Vector3i grid_pos = Vector3i(points[i] * ACCEL_GRID_SIZE); + grid_pos.x = CLAMP(grid_pos.x, 0, ACCEL_GRID_SIZE - 1); + grid_pos.y = CLAMP(grid_pos.y, 0, ACCEL_GRID_SIZE - 1); + grid_pos.z = CLAMP(grid_pos.z, 0, ACCEL_GRID_SIZE - 1); + + for (List::Element *E = acceleration_grid[grid_pos.x][grid_pos.y][grid_pos.z].front(); E;) { + List::Element *N = E->next(); //may be deleted + + Simplex *simplex = E->get(); + + if (simplex_contains(points, *simplex, i)) { + + static const uint32_t triangle_order[4][3] = { + { 0, 1, 2 }, + { 0, 1, 3 }, + { 0, 2, 3 }, + { 1, 2, 3 }, + }; + + for (uint32_t k = 0; k < 4; k++) { + Triangle t = Triangle(simplex->points[triangle_order[k][0]], simplex->points[triangle_order[k][1]], simplex->points[triangle_order[k][2]]); + uint32_t *p = triangles_inserted.lookup_ptr(t); + if (p) { + triangles[*p].bad = true; + } else { + triangles_inserted.insert(t, triangles.size()); + triangles.push_back(t); + } + } + + //remove simplex and continue + simplex_list.erase(simplex->SE); + + for (uint32_t k = 0; k < simplex->grid_positions.size(); k++) { + Vector3i p = simplex->grid_positions[k].pos; + acceleration_grid[p.x][p.y][p.z].erase(simplex->grid_positions[k].E); + } + memdelete(simplex); + } + E = N; + } + + uint32_t good_triangles = 0; + for (uint32_t j = 0; j < triangles.size(); j++) { + + if (triangles[j].bad) { + continue; + } + Simplex *new_simplex = memnew(Simplex(triangles[j].triangle[0], triangles[j].triangle[1], triangles[j].triangle[2], i)); + circum_sphere_compute(points, new_simplex); + new_simplex->SE = simplex_list.push_back(new_simplex); + { + Vector3 center; + center.x = double(new_simplex->circum_center_x); + center.y = double(new_simplex->circum_center_y); + center.z = double(new_simplex->circum_center_z); + + float radius2 = Math::sqrt(double(new_simplex->circum_r2)); + radius2 += 0.0001; // + Vector3 extents = Vector3(radius2, radius2, radius2); + Vector3i from = Vector3i((center - extents) * ACCEL_GRID_SIZE); + Vector3i to = Vector3i((center + extents) * ACCEL_GRID_SIZE); + from.x = CLAMP(from.x, 0, ACCEL_GRID_SIZE - 1); + from.y = CLAMP(from.y, 0, ACCEL_GRID_SIZE - 1); + from.z = CLAMP(from.z, 0, ACCEL_GRID_SIZE - 1); + to.x = CLAMP(to.x, 0, ACCEL_GRID_SIZE - 1); + to.y = CLAMP(to.y, 0, ACCEL_GRID_SIZE - 1); + to.z = CLAMP(to.z, 0, ACCEL_GRID_SIZE - 1); + + for (int32_t x = from.x; x <= to.x; x++) { + for (int32_t y = from.y; y <= to.y; y++) { + for (int32_t z = from.z; z <= to.z; z++) { + GridPos gp; + gp.pos = Vector3(x, y, z); + gp.E = acceleration_grid[x][y][z].push_back(new_simplex); + new_simplex->grid_positions.push_back(gp); + } + } + } + } + + good_triangles++; + } + + //print_line("at point " + itos(i) + "/" + itos(point_count) + " simplices added " + itos(good_triangles) + "/" + itos(simplex_list.size()) + " - triangles: " + itos(triangles.size())); + triangles.clear(); + triangles_inserted.clear(); + } + + //print_line("end with simplices: " + itos(simplex_list.size())); + Vector ret_simplices; + ret_simplices.resize(simplex_list.size()); + OutputSimplex *ret_simplicesw = ret_simplices.ptrw(); + uint32_t simplices_written = 0; + + for (List::Element *E = simplex_list.front(); E; E = E->next()) { + Simplex *simplex = E->get(); + bool invalid = false; + for (int j = 0; j < 4; j++) { + if (simplex->points[j] >= point_count) { + invalid = true; + break; + } + } + if (invalid || simplex_is_coplanar(points, *simplex)) { + memdelete(simplex); + continue; + } + + ret_simplicesw[simplices_written].points[0] = simplex->points[0]; + ret_simplicesw[simplices_written].points[1] = simplex->points[1]; + ret_simplicesw[simplices_written].points[2] = simplex->points[2]; + ret_simplicesw[simplices_written].points[3] = simplex->points[3]; + simplices_written++; + memdelete(simplex); + } + + ret_simplices.resize(simplices_written); + + memfree(points); + + return ret_simplices; + } +}; + +#endif // DELAUNAY_3D_H diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index e556eb3b9c..65b80856cc 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -33,6 +33,8 @@ #include "core/print_string.h" #include "thirdparty/misc/clipper.hpp" #include "thirdparty/misc/triangulator.h" +#define STB_RECT_PACK_IMPLEMENTATION +#include "thirdparty/stb_rect_pack/stb_rect_pack.h" #define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON. @@ -1242,3 +1244,195 @@ Vector Geometry::compute_convex_mesh_points(const Plane *p_planes, int return points; } + +Vector Geometry::pack_rects(const Vector &p_sizes, const Size2i &p_atlas_size) { + + Vector nodes; + nodes.resize(p_atlas_size.width); + + stbrp_context context; + stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width); + + Vector rects; + rects.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + rects.write[i].id = 0; + rects.write[i].w = p_sizes[i].width; + rects.write[i].h = p_sizes[i].height; + rects.write[i].x = 0; + rects.write[i].y = 0; + rects.write[i].was_packed = 0; + } + + int res = stbrp_pack_rects(&context, rects.ptrw(), rects.size()); + if (res == 0) { //pack failed + return Vector(); + } + + Vector ret; + ret.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + Point2i r(rects[i].x, rects[i].y); + ret.write[i] = r; + } + + return ret; +} + +Vector Geometry::partial_pack_rects(const Vector &p_sizes, const Size2i &p_atlas_size) { + + Vector nodes; + nodes.resize(p_atlas_size.width); + zeromem(nodes.ptrw(), sizeof(stbrp_node) * nodes.size()); + + stbrp_context context; + stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width); + + Vector rects; + rects.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + rects.write[i].id = i; + rects.write[i].w = p_sizes[i].width; + rects.write[i].h = p_sizes[i].height; + rects.write[i].x = 0; + rects.write[i].y = 0; + rects.write[i].was_packed = 0; + } + + stbrp_pack_rects(&context, rects.ptrw(), rects.size()); + + Vector ret; + ret.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + ret.write[rects[i].id] = Vector3i(rects[i].x, rects[i].y, rects[i].was_packed != 0 ? 1 : 0); + } + + return ret; +} + +#define square(m_s) ((m_s) * (m_s)) +#define INF 1e20 + +/* dt of 1d function using squared distance */ +static void edt(float *f, int stride, int n) { + + float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1)); + int *v = (int *)&(d[n]); + float *z = (float *)&v[n]; + + int k = 0; + v[0] = 0; + z[0] = -INF; + z[1] = +INF; + for (int q = 1; q <= n - 1; q++) { + float s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]); + while (s <= z[k]) { + k--; + s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]); + } + k++; + v[k] = q; + + z[k] = s; + z[k + 1] = +INF; + } + + k = 0; + for (int q = 0; q <= n - 1; q++) { + while (z[k + 1] < q) + k++; + d[q] = square(q - v[k]) + f[v[k] * stride]; + } + + for (int i = 0; i < n; i++) { + f[i * stride] = d[i]; + } +} + +#undef square + +Vector Geometry::generate_edf(const Vector &p_voxels, const Vector3i &p_size, bool p_negative) { + + uint32_t float_count = p_size.x * p_size.y * p_size.z; + + ERR_FAIL_COND_V((uint32_t)p_voxels.size() != float_count, Vector()); + + float *work_memory = memnew_arr(float, float_count); + for (uint32_t i = 0; i < float_count; i++) { + work_memory[i] = INF; + } + + uint32_t y_mult = p_size.x; + uint32_t z_mult = y_mult * p_size.y; + + //plot solid cells + { + const bool *voxr = p_voxels.ptr(); + for (uint32_t i = 0; i < float_count; i++) { + + bool plot = voxr[i]; + if (p_negative) { + plot = !plot; + } + if (plot) { + work_memory[i] = 0; + } + } + } + + //process in each direction + + //xy->z + + for (int i = 0; i < p_size.x; i++) { + for (int j = 0; j < p_size.y; j++) { + edt(&work_memory[i + j * y_mult], z_mult, p_size.z); + } + } + + //xz->y + + for (int i = 0; i < p_size.x; i++) { + for (int j = 0; j < p_size.z; j++) { + edt(&work_memory[i + j * z_mult], y_mult, p_size.y); + } + } + + //yz->x + for (int i = 0; i < p_size.y; i++) { + for (int j = 0; j < p_size.z; j++) { + edt(&work_memory[i * y_mult + j * z_mult], 1, p_size.x); + } + } + + Vector ret; + ret.resize(float_count); + { + uint32_t *w = ret.ptrw(); + for (uint32_t i = 0; i < float_count; i++) { + w[i] = uint32_t(Math::sqrt(work_memory[i])); + } + } + + return ret; +} + +Vector Geometry::generate_sdf8(const Vector &p_positive, const Vector &p_negative) { + ERR_FAIL_COND_V(p_positive.size() != p_negative.size(), Vector()); + Vector sdf8; + int s = p_positive.size(); + sdf8.resize(s); + + const uint32_t *rpos = p_positive.ptr(); + const uint32_t *rneg = p_negative.ptr(); + int8_t *wsdf = sdf8.ptrw(); + for (int i = 0; i < s; i++) { + int32_t diff = int32_t(rpos[i]) - int32_t(rneg[i]); + wsdf[i] = CLAMP(diff, -128, 127); + } + return sdf8; +} diff --git a/core/math/geometry.h b/core/math/geometry.h index 3bbd1911ee..5a8e21d02b 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -1024,6 +1024,249 @@ public: static Vector compute_convex_mesh_points(const Plane *p_planes, int p_plane_count); +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if (x1 < min) \ + min = x1; \ + if (x1 > max) \ + max = x1; \ + if (x2 < min) \ + min = x2; \ + if (x2 > max) \ + max = x2; + + _FORCE_INLINE_ static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) { + int q; + Vector3 vmin, vmax; + for (q = 0; q <= 2; q++) { + if (normal[q] > 0.0f) { + vmin[q] = -maxbox[q]; + vmax[q] = maxbox[q]; + } else { + vmin[q] = maxbox[q]; + vmax[q] = -maxbox[q]; + } + } + if (normal.dot(vmin) + d > 0.0f) + return false; + if (normal.dot(vmax) + d >= 0.0f) + return true; + + return false; + } + +/*======================== X-tests ========================*/ +#define AXISTEST_X01(a, b, fa, fb) \ + p0 = a * v0.y - b * v0.z; \ + p2 = a * v2.y - b * v2.z; \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + +#define AXISTEST_X2(a, b, fa, fb) \ + p0 = a * v0.y - b * v0.z; \ + p1 = a * v1.y - b * v1.z; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + +/*======================== Y-tests ========================*/ +#define AXISTEST_Y02(a, b, fa, fb) \ + p0 = -a * v0.x + b * v0.z; \ + p2 = -a * v2.x + b * v2.z; \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + +#define AXISTEST_Y1(a, b, fa, fb) \ + p0 = -a * v0.x + b * v0.z; \ + p1 = -a * v1.x + b * v1.z; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) \ + return false; + + /*======================== Z-tests ========================*/ + +#define AXISTEST_Z12(a, b, fa, fb) \ + p1 = a * v1.x - b * v1.y; \ + p2 = a * v2.x - b * v2.y; \ + if (p2 < p1) { \ + min = p2; \ + max = p1; \ + } else { \ + min = p1; \ + max = p2; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ + if (min > rad || max < -rad) \ + return false; + +#define AXISTEST_Z0(a, b, fa, fb) \ + p0 = a * v0.x - b * v0.y; \ + p1 = a * v1.x - b * v1.y; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ + if (min > rad || max < -rad) \ + return false; + + _FORCE_INLINE_ static bool triangle_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) { + + /* use separating axis theorem to test overlap between triangle and box */ + /* need to test for overlap in these directions: */ + /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ + /* we do not even need to test these) */ + /* 2) normal of the triangle */ + /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ + /* this gives 3x3=9 more tests */ + Vector3 v0, v1, v2; + float min, max, d, p0, p1, p2, rad, fex, fey, fez; + Vector3 normal, e0, e1, e2; + + /* This is the fastest branch on Sun */ + /* move everything so that the boxcenter is in (0,0,0) */ + + v0 = triverts[0] - boxcenter; + v1 = triverts[1] - boxcenter; + v2 = triverts[2] - boxcenter; + + /* compute triangle edges */ + e0 = v1 - v0; /* tri edge 0 */ + e1 = v2 - v1; /* tri edge 1 */ + e2 = v0 - v2; /* tri edge 2 */ + + /* Bullet 3: */ + /* test the 9 tests first (this was faster) */ + fex = Math::abs(e0.x); + fey = Math::abs(e0.y); + fez = Math::abs(e0.z); + AXISTEST_X01(e0.z, e0.y, fez, fey); + AXISTEST_Y02(e0.z, e0.x, fez, fex); + AXISTEST_Z12(e0.y, e0.x, fey, fex); + + fex = Math::abs(e1.x); + fey = Math::abs(e1.y); + fez = Math::abs(e1.z); + AXISTEST_X01(e1.z, e1.y, fez, fey); + AXISTEST_Y02(e1.z, e1.x, fez, fex); + AXISTEST_Z0(e1.y, e1.x, fey, fex); + + fex = Math::abs(e2.x); + fey = Math::abs(e2.y); + fez = Math::abs(e2.z); + AXISTEST_X2(e2.z, e2.y, fez, fey); + AXISTEST_Y1(e2.z, e2.x, fez, fex); + AXISTEST_Z12(e2.y, e2.x, fey, fex); + + /* Bullet 1: */ + /* first test overlap in the {x,y,z}-directions */ + /* find min, max of the triangle each direction, and test for overlap in */ + /* that direction -- this is equivalent to testing a minimal AABB around */ + /* the triangle against the AABB */ + + /* test in X-direction */ + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if (min > boxhalfsize.x || max < -boxhalfsize.x) + return false; + + /* test in Y-direction */ + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if (min > boxhalfsize.y || max < -boxhalfsize.y) + return false; + + /* test in Z-direction */ + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if (min > boxhalfsize.z || max < -boxhalfsize.z) + return false; + + /* Bullet 2: */ + /* test if the box intersects the plane of the triangle */ + /* compute plane equation of triangle: normal*x+d=0 */ + normal = e0.cross(e1); + d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ + return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */ + } + + static Vector pack_rects(const Vector &p_sizes, const Size2i &p_atlas_size); + static Vector partial_pack_rects(const Vector &p_sizes, const Size2i &p_atlas_size); + + static Vector generate_edf(const Vector &p_voxels, const Vector3i &p_size, bool p_negative); + static Vector generate_sdf8(const Vector &p_positive, const Vector &p_negative); + + static Vector3 triangle_get_barycentric_coords(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, const Vector3 &p_pos) { + Vector3 v0 = p_b - p_a; + Vector3 v1 = p_c - p_a; + Vector3 v2 = p_pos - p_a; + + float d00 = v0.dot(v0); + float d01 = v0.dot(v1); + float d11 = v1.dot(v1); + float d20 = v2.dot(v0); + float d21 = v2.dot(v1); + float denom = (d00 * d11 - d01 * d01); + if (denom == 0) { + return Vector3(); //invalid triangle, return empty + } + float v = (d11 * d20 - d01 * d21) / denom; + float w = (d00 * d21 - d01 * d20) / denom; + float u = 1.0f - v - w; + return Vector3(u, v, w); + } + + static Color tetrahedron_get_barycentric_coords(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, const Vector3 &p_d, const Vector3 &p_pos) { + Vector3 vap = p_pos - p_a; + Vector3 vbp = p_pos - p_b; + + Vector3 vab = p_b - p_a; + Vector3 vac = p_c - p_a; + Vector3 vad = p_d - p_a; + + Vector3 vbc = p_c - p_b; + Vector3 vbd = p_d - p_b; + // ScTP computes the scalar triple product +#define STP(m_a, m_b, m_c) ((m_a).dot((m_b).cross((m_c)))) + float va6 = STP(vbp, vbd, vbc); + float vb6 = STP(vap, vac, vad); + float vc6 = STP(vap, vad, vab); + float vd6 = STP(vap, vab, vac); + float v6 = 1 / STP(vab, vac, vad); + return Color(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6); +#undef STP + } + private: static Vector> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector &p_polypath_a, const Vector &p_polypath_b, bool is_a_open = false); static Vector> _polypath_offset(const Vector &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type); diff --git a/core/math/plane.cpp b/core/math/plane.cpp index a3818698bc..26ac0aac47 100644 --- a/core/math/plane.cpp +++ b/core/math/plane.cpp @@ -153,6 +153,10 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec /* misc */ +bool Plane::is_equal_approx_any_side(const Plane &p_plane) const { + return (normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d)) || (normal.is_equal_approx(-p_plane.normal) && Math::is_equal_approx(d, -p_plane.d)); +} + bool Plane::is_equal_approx(const Plane &p_plane) const { return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d); diff --git a/core/math/plane.h b/core/math/plane.h index 771c8fc705..d4f23ff2b6 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -69,6 +69,7 @@ public: Plane operator-() const { return Plane(-normal, -d); } bool is_equal_approx(const Plane &p_plane) const; + bool is_equal_approx_any_side(const Plane &p_plane) const; _FORCE_INLINE_ bool operator==(const Plane &p_plane) const; _FORCE_INLINE_ bool operator!=(const Plane &p_plane) const; diff --git a/core/math/r128.cpp b/core/math/r128.cpp new file mode 100644 index 0000000000..fb1e4733ee --- /dev/null +++ b/core/math/r128.cpp @@ -0,0 +1,2 @@ +#define R128_IMPLEMENTATION +#include "thirdparty/r128/r128.h" diff --git a/core/ustring.cpp b/core/ustring.cpp index beafb3018d..3e8a1ddbe3 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -548,8 +548,8 @@ signed char String::naturalnocasecmp_to(const String &p_str) const { return -1; /* Compare the numbers */ - this_int = to_int(this_str); - that_int = to_int(that_str); + this_int = to_int(this_str, -1, true); + that_int = to_int(that_str, -1, true); if (this_int < that_int) return -1; @@ -2138,7 +2138,7 @@ double String::to_double(const CharType *p_str, const CharType **r_end) { return built_in_strtod(p_str, (CharType **)r_end); } -int64_t String::to_int(const CharType *p_str, int p_len) { +int64_t String::to_int(const CharType *p_str, int p_len, bool p_clamp) { if (p_len == 0 || !p_str[0]) return 0; @@ -2182,7 +2182,15 @@ int64_t String::to_int(const CharType *p_str, int p_len) { while (*str && str != limit) { number += *(str++); } - ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + if (p_clamp) { + if (sign == 1) { + return INT64_MAX; + } else { + return INT64_MIN; + } + } else { + ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + } } integer *= 10; integer += c - '0'; diff --git a/core/ustring.h b/core/ustring.h index ee7e3b1e16..15bc2b323c 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -254,7 +254,7 @@ public: static int to_int(const char *p_str, int p_len = -1); static double to_double(const char *p_str); static double to_double(const CharType *p_str, const CharType **r_end = nullptr); - static int64_t to_int(const CharType *p_str, int p_len = -1); + static int64_t to_int(const CharType *p_str, int p_len = -1, bool p_clamp = false); String capitalize() const; String camelcase_to_underscore(bool lowercase = true) const; diff --git a/core/vector.h b/core/vector.h index b2133f800b..74e0ab91c0 100644 --- a/core/vector.h +++ b/core/vector.h @@ -39,6 +39,7 @@ #include "core/cowdata.h" #include "core/error_macros.h" +#include "core/os/copymem.h" #include "core/os/memory.h" #include "core/sort_array.h" @@ -125,6 +126,13 @@ public: return *this; } + Vector to_byte_array() const { + Vector ret; + ret.resize(size() * sizeof(T)); + copymem(ret.ptrw(), ptr(), sizeof(T) * size()); + return ret; + } + Vector subarray(int p_from, int p_to) const { if (p_from < 0) { diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 491dc4214f..71be891b1d 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -2453,7 +2453,7 @@ Vector RenderingDeviceVulkan::texture_get_data(RID p_texture, uint32_t uint32_t buffer_size = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps, &width, &height, &depth); //allocate buffer - VkCommandBuffer command_buffer = frames[frame].setup_command_buffer; + VkCommandBuffer command_buffer = frames[frame].draw_command_buffer; //makes more sense to retrieve Buffer tmp_buffer; _buffer_allocate(&tmp_buffer, buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_CPU_ONLY); @@ -6859,6 +6859,7 @@ void RenderingDeviceVulkan::sync() { context->local_device_sync(local_device); _begin_frame(); + local_device_processing = false; } void RenderingDeviceVulkan::_free_pending_resources(int p_frame) { @@ -6975,6 +6976,12 @@ uint32_t RenderingDeviceVulkan::get_frame_delay() const { return frame_count; } +uint64_t RenderingDeviceVulkan::get_memory_usage() const { + VmaStats stats; + vmaCalculateStats(allocator, &stats); + return stats.total.usedBytes; +} + void RenderingDeviceVulkan::_flush(bool p_current_frame) { if (local_device.is_valid() && !p_current_frame) { @@ -7039,6 +7046,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de if (p_local_device) { frame_count = 1; local_device = p_context->local_device_create(); + device = p_context->local_device_get_vk_device(local_device); } else { frame_count = p_context->get_swapchain_image_count() + 1; //always need one extra to ensure it's unused at any time, without having to use a fence for this. } diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 6432946fbe..87af5d03d4 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -1138,6 +1138,8 @@ public: virtual RenderingDevice *create_local_device(); + virtual uint64_t get_memory_usage() const; + RenderingDeviceVulkan(); ~RenderingDeviceVulkan(); }; diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index a7eb3e53b9..9471b4604c 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -1567,6 +1567,15 @@ void VulkanContext::local_device_push_command_buffers(RID p_local_device, const submit_info.pSignalSemaphores = nullptr; VkResult err = vkQueueSubmit(ld->queue, 1, &submit_info, VK_NULL_HANDLE); + if (err == VK_ERROR_OUT_OF_HOST_MEMORY) { + print_line("out of host memory"); + } + if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY) { + print_line("out of device memory"); + } + if (err == VK_ERROR_DEVICE_LOST) { + print_line("device lost"); + } ERR_FAIL_COND(err); ld->waiting = true; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index c37ede4166..1b1ce4ec37 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -158,6 +158,7 @@ #include "editor/plugins/style_box_editor_plugin.h" #include "editor/plugins/text_editor.h" #include "editor/plugins/texture_editor_plugin.h" +#include "editor/plugins/texture_layered_editor_plugin.h" #include "editor/plugins/texture_region_editor_plugin.h" #include "editor/plugins/theme_editor_plugin.h" #include "editor/plugins/tile_map_editor_plugin.h" @@ -381,6 +382,8 @@ void EditorNode::_notification(int p_what) { RS::get_singleton()->shadows_quality_set(shadows_quality); RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/directional_shadow/soft_shadow_quality"))); RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality); + float probe_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed"); + RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed); } ResourceImporterTexture::get_singleton()->update_imports(); @@ -713,7 +716,6 @@ void EditorNode::_sources_changed(bool p_exist) { // Reload the global shader variables, but this time // loading texures, as they are now properly imported. - print_line("done scanning, reload textures"); RenderingServer::get_singleton()->global_variables_load_settings(true); // Start preview thread now that it's safe. @@ -5678,7 +5680,7 @@ EditorNode::EditorNode() { import_texture.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_texture); - /* Ref import_cubemap; + Ref import_cubemap; import_cubemap.instance(); import_cubemap->set_mode(ResourceImporterLayeredTexture::MODE_CUBEMAP); ResourceFormatImporter::get_singleton()->add_importer(import_cubemap); @@ -5692,7 +5694,12 @@ EditorNode::EditorNode() { import_cubemap_array.instance(); import_cubemap_array->set_mode(ResourceImporterLayeredTexture::MODE_CUBEMAP_ARRAY); ResourceFormatImporter::get_singleton()->add_importer(import_cubemap_array); -*/ + + /*Ref import_3d; + import_3d.instance(); + import_3d->set_mode(ResourceImporterLayeredTexture::MODE_3D); + ResourceFormatImporter::get_singleton()->add_importer(import_3d);*/ + Ref import_image; import_image.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_image); @@ -6663,7 +6670,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(SpriteFramesEditorPlugin(this))); add_editor_plugin(memnew(TextureRegionEditorPlugin(this))); add_editor_plugin(memnew(GIProbeEditorPlugin(this))); - //add_editor_plugin(memnew(BakedLightmapEditorPlugin(this))); + add_editor_plugin(memnew(BakedLightmapEditorPlugin(this))); add_editor_plugin(memnew(Path2DEditorPlugin(this))); add_editor_plugin(memnew(Path3DEditorPlugin(this))); add_editor_plugin(memnew(Line2DEditorPlugin(this))); @@ -6674,6 +6681,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(CollisionShape2DEditorPlugin(this))); add_editor_plugin(memnew(CurveEditorPlugin(this))); add_editor_plugin(memnew(TextureEditorPlugin(this))); + add_editor_plugin(memnew(TextureLayeredEditorPlugin(this))); add_editor_plugin(memnew(AudioStreamEditorPlugin(this))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(Skeleton3DEditorPlugin(this))); diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index a4cbc81b26..c46cf4c1a8 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -36,9 +36,9 @@ #include "core/io/image_loader.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" +#include "resource_importer_texture.h" #include "scene/resources/texture.h" -#if 0 String ResourceImporterLayeredTexture::get_importer_name() const { switch (mode) { @@ -51,6 +51,9 @@ String ResourceImporterLayeredTexture::get_importer_name() const { case MODE_CUBEMAP_ARRAY: { return "cubemap_array_texture"; } break; + case MODE_3D: { + return "cubemap_3d_texture"; + } break; } ERR_FAIL_V(""); @@ -68,6 +71,9 @@ String ResourceImporterLayeredTexture::get_visible_name() const { case MODE_CUBEMAP_ARRAY: { return "CubemapArray"; } break; + case MODE_3D: { + return "3D"; + } break; } ERR_FAIL_V(""); @@ -79,13 +85,16 @@ void ResourceImporterLayeredTexture::get_recognized_extensions(List *p_e String ResourceImporterLayeredTexture::get_save_extension() const { switch (mode) { case MODE_CUBEMAP: { - return "cube"; + return "scube"; } break; case MODE_2D_ARRAY: { - return "tex2darr"; + return "stexarray"; } break; case MODE_CUBEMAP_ARRAY: { - return "cubearr"; + return "scubearray"; + } break; + case MODE_3D: { + return "stex3d"; } break; } @@ -96,13 +105,16 @@ String ResourceImporterLayeredTexture::get_resource_type() const { switch (mode) { case MODE_CUBEMAP: { - return "Cubemap"; + return "StreamCubemap"; } break; case MODE_2D_ARRAY: { - return "Texture2DArray"; + return "StreamTexture2DArray"; } break; case MODE_CUBEMAP_ARRAY: { - return "CubemapArray"; + return "StreamCubemapArray"; + } break; + case MODE_3D: { + return "StreamTexture3D"; } break; } ERR_FAIL_V(String()); @@ -110,6 +122,9 @@ String ResourceImporterLayeredTexture::get_resource_type() const { bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_option, const Map &p_options) const { + if (p_option == "compress/lossy_quality" && p_options.has("compress/mode")) { + return int(p_options["compress/mode"]) == COMPRESS_LOSSY; + } return true; } @@ -123,138 +138,109 @@ String ResourceImporterLayeredTexture::get_preset_name(int p_idx) const { void ResourceImporterLayeredTexture::get_import_options(List *r_options, int p_preset) const { - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Video RAM,Uncompressed", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/no_bptc_if_rgb"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,Video RAM,Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/bptc_ldr", PROPERTY_HINT_ENUM, "Disabled,Enabled,RGBA Only"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/channel_pack", PROPERTY_HINT_ENUM, "sRGB Friendly,Optimized"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "flags/mipmaps"), true)); - if (mode == MODE_2D_ARRAY) { + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "mipmaps/generate"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "mipmaps/limit", PROPERTY_HINT_RANGE, "-1,256"), -1)); + + if (mode == MODE_2D_ARRAY || mode == MODE_3D) { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/horizontal", PROPERTY_HINT_RANGE, "1,256,1"), 8)); - } - if (mode == MODE_2D_ARRAY || mode == MODE_CUBEMAP_ARRAY) { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/vertical", PROPERTY_HINT_RANGE, "1,256,1"), 8)); } + if (mode == MODE_CUBEMAP || mode == MODE_CUBEMAP_ARRAY) { + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/arrangement", PROPERTY_HINT_ENUM, "1x6,2x3,3x2,6x1"), 1)); + if (mode == MODE_CUBEMAP_ARRAY) { + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/layout", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/amount", PROPERTY_HINT_RANGE, "1,1024,1,or_greater"), 1)); + } + } } -void ResourceImporterLayeredTexture::_save_tex(const Vector > &p_images, const String &p_to_path, int p_compress_mode, Image::CompressMode p_vram_compression, bool p_mipmaps) { - - FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE); - f->store_8('G'); - f->store_8('D'); - switch (mode) { - case MODE_2D_ARRAY: f->store_8('A'); break; - case MODE_CUBEMAP: f->store_8('C'); break; - case MODE_CUBEMAP_ARRAY: f->store_8('X'); break; - } - - f->store_8('T'); //godot streamable texture - - f->store_32(p_images[0]->get_width()); - f->store_32(p_images[0]->get_height()); - f->store_32(p_images.size()); //depth - uint32_t flags = 0; - if (p_mipmaps) { - flags |= TEXTURE_FLAGS_MIPMAPS; - } - f->store_32(flags); - if (p_compress_mode != COMPRESS_VIDEO_RAM) { - //vram needs to do a first compression to tell what the format is, for the rest its ok - f->store_32(p_images[0]->get_format()); - f->store_32(p_compress_mode); // 0 - lossless (PNG), 1 - vram, 2 - uncompressed - } - - if ((p_compress_mode == COMPRESS_LOSSLESS) && p_images[0]->get_format() > Image::FORMAT_RGBA8) { - p_compress_mode = COMPRESS_UNCOMPRESSED; //these can't go as lossy - } +void ResourceImporterLayeredTexture::_save_tex(Vector> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2) { for (int i = 0; i < p_images.size(); i++) { - switch (p_compress_mode) { - case COMPRESS_LOSSLESS: { + if (p_force_po2) { + p_images.write[i]->resize_to_po2(); + } - Ref image = p_images[i]->duplicate(); - if (p_mipmaps) { - image->generate_mipmaps(); - } else { - image->clear_mipmaps(); - } - - int mmc = image->get_mipmap_count() + 1; - f->store_32(mmc); - - for (int j = 0; j < mmc; j++) { - - if (j > 0) { - image->shrink_x2(); - } - - Vector data = Image::lossless_packer(image); - int data_len = data.size(); - f->store_32(data_len); - - const uint8_t* r = data.ptr(); - f->store_buffer(r.ptr(), data_len); - } - - } break; - case COMPRESS_VIDEO_RAM: { - - Ref image = p_images[i]->duplicate(); - image->generate_mipmaps(false); - - Image::CompressSource csource = Image::COMPRESS_SOURCE_LAYERED; - image->compress(p_vram_compression, csource, 0.7); - - if (i == 0) { - //hack so we can properly tell the format - f->store_32(image->get_format()); - f->store_32(p_compress_mode); // 0 - lossless (PNG), 1 - vram, 2 - uncompressed - } - - Vector data = image->get_data(); - int dl = data.size(); - - const uint8_t* r = data.ptr(); - f->store_buffer(r.ptr(), dl); - } break; - case COMPRESS_UNCOMPRESSED: { - - Ref image = p_images[i]->duplicate(); - - if (p_mipmaps) { - image->generate_mipmaps(); - } else { - image->clear_mipmaps(); - } - - Vector data = image->get_data(); - int dl = data.size(); - - const uint8_t* r = data.ptr(); - - f->store_buffer(r.ptr(), dl); - - } break; + if (p_mipmaps) { + p_images.write[i]->generate_mipmaps(); + } else { + p_images.write[i]->clear_mipmaps(); } } - memdelete(f); + FileAccessRef f = FileAccess::open(p_to_path, FileAccess::WRITE); + f->store_8('G'); + f->store_8('S'); + f->store_8('T'); + f->store_8('L'); + + f->store_32(StreamTextureLayered::FORMAT_VERSION); + f->store_32(p_images.size()); + f->store_32(mode); + f->store_32(0); //dataformat + f->store_32(0); //mipmap limit + + //reserverd + f->store_32(0); + f->store_32(0); + f->store_32(0); + + for (int i = 0; i < p_images.size(); i++) { + ResourceImporterTexture::save_to_stex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy); + } + + f->close(); } Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { int compress_mode = p_options["compress/mode"]; - int no_bptc_if_rgb = p_options["compress/no_bptc_if_rgb"]; - bool mipmaps = p_options["flags/mipmaps"]; + float lossy = p_options["compress/lossy_quality"]; + int hdr_compression = p_options["compress/hdr_compression"]; + int bptc_ldr = p_options["compress/bptc_ldr"]; + bool mipmaps = p_options["mipmaps/generate"]; + //bool mipmap_limit = p_options["mipmaps/limit"]; + int channel_pack = p_options["compress/channel_pack"]; int hslices = (p_options.has("slices/horizontal")) ? int(p_options["slices/horizontal"]) : 0; int vslices = (p_options.has("slices/vertical")) ? int(p_options["slices/vertical"]) : 0; + int arrangement = (p_options.has("slices/arrangement")) ? int(p_options["slices/arrangement"]) : 0; + int layout = (p_options.has("slices/layout")) ? int(p_options["slices/layout"]) : 0; + int amount = (p_options.has("slices/amount")) ? int(p_options["slices/amount"]) : 0; - if (mode == MODE_CUBEMAP) { - hslices = 3; - vslices = 2; - } else if (mode == MODE_CUBEMAP_ARRAY) { - hslices = 3; - vslices *= 2; //put cubemaps vertically + if (mode == MODE_CUBEMAP || mode == MODE_CUBEMAP_ARRAY) { + switch (arrangement) { + case CUBEMAP_FORMAT_1X6: { + hslices = 1; + vslices = 6; + } break; + case CUBEMAP_FORMAT_2X3: { + hslices = 2; + vslices = 3; + } break; + case CUBEMAP_FORMAT_3X2: { + hslices = 3; + vslices = 2; + } break; + case CUBEMAP_FORMAT_6X1: { + hslices = 6; + vslices = 1; + } break; + } + + if (mode == MODE_CUBEMAP_ARRAY) { + if (layout == 0) { + hslices *= amount; + } else { + vslices *= amount; + } + } } Ref image; @@ -263,28 +249,40 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const if (err != OK) return err; - if (compress_mode == COMPRESS_VIDEO_RAM) { + if (compress_mode == COMPRESS_BASIS_UNIVERSAL && image->get_format() >= Image::FORMAT_RF) { + //basis universal does not support float formats, fall back + compress_mode = COMPRESS_VRAM_COMPRESSED; + } + + if (compress_mode == COMPRESS_VRAM_COMPRESSED) { mipmaps = true; } - Vector > slices; - - int slice_w = image->get_width() / hslices; - int slice_h = image->get_height() / vslices; - //optimize - if (compress_mode == COMPRESS_VIDEO_RAM) { + if (compress_mode == COMPRESS_VRAM_COMPRESSED) { //if using video ram, optimize if (channel_pack == 0) { //remove alpha if not needed, so compression is more efficient if (image->get_format() == Image::FORMAT_RGBA8 && !image->detect_alpha()) { image->convert(Image::FORMAT_RGB8); } - } else { + } else if (image->get_format() < Image::FORMAT_RGBA8) { image->optimize_channels(); } } + Image::CompressSource csource = Image::COMPRESS_SOURCE_GENERIC; + if (channel_pack == 0) { + csource = Image::COMPRESS_SOURCE_SRGB; + } + + Image::UsedChannels used_channels = image->detect_used_channels(csource); + + Vector> slices; + + int slice_w = image->get_width() / hslices; + int slice_h = image->get_height() / vslices; + for (int i = 0; i < vslices; i++) { for (int j = 0; j < hslices; j++) { int x = slice_w * j; @@ -301,58 +299,82 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String extension = get_save_extension(); Array formats_imported; - if (compress_mode == COMPRESS_VIDEO_RAM) { + if (compress_mode == COMPRESS_VRAM_COMPRESSED) { //must import in all formats, in order of priority (so platform choses the best supported one. IE, etc2 over etc). //Android, GLES 2.x bool ok_on_pc = false; - bool encode_bptc = false; + bool is_hdr = (image->get_format() >= Image::FORMAT_RF && image->get_format() <= Image::FORMAT_RGBE9995); + bool is_ldr = (image->get_format() >= Image::FORMAT_L8 && image->get_format() <= Image::FORMAT_RGB565); + bool can_bptc = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_bptc"); + bool can_s3tc = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc"); - if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_bptc")) { + if (can_bptc) { + formats_imported.push_back("bptc"); //needs to be aded anyway + } + bool can_compress_hdr = hdr_compression > 0; - encode_bptc = true; + if (is_hdr && can_compress_hdr) { - if (no_bptc_if_rgb) { - Image::UsedChannels channels = image->detect_used_channels(); - if (channels != Image::USED_CHANNELS_LA && channels != Image::USED_CHANNELS_RGBA) { - encode_bptc = false; + if (used_channels == Image::USED_CHANNELS_LA || used_channels == Image::USED_CHANNELS_RGBA) { + //can compress hdr, but hdr with alpha is not compressible + + if (hdr_compression == 2) { + //but user selected to compress hdr anyway, so force an alpha-less format. + if (image->get_format() == Image::FORMAT_RGBAF) { + for (int i = 0; i < slices.size(); i++) { + slices.write[i]->convert(Image::FORMAT_RGBF); + } + + } else if (image->get_format() == Image::FORMAT_RGBAH) { + for (int i = 0; i < slices.size(); i++) { + slices.write[i]->convert(Image::FORMAT_RGBH); + } + } + } else { + can_compress_hdr = false; } } - formats_imported.push_back("bptc"); + if (can_compress_hdr) { + + if (!can_bptc) { + + //default to rgbe + if (image->get_format() != Image::FORMAT_RGBE9995) { + for (int i = 0; i < slices.size(); i++) { + slices.write[i]->convert(Image::FORMAT_RGBE9995); + } + } + } + } else { + can_bptc = false; + } } - if (encode_bptc) { - - _save_tex(slices, p_save_path + ".bptc." + extension, compress_mode, Image::COMPRESS_BPTC, mipmaps); - r_platform_variants->push_back("bptc"); - ok_on_pc = true; + if (is_ldr && can_bptc) { + if (bptc_ldr == 0 || (bptc_ldr == 1 && !(used_channels == Image::USED_CHANNELS_LA || used_channels == Image::USED_CHANNELS_RGBA))) { + can_bptc = false; + } } - if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc")) { - - _save_tex(slices, p_save_path + ".s3tc." + extension, compress_mode, Image::COMPRESS_S3TC, mipmaps); + if (can_bptc || can_s3tc) { + _save_tex(slices, p_save_path + ".s3tc." + extension, compress_mode, lossy, can_bptc ? Image::COMPRESS_BPTC : Image::COMPRESS_S3TC, csource, used_channels, mipmaps, false); r_platform_variants->push_back("s3tc"); - ok_on_pc = true; formats_imported.push_back("s3tc"); + ok_on_pc = true; } if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) { - _save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, Image::COMPRESS_ETC2, mipmaps); + _save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, lossy, Image::COMPRESS_ETC2, csource, used_channels, mipmaps, true); r_platform_variants->push_back("etc2"); formats_imported.push_back("etc2"); } - if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc")) { - _save_tex(slices, p_save_path + ".etc." + extension, compress_mode, Image::COMPRESS_ETC, mipmaps); - r_platform_variants->push_back("etc"); - formats_imported.push_back("etc"); - } - if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc")) { - _save_tex(slices, p_save_path + ".pvrtc." + extension, compress_mode, Image::COMPRESS_PVRTC4, mipmaps); + _save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, lossy, Image::COMPRESS_ETC2, csource, used_channels, mipmaps, true); r_platform_variants->push_back("pvrtc"); formats_imported.push_back("pvrtc"); } @@ -362,12 +384,12 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const } } else { //import normally - _save_tex(slices, p_save_path + "." + extension, compress_mode, Image::COMPRESS_S3TC /*this is ignored */, mipmaps); + _save_tex(slices, p_save_path + "." + extension, compress_mode, lossy, Image::COMPRESS_S3TC /* IGNORED */, csource, used_channels, mipmaps, false); } if (r_metadata) { Dictionary metadata; - metadata["vram_texture"] = compress_mode == COMPRESS_VIDEO_RAM; + metadata["vram_texture"] = compress_mode == COMPRESS_VRAM_COMPRESSED; if (formats_imported.size()) { metadata["imported_formats"] = formats_imported; } @@ -448,4 +470,3 @@ ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() { ResourceImporterLayeredTexture::~ResourceImporterLayeredTexture() { } -#endif diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 40e5c9023e..18eaf31f6b 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -28,7 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if 0 /*************************************************************************/ /* resource_importer_layered_texture.h */ /*************************************************************************/ @@ -65,16 +64,24 @@ #include "core/image.h" #include "core/io/resource_importer.h" - -class StreamTexture; +class StreamTexture2D; class ResourceImporterLayeredTexture : public ResourceImporter { GDCLASS(ResourceImporterLayeredTexture, ResourceImporter); + public: enum Mode { - MODE_CUBEMAP, MODE_2D_ARRAY, - MODE_CUBEMAP_ARRAY + MODE_CUBEMAP, + MODE_CUBEMAP_ARRAY, + MODE_3D, + }; + + enum CubemapFormat { + CUBEMAP_FORMAT_1X6, + CUBEMAP_FORMAT_2X3, + CUBEMAP_FORMAT_3X2, + CUBEMAP_FORMAT_6X1, }; enum TextureFlags { @@ -86,9 +93,9 @@ private: static const char *compression_formats[]; protected: - static void _texture_reimport_srgb(const Ref &p_tex); - static void _texture_reimport_3d(const Ref &p_tex); - static void _texture_reimport_normal(const Ref &p_tex); + static void _texture_reimport_srgb(const Ref &p_tex); + static void _texture_reimport_3d(const Ref &p_tex); + static void _texture_reimport_normal(const Ref &p_tex); static ResourceImporterLayeredTexture *singleton; @@ -102,8 +109,10 @@ public: enum CompressMode { COMPRESS_LOSSLESS, - COMPRESS_VIDEO_RAM, - COMPRESS_UNCOMPRESSED + COMPRESS_LOSSY, + COMPRESS_VRAM_COMPRESSED, + COMPRESS_VRAM_UNCOMPRESSED, + COMPRESS_BASIS_UNIVERSAL }; virtual int get_preset_count() const; @@ -112,7 +121,7 @@ public: virtual void get_import_options(List *r_options, int p_preset = 0) const; virtual bool get_option_visibility(const String &p_option, const Map &p_options) const; - void _save_tex(const Vector > &p_images, const String &p_to_path, int p_compress_mode, Image::CompressMode p_vram_compression, bool p_mipmaps); + void _save_tex(Vector> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2); virtual Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files = nullptr, Variant *r_metadata = nullptr); @@ -126,6 +135,5 @@ public: ResourceImporterLayeredTexture(); ~ResourceImporterLayeredTexture(); }; -#endif // RESOURCE_IMPORTER_LAYERED_TEXTURE_H -#endif +#endif // RESOURCE_IMPORTER_LAYERED_TEXTURE_H diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index e7f87acd03..b9341b1fb6 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -354,7 +354,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map if (p_light_bake_mode != LIGHT_BAKE_DISABLED) { - mi->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true); + mi->set_gi_mode(GeometryInstance3D::GI_MODE_BAKED); } } @@ -955,7 +955,7 @@ void ResourceImporterScene::_find_meshes(Node *p_node, Map, Trans Transform transform; while (s) { transform = transform * s->get_transform(); - s = s->get_parent_spatial(); + s = Object::cast_to(s->get_parent()); } meshes[mesh] = transform; @@ -1358,8 +1358,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p scene->set_script(Variant(root_script)); } + float root_scale = 1.0; if (Object::cast_to(scene)) { - float root_scale = p_options["nodes/root_scale"]; + root_scale = p_options["nodes/root_scale"]; Object::cast_to(scene)->scale(Vector3(root_scale, root_scale, root_scale)); } diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index 3a6215e035..f085341969 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -103,7 +103,7 @@ Error ResourceImporterShaderFile::import(const String &p_source_file, const Stri Ref shader_file; shader_file.instance(); String base_path = p_source_file.get_base_dir(); - err = shader_file->parse_versions_from_text(file_txt, _include_function, &base_path); + err = shader_file->parse_versions_from_text(file_txt, "", _include_function, &base_path); if (err != OK) { if (!ShaderFileEditor::singleton->is_visible_in_tree()) { diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index f8ed9304b6..111eab78b4 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -36,7 +36,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" -void ResourceImporterTexture::_texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { +void ResourceImporterTexture::_texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { MutexLock lock(singleton->mutex); @@ -51,7 +51,7 @@ void ResourceImporterTexture::_texture_reimport_roughness(const Refmake_flags[path].normal_path_for_roughness = p_normal_path; } -void ResourceImporterTexture::_texture_reimport_3d(const Ref &p_tex) { +void ResourceImporterTexture::_texture_reimport_3d(const Ref &p_tex) { MutexLock lock(singleton->mutex); @@ -64,7 +64,7 @@ void ResourceImporterTexture::_texture_reimport_3d(const Ref &p_t singleton->make_flags[path].flags |= MAKE_3D_FLAG; } -void ResourceImporterTexture::_texture_reimport_normal(const Ref &p_tex) { +void ResourceImporterTexture::_texture_reimport_normal(const Ref &p_tex) { MutexLock lock(singleton->mutex); @@ -157,7 +157,7 @@ String ResourceImporterTexture::get_save_extension() const { String ResourceImporterTexture::get_resource_type() const { - return "StreamTexture"; + return "StreamTexture2D"; } bool ResourceImporterTexture::get_option_visibility(const String &p_option, const Map &p_options) const { @@ -207,8 +207,8 @@ void ResourceImporterTexture::get_import_options(List *r_options, r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 2 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_mode", PROPERTY_HINT_ENUM, "Enabled,Force RGBE"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/bptc_ldr", PROPERTY_HINT_ENUM, "Enabled,RGBA Only"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/bptc_ldr", PROPERTY_HINT_ENUM, "Disabled,Enabled,RGBA Only"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/normal_map", PROPERTY_HINT_ENUM, "Detect,Enable,Disabled"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/channel_pack", PROPERTY_HINT_ENUM, "sRGB Friendly,Optimized"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/streamed"), false)); @@ -225,12 +225,12 @@ void ResourceImporterTexture::get_import_options(List *r_options, r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 1.0)); } -void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality, bool p_force_rgbe) { +void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) { switch (p_compress_mode) { case COMPRESS_LOSSLESS: { - f->store_32(StreamTexture::DATA_FORMAT_LOSSLESS); + f->store_32(StreamTexture2D::DATA_FORMAT_LOSSLESS); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -249,7 +249,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Refstore_32(StreamTexture::DATA_FORMAT_LOSSY); + f->store_32(StreamTexture2D::DATA_FORMAT_LOSSY); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -269,13 +269,9 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref image = p_image->duplicate(); - if (p_force_rgbe && image->get_format() >= Image::FORMAT_RF && image->get_format() < Image::FORMAT_RGBE9995) { - image->convert(Image::FORMAT_RGBE9995); - } else { - image->compress_from_channels(p_compress_format, p_channels, p_lossy_quality); - } + image->compress_from_channels(p_compress_format, p_channels, p_lossy_quality); - f->store_32(StreamTexture::DATA_FORMAT_IMAGE); + f->store_32(StreamTexture2D::DATA_FORMAT_IMAGE); f->store_16(image->get_width()); f->store_16(image->get_height()); f->store_32(image->get_mipmap_count()); @@ -288,7 +284,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Refstore_32(StreamTexture::DATA_FORMAT_IMAGE); + f->store_32(StreamTexture2D::DATA_FORMAT_IMAGE); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -303,7 +299,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Refstore_32(StreamTexture::DATA_FORMAT_BASIS_UNIVERSAL); + f->store_32(StreamTexture2D::DATA_FORMAT_BASIS_UNIVERSAL); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); @@ -322,7 +318,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_force_rgbe, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref &p_normal, Image::RoughnessChannel p_roughness_channel) { +void ResourceImporterTexture::_save_stex(const Ref &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref &p_normal, Image::RoughnessChannel p_roughness_channel) { FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE); f->store_8('G'); @@ -331,22 +327,22 @@ void ResourceImporterTexture::_save_stex(const Ref &p_image, const String f->store_8('2'); //godot streamable texture 2D //format version - f->store_32(StreamTexture::FORMAT_VERSION); + f->store_32(StreamTexture2D::FORMAT_VERSION); //texture may be resized later, so original size must be saved first f->store_32(p_image->get_width()); f->store_32(p_image->get_height()); uint32_t flags = 0; if (p_streamable) - flags |= StreamTexture::FORMAT_BIT_STREAM; + flags |= StreamTexture2D::FORMAT_BIT_STREAM; if (p_mipmaps) - flags |= StreamTexture::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit + flags |= StreamTexture2D::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit if (p_detect_3d) - flags |= StreamTexture::FORMAT_BIT_DETECT_3D; + flags |= StreamTexture2D::FORMAT_BIT_DETECT_3D; if (p_detect_roughness) - flags |= StreamTexture::FORMAT_BIT_DETECT_ROUGNESS; + flags |= StreamTexture2D::FORMAT_BIT_DETECT_ROUGNESS; if (p_detect_normal) - flags |= StreamTexture::FORMAT_BIT_DETECT_NORMAL; + flags |= StreamTexture2D::FORMAT_BIT_DETECT_NORMAL; f->store_32(flags); f->store_32(p_limit_mipmap); @@ -385,10 +381,6 @@ void ResourceImporterTexture::_save_stex(const Ref &p_image, const String image->generate_mipmap_roughness(p_roughness_channel, p_normal); } - if (p_force_rgbe && image->get_format() >= Image::FORMAT_RF && image->get_format() < Image::FORMAT_RGBE9995) { - image->convert(Image::FORMAT_RGBE9995); - } - Image::CompressSource csource = Image::COMPRESS_SOURCE_GENERIC; if (p_force_normal) { csource = Image::COMPRESS_SOURCE_NORMAL; @@ -398,7 +390,7 @@ void ResourceImporterTexture::_save_stex(const Ref &p_image, const String Image::UsedChannels used_channels = image->detect_used_channels(csource); - save_to_stex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality, p_force_rgbe); + save_to_stex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality); memdelete(f); } @@ -418,7 +410,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String bool hdr_as_srgb = p_options["process/HDR_as_SRGB"]; int normal = p_options["compress/normal_map"]; float scale = p_options["svg/scale"]; - bool force_rgbe = int(p_options["compress/hdr_mode"]) == 1; + int hdr_compression = p_options["compress/hdr_compression"]; int bptc_ldr = p_options["compress/bptc_ldr"]; int roughness = p_options["roughness/mode"]; String normal_map = p_options["roughness/src_normal"]; @@ -501,30 +493,49 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String bool can_s3tc = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc"); if (can_bptc) { - Image::UsedChannels channels = image->detect_used_channels(); - if (is_hdr) { - - if (channels == Image::USED_CHANNELS_LA || channels == Image::USED_CHANNELS_RGBA) { - can_bptc = false; - } - } else if (is_ldr) { - - //handle "RGBA Only" setting - if (bptc_ldr == 1 && channels != Image::USED_CHANNELS_LA && channels != Image::USED_CHANNELS_RGBA) { - can_bptc = false; - } - } - + //add to the list anyway formats_imported.push_back("bptc"); } - if (!can_bptc && is_hdr && !force_rgbe) { - //convert to ldr if this can't be stored hdr - image->convert(Image::FORMAT_RGBA8); + bool can_compress_hdr = hdr_compression > 0; + bool has_alpha = image->detect_alpha() != Image::ALPHA_NONE; + + if (is_hdr && can_compress_hdr) { + + if (has_alpha) { + //can compress hdr, but hdr with alpha is not compressible + if (hdr_compression == 2) { + //but user selected to compress hdr anyway, so force an alpha-less format. + if (image->get_format() == Image::FORMAT_RGBAF) { + image->convert(Image::FORMAT_RGBF); + } else if (image->get_format() == Image::FORMAT_RGBAH) { + image->convert(Image::FORMAT_RGBH); + } + } else { + can_compress_hdr = false; + } + } + + if (can_compress_hdr) { + if (!can_bptc) { + //fallback to RGBE99995 + if (image->get_format() != Image::FORMAT_RGBE9995) { + image->convert(Image::FORMAT_RGBE9995); + } + } + } else { + can_bptc = false; + } + } + + if (is_ldr && can_bptc) { + if (bptc_ldr == 0 || (bptc_ldr == 1 && !has_alpha)) { + can_bptc = false; + } } if (can_bptc || can_s3tc) { - _save_stex(image, p_save_path + ".s3tc.stex", compress_mode, lossy, can_bptc ? Image::COMPRESS_BPTC : Image::COMPRESS_S3TC, mipmaps, stream, detect_3d, detect_roughness, force_rgbe, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".s3tc.stex", compress_mode, lossy, can_bptc ? Image::COMPRESS_BPTC : Image::COMPRESS_S3TC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("s3tc"); formats_imported.push_back("s3tc"); ok_on_pc = true; @@ -532,20 +543,20 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) { - _save_stex(image, p_save_path + ".etc2.stex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, force_rgbe, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".etc2.stex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("etc2"); formats_imported.push_back("etc2"); } if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc")) { - _save_stex(image, p_save_path + ".etc.stex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, force_rgbe, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".etc.stex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("etc"); formats_imported.push_back("etc"); } if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc")) { - _save_stex(image, p_save_path + ".pvrtc.stex", compress_mode, lossy, Image::COMPRESS_PVRTC4, mipmaps, stream, detect_3d, detect_roughness, force_rgbe, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".pvrtc.stex", compress_mode, lossy, Image::COMPRESS_PVRTC4, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("pvrtc"); formats_imported.push_back("pvrtc"); } @@ -555,7 +566,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } } else { //import normally - _save_stex(image, p_save_path + ".stex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, force_rgbe, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_stex(image, p_save_path + ".stex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); } if (r_metadata) { @@ -635,9 +646,9 @@ ResourceImporterTexture *ResourceImporterTexture::singleton = nullptr; ResourceImporterTexture::ResourceImporterTexture() { singleton = this; - StreamTexture::request_3d_callback = _texture_reimport_3d; - StreamTexture::request_roughness_callback = _texture_reimport_roughness; - StreamTexture::request_normal_callback = _texture_reimport_normal; + StreamTexture2D::request_3d_callback = _texture_reimport_3d; + StreamTexture2D::request_roughness_callback = _texture_reimport_roughness; + StreamTexture2D::request_normal_callback = _texture_reimport_normal; } ResourceImporterTexture::~ResourceImporterTexture() { diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index e1c71ff1b8..da8ce3c0a8 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -37,7 +37,7 @@ #include "scene/resources/texture.h" #include "servers/rendering_server.h" -class StreamTexture; +class StreamTexture2D; class ResourceImporterTexture : public ResourceImporter { GDCLASS(ResourceImporterTexture, ResourceImporter); @@ -72,17 +72,17 @@ protected: Map make_flags; - static void _texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, RenderingServer::TextureDetectRoughnessChannel p_channel); - static void _texture_reimport_3d(const Ref &p_tex); - static void _texture_reimport_normal(const Ref &p_tex); + static void _texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, RenderingServer::TextureDetectRoughnessChannel p_channel); + static void _texture_reimport_3d(const Ref &p_tex); + static void _texture_reimport_normal(const Ref &p_tex); static ResourceImporterTexture *singleton; static const char *compression_formats[]; - void _save_stex(const Ref &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_force_rgbe, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref &p_normal, Image::RoughnessChannel p_roughness_channel); + void _save_stex(const Ref &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref &p_normal, Image::RoughnessChannel p_roughness_channel); public: - void save_to_stex_format(FileAccess *f, const Ref &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality, bool p_force_rgbe); + static void save_to_stex_format(FileAccess *f, const Ref &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality); static ResourceImporterTexture *get_singleton() { return singleton; } virtual String get_importer_name() const; diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 2a399087b2..cb0d9fa02b 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -41,6 +41,7 @@ #include "scene/3d/gi_probe.h" #include "scene/3d/gpu_particles_3d.h" #include "scene/3d/light_3d.h" +#include "scene/3d/lightmap_probe.h" #include "scene/3d/listener_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/navigation_region_3d.h" @@ -3069,136 +3070,296 @@ void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } //// -#if 0 -BakedIndirectLightGizmoPlugin::BakedIndirectLightGizmoPlugin() { - Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/baked_indirect_light", Color(0.5, 0.6, 1)); - create_material("baked_indirect_light_material", gizmo_color); +BakedLightmapGizmoPlugin::BakedLightmapGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/lightmap_lines", Color(0.5, 0.6, 1)); gizmo_color.a = 0.1; - create_material("baked_indirect_light_internal_material", gizmo_color); + create_material("lightmap_lines", gizmo_color); - create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_icon("GizmoBakedLightmap", "EditorIcons")); - create_handle_material("handles"); + Ref mat = memnew(StandardMaterial3D); + mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); + mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, false); + + add_material("lightmap_probe_material", mat); + + create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoBakedLightmap", "EditorIcons")); } -String BakedIndirectLightGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { - - switch (p_idx) { - case 0: return "Extents X"; - case 1: return "Extents Y"; - case 2: return "Extents Z"; - } +String BakedLightmapGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { return ""; } -Variant BakedIndirectLightGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { +Variant BakedLightmapGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); - return baker->get_extents(); + return Variant(); } -void BakedIndirectLightGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { - - BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); - - Transform gt = baker->get_global_transform(); - Transform gi = gt.affine_inverse(); - - Vector3 extents = baker->get_extents(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_idx] = 1.0; - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) - d = 0.001; - - extents[p_idx] = d; - baker->set_extents(extents); +void BakedLightmapGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { } -void BakedIndirectLightGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - - BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); - - Vector3 restore = p_restore; - - if (p_cancel) { - baker->set_extents(restore); - return; - } - - UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Probe Extents")); - ur->add_do_method(baker, "set_extents", baker->get_extents()); - ur->add_undo_method(baker, "set_extents", restore); - ur->commit_action(); +void BakedLightmapGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { } -bool BakedIndirectLightGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool BakedLightmapGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String BakedIndirectLightGizmoPlugin::get_name() const { +String BakedLightmapGizmoPlugin::get_name() const { return "BakedLightmap"; } -int BakedIndirectLightGizmoPlugin::get_priority() const { +int BakedLightmapGizmoPlugin::get_priority() const { return -1; } -void BakedIndirectLightGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { +void BakedLightmapGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); - - Ref material = get_material("baked_indirect_light_material", p_gizmo); Ref icon = get_material("baked_indirect_light_icon", p_gizmo); - Ref material_internal = get_material("baked_indirect_light_internal_material", p_gizmo); + BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); + Ref data = baker->get_light_data(); + + p_gizmo->add_unscaled_billboard(icon, 0.05); + + if (data.is_null()) { + return; + } + + Ref material_lines = get_material("lightmap_lines", p_gizmo); + Ref material_probes = get_material("lightmap_probe_material", p_gizmo); p_gizmo->clear(); Vector lines; - Vector3 extents = baker->get_extents(); + Set lines_found; - AABB aabb = AABB(-extents, extents * 2); - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); + Vector points = data->get_capture_points(); + if (points.size() == 0) { + return; + } + Vector sh = data->get_capture_sh(); + if (sh.size() != points.size() * 9) { + return; } - p_gizmo->add_lines(lines, material); + Vector tetrahedrons = data->get_capture_tetrahedra(); - Vector handles; + for (int i = 0; i < tetrahedrons.size(); i += 4) { - for (int i = 0; i < 3; i++) { + for (int j = 0; j < 4; j++) { + for (int k = j + 1; k < 4; k++) { - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); + Vector2i pair; + pair.x = tetrahedrons[i + j]; + pair.y = tetrahedrons[i + k]; + + if (pair.y < pair.x) { + SWAP(pair.x, pair.y); + } + if (lines_found.has(pair)) { + continue; + } + lines_found.insert(pair); + lines.push_back(points[pair.x]); + lines.push_back(points[pair.y]); + } + } } - if (p_gizmo->is_selected()) { - p_gizmo->add_solid_box(material_internal, aabb.get_size()); + p_gizmo->add_lines(lines, material_lines); + + int stack_count = 8; + int sector_count = 16; + + float sector_step = 2 * Math_PI / sector_count; + float stack_step = Math_PI / stack_count; + + Vector vertices; + Vector colors; + Vector indices; + float radius = 0.3; + + for (int p = 0; p < points.size(); p++) { + + int vertex_base = vertices.size(); + Vector3 sh_col[9]; + for (int i = 0; i < 9; i++) { + sh_col[i].x = sh[p * 9 + i].r; + sh_col[i].y = sh[p * 9 + i].g; + sh_col[i].z = sh[p * 9 + i].b; + } + + for (int i = 0; i <= stack_count; ++i) { + float stack_angle = Math_PI / 2 - i * stack_step; // starting from pi/2 to -pi/2 + float xy = radius * Math::cos(stack_angle); // r * cos(u) + float z = radius * Math::sin(stack_angle); // r * sin(u) + + // add (sector_count+1) vertices per stack + // the first and last vertices have same position and normal, but different tex coords + for (int j = 0; j <= sector_count; ++j) { + float sector_angle = j * sector_step; // starting from 0 to 2pi + + // vertex position (x, y, z) + float x = xy * Math::cos(sector_angle); // r * cos(u) * cos(v) + float y = xy * Math::sin(sector_angle); // r * cos(u) * sin(v) + + Vector3 n = Vector3(x, z, y); + vertices.push_back(points[p] + n); + n.normalize(); + + const float c1 = 0.429043; + const float c2 = 0.511664; + const float c3 = 0.743125; + const float c4 = 0.886227; + const float c5 = 0.247708; + Vector3 light = (c1 * sh_col[8] * (n.x * n.x - n.y * n.y) + + c3 * sh_col[6] * n.z * n.z + + c4 * sh_col[0] - + c5 * sh_col[6] + + 2.0 * c1 * sh_col[4] * n.x * n.y + + 2.0 * c1 * sh_col[7] * n.x * n.z + + 2.0 * c1 * sh_col[5] * n.y * n.z + + 2.0 * c2 * sh_col[3] * n.x + + 2.0 * c2 * sh_col[1] * n.y + + 2.0 * c2 * sh_col[2] * n.z); + + colors.push_back(Color(light.x, light.y, light.z, 1)); + } + } + + for (int i = 0; i < stack_count; ++i) { + int k1 = i * (sector_count + 1); // beginning of current stack + int k2 = k1 + sector_count + 1; // beginning of next stack + + for (int j = 0; j < sector_count; ++j, ++k1, ++k2) { + // 2 triangles per sector excluding first and last stacks + // k1 => k2 => k1+1 + if (i != 0) { + indices.push_back(vertex_base + k1); + indices.push_back(vertex_base + k2); + indices.push_back(vertex_base + k1 + 1); + } + + // k1+1 => k2 => k2+1 + if (i != (stack_count - 1)) { + indices.push_back(vertex_base + k1 + 1); + indices.push_back(vertex_base + k2); + indices.push_back(vertex_base + k2 + 1); + } + } + } } - p_gizmo->add_unscaled_billboard(icon, 0.05); - p_gizmo->add_handles(handles, get_material("handles")); + Array array; + array.resize(RS::ARRAY_MAX); + array[RS::ARRAY_VERTEX] = vertices; + array[RS::ARRAY_INDEX] = indices; + array[RS::ARRAY_COLOR] = colors; + + Ref mesh; + mesh.instance(); + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array, Array(), Dictionary(), 0); //no compression + mesh->surface_set_material(0, material_probes); + + p_gizmo->add_mesh(mesh); +} +///////// + +LightmapProbeGizmoPlugin::LightmapProbeGizmoPlugin() { + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/lightprobe_lines", Color(0.5, 0.6, 1)); + + gizmo_color.a = 0.3; + create_material("lightprobe_lines", gizmo_color); +} + +String LightmapProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { + + return ""; +} +Variant LightmapProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { + + return Variant(); +} +void LightmapProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { +} + +void LightmapProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +} + +bool LightmapProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != nullptr; +} + +String LightmapProbeGizmoPlugin::get_name() const { + return "LightmapProbe"; +} + +int LightmapProbeGizmoPlugin::get_priority() const { + return -1; +} + +void LightmapProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + + Ref material_lines = get_material("lightprobe_lines", p_gizmo); + + p_gizmo->clear(); + + Vector lines; + + int stack_count = 8; + int sector_count = 16; + + float sector_step = 2 * Math_PI / sector_count; + float stack_step = Math_PI / stack_count; + + Vector vertices; + float radius = 0.2; + + for (int i = 0; i <= stack_count; ++i) { + float stack_angle = Math_PI / 2 - i * stack_step; // starting from pi/2 to -pi/2 + float xy = radius * Math::cos(stack_angle); // r * cos(u) + float z = radius * Math::sin(stack_angle); // r * sin(u) + + // add (sector_count+1) vertices per stack + // the first and last vertices have same position and normal, but different tex coords + for (int j = 0; j <= sector_count; ++j) { + float sector_angle = j * sector_step; // starting from 0 to 2pi + + // vertex position (x, y, z) + float x = xy * Math::cos(sector_angle); // r * cos(u) * cos(v) + float y = xy * Math::sin(sector_angle); // r * cos(u) * sin(v) + + Vector3 n = Vector3(x, z, y); + vertices.push_back(n); + } + } + + for (int i = 0; i < stack_count; ++i) { + int k1 = i * (sector_count + 1); // beginning of current stack + int k2 = k1 + sector_count + 1; // beginning of next stack + + for (int j = 0; j < sector_count; ++j, ++k1, ++k2) { + // 2 triangles per sector excluding first and last stacks + // k1 => k2 => k1+1 + if (i != 0) { + lines.push_back(vertices[k1]); + lines.push_back(vertices[k2]); + lines.push_back(vertices[k1]); + lines.push_back(vertices[k1 + 1]); + } + + if (i != (stack_count - 1)) { + lines.push_back(vertices[k1 + 1]); + lines.push_back(vertices[k2]); + lines.push_back(vertices[k2]); + lines.push_back(vertices[k2 + 1]); + } + } + } + + p_gizmo->add_lines(lines, material_lines); } -#endif //// CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() { diff --git a/editor/node_3d_editor_gizmos.h b/editor/node_3d_editor_gizmos.h index 6432feeecb..c25fff528c 100644 --- a/editor/node_3d_editor_gizmos.h +++ b/editor/node_3d_editor_gizmos.h @@ -321,25 +321,42 @@ public: GIProbeGizmoPlugin(); }; -#if 0 -class BakedIndirectLightGizmoPlugin : public EditorNode3DGizmoPlugin { +class BakedLightmapGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(BakedIndirectLightGizmoPlugin, EditorNode3DGizmoPlugin); + GDCLASS(BakedLightmapGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; void redraw(EditorNode3DGizmo *p_gizmo); String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - BakedIndirectLightGizmoPlugin(); + BakedLightmapGizmoPlugin(); }; -#endif + +class LightmapProbeGizmoPlugin : public EditorNode3DGizmoPlugin { + + GDCLASS(LightmapProbeGizmoPlugin, EditorNode3DGizmoPlugin); + +public: + bool has_gizmo(Node3D *p_spatial); + String get_name() const; + int get_priority() const; + void redraw(EditorNode3DGizmo *p_gizmo); + + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + + LightmapProbeGizmoPlugin(); +}; + class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin); diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp index ba161244d6..f754dd4725 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.cpp +++ b/editor/plugins/baked_lightmap_editor_plugin.cpp @@ -28,23 +28,36 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if 0 #include "baked_lightmap_editor_plugin.h" -void BakedLightmapEditorPlugin::_bake() { +void BakedLightmapEditorPlugin::_bake_select_file(const String &p_file) { if (lightmap) { BakedLightmap::BakeError err; if (get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root() == lightmap) { - err = lightmap->bake(lightmap); + err = lightmap->bake(lightmap, p_file, bake_func_step); } else { - err = lightmap->bake(lightmap->get_parent()); + err = lightmap->bake(lightmap->get_parent(), p_file, bake_func_step); } + bake_func_end(); + switch (err) { - case BakedLightmap::BAKE_ERROR_NO_SAVE_PATH: - EditorNode::get_singleton()->show_warning(TTR("Can't determine a save path for lightmap images.\nSave your scene (for images to be saved in the same dir), or pick a save path from the BakedLightmap properties.")); - break; + case BakedLightmap::BAKE_ERROR_NO_SAVE_PATH: { + String scene_path = lightmap->get_filename(); + if (scene_path == String()) { + scene_path = lightmap->get_owner()->get_filename(); + } + if (scene_path == String()) { + EditorNode::get_singleton()->show_warning(TTR("Can't determine a save path for lightmap images.\nSave your scene and try again.")); + break; + } + scene_path = scene_path.get_basename() + ".lmbake"; + + file_dialog->set_current_path(scene_path); + file_dialog->popup_centered_ratio(); + + } break; case BakedLightmap::BAKE_ERROR_NO_MESHES: EditorNode::get_singleton()->show_warning(TTR("No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake Light' flag is on.")); break; @@ -57,6 +70,11 @@ void BakedLightmapEditorPlugin::_bake() { } } +void BakedLightmapEditorPlugin::_bake() { + + _bake_select_file(""); +} + void BakedLightmapEditorPlugin::edit(Object *p_object) { BakedLightmap *s = Object::cast_to(p_object); @@ -83,23 +101,20 @@ void BakedLightmapEditorPlugin::make_visible(bool p_visible) { EditorProgress *BakedLightmapEditorPlugin::tmp_progress = nullptr; -void BakedLightmapEditorPlugin::bake_func_begin(int p_steps) { +bool BakedLightmapEditorPlugin::bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh) { - ERR_FAIL_COND(tmp_progress != nullptr); - - tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), p_steps, true)); -} - -bool BakedLightmapEditorPlugin::bake_func_step(int p_step, const String &p_description) { - - ERR_FAIL_COND_V(tmp_progress == nullptr, false); - return tmp_progress->step(p_description, p_step, false); + if (!tmp_progress) { + tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, false)); + ERR_FAIL_COND_V(tmp_progress == nullptr, false); + } + return tmp_progress->step(p_description, p_progress * 1000, p_refresh); } void BakedLightmapEditorPlugin::bake_func_end() { - ERR_FAIL_COND(tmp_progress == nullptr); - memdelete(tmp_progress); - tmp_progress = nullptr; + if (tmp_progress != nullptr) { + memdelete(tmp_progress); + tmp_progress = nullptr; + } } void BakedLightmapEditorPlugin::_bind_methods() { @@ -111,18 +126,20 @@ BakedLightmapEditorPlugin::BakedLightmapEditorPlugin(EditorNode *p_node) { editor = p_node; bake = memnew(ToolButton); - bake->set_icon(editor->get_gui_base()->get_icon("Bake", "EditorIcons")); + bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); bake->set_text(TTR("Bake Lightmaps")); bake->hide(); - bake->connect("pressed", this, "_bake"); + bake->connect("pressed", Callable(this, "_bake")); add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake); lightmap = nullptr; - BakedLightmap::bake_begin_function = bake_func_begin; - BakedLightmap::bake_step_function = bake_func_step; - BakedLightmap::bake_end_function = bake_func_end; + file_dialog = memnew(EditorFileDialog); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + file_dialog->add_filter("*.lmbake ; LightMap Bake"); + file_dialog->set_title(TTR("Select lightmap bake file:")); + file_dialog->connect("file_selected", callable_mp(this, &BakedLightmapEditorPlugin::_bake_select_file)); + bake->add_child(file_dialog); } BakedLightmapEditorPlugin::~BakedLightmapEditorPlugin() { } -#endif diff --git a/editor/plugins/baked_lightmap_editor_plugin.h b/editor/plugins/baked_lightmap_editor_plugin.h index 818cdfe8fa..2dbc09fc1d 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.h +++ b/editor/plugins/baked_lightmap_editor_plugin.h @@ -28,7 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if 0 #ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H #define BAKED_LIGHTMAP_EDITOR_PLUGIN_H @@ -46,11 +45,12 @@ class BakedLightmapEditorPlugin : public EditorPlugin { ToolButton *bake; EditorNode *editor; + EditorFileDialog *file_dialog; static EditorProgress *tmp_progress; - static void bake_func_begin(int p_steps); - static bool bake_func_step(int p_step, const String &p_description); + static bool bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh); static void bake_func_end(); + void _bake_select_file(const String &p_file); void _bake(); protected: @@ -67,5 +67,4 @@ public: ~BakedLightmapEditorPlugin(); }; -#endif // BAKED_LIGHTMAP_EDITOR_PLUGIN_H #endif diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 65c0763e63..b5fcf82d76 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -6161,7 +6161,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian type == "ViewportTexture" || type == "CurveTexture" || type == "GradientTexture" || - type == "StreamTexture" || + type == "StreamTexture2D" || type == "AtlasTexture" || type == "LargeTexture") { Ref texture = Ref(Object::cast_to(*res)); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 1bf5999906..69f8efa86e 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -6008,7 +6008,8 @@ void Node3DEditor::_register_all_gizmos() { add_gizmo_plugin(Ref(memnew(ReflectionProbeGizmoPlugin))); add_gizmo_plugin(Ref(memnew(DecalGizmoPlugin))); add_gizmo_plugin(Ref(memnew(GIProbeGizmoPlugin))); - // add_gizmo_plugin(Ref(memnew(BakedIndirectLightGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(BakedLightmapGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(LightmapProbeGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionShape3DGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionPolygon3DGizmoPlugin))); add_gizmo_plugin(Ref(memnew(NavigationRegion3DGizmoPlugin))); diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index c1184c1c89..7a3e571f16 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -84,8 +84,8 @@ void TextureEditor::_notification(int p_what) { String format; if (Object::cast_to(*texture)) { format = Image::get_format_name(Object::cast_to(*texture)->get_format()); - } else if (Object::cast_to(*texture)) { - format = Image::get_format_name(Object::cast_to(*texture)->get_format()); + } else if (Object::cast_to(*texture)) { + format = Image::get_format_name(Object::cast_to(*texture)->get_format()); } else { format = texture->get_class(); } @@ -144,7 +144,7 @@ TextureEditor::~TextureEditor() { // bool EditorInspectorPluginTexture::can_handle(Object *p_object) { - return Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr; + return Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr || Object::cast_to(p_object) != nullptr; } void EditorInspectorPluginTexture::parse_begin(Object *p_object) { diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp new file mode 100644 index 0000000000..6d716951b3 --- /dev/null +++ b/editor/plugins/texture_layered_editor_plugin.cpp @@ -0,0 +1,286 @@ +/*************************************************************************/ +/* texture_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "texture_layered_editor_plugin.h" + +#include "core/io/resource_loader.h" +#include "core/project_settings.h" +#include "editor/editor_settings.h" + +void TextureLayeredEditor::_gui_input(Ref p_event) { + Ref mm = p_event; + if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + y_rot += -mm->get_relative().x * 0.01; + x_rot += mm->get_relative().y * 0.01; + _update_material(); + } +} + +void TextureLayeredEditor::_texture_rect_draw() { + texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1)); +} + +void TextureLayeredEditor::_notification(int p_what) { + + if (p_what == NOTIFICATION_READY) { + + //get_scene()->connect("node_removed",this,"_node_removed"); + } + if (p_what == NOTIFICATION_RESIZED) { + _texture_rect_update_area(); + } + + if (p_what == NOTIFICATION_DRAW) { + + Ref checkerboard = get_theme_icon("Checkerboard", "EditorIcons"); + Size2 size = get_size(); + + draw_texture_rect(checkerboard, Rect2(Point2(), size), true); + } +} + +void TextureLayeredEditor::_changed_callback(Object *p_changed, const char *p_prop) { + + if (!is_visible()) + return; + update(); +} + +void TextureLayeredEditor::_update_material() { + + materials[0]->set_shader_param("layer", layer->get_value()); + materials[2]->set_shader_param("layer", layer->get_value()); + materials[texture->get_layered_type()]->set_shader_param("tex", texture->get_rid()); + + Vector3 v(1, 1, 1); + v.normalize(); + + Basis b; + b.rotate(Vector3(1, 0, 0), x_rot); + b.rotate(Vector3(0, 1, 0), y_rot); + + materials[1]->set_shader_param("normal", v); + materials[1]->set_shader_param("rot", b); + materials[2]->set_shader_param("normal", v); + materials[2]->set_shader_param("rot", b); + + String format = Image::get_format_name(texture->get_format()); + + String text; + if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_2D_ARRAY) { + text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers()) + ")" + format; + } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP) { + text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format; + } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY) { + text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers() / 6) + ")" + format; + } + + info->set_text(text); +} + +void TextureLayeredEditor::_make_shaders() { + String shader_2d_array = "" + "shader_type canvas_item;\n" + "uniform sampler2DArray tex;\n" + "uniform float layer;\n" + "void fragment() {\n" + " COLOR = textureLod(tex,vec3(UV,layer),0.0);\n" + "}"; + + shaders[0].instance(); + shaders[0]->set_code(shader_2d_array); + + String shader_cube = "" + "shader_type canvas_item;\n" + "uniform samplerCube tex;\n" + "uniform vec3 normal;\n" + "uniform mat3 rot;\n" + "void fragment() {\n" + " vec3 n = rot * normalize(vec3(normal.xy*(UV * 2.0 - 1.0),normal.z));\n" + " COLOR = textureLod(tex,n,0.0);\n" + "}"; + + shaders[1].instance(); + shaders[1]->set_code(shader_cube); + + String shader_cube_array = "" + "shader_type canvas_item;\n" + "uniform samplerCubeArray tex;\n" + "uniform vec3 normal;\n" + "uniform mat3 rot;\n" + "uniform float layer;\n" + "void fragment() {\n" + " vec3 n = rot * normalize(vec3(normal.xy*(UV * 2.0 - 1.0),normal.z));\n" + " COLOR = textureLod(tex,vec4(n,layer),0.0);\n" + "}"; + + shaders[2].instance(); + shaders[2]->set_code(shader_cube_array); + + for (int i = 0; i < 3; i++) { + materials[i].instance(); + materials[i]->set_shader(shaders[i]); + } +} + +void TextureLayeredEditor::_texture_rect_update_area() { + + Size2 size = get_size(); + int tex_width = texture->get_width() * size.height / texture->get_height(); + int tex_height = size.height; + + if (tex_width > size.width) { + tex_width = size.width; + tex_height = texture->get_height() * tex_width / texture->get_width(); + } + + // Prevent the texture from being unpreviewable after the rescale, so that we can still see something + if (tex_height <= 0) + tex_height = 1; + if (tex_width <= 0) + tex_width = 1; + + int ofs_x = (size.width - tex_width) / 2; + int ofs_y = (size.height - tex_height) / 2; + + texture_rect->set_position(Vector2(ofs_x, ofs_y)); + texture_rect->set_size(Vector2(tex_width, tex_height)); +} + +void TextureLayeredEditor::edit(Ref p_texture) { + + if (!texture.is_null()) + texture->remove_change_receptor(this); + + texture = p_texture; + + if (!texture.is_null()) { + + if (shaders[0].is_null()) { + _make_shaders(); + } + + texture->add_change_receptor(this); + update(); + texture_rect->set_material(materials[texture->get_layered_type()]); + setting = true; + if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_2D_ARRAY) { + layer->set_max(texture->get_layers() - 1); + layer->set_value(0); + layer->show(); + } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY) { + layer->set_max(texture->get_layers() / 6 - 1); + layer->set_value(0); + layer->show(); + } else { + layer->hide(); + } + x_rot = 0; + y_rot = 0; + _update_material(); + setting = false; + _texture_rect_update_area(); + } else { + hide(); + } +} + +void TextureLayeredEditor::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_gui_input"), &TextureLayeredEditor::_gui_input); + ClassDB::bind_method(D_METHOD("_layer_changed"), &TextureLayeredEditor::_layer_changed); +} + +TextureLayeredEditor::TextureLayeredEditor() { + + set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED); + set_custom_minimum_size(Size2(1, 150)); + texture_rect = memnew(Control); + texture_rect->connect("draw", callable_mp(this, &TextureLayeredEditor::_texture_rect_draw)); + texture_rect->set_mouse_filter(MOUSE_FILTER_IGNORE); + add_child(texture_rect); + + layer = memnew(SpinBox); + layer->set_step(1); + layer->set_max(100); + add_child(layer); + layer->set_anchor(MARGIN_RIGHT, 1); + layer->set_anchor(MARGIN_LEFT, 1); + layer->set_h_grow_direction(GROW_DIRECTION_BEGIN); + layer->set_modulate(Color(1, 1, 1, 0.8)); + info = memnew(Label); + add_child(info); + info->set_anchor(MARGIN_RIGHT, 1); + info->set_anchor(MARGIN_LEFT, 1); + info->set_anchor(MARGIN_BOTTOM, 1); + info->set_anchor(MARGIN_TOP, 1); + info->set_h_grow_direction(GROW_DIRECTION_BEGIN); + info->set_v_grow_direction(GROW_DIRECTION_BEGIN); + info->add_theme_color_override("font_color", Color(1, 1, 1, 1)); + info->add_theme_color_override("font_color_shadow", Color(0, 0, 0, 0.5)); + info->add_theme_color_override("font_color_shadow", Color(0, 0, 0, 0.5)); + info->add_theme_constant_override("shadow_as_outline", 1); + info->add_theme_constant_override("shadow_offset_x", 2); + info->add_theme_constant_override("shadow_offset_y", 2); + + setting = false; + layer->connect("value_changed", Callable(this, "_layer_changed")); +} + +TextureLayeredEditor::~TextureLayeredEditor() { + if (!texture.is_null()) { + texture->remove_change_receptor(this); + } +} +// +bool EditorInspectorPluginLayeredTexture::can_handle(Object *p_object) { + + return Object::cast_to(p_object) != nullptr; +} + +void EditorInspectorPluginLayeredTexture::parse_begin(Object *p_object) { + + TextureLayered *texture = Object::cast_to(p_object); + if (!texture) { + return; + } + Ref m(texture); + + TextureLayeredEditor *editor = memnew(TextureLayeredEditor); + editor->edit(m); + add_custom_control(editor); +} + +TextureLayeredEditorPlugin::TextureLayeredEditorPlugin(EditorNode *p_node) { + + Ref plugin; + plugin.instance(); + add_inspector_plugin(plugin); +} diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h new file mode 100644 index 0000000000..e8503e845e --- /dev/null +++ b/editor/plugins/texture_layered_editor_plugin.h @@ -0,0 +1,95 @@ +/*************************************************************************/ +/* texture_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_LAYERED_EDITOR_PLUGIN_H +#define TEXTURE_LAYERED_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/resources/shader.h" +#include "scene/resources/texture.h" +class TextureLayeredEditor : public Control { + + GDCLASS(TextureLayeredEditor, Control); + + SpinBox *layer; + Label *info; + Ref texture; + + Ref shaders[3]; + Ref materials[3]; + + float x_rot = 0; + float y_rot = 0; + Control *texture_rect; + + void _make_shaders(); + + void _update_material(); + bool setting; + void _layer_changed(double) { + if (!setting) + _update_material(); + } + + void _texture_rect_update_area(); + void _texture_rect_draw(); + +protected: + void _notification(int p_what); + void _gui_input(Ref p_event); + void _changed_callback(Object *p_changed, const char *p_prop); + static void _bind_methods(); + +public: + void edit(Ref p_texture); + TextureLayeredEditor(); + ~TextureLayeredEditor(); +}; + +class EditorInspectorPluginLayeredTexture : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginLayeredTexture, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object); + virtual void parse_begin(Object *p_object); +}; + +class TextureLayeredEditorPlugin : public EditorPlugin { + + GDCLASS(TextureLayeredEditorPlugin, EditorPlugin); + +public: + virtual String get_name() const { return "TextureLayered"; } + + TextureLayeredEditorPlugin(EditorNode *p_node); +}; + +#endif // TEXTURE_EDITOR_PLUGIN_H diff --git a/gles_builders.py b/gles_builders.py index 6ff2f4248b..85a8d7aa15 100644 --- a/gles_builders.py +++ b/gles_builders.py @@ -740,5 +740,69 @@ def build_rd_headers(target, source, env): build_rd_header(str(x)) +class RAWHeaderStruct: + def __init__(self): + self.code = "" + + +def include_file_in_raw_header(filename, header_data, depth): + fs = open(filename, "r") + line = fs.readline() + text = "" + + while line: + + while line.find("#include ") != -1: + includeline = line.replace("#include ", "").strip()[1:-1] + + import os.path + + included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline) + include_file_in_raw_header(included_file, header_data, depth + 1) + + line = fs.readline() + + header_data.code += line + line = fs.readline() + + fs.close() + + +def build_raw_header(filename): + header_data = RAWHeaderStruct() + include_file_in_raw_header(filename, header_data, 0) + + out_file = filename + ".gen.h" + fd = open(out_file, "w") + + enum_constants = [] + + fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n") + + out_file_base = out_file.replace(".glsl.gen.h", "_shader_glsl") + out_file_base = out_file_base[out_file_base.rfind("/") + 1 :] + out_file_base = out_file_base[out_file_base.rfind("\\") + 1 :] + out_file_ifdef = out_file_base.replace(".", "_").upper() + fd.write("#ifndef " + out_file_ifdef + "_RAW_H\n") + fd.write("#define " + out_file_ifdef + "_RAW_H\n") + fd.write("\n") + fd.write("static const char " + out_file_base + "[] = {\n") + for c in header_data.code: + fd.write(str(ord(c)) + ",") + fd.write("\t\t0};\n\n") + fd.write("#endif\n") + fd.close() + + +def build_rd_headers(target, source, env): + for x in source: + build_rd_header(str(x)) + + +def build_raw_headers(target, source, env): + for x in source: + build_raw_header(str(x)) + + if __name__ == "__main__": subprocess_main(globals()) diff --git a/main/main.cpp b/main/main.cpp index b6afd9160c..65c6fdd397 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2063,9 +2063,11 @@ bool Main::start() { } if (project_manager || editor) { - // Hide console window if requested (Windows-only). - bool hide_console = EditorSettings::get_singleton()->get_setting("interface/editor/hide_console_window"); - DisplayServer::get_singleton()->console_set_visible(!hide_console); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CONSOLE_WINDOW)) { + // Hide console window if requested (Windows-only). + bool hide_console = EditorSettings::get_singleton()->get_setting("interface/editor/hide_console_window"); + DisplayServer::get_singleton()->console_set_visible(!hide_console); + } // Load SSL Certificates from Editor Settings (or builtin) Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String()); diff --git a/main/tests/test_math.cpp b/main/tests/test_math.cpp index b6ef573b36..fbd1aa275a 100644 --- a/main/tests/test_math.cpp +++ b/main/tests/test_math.cpp @@ -32,8 +32,10 @@ #include "core/math/basis.h" #include "core/math/camera_matrix.h" +#include "core/math/delaunay_3d.h" #include "core/math/math_funcs.h" #include "core/math/transform.h" +#include "core/method_ptrcall.h" #include "core/os/file_access.h" #include "core/os/keyboard.h" #include "core/os/os.h" @@ -45,8 +47,6 @@ #include "scene/resources/texture.h" #include "servers/rendering/shader_language.h" -#include "core/method_ptrcall.h" - namespace TestMath { class GetClassAndNamespace { @@ -414,6 +414,55 @@ uint32_t ihash3(uint32_t a) { MainLoop *test() { + { + Vector points; + points.push_back(Vector3(0, 0, 0)); + points.push_back(Vector3(0, 0, 1)); + points.push_back(Vector3(0, 1, 0)); + points.push_back(Vector3(0, 1, 1)); + points.push_back(Vector3(1, 1, 0)); + points.push_back(Vector3(1, 0, 0)); + points.push_back(Vector3(1, 0, 1)); + points.push_back(Vector3(1, 1, 1)); + + for (int i = 0; i < 800; i++) { + points.push_back(Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * Vector3(25, 30, 33)); + } + + Vector os = Delaunay3D::tetrahedralize(points); + print_line("simplices in the end: " + itos(os.size())); + for (int i = 0; i < os.size(); i++) { + print_line("Simplex " + itos(i) + ": "); + print_line(points[os[i].points[0]]); + print_line(points[os[i].points[1]]); + print_line(points[os[i].points[2]]); + print_line(points[os[i].points[3]]); + } + + { + FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE); + for (int i = 0; i < os.size(); i++) { + f->store_line("o Simplex" + itos(i)); + for (int j = 0; j < 4; j++) { + f->store_line(vformat("v %f %f %f", points[os[i].points[j]].x, points[os[i].points[j]].y, points[os[i].points[j]].z)); + } + static const int face_order[4][3] = { + { 1, 2, 3 }, + { 1, 3, 4 }, + { 1, 2, 4 }, + { 2, 3, 4 } + }; + + for (int j = 0; j < 4; j++) { + f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2])); + } + } + f->close(); + } + + return nullptr; + } + { float r = 1; float g = 0.5; diff --git a/modules/denoise/SCsub b/modules/denoise/SCsub new file mode 100644 index 0000000000..8cf91b7dbd --- /dev/null +++ b/modules/denoise/SCsub @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +import resource_to_cpp +from platform_methods import run_in_subprocess + +Import("env") +Import("env_modules") + +env_oidn = env_modules.Clone() + +# Thirdparty source files +thirdparty_dir = "#thirdparty/oidn/" +thirdparty_sources = [ + "core/api.cpp", + "core/device.cpp", + "core/filter.cpp", + "core/network.cpp", + "core/autoencoder.cpp", + "core/transfer_function.cpp", + "weights/rtlightmap_hdr.cpp", + "mkl-dnn/src/common/batch_normalization.cpp", + "mkl-dnn/src/common/concat.cpp", + "mkl-dnn/src/common/convolution.cpp", + "mkl-dnn/src/common/convolution_pd.cpp", + "mkl-dnn/src/common/deconvolution.cpp", + "mkl-dnn/src/common/eltwise.cpp", + "mkl-dnn/src/common/engine.cpp", + "mkl-dnn/src/common/inner_product.cpp", + "mkl-dnn/src/common/inner_product_pd.cpp", + "mkl-dnn/src/common/lrn.cpp", + "mkl-dnn/src/common/memory.cpp", + "mkl-dnn/src/common/memory_desc_wrapper.cpp", + "mkl-dnn/src/common/mkldnn_debug.cpp", + "mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp", + "mkl-dnn/src/common/pooling.cpp", + "mkl-dnn/src/common/primitive.cpp", + "mkl-dnn/src/common/primitive_attr.cpp", + "mkl-dnn/src/common/primitive_desc.cpp", + "mkl-dnn/src/common/primitive_exec_types.cpp", + "mkl-dnn/src/common/primitive_iterator.cpp", + "mkl-dnn/src/common/query.cpp", + "mkl-dnn/src/common/reorder.cpp", + "mkl-dnn/src/common/rnn.cpp", + "mkl-dnn/src/common/scratchpad.cpp", + "mkl-dnn/src/common/shuffle.cpp", + "mkl-dnn/src/common/softmax.cpp", + "mkl-dnn/src/common/stream.cpp", + "mkl-dnn/src/common/sum.cpp", + "mkl-dnn/src/common/utils.cpp", + "mkl-dnn/src/common/verbose.cpp", + "mkl-dnn/src/cpu/cpu_barrier.cpp", + "mkl-dnn/src/cpu/cpu_concat.cpp", + "mkl-dnn/src/cpu/cpu_engine.cpp", + "mkl-dnn/src/cpu/cpu_memory.cpp", + "mkl-dnn/src/cpu/cpu_reducer.cpp", + "mkl-dnn/src/cpu/cpu_reorder.cpp", + "mkl-dnn/src/cpu/cpu_sum.cpp", + "mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_avx2_convolution.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp", + "mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp", + "mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp", + "mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp", + "mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_sse42_convolution.cpp", + "mkl-dnn/src/cpu/jit_transpose_src_utils.cpp", + "mkl-dnn/src/cpu/jit_uni_eltwise.cpp", + "mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_uni_pooling.cpp", + "mkl-dnn/src/cpu/jit_uni_reorder.cpp", + "mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp", + "mkl-dnn/src/cpu/jit_utils/jit_utils.cpp", + "mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c", + "common/platform.cpp", + "common/thread.cpp", + "common/tensor.cpp", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +thirdparty_include_dirs = [ + "", + "include", + "mkl-dnn/include", + "mkl-dnn/src", + "mkl-dnn/src/common", + "mkl-dnn/src/cpu/xbyak", + "mkl-dnn/src/cpu", +] +thirdparty_include_dirs = [thirdparty_dir + file for file in thirdparty_include_dirs] + + +env_oidn.Prepend(CPPPATH=thirdparty_include_dirs) +env_oidn.Append( + CPPDEFINES=[ + "MKLDNN_THR=MKLDNN_THR_SEQ", + "OIDN_STATIC_LIB", + "__STDC_CONSTANT_MACROS", + "__STDC_LIMIT_MACROS", + "DISABLE_VERBOSE", + "MKLDNN_ENABLE_CONCURRENT_EXEC", + "NDEBUG", + ] +) + +env_thirdparty = env_oidn.Clone() +env_thirdparty.disable_warnings() +env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) + +weights_in_path = thirdparty_dir + "weights/rtlightmap_hdr.tza" +weights_out_path = thirdparty_dir + "weights/rtlightmap_hdr.cpp" + +env_thirdparty.Depends(weights_out_path, weights_in_path) +env_thirdparty.CommandNoCache(weights_out_path, weights_in_path, resource_to_cpp.tza_to_cpp) + +env_oidn.add_source_files(env.modules_sources, "denoise_wrapper.cpp") +env_modules.add_source_files(env.modules_sources, ["register_types.cpp", "lightmap_denoiser.cpp"]) diff --git a/modules/denoise/config.py b/modules/denoise/config.py new file mode 100644 index 0000000000..53b8f2f2e3 --- /dev/null +++ b/modules/denoise/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return env["tools"] + + +def configure(env): + pass diff --git a/modules/denoise/denoise_wrapper.cpp b/modules/denoise/denoise_wrapper.cpp new file mode 100644 index 0000000000..feeeaef507 --- /dev/null +++ b/modules/denoise/denoise_wrapper.cpp @@ -0,0 +1,34 @@ +#include "denoise_wrapper.h" +#include "thirdparty/oidn/include/OpenImageDenoise/oidn.h" +#include + +void *oidn_denoiser_init() { + OIDNDeviceImpl *device = oidnNewDevice(OIDN_DEVICE_TYPE_CPU); + oidnCommitDevice(device); + return device; +} + +bool oidn_denoise(void *deviceptr, float *p_floats, int p_width, int p_height) { + OIDNDeviceImpl *device = (OIDNDeviceImpl *)deviceptr; + OIDNFilter filter = oidnNewFilter(device, "RTLightmap"); + oidnSetSharedFilterImage(filter, "color", (void *)p_floats, OIDN_FORMAT_FLOAT3, p_width, p_height, 0, 0, 0); + oidnSetSharedFilterImage(filter, "output", (void *)p_floats, OIDN_FORMAT_FLOAT3, p_width, p_height, 0, 0, 0); + oidnSetFilter1b(filter, "hdr", true); + //oidnSetFilter1f(filter, "hdrScale", 1.0f); + oidnCommitFilter(filter); + oidnExecuteFilter(filter); + + const char *msg; + bool success = true; + if (oidnGetDeviceError(device, &msg) != OIDN_ERROR_NONE) { + printf("LightmapDenoiser: %s\n", msg); + success = false; + } + + oidnReleaseFilter(filter); + return success; +} + +void oidn_denoiser_finish(void *device) { + oidnReleaseDevice((OIDNDeviceImpl *)device); +} diff --git a/modules/denoise/denoise_wrapper.h b/modules/denoise/denoise_wrapper.h new file mode 100644 index 0000000000..3aef326e22 --- /dev/null +++ b/modules/denoise/denoise_wrapper.h @@ -0,0 +1,8 @@ +#ifndef DENOISE_WRAPPER_H +#define DENOISE_WRAPPER_H + +void *oidn_denoiser_init(); +bool oidn_denoise(void *device, float *p_floats, int p_width, int p_height); +void oidn_denoiser_finish(void *device); + +#endif // DENOISE_WRAPPER_H diff --git a/modules/denoise/lightmap_denoiser.cpp b/modules/denoise/lightmap_denoiser.cpp new file mode 100644 index 0000000000..c821b22d85 --- /dev/null +++ b/modules/denoise/lightmap_denoiser.cpp @@ -0,0 +1,63 @@ +/*************************************************************************/ +/* lightmap_denoiser.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "lightmap_denoiser.h" +#include "denoise_wrapper.h" + +LightmapDenoiser *LightmapDenoiserOIDN::create_oidn_denoiser() { + return memnew(LightmapDenoiserOIDN); +} + +void LightmapDenoiserOIDN::make_default_denoiser() { + create_function = create_oidn_denoiser; +} + +Ref LightmapDenoiserOIDN::denoise_image(const Ref &p_image) { + + Ref img = p_image->duplicate(); + + img->convert(Image::FORMAT_RGBF); + + Vector data = img->get_data(); + if (!oidn_denoise(device, (float *)data.ptrw(), img->get_width(), img->get_height())) { + return p_image; + } + + img->create(img->get_width(), img->get_height(), false, img->get_format(), data); + return img; +} + +LightmapDenoiserOIDN::LightmapDenoiserOIDN() { + device = oidn_denoiser_init(); +} + +LightmapDenoiserOIDN::~LightmapDenoiserOIDN() { + oidn_denoiser_finish(device); +} diff --git a/modules/denoise/lightmap_denoiser.h b/modules/denoise/lightmap_denoiser.h new file mode 100644 index 0000000000..ac0cc8b9db --- /dev/null +++ b/modules/denoise/lightmap_denoiser.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* lightmap_denoiser.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHTMAP_DENOISER_H +#define LIGHTMAP_DENOISER_H + +#include "core/object.h" +#include "scene/3d/lightmapper.h" + +struct OIDNDeviceImpl; + +class LightmapDenoiserOIDN : public LightmapDenoiser { + + GDCLASS(LightmapDenoiserOIDN, LightmapDenoiser); + +protected: + void *device = nullptr; + +public: + static LightmapDenoiser *create_oidn_denoiser(); + + Ref denoise_image(const Ref &p_image); + + static void make_default_denoiser(); + + LightmapDenoiserOIDN(); + ~LightmapDenoiserOIDN(); +}; + +#endif // LIGHTMAP_DENOISER_H diff --git a/modules/denoise/register_types.cpp b/modules/denoise/register_types.cpp new file mode 100644 index 0000000000..b6b92701c8 --- /dev/null +++ b/modules/denoise/register_types.cpp @@ -0,0 +1,41 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "register_types.h" +#include "core/engine.h" +#include "lightmap_denoiser.h" + +void register_denoise_types() { + + LightmapDenoiserOIDN::make_default_denoiser(); +} + +void unregister_denoise_types() { +} diff --git a/modules/denoise/register_types.h b/modules/denoise/register_types.h new file mode 100644 index 0000000000..2ffc36ee2c --- /dev/null +++ b/modules/denoise/register_types.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +void register_denoise_types(); +void unregister_denoise_types(); diff --git a/modules/denoise/resource_to_cpp.py b/modules/denoise/resource_to_cpp.py new file mode 100644 index 0000000000..4c0b67f701 --- /dev/null +++ b/modules/denoise/resource_to_cpp.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +## ======================================================================== ## +## Copyright 2009-2019 Intel Corporation ## +## ## +## Licensed under the Apache License, Version 2.0 (the "License"); ## +## you may not use this file except in compliance with the License. ## +## You may obtain a copy of the License at ## +## ## +## http://www.apache.org/licenses/LICENSE-2.0 ## +## ## +## Unless required by applicable law or agreed to in writing, software ## +## distributed under the License is distributed on an "AS IS" BASIS, ## +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## +## See the License for the specific language governing permissions and ## +## limitations under the License. ## +## ======================================================================== ## + +import os +import sys +import argparse +from array import array + +# Generates a C++ file from the specified binary resource file +def generate(in_path, out_path): + + namespace = "oidn::weights" + scopes = namespace.split("::") + + file_name = os.path.basename(in_path) + var_name = os.path.splitext(file_name)[0] + + with open(in_path, "rb") as in_file, open(out_path, "w") as out_file: + # Header + out_file.write("// Generated from: %s\n" % file_name) + out_file.write("#include \n\n") + + # Open the namespaces + for s in scopes: + out_file.write("namespace %s {\n" % s) + if scopes: + out_file.write("\n") + + # Read the file + in_data = array("B", in_file.read()) + + # Write the size + out_file.write("//const size_t %s_size = %d;\n\n" % (var_name, len(in_data))) + + # Write the data + out_file.write("unsigned char %s[] = {" % var_name) + for i in range(len(in_data)): + c = in_data[i] + if i > 0: + out_file.write(",") + if (i + 1) % 20 == 1: + out_file.write("\n") + out_file.write("%d" % c) + out_file.write("\n};\n") + + # Close the namespaces + if scopes: + out_file.write("\n") + for scope in reversed(scopes): + out_file.write("} // namespace %s\n" % scope) + + +def tza_to_cpp(target, source, env): + for x in zip(source, target): + generate(str(x[0]), str(x[1])) diff --git a/modules/lightmapper_rd/SCsub b/modules/lightmapper_rd/SCsub new file mode 100644 index 0000000000..2f04f1833e --- /dev/null +++ b/modules/lightmapper_rd/SCsub @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_lightmapper_rd = env_modules.Clone() +env_lightmapper_rd.GLSL_HEADER("lm_raster.glsl") +env_lightmapper_rd.GLSL_HEADER("lm_compute.glsl") +env_lightmapper_rd.GLSL_HEADER("lm_blendseams.glsl") + +# Godot source files +env_lightmapper_rd.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/lightmapper_rd/config.py b/modules/lightmapper_rd/config.py new file mode 100644 index 0000000000..d22f9454ed --- /dev/null +++ b/modules/lightmapper_rd/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return True + + +def configure(env): + pass diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp new file mode 100644 index 0000000000..6983c222c0 --- /dev/null +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -0,0 +1,1754 @@ +#include "lightmapper_rd.h" +#include "core/math/geometry.h" +#include "core/project_settings.h" +#include "lm_blendseams.glsl.gen.h" +#include "lm_compute.glsl.gen.h" +#include "lm_raster.glsl.gen.h" +#include "servers/rendering/rendering_device_binds.h" + +//uncomment this if you want to see textures from all the process saved +//#define DEBUG_TEXTURES + +void LightmapperRD::add_mesh(const MeshData &p_mesh) { + ERR_FAIL_COND(p_mesh.albedo_on_uv2.is_null() || p_mesh.albedo_on_uv2->empty()); + ERR_FAIL_COND(p_mesh.emission_on_uv2.is_null() || p_mesh.emission_on_uv2->empty()); + ERR_FAIL_COND(p_mesh.albedo_on_uv2->get_width() != p_mesh.emission_on_uv2->get_width()); + ERR_FAIL_COND(p_mesh.albedo_on_uv2->get_height() != p_mesh.emission_on_uv2->get_height()); + ERR_FAIL_COND(p_mesh.points.size() == 0); + MeshInstance mi; + mi.data = p_mesh; + mesh_instances.push_back(mi); +} + +void LightmapperRD::add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance) { + Light l; + l.type = LIGHT_TYPE_DIRECTIONAL; + l.direction[0] = p_direction.x; + l.direction[1] = p_direction.y; + l.direction[2] = p_direction.z; + l.color[0] = p_color.r; + l.color[1] = p_color.g; + l.color[2] = p_color.b; + l.energy = p_energy; + l.static_bake = p_static; + l.size = p_angular_distance; + lights.push_back(l); +} +void LightmapperRD::add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size) { + Light l; + l.type = LIGHT_TYPE_OMNI; + l.position[0] = p_position.x; + l.position[1] = p_position.y; + l.position[2] = p_position.z; + l.range = p_range; + l.attenuation = p_attenuation; + l.color[0] = p_color.r; + l.color[1] = p_color.g; + l.color[2] = p_color.b; + l.energy = p_energy; + l.static_bake = p_static; + l.size = p_size; + lights.push_back(l); +} +void LightmapperRD::add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) { + + Light l; + l.type = LIGHT_TYPE_SPOT; + l.position[0] = p_position.x; + l.position[1] = p_position.y; + l.position[2] = p_position.z; + l.direction[0] = p_direction.x; + l.direction[1] = p_direction.y; + l.direction[2] = p_direction.z; + l.range = p_range; + l.attenuation = p_attenuation; + l.spot_angle = Math::deg2rad(p_spot_angle); + l.spot_attenuation = p_spot_attenuation; + l.color[0] = p_color.r; + l.color[1] = p_color.g; + l.color[2] = p_color.b; + l.energy = p_energy; + l.static_bake = p_static; + l.size = p_size; + lights.push_back(l); +} + +void LightmapperRD::add_probe(const Vector3 &p_position) { + Probe probe; + probe.position[0] = p_position.x; + probe.position[1] = p_position.y; + probe.position[2] = p_position.z; + probe.position[3] = 0; + probe_positions.push_back(probe); +} + +void LightmapperRD::_plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[3], uint32_t p_triangle_index, LocalVector &triangles, uint32_t p_grid_size) { + + int half_size = p_size / 2; + + for (int i = 0; i < 8; i++) { + + AABB aabb = p_bounds; + aabb.size *= 0.5; + Vector3i n = p_ofs; + + if (i & 1) { + aabb.position.x += aabb.size.x; + n.x += half_size; + } + if (i & 2) { + aabb.position.y += aabb.size.y; + n.y += half_size; + } + if (i & 4) { + aabb.position.z += aabb.size.z; + n.z += half_size; + } + + { + Vector3 qsize = aabb.size * 0.5; //quarter size, for fast aabb test + + if (!Geometry::triangle_box_overlap(aabb.position + qsize, qsize, p_points)) { + //does not fit in child, go on + continue; + } + } + + if (half_size == 1) { + //got to the end + TriangleSort ts; + ts.cell_index = n.x + (n.y * p_grid_size) + (n.z * p_grid_size * p_grid_size); + ts.triangle_index = p_triangle_index; + triangles.push_back(ts); + } else { + _plot_triangle_into_triangle_index_list(half_size, n, aabb, p_points, p_triangle_index, triangles, p_grid_size); + } + } +} + +Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_size, Vector> &albedo_images, Vector> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata) { + + Vector sizes; + + for (int m_i = 0; m_i < mesh_instances.size(); m_i++) { + + MeshInstance &mi = mesh_instances.write[m_i]; + Size2i s = Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height()); + sizes.push_back(s); + atlas_size.width = MAX(atlas_size.width, s.width); + atlas_size.height = MAX(atlas_size.height, s.height); + } + + int max = nearest_power_of_2_templated(atlas_size.width); + max = MAX(max, nearest_power_of_2_templated(atlas_size.height)); + + if (max > p_max_texture_size) { + return BAKE_ERROR_LIGHTMAP_TOO_SMALL; + } + + if (p_step_function) { + p_step_function(0.1, TTR("Determining optimal atlas size"), p_bake_userdata, true); + } + + atlas_size = Size2i(max, max); + + Size2i best_atlas_size; + int best_atlas_slices = 0; + int best_atlas_memory = 0x7FFFFFFF; + Vector best_atlas_offsets; + + //determine best texture array atlas size by bruteforce fitting + while (atlas_size.x <= p_max_texture_size && atlas_size.y <= p_max_texture_size) { + + Vector source_sizes = sizes; + Vector source_indices; + source_indices.resize(source_sizes.size()); + for (int i = 0; i < source_indices.size(); i++) { + source_indices.write[i] = i; + } + Vector atlas_offsets; + atlas_offsets.resize(source_sizes.size()); + + int slices = 0; + + while (source_sizes.size() > 0) { + + Vector offsets = Geometry::partial_pack_rects(source_sizes, atlas_size); + Vector new_indices; + Vector new_sources; + for (int i = 0; i < offsets.size(); i++) { + Vector3i ofs = offsets[i]; + int sidx = source_indices[i]; + if (ofs.z > 0) { + //valid + ofs.z = slices; + atlas_offsets.write[sidx] = ofs; + } else { + new_indices.push_back(sidx); + new_sources.push_back(source_sizes[i]); + } + } + + source_sizes = new_sources; + source_indices = new_indices; + slices++; + } + + int mem_used = atlas_size.x * atlas_size.y * slices; + if (mem_used < best_atlas_memory) { + best_atlas_size = atlas_size; + best_atlas_offsets = atlas_offsets; + best_atlas_slices = slices; + best_atlas_memory = mem_used; + } + + if (atlas_size.width == atlas_size.height) { + atlas_size.width *= 2; + } else { + atlas_size.height *= 2; + } + } + atlas_size = best_atlas_size; + atlas_slices = best_atlas_slices; + + // apply the offsets and slice to all images, and also blit albedo and emission + albedo_images.resize(atlas_slices); + emission_images.resize(atlas_slices); + + if (p_step_function) { + p_step_function(0.2, TTR("Blitting albedo and emission"), p_bake_userdata, true); + } + + for (int i = 0; i < atlas_slices; i++) { + Ref albedo; + albedo.instance(); + albedo->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBA8); + albedo->set_as_black(); + albedo_images.write[i] = albedo; + + Ref emission; + emission.instance(); + emission->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH); + emission->set_as_black(); + emission_images.write[i] = emission; + } + + //assign uv positions + + for (int m_i = 0; m_i < mesh_instances.size(); m_i++) { + + MeshInstance &mi = mesh_instances.write[m_i]; + mi.offset.x = best_atlas_offsets[m_i].x; + mi.offset.y = best_atlas_offsets[m_i].y; + mi.slice = best_atlas_offsets[m_i].z; + albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2(Vector2(), Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height())), mi.offset); + emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2(), Size2i(mi.data.emission_on_uv2->get_width(), mi.data.emission_on_uv2->get_height())), mi.offset); + } + + return BAKE_OK; +} + +void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector &probe_positions, GenerateProbes p_generate_probes, Vector &slice_triangle_count, Vector &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &grid_texture_sdf, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata) { + + HashMap vertex_map; + + //fill triangles array and vertex array + LocalVector triangles; + LocalVector vertex_array; + LocalVector box_array; + LocalVector seams; + + slice_triangle_count.resize(atlas_slices); + slice_seam_count.resize(atlas_slices); + + for (int i = 0; i < atlas_slices; i++) { + slice_triangle_count.write[i] = 0; + slice_seam_count.write[i] = 0; + } + + bounds = AABB(); + + for (int m_i = 0; m_i < mesh_instances.size(); m_i++) { + + if (p_step_function) { + float p = float(m_i + 1) / mesh_instances.size() * 0.1; + p_step_function(0.3 + p, vformat(TTR("Plotting mesh into acceleration structure %d/%d"), m_i + 1, mesh_instances.size()), p_bake_userdata, false); + } + + HashMap edges; + + MeshInstance &mi = mesh_instances.write[m_i]; + + Vector2 uv_scale = Vector2(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height()) / Vector2(atlas_size); + Vector2 uv_offset = Vector2(mi.offset) / Vector2(atlas_size); + if (m_i == 0) { + bounds.position = mi.data.points[0]; + } + + for (int i = 0; i < mi.data.points.size(); i += 3) { + + Vector3 vtxs[3] = { mi.data.points[i + 0], mi.data.points[i + 1], mi.data.points[i + 2] }; + Vector2 uvs[3] = { mi.data.uv2[i + 0] * uv_scale + uv_offset, mi.data.uv2[i + 1] * uv_scale + uv_offset, mi.data.uv2[i + 2] * uv_scale + uv_offset }; + Vector3 normal[3] = { mi.data.normal[i + 0], mi.data.normal[i + 1], mi.data.normal[i + 2] }; + + AABB taabb; + Triangle t; + t.slice = mi.slice; + for (int k = 0; k < 3; k++) { + + bounds.expand_to(vtxs[k]); + + Vertex v; + v.position[0] = vtxs[k].x; + v.position[1] = vtxs[k].y; + v.position[2] = vtxs[k].z; + v.uv[0] = uvs[k].x; + v.uv[1] = uvs[k].y; + v.normal_xy[0] = normal[k].x; + v.normal_xy[1] = normal[k].y; + v.normal_z = normal[k].z; + + uint32_t *indexptr = vertex_map.getptr(v); + + if (indexptr) { + t.indices[k] = *indexptr; + } else { + uint32_t new_index = vertex_map.size(); + t.indices[k] = new_index; + vertex_map[v] = new_index; + vertex_array.push_back(v); + } + + if (k == 0) { + taabb.position = vtxs[k]; + } else { + taabb.expand_to(vtxs[k]); + } + } + + //compute seams that will need to be blended later + for (int k = 0; k < 3; k++) { + int n = (k + 1) % 3; + + Edge edge(vtxs[k], vtxs[n], normal[k], normal[n]); + Vector2i edge_indices(t.indices[k], t.indices[n]); + EdgeUV2 uv2(uvs[k], uvs[n], edge_indices); + + if (edge.b == edge.a) { + continue; //degenerate, somehow + } + if (edge.b < edge.a) { + SWAP(edge.a, edge.b); + SWAP(edge.na, edge.nb); + SWAP(uv2.a, uv2.b); + SWAP(edge_indices.x, edge_indices.y); + } + + EdgeUV2 *euv2 = edges.getptr(edge); + if (!euv2) { + edges[edge] = uv2; + } else { + if (*euv2 == uv2) { + continue; // seam shared UV space, no need to blend + } + if (euv2->seam_found) { + continue; //bad geometry + } + + Seam seam; + seam.a = edge_indices; + seam.b = euv2->indices; + seam.slice = mi.slice; + seams.push_back(seam); + slice_seam_count.write[mi.slice]++; + euv2->seam_found = true; + } + } + + Box box; + box.min_bounds[0] = taabb.position.x; + box.min_bounds[1] = taabb.position.y; + box.min_bounds[2] = taabb.position.z; + box.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001); + box.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001); + box.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001); + box.pad0 = box.pad1 = 0; //make valgrind not complain + box_array.push_back(box); + + triangles.push_back(t); + slice_triangle_count.write[t.slice]++; + } + } + + //also consider probe positions for bounds + for (int i = 0; i < probe_positions.size(); i++) { + Vector3 pp(probe_positions[i].position[0], probe_positions[i].position[1], probe_positions[i].position[2]); + bounds.expand_to(pp); + } + bounds.grow_by(0.1); //grow a bit to avoid numerical error + + triangles.sort(); //sort by slice + seams.sort(); + + if (p_step_function) { + p_step_function(0.4, TTR("Optimizing acceleration structure"), p_bake_userdata, true); + } + + //fill list of triangles in grid + LocalVector triangle_sort; + for (uint32_t i = 0; i < triangles.size(); i++) { + + const Triangle &t = triangles[i]; + Vector3 face[3] = { + Vector3(vertex_array[t.indices[0]].position[0], vertex_array[t.indices[0]].position[1], vertex_array[t.indices[0]].position[2]), + Vector3(vertex_array[t.indices[1]].position[0], vertex_array[t.indices[1]].position[1], vertex_array[t.indices[1]].position[2]), + Vector3(vertex_array[t.indices[2]].position[0], vertex_array[t.indices[2]].position[1], vertex_array[t.indices[2]].position[2]) + }; + _plot_triangle_into_triangle_index_list(grid_size, Vector3i(), bounds, face, i, triangle_sort, grid_size); + } + //sort it + triangle_sort.sort(); + + Vector triangle_indices; + triangle_indices.resize(triangle_sort.size()); + Vector grid_indices; + grid_indices.resize(grid_size * grid_size * grid_size * 2); + zeromem(grid_indices.ptrw(), grid_indices.size() * sizeof(uint32_t)); + Vector solid; + solid.resize(grid_size * grid_size * grid_size); + zeromem(solid.ptrw(), solid.size() * sizeof(bool)); + + { + uint32_t *tiw = triangle_indices.ptrw(); + uint32_t last_cell = 0xFFFFFFFF; + uint32_t *giw = grid_indices.ptrw(); + bool *solidw = solid.ptrw(); + for (uint32_t i = 0; i < triangle_sort.size(); i++) { + uint32_t cell = triangle_sort[i].cell_index; + if (cell != last_cell) { + //cell changed, update pointer to indices + giw[cell * 2 + 1] = i; + last_cell = cell; + solidw[cell] = true; + } + tiw[i] = triangle_sort[i].triangle_index; + giw[cell * 2]++; //update counter + last_cell = cell; + } + } +#if 0 + for (int i = 0; i < grid_size; i++) { + for (int j = 0; j < grid_size; j++) { + for (int k = 0; k < grid_size; k++) { + uint32_t index = i * (grid_size * grid_size) + j * grid_size + k; + grid_indices.write[index * 2] = float(i) / grid_size * 255; + grid_indices.write[index * 2 + 1] = float(j) / grid_size * 255; + } + } + } +#endif + +#if 0 + for (int i = 0; i < grid_size; i++) { + Vector grid_usage; + grid_usage.resize(grid_size * grid_size); + for (int j = 0; j < grid_usage.size(); j++) { + uint32_t ofs = i * grid_size * grid_size + j; + uint32_t count = grid_indices[ofs * 2]; + grid_usage.write[j] = count > 0 ? 255 : 0; + } + + Ref img; + img.instance(); + img->create(grid_size, grid_size, false, Image::FORMAT_L8, grid_usage); + img->save_png("res://grid_layer_" + itos(1000 + i).substr(1, 3) + ".png"); + } +#endif + if (p_step_function) { + p_step_function(0.45, TTR("Generating Signed Distance Field"), p_bake_userdata, true); + } + + //generate SDF for raytracing + Vector euclidean_pos = Geometry::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), false); + Vector euclidean_neg = Geometry::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), true); + Vector sdf8 = Geometry::generate_sdf8(euclidean_pos, euclidean_neg); + + /*****************************/ + /*** CREATE GPU STRUCTURES ***/ + /*****************************/ + + lights.sort(); + + Vector seam_buffer_vec; + seam_buffer_vec.resize(seams.size() * 2); + for (uint32_t i = 0; i < seams.size(); i++) { + seam_buffer_vec.write[i * 2 + 0] = seams[i].a; + seam_buffer_vec.write[i * 2 + 1] = seams[i].b; + } + + { //buffers + Vector vb = vertex_array.to_byte_array(); + vertex_buffer = rd->storage_buffer_create(vb.size(), vb); + + Vector tb = triangles.to_byte_array(); + triangle_buffer = rd->storage_buffer_create(tb.size(), tb); + + Vector bb = box_array.to_byte_array(); + box_buffer = rd->storage_buffer_create(bb.size(), bb); + + Vector tib = triangle_indices.to_byte_array(); + triangle_cell_indices_buffer = rd->storage_buffer_create(tib.size(), tib); + + Vector lb = lights.to_byte_array(); + if (lb.size() == 0) { + lb.resize(sizeof(Light)); //even if no lights, the buffer must exist + } + lights_buffer = rd->storage_buffer_create(lb.size(), lb); + + Vector sb = seam_buffer_vec.to_byte_array(); + if (sb.size() == 0) { + sb.resize(sizeof(Vector2i) * 2); //even if no seams, the buffer must exist + } + seams_buffer = rd->storage_buffer_create(sb.size(), sb); + + Vector pb = probe_positions.to_byte_array(); + if (pb.size() == 0) { + pb.resize(sizeof(Probe)); + } + probe_positions_buffer = rd->storage_buffer_create(pb.size(), pb); + } + + { //grid + + RD::TextureFormat tf; + tf.width = grid_size; + tf.height = grid_size; + tf.depth = grid_size; + tf.type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + + Vector> texdata; + texdata.resize(1); + //grid and indices + tf.format = RD::DATA_FORMAT_R32G32_UINT; + texdata.write[0] = grid_indices.to_byte_array(); + grid_texture = rd->texture_create(tf, RD::TextureView(), texdata); + //sdf + tf.format = RD::DATA_FORMAT_R8_SNORM; + texdata.write[0] = sdf8.to_byte_array(); + grid_texture_sdf = rd->texture_create(tf, RD::TextureView(), texdata); + } +} + +void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform) { + + Vector framebuffers; + + for (int i = 0; i < atlas_slices; i++) { + RID slice_pos_tex = rd->texture_create_shared_from_slice(RD::TextureView(), position_tex, i, 0); + RID slice_unoc_tex = rd->texture_create_shared_from_slice(RD::TextureView(), unocclude_tex, i, 0); + RID slice_norm_tex = rd->texture_create_shared_from_slice(RD::TextureView(), normal_tex, i, 0); + Vector fb; + fb.push_back(slice_pos_tex); + fb.push_back(slice_norm_tex); + fb.push_back(slice_unoc_tex); + fb.push_back(raster_depth_buffer); + framebuffers.push_back(rd->framebuffer_create(fb)); + } + + RD::PipelineDepthStencilState ds; + ds.enable_depth_test = true; + ds.enable_depth_write = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS; //so it does render same pixel twice + + RID raster_pipeline = rd->render_pipeline_create(rasterize_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(3), 0); + RID raster_pipeline_wire; + { + + RD::PipelineRasterizationState rw; + rw.wireframe = true; + raster_pipeline_wire = rd->render_pipeline_create(rasterize_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, rw, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(3), 0); + } + + uint32_t triangle_offset = 0; + Vector clear_colors; + clear_colors.push_back(Color(0, 0, 0, 0)); + clear_colors.push_back(Color(0, 0, 0, 0)); + clear_colors.push_back(Color(0, 0, 0, 0)); + + for (int i = 0; i < atlas_slices; i++) { + + RasterPushConstant raster_push_constant; + raster_push_constant.atlas_size[0] = atlas_size.x; + raster_push_constant.atlas_size[1] = atlas_size.y; + raster_push_constant.base_triangle = triangle_offset; + raster_push_constant.to_cell_offset[0] = bounds.position.x; + raster_push_constant.to_cell_offset[1] = bounds.position.y; + raster_push_constant.to_cell_offset[2] = bounds.position.z; + raster_push_constant.bias = p_bias; + raster_push_constant.to_cell_size[0] = (1.0 / bounds.size.x) * float(grid_size); + raster_push_constant.to_cell_size[1] = (1.0 / bounds.size.y) * float(grid_size); + raster_push_constant.to_cell_size[2] = (1.0 / bounds.size.z) * float(grid_size); + raster_push_constant.grid_size[0] = grid_size; + raster_push_constant.grid_size[1] = grid_size; + raster_push_constant.grid_size[2] = grid_size; + raster_push_constant.uv_offset[0] = 0; + raster_push_constant.uv_offset[1] = 0; + + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + //draw opaque + rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline); + rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); + rd->draw_list_set_push_constant(draw_list, &raster_push_constant, sizeof(RasterPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3); + //draw wire + rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline_wire); + rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); + rd->draw_list_set_push_constant(draw_list, &raster_push_constant, sizeof(RasterPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3); + + rd->draw_list_end(); + + triangle_offset += slice_triangle_count[i]; + } +} + +LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata) { + + if (p_step_function) { + p_step_function(0.0, TTR("Begin Bake"), p_bake_userdata, true); + } + bake_textures.clear(); + int grid_size = 128; + + /* STEP 1: Fetch material textures and compute the bounds */ + + AABB bounds; + Size2i atlas_size; + int atlas_slices; + Vector> albedo_images; + Vector> emission_images; + + BakeError bake_error = _blit_meshes_into_atlas(p_max_texture_size, albedo_images, emission_images, bounds, atlas_size, atlas_slices, p_step_function, p_bake_userdata); + if (bake_error != BAKE_OK) { + return bake_error; + } + +#ifdef DEBUG_TEXTURES + for (int i = 0; i < atlas_slices; i++) { + albedo_images[i]->save_png("res://0_albedo_" + itos(i) + ".png"); + emission_images[i]->save_png("res://0_emission_" + itos(i) + ".png"); + } +#endif + + RenderingDevice *rd = RenderingDevice::get_singleton()->create_local_device(); + + RID albedo_array_tex; + RID emission_array_tex; + RID normal_tex; + RID position_tex; + RID unocclude_tex; + RID light_source_tex; + RID light_dest_tex; + RID light_accum_tex; + RID light_accum_tex2; + RID light_primary_dynamic_tex; + RID light_environment_tex; + +#define FREE_TEXTURES \ + rd->free(albedo_array_tex); \ + rd->free(emission_array_tex); \ + rd->free(normal_tex); \ + rd->free(position_tex); \ + rd->free(unocclude_tex); \ + rd->free(light_source_tex); \ + rd->free(light_accum_tex2); \ + rd->free(light_accum_tex); \ + rd->free(light_primary_dynamic_tex); \ + rd->free(light_environment_tex); + + { // create all textures + + Vector> albedo_data; + Vector> emission_data; + for (int i = 0; i < atlas_slices; i++) { + albedo_data.push_back(albedo_images[i]->get_data()); + emission_data.push_back(emission_images[i]->get_data()); + } + + RD::TextureFormat tf; + tf.width = atlas_size.width; + tf.height = atlas_size.height; + tf.array_layers = atlas_slices; + tf.type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + + albedo_array_tex = rd->texture_create(tf, RD::TextureView(), albedo_data); + + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + + emission_array_tex = rd->texture_create(tf, RD::TextureView(), emission_data); + + //this will be rastered to + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + normal_tex = rd->texture_create(tf, RD::TextureView()); + tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + position_tex = rd->texture_create(tf, RD::TextureView()); + unocclude_tex = rd->texture_create(tf, RD::TextureView()); + + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + + light_source_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_source_tex, Color(0, 0, 0, 0), 0, 1, 0, atlas_slices); + light_primary_dynamic_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_primary_dynamic_tex, Color(0, 0, 0, 0), 0, 1, 0, atlas_slices); + + if (p_bake_sh) { + tf.array_layers *= 4; + } + light_accum_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_accum_tex, Color(0, 0, 0, 0), 0, 1, 0, tf.array_layers); + light_dest_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_dest_tex, Color(0, 0, 0, 0), 0, 1, 0, tf.array_layers); + light_accum_tex2 = light_dest_tex; + + //env + { + Ref panorama_tex; + if (p_environment_panorama.is_valid()) { + panorama_tex = p_environment_panorama; + panorama_tex->convert(Image::FORMAT_RGBAF); + } else { + panorama_tex.instance(); + panorama_tex->create(8, 8, false, Image::FORMAT_RGBAF); + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + panorama_tex->set_pixel(i, j, Color(0, 0, 0, 1)); + } + } + } + + RD::TextureFormat tfp; + tfp.width = panorama_tex->get_width(); + tfp.height = panorama_tex->get_height(); + tfp.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tfp.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + + Vector> tdata; + tdata.push_back(panorama_tex->get_data()); + light_environment_tex = rd->texture_create(tfp, RD::TextureView(), tdata); + +#ifdef DEBUG_TEXTURES + panorama_tex->convert(Image::FORMAT_RGB8); + panorama_tex->save_png("res://0_panorama.png"); +#endif + } + } + + /* STEP 2: create the acceleration structure for the GPU*/ + + Vector slice_triangle_count; + RID vertex_buffer; + RID triangle_buffer; + RID box_buffer; + RID lights_buffer; + RID triangle_cell_indices_buffer; + RID grid_texture; + RID grid_texture_sdf; + RID seams_buffer; + RID probe_positions_buffer; + + Vector slice_seam_count; + +#define FREE_BUFFERS \ + rd->free(vertex_buffer); \ + rd->free(triangle_buffer); \ + rd->free(box_buffer); \ + rd->free(lights_buffer); \ + rd->free(triangle_cell_indices_buffer); \ + rd->free(grid_texture); \ + rd->free(grid_texture_sdf); \ + rd->free(seams_buffer); \ + rd->free(probe_positions_buffer); + + _create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, box_buffer, lights_buffer, triangle_cell_indices_buffer, probe_positions_buffer, grid_texture, grid_texture_sdf, seams_buffer, p_step_function, p_bake_userdata); + + if (p_step_function) { + p_step_function(0.47, TTR("Preparing shaders"), p_bake_userdata, true); + } + + //shaders + Ref raster_shader; + raster_shader.instance(); + Error err = raster_shader->parse_versions_from_text(lm_raster_shader_glsl); + if (err != OK) { + raster_shader->print_errors("raster_shader"); + + FREE_TEXTURES + FREE_BUFFERS + + memdelete(rd); + } + ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + RID rasterize_shader = rd->shader_create_from_bytecode(raster_shader->get_bytecode()); + + ERR_FAIL_COND_V(rasterize_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //this is a bug check, though, should not happen + + RID sampler; + { + RD::SamplerState s; + s.mag_filter = RD::SAMPLER_FILTER_LINEAR; + s.min_filter = RD::SAMPLER_FILTER_LINEAR; + s.max_lod = 0; + + sampler = rd->sampler_create(s); + } + + Vector base_uniforms; + { + { + + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 1; + u.ids.push_back(vertex_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.ids.push_back(triangle_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 3; + u.ids.push_back(box_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 4; + u.ids.push_back(triangle_cell_indices_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 5; + u.ids.push_back(lights_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 6; + u.ids.push_back(seams_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 7; + u.ids.push_back(probe_positions_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 8; + u.ids.push_back(grid_texture); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 9; + u.ids.push_back(grid_texture_sdf); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 10; + u.ids.push_back(albedo_array_tex); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 11; + u.ids.push_back(emission_array_tex); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 12; + u.ids.push_back(sampler); + base_uniforms.push_back(u); + } + } + + RID raster_base_uniform = rd->uniform_set_create(base_uniforms, rasterize_shader, 0); + RID raster_depth_buffer; + { + RD::TextureFormat tf; + tf.width = atlas_size.width; + tf.height = atlas_size.height; + tf.depth = 1; + tf.type = RD::TEXTURE_TYPE_2D; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + tf.format = RD::DATA_FORMAT_D32_SFLOAT; + + raster_depth_buffer = rd->texture_create(tf, RD::TextureView()); + } + + rd->submit(); + rd->sync(); + + /* STEP 3: Raster the geometry to UV2 coords in the atlas textures GPU*/ + + _raster_geometry(rd, atlas_size, atlas_slices, grid_size, bounds, p_bias, slice_triangle_count, position_tex, unocclude_tex, normal_tex, raster_depth_buffer, rasterize_shader, raster_base_uniform); + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices; i++) { + Vector s = rd->texture_get_data(position_tex, i); + Ref img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAF, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://1_position_" + itos(i) + ".png"); + + s = rd->texture_get_data(normal_tex, i); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://1_normal_" + itos(i) + ".png"); + } +#endif + +#define FREE_RASTER_RESOURCES \ + rd->free(rasterize_shader); \ + rd->free(sampler); \ + rd->free(raster_depth_buffer); + + /* Plot direct light */ + + Ref compute_shader; + compute_shader.instance(); + err = compute_shader->parse_versions_from_text(lm_compute_shader_glsl, p_bake_sh ? "\n#define USE_SH_LIGHTMAPS\n" : ""); + if (err != OK) { + + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + memdelete(rd); + compute_shader->print_errors("compute_shader"); + } + ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + //unoccluder + RID compute_shader_unocclude = rd->shader_create_from_bytecode(compute_shader->get_bytecode("unocclude")); + ERR_FAIL_COND_V(compute_shader_unocclude.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen + RID compute_shader_unocclude_pipeline = rd->compute_pipeline_create(compute_shader_unocclude); + + //direct light + RID compute_shader_primary = rd->shader_create_from_bytecode(compute_shader->get_bytecode("primary")); + ERR_FAIL_COND_V(compute_shader_primary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen + RID compute_shader_primary_pipeline = rd->compute_pipeline_create(compute_shader_primary); + + //indirect light + RID compute_shader_secondary = rd->shader_create_from_bytecode(compute_shader->get_bytecode("secondary")); + ERR_FAIL_COND_V(compute_shader_secondary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen + RID compute_shader_secondary_pipeline = rd->compute_pipeline_create(compute_shader_secondary); + + //dilate + RID compute_shader_dilate = rd->shader_create_from_bytecode(compute_shader->get_bytecode("dilate")); + ERR_FAIL_COND_V(compute_shader_dilate.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen + RID compute_shader_dilate_pipeline = rd->compute_pipeline_create(compute_shader_dilate); + + //dilate + RID compute_shader_light_probes = rd->shader_create_from_bytecode(compute_shader->get_bytecode("light_probes")); + ERR_FAIL_COND_V(compute_shader_light_probes.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen + RID compute_shader_light_probes_pipeline = rd->compute_pipeline_create(compute_shader_light_probes); + + RID compute_base_uniform_set = rd->uniform_set_create(base_uniforms, compute_shader_primary, 0); + +#define FREE_COMPUTE_RESOURCES \ + rd->free(compute_shader_unocclude); \ + rd->free(compute_shader_primary); \ + rd->free(compute_shader_secondary); \ + rd->free(compute_shader_dilate); \ + rd->free(compute_shader_light_probes); + + PushConstant push_constant; + { + //set defaults + push_constant.atlas_size[0] = atlas_size.width; + push_constant.atlas_size[1] = atlas_size.height; + push_constant.world_size[0] = bounds.size.x; + push_constant.world_size[1] = bounds.size.y; + push_constant.world_size[2] = bounds.size.z; + push_constant.to_cell_offset[0] = bounds.position.x; + push_constant.to_cell_offset[1] = bounds.position.y; + push_constant.to_cell_offset[2] = bounds.position.z; + push_constant.bias = p_bias; + push_constant.to_cell_size[0] = (1.0 / bounds.size.x) * float(grid_size); + push_constant.to_cell_size[1] = (1.0 / bounds.size.y) * float(grid_size); + push_constant.to_cell_size[2] = (1.0 / bounds.size.z) * float(grid_size); + push_constant.light_count = lights.size(); + push_constant.grid_size = grid_size; + push_constant.atlas_slice = 0; + push_constant.region_ofs[0] = 0; + push_constant.region_ofs[1] = 0; + push_constant.environment_xform[0] = p_environment_transform.elements[0][0]; + push_constant.environment_xform[1] = p_environment_transform.elements[1][0]; + push_constant.environment_xform[2] = p_environment_transform.elements[2][0]; + push_constant.environment_xform[3] = 0; + push_constant.environment_xform[4] = p_environment_transform.elements[0][1]; + push_constant.environment_xform[5] = p_environment_transform.elements[1][1]; + push_constant.environment_xform[6] = p_environment_transform.elements[2][1]; + push_constant.environment_xform[7] = 0; + push_constant.environment_xform[8] = p_environment_transform.elements[0][2]; + push_constant.environment_xform[9] = p_environment_transform.elements[1][2]; + push_constant.environment_xform[10] = p_environment_transform.elements[2][2]; + push_constant.environment_xform[11] = 0; + } + + Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); + rd->submit(); + rd->sync(); + + if (p_step_function) { + p_step_function(0.49, TTR("Un-occluding geometry"), p_bake_userdata, true); + } + + /* UNOCCLUDE */ + { + + Vector uniforms; + { + { + + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(position_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(unocclude_tex); //will be unused + uniforms.push_back(u); + } + } + + RID unocclude_uniform_set = rd->uniform_set_create(uniforms, compute_shader_unocclude, 1); + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_unocclude_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, unocclude_uniform_set, 1); + + for (int i = 0; i < atlas_slices; i++) { + push_constant.atlas_slice = i; + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + //no barrier, let them run all together + } + rd->compute_list_end(); //done + } + + if (p_step_function) { + p_step_function(0.5, TTR("Plot direct lighting"), p_bake_userdata, true); + } + + /* PRIMARY (direct) LIGHT PASS */ + { + + Vector uniforms; + { + { + + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(light_source_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_dest_tex); //will be unused + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.ids.push_back(position_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + u.ids.push_back(normal_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 4; + u.ids.push_back(light_accum_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(light_primary_dynamic_tex); + uniforms.push_back(u); + } + } + + RID light_uniform_set = rd->uniform_set_create(uniforms, compute_shader_primary, 1); + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_primary_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, light_uniform_set, 1); + + for (int i = 0; i < atlas_slices; i++) { + push_constant.atlas_slice = i; + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + //no barrier, let them run all together + } + rd->compute_list_end(); //done + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices; i++) { + Vector s = rd->texture_get_data(light_source_tex, i); + Ref img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://2_light_primary_" + itos(i) + ".png"); + } +#endif + + /* SECONDARY (indirect) LIGHT PASS(ES) */ + if (p_step_function) { + p_step_function(0.6, TTR("Integrate indirect lighting"), p_bake_userdata, true); + } + + if (p_bounces > 0) { + + Vector uniforms; + { + { + + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(light_dest_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_source_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.ids.push_back(position_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + u.ids.push_back(normal_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 4; + u.ids.push_back(light_accum_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(unocclude_tex); //reuse unocclude tex + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 6; + u.ids.push_back(light_environment_tex); //reuse unocclude tex + uniforms.push_back(u); + } + } + + RID secondary_uniform_set[2]; + secondary_uniform_set[0] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1); + uniforms.write[0].ids.write[0] = light_source_tex; + uniforms.write[1].ids.write[0] = light_dest_tex; + secondary_uniform_set[1] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1); + + switch (p_quality) { + case BAKE_QUALITY_LOW: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/low_quality_ray_count"); + } break; + case BAKE_QUALITY_MEDIUM: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/medium_quality_ray_count"); + } break; + case BAKE_QUALITY_HIGH: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/high_quality_ray_count"); + } break; + case BAKE_QUALITY_ULTRA: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/ultra_quality_ray_count"); + } break; + } + + push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192); + + int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/gpu_lightmapper/performance/region_size"))); + int max_rays = GLOBAL_GET("rendering/gpu_lightmapper/performance/max_rays_per_pass"); + + int x_regions = (atlas_size.width - 1) / max_region_size + 1; + int y_regions = (atlas_size.height - 1) / max_region_size + 1; + int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; + + rd->submit(); + rd->sync(); + + for (int b = 0; b < p_bounces; b++) { + int count = 0; + if (b > 0) { + SWAP(light_source_tex, light_dest_tex); + SWAP(secondary_uniform_set[0], secondary_uniform_set[1]); + } + + for (int s = 0; s < atlas_slices; s++) { + push_constant.atlas_slice = s; + + for (int i = 0; i < x_regions; i++) { + for (int j = 0; j < y_regions; j++) { + + int x = i * max_region_size; + int y = j * max_region_size; + int w = MIN((i + 1) * max_region_size, atlas_size.width) - x; + int h = MIN((j + 1) * max_region_size, atlas_size.height) - y; + + push_constant.region_ofs[0] = x; + push_constant.region_ofs[1] = y; + + group_size = Vector3i((w - 1) / 8 + 1, (h - 1) / 8 + 1, 1); + + for (int k = 0; k < ray_iterations; k++) { + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_secondary_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, secondary_uniform_set[0], 1); + + push_constant.ray_from = k * max_rays; + push_constant.ray_to = MIN((k + 1) * max_rays, int32_t(push_constant.ray_count)); + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + + rd->compute_list_end(); //done + rd->submit(); + rd->sync(); + + count++; + if (p_step_function) { + int total = (atlas_slices * x_regions * y_regions * ray_iterations); + int percent = count * 100 / total; + float p = float(count) / total * 0.1; + p_step_function(0.6 + p, vformat(TTR("Bounce %d/%d: Integrate indirect lighting %d%%"), b + 1, p_bounces, percent), p_bake_userdata, false); + } + } + } + } + } + } + } + + /* LIGHPROBES */ + + RID light_probe_buffer; + + if (probe_positions.size()) { + + light_probe_buffer = rd->storage_buffer_create(sizeof(float) * 4 * 9 * probe_positions.size()); + + if (p_step_function) { + p_step_function(0.7, TTR("Baking lightprobes"), p_bake_userdata, true); + } + + Vector uniforms; + { + + { + + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(light_probe_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_dest_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.ids.push_back(light_primary_dynamic_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + u.ids.push_back(light_environment_tex); + uniforms.push_back(u); + } + } + RID light_probe_uniform_set = rd->uniform_set_create(uniforms, compute_shader_light_probes, 1); + + switch (p_quality) { + case BAKE_QUALITY_LOW: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/low_quality_probe_ray_count"); + } break; + case BAKE_QUALITY_MEDIUM: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/medium_quality_probe_ray_count"); + } break; + case BAKE_QUALITY_HIGH: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/high_quality_probe_ray_count"); + } break; + case BAKE_QUALITY_ULTRA: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/ultra_quality_probe_ray_count"); + } break; + } + + push_constant.atlas_size[0] = probe_positions.size(); + push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192); + + int max_rays = GLOBAL_GET("rendering/gpu_lightmapper/performance/max_rays_per_probe_pass"); + int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; + + for (int i = 0; i < ray_iterations; i++) { + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_light_probes_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, light_probe_uniform_set, 1); + + push_constant.ray_from = i * max_rays; + push_constant.ray_to = MIN((i + 1) * max_rays, int32_t(push_constant.ray_count)); + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, (probe_positions.size() - 1) / 64 + 1, 1, 1); + + rd->compute_list_end(); //done + rd->submit(); + rd->sync(); + + if (p_step_function) { + int percent = i * 100 / ray_iterations; + float p = float(i) / ray_iterations * 0.1; + p_step_function(0.7 + p, vformat(TTR("Integrating light probes %d%%"), percent), p_bake_userdata, false); + } + } + + push_constant.atlas_size[0] = atlas_size.x; //restore + } + +#if 0 + for (int i = 0; i < probe_positions.size(); i++) { + Ref img; + img.instance(); + img->create(6, 4, false, Image::FORMAT_RGB8); + for (int j = 0; j < 6; j++) { + Vector s = rd->texture_get_data(lightprobe_tex, i * 6 + j); + Ref img2; + img2.instance(); + img2->create(2, 2, false, Image::FORMAT_RGBAF, s); + img2->convert(Image::FORMAT_RGB8); + img->blit_rect(img2, Rect2(0, 0, 2, 2), Point2((j % 3) * 2, (j / 3) * 2)); + } + img->save_png("res://3_light_probe_" + itos(i) + ".png"); + } +#endif + + /* DENOISE */ + + if (p_use_denoiser) { + if (p_step_function) { + p_step_function(0.8, TTR("Denoising"), p_bake_userdata, true); + } + + Ref denoiser = LightmapDenoiser::create(); + if (denoiser.is_valid()) { + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector s = rd->texture_get_data(light_accum_tex, i); + Ref img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + + Ref denoised = denoiser->denoise_image(img); + if (denoised != img) { + denoised->convert(Image::FORMAT_RGBAH); + Vector ds = denoised->get_data(); + denoised.unref(); //avoid copy on write + { //restore alpha + uint32_t count = s.size() / 2; //uint16s + const uint16_t *src = (const uint16_t *)s.ptr(); + uint16_t *dst = (uint16_t *)ds.ptrw(); + for (uint32_t j = 0; j < count; j += 4) { + dst[j + 3] = src[j + 3]; + } + } + rd->texture_update(light_accum_tex, i, ds, true); + } + } + } + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector s = rd->texture_get_data(light_accum_tex, i); + Ref img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://4_light_secondary_" + itos(i) + ".png"); + } +#endif + + /* DILATE LIGHTMAP */ + { + + SWAP(light_accum_tex, light_accum_tex2); + + Vector uniforms; + { + { + + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(light_accum_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_accum_tex2); + uniforms.push_back(u); + } + } + + RID dilate_uniform_set = rd->uniform_set_create(uniforms, compute_shader_dilate, 1); + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_dilate_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1); + push_constant.region_ofs[0] = 0; + push_constant.region_ofs[1] = 0; + group_size = Vector3i((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); //restore group size + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + push_constant.atlas_slice = i; + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + //no barrier, let them run all together + } + rd->compute_list_end(); + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector s = rd->texture_get_data(light_accum_tex, i); + Ref img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://5_dilated_" + itos(i) + ".png"); + } +#endif + + /* BLEND SEAMS */ + //shaders + Ref blendseams_shader; + blendseams_shader.instance(); + err = blendseams_shader->parse_versions_from_text(lm_blendseams_shader_glsl); + if (err != OK) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + blendseams_shader->print_errors("blendseams_shader"); + } + ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + RID blendseams_line_raster_shader = rd->shader_create_from_bytecode(blendseams_shader->get_bytecode("lines")); + + ERR_FAIL_COND_V(blendseams_line_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + RID blendseams_triangle_raster_shader = rd->shader_create_from_bytecode(blendseams_shader->get_bytecode("triangles")); + + ERR_FAIL_COND_V(blendseams_triangle_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + +#define FREE_BLENDSEAMS_RESOURCES \ + rd->free(blendseams_line_raster_shader); \ + rd->free(blendseams_triangle_raster_shader); + + { + + //pre copy + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + rd->texture_copy(light_accum_tex, light_accum_tex2, Vector3(), Vector3(), Vector3(atlas_size.width, atlas_size.height, 1), 0, 0, i, i, true); + } + + Vector framebuffers; + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + RID slice_tex = rd->texture_create_shared_from_slice(RD::TextureView(), light_accum_tex, i, 0); + Vector fb; + fb.push_back(slice_tex); + fb.push_back(raster_depth_buffer); + framebuffers.push_back(rd->framebuffer_create(fb)); + } + + Vector uniforms; + { + { + + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(light_accum_tex2); + uniforms.push_back(u); + } + } + + RID blendseams_raster_uniform = rd->uniform_set_create(uniforms, blendseams_line_raster_shader, 1); + + bool debug = false; + RD::PipelineColorBlendState bs = RD::PipelineColorBlendState::create_blend(1); + bs.attachments.write[0].src_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + bs.attachments.write[0].dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + + RD::PipelineDepthStencilState ds; + ds.enable_depth_test = true; + ds.enable_depth_write = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS; //so it does not render same pixel twice, this avoids wrong blending + + RID blendseams_line_raster_pipeline = rd->render_pipeline_create(blendseams_line_raster_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_LINES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, bs, 0); + RID blendseams_triangle_raster_pipeline = rd->render_pipeline_create(blendseams_triangle_raster_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, bs, 0); + + uint32_t seam_offset = 0; + uint32_t triangle_offset = 0; + + Vector clear_colors; + clear_colors.push_back(Color(0, 0, 0, 1)); + for (int i = 0; i < atlas_slices; i++) { + + int subslices = (p_bake_sh ? 4 : 1); + for (int k = 0; k < subslices; k++) { + + RasterSeamsPushConstant seams_push_constant; + seams_push_constant.slice = uint32_t(i * subslices + k); + seams_push_constant.debug = debug; + + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + + rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); + rd->draw_list_bind_uniform_set(draw_list, blendseams_raster_uniform, 1); + + const int uv_offset_count = 9; + static const Vector3 uv_offsets[uv_offset_count] = { + Vector3(0, 0, 0.5), //using zbuffer, so go inwards-outwards + Vector3(0, 1, 0.2), + Vector3(0, -1, 0.2), + Vector3(1, 0, 0.2), + Vector3(-1, 0, 0.2), + Vector3(-1, -1, 0.1), + Vector3(1, -1, 0.1), + Vector3(1, 1, 0.1), + Vector3(-1, 1, 0.1), + }; + + /* step 1 use lines to blend the edges */ + { + seams_push_constant.base_index = seam_offset; + rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline); + seams_push_constant.uv_offset[0] = uv_offsets[0].x / float(atlas_size.width); + seams_push_constant.uv_offset[1] = uv_offsets[0].y / float(atlas_size.height); + seams_push_constant.blend = uv_offsets[0].z; + + rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_seam_count[i] * 4); + } + + /* step 2 use triangles to mask the interior */ + + { + seams_push_constant.base_index = triangle_offset; + rd->draw_list_bind_render_pipeline(draw_list, blendseams_triangle_raster_pipeline); + seams_push_constant.blend = 0; //do not draw them, just fill the z-buffer so its used as a mask + + rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3); + } + /* step 3 blend around the triangle */ + + rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline); + + for (int j = 1; j < uv_offset_count; j++) { + + seams_push_constant.base_index = seam_offset; + seams_push_constant.uv_offset[0] = uv_offsets[j].x / float(atlas_size.width); + seams_push_constant.uv_offset[1] = uv_offsets[j].y / float(atlas_size.height); + seams_push_constant.blend = uv_offsets[0].z; + + rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_seam_count[i] * 4); + } + rd->draw_list_end(); + } + seam_offset += slice_seam_count[i]; + triangle_offset += slice_triangle_count[i]; + } + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector s = rd->texture_get_data(light_accum_tex, i); + Ref img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://5_blendseams" + itos(i) + ".png"); + } +#endif + if (p_step_function) { + p_step_function(0.9, TTR("Retrieving textures"), p_bake_userdata, true); + } + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector s = rd->texture_get_data(light_accum_tex, i); + Ref img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBH); //remove alpha + bake_textures.push_back(img); + } + + if (probe_positions.size() > 0) { + probe_values.resize(probe_positions.size() * 9); + Vector probe_data = rd->buffer_get_data(light_probe_buffer); + copymem(probe_values.ptrw(), probe_data.ptr(), probe_data.size()); + rd->free(light_probe_buffer); + +#ifdef DEBUG_TEXTURES + { + Ref img2; + img2.instance(); + img2->create(probe_values.size(), 1, false, Image::FORMAT_RGBAF, probe_data); + img2->save_png("res://6_lightprobes.png"); + } +#endif + } + + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + FREE_BLENDSEAMS_RESOURCES + + memdelete(rd); + + return BAKE_OK; +} + +int LightmapperRD::get_bake_texture_count() const { + return bake_textures.size(); +} +Ref LightmapperRD::get_bake_texture(int p_index) const { + ERR_FAIL_INDEX_V(p_index, bake_textures.size(), Ref()); + return bake_textures[p_index]; +} +int LightmapperRD::get_bake_mesh_count() const { + return mesh_instances.size(); +} +Variant LightmapperRD::get_bake_mesh_userdata(int p_index) const { + ERR_FAIL_INDEX_V(p_index, mesh_instances.size(), Variant()); + return mesh_instances[p_index].data.userdata; +} +Rect2 LightmapperRD::get_bake_mesh_uv_scale(int p_index) const { + + ERR_FAIL_COND_V(bake_textures.size() == 0, Rect2()); + Rect2 uv_ofs; + Vector2 atlas_size = Vector2(bake_textures[0]->get_width(), bake_textures[0]->get_height()); + uv_ofs.position = Vector2(mesh_instances[p_index].offset) / atlas_size; + uv_ofs.size = Vector2(mesh_instances[p_index].data.albedo_on_uv2->get_width(), mesh_instances[p_index].data.albedo_on_uv2->get_height()) / atlas_size; + return uv_ofs; +} +int LightmapperRD::get_bake_mesh_texture_slice(int p_index) const { + ERR_FAIL_INDEX_V(p_index, mesh_instances.size(), Variant()); + return mesh_instances[p_index].slice; +} + +int LightmapperRD::get_bake_probe_count() const { + return probe_positions.size(); +} + +Vector3 LightmapperRD::get_bake_probe_point(int p_probe) const { + ERR_FAIL_INDEX_V(p_probe, probe_positions.size(), Variant()); + return Vector3(probe_positions[p_probe].position[0], probe_positions[p_probe].position[1], probe_positions[p_probe].position[2]); +} + +Vector LightmapperRD::get_bake_probe_sh(int p_probe) const { + ERR_FAIL_INDEX_V(p_probe, probe_positions.size(), Vector()); + Vector ret; + ret.resize(9); + copymem(ret.ptrw(), &probe_values[p_probe * 9], sizeof(Color) * 9); + return ret; +} + +LightmapperRD::LightmapperRD() { +} diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h new file mode 100644 index 0000000000..cb98efbeaa --- /dev/null +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -0,0 +1,229 @@ +#ifndef LIGHTMAPPER_RD_H +#define LIGHTMAPPER_RD_H + +#include "core/local_vector.h" +#include "scene/3d/lightmapper.h" +#include "scene/resources/mesh.h" +#include "servers/rendering/rendering_device.h" + +class LightmapperRD : public Lightmapper { + GDCLASS(LightmapperRD, Lightmapper) + + struct MeshInstance { + MeshData data; + int slice = 0; + Vector2i offset; + }; + + struct Light { + float position[3]; + uint32_t type = LIGHT_TYPE_DIRECTIONAL; + float direction[3]; + float energy; + float color[3]; + float size; + float range; + float attenuation; + float spot_angle; + float spot_attenuation; + uint32_t static_bake; + uint32_t pad[3]; + + bool operator<(const Light &p_light) const { + return type < p_light.type; + } + }; + + struct Vertex { + float position[3]; + float normal_z; + float uv[2]; + float normal_xy[2]; + + bool operator==(const Vertex &p_vtx) const { + return (position[0] == p_vtx.position[0]) && + (position[1] == p_vtx.position[1]) && + (position[2] == p_vtx.position[2]) && + (uv[0] == p_vtx.uv[0]) && + (uv[1] == p_vtx.uv[1]) && + (normal_xy[0] == p_vtx.normal_xy[0]) && + (normal_xy[1] == p_vtx.normal_xy[1]) && + (normal_z == p_vtx.normal_z); + } + }; + + struct Edge { + Vector3 a; + Vector3 b; + Vector3 na; + Vector3 nb; + bool operator==(const Edge &p_seam) const { + return a == p_seam.a && b == p_seam.b && na == p_seam.na && nb == p_seam.nb; + } + Edge() { + } + + Edge(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_na, const Vector3 &p_nb) { + a = p_a; + b = p_b; + na = p_na; + nb = p_nb; + } + }; + + struct Probe { + float position[4]; + }; + + Vector probe_positions; + + struct EdgeHash { + _FORCE_INLINE_ static uint32_t hash(const Edge &p_edge) { + uint32_t h = hash_djb2_one_float(p_edge.a.x); + h = hash_djb2_one_float(p_edge.a.y, h); + h = hash_djb2_one_float(p_edge.a.z, h); + h = hash_djb2_one_float(p_edge.b.x, h); + h = hash_djb2_one_float(p_edge.b.y, h); + h = hash_djb2_one_float(p_edge.b.z, h); + return h; + } + }; + struct EdgeUV2 { + Vector2 a; + Vector2 b; + Vector2i indices; + bool operator==(const EdgeUV2 &p_uv2) const { + return a == p_uv2.a && b == p_uv2.b; + } + bool seam_found = false; + EdgeUV2(Vector2 p_a, Vector2 p_b, Vector2i p_indices) { + a = p_a; + b = p_b; + indices = p_indices; + } + EdgeUV2() {} + }; + + struct Seam { + Vector2i a; + Vector2i b; + uint32_t slice; + bool operator<(const Seam &p_seam) const { + return slice < p_seam.slice; + } + }; + + struct VertexHash { + _FORCE_INLINE_ static uint32_t hash(const Vertex &p_vtx) { + uint32_t h = hash_djb2_one_float(p_vtx.position[0]); + h = hash_djb2_one_float(p_vtx.position[1], h); + h = hash_djb2_one_float(p_vtx.position[2], h); + h = hash_djb2_one_float(p_vtx.uv[0], h); + h = hash_djb2_one_float(p_vtx.uv[1], h); + h = hash_djb2_one_float(p_vtx.normal_xy[0], h); + h = hash_djb2_one_float(p_vtx.normal_xy[1], h); + h = hash_djb2_one_float(p_vtx.normal_z, h); + return h; + } + }; + + struct Box { + float min_bounds[3]; + float pad0; + float max_bounds[3]; + float pad1; + }; + + struct Triangle { + uint32_t indices[3]; + uint32_t slice; + bool operator<(const Triangle &p_triangle) const { + return slice < p_triangle.slice; + } + }; + + Vector mesh_instances; + + Vector lights; + + struct TriangleSort { + uint32_t cell_index; + uint32_t triangle_index; + bool operator<(const TriangleSort &p_triangle_sort) const { + return cell_index < p_triangle_sort.cell_index; //sorting by triangle index in this case makes no sense + } + }; + + void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[], uint32_t p_triangle_index, LocalVector &triangles, uint32_t p_grid_size); + + struct RasterPushConstant { + float atlas_size[2]; + float uv_offset[2]; + float to_cell_size[3]; + uint32_t base_triangle; + float to_cell_offset[3]; + float bias; + int32_t grid_size[3]; + uint32_t pad2; + }; + + struct RasterSeamsPushConstant { + + uint32_t base_index; + uint32_t slice; + float uv_offset[2]; + uint32_t debug; + float blend; + uint32_t pad[2]; + }; + + struct PushConstant { + int32_t atlas_size[2]; + uint32_t ray_count; + uint32_t ray_to; + + float world_size[3]; + float bias; + + float to_cell_offset[3]; + uint32_t ray_from; + + float to_cell_size[3]; + uint32_t light_count; + + int32_t grid_size; + int32_t atlas_slice; + int32_t region_ofs[2]; + + float environment_xform[12]; + }; + + Vector> bake_textures; + Vector probe_values; + + BakeError _blit_meshes_into_atlas(int p_max_texture_size, Vector> &albedo_images, Vector> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata); + void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector &probe_positions, GenerateProbes p_generate_probes, Vector &slice_triangle_count, Vector &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &grid_texture_sdf, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata); + void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform); + +public: + virtual void add_mesh(const MeshData &p_mesh); + virtual void add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance); + virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size); + virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size); + virtual void add_probe(const Vector3 &p_position); + virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr); + + int get_bake_texture_count() const; + Ref get_bake_texture(int p_index) const; + int get_bake_mesh_count() const; + Variant get_bake_mesh_userdata(int p_index) const; + Rect2 get_bake_mesh_uv_scale(int p_index) const; + int get_bake_mesh_texture_slice(int p_index) const; + int get_bake_probe_count() const; + Vector3 get_bake_probe_point(int p_probe) const; + Vector get_bake_probe_sh(int p_probe) const; + + LightmapperRD(); +}; + +#endif // LIGHTMAPPER_H diff --git a/modules/lightmapper_rd/lm_blendseams.glsl b/modules/lightmapper_rd/lm_blendseams.glsl new file mode 100644 index 0000000000..ef1ece8ea1 --- /dev/null +++ b/modules/lightmapper_rd/lm_blendseams.glsl @@ -0,0 +1,117 @@ +/* clang-format off */ +[versions] + +lines = "#define MODE_LINES" +triangles = "#define MODE_TRIANGLES" + +[vertex] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + + /* clang-format on */ + + layout(push_constant, binding = 0, std430) uniform Params { + uint base_index; + uint slice; + vec2 uv_offset; + bool debug; + float blend; + uint pad[2]; + } params; + +layout(location = 0) out vec3 uv_interp; + +void main() { + +#ifdef MODE_TRIANGLES + + uint triangle_idx = params.base_index + gl_VertexIndex / 3; + uint triangle_subidx = gl_VertexIndex % 3; + + vec2 uv; + if (triangle_subidx == 0) { + uv = vertices.data[triangles.data[triangle_idx].indices.x].uv; + } else if (triangle_subidx == 1) { + uv = vertices.data[triangles.data[triangle_idx].indices.y].uv; + } else { + uv = vertices.data[triangles.data[triangle_idx].indices.z].uv; + } + + uv_interp = vec3(uv, float(params.slice)); + gl_Position = vec4((uv + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0); + +#endif + +#ifdef MODE_LINES + uint seam_idx = params.base_index + gl_VertexIndex / 4; + uint seam_subidx = gl_VertexIndex % 4; + + uint src_idx; + uint dst_idx; + + if (seam_subidx == 0) { + src_idx = seams.data[seam_idx].b.x; + dst_idx = seams.data[seam_idx].a.x; + } else if (seam_subidx == 1) { + src_idx = seams.data[seam_idx].b.y; + dst_idx = seams.data[seam_idx].a.y; + } else if (seam_subidx == 2) { + src_idx = seams.data[seam_idx].a.x; + dst_idx = seams.data[seam_idx].b.x; + } else if (seam_subidx == 3) { + src_idx = seams.data[seam_idx].a.y; + dst_idx = seams.data[seam_idx].b.y; + } + + vec2 src_uv = vertices.data[src_idx].uv; + vec2 dst_uv = vertices.data[dst_idx].uv + params.uv_offset; + + uv_interp = vec3(src_uv, float(params.slice)); + gl_Position = vec4(dst_uv * 2.0 - 1.0, 0.0001, 1.0); + ; +#endif +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + + /* clang-format on */ + + layout(push_constant, binding = 0, std430) uniform Params { + uint base_index; + uint slice; + vec2 uv_offset; + bool debug; + float blend; + uint pad[2]; + } params; + +layout(location = 0) in vec3 uv_interp; + +layout(location = 0) out vec4 dst_color; + +layout(set = 1, binding = 0) uniform texture2DArray src_color_tex; + +void main() { + + if (params.debug) { +#ifdef MODE_TRIANGLES + dst_color = vec4(1, 0, 1, 1); +#else + dst_color = vec4(1, 1, 0, 1); +#endif + } else { + vec4 src_color = textureLod(sampler2DArray(src_color_tex, linear_sampler), uv_interp, 0.0); + dst_color = vec4(src_color.rgb, params.blend); //mix + } +} diff --git a/modules/lightmapper_rd/lm_common_inc.glsl b/modules/lightmapper_rd/lm_common_inc.glsl new file mode 100644 index 0000000000..0ff455936e --- /dev/null +++ b/modules/lightmapper_rd/lm_common_inc.glsl @@ -0,0 +1,92 @@ + +/* SET 0, static data that does not change between any call */ + +struct Vertex { + vec3 position; + float normal_z; + vec2 uv; + vec2 normal_xy; +}; + +layout(set = 0, binding = 1, std430) restrict readonly buffer Vertices { + Vertex data[]; +} +vertices; + +struct Triangle { + uvec3 indices; + uint slice; +}; + +layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles { + Triangle data[]; +} +triangles; + +struct Box { + vec3 min_bounds; + uint pad0; + vec3 max_bounds; + uint pad1; +}; + +layout(set = 0, binding = 3, std430) restrict readonly buffer Boxes { + Box data[]; +} +boxes; + +layout(set = 0, binding = 4, std430) restrict readonly buffer GridIndices { + uint data[]; +} +grid_indices; + +#define LIGHT_TYPE_DIRECTIONAL 0 +#define LIGHT_TYPE_OMNI 1 +#define LIGHT_TYPE_SPOT 2 + +struct Light { + vec3 position; + uint type; + + vec3 direction; + float energy; + + vec3 color; + float size; + + float range; + float attenuation; + float spot_angle; + float spot_attenuation; + + bool static_bake; + uint pad[3]; +}; + +layout(set = 0, binding = 5, std430) restrict readonly buffer Lights { + Light data[]; +} +lights; + +struct Seam { + uvec2 a; + uvec2 b; +}; + +layout(set = 0, binding = 6, std430) restrict readonly buffer Seams { + Seam data[]; +} +seams; + +layout(set = 0, binding = 7, std430) restrict readonly buffer Probes { + vec4 data[]; +} +probe_positions; + +layout(set = 0, binding = 8) uniform utexture3D grid; +layout(set = 0, binding = 9) uniform texture3D grid_sdf; + +layout(set = 0, binding = 10) uniform texture2DArray albedo_tex; +layout(set = 0, binding = 11) uniform texture2DArray emission_tex; + +layout(set = 0, binding = 12) uniform sampler linear_sampler; diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl new file mode 100644 index 0000000000..a178bd9b2e --- /dev/null +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -0,0 +1,657 @@ +/* clang-format off */ +[versions] + +primary = "#define MODE_DIRECT_LIGHT" +secondary = "#define MODE_BOUNCE_LIGHT" +dilate = "#define MODE_DILATE" +unocclude = "#define MODE_UNOCCLUDE" +light_probes = "#define MODE_LIGHT_PROBES" + +[compute] + +#version 450 + +VERSION_DEFINES + +// One 2D local group focusing in one layer at a time, though all +// in parallel (no barriers) makes more sense than a 3D local group +// as this can take more advantage of the cache for each group. + +#ifdef MODE_LIGHT_PROBES + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +#else + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#endif + +#include "lm_common_inc.glsl" + +/* clang-format on */ + +#ifdef MODE_LIGHT_PROBES + +layout(set = 1, binding = 0, std430) restrict buffer LightProbeData { + vec4 data[]; +} +light_probes; + +layout(set = 1, binding = 1) uniform texture2DArray source_light; +layout(set = 1, binding = 2) uniform texture2DArray source_direct_light; //also need the direct light, which was omitted +layout(set = 1, binding = 3) uniform texture2D environment; +#endif + +#ifdef MODE_UNOCCLUDE + +layout(rgba32f, set = 1, binding = 0) uniform restrict image2DArray position; +layout(rgba32f, set = 1, binding = 1) uniform restrict readonly image2DArray unocclude; + +#endif + +#if defined(MODE_DIRECT_LIGHT) || defined(MODE_BOUNCE_LIGHT) + +layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_light; +layout(set = 1, binding = 1) uniform texture2DArray source_light; +layout(set = 1, binding = 2) uniform texture2DArray source_position; +layout(set = 1, binding = 3) uniform texture2DArray source_normal; +layout(rgba16f, set = 1, binding = 4) uniform restrict image2DArray accum_light; + +#endif + +#ifdef MODE_BOUNCE_LIGHT +layout(rgba32f, set = 1, binding = 5) uniform restrict image2DArray bounce_accum; +layout(set = 1, binding = 6) uniform texture2D environment; +#endif +#ifdef MODE_DIRECT_LIGHT +layout(rgba32f, set = 1, binding = 5) uniform restrict writeonly image2DArray primary_dynamic; +#endif + +#ifdef MODE_DILATE +layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_light; +layout(set = 1, binding = 1) uniform texture2DArray source_light; +#endif + +layout(push_constant, binding = 0, std430) uniform Params { + ivec2 atlas_size; // x used for light probe mode total probes + uint ray_count; + uint ray_to; + + vec3 world_size; + float bias; + + vec3 to_cell_offset; + uint ray_from; + + vec3 to_cell_size; + uint light_count; + + int grid_size; + int atlas_slice; + ivec2 region_ofs; + + mat3x4 env_transform; +} +params; + +//check it, but also return distance and barycentric coords (for uv lookup) +bool ray_hits_triangle(vec3 from, vec3 dir, float max_dist, vec3 p0, vec3 p1, vec3 p2, out float r_distance, out vec3 r_barycentric) { + + const vec3 e0 = p1 - p0; + const vec3 e1 = p0 - p2; + vec3 triangleNormal = cross(e1, e0); + + const vec3 e2 = (1.0 / dot(triangleNormal, dir)) * (p0 - from); + const vec3 i = cross(dir, e2); + + r_barycentric.y = dot(i, e1); + r_barycentric.z = dot(i, e0); + r_barycentric.x = 1.0 - (r_barycentric.z + r_barycentric.y); + r_distance = dot(triangleNormal, e2); + return (r_distance > params.bias) && (r_distance < max_dist) && all(greaterThanEqual(r_barycentric, vec3(0.0))); +} + +bool trace_ray(vec3 p_from, vec3 p_to +#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) + , + out uint r_triangle, out vec3 r_barycentric +#endif +#if defined(MODE_UNOCCLUDE) + , + out float r_distance, out vec3 r_normal +#endif +) { + + /* world coords */ + + vec3 rel = p_to - p_from; + float rel_len = length(rel); + vec3 dir = normalize(rel); + vec3 inv_dir = 1.0 / dir; + + /* cell coords */ + + vec3 from_cell = (p_from - params.to_cell_offset) * params.to_cell_size; + vec3 to_cell = (p_to - params.to_cell_offset) * params.to_cell_size; + + //prepare DDA + vec3 rel_cell = to_cell - from_cell; + ivec3 icell = ivec3(from_cell); + ivec3 iendcell = ivec3(to_cell); + vec3 dir_cell = normalize(rel_cell); + vec3 delta = abs(1.0 / dir_cell); //vec3(length(rel_cell)) / rel_cell); + ivec3 step = ivec3(sign(rel_cell)); + vec3 side = (sign(rel_cell) * (vec3(icell) - from_cell) + (sign(rel_cell) * 0.5) + 0.5) * delta; + + uint iters = 0; + while (all(greaterThanEqual(icell, ivec3(0))) && all(lessThan(icell, ivec3(params.grid_size))) && iters < 1000) { + + uvec2 cell_data = texelFetch(usampler3D(grid, linear_sampler), icell, 0).xy; + if (cell_data.x > 0) { //triangles here + + bool hit = false; +#if defined(MODE_UNOCCLUDE) + bool hit_backface = false; +#endif + float best_distance = 1e20; + + for (uint i = 0; i < cell_data.x; i++) { + uint tidx = grid_indices.data[cell_data.y + i]; + + //Ray-Box test + vec3 t0 = (boxes.data[tidx].min_bounds - p_from) * inv_dir; + vec3 t1 = (boxes.data[tidx].max_bounds - p_from) * inv_dir; + vec3 tmin = min(t0, t1), tmax = max(t0, t1); + + if (max(tmin.x, max(tmin.y, tmin.z)) <= min(tmax.x, min(tmax.y, tmax.z))) { + continue; //ray box failed + } + + //prepare triangle vertices + vec3 vtx0 = vertices.data[triangles.data[tidx].indices.x].position; + vec3 vtx1 = vertices.data[triangles.data[tidx].indices.y].position; + vec3 vtx2 = vertices.data[triangles.data[tidx].indices.z].position; +#if defined(MODE_UNOCCLUDE) + vec3 normal = -normalize(cross((vtx0 - vtx1), (vtx0 - vtx2))); + + bool backface = dot(normal, dir) >= 0.0; +#endif + float distance; + vec3 barycentric; + + if (ray_hits_triangle(p_from, dir, rel_len, vtx0, vtx1, vtx2, distance, barycentric)) { +#ifdef MODE_DIRECT_LIGHT + return true; //any hit good +#endif + +#if defined(MODE_UNOCCLUDE) + if (!backface) { + // the case of meshes having both a front and back face in the same plane is more common than + // expected, so if this is a front-face, bias it closer to the ray origin, so it always wins over the back-face + distance = max(params.bias, distance - params.bias); + } + + hit = true; + + if (distance < best_distance) { + hit_backface = backface; + best_distance = distance; + r_distance = distance; + r_normal = normal; + } + +#endif + +#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) + + hit = true; + if (distance < best_distance) { + best_distance = distance; + r_triangle = tidx; + r_barycentric = barycentric; + } + +#endif + } + } +#if defined(MODE_UNOCCLUDE) + + if (hit) { + return hit_backface; + } +#endif +#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) + if (hit) { + return true; + } +#endif + } + + if (icell == iendcell) { + break; + } + + bvec3 mask = lessThanEqual(side.xyz, min(side.yzx, side.zxy)); + side += vec3(mask) * delta; + icell += ivec3(vec3(mask)) * step; + + iters++; + } + + return false; +} + +const float PI = 3.14159265f; +const float GOLDEN_ANGLE = PI * (3.0 - sqrt(5.0)); + +vec3 vogel_hemisphere(uint p_index, uint p_count, float p_offset) { + float r = sqrt(float(p_index) + 0.5f) / sqrt(float(p_count)); + float theta = float(p_index) * GOLDEN_ANGLE + p_offset; + float y = cos(r * PI * 0.5); + float l = sin(r * PI * 0.5); + return vec3(l * cos(theta), l * sin(theta), y); +} + +float quick_hash(vec2 pos) { + return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237); +} + +void main() { + +#ifdef MODE_LIGHT_PROBES + int probe_index = int(gl_GlobalInvocationID.x); + if (probe_index >= params.atlas_size.x) { //too large, do nothing + return; + } + +#else + ivec2 atlas_pos = ivec2(gl_GlobalInvocationID.xy) + params.region_ofs; + if (any(greaterThanEqual(atlas_pos, params.atlas_size))) { //too large, do nothing + return; + } +#endif + +#ifdef MODE_DIRECT_LIGHT + + vec3 normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + if (length(normal) < 0.5) { + return; //empty texel, no process + } + vec3 position = texelFetch(sampler2DArray(source_position, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + + //go through all lights + //start by own light (emissive) + vec3 static_light = vec3(0.0); + vec3 dynamic_light = vec3(0.0); + +#ifdef USE_SH_LIGHTMAPS + vec4 sh_accum[4] = vec4[]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0)); +#endif + + for (uint i = 0; i < params.light_count; i++) { + + vec3 light_pos; + float attenuation; + if (lights.data[i].type == LIGHT_TYPE_DIRECTIONAL) { + vec3 light_vec = lights.data[i].direction; + light_pos = position - light_vec * length(params.world_size); + attenuation = 1.0; + } else { + light_pos = lights.data[i].position; + float d = distance(position, light_pos); + if (d > lights.data[i].range) { + continue; + } + + d /= lights.data[i].range; + + attenuation = pow(max(1.0 - d, 0.0), lights.data[i].attenuation); + + if (lights.data[i].type == LIGHT_TYPE_SPOT) { + + vec3 rel = normalize(position - light_pos); + float angle = acos(dot(rel, lights.data[i].direction)); + if (angle > lights.data[i].spot_angle) { + continue; //invisible, dont try + } + + float d = clamp(angle / lights.data[i].spot_angle, 0, 1); + attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation); + } + } + + vec3 light_dir = normalize(light_pos - position); + attenuation *= max(0.0, dot(normal, light_dir)); + + if (attenuation <= 0.0001) { + continue; //no need to do anything + } + + if (!trace_ray(position + light_dir * params.bias, light_pos)) { + vec3 light = lights.data[i].color * lights.data[i].energy * attenuation; + if (lights.data[i].static_bake) { + static_light += light; +#ifdef USE_SH_LIGHTMAPS + + float c[4] = float[]( + 0.282095, //l0 + 0.488603 * light_dir.y, //l1n1 + 0.488603 * light_dir.z, //l1n0 + 0.488603 * light_dir.x //l1p1 + ); + + for (uint j = 0; j < 4; j++) { + sh_accum[j].rgb += light * c[j] * (1.0 / 3.0); + } +#endif + + } else { + dynamic_light += light; + } + } + } + + vec3 albedo = texelFetch(sampler2DArray(albedo_tex, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).rgb; + vec3 emissive = texelFetch(sampler2DArray(emission_tex, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).rgb; + + dynamic_light *= albedo; //if it will bounce, must multiply by albedo + dynamic_light += emissive; + + //keep for lightprobes + imageStore(primary_dynamic, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0)); + + dynamic_light += static_light * albedo; //send for bounces + imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0)); + +#ifdef USE_SH_LIGHTMAPS + //keep for adding at the end + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 0), sh_accum[0]); + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 1), sh_accum[1]); + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 2), sh_accum[2]); + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 3), sh_accum[3]); + +#else + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), vec4(static_light, 1.0)); +#endif + +#endif + +#ifdef MODE_BOUNCE_LIGHT + + vec3 normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + if (length(normal) < 0.5) { + return; //empty texel, no process + } + + vec3 position = texelFetch(sampler2DArray(source_position, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, normal)); + vec3 bitangent = normalize(cross(tangent, normal)); + mat3 normal_mat = mat3(tangent, bitangent, normal); + +#ifdef USE_SH_LIGHTMAPS + vec4 sh_accum[4] = vec4[]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0)); +#endif + vec3 light_average = vec3(0.0); + for (uint i = params.ray_from; i < params.ray_to; i++) { + vec3 ray_dir = normal_mat * vogel_hemisphere(i, params.ray_count, quick_hash(vec2(atlas_pos))); + + uint tidx; + vec3 barycentric; + + vec3 light; + if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + //hit a triangle + vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; + vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; + vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv; + vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice)); + + light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; + } else { + //did not hit a triangle, reach out for the sky + vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); + + vec2 st = vec2( + atan(sky_dir.x, sky_dir.z), + acos(sky_dir.y)); + + if (st.x < 0.0) + st.x += PI * 2.0; + + st /= vec2(PI * 2.0, PI); + + light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb; + } + + light_average += light; + +#ifdef USE_SH_LIGHTMAPS + + float c[4] = float[]( + 0.282095, //l0 + 0.488603 * ray_dir.y, //l1n1 + 0.488603 * ray_dir.z, //l1n0 + 0.488603 * ray_dir.x //l1p1 + ); + + for (uint j = 0; j < 4; j++) { + sh_accum[j].rgb += light * c[j] * (8.0 / float(params.ray_count)); + } +#endif + } + + vec3 light_total; + if (params.ray_from == 0) { + light_total = vec3(0.0); + } else { + light_total = imageLoad(bounce_accum, ivec3(atlas_pos, params.atlas_slice)).rgb; + } + + light_total += light_average; + +#ifdef USE_SH_LIGHTMAPS + + for (int i = 0; i < 4; i++) { + vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + i)); + accum.rgb += sh_accum[i].rgb; + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + i), accum); + } + +#endif + if (params.ray_to == params.ray_count) { + light_total /= float(params.ray_count); + imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); +#ifndef USE_SH_LIGHTMAPS + vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice)); + accum.rgb += light_total; + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), accum); +#endif + } else { + imageStore(bounce_accum, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); + } + +#endif + +#ifdef MODE_UNOCCLUDE + + //texel_size = 0.5; + //compute tangents + + vec4 position_alpha = imageLoad(position, ivec3(atlas_pos, params.atlas_slice)); + if (position_alpha.a < 0.5) { + return; + } + + vec3 vertex_pos = position_alpha.xyz; + vec4 normal_tsize = imageLoad(unocclude, ivec3(atlas_pos, params.atlas_slice)); + + vec3 face_normal = normal_tsize.xyz; + float texel_size = normal_tsize.w; + + vec3 v0 = abs(face_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, face_normal)); + vec3 bitangent = normalize(cross(tangent, face_normal)); + vec3 base_pos = vertex_pos + face_normal * params.bias; //raise a bit + + vec3 rays[4] = vec3[](tangent, bitangent, -tangent, -bitangent); + float min_d = 1e20; + for (int i = 0; i < 4; i++) { + vec3 ray_to = base_pos + rays[i] * texel_size; + float d; + vec3 norm; + + if (trace_ray(base_pos, ray_to, d, norm)) { + + if (d < min_d) { + vertex_pos = base_pos + rays[i] * d + norm * params.bias * 10.0; //this bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back. + min_d = d; + } + } + } + + position_alpha.xyz = vertex_pos; + + imageStore(position, ivec3(atlas_pos, params.atlas_slice), position_alpha); + +#endif + +#ifdef MODE_LIGHT_PROBES + + vec3 position = probe_positions.data[probe_index].xyz; + + vec4 probe_sh_accum[9] = vec4[]( + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0)); + + for (uint i = params.ray_from; i < params.ray_to; i++) { + vec3 ray_dir = vogel_hemisphere(i, params.ray_count, quick_hash(vec2(float(probe_index), 0.0))); + if (bool(i & 1)) { + //throw to both sides, so alternate them + ray_dir.z *= -1.0; + } + + uint tidx; + vec3 barycentric; + vec3 light; + + if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; + vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; + vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv; + vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice)); + + light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; + light += textureLod(sampler2DArray(source_direct_light, linear_sampler), uvw, 0.0).rgb; + } else { + + //did not hit a triangle, reach out for the sky + vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); + + vec2 st = vec2( + atan(sky_dir.x, sky_dir.z), + acos(sky_dir.y)); + + if (st.x < 0.0) + st.x += PI * 2.0; + + st /= vec2(PI * 2.0, PI); + + light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb; + } + + { + float c[9] = float[]( + 0.282095, //l0 + 0.488603 * ray_dir.y, //l1n1 + 0.488603 * ray_dir.z, //l1n0 + 0.488603 * ray_dir.x, //l1p1 + 1.092548 * ray_dir.x * ray_dir.y, //l2n2 + 1.092548 * ray_dir.y * ray_dir.z, //l2n1 + //0.315392 * (ray_dir.x * ray_dir.x + ray_dir.y * ray_dir.y + 2.0 * ray_dir.z * ray_dir.z), //l20 + 0.315392 * (3.0 * ray_dir.z * ray_dir.z - 1.0), //l20 + 1.092548 * ray_dir.x * ray_dir.z, //l2p1 + 0.546274 * (ray_dir.x * ray_dir.x - ray_dir.y * ray_dir.y) //l2p2 + ); + + for (uint j = 0; j < 9; j++) { + probe_sh_accum[j].rgb += light * c[j]; + } + } + } + + if (params.ray_from > 0) { + for (uint j = 0; j < 9; j++) { //accum from existing + probe_sh_accum[j] += light_probes.data[probe_index * 9 + j]; + } + } + + if (params.ray_to == params.ray_count) { + for (uint j = 0; j < 9; j++) { //accum from existing + probe_sh_accum[j] *= 4.0 / float(params.ray_count); + } + } + + for (uint j = 0; j < 9; j++) { //accum from existing + light_probes.data[probe_index * 9 + j] = probe_sh_accum[j]; + } + +#endif + +#ifdef MODE_DILATE + + vec4 c = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0); + //sides first, as they are closer + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -1), params.atlas_slice), 0); + //endpoints second + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 1), params.atlas_slice), 0); + + //far sides third + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -2), params.atlas_slice), 0); + + //far-mid endpoints + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 1), params.atlas_slice), 0); + + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 2), params.atlas_slice), 0); + //far endpoints + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 2), params.atlas_slice), 0); + + imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), c); + +#endif +} diff --git a/modules/lightmapper_rd/lm_raster.glsl b/modules/lightmapper_rd/lm_raster.glsl new file mode 100644 index 0000000000..ae3038aead --- /dev/null +++ b/modules/lightmapper_rd/lm_raster.glsl @@ -0,0 +1,170 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + + /* clang-format on */ + + layout(location = 0) out vec3 vertex_interp; +layout(location = 1) out vec3 normal_interp; +layout(location = 2) out vec2 uv_interp; +layout(location = 3) out vec3 barycentric; +layout(location = 4) flat out uvec3 vertex_indices; +layout(location = 5) flat out vec3 face_normal; + +layout(push_constant, binding = 0, std430) uniform Params { + vec2 atlas_size; + vec2 uv_offset; + vec3 to_cell_size; + uint base_triangle; + vec3 to_cell_offset; + float bias; + ivec3 grid_size; + uint pad2; +} +params; + +/* clang-format on */ + +void main() { + + uint triangle_idx = params.base_triangle + gl_VertexIndex / 3; + uint triangle_subidx = gl_VertexIndex % 3; + + vertex_indices = triangles.data[triangle_idx].indices; + + uint vertex_idx; + if (triangle_subidx == 0) { + vertex_idx = vertex_indices.x; + barycentric = vec3(1, 0, 0); + } else if (triangle_subidx == 1) { + vertex_idx = vertex_indices.y; + barycentric = vec3(0, 1, 0); + } else { + vertex_idx = vertex_indices.z; + barycentric = vec3(0, 0, 1); + } + + vertex_interp = vertices.data[vertex_idx].position; + uv_interp = vertices.data[vertex_idx].uv; + normal_interp = vec3(vertices.data[vertex_idx].normal_xy, vertices.data[vertex_idx].normal_z); + + face_normal = -normalize(cross((vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.y].position), (vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.z].position))); + + gl_Position = vec4((uv_interp + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0); + ; +} + +/* clang-format off */ + +[fragment] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + + +layout(push_constant, binding = 0, std430) uniform Params { + vec2 atlas_size; + vec2 uv_offset; + vec3 to_cell_size; + uint base_triangle; + vec3 to_cell_offset; + float bias; + ivec3 grid_size; + uint pad2; +} params; + +/* clang-format on */ + +layout(location = 0) in vec3 vertex_interp; +layout(location = 1) in vec3 normal_interp; +layout(location = 2) in vec2 uv_interp; +layout(location = 3) in vec3 barycentric; +layout(location = 4) in flat uvec3 vertex_indices; +layout(location = 5) in flat vec3 face_normal; + +layout(location = 0) out vec4 position; +layout(location = 1) out vec4 normal; +layout(location = 2) out vec4 unocclude; + +void main() { + + vec3 vertex_pos = vertex_interp; + + { + // smooth out vertex position by interpolating its projection in the 3 normal planes (normal plane is created by vertex pos and normal) + // because we don't want to interpolate inwards, normals found pointing inwards are pushed out. + + vec3 pos_a = vertices.data[vertex_indices.x].position; + vec3 pos_b = vertices.data[vertex_indices.y].position; + vec3 pos_c = vertices.data[vertex_indices.z].position; + vec3 center = (pos_a + pos_b + pos_c) * 0.3333333; + vec3 norm_a = vec3(vertices.data[vertex_indices.x].normal_xy, vertices.data[vertex_indices.x].normal_z); + vec3 norm_b = vec3(vertices.data[vertex_indices.y].normal_xy, vertices.data[vertex_indices.y].normal_z); + vec3 norm_c = vec3(vertices.data[vertex_indices.z].normal_xy, vertices.data[vertex_indices.z].normal_z); + + { + vec3 dir_a = normalize(pos_a - center); + float d_a = dot(dir_a, norm_a); + if (d_a < 0) { + //pointing inwards + norm_a = normalize(norm_a - dir_a * d_a); + } + } + { + vec3 dir_b = normalize(pos_b - center); + float d_b = dot(dir_b, norm_b); + if (d_b < 0) { + //pointing inwards + norm_b = normalize(norm_b - dir_b * d_b); + } + } + { + vec3 dir_c = normalize(pos_c - center); + float d_c = dot(dir_c, norm_c); + if (d_c < 0) { + //pointing inwards + norm_c = normalize(norm_c - dir_c * d_c); + } + } + + float d_a = dot(norm_a, pos_a); + float d_b = dot(norm_b, pos_b); + float d_c = dot(norm_c, pos_c); + + vec3 proj_a = vertex_pos - norm_a * (dot(norm_a, vertex_pos) - d_a); + vec3 proj_b = vertex_pos - norm_b * (dot(norm_b, vertex_pos) - d_b); + vec3 proj_c = vertex_pos - norm_c * (dot(norm_c, vertex_pos) - d_c); + + vec3 smooth_position = proj_a * barycentric.x + proj_b * barycentric.y + proj_c * barycentric.z; + + if (dot(face_normal, smooth_position) > dot(face_normal, vertex_pos)) { //only project outwards + vertex_pos = smooth_position; + } + } + + { + // unocclusion technique based on: + // https://ndotl.wordpress.com/2018/08/29/baking-artifact-free-lightmaps/ + + /* compute texel size */ + vec3 delta_uv = max(abs(dFdx(vertex_interp)), abs(dFdy(vertex_interp))); + float texel_size = max(delta_uv.x, max(delta_uv.y, delta_uv.z)); + texel_size *= sqrt(2.0); //expand to unit box edge length (again, worst case) + + unocclude.xyz = face_normal; + unocclude.w = texel_size; + + //continued on lm_compute.glsl + } + + position = vec4(vertex_pos, 1.0); + normal = vec4(normalize(normal_interp), 1.0); +} diff --git a/modules/lightmapper_rd/register_types.cpp b/modules/lightmapper_rd/register_types.cpp new file mode 100644 index 0000000000..f3938f3190 --- /dev/null +++ b/modules/lightmapper_rd/register_types.cpp @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "register_types.h" + +#include "core/project_settings.h" +#include "lightmapper_rd.h" +#include "scene/3d/lightmapper.h" + +#ifndef _3D_DISABLED +static Lightmapper *create_lightmapper_rd() { + return memnew(LightmapperRD); +} +#endif + +void register_lightmapper_rd_types() { + + GLOBAL_DEF("rendering/gpu_lightmapper/quality/low_quality_ray_count", 16); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/medium_quality_ray_count", 64); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/high_quality_ray_count", 256); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/ultra_quality_ray_count", 1024); + GLOBAL_DEF("rendering/gpu_lightmapper/performance/max_rays_per_pass", 32); + GLOBAL_DEF("rendering/gpu_lightmapper/performance/region_size", 512); + + GLOBAL_DEF("rendering/gpu_lightmapper/quality/low_quality_probe_ray_count", 64); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/medium_quality_probe_ray_count", 256); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/high_quality_probe_ray_count", 512); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/ultra_quality_probe_ray_count", 2048); + GLOBAL_DEF("rendering/gpu_lightmapper/performance/max_rays_per_probe_pass", 64); +#ifndef _3D_DISABLED + ClassDB::register_class(); + Lightmapper::create_gpu = create_lightmapper_rd; +#endif +} + +void unregister_lightmapper_rd_types() { +} diff --git a/modules/lightmapper_rd/register_types.h b/modules/lightmapper_rd/register_types.h new file mode 100644 index 0000000000..b0e15a927f --- /dev/null +++ b/modules/lightmapper_rd/register_types.h @@ -0,0 +1,37 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHTMAPPER_RD_REGISTER_TYPES_H +#define LIGHTMAPPER_RD_REGISTER_TYPES_H + +void register_lightmapper_rd_types(); +void unregister_lightmapper_rd_types(); + +#endif // XATLAS_UNWRAP_REGISTER_TYPES_H diff --git a/modules/tinyexr/image_saver_tinyexr.cpp b/modules/tinyexr/image_saver_tinyexr.cpp index 05080289bd..bc30f4e4fd 100644 --- a/modules/tinyexr/image_saver_tinyexr.cpp +++ b/modules/tinyexr/image_saver_tinyexr.cpp @@ -267,13 +267,21 @@ Error save_exr(const String &p_path, const Ref &p_img, bool p_grayscale) header.channels = channel_infos; header.pixel_types = pixel_types; header.requested_pixel_types = requested_pixel_types; + header.compression_type = TINYEXR_COMPRESSIONTYPE_PIZ; - CharString utf8_filename = p_path.utf8(); - const char *err; - int ret = SaveEXRImageToFile(&image, &header, utf8_filename.ptr(), &err); - if (ret != TINYEXR_SUCCESS) { + unsigned char *mem = nullptr; + const char *err = nullptr; + + size_t bytes = SaveEXRImageToMemory(&image, &header, &mem, &err); + + if (bytes == 0) { print_error(String("Saving EXR failed. Error: {0}").format(varray(err))); return ERR_FILE_CANT_WRITE; + } else { + FileAccessRef ref = FileAccess::open(p_path, FileAccess::WRITE); + ERR_FAIL_COND_V(!ref, ERR_FILE_CANT_WRITE); + ref->store_buffer(mem, bytes); + free(mem); } return OK; diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp index 8c5525bed3..f77646ce28 100644 --- a/modules/xatlas_unwrap/register_types.cpp +++ b/modules/xatlas_unwrap/register_types.cpp @@ -137,6 +137,7 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver pack_options.maxChartSize = 4096; pack_options.blockAlign = true; + pack_options.padding = 1; pack_options.texelsPerUnit = 1.0 / p_texel_size; xatlas::Atlas *atlas = xatlas::Create(); diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index f6618bfb47..bee1ddfc99 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -750,7 +750,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform { return false; } - bool _valid_image(const StreamTexture *p_image, int p_width, int p_height) const { + bool _valid_image(const StreamTexture2D *p_image, int p_width, int p_height) const { if (!p_image) { return false; @@ -887,22 +887,22 @@ class EditorExportPlatformUWP : public EditorExportPlatform { Vector _get_image_data(const Ref &p_preset, const String &p_path) { Vector data; - StreamTexture *image = nullptr; + StreamTexture2D *image = nullptr; if (p_path.find("StoreLogo") != -1) { - image = p_preset->get("images/store_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/store_logo"))); + image = p_preset->get("images/store_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/store_logo"))); } else if (p_path.find("Square44x44Logo") != -1) { - image = p_preset->get("images/square44x44_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square44x44_logo"))); + image = p_preset->get("images/square44x44_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square44x44_logo"))); } else if (p_path.find("Square71x71Logo") != -1) { - image = p_preset->get("images/square71x71_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square71x71_logo"))); + image = p_preset->get("images/square71x71_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square71x71_logo"))); } else if (p_path.find("Square150x150Logo") != -1) { - image = p_preset->get("images/square150x150_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square150x150_logo"))); + image = p_preset->get("images/square150x150_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square150x150_logo"))); } else if (p_path.find("Square310x310Logo") != -1) { - image = p_preset->get("images/square310x310_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square310x310_logo"))); + image = p_preset->get("images/square310x310_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/square310x310_logo"))); } else if (p_path.find("Wide310x150Logo") != -1) { - image = p_preset->get("images/wide310x150_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/wide310x150_logo"))); + image = p_preset->get("images/wide310x150_logo").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/wide310x150_logo"))); } else if (p_path.find("SplashScreen") != -1) { - image = p_preset->get("images/splash_screen").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/splash_screen"))); + image = p_preset->get("images/splash_screen").is_zero() ? nullptr : Object::cast_to(((Object *)p_preset->get("images/splash_screen"))); } else { ERR_PRINT("Unable to load logo"); } @@ -1066,13 +1066,13 @@ public: r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait_flipped"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "images/background_color"), "transparent")); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/store_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square44x44_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square71x71_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square150x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square310x310_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/wide310x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture"), Variant())); - r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/splash_screen", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/store_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square44x44_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square71x71_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square150x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/square310x310_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/wide310x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); + r_options->push_back(ExportOption(PropertyInfo(Variant::OBJECT, "images/splash_screen", PROPERTY_HINT_RESOURCE_TYPE, "StreamTexture2D"), Variant())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "tiles/show_name_on_square150x150"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "tiles/show_name_on_wide310x150"), false)); @@ -1173,37 +1173,37 @@ public: err += TTR("Invalid background color.") + "\n"; } - if (!p_preset->get("images/store_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/store_logo"))), 50, 50)) { + if (!p_preset->get("images/store_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/store_logo"))), 50, 50)) { valid = false; err += TTR("Invalid Store Logo image dimensions (should be 50x50).") + "\n"; } - if (!p_preset->get("images/square44x44_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square44x44_logo"))), 44, 44)) { + if (!p_preset->get("images/square44x44_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square44x44_logo"))), 44, 44)) { valid = false; err += TTR("Invalid square 44x44 logo image dimensions (should be 44x44).") + "\n"; } - if (!p_preset->get("images/square71x71_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square71x71_logo"))), 71, 71)) { + if (!p_preset->get("images/square71x71_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square71x71_logo"))), 71, 71)) { valid = false; err += TTR("Invalid square 71x71 logo image dimensions (should be 71x71).") + "\n"; } - if (!p_preset->get("images/square150x150_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square150x150_logo"))), 150, 150)) { + if (!p_preset->get("images/square150x150_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square150x150_logo"))), 150, 150)) { valid = false; err += TTR("Invalid square 150x150 logo image dimensions (should be 150x150).") + "\n"; } - if (!p_preset->get("images/square310x310_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square310x310_logo"))), 310, 310)) { + if (!p_preset->get("images/square310x310_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/square310x310_logo"))), 310, 310)) { valid = false; err += TTR("Invalid square 310x310 logo image dimensions (should be 310x310).") + "\n"; } - if (!p_preset->get("images/wide310x150_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/wide310x150_logo"))), 310, 150)) { + if (!p_preset->get("images/wide310x150_logo").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/wide310x150_logo"))), 310, 150)) { valid = false; err += TTR("Invalid wide 310x150 logo image dimensions (should be 310x150).") + "\n"; } - if (!p_preset->get("images/splash_screen").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/splash_screen"))), 620, 300)) { + if (!p_preset->get("images/splash_screen").is_zero() && !_valid_image((Object::cast_to((Object *)p_preset->get("images/splash_screen"))), 620, 300)) { valid = false; err += TTR("Invalid splash screen image dimensions (should be 620x300).") + "\n"; } diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 6bde56104e..6efe7f60b2 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -28,72 +28,24 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if 0 #include "baked_lightmap.h" #include "core/io/config_file.h" #include "core/io/resource_saver.h" +#include "core/math/camera_matrix.h" +#include "core/math/delaunay_3d.h" #include "core/os/dir_access.h" +#include "core/os/file_access.h" #include "core/os/os.h" -#include "voxel_light_baker.h" +#include "core/sort_array.h" +#include "lightmap_probe.h" -void BakedLightmapData::set_bounds(const AABB &p_bounds) { +void BakedLightmapData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) { - bounds = p_bounds; - RS::get_singleton()->lightmap_capture_set_bounds(baked_light, p_bounds); -} - -AABB BakedLightmapData::get_bounds() const { - - return bounds; -} - -void BakedLightmapData::set_octree(const Vector &p_octree) { - - RS::get_singleton()->lightmap_capture_set_octree(baked_light, p_octree); -} - -Vector BakedLightmapData::get_octree() const { - - return RS::get_singleton()->lightmap_capture_get_octree(baked_light); -} - -void BakedLightmapData::set_cell_space_transform(const Transform &p_xform) { - - cell_space_xform = p_xform; - RS::get_singleton()->lightmap_capture_set_octree_cell_transform(baked_light, p_xform); -} - -Transform BakedLightmapData::get_cell_space_transform() const { - return cell_space_xform; -} - -void BakedLightmapData::set_cell_subdiv(int p_cell_subdiv) { - cell_subdiv = p_cell_subdiv; - RS::get_singleton()->lightmap_capture_set_octree_cell_subdiv(baked_light, p_cell_subdiv); -} - -int BakedLightmapData::get_cell_subdiv() const { - return cell_subdiv; -} - -void BakedLightmapData::set_energy(float p_energy) { - - energy = p_energy; - RS::get_singleton()->lightmap_capture_set_energy(baked_light, energy); -} - -float BakedLightmapData::get_energy() const { - - return energy; -} - -void BakedLightmapData::add_user(const NodePath &p_path, const Ref &p_lightmap, int p_instance) { - - ERR_FAIL_COND_MSG(p_lightmap.is_null(), "It's not a reference to a valid Texture object."); User user; user.path = p_path; - user.lightmap = p_lightmap; - user.instance_index = p_instance; + user.uv_scale = p_uv_scale; + user.slice_index = p_slice_index; + user.sub_instance = p_sub_instance; users.push_back(user); } @@ -106,16 +58,23 @@ NodePath BakedLightmapData::get_user_path(int p_user) const { ERR_FAIL_INDEX_V(p_user, users.size(), NodePath()); return users[p_user].path; } -Ref BakedLightmapData::get_user_lightmap(int p_user) const { - ERR_FAIL_INDEX_V(p_user, users.size(), Ref()); - return users[p_user].lightmap; -} - -int BakedLightmapData::get_user_instance(int p_user) const { +int32_t BakedLightmapData::get_user_sub_instance(int p_user) const { ERR_FAIL_INDEX_V(p_user, users.size(), -1); - return users[p_user].instance_index; + return users[p_user].sub_instance; +} + +Rect2 BakedLightmapData::get_user_lightmap_uv_scale(int p_user) const { + + ERR_FAIL_INDEX_V(p_user, users.size(), Rect2()); + return users[p_user].uv_scale; +} + +int BakedLightmapData::get_user_lightmap_slice_index(int p_user) const { + + ERR_FAIL_INDEX_V(p_user, users.size(), -1); + return users[p_user].slice_index; } void BakedLightmapData::clear_users() { @@ -124,10 +83,10 @@ void BakedLightmapData::clear_users() { void BakedLightmapData::_set_user_data(const Array &p_data) { - ERR_FAIL_COND((p_data.size() % 3) != 0); + ERR_FAIL_COND((p_data.size() % 4) != 0); - for (int i = 0; i < p_data.size(); i += 3) { - add_user(p_data[i], p_data[i + 1], p_data[i + 2]); + for (int i = 0; i < p_data.size(); i += 4) { + add_user(p_data[i + 0], p_data[i + 1], p_data[i + 2], p_data[i + 3]); } } @@ -136,522 +95,1132 @@ Array BakedLightmapData::_get_user_data() const { Array ret; for (int i = 0; i < users.size(); i++) { ret.push_back(users[i].path); - ret.push_back(users[i].lightmap); - ret.push_back(users[i].instance_index); + ret.push_back(users[i].uv_scale); + ret.push_back(users[i].slice_index); + ret.push_back(users[i].sub_instance); } return ret; } RID BakedLightmapData::get_rid() const { - return baked_light; + return lightmap; +} + +void BakedLightmapData::clear() { + users.clear(); +} + +void BakedLightmapData::set_light_texture(const Ref &p_light_texture) { + light_texture = p_light_texture; + RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); +} + +Ref BakedLightmapData::get_light_texture() const { + return light_texture; +} + +void BakedLightmapData::set_uses_spherical_harmonics(bool p_enable) { + uses_spherical_harmonics = p_enable; + RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); +} + +bool BakedLightmapData::is_using_spherical_harmonics() const { + return uses_spherical_harmonics; +} + +void BakedLightmapData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { + if (p_points.size()) { + int pc = p_points.size(); + ERR_FAIL_COND(pc * 9 != p_point_sh.size()); + ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0); + ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0); + RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, p_points, p_point_sh, p_tetrahedra, p_bsp_tree); + RS::get_singleton()->lightmap_set_probe_bounds(lightmap, p_bounds); + RS::get_singleton()->lightmap_set_probe_interior(lightmap, p_interior); + } else { + RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, PackedVector3Array(), PackedColorArray(), PackedInt32Array(), PackedInt32Array()); + RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB()); + RS::get_singleton()->lightmap_set_probe_interior(lightmap, false); + } + interior = p_interior; + bounds = p_bounds; +} + +PackedVector3Array BakedLightmapData::get_capture_points() const { + return RS::get_singleton()->lightmap_get_probe_capture_points(lightmap); +} +PackedColorArray BakedLightmapData::get_capture_sh() const { + return RS::get_singleton()->lightmap_get_probe_capture_sh(lightmap); +} +PackedInt32Array BakedLightmapData::get_capture_tetrahedra() const { + return RS::get_singleton()->lightmap_get_probe_capture_tetrahedra(lightmap); +} + +PackedInt32Array BakedLightmapData::get_capture_bsp_tree() const { + return RS::get_singleton()->lightmap_get_probe_capture_bsp_tree(lightmap); +} + +AABB BakedLightmapData::get_capture_bounds() const { + return bounds; +} + +bool BakedLightmapData::is_interior() const { + return interior; +} + +void BakedLightmapData::_set_probe_data(const Dictionary &p_data) { + ERR_FAIL_COND(!p_data.has("bounds")); + ERR_FAIL_COND(!p_data.has("points")); + ERR_FAIL_COND(!p_data.has("tetrahedra")); + ERR_FAIL_COND(!p_data.has("bsp")); + ERR_FAIL_COND(!p_data.has("sh")); + ERR_FAIL_COND(!p_data.has("interior")); + set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]); +} + +Dictionary BakedLightmapData::_get_probe_data() const { + Dictionary d; + d["bounds"] = get_capture_bounds(); + d["points"] = get_capture_points(); + d["tetrahedra"] = get_capture_tetrahedra(); + d["bsp"] = get_capture_bsp_tree(); + d["sh"] = get_capture_sh(); + d["interior"] = is_interior(); + return d; } void BakedLightmapData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &BakedLightmapData::_set_user_data); ClassDB::bind_method(D_METHOD("_get_user_data"), &BakedLightmapData::_get_user_data); - ClassDB::bind_method(D_METHOD("set_bounds", "bounds"), &BakedLightmapData::set_bounds); - ClassDB::bind_method(D_METHOD("get_bounds"), &BakedLightmapData::get_bounds); + ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &BakedLightmapData::set_light_texture); + ClassDB::bind_method(D_METHOD("get_light_texture"), &BakedLightmapData::get_light_texture); - ClassDB::bind_method(D_METHOD("set_cell_space_transform", "xform"), &BakedLightmapData::set_cell_space_transform); - ClassDB::bind_method(D_METHOD("get_cell_space_transform"), &BakedLightmapData::get_cell_space_transform); + ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &BakedLightmapData::set_uses_spherical_harmonics); + ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &BakedLightmapData::is_using_spherical_harmonics); - ClassDB::bind_method(D_METHOD("set_cell_subdiv", "cell_subdiv"), &BakedLightmapData::set_cell_subdiv); - ClassDB::bind_method(D_METHOD("get_cell_subdiv"), &BakedLightmapData::get_cell_subdiv); - - ClassDB::bind_method(D_METHOD("set_octree", "octree"), &BakedLightmapData::set_octree); - ClassDB::bind_method(D_METHOD("get_octree"), &BakedLightmapData::get_octree); - - ClassDB::bind_method(D_METHOD("set_energy", "energy"), &BakedLightmapData::set_energy); - ClassDB::bind_method(D_METHOD("get_energy"), &BakedLightmapData::get_energy); - - ClassDB::bind_method(D_METHOD("add_user", "path", "lightmap", "instance"), &BakedLightmapData::add_user); + ClassDB::bind_method(D_METHOD("add_user", "path", "lightmap", "offset"), &BakedLightmapData::add_user); ClassDB::bind_method(D_METHOD("get_user_count"), &BakedLightmapData::get_user_count); ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path); - ClassDB::bind_method(D_METHOD("get_user_lightmap", "user_idx"), &BakedLightmapData::get_user_lightmap); ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users); - ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "cell_space_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_space_transform", "get_cell_space_transform"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_subdiv", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_subdiv", "get_cell_subdiv"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy"); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "octree", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_octree", "get_octree"); + ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &BakedLightmapData::_set_probe_data); + ClassDB::bind_method(D_METHOD("_get_probe_data"), &BakedLightmapData::_get_probe_data); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); } BakedLightmapData::BakedLightmapData() { - baked_light = RS::get_singleton()->lightmap_capture_create(); - energy = 1; - cell_subdiv = 1; + lightmap = RS::get_singleton()->lightmap_create(); } BakedLightmapData::~BakedLightmapData() { - RS::get_singleton()->free(baked_light); + RS::get_singleton()->free(lightmap); } /////////////////////////// -BakedLightmap::BakeBeginFunc BakedLightmap::bake_begin_function = nullptr; -BakedLightmap::BakeStepFunc BakedLightmap::bake_step_function = nullptr; -BakedLightmap::BakeEndFunc BakedLightmap::bake_end_function = nullptr; +void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector &meshes, Vector &lights, Vector &probes) { -void BakedLightmap::set_bake_cell_size(float p_cell_size) { - bake_cell_size = p_cell_size; -} - -float BakedLightmap::get_bake_cell_size() const { - return bake_cell_size; -} - -void BakedLightmap::set_capture_cell_size(float p_cell_size) { - capture_cell_size = p_cell_size; -} - -float BakedLightmap::get_capture_cell_size() const { - return capture_cell_size; -} - -void BakedLightmap::set_extents(const Vector3 &p_extents) { - extents = p_extents; - update_gizmo(); - _change_notify("bake_extents"); -} - -Vector3 BakedLightmap::get_extents() const { - return extents; -} - -void BakedLightmap::set_bake_default_texels_per_unit(const float &p_bake_texels_per_unit) { - bake_default_texels_per_unit = p_bake_texels_per_unit; - update_gizmo(); -} - -float BakedLightmap::get_bake_default_texels_per_unit() const { - return bake_default_texels_per_unit; -} - -void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List &plot_meshes, List &plot_lights) { - - MeshInstance *mi = Object::cast_to(p_at_node); - if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) { + MeshInstance3D *mi = Object::cast_to(p_at_node); + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { - bool all_have_uv2 = true; + bool all_have_uv2_and_normal = true; + bool surfaces_found = false; for (int i = 0; i < mesh->get_surface_count(); i++) { + + if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { + continue; + } if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) { - all_have_uv2 = false; + all_have_uv2_and_normal = false; break; } + if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) { + all_have_uv2_and_normal = false; + break; + } + surfaces_found = true; } - if (all_have_uv2) { + if (surfaces_found && all_have_uv2_and_normal) { //READY TO BAKE! size hint could be computed if not found, actually.. - AABB aabb = mesh->get_aabb(); + MeshesFound mf; + mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform(); + mf.node_path = get_path_to(mi); + mf.subindex = -1; + mf.mesh = mesh; - Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); + static const int lightmap_scale[GeometryInstance3D::LIGHTMAP_SCALE_MAX] = { 1, 2, 4, 8 }; + mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()]; - if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { - PlotMesh pm; - pm.local_xform = xf; - pm.mesh = mesh; - pm.path = get_path_to(mi); - pm.instance_idx = -1; - for (int i = 0; i < mesh->get_surface_count(); i++) { - pm.instance_materials.push_back(mi->get_surface_material(i)); + Ref all_override = mi->get_material_override(); + for (int i = 0; i < mesh->get_surface_count(); i++) { + if (all_override.is_valid()) { + mf.overrides.push_back(all_override); + } else { + mf.overrides.push_back(mi->get_surface_material(i)); } - pm.override_material = mi->get_material_override(); - plot_meshes.push_back(pm); } + + meshes.push_back(mf); } } } - Spatial *s = Object::cast_to(p_at_node); + Node3D *s = Object::cast_to(p_at_node); if (!mi && s) { - Array meshes = p_at_node->call("get_bake_meshes"); - if (meshes.size() && (meshes.size() & 1) == 0) { + Array bmeshes = p_at_node->call("get_bake_bmeshes"); + if (bmeshes.size() && (bmeshes.size() & 1) == 0) { Transform xf = get_global_transform().affine_inverse() * s->get_global_transform(); - for (int i = 0; i < meshes.size(); i += 2) { - PlotMesh pm; - Transform mesh_xf = meshes[i + 1]; - pm.local_xform = xf * mesh_xf; - pm.mesh = meshes[i]; - pm.instance_idx = i / 2; - if (!pm.mesh.is_valid()) + for (int i = 0; i < bmeshes.size(); i += 2) { + + Ref mesh = bmeshes[i]; + if (!mesh.is_valid()) continue; - pm.path = get_path_to(s); - plot_meshes.push_back(pm); + + MeshesFound mf; + + Transform mesh_xf = bmeshes[i + 1]; + mf.xform = xf * mesh_xf; + mf.node_path = get_path_to(s); + mf.subindex = i / 2; + mf.lightmap_scale = 1; + mf.mesh = mesh; + + meshes.push_back(mf); } } } - Light *light = Object::cast_to(p_at_node); + Light3D *light = Object::cast_to(p_at_node); - if (light && light->get_bake_mode() != Light::BAKE_DISABLED) { - PlotLight pl; - Transform xf = get_global_transform().affine_inverse() * light->get_global_transform(); + if (light && light->get_bake_mode() != Light3D::BAKE_DISABLED) { - pl.local_xform = xf; - pl.light = light; - plot_lights.push_back(pl); + LightsFound lf; + lf.xform = get_global_transform().affine_inverse() * light->get_global_transform(); + lf.light = light; + lights.push_back(lf); } + + LightmapProbe *probe = Object::cast_to(p_at_node); + + if (probe) { + Transform xf = get_global_transform().affine_inverse() * probe->get_global_transform(); + probes.push_back(xf.origin); + } + for (int i = 0; i < p_at_node->get_child_count(); i++) { Node *child = p_at_node->get_child(i); if (!child->get_owner()) continue; //maybe a helper - _find_meshes_and_lights(child, plot_meshes, plot_lights); + _find_meshes_and_lights(child, meshes, lights, probes); } } -void BakedLightmap::set_hdr(bool p_enable) { - hdr = p_enable; -} +int BakedLightmap::_bsp_get_simplex_side(const Vector &p_points, const LocalVector &p_simplices, const Plane &p_plane, uint32_t p_simplex) const { -bool BakedLightmap::is_hdr() const { - return hdr; -} - -bool BakedLightmap::_bake_time(void *ud, float p_secs, float p_progress) { - - uint64_t time = OS::get_singleton()->get_ticks_usec(); - BakeTimeData *btd = (BakeTimeData *)ud; - - if (time - btd->last_step > 1000000) { - - int mins_left = p_secs / 60; - int secs_left = Math::fmod(p_secs, 60.0f); - int percent = p_progress * 100; - bool abort = bake_step_function(btd->pass + percent, btd->text + " " + vformat(RTR("%d%%"), percent) + " " + vformat(RTR("(Time Left: %d:%02d s)"), mins_left, secs_left)); - btd->last_step = time; - if (abort) - return true; + int over = 0; + int under = 0; + int coplanar = 0; + const BSPSimplex &s = p_simplices[p_simplex]; + for (int i = 0; i < 4; i++) { + const Vector3 v = p_points[s.vertices[i]]; + if (p_plane.has_point(v)) { //coplanar + coplanar++; + } else if (p_plane.is_point_over(v)) { + over++; + } else { + under++; + } } - return false; -} - -BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_visual_debug) { - - String save_path; - - if (image_path.begins_with("res://")) { - save_path = image_path; + ERR_FAIL_COND_V(under == 0 && over == 0, -2); //should never happen, we discarded flat simplices before, but in any case drop it from the bsp tree and throw an error + if (under == 0) { + return 1; // all over + } else if (over == 0) { + return -1; // all under } else { - if (get_filename() != "") { - save_path = get_filename().get_base_dir(); - } else if (get_owner() && get_owner()->get_filename() != "") { - save_path = get_owner()->get_filename().get_base_dir(); - } - - if (save_path == "") { - return BAKE_ERROR_NO_SAVE_PATH; - } - if (image_path != "") { - save_path.plus_file(image_path); - } - } - { - //check for valid save path - DirAccessRef d = DirAccess::open(save_path); - if (!d) { - ERR_PRINT("Invalid Save Path '" + save_path + "'."); - return BAKE_ERROR_NO_SAVE_PATH; - } + return 0; // crossing } +} - Ref new_light_data; - new_light_data.instance(); +//#define DEBUG_BSP - Voxelizer baker; +int32_t BakedLightmap::_compute_bsp_tree(const Vector &p_points, const LocalVector &p_planes, LocalVector &planes_tested, const LocalVector &p_simplices, const LocalVector &p_simplex_indices, LocalVector &bsp_nodes) { - int bake_subdiv; - int capture_subdiv; - AABB bake_bounds; - { - bake_bounds = AABB(-extents, extents * 2.0); - int subdiv = nearest_power_of_2_templated(int(bake_bounds.get_longest_axis_size() / bake_cell_size)); - bake_bounds.size[bake_bounds.get_longest_axis_index()] = subdiv * bake_cell_size; - bake_subdiv = nearest_shift(subdiv) + 1; + //if we reach here, it means there is more than one simplex + int32_t node_index = (int32_t)bsp_nodes.size(); + bsp_nodes.push_back(BSPNode()); - capture_subdiv = bake_subdiv; - float css = bake_cell_size; - while (css < capture_cell_size && capture_subdiv > 2) { - capture_subdiv--; - css *= 2.0; - } - } + //test with all the simplex planes + Plane best_plane; + float best_plane_score = -1.0; - baker.begin_bake(bake_subdiv, bake_bounds); - - List mesh_list; - List light_list; - - _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), mesh_list, light_list); - - if (bake_begin_function) { - bake_begin_function(mesh_list.size() + light_list.size() + 1 + mesh_list.size() * 100); - } - - int step = 0; - - int pmc = 0; - - for (List::Element *E = mesh_list.front(); E; E = E->next()) { - - if (bake_step_function) { - bake_step_function(step++, RTR("Plotting Meshes: ") + " (" + itos(pmc + 1) + "/" + itos(mesh_list.size()) + ")"); - } - - pmc++; - baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material); - } - - pmc = 0; - baker.begin_bake_light(Voxelizer::BakeQuality(bake_quality), Voxelizer::BakeMode(bake_mode), propagation, energy); - - for (List::Element *E = light_list.front(); E; E = E->next()) { - - if (bake_step_function) { - bake_step_function(step++, RTR("Plotting Lights:") + " (" + itos(pmc + 1) + "/" + itos(light_list.size()) + ")"); - } - - pmc++; - PlotLight pl = E->get(); - switch (pl.light->get_light_type()) { - case RS::LIGHT_DIRECTIONAL: { - baker.plot_light_directional(-pl.local_xform.basis.get_axis(2), pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_bake_mode() == Light::BAKE_ALL); - } break; - case RS::LIGHT_OMNI: { - baker.plot_light_omni(pl.local_xform.origin, pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_param(Light::PARAM_RANGE), pl.light->get_param(Light::PARAM_ATTENUATION), pl.light->get_bake_mode() == Light::BAKE_ALL); - } break; - case RS::LIGHT_SPOT: { - baker.plot_light_spot(pl.local_xform.origin, pl.local_xform.basis.get_axis(2), pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_param(Light::PARAM_RANGE), pl.light->get_param(Light::PARAM_ATTENUATION), pl.light->get_param(Light::PARAM_SPOT_ANGLE), pl.light->get_param(Light::PARAM_SPOT_ATTENUATION), pl.light->get_bake_mode() == Light::BAKE_ALL); - - } break; - } - } - /*if (bake_step_function) { - bake_step_function(pmc++, RTR("Finishing Plot")); - }*/ - - baker.end_bake(); - - Set used_mesh_names; - - pmc = 0; - for (List::Element *E = mesh_list.front(); E; E = E->next()) { - - String mesh_name = E->get().mesh->get_name(); - if (mesh_name == "" || mesh_name.find(":") != -1 || mesh_name.find("/") != -1) { - mesh_name = "LightMap"; - } - - if (used_mesh_names.has(mesh_name)) { - int idx = 2; - String base = mesh_name; - while (true) { - mesh_name = base + itos(idx); - if (!used_mesh_names.has(mesh_name)) - break; - idx++; - } - } - used_mesh_names.insert(mesh_name); - - pmc++; - Voxelizer::LightMapData lm; - - Error err; - if (bake_step_function) { - BakeTimeData btd; - btd.text = RTR("Lighting Meshes: ") + mesh_name + " (" + itos(pmc) + "/" + itos(mesh_list.size()) + ")"; - btd.pass = step; - btd.last_step = 0; - err = baker.make_lightmap(E->get().local_xform, E->get().mesh, bake_default_texels_per_unit, lm, _bake_time, &btd); - if (err != OK) { - bake_end_function(); - if (err == ERR_SKIP) - return BAKE_ERROR_USER_ABORTED; - return BAKE_ERROR_CANT_CREATE_IMAGE; - } - step += 100; - } else { - - err = baker.make_lightmap(E->get().local_xform, E->get().mesh, bake_default_texels_per_unit, lm); - } - - if (err == OK) { - - Ref image; - image.instance(); - - if (hdr) { - - //just save a regular image - Vector data; - int s = lm.light.size(); - data.resize(lm.light.size() * 2); - { - - uint8_t* w = data.ptrw(); - const float* r = lm.light.ptr(); - uint16_t *hfw = (uint16_t *)w.ptr(); - for (int i = 0; i < s; i++) { - hfw[i] = Math::make_half_float(r[i]); - } - } - - image->create(lm.width, lm.height, false, Image::FORMAT_RGBH, data); - - } else { - - //just save a regular image - Vector data; - int s = lm.light.size(); - data.resize(lm.light.size()); - { - - uint8_t* w = data.ptrw(); - const float* r = lm.light.ptr(); - for (int i = 0; i < s; i += 3) { - Color c(r[i + 0], r[i + 1], r[i + 2]); - c = c.to_srgb(); - w[i + 0] = CLAMP(c.r * 255, 0, 255); - w[i + 1] = CLAMP(c.g * 255, 0, 255); - w[i + 2] = CLAMP(c.b * 255, 0, 255); - } - } - - image->create(lm.width, lm.height, false, Image::FORMAT_RGB8, data); - - //This texture is saved to SRGB for two reasons: - // 1) first is so it looks better when doing the LINEAR->SRGB conversion (more accurate) - // 2) So it can be used in the GLES2 backend, which does not support linkear workflow + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { + const BSPSimplex &s = p_simplices[p_simplex_indices[i]]; + for (int j = 0; j < 4; j++) { + uint32_t plane_index = s.planes[j]; + if (planes_tested[plane_index] == node_index) { + continue; //tested this plane already } - String image_path = save_path.plus_file(mesh_name); - Ref texture; + planes_tested[plane_index] = node_index; - if (ResourceLoader::import) { + static const int face_order[4][3] = { + { 0, 1, 2 }, + { 0, 2, 3 }, + { 0, 1, 3 }, + { 1, 2, 3 } + }; - bool srgb = false; - if (false && hdr) { - //save hdr - } else { - image_path += ".png"; - print_line("image path saving png: " + image_path); - image->save_png(image_path); - srgb = true; + // despite getting rid of plane duplicates, we should still use here the actual plane to avoid numerical error + // from thinking this same simplex is intersecting rather than on a side + Vector3 v0 = p_points[s.vertices[face_order[j][0]]]; + Vector3 v1 = p_points[s.vertices[face_order[j][1]]]; + Vector3 v2 = p_points[s.vertices[face_order[j][2]]]; + + Plane plane(v0, v1, v2); + + //test with all the simplices + int over_count = 0; + int under_count = 0; + + for (uint32_t k = 0; k < p_simplex_indices.size(); k++) { + int side = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[k]); + if (side == -2) { + continue; //this simplex is invalid, skip for now + } else if (side < 0) { + under_count++; + } else if (side > 0) { + over_count++; } - - if (!FileAccess::exists(image_path + ".import")) { - Ref config; - config.instance(); - config->set_value("remap", "importer", "texture"); - config->set_value("remap", "type", "StreamTexture"); - config->set_value("params", "compress/mode", 2); - config->set_value("params", "detect_3d", false); - config->set_value("params", "flags/repeat", false); - config->set_value("params", "flags/filter", true); - config->set_value("params", "flags/mipmaps", false); - config->set_value("params", "flags/srgb", srgb); - - config->save(image_path + ".import"); - } - - ResourceLoader::import(image_path); - texture = ResourceLoader::load(image_path); //if already loaded, it will be updated on refocus? - } else { - - image_path += ".text"; - Ref tex; - bool set_path = true; - if (ResourceCache::has(image_path)) { - tex = Ref((Resource *)ResourceCache::get(image_path)); - set_path = false; - } - - if (!tex.is_valid()) { - tex.instance(); - } - - tex->create_from_image(image); - - err = ResourceSaver::save(image_path, tex, ResourceSaver::FLAG_CHANGE_PATH); - if (set_path) { - tex->set_path(image_path); - } - texture = tex; - } - if (err != OK) { - if (bake_end_function) { - bake_end_function(); - } - ERR_FAIL_COND_V(err != OK, BAKE_ERROR_CANT_CREATE_IMAGE); } - new_light_data->add_user(E->get().path, texture, E->get().instance_idx); + if (under_count == 0 && over_count == 0) { + continue; //most likely precision issue with a flat simplex, do not try this plane + } + + if (under_count > over_count) { //make sure under is always less than over, so we can compute the same ratio + SWAP(under_count, over_count); + } + + float score = 0; //by default, score is 0 (worst) + if (over_count > 0) { + //give score mainly based on ratio (under / over), this means that this plane is splitting simplices a lot, but its balanced + score = float(under_count) / over_count; + } + + //adjusting priority over least splits, probably not a great idea + //score *= Math::sqrt(float(over_count + under_count) / p_simplex_indices.size()); //also multiply score + + if (score > best_plane_score) { + + best_plane = plane; + best_plane_score = score; + } } } - AABB bounds = AABB(-extents, extents * 2); - new_light_data->set_cell_subdiv(capture_subdiv); - new_light_data->set_bounds(bounds); - new_light_data->set_octree(baker.create_capture_octree(capture_subdiv)); - { + LocalVector indices_over; + LocalVector indices_under; - float bake_bound_size = bake_bounds.get_longest_axis_size(); - Transform to_bounds; - to_bounds.basis.scale(Vector3(bake_bound_size, bake_bound_size, bake_bound_size)); - to_bounds.origin = bounds.position; + //split again, but add to list + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { - Transform to_grid; - to_grid.basis.scale(Vector3(1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1))); + uint32_t index = p_simplex_indices[i]; + int side = _bsp_get_simplex_side(p_points, p_simplices, best_plane, index); - Transform to_cell_space = to_grid * to_bounds.affine_inverse(); - new_light_data->set_cell_space_transform(to_cell_space); - } - - if (bake_end_function) { - bake_end_function(); - } - - //create the data for visual server - - if (p_create_visual_debug) { - MultiMeshInstance *mmi = memnew(MultiMeshInstance); - mmi->set_multimesh(baker.create_debug_multimesh(Voxelizer::DEBUG_LIGHT)); - add_child(mmi); -#ifdef TOOLS_ENABLED - if (get_tree()->get_edited_scene_root() == this) { - mmi->set_owner(this); - } else { - mmi->set_owner(get_owner()); + if (side == -2) { + continue; //simplex sits on the plane, does not make sense to use it } -#else - mmi->set_owner(get_owner()); + if (side <= 0) { + indices_under.push_back(index); + } + + if (side >= 0) { + indices_over.push_back(index); + } + } + +#ifdef DEBUG_BSP + print_line("node " + itos(node_index) + " found plane: " + best_plane + " score:" + rtos(best_plane_score) + " - over " + itos(indices_over.size()) + " under " + itos(indices_under.size()) + " intersecting " + itos(intersecting)); #endif + + if (best_plane_score < 0.0 || indices_over.size() == p_simplex_indices.size() || indices_under.size() == p_simplex_indices.size()) { + ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug + + // Failed to separate the tetrahedrons using planes + // this means Delaunay borked at some point. + // Luckily, because we are using tetrahedrons, we can resort to + // less precise but still working ways to generate the separating plane + // this will most likely look bad when interpolating, but at least it will not crash. + // and the arctifact will most likely also be very small, so too difficult to notice. + + //find the longest axis + + WARN_PRINT("Inconsistency found in triangulation while building BSP, probe interpolation quality may degrade a bit."); + + LocalVector centers; + AABB bounds_all; + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { + AABB bounds; + for (uint32_t j = 0; j < 4; j++) { + + Vector3 p = p_points[p_simplices[p_simplex_indices[i]].vertices[j]]; + if (j == 0) { + bounds.position = p; + } else { + bounds.expand_to(p); + } + } + if (i == 0) { + centers.push_back(bounds.position + bounds.size * 0.5); + } else { + bounds_all.merge_with(bounds); + } + } + Vector3::Axis longest_axis = Vector3::Axis(bounds_all.get_longest_axis_index()); + + //find the simplex that will go under + uint32_t min_d_idx = 0xFFFFFFFF; + float min_d_dist = 1e20; + + for (uint32_t i = 0; i < centers.size(); i++) { + if (centers[i][longest_axis] < min_d_dist) { + min_d_idx = i; + min_d_dist = centers[i][longest_axis]; + } + } + //rebuild best_plane and over/under arrays + best_plane = Plane(); + best_plane.normal[longest_axis] = 1.0; + best_plane.d = min_d_dist; + + indices_under.clear(); + indices_under.push_back(min_d_idx); + + indices_over.clear(); + + for (uint32_t i = 0; i < p_simplex_indices.size(); i++) { + if (i == min_d_idx) { + continue; + } + indices_over.push_back(p_simplex_indices[i]); + } } - set_light_data(new_light_data); + BSPNode node; + node.plane = best_plane; + + if (indices_under.size() == 0) { + //noting to do here + node.under = BSPNode::EMPTY_LEAF; + } else if (indices_under.size() == 1) { + node.under = -(indices_under[0] + 1); + } else { + node.under = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_under, bsp_nodes); + } + + if (indices_over.size() == 0) { + //noting to do here + node.over = BSPNode::EMPTY_LEAF; + } else if (indices_over.size() == 1) { + node.over = -(indices_over[0] + 1); + } else { + node.over = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_over, bsp_nodes); + } + + bsp_nodes[node_index] = node; + + return node_index; +} + +bool BakedLightmap::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) { + + BakeStepUD *bsud = (BakeStepUD *)ud; + bool ret = false; + if (bsud->func) { + ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh); + } + return ret; +} + +void BakedLightmap::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle) { + + for (int i = 0; i < 8; i++) { + Vector3i pos = p_cell->offset; + uint32_t half_size = p_cell->size / 2; + if (i & 1) { + pos.x += half_size; + } + if (i & 2) { + pos.y += half_size; + } + if (i & 4) { + pos.z += half_size; + } + + AABB subcell; + subcell.position = Vector3(pos) * p_cell_size; + subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size; + + if (!Geometry::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) + continue; + + if (p_cell->children[i] == nullptr) { + GenProbesOctree *child = memnew(GenProbesOctree); + child->offset = pos; + child->size = half_size; + p_cell->children[i] = child; + } + + if (half_size > 1) { + //still levels missing + _plot_triangle_into_octree(p_cell->children[i], p_cell_size, p_triangle); + } + } +} +void BakedLightmap::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector &probe_positions, LocalVector &new_probe_positions, HashMap &positions_used, const AABB &p_bounds) { + + for (int i = 0; i < 8; i++) { + + Vector3i pos = p_cell->offset; + if (i & 1) { + pos.x += p_cell->size; + } + if (i & 2) { + pos.y += p_cell->size; + } + if (i & 4) { + pos.z += p_cell->size; + } + + if (p_cell->size == 1 && !positions_used.has(pos)) { + //new position to insert! + Vector3 real_pos = p_bounds.position + Vector3(pos) * p_cell_size; + //see if a user submitted probe is too close + int ppcount = probe_positions.size(); + const Vector3 *pp = probe_positions.ptr(); + bool exists = false; + for (int j = 0; j < ppcount; j++) { + + if (pp[j].distance_to(real_pos) < CMP_EPSILON) { + exists = true; + break; + } + } + + if (!exists) { + new_probe_positions.push_back(real_pos); + } + + positions_used[pos] = true; + } + + if (p_cell->children[i] != nullptr) { + _gen_new_positions_from_octree(p_cell->children[i], p_cell_size, probe_positions, new_probe_positions, positions_used, p_bounds); + } + } +} +BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) { + + if (p_image_data_path == "" && (get_light_data().is_null() || !get_light_data()->get_path().is_resource_file())) { + return BAKE_ERROR_NO_SAVE_PATH; + } + + if (p_image_data_path == "") { + + if (get_light_data().is_null()) { + return BAKE_ERROR_NO_SAVE_PATH; + } + + p_image_data_path = get_light_data()->get_path(); + if (!p_image_data_path.is_resource_file()) { + return BAKE_ERROR_NO_SAVE_PATH; + } + } + + Ref lightmapper = Lightmapper::create(); + ERR_FAIL_COND_V(lightmapper.is_null(), BAKE_ERROR_NO_LIGHTMAPPER); + + BakeStepUD bsud; + bsud.func = p_bake_step; + bsud.ud = p_bake_userdata; + bsud.from_percent = 0.2; + bsud.to_percent = 0.8; + + if (p_bake_step) { + p_bake_step(0.0, TTR("Finding meshes, lights and probes"), p_bake_userdata, true); + } + /* STEP 1, FIND MESHES, LIGHTS AND PROBES */ + Vector mesh_data; + Vector lights_found; + Vector probes_found; + AABB bounds; + { + Vector meshes_found; + _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found, probes_found); + + if (meshes_found.size() == 0) { + return BAKE_ERROR_NO_MESHES; + } + // create mesh data for insert + + //get the base material textures, help compute altlas size and bounds + for (int m_i = 0; m_i < meshes_found.size(); m_i++) { + + if (p_bake_step) { + float p = (float)(m_i) / meshes_found.size(); + p_bake_step(p * 0.1, vformat(TTR("Preparing geometry %d/%d"), m_i, meshes_found.size()), p_bake_userdata, false); + } + + MeshesFound &mf = meshes_found.write[m_i]; + + Size2i lightmap_size = mf.mesh->get_lightmap_size_hint() * mf.lightmap_scale; + Vector overrides; + overrides.resize(mf.overrides.size()); + for (int i = 0; i < mf.overrides.size(); i++) { + if (mf.overrides[i].is_valid()) { + overrides.write[i] = mf.overrides[i]->get_rid(); + } + } + TypedArray images = RS::get_singleton()->bake_render_uv2(mf.mesh->get_rid(), overrides, lightmap_size); + + ERR_FAIL_COND_V(images.empty(), BAKE_ERROR_CANT_CREATE_IMAGE); + + Ref albedo = images[RS::BAKE_CHANNEL_ALBEDO_ALPHA]; + Ref orm = images[RS::BAKE_CHANNEL_ORM]; + + //multiply albedo by metal + + Lightmapper::MeshData md; + + { + Dictionary d; + d["path"] = mf.node_path; + if (mf.subindex >= 0) { + d["subindex"] = mf.subindex; + } + md.userdata = d; + } + + { + + if (albedo->get_format() != Image::FORMAT_RGBA8) { + albedo->convert(Image::FORMAT_RGBA8); + } + if (orm->get_format() != Image::FORMAT_RGBA8) { + orm->convert(Image::FORMAT_RGBA8); + } + Vector albedo_alpha = albedo->get_data(); + Vector orm_data = orm->get_data(); + + Vector albedom; + uint32_t len = albedo_alpha.size(); + albedom.resize(len); + const uint8_t *r_aa = albedo_alpha.ptr(); + const uint8_t *r_orm = orm_data.ptr(); + uint8_t *w_albedo = albedom.ptrw(); + + for (uint32_t i = 0; i < len; i += 4) { + w_albedo[i + 0] = uint8_t(CLAMP(float(r_aa[i + 0]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); + w_albedo[i + 1] = uint8_t(CLAMP(float(r_aa[i + 1]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); + w_albedo[i + 2] = uint8_t(CLAMP(float(r_aa[i + 2]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255)); + w_albedo[i + 3] = 255; + } + + md.albedo_on_uv2.instance(); + md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom); + } + + md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION]; + if (md.emission_on_uv2->get_format() != Image::FORMAT_RGBAH) { + md.emission_on_uv2->convert(Image::FORMAT_RGBAH); + } + + //get geometry + + Basis normal_xform = mf.xform.basis.inverse().transposed(); + + for (int i = 0; i < mf.mesh->get_surface_count(); i++) { + if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { + continue; + } + Array a = mf.mesh->surface_get_arrays(i); + + Vector vertices = a[Mesh::ARRAY_VERTEX]; + const Vector3 *vr = vertices.ptr(); + Vector uv = a[Mesh::ARRAY_TEX_UV2]; + const Vector2 *uvr = nullptr; + Vector normals = a[Mesh::ARRAY_NORMAL]; + const Vector3 *nr = nullptr; + Vector index = a[Mesh::ARRAY_INDEX]; + + ERR_CONTINUE(uv.size() == 0); + ERR_CONTINUE(normals.size() == 0); + + uvr = uv.ptr(); + nr = normals.ptr(); + + int facecount; + const int *ir = nullptr; + + if (index.size()) { + + facecount = index.size() / 3; + ir = index.ptr(); + } else { + facecount = vertices.size() / 3; + } + + for (int j = 0; j < facecount; j++) { + + uint32_t vidx[3]; + + if (ir) { + for (int k = 0; k < 3; k++) { + vidx[k] = ir[j * 3 + k]; + } + } else { + for (int k = 0; k < 3; k++) { + vidx[k] = j * 3 + k; + } + } + + for (int k = 0; k < 3; k++) { + Vector3 v = mf.xform.xform(vr[vidx[k]]); + if (bounds == AABB()) { + bounds.position = v; + } else { + bounds.expand_to(v); + } + md.points.push_back(v); + + md.uv2.push_back(uvr[vidx[k]]); + md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized()); + } + } + } + + mesh_data.push_back(md); + } + } + + /* STEP 2, CREATE PROBES */ + + if (p_bake_step) { + p_bake_step(0.3, TTR("Creating probes"), p_bake_userdata, true); + } + + //bounds need to include the user probes + for (int i = 0; i < probes_found.size(); i++) { + bounds.expand_to(probes_found[i]); + } + + bounds.grow_by(bounds.size.length() * 0.001); + + if (gen_probes == GENERATE_PROBES_DISABLED) { + // generate 8 probes on bound endpoints + for (int i = 0; i < 8; i++) { + probes_found.push_back(bounds.get_endpoint(i)); + } + } else { + // detect probes from geometry + static const int subdiv_values[6] = { 0, 4, 8, 16, 32 }; + int subdiv = subdiv_values[gen_probes]; + + float subdiv_cell_size; + Vector3i bound_limit; + { + int longest_axis = bounds.get_longest_axis_index(); + subdiv_cell_size = bounds.size[longest_axis] / subdiv; + int axis_n1 = (longest_axis + 1) % 3; + int axis_n2 = (longest_axis + 2) % 3; + + bound_limit[longest_axis] = subdiv; + bound_limit[axis_n1] = int(Math::ceil(bounds.size[axis_n1] / subdiv_cell_size)); + bound_limit[axis_n2] = int(Math::ceil(bounds.size[axis_n2] / subdiv_cell_size)); + //compensate bounds + bounds.size[axis_n1] = bound_limit[axis_n1] * subdiv_cell_size; + bounds.size[axis_n2] = bound_limit[axis_n2] * subdiv_cell_size; + } + + GenProbesOctree octree; + octree.size = subdiv; + + for (int i = 0; i < mesh_data.size(); i++) { + if (p_bake_step) { + float p = (float)(i) / mesh_data.size(); + p_bake_step(0.3 + p * 0.1, vformat(TTR("Creating probes from mesh %d/%d"), i, mesh_data.size()), p_bake_userdata, false); + } + + for (int j = 0; j < mesh_data[i].points.size(); j += 3) { + Vector3 points[3] = { mesh_data[i].points[j + 0] - bounds.position, mesh_data[i].points[j + 1] - bounds.position, mesh_data[i].points[j + 2] - bounds.position }; + _plot_triangle_into_octree(&octree, subdiv_cell_size, points); + } + } + + LocalVector new_probe_positions; + HashMap positions_used; + for (uint32_t i = 0; i < 8; i++) { //insert bounding endpoints + Vector3i pos; + if (i & 1) { + pos.x += bound_limit.x; + } + if (i & 2) { + pos.y += bound_limit.y; + } + if (i & 4) { + pos.z += bound_limit.z; + } + + positions_used[pos] = true; + Vector3 real_pos = bounds.position + Vector3(pos) * subdiv_cell_size; //use same formula for numerical stability + new_probe_positions.push_back(real_pos); + } + //skip first level, since probes are always added at bounds endpoints anyway (code above this) + for (int i = 0; i < 8; i++) { + + if (octree.children[i]) { + _gen_new_positions_from_octree(octree.children[i], subdiv_cell_size, probes_found, new_probe_positions, positions_used, bounds); + } + } + + for (uint32_t i = 0; i < new_probe_positions.size(); i++) { + probes_found.push_back(new_probe_positions[i]); + } + } + + // Add everything to lightmapper + if (p_bake_step) { + p_bake_step(0.4, TTR("Preparing Lightmapper"), p_bake_userdata, true); + } + + { + + for (int i = 0; i < mesh_data.size(); i++) { + lightmapper->add_mesh(mesh_data[i]); + } + for (int i = 0; i < lights_found.size(); i++) { + Light3D *light = lights_found[i].light; + Transform xf = lights_found[i].xform; + + if (Object::cast_to(light)) { + DirectionalLight3D *l = Object::cast_to(light); + lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); + } else if (Object::cast_to(light)) { + OmniLight3D *l = Object::cast_to(light); + lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + } else if (Object::cast_to(light)) { + SpotLight3D *l = Object::cast_to(light); + lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + } + } + for (int i = 0; i < probes_found.size(); i++) { + lightmapper->add_probe(probes_found[i]); + } + } + + Ref environment_image; + Basis environment_transform; + + // Add everything to lightmapper + if (environment_mode != ENVIRONMENT_MODE_DISABLED) { + if (p_bake_step) { + p_bake_step(4.1, TTR("Preparing Environment"), p_bake_userdata, true); + } + + environment_transform = get_global_transform().basis; + + switch (environment_mode) { + case ENVIRONMENT_MODE_DISABLED: { + //nothing + } break; + case ENVIRONMENT_MODE_SCENE: { + Ref world = get_world_3d(); + if (world.is_valid()) { + Ref env = world->get_environment(); + if (env.is_null()) { + env = world->get_fallback_environment(); + } + + if (env.is_valid()) { + environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64)); + } + } + } break; + case ENVIRONMENT_MODE_CUSTOM_SKY: { + if (environment_custom_sky.is_valid()) { + environment_image = RS::get_singleton()->sky_bake_panorama(environment_custom_sky->get_rid(), environment_custom_energy, true, Size2i(128, 64)); + } + + } break; + case ENVIRONMENT_MODE_CUSTOM_COLOR: { + environment_image.instance(); + environment_image->create(128, 64, false, Image::FORMAT_RGBAF); + Color c = environment_custom_color; + c.r *= environment_custom_energy; + c.g *= environment_custom_energy; + c.b *= environment_custom_energy; + for (int i = 0; i < 128; i++) { + for (int j = 0; j < 64; j++) { + environment_image->set_pixel(i, j, c); + } + } + + } break; + } + } + + Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud); + + if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) { + return BAKE_ERROR_MESHES_INVALID; + } + + /* POSTBAKE: Save Textures */ + + Ref texture; + { + + Vector> images; + for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { + images.push_back(lightmapper->get_bake_texture(i)); + } + //we assume they are all the same, so lets create a large one for saving + Ref large_image; + large_image.instance(); + + large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format()); + + for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { + large_image->blit_rect(images[i], Rect2(0, 0, images[i]->get_width(), images[i]->get_height()), Point2(0, images[i]->get_height() * i)); + } + + String base_path = p_image_data_path.get_basename() + ".exr"; + + Ref config; + + config.instance(); + if (FileAccess::exists(base_path + ".import")) { + + config->load(base_path + ".import"); + } + + config->set_value("remap", "importer", "2d_array_texture"); + config->set_value("remap", "type", "StreamTexture2DArray"); + if (!config->has_section_key("params", "compress/mode")) { + config->set_value("params", "compress/mode", 2); //user may want another compression, so leave it be + } + config->set_value("params", "compress/channel_pack", 1); + config->set_value("params", "mipmaps/generate", false); + config->set_value("params", "slices/horizontal", 1); + config->set_value("params", "slices/vertical", images.size()); + + config->save(base_path + ".import"); + + Error err = large_image->save_exr(base_path, false); + ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE); + ResourceLoader::import(base_path); + Ref t = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus? + ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE); + texture = t; + } + + /* POSTBAKE: Save Light Data */ + + Ref data; + if (get_light_data().is_valid()) { + data = get_light_data(); + set_light_data(Ref()); //clear + data->clear(); + } else { + data.instance(); + } + + data->set_light_texture(texture); + data->set_uses_spherical_harmonics(directional); + + for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) { + Dictionary d = lightmapper->get_bake_mesh_userdata(i); + NodePath np = d["path"]; + int32_t subindex = -1; + if (d.has("subindex")) { + subindex = d["subindex"]; + } + + Rect2 uv_scale = lightmapper->get_bake_mesh_uv_scale(i); + int slice_index = lightmapper->get_bake_mesh_texture_slice(i); + data->add_user(np, uv_scale, slice_index, subindex); + } + + { + // create tetrahedrons + Vector points; + Vector sh; + points.resize(lightmapper->get_bake_probe_count()); + sh.resize(lightmapper->get_bake_probe_count() * 9); + for (int i = 0; i < lightmapper->get_bake_probe_count(); i++) { + points.write[i] = lightmapper->get_bake_probe_point(i); + Vector colors = lightmapper->get_bake_probe_sh(i); + ERR_CONTINUE(colors.size() != 9); + for (int j = 0; j < 9; j++) { + sh.write[i * 9 + j] = colors[j]; + } + } + + //Obtain solved simplices + + if (p_bake_step) { + p_bake_step(0.8, TTR("Generating Probe Volumes"), p_bake_userdata, true); + } + Vector solved_simplices = Delaunay3D::tetrahedralize(points); + + LocalVector bsp_simplices; + LocalVector bsp_planes; + LocalVector bsp_simplex_indices; + PackedInt32Array tetrahedrons; + + for (int i = 0; i < solved_simplices.size(); i++) { + + //Prepare a special representation of the simplex, which uses a BSP Tree + BSPSimplex bsp_simplex; + for (int j = 0; j < 4; j++) { + bsp_simplex.vertices[j] = solved_simplices[i].points[j]; + } + for (int j = 0; j < 4; j++) { + static const int face_order[4][3] = { + { 0, 1, 2 }, + { 0, 2, 3 }, + { 0, 1, 3 }, + { 1, 2, 3 } + }; + Vector3 a = points[solved_simplices[i].points[face_order[j][0]]]; + Vector3 b = points[solved_simplices[i].points[face_order[j][1]]]; + Vector3 c = points[solved_simplices[i].points[face_order[j][2]]]; + + //store planes in an array, but ensure they are reused, to speed up processing + + Plane p(a, b, c); + int plane_index = -1; + for (uint32_t k = 0; k < bsp_planes.size(); k++) { + + if (bsp_planes[k].is_equal_approx_any_side(p)) { + plane_index = k; + break; + } + } + + if (plane_index == -1) { + plane_index = bsp_planes.size(); + bsp_planes.push_back(p); + } + + bsp_simplex.planes[j] = plane_index; + + //also fill simplex array + tetrahedrons.push_back(solved_simplices[i].points[j]); + } + + bsp_simplex_indices.push_back(bsp_simplices.size()); + bsp_simplices.push_back(bsp_simplex); + } + +//#define DEBUG_SIMPLICES_AS_OBJ_FILE +#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE + { + FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE); + for (uint32_t i = 0; i < bsp_simplices.size(); i++) { + f->store_line("o Simplex" + itos(i)); + for (int j = 0; j < 4; j++) { + f->store_line(vformat("v %f %f %f", points[bsp_simplices[i].vertices[j]].x, points[bsp_simplices[i].vertices[j]].y, points[bsp_simplices[i].vertices[j]].z)); + } + static const int face_order[4][3] = { + { 1, 2, 3 }, + { 1, 3, 4 }, + { 1, 2, 4 }, + { 2, 3, 4 } + }; + + for (int j = 0; j < 4; j++) { + f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2])); + } + } + f->close(); + } +#endif + + LocalVector bsp_nodes; + LocalVector planes_tested; + planes_tested.resize(bsp_planes.size()); + for (uint32_t i = 0; i < planes_tested.size(); i++) { + planes_tested[i] = 0x7FFFFFFF; + } + + if (p_bake_step) { + p_bake_step(0.9, TTR("Generating Probe Acceleration Structures"), p_bake_userdata, true); + } + + _compute_bsp_tree(points, bsp_planes, planes_tested, bsp_simplices, bsp_simplex_indices, bsp_nodes); + + PackedInt32Array bsp_array; + bsp_array.resize(bsp_nodes.size() * 6); // six 32 bits values used for each BSP node + { + float *fptr = (float *)bsp_array.ptrw(); + int32_t *iptr = (int32_t *)bsp_array.ptrw(); + for (uint32_t i = 0; i < bsp_nodes.size(); i++) { + fptr[i * 6 + 0] = bsp_nodes[i].plane.normal.x; + fptr[i * 6 + 1] = bsp_nodes[i].plane.normal.y; + fptr[i * 6 + 2] = bsp_nodes[i].plane.normal.z; + fptr[i * 6 + 3] = bsp_nodes[i].plane.d; + iptr[i * 6 + 4] = bsp_nodes[i].over; + iptr[i * 6 + 5] = bsp_nodes[i].under; + } +//#define DEBUG_BSP_TREE +#ifdef DEBUG_BSP_TREE + FileAccessRef f = FileAccess::open("res://bsp.txt", FileAccess::WRITE); + for (uint32_t i = 0; i < bsp_nodes.size(); i++) { + f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under)); + } +#endif + } + + /* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */ + + data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array); + /* Compute a BSP tree of the simplices, so it's easy to find the exact one */ + } + + Error err = ResourceSaver::save(p_image_data_path, data); + data->set_path(p_image_data_path); + + if (err != OK) { + return BAKE_ERROR_CANT_CREATE_IMAGE; + } + + set_light_data(data); return BAKE_ERROR_OK; } void BakedLightmap::_notification(int p_what) { - if (p_what == NOTIFICATION_READY) { + if (p_what == NOTIFICATION_POST_ENTER_TREE) { if (light_data.is_valid()) { _assign_lightmaps(); } - request_ready(); //will need ready again if re-enters tree } if (p_what == NOTIFICATION_EXIT_TREE) { @@ -667,20 +1236,18 @@ void BakedLightmap::_assign_lightmaps() { ERR_FAIL_COND(!light_data.is_valid()); for (int i = 0; i < light_data->get_user_count(); i++) { - Ref lightmap = light_data->get_user_lightmap(i); - ERR_CONTINUE(!lightmap.is_valid()); Node *node = get_node(light_data->get_user_path(i)); - int instance_idx = light_data->get_user_instance(i); + int instance_idx = light_data->get_user_sub_instance(i); if (instance_idx >= 0) { RID instance = node->call("get_bake_mesh_instance", instance_idx); if (instance.is_valid()) { - RS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), lightmap->get_rid()); + RS::get_singleton()->instance_geometry_set_lightmap(instance, get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i)); } } else { - VisualInstance *vi = Object::cast_to(node); + VisualInstance3D *vi = Object::cast_to(node); ERR_CONTINUE(!vi); - RS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), lightmap->get_rid()); + RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i)); } } } @@ -689,16 +1256,16 @@ void BakedLightmap::_clear_lightmaps() { ERR_FAIL_COND(!light_data.is_valid()); for (int i = 0; i < light_data->get_user_count(); i++) { Node *node = get_node(light_data->get_user_path(i)); - int instance_idx = light_data->get_user_instance(i); + int instance_idx = light_data->get_user_sub_instance(i); if (instance_idx >= 0) { RID instance = node->call("get_bake_mesh_instance", instance_idx); if (instance.is_valid()) { - RS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), RID()); + RS::get_singleton()->instance_geometry_set_lightmap(instance, RID(), Rect2(), 0); } } else { - VisualInstance *vi = Object::cast_to(node); + VisualInstance3D *vi = Object::cast_to(node); ERR_CONTINUE(!vi); - RS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), RID()); + RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), RID(), Rect2(), 0); } } } @@ -719,6 +1286,8 @@ void BakedLightmap::set_light_data(const Ref &p_data) { _assign_lightmaps(); } } + + update_gizmo(); } Ref BakedLightmap::get_light_data() const { @@ -726,28 +1295,6 @@ Ref BakedLightmap::get_light_data() const { return light_data; } -void BakedLightmap::_debug_bake() { - bake(get_parent(), true); -} - -void BakedLightmap::set_propagation(float p_propagation) { - propagation = p_propagation; -} - -float BakedLightmap::get_propagation() const { - - return propagation; -} - -void BakedLightmap::set_energy(float p_energy) { - energy = p_energy; -} - -float BakedLightmap::get_energy() const { - - return energy; -} - void BakedLightmap::set_bake_quality(BakeQuality p_quality) { bake_quality = p_quality; } @@ -756,109 +1303,206 @@ BakedLightmap::BakeQuality BakedLightmap::get_bake_quality() const { return bake_quality; } -void BakedLightmap::set_bake_mode(BakeMode p_mode) { - bake_mode = p_mode; -} - -BakedLightmap::BakeMode BakedLightmap::get_bake_mode() const { - return bake_mode; -} - -void BakedLightmap::set_image_path(const String &p_path) { - image_path = p_path; -} - -String BakedLightmap::get_image_path() const { - return image_path; -} - AABB BakedLightmap::get_aabb() const { - return AABB(-extents, extents * 2); + return AABB(); } Vector BakedLightmap::get_faces(uint32_t p_usage_flags) const { return Vector(); } +void BakedLightmap::set_use_denoiser(bool p_enable) { + + use_denoiser = p_enable; +} + +bool BakedLightmap::is_using_denoiser() const { + + return use_denoiser; +} + +void BakedLightmap::set_directional(bool p_enable) { + directional = p_enable; +} + +bool BakedLightmap::is_directional() const { + return directional; +} + +void BakedLightmap::set_interior(bool p_enable) { + interior = p_enable; +} +bool BakedLightmap::is_interior() const { + return interior; +} + +void BakedLightmap::set_environment_mode(EnvironmentMode p_mode) { + environment_mode = p_mode; + _change_notify(); +} + +BakedLightmap::EnvironmentMode BakedLightmap::get_environment_mode() const { + return environment_mode; +} + +void BakedLightmap::set_environment_custom_sky(const Ref &p_sky) { + environment_custom_sky = p_sky; +} + +Ref BakedLightmap::get_environment_custom_sky() const { + return environment_custom_sky; +} + +void BakedLightmap::set_environment_custom_color(const Color &p_color) { + environment_custom_color = p_color; +} +Color BakedLightmap::get_environment_custom_color() const { + return environment_custom_color; +} + +void BakedLightmap::set_environment_custom_energy(float p_energy) { + environment_custom_energy = p_energy; +} +float BakedLightmap::get_environment_custom_energy() const { + return environment_custom_energy; +} + +void BakedLightmap::set_bounces(int p_bounces) { + ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16); + bounces = p_bounces; +} + +int BakedLightmap::get_bounces() const { + return bounces; +} + +void BakedLightmap::set_bias(float p_bias) { + ERR_FAIL_COND(p_bias < 0.00001); + bias = p_bias; +} + +float BakedLightmap::get_bias() const { + return bias; +} + +void BakedLightmap::set_max_texture_size(int p_size) { + ERR_FAIL_COND(p_size < 2048); + max_texture_size = p_size; +} + +int BakedLightmap::get_max_texture_size() const { + return max_texture_size; +} + +void BakedLightmap::set_generate_probes(GenerateProbes p_generate_probes) { + gen_probes = p_generate_probes; +} + +BakedLightmap::GenerateProbes BakedLightmap::get_generate_probes() const { + return gen_probes; +} + +void BakedLightmap::_validate_property(PropertyInfo &property) const { + if (property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) { + property.usage = 0; + } + if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) { + property.usage = 0; + } + if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) { + property.usage = 0; + } +} + void BakedLightmap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_light_data", "data"), &BakedLightmap::set_light_data); ClassDB::bind_method(D_METHOD("get_light_data"), &BakedLightmap::get_light_data); - ClassDB::bind_method(D_METHOD("set_bake_cell_size", "bake_cell_size"), &BakedLightmap::set_bake_cell_size); - ClassDB::bind_method(D_METHOD("get_bake_cell_size"), &BakedLightmap::get_bake_cell_size); - - ClassDB::bind_method(D_METHOD("set_capture_cell_size", "capture_cell_size"), &BakedLightmap::set_capture_cell_size); - ClassDB::bind_method(D_METHOD("get_capture_cell_size"), &BakedLightmap::get_capture_cell_size); - ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &BakedLightmap::set_bake_quality); ClassDB::bind_method(D_METHOD("get_bake_quality"), &BakedLightmap::get_bake_quality); - ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &BakedLightmap::set_bake_mode); - ClassDB::bind_method(D_METHOD("get_bake_mode"), &BakedLightmap::get_bake_mode); + ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &BakedLightmap::set_bounces); + ClassDB::bind_method(D_METHOD("get_bounces"), &BakedLightmap::get_bounces); - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BakedLightmap::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &BakedLightmap::get_extents); + ClassDB::bind_method(D_METHOD("set_generate_probes", "subdivision"), &BakedLightmap::set_generate_probes); + ClassDB::bind_method(D_METHOD("get_generate_probes"), &BakedLightmap::get_generate_probes); - ClassDB::bind_method(D_METHOD("set_bake_default_texels_per_unit", "texels"), &BakedLightmap::set_bake_default_texels_per_unit); - ClassDB::bind_method(D_METHOD("get_bake_default_texels_per_unit"), &BakedLightmap::get_bake_default_texels_per_unit); + ClassDB::bind_method(D_METHOD("set_bias", "bias"), &BakedLightmap::set_bias); + ClassDB::bind_method(D_METHOD("get_bias"), &BakedLightmap::get_bias); - ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &BakedLightmap::set_propagation); - ClassDB::bind_method(D_METHOD("get_propagation"), &BakedLightmap::get_propagation); + ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &BakedLightmap::set_environment_mode); + ClassDB::bind_method(D_METHOD("get_environment_mode"), &BakedLightmap::get_environment_mode); - ClassDB::bind_method(D_METHOD("set_energy", "energy"), &BakedLightmap::set_energy); - ClassDB::bind_method(D_METHOD("get_energy"), &BakedLightmap::get_energy); + ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &BakedLightmap::set_environment_custom_sky); + ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &BakedLightmap::get_environment_custom_sky); - ClassDB::bind_method(D_METHOD("set_hdr", "hdr"), &BakedLightmap::set_hdr); - ClassDB::bind_method(D_METHOD("is_hdr"), &BakedLightmap::is_hdr); + ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &BakedLightmap::set_environment_custom_color); + ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &BakedLightmap::get_environment_custom_color); - ClassDB::bind_method(D_METHOD("set_image_path", "image_path"), &BakedLightmap::set_image_path); - ClassDB::bind_method(D_METHOD("get_image_path"), &BakedLightmap::get_image_path); + ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &BakedLightmap::set_environment_custom_energy); + ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &BakedLightmap::get_environment_custom_energy); - ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &BakedLightmap::bake, DEFVAL(Variant()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("debug_bake"), &BakedLightmap::_debug_bake); - ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &BakedLightmap::set_max_texture_size); + ClassDB::bind_method(D_METHOD("get_max_texture_size"), &BakedLightmap::get_max_texture_size); - ADD_GROUP("Bake", "bake_"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_bake_cell_size", "get_bake_cell_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_bake_quality", "get_bake_quality"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mode", PROPERTY_HINT_ENUM, "ConeTrace,RayTrace"), "set_bake_mode", "get_bake_mode"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_energy", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_energy", "get_energy"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_hdr"), "set_hdr", "is_hdr"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bake_extents"), "set_extents", "get_extents"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_default_texels_per_unit"), "set_bake_default_texels_per_unit", "get_bake_default_texels_per_unit"); - ADD_GROUP("Capture", "capture_"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "capture_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_capture_cell_size", "get_capture_cell_size"); + ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &BakedLightmap::set_use_denoiser); + ClassDB::bind_method(D_METHOD("is_using_denoiser"), &BakedLightmap::is_using_denoiser); + + ClassDB::bind_method(D_METHOD("set_interior", "enable"), &BakedLightmap::set_interior); + ClassDB::bind_method(D_METHOD("is_interior"), &BakedLightmap::is_interior); + + ClassDB::bind_method(D_METHOD("set_directional", "directional"), &BakedLightmap::set_directional); + ClassDB::bind_method(D_METHOD("is_directional"), &BakedLightmap::is_directional); + + // ClassDB::bind_method(D_METHOD("bake", "from_node"), &BakedLightmap::bake, DEFVAL(Variant())); + + ADD_GROUP("Tweaks", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional"), "set_directional", "is_directional"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size"); + ADD_GROUP("Environment", "environment_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy"); + ADD_GROUP("Gen Probes", "generate_probes_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes"); ADD_GROUP("Data", ""); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "image_path", PROPERTY_HINT_DIR), "set_image_path", "get_image_path"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedLightmapData"), "set_light_data", "get_light_data"); BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW); BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM); BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH); - BIND_ENUM_CONSTANT(BAKE_MODE_CONE_TRACE); - BIND_ENUM_CONSTANT(BAKE_MODE_RAY_TRACE); BIND_ENUM_CONSTANT(BAKE_ERROR_OK); BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH); BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES); BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE); BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED); + + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED); + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE); + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY); + BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR); } BakedLightmap::BakedLightmap() { - extents = Vector3(10, 10, 10); - bake_default_texels_per_unit = 20; - bake_cell_size = 0.25; - capture_cell_size = 0.5; + environment_mode = ENVIRONMENT_MODE_DISABLED; + environment_custom_color = Color(0.2, 0.7, 1.0); + environment_custom_energy = 1.0; bake_quality = BAKE_QUALITY_MEDIUM; - bake_mode = BAKE_MODE_CONE_TRACE; - energy = 1; - propagation = 1; - hdr = false; - image_path = "."; - set_disable_scale(true); + interior = false; + directional = false; + + gen_probes = GENERATE_PROBES_DISABLED; + use_denoiser = true; + bounces = 1; + bias = 0.0005; + max_texture_size = 16384; } -#endif diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h index bc9e3f55ea..020d5fe1e0 100644 --- a/scene/3d/baked_lightmap.h +++ b/scene/3d/baked_lightmap.h @@ -28,189 +28,257 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if 0 #ifndef BAKED_INDIRECT_LIGHT_H #define BAKED_INDIRECT_LIGHT_H -#include "multimesh_instance.h" -#include "scene/3d/light.h" -#include "scene/3d/visual_instance.h" +#include "core/local_vector.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/lightmapper.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/multimesh_instance_3d.h" +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/sky.h" class BakedLightmapData : public Resource { GDCLASS(BakedLightmapData, Resource); + RES_BASE_EXTENSION("lmbake") - RID baked_light; + Ref light_texture; + + bool uses_spherical_harmonics = false; + bool interior = false; + + RID lightmap; AABB bounds; - float energy; - int cell_subdiv; - Transform cell_space_xform; struct User { NodePath path; - Ref lightmap; - int instance_index; + int32_t sub_instance; + Rect2 uv_scale; + int slice_index; }; Vector users; void _set_user_data(const Array &p_data); Array _get_user_data() const; + void _set_probe_data(const Dictionary &p_data); + Dictionary _get_probe_data() const; protected: static void _bind_methods(); public: - void set_bounds(const AABB &p_bounds); - AABB get_bounds() const; - - void set_octree(const Vector &p_octree); - Vector get_octree() const; - - void set_cell_space_transform(const Transform &p_xform); - Transform get_cell_space_transform() const; - - void set_cell_subdiv(int p_cell_subdiv); - int get_cell_subdiv() const; - - void set_energy(float p_energy); - float get_energy() const; - - void add_user(const NodePath &p_path, const Ref &p_lightmap, int p_instance = -1); + void add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance = -1); int get_user_count() const; NodePath get_user_path(int p_user) const; - Ref get_user_lightmap(int p_user) const; - int get_user_instance(int p_user) const; + int32_t get_user_sub_instance(int p_user) const; + Rect2 get_user_lightmap_uv_scale(int p_user) const; + int get_user_lightmap_slice_index(int p_user) const; void clear_users(); + void set_light_texture(const Ref &p_light_texture); + Ref get_light_texture() const; + + void set_uses_spherical_harmonics(bool p_enable); + bool is_using_spherical_harmonics() const; + + bool is_interior() const; + + void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree); + PackedVector3Array get_capture_points() const; + PackedColorArray get_capture_sh() const; + PackedInt32Array get_capture_tetrahedra() const; + PackedInt32Array get_capture_bsp_tree() const; + AABB get_capture_bounds() const; + + void clear(); + virtual RID get_rid() const; BakedLightmapData(); ~BakedLightmapData(); }; -class BakedLightmap : public VisualInstance { - GDCLASS(BakedLightmap, VisualInstance); +class BakedLightmap : public VisualInstance3D { + GDCLASS(BakedLightmap, VisualInstance3D); public: enum BakeQuality { BAKE_QUALITY_LOW, BAKE_QUALITY_MEDIUM, - BAKE_QUALITY_HIGH + BAKE_QUALITY_HIGH, + BAKE_QUALITY_ULTRA, }; - - enum BakeMode { - BAKE_MODE_CONE_TRACE, - BAKE_MODE_RAY_TRACE, + enum GenerateProbes { + GENERATE_PROBES_DISABLED, + GENERATE_PROBES_SUBDIV_4, + GENERATE_PROBES_SUBDIV_8, + GENERATE_PROBES_SUBDIV_16, + GENERATE_PROBES_SUBDIV_32, }; enum BakeError { BAKE_ERROR_OK, + BAKE_ERROR_NO_LIGHTMAPPER, BAKE_ERROR_NO_SAVE_PATH, BAKE_ERROR_NO_MESHES, + BAKE_ERROR_MESHES_INVALID, BAKE_ERROR_CANT_CREATE_IMAGE, BAKE_ERROR_USER_ABORTED }; - typedef void (*BakeBeginFunc)(int); - typedef bool (*BakeStepFunc)(int, const String &); - typedef void (*BakeEndFunc)(); + enum EnvironmentMode { + ENVIRONMENT_MODE_DISABLED, + ENVIRONMENT_MODE_SCENE, + ENVIRONMENT_MODE_CUSTOM_SKY, + ENVIRONMENT_MODE_CUSTOM_COLOR, + }; private: - float bake_cell_size; - float capture_cell_size; - Vector3 extents; - float bake_default_texels_per_unit; - float propagation; - float energy; BakeQuality bake_quality; - BakeMode bake_mode; - bool hdr; - String image_path; + bool use_denoiser; + int bounces; + float bias; + int max_texture_size; + bool interior; + EnvironmentMode environment_mode; + Ref environment_custom_sky; + Color environment_custom_color; + float environment_custom_energy; + bool directional; + GenerateProbes gen_probes; Ref light_data; - struct PlotMesh { - Ref override_material; - Vector > instance_materials; + struct LightsFound { + Transform xform; + Light3D *light; + }; + + struct MeshesFound { + Transform xform; + NodePath node_path; + int32_t subindex; Ref mesh; - Transform local_xform; - NodePath path; - int instance_idx; + int32_t lightmap_scale; + Vector> overrides; }; - struct PlotLight { - Light *light; - Transform local_xform; - }; - - void _find_meshes_and_lights(Node *p_at_node, List &plot_meshes, List &plot_lights); - - void _debug_bake(); + void _find_meshes_and_lights(Node *p_at_node, Vector &meshes, Vector &lights, Vector &probes); void _assign_lightmaps(); void _clear_lightmaps(); - static bool _bake_time(void *ud, float p_secs, float p_progress); - struct BakeTimeData { String text; int pass; uint64_t last_step; }; + struct BSPSimplex { + int vertices[4]; + int planes[4]; + }; + + struct BSPNode { + static const int32_t EMPTY_LEAF = INT32_MIN; + Plane plane; + int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; + }; + + int _bsp_get_simplex_side(const Vector &p_points, const LocalVector &p_simplices, const Plane &p_plane, uint32_t p_simplex) const; + int32_t _compute_bsp_tree(const Vector &p_points, const LocalVector &p_planes, LocalVector &planes_tested, const LocalVector &p_simplices, const LocalVector &p_simplex_indices, LocalVector &bsp_nodes); + + struct BakeStepUD { + Lightmapper::BakeStepFunc func; + void *ud; + float from_percent; + float to_percent; + }; + + static bool _lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh); + + struct GenProbesOctree { + Vector3i offset; + uint32_t size; + GenProbesOctree *children[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + ~GenProbesOctree() { + for (int i = 0; i < 8; i++) { + if (children[i] != nullptr) { + memdelete(children[i]); + } + } + } + }; + + struct Vector3iHash { + _FORCE_INLINE_ static uint32_t hash(const Vector3i &p_vtx) { + uint32_t h = hash_djb2_one_32(p_vtx.x); + h = hash_djb2_one_32(p_vtx.y, h); + return hash_djb2_one_32(p_vtx.z, h); + } + }; + + void _plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle); + void _gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector &probe_positions, LocalVector &new_probe_positions, HashMap &positions_used, const AABB &p_bounds); + protected: + void _validate_property(PropertyInfo &property) const; static void _bind_methods(); void _notification(int p_what); public: - static BakeBeginFunc bake_begin_function; - static BakeStepFunc bake_step_function; - static BakeEndFunc bake_end_function; - void set_light_data(const Ref &p_data); Ref get_light_data() const; - void set_bake_cell_size(float p_cell_size); - float get_bake_cell_size() const; - - void set_capture_cell_size(float p_cell_size); - float get_capture_cell_size() const; - - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; - - void set_bake_default_texels_per_unit(const float &p_bake_texels_per_unit); - float get_bake_default_texels_per_unit() const; - - void set_propagation(float p_propagation); - float get_propagation() const; - - void set_energy(float p_energy); - float get_energy() const; - void set_bake_quality(BakeQuality p_quality); BakeQuality get_bake_quality() const; - void set_bake_mode(BakeMode p_mode); - BakeMode get_bake_mode() const; + void set_use_denoiser(bool p_enable); + bool is_using_denoiser() const; - void set_hdr(bool p_enable); - bool is_hdr() const; + void set_directional(bool p_enable); + bool is_directional() const; - void set_image_path(const String &p_path); - String get_image_path() const; + void set_interior(bool p_interior); + bool is_interior() const; + + void set_environment_mode(EnvironmentMode p_mode); + EnvironmentMode get_environment_mode() const; + + void set_environment_custom_sky(const Ref &p_sky); + Ref get_environment_custom_sky() const; + + void set_environment_custom_color(const Color &p_color); + Color get_environment_custom_color() const; + + void set_environment_custom_energy(float p_energy); + float get_environment_custom_energy() const; + + void set_bounces(int p_bounces); + int get_bounces() const; + + void set_bias(float p_bias); + float get_bias() const; + + void set_max_texture_size(int p_size); + int get_max_texture_size() const; + + void set_generate_probes(GenerateProbes p_generate_probes); + GenerateProbes get_generate_probes() const; AABB get_aabb() const; Vector get_faces(uint32_t p_usage_flags) const; - BakeError bake(Node *p_from_node, bool p_create_visual_debug = false); + BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr); BakedLightmap(); }; +VARIANT_ENUM_CAST(BakedLightmap::GenerateProbes); VARIANT_ENUM_CAST(BakedLightmap::BakeQuality); -VARIANT_ENUM_CAST(BakedLightmap::BakeMode); VARIANT_ENUM_CAST(BakedLightmap::BakeError); +VARIANT_ENUM_CAST(BakedLightmap::EnvironmentMode); -#endif #endif // BAKED_INDIRECT_LIGHT_H diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 6d571ee4f2..65a330ddc0 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -349,7 +349,7 @@ Vector3 GIProbe::get_extents() const { void GIProbe::_find_meshes(Node *p_at_node, List &plot_meshes) { MeshInstance3D *mi = Object::cast_to(p_at_node); - if (mi && mi->get_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) { + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { diff --git a/scene/3d/lightmap_probe.cpp b/scene/3d/lightmap_probe.cpp new file mode 100644 index 0000000000..2da81337f0 --- /dev/null +++ b/scene/3d/lightmap_probe.cpp @@ -0,0 +1,4 @@ +#include "lightmap_probe.h" + +LightmapProbe::LightmapProbe() { +} diff --git a/scene/3d/lightmap_probe.h b/scene/3d/lightmap_probe.h new file mode 100644 index 0000000000..65bc6914f4 --- /dev/null +++ b/scene/3d/lightmap_probe.h @@ -0,0 +1,12 @@ +#ifndef LIGHTMAP_PROBE_H +#define LIGHTMAP_PROBE_H + +#include "scene/3d/node_3d.h" + +class LightmapProbe : public Node3D { + GDCLASS(LightmapProbe, Node3D) +public: + LightmapProbe(); +}; + +#endif // LIGHTMAP_PROBE_H diff --git a/scene/3d/lightmapper.cpp b/scene/3d/lightmapper.cpp new file mode 100644 index 0000000000..53ebd5ee2e --- /dev/null +++ b/scene/3d/lightmapper.cpp @@ -0,0 +1,37 @@ +#include "lightmapper.h" + +LightmapDenoiser *(*LightmapDenoiser::create_function)() = nullptr; + +Ref LightmapDenoiser::create() { + if (create_function) { + return Ref(create_function()); + } + return Ref(); +} + +Lightmapper::CreateFunc Lightmapper::create_custom = nullptr; +Lightmapper::CreateFunc Lightmapper::create_gpu = nullptr; +Lightmapper::CreateFunc Lightmapper::create_cpu = nullptr; + +Ref Lightmapper::create() { + Lightmapper *lm = nullptr; + if (create_custom) { + lm = create_custom(); + } + + if (!lm && create_gpu) { + lm = create_gpu(); + } + + if (!lm && create_cpu) { + lm = create_cpu(); + } + if (!lm) { + return Ref(); + } else { + return Ref(lm); + } +} + +Lightmapper::Lightmapper() { +} diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h new file mode 100644 index 0000000000..7c052a30a0 --- /dev/null +++ b/scene/3d/lightmapper.h @@ -0,0 +1,90 @@ +#ifndef LIGHTMAPPER_H +#define LIGHTMAPPER_H + +#include "scene/resources/mesh.h" +#include "servers/rendering/rendering_device.h" + +class LightmapDenoiser : public Reference { + GDCLASS(LightmapDenoiser, Reference) +protected: + static LightmapDenoiser *(*create_function)(); + +public: + virtual Ref denoise_image(const Ref &p_image) = 0; + static Ref create(); +}; + +class Lightmapper : public Reference { + GDCLASS(Lightmapper, Reference) +public: + enum GenerateProbes { + GENERATE_PROBES_DISABLED, + GENERATE_PROBES_SUBDIV_4, + GENERATE_PROBES_SUBDIV_8, + GENERATE_PROBES_SUBDIV_16, + GENERATE_PROBES_SUBDIV_32, + + }; + + enum LightType { + LIGHT_TYPE_DIRECTIONAL, + LIGHT_TYPE_OMNI, + LIGHT_TYPE_SPOT + }; + + enum BakeError { + BAKE_ERROR_LIGHTMAP_TOO_SMALL, + BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES, + BAKE_OK + }; + + enum BakeQuality { + BAKE_QUALITY_LOW, + BAKE_QUALITY_MEDIUM, + BAKE_QUALITY_HIGH, + BAKE_QUALITY_ULTRA, + }; + + typedef Lightmapper *(*CreateFunc)(); + + static CreateFunc create_custom; + static CreateFunc create_gpu; + static CreateFunc create_cpu; + +protected: +public: + typedef bool (*BakeStepFunc)(float, const String &, void *, bool); //step index, step total, step description, userdata + + struct MeshData { + //triangle data + Vector points; + Vector uv2; + Vector normal; + Ref albedo_on_uv2; + Ref emission_on_uv2; + Variant userdata; + }; + + virtual void add_mesh(const MeshData &p_mesh) = 0; + virtual void add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance) = 0; + virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size) = 0; + virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) = 0; + virtual void add_probe(const Vector3 &p_position) = 0; + virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr) = 0; + + virtual int get_bake_texture_count() const = 0; + virtual Ref get_bake_texture(int p_index) const = 0; + virtual int get_bake_mesh_count() const = 0; + virtual Variant get_bake_mesh_userdata(int p_index) const = 0; + virtual Rect2 get_bake_mesh_uv_scale(int p_index) const = 0; + virtual int get_bake_mesh_texture_slice(int p_index) const = 0; + virtual int get_bake_probe_count() const = 0; + virtual Vector3 get_bake_probe_point(int p_probe) const = 0; + virtual Vector get_bake_probe_sh(int p_probe) const = 0; + + static Ref create(); + + Lightmapper(); +}; + +#endif // LIGHTMAPPER_H diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index ce8672c1dd..4724c88a30 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -239,7 +239,17 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) set_shader_instance_uniform(*r, p_value); return true; } +#ifndef DISABLE_DEPRECATED + if (p_name == SceneStringNames::get_singleton()->use_in_baked_light && bool(p_value)) { + set_gi_mode(GI_MODE_BAKED); + return true; + } + if (p_name == SceneStringNames::get_singleton()->use_dynamic_gi && bool(p_value)) { + set_gi_mode(GI_MODE_DYNAMIC); + return true; + } +#endif return false; } @@ -273,23 +283,6 @@ void GeometryInstance3D::_get_property_list(List *p_list) const { } } -void GeometryInstance3D::set_flag(Flags p_flag, bool p_value) { - - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - if (flags[p_flag] == p_value) - return; - - flags[p_flag] = p_value; - RS::get_singleton()->instance_geometry_set_flag(get_instance(), (RS::InstanceFlags)p_flag, p_value); -} - -bool GeometryInstance3D::get_flag(Flags p_flag) const { - - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - - return flags[p_flag]; -} - void GeometryInstance3D::set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting) { shadow_casting_setting = p_shadow_casting_setting; @@ -335,14 +328,45 @@ void GeometryInstance3D::set_custom_aabb(AABB aabb) { RS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb); } +void GeometryInstance3D::set_lightmap_scale(LightmapScale p_scale) { + ERR_FAIL_INDEX(p_scale, LIGHTMAP_SCALE_MAX); + lightmap_scale = p_scale; +} + +GeometryInstance3D::LightmapScale GeometryInstance3D::get_lightmap_scale() const { + return lightmap_scale; +} + +void GeometryInstance3D::set_gi_mode(GIMode p_mode) { + + switch (p_mode) { + case GI_MODE_DISABLED: { + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false); + } break; + case GI_MODE_BAKED: { + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, true); + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false); + + } break; + case GI_MODE_DYNAMIC: { + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, true); + } break; + } + + gi_mode = p_mode; +} + +GeometryInstance3D::GIMode GeometryInstance3D::get_gi_mode() const { + return gi_mode; +} + void GeometryInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance3D::set_material_override); ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance3D::get_material_override); - ClassDB::bind_method(D_METHOD("set_flag", "flag", "value"), &GeometryInstance3D::set_flag); - ClassDB::bind_method(D_METHOD("get_flag", "flag"), &GeometryInstance3D::get_flag); - ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance3D::set_cast_shadows_setting); ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance3D::get_cast_shadows_setting); @@ -364,6 +388,12 @@ void GeometryInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance3D::set_extra_cull_margin); ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance3D::get_extra_cull_margin); + ClassDB::bind_method(D_METHOD("set_lightmap_scale", "scale"), &GeometryInstance3D::set_lightmap_scale); + ClassDB::bind_method(D_METHOD("get_lightmap_scale"), &GeometryInstance3D::get_lightmap_scale); + + ClassDB::bind_method(D_METHOD("set_gi_mode", "mode"), &GeometryInstance3D::set_gi_mode); + ClassDB::bind_method(D_METHOD("get_gi_mode"), &GeometryInstance3D::get_gi_mode); + ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance3D::set_custom_aabb); ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance3D::get_aabb); @@ -372,8 +402,9 @@ void GeometryInstance3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_dynamic_gi"), "set_flag", "get_flag", FLAG_USE_DYNAMIC_GI); + ADD_GROUP("Global Illumination", "gi_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Baked,Dynamic"), "set_gi_mode", "get_gi_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, "1x,2x,4x,8x"), "set_lightmap_scale", "get_lightmap_scale"); ADD_GROUP("LOD", "lod_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance"); @@ -388,10 +419,15 @@ void GeometryInstance3D::_bind_methods() { BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED); BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); - BIND_ENUM_CONSTANT(FLAG_USE_BAKED_LIGHT); - BIND_ENUM_CONSTANT(FLAG_USE_DYNAMIC_GI); - BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE); - BIND_ENUM_CONSTANT(FLAG_MAX); + BIND_ENUM_CONSTANT(GI_MODE_DISABLED); + BIND_ENUM_CONSTANT(GI_MODE_BAKED); + BIND_ENUM_CONSTANT(GI_MODE_DYNAMIC); + + BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_1X); + BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_2X); + BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_4X); + BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_8X); + BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_MAX); } GeometryInstance3D::GeometryInstance3D() { @@ -400,9 +436,8 @@ GeometryInstance3D::GeometryInstance3D() { lod_min_hysteresis = 0; lod_max_hysteresis = 0; - for (int i = 0; i < FLAG_MAX; i++) { - flags[i] = false; - } + gi_mode = GI_MODE_DISABLED; + lightmap_scale = LIGHTMAP_SCALE_1X; shadow_casting_setting = SHADOW_CASTING_SETTING_ON; extra_cull_margin = 0; diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index cc5f92066f..a871c65b6a 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -85,13 +85,6 @@ class GeometryInstance3D : public VisualInstance3D { GDCLASS(GeometryInstance3D, VisualInstance3D); public: - enum Flags { - FLAG_USE_BAKED_LIGHT = RS::INSTANCE_FLAG_USE_BAKED_LIGHT, - FLAG_USE_DYNAMIC_GI = RS::INSTANCE_FLAG_USE_DYNAMIC_GI, - FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, - FLAG_MAX = RS::INSTANCE_FLAG_MAX, - }; - enum ShadowCastingSetting { SHADOW_CASTING_SETTING_OFF = RS::SHADOW_CASTING_SETTING_OFF, SHADOW_CASTING_SETTING_ON = RS::SHADOW_CASTING_SETTING_ON, @@ -99,8 +92,21 @@ public: SHADOW_CASTING_SETTING_SHADOWS_ONLY = RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY }; + enum GIMode { + GI_MODE_DISABLED, + GI_MODE_BAKED, + GI_MODE_DYNAMIC + }; + + enum LightmapScale { + LIGHTMAP_SCALE_1X, + LIGHTMAP_SCALE_2X, + LIGHTMAP_SCALE_4X, + LIGHTMAP_SCALE_8X, + LIGHTMAP_SCALE_MAX, + }; + private: - bool flags[FLAG_MAX]; ShadowCastingSetting shadow_casting_setting; Ref material_override; float lod_min_distance; @@ -112,6 +118,8 @@ private: mutable HashMap instance_uniform_property_remap; float extra_cull_margin; + LightmapScale lightmap_scale; + GIMode gi_mode; const StringName *_instance_uniform_get_remap(const StringName p_name) const; @@ -124,9 +132,6 @@ protected: static void _bind_methods(); public: - void set_flag(Flags p_flag, bool p_value); - bool get_flag(Flags p_flag) const; - void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting); ShadowCastingSetting get_cast_shadows_setting() const; @@ -148,6 +153,12 @@ public: void set_extra_cull_margin(float p_margin); float get_extra_cull_margin() const; + void set_gi_mode(GIMode p_mode); + GIMode get_gi_mode() const; + + void set_lightmap_scale(LightmapScale p_scale); + LightmapScale get_lightmap_scale() const; + void set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value); Variant get_shader_instance_uniform(const StringName &p_uniform) const; @@ -156,7 +167,8 @@ public: GeometryInstance3D(); }; -VARIANT_ENUM_CAST(GeometryInstance3D::Flags); VARIANT_ENUM_CAST(GeometryInstance3D::ShadowCastingSetting); +VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale); +VARIANT_ENUM_CAST(GeometryInstance3D::GIMode); #endif diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index a2d305f3cb..f9c3810843 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -29,207 +29,12 @@ /*************************************************************************/ #include "voxelizer.h" +#include "core/math/geometry.h" #include "core/os/os.h" #include "core/os/threaded_array_processor.h" #include -#define FINDMINMAX(x0, x1, x2, min, max) \ - min = max = x0; \ - if (x1 < min) \ - min = x1; \ - if (x1 > max) \ - max = x1; \ - if (x2 < min) \ - min = x2; \ - if (x2 > max) \ - max = x2; - -static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) { - int q; - Vector3 vmin, vmax; - for (q = 0; q <= 2; q++) { - if (normal[q] > 0.0f) { - vmin[q] = -maxbox[q]; - vmax[q] = maxbox[q]; - } else { - vmin[q] = maxbox[q]; - vmax[q] = -maxbox[q]; - } - } - if (normal.dot(vmin) + d > 0.0f) - return false; - if (normal.dot(vmax) + d >= 0.0f) - return true; - - return false; -} - -/*======================== X-tests ========================*/ -#define AXISTEST_X01(a, b, fa, fb) \ - p0 = a * v0.y - b * v0.z; \ - p2 = a * v2.y - b * v2.z; \ - if (p0 < p2) { \ - min = p0; \ - max = p2; \ - } else { \ - min = p2; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -#define AXISTEST_X2(a, b, fa, fb) \ - p0 = a * v0.y - b * v0.z; \ - p1 = a * v1.y - b * v1.z; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -/*======================== Y-tests ========================*/ -#define AXISTEST_Y02(a, b, fa, fb) \ - p0 = -a * v0.x + b * v0.z; \ - p2 = -a * v2.x + b * v2.z; \ - if (p0 < p2) { \ - min = p0; \ - max = p2; \ - } else { \ - min = p2; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -#define AXISTEST_Y1(a, b, fa, fb) \ - p0 = -a * v0.x + b * v0.z; \ - p1 = -a * v1.x + b * v1.z; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -/*======================== Z-tests ========================*/ - -#define AXISTEST_Z12(a, b, fa, fb) \ - p1 = a * v1.x - b * v1.y; \ - p2 = a * v2.x - b * v2.y; \ - if (p2 < p1) { \ - min = p2; \ - max = p1; \ - } else { \ - min = p1; \ - max = p2; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ - if (min > rad || max < -rad) \ - return false; - -#define AXISTEST_Z0(a, b, fa, fb) \ - p0 = a * v0.x - b * v0.y; \ - p1 = a * v1.x - b * v1.y; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ - if (min > rad || max < -rad) \ - return false; - -static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) { - - /* use separating axis theorem to test overlap between triangle and box */ - /* need to test for overlap in these directions: */ - /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ - /* we do not even need to test these) */ - /* 2) normal of the triangle */ - /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ - /* this gives 3x3=9 more tests */ - Vector3 v0, v1, v2; - float min, max, d, p0, p1, p2, rad, fex, fey, fez; - Vector3 normal, e0, e1, e2; - - /* This is the fastest branch on Sun */ - /* move everything so that the boxcenter is in (0,0,0) */ - - v0 = triverts[0] - boxcenter; - v1 = triverts[1] - boxcenter; - v2 = triverts[2] - boxcenter; - - /* compute triangle edges */ - e0 = v1 - v0; /* tri edge 0 */ - e1 = v2 - v1; /* tri edge 1 */ - e2 = v0 - v2; /* tri edge 2 */ - - /* Bullet 3: */ - /* test the 9 tests first (this was faster) */ - fex = Math::abs(e0.x); - fey = Math::abs(e0.y); - fez = Math::abs(e0.z); - AXISTEST_X01(e0.z, e0.y, fez, fey); - AXISTEST_Y02(e0.z, e0.x, fez, fex); - AXISTEST_Z12(e0.y, e0.x, fey, fex); - - fex = Math::abs(e1.x); - fey = Math::abs(e1.y); - fez = Math::abs(e1.z); - AXISTEST_X01(e1.z, e1.y, fez, fey); - AXISTEST_Y02(e1.z, e1.x, fez, fex); - AXISTEST_Z0(e1.y, e1.x, fey, fex); - - fex = Math::abs(e2.x); - fey = Math::abs(e2.y); - fez = Math::abs(e2.z); - AXISTEST_X2(e2.z, e2.y, fez, fey); - AXISTEST_Y1(e2.z, e2.x, fez, fex); - AXISTEST_Z12(e2.y, e2.x, fey, fex); - - /* Bullet 1: */ - /* first test overlap in the {x,y,z}-directions */ - /* find min, max of the triangle each direction, and test for overlap in */ - /* that direction -- this is equivalent to testing a minimal AABB around */ - /* the triangle against the AABB */ - - /* test in X-direction */ - FINDMINMAX(v0.x, v1.x, v2.x, min, max); - if (min > boxhalfsize.x || max < -boxhalfsize.x) - return false; - - /* test in Y-direction */ - FINDMINMAX(v0.y, v1.y, v2.y, min, max); - if (min > boxhalfsize.y || max < -boxhalfsize.y) - return false; - - /* test in Z-direction */ - FINDMINMAX(v0.z, v1.z, v2.z, min, max); - if (min > boxhalfsize.z || max < -boxhalfsize.z) - return false; - - /* Bullet 2: */ - /* test if the box intersects the plane of the triangle */ - /* compute plane equation of triangle: normal*x+d=0 */ - normal = e0.cross(e1); - d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ - return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */ -} - static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) { if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) { @@ -324,7 +129,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector3 half = (to - from) * 0.5; //is in this cell? - if (!fast_tri_box_overlap(from + half, half, p_vtx)) { + if (!Geometry::triangle_box_overlap(from + half, half, p_vtx)) { continue; //face does not span this cell } @@ -467,7 +272,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test - if (!fast_tri_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) { + if (!Geometry::triangle_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) { //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) { //does not fit in child, go on continue; @@ -648,7 +453,7 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref &p_mesh, const Vec } //test against original bounds - if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) + if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) continue; //plot _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds); @@ -681,7 +486,7 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref &p_mesh, const Vec } //test against original bounds - if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) + if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) continue; //plot face _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index dc3ef5b508..684df728b8 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -193,6 +193,7 @@ #include "scene/3d/gpu_particles_3d.h" #include "scene/3d/immediate_geometry_3d.h" #include "scene/3d/light_3d.h" +#include "scene/3d/lightmap_probe.h" #include "scene/3d/listener_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/multimesh_instance_3d.h" @@ -225,8 +226,8 @@ static Ref resource_loader_text; static Ref resource_loader_dynamic_font; -static Ref resource_loader_stream_texture; -static Ref resource_loader_texture_layered; +static Ref resource_loader_stream_texture; +static Ref resource_loader_texture_layered; static Ref resource_loader_bmfont; @@ -432,8 +433,9 @@ void register_scene_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - //ClassDB::register_class(); - //ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -675,7 +677,7 @@ void register_scene_types() { ClassDB::register_virtual_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -689,6 +691,11 @@ void register_scene_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); @@ -867,6 +874,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("VisualShaderNodeScalarOp", "VisualShaderNodeFloatOp"); ClassDB::add_compatibility_class("VisualShaderNodeScalarUniform", "VisualShaderNodeFloatUniform"); ClassDB::add_compatibility_class("World", "World3D"); + ClassDB::add_compatibility_class("StreamTexture", "StreamTexture2D"); #endif diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 401b689145..6548c65cd7 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -472,11 +472,11 @@ Ref Mesh::create_outline(float p_margin) const { return newmesh; } -void Mesh::set_lightmap_size_hint(const Vector2 &p_size) { +void Mesh::set_lightmap_size_hint(const Size2i &p_size) { lightmap_size_hint = p_size; } -Size2 Mesh::get_lightmap_size_hint() const { +Size2i Mesh::get_lightmap_size_hint() const { return lightmap_size_hint; } @@ -486,7 +486,7 @@ void Mesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_aabb"), &Mesh::get_aabb); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count); ClassDB::bind_method(D_METHOD("surface_get_arrays", "surf_idx"), &Mesh::surface_get_arrays); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index a65cf0a928..80cd57846b 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -43,7 +43,7 @@ class Mesh : public Resource { mutable Ref triangle_mesh; //cached mutable Vector debug_lines; - Size2 lightmap_size_hint; + Size2i lightmap_size_hint; protected: static void _bind_methods(); @@ -138,8 +138,8 @@ public: virtual AABB get_aabb() const = 0; - void set_lightmap_size_hint(const Vector2 &p_size); - Size2 get_lightmap_size_hint() const; + void set_lightmap_size_hint(const Size2i &p_size); + Size2i get_lightmap_size_hint() const; void clear_cache() const; typedef Vector> (*ConvexDecompositionFunc)(const Vector &); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 91c40d871d..6e155ddf91 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -355,7 +355,7 @@ ImageTexture::~ImageTexture() { ////////////////////////////////////////// -Ref StreamTexture::load_image_from_file(FileAccess *f, int p_size_limit) { +Ref StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit) { uint32_t data_format = f->get_32(); uint32_t w = f->get_16(); @@ -492,7 +492,7 @@ Ref StreamTexture::load_image_from_file(FileAccess *f, int p_size_limit) return Ref(); } -void StreamTexture::set_path(const String &p_path, bool p_take_over) { +void StreamTexture2D::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); @@ -501,40 +501,40 @@ void StreamTexture::set_path(const String &p_path, bool p_take_over) { Resource::set_path(p_path, p_take_over); } -void StreamTexture::_requested_3d(void *p_ud) { +void StreamTexture2D::_requested_3d(void *p_ud) { - StreamTexture *st = (StreamTexture *)p_ud; - Ref stex(st); + StreamTexture2D *st = (StreamTexture2D *)p_ud; + Ref stex(st); ERR_FAIL_COND(!request_3d_callback); request_3d_callback(stex); } -void StreamTexture::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) { +void StreamTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) { - StreamTexture *st = (StreamTexture *)p_ud; - Ref stex(st); + StreamTexture2D *st = (StreamTexture2D *)p_ud; + Ref stex(st); ERR_FAIL_COND(!request_roughness_callback); request_roughness_callback(stex, p_normal_path, p_roughness_channel); } -void StreamTexture::_requested_normal(void *p_ud) { +void StreamTexture2D::_requested_normal(void *p_ud) { - StreamTexture *st = (StreamTexture *)p_ud; - Ref stex(st); + StreamTexture2D *st = (StreamTexture2D *)p_ud; + Ref stex(st); ERR_FAIL_COND(!request_normal_callback); request_normal_callback(stex); } -StreamTexture::TextureFormatRequestCallback StreamTexture::request_3d_callback = nullptr; -StreamTexture::TextureFormatRoughnessRequestCallback StreamTexture::request_roughness_callback = nullptr; -StreamTexture::TextureFormatRequestCallback StreamTexture::request_normal_callback = nullptr; +StreamTexture2D::TextureFormatRequestCallback StreamTexture2D::request_3d_callback = nullptr; +StreamTexture2D::TextureFormatRoughnessRequestCallback StreamTexture2D::request_roughness_callback = nullptr; +StreamTexture2D::TextureFormatRequestCallback StreamTexture2D::request_normal_callback = nullptr; -Image::Format StreamTexture::get_format() const { +Image::Format StreamTexture2D::get_format() const { return format; } -Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) { +Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) { alpha_cache.unref(); @@ -595,7 +595,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_ return OK; } -Error StreamTexture::load(const String &p_path) { +Error StreamTexture2D::load(const String &p_path) { int lw, lh, lwc, lhc; Ref image; @@ -661,20 +661,20 @@ Error StreamTexture::load(const String &p_path) { emit_changed(); return OK; } -String StreamTexture::get_load_path() const { +String StreamTexture2D::get_load_path() const { return path_to_file; } -int StreamTexture::get_width() const { +int StreamTexture2D::get_width() const { return w; } -int StreamTexture::get_height() const { +int StreamTexture2D::get_height() const { return h; } -RID StreamTexture::get_rid() const { +RID StreamTexture2D::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_2d_placeholder_create(); @@ -682,7 +682,7 @@ RID StreamTexture::get_rid() const { return texture; } -void StreamTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void StreamTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if ((w | h) == 0) return; @@ -690,7 +690,7 @@ void StreamTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_ RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void StreamTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if ((w | h) == 0) return; @@ -698,7 +698,7 @@ void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_til RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void StreamTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { if ((w | h) == 0) return; @@ -707,12 +707,12 @@ void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, con RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); } -bool StreamTexture::has_alpha() const { +bool StreamTexture2D::has_alpha() const { return false; } -Ref StreamTexture::get_data() const { +Ref StreamTexture2D::get_data() const { if (texture.is_valid()) { return RS::get_singleton()->texture_2d_get(texture); @@ -721,7 +721,7 @@ Ref StreamTexture::get_data() const { } } -bool StreamTexture::is_pixel_opaque(int p_x, int p_y) const { +bool StreamTexture2D::is_pixel_opaque(int p_x, int p_y) const { if (!alpha_cache.is_valid()) { Ref img = get_data(); @@ -757,7 +757,7 @@ bool StreamTexture::is_pixel_opaque(int p_x, int p_y) const { return true; } -void StreamTexture::reload_from_file() { +void StreamTexture2D::reload_from_file() { String path = get_path(); if (!path.is_resource_file()) @@ -771,34 +771,34 @@ void StreamTexture::reload_from_file() { load(path); } -void StreamTexture::_validate_property(PropertyInfo &property) const { +void StreamTexture2D::_validate_property(PropertyInfo &property) const { } -void StreamTexture::_bind_methods() { +void StreamTexture2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture::load); - ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture::get_load_path); + ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture2D::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture2D::get_load_path); ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); } -StreamTexture::StreamTexture() { +StreamTexture2D::StreamTexture2D() { format = Image::FORMAT_MAX; w = 0; h = 0; } -StreamTexture::~StreamTexture() { +StreamTexture2D::~StreamTexture2D() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } } -RES ResourceFormatLoaderStreamTexture::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoaderStreamTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { - Ref st; + Ref st; st.instance(); Error err = st->load(p_path); if (r_error) @@ -809,17 +809,17 @@ RES ResourceFormatLoaderStreamTexture::load(const String &p_path, const String & return st; } -void ResourceFormatLoaderStreamTexture::get_recognized_extensions(List *p_extensions) const { +void ResourceFormatLoaderStreamTexture2D::get_recognized_extensions(List *p_extensions) const { p_extensions->push_back("stex"); } -bool ResourceFormatLoaderStreamTexture::handles_type(const String &p_type) const { - return p_type == "StreamTexture"; +bool ResourceFormatLoaderStreamTexture2D::handles_type(const String &p_type) const { + return p_type == "StreamTexture2D"; } -String ResourceFormatLoaderStreamTexture::get_resource_type(const String &p_path) const { +String ResourceFormatLoaderStreamTexture2D::get_resource_type(const String &p_path) const { if (p_path.get_extension().to_lower() == "stex") - return "StreamTexture"; + return "StreamTexture2D"; return ""; } @@ -1930,23 +1930,47 @@ AnimatedTexture::~AnimatedTexture() { } /////////////////////////////// -Image::Format TextureLayered::get_format() const { +void TextureLayered::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_format"), &TextureLayered::get_format); + ClassDB::bind_method(D_METHOD("get_layered_type"), &TextureLayered::get_layered_type); + ClassDB::bind_method(D_METHOD("get_width"), &TextureLayered::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &TextureLayered::get_height); + ClassDB::bind_method(D_METHOD("get_layers"), &TextureLayered::get_layers); + ClassDB::bind_method(D_METHOD("has_mipmaps"), &TextureLayered::has_mipmaps); + ClassDB::bind_method(D_METHOD("get_layer_data"), &TextureLayered::get_layer_data); + + BIND_ENUM_CONSTANT(LAYERED_TYPE_2D_ARRAY); + BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP); + BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP_ARRAY); +} + +/////////////////////////////// +Image::Format ImageTextureLayered::get_format() const { return format; } -uint32_t TextureLayered::get_width() const { +int ImageTextureLayered::get_width() const { return width; } -uint32_t TextureLayered::get_height() const { +int ImageTextureLayered::get_height() const { return height; } -uint32_t TextureLayered::get_layers() const { +int ImageTextureLayered::get_layers() const { return layers; } -Error TextureLayered::_create_from_images(const Array &p_images) { +bool ImageTextureLayered::has_mipmaps() const { + return mipmaps; +} + +ImageTextureLayered::LayeredType ImageTextureLayered::get_layered_type() const { + return layered_type; +} + +Error ImageTextureLayered::_create_from_images(const Array &p_images) { Vector> images; for (int i = 0; i < p_images.size(); i++) { Ref img = p_images[i]; @@ -1957,7 +1981,7 @@ Error TextureLayered::_create_from_images(const Array &p_images) { return create_from_images(images); } -Array TextureLayered::_get_images() const { +Array ImageTextureLayered::_get_images() const { Array images; for (int i = 0; i < layers; i++) { images.push_back(get_layer_data(i)); @@ -1965,14 +1989,14 @@ Array TextureLayered::_get_images() const { return images; } -Error TextureLayered::create_from_images(Vector> p_images) { +Error ImageTextureLayered::create_from_images(Vector> p_images) { int new_layers = p_images.size(); ERR_FAIL_COND_V(new_layers == 0, ERR_INVALID_PARAMETER); - if (layered_type == RS::TEXTURE_LAYERED_CUBEMAP) { + if (layered_type == LAYERED_TYPE_CUBEMAP) { ERR_FAIL_COND_V_MSG(new_layers != 6, ERR_INVALID_PARAMETER, "Cubemaps require exactly 6 layers"); - } else if (layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY) { + } else if (layered_type == LAYERED_TYPE_CUBEMAP_ARRAY) { ERR_FAIL_COND_V_MSG((new_layers % 6) != 0, ERR_INVALID_PARAMETER, "Cubemap array layers must be a multiple of 6"); } @@ -1994,11 +2018,11 @@ Error TextureLayered::create_from_images(Vector> p_images) { } if (texture.is_valid()) { - RID new_texture = RS::get_singleton()->texture_2d_layered_create(p_images, layered_type); + RID new_texture = RS::get_singleton()->texture_2d_layered_create(p_images, RS::TextureLayeredType(layered_type)); ERR_FAIL_COND_V(!new_texture.is_valid(), ERR_CANT_CREATE); RS::get_singleton()->texture_replace(texture, new_texture); } else { - texture = RS::get_singleton()->texture_2d_layered_create(p_images, layered_type); + texture = RS::get_singleton()->texture_2d_layered_create(p_images, RS::TextureLayeredType(layered_type)); ERR_FAIL_COND_V(!texture.is_valid(), ERR_CANT_CREATE); } @@ -2010,7 +2034,7 @@ Error TextureLayered::create_from_images(Vector> p_images) { return OK; } -void TextureLayered::update_layer(const Ref &p_image, int p_layer) { +void ImageTextureLayered::update_layer(const Ref &p_image, int p_layer) { ERR_FAIL_COND(texture.is_valid()); ERR_FAIL_COND(p_image.is_null()); ERR_FAIL_COND(p_image->get_format() != format); @@ -2020,19 +2044,19 @@ void TextureLayered::update_layer(const Ref &p_image, int p_layer) { RS::get_singleton()->texture_2d_update(texture, p_image, p_layer); } -Ref TextureLayered::get_layer_data(int p_layer) const { +Ref ImageTextureLayered::get_layer_data(int p_layer) const { ERR_FAIL_INDEX_V(p_layer, layers, Ref()); return RS::get_singleton()->texture_2d_layer_get(texture, p_layer); } -RID TextureLayered::get_rid() const { +RID ImageTextureLayered::get_rid() const { if (texture.is_null()) { - texture = RS::get_singleton()->texture_2d_layered_placeholder_create(); + texture = RS::get_singleton()->texture_2d_layered_placeholder_create(RS::TextureLayeredType(layered_type)); } return texture; } -void TextureLayered::set_path(const String &p_path, bool p_take_over) { +void ImageTextureLayered::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { RS::get_singleton()->texture_set_path(texture, p_path); } @@ -2040,24 +2064,17 @@ void TextureLayered::set_path(const String &p_path, bool p_take_over) { Resource::set_path(p_path, p_take_over); } -void TextureLayered::_bind_methods() { +void ImageTextureLayered::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_format"), &TextureLayered::get_format); + ClassDB::bind_method(D_METHOD("create_from_images", "images"), &ImageTextureLayered::_create_from_images); + ClassDB::bind_method(D_METHOD("update_layer", "image", "layer"), &ImageTextureLayered::update_layer); - ClassDB::bind_method(D_METHOD("get_width"), &TextureLayered::get_width); - ClassDB::bind_method(D_METHOD("get_height"), &TextureLayered::get_height); - ClassDB::bind_method(D_METHOD("get_layers"), &TextureLayered::get_layers); - - ClassDB::bind_method(D_METHOD("create_from_images", "images"), &TextureLayered::_create_from_images); - ClassDB::bind_method(D_METHOD("update_layer", "image", "layer"), &TextureLayered::update_layer); - ClassDB::bind_method(D_METHOD("get_layer_data", "layer"), &TextureLayered::get_layer_data); - - ClassDB::bind_method(D_METHOD("_get_images"), &TextureLayered::_get_images); + ClassDB::bind_method(D_METHOD("_get_images"), &ImageTextureLayered::_get_images); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_INTERNAL), "create_from_images", "_get_images"); } -TextureLayered::TextureLayered(RenderingServer::TextureLayeredType p_layered_type) { +ImageTextureLayered::ImageTextureLayered(LayeredType p_layered_type) { layered_type = p_layered_type; format = Image::FORMAT_MAX; @@ -2066,193 +2083,241 @@ TextureLayered::TextureLayered(RenderingServer::TextureLayeredType p_layered_typ layers = 0; } -TextureLayered::~TextureLayered() { +ImageTextureLayered::~ImageTextureLayered() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } } -RES ResourceFormatLoaderTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +/////////////////////////////////////////// - if (r_error) { - *r_error = ERR_CANT_OPEN; +void StreamTextureLayered::set_path(const String &p_path, bool p_take_over) { + + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_set_path(texture, p_path); } - Ref lt; + Resource::set_path(p_path, p_take_over); +} - if (p_path.ends_with("cube")) { - Ref cube; - cube.instance(); - lt = cube; - } else if (p_path.ends_with("cubearr")) { - Ref cubearr; - cubearr.instance(); - lt = cubearr; - } else if (p_path.ends_with("tex2darr")) { - Ref t2darr; - t2darr.instance(); - lt = t2darr; - } else { - ERR_FAIL_V_MSG(RES(), "Unrecognized layered texture extension."); +Image::Format StreamTextureLayered::get_format() const { + + return format; +} + +Error StreamTextureLayered::_load_data(const String &p_path, Vector> &images, int &mipmap_limit, int p_size_limit) { + + ERR_FAIL_COND_V(images.size() != 0, ERR_INVALID_PARAMETER); + + FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + + uint8_t header[4]; + f->get_buffer(header, 4); + if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L') { + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture layered file is corrupt (Bad header)."); } - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(!f, RES(), "Cannot open file '" + p_path + "'."); + uint32_t version = f->get_32(); - char header[5] = { 0, 0, 0, 0, 0 }; - f->get_buffer((uint8_t *)header, 4); - - if (String(header) != "GDLT") { - f->close(); - memdelete(f); - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - // FIXME: It's bogus that we fail in both branches. Seen while rebasing - // vulkan branch on master branch. - ERR_FAIL_V_MSG(RES(), "Unrecognized layered texture."); - } else { - - f->close(); - memdelete(f); - ERR_FAIL_V_MSG(RES(), "Unrecognized layered texture file format '" + String((const char *)header) + "'."); + if (version > FORMAT_VERSION) { + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); } - int tw = f->get_32(); - int th = f->get_32(); - int td = f->get_32(); - bool use_mipmaps = f->get_32() != 0; //texture flags (deprecated) - Image::Format format = Image::Format(f->get_32()); - uint32_t compression = f->get_32(); // 0 - lossless (PNG), 1 - vram, 2 - uncompressed + uint32_t layer_count = f->get_32(); //layer count + uint32_t type = f->get_32(); //layer count + ERR_FAIL_COND_V(type != layered_type, ERR_INVALID_DATA); + + uint32_t df = f->get_32(); //data format + mipmap_limit = int(f->get_32()); + //reserverd + f->get_32(); + f->get_32(); + f->get_32(); + + if (!(df & FORMAT_BIT_STREAM)) { + p_size_limit = 0; + } + + images.resize(layer_count); + + for (uint32_t i = 0; i < layer_count; i++) { + Ref image = StreamTexture2D::load_image_from_file(f, p_size_limit); + ERR_FAIL_COND_V(image.is_null() || image->empty(), ERR_CANT_OPEN); + images.write[i] = image; + } + + return OK; +} + +Error StreamTextureLayered::load(const String &p_path) { Vector> images; - for (int layer = 0; layer < td; layer++) { - Ref image; - image.instance(); + int mipmap_limit; - if (compression == COMPRESSION_LOSSLESS) { - //look for a PNG file inside + Error err = _load_data(p_path, images, mipmap_limit); + if (err) + return err; - int mipmaps = f->get_32(); - Vector> mipmap_images; - - for (int i = 0; i < mipmaps; i++) { - uint32_t size = f->get_32(); - - Vector pv; - pv.resize(size); - { - uint8_t *w = pv.ptrw(); - f->get_buffer(w, size); - } - - Ref img = Image::lossless_unpacker(pv); - - if (img.is_null() || img->empty() || format != img->get_format()) { - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - f->close(); - memdelete(f); - ERR_FAIL_V(RES()); - } - - mipmap_images.push_back(img); - } - - if (mipmap_images.size() == 1) { - - image = mipmap_images[0]; - - } else { - int total_size = Image::get_image_data_size(tw, th, format, true); - Vector img_data; - img_data.resize(total_size); - - { - uint8_t *w = img_data.ptrw(); - - int ofs = 0; - for (int i = 0; i < mipmap_images.size(); i++) { - - Vector id = mipmap_images[i]->get_data(); - int len = id.size(); - const uint8_t *r = id.ptr(); - copymem(&w[ofs], r, len); - ofs += len; - } - } - - image->create(tw, th, true, format, img_data); - if (image->empty()) { - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - f->close(); - memdelete(f); - ERR_FAIL_V(RES()); - } - } - - } else { - - //look for regular format - - int total_size = Image::get_image_data_size(tw, th, format, use_mipmaps); - - Vector img_data; - img_data.resize(total_size); - - { - uint8_t *w = img_data.ptrw(); - int bytes = f->get_buffer(w, total_size); - if (bytes != total_size) { - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - f->close(); - memdelete(f); - ERR_FAIL_V(RES()); - } - } - - image->create(tw, th, use_mipmaps, format, img_data); - } - - images.push_back(image); - } - - Error err = lt->create_from_images(images); - if (err != OK) { - *r_error = err; - return RES(); + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TextureLayeredType(layered_type)); + RS::get_singleton()->texture_replace(texture, new_texture); } else { - - if (r_error) - *r_error = OK; + texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TextureLayeredType(layered_type)); } - return lt; + w = images[0]->get_width(); + h = images[0]->get_height(); + mipmaps = images[0]->has_mipmaps(); + format = images[0]->get_format(); + layers = images.size(); + + path_to_file = p_path; + + if (get_path() == String()) { + //temporarily set path if no path set for resource, helps find errors + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + + _change_notify(); + emit_changed(); + return OK; +} +String StreamTextureLayered::get_load_path() const { + + return path_to_file; } -void ResourceFormatLoaderTextureLayered::get_recognized_extensions(List *p_extensions) const { +int StreamTextureLayered::get_width() const { - p_extensions->push_back("cube"); - p_extensions->push_back("cubearr"); - p_extensions->push_back("tex2darr"); + return w; } -bool ResourceFormatLoaderTextureLayered::handles_type(const String &p_type) const { - return p_type == "Texture2DArray" || p_type == "Cubemap" || p_type == "CubemapArray"; -} -String ResourceFormatLoaderTextureLayered::get_resource_type(const String &p_path) const { +int StreamTextureLayered::get_height() const { - if (p_path.get_extension().to_lower() == "cube") - return "Cubemap"; - if (p_path.get_extension().to_lower() == "cubearr") - return "CubemapArray"; - if (p_path.get_extension().to_lower() == "tex2darr") - return "Texture2DArray"; + return h; +} +int StreamTextureLayered::get_layers() const { + + return layers; +} +bool StreamTextureLayered::has_mipmaps() const { + return mipmaps; +} + +TextureLayered::LayeredType StreamTextureLayered::get_layered_type() const { + + return layered_type; +} + +RID StreamTextureLayered::get_rid() const { + + if (!texture.is_valid()) { + texture = RS::get_singleton()->texture_2d_layered_placeholder_create(RS::TextureLayeredType(layered_type)); + } + return texture; +} + +Ref StreamTextureLayered::get_layer_data(int p_layer) const { + + if (texture.is_valid()) { + return RS::get_singleton()->texture_2d_layer_get(texture, p_layer); + } else { + return Ref(); + } +} + +void StreamTextureLayered::reload_from_file() { + + String path = get_path(); + if (!path.is_resource_file()) + return; + + path = ResourceLoader::path_remap(path); //remap for translation + path = ResourceLoader::import_remap(path); //remap for import + if (!path.is_resource_file()) + return; + + load(path); +} + +void StreamTextureLayered::_validate_property(PropertyInfo &property) const { +} + +void StreamTextureLayered::_bind_methods() { + + ClassDB::bind_method(D_METHOD("load", "path"), &StreamTextureLayered::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTextureLayered::get_load_path); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); +} + +StreamTextureLayered::StreamTextureLayered(LayeredType p_type) { + + layered_type = p_type; + format = Image::FORMAT_MAX; + w = 0; + h = 0; + layers = 0; + mipmaps = false; +} + +StreamTextureLayered::~StreamTextureLayered() { + + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } +} + +///////////////////////////////////////////////// + +RES ResourceFormatLoaderStreamTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + + Ref st; + if (p_path.get_extension().to_lower() == "stexarray") { + Ref s; + s.instance(); + st = s; + } else if (p_path.get_extension().to_lower() == "scube") { + Ref s; + s.instance(); + st = s; + } else if (p_path.get_extension().to_lower() == "scubearray") { + Ref s; + s.instance(); + st = s; + } else { + if (r_error) { + *r_error = ERR_FILE_UNRECOGNIZED; + } + return RES(); + } + Error err = st->load(p_path); + if (r_error) + *r_error = err; + if (err != OK) + return RES(); + + return st; +} + +void ResourceFormatLoaderStreamTextureLayered::get_recognized_extensions(List *p_extensions) const { + + p_extensions->push_back("stexarray"); + p_extensions->push_back("scube"); + p_extensions->push_back("scubearray"); +} +bool ResourceFormatLoaderStreamTextureLayered::handles_type(const String &p_type) const { + return p_type == "StreamTexture2DArray" || p_type == "StreamCubemap" || p_type == "StreamCubemapArray"; +} +String ResourceFormatLoaderStreamTextureLayered::get_resource_type(const String &p_path) const { + + if (p_path.get_extension().to_lower() == "stexarray") + return "StreamTexture2DArray"; + if (p_path.get_extension().to_lower() == "scube") + return "StreamCubemap"; + if (p_path.get_extension().to_lower() == "scubearray") + return "StreamCubemapArray"; return ""; } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 5d5f438eba..5d4131ec4c 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -132,9 +132,9 @@ public: ~ImageTexture(); }; -class StreamTexture : public Texture2D { +class StreamTexture2D : public Texture2D { - GDCLASS(StreamTexture, Texture2D); + GDCLASS(StreamTexture2D, Texture2D); public: enum DataFormat { @@ -181,8 +181,8 @@ protected: public: static Ref load_image_from_file(FileAccess *p_file, int p_size_limit); - typedef void (*TextureFormatRequestCallback)(const Ref &); - typedef void (*TextureFormatRoughnessRequestCallback)(const Ref &, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); + typedef void (*TextureFormatRequestCallback)(const Ref &); + typedef void (*TextureFormatRoughnessRequestCallback)(const Ref &, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); static TextureFormatRequestCallback request_3d_callback; static TextureFormatRoughnessRequestCallback request_roughness_callback; @@ -207,11 +207,11 @@ public: virtual Ref get_data() const; - StreamTexture(); - ~StreamTexture(); + StreamTexture2D(); + ~StreamTexture2D(); }; -class ResourceFormatLoaderStreamTexture : public ResourceFormatLoader { +class ResourceFormatLoaderStreamTexture2D : public ResourceFormatLoader { public: virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List *p_extensions) const; @@ -349,10 +349,34 @@ public: }; class TextureLayered : public Texture { - GDCLASS(TextureLayered, Texture); - RS::TextureLayeredType layered_type; +protected: + static void _bind_methods(); + +public: + enum LayeredType { + LAYERED_TYPE_2D_ARRAY, + LAYERED_TYPE_CUBEMAP, + LAYERED_TYPE_CUBEMAP_ARRAY + }; + + virtual Image::Format get_format() const = 0; + virtual LayeredType get_layered_type() const = 0; + virtual int get_width() const = 0; + virtual int get_height() const = 0; + virtual int get_layers() const = 0; + virtual bool has_mipmaps() const = 0; + virtual Ref get_layer_data(int p_layer) const = 0; +}; + +VARIANT_ENUM_CAST(TextureLayered::LayeredType) + +class ImageTextureLayered : public TextureLayered { + + GDCLASS(ImageTextureLayered, TextureLayered); + + LayeredType layered_type; mutable RID texture; Image::Format format; @@ -370,57 +394,137 @@ protected: static void _bind_methods(); public: - Image::Format get_format() const; - uint32_t get_width() const; - uint32_t get_height() const; - uint32_t get_layers() const; - bool has_mipmaps() const; + virtual Image::Format get_format() const; + virtual int get_width() const; + virtual int get_height() const; + virtual int get_layers() const; + virtual bool has_mipmaps() const; + virtual LayeredType get_layered_type() const; Error create_from_images(Vector> p_images); void update_layer(const Ref &p_image, int p_layer); - Ref get_layer_data(int p_layer) const; + virtual Ref get_layer_data(int p_layer) const; virtual RID get_rid() const; virtual void set_path(const String &p_path, bool p_take_over = false); - TextureLayered(RS::TextureLayeredType p_layered_type); - ~TextureLayered(); + ImageTextureLayered(LayeredType p_layered_type); + ~ImageTextureLayered(); }; -class Texture2DArray : public TextureLayered { +class Texture2DArray : public ImageTextureLayered { - GDCLASS(Texture2DArray, TextureLayered) + GDCLASS(Texture2DArray, ImageTextureLayered) public: Texture2DArray() : - TextureLayered(RS::TEXTURE_LAYERED_2D_ARRAY) {} + ImageTextureLayered(LAYERED_TYPE_2D_ARRAY) {} }; -class Cubemap : public TextureLayered { +class Cubemap : public ImageTextureLayered { - GDCLASS(Cubemap, TextureLayered); + GDCLASS(Cubemap, ImageTextureLayered); public: Cubemap() : - TextureLayered(RS::TEXTURE_LAYERED_CUBEMAP) {} + ImageTextureLayered(LAYERED_TYPE_CUBEMAP) {} }; -class CubemapArray : public TextureLayered { +class CubemapArray : public ImageTextureLayered { - GDCLASS(CubemapArray, TextureLayered); + GDCLASS(CubemapArray, ImageTextureLayered); public: CubemapArray() : - TextureLayered(RS::TEXTURE_LAYERED_CUBEMAP_ARRAY) {} + ImageTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} }; -class ResourceFormatLoaderTextureLayered : public ResourceFormatLoader { +class StreamTextureLayered : public TextureLayered { + + GDCLASS(StreamTextureLayered, TextureLayered); + public: - enum Compression { - COMPRESSION_LOSSLESS, - COMPRESSION_VRAM, - COMPRESSION_UNCOMPRESSED + enum DataFormat { + DATA_FORMAT_IMAGE, + DATA_FORMAT_LOSSLESS, + DATA_FORMAT_LOSSY, + DATA_FORMAT_BASIS_UNIVERSAL, }; + enum { + FORMAT_VERSION = 1 + }; + + enum FormatBits { + FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1, + FORMAT_BIT_LOSSLESS = 1 << 20, + FORMAT_BIT_LOSSY = 1 << 21, + FORMAT_BIT_STREAM = 1 << 22, + FORMAT_BIT_HAS_MIPMAPS = 1 << 23, + }; + +private: + Error _load_data(const String &p_path, Vector> &images, int &mipmap_limit, int p_size_limit = 0); + String path_to_file; + mutable RID texture; + Image::Format format; + int w, h, layers; + bool mipmaps; + LayeredType layered_type; + + virtual void reload_from_file(); + +protected: + static void _bind_methods(); + void _validate_property(PropertyInfo &property) const; + +public: + Image::Format get_format() const; + Error load(const String &p_path); + String get_load_path() const; + virtual LayeredType get_layered_type() const; + + int get_width() const; + int get_height() const; + int get_layers() const; + virtual bool has_mipmaps() const; + virtual RID get_rid() const; + + virtual void set_path(const String &p_path, bool p_take_over); + + virtual Ref get_layer_data(int p_layer) const; + + StreamTextureLayered(LayeredType p_layered_type); + ~StreamTextureLayered(); +}; + +class StreamTexture2DArray : public StreamTextureLayered { + + GDCLASS(StreamTexture2DArray, StreamTextureLayered) +public: + StreamTexture2DArray() : + StreamTextureLayered(LAYERED_TYPE_2D_ARRAY) {} +}; + +class StreamCubemap : public StreamTextureLayered { + + GDCLASS(StreamCubemap, StreamTextureLayered); + +public: + StreamCubemap() : + StreamTextureLayered(LAYERED_TYPE_CUBEMAP) {} +}; + +class StreamCubemapArray : public StreamTextureLayered { + + GDCLASS(StreamCubemapArray, StreamTextureLayered); + +public: + StreamCubemapArray() : + StreamTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} +}; + +class ResourceFormatLoaderStreamTextureLayered : public ResourceFormatLoader { +public: virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String &p_type) const; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 5e3f8b803b..e761354cc9 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -205,4 +205,9 @@ SceneStringNames::SceneStringNames() { shader_overrides_group = StaticCString::create("_shader_overrides_group_"); shader_overrides_group_active = StaticCString::create("_shader_overrides_group_active_"); + +#ifndef DISABLE_DEPRECATED + use_in_baked_light = StaticCString::create("use_in_baked_light"); + use_dynamic_gi = StaticCString::create("use_dynamic_gi"); +#endif } diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index c5de10a6f6..c5c98ba9e5 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -210,6 +210,10 @@ public: StringName shader_overrides_group; StringName shader_overrides_group_active; +#ifndef DISABLE_DEPRECATED + StringName use_in_baked_light; + StringName use_dynamic_gi; +#endif enum { MAX_MATERIALS = 32 }; diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index 099e155553..48ee6e02d0 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -57,6 +57,7 @@ public: virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0; virtual void sky_set_material(RID p_sky, RID p_material) = 0; + virtual Ref sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; /* ENVIRONMENT API */ @@ -94,6 +95,8 @@ public: virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; + virtual Ref environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; + virtual bool is_environment(RID p_env) const = 0; virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0; virtual int environment_get_canvas_max_layer(RID p_env) const = 0; @@ -160,9 +163,11 @@ public: SelfList dependency_item; - InstanceBase *lightmap_capture; - RID lightmap; - Vector lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader + InstanceBase *lightmap; + Rect2 lightmap_uv_scale; + int lightmap_slice_index; + uint32_t lightmap_cull_index; + Vector lightmap_sh; //spherical harmonic AABB aabb; AABB transformed_aabb; @@ -178,8 +183,8 @@ public: bool instance_allocated_shader_parameters = false; int32_t instance_allocated_shader_parameters_offset = -1; - virtual void dependency_deleted(RID p_dependency) = 0; - virtual void dependency_changed(bool p_aabb, bool p_dependencies) = 0; + virtual void dependency_deleted(RID p_dependency) {} + virtual void dependency_changed(bool p_aabb, bool p_dependencies) {} Set dependencies; @@ -233,7 +238,9 @@ public: baked_light = false; dynamic_gi = false; redraw_if_visible = false; - lightmap_capture = nullptr; + lightmap_slice_index = 0; + lightmap = nullptr; + lightmap_cull_index = 0; } virtual ~InstanceBase() { @@ -268,7 +275,7 @@ public: virtual bool gi_probe_needs_update(RID p_probe) const = 0; virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0; - virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; + virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0; virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; @@ -286,6 +293,8 @@ public: virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0; virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0; + virtual TypedArray bake_render_uv2(RID p_base, const Vector &p_material_overrides, const Size2i &p_image_size) = 0; + virtual bool free(RID p_rid) = 0; virtual void update() = 0; @@ -311,7 +320,7 @@ public: //these two APIs can be used together or in combination with the others. virtual RID texture_2d_placeholder_create() = 0; - virtual RID texture_2d_layered_placeholder_create() = 0; + virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) = 0; virtual RID texture_3d_placeholder_create() = 0; virtual Ref texture_2d_get(RID p_texture) const = 0; @@ -593,29 +602,21 @@ public: /* LIGHTMAP CAPTURE */ - struct LightmapCaptureOctree { + virtual RID lightmap_create() = 0; - enum { - CHILD_EMPTY = 0xFFFFFFFF - }; - - uint16_t light[6][3]; //anisotropic light - float alpha; - uint32_t children[8]; - }; - - virtual RID lightmap_capture_create() = 0; - virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0; - virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) = 0; - virtual Vector lightmap_capture_get_octree(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0; - virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0; - virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0; - virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0; - virtual float lightmap_capture_get_energy(RID p_capture) const = 0; - virtual const Vector *lightmap_capture_get_octree_ptr(RID p_capture) const = 0; + virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0; + virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0; + virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0; + virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0; + virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0; + virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0; + virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0; + virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0; + virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0; + virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0; + virtual bool lightmap_is_interior(RID p_lightmap) const = 0; + virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0; + virtual float lightmap_get_probe_capture_update_speed() const = 0; /* PARTICLES */ @@ -1370,6 +1371,8 @@ public: virtual void end_frame(bool p_swap_buffers) = 0; virtual void finalize() = 0; + virtual uint64_t get_frame_number() const = 0; + virtual float get_frame_delta_time() const = 0; virtual bool is_low_end() const = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp index 956bf54d01..3505b18c8a 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp @@ -1539,8 +1539,8 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } } - if (md->last_frame != RasterizerRD::get_frame_number()) { - md->last_frame = RasterizerRD::get_frame_number(); + if (md->last_frame != RasterizerRD::singleton->get_frame_number()) { + md->last_frame = RasterizerRD::singleton->get_frame_number(); if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) { // uniform set may be gone because a dependency was erased. In this case, it will happen // if a texture is deleted, so just re-create it. diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp index d469dd97ca..ed25cc4139 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp @@ -282,6 +282,30 @@ void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_textu RD::get_singleton()->compute_list_end(); } +void RasterizerEffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) { + + zeromem(©.push_constant, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_panorama_size.width; + copy.push_constant.section[3] = p_panorama_size.height; + copy.push_constant.target[0] = 0; + copy.push_constant.target[1] = 0; + copy.push_constant.camera_z_far = p_lod; + + int32_t x_groups = (p_panorama_size.width - 1) / 8 + 1; + int32_t y_groups = (p_panorama_size.height - 1) / 8 + 1; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cube), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_panorama), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_end(); +} + void RasterizerEffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) { zeromem(©.push_constant, sizeof(CopyPushConstant)); @@ -1202,7 +1226,9 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format)); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1); + if (p_uniform_set.is_valid()) { //material may not have uniform set + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1); + } RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_lights, 3); @@ -1226,6 +1252,8 @@ RasterizerEffectsRD::RasterizerEffectsRD() { copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n"); copy_modes.push_back("\n#define MODE_MIPMAP\n"); copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n"); + copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n"); + copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n"); copy.shader.initialize(copy_modes); zeromem(©.push_constant, sizeof(CopyPushConstant)); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h index 531591442b..1b16648ca6 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h @@ -66,6 +66,8 @@ class RasterizerEffectsRD { COPY_MODE_SIMPLY_COPY_DEPTH, COPY_MODE_MIPMAP, COPY_MODE_LINEARIZE_DEPTH, + COPY_MODE_CUBE_TO_PANORAMA, + COPY_MODE_CUBE_ARRAY_TO_PANORAMA, COPY_MODE_MAX, }; @@ -564,6 +566,7 @@ class RasterizerEffectsRD { public: void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false); void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false); + void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp index 4c92912e9c..4267a087b6 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp @@ -79,6 +79,7 @@ void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_scree void RasterizerRD::begin_frame(double frame_step) { frame++; + delta = frame_step; time += frame_step; double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs"); @@ -157,7 +158,7 @@ void RasterizerRD::initialize() { } ThreadWorkPool RasterizerRD::thread_work_pool; -uint32_t RasterizerRD::frame = 1; +uint64_t RasterizerRD::frame = 1; void RasterizerRD::finalize() { @@ -173,7 +174,10 @@ void RasterizerRD::finalize() { RD::get_singleton()->free(copy_viewports_sampler); } +RasterizerRD *RasterizerRD::singleton = nullptr; + RasterizerRD::RasterizerRD() { + singleton = this; thread_work_pool.init(); time = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.h b/servers/rendering/rasterizer_rd/rasterizer_rd.h index 756b9499ca..cb53a531ac 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_rd.h @@ -53,8 +53,9 @@ protected: Map render_target_descriptors; double time; + float delta; - static uint32_t frame; + static uint64_t frame; public: RasterizerStorage *get_storage() { return storage; } @@ -71,7 +72,8 @@ public: void end_frame(bool p_swap_buffers); void finalize(); - static _ALWAYS_INLINE_ uint64_t get_frame_number() { return frame; } + _ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; } + _ALWAYS_INLINE_ float get_frame_delta_time() const { return delta; } static Error is_viable() { return OK; @@ -89,6 +91,7 @@ public: static ThreadWorkPool thread_work_pool; + static RasterizerRD *singleton; RasterizerRD(); ~RasterizerRD() {} }; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index 6986f82065..3f0062b2ae 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -67,18 +67,18 @@ static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) { p_array[11] = 0; } -static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.elements[0][0]; - p_array[1] = p_mtx.basis.elements[1][0]; - p_array[2] = p_mtx.basis.elements[2][0]; +static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) { + p_array[0] = p_mtx.elements[0][0]; + p_array[1] = p_mtx.elements[1][0]; + p_array[2] = p_mtx.elements[2][0]; p_array[3] = 0; - p_array[4] = p_mtx.basis.elements[0][1]; - p_array[5] = p_mtx.basis.elements[1][1]; - p_array[6] = p_mtx.basis.elements[2][1]; + p_array[4] = p_mtx.elements[0][1]; + p_array[5] = p_mtx.elements[1][1]; + p_array[6] = p_mtx.elements[2][1]; p_array[7] = 0; - p_array[8] = p_mtx.basis.elements[0][2]; - p_array[9] = p_mtx.basis.elements[1][2]; - p_array[10] = p_mtx.basis.elements[2][2]; + p_array[8] = p_mtx.elements[0][2]; + p_array[9] = p_mtx.elements[1][2]; + p_array[10] = p_mtx.elements[2][2]; p_array[11] = 0; } @@ -841,6 +841,8 @@ bool RasterizerSceneHighEndRD::free(RID p_rid) { void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth) { + uint32_t lightmap_captures_used = 0; + for (int i = 0; i < p_element_count; i++) { const RenderList::Element *e = p_elements[i]; @@ -898,6 +900,7 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, if (written == 0) { id.gi_offset = index; + id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE; written = 1; } else { id.gi_offset = index << 16; @@ -910,17 +913,53 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, } else if (written == 1) { id.gi_offset |= 0xFFFF0000; } + } else if (e->instance->lightmap) { + + int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base); + if (lightmap_index >= 0) { + id.gi_offset = lightmap_index; + id.gi_offset |= e->instance->lightmap_slice_index << 12; + id.gi_offset |= e->instance->lightmap_cull_index << 20; + id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x; + id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y; + id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width; + id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height; + id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP; + if (storage->lightmap_uses_spherical_harmonics(e->instance->lightmap->base)) { + id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP; + } + } else { + id.gi_offset = 0xFFFFFFFF; + } + } else if (!e->instance->lightmap_sh.empty()) { + if (lightmap_captures_used < scene_state.max_lightmap_captures) { + + const Color *src_capture = e->instance->lightmap_sh.ptr(); + LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used]; + for (int j = 0; j < 9; j++) { + lcd.sh[j * 4 + 0] = src_capture[j].r; + lcd.sh[j * 4 + 1] = src_capture[j].g; + lcd.sh[j * 4 + 2] = src_capture[j].b; + lcd.sh[j * 4 + 3] = src_capture[j].a; + } + id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE; + id.gi_offset = lightmap_captures_used; + lightmap_captures_used++; + } } else { id.gi_offset = 0xFFFFFFFF; } } RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true); + if (lightmap_captures_used) { + RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true); + } } /// RENDERING /// -void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set) { +void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset) { RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; @@ -949,6 +988,8 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l PushConstant push_constant; zeromem(&push_constant, sizeof(PushConstant)); + push_constant.bake_uv2_offset[0] = p_uv_offset.x; + push_constant.bake_uv2_offset[1] = p_uv_offset.y; for (int i = 0; i < p_element_count; i++) { @@ -961,7 +1002,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l //find cull variant ShaderData::CullVariant cull_variant; - if ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { + if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) { cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED; } else { bool mirror = e->instance->mirror; @@ -1080,7 +1121,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l prev_index_array_rd = index_array_rd; } - RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format); + RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_force_wireframe); if (pipeline_rd != prev_pipeline_rd) { // checking with prev shader does not make so much sense, as @@ -1255,6 +1296,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer scene_state.ubo.use_ambient_cubemap = false; scene_state.ubo.use_reflection_cubemap = false; + scene_state.ubo.ssao_enabled = false; } scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active(); @@ -1271,8 +1313,6 @@ void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t if (unlikely(get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_DISABLED)) { if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { m_src = overdraw_material; - } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME) { - m_src = wireframe_material; } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING) { m_src = default_material; } @@ -1374,7 +1414,7 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta e->geometry_index = p_geometry_index; e->material_index = e->material->index; e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH; - e->uses_lightmap = e->instance->lightmap.is_valid(); + e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.empty(); e->uses_vct = e->instance->gi_probe_instances.size(); e->shader_index = e->shader_index; e->depth_layer = e->instance->depth_layer; @@ -1575,6 +1615,26 @@ void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_r } } +void RasterizerSceneHighEndRD::_setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform) { + + uint32_t lightmaps_used = 0; + for (int i = 0; i < p_lightmap_cull_count; i++) { + if (i >= (int)scene_state.max_lightmaps) { + break; + } + + InstanceBase *lm = p_lightmap_cull_result[i]; + Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis; + to_lm = to_lm.inverse().transposed(); //will transform normals + store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); + lm->lightmap_cull_index = i; + lightmaps_used++; + } + if (lightmaps_used > 0) { + RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * lightmaps_used, scene_state.lightmaps, true); + } +} + void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) { int index = 0; @@ -2118,7 +2178,7 @@ void RasterizerSceneHighEndRD::_setup_decals(const RID *p_decal_instances, int p } } -void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) { +void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) { RenderBufferDataHighEnd *render_buffer = nullptr; if (p_render_buffer.is_valid()) { @@ -2238,6 +2298,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor _setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse()); _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment); _setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform); + _setup_lightmaps(p_lightmap_cull_result, p_lightmap_cull_count, p_cam_transform); _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); cluster_builder.bake_cluster(); //bake to cluster @@ -2338,7 +2399,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor bool finish_depth = using_ssao; RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID()); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID(), get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); RD::get_singleton()->draw_list_end(); if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { @@ -2394,7 +2455,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer; RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (using_ssao ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); RD::get_singleton()->draw_list_end(); if (will_continue_color && using_separate_specular) { @@ -2472,7 +2533,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); RD::get_singleton()->draw_list_end(); } @@ -2517,13 +2578,14 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase ** } void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { - RENDER_TIMESTAMP("Setup Rendering Shadow"); + RENDER_TIMESTAMP("Setup Rendering Material"); _update_render_base_uniform_set(); render_pass++; scene_state.ubo.dual_paraboloid_side = 0; + scene_state.ubo.material_uv2_mode = true; _setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); @@ -2554,6 +2616,67 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform } } +void RasterizerSceneHighEndRD::_render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { + RENDER_TIMESTAMP("Setup Rendering UV2"); + + _update_render_base_uniform_set(); + + render_pass++; + + scene_state.ubo.dual_paraboloid_side = 0; + scene_state.ubo.material_uv2_mode = true; + + _setup_environment(RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); + + render_list.clear(); + + PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; + _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); + + _setup_view_dependant_uniform_set(RID(), RID()); + + RENDER_TIMESTAMP("Render Material"); + + render_list.sort_by_key(false); + + _fill_instances(render_list.elements, render_list.element_count, true); + + { + //regular forward for now + Vector clear; + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); + + const int uv_offset_count = 9; + static const Vector2 uv_offsets[uv_offset_count] = { + Vector2(-1, 1), + Vector2(1, 1), + Vector2(1, -1), + Vector2(-1, -1), + Vector2(-1, 0), + Vector2(1, 0), + Vector2(0, -1), + Vector2(0, 1), + Vector2(0, 0), + + }; + + for (int i = 0; i < uv_offset_count; i++) { + Vector2 ofs = uv_offsets[i]; + ofs.x /= p_region.size.width; + ofs.y /= p_region.size.height; + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID(), true, ofs); //first wireframe, for pseudo conservative + } + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID(), false); //second regular triangles + + RD::get_singleton()->draw_list_end(); + } +} + void RasterizerSceneHighEndRD::_base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { @@ -2564,12 +2687,14 @@ void RasterizerSceneHighEndRD::_base_uniforms_changed() { void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { - if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { + if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) { if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } + lightmap_texture_array_version = storage->lightmap_array_get_version(); + Vector uniforms; { @@ -2685,6 +2810,27 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; u.binding = 10; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(scene_state.lightmap_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 11; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids = storage->lightmap_array_get_textures(); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 12; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(scene_state.lightmap_capture_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 13; u.type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture(); u.ids.push_back(decal_atlas); @@ -2692,7 +2838,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { } { RD::Uniform u; - u.binding = 11; + u.binding = 14; u.type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture_srgb(); u.ids.push_back(decal_atlas); @@ -2700,7 +2846,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { } { RD::Uniform u; - u.binding = 12; + u.binding = 15; u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(scene_state.decal_buffer); uniforms.push_back(u); @@ -2708,14 +2854,14 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; - u.binding = 13; + u.binding = 16; u.type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(cluster_builder.get_cluster_texture()); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 14; + u.binding = 17; u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(cluster_builder.get_cluster_indices_buffer()); uniforms.push_back(u); @@ -2723,7 +2869,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; - u.binding = 15; + u.binding = 18; u.type = RD::UNIFORM_TYPE_TEXTURE; if (directional_shadow_get_texture().is_valid()) { u.ids.push_back(directional_shadow_get_texture()); @@ -2736,7 +2882,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 16; + u.binding = 19; u.ids.push_back(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -2951,7 +3097,21 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag scene_state.gi_probe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * scene_state.max_gi_probes); defines += "\n#define MAX_GI_PROBES " + itos(scene_state.max_gi_probes) + "\n"; } + { + //lightmaps + scene_state.max_lightmaps = storage->lightmap_array_get_size(); + defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n"; + defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n"; + scene_state.lightmaps = memnew_arr(LightmapData, scene_state.max_lightmaps); + scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps); + } + { + //captures + scene_state.max_lightmap_captures = 2048; + scene_state.lightmap_captures = memnew_arr(LightmapCaptureData, scene_state.max_lightmap_captures); + scene_state.lightmap_capture_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapCaptureData) * scene_state.max_lightmap_captures); + } { //decals scene_state.max_decals = MIN(1024 * 1024, uniform_max_size) / sizeof(DecalData); //1mb of decals uint32_t decal_buffer_size = scene_state.max_decals * sizeof(DecalData); @@ -2959,6 +3119,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag scene_state.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size); } + { + + defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n"; + } + Vector shader_versions; shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h index a48e2e2259..e8736a0e53 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -193,7 +193,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { struct PushConstant { uint32_t index; - uint32_t pad[3]; + uint32_t pad; + float bake_uv2_offset[2]; }; /* Framebuffer */ @@ -241,6 +242,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { RID render_base_uniform_set; RID view_dependant_uniform_set; + uint64_t lightmap_texture_array_version = 0xFFFFFFFF; + virtual void _base_uniforms_changed(); void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb); virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); @@ -331,6 +334,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { uint32_t pad[1]; }; + struct LightmapData { + float normal_xform[12]; + }; + struct DecalData { float xform[16]; float inv_extents[3]; @@ -349,7 +356,15 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float normal_fade; }; + struct LightmapCaptureData { + float sh[9 * 4]; + }; + enum { + INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, + INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, + INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, + INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11, INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, @@ -366,6 +381,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap) uint32_t mask; + float lightmap_uv_scale[4]; }; struct SceneState { @@ -418,6 +434,9 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { uint32_t roughness_limiter_enabled; float ao_color[4]; + + uint32_t material_uv2_mode; + uint32_t pad_material[3]; }; UBO ubo; @@ -434,6 +453,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { RID gi_probe_buffer; uint32_t max_gi_probe_probes_per_instance; + LightmapData *lightmaps; + uint32_t max_lightmaps; + RID lightmap_buffer; + DecalData *decals; uint32_t max_decals; RID decal_buffer; @@ -446,6 +469,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { uint32_t max_directional_lights; RID directional_light_buffer; + LightmapCaptureData *lightmap_captures; + uint32_t max_lightmap_captures; + RID lightmap_capture_buffer; + RID instance_buffer; InstanceData *instances; uint32_t max_instances; @@ -456,6 +483,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { bool used_sss = false; uint32_t current_shader_index = 0; uint32_t current_material_index = 0; + } scene_state; /* Render List */ @@ -632,18 +660,20 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform); void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment); void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform); + void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform); void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth); - void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set); + void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2()); _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index); _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index); void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi); protected: - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color); + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color); virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake); virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); + virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); public: virtual void set_time(double p_time, double p_step); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index ab669e7647..02221d1536 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -263,7 +263,47 @@ void RasterizerSceneRD::sky_set_material(RID p_sky, RID p_material) { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND(!sky); sky->material = p_material; + _sky_invalidate(sky); } + +Ref RasterizerSceneRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { + + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND_V(!sky, Ref()); + + _update_dirty_skys(); + + if (sky->radiance.is_valid()) { + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + tf.width = p_size.width; + tf.height = p_size.height; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + + RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); + storage->get_effects()->copy_cubemap_to_panorama(sky->radiance, rad_tex, p_size, p_bake_irradiance ? roughness_layers : 0, sky->reflection.layers.size() > 1); + Vector data = RD::get_singleton()->texture_get_data(rad_tex, 0); + RD::get_singleton()->free(rad_tex); + + Ref img; + img.instance(); + img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data); + for (int i = 0; i < p_size.width; i++) { + for (int j = 0; j < p_size.height; j++) { + Color c = img->get_pixel(i, j); + c.r *= p_energy; + c.g *= p_energy; + c.b *= p_energy; + img->set_pixel(i, j, c); + } + } + return img; + } + + return Ref(); +} + void RasterizerSceneRD::_update_dirty_skys() { Sky *sky = dirty_sky_list; @@ -1336,6 +1376,43 @@ bool RasterizerSceneRD::is_environment(RID p_env) const { return environment_owner.owns(p_env); } +Ref RasterizerSceneRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Ref()); + + if (env->background == RS::ENV_BG_CAMERA_FEED || env->background == RS::ENV_BG_CANVAS || env->background == RS::ENV_BG_KEEP) { + return Ref(); //nothing to bake + } + + if (env->background == RS::ENV_BG_CLEAR_COLOR || env->background == RS::ENV_BG_COLOR) { + Color color; + if (env->background == RS::ENV_BG_CLEAR_COLOR) { + color = storage->get_default_clear_color(); + } else { + color = env->bg_color; + } + color.r *= env->bg_energy; + color.g *= env->bg_energy; + color.b *= env->bg_energy; + + Ref ret; + ret.instance(); + ret->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF); + for (int i = 0; i < p_size.width; i++) { + for (int j = 0; j < p_size.height; j++) { + ret->set_pixel(i, j, color); + } + } + return ret; + } + + if (env->background == RS::ENV_BG_SKY && env->sky.is_valid()) { + return sky_bake_panorama(env->sky, env->bg_energy, p_bake_irradiance, p_size); + } + + return Ref(); +} + //////////////////////////////////////////////////////////// RID RasterizerSceneRD::reflection_atlas_create() { @@ -3741,7 +3818,7 @@ RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data( return rb->data; } -void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { +void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { Color clear_color; if (p_render_buffers.is_valid()) { @@ -3752,7 +3829,7 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca clear_color = storage->get_default_clear_color(); } - _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_decal_cull_result, p_decal_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color); + _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_decal_cull_result, p_decal_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color); if (p_render_buffers.is_valid()) { RENDER_TIMESTAMP("Tonemap"); @@ -4079,6 +4156,98 @@ float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const { return screen_space_roughness_limiter_curve; } +TypedArray RasterizerSceneRD::bake_render_uv2(RID p_base, const Vector &p_material_overrides, const Size2i &p_image_size) { + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tf.width = p_image_size.width; // Always 64x64 + tf.height = p_image_size.height; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + + RID albedo_alpha_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RID normal_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RID orm_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + RID emission_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + RID depth_write_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + RID depth_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector fb_tex; + fb_tex.push_back(albedo_alpha_tex); + fb_tex.push_back(normal_tex); + fb_tex.push_back(orm_tex); + fb_tex.push_back(emission_tex); + fb_tex.push_back(depth_write_tex); + fb_tex.push_back(depth_tex); + + RID fb = RD::get_singleton()->framebuffer_create(fb_tex); + + //RID sampled_light; + + InstanceBase ins; + + ins.base_type = RSG::storage->get_base_type(p_base); + ins.base = p_base; + ins.materials.resize(RSG::storage->mesh_get_surface_count(p_base)); + for (int i = 0; i < ins.materials.size(); i++) { + if (i < p_material_overrides.size()) { + ins.materials.write[i] = p_material_overrides[i]; + } + } + + InstanceBase *cull = &ins; + _render_uv2(&cull, 1, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height)); + + TypedArray ret; + + { + PackedByteArray data = RD::get_singleton()->texture_get_data(albedo_alpha_tex, 0); + Ref img; + img.instance(); + img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); + RD::get_singleton()->free(albedo_alpha_tex); + ret.push_back(img); + } + + { + PackedByteArray data = RD::get_singleton()->texture_get_data(normal_tex, 0); + Ref img; + img.instance(); + img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); + RD::get_singleton()->free(normal_tex); + ret.push_back(img); + } + + { + PackedByteArray data = RD::get_singleton()->texture_get_data(orm_tex, 0); + Ref img; + img.instance(); + img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); + RD::get_singleton()->free(orm_tex); + ret.push_back(img); + } + + { + PackedByteArray data = RD::get_singleton()->texture_get_data(emission_tex, 0); + Ref img; + img.instance(); + img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBAH, data); + RD::get_singleton()->free(emission_tex); + ret.push_back(img); + } + + RD::get_singleton()->free(depth_write_tex); + RD::get_singleton()->free(depth_tex); + + return ret; +} + RasterizerSceneRD *RasterizerSceneRD::singleton = nullptr; RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h index a511838e16..5aaa15f441 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -80,9 +80,10 @@ protected: }; virtual RenderBufferData *_create_render_buffer_data() = 0; - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0; + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0; virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0; virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); @@ -843,6 +844,7 @@ public: void sky_set_radiance_size(RID p_sky, int p_radiance_size); void sky_set_mode(RID p_sky, RS::SkyMode p_mode); void sky_set_material(RID p_sky, RID p_material); + Ref sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size); RID sky_get_radiance_texture_rd(RID p_sky) const; RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const; @@ -900,6 +902,8 @@ public: void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {} void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {} + virtual Ref environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size); + virtual RID camera_effects_create(); virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter); @@ -1194,7 +1198,7 @@ public: RID render_buffers_get_ao_texture(RID p_render_buffers); RID render_buffers_get_back_buffer_texture(RID p_render_buffers); - void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count); @@ -1235,6 +1239,8 @@ public: int get_roughness_layers() const; bool is_using_radiance_cubemap_array() const; + virtual TypedArray bake_render_uv2(RID p_base, const Vector &p_material_overrides, const Size2i &p_image_size); + virtual bool free(RID p_rid); virtual void update(); diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index 8d299d623a..0203293a76 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -610,7 +610,113 @@ RID RasterizerStorageRD::texture_2d_create(const Ref &p_image) { RID RasterizerStorageRD::texture_2d_layered_create(const Vector> &p_layers, RS::TextureLayeredType p_layered_type) { - return RID(); + ERR_FAIL_COND_V(p_layers.size() == 0, RID()); + + ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6, RID()); + ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0), RID()); + + TextureToRDFormat ret_format; + Vector> images; + { + int valid_width = 0; + int valid_height = 0; + bool valid_mipmaps = false; + Image::Format valid_format = Image::FORMAT_MAX; + + for (int i = 0; i < p_layers.size(); i++) { + ERR_FAIL_COND_V(p_layers[i]->empty(), RID()); + + if (i == 0) { + valid_width = p_layers[i]->get_width(); + valid_height = p_layers[i]->get_height(); + valid_format = p_layers[i]->get_format(); + valid_mipmaps = p_layers[i]->has_mipmaps(); + } else { + ERR_FAIL_COND_V(p_layers[i]->get_width() != valid_width, RID()); + ERR_FAIL_COND_V(p_layers[i]->get_height() != valid_height, RID()); + ERR_FAIL_COND_V(p_layers[i]->get_format() != valid_format, RID()); + ERR_FAIL_COND_V(p_layers[i]->has_mipmaps() != valid_mipmaps, RID()); + } + + images.push_back(_validate_texture_format(p_layers[i], ret_format)); + } + } + + Texture texture; + + texture.type = Texture::TYPE_LAYERED; + texture.layered_type = p_layered_type; + + texture.width = p_layers[0]->get_width(); + texture.height = p_layers[0]->get_height(); + texture.layers = p_layers.size(); + texture.mipmaps = p_layers[0]->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_layers[0]->get_format(); + texture.validated_format = images[0]->get_format(); + + switch (p_layered_type) { + case RS::TEXTURE_LAYERED_2D_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + } break; + } + + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = texture.layers; + rd_format.mipmaps = texture.mipmaps; + rd_format.type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector> data_slices; + for (int i = 0; i < images.size(); i++) { + Vector data = images[i]->get_data(); //use image data + data_slices.push_back(data); + } + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + return texture_owner.make_rid(texture); } RID RasterizerStorageRD::texture_3d_create(const Vector> &p_slices) { @@ -729,9 +835,31 @@ RID RasterizerStorageRD::texture_2d_placeholder_create() { return texture_2d_create(image); } -RID RasterizerStorageRD::texture_2d_layered_placeholder_create() { +RID RasterizerStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredType p_layered_type) { - return RID(); + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref image; + image.instance(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + image->set_pixel(i, j, Color(1, 0, 1, 1)); + } + } + + Vector> images; + if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { + images.push_back(image); + } else { + //cube + for (int i = 0; i < 6; i++) { + images.push_back(image); + } + } + + return texture_2d_layered_create(images, p_layered_type); } RID RasterizerStorageRD::texture_3d_placeholder_create() { @@ -4139,6 +4267,180 @@ RID RasterizerStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) { return gi_probe->sdf_texture; } +/* LIGHTMAP API */ + +RID RasterizerStorageRD::lightmap_create() { + return lightmap_owner.make_rid(Lightmap()); +} + +void RasterizerStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) { + + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND(!lm); + + lightmap_array_version++; + + //erase lightmap users + if (lm->light_texture.is_valid()) { + Texture *t = texture_owner.getornull(lm->light_texture); + if (t) { + t->lightmap_users.erase(p_lightmap); + } + } + + Texture *t = texture_owner.getornull(p_light); + lm->light_texture = p_light; + lm->uses_spherical_harmonics = p_uses_spherical_haromics; + + RID default_2d_array = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + if (!t) { + + if (using_lightmap_array) { + if (lm->array_index >= 0) { + lightmap_textures.write[lm->array_index] = default_2d_array; + lm->array_index = -1; + } + } + + return; + } + + t->lightmap_users.insert(p_lightmap); + + if (using_lightmap_array) { + if (lm->array_index < 0) { + //not in array, try to put in array + for (int i = 0; i < lightmap_textures.size(); i++) { + if (lightmap_textures[i] == default_2d_array) { + lm->array_index = i; + break; + } + } + } + ERR_FAIL_COND_MSG(lm->array_index < 0, "Maximum amount of lightmaps in use (" + itos(lightmap_textures.size()) + ") has been exceeded, lightmap will nod display properly."); + + lightmap_textures.write[lm->array_index] = t->rd_texture; + } +} + +void RasterizerStorageRD::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) { + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND(!lm); + lm->bounds = p_bounds; +} + +void RasterizerStorageRD::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) { + + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND(!lm); + lm->interior = p_interior; +} + +void RasterizerStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { + + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND(!lm); + + if (p_points.size()) { + ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size()); + ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0); + ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0); + } + + lm->points = p_points; + lm->bsp_tree = p_bsp_tree; + lm->point_sh = p_point_sh; + lm->tetrahedra = p_tetrahedra; +} + +PackedVector3Array RasterizerStorageRD::lightmap_get_probe_capture_points(RID p_lightmap) const { + + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND_V(!lm, PackedVector3Array()); + + return lm->points; +} +PackedColorArray RasterizerStorageRD::lightmap_get_probe_capture_sh(RID p_lightmap) const { + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND_V(!lm, PackedColorArray()); + return lm->point_sh; +} +PackedInt32Array RasterizerStorageRD::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const { + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND_V(!lm, PackedInt32Array()); + return lm->tetrahedra; +} +PackedInt32Array RasterizerStorageRD::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const { + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND_V(!lm, PackedInt32Array()); + return lm->bsp_tree; +} + +void RasterizerStorageRD::lightmap_set_probe_capture_update_speed(float p_speed) { + lightmap_probe_capture_update_speed = p_speed; +} + +void RasterizerStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) { + Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND(!lm); + + for (int i = 0; i < 9; i++) { + r_sh[i] = Color(0, 0, 0, 0); + } + + if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) { + return; + } + + static_assert(sizeof(Lightmap::BSP) == 24); + + const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr(); + int32_t node = 0; + while (node >= 0) { + + if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node); +#endif + + node = bsp[node].over; + } else { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node); +#endif + node = bsp[node].under; + } + } + + if (node == Lightmap::BSP::EMPTY_LEAF) { + return; //nothing could be done + } + + node = ABS(node) - 1; + + uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4]; + Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] }; + const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] }; + Color barycentric = Geometry::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point); + + for (int i = 0; i < 4; i++) { + float c = CLAMP(barycentric[i], 0.0, 1.0); + for (int j = 0; j < 9; j++) { + r_sh[j] += sh_colors[i][j] * c; + } + } +} + +bool RasterizerStorageRD::lightmap_is_interior(RID p_lightmap) const { + const Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND_V(!lm, false); + return lm->interior; +} +AABB RasterizerStorageRD::lightmap_get_aabb(RID p_lightmap) const { + const Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND_V(!lm, AABB()); + return lm->bounds; +} /* RENDER TARGET API */ @@ -4491,6 +4793,9 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In } else if (gi_probe_owner.owns(p_base)) { GIProbe *gip = gi_probe_owner.getornull(p_base); p_instance->update_dependency(&gip->instance_dependency); + } else if (lightmap_owner.owns(p_base)) { + Lightmap *lm = lightmap_owner.getornull(p_base); + p_instance->update_dependency(&lm->instance_dependency); } else if (light_owner.owns(p_base)) { Light *l = light_owner.getornull(p_base); p_instance->update_dependency(&l->instance_dependency); @@ -4525,6 +4830,9 @@ RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const { if (light_owner.owns(p_rid)) { return RS::INSTANCE_LIGHT; } + if (lightmap_owner.owns(p_rid)) { + return RS::INSTANCE_LIGHTMAP; + } return RS::INSTANCE_NONE; } @@ -4678,7 +4986,7 @@ void RasterizerStorageRD::_update_decal_atlas() { DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture); t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2); t->uv_rect.size = items[i].pixel_size; - //print_line("blitrect: " + t->uv_rect); + t->uv_rect.position /= Size2(decal_atlas.size); t->uv_rect.size /= Size2(decal_atlas.size); } @@ -5563,6 +5871,11 @@ bool RasterizerStorageRD::free(RID p_rid) { GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); gi_probe->instance_dependency.instance_notify_deleted(p_rid); gi_probe_owner.free(p_rid); + } else if (lightmap_owner.owns(p_rid)) { + lightmap_set_textures(p_rid, RID(), false); + Lightmap *lightmap = lightmap_owner.getornull(p_rid); + lightmap->instance_dependency.instance_notify_deleted(p_rid); + lightmap_owner.free(p_rid); } else if (light_owner.owns(p_rid)) { @@ -5801,6 +6114,32 @@ RasterizerStorageRD::RasterizerStorageRD() { } } + { //create default array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 1; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_2D_ARRAY; + + Vector pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + //default samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { @@ -5872,124 +6211,133 @@ RasterizerStorageRD::RasterizerStorageRD() { //default rd buffers { - //vertex + Vector buffer; { - Vector buffer; + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} + { //normal + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } -{ //normal - Vector buffer; - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} + { //tangent + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } -{ //tangent - Vector buffer; - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} + { //color + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 1.0; + fptr[2] = 1.0; + fptr[3] = 1.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } -{ //color - Vector buffer; - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 1.0; - fptr[2] = 1.0; - fptr[3] = 1.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} + { //tex uv 1 + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + { //tex uv 2 + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } -{ //tex uv 1 - Vector buffer; - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} -{ //tex uv 2 - Vector buffer; - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} + { //bones + buffer.resize(sizeof(uint32_t) * 4); + { + uint8_t *w = buffer.ptrw(); + uint32_t *fptr = (uint32_t *)w; + fptr[0] = 0; + fptr[1] = 0; + fptr[2] = 0; + fptr[3] = 0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } -{ //bones - Vector buffer; - buffer.resize(sizeof(uint32_t) * 4); - { - uint8_t *w = buffer.ptrw(); - uint32_t *fptr = (uint32_t *)w; - fptr[0] = 0; - fptr[1] = 0; - fptr[2] = 0; - fptr[3] = 0; + { //weights + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} -{ //weights - Vector buffer; - buffer.resize(sizeof(float) * 4); { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; + Vector sdf_versions; + sdf_versions.push_back(""); //one only + giprobe_sdf_shader.initialize(sdf_versions); + giprobe_sdf_shader_version = giprobe_sdf_shader.version_create(); + giprobe_sdf_shader.version_set_compute_code(giprobe_sdf_shader_version, "", "", "", Vector()); + giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0); + giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader); } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} -} -{ - Vector sdf_versions; - sdf_versions.push_back(""); //one only - giprobe_sdf_shader.initialize(sdf_versions); - giprobe_sdf_shader_version = giprobe_sdf_shader.version_create(); - giprobe_sdf_shader.version_set_compute_code(giprobe_sdf_shader_version, "", "", "", Vector()); - giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0); - giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader); -} + using_lightmap_array = true; // high end + if (using_lightmap_array) { + + uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + + if (textures_per_stage <= 256) { + lightmap_textures.resize(32); + } else { + lightmap_textures.resize(1024); + } + + for (int i = 0; i < lightmap_textures.size(); i++) { + lightmap_textures.write[i] = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + } + } + + lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed"); } RasterizerStorageRD::~RasterizerStorageRD() { diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h index f874c3baf8..94b373247f 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h @@ -92,6 +92,7 @@ public: DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, DEFAULT_RD_TEXTURE_3D_WHITE, + DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, DEFAULT_RD_TEXTURE_MAX }; @@ -118,6 +119,7 @@ private: }; Type type; + RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; RenderingDevice::TextureType rd_type; RID rd_texture; @@ -147,6 +149,7 @@ private: RID proxy_to; Vector proxies; + Set lightmap_users; RS::TextureDetectCallback detect_3d_callback = nullptr; void *detect_3d_callback_ud = nullptr; @@ -524,6 +527,40 @@ private: mutable RID_Owner gi_probe_owner; + /* REFLECTION PROBE */ + + struct Lightmap { + + RID light_texture; + bool uses_spherical_harmonics = false; + bool interior = false; + AABB bounds = AABB(Vector3(), Vector3(1, 1, 1)); + int32_t array_index = -1; //unassigned + PackedVector3Array points; + PackedColorArray point_sh; + PackedInt32Array tetrahedra; + PackedInt32Array bsp_tree; + + struct BSP { + static const int32_t EMPTY_LEAF = INT32_MIN; + float plane[4]; + int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; + }; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + bool using_lightmap_array; //high end uses this + /* for high end */ + + Vector lightmap_textures; + + uint64_t lightmap_array_version = 0; + + mutable RID_Owner lightmap_owner; + + float lightmap_probe_capture_update_speed = 4; + /* RENDER TARGET */ struct RenderTarget { @@ -653,7 +690,7 @@ public: //these two APIs can be used together or in combination with the others. virtual RID texture_2d_placeholder_create(); - virtual RID texture_2d_layered_placeholder_create(); + virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type); virtual RID texture_3d_placeholder_create(); virtual Ref texture_2d_get(RID p_texture) const; @@ -1270,23 +1307,47 @@ public: /* LIGHTMAP CAPTURE */ - void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {} - AABB lightmap_capture_get_bounds(RID p_capture) const { return AABB(); } - void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) {} - RID lightmap_capture_create() { - return RID(); + virtual RID lightmap_create(); + + virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics); + virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds); + virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior); + virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree); + virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const; + virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const; + virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const; + virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const; + virtual AABB lightmap_get_aabb(RID p_lightmap) const; + virtual bool lightmap_is_interior(RID p_lightmap) const; + virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh); + virtual void lightmap_set_probe_capture_update_speed(float p_speed); + _FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const { + return lightmap_probe_capture_update_speed; } - Vector lightmap_capture_get_octree(RID p_capture) const { - return Vector(); + + _FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const { + ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays + const Lightmap *lm = lightmap_owner.getornull(p_lightmap); + return lm->array_index; } - void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {} - Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const { return Transform(); } - void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {} - int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { return 0; } - void lightmap_capture_set_energy(RID p_capture, float p_energy) {} - float lightmap_capture_get_energy(RID p_capture) const { return 0.0; } - const Vector *lightmap_capture_get_octree_ptr(RID p_capture) const { - return nullptr; + _FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const { + ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays + const Lightmap *lm = lightmap_owner.getornull(p_lightmap); + return lm->uses_spherical_harmonics; + } + _FORCE_INLINE_ uint64_t lightmap_array_get_version() const { + ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays + return lightmap_array_version; + } + + _FORCE_INLINE_ int lightmap_array_get_size() const { + ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays + return lightmap_textures.size(); + } + + _FORCE_INLINE_ const Vector &lightmap_array_get_textures() const { + ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays + return lightmap_textures; } /* PARTICLES */ diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp index 2bfdb7fffe..5838936f35 100644 --- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp +++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp @@ -31,16 +31,20 @@ #include "render_pipeline_vertex_format_cache_rd.h" #include "core/os/memory.h" -RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { +RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe) { RD::PipelineMultisampleState multisample_state_version = multisample_state; multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id); - RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, rasterization_state, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags); + RD::PipelineRasterizationState raster_state_version = rasterization_state; + raster_state_version.wireframe = p_wireframe; + + RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags); ERR_FAIL_COND_V(pipeline.is_null(), RID()); versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1)); versions[version_count].framebuffer_id = p_framebuffer_format_id; versions[version_count].vertex_id = p_vertex_format_id; + versions[version_count].wireframe = p_wireframe; versions[version_count].pipeline = pipeline; version_count++; return pipeline; diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h index ecb1b42b06..a8bfdb5a26 100644 --- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h +++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h @@ -51,13 +51,14 @@ class RenderPipelineVertexFormatCacheRD { struct Version { RD::VertexFormatID vertex_id; RD::FramebufferFormatID framebuffer_id; + bool wireframe; RID pipeline; }; Version *versions; uint32_t version_count; - RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id); + RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe); void _clear(); @@ -65,7 +66,7 @@ public: void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0); void update_shader(RID p_shader); - _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { + _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false) { #ifdef DEBUG_ENABLED ERR_FAIL_COND_V_MSG(shader.is_null(), RID(), "Attempted to use an unused shader variant (shader is null),"); @@ -74,13 +75,13 @@ public: spin_lock.lock(); RID result; for (uint32_t i = 0; i < version_count; i++) { - if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) { + if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe) { result = versions[i].pipeline; spin_lock.unlock(); return result; } } - result = _generate_version(p_vertex_format_id, p_framebuffer_format_id); + result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe); spin_lock.unlock(); return result; } diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp index 25856c92c7..2ef29e97ff 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp @@ -120,8 +120,11 @@ static int _get_datatype_size(SL::DataType p_type) { return 16; case SL::TYPE_SAMPLERCUBE: return 16; + case SL::TYPE_SAMPLERCUBEARRAY: + return 16; case SL::TYPE_STRUCT: return 0; + case SL::TYPE_MAX: { ERR_FAIL_V(0); }; @@ -194,6 +197,8 @@ static int _get_datatype_alignment(SL::DataType p_type) { return 16; case SL::TYPE_SAMPLERCUBE: return 16; + case SL::TYPE_SAMPLERCUBEARRAY: + return 16; case SL::TYPE_STRUCT: return 0; case SL::TYPE_MAX: { diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl index 2d7661f65f..075ee2af22 100644 --- a/servers/rendering/rasterizer_rd/shaders/copy.glsl +++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl @@ -39,7 +39,13 @@ layout(push_constant, binding = 1, std430) uniform Params { } params; +#ifdef MODE_CUBEMAP_ARRAY_TO_PANORAMA +layout(set = 0, binding = 0) uniform samplerCubeArray source_color; +#elif defined(MODE_CUBEMAP_TO_PANORAMA) +layout(set = 0, binding = 0) uniform samplerCube source_color; +#else layout(set = 0, binding = 0) uniform sampler2D source_color; +#endif #ifdef GLOW_USE_AUTO_EXPOSURE layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; @@ -57,7 +63,7 @@ void main() { // Pixel being shaded ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(pos, params.section.zw))) { //too large, do nothing + if (any(greaterThanEqual(pos, params.section.zw))) { //too large, do nothing return; } @@ -217,4 +223,25 @@ void main() { imageStore(dest_buffer, pos + params.target, color); #endif + +#if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA) + + const float PI = 3.14159265359; + vec2 uv = vec2(pos) / vec2(params.section.zw); + uv.y = 1.0 - uv.y; + float phi = uv.x * 2.0 * PI; + float theta = uv.y * PI; + + vec3 normal; + normal.x = sin(phi) * sin(theta) * -1.0; + normal.y = cos(theta); + normal.z = cos(phi) * sin(theta) * -1.0; + +#ifdef MODE_CUBEMAP_TO_PANORAMA + vec4 color = textureLod(source_color, normal, params.camera_z_far); //the biggest the lod the least the acne +#else + vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne +#endif + imageStore(dest_buffer, pos + params.target, color); +#endif } diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl index 4eba5d41d8..90e37b3ec4 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl @@ -22,7 +22,7 @@ layout(location = 3) in vec4 color_attrib; layout(location = 4) in vec2 uv_attrib; -#if defined(UV2_USED) || defined(USE_LIGHTMAP) +#if defined(UV2_USED) || defined(USE_LIGHTMAP) || defined(MODE_RENDER_MATERIAL) layout(location = 5) in vec2 uv2_attrib; #endif @@ -49,7 +49,7 @@ layout(location = 6) out vec3 binormal_interp; #endif #ifdef USE_MATERIAL_UNIFORMS -layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ +layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{ /* clang-format off */ MATERIAL_UNIFORMS /* clang-format on */ @@ -263,6 +263,14 @@ VERTEX_SHADER_CODE } } #endif + +#ifdef MODE_RENDER_MATERIAL + if (scene_data.material_uv2_mode) { + gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0; + gl_Position.z = 0.00001; + gl_Position.w = 1.0; + } +#endif } /* clang-format off */ @@ -315,7 +323,7 @@ layout(location = 8) in float dp_clip; #endif #ifdef USE_MATERIAL_UNIFORMS -layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ +layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{ /* clang-format off */ MATERIAL_UNIFORMS /* clang-format on */ @@ -1917,42 +1925,96 @@ FRAGMENT_SHADER_CODE #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) //gi probes - //lightmap +#ifdef USE_LIGHTMAP + //lightmap + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture + uint index = instances.data[instance_index].gi_offset; + + vec3 wnormal = mat3(scene_data.camera_matrix) * normal; + const float c1 = 0.429043; + const float c2 = 0.511664; + const float c3 = 0.743125; + const float c4 = 0.886227; + const float c5 = 0.247708; + ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) + + c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z + + c4 * lightmap_captures.data[index].sh[0].rgb - + c5 * lightmap_captures.data[index].sh[6].rgb + + 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y + + 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z + + 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z + + 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x + + 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y + + 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z); + + } else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap + bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); + uint ofs = instances.data[instance_index].gi_offset & 0xFFF; + vec3 uvw; + uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy; + uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF); + + if (uses_sh) { + uvw.z *= 4.0; //SH textures use 4 times more data + vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb; + vec3 lm_light_l1n1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb; + vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb; + vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb; + + uint idx = instances.data[instance_index].gi_offset >> 20; + vec3 n = normalize(lightmaps.data[idx].normal_xform * normal); + + ambient_light += lm_light_l0 * 0.282095f; + ambient_light += lm_light_l1n1 * 0.32573 * n.y; + ambient_light += lm_light_l1_0 * 0.32573 * n.z; + ambient_light += lm_light_l1p1 * 0.32573 * n.x; + if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick + vec3 r = reflect(normalize(-vertex), normal); + specular_light += lm_light_l1n1 * 0.32573 * r.y; + specular_light += lm_light_l1_0 * 0.32573 * r.z; + specular_light += lm_light_l1p1 * 0.32573 * r.x; + } + + } else { + + ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb; + } + } +#endif //lightmap capture #ifdef USE_VOXEL_CONE_TRACING - { // process giprobes + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes + uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; - if (index1 != 0xFFFF) { - vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); - //find arbitrary tangent and bitangent, then build a matrix - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); - vec3 tangent = normalize(cross(v0, normal)); - vec3 bitangent = normalize(cross(tangent, normal)); - mat3 normal_mat = mat3(tangent, bitangent, normal); + vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); + //find arbitrary tangent and bitangent, then build a matrix + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, normal)); + vec3 bitangent = normalize(cross(tangent, normal)); + mat3 normal_mat = mat3(tangent, bitangent, normal); - vec4 amb_accum = vec4(0.0); - vec4 spec_accum = vec4(0.0); - gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); + vec4 amb_accum = vec4(0.0); + vec4 spec_accum = vec4(0.0); + gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); - uint index2 = instances.data[instance_index].gi_offset >> 16; + uint index2 = instances.data[instance_index].gi_offset >> 16; - if (index2 != 0xFFFF) { - gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); - } - - if (amb_accum.a > 0.0) { - amb_accum.rgb /= amb_accum.a; - } - - if (spec_accum.a > 0.0) { - spec_accum.rgb /= spec_accum.a; - } - - specular_light = spec_accum.rgb; - ambient_light = amb_accum.rgb; + if (index2 != 0xFFFF) { + gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); } + + if (amb_accum.a > 0.0) { + amb_accum.rgb /= amb_accum.a; + } + + if (spec_accum.a > 0.0) { + spec_accum.rgb /= spec_accum.a; + } + + specular_light = spec_accum.rgb; + ambient_light = amb_accum.rgb; } #endif @@ -2424,7 +2486,6 @@ FRAGMENT_SHADER_CODE ao_light_affect = mix(1.0, ao, ao_light_affect); specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect); diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect); - #else if (scene_data.ssao_enabled) { diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl index ce4fabf9f2..89706b74d6 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl @@ -3,7 +3,8 @@ layout(push_constant, binding = 0, std430) uniform DrawCall { uint instance_index; - uint pad[3]; //16 bits minimum size + uint pad; //16 bits minimum size + vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise } draw_call; @@ -77,6 +78,10 @@ layout(set = 0, binding = 3, std140) uniform SceneData { bool roughness_limiter_enabled; vec4 ao_color; + bool material_uv2_mode; + uint pad_material0; + uint pad_material1; + uint pad_material2; #if 0 vec4 ambient_light_color; @@ -115,11 +120,10 @@ layout(set = 0, binding = 3, std140) uniform SceneData { } scene_data; -#define INSTANCE_FLAGS_FORWARD_MASK 0x7 -#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3 -#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6 -#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9 - +#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) +#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) +#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) +#define INSTANCE_FLAGS_USE_GIPROBE (1 << 11) #define INSTANCE_FLAGS_MULTIMESH (1 << 12) #define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) @@ -135,8 +139,9 @@ struct InstanceData { mat4 normal_transform; uint flags; uint instance_uniforms_ofs; //base offset in global buffer for instance variables - uint gi_offset; //GI information when using lightmapping (VCT or lightmap) + uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) uint layer_mask; + vec4 lightmap_uv_scale; }; layout(set = 0, binding = 4, std430) restrict readonly buffer Instances { @@ -248,12 +253,35 @@ gi_probes; layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES]; +#define LIGHTMAP_FLAG_USE_DIRECTION 1 +#define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2 + +struct Lightmap { + mat3 normal_xform; +}; + +layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps { + Lightmap data[]; +} +lightmaps; + +layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; + +struct LightmapCapture { + vec4 sh[9]; +}; + +layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures { + LightmapCapture data[]; +} +lightmap_captures; + #define CLUSTER_COUNTER_SHIFT 20 #define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1) #define CLUSTER_COUNTER_MASK 0xfff -layout(set = 0, binding = 10) uniform texture2D decal_atlas; -layout(set = 0, binding = 11) uniform texture2D decal_atlas_srgb; +layout(set = 0, binding = 13) uniform texture2D decal_atlas; +layout(set = 0, binding = 14) uniform texture2D decal_atlas_srgb; struct DecalData { mat4 xform; //to decal transform @@ -273,21 +301,21 @@ struct DecalData { float normal_fade; }; -layout(set = 0, binding = 12, std430) restrict readonly buffer Decals { +layout(set = 0, binding = 15, std430) restrict readonly buffer Decals { DecalData data[]; } decals; -layout(set = 0, binding = 13) uniform utexture3D cluster_texture; +layout(set = 0, binding = 16) uniform utexture3D cluster_texture; -layout(set = 0, binding = 14, std430) restrict readonly buffer ClusterData { +layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData { uint indices[]; } cluster_data; -layout(set = 0, binding = 15) uniform texture2D directional_shadow_atlas; +layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas; -layout(set = 0, binding = 16, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData { vec4 data[]; } global_variables; @@ -312,7 +340,7 @@ layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; layout(set = 2, binding = 1) uniform texture2D shadow_atlas; -/* Set 1, Render Buffers */ +/* Set 3, Render Buffers */ layout(set = 3, binding = 0) uniform texture2D depth_buffer; layout(set = 3, binding = 1) uniform texture2D color_buffer; diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl index e3c26c9b72..11a0d85c58 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl @@ -68,7 +68,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing return; } diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl index 1a5dd5ab55..8571d9d6d1 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl +++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl @@ -120,7 +120,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing return; } diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl index cec6c14c76..f2c3230679 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl +++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl @@ -34,7 +34,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing return; } //do not filter, SSR will generate arctifacts if this is done diff --git a/servers/rendering/rasterizer_rd/shaders/ssao.glsl b/servers/rendering/rasterizer_rd/shaders/ssao.glsl index c9d7134610..0175e26b85 100644 --- a/servers/rendering/rasterizer_rd/shaders/ssao.glsl +++ b/servers/rendering/rasterizer_rd/shaders/ssao.glsl @@ -212,7 +212,7 @@ float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in f void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing return; } diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl index e90c788e08..877e5d50fe 100644 --- a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl +++ b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl @@ -49,7 +49,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing return; } diff --git a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl index 41f8fde3ca..4cb486a499 100644 --- a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl +++ b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl @@ -142,7 +142,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing return; } diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index a3bb39cd90..aeac6f2eff 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -147,7 +147,7 @@ Ref RenderingDevice::_shader_compile_from_source(const Ref &p_bytecode) { +RID RenderingDevice::shader_create_from_bytecode(const Ref &p_bytecode) { ERR_FAIL_COND_V(p_bytecode.is_null(), RID()); Vector stage_data; @@ -276,7 +276,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create); ClassDB::bind_method(D_METHOD("shader_compile_from_source", "shader_source", "allow_cache"), &RenderingDevice::_shader_compile_from_source, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("shader_create", "shader_data"), &RenderingDevice::_shader_create); + ClassDB::bind_method(D_METHOD("shader_create", "shader_data"), &RenderingDevice::shader_create_from_bytecode); ClassDB::bind_method(D_METHOD("shader_get_vertex_input_attribute_mask", "shader"), &RenderingDevice::shader_get_vertex_input_attribute_mask); ClassDB::bind_method(D_METHOD("uniform_buffer_create", "size_bytes", "data"), &RenderingDevice::uniform_buffer_create, DEFVAL(Vector())); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index c76fce5b5c..c7d0a1cdd2 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -596,6 +596,7 @@ public: } }; + RID shader_create_from_bytecode(const Ref &p_bytecode); virtual RID shader_create(const Vector &p_stages) = 0; virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader) = 0; @@ -1045,6 +1046,8 @@ public: virtual void submit() = 0; virtual void sync() = 0; + virtual uint64_t get_memory_usage() const = 0; + virtual RenderingDevice *create_local_device() = 0; static RenderingDevice *get_singleton(); @@ -1063,7 +1066,6 @@ protected: RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray &p_src_buffers); Ref _shader_compile_from_source(const Ref &p_source, bool p_allow_cache = true); - RID _shader_create(const Ref &p_bytecode); RID _uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set); diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp index 43121e2cb5..91076a538e 100644 --- a/servers/rendering/rendering_device_binds.cpp +++ b/servers/rendering/rendering_device_binds.cpp @@ -30,7 +30,7 @@ #include "rendering_device_binds.h" -Error RDShaderFile::parse_versions_from_text(const String &p_text, OpenIncludeFunction p_include_func, void *p_include_func_userdata) { +Error RDShaderFile::parse_versions_from_text(const String &p_text, const String p_defines, OpenIncludeFunction p_include_func, void *p_include_func_userdata) { Vector lines = p_text.split("\n"); @@ -56,6 +56,9 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, OpenIncludeFu { String ls = line.strip_edges(); + if (ls.begins_with("#[")) { //workaround for clang format + ls = ls.replace_first("#[", "["); + } if (ls.begins_with("[") && ls.ends_with("]")) { String section = ls.substr(1, ls.length() - 2).strip_edges(); if (section == "versions") { @@ -90,9 +93,17 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, OpenIncludeFu } } + if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") { + line = line.strip_edges(); + if (line.begins_with("//") || line.begins_with("/*")) { + continue; //assuming comment (single line) + } + } + if (reading_versions) { String l = line.strip_edges(); if (l != "") { + int eqpos = l.find("="); if (eqpos == -1) { base_error = "Version syntax is version=\"\"."; @@ -110,7 +121,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, OpenIncludeFu } define = "\n" + define.substr(1, define.length() - 2).c_unescape() + "\n"; //add newline before and after jsut in case - version_texts[version] = define; + version_texts[version] = define + "\n" + p_defines; } } else { if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") { diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index 2a5396a3e8..fe8d554594 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -322,8 +322,31 @@ public: return base_error; } + void print_errors(const String &p_file) { + if (base_error != "") { + ERR_PRINT("Error parsing shader '" + p_file + "':\n\n" + base_error); + } else { + for (Map>::Element *E = versions.front(); E; E = E->next()) { + for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) { + String error = E->get()->get_stage_compile_error(RD::ShaderStage(i)); + if (error != String()) { + static const char *stage_str[RD::SHADER_STAGE_MAX] = { + "vertex", + "fragment", + "tesselation_control", + "tesselation_evaluation", + "compute" + }; + + ERR_PRINT("Error parsing shader '" + p_file + "', version '" + String(E->key()) + "', stage '" + stage_str[i] + "':\n\n" + error); + } + } + } + } + } + typedef String (*OpenIncludeFunction)(const String &, void *userdata); - Error parse_versions_from_text(const String &p_text, OpenIncludeFunction p_include_func = nullptr, void *p_include_func_userdata = nullptr); + Error parse_versions_from_text(const String &p_text, const String p_defines = String(), OpenIncludeFunction p_include_func = nullptr, void *p_include_func_userdata = nullptr); protected: Dictionary _get_versions() const { diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index f7b963a015..5dd146861d 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -108,8 +108,12 @@ public: m_r m_name(m_type1 arg1, m_type2 arg2) { return BINDBASE->m_name(arg1, arg2); } #define BIND2RC(m_r, m_name, m_type1, m_type2) \ m_r m_name(m_type1 arg1, m_type2 arg2) const { return BINDBASE->m_name(arg1, arg2); } +#define BIND3R(m_r, m_name, m_type1, m_type2, m_type3) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { return BINDBASE->m_name(arg1, arg2, arg3); } #define BIND3RC(m_r, m_name, m_type1, m_type2, m_type3) \ m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return BINDBASE->m_name(arg1, arg2, arg3); } +#define BIND4R(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { return BINDBASE->m_name(arg1, arg2, arg3, arg4); } #define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); } @@ -170,7 +174,7 @@ public: //these also go pass-through BIND0R(RID, texture_2d_placeholder_create) - BIND0R(RID, texture_2d_layered_placeholder_create) + BIND1R(RID, texture_2d_layered_placeholder_create, TextureLayeredType) BIND0R(RID, texture_3d_placeholder_create) BIND1RC(Ref, texture_2d_get, RID) @@ -404,23 +408,19 @@ public: BIND2(gi_probe_set_anisotropy_strength, RID, float) BIND1RC(float, gi_probe_get_anisotropy_strength, RID) - /* LIGHTMAP CAPTURE */ + /* LIGHTMAP */ - BIND0R(RID, lightmap_capture_create) + BIND0R(RID, lightmap_create) - BIND2(lightmap_capture_set_bounds, RID, const AABB &) - BIND1RC(AABB, lightmap_capture_get_bounds, RID) - - BIND2(lightmap_capture_set_octree, RID, const Vector &) - BIND1RC(Vector, lightmap_capture_get_octree, RID) - - BIND2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) - BIND1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) - BIND2(lightmap_capture_set_octree_cell_subdiv, RID, int) - BIND1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) - - BIND2(lightmap_capture_set_energy, RID, float) - BIND1RC(float, lightmap_capture_get_energy, RID) + BIND3(lightmap_set_textures, RID, RID, bool) + BIND2(lightmap_set_probe_bounds, RID, const AABB &) + BIND2(lightmap_set_probe_interior, RID, bool) + BIND5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &) + BIND1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID) + BIND1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID) + BIND1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID) + BIND1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID) + BIND1(lightmap_set_probe_capture_update_speed, float) /* PARTICLES */ @@ -532,6 +532,7 @@ public: BIND2(sky_set_radiance_size, RID, int) BIND2(sky_set_mode, RID, SkyMode) BIND2(sky_set_material, RID, RID) + BIND4R(Ref, sky_bake_panorama, RID, float, bool, const Size2i &) BIND0R(RID, environment_create) @@ -565,6 +566,8 @@ public: BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) BIND5(environment_set_fog_height, RID, bool, float, float, float) + BIND3R(Ref, environment_bake_panorama, RID, bool, const Size2i &) + BIND2(screen_space_roughness_limiter_set_active, bool, float) BIND1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality) BIND2(sub_surface_scattering_set_scale, float, float) @@ -605,7 +608,6 @@ public: BIND3(instance_set_blend_shape_weight, RID, int, float) BIND3(instance_set_surface_material, RID, int, RID) BIND2(instance_set_visible, RID, bool) - BIND3(instance_set_use_lightmap, RID, RID, RID) BIND2(instance_set_custom_aabb, RID, AABB) @@ -625,12 +627,15 @@ public: BIND5(instance_geometry_set_draw_range, RID, float, float, float, float) BIND2(instance_geometry_set_as_instance_lod, RID, RID) + BIND4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int) BIND3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &) BIND2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &) BIND2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &) BIND2C(instance_geometry_get_shader_parameter_list, RID, List *) + BIND3R(TypedArray, bake_render_uv2, RID, const Vector &, const Size2i &) + #undef BINDBASE //from now on, calls forwarded to this singleton #define BINDBASE RSG::canvas diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp index 4f338ee2a5..95334ee102 100644 --- a/servers/rendering/rendering_server_scene.cpp +++ b/servers/rendering/rendering_server_scene.cpp @@ -169,19 +169,22 @@ void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instan geom->decal_dirty = true; return E; //this element should make freeing faster - } else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceLightmapCaptureData *lightmap_capture = static_cast(B->base_data); + InstanceLightmapData *lightmap_data = static_cast(B->base_data); InstanceGeometryData *geom = static_cast(A->base_data); - InstanceLightmapCaptureData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->lightmap_captures.push_back(B); + if (A->dynamic_gi) { + InstanceLightmapData::PairInfo pinfo; + pinfo.geometry = A; + pinfo.L = geom->lightmap_captures.push_back(B); + List::Element *E = lightmap_data->geometries.push_back(pinfo); + ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture + return E; //this element should make freeing faster + } else { + return nullptr; + } - List::Element *E = lightmap_capture->geometries.push_back(pinfo); - ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture - - return E; //this element should make freeing faster } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { InstanceGIProbeData *gi_probe = static_cast(B->base_data); @@ -258,16 +261,18 @@ void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Insta decal->geometries.erase(E); geom->decal_dirty = true; - } else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceLightmapCaptureData *lightmap_capture = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); + if (udata) { //only for dynamic geometries + InstanceLightmapData *lightmap_data = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); - List::Element *E = reinterpret_cast::Element *>(udata); + List::Element *E = reinterpret_cast::Element *>(udata); - geom->lightmap_captures.erase(E->get().L); - lightmap_capture->geometries.erase(E); - ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture + geom->lightmap_captures.erase(E->get().L); + lightmap_data->geometries.erase(E); + ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture + } } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { @@ -418,12 +423,12 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) { RSG::scene_render->free(decal->instance); } break; - case RS::INSTANCE_LIGHTMAP_CAPTURE: { + case RS::INSTANCE_LIGHTMAP: { - InstanceLightmapCaptureData *lightmap_capture = static_cast(instance->base_data); + InstanceLightmapData *lightmap_data = static_cast(instance->base_data); //erase dependencies, since no longer a lightmap - while (lightmap_capture->users.front()) { - instance_set_use_lightmap(lightmap_capture->users.front()->get()->self, RID(), RID()); + while (lightmap_data->users.front()) { + instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0); } } break; case RS::INSTANCE_GI_PROBE: { @@ -443,14 +448,6 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) { gi_probe_update_list.remove(&gi_probe->update_element); } - if (instance->lightmap_capture) { - Instance *capture = (Instance *)instance->lightmap_capture; - InstanceLightmapCaptureData *lightmap_capture = static_cast(capture->base_data); - lightmap_capture->users.erase(instance); - instance->lightmap_capture = nullptr; - instance->lightmap = RID(); - } - RSG::scene_render->free(gi_probe->probe_instance); } break; @@ -515,11 +512,11 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) { decal->instance = RSG::scene_render->decal_instance_create(p_base); } break; - case RS::INSTANCE_LIGHTMAP_CAPTURE: { + case RS::INSTANCE_LIGHTMAP: { - InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData); - instance->base_data = lightmap_capture; - //lightmap_capture->instance = RSG::scene_render->lightmap_capture_instance_create(p_base); + InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData); + instance->base_data = lightmap_data; + //lightmap_data->instance = RSG::scene_render->lightmap_data_instance_create(p_base); } break; case RS::INSTANCE_GI_PROBE: { @@ -736,9 +733,9 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible) } } break; - case RS::INSTANCE_LIGHTMAP_CAPTURE: { + case RS::INSTANCE_LIGHTMAP: { if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP_CAPTURE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); + instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); } } break; @@ -756,30 +753,6 @@ inline bool is_geometry_instance(RenderingServer::InstanceType p_type) { return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE; } -void RenderingServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->lightmap_capture) { - InstanceLightmapCaptureData *lightmap_capture = static_cast(((Instance *)instance->lightmap_capture)->base_data); - lightmap_capture->users.erase(instance); - instance->lightmap = RID(); - instance->lightmap_capture = nullptr; - } - - if (p_lightmap_instance.is_valid()) { - Instance *lightmap_instance = instance_owner.getornull(p_lightmap_instance); - ERR_FAIL_COND(!lightmap_instance); - ERR_FAIL_COND(lightmap_instance->base_type != RS::INSTANCE_LIGHTMAP_CAPTURE); - instance->lightmap_capture = lightmap_instance; - - InstanceLightmapCaptureData *lightmap_capture = static_cast(((Instance *)instance->lightmap_capture)->base_data); - lightmap_capture->users.insert(instance); - instance->lightmap = p_lightmap; - } -} - void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { Instance *instance = instance_owner.getornull(p_instance); @@ -968,6 +941,29 @@ void RenderingServerScene::instance_geometry_set_draw_range(RID p_instance, floa void RenderingServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) { } +void RenderingServerScene::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->lightmap) { + InstanceLightmapData *lightmap_data = static_cast(((Instance *)instance->lightmap)->base_data); + lightmap_data->users.erase(instance); + instance->lightmap = nullptr; + } + + Instance *lightmap_instance = instance_owner.getornull(p_lightmap); + + instance->lightmap = lightmap_instance; + instance->lightmap_uv_scale = p_lightmap_uv_scale; + instance->lightmap_slice_index = p_slice_index; + + if (lightmap_instance) { + InstanceLightmapData *lightmap_data = static_cast(lightmap_instance->base_data); + lightmap_data->users.insert(instance); + } +} + void RenderingServerScene::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) { Instance *instance = instance_owner.getornull(p_instance); @@ -1084,16 +1080,29 @@ void RenderingServerScene::_update_instance(Instance *p_instance) { } } - if (!p_instance->lightmap_capture && geom->lightmap_captures.size()) { + if (!p_instance->lightmap && geom->lightmap_captures.size()) { //affected by lightmap captures, must update capture info! _update_instance_lightmap_captures(p_instance); } else { - if (!p_instance->lightmap_capture_data.empty()) { - p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data + if (!p_instance->lightmap_sh.empty()) { + p_instance->lightmap_sh.clear(); //don't need SH + p_instance->lightmap_target_sh.clear(); //don't need SH } } } + if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) { + + //if this moved, update the captured objects + InstanceLightmapData *lightmap_data = static_cast(p_instance->base_data); + //erase dependencies, since no longer a lightmap + + for (List::Element *E = lightmap_data->geometries.front(); E; E = E->next()) { + Instance *geom = E->get().geometry; + _instance_queue_update(geom, true, false); + } + } + p_instance->mirror = p_instance->transform.basis.determinant() < 0.0; AABB new_aabb; @@ -1113,7 +1122,7 @@ void RenderingServerScene::_update_instance(Instance *p_instance) { uint32_t pairable_mask = 0; bool pairable = false; - if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE) { + if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP) { pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0; pairable = true; @@ -1203,9 +1212,9 @@ void RenderingServerScene::_update_instance_aabb(Instance *p_instance) { new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base); } break; - case RenderingServer::INSTANCE_LIGHTMAP_CAPTURE: { + case RenderingServer::INSTANCE_LIGHTMAP: { - new_aabb = RSG::storage->lightmap_capture_get_bounds(p_instance->base); + new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base); } break; default: { @@ -1219,235 +1228,82 @@ void RenderingServerScene::_update_instance_aabb(Instance *p_instance) { p_instance->aabb = new_aabb; } -_FORCE_INLINE_ static void _light_capture_sample_octree(const RasterizerStorage::LightmapCaptureOctree *p_octree, int p_cell_subdiv, const Vector3 &p_pos, const Vector3 &p_dir, float p_level, Vector3 &r_color, float &r_alpha) { +void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) { - static const Vector3 aniso_normal[6] = { - Vector3(-1, 0, 0), - Vector3(1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, 1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, 1) - }; + bool first_set = p_instance->lightmap_sh.size() == 0; + p_instance->lightmap_sh.resize(9); //using SH + p_instance->lightmap_target_sh.resize(9); //using SH + Color *instance_sh = p_instance->lightmap_target_sh.ptrw(); + bool inside = false; + Color accum_sh[9]; + float accum_blend = 0.0; - int size = 1 << (p_cell_subdiv - 1); + InstanceGeometryData *geom = static_cast(p_instance->base_data); + for (List::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { + Instance *lightmap = E->get(); - int clamp_v = size - 1; - //first of all, clamp - Vector3 pos; - pos.x = CLAMP(p_pos.x, 0, clamp_v); - pos.y = CLAMP(p_pos.y, 0, clamp_v); - pos.z = CLAMP(p_pos.z, 0, clamp_v); + bool interior = RSG::storage->lightmap_is_interior(lightmap->base); - float level = (p_cell_subdiv - 1) - p_level; + if (inside && !interior) { + continue; //we are inside, ignore exteriors + } - int target_level; - float level_filter; - if (level <= 0.0) { - level_filter = 0; - target_level = 0; - } else { - target_level = Math::ceil(level); - level_filter = target_level - level; - } + Transform to_bounds = lightmap->transform.affine_inverse(); + Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center - Vector3 color[2][8]; - float alpha[2][8]; - zeromem(alpha, sizeof(float) * 2 * 8); + Vector3 lm_pos = to_bounds.xform(center); - //find cell at given level first + AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base); + if (!bounds.has_point(lm_pos)) { + continue; //not in this lightmap + } - for (int c = 0; c < 2; c++) { + Color sh[9]; + RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh); - int current_level = MAX(0, target_level - c); - int level_cell_size = (1 << (p_cell_subdiv - 1)) >> current_level; - - for (int n = 0; n < 8; n++) { - - int x = int(pos.x); - int y = int(pos.y); - int z = int(pos.z); - - if (n & 1) - x += level_cell_size; - if (n & 2) - y += level_cell_size; - if (n & 4) - z += level_cell_size; - - int ofs_x = 0; - int ofs_y = 0; - int ofs_z = 0; - - x = CLAMP(x, 0, clamp_v); - y = CLAMP(y, 0, clamp_v); - z = CLAMP(z, 0, clamp_v); - - int half = size / 2; - uint32_t cell = 0; - for (int i = 0; i < current_level; i++) { - - const RasterizerStorage::LightmapCaptureOctree *bc = &p_octree[cell]; - - int child = 0; - if (x >= ofs_x + half) { - child |= 1; - ofs_x += half; - } - if (y >= ofs_y + half) { - child |= 2; - ofs_y += half; - } - if (z >= ofs_z + half) { - child |= 4; - ofs_z += half; - } - - cell = bc->children[child]; - if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) - break; - - half >>= 1; + //rotate it + Basis rot = lightmap->transform.basis.orthonormalized(); + for (int i = 0; i < 3; i++) { + float csh[9]; + for (int j = 0; j < 9; j++) { + csh[j] = sh[j][i]; } - - if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) { - alpha[c][n] = 0; - } else { - alpha[c][n] = p_octree[cell].alpha; - - for (int i = 0; i < 6; i++) { - //anisotropic read light - float amount = p_dir.dot(aniso_normal[i]); - if (amount < 0) - amount = 0; - color[c][n].x += p_octree[cell].light[i][0] / 1024.0 * amount; - color[c][n].y += p_octree[cell].light[i][1] / 1024.0 * amount; - color[c][n].z += p_octree[cell].light[i][2] / 1024.0 * amount; - } + rot.rotate_sh(csh); + for (int j = 0; j < 9; j++) { + sh[j][i] = csh[j]; } + } - //print_line("\tlev " + itos(c) + " - " + itos(n) + " alpha: " + rtos(cells[test_cell].alpha) + " col: " + color[c][n]); + Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0); + + float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z)); + //make blend more rounded + blend = Math::lerp(inner_pos.length(), blend, blend); + blend *= blend; + blend = MAX(0.0, 1.0 - blend); + + if (interior && !inside) { + //do not blend, just replace + for (int j = 0; j < 9; j++) { + accum_sh[j] = sh[j] * blend; + } + accum_blend = blend; + inside = true; + } else { + for (int j = 0; j < 9; j++) { + accum_sh[j] += sh[j] * blend; + } + accum_blend += blend; } } - float target_level_size = size >> target_level; - Vector3 pos_fract[2]; + if (accum_blend > 0.0) { + for (int j = 0; j < 9; j++) { - pos_fract[0].x = Math::fmod(pos.x, target_level_size) / target_level_size; - pos_fract[0].y = Math::fmod(pos.y, target_level_size) / target_level_size; - pos_fract[0].z = Math::fmod(pos.z, target_level_size) / target_level_size; - - target_level_size = size >> MAX(0, target_level - 1); - - pos_fract[1].x = Math::fmod(pos.x, target_level_size) / target_level_size; - pos_fract[1].y = Math::fmod(pos.y, target_level_size) / target_level_size; - pos_fract[1].z = Math::fmod(pos.z, target_level_size) / target_level_size; - - float alpha_interp[2]; - Vector3 color_interp[2]; - - for (int i = 0; i < 2; i++) { - - Vector3 color_x00 = color[i][0].lerp(color[i][1], pos_fract[i].x); - Vector3 color_xy0 = color[i][2].lerp(color[i][3], pos_fract[i].x); - Vector3 blend_z0 = color_x00.lerp(color_xy0, pos_fract[i].y); - - Vector3 color_x0z = color[i][4].lerp(color[i][5], pos_fract[i].x); - Vector3 color_xyz = color[i][6].lerp(color[i][7], pos_fract[i].x); - Vector3 blend_z1 = color_x0z.lerp(color_xyz, pos_fract[i].y); - - color_interp[i] = blend_z0.lerp(blend_z1, pos_fract[i].z); - - float alpha_x00 = Math::lerp(alpha[i][0], alpha[i][1], pos_fract[i].x); - float alpha_xy0 = Math::lerp(alpha[i][2], alpha[i][3], pos_fract[i].x); - float alpha_z0 = Math::lerp(alpha_x00, alpha_xy0, pos_fract[i].y); - - float alpha_x0z = Math::lerp(alpha[i][4], alpha[i][5], pos_fract[i].x); - float alpha_xyz = Math::lerp(alpha[i][6], alpha[i][7], pos_fract[i].x); - float alpha_z1 = Math::lerp(alpha_x0z, alpha_xyz, pos_fract[i].y); - - alpha_interp[i] = Math::lerp(alpha_z0, alpha_z1, pos_fract[i].z); - } - - r_color = color_interp[0].lerp(color_interp[1], level_filter); - r_alpha = Math::lerp(alpha_interp[0], alpha_interp[1], level_filter); - - //print_line("pos: " + p_posf + " level " + rtos(p_level) + " down to " + itos(target_level) + "." + rtos(level_filter) + " color " + r_color + " alpha " + rtos(r_alpha)); -} - -_FORCE_INLINE_ static Color _light_capture_voxel_cone_trace(const RasterizerStorage::LightmapCaptureOctree *p_octree, const Vector3 &p_pos, const Vector3 &p_dir, float p_aperture, int p_cell_subdiv) { - - float bias = 0.0; //no need for bias here - float max_distance = (Vector3(1, 1, 1) * (1 << (p_cell_subdiv - 1))).length(); - - float dist = bias; - float alpha = 0.0; - Vector3 color; - - Vector3 scolor; - float salpha; - - while (dist < max_distance && alpha < 0.95) { - float diameter = MAX(1.0, 2.0 * p_aperture * dist); - _light_capture_sample_octree(p_octree, p_cell_subdiv, p_pos + dist * p_dir, p_dir, log2(diameter), scolor, salpha); - float a = (1.0 - alpha); - color += scolor * a; - alpha += a * salpha; - dist += diameter * 0.5; - } - - return Color(color.x, color.y, color.z, alpha); -} - -void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) { - - InstanceGeometryData *geom = static_cast(p_instance->base_data); - - static const Vector3 cone_traces[12] = { - Vector3(0, 0, 1), - Vector3(0.866025, 0, 0.5), - Vector3(0.267617, 0.823639, 0.5), - Vector3(-0.700629, 0.509037, 0.5), - Vector3(-0.700629, -0.509037, 0.5), - Vector3(0.267617, -0.823639, 0.5), - Vector3(0, 0, -1), - Vector3(0.866025, 0, -0.5), - Vector3(0.267617, 0.823639, -0.5), - Vector3(-0.700629, 0.509037, -0.5), - Vector3(-0.700629, -0.509037, -0.5), - Vector3(0.267617, -0.823639, -0.5) - }; - - float cone_aperture = 0.577; // tan(angle) 60 degrees - - if (p_instance->lightmap_capture_data.empty()) { - p_instance->lightmap_capture_data.resize(12); - } - - //print_line("update captures for pos: " + p_instance->transform.origin); - - for (int i = 0; i < 12; i++) - new (&p_instance->lightmap_capture_data.ptrw()[i]) Color; - - //this could use some sort of blending.. - for (List::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { - const Vector *octree = RSG::storage->lightmap_capture_get_octree_ptr(E->get()->base); - //print_line("octree size: " + itos(octree->size())); - if (octree->size() == 0) - continue; - Transform to_cell_xform = RSG::storage->lightmap_capture_get_octree_cell_transform(E->get()->base); - int cell_subdiv = RSG::storage->lightmap_capture_get_octree_cell_subdiv(E->get()->base); - to_cell_xform = to_cell_xform * E->get()->transform.affine_inverse(); - - const RasterizerStorage::LightmapCaptureOctree *octree_r = octree->ptr(); - - Vector3 pos = to_cell_xform.xform(p_instance->transform.origin); - - for (int i = 0; i < 12; i++) { - - Vector3 dir = to_cell_xform.basis.xform(cone_traces[i]).normalized(); - Color capture = _light_capture_voxel_cone_trace(octree_r, pos, dir, cone_aperture, cell_subdiv); - p_instance->lightmap_capture_data.write[i] += capture; + instance_sh[j] = accum_sh[j] / accum_blend; + if (first_set) { + p_instance->lightmap_sh.write[j] = instance_sh[j]; + } } } } @@ -1762,10 +1618,6 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c } else { camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); } - - if (i == 0) { - //print_line("prev he: " + vp_he + " new he: " + camera_matrix_square.get_viewport_half_extents()); - } } Vector3 endpoints_square[8]; // frustum plane endpoints @@ -2147,6 +1999,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const reflection_probe_cull_count = 0; decal_cull_count = 0; gi_probe_cull_count = 0; + lightmap_cull_count = 0; //light_samplers_culled=0; @@ -2161,6 +2014,8 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const //removed, will replace with culling /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */ + uint64_t frame_number = RSG::rasterizer->get_frame_number(); + float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time(); for (int i = 0; i < instance_cull_count; i++) { @@ -2239,6 +2094,12 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance; gi_probe_cull_count++; } + } else if (ins->base_type == RS::INSTANCE_LIGHTMAP && ins->visible) { + + if (lightmap_cull_count < MAX_LIGHTMAPS_CULLED) { + lightmap_cull_result[lightmap_cull_count] = ins; + lightmap_cull_count++; + } } else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { @@ -2307,6 +2168,14 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const geom->gi_probes_dirty = false; } + if (ins->last_frame_pass != frame_number && !ins->lightmap_target_sh.empty() && !ins->lightmap_sh.empty()) { + Color *sh = ins->lightmap_sh.ptrw(); + const Color *target_sh = ins->lightmap_target_sh.ptr(); + for (uint32_t j = 0; j < 9; j++) { + sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed)); + } + } + ins->depth = near_plane.distance_to(ins->transform.origin); ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15); } @@ -2321,6 +2190,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const ins->last_render_pass = render_pass; } + ins->last_frame_pass = frame_number; } /* STEP 5 - PROCESS LIGHTS */ @@ -2494,7 +2364,7 @@ void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p /* PROCESS GEOMETRY AND DRAW SCENE */ RENDER_TIMESTAMP("Render Scene "); - RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); + RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); } void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { @@ -2509,7 +2379,7 @@ void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenar else environment = scenario->fallback_environment; RENDER_TIMESTAMP("Render Empty Scene "); - RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0); + RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0); #endif } @@ -3123,7 +2993,7 @@ bool RenderingServerScene::free(RID p_rid) { Instance *instance = instance_owner.getornull(p_rid); - instance_set_use_lightmap(p_rid, RID(), RID()); + instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0); instance_set_scenario(p_rid, RID()); instance_set_base(p_rid, RID()); instance_geometry_set_material_override(p_rid, RID()); @@ -3144,6 +3014,10 @@ bool RenderingServerScene::free(RID p_rid) { return true; } +TypedArray RenderingServerScene::bake_render_uv2(RID p_base, const Vector &p_material_overrides, const Size2i &p_image_size) { + return RSG::scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size); +} + RenderingServerScene *RenderingServerScene::singleton = nullptr; RenderingServerScene::RenderingServerScene() { diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h index eb66cea3aa..df9e650ac7 100644 --- a/servers/rendering/rendering_server_scene.h +++ b/servers/rendering/rendering_server_scene.h @@ -51,6 +51,7 @@ public: MAX_DECALS_CULLED = 4096, MAX_GI_PROBES_CULLED = 4096, MAX_ROOM_CULL = 32, + MAX_LIGHTMAPS_CULLED = 4096, MAX_EXTERIOR_PORTALS = 128, }; @@ -171,6 +172,8 @@ public: float lod_end_hysteresis; RID lod_instance; + Vector lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior + uint64_t last_render_pass; uint64_t last_frame_pass; @@ -374,7 +377,7 @@ public: SelfList::List gi_probe_update_list; - struct InstanceLightmapCaptureData : public InstanceBaseData { + struct InstanceLightmapData : public InstanceBaseData { struct PairInfo { List::Element *L; //iterator in geometry @@ -384,7 +387,7 @@ public: Set users; - InstanceLightmapCaptureData() { + InstanceLightmapData() { } }; @@ -401,6 +404,8 @@ public: int decal_cull_count; RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED]; int gi_probe_cull_count; + Instance *lightmap_cull_result[MAX_LIGHTS_CULLED]; + int lightmap_cull_count; RID_PtrOwner instance_owner; @@ -414,7 +419,6 @@ public: virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); virtual void instance_set_visible(RID p_instance, bool p_visible); - virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap); virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb); @@ -434,6 +438,7 @@ public: virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin); virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance); + virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index); void _update_instance_shader_parameters_from_material(Map &isparams, const Map &existing_isparams, RID p_material); @@ -460,6 +465,8 @@ public: void render_probes(); + TypedArray bake_render_uv2(RID p_base, const Vector &p_material_overrides, const Size2i &p_image_size); + bool free(RID p_rid); RenderingServerScene(); diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp index 4ca13dbef9..a7a166bec6 100644 --- a/servers/rendering/rendering_server_wrap_mt.cpp +++ b/servers/rendering/rendering_server_wrap_mt.cpp @@ -138,7 +138,7 @@ void RenderingServerWrapMT::finish() { spot_light_free_cached_ids(); reflection_probe_free_cached_ids(); gi_probe_free_cached_ids(); - lightmap_capture_free_cached_ids(); + lightmap_free_cached_ids(); particles_free_cached_ids(); camera_free_cached_ids(); viewport_free_cached_ids(); diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index d4e58485b8..6580b71508 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -92,7 +92,7 @@ public: //these also go pass-through virtual RID texture_2d_placeholder_create() { return rendering_server->texture_2d_placeholder_create(); } - virtual RID texture_2d_layered_placeholder_create() { return rendering_server->texture_2d_layered_placeholder_create(); } + virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_type) { return rendering_server->texture_2d_layered_placeholder_create(p_type); } virtual RID texture_3d_placeholder_create() { return rendering_server->texture_3d_placeholder_create(); } FUNC1RC(Ref, texture_2d_get, RID) @@ -324,19 +324,17 @@ public: /* LIGHTMAP CAPTURE */ - FUNCRID(lightmap_capture) + FUNCRID(lightmap) + FUNC3(lightmap_set_textures, RID, RID, bool) + FUNC2(lightmap_set_probe_bounds, RID, const AABB &) + FUNC2(lightmap_set_probe_interior, RID, bool) + FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &) + FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID) + FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID) + FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID) + FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID) - FUNC2(lightmap_capture_set_bounds, RID, const AABB &) - FUNC1RC(AABB, lightmap_capture_get_bounds, RID) - - FUNC2(lightmap_capture_set_octree, RID, const Vector &) - FUNC1RC(Vector, lightmap_capture_get_octree, RID) - FUNC2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) - FUNC1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) - FUNC2(lightmap_capture_set_octree_cell_subdiv, RID, int) - FUNC1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) - FUNC2(lightmap_capture_set_energy, RID, float) - FUNC1RC(float, lightmap_capture_get_energy, RID) + FUNC1(lightmap_set_probe_capture_update_speed, float) /* PARTICLES */ @@ -442,6 +440,7 @@ public: FUNC2(sky_set_radiance_size, RID, int) FUNC2(sky_set_mode, RID, SkyMode) FUNC2(sky_set_material, RID, RID) + FUNC4R(Ref, sky_bake_panorama, RID, float, bool, const Size2i &) /* ENVIRONMENT API */ @@ -478,6 +477,8 @@ public: FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) FUNC5(environment_set_fog_height, RID, bool, float, float, float) + FUNC3R(Ref, environment_bake_panorama, RID, bool, const Size2i &) + FUNC2(screen_space_roughness_limiter_set_active, bool, float) FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality) FUNC2(sub_surface_scattering_set_scale, float, float) @@ -511,7 +512,6 @@ public: FUNC3(instance_set_blend_shape_weight, RID, int, float) FUNC3(instance_set_surface_material, RID, int, RID) FUNC2(instance_set_visible, RID, bool) - FUNC3(instance_set_use_lightmap, RID, RID, RID) FUNC2(instance_set_custom_aabb, RID, AABB) @@ -531,12 +531,17 @@ public: FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float) FUNC2(instance_geometry_set_as_instance_lod, RID, RID) + FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int) FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &) FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &) FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &) FUNC2SC(instance_geometry_get_shader_parameter_list, RID, List *) + /* BAKE */ + + FUNC3R(TypedArray, bake_render_uv2, RID, const Vector &, const Size2i &) + /* CANVAS (2D) */ FUNCRID(canvas) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 2a5492d93f..e3725043d9 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -132,6 +132,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "TYPE_ISAMPLER3D", "TYPE_USAMPLER3D", "TYPE_SAMPLERCUBE", + "TYPE_SAMPLERCUBEARRAY", "INTERPOLATION_FLAT", "INTERPOLATION_SMOOTH", "CONST", @@ -283,6 +284,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_TYPE_ISAMPLER3D, "isampler3D" }, { TK_TYPE_USAMPLER3D, "usampler3D" }, { TK_TYPE_SAMPLERCUBE, "samplerCube" }, + { TK_TYPE_SAMPLERCUBEARRAY, "samplerCubeArray" }, { TK_INTERPOLATION_FLAT, "flat" }, { TK_INTERPOLATION_SMOOTH, "smooth" }, { TK_CONST, "const" }, @@ -783,7 +785,8 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) { p_type == TK_TYPE_SAMPLER3D || p_type == TK_TYPE_ISAMPLER3D || p_type == TK_TYPE_USAMPLER3D || - p_type == TK_TYPE_SAMPLERCUBE); + p_type == TK_TYPE_SAMPLERCUBE || + p_type == TK_TYPE_SAMPLERCUBEARRAY); } ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { @@ -902,6 +905,8 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { return "usampler3D"; case TYPE_SAMPLERCUBE: return "samplerCube"; + case TYPE_SAMPLERCUBEARRAY: + return "samplerCubeArray"; case TYPE_STRUCT: return "struct"; case TYPE_MAX: @@ -2046,6 +2051,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, @@ -2067,6 +2073,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, @@ -2097,6 +2105,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, @@ -2128,6 +2137,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, @@ -2618,7 +2628,8 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) { p_type == TYPE_SAMPLER3D || p_type == TYPE_ISAMPLER3D || p_type == TYPE_USAMPLER3D || - p_type == TYPE_SAMPLERCUBE; + p_type == TYPE_SAMPLERCUBE || + p_type == TYPE_SAMPLERCUBEARRAY; } Variant ShaderLanguage::constant_value_to_variant(const Vector &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) { @@ -2712,7 +2723,9 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector &p_funct return ERR_PARSE_ERROR; } } else { - if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) { + if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) { _set_error("Uniforms with 'instance' qualifiers can't be of matrix type."); return ERR_PARSE_ERROR; } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 973e1c4937..314e4a5fba 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -79,6 +79,7 @@ public: TK_TYPE_ISAMPLER3D, TK_TYPE_USAMPLER3D, TK_TYPE_SAMPLERCUBE, + TK_TYPE_SAMPLERCUBEARRAY, TK_INTERPOLATION_FLAT, TK_INTERPOLATION_SMOOTH, TK_CONST, @@ -218,6 +219,7 @@ public: TYPE_ISAMPLER3D, TYPE_USAMPLER3D, TYPE_SAMPLERCUBE, + TYPE_SAMPLERCUBEARRAY, TYPE_STRUCT, TYPE_MAX }; @@ -682,6 +684,7 @@ public: texture_order(0), type(TYPE_VOID), precision(PRECISION_DEFAULT), + scope(SCOPE_LOCAL), hint(HINT_NONE), filter(FILTER_DEFAULT), repeat(REPEAT_DEFAULT), diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index e170b66562..3dac846357 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1784,8 +1784,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &RenderingServer::gi_probe_set_compress); ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &RenderingServer::gi_probe_is_compressed); #endif - - ClassDB::bind_method(D_METHOD("lightmap_capture_create"), &RenderingServer::lightmap_capture_create); +/* + ClassDB::bind_method(D_METHOD("lightmap_create()"), &RenderingServer::lightmap_capture_create); ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &RenderingServer::lightmap_capture_set_bounds); ClassDB::bind_method(D_METHOD("lightmap_capture_get_bounds", "capture"), &RenderingServer::lightmap_capture_get_bounds); ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree", "capture", "octree"), &RenderingServer::lightmap_capture_set_octree); @@ -1796,6 +1796,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree", "capture"), &RenderingServer::lightmap_capture_get_octree); ClassDB::bind_method(D_METHOD("lightmap_capture_set_energy", "capture", "energy"), &RenderingServer::lightmap_capture_set_energy); ClassDB::bind_method(D_METHOD("lightmap_capture_get_energy", "capture"), &RenderingServer::lightmap_capture_get_energy); +*/ #endif ClassDB::bind_method(D_METHOD("particles_create"), &RenderingServer::particles_create); ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &RenderingServer::particles_set_emitting); @@ -1895,7 +1896,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight); ClassDB::bind_method(D_METHOD("instance_set_surface_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_material); ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible); - ClassDB::bind_method(D_METHOD("instance_set_use_lightmap", "instance", "lightmap_instance", "lightmap"), &RenderingServer::instance_set_use_lightmap); + // ClassDB::bind_method(D_METHOD("instance_set_use_lightmap", "instance", "lightmap_instance", "lightmap"), &RenderingServer::instance_set_use_lightmap); ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb); ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton); ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior); @@ -2266,7 +2267,7 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE); BIND_ENUM_CONSTANT(INSTANCE_DECAL); BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE); - BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP_CAPTURE); + BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP); BIND_ENUM_CONSTANT(INSTANCE_MAX); BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK); @@ -2513,6 +2514,9 @@ RenderingServer::RenderingServer() { ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001")); GLOBAL_DEF("rendering/high_end/global_shader_variables_buffer_size", 65536); + + GLOBAL_DEF("rendering/lightmapper/probe_capture_update_speed", 15); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/lightmapper/probe_capture_update_speed", PropertyInfo(Variant::FLOAT, "rendering/lightmapper/probe_capture_update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001")); } RenderingServer::~RenderingServer() { diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 8ca070b4a9..d426f205d0 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -36,6 +36,7 @@ #include "core/math/transform_2d.h" #include "core/object.h" #include "core/rid.h" +#include "core/typed_array.h" #include "core/variant.h" #include "servers/display_server.h" #include "servers/rendering/shader_language.h" @@ -106,7 +107,7 @@ public: //these two APIs can be used together or in combination with the others. virtual RID texture_2d_placeholder_create() = 0; - virtual RID texture_2d_layered_placeholder_create() = 0; + virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_layered_type) = 0; virtual RID texture_3d_placeholder_create() = 0; virtual Ref texture_2d_get(RID p_texture) const = 0; @@ -522,19 +523,20 @@ public: virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; - /* LIGHTMAP CAPTURE */ + /* LIGHTMAP */ - virtual RID lightmap_capture_create() = 0; - virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0; - virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) = 0; - virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0; - virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0; - virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0; - virtual Vector lightmap_capture_get_octree(RID p_capture) const = 0; - virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0; - virtual float lightmap_capture_get_energy(RID p_capture) const = 0; + virtual RID lightmap_create() = 0; + + virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0; + virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0; + virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0; + virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0; + virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0; + virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0; + virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0; + virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0; + + virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0; /* PARTICLES API */ @@ -713,6 +715,7 @@ public: virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; virtual void sky_set_mode(RID p_sky, SkyMode p_mode) = 0; virtual void sky_set_material(RID p_sky, RID p_material) = 0; + virtual Ref sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; /* ENVIRONMENT API */ @@ -809,6 +812,8 @@ public: virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; + virtual Ref environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; enum SubSurfaceScatteringQuality { @@ -885,7 +890,7 @@ public: INSTANCE_REFLECTION_PROBE, INSTANCE_DECAL, INSTANCE_GI_PROBE, - INSTANCE_LIGHTMAP_CAPTURE, + INSTANCE_LIGHTMAP, INSTANCE_MAX, INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES) @@ -904,8 +909,6 @@ public: virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0; virtual void instance_set_visible(RID p_instance, bool p_visible) = 0; - virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) = 0; - virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0; virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0; @@ -942,12 +945,24 @@ public: virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0; virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0; + virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice) = 0; virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0; virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0; virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &) const = 0; virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List *p_parameters) const = 0; + /* Bake 3D objects */ + + enum BakeChannels { + BAKE_CHANNEL_ALBEDO_ALPHA, + BAKE_CHANNEL_NORMAL, + BAKE_CHANNEL_ORM, + BAKE_CHANNEL_EMISSION + }; + + virtual TypedArray bake_render_uv2(RID p_base, const Vector &p_material_overrides, const Size2i &p_image_size) = 0; + /* CANVAS (2D) */ virtual RID canvas_create() = 0; @@ -1186,8 +1201,6 @@ public: virtual Vector get_frame_profile() = 0; virtual uint64_t get_frame_profile_frame() = 0; - /* Materials for 2D on 3D */ - /* TESTING */ virtual RID get_test_cube() = 0; diff --git a/thirdparty/oidn/.gitignore b/thirdparty/oidn/.gitignore new file mode 100644 index 0000000000..6be206fc29 --- /dev/null +++ b/thirdparty/oidn/.gitignore @@ -0,0 +1 @@ +weights/rtlightmap_hdr.cpp diff --git a/thirdparty/oidn/common/barrier.h b/thirdparty/oidn/common/barrier.h new file mode 100644 index 0000000000..b20f670053 --- /dev/null +++ b/thirdparty/oidn/common/barrier.h @@ -0,0 +1,52 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "platform.h" +#include +#include + +namespace oidn { + + class Barrier + { + private: + std::mutex m; + std::condition_variable cv; + volatile int count; + + public: + Barrier(int count) : count(count) {} + + void wait() + { + std::unique_lock lk(m); + count--; + + if (count == 0) + { + lk.unlock(); + cv.notify_all(); + } + else + { + cv.wait(lk, [&]{ return count == 0; }); + } + } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/common/exception.h b/thirdparty/oidn/common/exception.h new file mode 100644 index 0000000000..18069c6a7d --- /dev/null +++ b/thirdparty/oidn/common/exception.h @@ -0,0 +1,45 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include +#include "platform.h" + +namespace oidn { + + class Exception : public std::exception + { + private: + Error error; + const char* message; + + public: + Exception(Error error, const char* message) + : error(error), message(message) {} + + Error code() const noexcept + { + return error; + } + + const char* what() const noexcept override + { + return message; + } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/common/platform.cpp b/thirdparty/oidn/common/platform.cpp new file mode 100644 index 0000000000..59a14ff47c --- /dev/null +++ b/thirdparty/oidn/common/platform.cpp @@ -0,0 +1,114 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "platform.h" + +namespace oidn { + + // ---------------------------------------------------------------------------- + // Common functions + // ---------------------------------------------------------------------------- + + void* alignedMalloc(size_t size, size_t alignment) + { + if (size == 0) + return nullptr; + + assert((alignment & (alignment-1)) == 0); + void* ptr = _mm_malloc(size, alignment); + + if (ptr == nullptr) + throw std::bad_alloc(); + + return ptr; + } + + void alignedFree(void* ptr) + { + if (ptr) + _mm_free(ptr); + } + + // ---------------------------------------------------------------------------- + // System information + // ---------------------------------------------------------------------------- + + std::string getPlatformName() + { + std::string name; + + #if defined(__linux__) + name = "Linux"; + #elif defined(__FreeBSD__) + name = "FreeBSD"; + #elif defined(__CYGWIN__) + name = "Cygwin"; + #elif defined(_WIN32) + name = "Windows"; + #elif defined(__APPLE__) + name = "macOS"; + #elif defined(__unix__) + name = "Unix"; + #else + return "Unknown"; + #endif + + #if defined(__x86_64__) || defined(_M_X64) || defined(__ia64__) || defined(__aarch64__) + name += " (64-bit)"; + #else + name += " (32-bit)"; + #endif + + return name; + } + + std::string getCompilerName() + { + #if defined(__INTEL_COMPILER) + int mayor = __INTEL_COMPILER / 100 % 100; + int minor = __INTEL_COMPILER % 100; + std::string version = "Intel Compiler "; + version += toString(mayor); + version += "." + toString(minor); + #if defined(__INTEL_COMPILER_UPDATE) + version += "." + toString(__INTEL_COMPILER_UPDATE); + #endif + return version; + #elif defined(__clang__) + return "Clang " __clang_version__; + #elif defined(__GNUC__) + return "GCC " __VERSION__; + #elif defined(_MSC_VER) + std::string version = toString(_MSC_FULL_VER); + version.insert(4, "."); + version.insert(9, "."); + version.insert(2, "."); + return "Visual C++ Compiler " + version; + #else + return "Unknown"; + #endif + } + + std::string getBuildName() + { + #if defined(NDEBUG) + return "Release"; + #else + return "Debug"; + #endif + } + +} // namespace oidn diff --git a/thirdparty/oidn/common/platform.h b/thirdparty/oidn/common/platform.h new file mode 100644 index 0000000000..205ac8981d --- /dev/null +++ b/thirdparty/oidn/common/platform.h @@ -0,0 +1,131 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#if defined(_WIN32) + #define WIN32_LEAN_AND_MEAN + #define NOMINMAX + #include +#elif defined(__APPLE__) + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "include/OpenImageDenoise/oidn.hpp" + +namespace oidn { + + // ---------------------------------------------------------------------------- + // Macros + // ---------------------------------------------------------------------------- + + #if defined(_WIN32) + // Windows + #if !defined(__noinline) + #define __noinline __declspec(noinline) + #endif + #else + // Unix + #if !defined(__forceinline) + #define __forceinline inline __attribute__((always_inline)) + #endif + #if !defined(__noinline) + #define __noinline __attribute__((noinline)) + #endif + #endif + + #ifndef UNUSED + #define UNUSED(x) ((void)x) + #endif + #ifndef MAYBE_UNUSED + #define MAYBE_UNUSED(x) UNUSED(x) + #endif + + // ---------------------------------------------------------------------------- + // Error handling and debugging + // ---------------------------------------------------------------------------- + + struct Verbose + { + int verbose; + + Verbose(int v = 0) : verbose(v) {} + __forceinline bool isVerbose(int v = 1) const { return v <= verbose; } + }; + + #define OIDN_WARNING(message) { if (isVerbose()) std::cerr << "Warning: " << message << std::endl; } + #define OIDN_FATAL(message) throw std::runtime_error(message); + + // ---------------------------------------------------------------------------- + // Common functions + // ---------------------------------------------------------------------------- + + using std::min; + using std::max; + + template + __forceinline T clamp(const T& value, const T& minValue, const T& maxValue) + { + return min(max(value, minValue), maxValue); + } + + void* alignedMalloc(size_t size, size_t alignment); + void alignedFree(void* ptr); + + template + inline std::string toString(const T& a) + { + std::stringstream sm; + sm << a; + return sm.str(); + } + +#if defined(__APPLE__) + template + bool getSysctl(const char* name, T& value) + { + int64_t result = 0; + size_t size = sizeof(result); + + if (sysctlbyname(name, &result, &size, nullptr, 0) != 0) + return false; + + value = T(result); + return true; + } +#endif + + // ---------------------------------------------------------------------------- + // System information + // ---------------------------------------------------------------------------- + + std::string getPlatformName(); + std::string getCompilerName(); + std::string getBuildName(); + +} // namespace oidn diff --git a/thirdparty/oidn/common/ref.h b/thirdparty/oidn/common/ref.h new file mode 100644 index 0000000000..de44603af2 --- /dev/null +++ b/thirdparty/oidn/common/ref.h @@ -0,0 +1,163 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "platform.h" + +namespace oidn { + + class RefCount + { + private: + std::atomic count; + + public: + __forceinline RefCount(int count = 0) noexcept : count(count) {} + + __forceinline size_t incRef() noexcept + { + return count.fetch_add(1) + 1; + } + + __forceinline size_t decRef() + { + const size_t newCount = decRefKeep(); + if (newCount == 0) + destroy(); + return newCount; + } + + __forceinline size_t decRefKeep() noexcept + { + return count.fetch_add(-1) - 1; + } + + __forceinline void destroy() + { + delete this; + } + + protected: + // Disable copying + RefCount(const RefCount&) = delete; + RefCount& operator =(const RefCount&) = delete; + + virtual ~RefCount() noexcept = default; + }; + + template + class Ref + { + private: + T* ptr; + + public: + __forceinline Ref() noexcept : ptr(nullptr) {} + __forceinline Ref(std::nullptr_t) noexcept : ptr(nullptr) {} + __forceinline Ref(const Ref& other) noexcept : ptr(other.ptr) { if (ptr) ptr->incRef(); } + __forceinline Ref(Ref&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; } + __forceinline Ref(T* ptr) noexcept : ptr(ptr) { if (ptr) ptr->incRef(); } + + template + __forceinline Ref(const Ref& other) noexcept : ptr(other.get()) { if (ptr) ptr->incRef(); } + + template + __forceinline explicit Ref(Y* ptr) noexcept : ptr(ptr) { if (ptr) ptr->incRef(); } + + __forceinline ~Ref() { if (ptr) ptr->decRef(); } + + __forceinline Ref& operator =(const Ref& other) + { + if (other.ptr) + other.ptr->incRef(); + if (ptr) + ptr->decRef(); + ptr = other.ptr; + return *this; + } + + __forceinline Ref& operator =(Ref&& other) + { + if (ptr) + ptr->decRef(); + ptr = other.ptr; + other.ptr = nullptr; + return *this; + } + + __forceinline Ref& operator =(T* other) + { + if (other) + other->incRef(); + if (ptr) + ptr->decRef(); + ptr = other; + return *this; + } + + __forceinline Ref& operator =(std::nullptr_t) + { + if (ptr) + ptr->decRef(); + ptr = nullptr; + return *this; + } + + __forceinline operator bool() const noexcept { return ptr != nullptr; } + + __forceinline T& operator *() const noexcept { return *ptr; } + __forceinline T* operator ->() const noexcept { return ptr; } + + __forceinline T* get() const noexcept { return ptr; } + + __forceinline T* detach() noexcept + { + T* res = ptr; + ptr = nullptr; + return res; + } + }; + + template __forceinline bool operator < (const Ref& a, const Ref& b) noexcept { return a.ptr < b.ptr; } + + template __forceinline bool operator ==(const Ref& a, std::nullptr_t) noexcept { return a.ptr == nullptr; } + template __forceinline bool operator ==(std::nullptr_t, const Ref& b) noexcept { return nullptr == b.ptr; } + template __forceinline bool operator ==(const Ref& a, const Ref& b) noexcept { return a.ptr == b.ptr; } + + template __forceinline bool operator !=(const Ref& a, std::nullptr_t) noexcept { return a.ptr != nullptr; } + template __forceinline bool operator !=(std::nullptr_t, const Ref& b) noexcept { return nullptr != b.ptr; } + template __forceinline bool operator !=(const Ref& a, const Ref& b) noexcept { return a.ptr != b.ptr; } + + template + __forceinline Ref makeRef(Args&&... args) + { + return Ref(new T(std::forward(args)...)); + } + + template + __forceinline Ref staticRefCast(const Ref& a) + { + return Ref(static_cast(a.get())); + } + + template + __forceinline Ref dynamicRefCast(const Ref& a) + { + return Ref(dynamic_cast(a.get())); + } + +} // namespace oidn diff --git a/thirdparty/oidn/common/tensor.cpp b/thirdparty/oidn/common/tensor.cpp new file mode 100644 index 0000000000..0249f2e141 --- /dev/null +++ b/thirdparty/oidn/common/tensor.cpp @@ -0,0 +1,83 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "exception.h" +#include "tensor.h" + +namespace oidn { + + std::map parseTensors(void* buffer) + { + char* input = (char*)buffer; + + // Parse the magic value + const int magic = *(unsigned short*)input; + if (magic != 0x41D7) + throw Exception(Error::InvalidOperation, "invalid tensor archive"); + input += sizeof(unsigned short); + + // Parse the version + const int majorVersion = *(unsigned char*)input++; + const int minorVersion = *(unsigned char*)input++; + UNUSED(minorVersion); + if (majorVersion > 1) + throw Exception(Error::InvalidOperation, "unsupported tensor archive version"); + + // Parse the number of tensors + const int numTensors = *(int*)input; + input += sizeof(int); + + // Parse the tensors + std::map tensorMap; + for (int i = 0; i < numTensors; ++i) + { + Tensor tensor; + + // Parse the name + const int nameLen = *(unsigned char*)input++; + std::string name(input, nameLen); + input += nameLen; + + // Parse the number of dimensions + const int ndims = *(unsigned char*)input++; + + // Parse the shape of the tensor + tensor.dims.resize(ndims); + for (int i = 0; i < ndims; ++i) + tensor.dims[i] = ((int*)input)[i]; + input += ndims * sizeof(int); + + // Parse the format of the tensor + tensor.format = std::string(input, input + ndims); + input += ndims; + + // Parse the data type of the tensor + const char type = *(unsigned char*)input++; + if (type != 'f') // only float32 is supported + throw Exception(Error::InvalidOperation, "unsupported tensor data type"); + + // Skip the data + tensor.data = (float*)input; + input += tensor.size() * sizeof(float); + + // Add the tensor to the map + tensorMap.emplace(name, std::move(tensor)); + } + + return tensorMap; + } + +} // namespace oidn diff --git a/thirdparty/oidn/common/tensor.h b/thirdparty/oidn/common/tensor.h new file mode 100644 index 0000000000..48e7d1123d --- /dev/null +++ b/thirdparty/oidn/common/tensor.h @@ -0,0 +1,66 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "platform.h" +#include +#include + +namespace oidn { + + template + using shared_vector = std::shared_ptr>; + + // Generic tensor + struct Tensor + { + float* data; + std::vector dims; + std::string format; + shared_vector buffer; // optional, only for reference counting + + __forceinline Tensor() : data(nullptr) {} + + __forceinline Tensor(const std::vector& dims, const std::string& format) + : dims(dims), + format(format) + { + buffer = std::make_shared>(size() * sizeof(float)); + data = (float*)buffer->data(); + } + + __forceinline operator bool() const { return data != nullptr; } + + __forceinline int ndims() const { return (int)dims.size(); } + + // Returns the number of values + __forceinline size_t size() const + { + size_t size = 1; + for (int i = 0; i < ndims(); ++i) + size *= dims[i]; + return size; + } + + __forceinline float& operator [](size_t i) { return data[i]; } + __forceinline const float& operator [](size_t i) const { return data[i]; } + }; + + // Parses tensors from a buffer + std::map parseTensors(void* buffer); + +} // namespace oidn diff --git a/thirdparty/oidn/common/thread.cpp b/thirdparty/oidn/common/thread.cpp new file mode 100644 index 0000000000..48c489c57b --- /dev/null +++ b/thirdparty/oidn/common/thread.cpp @@ -0,0 +1,297 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#if defined(_MSC_VER) + #pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned +#endif + +#if defined(__APPLE__) + #include + #include +#endif + +#include "thread.h" +#include + +namespace oidn { + +#if defined(_WIN32) + + // -------------------------------------------------------------------------- + // ThreadAffinity - Windows + // -------------------------------------------------------------------------- + + ThreadAffinity::ThreadAffinity(int numThreadsPerCore, int verbose) + : Verbose(verbose) + { + HMODULE hLib = GetModuleHandle(TEXT("kernel32")); + pGetLogicalProcessorInformationEx = (GetLogicalProcessorInformationExFunc)GetProcAddress(hLib, "GetLogicalProcessorInformationEx"); + pSetThreadGroupAffinity = (SetThreadGroupAffinityFunc)GetProcAddress(hLib, "SetThreadGroupAffinity"); + + if (pGetLogicalProcessorInformationEx && pSetThreadGroupAffinity) + { + // Get logical processor information + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = nullptr; + DWORD bufferSize = 0; + + // First call the function with an empty buffer to get the required buffer size + BOOL result = pGetLogicalProcessorInformationEx(RelationProcessorCore, buffer, &bufferSize); + if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + OIDN_WARNING("GetLogicalProcessorInformationEx failed"); + return; + } + + // Allocate the buffer + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(bufferSize); + if (!buffer) + { + OIDN_WARNING("SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX allocation failed"); + return; + } + + // Call again the function but now with the properly sized buffer + result = pGetLogicalProcessorInformationEx(RelationProcessorCore, buffer, &bufferSize); + if (!result) + { + OIDN_WARNING("GetLogicalProcessorInformationEx failed"); + free(buffer); + return; + } + + // Iterate over the logical processor information structures + // There should be one structure for each physical core + char* ptr = (char*)buffer; + while (ptr < (char*)buffer + bufferSize) + { + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX item = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)ptr; + if (item->Relationship == RelationProcessorCore && item->Processor.GroupCount > 0) + { + // Iterate over the groups + int numThreads = 0; + for (int group = 0; (group < item->Processor.GroupCount) && (numThreads < numThreadsPerCore); ++group) + { + GROUP_AFFINITY coreAffinity = item->Processor.GroupMask[group]; + while ((coreAffinity.Mask != 0) && (numThreads < numThreadsPerCore)) + { + // Extract the next set bit/thread from the mask + GROUP_AFFINITY threadAffinity = coreAffinity; + threadAffinity.Mask = threadAffinity.Mask & -threadAffinity.Mask; + + // Push the affinity for this thread + affinities.push_back(threadAffinity); + oldAffinities.push_back(threadAffinity); + numThreads++; + + // Remove this bit/thread from the mask + coreAffinity.Mask ^= threadAffinity.Mask; + } + } + } + + // Next structure + ptr += item->Size; + } + + // Free the buffer + free(buffer); + } + } + + void ThreadAffinity::set(int threadIndex) + { + if (threadIndex >= (int)affinities.size()) + return; + + // Save the current affinity and set the new one + const HANDLE thread = GetCurrentThread(); + if (!pSetThreadGroupAffinity(thread, &affinities[threadIndex], &oldAffinities[threadIndex])) + OIDN_WARNING("SetThreadGroupAffinity failed"); + } + + void ThreadAffinity::restore(int threadIndex) + { + if (threadIndex >= (int)affinities.size()) + return; + + // Restore the original affinity + const HANDLE thread = GetCurrentThread(); + if (!pSetThreadGroupAffinity(thread, &oldAffinities[threadIndex], nullptr)) + OIDN_WARNING("SetThreadGroupAffinity failed"); + } + +#elif defined(__linux__) + + // -------------------------------------------------------------------------- + // ThreadAffinity - Linux + // -------------------------------------------------------------------------- + + ThreadAffinity::ThreadAffinity(int numThreadsPerCore, int verbose) + : Verbose(verbose) + { + std::vector threadIds; + + // Parse the thread/CPU topology + for (int cpuId = 0; ; cpuId++) + { + std::fstream fs; + std::string cpu = std::string("/sys/devices/system/cpu/cpu") + std::to_string(cpuId) + std::string("/topology/thread_siblings_list"); + fs.open(cpu.c_str(), std::fstream::in); + if (fs.fail()) break; + + int i; + int j = 0; + while ((j < numThreadsPerCore) && (fs >> i)) + { + if (std::none_of(threadIds.begin(), threadIds.end(), [&](int id) { return id == i; })) + threadIds.push_back(i); + + if (fs.peek() == ',') + fs.ignore(); + j++; + } + + fs.close(); + } + + #if 0 + for (size_t i = 0; i < thread_ids.size(); ++i) + std::cout << "thread " << i << " -> " << thread_ids[i] << std::endl; + #endif + + // Create the affinity structures + affinities.resize(threadIds.size()); + oldAffinities.resize(threadIds.size()); + + for (size_t i = 0; i < threadIds.size(); ++i) + { + cpu_set_t affinity; + CPU_ZERO(&affinity); + CPU_SET(threadIds[i], &affinity); + + affinities[i] = affinity; + oldAffinities[i] = affinity; + } + } + + void ThreadAffinity::set(int threadIndex) + { + if (threadIndex >= (int)affinities.size()) + return; + + const pthread_t thread = pthread_self(); + + // Save the current affinity + if (pthread_getaffinity_np(thread, sizeof(cpu_set_t), &oldAffinities[threadIndex]) != 0) + { + OIDN_WARNING("pthread_getaffinity_np failed"); + oldAffinities[threadIndex] = affinities[threadIndex]; + return; + } + + // Set the new affinity + if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &affinities[threadIndex]) != 0) + OIDN_WARNING("pthread_setaffinity_np failed"); + } + + void ThreadAffinity::restore(int threadIndex) + { + if (threadIndex >= (int)affinities.size()) + return; + + const pthread_t thread = pthread_self(); + + // Restore the original affinity + if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &oldAffinities[threadIndex]) != 0) + OIDN_WARNING("pthread_setaffinity_np failed"); + } + +#elif defined(__APPLE__) + + // -------------------------------------------------------------------------- + // ThreadAffinity - macOS + // -------------------------------------------------------------------------- + + ThreadAffinity::ThreadAffinity(int numThreadsPerCore, int verbose) + : Verbose(verbose) + { + // Query the thread/CPU topology + int numPhysicalCpus; + int numLogicalCpus; + + if (!getSysctl("hw.physicalcpu", numPhysicalCpus) || !getSysctl("hw.logicalcpu", numLogicalCpus)) + { + OIDN_WARNING("sysctlbyname failed"); + return; + } + + if ((numLogicalCpus % numPhysicalCpus != 0) && (numThreadsPerCore > 1)) + return; // this shouldn't happen + const int maxThreadsPerCore = numLogicalCpus / numPhysicalCpus; + + // Create the affinity structures + // macOS doesn't support binding a thread to a specific core, but we can at least group threads which + // should be on the same core together + for (int core = 1; core <= numPhysicalCpus; ++core) // tags start from 1! + { + thread_affinity_policy affinity; + affinity.affinity_tag = core; + + for (int thread = 0; thread < min(numThreadsPerCore, maxThreadsPerCore); ++thread) + { + affinities.push_back(affinity); + oldAffinities.push_back(affinity); + } + } + } + + void ThreadAffinity::set(int threadIndex) + { + if (threadIndex >= (int)affinities.size()) + return; + + const auto thread = mach_thread_self(); + + // Save the current affinity + mach_msg_type_number_t policyCount = THREAD_AFFINITY_POLICY_COUNT; + boolean_t getDefault = FALSE; + if (thread_policy_get(thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&oldAffinities[threadIndex], &policyCount, &getDefault) != KERN_SUCCESS) + { + OIDN_WARNING("thread_policy_get failed"); + oldAffinities[threadIndex] = affinities[threadIndex]; + return; + } + + // Set the new affinity + if (thread_policy_set(thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&affinities[threadIndex], THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS) + OIDN_WARNING("thread_policy_set failed"); + } + + void ThreadAffinity::restore(int threadIndex) + { + if (threadIndex >= (int)affinities.size()) + return; + + const auto thread = mach_thread_self(); + + // Restore the original affinity + if (thread_policy_set(thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&oldAffinities[threadIndex], THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS) + OIDN_WARNING("thread_policy_set failed"); + } + +#endif + +} // namespace oidn diff --git a/thirdparty/oidn/common/thread.h b/thirdparty/oidn/common/thread.h new file mode 100644 index 0000000000..2c731367da --- /dev/null +++ b/thirdparty/oidn/common/thread.h @@ -0,0 +1,202 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "platform.h" + +#if !defined(_WIN32) + #include + #include + #if defined(__APPLE__) + #include + #endif +#endif + +#include +#include + +namespace oidn { + + // -------------------------------------------------------------------------- + // ThreadLocal + // -------------------------------------------------------------------------- + + // Wrapper which makes any variable thread-local + template + class ThreadLocal : public Verbose + { + private: + #if defined(_WIN32) + DWORD key; + #else + pthread_key_t key; + #endif + + std::vector instances; + std::mutex mutex; + + public: + ThreadLocal(int verbose = 0) + : Verbose(verbose) + { + #if defined(_WIN32) + key = TlsAlloc(); + if (key == TLS_OUT_OF_INDEXES) + OIDN_FATAL("TlsAlloc failed"); + #else + if (pthread_key_create(&key, nullptr) != 0) + OIDN_FATAL("pthread_key_create failed"); + #endif + } + + ~ThreadLocal() + { + std::lock_guard lock(mutex); + for (T* ptr : instances) + delete ptr; + + #if defined(_WIN32) + if (!TlsFree(key)) + OIDN_WARNING("TlsFree failed"); + #else + if (pthread_key_delete(key) != 0) + OIDN_WARNING("pthread_key_delete failed"); + #endif + } + + T& get() + { + #if defined(_WIN32) + T* ptr = (T*)TlsGetValue(key); + #else + T* ptr = (T*)pthread_getspecific(key); + #endif + + if (ptr) + return *ptr; + + ptr = new T; + std::lock_guard lock(mutex); + instances.push_back(ptr); + + #if defined(_WIN32) + if (!TlsSetValue(key, ptr)) + OIDN_FATAL("TlsSetValue failed"); + #else + if (pthread_setspecific(key, ptr) != 0) + OIDN_FATAL("pthread_setspecific failed"); + #endif + + return *ptr; + } + }; + +#if defined(_WIN32) + + // -------------------------------------------------------------------------- + // ThreadAffinity - Windows + // -------------------------------------------------------------------------- + + class ThreadAffinity : public Verbose + { + private: + typedef BOOL (WINAPI *GetLogicalProcessorInformationExFunc)(LOGICAL_PROCESSOR_RELATIONSHIP, + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, + PDWORD); + + typedef BOOL (WINAPI *SetThreadGroupAffinityFunc)(HANDLE, + CONST GROUP_AFFINITY*, + PGROUP_AFFINITY); + + GetLogicalProcessorInformationExFunc pGetLogicalProcessorInformationEx = nullptr; + SetThreadGroupAffinityFunc pSetThreadGroupAffinity = nullptr; + + std::vector affinities; // thread affinities + std::vector oldAffinities; // original thread affinities + + public: + ThreadAffinity(int numThreadsPerCore = INT_MAX, int verbose = 0); + + int getNumThreads() const + { + return (int)affinities.size(); + } + + // Sets the affinity (0..numThreads-1) of the thread after saving the current affinity + void set(int threadIndex); + + // Restores the affinity of the thread + void restore(int threadIndex); + }; + +#elif defined(__linux__) + + // -------------------------------------------------------------------------- + // ThreadAffinity - Linux + // -------------------------------------------------------------------------- + + class ThreadAffinity : public Verbose + { + private: + std::vector affinities; // thread affinities + std::vector oldAffinities; // original thread affinities + + public: + ThreadAffinity(int numThreadsPerCore = INT_MAX, int verbose = 0); + + int getNumThreads() const + { + return (int)affinities.size(); + } + + // Sets the affinity (0..numThreads-1) of the thread after saving the current affinity + void set(int threadIndex); + + // Restores the affinity of the thread + void restore(int threadIndex); + }; + +#elif defined(__APPLE__) + + // -------------------------------------------------------------------------- + // ThreadAffinity - macOS + // -------------------------------------------------------------------------- + + class ThreadAffinity : public Verbose + { + private: + std::vector affinities; // thread affinities + std::vector oldAffinities; // original thread affinities + + public: + ThreadAffinity(int numThreadsPerCore = INT_MAX, int verbose = 0); + + int getNumThreads() const + { + return (int)affinities.size(); + } + + // Sets the affinity (0..numThreads-1) of the thread after saving the current affinity + void set(int threadIndex); + + // Restores the affinity of the thread + void restore(int threadIndex); + }; + +#endif + +} // namespace oidn diff --git a/thirdparty/oidn/common/timer.h b/thirdparty/oidn/common/timer.h new file mode 100644 index 0000000000..62aaaa1c33 --- /dev/null +++ b/thirdparty/oidn/common/timer.h @@ -0,0 +1,49 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "platform.h" +#include + +namespace oidn { + + class Timer + { + private: + using clock = std::chrono::high_resolution_clock; + + std::chrono::time_point start; + + public: + Timer() + { + reset(); + } + + void reset() + { + start = clock::now(); + } + + double query() const + { + auto end = clock::now(); + return std::chrono::duration_cast>(end - start).count(); + } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/api.cpp b/thirdparty/oidn/core/api.cpp new file mode 100644 index 0000000000..7353fe4e25 --- /dev/null +++ b/thirdparty/oidn/core/api.cpp @@ -0,0 +1,408 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#ifdef _WIN32 +# define OIDN_API extern "C" __declspec(dllexport) +#else +# define OIDN_API extern "C" __attribute__ ((visibility ("default"))) +#endif + +// Locks the device that owns the specified object +// Use *only* inside OIDN_TRY/CATCH! +#define OIDN_LOCK(obj) \ + std::lock_guard lock(obj->getDevice()->getMutex()); + +// Try/catch for converting exceptions to errors +#define OIDN_TRY \ + try { + +#define OIDN_CATCH(obj) \ + } catch (Exception& e) { \ + Device::setError(obj ? obj->getDevice() : nullptr, e.code(), e.what()); \ + } catch (std::bad_alloc&) { \ + Device::setError(obj ? obj->getDevice() : nullptr, Error::OutOfMemory, "out of memory"); \ + } catch (mkldnn::error& e) { \ + if (e.status == mkldnn_out_of_memory) \ + Device::setError(obj ? obj->getDevice() : nullptr, Error::OutOfMemory, "out of memory"); \ + else \ + Device::setError(obj ? obj->getDevice() : nullptr, Error::Unknown, e.message); \ + } catch (std::exception& e) { \ + Device::setError(obj ? obj->getDevice() : nullptr, Error::Unknown, e.what()); \ + } catch (...) { \ + Device::setError(obj ? obj->getDevice() : nullptr, Error::Unknown, "unknown exception caught"); \ + } + +#include "device.h" +#include "filter.h" +#include + +namespace oidn { + + namespace + { + __forceinline void checkHandle(void* handle) + { + if (handle == nullptr) + throw Exception(Error::InvalidArgument, "invalid handle"); + } + + template + __forceinline void retainObject(T* obj) + { + if (obj) + { + obj->incRef(); + } + else + { + OIDN_TRY + checkHandle(obj); + OIDN_CATCH(obj) + } + } + + template + __forceinline void releaseObject(T* obj) + { + if (obj == nullptr || obj->decRefKeep() == 0) + { + OIDN_TRY + checkHandle(obj); + OIDN_LOCK(obj); + obj->destroy(); + OIDN_CATCH(obj) + } + } + + template<> + __forceinline void releaseObject(Device* obj) + { + if (obj == nullptr || obj->decRefKeep() == 0) + { + OIDN_TRY + checkHandle(obj); + // Do NOT lock the device because it owns the mutex + obj->destroy(); + OIDN_CATCH(obj) + } + } + } + + OIDN_API OIDNDevice oidnNewDevice(OIDNDeviceType type) + { + Ref device = nullptr; + OIDN_TRY + if (type == OIDN_DEVICE_TYPE_CPU || type == OIDN_DEVICE_TYPE_DEFAULT) + device = makeRef(); + else + throw Exception(Error::InvalidArgument, "invalid device type"); + OIDN_CATCH(device) + return (OIDNDevice)device.detach(); + } + + OIDN_API void oidnRetainDevice(OIDNDevice hDevice) + { + Device* device = (Device*)hDevice; + retainObject(device); + } + + OIDN_API void oidnReleaseDevice(OIDNDevice hDevice) + { + Device* device = (Device*)hDevice; + releaseObject(device); + } + + OIDN_API void oidnSetDevice1b(OIDNDevice hDevice, const char* name, bool value) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + device->set1i(name, value); + OIDN_CATCH(device) + } + + OIDN_API void oidnSetDevice1i(OIDNDevice hDevice, const char* name, int value) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + device->set1i(name, value); + OIDN_CATCH(device) + } + + OIDN_API bool oidnGetDevice1b(OIDNDevice hDevice, const char* name) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + return device->get1i(name); + OIDN_CATCH(device) + return false; + } + + OIDN_API int oidnGetDevice1i(OIDNDevice hDevice, const char* name) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + return device->get1i(name); + OIDN_CATCH(device) + return 0; + } + + OIDN_API void oidnSetDeviceErrorFunction(OIDNDevice hDevice, OIDNErrorFunction func, void* userPtr) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + device->setErrorFunction((ErrorFunction)func, userPtr); + OIDN_CATCH(device) + } + + OIDN_API OIDNError oidnGetDeviceError(OIDNDevice hDevice, const char** outMessage) + { + Device* device = (Device*)hDevice; + OIDN_TRY + return (OIDNError)Device::getError(device, outMessage); + OIDN_CATCH(device) + if (outMessage) *outMessage = ""; + return OIDN_ERROR_UNKNOWN; + } + + OIDN_API void oidnCommitDevice(OIDNDevice hDevice) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + device->commit(); + OIDN_CATCH(device) + } + + OIDN_API OIDNBuffer oidnNewBuffer(OIDNDevice hDevice, size_t byteSize) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + Ref buffer = device->newBuffer(byteSize); + return (OIDNBuffer)buffer.detach(); + OIDN_CATCH(device) + return nullptr; + } + + OIDN_API OIDNBuffer oidnNewSharedBuffer(OIDNDevice hDevice, void* ptr, size_t byteSize) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + Ref buffer = device->newBuffer(ptr, byteSize); + return (OIDNBuffer)buffer.detach(); + OIDN_CATCH(device) + return nullptr; + } + + OIDN_API void oidnRetainBuffer(OIDNBuffer hBuffer) + { + Buffer* buffer = (Buffer*)hBuffer; + retainObject(buffer); + } + + OIDN_API void oidnReleaseBuffer(OIDNBuffer hBuffer) + { + Buffer* buffer = (Buffer*)hBuffer; + releaseObject(buffer); + } + + OIDN_API void* oidnMapBuffer(OIDNBuffer hBuffer, OIDNAccess access, size_t byteOffset, size_t byteSize) + { + Buffer* buffer = (Buffer*)hBuffer; + OIDN_TRY + checkHandle(hBuffer); + OIDN_LOCK(buffer); + return buffer->map(byteOffset, byteSize); + OIDN_CATCH(buffer) + return nullptr; + } + + OIDN_API void oidnUnmapBuffer(OIDNBuffer hBuffer, void* mappedPtr) + { + Buffer* buffer = (Buffer*)hBuffer; + OIDN_TRY + checkHandle(hBuffer); + OIDN_LOCK(buffer); + return buffer->unmap(mappedPtr); + OIDN_CATCH(buffer) + } + + OIDN_API OIDNFilter oidnNewFilter(OIDNDevice hDevice, const char* type) + { + Device* device = (Device*)hDevice; + OIDN_TRY + checkHandle(hDevice); + OIDN_LOCK(device); + Ref filter = device->newFilter(type); + return (OIDNFilter)filter.detach(); + OIDN_CATCH(device) + return nullptr; + } + + OIDN_API void oidnRetainFilter(OIDNFilter hFilter) + { + Filter* filter = (Filter*)hFilter; + retainObject(filter); + } + + OIDN_API void oidnReleaseFilter(OIDNFilter hFilter) + { + Filter* filter = (Filter*)hFilter; + releaseObject(filter); + } + + OIDN_API void oidnSetFilterImage(OIDNFilter hFilter, const char* name, + OIDNBuffer hBuffer, OIDNFormat format, + size_t width, size_t height, + size_t byteOffset, + size_t bytePixelStride, size_t byteRowStride) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + checkHandle(hBuffer); + OIDN_LOCK(filter); + Ref buffer = (Buffer*)hBuffer; + if (buffer->getDevice() != filter->getDevice()) + throw Exception(Error::InvalidArgument, "the specified objects are bound to different devices"); + Image data(buffer, (Format)format, (int)width, (int)height, byteOffset, bytePixelStride, byteRowStride); + filter->setImage(name, data); + OIDN_CATCH(filter) + } + + OIDN_API void oidnSetSharedFilterImage(OIDNFilter hFilter, const char* name, + void* ptr, OIDNFormat format, + size_t width, size_t height, + size_t byteOffset, + size_t bytePixelStride, size_t byteRowStride) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + Image data(ptr, (Format)format, (int)width, (int)height, byteOffset, bytePixelStride, byteRowStride); + filter->setImage(name, data); + OIDN_CATCH(filter) + } + + OIDN_API void oidnSetFilter1b(OIDNFilter hFilter, const char* name, bool value) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + filter->set1i(name, int(value)); + OIDN_CATCH(filter) + } + + OIDN_API bool oidnGetFilter1b(OIDNFilter hFilter, const char* name) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + return filter->get1i(name); + OIDN_CATCH(filter) + return false; + } + + OIDN_API void oidnSetFilter1i(OIDNFilter hFilter, const char* name, int value) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + filter->set1i(name, value); + OIDN_CATCH(filter) + } + + OIDN_API int oidnGetFilter1i(OIDNFilter hFilter, const char* name) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + return filter->get1i(name); + OIDN_CATCH(filter) + return 0; + } + + OIDN_API void oidnSetFilter1f(OIDNFilter hFilter, const char* name, float value) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + filter->set1f(name, value); + OIDN_CATCH(filter) + } + + OIDN_API float oidnGetFilter1f(OIDNFilter hFilter, const char* name) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + return filter->get1f(name); + OIDN_CATCH(filter) + return 0; + } + + OIDN_API void oidnSetFilterProgressMonitorFunction(OIDNFilter hFilter, OIDNProgressMonitorFunction func, void* userPtr) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + filter->setProgressMonitorFunction(func, userPtr); + OIDN_CATCH(filter) + } + + OIDN_API void oidnCommitFilter(OIDNFilter hFilter) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + filter->commit(); + OIDN_CATCH(filter) + } + + OIDN_API void oidnExecuteFilter(OIDNFilter hFilter) + { + Filter* filter = (Filter*)hFilter; + OIDN_TRY + checkHandle(hFilter); + OIDN_LOCK(filter); + filter->execute(); + OIDN_CATCH(filter) + } + +} // namespace oidn diff --git a/thirdparty/oidn/core/autoencoder.cpp b/thirdparty/oidn/core/autoencoder.cpp new file mode 100644 index 0000000000..8ae2421fa6 --- /dev/null +++ b/thirdparty/oidn/core/autoencoder.cpp @@ -0,0 +1,519 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "autoencoder.h" + +namespace oidn { + + // -------------------------------------------------------------------------- + // AutoencoderFilter + // -------------------------------------------------------------------------- + + AutoencoderFilter::AutoencoderFilter(const Ref& device) + : Filter(device) + { + } + + void AutoencoderFilter::setImage(const std::string& name, const Image& data) + { + if (name == "color") + color = data; + else if (name == "albedo") + albedo = data; + else if (name == "normal") + normal = data; + else if (name == "output") + output = data; + + dirty = true; + } + + void AutoencoderFilter::set1i(const std::string& name, int value) + { + if (name == "hdr") + hdr = value; + else if (name == "srgb") + srgb = value; + else if (name == "maxMemoryMB") + maxMemoryMB = value; + + dirty = true; + } + + int AutoencoderFilter::get1i(const std::string& name) + { + if (name == "hdr") + return hdr; + else if (name == "srgb") + return srgb; + else if (name == "maxMemoryMB") + return maxMemoryMB; + else if (name == "alignment") + return alignment; + else if (name == "overlap") + return overlap; + else + throw Exception(Error::InvalidArgument, "invalid parameter"); + } + + void AutoencoderFilter::set1f(const std::string& name, float value) + { + if (name == "hdrScale") + hdrScale = value; + + dirty = true; + } + + float AutoencoderFilter::get1f(const std::string& name) + { + if (name == "hdrScale") + return hdrScale; + else + throw Exception(Error::InvalidArgument, "invalid parameter"); + } + + void AutoencoderFilter::commit() + { + if (!dirty) + return; + + { + if (mayiuse(avx512_common)) + net = buildNet<16>(); + else + net = buildNet<8>(); + } + + dirty = false; + } + + void AutoencoderFilter::execute() + { + if (dirty) + throw Exception(Error::InvalidOperation, "changes to the filter are not committed"); + + if (!net) + return; + + { + Progress progress; + progress.func = progressFunc; + progress.userPtr = progressUserPtr; + progress.taskCount = tileCountH * tileCountW; + + // Iterate over the tiles + int tileIndex = 0; + + for (int i = 0; i < tileCountH; ++i) + { + const int h = i * (tileH - 2*overlap); // input tile position (including overlap) + const int overlapBeginH = i > 0 ? overlap : 0; // overlap on the top + const int overlapEndH = i < tileCountH-1 ? overlap : 0; // overlap on the bottom + const int tileH1 = min(H - h, tileH); // input tile size (including overlap) + const int tileH2 = tileH1 - overlapBeginH - overlapEndH; // output tile size + const int alignOffsetH = tileH - roundUp(tileH1, alignment); // align to the bottom in the tile buffer + + for (int j = 0; j < tileCountW; ++j) + { + const int w = j * (tileW - 2*overlap); // input tile position (including overlap) + const int overlapBeginW = j > 0 ? overlap : 0; // overlap on the left + const int overlapEndW = j < tileCountW-1 ? overlap : 0; // overlap on the right + const int tileW1 = min(W - w, tileW); // input tile size (including overlap) + const int tileW2 = tileW1 - overlapBeginW - overlapEndW; // output tile size + const int alignOffsetW = tileW - roundUp(tileW1, alignment); // align to the right in the tile buffer + + // Set the input tile + inputReorder->setTile(h, w, + alignOffsetH, alignOffsetW, + tileH1, tileW1); + + // Set the output tile + outputReorder->setTile(alignOffsetH + overlapBeginH, alignOffsetW + overlapBeginW, + h + overlapBeginH, w + overlapBeginW, + tileH2, tileW2); + + //printf("Tile: %d %d -> %d %d\n", w+overlapBeginW, h+overlapBeginH, w+overlapBeginW+tileW2, h+overlapBeginH+tileH2); + + // Denoise the tile + net->execute(progress, tileIndex); + + // Next tile + tileIndex++; + } + } + } + } + + void AutoencoderFilter::computeTileSize() + { + const int minTileSize = 3*overlap; + const int estimatedBytesPerPixel = mayiuse(avx512_common) ? estimatedBytesPerPixel16 : estimatedBytesPerPixel8; + const int64_t maxTilePixels = (int64_t(maxMemoryMB)*1024*1024 - estimatedBytesBase) / estimatedBytesPerPixel; + + tileCountH = 1; + tileCountW = 1; + tileH = roundUp(H, alignment); + tileW = roundUp(W, alignment); + + // Divide the image into tiles until the tile size gets below the threshold + while (int64_t(tileH) * tileW > maxTilePixels) + { + if (tileH > minTileSize && tileH > tileW) + { + tileCountH++; + tileH = max(roundUp(ceilDiv(H - 2*overlap, tileCountH), alignment) + 2*overlap, minTileSize); + } + else if (tileW > minTileSize) + { + tileCountW++; + tileW = max(roundUp(ceilDiv(W - 2*overlap, tileCountW), alignment) + 2*overlap, minTileSize); + } + else + break; + } + + // Compute the final number of tiles + tileCountH = (H > tileH) ? ceilDiv(H - 2*overlap, tileH - 2*overlap) : 1; + tileCountW = (W > tileW) ? ceilDiv(W - 2*overlap, tileW - 2*overlap) : 1; + + if (device->isVerbose(2)) + { + std::cout << "Tile size : " << tileW << "x" << tileH << std::endl; + std::cout << "Tile count: " << tileCountW << "x" << tileCountH << std::endl; + } + } + + template + std::shared_ptr AutoencoderFilter::buildNet() + { + H = color.height; + W = color.width; + + // Configure the network + int inputC; + void* weightPtr; + + if (srgb && hdr) + throw Exception(Error::InvalidOperation, "srgb and hdr modes cannot be enabled at the same time"); + + if (color && !albedo && !normal && weightData.hdr) + { + inputC = 3; + weightPtr = hdr ? weightData.hdr : weightData.ldr; + } + else if (color && albedo && !normal && weightData.hdr_alb) + { + inputC = 6; + weightPtr = hdr ? weightData.hdr_alb : weightData.ldr_alb; + } + else if (color && albedo && normal && weightData.hdr_alb_nrm) + { + inputC = 9; + weightPtr = hdr ? weightData.hdr_alb_nrm : weightData.ldr_alb_nrm; + } + else + { + throw Exception(Error::InvalidOperation, "unsupported combination of input features"); + } + + if (!output) + throw Exception(Error::InvalidOperation, "output image not specified"); + + if ((color.format != Format::Float3) + || (albedo && albedo.format != Format::Float3) + || (normal && normal.format != Format::Float3) + || (output.format != Format::Float3)) + throw Exception(Error::InvalidOperation, "unsupported image format"); + + if ((albedo && (albedo.width != W || albedo.height != H)) + || (normal && (normal.width != W || normal.height != H)) + || (output.width != W || output.height != H)) + throw Exception(Error::InvalidOperation, "image size mismatch"); + + // Compute the tile size + computeTileSize(); + + // If the image size is zero, there is nothing else to do + if (H <= 0 || W <= 0) + return nullptr; + + // Parse the weights + const auto weightMap = parseTensors(weightPtr); + + // Create the network + std::shared_ptr> net = std::make_shared>(device, weightMap); + + // Compute the tensor sizes + const auto inputDims = memory::dims({1, inputC, tileH, tileW}); + const auto inputReorderDims = net->getInputReorderDims(inputDims, alignment); //-> concat0 + + const auto conv1Dims = net->getConvDims("conv1", inputReorderDims); //-> temp0 + const auto conv1bDims = net->getConvDims("conv1b", conv1Dims); //-> temp1 + const auto pool1Dims = net->getPoolDims(conv1bDims); //-> concat1 + const auto conv2Dims = net->getConvDims("conv2", pool1Dims); //-> temp0 + const auto pool2Dims = net->getPoolDims(conv2Dims); //-> concat2 + const auto conv3Dims = net->getConvDims("conv3", pool2Dims); //-> temp0 + const auto pool3Dims = net->getPoolDims(conv3Dims); //-> concat3 + const auto conv4Dims = net->getConvDims("conv4", pool3Dims); //-> temp0 + const auto pool4Dims = net->getPoolDims(conv4Dims); //-> concat4 + const auto conv5Dims = net->getConvDims("conv5", pool4Dims); //-> temp0 + const auto pool5Dims = net->getPoolDims(conv5Dims); //-> temp1 + const auto upsample4Dims = net->getUpsampleDims(pool5Dims); //-> concat4 + const auto concat4Dims = net->getConcatDims(upsample4Dims, pool4Dims); + const auto conv6Dims = net->getConvDims("conv6", concat4Dims); //-> temp0 + const auto conv6bDims = net->getConvDims("conv6b", conv6Dims); //-> temp1 + const auto upsample3Dims = net->getUpsampleDims(conv6bDims); //-> concat3 + const auto concat3Dims = net->getConcatDims(upsample3Dims, pool3Dims); + const auto conv7Dims = net->getConvDims("conv7", concat3Dims); //-> temp0 + const auto conv7bDims = net->getConvDims("conv7b", conv7Dims); //-> temp1 + const auto upsample2Dims = net->getUpsampleDims(conv7bDims); //-> concat2 + const auto concat2Dims = net->getConcatDims(upsample2Dims, pool2Dims); + const auto conv8Dims = net->getConvDims("conv8", concat2Dims); //-> temp0 + const auto conv8bDims = net->getConvDims("conv8b", conv8Dims); //-> temp1 + const auto upsample1Dims = net->getUpsampleDims(conv8bDims); //-> concat1 + const auto concat1Dims = net->getConcatDims(upsample1Dims, pool1Dims); + const auto conv9Dims = net->getConvDims("conv9", concat1Dims); //-> temp0 + const auto conv9bDims = net->getConvDims("conv9b", conv9Dims); //-> temp1 + const auto upsample0Dims = net->getUpsampleDims(conv9bDims); //-> concat0 + const auto concat0Dims = net->getConcatDims(upsample0Dims, inputReorderDims); + const auto conv10Dims = net->getConvDims("conv10", concat0Dims); //-> temp0 + const auto conv10bDims = net->getConvDims("conv10b", conv10Dims); //-> temp1 + const auto conv11Dims = net->getConvDims("conv11", conv10bDims); //-> temp0 + + const auto outputDims = memory::dims({1, 3, tileH, tileW}); + + // Allocate two temporary ping-pong buffers to decrease memory usage + const auto temp0Dims = getMaxTensorDims({ + conv1Dims, + conv2Dims, + conv3Dims, + conv4Dims, + conv5Dims, + conv6Dims, + conv7Dims, + conv8Dims, + conv9Dims, + conv10Dims, + conv11Dims + }); + + const auto temp1Dims = getMaxTensorDims({ + conv1bDims, + pool5Dims, + conv6bDims, + conv7bDims, + conv8bDims, + conv9bDims, + conv10bDims, + }); + + auto temp0 = net->allocTensor(temp0Dims); + auto temp1 = net->allocTensor(temp1Dims); + + // Allocate enough memory to hold the concat outputs. Then use the first + // half to hold the previous conv output and the second half to hold the + // pool/orig image output. This works because everything is C dimension + // outermost, padded to K floats, and all the concats are on the C dimension. + auto concat0Dst = net->allocTensor(concat0Dims); + auto concat1Dst = net->allocTensor(concat1Dims); + auto concat2Dst = net->allocTensor(concat2Dims); + auto concat3Dst = net->allocTensor(concat3Dims); + auto concat4Dst = net->allocTensor(concat4Dims); + + // Transfer function + std::shared_ptr transferFunc = makeTransferFunc(); + + // Autoexposure + if (auto tf = std::dynamic_pointer_cast(transferFunc)) + { + if (isnan(hdrScale)) + net->addAutoexposure(color, tf); + else + tf->setExposure(hdrScale); + } + + // Input reorder + auto inputReorderDst = net->castTensor(inputReorderDims, concat0Dst, upsample0Dims); + inputReorder = net->addInputReorder(color, albedo, normal, + transferFunc, + alignment, inputReorderDst); + + // conv1 + auto conv1 = net->addConv("conv1", inputReorder->getDst(), temp0); + + // conv1b + auto conv1b = net->addConv("conv1b", conv1->getDst(), temp1); + + // pool1 + // Adjust pointer for pool1 to eliminate concat1 + auto pool1Dst = net->castTensor(pool1Dims, concat1Dst, upsample1Dims); + auto pool1 = net->addPool(conv1b->getDst(), pool1Dst); + + // conv2 + auto conv2 = net->addConv("conv2", pool1->getDst(), temp0); + + // pool2 + // Adjust pointer for pool2 to eliminate concat2 + auto pool2Dst = net->castTensor(pool2Dims, concat2Dst, upsample2Dims); + auto pool2 = net->addPool(conv2->getDst(), pool2Dst); + + // conv3 + auto conv3 = net->addConv("conv3", pool2->getDst(), temp0); + + // pool3 + // Adjust pointer for pool3 to eliminate concat3 + auto pool3Dst = net->castTensor(pool3Dims, concat3Dst, upsample3Dims); + auto pool3 = net->addPool(conv3->getDst(), pool3Dst); + + // conv4 + auto conv4 = net->addConv("conv4", pool3->getDst(), temp0); + + // pool4 + // Adjust pointer for pool4 to eliminate concat4 + auto pool4Dst = net->castTensor(pool4Dims, concat4Dst, upsample4Dims); + auto pool4 = net->addPool(conv4->getDst(), pool4Dst); + + // conv5 + auto conv5 = net->addConv("conv5", pool4->getDst(), temp0); + + // pool5 + auto pool5 = net->addPool(conv5->getDst(), temp1); + + // upsample4 + auto upsample4Dst = net->castTensor(upsample4Dims, concat4Dst); + auto upsample4 = net->addUpsample(pool5->getDst(), upsample4Dst); + + // conv6 + auto conv6 = net->addConv("conv6", concat4Dst, temp0); + + // conv6b + auto conv6b = net->addConv("conv6b", conv6->getDst(), temp1); + + // upsample3 + auto upsample3Dst = net->castTensor(upsample3Dims, concat3Dst); + auto upsample3 = net->addUpsample(conv6b->getDst(), upsample3Dst); + + // conv7 + auto conv7 = net->addConv("conv7", concat3Dst, temp0); + + // conv7b + auto conv7b = net->addConv("conv7b", conv7->getDst(), temp1); + + // upsample2 + auto upsample2Dst = net->castTensor(upsample2Dims, concat2Dst); + auto upsample2 = net->addUpsample(conv7b->getDst(), upsample2Dst); + + // conv8 + auto conv8 = net->addConv("conv8", concat2Dst, temp0); + + // conv8b + auto conv8b = net->addConv("conv8b", conv8->getDst(), temp1); + + // upsample1 + auto upsample1Dst = net->castTensor(upsample1Dims, concat1Dst); + auto upsample1 = net->addUpsample(conv8b->getDst(), upsample1Dst); + + // conv9 + auto conv9 = net->addConv("conv9", concat1Dst, temp0); + + // conv9b + auto conv9b = net->addConv("conv9b", conv9->getDst(), temp1); + + // upsample0 + auto upsample0Dst = net->castTensor(upsample0Dims, concat0Dst); + auto upsample0 = net->addUpsample(conv9b->getDst(), upsample0Dst); + + // conv10 + auto conv10 = net->addConv("conv10", concat0Dst, temp0); + + // conv10b + auto conv10b = net->addConv("conv10b", conv10->getDst(), temp1); + + // conv11 + auto conv11 = net->addConv("conv11", conv10b->getDst(), temp0, false /* no relu */); + + // Output reorder + outputReorder = net->addOutputReorder(conv11->getDst(), transferFunc, output); + + net->finalize(); + return net; + } + + std::shared_ptr AutoencoderFilter::makeTransferFunc() + { + if (hdr) + return std::make_shared(); + else if (srgb) + return std::make_shared(); + else + return std::make_shared(); + } + +// Godot doesn't need Raytracing filters. Removing them saves space in the weights files. +#if 0 + // -------------------------------------------------------------------------- + // RTFilter + // -------------------------------------------------------------------------- + + namespace weights + { + // LDR + extern unsigned char rt_ldr[]; // color + extern unsigned char rt_ldr_alb[]; // color, albedo + extern unsigned char rt_ldr_alb_nrm[]; // color, albedo, normal + + // HDR + extern unsigned char rt_hdr[]; // color + extern unsigned char rt_hdr_alb[]; // color, albedo + extern unsigned char rt_hdr_alb_nrm[]; // color, albedo, normal + } + + RTFilter::RTFilter(const Ref& device) + : AutoencoderFilter(device) + { + weightData.ldr = weights::rt_ldr; + weightData.ldr_alb = weights::rt_ldr_alb; + weightData.ldr_alb_nrm = weights::rt_ldr_alb_nrm; + weightData.hdr = weights::rt_hdr; + weightData.hdr_alb = weights::rt_hdr_alb; + weightData.hdr_alb_nrm = weights::rt_hdr_alb_nrm; + } +#endif + + // -------------------------------------------------------------------------- + // RTLightmapFilter + // -------------------------------------------------------------------------- + + namespace weights + { + // HDR + extern unsigned char rtlightmap_hdr[]; // color + } + + RTLightmapFilter::RTLightmapFilter(const Ref& device) + : AutoencoderFilter(device) + { + weightData.hdr = weights::rtlightmap_hdr; + + hdr = true; + } + + std::shared_ptr RTLightmapFilter::makeTransferFunc() + { + return std::make_shared(); + } + +} // namespace oidn diff --git a/thirdparty/oidn/core/autoencoder.h b/thirdparty/oidn/core/autoencoder.h new file mode 100644 index 0000000000..97432f2bbd --- /dev/null +++ b/thirdparty/oidn/core/autoencoder.h @@ -0,0 +1,116 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "filter.h" +#include "network.h" +#include "transfer_function.h" + +namespace oidn { + + // -------------------------------------------------------------------------- + // AutoencoderFilter - Direct-predicting autoencoder + // -------------------------------------------------------------------------- + + class AutoencoderFilter : public Filter + { + protected: + static constexpr int alignment = 32; // required spatial alignment in pixels (padding may be necessary) + static constexpr int receptiveField = 222; // receptive field in pixels + static constexpr int overlap = roundUp(receptiveField / 2, alignment); // required spatial overlap between tiles in pixels + + static constexpr int estimatedBytesBase = 16*1024*1024; // estimated base memory usage + static constexpr int estimatedBytesPerPixel8 = 889; // estimated memory usage per pixel for K=8 + static constexpr int estimatedBytesPerPixel16 = 2185; // estimated memory usage per pixel for K=16 + + Image color; + Image albedo; + Image normal; + Image output; + bool hdr = false; + float hdrScale = std::numeric_limits::quiet_NaN(); + bool srgb = false; + int maxMemoryMB = 6000; // approximate maximum memory usage in MBs + + int H = 0; // image height + int W = 0; // image width + int tileH = 0; // tile height + int tileW = 0; // tile width + int tileCountH = 1; // number of tiles in H dimension + int tileCountW = 1; // number of tiles in W dimension + + std::shared_ptr net; + std::shared_ptr inputReorder; + std::shared_ptr outputReorder; + + struct + { + void* ldr = nullptr; + void* ldr_alb = nullptr; + void* ldr_alb_nrm = nullptr; + void* hdr = nullptr; + void* hdr_alb = nullptr; + void* hdr_alb_nrm = nullptr; + } weightData; + + explicit AutoencoderFilter(const Ref& device); + virtual std::shared_ptr makeTransferFunc(); + + public: + void setImage(const std::string& name, const Image& data) override; + void set1i(const std::string& name, int value) override; + int get1i(const std::string& name) override; + void set1f(const std::string& name, float value) override; + float get1f(const std::string& name) override; + + void commit() override; + void execute() override; + + private: + void computeTileSize(); + + template + std::shared_ptr buildNet(); + + bool isCommitted() const { return bool(net); } + }; + + // -------------------------------------------------------------------------- + // RTFilter - Generic ray tracing denoiser + // -------------------------------------------------------------------------- + +// Godot doesn't need Raytracing filters. Removing them saves space in the weights files. +#if 0 + class RTFilter : public AutoencoderFilter + { + public: + explicit RTFilter(const Ref& device); + }; +#endif + + // -------------------------------------------------------------------------- + // RTLightmapFilter - Ray traced lightmap denoiser + // -------------------------------------------------------------------------- + + class RTLightmapFilter : public AutoencoderFilter + { + public: + explicit RTLightmapFilter(const Ref& device); + std::shared_ptr makeTransferFunc() override; + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/buffer.h b/thirdparty/oidn/core/buffer.h new file mode 100644 index 0000000000..b95109152e --- /dev/null +++ b/thirdparty/oidn/core/buffer.h @@ -0,0 +1,75 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "common.h" +#include "device.h" + +namespace oidn { + + class Device; + + // Buffer which may or may not own its data + class Buffer : public RefCount + { + private: + char* ptr; + size_t byteSize; + bool shared; + Ref device; + + public: + __forceinline Buffer(const Ref& device, size_t size) + : ptr((char*)alignedMalloc(size, 64)), + byteSize(size), + shared(false), + device(device) {} + + __forceinline Buffer(const Ref& device, void* data, size_t size) + : ptr((char*)data), + byteSize(size), + shared(true), + device(device) + { + if (data == nullptr) + throw Exception(Error::InvalidArgument, "buffer pointer null"); + } + + __forceinline ~Buffer() + { + if (!shared) + alignedFree(ptr); + } + + __forceinline char* data() { return ptr; } + __forceinline const char* data() const { return ptr; } + __forceinline size_t size() const { return byteSize; } + + void* map(size_t offset, size_t size) + { + if (offset + size > byteSize) + throw Exception(Error::InvalidArgument, "buffer region out of range"); + + return ptr + offset; + } + + void unmap(void* mappedPtr) {} + + Device* getDevice() { return device.get(); } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/common.h b/thirdparty/oidn/core/common.h new file mode 100644 index 0000000000..6c87f377bc --- /dev/null +++ b/thirdparty/oidn/core/common.h @@ -0,0 +1,133 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "common/platform.h" + +#include "mkl-dnn/include/mkldnn.hpp" +#include "mkl-dnn/include/mkldnn_debug.h" +#include "mkl-dnn/src/common/mkldnn_thread.hpp" +#include "mkl-dnn/src/common/type_helpers.hpp" +#include "mkl-dnn/src/cpu/jit_generator.hpp" + +#include "common/ref.h" +#include "common/exception.h" +#include "common/thread.h" +#include "math.h" + +namespace oidn { + + using namespace mkldnn; + using namespace mkldnn::impl::cpu; + using mkldnn::impl::parallel_nd; + using mkldnn::impl::memory_desc_matches_tag; + + + inline size_t getFormatBytes(Format format) + { + switch (format) + { + case Format::Undefined: return 1; + case Format::Float: return sizeof(float); + case Format::Float2: return sizeof(float)*2; + case Format::Float3: return sizeof(float)*3; + case Format::Float4: return sizeof(float)*4; + } + assert(0); + return 0; + } + + + inline memory::dims getTensorDims(const std::shared_ptr& mem) + { + const mkldnn_memory_desc_t& desc = mem->get_desc().data; + return memory::dims(&desc.dims[0], &desc.dims[desc.ndims]); + } + + inline memory::data_type getTensorType(const std::shared_ptr& mem) + { + const mkldnn_memory_desc_t& desc = mem->get_desc().data; + return memory::data_type(desc.data_type); + } + + // Returns the number of values in a tensor + inline size_t getTensorSize(const memory::dims& dims) + { + size_t res = 1; + for (int i = 0; i < (int)dims.size(); ++i) + res *= dims[i]; + return res; + } + + inline memory::dims getMaxTensorDims(const std::vector& dims) + { + memory::dims result; + size_t maxSize = 0; + + for (const auto& d : dims) + { + const size_t size = getTensorSize(d); + if (size > maxSize) + { + result = d; + maxSize = size; + } + } + + return result; + } + + inline size_t getTensorSize(const std::shared_ptr& mem) + { + return getTensorSize(getTensorDims(mem)); + } + + + template + inline int getPadded(int dim) + { + return (dim + (K-1)) & ~(K-1); + } + + template + inline memory::dims getPadded_nchw(const memory::dims& dims) + { + assert(dims.size() == 4); + memory::dims padDims = dims; + padDims[1] = getPadded(dims[1]); // pad C + return padDims; + } + + + template + struct BlockedFormat; + + template<> + struct BlockedFormat<8> + { + static constexpr memory::format_tag nChwKc = memory::format_tag::nChw8c; + static constexpr memory::format_tag OIhwKiKo = memory::format_tag::OIhw8i8o; + }; + + template<> + struct BlockedFormat<16> + { + static constexpr memory::format_tag nChwKc = memory::format_tag::nChw16c; + static constexpr memory::format_tag OIhwKiKo = memory::format_tag::OIhw16i16o; + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/device.cpp b/thirdparty/oidn/core/device.cpp new file mode 100644 index 0000000000..0812624bb5 --- /dev/null +++ b/thirdparty/oidn/core/device.cpp @@ -0,0 +1,205 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "device.h" +#include "autoencoder.h" + +namespace oidn { + + thread_local Device::ErrorState Device::globalError; + + Device::Device() + { + if (!mayiuse(sse41)) + throw Exception(Error::UnsupportedHardware, "SSE4.1 support is required at minimum"); + } + + Device::~Device() + { + } + + void Device::setError(Device* device, Error code, const std::string& message) + { + // Update the stored error only if the previous error was queried + if (device) + { + ErrorState& curError = device->error.get(); + + if (curError.code == Error::None) + { + curError.code = code; + curError.message = message; + } + + // Print the error message in verbose mode + if (device->isVerbose()) + std::cerr << "Error: " << message << std::endl; + + // Call the error callback function + ErrorFunction errorFunc; + void* errorUserPtr; + + { + std::lock_guard lock(device->mutex); + errorFunc = device->errorFunc; + errorUserPtr = device->errorUserPtr; + } + + if (errorFunc) + errorFunc(errorUserPtr, code, (code == Error::None) ? nullptr : message.c_str()); + } + else + { + if (globalError.code == Error::None) + { + globalError.code = code; + globalError.message = message; + } + } + } + + Error Device::getError(Device* device, const char** outMessage) + { + // Return and clear the stored error code, but keep the error message so pointers to it will + // remain valid until the next getError call + if (device) + { + ErrorState& curError = device->error.get(); + const Error code = curError.code; + if (outMessage) + *outMessage = (code == Error::None) ? nullptr : curError.message.c_str(); + curError.code = Error::None; + return code; + } + else + { + const Error code = globalError.code; + if (outMessage) + *outMessage = (code == Error::None) ? nullptr : globalError.message.c_str(); + globalError.code = Error::None; + return code; + } + } + + void Device::setErrorFunction(ErrorFunction func, void* userPtr) + { + errorFunc = func; + errorUserPtr = userPtr; + } + + int Device::get1i(const std::string& name) + { + if (name == "numThreads") + return numThreads; + else if (name == "setAffinity") + return setAffinity; + else if (name == "verbose") + return verbose; + else if (name == "version") + return OIDN_VERSION; + else if (name == "versionMajor") + return OIDN_VERSION_MAJOR; + else if (name == "versionMinor") + return OIDN_VERSION_MINOR; + else if (name == "versionPatch") + return OIDN_VERSION_PATCH; + else + throw Exception(Error::InvalidArgument, "invalid parameter"); + } + + void Device::set1i(const std::string& name, int value) + { + if (name == "numThreads") + numThreads = value; + else if (name == "setAffinity") + setAffinity = value; + else if (name == "verbose") + { + verbose = value; + error.verbose = value; + } + + dirty = true; + } + + void Device::commit() + { + if (isCommitted()) + throw Exception(Error::InvalidOperation, "device can be committed only once"); + + // Create the task arena + const int maxNumThreads = 1; //affinity ? affinity->getNumThreads() : tbb::this_task_arena::max_concurrency(); + numThreads = (numThreads > 0) ? min(numThreads, maxNumThreads) : maxNumThreads; + + dirty = false; + + if (isVerbose()) + print(); + } + + void Device::checkCommitted() + { + if (dirty) + throw Exception(Error::InvalidOperation, "changes to the device are not committed"); + } + + Ref Device::newBuffer(size_t byteSize) + { + checkCommitted(); + return makeRef(Ref(this), byteSize); + } + + Ref Device::newBuffer(void* ptr, size_t byteSize) + { + checkCommitted(); + return makeRef(Ref(this), ptr, byteSize); + } + + Ref Device::newFilter(const std::string& type) + { + checkCommitted(); + + if (isVerbose()) + std::cout << "Filter: " << type << std::endl; + + Ref filter; + +// Godot doesn't need Raytracing filters. Removing them saves space in the weights files. +#if 0 + if (type == "RT") + filter = makeRef(Ref(this)); +#endif + if (type == "RTLightmap") + filter = makeRef(Ref(this)); + else + throw Exception(Error::InvalidArgument, "unknown filter type"); + + return filter; + } + + void Device::print() + { + std::cout << std::endl; + + std::cout << "Intel(R) Open Image Denoise " << OIDN_VERSION_STRING << std::endl; + std::cout << " Compiler: " << getCompilerName() << std::endl; + std::cout << " Build : " << getBuildName() << std::endl; + std::cout << " Platform: " << getPlatformName() << std::endl; + + std::cout << std::endl; + } + +} // namespace oidn diff --git a/thirdparty/oidn/core/device.h b/thirdparty/oidn/core/device.h new file mode 100644 index 0000000000..93a83eb731 --- /dev/null +++ b/thirdparty/oidn/core/device.h @@ -0,0 +1,78 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "common.h" + +namespace oidn { + + class Buffer; + class Filter; + + class Device : public RefCount, public Verbose + { + private: + // Thread-safety + std::mutex mutex; + + // Error handling + struct ErrorState + { + Error code = Error::None; + std::string message; + }; + + static thread_local ErrorState globalError; + ThreadLocal error; + ErrorFunction errorFunc = nullptr; + void* errorUserPtr = nullptr; + + // Parameters + int numThreads = 0; // autodetect by default + bool setAffinity = true; + + bool dirty = true; + + public: + Device(); + ~Device(); + + static void setError(Device* device, Error code, const std::string& message); + static Error getError(Device* device, const char** outMessage); + + void setErrorFunction(ErrorFunction func, void* userPtr); + + int get1i(const std::string& name); + void set1i(const std::string& name, int value); + + void commit(); + + Ref newBuffer(size_t byteSize); + Ref newBuffer(void* ptr, size_t byteSize); + Ref newFilter(const std::string& type); + + __forceinline Device* getDevice() { return this; } + __forceinline std::mutex& getMutex() { return mutex; } + + private: + bool isCommitted() const { return false; } + void checkCommitted(); + + void print(); + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/filter.cpp b/thirdparty/oidn/core/filter.cpp new file mode 100644 index 0000000000..ec1f10af87 --- /dev/null +++ b/thirdparty/oidn/core/filter.cpp @@ -0,0 +1,27 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "filter.h" + +namespace oidn { + + void Filter::setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr) + { + progressFunc = func; + progressUserPtr = userPtr; + } + +} // namespace oidn diff --git a/thirdparty/oidn/core/filter.h b/thirdparty/oidn/core/filter.h new file mode 100644 index 0000000000..935fa202f4 --- /dev/null +++ b/thirdparty/oidn/core/filter.h @@ -0,0 +1,52 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "common.h" +#include "device.h" +#include "image.h" + +namespace oidn { + + class Filter : public RefCount + { + protected: + Ref device; + + ProgressMonitorFunction progressFunc = nullptr; + void* progressUserPtr = nullptr; + + bool dirty = true; + + public: + explicit Filter(const Ref& device) : device(device) {} + + virtual void setImage(const std::string& name, const Image& data) = 0; + virtual void set1i(const std::string& name, int value) = 0; + virtual int get1i(const std::string& name) = 0; + virtual void set1f(const std::string& name, float value) = 0; + virtual float get1f(const std::string& name) = 0; + + void setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr); + + virtual void commit() = 0; + virtual void execute() = 0; + + Device* getDevice() { return device.get(); } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/image.h b/thirdparty/oidn/core/image.h new file mode 100644 index 0000000000..748f49c4e5 --- /dev/null +++ b/thirdparty/oidn/core/image.h @@ -0,0 +1,111 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "common.h" +#include "buffer.h" + +namespace oidn { + + struct Image + { + static constexpr int maxSize = 65536; + + char* ptr; // pointer to the first pixel + int width; // width in number of pixels + int height; // height in number of pixels + size_t bytePixelStride; // pixel stride in number of *bytes* + size_t rowStride; // row stride in number of *pixel strides* + Format format; // pixel format + Ref buffer; // buffer containing the image data + + Image() : ptr(nullptr), width(0), height(0), bytePixelStride(0), rowStride(0), format(Format::Undefined) {} + + Image(void* ptr, Format format, int width, int height, size_t byteOffset, size_t inBytePixelStride, size_t inByteRowStride) + { + if (ptr == nullptr) + throw Exception(Error::InvalidArgument, "buffer pointer null"); + + init((char*)ptr + byteOffset, format, width, height, inBytePixelStride, inByteRowStride); + } + + Image(const Ref& buffer, Format format, int width, int height, size_t byteOffset, size_t inBytePixelStride, size_t inByteRowStride) + { + init(buffer->data() + byteOffset, format, width, height, inBytePixelStride, inByteRowStride); + + if (byteOffset + height * rowStride * bytePixelStride > buffer->size()) + throw Exception(Error::InvalidArgument, "buffer region out of range"); + } + + void init(char* ptr, Format format, int width, int height, size_t inBytePixelStride, size_t inByteRowStride) + { + assert(width >= 0); + assert(height >= 0); + if (width > maxSize || height > maxSize) + throw Exception(Error::InvalidArgument, "image size too large"); + + this->ptr = ptr; + this->width = width; + this->height = height; + + const size_t pixelSize = getFormatBytes(format); + if (inBytePixelStride != 0) + { + if (inBytePixelStride < pixelSize) + throw Exception(Error::InvalidArgument, "pixel stride smaller than pixel size"); + + this->bytePixelStride = inBytePixelStride; + } + else + { + this->bytePixelStride = pixelSize; + } + + if (inByteRowStride != 0) + { + if (inByteRowStride < width * this->bytePixelStride) + throw Exception(Error::InvalidArgument, "row stride smaller than width * pixel stride"); + if (inByteRowStride % this->bytePixelStride != 0) + throw Exception(Error::InvalidArgument, "row stride not integer multiple of pixel stride"); + + this->rowStride = inByteRowStride / this->bytePixelStride; + } + else + { + this->rowStride = width; + } + + this->format = format; + } + + __forceinline char* get(int y, int x) + { + return ptr + ((size_t(y) * rowStride + size_t(x)) * bytePixelStride); + } + + __forceinline const char* get(int y, int x) const + { + return ptr + ((size_t(y) * rowStride + size_t(x)) * bytePixelStride); + } + + operator bool() const + { + return ptr != nullptr; + } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/input_reorder.h b/thirdparty/oidn/core/input_reorder.h new file mode 100644 index 0000000000..966856afe9 --- /dev/null +++ b/thirdparty/oidn/core/input_reorder.h @@ -0,0 +1,232 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "node.h" +#include "image.h" + +namespace oidn { + + // Input reorder node + template + class InputReorderNode : public Node + { + private: + // Source + Image color; + Image albedo; + Image normal; + + // Destination + std::shared_ptr dst; + float* dstPtr; + int C2; + int H2; + int W2; + + // Tile + int h1Begin; + int w1Begin; + int h2Begin; + int w2Begin; + int H; + int W; + + std::shared_ptr transferFunc; + + public: + InputReorderNode(const Image& color, + const Image& albedo, + const Image& normal, + const std::shared_ptr& dst, + const std::shared_ptr& transferFunc) + : color(color), albedo(albedo), normal(normal), + dst(dst), + h1Begin(0), w1Begin(0), + H(color.height), W(color.width), + transferFunc(transferFunc) + { + const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data; + assert(memory_desc_matches_tag(dstDesc, mkldnn_format_tag_t(BlockedFormat::nChwKc))); + assert(dstDesc.ndims == 4); + assert(dstDesc.data_type == memory::data_type::f32); + assert(dstDesc.dims[0] == 1); + //assert(dstDesc.dims[1] >= getPadded(C1)); + + dstPtr = (float*)dst->get_data_handle(); + C2 = dstDesc.dims[1]; + H2 = dstDesc.dims[2]; + W2 = dstDesc.dims[3]; + } + + void setTile(int h1, int w1, int h2, int w2, int H, int W) override + { + h1Begin = h1; + w1Begin = w1; + h2Begin = h2; + w2Begin = w2; + this->H = H; + this->W = W; + } + + void execute(stream& sm) override + { + assert(H + h1Begin <= color.height); + assert(W + w1Begin <= color.width); + assert(H + h2Begin <= H2); + assert(W + w2Begin <= W2); + + parallel_nd(H2, [&](int h2) + { + const int h = h2 - h2Begin; + + if (h >= 0 && h < H) + { + const int h1 = h + h1Begin; + + // Zero pad + for (int w2 = 0; w2 < w2Begin; ++w2) + { + int c = 0; + while (c < C2) + store(h2, w2, c, 0.f); + } + + // Reorder + for (int w = 0; w < W; ++w) + { + const int w1 = w + w1Begin; + const int w2 = w + w2Begin; + + int c = 0; + storeColor(h2, w2, c, (float*)color.get(h1, w1)); + if (albedo) + storeAlbedo(h2, w2, c, (float*)albedo.get(h1, w1)); + if (normal) + storeNormal(h2, w2, c, (float*)normal.get(h1, w1)); + while (c < C2) + store(h2, w2, c, 0.f); + } + + // Zero pad + for (int w2 = W + w2Begin; w2 < W2; ++w2) + { + int c = 0; + while (c < C2) + store(h2, w2, c, 0.f); + } + } + else + { + // Zero pad + for (int w2 = 0; w2 < W2; ++w2) + { + int c = 0; + while (c < C2) + store(h2, w2, c, 0.f); + } + } + }); + } + + std::shared_ptr getDst() const override { return dst; } + + private: + // Stores a single value + __forceinline void store(int h, int w, int& c, float value) + { + // Destination is in nChwKc format + float* dst_c = dstPtr + (H2*W2*K*(c/K)) + h*W2*K + w*K + (c%K); + *dst_c = value; + c++; + } + + // Stores a color + __forceinline void storeColor(int h, int w, int& c, const float* values) + { + #pragma unroll + for (int i = 0; i < 3; ++i) + { + // Load the value + float x = values[i]; + + // Sanitize the value + x = maxSafe(x, 0.f); + + // Apply the transfer function + x = transferFunc->forward(x); + + // Store the value + store(h, w, c, x); + } + } + + // Stores an albedo + __forceinline void storeAlbedo(int h, int w, int& c, const float* values) + { + #pragma unroll + for (int i = 0; i < 3; ++i) + { + // Load the value + float x = values[i]; + + // Sanitize the value + x = clampSafe(x, 0.f, 1.f); + + // Store the value + store(h, w, c, x); + } + } + + // Stores a normal + __forceinline void storeNormal(int h, int w, int& c, const float* values) + { + // Load the normal + float x = values[0]; + float y = values[1]; + float z = values[2]; + + // Compute the length of the normal + const float lengthSqr = sqr(x) + sqr(y) + sqr(z); + + // Normalize the normal and transform it to [0..1] + if (isfinite(lengthSqr)) + { + const float invLength = (lengthSqr > minVectorLengthSqr) ? rsqrt(lengthSqr) : 1.f; + + const float scale = invLength * 0.5f; + const float offset = 0.5f; + + x = x * scale + offset; + y = y * scale + offset; + z = z * scale + offset; + } + else + { + x = 0.f; + y = 0.f; + z = 0.f; + } + + // Store the normal + store(h, w, c, x); + store(h, w, c, y); + store(h, w, c, z); + } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/math.h b/thirdparty/oidn/core/math.h new file mode 100644 index 0000000000..a844ef0d1d --- /dev/null +++ b/thirdparty/oidn/core/math.h @@ -0,0 +1,78 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "common/platform.h" + +namespace oidn { + + constexpr float minVectorLength = 1e-10f; + constexpr float minVectorLengthSqr = minVectorLength * minVectorLength; + + using std::log; + using std::log2; + using std::exp; + using std::exp2; + using std::pow; + using std::isfinite; + using std::isnan; + + __forceinline float sqr(float x) + { + return x * x; + } + + __forceinline float rcp(float x) + { + __m128 r = _mm_rcp_ss(_mm_set_ss(x)); + return _mm_cvtss_f32(_mm_sub_ss(_mm_add_ss(r, r), _mm_mul_ss(_mm_mul_ss(r, r), _mm_set_ss(x)))); + } + + __forceinline float rsqrt(float x) + { + __m128 r = _mm_rsqrt_ss(_mm_set_ss(x)); + return _mm_cvtss_f32(_mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r), + _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(_mm_set_ss(x), _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)))); + } + + __forceinline float maxSafe(float value, float minValue) + { + return isfinite(value) ? max(value, minValue) : minValue; + } + + __forceinline float clampSafe(float value, float minValue, float maxValue) + { + return isfinite(value) ? clamp(value, minValue, maxValue) : minValue; + } + + // Returns ceil(a / b) for non-negative integers + template + __forceinline constexpr Int ceilDiv(Int a, Int b) + { + //assert(a >= 0); + //assert(b > 0); + return (a + b - 1) / b; + } + + // Returns a rounded up to multiple of b + template + __forceinline constexpr Int roundUp(Int a, Int b) + { + return ceilDiv(a, b) * b; + } + +} // namespace oidn diff --git a/thirdparty/oidn/core/network.cpp b/thirdparty/oidn/core/network.cpp new file mode 100644 index 0000000000..4da32073cd --- /dev/null +++ b/thirdparty/oidn/core/network.cpp @@ -0,0 +1,434 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "network.h" +#include "upsample.h" +#include "weights_reorder.h" +#include + +namespace oidn { + + template + Network::Network(const Ref& device, const std::map& weightMap) + : device(device), + eng(engine::cpu, 0), + sm(eng), + weightMap(weightMap) + { + } + + template + void Network::execute(const Progress& progress, int taskIndex) + { + if (progress.func) + { + const double value = double(taskIndex) / double(progress.taskCount); + if (!progress.func(progress.userPtr, value)) + throw Exception(Error::Cancelled, "execution was cancelled"); + } + + for (size_t i = 0; i < nodes.size(); ++i) + { + nodes[i]->execute(sm); + + if (progress.func) + { + const double value = (double(taskIndex) + double(i+1) / double(nodes.size())) / double(progress.taskCount); + if (!progress.func(progress.userPtr, value)) + throw Exception(Error::Cancelled, "execution was cancelled"); + } + } + } + + template + std::shared_ptr Network::allocTensor(const memory::dims& dims, + memory::format_tag format, + void* data) + { + if (format == memory::format_tag::any) + { + if (dims.size() == 4) + format = BlockedFormat::nChwKc; + else if (dims.size() == 1) + format = memory::format_tag::x; + else + assert(0); + } + memory::desc desc(dims, memory::data_type::f32, format); + if (data == nullptr) + { + const size_t bytes = getTensorSize(dims) * sizeof(float); + if (format == BlockedFormat::nChwKc) + activationAllocBytes += bytes; + totalAllocBytes += bytes; + + return std::make_shared(desc, eng); + } + else + { + return std::make_shared(desc, eng, data); + } + } + + template + std::shared_ptr Network::castTensor(const memory::dims& dims, + const std::shared_ptr& src, + size_t srcOffset, + memory::format_tag format) + { + const mkldnn_memory_desc_t& srcDesc = src->get_desc().data; + MAYBE_UNUSED(srcDesc); + assert(srcDesc.data_type == memory::data_type::f32); + assert(getTensorSize(src) >= srcOffset + getTensorSize(dims)); + + if (format == memory::format_tag::any) + { + if (dims.size() == 4) + format = BlockedFormat::nChwKc; + else if (dims.size() == 1) + format = memory::format_tag::x; + else + assert(0); + } + memory::desc desc(dims, memory::data_type::f32, format); + float* srcPtr = (float*)src->get_data_handle() + srcOffset; + return std::make_shared(desc, eng, srcPtr); + } + + template + std::shared_ptr Network::castTensor(const memory::dims& dims, + const std::shared_ptr& src, + const memory::dims& srcOffset) + { + return castTensor(dims, src, getTensorSize(srcOffset)); + } + + template + void Network::zeroTensor(const std::shared_ptr& dst) + { + assert(getTensorType(dst) == memory::data_type::f32); + memset(dst->get_data_handle(), 0, getTensorSize(dst)*sizeof(float)); + } + + template + memory::dims Network::getInputReorderDims(const memory::dims& srcDims, int alignment) + { + memory::dims dstDims = srcDims; + dstDims[1] = getPadded(srcDims[1]); // round up C + dstDims[2] = roundUp(srcDims[2], memory::dim(alignment)); // round up H + dstDims[3] = roundUp(srcDims[3], memory::dim(alignment)); // round up W + return dstDims; + } + + template + std::shared_ptr Network::addInputReorder(const Image& color, + const Image& albedo, + const Image& normal, + const std::shared_ptr& transferFunc, + int alignment, + const std::shared_ptr& userDst) + { + assert(color); + int inputC = 3; + if (albedo) inputC += 3; + if (normal) inputC += 3; + + memory::dims srcDims = {1, inputC, color.height, color.width}; + memory::dims dstDims = getInputReorderDims(srcDims, alignment); + + // Allocate padded memory + auto dst = userDst; + if (!dst) + dst = allocTensor(dstDims); + + // Push node + std::shared_ptr node; + + if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(color, albedo, normal, dst, tf); + else if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(color, albedo, normal, dst, tf); + else if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(color, albedo, normal, dst, tf); + else if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(color, albedo, normal, dst, tf); + else + assert(0); + + nodes.push_back(node); + return node; + } + + template + std::shared_ptr Network::addOutputReorder(const std::shared_ptr& src, + const std::shared_ptr& transferFunc, + const Image& output) + { + memory::dims srcDims = getTensorDims(src); + assert(srcDims[1] == K); + + // Push node + std::shared_ptr node; + + if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(src, output, tf); + else if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(src, output, tf); + else if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(src, output, tf); + else if (auto tf = std::dynamic_pointer_cast(transferFunc)) + node = std::make_shared>(src, output, tf); + else + assert(0); + + nodes.push_back(node); + return node; + } + + template + memory::dims Network::getConvDims(const std::string& name, const memory::dims& srcDims) + { + auto b = weightMap[name + "/b"]; + memory::dims dstDims = srcDims; + dstDims[1] = getPadded(b.dims[0]); // dstDims[C] = getPadded(OC) + return dstDims; + } + + template + std::shared_ptr Network::addConv(const std::string& name, + const std::shared_ptr& src, + const std::shared_ptr& userDst, + bool relu) + { + const memory::dims strides = {1, 1}; + const memory::dims padding = {1, 1}; + + memory::dims srcDims = getTensorDims(src); + + // Get the weights + const auto& W = weightMap[name + "/W"]; + if (W.ndims() != 4 || W.format != "oihw") + throw Exception(Error::InvalidOperation, "invalid convolution weights"); + memory::dims weightsDims = W.dims; + auto userWeights = allocTensor(weightsDims, memory::format_tag::oihw, W.data); + + // Pad the weights + memory::dims weightsPadDims = weightsDims; + weightsPadDims[1] = getPadded(weightsDims[1]); // IC + weightsPadDims[0] = getPadded(weightsDims[0]); // OC + assert(srcDims[1] == weightsPadDims[1]); // srcDims[C] == weightsPadDims[IC] + auto weightsPad = allocTensor(weightsPadDims, memory::format_tag::oihw); + WeightsReorderNode(userWeights, weightsPad).execute(sm); + + // Get the biases + const auto& b = weightMap[name + "/b"]; + if (b.ndims() != 1) + throw Exception(Error::InvalidOperation, "invalid convolution biases"); + memory::dims biasDims = b.dims; + + // Copy/pad the biases + memory::dims biasPadDims = {getPadded(biasDims[0])}; + auto bias = allocTensor(biasPadDims); + if (biasDims[0] != biasPadDims[0]) + memset(bias->get_data_handle(), 0, biasPadDims[0]*sizeof(float)); + memcpy(bias->get_data_handle(), b.data, biasDims[0]*sizeof(float)); + + // Allocate memory for destination + memory::dims dstDims = srcDims; + dstDims[1] = weightsPadDims[0]; // dstDims[C] = weightsPadDims[OC] + + std::shared_ptr dst; + if (!userDst) + dst = allocTensor(dstDims); + else if (getTensorDims(userDst) == dstDims) + dst = userDst; + else + dst = castTensor(dstDims, userDst); + + // Create a convolution + // Let the convolution primitive choose the weights format + auto weightsDesc = memory::desc({ weightsPadDims }, memory::data_type::f32, memory::format_tag::any); + + auto convAlgo = (K == 16) ? convolution_winograd : convolution_direct; + auto convDesc = convolution_forward::desc( + prop_kind::forward_inference, convAlgo, + src->get_desc(), + weightsDesc, + bias->get_desc(), + dst->get_desc(), + strides, padding, padding, padding_kind::zero); + + // Incorporate relu + mkldnn::primitive_attr convAttr; + if (relu) + { + mkldnn::post_ops ops; + ops.append_eltwise( + 1.f, // scale factor, not used + algorithm::eltwise_relu, + 0.f, // max with + 0.f // unused + ); + convAttr.set_post_ops(ops); + } + convAttr.set_scratchpad_mode(scratchpad_mode_user); + + auto convPrimDesc = convolution_forward::primitive_desc(convDesc, convAttr, eng); + + // Reorder the weights to the final format, if necessary + auto weights = weightsPad; + if (convPrimDesc.weights_desc() != weightsPad->get_desc()) + { + weights = std::make_shared(convPrimDesc.weights_desc(), eng); + ReorderNode(weightsPad, weights).execute(sm); + } + + // Create convolution node and add it to the net + auto node = std::make_shared(convPrimDesc, src, weights, bias, dst); + nodes.push_back(node); + return node; + } + + template + memory::dims Network::getPoolDims(const memory::dims& srcDims) + { + memory::dims dstDims = srcDims; + dstDims[2] /= 2; // H/2 + dstDims[3] /= 2; // W/2 + return dstDims; + } + + template + std::shared_ptr Network::addPool(const std::shared_ptr& src, + const std::shared_ptr& userDst) + { + const memory::dims kernel = {2, 2}; + const memory::dims strides = {2, 2}; + const memory::dims padding = {0, 0}; + + memory::dims srcDims = getTensorDims(src); + memory::dims dstDims = getPoolDims(srcDims); + + std::shared_ptr dst; + if (!userDst) + dst = allocTensor(dstDims); + else if (getTensorDims(userDst) == dstDims) + dst = userDst; + else + dst = castTensor(dstDims, userDst); + + auto poolDesc = pooling_forward::desc( + prop_kind::forward_inference, pooling_max, + src->get_desc(), + dst->get_desc(), + strides, kernel, padding, padding, padding_kind::zero); + + mkldnn::primitive_attr poolAttr; + poolAttr.set_scratchpad_mode(scratchpad_mode_user); + + auto poolPrimDesc = pooling_forward::primitive_desc(poolDesc, poolAttr, eng); + + auto node = std::make_shared(poolPrimDesc, src, dst); + nodes.push_back(node); + return node; + } + + template + memory::dims Network::getUpsampleDims(const memory::dims& srcDims) + { + memory::dims dstDims = srcDims; + dstDims[2] *= 2; // H*2 + dstDims[3] *= 2; // W*2 + return dstDims; + } + + template + std::shared_ptr Network::addUpsample(const std::shared_ptr& src, + const std::shared_ptr& userDst) + { + memory::dims srcDims = getTensorDims(src); + memory::dims dstDims = getUpsampleDims(srcDims); + + std::shared_ptr dst; + if (!userDst) + dst = allocTensor(dstDims); + else if (getTensorDims(userDst) == dstDims) + dst = userDst; + else + dst = castTensor(dstDims, userDst); + + // Create upsampling node and add it to net + auto node = std::make_shared>(src, dst); + nodes.push_back(node); + return node; + } + + template + memory::dims Network::getConcatDims(const memory::dims& src1Dims, const memory::dims& src2Dims) + { + assert(src1Dims[0] == src2Dims[0]); // N + assert(src1Dims[2] == src2Dims[2]); // H + assert(src1Dims[3] == src2Dims[3]); // W + + memory::dims dstDims = src1Dims; + dstDims[1] += src2Dims[1]; // C + return dstDims; + } + + template + std::shared_ptr Network::addAutoexposure(const Image& color, + const std::shared_ptr& transferFunc) + { + auto node = std::make_shared(color, transferFunc); + nodes.push_back(node); + return node; + } + + template + void Network::finalize() + { + // Compute the size of the scratchpad + size_t scratchpadSize = 0; + for (const auto& node : nodes) + scratchpadSize = max(scratchpadSize, node->getScratchpadSize()); + + // Allocate the scratchpad + memory::dims scratchpadDims = { memory::dim(scratchpadSize) }; + memory::desc scratchpadDesc(scratchpadDims, memory::data_type::u8, memory::format_tag::x); + auto scratchpad = std::make_shared(scratchpadDesc, eng); + activationAllocBytes += scratchpadSize; + totalAllocBytes += scratchpadSize; + + // Set the scratchpad for the nodes + for (auto& node : nodes) + node->setScratchpad(scratchpad); + + // Free the weights + weightMap.clear(); + + // Print statistics + if (device->isVerbose(2)) + { + std::cout << "Activation bytes: " << activationAllocBytes << std::endl; + std::cout << "Scratchpad bytes: " << scratchpadSize << std::endl; + std::cout << "Total bytes : " << totalAllocBytes << std::endl; + } + } + + template class Network<8>; + template class Network<16>; + +} // namespace oidn diff --git a/thirdparty/oidn/core/network.h b/thirdparty/oidn/core/network.h new file mode 100644 index 0000000000..7a696fd355 --- /dev/null +++ b/thirdparty/oidn/core/network.h @@ -0,0 +1,112 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "common/tensor.h" +#include "image.h" +#include "node.h" +#include "input_reorder.h" +#include "output_reorder.h" +#include "transfer_function.h" + +#pragma once + +namespace oidn { + + // Progress state + struct Progress + { + ProgressMonitorFunction func; + void* userPtr; + int taskCount; + }; + + class Executable + { + public: + virtual ~Executable() {} + virtual void execute(const Progress& progress, int taskIndex) = 0; + }; + + template + class Network : public Executable + { + public: + Network(const Ref& device, const std::map& weightMap); + + void execute(const Progress& progress, int taskIndex) override; + + std::shared_ptr allocTensor(const memory::dims& dims, + memory::format_tag format = memory::format_tag::any, + void* data = nullptr); + + std::shared_ptr castTensor(const memory::dims& dims, + const std::shared_ptr& src, + size_t srcOffset = 0, + memory::format_tag format = memory::format_tag::any); + + std::shared_ptr castTensor(const memory::dims& dims, + const std::shared_ptr& src, + const memory::dims& srcOffset); + + void zeroTensor(const std::shared_ptr& dst); + + memory::dims getInputReorderDims(const memory::dims& srcDims, int alignment); + + std::shared_ptr addInputReorder(const Image& color, + const Image& albedo, + const Image& normal, + const std::shared_ptr& transferFunc, + int alignment, + const std::shared_ptr& userDst = nullptr); + + std::shared_ptr addOutputReorder(const std::shared_ptr& src, + const std::shared_ptr& transferFunc, + const Image& output); + + memory::dims getConvDims(const std::string& name, const memory::dims& srcDims); + std::shared_ptr addConv(const std::string& name, + const std::shared_ptr& src, + const std::shared_ptr& userDst = nullptr, + bool relu = true); + + memory::dims getPoolDims(const memory::dims& srcDims); + std::shared_ptr addPool(const std::shared_ptr& src, + const std::shared_ptr& userDst = nullptr); + + memory::dims getUpsampleDims(const memory::dims& srcDims); + std::shared_ptr addUpsample(const std::shared_ptr& src, + const std::shared_ptr& userDst = nullptr); + + memory::dims getConcatDims(const memory::dims& src1Dims, const memory::dims& src2Dims); + + std::shared_ptr addAutoexposure(const Image& color, + const std::shared_ptr& transferFunc); + + void finalize(); + + private: + Ref device; + engine eng; + stream sm; + std::vector> nodes; + std::map weightMap; + + // Memory allocation statistics + size_t activationAllocBytes = 0; // number of allocated activation bytes + size_t totalAllocBytes = 0; // total number of allocated bytes + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/node.h b/thirdparty/oidn/core/node.h new file mode 100644 index 0000000000..b9ffe906df --- /dev/null +++ b/thirdparty/oidn/core/node.h @@ -0,0 +1,142 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "common.h" +#include + +namespace oidn { + + class Node + { + public: + virtual ~Node() = default; + + virtual void execute(stream& sm) = 0; + + virtual std::shared_ptr getDst() const { return nullptr; } + + virtual size_t getScratchpadSize() const { return 0; } + virtual void setScratchpad(const std::shared_ptr& mem) {} + + virtual void setTile(int h1, int w1, int h2, int w2, int H, int W) + { + assert(0); // not supported + } + }; + + // Node wrapping an MKL-DNN primitive + class MklNode : public Node + { + private: + primitive prim; + std::unordered_map args; + std::shared_ptr scratchpad; + + public: + MklNode(const primitive& prim, const std::unordered_map& args) + : prim(prim), + args(args) + {} + + size_t getScratchpadSize() const override + { + const auto primDesc = prim.get_primitive_desc(); + const mkldnn_memory_desc_t* scratchpadDesc = mkldnn_primitive_desc_query_md(primDesc, mkldnn_query_scratchpad_md, 0); + if (scratchpadDesc == nullptr) + return 0; + return mkldnn_memory_desc_get_size(scratchpadDesc); + } + + void setScratchpad(const std::shared_ptr& mem) override + { + scratchpad = mem; + args.insert(std::make_pair(MKLDNN_ARG_SCRATCHPAD, *scratchpad)); + } + + void execute(stream& sm) override + { + prim.execute(sm, args); + } + }; + + // Convolution node + class ConvNode : public MklNode + { + private: + std::shared_ptr src; + std::shared_ptr weights; + std::shared_ptr bias; + std::shared_ptr dst; + + public: + ConvNode(const convolution_forward::primitive_desc& desc, + const std::shared_ptr& src, + const std::shared_ptr& weights, + const std::shared_ptr& bias, + const std::shared_ptr& dst) + : MklNode(convolution_forward(desc), + { { MKLDNN_ARG_SRC, *src }, + { MKLDNN_ARG_WEIGHTS, *weights }, + { MKLDNN_ARG_BIAS, *bias }, + { MKLDNN_ARG_DST, *dst } }), + src(src), weights(weights), bias(bias), dst(dst) + {} + + std::shared_ptr getDst() const override { return dst; } + }; + + // Pooling node + class PoolNode : public MklNode + { + private: + std::shared_ptr src; + std::shared_ptr dst; + + public: + PoolNode(const pooling_forward::primitive_desc& desc, + const std::shared_ptr& src, + const std::shared_ptr& dst) + : MklNode(pooling_forward(desc), + { { MKLDNN_ARG_SRC, *src }, + { MKLDNN_ARG_DST, *dst } }), + src(src), dst(dst) + {} + + std::shared_ptr getDst() const override { return dst; } + }; + + // Reorder node + class ReorderNode : public MklNode + { + private: + std::shared_ptr src; + std::shared_ptr dst; + + public: + ReorderNode(const std::shared_ptr& src, + const std::shared_ptr& dst) + : MklNode(reorder(reorder::primitive_desc(*src, *dst)), + { { MKLDNN_ARG_SRC, *src }, + { MKLDNN_ARG_DST, *dst } }), + src(src), dst(dst) + {} + + std::shared_ptr getDst() const override { return dst; } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/output_reorder.h b/thirdparty/oidn/core/output_reorder.h new file mode 100644 index 0000000000..7918d48e15 --- /dev/null +++ b/thirdparty/oidn/core/output_reorder.h @@ -0,0 +1,126 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "node.h" +#include "image.h" + +namespace oidn { + + // Output reorder node + template + class OutputReorderNode : public Node + { + private: + // Source + std::shared_ptr src; + const float* srcPtr; + int H1; + int W1; + + // Destination + Image output; + + // Tile + int h1Begin; + int w1Begin; + int h2Begin; + int w2Begin; + int H; + int W; + + std::shared_ptr transferFunc; + + public: + OutputReorderNode(const std::shared_ptr& src, + const Image& output, + const std::shared_ptr& transferFunc) + : src(src), + output(output), + h1Begin(0), w1Begin(0), + h2Begin(0), w2Begin(0), + H(output.height), W(output.width), + transferFunc(transferFunc) + { + const mkldnn_memory_desc_t& srcDesc = src->get_desc().data; + MAYBE_UNUSED(srcDesc); + assert(memory_desc_matches_tag(srcDesc, mkldnn_format_tag_t(BlockedFormat::nChwKc))); + assert(srcDesc.ndims == 4); + assert(srcDesc.data_type == memory::data_type::f32); + assert(srcDesc.dims[0] == 1); + // We assume output data is <= K OC + assert(srcDesc.dims[1] == K); + + srcPtr = (float*)src->get_data_handle(); + H1 = srcDesc.dims[2]; + W1 = srcDesc.dims[3]; + } + + void setTile(int h1, int w1, int h2, int w2, int H, int W) override + { + h1Begin = h1; + w1Begin = w1; + h2Begin = h2; + w2Begin = w2; + this->H = H; + this->W = W; + } + + void execute(stream& sm) override + { + assert(h1Begin + H <= H1); + assert(w1Begin + W <= W1); + assert(h2Begin + H <= output.height); + assert(w2Begin + W <= output.width); + + const int C1 = K; + + parallel_nd(H, [&](int h) + { + const int h1 = h + h1Begin; + const int h2 = h + h2Begin; + + for (int w = 0; w < W; ++w) + { + const int w1 = w + w1Begin; + const int w2 = w + w2Begin; + float* dstPtr_C = (float*)output.get(h2, w2); + + // Source is in nChwKc format. In this case C is 1 so this is really nhwc + const float* srcPtr_C = srcPtr + h1*W1*C1 + w1*C1; + + #pragma unroll + for (int i = 0; i < 3; ++i) + { + // Load the value + float x = srcPtr_C[i]; + + // The CNN output may contain negative values or even NaNs, so it must be sanitized + x = maxSafe(x, 0.f); + + // Apply the inverse transfer function + x = transferFunc->inverse(x); + + // Sanitize and store the final value + dstPtr_C[i] = max(x, 0.f); + } + } + }); + } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/transfer_function.cpp b/thirdparty/oidn/core/transfer_function.cpp new file mode 100644 index 0000000000..a33e3c84bc --- /dev/null +++ b/thirdparty/oidn/core/transfer_function.cpp @@ -0,0 +1,95 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#include "transfer_function.h" + +namespace oidn { + + const float LogTransferFunction::xScale = 1.f / log(LogTransferFunction::yMax + 1.f); + const float PQXTransferFunction::xScale = 1.f / PQXTransferFunction::pqxForward(PQXTransferFunction::yMax * PQXTransferFunction::yScale); + + float AutoexposureNode::autoexposure(const Image& color) + { + assert(color.format == Format::Float3); + return 1.0f; + + /*constexpr float key = 0.18f; + constexpr float eps = 1e-8f; + constexpr int K = 16; // downsampling amount + + // Downsample the image to minimize sensitivity to noise + const int H = color.height; // original height + const int W = color.width; // original width + const int HK = (H + K/2) / K; // downsampled height + const int WK = (W + K/2) / K; // downsampled width + + // Compute the average log luminance of the downsampled image + using Sum = std::pair; + + Sum sum = + tbb::parallel_reduce( + tbb::blocked_range2d(0, HK, 0, WK), + Sum(0.f, 0), + [&](const tbb::blocked_range2d& r, Sum sum) -> Sum + { + // Iterate over blocks + for (int i = r.rows().begin(); i != r.rows().end(); ++i) + { + for (int j = r.cols().begin(); j != r.cols().end(); ++j) + { + // Compute the average luminance in the current block + const int beginH = int(ptrdiff_t(i) * H / HK); + const int beginW = int(ptrdiff_t(j) * W / WK); + const int endH = int(ptrdiff_t(i+1) * H / HK); + const int endW = int(ptrdiff_t(j+1) * W / WK); + + float L = 0.f; + + for (int h = beginH; h < endH; ++h) + { + for (int w = beginW; w < endW; ++w) + { + const float* rgb = (const float*)color.get(h, w); + + const float r = maxSafe(rgb[0], 0.f); + const float g = maxSafe(rgb[1], 0.f); + const float b = maxSafe(rgb[2], 0.f); + + L += luminance(r, g, b); + } + } + + L /= (endH - beginH) * (endW - beginW); + + // Accumulate the log luminance + if (L > eps) + { + sum.first += log2(L); + sum.second++; + } + } + } + + return sum; + }, + [](Sum a, Sum b) -> Sum { return Sum(a.first+b.first, a.second+b.second); }, + tbb::static_partitioner() + ); + + return (sum.second > 0) ? (key / exp2(sum.first / float(sum.second))) : 1.f;*/ + } + +} // namespace oidn diff --git a/thirdparty/oidn/core/transfer_function.h b/thirdparty/oidn/core/transfer_function.h new file mode 100644 index 0000000000..35f2833092 --- /dev/null +++ b/thirdparty/oidn/core/transfer_function.h @@ -0,0 +1,201 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "image.h" +#include "node.h" + +namespace oidn { + + __forceinline float luminance(float r, float g, float b) + { + return 0.212671f * r + 0.715160f * g + 0.072169f * b; + } + + // Color transfer function base class + class TransferFunction + { + public: + virtual ~TransferFunction() = default; + + virtual float forward(float y) const = 0; + virtual float inverse(float x) const = 0; + }; + + // HDR transfer function base class + class HDRTransferFunction : public TransferFunction + { + protected: + static constexpr float yMax = 65504.f; + + float exposure; + float rcpExposure; + + public: + HDRTransferFunction(float exposure = 1.f) + { + setExposure(exposure); + } + + void setExposure(float exposure) + { + this->exposure = exposure; + this->rcpExposure = (exposure != 0.f) ? (1.f / exposure) : 0.f; + } + }; + + // Linear transfer function (LDR) + class LinearTransferFunction : public TransferFunction + { + public: + __forceinline float forward(float y) const override + { + return min(y, 1.f); + } + + __forceinline float inverse(float x) const override + { + return min(x, 1.f); + } + }; + + // 2.2 gamma transfer function (LDR) + class GammaTransferFunction : public TransferFunction + { + public: + __forceinline float forward(float y) const override + { + return min(pow(y, 1.f/2.2f), 1.f); + } + + __forceinline float inverse(float x) const override + { + return min(pow(x, 2.2f), 1.f); + } + }; + + // Logarithmic transfer function (HDR) + // Compresses [0..65504] to [0..1] + class LogTransferFunction : public HDRTransferFunction + { + private: + static const float xScale; + + public: + LogTransferFunction(float exposure = 1.f) + : HDRTransferFunction(exposure) + { + } + + __forceinline float forward(float y) const override + { + return log(y * exposure + 1.f) * xScale; + } + + __forceinline float inverse(float x) const override + { + return (exp(x * (1.f/xScale)) - 1.f) * rcpExposure; + } + }; + + // PQX transfer function (HDR) + // Compresses [0..65504] to [0..1] + class PQXTransferFunction : public HDRTransferFunction + { + private: + static constexpr float m1 = 2610.f / 4096.f / 4.f; + static constexpr float m2 = 2523.f / 4096.f * 128.f; + static constexpr float c1 = 3424.f / 4096.f; + static constexpr float c2 = 2413.f / 4096.f * 32.f; + static constexpr float c3 = 2392.f / 4096.f * 32.f; + static constexpr float a = 3711.f / 4096.f / 8.f; + + static constexpr float yScale = 100.f / 10000.f; + static const float xScale; + + public: + PQXTransferFunction(float exposure = 1.f) + : HDRTransferFunction(exposure) + { + } + + __forceinline float forward(float y) const override + { + return pqxForward(y * exposure * yScale) * xScale; + } + + __forceinline float inverse(float x) const override + { + return pqxInverse(x * (1.f/xScale)) * (1.f/yScale) * rcpExposure; + } + + private: + static __forceinline float pqForward(float y) + { + const float yp = pow(y, m1); + return pow((c1 + c2 * yp) * rcp(1.f + c3 * yp), m2); + } + + static __forceinline float pqxForward(float y) + { + if (y <= 1.f) + return pqForward(y); + else + return a * log(y) + 1.f; + } + + static __forceinline float pqInverse(float x) + { + const float xp = pow(x, 1.f/m2); + return pow(max((xp - c1) * rcp(c2 - c3 * xp), 0.f), 1.f/m1); + } + + static __forceinline float pqxInverse(float x) + { + if (x <= 1.f) + return pqInverse(x); + else + return exp((x - 1.f) * (1.f/a)); + } + }; + + // Autoexposure node + class AutoexposureNode : public Node + { + private: + Image color; + std::shared_ptr transferFunc; + + public: + AutoexposureNode(const Image& color, + const std::shared_ptr& transferFunc) + : color(color), + transferFunc(transferFunc) + {} + + void execute(stream& sm) override + { + const float exposure = autoexposure(color); + //printf("exposure = %f\n", exposure); + transferFunc->setExposure(exposure); + } + + private: + static float autoexposure(const Image& color); + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/upsample.h b/thirdparty/oidn/core/upsample.h new file mode 100644 index 0000000000..f6cace44cd --- /dev/null +++ b/thirdparty/oidn/core/upsample.h @@ -0,0 +1,92 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "node.h" + +namespace oidn { + + // 2x2 nearest-neighbor upsampling node + template + class UpsampleNode : public Node + { + private: + std::shared_ptr src; + std::shared_ptr dst; + + public: + UpsampleNode(const std::shared_ptr& src, + const std::shared_ptr& dst) + : src(src), + dst(dst) + { + const mkldnn_memory_desc_t& srcDesc = src->get_desc().data; + const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data; + MAYBE_UNUSED(srcDesc); + MAYBE_UNUSED(dstDesc); + assert(memory_desc_matches_tag(srcDesc, mkldnn_format_tag_t(BlockedFormat::nChwKc))); + assert(memory_desc_matches_tag(dstDesc, mkldnn_format_tag_t(BlockedFormat::nChwKc))); + assert(srcDesc.ndims == 4); + assert(dstDesc.ndims == 4); + assert(srcDesc.data_type == memory::data_type::f32); + assert(dstDesc.data_type == memory::data_type::f32); + assert(srcDesc.dims[0] == 1); + assert(dstDesc.dims[0] == 1); + // 2x2 upsampling + assert(dstDesc.dims[2] == srcDesc.dims[2] * 2); + assert(dstDesc.dims[3] == srcDesc.dims[3] * 2); + } + + void execute(stream& sm) override + { + const mkldnn_memory_desc_t& srcDesc = src->get_desc().data; + + const float* srcPtr = (float*)src->get_data_handle(); + float* dstPtr = (float*)dst->get_data_handle(); + + const int C = srcDesc.dims[1]; + const int H = srcDesc.dims[2]; + const int W = srcDesc.dims[3]; + const int CK = C / K; + + parallel_nd(CK, H, [&](int ck, int h) + { + const size_t offset = ck*H*W*K + h*W*K; + const float* srcPtr_line = srcPtr + offset; + float* dstPtr_line0 = dstPtr + offset * 4; + float* dstPtr_line1 = dstPtr_line0 + W*2*K; // next line + + for (int w = 0; w < W; ++w) + { + #pragma unroll + for (int k = 0; k < K; k += 4) + { + const __m128 m = _mm_load_ps(&srcPtr_line[w*K + k]); + + _mm_stream_ps(&dstPtr_line0[w*2*K + k], m); + _mm_stream_ps(&dstPtr_line0[w*2*K+K + k], m); + _mm_stream_ps(&dstPtr_line1[w*2*K + k], m); + _mm_stream_ps(&dstPtr_line1[w*2*K+K + k], m); + } + } + }); + } + + std::shared_ptr getDst() const override { return dst; } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/core/weights_reorder.h b/thirdparty/oidn/core/weights_reorder.h new file mode 100644 index 0000000000..6c5dacb8aa --- /dev/null +++ b/thirdparty/oidn/core/weights_reorder.h @@ -0,0 +1,99 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include "node.h" + +namespace oidn { + + // Reorders weights from oihw to padded oihw format + template + class WeightsReorderNode : public Node + { + private: + std::shared_ptr src; + std::shared_ptr dst; + + public: + WeightsReorderNode(const std::shared_ptr& src, + const std::shared_ptr& dst) + : src(src), + dst(dst) + { + const mkldnn_memory_desc_t& srcDesc = src->get_desc().data; + const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data; + MAYBE_UNUSED(srcDesc); + MAYBE_UNUSED(dstDesc); + assert(memory_desc_matches_tag(srcDesc, mkldnn_format_tag_t(memory::format_tag::oihw))); + assert(memory_desc_matches_tag(dstDesc, mkldnn_format_tag_t(memory::format_tag::oihw))); + assert(srcDesc.ndims == 4); + assert(dstDesc.ndims == 4); + assert(srcDesc.data_type == memory::data_type::f32); + assert(dstDesc.data_type == memory::data_type::f32); + assert(getPadded(srcDesc.dims[0]) == dstDesc.dims[0]); // OC + assert(getPadded(srcDesc.dims[1]) == dstDesc.dims[1]); // IC + assert(srcDesc.dims[2] == dstDesc.dims[2]); + assert(srcDesc.dims[3] == dstDesc.dims[3]); + } + + void execute(stream& sm) override + { + const mkldnn_memory_desc_t& srcDesc = src->get_desc().data; + const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data; + + const float* srcPtr = (float*)src->get_data_handle(); + float* dstPtr = (float*)dst->get_data_handle(); + + const int OC1 = srcDesc.dims[0]; + const int OC2 = dstDesc.dims[0]; + const int IC1 = srcDesc.dims[1]; + const int IC2 = dstDesc.dims[1]; + const int H = dstDesc.dims[2]; + const int W = dstDesc.dims[3]; + + for (int oc = 0; oc < OC2; ++oc) + { + for (int ic = 0; ic < IC2; ++ic) + { + for (int h = 0; h < H; ++h) + { + for (int w = 0; w < W; ++w) + { + // Output is in oihw format + float* dstPtr_c = dstPtr + oc*IC2*H*W + ic*H*W + h*W + w; + + if (oc < OC1 && ic < IC1) + { + // Input is in oihw format + const float* srcPtr_c = srcPtr + oc*IC1*H*W + ic*H*W + h*W + w; + *dstPtr_c = *srcPtr_c; + } + else + { + // padding + *dstPtr_c = 0; + } + } + } + } + } + } + + std::shared_ptr getDst() const override { return dst; } + }; + +} // namespace oidn diff --git a/thirdparty/oidn/include/OpenImageDenoise/oidn.h b/thirdparty/oidn/include/OpenImageDenoise/oidn.h new file mode 100644 index 0000000000..57ba6baa21 --- /dev/null +++ b/thirdparty/oidn/include/OpenImageDenoise/oidn.h @@ -0,0 +1,214 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include +#include +#include + +#include "version.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef OIDN_API +#if defined(_WIN32) && !defined(OIDN_STATIC_LIB) +# define OIDN_API __declspec(dllimport) +#else +# define OIDN_API +#endif +#endif + +// ---------------------------------------------------------------------------- +// Device +// ---------------------------------------------------------------------------- + +// Device types +typedef enum +{ + OIDN_DEVICE_TYPE_DEFAULT = 0, // select device automatically + + OIDN_DEVICE_TYPE_CPU = 1, // CPU device +} OIDNDeviceType; + +// Error codes +typedef enum +{ + OIDN_ERROR_NONE = 0, // no error occurred + OIDN_ERROR_UNKNOWN = 1, // an unknown error occurred + OIDN_ERROR_INVALID_ARGUMENT = 2, // an invalid argument was specified + OIDN_ERROR_INVALID_OPERATION = 3, // the operation is not allowed + OIDN_ERROR_OUT_OF_MEMORY = 4, // not enough memory to execute the operation + OIDN_ERROR_UNSUPPORTED_HARDWARE = 5, // the hardware (e.g. CPU) is not supported + OIDN_ERROR_CANCELLED = 6, // the operation was cancelled by the user +} OIDNError; + +// Error callback function +typedef void (*OIDNErrorFunction)(void* userPtr, OIDNError code, const char* message); + +// Device handle +typedef struct OIDNDeviceImpl* OIDNDevice; + +// Creates a new device. +OIDN_API OIDNDevice oidnNewDevice(OIDNDeviceType type); + +// Retains the device (increments the reference count). +OIDN_API void oidnRetainDevice(OIDNDevice device); + +// Releases the device (decrements the reference count). +OIDN_API void oidnReleaseDevice(OIDNDevice device); + +// Sets a boolean parameter of the device. +OIDN_API void oidnSetDevice1b(OIDNDevice device, const char* name, bool value); + +// Sets an integer parameter of the device. +OIDN_API void oidnSetDevice1i(OIDNDevice device, const char* name, int value); + +// Gets a boolean parameter of the device. +OIDN_API bool oidnGetDevice1b(OIDNDevice device, const char* name); + +// Gets an integer parameter of the device (e.g. "version"). +OIDN_API int oidnGetDevice1i(OIDNDevice device, const char* name); + +// Sets the error callback function of the device. +OIDN_API void oidnSetDeviceErrorFunction(OIDNDevice device, OIDNErrorFunction func, void* userPtr); + +// Returns the first unqueried error code stored in the device for the current +// thread, optionally also returning a string message (if not NULL), and clears +// the stored error. Can be called with a NULL device as well to check why a +// device creation failed. +OIDN_API OIDNError oidnGetDeviceError(OIDNDevice device, const char** outMessage); + +// Commits all previous changes to the device. +// Must be called before first using the device (e.g. creating filters). +OIDN_API void oidnCommitDevice(OIDNDevice device); + +// ---------------------------------------------------------------------------- +// Buffer +// ---------------------------------------------------------------------------- + +// Formats for images and other data stored in buffers +typedef enum +{ + OIDN_FORMAT_UNDEFINED = 0, + + // 32-bit single-precision floating point scalar and vector formats + OIDN_FORMAT_FLOAT = 1, + OIDN_FORMAT_FLOAT2 = 2, + OIDN_FORMAT_FLOAT3 = 3, + OIDN_FORMAT_FLOAT4 = 4, +} OIDNFormat; + +// Access modes for mapping buffers +typedef enum +{ + OIDN_ACCESS_READ = 0, // read-only access + OIDN_ACCESS_WRITE = 1, // write-only access + OIDN_ACCESS_READ_WRITE = 2, // read and write access + OIDN_ACCESS_WRITE_DISCARD = 3, // write-only access, previous contents discarded +} OIDNAccess; + +// Buffer handle +typedef struct OIDNBufferImpl* OIDNBuffer; + +// Creates a new buffer (data allocated and owned by the device). +OIDN_API OIDNBuffer oidnNewBuffer(OIDNDevice device, size_t byteSize); + +// Creates a new shared buffer (data allocated and owned by the user). +OIDN_API OIDNBuffer oidnNewSharedBuffer(OIDNDevice device, void* ptr, size_t byteSize); + +// Maps a region of the buffer to host memory. +// If byteSize is 0, the maximum available amount of memory will be mapped. +OIDN_API void* oidnMapBuffer(OIDNBuffer buffer, OIDNAccess access, size_t byteOffset, size_t byteSize); + +// Unmaps a region of the buffer. +// mappedPtr must be a pointer returned by a previous call to oidnMapBuffer. +OIDN_API void oidnUnmapBuffer(OIDNBuffer buffer, void* mappedPtr); + +// Retains the buffer (increments the reference count). +OIDN_API void oidnRetainBuffer(OIDNBuffer buffer); + +// Releases the buffer (decrements the reference count). +OIDN_API void oidnReleaseBuffer(OIDNBuffer buffer); + +// ---------------------------------------------------------------------------- +// Filter +// ---------------------------------------------------------------------------- + +// Progress monitor callback function +typedef bool (*OIDNProgressMonitorFunction)(void* userPtr, double n); + +// Filter handle +typedef struct OIDNFilterImpl* OIDNFilter; + +// Creates a new filter of the specified type (e.g. "RT"). +OIDN_API OIDNFilter oidnNewFilter(OIDNDevice device, const char* type); + +// Retains the filter (increments the reference count). +OIDN_API void oidnRetainFilter(OIDNFilter filter); + +// Releases the filter (decrements the reference count). +OIDN_API void oidnReleaseFilter(OIDNFilter filter); + +// Sets an image parameter of the filter (stored in a buffer). +// If bytePixelStride and/or byteRowStride are zero, these will be computed automatically. +OIDN_API void oidnSetFilterImage(OIDNFilter filter, const char* name, + OIDNBuffer buffer, OIDNFormat format, + size_t width, size_t height, + size_t byteOffset, + size_t bytePixelStride, size_t byteRowStride); + +// Sets an image parameter of the filter (owned by the user). +// If bytePixelStride and/or byteRowStride are zero, these will be computed automatically. +OIDN_API void oidnSetSharedFilterImage(OIDNFilter filter, const char* name, + void* ptr, OIDNFormat format, + size_t width, size_t height, + size_t byteOffset, + size_t bytePixelStride, size_t byteRowStride); + +// Sets a boolean parameter of the filter. +OIDN_API void oidnSetFilter1b(OIDNFilter filter, const char* name, bool value); + +// Gets a boolean parameter of the filter. +OIDN_API bool oidnGetFilter1b(OIDNFilter filter, const char* name); + +// Sets an integer parameter of the filter. +OIDN_API void oidnSetFilter1i(OIDNFilter filter, const char* name, int value); + +// Gets an integer parameter of the filter. +OIDN_API int oidnGetFilter1i(OIDNFilter filter, const char* name); + +// Sets a float parameter of the filter. +OIDN_API void oidnSetFilter1f(OIDNFilter filter, const char* name, float value); + +// Gets a float parameter of the filter. +OIDN_API float oidnGetFilter1f(OIDNFilter filter, const char* name); + +// Sets the progress monitor callback function of the filter. +OIDN_API void oidnSetFilterProgressMonitorFunction(OIDNFilter filter, OIDNProgressMonitorFunction func, void* userPtr); + +// Commits all previous changes to the filter. +// Must be called before first executing the filter. +OIDN_API void oidnCommitFilter(OIDNFilter filter); + +// Executes the filter. +OIDN_API void oidnExecuteFilter(OIDNFilter filter); + +#if defined(__cplusplus) +} +#endif diff --git a/thirdparty/oidn/include/OpenImageDenoise/oidn.hpp b/thirdparty/oidn/include/OpenImageDenoise/oidn.hpp new file mode 100644 index 0000000000..9f95a56fe1 --- /dev/null +++ b/thirdparty/oidn/include/OpenImageDenoise/oidn.hpp @@ -0,0 +1,468 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#include +#include "oidn.h" + +namespace oidn { + + // -------------------------------------------------------------------------- + // Buffer + // -------------------------------------------------------------------------- + + // Formats for images and other data stored in buffers + enum class Format + { + Undefined = OIDN_FORMAT_UNDEFINED, + + // 32-bit single-precision floating point scalar and vector formats + Float = OIDN_FORMAT_FLOAT, + Float2 = OIDN_FORMAT_FLOAT2, + Float3 = OIDN_FORMAT_FLOAT3, + Float4 = OIDN_FORMAT_FLOAT4, + }; + + // Access modes for mapping buffers + enum class Access + { + Read = OIDN_ACCESS_READ, // read-only access + Write = OIDN_ACCESS_WRITE, // write-only access + ReadWrite = OIDN_ACCESS_READ_WRITE, // read and write access + WriteDiscard = OIDN_ACCESS_WRITE_DISCARD, // write-only access, previous contents discarded + }; + + // Buffer object with automatic reference counting + class BufferRef + { + private: + OIDNBuffer handle; + + public: + BufferRef() : handle(nullptr) {} + BufferRef(OIDNBuffer handle) : handle(handle) {} + + BufferRef(const BufferRef& other) : handle(other.handle) + { + if (handle) + oidnRetainBuffer(handle); + } + + BufferRef(BufferRef&& other) : handle(other.handle) + { + other.handle = nullptr; + } + + BufferRef& operator =(const BufferRef& other) + { + if (&other != this) + { + if (other.handle) + oidnRetainBuffer(other.handle); + if (handle) + oidnReleaseBuffer(handle); + handle = other.handle; + } + return *this; + } + + BufferRef& operator =(BufferRef&& other) + { + std::swap(handle, other.handle); + return *this; + } + + BufferRef& operator =(OIDNBuffer other) + { + if (other) + oidnRetainBuffer(other); + if (handle) + oidnReleaseBuffer(handle); + handle = other; + return *this; + } + + ~BufferRef() + { + if (handle) + oidnReleaseBuffer(handle); + } + + OIDNBuffer getHandle() const + { + return handle; + } + + operator bool() const + { + return handle != nullptr; + } + + // Maps a region of the buffer to host memory. + // If byteSize is 0, the maximum available amount of memory will be mapped. + void* map(Access access = Access::ReadWrite, size_t byteOffset = 0, size_t byteSize = 0) + { + return oidnMapBuffer(handle, (OIDNAccess)access, byteOffset, byteSize); + } + + // Unmaps a region of the buffer. + // mappedPtr must be a pointer returned by a previous call to map. + void unmap(void* mappedPtr) + { + oidnUnmapBuffer(handle, mappedPtr); + } + }; + + // -------------------------------------------------------------------------- + // Filter + // -------------------------------------------------------------------------- + + // Progress monitor callback function + typedef bool (*ProgressMonitorFunction)(void* userPtr, double n); + + // Filter object with automatic reference counting + class FilterRef + { + private: + OIDNFilter handle; + + public: + FilterRef() : handle(nullptr) {} + FilterRef(OIDNFilter handle) : handle(handle) {} + + FilterRef(const FilterRef& other) : handle(other.handle) + { + if (handle) + oidnRetainFilter(handle); + } + + FilterRef(FilterRef&& other) : handle(other.handle) + { + other.handle = nullptr; + } + + FilterRef& operator =(const FilterRef& other) + { + if (&other != this) + { + if (other.handle) + oidnRetainFilter(other.handle); + if (handle) + oidnReleaseFilter(handle); + handle = other.handle; + } + return *this; + } + + FilterRef& operator =(FilterRef&& other) + { + std::swap(handle, other.handle); + return *this; + } + + FilterRef& operator =(OIDNFilter other) + { + if (other) + oidnRetainFilter(other); + if (handle) + oidnReleaseFilter(handle); + handle = other; + return *this; + } + + ~FilterRef() + { + if (handle) + oidnReleaseFilter(handle); + } + + OIDNFilter getHandle() const + { + return handle; + } + + operator bool() const + { + return handle != nullptr; + } + + // Sets an image parameter of the filter (stored in a buffer). + void setImage(const char* name, + const BufferRef& buffer, Format format, + size_t width, size_t height, + size_t byteOffset = 0, + size_t bytePixelStride = 0, size_t byteRowStride = 0) + { + oidnSetFilterImage(handle, name, + buffer.getHandle(), (OIDNFormat)format, + width, height, + byteOffset, + bytePixelStride, byteRowStride); + } + + // Sets an image parameter of the filter (owned by the user). + void setImage(const char* name, + void* ptr, Format format, + size_t width, size_t height, + size_t byteOffset = 0, + size_t bytePixelStride = 0, size_t byteRowStride = 0) + { + oidnSetSharedFilterImage(handle, name, + ptr, (OIDNFormat)format, + width, height, + byteOffset, + bytePixelStride, byteRowStride); + } + + // Sets a boolean parameter of the filter. + void set(const char* name, bool value) + { + oidnSetFilter1b(handle, name, value); + } + + // Sets an integer parameter of the filter. + void set(const char* name, int value) + { + oidnSetFilter1i(handle, name, value); + } + + // Sets a float parameter of the filter. + void set(const char* name, float value) + { + oidnSetFilter1f(handle, name, value); + } + + // Gets a parameter of the filter. + template + T get(const char* name); + + // Sets the progress monitor callback function of the filter. + void setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr = nullptr) + { + oidnSetFilterProgressMonitorFunction(handle, (OIDNProgressMonitorFunction)func, userPtr); + } + + // Commits all previous changes to the filter. + void commit() + { + oidnCommitFilter(handle); + } + + // Executes the filter. + void execute() + { + oidnExecuteFilter(handle); + } + }; + + // Gets a boolean parameter of the filter. + template<> + inline bool FilterRef::get(const char* name) + { + return oidnGetFilter1b(handle, name); + } + + // Gets an integer parameter of the filter. + template<> + inline int FilterRef::get(const char* name) + { + return oidnGetFilter1i(handle, name); + } + + // Gets a float parameter of the filter. + template<> + inline float FilterRef::get(const char* name) + { + return oidnGetFilter1f(handle, name); + } + + // -------------------------------------------------------------------------- + // Device + // -------------------------------------------------------------------------- + + // Device types + enum class DeviceType + { + Default = OIDN_DEVICE_TYPE_DEFAULT, // select device automatically + + CPU = OIDN_DEVICE_TYPE_CPU, // CPU device + }; + + // Error codes + enum class Error + { + None = OIDN_ERROR_NONE, // no error occurred + Unknown = OIDN_ERROR_UNKNOWN, // an unknown error occurred + InvalidArgument = OIDN_ERROR_INVALID_ARGUMENT, // an invalid argument was specified + InvalidOperation = OIDN_ERROR_INVALID_OPERATION, // the operation is not allowed + OutOfMemory = OIDN_ERROR_OUT_OF_MEMORY, // not enough memory to execute the operation + UnsupportedHardware = OIDN_ERROR_UNSUPPORTED_HARDWARE, // the hardware (e.g. CPU) is not supported + Cancelled = OIDN_ERROR_CANCELLED, // the operation was cancelled by the user + }; + + // Error callback function + typedef void (*ErrorFunction)(void* userPtr, Error code, const char* message); + + // Device object with automatic reference counting + class DeviceRef + { + private: + OIDNDevice handle; + + public: + DeviceRef() : handle(nullptr) {} + DeviceRef(OIDNDevice handle) : handle(handle) {} + + DeviceRef(const DeviceRef& other) : handle(other.handle) + { + if (handle) + oidnRetainDevice(handle); + } + + DeviceRef(DeviceRef&& other) : handle(other.handle) + { + other.handle = nullptr; + } + + DeviceRef& operator =(const DeviceRef& other) + { + if (&other != this) + { + if (other.handle) + oidnRetainDevice(other.handle); + if (handle) + oidnReleaseDevice(handle); + handle = other.handle; + } + return *this; + } + + DeviceRef& operator =(DeviceRef&& other) + { + std::swap(handle, other.handle); + return *this; + } + + DeviceRef& operator =(OIDNDevice other) + { + if (other) + oidnRetainDevice(other); + if (handle) + oidnReleaseDevice(handle); + handle = other; + return *this; + } + + ~DeviceRef() + { + if (handle) + oidnReleaseDevice(handle); + } + + OIDNDevice getHandle() const + { + return handle; + } + + operator bool() const + { + return handle != nullptr; + } + + // Sets a boolean parameter of the device. + void set(const char* name, bool value) + { + oidnSetDevice1b(handle, name, value); + } + + // Sets an integer parameter of the device. + void set(const char* name, int value) + { + oidnSetDevice1i(handle, name, value); + } + + // Gets a parameter of the device. + template + T get(const char* name); + + // Sets the error callback function of the device. + void setErrorFunction(ErrorFunction func, void* userPtr = nullptr) + { + oidnSetDeviceErrorFunction(handle, (OIDNErrorFunction)func, userPtr); + } + + // Returns the first unqueried error code and clears the stored error. + // Can be called for a null device as well to check why a device creation failed. + Error getError() + { + return (Error)oidnGetDeviceError(handle, nullptr); + } + + // Returns the first unqueried error code and string message, and clears the stored error. + // Can be called for a null device as well to check why a device creation failed. + Error getError(const char*& outMessage) + { + return (Error)oidnGetDeviceError(handle, &outMessage); + } + + // Commits all previous changes to the device. + // Must be called before first using the device (e.g. creating filters). + void commit() + { + oidnCommitDevice(handle); + } + + // Creates a new buffer (data allocated and owned by the device). + BufferRef newBuffer(size_t byteSize) + { + return oidnNewBuffer(handle, byteSize); + } + + // Creates a new shared buffer (data allocated and owned by the user). + BufferRef newBuffer(void* ptr, size_t byteSize) + { + return oidnNewSharedBuffer(handle, ptr, byteSize); + } + + // Creates a new filter of the specified type (e.g. "RT"). + FilterRef newFilter(const char* type) + { + return oidnNewFilter(handle, type); + } + }; + + // Gets a boolean parameter of the device. + template<> + inline bool DeviceRef::get(const char* name) + { + return oidnGetDevice1b(handle, name); + } + + // Gets an integer parameter of the device (e.g. "version"). + template<> + inline int DeviceRef::get(const char* name) + { + return oidnGetDevice1i(handle, name); + } + + // Creates a new device. + inline DeviceRef newDevice(DeviceType type = DeviceType::Default) + { + return DeviceRef(oidnNewDevice((OIDNDeviceType)type)); + } + +} // namespace oidn diff --git a/thirdparty/oidn/include/OpenImageDenoise/version.h b/thirdparty/oidn/include/OpenImageDenoise/version.h new file mode 100644 index 0000000000..66b347c992 --- /dev/null +++ b/thirdparty/oidn/include/OpenImageDenoise/version.h @@ -0,0 +1,23 @@ +// ======================================================================== // +// Copyright 2009-2019 Intel Corporation // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// ======================================================================== // + +#pragma once + +#define OIDN_VERSION_MAJOR 1 +#define OIDN_VERSION_MINOR 1 +#define OIDN_VERSION_PATCH 0 +#define OIDN_VERSION 10100 +#define OIDN_VERSION_STRING "1.1.0" diff --git a/thirdparty/oidn/mkl-dnn/LICENSE b/thirdparty/oidn/mkl-dnn/LICENSE new file mode 100644 index 0000000000..d13f7b7ca0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/LICENSE @@ -0,0 +1,214 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ============================================================================ + + Intel MKL-DNN includes components with separate copyright + notices and license terms. + + XByak, 3-clause BSD license + Copyright (c) 2007 MITSUNARI Shigeo + See full copyright notice and license text in src/cpu/xbyak/COPYRIGHT + + gtest, 3-clause BSD license + Copyright 2008, Google Inc. + See full copyright notice and license text in tests/gtests/gtest/LICENSE diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn.h b/thirdparty/oidn/mkl-dnn/include/mkldnn.h new file mode 100644 index 0000000000..9b64994922 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/include/mkldnn.h @@ -0,0 +1,1771 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_H +#define MKLDNN_H + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/* All symbols shall be internal unless marked as MKLDNN_API */ +#if defined _WIN32 || defined __CYGWIN__ +# define MKLDNN_HELPER_DLL_IMPORT __declspec(dllimport) +# define MKLDNN_HELPER_DLL_EXPORT __declspec(dllexport) +#else +# if __GNUC__ >= 4 +# define MKLDNN_HELPER_DLL_IMPORT __attribute__ ((visibility ("default"))) +# define MKLDNN_HELPER_DLL_EXPORT __attribute__ ((visibility ("default"))) +# else +# define MKLDNN_HELPER_DLL_IMPORT +# define MKLDNN_HELPER_DLL_EXPORT +# endif +#endif + +#ifdef MKLDNN_DLL +# ifdef MKLDNN_DLL_EXPORTS +# define MKLDNN_API MKLDNN_HELPER_DLL_EXPORT +# else +# define MKLDNN_API MKLDNN_HELPER_DLL_IMPORT +# endif +#else +# define MKLDNN_API +#endif + +#if defined (__GNUC__) +# define MKLDNN_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define MKLDNN_DEPRECATED __declspec(deprecated) +#else +# define MKLDNN_DEPRECATED +#endif + +#include "mkldnn_types.h" +#include "mkldnn_version.h" +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup c_api C API + * @{ */ + +/** @addtogroup c_api_primitive Primitive operations + * @{ */ + +/** @addtogroup c_api_primitive_common Common primitive operations + * @{ */ + +/** Creates a primitive descriptor @p iterator for given @p op_desc, @p attr, + * @p engine, and optionally a hint primitive descriptor from forward + * propagation (required for backward propagation). Pass @c NULL for forward + * propagation. + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_iterator_create( + mkldnn_primitive_desc_iterator_t *iterator, + const_mkldnn_op_desc_t op_desc, const_mkldnn_primitive_attr_t attr, + mkldnn_engine_t engine, + const_mkldnn_primitive_desc_t hint_forward_primitive_desc); + +/** Iterates over primitive descriptors. Returns #mkldnn_iterator_ends if no + * more primitive descriptors are available. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_iterator_next( + mkldnn_primitive_desc_iterator_t iterator); + +/** Fetches the current primitive descriptor. + * + * @note + * The user should delete the fetched primitive descriptor using + * mkldnn_primitive_desc_destroy() once it is no longer needed. */ +mkldnn_primitive_desc_t MKLDNN_API mkldnn_primitive_desc_iterator_fetch( + const_mkldnn_primitive_desc_iterator_t iterator); + +/** Deletes a primitive descriptor @p iterator */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_iterator_destroy( + mkldnn_primitive_desc_iterator_t iterator); + +/** Creates a @p primitive_desc using @p op_desc, @p attr, @p engine, and + * optionally a hint primitive descriptor from forward propagation. The call is + * equivalent to creating a primitive descriptor iterator, immediately fetching + * a primitive descriptor, and then destroying the iterator. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_create( + mkldnn_primitive_desc_t *primitive_desc, + const_mkldnn_op_desc_t op_desc, const_mkldnn_primitive_attr_t attr, + mkldnn_engine_t engine, + const_mkldnn_primitive_desc_t hint_forward_primitive_desc); + +/** Makes a copy of a @p primitive_desc. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_clone( + mkldnn_primitive_desc_t *primitive_desc, + const_mkldnn_primitive_desc_t existing_primitive_desc); + +/** Returns a constant reference to the attribute of a @p primitive_desc. + * + * @warning + * The user should not destroy the obtained @p attr. + * + * @warning + * The lifetime of an @p attr is the same as that of a @p primitive_desc, + * so it is illegal to use the @p attr once @p primitive_desc has been + * destroyed. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_get_attr( + const_mkldnn_primitive_desc_t primitive_desc, + const_mkldnn_primitive_attr_t *attr); + +/** Deletes a @p primitive_desc. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_destroy( + mkldnn_primitive_desc_t primitive_desc); + +/** Queries primitive descriptor + * + * One of the most typical use cases is to query a convolution primitive + * descriptor created with source, weights, and destination formats equal + * to #mkldnn_format_tag_any about the corresponding memory descriptors + * (@p what equals #mkldnn_query_src_md, #mkldnn_query_weights_md, and + * #mkldnn_query_dst_md respectively) to be able to prepare memory and + * create reorders if required. + * + * Another quite typical use case is to query an operation primitive + * descriptor for a workspace (@p what equals #mkldnn_query_workspace_md). + * The returned status #mkldnn_not_required indicates that a workspace is + * not required. + * + * A few other possibilities: + * - query an operation primitive descriptor for the underlying operation + * descriptor (#mkldnn_query_convolution_d, #mkldnn_query_eltwise_d, + * #mkldnn_query_rnn_d, etc.) + * - query an operation primitive descriptor for the implementation + * information string (#mkldnn_query_impl_info_str) + * - query an operation primitive descriptor for the number of inputs and + * outputs (#mkldnn_query_num_of_inputs_s32 and + * #mkldnn_query_num_of_outputs_s32 respectively) + * + * @sa mkldnn_query_t for more options + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_query( + const_mkldnn_primitive_desc_t primitive_desc, mkldnn_query_t what, + int index, void *result); + +/** Queries primitive descriptor for memory descriptor + * + * @returns NULL in case of any error. + * + * This is just a specialized version of mkldnn_primitive_desc_query + * used for convenience. + */ +const mkldnn_memory_desc_t MKLDNN_API *mkldnn_primitive_desc_query_md( + const_mkldnn_primitive_desc_t primitive_desc, mkldnn_query_t what, + int index); + +/** Queries primitive descriptor for signed 32bit int + * + * @returns 0 in case of any error (in particular if the queried entity is + * not of type int32_t). Note that 0 might also be the actual returned + * value. + * + * This is just a specialized version of mkldnn_primitive_desc_query + * used for convenience. + */ +int MKLDNN_API mkldnn_primitive_desc_query_s32( + const_mkldnn_primitive_desc_t primitive_desc, mkldnn_query_t what, + int index); + +/** Creates a @p primitive using a @p primitive_desc descriptor. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_create( + mkldnn_primitive_t *primitive, + const_mkldnn_primitive_desc_t primitive_desc); + +/** Executes a @p primitive using a @p stream, and @p nargs arguments + * @p args. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_execute( + const_mkldnn_primitive_t primitive, mkldnn_stream_t stream, + int nargs, const mkldnn_exec_arg_t *args); + +/** Retrieves a reference to the @p primitive_desc descriptor of given @p + * primitive. + * + * @warning + * The returned object must not be destroyed by the user. The @c const + * qualifier of the returned object prevents such attempts. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_get_primitive_desc( + const_mkldnn_primitive_t primitive, + const_mkldnn_primitive_desc_t *primitive_desc); + +/** Deletes a @p primitive. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_destroy( + mkldnn_primitive_t primitive); + +/** @} */ + +/** @addtogroup c_api_attributes Attributes + * An extension for controlling primitive behavior. + * @{ */ + +/** Creates an empty (default) @p attr attribute. All the parameters are set to + * default values. + * + * An empty attribute is used in primitive descriptor creation whenever it + * is not passed explicitly, e.g. in mkldnn_primitive_desc_create. + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_create( + mkldnn_primitive_attr_t *attr); + +/** Makes a copy of an @p existing_attr. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_clone( + mkldnn_primitive_attr_t *attr, + const_mkldnn_primitive_attr_t existing_attr); + +/** Deletes an @p attr. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_destroy( + mkldnn_primitive_attr_t attr); + +/** Returns the scratchpad @p mode set in the attribute @p attr */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_get_scratchpad_mode( + const_mkldnn_primitive_attr_t attr, mkldnn_scratchpad_mode_t *mode); + +/** Sets scratchpad @p mode. + * + * The possible values are: #mkldnn_scratchpad_mode_library (default) and + * #mkldnn_scratchpad_mode_user. */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_scratchpad_mode( + mkldnn_primitive_attr_t attr, mkldnn_scratchpad_mode_t mode); + +/** Returns @p count, correspondence scale @p mask, and a pointer to a constant + * floating point array of output @p scales for given @p attr, previously set + * by mkldnn_primitive_attr_set_output_scales. + * + * @warning + * The @p scales array points to the internal @p attr field, so the user + * should not modify or destroy @p scales. + * + * @warning + * The lifetime of @p scales is the same as that of the @p attr to which it + * belongs, so it is illegal to use @p scales after @p attr is destroyed. + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_get_output_scales( + const_mkldnn_primitive_attr_t attr, mkldnn_dim_t *count, int *mask, + const float **scales); + +/** Sets output @p scales for primitive operations. The number of elements @p + * count and correspondence scale @p mask are stored for future use. + * + * The @p mask argument defines the correspondence between the output tensor + * dimensions and the @p scales array. Set the i-th bit of @p mask to 1 to use a + * dedicated scaling factor for each slice of the output tensor over the i-th + * dimension. Set @p mask to 0 to use a common scaling factor for the whole + * output tensor. + * + * @note + * The dimension order is always native and does not depend on the actual + * layout used. Examples: + * - 2D dimensional data the order of dimensions is always: (n, c) + * - 4D dimensional data the order is always: (n, c, h, w) + * - 5D dimensional weights the order is always: (g, oc, ic, kh, kw) + * + * Example usage: + * @code + * int mb = 32, oc = 32, oh = 14, ow = 14; // convolution output params + * float scales[oc] = { ... }; // unique output scales per output channel + * int oc_dim = 1; // mb_dim = 0, channel_dim = 1, height_dim = 2, ... + * + * mkldnn_convolution_desc_t cd; // create & configure convolution op_desc + * + * mkldnn_primitive_attr_t attr; + * mkldnn_primitive_attr_create(&attr); // create default attributes + * mkldnn_primitive_attr_set_output_scales(attr, oc, 1 << oc_dim, scales); + * + * mkldnn_primitive_desc_t cpd; + * mkldnn_primitive_desc_create(&cpd, &cd, attr, NULL); + * @endcode + * + * @note + * There is no way to check that @p count corresponds to @p mask until an + * actual primitive descriptor is created, so it is the user's + * responsibility to set proper values. The following formula must hold: + * + * \f[count = \prod\limits_{d \in mask} output.dims[d]\f] + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_output_scales( + mkldnn_primitive_attr_t attr, mkldnn_dim_t count, int mask, + const float *scales); + +/** Returns @p post_ops for given @p attr. + * + * @warning + * @p post_ops points to the internal @p attr field, so the user should not + * modify or destroy @p post_ops. Also, the lifetime of @p post_ops is the + * same as that of the @p attr it belongs to, so it is illegal to use @p + * post_ops after @p attr has been destroyed. + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_get_post_ops( + const_mkldnn_primitive_attr_t attr, const_mkldnn_post_ops_t *post_ops); + +/** Sets configured @p post_ops to an attribute @p attr for future use (when + * primitive descriptor is being created). + * + * @note + * At this point in time, there is no way to check whether the primitive + * descriptor does or does not support a given sequence of post operations. + * Therefore the user should handle an error that might occur at the + * mkldnn_primitive_desc_create call. + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_post_ops( + mkldnn_primitive_attr_t attr, const_mkldnn_post_ops_t post_ops); + +/** @addtogroup c_api_attributes_post_ops Sequence of post operations + * An extension for performing extra operations after a base operation. + * @{ */ + +/** Creates an empty sequence of post operations @p post_ops. */ +mkldnn_status_t MKLDNN_API mkldnn_post_ops_create(mkldnn_post_ops_t *post_ops); + +/** Deletes a @p post_ops sequence. */ +mkldnn_status_t MKLDNN_API mkldnn_post_ops_destroy(mkldnn_post_ops_t post_ops); + +/** Returns the @p length of post operations for given @p post_ops. */ +int MKLDNN_API mkldnn_post_ops_len(const_mkldnn_post_ops_t post_ops); + +/** Returns the type of post operation with index @p index in given + * @p post_ops. In case of error, returns #mkldnn_undefined_primitive. */ +mkldnn_primitive_kind_t MKLDNN_API mkldnn_post_ops_get_kind( + const_mkldnn_post_ops_t post_ops, int index); + +/** Appends accumulation (sum) post operation to the @p post_ops. Prior to + * accumulating the result, the previous value would be multiplied by @p scale. + * + * The kind of this post operation is #mkldnn_sum. + * + * This feature might improve performance for cases like residual learning + * blocks, where the result of convolution is accumulated to the previously + * computed activations. The parameter @p scale might be extreme for the + * integer-based computations when the result and previous activations have + * different logical scaling factors. + * + * In the simplest case when the accumulation is the only post operation, the + * computations would be: + * dst[] <- scale * dst[] + op(...) // instead of dst[] <- op(...) + * + * @note + * This post operation (as well as all the others) disregards the original + * layout of the destination; that is, the layout of the original + * destination is expected to be the same as the layout of the stored + * destination. + */ +mkldnn_status_t MKLDNN_API mkldnn_post_ops_append_sum( + mkldnn_post_ops_t post_ops, float scale); + +/** Gets the parameters of the accumulation (sum) post operation with index + * @p index in the sequence of @p post_ops. + * + * @note + * If index @p index would not correspond to the accumulation post + * operation, the function returns #mkldnn_invalid_arguments. + */ +mkldnn_status_t MKLDNN_API mkldnn_post_ops_get_params_sum( + const_mkldnn_post_ops_t post_ops, int index, float *scale); + +/** Appends eltwise post operation to the @p post_ops with given parameters + * @p kind, @p alpha, and @p beta (@sa mkldnn_eltwise_forward_desc_init and + * mkldnn_eltwise_desc_t). + * + * The kind of this post operation is #mkldnn_eltwise. + * + * In the simplest case when the eltwise is the only post operation, the + * computations would be: + * dst[] <- scale * eltwise_op ( op(...) ) // instead of dst[] <- op(...) + * where eltwise_op is configured with the given parameters. + */ +mkldnn_status_t MKLDNN_API mkldnn_post_ops_append_eltwise( + mkldnn_post_ops_t post_ops, float scale, mkldnn_alg_kind_t alg, + float alpha, float beta); + +/** Gets the eltwise parameters of the post operation with index @p index in + * the sequence of @p post_ops. + */ +mkldnn_status_t MKLDNN_API mkldnn_post_ops_get_params_eltwise( + const_mkldnn_post_ops_t post_ops, int index, float *scale, + mkldnn_alg_kind_t *alg, float *alpha, float *beta); + +/** @} */ + +/** @} */ + +/** @addtogroup c_api_memory Memory + * A primitive to describe and store data. + * + * The library supports various data types and formats. Memory hierarchy + * consists of three levels of abstraction: + * 1. **Memory descriptor** -- engine agnostic logical description of data + * (number of dimensions, dimensions themselves, and data type), and + * optionally the format/layout that describes the physical representation + * of data in memory. If the format is not known yet, one can pass + * #mkldnn_format_tag_any. This approach is used to allow compute-intensive + * primitives to specify the most appropriate format on their own with + * users required to reorder the data if the incoming format doesn't match + * the primitive's selection. Memory descriptor can be initialized with + * mkldnn_memory_desc_init_by_tag() or mkldnn_memory_desc_init_by_strides() + * functions, or by directly filling the mkldnn_memory_desc_t structure. + * The latter requires deep knowledge of how the physical data + * representation is mapped to the structure. + * The @ref understanding_memory_formats topic should shed some light on + * that. + * For the fully defined memory descriptors (i.e. where the format kind is + * not equal to #mkldnn_format_kind_any) a user can the size, using the + * mkldnn_memory_desc_get_size() function. As described in + * @ref understanding_memory_formats, the size of data sometimes cannot + * be computed as the product of dimensions times the size of the data + * type. So users are encouraged to use this function for better code + * portability. + * Two memory descriptors can be compared with mkldnn_memory_desc_equal(). + * The comparison is especially useful when checking whether a primitive + * requires reorder from the user's data format to the primitive's format. + * 2. **Memory** -- an engine-specific object that handles the data and its + * description (a memory descriptor). For CPU enigne, the data handle is + * simply a pointer to @c void. The data handle can be queried using + * mkldnn_memory_get_data_handle() and set using + * mkldnn_memory_set_data_handle(). The latter function always sets the + * memory in the padding region to zero, which is the invariant maintained + * by all the primitives in Intel MKL-DNN. + * See @ref understanding_memory_formats for more details. + * A memory can be created using mkldnn_memory_create() function. + * A memory can also be queried for the underlying memory descriptor and + * engine using mkldnn_memory_get_memory_desc() and + * mkldnn_memory_get_engine() functions. + * + * Along with ordinary memory with all dimensions being positive, Intel + * MKL-DNN supports *zero-volume* memory with one or more dimensions set to + * zero. This is to support the NumPy\* convention. + * If a *zero-volume* memory is passed to a primitive, the primitive does + * not perform any computations on this memory. For example: + * - Convolution with `(0 batch, 3 input channels, 13 height, 13 width)` + * source and `(16 output channels, 3 inputs, channel, 3 height, 3 width)` + * weights would produce `(0 batch, 16 output channels, 11 height, 11 width)` + * destination (assuming strides are `1` and paddings are zero) and perform + * zero multiply-add operations. + * - Concatenation of three memories of shapes `(3, 4, 13, 13)`, + * `(3, 0, 13, 13)`, and `(3, 1, 13, 13)` along the second axis would produce + * the output of the shape `(3, 5, 13, 13)`, effectively ignoring the second + * input (however, if the user created a concatenation primitive descriptor + * with three inputs they should also provide all three memories to the + * concatenation primitive, including the one with zero second dimension). + * - However, Intel MKL-DNN would return an error when attempting to create a + * convolution with *zero-volume* memory passed for weights because such a + * convolution is not well-defined: + * ~~~ + * dst(1, 16, 11, 11) <-- src(1, 0, 13, 13) (*) wei(16, 0, 3, 3) + * ~~~ + * Should the values in the destination be zeroes or just not accessed at + * all? Moreover, backward pass w.r.t. weights in such cases is also not + * well-defined. + * + * Data handle of *zero-volume* memory is never accessed and hence can be + * unset (NULL in case of CPU engine). + * + * @sa @ref understanding_memory_formats + * @{ */ + +/** Initializes a @p memory_desc memory descriptor using @p ndims, @p dims, @p + * data_type, and @p strides. + * + * The @p strides might be NULL, which means the order of physical dimensions + * is the same as the order of logical ones. + * + * @note The logical order of dimensions is defined by a primitive that + * consumes the memory. + */ +mkldnn_status_t MKLDNN_API mkldnn_memory_desc_init_by_strides( + mkldnn_memory_desc_t *memory_desc, int ndims, const mkldnn_dims_t dims, + mkldnn_data_type_t data_type, const mkldnn_dims_t strides); + +/** Initializes a @p memory_desc memory descriptor using @p ndims, @p dims, @p + * data_type, and format @p tag. + * + * @p tag can be #mkldnn_format_tag_any, which allows a primitive to define + * the appropriate memory format. In this case, the @p format_kind would be set + * to #mkldnn_format_kind_any */ +mkldnn_status_t MKLDNN_API mkldnn_memory_desc_init_by_tag( + mkldnn_memory_desc_t *memory_desc, int ndims, const mkldnn_dims_t dims, + mkldnn_data_type_t data_type, mkldnn_format_tag_t tag); + +/** Initializes a @p memory_desc for a given @p parent_memory_desc, with + * @p dims sizes and @p offsets. May fail if layout used does not allow + * obtain desired submemory. In this case consider using `extract` or `insert` + * primitive */ +mkldnn_status_t MKLDNN_API mkldnn_memory_desc_init_submemory( + mkldnn_memory_desc_t *memory_desc, + const mkldnn_memory_desc_t *parent_memory_desc, + const mkldnn_dims_t dims, const mkldnn_dims_t offsets); + +/** Compares two memory descriptors. + * @return 1 if the descriptors are the same. + * @return 0 if the descriptors are different. + * + * Use this function to identify whether a reorder is required between the + * two memories */ +int MKLDNN_API mkldnn_memory_desc_equal( + const mkldnn_memory_desc_t *lhs, + const mkldnn_memory_desc_t *rhs); + +/** Returns the size (in bytes) that is required for given @p memory_desc */ +size_t MKLDNN_API mkldnn_memory_desc_get_size( + const mkldnn_memory_desc_t *memory_desc); + +/** Creates a memory for given @p memory_desc and @p engine. Also sets handle + * to @p native_handle. + * The @p native_handle can: + * - point to the user allocated memory, i.e. valid handle. In this case the + * library doesn't own allocated memory. + * - be MKLDNN_NATIVE_HANDLE_ALLOCATE to ask the library to allocate and + * attach memory. In this case the library owns allocated memory. + * - be MKLDNN_NATIVE_HANDLE_NONE to create mkldnn_memory w/o attached memory. + */ +mkldnn_status_t MKLDNN_API mkldnn_memory_create(mkldnn_memory_t *memory, + const mkldnn_memory_desc_t *memory_desc, mkldnn_engine_t engine, + void *native_handle); + +/** Returns a @p memory_desc associated with @p memory. */ +mkldnn_status_t MKLDNN_API mkldnn_memory_get_memory_desc( + const_mkldnn_memory_t memory, + const mkldnn_memory_desc_t **memory_desc); + +/** Returns an @p engine associated with @p memory. */ +mkldnn_status_t MKLDNN_API mkldnn_memory_get_engine( + const_mkldnn_memory_t memory, mkldnn_engine_t *engine); + +/** For a @p memory, returns the data @p handle. + * + * For the CPU engine, the data handle is a pointer to the actual data. */ +mkldnn_status_t MKLDNN_API mkldnn_memory_get_data_handle( + const_mkldnn_memory_t memory, void **handle); + +/** For a @p memory, sets the data @p handle. */ +mkldnn_status_t MKLDNN_API mkldnn_memory_set_data_handle( + mkldnn_memory_t memory, void *handle); + +/** Deletes a @p memory. */ +mkldnn_status_t MKLDNN_API mkldnn_memory_destroy(mkldnn_memory_t memory); + +/** @} */ + +/** @addtogroup c_api_reorder Reorder + * A primitive to copy data between memory formats. + * @{ */ + +/** Initializes a @p reorder_primitive_desc using the description of the source + * (@p src_engine and @p src_md) and destination (@p dst_engine and @p dst_md) + * memory, and an @p attr attribute. + * + * Inputs: + * - input (#mkldnn_query_src_md, 0) + * + * Outputs: + * - output (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_reorder_primitive_desc_create( + mkldnn_primitive_desc_t *reorder_primitive_desc, + mkldnn_engine_t src_engine, const mkldnn_memory_desc_t *src_md, + mkldnn_engine_t dst_engine, const mkldnn_memory_desc_t *dst_md, + const_mkldnn_primitive_attr_t attr); + +/** @} */ + +/** @addtogroup c_api_concat Concat + * A primitive to concatenate data by arbitrary dimension. + * @{ */ + +/** Creates out-of-place @p concat_primitive_desc for concatenation of @p n + * inputs by @p concat_dimension with resulting @p output_desc memory + * descriptor. @p output_desc can be NULL or specified with the + * #mkldnn_format_kind_any format kind -- in this case, the appropriate memory + * format would be chosen automatically. + * + * Inputs: + * - input 0 (#mkldnn_query_src_md, 0) + * - input 1 (#mkldnn_query_src_md, 1) + * - ... + * - input @p n - 1 (#mkldnn_query_src_md, @p n - 1) + * + * Outputs: + * - output (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_concat_primitive_desc_create( + mkldnn_primitive_desc_t *concat_primitive_desc, + const mkldnn_memory_desc_t *dst_md, + int n, int concat_dimension, + const mkldnn_memory_desc_t *src_mds, + const_mkldnn_primitive_attr_t attr, + mkldnn_engine_t engine); + +/** @} */ + +/** @addtogroup c_api_sum Sum + * A primitive to sum data. + * @{ */ + +/** Creates out-of-place @p sum_primitive_desc for sum of @p n + * inputs multiplied by scale with resulting @p output_desc memory + * descriptor. @p output_desc can be NULL or specified with the + * #mkldnn_format_kind_any format kind -- in this case, the appropriate memory + * format would be chosen automatically. + * + * Inputs: + * - src 0 (#mkldnn_query_src_md, 0) + * - src 1 (#mkldnn_query_src_md, 1) + * - ... + * - src @p n - 1 (#mkldnn_query_src_md, @p n - 1) + * + * Outputs: + * - output (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_sum_primitive_desc_create( + mkldnn_primitive_desc_t *sum_primitive_desc, + const mkldnn_memory_desc_t *dst_mds, + int n, const float *scales, + const mkldnn_memory_desc_t *src_mds, + const_mkldnn_primitive_attr_t attr, + mkldnn_engine_t engine); + +/** @} */ + +/** @addtogroup c_api_convolution Convolution + * A primitive to compute convolution using different algorithms. + * + * \f[dst[n][oc][oh][ow] = + * \sum_{kw=0}^{KW}\sum_{kh=0}^{KH}\sum_{ic=0}^{IC} + * src[n][ic][oh \cdot s_h - p_l[0] + kh][ow \cdot s_w - p_r[1] + kw] + * \cdot weights[g][oc][ic][kh][kw] + * + bias[g][oc],\f] + * + * where size of output spatial domain is given by + * \f$ OH = \left\lfloor{\frac{IH - KH + p_l[0] + p_r[0]}{s_h}} + * \right\rfloor + 1\f$, + * \f$ OW = \left\lfloor{\frac{IW - KW + p_l[1] + p_r[1]}{s_w}} + * \right\rfloor + 1\f$, + * + * and summation is carried over input channels \f$ic\f$ in + * group \f$g\f$, and \f$s_h, s_w\f$ are @p strides and + * \f$p_l, p_r\f$ are @p padding_l and @p padding_r. + * @{ */ + +/** Initializes a convolution descriptor @p conv_desc for forward propagation + * using @p prop_kind (possible values are #mkldnn_forward_training and + * #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides, @p + * padding_l, @p padding_r, and @p padding_kind. In order to create a + * convolution without bias, @p bias_desc should either be @c NULL or point to + * a descriptor with memory format kind equal to #mkldnn_format_kind_undef. + * + * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * - bias (#mkldnn_query_weights_md, 1), if created with bias + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_convolution_forward_desc_init( + mkldnn_convolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind, + mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *bias_desc, + const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r, + mkldnn_padding_kind_t padding_kind); + +/** Initializes a dilated convolution descriptor @p conv_desc for forward + * propagation using @p prop_kind (possible values are #mkldnn_forward_training + * and #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides, + * @p dilates, @p padding_l, @p padding_r, and @p padding_kind. + * In order to create a dilated convolution without bias, @p bias_desc + * should either be @c NULL or point to a descriptor with memory format kind + * equals #mkldnn_format_kind_undef. + * + * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * - bias (#mkldnn_query_weights_md, 1), if created with bias + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_dilated_convolution_forward_desc_init( + mkldnn_convolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind, + mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *bias_desc, + const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** Initializes a convolution descriptor @p conv_desc for backward propagation + * with respect to data using @p alg_kind, memory descriptors, @p strides, @p + * padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_convolution_backward_data_desc_init( + mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *diff_src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r, + mkldnn_padding_kind_t padding_kind); + +/** Initializes a dilated convolution descriptor @p conv_desc for backward + * propagation with respect to data using @p alg_kind, memory descriptors, @p + * strides, @p dilates @p padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_dilated_convolution_backward_data_desc_init( + mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *diff_src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** Initializes a convolution descriptor @p conv_desc for backward propagation + * with respect to weights using @p alg_kind, memory descriptors, @p strides, + * @p padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_weights (#mkldnn_query_diff_weights_md, 0) + * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias + */ +mkldnn_status_t MKLDNN_API mkldnn_convolution_backward_weights_desc_init( + mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *diff_weights_desc, + const mkldnn_memory_desc_t *diff_bias_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r, + mkldnn_padding_kind_t padding_kind); + +/** Initializes a convolution descriptor @p conv_desc for backward propagation + * with respect to weights using @p alg_kind, memory descriptors, @p strides, + * @p dilates @p padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_weights (#mkldnn_query_diff_weights_md, 0) + * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias + */ +mkldnn_status_t MKLDNN_API +mkldnn_dilated_convolution_backward_weights_desc_init( + mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *diff_weights_desc, + const mkldnn_memory_desc_t *diff_bias_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** @} */ + +/** @addtogroup c_api_deconvolution Deconvolution + * A primitive to compute deconvolution using different algorithms. + * + * @{ */ + + +/** Initializes a deconvolution descriptor @p deconv_desc for forward + * propagation using @p prop_kind (possible values are #mkldnn_forward_training + * and #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides, + * @p padding_l, @p padding_r, and @p padding_kind. In order to create a + * deconvolution without bias, @p bias_desc should either be @c NULL or point to + * a descriptor with memory format kind equals #mkldnn_format_kind_undef. + * + * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * - bias (#mkldnn_query_weights_md, 1), if created with bias + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_deconvolution_forward_desc_init( + mkldnn_deconvolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind, + mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *bias_desc, + const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r, + mkldnn_padding_kind_t padding_kind); + +/** Initializes a dilated deconvolution descriptor @p deconv_desc for forward + * propagation using @p prop_kind (possible values are #mkldnn_forward_training + * and #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides, + * @p dilates, @p padding_l, @p padding_r, and @p padding_kind. In order to + * create a dilated deconvolution without bias, @p bias_desc should either be + * @c NULL or point to a descriptor with memory format kind equal + * #mkldnn_format_kind_undef. + * + * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * - bias (#mkldnn_query_weights_md, 1), if created with bias + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_dilated_deconvolution_forward_desc_init( + mkldnn_deconvolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind, + mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *bias_desc, + const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** Initializes a deconvolution descriptor @p conv_desc for backward propagation + * with respect to data using @p alg_kind, memory descriptors, @p strides, @p + * padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_deconvolution_backward_data_desc_init( + mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *diff_src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r, + mkldnn_padding_kind_t padding_kind); + +/** Initializes a dilated deconvolution descriptor @p conv_desc for backward + * propagation with respect to data using @p alg_kind, memory descriptors, @p + * strides, @p dilates, @p padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_dilated_deconvolution_backward_data_desc_init( + mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *diff_src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** Initializes a deconvolution descriptor @p conv_desc for backward propagation + * with respect to weights using @p alg_kind, memory descriptors, @p strides, + * @p padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_weights (#mkldnn_query_diff_weights_md, 0) + * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias + */ +mkldnn_status_t MKLDNN_API mkldnn_deconvolution_backward_weights_desc_init( + mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *diff_weights_desc, + const mkldnn_memory_desc_t *diff_bias_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r, + mkldnn_padding_kind_t padding_kind); + +/** Initializes a dilated deconvolution descriptor @p conv_desc for backward + * propagation with respect to weights using @p alg_kind, memory descriptors, + * @p strides, @p dilates, @p padding_l, @p padding_r, and @p padding_kind. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_weights (#mkldnn_query_diff_weights_md, 0) + * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias + */ +mkldnn_status_t MKLDNN_API mkldnn_dilated_deconvolution_backward_weights_desc_init( + mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *diff_weights_desc, + const mkldnn_memory_desc_t *diff_bias_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** @} */ + +/** @addtogroup c_api_shuffle Shuffle + * A primitive to shuffle data along the axis. + * @{ */ + +/** Initializes a @p shuffle_desc for forward propagation using @p prop_kind, + * memory descriptor @p data_desc, @p axis, and @p group_size. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + * + */ +mkldnn_status_t MKLDNN_API mkldnn_shuffle_forward_desc_init( + mkldnn_shuffle_desc_t *shuffle_desc, mkldnn_prop_kind_t prop_kind, + const mkldnn_memory_desc_t *data_desc, int axis, + mkldnn_dim_t group_size); + +/** Initializes a @p shuffle_desc for backward propagation using memory + * descriptor @p diff_data_desc, @p axis, and @p group_size. + * + * + * Inputs: + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + * + */ +mkldnn_status_t MKLDNN_API mkldnn_shuffle_backward_desc_init( + mkldnn_shuffle_desc_t *shuffle_desc, + const mkldnn_memory_desc_t *diff_data_desc, int axis, + mkldnn_dim_t group_size); + +/** @} */ + +/** @addtogroup c_api_eltwise Eltwise + * A primitive to compute element-wise operations like parametric rectifier + * linear unit (ReLU). + * + * Both forward and backward passes support in-place operation; that is, src + * and dst point to the same memory for forward pass, and diff_dst and diff_src + * point to the same memory for backward pass. + * + * @warning Because the original src is required for backward pass, in-place + * forward pass in general cannot be applied during training. However, for some + * kinds of element-wise operations (namely ReLU with alpha parameter equals 0), + * dst and src can be interchangeable for the backward pass, which enables + * performing in-place forward even for training. + * + * @{ */ + +/** Initializes an @p eltwise_desc for forward propagation using @p prop_kind + * (possible values are #mkldnn_forward_training and #mkldnn_forward_inference), + * @p alg_kind algorithm, memory descriptor @p data_desc, @p alpha, and + * @p beta parameters. + * + * @sa mkldnn_eltwise_desc_t for details. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_eltwise_forward_desc_init( + mkldnn_eltwise_desc_t *eltwise_desc, mkldnn_prop_kind_t prop_kind, + mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *data_desc, + float alpha, float beta); + +/** Initializes an @p eltwise_desc for backward propagation using @p alg_kind + * algorithm memory descriptors @p diff_data_desc and @p data_desc, and the + * @p alpha and @p beta parameters. + * + * @sa mkldnn_eltwise_desc_t for details. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_eltwise_backward_desc_init( + mkldnn_eltwise_desc_t *eltwise_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *diff_data_desc, + const mkldnn_memory_desc_t *data_desc, float alpha, float beta); + +/** @} */ + +/** @addtogroup c_api_softmax Softmax + * A primitive to perform softmax. + * + * \f[dst[u][c][in] = + * \frac{\exp(src[ou][c][in]) - \max\limits_{c}(src[ou][c][in])} + * {\sum\limits_{c}\{\exp(src[ou][c][in]) + * - \max\limits_{c}(src[ou][c][in])\}},\f] + * + * where \f$ou, iu\f$ are outer and inner sizes repectively, defined + * by @p data_desc.dims and @p softmax_axis. + * @{ */ + +/** Initializes a @p softmax_desc for forward propagation using @p prop_kind + * (possible values are #mkldnn_forward_training and #mkldnn_forward_inference) + * and memory descriptor @p data_desc. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_softmax_forward_desc_init( + mkldnn_softmax_desc_t *softmax_desc, mkldnn_prop_kind_t prop_kind, + const mkldnn_memory_desc_t *data_desc, int softmax_axis); + +/** Initializes a @p softmax_desc for backward propagation using memory + * descriptors @p diff_desc and @p data_desc. + * + * Inputs: + * - dst (#mkldnn_query_dst_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_softmax_backward_desc_init( + mkldnn_softmax_desc_t *softmax_desc, + const mkldnn_memory_desc_t *diff_desc, + const mkldnn_memory_desc_t *data_desc, int softmax_axis); + +/** @} */ + +/** @addtogroup c_api_pooling Pooling + * A primitive to perform max or average pooling. + * + * Max pooling: + * \f[dst[n][oc][oh][ow] = + * \max\limits_{kw,kh} + * (src[n][ic][oh \cdot s_h - p_l[0] + kh][ow \cdot s_w - p_r[1] + kw]),\f] + * + * Average pooling: + * \f[dst[n][oc][oh][ow] = + * \frac{1}{KW \cdot KH}\sum\limits_{kw,kh} + * src[n][ic][oh \cdot s_h - p_l[0] + kh][ow \cdot s_w - p_r[1] + kw],\f] + * + * where \f$p_l, p_r\f$ are @p padding_l and @p padding_r respectively, and + * output spatial dimensions are calculated similarly to how they are done in + * convolution. + * + * During training, max pooling requires a workspace on forward + * (#mkldnn_forward_training) and backward (#mkldnn_backward) passes to + * save indices where maximum was found. The workspace layout is opaque, and + * the indices cannot be restored from it. However, one can use backward + * pooling to perform up-sampling (used in some detection topologies). + * + * @{ */ + +/** Initializes a pooling descriptor @p pool_desc for forward propagation using + * @p prop_kind (possible values are #mkldnn_forward_training and + * #mkldnn_forward_inference), @p alg_kind, memory descriptors, and pooling + * parameters in the spatial domain: @p strides, @p kernel sizes, @p padding_l, + * @p padding_r, and @p padding_kind. + * + * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + * - workspace (#mkldnn_query_workspace_md, 0), + * if @p alg_kind = #mkldnn_pooling_max and + * @p prop_kind = #mkldnn_forward_training + */ +mkldnn_status_t MKLDNN_API mkldnn_pooling_forward_desc_init( + mkldnn_pooling_desc_t *pool_desc, mkldnn_prop_kind_t prop_kind, + mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t kernel, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** Initializes a pooling descriptor @p pool_desc for backward propagation + * using @p alg_kind, memory descriptors, and pooling parameters in the spatial + * domain: @p strides, @p kernel sizes, @p padding_l, @p padding_r, and @p + * padding_kind. + * + * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric. + * + * Inputs: + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - workspace (#mkldnn_query_workspace_md, 0), + * if @p alg_kind = #mkldnn_pooling_max + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_pooling_backward_desc_init( + mkldnn_pooling_desc_t *pool_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *diff_src_desc, + const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides, + const mkldnn_dims_t kernel, const mkldnn_dims_t padding_l, + const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind); + +/** @} */ + +/** @addtogroup c_api_lrn LRN + * A primitive to perform local response normalization (LRN) across or within + * channels. + * + * LRN accross channels: + * \f[dst[n][c][h][w] = \left\{k + \frac{\alpha}{n_{l}} + * \sum\limits_{i=-(n_{l}-1)/2}^{(n_{l}+1)/2} + * (src[n][c+i][h][w])^2\right\}^{-\beta} + * src[n][c][h][w],\f] + * + * LRN within channels: + * \f[dst[n][c][h][w] = \left\{k + \frac{\alpha}{n_{l}} + * \sum\limits_{i=-(n_{l}-1)/2}^{(n_{l}+1)/2} + * (src[n][c][h+i][w+i])^2\right\}^{-\beta} + * src[n][c][h][w],\f] + * + * where \f$n_{l}\f$ is the @p local_size. + * + * During training, LRN might or might not require a workspace on forward + * (#mkldnn_forward_training) and backward (#mkldnn_backward) passes. The + * behavior is implementation specific. Optimized implementations typically + * require a workspace and use it to save some intermediate results from the + * forward pass that accelerate computations on the backward pass. + * + * To check whether a workspace is required, query the LRN primitive descriptor + * for the workspace (#mkldnn_query_workspace_md). Success indicates that the + * workspace is required and its description will be returned. + * @sa mkldnn_primitive_desc_query and mkldnn_primitive_desc_query_pd + * + * @{ */ + +/** Initializes an @p lrn_desc for forward propagation using @p prop_kind + * (possible values are #mkldnn_forward_training and #mkldnn_forward_inference), + * @p alg_kind, memory descriptor @p data_desc, and regularization + * parameters @p local_size, @p alpha, @p beta, and @p k. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + * - workspace (#mkldnn_query_workspace_md, 0), + * if the underlying implementation requires + */ +mkldnn_status_t MKLDNN_API mkldnn_lrn_forward_desc_init( + mkldnn_lrn_desc_t *lrn_desc, mkldnn_prop_kind_t prop_kind, + mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *data_desc, + mkldnn_dim_t local_size, float alpha, float beta, float k); + +/** Initializes an @p lrn_desc for backward propagation using @p alg_kind, + * memory descriptors @p data_desc and @p diff_data_desc, and regularization + * parameters @p local_size, @p alpha, @p beta, and @p k. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - workspace (#mkldnn_query_workspace_md, 0), + * if the underlying implementation requires + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_lrn_backward_desc_init( + mkldnn_lrn_desc_t *lrn_desc, mkldnn_alg_kind_t alg_kind, + const mkldnn_memory_desc_t *diff_data_desc, + const mkldnn_memory_desc_t *data_desc, mkldnn_dim_t local_size, + float alpha, float beta, float k); + +/** @} */ + +/** @addtogroup c_api_batch_normalization Batch Normalization + * A primitive to perform batch normalization. + * + * \f[dst[n][c][h][w] = \gamma[c] \frac{src[n][c][h][w] - \mu[c]} + * {\sqrt{\sigma[c] + eps}} + \beta[c],\f] + * + * where \f$\gamma[c], \beta[c]\f$ are weights and bias for a channel and, + * + * \f$\mu[c] = \frac{1}{NHW} \sum\limits_{whn} src[n][c][h][w]\f$, + * \f$\sigma[c] = \frac{1}{NHW} \sum\limits_{whn} + * (src[n][c][h][w] - \mu[c])^2\f$, + * + * and @c eps is a constant to improve numerical stability. + * + * Both forward and backward passes support in-place operation; that is, src + * and dst point to the same memory for forward pass, and diff_dst and diff_src + * point to the same memory for backward pass. + * + * Batch normalization supports different flavors controlled by + * mkldnn_batch_normalization_desc_t. For example, batch normalization can + * compute the mean and variance on its own or take them as inputs. It can + * either perform scaling and shifting using gamma and beta parameters or not. + * Optionally it can also perform a fused ReLU, which in case of training would + * also require a workspace. + * + * @sa mkldnn_batch_normalization_desc_t + * @{ */ + +/** Initializes a batch normalization descriptor @p bnrm_desc for forward + * propagation using @p prop_kind (possible values are + * #mkldnn_forward_training and #mkldnn_forward_inference), memory descriptor + * @p data_desc, normalization parameter @p epsilon, and @p flags set using bit + * flags of type mkldnn_batch_normalization_desc_t. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - mean (#mkldnn_query_src_md, 1), + * if #mkldnn_use_global_stats bit-flags is set in @p flags + * - variance (#mkldnn_query_src_md, 2), + * if #mkldnn_use_global_stats bit-flags is set in @p flags + * - scale_and_shift (#mkldnn_query_weights_md, 0), + * if #mkldnn_use_scaleshift bit-flags is set in @p flags + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + * - mean (#mkldnn_query_dst_md, 1), + * if #mkldnn_use_global_stats bit-flags is not set in @p flags + * @p prop_kind = #mkldnn_forward_training + * - variance (#mkldnn_query_dst_md, 2), + * if #mkldnn_use_global_stats bit-flags is not set in @p flags + * and @p prop_kind = #mkldnn_forward_training + * - workspace (#mkldnn_query_workspace_md, 0), + * if #mkldnn_fuse_bn_relu bit-flags is set in @p flags + * and @p prop_kind = #mkldnn_forward_training + * + * @note In-place operation is supported; that is, dst points to the same memory + * as src. + * + * @sa mkldnn_batch_normalization_desc_t + */ +mkldnn_status_t MKLDNN_API mkldnn_batch_normalization_forward_desc_init( + mkldnn_batch_normalization_desc_t *bnrm_desc, + mkldnn_prop_kind_t prop_kind, const mkldnn_memory_desc_t *data_desc, + float epsilon, unsigned flags); + +/** Initializes a batch normalization descriptor @p bnrm_desc for backward + * propagation with respect to data and scale-shift parameters using memory + * descriptors @p data_desc and @p diff_data_desc, normalization parameter + * @p epsilon, and @p flags set using bit flags of type + * mkldnn_batch_normalization_desc_t. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - mean (#mkldnn_query_src_md, 1) + * - variance (#mkldnn_query_src_md, 2) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - scale_and_shift (#mkldnn_query_weights_md, 0), + * if #mkldnn_use_scaleshift bit-flags is set in @p flags + * - workspace (#mkldnn_query_workspace_md, 0), + * if #mkldnn_fuse_bn_relu bit-flags is set in @p flags + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + * - diff_scale_and_shift (#mkldnn_query_diff_weights_md, 0), + * if #mkldnn_use_scaleshift bit-flags is set in @p flags + * and @p prop_kind = #mkldnn_backward + * + * @note in-place operation is supported, + * i.e. diff_src points to the same memory as diff_dst. + * + * @sa mkldnn_batch_normalization_desc_t + */ +mkldnn_status_t MKLDNN_API mkldnn_batch_normalization_backward_desc_init( + mkldnn_batch_normalization_desc_t *bnrm_desc, + mkldnn_prop_kind_t prop_kind, + const mkldnn_memory_desc_t *diff_data_desc, + const mkldnn_memory_desc_t *data_desc, + float epsilon, unsigned flags); + +/** @} */ + +/** @addtogroup c_api_inner_product Inner product + * A primitive to compute an inner product. + * + * Inner product layer is also known as fully connected layer. + * With spatial dimension: + * + * \f[dst[n][oc] = \sum\limits_{ic, kh, kw} + * src[n][ic][kh][kw] \cdot weights[oc][ic][kh][kw] + * + bias[oc]\f] + * @{ */ + +/** Initializes an inner product descriptor @p ip_desc for forward propagation + * using @p prop_kind (possible values are #mkldnn_forward_training and + * #mkldnn_forward_inference) and memory descriptors. In order to create an + * inner product without bias, @p bias_desc should be either @c NULL or a + * pointer to a descriptor with memory format kind equals + * #mkldnn_format_kind_undef. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * - bias (#mkldnn_query_weights_md, 1), if created with bias + * + * Outputs: + * - dst (#mkldnn_query_dst_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_inner_product_forward_desc_init( + mkldnn_inner_product_desc_t *ip_desc, mkldnn_prop_kind_t prop_kind, + const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *bias_desc, + const mkldnn_memory_desc_t *dst_desc); + +/** Initializes an inner product descriptor @p ip_desc for backward propagation + * with respect to data using memory descriptors. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * - weights (#mkldnn_query_weights_md, 0) + * + * Outputs: + * - diff_src (#mkldnn_query_diff_src_md, 0) + */ +mkldnn_status_t MKLDNN_API mkldnn_inner_product_backward_data_desc_init( + mkldnn_inner_product_desc_t *ip_desc, + const mkldnn_memory_desc_t *diff_src_desc, + const mkldnn_memory_desc_t *weights_desc, + const mkldnn_memory_desc_t *diff_dst_desc); + +/** Initializes an inner product descriptor @p ip_desc for backward propagation + * with respect to weights using memory descriptors. + * + * @note Memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src (#mkldnn_query_src_md, 0) + * - diff_dst (#mkldnn_query_diff_dst_md, 0) + * + * Outputs: + * - diff_weights (#mkldnn_query_diff_weights_md, 0) + * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias + */ +mkldnn_status_t MKLDNN_API mkldnn_inner_product_backward_weights_desc_init( + mkldnn_inner_product_desc_t *ip_desc, + const mkldnn_memory_desc_t *src_desc, + const mkldnn_memory_desc_t *diff_weights_desc, + const mkldnn_memory_desc_t *diff_bias_desc, + const mkldnn_memory_desc_t *diff_dst_desc); + +/** @} */ + +/** @addtogroup c_api_rnn RNN + * A primitive to compute the common recurrent layer. + * @todo add additional description for the group + * @{ */ + +/** + * Initializes a recurrent cell descriptor @p rnn_cell_desc + * using @p rnn_cell_desc, @p kind (possible values are + * #mkldnn_vanilla_rnn, #mkldnn_vanilla_lstm, #mkldnn_vanilla_gru, and + * #mkldnn_gru_linear_before_reset), + * @p f (possible values are #mkldnn_eltwise_relu and + * #mkldnn_eltwise_tanh), @p flags, @p alpha, and @p clipping. + */ +mkldnn_status_t MKLDNN_API mkldnn_rnn_cell_desc_init( + mkldnn_rnn_cell_desc_t *rnn_cell_desc, + mkldnn_alg_kind_t kind, mkldnn_alg_kind_t f, + unsigned int flags, float alpha, float clipping); + +/** Returns the number of gates of a particular @p rnn_cell_desc. */ +int MKLDNN_API mkldnn_rnn_cell_get_gates_count( + const mkldnn_rnn_cell_desc_t *rnn_cell_desc); + +/** Returns the number of states of a particular @p rnn_cell_desc. */ +int MKLDNN_API mkldnn_rnn_cell_get_states_count( + const mkldnn_rnn_cell_desc_t *rnn_cell_desc); + +/** Sets quantization @p scale and @p shift for RNN data tensors. + * For performance reasons, low precision configuration of RNN primitive + * expects input activations to have unsigned int8 data type. Scale and shift + * used to quantize floating point data to unsigned integer must be passed to + * RNN primitive using attributes. + * Example usage: + * @code + * // rnn parameters + * int l = 2, t = 2, mb = 32, sic = 32, slc = 32, dic = 32, dlc = 32; + * // activations quantization parameters + * float scale = ..., shift = ..; + * + * mkldnn_primitive_attr_t rnn_attr; + * // create default attributes + * mkldnn_primitive_attr_create(&rnn_attr); + * + * // set scale and shift for int8 quantization of activation + * mkldnn_primitive_attr_set_rnn_data_qparams(rnn_attr, scale, shift); + * + * // create & configure rnn op_desc + * mkldnn_rnn_desc_t rnn_d; + * mkldnn_primitive_desc_t rnn_pd; + * mkldnn_primitive_desc_create(&rnn_pd, &rnn_d, attr, engine, NULL); + * @endcode + * @note + * Quantization scale and shift are common for src_layer, src_iter, + * dst_iter and dst_layer. + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_rnn_data_qparams( + mkldnn_primitive_attr_t attr, const float scale, const float shift); + +/** Sets quantization scales @p weights_scales for RNN weights tensors. + * Low precision configuration of RNN primitive expects input weights to have + * signed int8 data type. Scales used to quantize floating point data + * to signed integer must be passed to RNN primitive using attributes. + * The @p mask argument defines correspondence between output tensor dimensions + * and the @p weights_scales array. Set i-th bit of @p mask to 1 to use + * dedicated scaling factor for each slice of the output tensor over i-th + * dimension. Set @p mask to 0 to use common scaling factor for the whole output + * tensor. Example usage: + * @code + * // rnn parameters + * int l = 2, t = 2, mb = 32, sic = 32, slc = 32, dic = 32, dlc = 32; + * // unique output scales per output channel + * float weights_scales[dic * n_gates] = { ... }; + * // mask that specifies last two dimensions of ldigo format + * int mask = 0x3; + * + * mkldnn_primitive_attr_t attr; + * // create default attributes + * mkldnn_primitive_attr_create(&attr); + * + * // set output channel-wise weights scales + * mkldnn_primitive_attr_set_rnn_weights_qparams(attr, dic * n_gates, mask, + * weights_scales); + * + * // create & configure rnn op_desc + * mkldnn_rnn_desc_t rnn_d; + * mkldnn_primitive_desc_t rnn_pd; + * mkldnn_primitive_desc_create(&rnn_pd, &rnn_d, attr, engine, NULL); + * @endcode + * @note + * The dimension order is always native and does not depend on the actual + * layout used. For example, 5 dimensional weights always have + * (l, d, i, g, o) logical dimension ordering. + * @note + * Quantization sales are common for weights_layer and weights_iteration + * @note + * There is no way to check that @p count corresponds to @p mask until an + * actual primitive descriptor is created, so it is user's responsibility + * to set proper values. The following formula must be held: + * + * \f[count = \prod\limits_{d \in mask} output.dims[d]\f] + */ +mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_rnn_weights_qparams ( + mkldnn_primitive_attr_t attr, mkldnn_dim_t count, int mask, + const float *weights_scales); + +/** Initializes a rnn descriptor @p rnn_desc for forward propagation + * using @p prop_kind, @p rnn_cell_desc, @p direction, and memory descriptors. + * @note If @p prop_kind equals #mkldnn_forward_training, you must query a + * workspace memory descriptor before creating the primitive. + * + * @p src_iter_desc, @p bias_desc, and @p dst_iter_desc are allowed to either be + * @c NULL or point to a zero memory descriptor, which would indicate that the + * RNN primitive should not use them. + * + * @note All memory descriptors except @p src_iter_desc are allowed to be + * initialized with #mkldnn_format_kind_any value of @p format_kind. + * + * Inputs: + * - src_layer (#mkldnn_query_src_md, 0) + * - src_iter (#mkldnn_query_src_md, 1), if used + * - weights_layer (#mkldnn_query_weights_md, 0) + * - weights_iter (#mkldnn_query_weights_md, 1) + * - bias (#mkldnn_query_weights_md, 2), if used + * + * Outputs: + * - dst_layer (#mkldnn_query_dst_md, 0) + * - dst_iter (#mkldnn_query_dst_md, 1), if used + * - workspace (#mkldnn_query_workspace_md, 0), + * if @p prop_kind equals #mkldnn_forward_training + */ +mkldnn_status_t MKLDNN_API mkldnn_rnn_forward_desc_init( + mkldnn_rnn_desc_t *rnn_desc, mkldnn_prop_kind_t prop_kind, + const mkldnn_rnn_cell_desc_t *rnn_cell_desc, + const mkldnn_rnn_direction_t direction, + const mkldnn_memory_desc_t *src_layer_desc, + const mkldnn_memory_desc_t *src_iter_desc, + const mkldnn_memory_desc_t *weights_layer_desc, + const mkldnn_memory_desc_t *weights_iter_desc, + const mkldnn_memory_desc_t *bias_desc, + const mkldnn_memory_desc_t *dst_layer_desc, + const mkldnn_memory_desc_t *dst_iter_desc); + +/** Initializes a rnn descriptor @p rnn_desc for backward propagation + * using @p prop_kind, @p rnn_cell_desc, @p direction, and memory descriptors. + * + * @note All memory descriptors are allowed to be initialized with + * #mkldnn_format_kind_any value of @p format_kind. + * + * @p src_iter_desc (simultaneously with @p diff_src_iter_desc), + * @p bias_desc (simultaneously with @p diff_bias_desc), and + * @p dst_iter_desc (simultaneously with @p diff_src_iter_desc) are allowed to + * either be @c NULL or point to a zero memory descriptor, which would indicate + * that the RNN primitive should not use them. + * + * Inputs: + * - src_layer (#mkldnn_query_src_md, 0) + * - src_iter (#mkldnn_query_src_md, 1), if used + * - weights_layer (#mkldnn_query_weights_md, 0) + * - weights_iter (#mkldnn_query_weights_md, 1) + * - bias (#mkldnn_query_weights_md, 2), if used + * - dst_layer (#mkldnn_query_dst_md, 0) + * - dst_iter (#mkldnn_query_dst_md, 1), if used + * - diff_dst_layer (#mkldnn_query_diff_dst_md, 0) + * - diff_dst_iter (#mkldnn_query_diff_dst_md, 1), if used + * - workspace (#mkldnn_query_workspace_md, 0) + * + * Outputs: + * - diff_src_layer (#mkldnn_query_diff_src_md, 0) + * - diff_src_iter (#mkldnn_query_diff_src_md, 1), if used + * - diff_weights_layer (#mkldnn_query_diff_weights_md, 0) + * - diff_weights_iter (#mkldnn_query_diff_weights_md, 1) + * - diff_bias (#mkldnn_query_diff_weights_md, 2), if used + */ +mkldnn_status_t MKLDNN_API mkldnn_rnn_backward_desc_init( + mkldnn_rnn_desc_t *rnn_desc, mkldnn_prop_kind_t prop_kind, + const mkldnn_rnn_cell_desc_t *rnn_cell_desc, + const mkldnn_rnn_direction_t direction, + const mkldnn_memory_desc_t *src_layer_desc, + const mkldnn_memory_desc_t *src_iter_desc, + const mkldnn_memory_desc_t *weights_layer_desc, + const mkldnn_memory_desc_t *weights_iter_desc, + const mkldnn_memory_desc_t *bias_desc, + const mkldnn_memory_desc_t *dst_layer_desc, + const mkldnn_memory_desc_t *dst_iter_desc, + const mkldnn_memory_desc_t *diff_src_layer_desc, + const mkldnn_memory_desc_t *diff_src_iter_desc, + const mkldnn_memory_desc_t *diff_weights_layer_desc, + const mkldnn_memory_desc_t *diff_weights_iter_desc, + const mkldnn_memory_desc_t *diff_bias_desc, + const mkldnn_memory_desc_t *diff_dst_layer, + const mkldnn_memory_desc_t *diff_dst_iter_desc); + +/** @} */ + +/** @} */ + +/** @addtogroup c_api_engine Engine operations + * @{ */ + +/** Returns the number of engines of a particular @p kind. */ +size_t MKLDNN_API mkldnn_engine_get_count(mkldnn_engine_kind_t kind); + +/** Creates an @p engine of particular @p kind and @p index. */ +mkldnn_status_t MKLDNN_API mkldnn_engine_create(mkldnn_engine_t *engine, + mkldnn_engine_kind_t kind, size_t index); + +/** Returns the kind of an @p engine. */ +mkldnn_status_t MKLDNN_API mkldnn_engine_get_kind(mkldnn_engine_t engine, + mkldnn_engine_kind_t *kind); + +/** Destroys an @p engine. */ +mkldnn_status_t MKLDNN_API mkldnn_engine_destroy(mkldnn_engine_t engine); + +/** @} */ + +/** @addtogroup c_api_stream Execution stream operations + * @{ */ + +/** Creates an execution @p stream for @p engine and with @p flags. */ +mkldnn_status_t MKLDNN_API mkldnn_stream_create(mkldnn_stream_t *stream, + mkldnn_engine_t engine, unsigned flags); + +/** Destroys an execution @p stream. */ +mkldnn_status_t MKLDNN_API mkldnn_stream_destroy(mkldnn_stream_t stream); + +/** @} */ + +/** @addtogroup c_api_service Service functions + * @{ */ + +/** Sets verbosity level (print information to stdout). + * Possible levels are: + * - 0 -- no verbose output (default) + * - 1 -- primitive information at execution + * - 2 -- primitive information at creation and execution + * + * @note + * Dumping information might affect performance. + * This setting overrides the MKLDNN_VERBOSE environment variable. */ +mkldnn_status_t MKLDNN_API mkldnn_set_verbose(int level); + +/** Enables or disables dumping of JIT-generated code. + * The enable parameter can be: + * - 0 -- disable + * - any other value -- enable + * + * @note + * This setting overrides the MKLDNN_JIT_DUMP environment variable. */ +mkldnn_status_t MKLDNN_API mkldnn_set_jit_dump(int enable); + +/** Gets library version information. + * Version information includes: + * - major -- major version number + * - minor -- minor version number + * - patch -- patch release number + * - hash -- git commit hash */ +const mkldnn_version_t MKLDNN_API *mkldnn_version(); + +/** @} */ + +/** @addtogroup c_api_blas BLAS functions + * A subset of Basic Linear ALgebra (BLAS) functions to perform + * matrix-matrix multiplication. + * @{ */ + +/** SGEMM performs a matrix-matrix multiplication operation defined as + * + * C := alpha*op( A )*op( B ) + beta*C + * + * where + * - op( X ) is one of op( X ) = X or op( X ) = X**T, + * - alpha and beta are scalars, + * - A, B and C are matrices, with op( A ) an m by k matrix, op( B ) a k by n matrix + * and C an m by n matrix. + * + * The matrices are assumed to be stored in column-major order (the elements + * in a matrix columns are contiguous in memory). + * + * @note + * The API is different from the standard BLAS routine + * because it returns mkldnn_status_t for error handling. + * XERBLA is not supported: no error message will be printed + * in case of incorrect parameters. */ +mkldnn_status_t MKLDNN_API mkldnn_sgemm( + const char *transa, const char *transb, + const mkldnn_dim_t *M, const mkldnn_dim_t *N, const mkldnn_dim_t *K, + const float *alpha, const float *A, const mkldnn_dim_t *lda, + const float *B, const mkldnn_dim_t *ldb, + const float *beta, float *C, const mkldnn_dim_t *ldc); + +/** gemm_s8u8s32 and gemm_s8s8s32 perform a matrix-matrix multiplication + * operation and add the result to a scalar-matrix product. For the final + * result, a vector is added to each row or column of the output matrix. + * The operation is defined as: + * + * C := alpha*(op(A) + A_offset) * (op(B) + B_offset) + beta*C + C_offset + * + * where + * - op( X ) = X or op( X ) = X**T, + * - A_offset is an m-by-k matrix with every element equal to the value oa, + * - B_offset is an k-by-n matrix with every element equal to the value ob, + * - C_offset is an m-by-n matrix defined by the oc array, size len: + * - if offsetc = F: len must be at least 1 + * - if offsetc = C: len must be at least max(1, m) + * - if offsetc = R: len must be at least max(1, n) + * - alpha and beta are scalars, and A, B and C are matrices, with op( A ) + * an m-by-k matrix, op( B ) a k-by-n matrix and C an m-by-n matrix. + * + * The matrices are assumed to be stored in column-major order (the elements + * in a matrix columns are contiguous in memory). + * + * @note + * The API is different compared with the standard BLAS routine + * because it returns mkldnn_status_t for error handling. + * XERBLA is not supported: no error message will be printed + * in case of incorrect parameters. */ +mkldnn_status_t MKLDNN_API mkldnn_gemm_s8u8s32( + const char *transa, const char *transb, const char *offsetc, + const mkldnn_dim_t *M, const mkldnn_dim_t *N, const mkldnn_dim_t *K, + const float *alpha, + const int8_t *A, const mkldnn_dim_t *lda, const int8_t *ao, + const uint8_t *B, const mkldnn_dim_t *ldb, const int8_t *bo, + const float *beta, + int32_t *c, const mkldnn_dim_t *ldc, const int32_t *co); + +mkldnn_status_t MKLDNN_API mkldnn_gemm_s8s8s32( + const char *transa, const char *transb, const char *offsetc, + const mkldnn_dim_t *M, const mkldnn_dim_t *N, const mkldnn_dim_t *K, + const float *alpha, + const int8_t *A, const mkldnn_dim_t *lda, const int8_t *ao, + const int8_t *B, const mkldnn_dim_t *ldb, const int8_t *bo, + const float *beta, + int32_t *c, const mkldnn_dim_t *ldc, const int32_t *co); +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn.hpp b/thirdparty/oidn/mkl-dnn/include/mkldnn.hpp new file mode 100644 index 0000000000..581400a013 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/include/mkldnn.hpp @@ -0,0 +1,2615 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_HPP +#define MKLDNN_HPP + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +#include +#include +#include +#include +#include +#include + +#include "mkldnn.h" +#endif + +namespace mkldnn { + +/// @addtogroup cpp_api C++ API +/// @{ + +/// @addtogroup cpp_api_utils Utils +/// @{ + +/// A class that provides the destructor for an Intel(R) MKL-DNN C handle +template class handle_traits {}; + +/// A class for wrapping an Intel(R) MKL-DNN handle. It is used as the base +/// class for primitive (#mkldnn_primitive_t), engine (#mkldnn_engine_t), and +/// stream (#mkldnn_stream_t) handles. An object of the #mkldnn::handle class +/// can be passed by value. This class enables wrapping: +/// - Newly constructed handles. +/// @n In this case, the constructed handle uses reference counting provided +/// by @p std::shared_ptr with a proper deleter function specified through +/// the @p handle_traits class. +/// - Pre-existing handles returned by the Intel(R) MKL-DNN C API (for +/// example, through mkldnn_primitive_get_primitive_desc()). +/// @n In this case, an Intel(R) MKL-DNN C API handle is wrapped without a +/// deleter because it is assumed that the handle wrapper for the original +/// object deletes the handle (this model is similar to @p std::weak_ptr). +template > class handle { +private: + std::shared_ptr::type> _data; + handle(const handle &&) = delete; + handle &operator=(const handle &&other) = delete; +protected: + bool operator==(const T other) const { return other == _data.get(); } + bool operator!=(const T other) const { return !(*this == other); } +public: + /// Constructs a C handle wrapper. + /// @param t The C handle to wrap. + /// @param weak A flag to specify whether to construct a weak wrapper. + handle(T t = 0, bool weak = false): _data(0) { + reset(t, weak); + } + + handle(const handle &other): _data(other._data) {} + handle &operator=(const handle &other) { + _data = other._data; + return *this; + } + /// Resets the value of a C handle. + /// @param t The new value of the C handle. + /// @param weak A flag to specify whether the wrapper should be weak. + void reset(T t, bool weak = false) { + auto dummy_destructor = [](T) { return decltype(traits::destructor(0))(0); }; + _data.reset(t, weak ? dummy_destructor : traits::destructor); + } + + /// Returns the value of the underlying C handle. + T get() const { return _data.get(); } + + bool operator==(const handle &other) const { return other._data.get() == _data.get(); } + bool operator!=(const handle &other) const { return !(*this == other); } +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_memory_destroy; +}; + +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_primitive_desc_destroy; +}; + +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_primitive_destroy; +}; + +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_primitive_desc_iterator_destroy; +}; +#endif + +struct memory; +struct primitive_desc; + +/// Base class for all computational primitives. +class primitive: public handle { + friend struct error; + friend struct stream; + using handle::handle; +public: + /// A proxy to C primitive kind enum + enum class kind { + undefined_primitive = mkldnn_undefined_primitive, + reorder = mkldnn_reorder, + concat = mkldnn_concat, + sum = mkldnn_sum, + convolution = mkldnn_convolution, + deconvolution = mkldnn_deconvolution, + shuffle = mkldnn_shuffle, + eltwise = mkldnn_eltwise, + softmax = mkldnn_softmax, + pooling = mkldnn_pooling, + lrn = mkldnn_lrn, + batch_normalization = mkldnn_batch_normalization, + inner_product = mkldnn_inner_product, + rnn = mkldnn_rnn, + }; + + primitive(const_mkldnn_primitive_desc_t c_pd); + primitive(const primitive_desc &pd); + + /// Returns the descriptor of the underlying C API primitive. + inline const_mkldnn_primitive_desc_t get_primitive_desc() const; + // TODO: use the C++ API wrapper structure. + + void execute(struct stream &astream, + const std::unordered_map &args) const; +}; + +inline mkldnn_primitive_kind_t convert_to_c(primitive::kind akind) { + return static_cast(akind); +} +/// Intel(R) MKL-DNN exception class. +/// +/// This class captures the status returned by the failed C API function, error +/// message, and, optionally, handle of the primitive that caused the error. +struct error: public std::exception { + mkldnn_status_t status; + const char *message; + + /// Constructs an error instance. + /// + /// @param astatus The error status returned by the C API. + /// @param amessage The error message. + error(mkldnn_status_t astatus, const char *amessage) + : status(astatus), message(amessage) {} + + /// A convenience function for wrapping calls to the C API. Checks the + /// return status and throws an #error in case of failure. + /// + /// @param status The error status returned by the C API. + /// @param message The error message. + static void wrap_c_api(mkldnn_status_t status, const char *message) { + if (status != mkldnn_success) + throw error(status, message); + } +}; + +const_mkldnn_primitive_desc_t primitive::get_primitive_desc() const { + const_mkldnn_primitive_desc_t pd; + error::wrap_c_api(mkldnn_primitive_get_primitive_desc(get(), &pd), + "could not get primitive descriptor by primitive"); + return pd; +} +/// @} + +/// @addtogroup cpp_api_enums Common data types and enumerations +/// A proxy to @ref c_api_types in @ref c_api. +/// +/// @{ + +enum scratchpad_mode { + scratchpad_mode_library = mkldnn_scratchpad_mode_library, + scratchpad_mode_user = mkldnn_scratchpad_mode_user, +}; + +inline mkldnn_scratchpad_mode_t convert_to_c(scratchpad_mode mode) { + return static_cast(mode); +} + +enum padding_kind { + zero = mkldnn_padding_zero +}; + +inline mkldnn_padding_kind_t convert_to_c(padding_kind kind) { + return static_cast(kind); +} + +enum prop_kind { + forward_training = mkldnn_forward_training, + forward_scoring = mkldnn_forward_scoring, + forward_inference = mkldnn_forward_inference, + forward = mkldnn_forward, + backward = mkldnn_backward, + backward_data = mkldnn_backward_data, + backward_weights = mkldnn_backward_weights, + backward_bias = mkldnn_backward_bias +}; + +inline mkldnn_prop_kind_t convert_to_c(prop_kind kind) { + return static_cast(kind); +} + +enum algorithm { + algorithm_undef = mkldnn_alg_kind_undef, + convolution_auto = mkldnn_convolution_auto, + convolution_direct = mkldnn_convolution_direct, + convolution_winograd = mkldnn_convolution_winograd, + deconvolution_direct = mkldnn_deconvolution_direct, + deconvolution_winograd = mkldnn_deconvolution_winograd, + eltwise_relu = mkldnn_eltwise_relu, + eltwise_tanh = mkldnn_eltwise_tanh, + eltwise_elu = mkldnn_eltwise_elu, + eltwise_square = mkldnn_eltwise_square, + eltwise_abs = mkldnn_eltwise_abs, + eltwise_sqrt = mkldnn_eltwise_sqrt, + eltwise_linear = mkldnn_eltwise_linear, + eltwise_bounded_relu = mkldnn_eltwise_bounded_relu, + eltwise_soft_relu = mkldnn_eltwise_soft_relu, + eltwise_logistic = mkldnn_eltwise_logistic, + lrn_across_channels = mkldnn_lrn_across_channels, + lrn_within_channel = mkldnn_lrn_within_channel, + pooling_max = mkldnn_pooling_max, + pooling_avg = mkldnn_pooling_avg, + pooling_avg_include_padding = mkldnn_pooling_avg_include_padding, + pooling_avg_exclude_padding = mkldnn_pooling_avg_exclude_padding, + vanilla_rnn = mkldnn_vanilla_rnn, + vanilla_lstm = mkldnn_vanilla_lstm, + vanilla_gru = mkldnn_vanilla_gru, + gru_linear_before_reset = mkldnn_gru_linear_before_reset +}; + +inline mkldnn_alg_kind_t convert_to_c(algorithm aalgorithm) { + return static_cast(aalgorithm); +} + +enum batch_normalization_flag { + use_global_stats = mkldnn_use_global_stats, + use_scale_shift = mkldnn_use_scaleshift, + fuse_bn_relu = mkldnn_fuse_bn_relu +}; + +inline mkldnn_batch_normalization_flag_t convert_to_c( + batch_normalization_flag aflag) { + return static_cast(aflag); +} + +enum rnn_direction { + unidirectional_left2right = mkldnn_unidirectional_left2right, + unidirectional_right2left = mkldnn_unidirectional_right2left, + unidirectional = mkldnn_unidirectional, + bidirectional_concat = mkldnn_bidirectional_concat, + bidirectional_sum = mkldnn_bidirectional_sum, +}; + +inline mkldnn_rnn_direction_t convert_to_c(rnn_direction adir) { + return static_cast(adir); +} + +enum query { + undef = mkldnn_query_undef, + + query_engine = mkldnn_query_engine, + primitive_kind = mkldnn_query_primitive_kind, + + num_of_inputs_s32 = mkldnn_query_num_of_inputs_s32, + num_of_outputs_s32 = mkldnn_query_num_of_outputs_s32, + + time_estimate_f64 = mkldnn_query_time_estimate_f64, + memory_consumption_s64 = mkldnn_query_memory_consumption_s64, + + query_scratchpad_engine = mkldnn_query_scratchpad_engine, + + impl_info_str = mkldnn_query_impl_info_str, + + op_d = mkldnn_query_op_d, + convolution_d = mkldnn_query_convolution_d, + deconvolution_d = mkldnn_query_deconvolution_d, + shuffle_d = mkldnn_query_shuffle_d, + eltwise_d = mkldnn_query_eltwise_d, + softmax_d = mkldnn_query_softmax_d, + pooling_d = mkldnn_query_pooling_d, + lrn_d = mkldnn_query_lrn_d, + batch_normalization_d = mkldnn_query_batch_normalization_d, + inner_product_d = mkldnn_query_inner_product_d, + rnn_d = mkldnn_query_rnn_d, + + src_md = mkldnn_query_src_md, + diff_src_md = mkldnn_query_diff_src_md, + weights_md = mkldnn_query_weights_md, + diff_weights_md = mkldnn_query_diff_weights_md, + dst_md = mkldnn_query_dst_md, + diff_dst_md = mkldnn_query_diff_dst_md, + workspace_md = mkldnn_query_workspace_md, + scratchpad_md = mkldnn_query_scratchpad_md, +}; + +inline mkldnn_query_t convert_to_c(query aquery) { + return static_cast(aquery); +} + +/// @} + +/// @addtogroup cpp_api_attr Attributes +/// An extension for controlling primitive behavior. +/// +/// @sa @ref c_api_attributes in @ref c_api +/// @{ + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_post_ops_destroy; +}; +#endif + +struct post_ops: public handle { + post_ops() { + mkldnn_post_ops_t result; + error::wrap_c_api(mkldnn_post_ops_create(&result), + "could not create post operation sequence"); + reset(result); + } + + int len() const { return mkldnn_post_ops_len(get()); } + + primitive::kind kind(int index) const { + error::wrap_c_api( + index < len() ? mkldnn_success : mkldnn_invalid_arguments, + "post_ops index is out of range"); + return static_cast(mkldnn_post_ops_get_kind(get(), + index)); + } + + void append_sum(float scale = 1.) { + error::wrap_c_api(mkldnn_post_ops_append_sum(get(), scale), + "could not append sum"); + } + + void get_params_sum(int index, float &scale) const { + error::wrap_c_api(mkldnn_post_ops_get_params_sum(get(), index, &scale), + "could not get sum params"); + } + + void append_eltwise(float scale, algorithm alg, float alpha, + float beta) { + error::wrap_c_api(mkldnn_post_ops_append_eltwise(get(), scale, + convert_to_c(alg), alpha, beta), + "could not append eltwise"); + } + + void get_params_eltwise(int index, float &scale, algorithm &alg, + float &alpha, float &beta) const { + mkldnn_alg_kind_t c_alg; + error::wrap_c_api(mkldnn_post_ops_get_params_eltwise(get(), index, + &scale, &c_alg, &alpha, &beta), + "could not get eltwise params"); + alg = static_cast(c_alg); + } +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_primitive_attr_destroy; +}; +#endif + +struct primitive_attr: public handle { + primitive_attr() { + mkldnn_primitive_attr_t result; + error::wrap_c_api(mkldnn_primitive_attr_create(&result), + "could not create a primitive attr"); + reset(result); + } + + scratchpad_mode get_scratchpad_mode() const { + mkldnn_scratchpad_mode_t result; + error::wrap_c_api(mkldnn_primitive_attr_get_scratchpad_mode( + get(), &result), "could not get scratchpad mode"); + return scratchpad_mode(result); + } + + void set_scratchpad_mode(scratchpad_mode mode) { + error::wrap_c_api(mkldnn_primitive_attr_set_scratchpad_mode( + get(), mkldnn::convert_to_c(mode)), + "could not set scratchpad mode"); + } + + void get_output_scales(int &mask, std::vector &scales) const + { + mkldnn_dim_t count; + int c_mask; + const float *c_scales; + error::wrap_c_api(mkldnn_primitive_attr_get_output_scales(get(), + &count, &c_mask, &c_scales), + "could not get int output scales"); + scales.resize(count); + + mask = c_mask; + for (mkldnn_dim_t c = 0; c < count; ++c) + scales[c] = c_scales[c]; + } + + void set_output_scales(int mask, const std::vector &scales) + { + error::wrap_c_api(mkldnn_primitive_attr_set_output_scales(get(), + (mkldnn_dim_t)scales.size(), mask, &scales[0]), + "could not set int output scales"); + } + + const post_ops get_post_ops() const { + post_ops result; + const_mkldnn_post_ops_t c_result; + error::wrap_c_api(mkldnn_primitive_attr_get_post_ops(get(), &c_result), + "could not get post operation sequence"); + result.reset(const_cast(c_result), true); + return result; + } + + void set_post_ops(post_ops ops) { + error::wrap_c_api(mkldnn_primitive_attr_set_post_ops(get(), ops.get()), + "could not set post operation sequence"); + } + + void set_rnn_data_qparams(const float scale, const float shift) + { + error::wrap_c_api(mkldnn_primitive_attr_set_rnn_data_qparams(get(), + scale, shift), "could not set rnn data int scale/shift"); + } + + void set_rnn_weights_qparams(int mask, const std::vector &scales) + { + error::wrap_c_api(mkldnn_primitive_attr_set_rnn_weights_qparams(get(), + (int)scales.size(), mask, &scales[0]), + "could not set rnn weights int scales"); + } +}; + +/// @} + +/// @addtogroup cpp_api_engine Engine +/// Engine operations. +/// +/// @sa @ref c_api_engine in @ref c_api +/// @{ + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_engine_destroy; +}; +#endif + +/// An execution engine. +struct engine: public handle { + friend class primitive; + // gcc bug??? using handle::handle; + + /// Kinds of engines. + enum kind { + /// An unspecified engine + any = mkldnn_any_engine, + /// CPU engine + cpu = mkldnn_cpu, + }; + + /// Returns the number of engines of a certain kind. + /// + /// @param akind The kind of engines to count. + + static size_t get_count(kind akind) { + return mkldnn_engine_get_count(convert_to_c(akind)); + } + + /// Constructs an engine. + /// + /// @param akind The kind of engine to construct. + /// @param index The index of the engine. Must be less than the value + /// returned by #get_count() for this particular kind of engine. + + engine(kind akind, size_t index) { + mkldnn_engine_t aengine; + error::wrap_c_api( + mkldnn_engine_create(&aengine, + convert_to_c(akind), index), + "could not create an engine"); + reset(aengine); + } + + explicit engine(const mkldnn_engine_t& aengine) + : handle(aengine, true) {} + + engine(const handle &pd) { + mkldnn_engine_t engine_q; + error::wrap_c_api( + mkldnn_primitive_desc_query(pd.get(), + mkldnn::convert_to_c(query_engine), 0, &engine_q), + "could not get engine from primitive_desc"); + reset(engine_q, true); + } + + template + static engine query(const primitive_desc &pd) { + mkldnn_engine_t engine_q; + error::wrap_c_api( + mkldnn_primitive_desc_query(pd.get(), + mkldnn::convert_to_c(query_engine), 0, &engine_q), + "could not get engine from primitive_desc"); + + return engine(engine_q); + } + +private: + static mkldnn_engine_kind_t convert_to_c(kind akind) { + return static_cast(akind); + } +}; + +/// @} + +/// @addtogroup cpp_api_stream Stream +/// Execution stream operations +/// +/// @sa @ref c_api_stream in @ref c_api +/// @{ + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template <> struct handle_traits { + static constexpr auto destructor = &mkldnn_stream_destroy; +}; +#endif + +struct stream: public handle { + using handle::handle; + + enum: unsigned { + default_flags = mkldnn_stream_default_flags, + }; + + /// Constructs a stream. + stream(const engine &aengine, + unsigned flags = static_cast(default_flags)) { + mkldnn_stream_t astream; + error::wrap_c_api(mkldnn_stream_create(&astream, aengine.get(), flags), + "could not create a stream"); + reset(astream); + } +}; + +/// @} + +/// @addtogroup cpp_api_memory_related Memory and memory related operations +/// @{ + +/// @addtogroup cpp_api_memory Memory +/// A primitive to describe and store data. +/// +/// For more information, refer to @ref c_api_memory in @ref c_api. +/// @{ + +/// Memory that describes the data. +struct memory: public handle { + public: + typedef mkldnn_dim_t dim; + typedef std::vector dims; + + template static void validate_dims(const std::vector &v) { + if (v.size() > MKLDNN_MAX_NDIMS) + throw error(mkldnn_invalid_arguments, "invalid dimensions"); + } + + /// Data type specification. See #mkldnn_data_type_t for a detailed + /// description. + enum data_type { + data_undef = mkldnn_data_type_undef, + f32 = mkldnn_f32, + s32 = mkldnn_s32, + s8 = mkldnn_s8, + u8 = mkldnn_u8, + }; + + /// Memory format tag specification. See #mkldnn_format_tag_t + /// for a detailed description. + enum format_tag { + format_tag_undef = mkldnn_format_tag_undef, + any = mkldnn_format_tag_any, + a = mkldnn_a, + ab = mkldnn_ab, + abc = mkldnn_abc, + abcd = mkldnn_abcd, + abcde = mkldnn_abcde, + abcdef = mkldnn_abcdef, + abdec = mkldnn_abdec, + acb = mkldnn_acb, + acbde = mkldnn_acbde, + acdb = mkldnn_acdb, + acdeb = mkldnn_acdeb, + ba = mkldnn_ba, + bac = mkldnn_bac, + bacd = mkldnn_bacd, + bcda = mkldnn_bcda, + cba = mkldnn_cba, + cdba = mkldnn_cdba, + cdeba = mkldnn_cdeba, + decab = mkldnn_decab, + Abc16a = mkldnn_Abc16a, + ABc16a16b = mkldnn_ABc16a16b, + aBc16b = mkldnn_aBc16b, + ABc16b16a = mkldnn_ABc16b16a, + Abc4a = mkldnn_Abc4a, + aBc4b = mkldnn_aBc4b, + ABc4b16a4b = mkldnn_ABc4b16a4b, + ABc4b4a = mkldnn_ABc4b4a, + ABc8a16b2a = mkldnn_ABc8a16b2a, + ABc8a8b = mkldnn_ABc8a8b, + aBc8b = mkldnn_aBc8b, + ABc8b16a2b = mkldnn_ABc8b16a2b, + ABc8b8a = mkldnn_ABc8b8a, + Abcd16a = mkldnn_Abcd16a, + ABcd16a16b = mkldnn_ABcd16a16b, + aBcd16b = mkldnn_aBcd16b, + ABcd16b16a = mkldnn_ABcd16b16a, + aBCd16b16c = mkldnn_aBCd16b16c, + aBCd16c16b = mkldnn_aBCd16c16b, + Abcd4a = mkldnn_Abcd4a, + aBcd4b = mkldnn_aBcd4b, + ABcd4b16a4b = mkldnn_ABcd4b16a4b, + ABcd4b4a = mkldnn_ABcd4b4a, + aBCd4c16b4c = mkldnn_aBCd4c16b4c, + aBCd4c4b = mkldnn_aBCd4c4b, + ABcd8a16b2a = mkldnn_ABcd8a16b2a, + ABcd8a8b = mkldnn_ABcd8a8b, + aBcd8b = mkldnn_aBcd8b, + ABcd8b16a2b = mkldnn_ABcd8b16a2b, + aBCd8b16c2b = mkldnn_aBCd8b16c2b, + ABcd8b8a = mkldnn_ABcd8b8a, + aBCd8b8c = mkldnn_aBCd8b8c, + aBCd8c16b2c = mkldnn_aBCd8c16b2c, + aBCd8c8b = mkldnn_aBCd8c8b, + Abcde16a = mkldnn_Abcde16a, + ABcde16a16b = mkldnn_ABcde16a16b, + aBcde16b = mkldnn_aBcde16b, + ABcde16b16a = mkldnn_ABcde16b16a, + aBCde16b16c = mkldnn_aBCde16b16c, + aBCde16c16b = mkldnn_aBCde16c16b, + aBCde2c8b4c = mkldnn_aBCde2c8b4c, + Abcde4a = mkldnn_Abcde4a, + aBcde4b = mkldnn_aBcde4b, + ABcde4b4a = mkldnn_ABcde4b4a, + aBCde4b4c = mkldnn_aBCde4b4c, + aBCde4c16b4c = mkldnn_aBCde4c16b4c, + aBCde4c4b = mkldnn_aBCde4c4b, + Abcde8a = mkldnn_Abcde8a, + ABcde8a8b = mkldnn_ABcde8a8b, + aBcde8b = mkldnn_aBcde8b, + ABcde8b16a2b = mkldnn_ABcde8b16a2b, + aBCde8b16c2b = mkldnn_aBCde8b16c2b, + ABcde8b8a = mkldnn_ABcde8b8a, + aBCde8b8c = mkldnn_aBCde8b8c, + aBCde8c16b2c = mkldnn_aBCde8c16b2c, + aBCde8c8b = mkldnn_aBCde8c8b, + aBcdef16b = mkldnn_aBcdef16b, + aBCdef16b16c = mkldnn_aBCdef16b16c, + aBCdef16c16b = mkldnn_aBCdef16c16b, + aBcdef4b = mkldnn_aBcdef4b, + aBCdef4c4b = mkldnn_aBCdef4c4b, + aBCdef8b8c = mkldnn_aBCdef8b8c, + aBCdef8c16b2c = mkldnn_aBCdef8c16b2c, + aBCdef8c8b = mkldnn_aBCdef8c8b, + aBdc16b = mkldnn_aBdc16b, + aBdc4b = mkldnn_aBdc4b, + aBdc8b = mkldnn_aBdc8b, + aBdec16b = mkldnn_aBdec16b, + aBdec4b = mkldnn_aBdec4b, + aBdec8b = mkldnn_aBdec8b, + aBdefc16b = mkldnn_aBdefc16b, + aBdefc4b = mkldnn_aBdefc4b, + aBdefc8b = mkldnn_aBdefc8b, + Acb16a = mkldnn_Acb16a, + Acb4a = mkldnn_Acb4a, + Acb8a = mkldnn_Acb8a, + aCBd16b16c = mkldnn_aCBd16b16c, + aCBde16b16c = mkldnn_aCBde16b16c, + Acdb16a = mkldnn_Acdb16a, + Acdb4a = mkldnn_Acdb4a, + Acdb8a = mkldnn_Acdb8a, + Acdeb16a = mkldnn_Acdeb16a, + Acdeb4a = mkldnn_Acdeb4a, + Acdeb8a = mkldnn_Acdeb8a, + BAc16a16b = mkldnn_BAc16a16b, + BAcd16a16b = mkldnn_BAcd16a16b, + format_tag_last = mkldnn_format_tag_last, + + x = mkldnn_x, + nc = mkldnn_nc, + cn = mkldnn_cn, + ncw = mkldnn_ncw, + nwc = mkldnn_nwc, + nchw = mkldnn_nchw, + nhwc = mkldnn_nhwc, + chwn = mkldnn_chwn, + ncdhw = mkldnn_ncdhw, + ndhwc = mkldnn_ndhwc, + oi = mkldnn_oi, + io = mkldnn_io, + oiw = mkldnn_oiw, + wio = mkldnn_wio, + oihw = mkldnn_oihw, + hwio = mkldnn_hwio, + ihwo = mkldnn_ihwo, + iohw = mkldnn_iohw, + oidhw = mkldnn_oidhw, + dhwio = mkldnn_dhwio, + goiw = mkldnn_goiw, + goihw = mkldnn_goihw, + hwigo = mkldnn_hwigo, + giohw = mkldnn_giohw, + goidhw = mkldnn_goidhw, + tnc = mkldnn_tnc, + ntc = mkldnn_ntc, + ldsnc = mkldnn_ldsnc, + ldigo = mkldnn_ldigo, + ldgoi = mkldnn_ldgoi, + ldgo = mkldnn_ldgo, + nCdhw16c = mkldnn_nCdhw16c, + nCdhw4c = mkldnn_nCdhw4c, + nCdhw8c = mkldnn_nCdhw8c, + nChw16c = mkldnn_nChw16c, + nChw4c = mkldnn_nChw4c, + nChw8c = mkldnn_nChw8c, + nCw16c = mkldnn_nCw16c, + nCw4c = mkldnn_nCw4c, + nCw8c = mkldnn_nCw8c, + IOw16o16i = mkldnn_IOw16o16i, + OIw16i16o = mkldnn_OIw16i16o, + OIw16o16i = mkldnn_OIw16o16i, + Oiw16o = mkldnn_Oiw16o, + OIw4i16o4i = mkldnn_OIw4i16o4i, + OIw4i4o = mkldnn_OIw4i4o, + Oiw4o = mkldnn_Oiw4o, + OIw8i16o2i = mkldnn_OIw8i16o2i, + OIw8i8o = mkldnn_OIw8i8o, + OIw8o16i2o = mkldnn_OIw8o16i2o, + OIw8o8i = mkldnn_OIw8o8i, + Owi16o = mkldnn_Owi16o, + Owi4o = mkldnn_Owi4o, + Owi8o = mkldnn_Owi8o, + IOhw16o16i = mkldnn_IOhw16o16i, + Ohwi16o = mkldnn_Ohwi16o, + Ohwi4o = mkldnn_Ohwi4o, + Ohwi8o = mkldnn_Ohwi8o, + OIhw16i16o = mkldnn_OIhw16i16o, + OIhw16o16i = mkldnn_OIhw16o16i, + Oihw16o = mkldnn_Oihw16o, + OIhw4i16o4i = mkldnn_OIhw4i16o4i, + OIhw4i4o = mkldnn_OIhw4i4o, + Oihw4o = mkldnn_Oihw4o, + OIhw8i16o2i = mkldnn_OIhw8i16o2i, + OIhw8i8o = mkldnn_OIhw8i8o, + OIhw8o16i2o = mkldnn_OIhw8o16i2o, + OIhw8o8i = mkldnn_OIhw8o8i, + Odhwi16o = mkldnn_Odhwi16o, + Odhwi4o = mkldnn_Odhwi4o, + Odhwi8o = mkldnn_Odhwi8o, + OIdhw16i16o = mkldnn_OIdhw16i16o, + OIdhw16o16i = mkldnn_OIdhw16o16i, + Oidhw16o = mkldnn_Oidhw16o, + OIdhw4i4o = mkldnn_OIdhw4i4o, + Oidhw4o = mkldnn_Oidhw4o, + OIdhw8i16o2i = mkldnn_OIdhw8i16o2i, + OIdhw8i8o = mkldnn_OIdhw8i8o, + OIdhw8o8i = mkldnn_OIdhw8o8i, + gIOw16o16i = mkldnn_gIOw16o16i, + gOIw16i16o = mkldnn_gOIw16i16o, + gOIw16o16i = mkldnn_gOIw16o16i, + gOiw16o = mkldnn_gOiw16o, + gOIw4i16o4i = mkldnn_gOIw4i16o4i, + gOIw4i4o = mkldnn_gOIw4i4o, + gOiw4o = mkldnn_gOiw4o, + gOIw8i16o2i = mkldnn_gOIw8i16o2i, + gOIw8i8o = mkldnn_gOIw8i8o, + gOIw8o16i2o = mkldnn_gOIw8o16i2o, + gOIw8o8i = mkldnn_gOIw8o8i, + gOwi16o = mkldnn_gOwi16o, + gOwi4o = mkldnn_gOwi4o, + gOwi8o = mkldnn_gOwi8o, + gIOhw16o16i = mkldnn_gIOhw16o16i, + gOhwi16o = mkldnn_gOhwi16o, + gOhwi4o = mkldnn_gOhwi4o, + gOhwi8o = mkldnn_gOhwi8o, + Goihw16g = mkldnn_Goihw16g, + gOIhw16i16o = mkldnn_gOIhw16i16o, + gOIhw16o16i = mkldnn_gOIhw16o16i, + gOihw16o = mkldnn_gOihw16o, + gOIhw2i8o4i = mkldnn_gOIhw2i8o4i, + gOIhw4i16o4i = mkldnn_gOIhw4i16o4i, + gOIhw4i4o = mkldnn_gOIhw4i4o, + gOIhw4o4i = mkldnn_gOIhw4o4i, + gOihw4o = mkldnn_gOihw4o, + Goihw8g = mkldnn_Goihw8g, + gOIhw8i16o2i = mkldnn_gOIhw8i16o2i, + gOIhw8i8o = mkldnn_gOIhw8i8o, + gOIhw8o16i2o = mkldnn_gOIhw8o16i2o, + gOIhw8o8i = mkldnn_gOIhw8o8i, + gOdhwi16o = mkldnn_gOdhwi16o, + gOdhwi4o = mkldnn_gOdhwi4o, + gOdhwi8o = mkldnn_gOdhwi8o, + gOIdhw16i16o = mkldnn_gOIdhw16i16o, + gOIdhw16o16i = mkldnn_gOIdhw16o16i, + gOidhw16o = mkldnn_gOidhw16o, + gOIdhw4i4o = mkldnn_gOIdhw4i4o, + gOidhw4o = mkldnn_gOidhw4o, + gOIdhw8i16o2i = mkldnn_gOIdhw8i16o2i, + gOIdhw8i8o = mkldnn_gOIdhw8i8o, + gOIdhw8o8i = mkldnn_gOIdhw8o8i, + }; + + /// A memory descriptor. + struct desc { + friend struct memory; + /// The underlying C API data structure. + mkldnn_memory_desc_t data; + + /// Constructs a zero memory descriptor + desc(): data() {} + + /// Constructs a memory descriptor. + /// + /// @param adims Data dimensions + /// @param adata_type Data precision/type. + /// @param aformat Data layout format tag. + desc(const dims &adims, data_type adata_type, + format_tag aformat) { + validate_dims(adims); + error::wrap_c_api(mkldnn_memory_desc_init_by_tag(&data, (int)adims.size(), + adims.size() == 0 ? nullptr : &adims[0], + convert_to_c(adata_type), convert_to_c(aformat)), + "could not initialize a memory descriptor"); + } + + /// Constructs a memory descriptor from a C API data structure. + /// + /// @param adata A C API #mkldnn_memory_desc_t structure. + desc(const mkldnn_memory_desc_t &adata): data(adata) {} + + /// Constructs a sub-memory descriptor + // + /// @param adims Sizes of a sub-memory + /// @param offsets Offsets of a sub-memory + desc submemory_desc(const dims &adims, const dims &offsets) { + mkldnn_memory_desc_t sub_md; + error::wrap_c_api(mkldnn_memory_desc_init_submemory(&sub_md, + &data, &adims[0], &offsets[0]), + "could not initialize a sub-memory"); + return desc(sub_md); + } + + /// Returns the number of bytes required to allocate the memory described + /// including the padding area. + size_t get_size() const { return mkldnn_memory_desc_get_size(&data); } + + bool operator==(const desc &other) const { + return mkldnn_memory_desc_equal(&data, &other.data) != 0; + } + + bool operator!=(const desc &other) const { return !operator==(other); } + }; + + /// Constructs a memory. + /// + /// @param md Memory descriptor. + /// @param aengine Engine. + /// @param ahandle Native handle. + memory(const desc &md, const engine &aengine, void *ahandle) { + mkldnn_memory_t result; + error::wrap_c_api(mkldnn_memory_create(&result, &md.data, + aengine.get(), ahandle), "could not create a memory"); + reset(result); + } + + /// Constructs a memory. + /// + /// @param md Memory descriptor. + /// @param aengine Engine. + memory(const desc &md, const engine &aengine) + : memory(md, aengine, MKLDNN_NATIVE_HANDLE_ALLOCATE) {} + + /// Returns the descriptor of the memory. + desc get_desc() const { + const mkldnn_memory_desc_t *cdesc; + error::wrap_c_api(mkldnn_memory_get_memory_desc(get(), &cdesc), + "could not get memory descriptor from a memory"); + return desc(*cdesc); + } + + /// Returns the engine of the memory. + engine get_engine() const { + mkldnn_engine_t engine_q; + error::wrap_c_api(mkldnn_memory_get_engine(get(), &engine_q), + "could not get engine from a memory"); + return engine(engine_q); + } + + /// Returns a handle of the data contained in the memory. + /// + /// On the CPU engine, this is a pointer to the allocated memory. + void *get_data_handle() const { + void *handle; + error::wrap_c_api(mkldnn_memory_get_data_handle(get(), &handle), + "could not get native handle"); + return handle; + } + + void set_data_handle(void *handle) const { + error::wrap_c_api(mkldnn_memory_set_data_handle(get(), handle), + "could not set native handle"); + } + + // Must go away or be private: + static mkldnn_data_type_t convert_to_c(data_type adata_type) { + return static_cast(adata_type); + } + static mkldnn_format_tag_t convert_to_c(format_tag aformat) { + return static_cast(aformat); + } +}; + +inline bool operator==(mkldnn_data_type_t a, memory::data_type b) { + return a == memory::convert_to_c(b); +} +inline bool operator!=(mkldnn_data_type_t a, memory::data_type b) { + return !(a == b); +} +inline bool operator==(memory::data_type a, mkldnn_data_type_t b) { + return b == a; +} +inline bool operator!=(memory::data_type a, mkldnn_data_type_t b) { + return !(a == b); +} + +inline bool operator==(mkldnn_format_tag_t a, memory::format_tag b) { + return a == memory::convert_to_c(b); +} +inline bool operator!=(mkldnn_format_tag_t a, memory::format_tag b) { + return !(a == b); +} +inline bool operator==(memory::format_tag a, mkldnn_format_tag_t b) { + return b == a; +} +inline bool operator!=(memory::format_tag a, mkldnn_format_tag_t b) { + return !(a == b); +} + +/// @} + +/// @addtogroup cpp_api_reorder Reorder +/// A primitive to copy data between memory formats. +/// +/// @sa @ref c_api_reorder in @ref c_api +/// @{ + +struct reorder : public primitive { + struct primitive_desc : public handle { + primitive_desc(const engine &src_engine, const memory::desc &src_md, + const engine &dst_engine, const memory::desc &dst_md, + const primitive_attr &aattr) { + mkldnn_primitive_desc_t result; + error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result, + src_engine.get(), &src_md.data, + dst_engine.get(), &dst_md.data, aattr.get()), + "could not create a reorder primitive descriptor"); + reset(result); + } + + primitive_desc(const engine &src_engine, const memory::desc &src_md, + const engine &dst_engine, const memory::desc &dst_md) { + mkldnn_primitive_desc_t result; + error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result, + src_engine.get(), &src_md.data, + dst_engine.get(), &dst_md.data, nullptr), + "could not create a reorder primitive descriptor"); + reset(result); + } + + primitive_desc(const memory &src, const memory &dst, + const primitive_attr &aattr) { + mkldnn_primitive_desc_t result; + auto src_md = src.get_desc(); + auto dst_md = dst.get_desc(); + error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result, + src.get_engine().get(), &src_md.data, + dst.get_engine().get(), &dst_md.data, aattr.get()), + "could not create a reorder primitive descriptor"); + reset(result); + } + + primitive_desc(const memory &src, const memory &dst) { + mkldnn_primitive_desc_t result; + auto src_md = src.get_desc(); + auto dst_md = dst.get_desc(); + error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result, + src.get_engine().get(), &src_md.data, + dst.get_engine().get(), &dst_md.data, nullptr), + "could not create a reorder primitive descriptor"); + reset(result); + } + + memory::desc scratchpad_desc() const { + const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md( + get(), mkldnn::convert_to_c(scratchpad_md), 0); + if (cdesc == nullptr) + return memory::desc(); + return memory::desc(*cdesc); + } + + engine scratchpad_engine() { + mkldnn_engine_t engine_q; + error::wrap_c_api( + mkldnn_primitive_desc_query(get(), + mkldnn::convert_to_c(query_scratchpad_engine), 0, &engine_q), + "could not get scratchpad engine from reorder primitive_desc"); + + return engine(engine_q); + } + + engine get_engine() { return engine::query(*this); } + }; + + reorder(const primitive_desc &pd): primitive(pd.get()) {} + + reorder(const memory &src, const memory &dst): + primitive(primitive_desc(src, dst).get()) {} + + void execute(stream astream, memory &src, memory &dst) { + primitive::execute(astream, + {{MKLDNN_ARG_FROM, src}, {MKLDNN_ARG_TO, dst}}); + } +}; + +/// @} + +/// @addtogroup cpp_api_concat Concat +/// A primitive to concatenate data by arbitrary dimension. +/// +/// @sa @ref c_api_concat in @ref c_api +/// @{ + +struct concat : public primitive { + struct primitive_desc : public handle { + std::vector cpp_to_c( + const std::vector &srcs) { + std::vector c_api_srcs; + c_api_srcs.reserve(srcs.size()); + for (const auto &s : srcs) c_api_srcs.push_back(s.data); + return c_api_srcs; + } + + primitive_desc(const memory::desc &dst, int concat_dimension, + const std::vector &srcs, const engine &aengine) { + auto c_api_srcs = cpp_to_c(srcs); + + mkldnn_primitive_desc_t result; + error::wrap_c_api(mkldnn_concat_primitive_desc_create( + &result, &dst.data, (int)c_api_srcs.size(), + concat_dimension, &c_api_srcs[0], nullptr, aengine.get()), + "could not create a concat primitive descriptor"); + reset(result); + } + + primitive_desc(int concat_dimension, + const std::vector &srcs, const engine &aengine) { + auto c_api_srcs = cpp_to_c(srcs); + + mkldnn_primitive_desc_t result; + error::wrap_c_api(mkldnn_concat_primitive_desc_create( + &result, nullptr, (int)c_api_srcs.size(), + concat_dimension, &c_api_srcs[0], nullptr, aengine.get()), + "could not create a concat primitive descriptor"); + reset(result); + } + + memory::desc dst_desc() const { + const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md( + get(), mkldnn::convert_to_c(dst_md), 0); + error::wrap_c_api( + cdesc == nullptr ? mkldnn_runtime_error : mkldnn_success, + "could not get a dst memory descriptor"); + return memory::desc(*cdesc); + } + + memory::desc scratchpad_desc() const { + const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md( + get(), mkldnn::convert_to_c(scratchpad_md), 0); + if (cdesc == nullptr) + return memory::desc(); + return memory::desc(*cdesc); + } + + engine get_engine() { return engine::query(*this); } + }; + + concat(const primitive_desc &pd): primitive(pd.get()) {} +}; + +/// @} + +/// @addtogroup cpp_api_sum Sum +/// A primitive to sum data. +/// +/// @sa @ref c_api_sum in @ref c_api +/// @{ + +struct sum : public primitive { + struct primitive_desc : public handle { + std::vector cpp_to_c( + const std::vector &srcs) { + std::vector c_api_srcs; + c_api_srcs.reserve(srcs.size()); + for (const auto &s : srcs) c_api_srcs.push_back(s.data); + return c_api_srcs; + } + + primitive_desc(const memory::desc &dst, + const std::vector &scales, + const std::vector &srcs, const engine &aengine) { + error::wrap_c_api(scales.size() == srcs.size() + ? mkldnn_success : mkldnn_invalid_arguments, + "number of scales not equal to number of srcs"); + + auto c_api_srcs = cpp_to_c(srcs); + + mkldnn_primitive_desc_t result; + error::wrap_c_api(mkldnn_sum_primitive_desc_create( + &result, &dst.data, (int)c_api_srcs.size(), + &scales[0], &c_api_srcs[0], nullptr, aengine.get()), + "could not create a sum primitive descriptor"); + reset(result); + } + + primitive_desc(const std::vector &scales, + const std::vector &srcs, const engine &aengine) { + error::wrap_c_api(scales.size() == srcs.size() + ? mkldnn_success : mkldnn_invalid_arguments, + "number of scales not equal to number of srcs"); + + auto c_api_srcs = cpp_to_c(srcs); + mkldnn_primitive_desc_t result; + error::wrap_c_api(mkldnn_sum_primitive_desc_create(&result, + nullptr, (int)c_api_srcs.size(), &scales[0], + &c_api_srcs[0], nullptr, aengine.get()), + "could not create a sum primitive descriptor"); + reset(result); + } + + memory::desc dst_desc() const { + const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md( + get(), mkldnn::convert_to_c(dst_md), 0); + error::wrap_c_api( + cdesc == nullptr ? mkldnn_runtime_error : mkldnn_success, + "could not get a dst memory descriptor"); + return memory::desc(*cdesc); + } + + memory::desc scratchpad_desc() const { + const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md( + get(), mkldnn::convert_to_c(scratchpad_md), 0); + if (cdesc == nullptr) + return memory::desc(); + return memory::desc(*cdesc); + } + + engine get_engine() { return engine::query(*this); } + }; + + sum(const primitive_desc &pd): primitive(pd.get()) {} +}; + +/// @} + +/// @} + +/// @addtogroup cpp_api_primitives Primitives +/// @{ + +/// @addtogroup cpp_api_primitive_descriptors Primitive descriptors +/// @{ + +/// A base class for all primitive descriptors. +struct primitive_desc : public handle { + primitive_desc(const_mkldnn_op_desc_t desc, const primitive_attr *attr, + const engine &e, const_mkldnn_primitive_desc_t hint_fwd_pd) { + mkldnn_primitive_desc_iterator_t iterator = nullptr; + mkldnn_status_t status = mkldnn_primitive_desc_iterator_create( + &iterator, desc, attr ? attr->get() : nullptr, e.get(), + hint_fwd_pd); + error::wrap_c_api(status, + "could not create a primitive descriptor iterator"); + pd_iterator.reset(iterator); + fetch_impl(); + } + + engine get_engine() { return engine::query(*this); } + + primitive_attr get_primitive_attr() const { + const_mkldnn_primitive_attr_t const_cattr; + error::wrap_c_api(mkldnn_primitive_desc_get_attr(get(), &const_cattr), + "could not get attributes"); + mkldnn_primitive_attr_t cattr; + error::wrap_c_api(mkldnn_primitive_attr_clone(&cattr, const_cattr), + "could not clone attributes"); + + primitive_attr attr; + attr.reset(cattr); + return attr; + } + + /// Returns implementation name + const char *impl_info_str() const { + const char *res; + error::wrap_c_api(mkldnn_primitive_desc_query(get(), + mkldnn_query_impl_info_str, 0, &res), + "could not query implementation info string"); + return res; + } + + /// Queries the memory::dim value (same as int64_t) + memory::dim query_s64(query q) const { + memory::dim res; + mkldnn_status_t status = mkldnn_primitive_desc_query(get(), + mkldnn::convert_to_c(q), 0, &res); + return status == mkldnn_success ? res : 0; + } + + /// Advances the next implementation for the given op descriptor. + /// + /// Returns: + /// - @c true on success + /// - @c false if the last implementation reached, and + /// the primitive descriptor itself is kept unchanged + bool next_impl() { + mkldnn_status_t status = mkldnn_primitive_desc_iterator_next( + pd_iterator.get()); + if (status == mkldnn_iterator_ends) return false; + error::wrap_c_api(status, "primitive descriptor iterator next failed"); + + fetch_impl(); + return true; + } + + /// Queries and returns requested memory descriptor. + memory::desc query_md(query what, int idx = 0) const { + std::vector valid_q{src_md, diff_src_md, weights_md, + diff_weights_md, dst_md, diff_dst_md, workspace_md, scratchpad_md}; + if (!std::any_of(valid_q.cbegin(), valid_q.cend(), + [=](query q) { return what == q; })) + throw error(mkldnn_invalid_arguments, "invalid memory query"); + + const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md( + get(), mkldnn::convert_to_c(what), idx); + if (cdesc == nullptr) return memory::desc(); + + return memory::desc(*cdesc); + } + + // register specialized queries, e.g. src_desc() +# define REG_QUERY_MD(name, what, idx) \ + memory::desc name ## _desc() const { return query_md(what ## _md, idx); } + + private: + handle pd_iterator; + void fetch_impl() { + mkldnn_primitive_desc_t pd = mkldnn_primitive_desc_iterator_fetch( + pd_iterator.get()); + error::wrap_c_api(pd != nullptr ? mkldnn_success : mkldnn_runtime_error, + "could not fetch a primitive descriptor from the iterator"); + reset(pd); + } +}; + +/// @} + +/// @addtogroup cpp_api_convolution Convolution +/// A primitive to compute convolution using different algorithms. +/// +/// @sa @ref c_api_convolution in @ref c_api +/// @{ + +struct convolution_forward: public primitive { + struct desc { + mkldnn_convolution_desc_t data; + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &bias_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_convolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, &bias_desc.data, + &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution forward descriptor"); + } + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_convolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, nullptr, + &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution forward descriptor"); + } + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &bias_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api( + mkldnn_dilated_convolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, &bias_desc.data, + &dst_desc.data, &strides[0], &dilates[0], + &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a dilated convolution forward descriptor"); + } + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api( + mkldnn_dilated_convolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, nullptr, + &dst_desc.data, &strides[0], &dilates[0], + &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a dilated convolution forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(bias, weights, 1); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + convolution_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct convolution_backward_data : public primitive { + struct desc { + mkldnn_convolution_desc_t data; + desc(algorithm aalgorithm, + const memory::desc &diff_src_desc, + const memory::desc &weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_convolution_backward_data_desc_init( + &data, convert_to_c(aalgorithm), &diff_src_desc.data, + &weights_desc.data, &diff_dst_desc.data, + &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution backward data descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &diff_src_desc, + const memory::desc &weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api( + mkldnn_dilated_convolution_backward_data_desc_init( + &data, convert_to_c(aalgorithm), &diff_src_desc.data, + &weights_desc.data, &diff_dst_desc.data, + &strides[0], &dilates[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution backward data descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const convolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const convolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + convolution_backward_data(const primitive_desc &pd): primitive(pd) {} +}; + +struct convolution_backward_weights : public primitive { + struct desc { + mkldnn_convolution_desc_t data; + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_bias_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_convolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, &diff_bias_desc.data, + &diff_dst_desc.data, + &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution backward weights descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_convolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, nullptr, &diff_dst_desc.data, + &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution backward weights descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_bias_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_dilated_convolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, &diff_bias_desc.data, + &diff_dst_desc.data, + &strides[0], &dilates[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution backward weights descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_dilated_convolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, nullptr, &diff_dst_desc.data, + &strides[0], &dilates[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a convolution backward weights descriptor"); + } + + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const convolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const convolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(diff_weights, diff_weights, 0); + REG_QUERY_MD(diff_bias, diff_weights, 1); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + convolution_backward_weights(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} +// +/// @addtogroup cpp_api_deconvolution Deconvolution +/// A primitive to compute deconvolution using different algorithms. +/// +/// @sa @ref c_api_deconvolution in @ref c_api +/// @{ + +struct deconvolution_forward: public primitive { + struct desc { + mkldnn_deconvolution_desc_t data; + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &bias_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_deconvolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, &bias_desc.data, + &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a deconvolution forward descriptor"); + } + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_deconvolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, nullptr, + &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a deconvolution forward descriptor"); + } + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &bias_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_dilated_deconvolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, &bias_desc.data, + &dst_desc.data, &strides[0], &dilates[0], &padding_l[0], + &padding_r[0], mkldnn::convert_to_c(apadding_kind)), + "could not create a dilated deconvolution forward descriptor"); + } + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_dilated_deconvolution_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, &weights_desc.data, nullptr, + &dst_desc.data, &strides[0], &dilates[0], &padding_l[0], + &padding_r[0], mkldnn::convert_to_c(apadding_kind)), + "could not create a dilated deconvolution forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(bias, weights, 1); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + deconvolution_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct deconvolution_backward_data : public primitive { + struct desc { + mkldnn_deconvolution_desc_t data; + desc(algorithm aalgorithm, + const memory::desc &diff_src_desc, + const memory::desc &weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_deconvolution_backward_data_desc_init( + &data, convert_to_c(aalgorithm), &diff_src_desc.data, + &weights_desc.data, &diff_dst_desc.data, + &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a deconvolution backward data descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &diff_src_desc, + const memory::desc &weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_dilated_deconvolution_backward_data_desc_init( + &data, convert_to_c(aalgorithm), &diff_src_desc.data, + &weights_desc.data, &diff_dst_desc.data, + &strides[0], &dilates[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a dilated deconvolution backward data descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const deconvolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const deconvolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + deconvolution_backward_data(const primitive_desc &pd): primitive(pd) {} +}; + +struct deconvolution_backward_weights : public primitive { + struct desc { + mkldnn_deconvolution_desc_t data; + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_bias_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_deconvolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, &diff_bias_desc.data, + &diff_dst_desc.data, + &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a deconvolution backward weights descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_deconvolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, nullptr, &diff_dst_desc.data, + &strides[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a deconvolution backward weights descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_bias_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_dilated_deconvolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, &diff_bias_desc.data, + &diff_dst_desc.data, + &strides[0], &dilates[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a dilated deconvolution backward weights descriptor"); + } + desc(algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_dst_desc, + const memory::dims strides, + const memory::dims dilates, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(dilates); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_dilated_deconvolution_backward_weights_desc_init( + &data, convert_to_c(aalgorithm), &src_desc.data, + &diff_weights_desc.data, nullptr, &diff_dst_desc.data, + &strides[0], &dilates[0], &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not create a dilated deconvolution backward weights descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const deconvolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const deconvolution_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(diff_weights, diff_weights, 0); + REG_QUERY_MD(diff_bias, diff_weights, 1); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + deconvolution_backward_weights(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_lrn LRN +/// A primitive to perform local response normalization (LRN) across or within +/// channels. +/// +/// @sa @ref c_api_lrn in @ref c_api +/// @{ + +struct lrn_forward : public primitive { + struct desc { + mkldnn_lrn_desc_t data; + + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, memory::dim local_size, + float alpha, float beta, float k = 1.f) { + error::wrap_c_api(mkldnn_lrn_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm), + &src_desc.data, local_size, alpha, beta, k), + "could not create a lrn forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(workspace, workspace, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + lrn_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct lrn_backward : public primitive { + struct desc { + mkldnn_lrn_desc_t data; + + desc(algorithm aalgorithm, const memory::desc &data_desc, + const memory::desc &diff_data_desc, memory::dim local_size, + float alpha, float beta, float k = 1.f) { + error::wrap_c_api(mkldnn_lrn_backward_desc_init(&data, + convert_to_c(aalgorithm), &diff_data_desc.data, + &data_desc.data, local_size, alpha, beta, k), + "could not create a lrn backward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const lrn_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const lrn_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(workspace, workspace, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + lrn_backward(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_pooling Pooling +/// A primitive to perform max or average pooling. +/// +/// @sa @ref c_api_pooling in @ref c_api +/// @{ + +struct pooling_forward : public primitive { + struct desc { + mkldnn_pooling_desc_t data; + desc(prop_kind aprop_kind, algorithm aalgorithm, + const memory::desc &src_desc, + const memory::desc &dst_desc, + const memory::dims strides, + const memory::dims kernel, + const memory::dims padding_l, + const memory::dims padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(kernel); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_pooling_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), + convert_to_c(aalgorithm), + &src_desc.data, &dst_desc.data, + &strides[0], &kernel[0], + &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not init a forward pooling descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(workspace, workspace, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + pooling_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct pooling_backward : public primitive { + struct desc { + mkldnn_pooling_desc_t data; + desc(algorithm aalgorithm, + const memory::desc &diff_src_desc, + const memory::desc &diff_dst_desc, + const memory::dims &strides, + const memory::dims &kernel, + const memory::dims &padding_l, + const memory::dims &padding_r, + const padding_kind apadding_kind) { + memory::validate_dims(strides); + memory::validate_dims(kernel); + memory::validate_dims(padding_l); + memory::validate_dims(padding_r); + error::wrap_c_api(mkldnn_pooling_backward_desc_init(&data, + convert_to_c(aalgorithm), + &diff_src_desc.data, &diff_dst_desc.data, + &strides[0], &kernel[0], + &padding_l[0], &padding_r[0], + mkldnn::convert_to_c(apadding_kind)), + "could not init a backward pooling descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const pooling_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const pooling_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(workspace, workspace, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + pooling_backward(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_eltwise Eltwise +/// A primitive to compute element-wise operations like parametric rectifier +/// linear unit (ReLU). +/// +/// @sa @ref c_api_eltwise in @ref c_api +/// @{ + +struct eltwise_forward : public primitive { + struct desc { + mkldnn_eltwise_desc_t data; + template + desc(prop_kind aprop_kind, algorithm alg_kind, + const memory::desc &src_desc, T alpha = 0, T beta = 0) { + error::wrap_c_api(mkldnn_eltwise_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), + mkldnn::convert_to_c(alg_kind), &src_desc.data, + static_cast(alpha), static_cast(beta)), + "could not create a eltwise forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + eltwise_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct eltwise_backward : public primitive { + struct desc { + mkldnn_eltwise_desc_t data; + + template + desc(algorithm alg_kind, const memory::desc &diff_data_desc, + const memory::desc &data_desc, T alpha = 0, T beta = 0) { + error::wrap_c_api(mkldnn_eltwise_backward_desc_init(&data, + mkldnn::convert_to_c(alg_kind), &diff_data_desc.data, + &data_desc.data, static_cast(alpha), + static_cast(beta)), + "could not create a eltwise backward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const eltwise_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const eltwise_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + eltwise_backward(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_softmax Softmax +/// A primitive to perform softmax. +/// +/// @sa @ref c_api_softmax in @ref c_api +/// @{ + +struct softmax_forward : public primitive { + struct desc { + mkldnn_softmax_desc_t data; + desc(prop_kind aprop_kind, const memory::desc &data_desc, + int softmax_axis) { + error::wrap_c_api(mkldnn_softmax_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), &data_desc.data, + softmax_axis), + "could not create a softmax forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + softmax_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct softmax_backward : public primitive { + struct desc { + mkldnn_softmax_desc_t data; + desc(const memory::desc &diff_desc, const memory::desc &data_desc, + int softmax_axis) { + error::wrap_c_api(mkldnn_softmax_backward_desc_init(&data, + &diff_desc.data, &data_desc.data, softmax_axis), + "could not init a backward softmax descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const softmax_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const softmax_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(workspace, workspace, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + softmax_backward(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_batch_norm Batch normalization +/// A primitive to perform batch normalization. +/// +/// @sa @ref c_api_batch_normalization in @ref c_api +/// @{ + +struct batch_normalization_forward : public primitive { + struct desc { + mkldnn_batch_normalization_desc_t data; + template + desc(prop_kind aprop_kind, const memory::desc &src_desc, T epsilon, + unsigned flags) { + error::wrap_c_api( + mkldnn_batch_normalization_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), &src_desc.data, + static_cast(epsilon), flags), + "could not create a batch normalization forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(workspace, workspace, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + + memory::desc mean_desc() const { return stat_desc(mean); } + memory::desc variance_desc() const { return stat_desc(var); } + + private: + enum { mean = 1, var = 2, }; + memory::desc stat_desc(int kind) const { + mkldnn_batch_normalization_desc_t *p; + error::wrap_c_api(mkldnn_primitive_desc_query( + get(), mkldnn::convert_to_c(batch_normalization_d), 0, &p), + "could not get a batch-normalization descriptor"); + return query_md(p->flags & use_global_stats ? src_md : dst_md, kind); + } + }; + + batch_normalization_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct batch_normalization_backward : public primitive { + struct desc { + mkldnn_batch_normalization_desc_t data; + template + desc(prop_kind aprop_kind, const memory::desc &diff_data_desc, + const memory::desc &data_desc, T epsilon, unsigned flags) { + error::wrap_c_api( + mkldnn_batch_normalization_backward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), + &diff_data_desc.data, &data_desc.data, + static_cast(epsilon), flags), + "could not create a batch normalization backward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const batch_normalization_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const batch_normalization_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(mean, src, 1); + REG_QUERY_MD(variance, src, 2); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(workspace, workspace, 0); + + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(diff_weights, diff_weights, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + batch_normalization_backward(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_inner_product Inner Product +/// A primitive to compute an inner product. +/// +/// @sa @ref c_api_inner_product in @ref c_api +/// @{ + +struct inner_product_forward: public primitive { + struct desc { + mkldnn_inner_product_desc_t data; + desc(prop_kind aprop_kind, const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &bias_desc, + const memory::desc &dst_desc) { + error::wrap_c_api( + mkldnn_inner_product_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), &src_desc.data, + &weights_desc.data, &bias_desc.data, &dst_desc.data), + "could not create a inner product forward descriptor"); + } + + desc(prop_kind aprop_kind, const memory::desc &src_desc, + const memory::desc &weights_desc, + const memory::desc &dst_desc) { + error::wrap_c_api( + mkldnn_inner_product_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), &src_desc.data, + &weights_desc.data, nullptr, &dst_desc.data), + "could not create a inner product forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(bias, weights, 1); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + inner_product_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct inner_product_backward_data: public primitive { + struct desc { + mkldnn_inner_product_desc_t data; + desc(const memory::desc &diff_src_desc, + const memory::desc &weights_desc, + const memory::desc &diff_dst_desc) { + error::wrap_c_api( + mkldnn_inner_product_backward_data_desc_init(&data, + &diff_src_desc.data, &weights_desc.data, + &diff_dst_desc.data), + "could not create a inner product backward data descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const inner_product_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const inner_product_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(weights, weights, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + inner_product_backward_data(const primitive_desc &pd): primitive(pd) {} +}; + +struct inner_product_backward_weights: public primitive { + struct desc { + mkldnn_inner_product_desc_t data; + desc(const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_bias_desc, + const memory::desc &diff_dst_desc) { + error::wrap_c_api( + mkldnn_inner_product_backward_weights_desc_init( + &data, &src_desc.data, &diff_weights_desc.data, + &diff_bias_desc.data, &diff_dst_desc.data), + "could not create a inner product backward weights descriptor"); + } + desc(const memory::desc &src_desc, + const memory::desc &diff_weights_desc, + const memory::desc &diff_dst_desc) { + error::wrap_c_api( + mkldnn_inner_product_backward_weights_desc_init( + &data, &src_desc.data, &diff_weights_desc.data, + nullptr, &diff_dst_desc.data), + "could not create a inner product backward weights descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const inner_product_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const inner_product_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(diff_weights, diff_weights, 0); + REG_QUERY_MD(diff_bias, diff_weights, 1); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + inner_product_backward_weights(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_rnn RNN +/// A primitive to compute common recurrent layer. +/// +/// @sa @ref c_api_rnn in @ref c_api +/// @{ + +struct rnn_cell { + struct desc { + mkldnn_rnn_cell_desc_t c_rnn_cell_; + + desc(algorithm kind, algorithm activation_f) { + error::wrap_c_api(mkldnn_rnn_cell_desc_init(&c_rnn_cell_, + mkldnn::convert_to_c(kind), + mkldnn::convert_to_c(activation_f), 0U, 0, 0), + "could not init an rnn cell descriptor"); + } + desc(algorithm kind): desc(kind, algorithm::algorithm_undef) {} + + operator const mkldnn_rnn_cell_desc_t*() const { return &c_rnn_cell_; } + + algorithm get_cell_kind() const + { return algorithm(c_rnn_cell_.cell_kind); } + algorithm get_activation() const + { return algorithm(c_rnn_cell_.activation_kind); } + + float get_alpha() const { return c_rnn_cell_.alpha; } + void set_alpha(float alpha) { + c_rnn_cell_.flags |= mkldnn_rnn_cell_with_relu; + c_rnn_cell_.alpha = alpha; + } + + float get_clipping() const { return c_rnn_cell_.clipping; } + void set_clipping(float clipping) { + c_rnn_cell_.flags |= mkldnn_rnn_cell_with_clipping; + c_rnn_cell_.clipping = clipping; + } + + int get_gates_count() const { + return mkldnn_rnn_cell_get_gates_count(&c_rnn_cell_); + } + int get_state_count() const { + return mkldnn_rnn_cell_get_states_count(&c_rnn_cell_); + } + }; +}; + +struct rnn_forward : public primitive { + struct desc { + mkldnn_rnn_desc_t data; + desc(prop_kind aprop_kind, rnn_cell::desc cell, + const rnn_direction direction, + const memory::desc &src_layer_desc, + const memory::desc &src_iter_desc, + const memory::desc &weights_layer_desc, + const memory::desc &weights_iter_desc, + const memory::desc &bias_desc, + const memory::desc &dst_layer_desc, + const memory::desc &dst_iter_desc + ) { + error::wrap_c_api(mkldnn_rnn_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), cell, + mkldnn::convert_to_c(direction), + &src_layer_desc.data, &src_iter_desc.data, + &weights_layer_desc.data, &weights_iter_desc.data, + &bias_desc.data, + &dst_layer_desc.data, &dst_iter_desc.data), + "could not create an RNN forward descriptor"); + } + + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e) + : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {} + + REG_QUERY_MD(src_layer, src, 0); + REG_QUERY_MD(src_iter, src, 1); + REG_QUERY_MD(weights_layer, weights, 0); + REG_QUERY_MD(weights_iter, weights, 1); + REG_QUERY_MD(bias, weights, 2); + REG_QUERY_MD(dst_layer, dst, 0); + REG_QUERY_MD(dst_iter, dst, 1); + REG_QUERY_MD(workspace, workspace, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + rnn_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct rnn_backward : public primitive { + struct desc { + mkldnn_rnn_desc_t data; + desc(prop_kind aprop_kind, rnn_cell::desc cell, + const rnn_direction direction, + const memory::desc &src_layer_desc, + const memory::desc &src_iter_desc, + const memory::desc &weights_layer_desc, + const memory::desc &weights_iter_desc, + const memory::desc &bias_desc, + const memory::desc &dst_layer_desc, + const memory::desc &dst_iter_desc, + const memory::desc &diff_src_layer_desc, + const memory::desc &diff_src_iter_desc, + const memory::desc &diff_weights_layer_desc, + const memory::desc &diff_weights_iter_desc, + const memory::desc &diff_bias_desc, + const memory::desc &diff_dst_layer_desc, + const memory::desc &diff_dst_iter_desc) { + error::wrap_c_api(mkldnn_rnn_backward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), cell, + mkldnn::convert_to_c(direction), + &src_layer_desc.data, &src_iter_desc.data, + &weights_layer_desc.data, &weights_iter_desc.data, + &bias_desc.data, + &dst_layer_desc.data, &dst_iter_desc.data, + &diff_src_layer_desc.data, &diff_src_iter_desc.data, + &diff_weights_layer_desc.data, + &diff_weights_iter_desc.data, &diff_bias_desc.data, + &diff_dst_layer_desc.data, &diff_dst_iter_desc.data), + "could not create an RNN backward descriptor"); + } + + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const rnn_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e, + const rnn_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(src_layer, src, 0); + REG_QUERY_MD(src_iter, src, 1); + REG_QUERY_MD(weights_layer, weights, 0); + REG_QUERY_MD(weights_iter, weights, 1); + REG_QUERY_MD(bias, weights, 2); + REG_QUERY_MD(dst_layer, dst, 0); + REG_QUERY_MD(dst_iter, dst, 1); + REG_QUERY_MD(workspace, workspace, 0); + + REG_QUERY_MD(diff_src_layer, diff_src, 0); + REG_QUERY_MD(diff_src_iter, diff_src, 1); + REG_QUERY_MD(diff_weights_layer, diff_weights, 0); + REG_QUERY_MD(diff_weights_iter, diff_weights, 1); + REG_QUERY_MD(diff_bias, diff_weights, 2); + REG_QUERY_MD(diff_dst_layer, diff_dst, 0); + REG_QUERY_MD(diff_dst_iter, diff_dst, 1); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + // With last iteration (with and without input src_iter) + rnn_backward(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @addtogroup cpp_api_shuffle Shuffle +/// A primitive to shuffle data along the axis. +/// +/// @sa @ref c_api_shuffle in @ref c_api +/// @{ + +struct shuffle_forward : public primitive { + struct desc { + mkldnn_shuffle_desc_t data; + desc(prop_kind aprop_kind, const memory::desc &data_desc, + int axis, int group_size) { + error::wrap_c_api(mkldnn_shuffle_forward_desc_init(&data, + mkldnn::convert_to_c(aprop_kind), &data_desc.data, + axis, group_size), + "could not create a shuffle forward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e) + : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {} + + REG_QUERY_MD(src, src, 0); + REG_QUERY_MD(dst, dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + shuffle_forward(const primitive_desc &pd): primitive(pd) {} +}; + +struct shuffle_backward : public primitive { + struct desc { + mkldnn_shuffle_desc_t data; + desc(const memory::desc &diff_data_desc, int axis, int group_size) { + error::wrap_c_api(mkldnn_shuffle_backward_desc_init(&data, + &diff_data_desc.data, axis, group_size), + "could not create a shuffle backward descriptor"); + } + }; + + struct primitive_desc : public mkldnn::primitive_desc { + primitive_desc(const desc &desc, const engine &e, + const shuffle_forward::primitive_desc &hint_fwd_pd) + : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {} + + REG_QUERY_MD(diff_src, diff_src, 0); + REG_QUERY_MD(diff_dst, diff_dst, 0); + REG_QUERY_MD(scratchpad, scratchpad, 0); + }; + + shuffle_backward(const primitive_desc &pd): primitive(pd) {} +}; + +/// @} + +/// @} Primitives + +/// @} C++ API + +#undef REG_QUERY_MD + +// implementation section +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +inline primitive::primitive(const_mkldnn_primitive_desc_t c_pd) { + mkldnn_primitive_t result; + error::wrap_c_api(mkldnn_primitive_create(&result, c_pd), + "could not create a primitive"); + reset(result); +} + +inline primitive::primitive(const primitive_desc &pd): primitive(pd.get()) {} + +inline void primitive::execute(stream &astream, + const std::unordered_map &args) const { + std::vector c_args; + c_args.reserve(args.size()); + for (const auto &a: args) + c_args.push_back({a.first, a.second.get()}); + + error::wrap_c_api(mkldnn_primitive_execute(get(), astream.get(), + (int)c_args.size(), c_args.data()), + "primitive execution fail"); +} +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} // namespace mkldnn + +#endif diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h b/thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h new file mode 100644 index 0000000000..f4dc2fdfa6 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h @@ -0,0 +1,98 @@ +/******************************************************************************* +* Copyright 2018-2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* DO NOT EDIT, AUTO-GENERATED */ + +#ifndef MKLDNN_DEBUG_H +#define MKLDNN_DEBUG_H + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/* All symbols shall be internal unless marked as MKLDNN_API */ +#if defined _WIN32 || defined __CYGWIN__ +# define MKLDNN_HELPER_DLL_IMPORT __declspec(dllimport) +# define MKLDNN_HELPER_DLL_EXPORT __declspec(dllexport) +#else +# if __GNUC__ >= 4 +# define MKLDNN_HELPER_DLL_IMPORT __attribute__ ((visibility ("default"))) +# define MKLDNN_HELPER_DLL_EXPORT __attribute__ ((visibility ("default"))) +# else +# define MKLDNN_HELPER_DLL_IMPORT +# define MKLDNN_HELPER_DLL_EXPORT +# endif +#endif + +#ifdef MKLDNN_DLL +# ifdef MKLDNN_DLL_EXPORTS +# define MKLDNN_API MKLDNN_HELPER_DLL_EXPORT +# else +# define MKLDNN_API MKLDNN_HELPER_DLL_IMPORT +# endif +#else +# define MKLDNN_API +#endif + +#if defined (__GNUC__) +# define MKLDNN_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define MKLDNN_DEPRECATED __declspec(deprecated) +#else +# define MKLDNN_DEPRECATED +#endif + +#include "mkldnn_types.h" +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +#ifdef __cplusplus +extern "C" { +#endif + +const char MKLDNN_API *mkldnn_status2str(mkldnn_status_t v); +const char MKLDNN_API *mkldnn_dt2str(mkldnn_data_type_t v); +const char MKLDNN_API *mkldnn_fmt_kind2str(mkldnn_format_kind_t v); +const char MKLDNN_API *mkldnn_fmt_tag2str(mkldnn_format_tag_t v); +const char MKLDNN_API *mkldnn_prop_kind2str(mkldnn_prop_kind_t v); +const char MKLDNN_API *mkldnn_prim_kind2str(mkldnn_primitive_kind_t v); +const char MKLDNN_API *mkldnn_alg_kind2str(mkldnn_alg_kind_t v); +const char MKLDNN_API *mkldnn_rnn_direction2str(mkldnn_rnn_direction_t v); + +/** Forms a format string for a given memory descriptor. + * + * The format is defined as: 'dt:[p|o|0]:fmt_kind:fmt:extra'. + * Here: + * - dt -- data type + * - p -- indicates there is non-trivial padding + * - o -- indicates there is non-trivial padding offset + * - 0 -- indicates there is non-trivial offset0 + * - fmt_kind -- format kind (blocked, wino, etc...) + * - fmt -- extended format string (format_kind specific) + * - extra -- shows extra fields (underspecified) + */ +int MKLDNN_API mkldnn_md2fmt_str(char *fmt_str, size_t fmt_str_len, + const mkldnn_memory_desc_t *md); + +/** Forms a dimension string for a given memory descriptor. + * + * The format is defined as: 'dim0xdim1x...xdimN + */ +int MKLDNN_API mkldnn_md2dim_str(char *dim_str, size_t dim_str_len, + const mkldnn_memory_desc_t *md); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_types.h b/thirdparty/oidn/mkl-dnn/include/mkldnn_types.h new file mode 100644 index 0000000000..1b6c356982 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_types.h @@ -0,0 +1,1415 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_TYPES_H +#define MKLDNN_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +#include +#include +#endif + +/** @addtogroup c_api C API + * @{ + * + * @addtogroup c_api_types Types + * @{ + * + * @addtogroup c_api_types_generic Generic + * @{ */ + +/** Intel(R) MKL-DNN Version type */ +typedef struct { + int major; + int minor; + int patch; + const char *hash; +} mkldnn_version_t; + +/** Status values returned by Intel(R) MKL-DNN functions. */ +typedef enum { + /** The operation was successful */ + mkldnn_success = 0, + /** The operation failed due to an out-of-memory condition */ + mkldnn_out_of_memory = 1, + /** The operation failed and should be retried */ + mkldnn_try_again = 2, + /** The operation failed because of incorrect function arguments */ + mkldnn_invalid_arguments = 3, + /** The operation failed because a primitive was not ready for execution */ + mkldnn_not_ready = 4, + /** The operation failed because requested functionality is not implemented + */ + mkldnn_unimplemented = 5, + /** Primitive iterator passed over last primitive descriptor */ + mkldnn_iterator_ends = 6, + /** Primitive or engine failed on execution */ + mkldnn_runtime_error = 7, + /** Queried element is not required for given primitive */ + mkldnn_not_required = 8, +} mkldnn_status_t; + +/** Data type specification */ +typedef enum { + /** Undefined data type, used for empty memory descriptors. */ + mkldnn_data_type_undef = 0, + /** 32-bit/single-precision floating point. */ + mkldnn_f32 = 1, + /** 32-bit signed integer. */ + mkldnn_s32 = 2, + /** 8-bit signed integer. */ + mkldnn_s8 = 3, + /** 8-bit unsigned integer. */ + mkldnn_u8 = 4, +} mkldnn_data_type_t; + +/** Memory format kind */ +typedef enum { + /** Undefined memory format, used for empty memory descriptors. */ + mkldnn_format_kind_undef = 0, + /** Unspecified format. The primitive selects a format automatically. */ + mkldnn_format_kind_any, + /** A tensor in a generic format described by the stride and blocking + * values in each dimension. See #mkldnn_blocking_desc_t for more + * information. */ + mkldnn_blocked, + /** Weights format used in 8bit Winograd convolution */ + mkldnn_format_kind_wino, + /** Packed weights format used in RNN */ + mkldnn_format_kind_rnn_packed, +} mkldnn_format_kind_t; + +/** Memory format tag specification. + * + * Intel MKL-DNN formats describe physical data layout. The physical layout + * is described as a sequence of the dimensions as they are laid out in the + * memory (from the outer-most to the inner-most). Note that this order + * doesn't affect the logical order of the dimensions that is kept in the + * `dims` field of the mkldnn_memory_desc_t structure. The logical order of the + * dimensions is specified by the type of tensor. + * + * For example, CNN 5D tensor always has its logical dimensions in the order + * `(batch, channels, depth, height, width)`, while the physical layout might be + * #mkldnn_ncdhw or #mkldnn_ndhwc: + * + * ~~~cpp + * int batch = 2, channels = 16, depth = 13, height = 13, width = 13; + * + * int ndims = 5; // 5D tensor + * mkldnn_dims_t dims = {batch, channels, depth, height, width}; + * mkldnn_memory_desc_t data_in_ncdhw; + * mkldnn_memory_desc_init_by_tag( + * &data_in_ncdhw, 5, dims, mkldnn_f32, mkldnn_ncdhw); + * + * // note that in both cases dims passed are the same + * mkldnn_memory_desc_t data_in_ndhwc; + * mkldnn_memory_desc_init_by_tag( + * &data_in_ndhwc, 5, dims, mkldnn_f32, mkldnn_ndhwc); + * ~~~ + * + * The following notation applies to memory format names: + * - @c 'n' denotes the mini-batch dimension + * - @c 'c' denotes a channels dimension + * - When there are multiple channel dimensions (for example, in convolution + * weights tensor), @c 'i' and @c 'o' denote dimensions of input and output + * channels + * - @c 'd', @c 'h', and @c 'w' denote spatial depth, height, and width + * respectively + * - Upper-case letters indicate that the data is laid out in blocks + * for a particular dimension. In such cases, the format name contains both + * upper- and lower-case letters for that dimension with a lower-case letter + * preceded by the block size. For example: @c 'mkldnn_nChw8c' describes a + * format where the outermost dimension is mini-batch, followed by the + * channel block number, followed by the spatial height and width, and + * finally followed by 8-element channel blocks. + * + * @note + * Channel designations can be different. For example, both the @c + * 'mkldnn_nc' and @c 'mkldnn_io' formats can be used to describe a 2D + * tensor. + * + * @sa @ref understanding_memory_formats + */ +typedef enum { + /** Undefined memory format tag */ + mkldnn_format_tag_undef = 0, + /** Undefined memory format tag. + * The primitive selects a format automatically. */ + mkldnn_format_tag_any, + + /* Semantic agnostic section */ + /* The physical order of dimensions is defined by the permutation of the + * characters, assuming that ab..z defines the natural order. + */ + + /* Plain formats */ + + mkldnn_a, + mkldnn_ab, + mkldnn_abc, + mkldnn_abcd, + mkldnn_abcde, + mkldnn_abcdef, + mkldnn_abdec, + mkldnn_acb, + mkldnn_acbde, + mkldnn_acdb, + mkldnn_acdeb, + mkldnn_ba, + mkldnn_bac, + mkldnn_bacd, + mkldnn_bcda, + mkldnn_cba, + mkldnn_cdba, + mkldnn_cdeba, + mkldnn_decab, + + /* Opaque blocked formats */ + + mkldnn_Abc16a, + mkldnn_ABc16a16b, + mkldnn_aBc16b, + mkldnn_ABc16b16a, + mkldnn_Abc4a, + mkldnn_aBc4b, + mkldnn_ABc4b16a4b, + mkldnn_ABc4b4a, + mkldnn_ABc8a16b2a, + mkldnn_ABc8a8b, + mkldnn_aBc8b, + mkldnn_ABc8b16a2b, + mkldnn_ABc8b8a, + mkldnn_Abcd16a, + mkldnn_ABcd16a16b, + mkldnn_aBcd16b, + mkldnn_ABcd16b16a, + mkldnn_aBCd16b16c, + mkldnn_aBCd16c16b, + mkldnn_Abcd4a, + mkldnn_aBcd4b, + mkldnn_ABcd4b16a4b, + mkldnn_ABcd4b4a, + mkldnn_aBCd4c16b4c, + mkldnn_aBCd4c4b, + mkldnn_ABcd8a16b2a, + mkldnn_ABcd8a8b, + mkldnn_aBcd8b, + mkldnn_ABcd8b16a2b, + mkldnn_aBCd8b16c2b, + mkldnn_ABcd8b8a, + mkldnn_aBCd8b8c, + mkldnn_aBCd8c16b2c, + mkldnn_aBCd8c8b, + mkldnn_Abcde16a, + mkldnn_ABcde16a16b, + mkldnn_aBcde16b, + mkldnn_ABcde16b16a, + mkldnn_aBCde16b16c, + mkldnn_aBCde16c16b, + mkldnn_aBCde2c8b4c, + mkldnn_Abcde4a, + mkldnn_aBcde4b, + mkldnn_ABcde4b4a, + mkldnn_aBCde4b4c, + mkldnn_aBCde4c16b4c, + mkldnn_aBCde4c4b, + mkldnn_Abcde8a, + mkldnn_ABcde8a8b, + mkldnn_aBcde8b, + mkldnn_ABcde8b16a2b, + mkldnn_aBCde8b16c2b, + mkldnn_ABcde8b8a, + mkldnn_aBCde8b8c, + mkldnn_aBCde8c16b2c, + mkldnn_aBCde8c8b, + mkldnn_aBcdef16b, + mkldnn_aBCdef16b16c, + mkldnn_aBCdef16c16b, + mkldnn_aBcdef4b, + mkldnn_aBCdef4c4b, + mkldnn_aBCdef8b8c, + mkldnn_aBCdef8c16b2c, + mkldnn_aBCdef8c8b, + mkldnn_aBdc16b, + mkldnn_aBdc4b, + mkldnn_aBdc8b, + mkldnn_aBdec16b, + mkldnn_aBdec4b, + mkldnn_aBdec8b, + mkldnn_aBdefc16b, + mkldnn_aBdefc4b, + mkldnn_aBdefc8b, + mkldnn_Acb16a, + mkldnn_Acb4a, + mkldnn_Acb8a, + mkldnn_aCBd16b16c, + mkldnn_aCBde16b16c, + mkldnn_Acdb16a, + mkldnn_Acdb4a, + mkldnn_Acdb8a, + mkldnn_Acdeb16a, + mkldnn_Acdeb4a, + mkldnn_Acdeb8a, + mkldnn_BAc16a16b, + mkldnn_BAcd16a16b, + + /** Just a sentinel, not real memory format tag. Must be changed after new + * format tag is added. */ + mkldnn_format_tag_last, + + /* Aliases */ + + mkldnn_x = mkldnn_a, + mkldnn_nc = mkldnn_ab, + mkldnn_cn = mkldnn_ba, + mkldnn_ncw = mkldnn_abc, + mkldnn_nwc = mkldnn_acb, + mkldnn_nchw = mkldnn_abcd, + mkldnn_nhwc = mkldnn_acdb, + mkldnn_chwn = mkldnn_bcda, + mkldnn_ncdhw = mkldnn_abcde, + mkldnn_ndhwc = mkldnn_acdeb, + + mkldnn_oi = mkldnn_ab, + mkldnn_io = mkldnn_ba, + mkldnn_oiw = mkldnn_abc, + mkldnn_wio = mkldnn_cba, + mkldnn_oihw = mkldnn_abcd, + mkldnn_hwio = mkldnn_cdba, + mkldnn_ihwo = mkldnn_bcda, + mkldnn_iohw = mkldnn_bacd, + mkldnn_oidhw = mkldnn_abcde, + mkldnn_dhwio = mkldnn_cdeba, + mkldnn_goiw = mkldnn_abcd, + mkldnn_goihw = mkldnn_abcde, + mkldnn_hwigo = mkldnn_decab, + mkldnn_giohw = mkldnn_acbde, + mkldnn_goidhw = mkldnn_abcdef, + + /** 3D RNN data tensor in the format (seq_length, batch, input channels). */ + mkldnn_tnc = mkldnn_abc, + /** 3D RNN data tensor in the format (batch, seq_length, input channels). */ + mkldnn_ntc = mkldnn_bac, + /** 5D RNN states tensor in the format (num_layers, num_directions, + * num_states, batch, state channels). */ + mkldnn_ldsnc = mkldnn_abcde, + /** 5D RNN weights tensor in the format (num_layers, num_directions, + * input_channels, num_gates, output_channels). + * + * - For LSTM cells, the gates order is input, forget, candidate + * and output gate. + * - For GRU cells, the gates order is update, reset and output gate. */ + mkldnn_ldigo = mkldnn_abcde, + /** 5D RNN weights tensor in the format (num_layers, num_directions, + * num_gates, output_channels, input_channels). + * + * - For LSTM cells, the gates order is input, forget, candidate + * and output gate. + * - For GRU cells, the gates order is update, reset and output gate. */ + mkldnn_ldgoi = mkldnn_abdec, + /** 4D RNN bias tensor in the format (num_layers, num_directions, + * num_gates, output_channels). + * + * - For LSTM cells, the gates order is input, forget, candidate + * and output gate. + * - For GRU cells, the gates order is update, reset and output gate. */ + mkldnn_ldgo = mkldnn_abcd, + + /* Opaque data types, are not to be used explicitly */ + + /* data */ + mkldnn_nCdhw16c = mkldnn_aBcde16b, + mkldnn_nCdhw4c = mkldnn_aBcde4b, + mkldnn_nCdhw8c = mkldnn_aBcde8b, + mkldnn_nChw16c = mkldnn_aBcd16b, + mkldnn_nChw4c = mkldnn_aBcd4b, + mkldnn_nChw8c = mkldnn_aBcd8b, + mkldnn_nCw16c = mkldnn_aBc16b, + mkldnn_nCw4c = mkldnn_aBc4b, + mkldnn_nCw8c = mkldnn_aBc8b, + + /* weights, 3D */ + mkldnn_IOw16o16i = mkldnn_BAc16a16b, + mkldnn_OIw16i16o = mkldnn_ABc16b16a, + mkldnn_OIw16o16i = mkldnn_ABc16a16b, + mkldnn_Oiw16o = mkldnn_Abc16a, + mkldnn_OIw4i16o4i = mkldnn_ABc4b16a4b, + mkldnn_OIw4i4o = mkldnn_ABc4b4a, + mkldnn_Oiw4o = mkldnn_Abc4a, + mkldnn_OIw8i16o2i = mkldnn_ABc8b16a2b, + mkldnn_OIw8i8o = mkldnn_ABc8b8a, + mkldnn_OIw8o16i2o = mkldnn_ABc8a16b2a, + mkldnn_OIw8o8i = mkldnn_ABc8a8b, + mkldnn_Owi16o = mkldnn_Acb16a, + mkldnn_Owi4o = mkldnn_Acb4a, + mkldnn_Owi8o = mkldnn_Acb8a, + + /* weights, 4D */ + mkldnn_IOhw16o16i = mkldnn_BAcd16a16b, + mkldnn_Ohwi16o = mkldnn_Acdb16a, + mkldnn_Ohwi4o = mkldnn_Acdb4a, + mkldnn_Ohwi8o = mkldnn_Acdb8a, + mkldnn_OIhw16i16o = mkldnn_ABcd16b16a, + mkldnn_OIhw16o16i = mkldnn_ABcd16a16b, + mkldnn_Oihw16o = mkldnn_Abcd16a, + mkldnn_OIhw4i16o4i = mkldnn_ABcd4b16a4b, + mkldnn_OIhw4i4o = mkldnn_ABcd4b4a, + mkldnn_Oihw4o = mkldnn_Abcd4a, + mkldnn_OIhw8i16o2i = mkldnn_ABcd8b16a2b, + mkldnn_OIhw8i8o = mkldnn_ABcd8b8a, + mkldnn_OIhw8o16i2o = mkldnn_ABcd8a16b2a, + mkldnn_OIhw8o8i = mkldnn_ABcd8a8b, + + /* weights, 5D */ + mkldnn_Odhwi16o = mkldnn_Acdeb16a, + mkldnn_Odhwi4o = mkldnn_Acdeb4a, + mkldnn_Odhwi8o = mkldnn_Acdeb8a, + mkldnn_OIdhw16i16o = mkldnn_ABcde16b16a, + mkldnn_OIdhw16o16i = mkldnn_ABcde16a16b, + mkldnn_Oidhw16o = mkldnn_Abcde16a, + mkldnn_OIdhw4i4o = mkldnn_ABcde4b4a, + mkldnn_Oidhw4o = mkldnn_Abcde4a, + mkldnn_OIdhw8i16o2i = mkldnn_ABcde8b16a2b, + mkldnn_OIdhw8i8o = mkldnn_ABcde8b8a, + mkldnn_OIdhw8o8i = mkldnn_ABcde8a8b, + + /* weights w/ groups, 3D */ + mkldnn_Goiw16g = mkldnn_Abcd16a, + mkldnn_gIOw16o16i = mkldnn_aCBd16b16c, + mkldnn_gOIw16i16o = mkldnn_aBCd16c16b, + mkldnn_gOIw16o16i = mkldnn_aBCd16b16c, + mkldnn_gOiw16o = mkldnn_aBcd16b, + mkldnn_gOIw4i16o4i = mkldnn_aBCd4c16b4c, + mkldnn_gOIw4i4o = mkldnn_aBCd4c4b, + mkldnn_gOiw4o = mkldnn_aBcd4b, + mkldnn_gOIw8i16o2i = mkldnn_aBCd8c16b2c, + mkldnn_gOIw8i8o = mkldnn_aBCd8c8b, + mkldnn_gOIw8o16i2o = mkldnn_aBCd8b16c2b, + mkldnn_gOIw8o8i = mkldnn_aBCd8b8c, + mkldnn_gOwi16o = mkldnn_aBdc16b, + mkldnn_gOwi4o = mkldnn_aBdc4b, + mkldnn_gOwi8o = mkldnn_aBdc8b, + + /* weights w/ groups, 4D */ + mkldnn_gIOhw16o16i = mkldnn_aCBde16b16c, + mkldnn_gOhwi16o = mkldnn_aBdec16b, + mkldnn_gOhwi4o = mkldnn_aBdec4b, + mkldnn_gOhwi8o = mkldnn_aBdec8b, + mkldnn_Goihw16g = mkldnn_Abcde16a, + mkldnn_gOIhw16i16o = mkldnn_aBCde16c16b, + mkldnn_gOIhw16o16i = mkldnn_aBCde16b16c, + mkldnn_gOihw16o = mkldnn_aBcde16b, + mkldnn_gOIhw2i8o4i = mkldnn_aBCde2c8b4c, + mkldnn_gOIhw4i16o4i = mkldnn_aBCde4c16b4c, + mkldnn_gOIhw4i4o = mkldnn_aBCde4c4b, + mkldnn_gOIhw4o4i = mkldnn_aBCde4b4c, + mkldnn_gOihw4o = mkldnn_aBcde4b, + mkldnn_Goihw8g = mkldnn_Abcde8a, + mkldnn_gOIhw8i16o2i = mkldnn_aBCde8c16b2c, + mkldnn_gOIhw8i8o = mkldnn_aBCde8c8b, + mkldnn_gOIhw8o16i2o = mkldnn_aBCde8b16c2b, + mkldnn_gOIhw8o8i = mkldnn_aBCde8b8c, + + /* weights w/ groups, 6D */ + mkldnn_gOdhwi16o = mkldnn_aBdefc16b, + mkldnn_gOdhwi4o = mkldnn_aBdefc4b, + mkldnn_gOdhwi8o = mkldnn_aBdefc8b, + mkldnn_gOIdhw16i16o = mkldnn_aBCdef16c16b, + mkldnn_gOIdhw16o16i = mkldnn_aBCdef16b16c, + mkldnn_gOidhw16o = mkldnn_aBcdef16b, + mkldnn_gOIdhw4i4o = mkldnn_aBCdef4c4b, + mkldnn_gOidhw4o = mkldnn_aBcdef4b, + mkldnn_gOIdhw8i16o2i = mkldnn_aBCdef8c16b2c, + mkldnn_gOIdhw8i8o = mkldnn_aBCdef8c8b, + mkldnn_gOIdhw8o8i = mkldnn_aBCdef8b8c, +} mkldnn_format_tag_t; + +/** Kinds of padding. Define how to interpret the data in padding regions. */ +typedef enum { + /** The data in padding regions is zero. */ + mkldnn_padding_zero, +} mkldnn_padding_kind_t; + +/** Kinds of propagation. */ +typedef enum { + /* TODO: suggest renames */ + /** Undefined propagation type. */ + mkldnn_prop_kind_undef = 0, + /** Forward data propagation (training mode). In this mode primitives + * perform computations necessary for subsequent backward propagation. */ + mkldnn_forward_training = 64, + /** Forward data propagation (inference mode). In this mode primitives + * perform only computations that are necessary for inference and omit + * computations that are necessary only for backward propagation. */ + mkldnn_forward_inference = 96, + /** Forward data propagation (alias for @c mkldnn_forward_inference) */ + mkldnn_forward_scoring = mkldnn_forward_inference, + /** Forward data propagation (alias for @c mkldnn_forward_training) */ + mkldnn_forward = mkldnn_forward_training, + /** Backward propagation (with respect to all parameters */ + mkldnn_backward = 128, + /** Backward data propagation */ + mkldnn_backward_data = 160, + /** Backward weights propagation */ + mkldnn_backward_weights = 192, + /** Backward bias propagation */ + mkldnn_backward_bias = 193, +} mkldnn_prop_kind_t; + +/** Kinds of primitives. Used to implement a way to extend the library with new + * primitives without changing the ABI. */ +typedef enum { + /** Undefined primitive (XXX: why do we have it?). */ + mkldnn_undefined_primitive, + /** A reorder primitive.*/ + mkldnn_reorder, + /** A shuffle primitive.*/ + mkldnn_shuffle, + /** A (out-of-place) concat primitive. */ + mkldnn_concat, + /** A sum primitive. */ + mkldnn_sum, + /** A convolution primitive. */ + mkldnn_convolution, + /** A deconvolution primitive. */ + mkldnn_deconvolution, + /** An element-wise primitive. */ + mkldnn_eltwise, + /** A Softmax primitive. */ + mkldnn_softmax, + /** A pooling primitive. */ + mkldnn_pooling, + /** An LRN primitive. */ + mkldnn_lrn, + /** An batch normalization primitive. */ + mkldnn_batch_normalization, + /** An inner product primitive. */ + mkldnn_inner_product, + /** A rnn primitive. */ + mkldnn_rnn, +} mkldnn_primitive_kind_t; + +/** Kinds of algorithms. */ +typedef enum { + mkldnn_alg_kind_undef, + /** Direct convolution */ + mkldnn_convolution_direct = 0x1, + /** Winograd convolution */ + mkldnn_convolution_winograd = 0x2, + /** Convolution algorithm(either direct or Winograd) is chosen just in time **/ + mkldnn_convolution_auto = 0x3, + /** Direct deconvolution */ + mkldnn_deconvolution_direct = 0xa, + /** Winograd deconvolution */ + mkldnn_deconvolution_winograd = 0xb, + /** Eltwise: ReLU */ + mkldnn_eltwise_relu = 0x1f, + /** Eltwise: hyperbolic tangent non-linearity (tanh) */ + mkldnn_eltwise_tanh = 0x2f, + /** Eltwise: parametric exponential linear unit (elu) */ + mkldnn_eltwise_elu = 0x3f, + /** Eltwise: square */ + mkldnn_eltwise_square = 0x4f, + /** Eltwise: abs */ + mkldnn_eltwise_abs = 0x5f, + /** Eltwise: square root */ + mkldnn_eltwise_sqrt = 0x6f, + /** Eltwise: linear */ + mkldnn_eltwise_linear = 0x7f, + /** Eltwise: bounded_relu */ + mkldnn_eltwise_bounded_relu = 0x8f, + /** Eltwise: soft_relu */ + mkldnn_eltwise_soft_relu = 0x9f, + /** Eltwise: logistic */ + mkldnn_eltwise_logistic = 0xaf, + /** Max pooling */ + mkldnn_pooling_max = 0x1ff, + /** Average pooling include padding */ + mkldnn_pooling_avg_include_padding = 0x2ff, + /** Average pooling exclude padding */ + mkldnn_pooling_avg_exclude_padding = 0x3ff, + mkldnn_pooling_avg = mkldnn_pooling_avg_exclude_padding, + /** Local response normalization (LRN) across multiple channels */ + mkldnn_lrn_across_channels = 0xaff, + /** LRN within a single channel */ + mkldnn_lrn_within_channel = 0xbff, + /** RNN cell */ + mkldnn_vanilla_rnn = 0x1fff, + /** LSTM cell */ + mkldnn_vanilla_lstm = 0x2fff, + /** GRU cell */ + mkldnn_vanilla_gru = 0x3fff, + /** GRU cell with linear before reset + * + * Modification of original GRU cell. Differs from #mkldnn_vanilla_gru + * in how the new memory gate is calculated: + * \f[ c_t = tanh(W_c*x_t + b_{c_x} + r_t*(U_c*h_{t-1}+b_{c_h})) \f] + * Primitive expects 4 biases on input: + * \f$[b_{u}, b_{r}, b_{c_x}, b_{c_h}]\f$ + * */ + mkldnn_gru_linear_before_reset = 0x4fff, +} mkldnn_alg_kind_t; + +/** Flags for batch-normalization primititve. */ +typedef enum { + /** Use global statistics + * + * If specified + * - on forward propagation use mean and variance provided by user (input) + * - on backward propagation reduces the amount of computations, since + * mean and variance are considered as constants + * + * If not specified: + * - on forward propagation mean and variance are computed and stored in + * output + * - on backward propagation compute full derivative wrt to data + */ + mkldnn_use_global_stats = 0x1U, + /** Use scale and shift parameters + * + * If specified: + * - on forward propagation use scale and shift (aka scale and bias) for + * the batch normalization results + * - on backward propagation (for prop_kind == #mkldnn_backward) compute + * diff wrt to scale and shift (hence one extra output used) + * + * If no specified: + * - on backward propagation prop_kind == #mkldnn_backward_data has the + * same behavior as prop_kind == #mkldnn_backward + */ + mkldnn_use_scaleshift = 0x2U, + /** Fuse with ReLU + * + * If specified: + * - on inference this option behaves the same as if the primitive were + * fused with ReLU via post ops API + * - on training primitive requires workspace (required to be able to + * perform backward pass) + */ + mkldnn_fuse_bn_relu = 0x4U, +} mkldnn_batch_normalization_flag_t; + +/** @} */ + +/** @addtogroup c_api_types_memory Memory + * @{ */ + +/** Maximum number of dimensions a tensor can have. Only restricts the amount + * of space used for the tensor description. Individual computational + * primitives may support only tensors of certain dimensions. */ +#define MKLDNN_MAX_NDIMS 12 + +/** A type to describe tensor dimension. */ +typedef int64_t mkldnn_dim_t; + +/** A type to describe tensor dimensions. */ +typedef mkldnn_dim_t mkldnn_dims_t[MKLDNN_MAX_NDIMS]; + +/** A type to describe strides within a tensor. */ +typedef mkldnn_dim_t mkldnn_strides_t[MKLDNN_MAX_NDIMS]; + +/** Generic description of blocked data layout for most memory formats. + * + * @sa @ref understanding_memory_formats */ +typedef struct { + /** The strides between the outermost blocks. + * In case of plain (non-blocked) formats the strides between dimensions. */ + mkldnn_dims_t strides; + /* Innermost section + * ASSUMPTION: the innermost blocks are always dense */ + /** The number of innermost blocks, e.g. 3 in case of `OIhw_4i16o4i_` */ + int inner_nblks; + /** The size of the blocks, e.g. `{4, 16, 4}` in case of `OIhw_4i16o4i` */ + mkldnn_dims_t inner_blks; + /** The logical indices of the blocks, e.g. `{1, 0, 1}` in case of + * `4i16o4i`, because `i` is the 1st dim and `o` is the 0st dim */ + mkldnn_dims_t inner_idxs; +} mkldnn_blocking_desc_t; + +typedef enum { + /** Undefined memory format, used for empty memory descriptors. */ + mkldnn_wino_undef = 0, + /** Tensors of weights for 2x3 winograd convolutions. */ + mkldnn_wino_wei_aaOIoi, + mkldnn_wino_wei_aaOio, + mkldnn_wino_wei_aaOBiOo, + /** Tensor of weights for 4x3 convolution. */ + mkldnn_wino_wei_OBaaIBOIio +} mkldnn_wino_memory_format_t; + +/** Description of tensor of weights for winograd 2x3 convolution. */ +typedef struct { + mkldnn_wino_memory_format_t wino_format; + int r; + int alpha; + int ic; + int oc; + int ic_block; + int oc_block; + int ic2_block; + int oc2_block; + float adj_scale; + size_t size; +} mkldnn_wino_desc_t; + +typedef enum { + mkldnn_packed_format_undef = 0, + mkldnn_ldigo_p, + mkldnn_ldgoi_p +} mkldnn_rnn_packed_memory_format_t; + +/* Maximum number of parts of RNN weights tensor that require separate + * computation. */ +#define MKLDNN_RNN_MAX_N_PARTS 4 + +/** Description of tensor of packed weights for rnn. */ +typedef struct { + mkldnn_rnn_packed_memory_format_t format; + int n_parts; + int n; + int parts[MKLDNN_RNN_MAX_N_PARTS]; + size_t part_pack_size[MKLDNN_RNN_MAX_N_PARTS]; + size_t offset_compensation; + size_t size; +} mkldnn_rnn_packed_desc_t; + +typedef enum { + mkldnn_memory_extra_flag_none = 0x0U, + /** Indicates the weights have an additional buffer, that depends on the + * @p compensation_mask. + * + * For instance, in 4D case with the compensation mask equals (1 << 0) + * the additional buffer would consist of OC values: + * O[oc : 0,OC] = + * -128 * SUM(ic : 0,IC; kh : 0,KH; kw : 0,KW){ weights(oc, ic, kh, kw) } + */ + mkldnn_memory_extra_flag_compensation_conv_s8s8 = 0x1U, + mkldnn_memory_extra_flag_scale_adjust = 0x2U, +} mkldnn_memory_extra_flags_t; + +/** Description of extra information stored in memory */ +typedef struct { + /** The flags contain arbitrary extra information, such as compensation. + * @sa mkldnn_memory_extra_flags_t */ + uint64_t flags; + /** Compensation mask */ + int compensation_mask; + /** Scale applied to the data */ + float scale_adjust; + /** For future backwards compatibility */ + char reserved[64]; +} mkldnn_memory_extra_desc_t; + +/** Memory descriptor. The description is based on a number of dimensions, + * dimensions themselves, plus information about elements type and memory + * format. Additionally, contains format-specific descriptions of the data + * layout. */ +typedef struct { + /** Number of dimensions */ + int ndims; + /** Dimensions in the following order: + * - CNN data tensors: mini-batch, channel, spatial + * ({N, C, [[D,] H,] W}) + * - CNN weight tensors: group (optional), output channel, input channel, + * spatial ({[G,] O, I, [[D,] H,] W}) + * - RNN data tensors: time, mini-batch, channels ({T, N, C}) + * or layers, directions, states, mini-batch, channels ({L, D, S, N, C}) + * - RNN weight tensor: layers, directions, input channel, gates, output channels + * ({L, D, I, G, O}). + * + * @note + * The order of dimensions does not depend on the memory format, so + * whether the data is laid out in #mkldnn_nchw or #mkldnn_nhwc + * the dims for 4D CN data tensor would be {N, C, H, W}. + */ + mkldnn_dims_t dims; + /** Data type of the tensor elements. */ + mkldnn_data_type_t data_type; + + /** Size of the data including padding in each dimension. */ + mkldnn_dims_t padded_dims; + /** Per-dimension offset from the padding to actual data, the top-level + * tensor with offsets applied must lie within the padding area. */ + mkldnn_dims_t padded_offsets; + + /** Offset from memory origin to the current block, non-zero only in + * a description of a memory sub-block. */ + mkldnn_dim_t offset0; + + /** Memory format kind. */ + mkldnn_format_kind_t format_kind; + union { + /** Description of the data layout for memory formats that use + * blocking. */ + mkldnn_blocking_desc_t blocking; + /** Tensor of weights for integer 8bit winograd convolution. */ + mkldnn_wino_desc_t wino_desc; + /** Tensor of packed weights for RNN. */ + mkldnn_rnn_packed_desc_t rnn_packed_desc; + /* ... other descriptions possible */ + } format_desc; + + mkldnn_memory_extra_desc_t extra; +} mkldnn_memory_desc_t; + +/** @struct mkldnn_memory + * An opaque structure to describe a memory. */ +struct mkldnn_memory; + +/** A memory handle. */ +typedef struct mkldnn_memory *mkldnn_memory_t; + +/** A constant memory handle. */ +typedef const struct mkldnn_memory *const_mkldnn_memory_t; + +#define MKLDNN_NATIVE_HANDLE_NONE (NULL) +#define MKLDNN_NATIVE_HANDLE_ALLOCATE ((void *)(size_t)-1) + +/** @} */ + +/** @addtogroup c_api_types_op_descs Operation descriptors + * @{*/ + +/** A pointer to any of the operation descriptors. */ +typedef void *mkldnn_op_desc_t; +/** A pointer to any of the operation descriptors (constant variant). */ +typedef const void *const_mkldnn_op_desc_t; + +/** A descriptor of a convolution operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_convolution. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, #mkldnn_backward_data, + * #mkldnn_backward_weights, and #mkldnn_backward_bias. */ + mkldnn_prop_kind_t prop_kind; + /** The kind of the convolution algorithm. Possible values: + * #mkldnn_convolution_direct. */ + mkldnn_alg_kind_t alg_kind; + /** Source memory descriptor. */ + mkldnn_memory_desc_t src_desc; + /** Source gradient memory descriptor. */ + mkldnn_memory_desc_t diff_src_desc; + /** Weights memory descriptor. */ + mkldnn_memory_desc_t weights_desc; + /** Weights gradient memory descriptor. */ + mkldnn_memory_desc_t diff_weights_desc; + /** Bias memory descriptor. */ + mkldnn_memory_desc_t bias_desc; + /** Bias gradient memory descriptor. */ + mkldnn_memory_desc_t diff_bias_desc; + /** Destination memory descriptor. */ + mkldnn_memory_desc_t dst_desc; + /** Destination gradient memory descriptor. */ + mkldnn_memory_desc_t diff_dst_desc; + /** Convolution strides in each spatial dimension. */ + mkldnn_dims_t strides; + /** Convolution dilates in each spatial dimension. */ + mkldnn_dims_t dilates; + /** Padding in each spatial dimension. padding[0] is a padding in the + * beginning (@p padding_l), padding[1] is a padding in the end (@p + * padding_r). */ + mkldnn_dims_t padding[2]; + /** The kind of padding to use. */ + mkldnn_padding_kind_t padding_kind; + /** The accumulator data type. Initialized automatically. */ + mkldnn_data_type_t accum_data_type; +} mkldnn_convolution_desc_t; + +/** A descriptor of a deconvolution operation. */ +typedef mkldnn_convolution_desc_t mkldnn_deconvolution_desc_t; + +/** A descriptor of a shuffle operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_convolution. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, and #mkldnn_backward_data. */ + mkldnn_prop_kind_t prop_kind; + /** Source and destination memory descriptor, + * and source and destination gradient memory descriptor. */ + mkldnn_memory_desc_t data_desc; + /** axis for shuffling. */ + int axis; + /** number of groups in group convolution */ + mkldnn_dim_t group_size; +} mkldnn_shuffle_desc_t; + +/** A descriptor of a element-wise operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_eltwise. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data. + */ + mkldnn_prop_kind_t prop_kind; + /** The kind of eltwise algorithm. Possible values: #mkldnn_eltwise_relu, + * #mkldnn_eltwise_tanh, #mkldnn_eltwise_elu, #mkldnn_eltwise_square, + * #mkldnn_eltwise_abs, #mkldnn_eltwise_sqrt, #mkldnn_eltwise_linear, + * #mkldnn_eltwise_bounded_relu, #mkldnn_eltwise_soft_relu, and + * #mkldnn_eltwise_logistic. */ + mkldnn_alg_kind_t alg_kind; + /** Source and destination memory descriptor. */ + mkldnn_memory_desc_t data_desc; + /** Source and destination gradient memory descriptor. */ + mkldnn_memory_desc_t diff_data_desc; + /** Algorithm specific parameter. + * Accordance table: + * - #mkldnn_eltwise_relu: @p alpha -- negative slope, @p beta ignored + * - #mkldnn_eltwise_tanh: @p alpha and @p beta ignored + * - #mkldnn_eltwise_elu: @p alpha -- negative slope, @p beta ignored + * - #mkldnn_eltwise_square: @p alpha and @p beta ignored + * - #mkldnn_eltwise_abs: @p alpha and @p beta ignored + * - #mkldnn_eltwise_sqrt: @p alpha and @p beta ignored + * - #mkldnn_eltwise_linear: @p alpha -- scale, @p beta -- shift + * - #mkldnn_eltwise_bounded_relu: @p alpha -- upper bound, @p beta ignored + * - #mkldnn_eltwise_soft_relu: @p alpha and @p beta ignored + * - #mkldnn_eltwise_logistic: @p alpha and @p beta ignored + */ + float alpha, beta; +} mkldnn_eltwise_desc_t; + +/** A descriptor of a Softmax operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_softmax. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training and + * #mkldnn_forward_inference. */ + mkldnn_prop_kind_t prop_kind; + /** Source and destination memory descriptor. */ + mkldnn_memory_desc_t data_desc; + /** Source and Destination of gradient memory descriptor. */ + mkldnn_memory_desc_t diff_desc; + /** The axis along which to perform the softmax. */ + int softmax_axis; +} mkldnn_softmax_desc_t; + +/** A descriptor of a pooling operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_pooling. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data. + */ + mkldnn_prop_kind_t prop_kind; + /** The kind of pooling algorithm. Possible values: #mkldnn_pooling_max and + * #mkldnn_pooling_avg. */ + mkldnn_alg_kind_t alg_kind; + /** Source memory descriptor. */ + mkldnn_memory_desc_t src_desc; + /** Source gradient memory descriptor. */ + mkldnn_memory_desc_t diff_src_desc; + /** Destination memory descriptor. */ + mkldnn_memory_desc_t dst_desc; + /** Destination gradient memory descriptor. */ + mkldnn_memory_desc_t diff_dst_desc; + /** Pooling kernel strides for spatial dimensions. */ + mkldnn_dims_t strides; + /** Pooling kernel spatial dimensions. */ + mkldnn_dims_t kernel; + /** Padding in each spatial dimension. padding[0] is a padding in the + * beginning (@p padding_l), padding[1] is a padding in the end (@p + * padding_r). */ + mkldnn_dims_t padding[2]; + /** The kind of padding to use. */ + mkldnn_padding_kind_t padding_kind; + /** The accumulator data type. Initialized automatically. */ + mkldnn_data_type_t accum_data_type; +} mkldnn_pooling_desc_t; + +/** A descriptor of a Local Response Normalization (LRN) operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_lrn. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data. + */ + mkldnn_prop_kind_t prop_kind; + /** LRN algorithm. Possible values: #mkldnn_lrn_within_channel and + * #mkldnn_lrn_across_channels. */ + mkldnn_alg_kind_t alg_kind; + /** Source and destination memory descriptor. */ + mkldnn_memory_desc_t data_desc; + /** Source and destination gradient memory descriptor. */ + mkldnn_memory_desc_t diff_data_desc; + /** The number of channels to sum over (for cross-channel LRN) or the side + * length of the square region to sum over (for within-channel LRN). */ + mkldnn_dim_t local_size; + /** LRN alpha parameter. */ + float lrn_alpha; + /** LRN beta parameter. */ + float lrn_beta; + /** LRN k parameter. */ + float lrn_k; +} mkldnn_lrn_desc_t; + +/** A descriptor of a Batch Normalization operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_batch_normalization. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data. + */ + mkldnn_prop_kind_t prop_kind; + /** Source and destination memory descriptor. */ + mkldnn_memory_desc_t data_desc; + /** Source and destination gradient memory descriptor. */ + mkldnn_memory_desc_t diff_data_desc; + /** Scale and shift data and gradient memory descriptors. + * + * Scaleshift memory descriptor uses 2D #mkldnn_nc format[2,Channels]. 1-st + * dimension contains gamma parameter, 2-nd dimension contains beta + * parameter. */ + mkldnn_memory_desc_t data_scaleshift_desc; + mkldnn_memory_desc_t diff_data_scaleshift_desc; + /** Mean and variance data memory descriptors. + * + * Mean and variance memory descriptors use 1D #mkldnn_x format[Channels]. + */ + mkldnn_memory_desc_t mean_desc; + mkldnn_memory_desc_t variance_desc; + /** Batch normalization epsilon parameter. */ + float batch_norm_epsilon; + unsigned flags; +} mkldnn_batch_normalization_desc_t; + +/** A descriptor of an inner product operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_inner_product. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, #mkldnn_backward_data, + * #mkldnn_backward_weights, and #mkldnn_backward_bias. */ + mkldnn_prop_kind_t prop_kind; + /** Source memory descriptor. */ + mkldnn_memory_desc_t src_desc; + /** Source gradient memory descriptor. */ + mkldnn_memory_desc_t diff_src_desc; + /** Weights memory descriptor. */ + mkldnn_memory_desc_t weights_desc; + /** Weights gradient memory descriptor. */ + mkldnn_memory_desc_t diff_weights_desc; + /** Bias memory descriptor. */ + mkldnn_memory_desc_t bias_desc; + /** Bias gradient memory descriptor. */ + mkldnn_memory_desc_t diff_bias_desc; + /** Destination memory descriptor. */ + mkldnn_memory_desc_t dst_desc; + /** Destination gradient memory descriptor. */ + mkldnn_memory_desc_t diff_dst_desc; + /** The accumulator data type. Initialized automatically. */ + mkldnn_data_type_t accum_data_type; +} mkldnn_inner_product_desc_t; + +/** Flags for RNN cell. */ +typedef enum { + mkldnn_rnn_cell_with_relu = 0x1U, + mkldnn_rnn_cell_with_clipping = 0x2U, +} mkldnn_rnn_cell_flags_t; + +typedef struct { + /** RNN cell kind. Must be one of #mkldnn_vanilla_rnn, + * #mkldnn_vanilla_lstm, #mkldnn_vanilla_gru, + * or #mkldnn_gru_linear_before_reset. */ + mkldnn_alg_kind_t cell_kind; + /** Activation function used. Must be either #mkldnn_eltwise_relu or + * #mkldnn_eltwise_tanh. */ + mkldnn_alg_kind_t activation_kind; + /** RNN cell flags */ + unsigned int flags; + /** @c alpha is a negative slope parameter (used only if + * `(flags & #mkldnn_rnn_cell_with_relu) != 0`) */ + float alpha; + /** clipping parameter (used only if + * `(flags & #mkldnn_rnn_cell_with_clipping) != 0`) */ + float clipping; +} mkldnn_rnn_cell_desc_t; + +/** A direction of RNN primitive execution. */ +typedef enum { + /* Unidirectional execution of RNN primitive from left to right. */ + mkldnn_unidirectional_left2right, + /* Unidirectional execution of RNN primitive from right to left. */ + mkldnn_unidirectional_right2left, + /* Bidirectional execution of RNN primitive with concatenation of the + * results. */ + mkldnn_bidirectional_concat, + /* Bidirectional execution of RNN primitive with summation of the + * results. */ + mkldnn_bidirectional_sum, + mkldnn_unidirectional = mkldnn_unidirectional_left2right, +} mkldnn_rnn_direction_t; + +/** A descriptor for an RNN operation. */ +typedef struct { + /** The kind of primitive. Used for self-identifying the primitive + * descriptor. Must be #mkldnn_rnn. */ + mkldnn_primitive_kind_t primitive_kind; + /** The kind of propagation. Possible values: #mkldnn_forward_training, + * #mkldnn_forward_inference, and #mkldnn_backward. */ + mkldnn_prop_kind_t prop_kind; + /** The RNN cell desc. */ + mkldnn_rnn_cell_desc_t cell_desc; + /** The direction of RNN primitive execution. */ + mkldnn_rnn_direction_t direction; + /** Source layer memory descriptor. */ + mkldnn_memory_desc_t src_layer_desc; + /** Source iteration memory descriptor. */ + mkldnn_memory_desc_t src_iter_desc; + /** Weights layer memory descriptor. */ + mkldnn_memory_desc_t weights_layer_desc; + /** Weights iteration memory descriptor. */ + mkldnn_memory_desc_t weights_iter_desc; + /** Bias memory descriptor. */ + mkldnn_memory_desc_t bias_desc; + /** Destination layer memory descriptor. */ + mkldnn_memory_desc_t dst_layer_desc; + /** Destination iter memory descriptor. */ + mkldnn_memory_desc_t dst_iter_desc; + /** Source gradient layer memory descriptor. */ + mkldnn_memory_desc_t diff_src_layer_desc; + /** Source gradient iter memory descriptor. */ + mkldnn_memory_desc_t diff_src_iter_desc; + /** Weights gradient layer memory descriptor. */ + mkldnn_memory_desc_t diff_weights_layer_desc; + /** Weights gradient iter memory descriptor. */ + mkldnn_memory_desc_t diff_weights_iter_desc; + /** Bias gradient memory descriptor. */ + mkldnn_memory_desc_t diff_bias_desc; + /** Destination gradient layer memory descriptor. */ + mkldnn_memory_desc_t diff_dst_layer_desc; + /** Destination gradient iteration memory descriptor. */ + mkldnn_memory_desc_t diff_dst_iter_desc; +} mkldnn_rnn_desc_t; + +/** @} */ + +/** @addtogroup c_api_engine_types Engine + * @{ */ + +/** @brief Kinds of engines. */ +typedef enum { + /** An unspecified engine. */ + mkldnn_any_engine, + /** CPU engine. */ + mkldnn_cpu, +} mkldnn_engine_kind_t; + +/** @struct mkldnn_engine + * @brief An opaque structure to describe an engine. */ +struct mkldnn_engine; +/** @brief An engine handle. */ +typedef struct mkldnn_engine *mkldnn_engine_t; +#if 0 +/* FIXME: looks like this never happens */ +/** @brief A constant engine handle. */ +typedef const struct mkldnn_engine *const_mkldnn_engine_t; +#endif + +/** @} */ + +/** @addtogroup c_api_primitive_desc_iterators Primitive descriptor iterators + * @{ */ + +/** @struct mkldnn_primitive_desc_iterator + * @brief An opaque structure to describe a primitive descriptor iterator. */ +struct mkldnn_primitive_desc_iterator; + +/** @brief A primitive descriptor iterator handle. */ +typedef struct mkldnn_primitive_desc_iterator + *mkldnn_primitive_desc_iterator_t; + +/** @brief A constant primitive descriptor iterator handle. */ +typedef const struct mkldnn_primitive_desc_iterator + *const_mkldnn_primitive_desc_iterator_t; + +/** @} */ + +/** @addtogroup c_api_primitive_descs Primitive descriptors + * @{ */ + +/** @struct mkldnn_primitive_desc + * @brief An opaque structure to describe a primitive descriptor. */ +struct mkldnn_primitive_desc; + +/** @brief A primitive descriptor handle. */ +typedef struct mkldnn_primitive_desc *mkldnn_primitive_desc_t; + +/** @brief A constant primitive descriptor handle. */ +typedef const struct mkldnn_primitive_desc *const_mkldnn_primitive_desc_t; + +/** @} */ + +/** @addtogroup c_api_primitive_attr Primitive descriptor attributes + * @{ */ + +/** Scratchpad mode */ +typedef enum { + /** The library manages scratchpad (default) */ + mkldnn_scratchpad_mode_library, + /** A user shall query and provide the scratchpad memory to primitives */ + mkldnn_scratchpad_mode_user, +} mkldnn_scratchpad_mode_t; + +/** @struct mkldnn_primitive_attr + * @brief An opaque structure for primitive descriptor attributes. + * + * Attributes may contain: + * - output scales (to scale the result prior to storing it to the memory) + */ +struct mkldnn_primitive_attr; + +/** @brief A primitive descriptor attributes handle that controls primitive + * behavior. */ +typedef struct mkldnn_primitive_attr *mkldnn_primitive_attr_t; + +/** @brief A constant primitive descriptor attributes handle. */ +typedef const struct mkldnn_primitive_attr *const_mkldnn_primitive_attr_t; + +/** @struct mkldnn_post_ops + * @brief An opaque structure for a chain of post operations. + * + * mkldnn_post_ops can be used to perform some (trivial) operations like + * accumulation or eltwise after certain primitives like convolution. + * + * Post operations might be combined together, making a chain of post + * operations. For instance one can configure convolution followed by + * accumulation followed by eltwise. This might be especially beneficial + * for residual learning blocks. + * + * @warning + * Of course not all combinations are supported, so the user should handle + * errors accordingly. + * + * Supported post operations: + * - accumulation (base primitive: convolution) + * - eltwise (base primitive: convolution) + */ +struct mkldnn_post_ops; + +/** @brief A post operation chain handle. */ +typedef struct mkldnn_post_ops *mkldnn_post_ops_t; + +/** @brief A constant post operation chain handle. */ +typedef const struct mkldnn_post_ops *const_mkldnn_post_ops_t; + +/** @} */ + +/** @addtogroup c_api_types_primitive Primitive + * @{ */ + +/** @struct mkldnn_primitive + * An opaque structure to describe a primitive. */ +struct mkldnn_primitive; +/** A primitive handle. */ +typedef struct mkldnn_primitive *mkldnn_primitive_t; +/** A constant primitive handle. */ +typedef const struct mkldnn_primitive *const_mkldnn_primitive_t; + +/** @addtogroup c_api_types_arguments Argument indices + * @{ */ + +#define MKLDNN_ARG_SRC_0 1 +#define MKLDNN_ARG_SRC MKLDNN_ARG_SRC_0 +#define MKLDNN_ARG_SRC_LAYER MKLDNN_ARG_SRC_0 +#define MKLDNN_ARG_FROM MKLDNN_ARG_SRC_0 + +#define MKLDNN_ARG_SRC_1 2 +#define MKLDNN_ARG_SRC_ITER MKLDNN_ARG_SRC_1 + +#define MKLDNN_ARG_DST_0 17 +#define MKLDNN_ARG_DST MKLDNN_ARG_DST_0 +#define MKLDNN_ARG_TO MKLDNN_ARG_DST_0 +#define MKLDNN_ARG_DST_LAYER MKLDNN_ARG_DST_0 + +#define MKLDNN_ARG_DST_1 18 +#define MKLDNN_ARG_DST_ITER MKLDNN_ARG_DST_1 + +#define MKLDNN_ARG_WEIGHTS_0 33 +#define MKLDNN_ARG_WEIGHTS MKLDNN_ARG_WEIGHTS_0 +#define MKLDNN_ARG_SCALE_SHIFT MKLDNN_ARG_WEIGHTS_0 +#define MKLDNN_ARG_WEIGHTS_LAYER MKLDNN_ARG_WEIGHTS_0 + +#define MKLDNN_ARG_WEIGHTS_1 34 +#define MKLDNN_ARG_WEIGHTS_ITER MKLDNN_ARG_WEIGHTS_1 + +#define MKLDNN_ARG_BIAS 41 + +#define MKLDNN_ARG_MEAN 49 +#define MKLDNN_ARG_VARIANCE 50 + +#define MKLDNN_ARG_WORKSPACE 64 +#define MKLDNN_ARG_SCRATCHPAD 80 + +#define MKLDNN_ARG_DIFF_SRC_0 129 +#define MKLDNN_ARG_DIFF_SRC MKLDNN_ARG_DIFF_SRC_0 +#define MKLDNN_ARG_DIFF_SRC_LAYER MKLDNN_ARG_DIFF_SRC_0 + +#define MKLDNN_ARG_DIFF_SRC_1 130 +#define MKLDNN_ARG_DIFF_SRC_ITER MKLDNN_ARG_DIFF_SRC_1 + +#define MKLDNN_ARG_DIFF_DST_0 145 +#define MKLDNN_ARG_DIFF_DST MKLDNN_ARG_DIFF_DST_0 +#define MKLDNN_ARG_DIFF_DST_LAYER MKLDNN_ARG_DIFF_DST_0 + +#define MKLDNN_ARG_DIFF_DST_1 146 +#define MKLDNN_ARG_DIFF_DST_ITER MKLDNN_ARG_DIFF_DST_1 + +#define MKLDNN_ARG_DIFF_WEIGHTS_0 161 +#define MKLDNN_ARG_DIFF_WEIGHTS MKLDNN_ARG_DIFF_WEIGHTS_0 +#define MKLDNN_ARG_DIFF_SCALE_SHIFT MKLDNN_ARG_DIFF_WEIGHTS_0 +#define MKLDNN_ARG_DIFF_WEIGHTS_LAYER MKLDNN_ARG_DIFF_WEIGHTS_0 + +#define MKLDNN_ARG_DIFF_WEIGHTS_1 162 +#define MKLDNN_ARG_DIFF_WEIGHTS_ITER MKLDNN_ARG_DIFF_WEIGHTS_1 + +#define MKLDNN_ARG_DIFF_BIAS 169 + +#define MKLDNN_ARG_MULTIPLE_SRC 1024 +#define MKLDNN_ARG_MULTIPLE_DST 2048 + +/** @} */ + +/** An auxiliary structure to specify primitive's inputs/outputs at execution + * + * @warning + * With this API it's impossible to preserve constness of memory, so all + * memories are passed w/o const qualifier. However only memories with + * output semantics might be changed during the execution */ +typedef struct { + int arg; /**< An argument index, e.g. MKLDNN_ARG_SRC */ + mkldnn_memory_t memory; /**< Input/output memory */ +} mkldnn_exec_arg_t; + +/** @} */ + +/** @addtogroup c_api_types_query Queries + * @{ */ + +/** Primitive descriptor query specification + * + * For generic function mkldnn_primitive_desc_query(), the type of result must + * agree with the queried argument. The correspondence table: + * Query | type of result + * -------------------------------------------------------------- + * #mkldnn_query_engine | mkldnn_engine_t * + * #mkldnn_query_scratchpad_engine | mkldnn_engine_t * + * #mkldnn_query_primitive_kind | mkldnn_primitive_kind_t * + * *_s32 | int * + * *_s64 | mkldnn_dim_t * (same as int64_t *) + * *_f64 | double * + * *_str | const char ** + * #mkldnn_query_op_d | const_mkldnn_op_desc_t * + * *_md | const mkldnn_memory_desc_t ** + * *_${op}_d | const mkldnn_${op}_desc_t ** + * *_pd | const_mkldnn_primitive_desc_t * + * + * @note + * Rule of thumb: all opaque types and structures are returned by + * reference. All numbers are returned by value. + * + * @warning + * All returned references point to constant objects and are valid only + * during the lifetime of the queried primitive descriptor. Returned objects + * must not be destroyed by the user. If you need to keep the object longer + * than the lifetime of the queried primitive descriptor, use + * mkldnn_primitive_desc_clone() to make a copy. */ +typedef enum { + mkldnn_query_undef = 0, /**< no query */ + + mkldnn_query_engine, /**< execution engine */ + mkldnn_query_primitive_kind, /**< primitive kind */ + + mkldnn_query_num_of_inputs_s32, /**< number of inputs expected */ + mkldnn_query_num_of_outputs_s32, /**< number of outputs expected */ + + mkldnn_query_time_estimate_f64, /**< runtime estimation (seconds) */ + mkldnn_query_memory_consumption_s64, /**< memory consumption -- extra + (scratch) memory, additional to all + inputs and outputs memory (bytes) */ + + mkldnn_query_scratchpad_engine, /**< scratchpad engine -- engine to be used + for creating scratchpad memory */ + + mkldnn_query_impl_info_str, /**< implementation name */ + + /* memory and op descriptor section */ + mkldnn_query_some_d = 64, /**< stub */ + mkldnn_query_op_d, /**< op descriptor */ + mkldnn_query_convolution_d, /**< convolution descriptor */ + mkldnn_query_deconvolution_d, /**< deconvolution descriptor */ + mkldnn_query_shuffle_d, /**< shuffle descriptor */ + mkldnn_query_eltwise_d, /**< eltwise descriptor */ + mkldnn_query_softmax_d, /**< softmax descriptor */ + mkldnn_query_pooling_d, /**< pooling descriptor */ + mkldnn_query_lrn_d, /**< lrn descriptor */ + mkldnn_query_batch_normalization_d, /**< batch normalization descriptor */ + mkldnn_query_inner_product_d, /**< inner product descriptor */ + mkldnn_query_rnn_d, /**< rnn descriptor */ + + /* memory descriptor section */ + mkldnn_query_some_md = 128, /**< stub */ + mkldnn_query_src_md, /**< source memory desc */ + mkldnn_query_diff_src_md, /**< source gradient memory desc */ + mkldnn_query_weights_md, /**< weights memory descriptor desc */ + mkldnn_query_diff_weights_md, /**< weights grad. memory desc */ + mkldnn_query_dst_md, /**< destination memory desc */ + mkldnn_query_diff_dst_md, /**< destination grad. memory desc */ + mkldnn_query_workspace_md, /**< workspace memory desc */ + mkldnn_query_scratchpad_md, /**< scratchpad memory desc */ +} mkldnn_query_t; + +/** @} */ + +/** @addtogroup c_api_types_stream Execution stream + * @{ */ + +/** @brief Stream flags. */ +typedef enum { + /** A default stream configuration. */ + mkldnn_stream_default_flags = 0x0U, +} mkldnn_stream_flags_t; + +/** @struct mkldnn_stream + * An opaque structure to describe an execution stream. */ +struct mkldnn_stream; +/** An execution stream handle. */ +typedef struct mkldnn_stream *mkldnn_stream_t; +/** A constant execution stream handle. */ +typedef const struct mkldnn_stream *const_mkldnn_stream_t; + +/** @} */ +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h new file mode 100644 index 0000000000..a2713deccb --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h @@ -0,0 +1,32 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_VERSION_H +#define MKLDNN_VERSION_H + +/* Major version of MKL-DNN */ +#define MKLDNN_VERSION_MAJOR 0 + +/* Minor version of MKL-DNN */ +#define MKLDNN_VERSION_MINOR 90 + +/* Patch version of MKL-DNN */ +#define MKLDNN_VERSION_PATCH 0 + +/* Git Commit Hash of MKL-DNN */ +#define MKLDNN_VERSION_HASH "096bda1ca23324879f2df5a129e610e4405f775c" + +#endif diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in new file mode 100644 index 0000000000..5ee0126188 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in @@ -0,0 +1,32 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_VERSION_H +#define MKLDNN_VERSION_H + +/* Major version of MKL-DNN */ +#define MKLDNN_VERSION_MAJOR @MKLDNN_VERSION_MAJOR@ + +/* Minor version of MKL-DNN */ +#define MKLDNN_VERSION_MINOR @MKLDNN_VERSION_MINOR@ + +/* Patch version of MKL-DNN */ +#define MKLDNN_VERSION_PATCH @MKLDNN_VERSION_PATCH@ + +/* Git Commit Hash of MKL-DNN */ +#define MKLDNN_VERSION_HASH "@MKLDNN_VERSION_HASH@" + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp new file mode 100644 index 0000000000..1a51d8562b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp @@ -0,0 +1,104 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::alg_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t bnrm_desc_init(batch_normalization_desc_t *bnrm_desc, + prop_kind_t prop_kind, const memory_desc_t *data_desc, + const memory_desc_t *diff_data_desc, float epsilon, unsigned flags) { + bool args_ok = true + && !any_null(bnrm_desc, data_desc) + && one_of(prop_kind, forward_training, forward_inference, + backward_data, backward) + && IMPLICATION(prop_kind & backward, diff_data_desc != nullptr); + if (!args_ok) return invalid_arguments; + + auto bd = batch_normalization_desc_t(); + bd.primitive_kind = primitive_kind::batch_normalization; + bd.prop_kind = prop_kind; + + bd.data_desc = *data_desc; + bd.diff_data_desc = zero_md(); + if ( one_of(bd.prop_kind,backward_data, backward) ) + bd.diff_data_desc = *diff_data_desc; + + dims_t scaleshift_dims = { 2, data_desc->dims[1] }; + mkldnn_memory_desc_init_by_tag(&bd.data_scaleshift_desc, 2, + scaleshift_dims, data_type::f32, mkldnn_nc); + bd.diff_data_scaleshift_desc = zero_md(); + if (bd.prop_kind == backward) { + bd.diff_data_scaleshift_desc = bd.data_scaleshift_desc; + } + + dims_t stats_dims = { data_desc->dims[1] }; + mkldnn_memory_desc_init_by_tag(&bd.mean_desc, 1, stats_dims, + data_type::f32, mkldnn_x); + bd.variance_desc = bd.mean_desc; + bd.batch_norm_epsilon = epsilon; + + unsigned bnorm_flags = + mkldnn_use_global_stats | mkldnn_use_scaleshift | mkldnn_fuse_bn_relu; + if ((~bnorm_flags & flags) != 0) return invalid_arguments; + + bd.flags = flags; + + bool consistency = true + && utils::one_of(bd.data_desc.ndims, 2, 4, 5); + if (bd.prop_kind == backward_data) + consistency = consistency + && utils::one_of(bd.diff_data_desc.ndims, 2, 4, 5) + && array_cmp(bd.diff_data_desc.dims, bd.data_desc.dims, + bd.diff_data_desc.ndims); + if (!consistency) return invalid_arguments; + + *bnrm_desc = bd; + return success; +} +} + +status_t mkldnn_batch_normalization_forward_desc_init( + batch_normalization_desc_t *bnrm_desc, prop_kind_t prop_kind, + const memory_desc_t *data_desc, float epsilon, unsigned flags) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return bnrm_desc_init(bnrm_desc, prop_kind, data_desc, nullptr, + epsilon, flags); +} + +status_t mkldnn_batch_normalization_backward_desc_init( + batch_normalization_desc_t *bnrm_desc, prop_kind_t prop_kind, + const memory_desc_t *diff_data_desc, const memory_desc_t *data_desc, + float epsilon, unsigned flags) { + if (!one_of(prop_kind, backward, backward_data)) + return invalid_arguments; + return bnrm_desc_init(bnrm_desc, prop_kind, data_desc, diff_data_desc, + epsilon, flags); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp new file mode 100644 index 0000000000..f61410b33c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp @@ -0,0 +1,240 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef BATCH_NORMALIZATION_PD_HPP +#define BATCH_NORMALIZATION_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +struct batch_normalization_fwd_pd_t; + +struct batch_normalization_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::batch_normalization; + + batch_normalization_pd_t(engine_t *engine, + const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + , data_md_(desc_.data_desc) + , stat_md_(desc_.mean_desc) + , scaleshift_md_(desc_.data_scaleshift_desc) + , ws_md_() + {} + + const batch_normalization_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::batch_normalization_d: + *(const batch_normalization_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common batch_normalization aux functions */ + + dim_t MB() const { return data_desc().dims[0]; } + dim_t C() const { return data_desc().dims[1]; } + dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; } + dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; } + dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; } + + int ndims() const { return desc_.data_desc.ndims; } + + bool stats_is_src() const { return desc_.flags & mkldnn_use_global_stats; } + bool use_scaleshift() const { return desc_.flags & mkldnn_use_scaleshift; } + bool use_global_stats() const + { return desc_.flags & mkldnn_use_global_stats; } + bool fuse_bn_relu() const { return desc_.flags & mkldnn_fuse_bn_relu; } + bool with_relu_post_op() const { + const auto &p = this->attr()->post_ops_; + return p.len_ == 1 && p.entry_[0].is_relu(true, true); + } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + bool is_bwd() const { return !this->is_fwd(); } + bool is_training() const + { return desc_.prop_kind == prop_kind::forward_training; } + + bool has_zero_dim_memory() const + { return memory_desc_wrapper(desc_.data_desc).has_zero_dim(); } + +protected: + batch_normalization_desc_t desc_; + const batch_normalization_fwd_pd_t *hint_fwd_pd_; + + memory_desc_t data_md_; + memory_desc_t stat_md_; + memory_desc_t scaleshift_md_; + + memory_desc_t ws_md_; + + void init_default_ws(size_t bits_per_element) { + const auto data_mdw = memory_desc_wrapper(data_md_); + + const dim_t data_nelems = data_mdw.nelems(true); + const dim_t bits_per_byte = 8; + const dims_t ws_sz = { (dim_t)utils::div_up( + data_nelems * bits_per_element, bits_per_byte) }; + mkldnn_memory_desc_init_by_tag(&ws_md_, 1, ws_sz, impl::data_type::u8, + format_tag::x); + } + +private: + const memory_desc_t &data_desc() const { return desc_.data_desc; } +}; + +struct batch_normalization_fwd_pd_t: public batch_normalization_pd_t { + typedef batch_normalization_fwd_pd_t base_class; + typedef batch_normalization_fwd_pd_t hint_class; + + batch_normalization_fwd_pd_t(engine_t *engine, + const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : batch_normalization_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_SRC) return arg_usage_t::input; + if (arg == MKLDNN_ARG_DST) return arg_usage_t::output; + + if (utils::one_of(arg, MKLDNN_ARG_MEAN, MKLDNN_ARG_VARIANCE)) { + if (stats_is_src()) return arg_usage_t::input; + if (!stats_is_src() && is_training()) return arg_usage_t::output; + return arg_usage_t::unused; + } + + if (arg == MKLDNN_ARG_SCALE_SHIFT && use_scaleshift()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_WORKSPACE && is_training() && fuse_bn_relu()) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override { + if (index == 0) return &data_md_; + if (stats_is_src() && (index == 1 || index == 2)) return &stat_md_; + return nullptr; + } + + virtual const memory_desc_t *dst_md(int index = 0) const override { + if (index == 0) return &data_md_; + if (!stats_is_src() && is_training() && (index == 1 || index == 2)) + return &stat_md_; + return nullptr; + } + + virtual const memory_desc_t *weights_md(int index = 0) const override + { return index == 0 ? &scaleshift_md_ : nullptr; } + + virtual const memory_desc_t *workspace_md(int index = 0) const override + { return index == 0 && is_training() && fuse_bn_relu() ? &ws_md_ : nullptr; } + + const memory_desc_t *stat_md() const + { return stats_is_src() ? src_md(1) : dst_md(1); } + + virtual int n_inputs() const override + { return 1 + 2 * stats_is_src() + use_scaleshift(); } + virtual int n_outputs() const override + { return 1 + (fuse_bn_relu() + 2 * (!stats_is_src())) * is_training(); } +}; + +struct batch_normalization_bwd_pd_t: public batch_normalization_pd_t { + typedef batch_normalization_bwd_pd_t base_class; + typedef batch_normalization_fwd_pd_t hint_class; + + batch_normalization_bwd_pd_t(engine_t *engine, + const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : batch_normalization_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_data_md_(desc_.diff_data_desc) + , diff_scaleshift_md_(desc_.diff_data_scaleshift_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_MEAN, + MKLDNN_ARG_VARIANCE, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_SCALE_SHIFT && use_scaleshift()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_WORKSPACE && fuse_bn_relu()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_DIFF_SCALE_SHIFT && use_scaleshift()) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &data_md_ : index <= 2 ? &stat_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + + virtual const memory_desc_t *weights_md(int index = 0) const override + { return index == 0 ? &scaleshift_md_ : nullptr; } + virtual const memory_desc_t *diff_weights_md(int index = 0) const override + { return index == 0 ? &diff_scaleshift_md_ : nullptr; } + + virtual const memory_desc_t *workspace_md(int index = 0) const override + { return index == 0 && fuse_bn_relu() ? &ws_md_ : nullptr; } + + const memory_desc_t *stat_md() const { return src_md(1); } + + virtual int n_inputs() const override + { return 4 + use_scaleshift() + fuse_bn_relu(); } + virtual int n_outputs() const override + { return 1 + (desc_.prop_kind == prop_kind::backward); } + +protected: + memory_desc_t diff_data_md_; + memory_desc_t diff_scaleshift_md_; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp b/thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp new file mode 100644 index 0000000000..3d43a0fbee --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp @@ -0,0 +1,550 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef TYPE_MAPPING_HPP +#define TYPE_MAPPING_HPP + +#include "mkldnn_types.h" + +namespace mkldnn { +namespace impl { + +// TODO: autogenerate this + +using dim_t = mkldnn_dim_t; +using dims_t = mkldnn_dims_t; +using stride_t = mkldnn_dim_t; +using strides_t = mkldnn_strides_t; + +using status_t = mkldnn_status_t; +namespace status { + const status_t success = mkldnn_success; + const status_t out_of_memory = mkldnn_out_of_memory; + const status_t try_again = mkldnn_try_again; + const status_t invalid_arguments = mkldnn_invalid_arguments; + const status_t not_ready = mkldnn_not_ready; + const status_t unimplemented = mkldnn_unimplemented; + const status_t iterator_ends = mkldnn_iterator_ends; + const status_t runtime_error = mkldnn_runtime_error; + const status_t not_required = mkldnn_not_required; +} + +using prop_kind_t = mkldnn_prop_kind_t; +namespace prop_kind { + const prop_kind_t undef = mkldnn_prop_kind_undef; + const prop_kind_t forward_training = mkldnn_forward_training; + const prop_kind_t forward_inference = mkldnn_forward_inference; + const prop_kind_t forward_scoring = mkldnn_forward_scoring; + const prop_kind_t forward = mkldnn_forward; + const prop_kind_t backward = mkldnn_backward; + const prop_kind_t backward_data = mkldnn_backward_data; + const prop_kind_t backward_weights = mkldnn_backward_weights; + const prop_kind_t backward_bias = mkldnn_backward_bias; +} + +using alg_kind_t = mkldnn_alg_kind_t; +namespace alg_kind { + const alg_kind_t undef = mkldnn_alg_kind_undef; + const alg_kind_t convolution_auto = mkldnn_convolution_auto; + const alg_kind_t convolution_direct = mkldnn_convolution_direct; + const alg_kind_t convolution_winograd = mkldnn_convolution_winograd; + const alg_kind_t deconvolution_direct = mkldnn_deconvolution_direct; + const alg_kind_t deconvolution_winograd = mkldnn_deconvolution_winograd; + const alg_kind_t eltwise_relu = mkldnn_eltwise_relu; + const alg_kind_t eltwise_tanh = mkldnn_eltwise_tanh; + const alg_kind_t eltwise_elu = mkldnn_eltwise_elu; + const alg_kind_t eltwise_square = mkldnn_eltwise_square; + const alg_kind_t eltwise_abs = mkldnn_eltwise_abs; + const alg_kind_t eltwise_sqrt = mkldnn_eltwise_sqrt; + const alg_kind_t eltwise_linear = mkldnn_eltwise_linear; + const alg_kind_t eltwise_bounded_relu = mkldnn_eltwise_bounded_relu; + const alg_kind_t eltwise_soft_relu = mkldnn_eltwise_soft_relu; + const alg_kind_t eltwise_logistic = mkldnn_eltwise_logistic; + const alg_kind_t pooling_max = mkldnn_pooling_max; + const alg_kind_t pooling_avg = mkldnn_pooling_avg; + const alg_kind_t pooling_avg_include_padding = mkldnn_pooling_avg_include_padding; + const alg_kind_t pooling_avg_exclude_padding = mkldnn_pooling_avg_exclude_padding; + const alg_kind_t lrn_across_channels = mkldnn_lrn_across_channels; + const alg_kind_t lrn_within_channel = mkldnn_lrn_within_channel; + const alg_kind_t vanilla_rnn = mkldnn_vanilla_rnn; + const alg_kind_t vanilla_lstm = mkldnn_vanilla_lstm; + const alg_kind_t vanilla_gru = mkldnn_vanilla_gru; + const alg_kind_t gru_linear_before_reset = mkldnn_gru_linear_before_reset; +} + +using data_type_t = mkldnn_data_type_t; +namespace data_type { + const data_type_t undef = mkldnn_data_type_undef; + const data_type_t f32 = mkldnn_f32; + const data_type_t s32 = mkldnn_s32; + const data_type_t s8 = mkldnn_s8; + const data_type_t u8 = mkldnn_u8; +} + +using scratchpad_mode_t = mkldnn_scratchpad_mode_t; +namespace scratchpad_mode { + const scratchpad_mode_t library = mkldnn_scratchpad_mode_library; + const scratchpad_mode_t user = mkldnn_scratchpad_mode_user; +} + +using rnn_packed_format_t = mkldnn_rnn_packed_memory_format_t; +namespace rnn_packed_format { + const rnn_packed_format_t undef = mkldnn_packed_format_undef; + const rnn_packed_format_t ldigo_p = mkldnn_ldigo_p; + const rnn_packed_format_t ldgoi_p = mkldnn_ldgoi_p; +} + +using format_kind_t = mkldnn_format_kind_t; +namespace format_kind { + const format_kind_t undef = mkldnn_format_kind_undef; + const format_kind_t any = mkldnn_format_kind_any; + const format_kind_t blocked = mkldnn_blocked; + const format_kind_t wino = mkldnn_format_kind_wino; + const format_kind_t rnn_packed = mkldnn_format_kind_rnn_packed; +} + +using format_tag_t = mkldnn_format_tag_t; +namespace format_tag { + const format_tag_t undef = mkldnn_format_tag_undef; + const format_tag_t any = mkldnn_format_tag_any; + const format_tag_t a = mkldnn_a; + const format_tag_t ab = mkldnn_ab; + const format_tag_t abc = mkldnn_abc; + const format_tag_t abcd = mkldnn_abcd; + const format_tag_t abcde = mkldnn_abcde; + const format_tag_t abcdef = mkldnn_abcdef; + const format_tag_t abdec = mkldnn_abdec; + const format_tag_t acb = mkldnn_acb; + const format_tag_t acbde = mkldnn_acbde; + const format_tag_t acdb = mkldnn_acdb; + const format_tag_t acdeb = mkldnn_acdeb; + const format_tag_t ba = mkldnn_ba; + const format_tag_t bac = mkldnn_bac; + const format_tag_t bacd = mkldnn_bacd; + const format_tag_t bcda = mkldnn_bcda; + const format_tag_t cba = mkldnn_cba; + const format_tag_t cdba = mkldnn_cdba; + const format_tag_t cdeba = mkldnn_cdeba; + const format_tag_t decab = mkldnn_decab; + const format_tag_t Abc16a = mkldnn_Abc16a; + const format_tag_t ABc16a16b = mkldnn_ABc16a16b; + const format_tag_t aBc16b = mkldnn_aBc16b; + const format_tag_t ABc16b16a = mkldnn_ABc16b16a; + const format_tag_t Abc4a = mkldnn_Abc4a; + const format_tag_t aBc4b = mkldnn_aBc4b; + const format_tag_t ABc4b16a4b = mkldnn_ABc4b16a4b; + const format_tag_t ABc4b4a = mkldnn_ABc4b4a; + const format_tag_t ABc8a16b2a = mkldnn_ABc8a16b2a; + const format_tag_t ABc8a8b = mkldnn_ABc8a8b; + const format_tag_t aBc8b = mkldnn_aBc8b; + const format_tag_t ABc8b16a2b = mkldnn_ABc8b16a2b; + const format_tag_t ABc8b8a = mkldnn_ABc8b8a; + const format_tag_t Abcd16a = mkldnn_Abcd16a; + const format_tag_t ABcd16a16b = mkldnn_ABcd16a16b; + const format_tag_t aBcd16b = mkldnn_aBcd16b; + const format_tag_t ABcd16b16a = mkldnn_ABcd16b16a; + const format_tag_t aBCd16b16c = mkldnn_aBCd16b16c; + const format_tag_t aBCd16c16b = mkldnn_aBCd16c16b; + const format_tag_t Abcd4a = mkldnn_Abcd4a; + const format_tag_t aBcd4b = mkldnn_aBcd4b; + const format_tag_t ABcd4b16a4b = mkldnn_ABcd4b16a4b; + const format_tag_t ABcd4b4a = mkldnn_ABcd4b4a; + const format_tag_t aBCd4c16b4c = mkldnn_aBCd4c16b4c; + const format_tag_t aBCd4c4b = mkldnn_aBCd4c4b; + const format_tag_t ABcd8a16b2a = mkldnn_ABcd8a16b2a; + const format_tag_t ABcd8a8b = mkldnn_ABcd8a8b; + const format_tag_t aBcd8b = mkldnn_aBcd8b; + const format_tag_t ABcd8b16a2b = mkldnn_ABcd8b16a2b; + const format_tag_t aBCd8b16c2b = mkldnn_aBCd8b16c2b; + const format_tag_t ABcd8b8a = mkldnn_ABcd8b8a; + const format_tag_t aBCd8b8c = mkldnn_aBCd8b8c; + const format_tag_t aBCd8c16b2c = mkldnn_aBCd8c16b2c; + const format_tag_t aBCd8c8b = mkldnn_aBCd8c8b; + const format_tag_t Abcde16a = mkldnn_Abcde16a; + const format_tag_t ABcde16a16b = mkldnn_ABcde16a16b; + const format_tag_t aBcde16b = mkldnn_aBcde16b; + const format_tag_t ABcde16b16a = mkldnn_ABcde16b16a; + const format_tag_t aBCde16b16c = mkldnn_aBCde16b16c; + const format_tag_t aBCde16c16b = mkldnn_aBCde16c16b; + const format_tag_t aBCde2c8b4c = mkldnn_aBCde2c8b4c; + const format_tag_t Abcde4a = mkldnn_Abcde4a; + const format_tag_t aBcde4b = mkldnn_aBcde4b; + const format_tag_t ABcde4b4a = mkldnn_ABcde4b4a; + const format_tag_t aBCde4b4c = mkldnn_aBCde4b4c; + const format_tag_t aBCde4c16b4c = mkldnn_aBCde4c16b4c; + const format_tag_t aBCde4c4b = mkldnn_aBCde4c4b; + const format_tag_t Abcde8a = mkldnn_Abcde8a; + const format_tag_t ABcde8a8b = mkldnn_ABcde8a8b; + const format_tag_t aBcde8b = mkldnn_aBcde8b; + const format_tag_t ABcde8b16a2b = mkldnn_ABcde8b16a2b; + const format_tag_t aBCde8b16c2b = mkldnn_aBCde8b16c2b; + const format_tag_t ABcde8b8a = mkldnn_ABcde8b8a; + const format_tag_t aBCde8b8c = mkldnn_aBCde8b8c; + const format_tag_t aBCde8c16b2c = mkldnn_aBCde8c16b2c; + const format_tag_t aBCde8c8b = mkldnn_aBCde8c8b; + const format_tag_t aBcdef16b = mkldnn_aBcdef16b; + const format_tag_t aBCdef16b16c = mkldnn_aBCdef16b16c; + const format_tag_t aBCdef16c16b = mkldnn_aBCdef16c16b; + const format_tag_t aBcdef4b = mkldnn_aBcdef4b; + const format_tag_t aBCdef4c4b = mkldnn_aBCdef4c4b; + const format_tag_t aBCdef8b8c = mkldnn_aBCdef8b8c; + const format_tag_t aBCdef8c16b2c = mkldnn_aBCdef8c16b2c; + const format_tag_t aBCdef8c8b = mkldnn_aBCdef8c8b; + const format_tag_t aBdc16b = mkldnn_aBdc16b; + const format_tag_t aBdc4b = mkldnn_aBdc4b; + const format_tag_t aBdc8b = mkldnn_aBdc8b; + const format_tag_t aBdec16b = mkldnn_aBdec16b; + const format_tag_t aBdec4b = mkldnn_aBdec4b; + const format_tag_t aBdec8b = mkldnn_aBdec8b; + const format_tag_t aBdefc16b = mkldnn_aBdefc16b; + const format_tag_t aBdefc4b = mkldnn_aBdefc4b; + const format_tag_t aBdefc8b = mkldnn_aBdefc8b; + const format_tag_t Acb16a = mkldnn_Acb16a; + const format_tag_t Acb4a = mkldnn_Acb4a; + const format_tag_t Acb8a = mkldnn_Acb8a; + const format_tag_t aCBd16b16c = mkldnn_aCBd16b16c; + const format_tag_t aCBde16b16c = mkldnn_aCBde16b16c; + const format_tag_t Acdb16a = mkldnn_Acdb16a; + const format_tag_t Acdb4a = mkldnn_Acdb4a; + const format_tag_t Acdb8a = mkldnn_Acdb8a; + const format_tag_t Acdeb16a = mkldnn_Acdeb16a; + const format_tag_t Acdeb4a = mkldnn_Acdeb4a; + const format_tag_t Acdeb8a = mkldnn_Acdeb8a; + const format_tag_t BAc16a16b = mkldnn_BAc16a16b; + const format_tag_t BAcd16a16b = mkldnn_BAcd16a16b; + const format_tag_t last = mkldnn_format_tag_last; + + const format_tag_t x = mkldnn_x; + const format_tag_t nc = mkldnn_nc; + const format_tag_t cn = mkldnn_cn; + const format_tag_t ncw = mkldnn_ncw; + const format_tag_t nwc = mkldnn_nwc; + const format_tag_t nchw = mkldnn_nchw; + const format_tag_t nhwc = mkldnn_nhwc; + const format_tag_t chwn = mkldnn_chwn; + const format_tag_t ncdhw = mkldnn_ncdhw; + const format_tag_t ndhwc = mkldnn_ndhwc; + const format_tag_t oi = mkldnn_oi; + const format_tag_t io = mkldnn_io; + const format_tag_t oiw = mkldnn_oiw; + const format_tag_t wio = mkldnn_wio; + const format_tag_t oihw = mkldnn_oihw; + const format_tag_t hwio = mkldnn_hwio; + const format_tag_t ihwo = mkldnn_ihwo; + const format_tag_t iohw = mkldnn_iohw; + const format_tag_t oidhw = mkldnn_oidhw; + const format_tag_t dhwio = mkldnn_dhwio; + const format_tag_t goiw = mkldnn_goiw; + const format_tag_t goihw = mkldnn_goihw; + const format_tag_t hwigo = mkldnn_hwigo; + const format_tag_t giohw = mkldnn_giohw; + const format_tag_t goidhw = mkldnn_goidhw; + const format_tag_t tnc = mkldnn_tnc; + const format_tag_t ntc = mkldnn_ntc; + const format_tag_t ldsnc = mkldnn_ldsnc; + const format_tag_t ldigo = mkldnn_ldigo; + const format_tag_t ldgoi = mkldnn_ldgoi; + const format_tag_t ldgo = mkldnn_ldgo; + const format_tag_t nCdhw16c = mkldnn_nCdhw16c; + const format_tag_t nCdhw4c = mkldnn_nCdhw4c; + const format_tag_t nCdhw8c = mkldnn_nCdhw8c; + const format_tag_t nChw16c = mkldnn_nChw16c; + const format_tag_t nChw4c = mkldnn_nChw4c; + const format_tag_t nChw8c = mkldnn_nChw8c; + const format_tag_t nCw16c = mkldnn_nCw16c; + const format_tag_t nCw4c = mkldnn_nCw4c; + const format_tag_t nCw8c = mkldnn_nCw8c; + const format_tag_t IOw16o16i = mkldnn_IOw16o16i; + const format_tag_t OIw16i16o = mkldnn_OIw16i16o; + const format_tag_t OIw16o16i = mkldnn_OIw16o16i; + const format_tag_t Oiw16o = mkldnn_Oiw16o; + const format_tag_t OIw4i16o4i = mkldnn_OIw4i16o4i; + const format_tag_t OIw4i4o = mkldnn_OIw4i4o; + const format_tag_t Oiw4o = mkldnn_Oiw4o; + const format_tag_t OIw8i16o2i = mkldnn_OIw8i16o2i; + const format_tag_t OIw8i8o = mkldnn_OIw8i8o; + const format_tag_t OIw8o16i2o = mkldnn_OIw8o16i2o; + const format_tag_t OIw8o8i = mkldnn_OIw8o8i; + const format_tag_t Owi16o = mkldnn_Owi16o; + const format_tag_t Owi4o = mkldnn_Owi4o; + const format_tag_t Owi8o = mkldnn_Owi8o; + const format_tag_t IOhw16o16i = mkldnn_IOhw16o16i; + const format_tag_t Ohwi16o = mkldnn_Ohwi16o; + const format_tag_t Ohwi4o = mkldnn_Ohwi4o; + const format_tag_t Ohwi8o = mkldnn_Ohwi8o; + const format_tag_t OIhw16i16o = mkldnn_OIhw16i16o; + const format_tag_t OIhw16o16i = mkldnn_OIhw16o16i; + const format_tag_t Oihw16o = mkldnn_Oihw16o; + const format_tag_t OIhw4i16o4i = mkldnn_OIhw4i16o4i; + const format_tag_t OIhw4i4o = mkldnn_OIhw4i4o; + const format_tag_t Oihw4o = mkldnn_Oihw4o; + const format_tag_t OIhw8i16o2i = mkldnn_OIhw8i16o2i; + const format_tag_t OIhw8i8o = mkldnn_OIhw8i8o; + const format_tag_t OIhw8o16i2o = mkldnn_OIhw8o16i2o; + const format_tag_t OIhw8o8i = mkldnn_OIhw8o8i; + const format_tag_t Odhwi16o = mkldnn_Odhwi16o; + const format_tag_t Odhwi4o = mkldnn_Odhwi4o; + const format_tag_t Odhwi8o = mkldnn_Odhwi8o; + const format_tag_t OIdhw16i16o = mkldnn_OIdhw16i16o; + const format_tag_t OIdhw16o16i = mkldnn_OIdhw16o16i; + const format_tag_t Oidhw16o = mkldnn_Oidhw16o; + const format_tag_t OIdhw4i4o = mkldnn_OIdhw4i4o; + const format_tag_t Oidhw4o = mkldnn_Oidhw4o; + const format_tag_t OIdhw8i16o2i = mkldnn_OIdhw8i16o2i; + const format_tag_t OIdhw8i8o = mkldnn_OIdhw8i8o; + const format_tag_t OIdhw8o8i = mkldnn_OIdhw8o8i; + const format_tag_t gIOw16o16i = mkldnn_gIOw16o16i; + const format_tag_t Goiw16g = mkldnn_Goiw16g; + const format_tag_t gOIw16i16o = mkldnn_gOIw16i16o; + const format_tag_t gOIw16o16i = mkldnn_gOIw16o16i; + const format_tag_t gOiw16o = mkldnn_gOiw16o; + const format_tag_t gOIw4i16o4i = mkldnn_gOIw4i16o4i; + const format_tag_t gOIw4i4o = mkldnn_gOIw4i4o; + const format_tag_t gOiw4o = mkldnn_gOiw4o; + const format_tag_t gOIw8i16o2i = mkldnn_gOIw8i16o2i; + const format_tag_t gOIw8i8o = mkldnn_gOIw8i8o; + const format_tag_t gOIw8o16i2o = mkldnn_gOIw8o16i2o; + const format_tag_t gOIw8o8i = mkldnn_gOIw8o8i; + const format_tag_t gOwi16o = mkldnn_gOwi16o; + const format_tag_t gOwi4o = mkldnn_gOwi4o; + const format_tag_t gOwi8o = mkldnn_gOwi8o; + const format_tag_t gIOhw16o16i = mkldnn_gIOhw16o16i; + const format_tag_t gOhwi16o = mkldnn_gOhwi16o; + const format_tag_t gOhwi4o = mkldnn_gOhwi4o; + const format_tag_t gOhwi8o = mkldnn_gOhwi8o; + const format_tag_t Goihw16g = mkldnn_Goihw16g; + const format_tag_t gOIhw16i16o = mkldnn_gOIhw16i16o; + const format_tag_t gOIhw16o16i = mkldnn_gOIhw16o16i; + const format_tag_t gOihw16o = mkldnn_gOihw16o; + const format_tag_t gOIhw2i8o4i = mkldnn_gOIhw2i8o4i; + const format_tag_t gOIhw4i16o4i = mkldnn_gOIhw4i16o4i; + const format_tag_t gOIhw4i4o = mkldnn_gOIhw4i4o; + const format_tag_t gOIhw4o4i = mkldnn_gOIhw4o4i; + const format_tag_t gOihw4o = mkldnn_gOihw4o; + const format_tag_t Goihw8g = mkldnn_Goihw8g; + const format_tag_t gOIhw8i16o2i = mkldnn_gOIhw8i16o2i; + const format_tag_t gOIhw8i8o = mkldnn_gOIhw8i8o; + const format_tag_t gOIhw8o16i2o = mkldnn_gOIhw8o16i2o; + const format_tag_t gOIhw8o8i = mkldnn_gOIhw8o8i; + const format_tag_t gOdhwi16o = mkldnn_gOdhwi16o; + const format_tag_t gOdhwi4o = mkldnn_gOdhwi4o; + const format_tag_t gOdhwi8o = mkldnn_gOdhwi8o; + const format_tag_t gOIdhw16i16o = mkldnn_gOIdhw16i16o; + const format_tag_t gOIdhw16o16i = mkldnn_gOIdhw16o16i; + const format_tag_t gOidhw16o = mkldnn_gOidhw16o; + const format_tag_t gOIdhw4i4o = mkldnn_gOIdhw4i4o; + const format_tag_t gOidhw4o = mkldnn_gOidhw4o; + const format_tag_t gOIdhw8i16o2i = mkldnn_gOIdhw8i16o2i; + const format_tag_t gOIdhw8i8o = mkldnn_gOIdhw8i8o; + const format_tag_t gOIdhw8o8i = mkldnn_gOIdhw8o8i; +} + +using memory_extra_flags_t = mkldnn_memory_extra_flags_t; +namespace memory_extra_flags { + const memory_extra_flags_t none = mkldnn_memory_extra_flag_none; + const memory_extra_flags_t compensation_conv_s8s8 = mkldnn_memory_extra_flag_compensation_conv_s8s8; + const memory_extra_flags_t scale_adjust = mkldnn_memory_extra_flag_scale_adjust; +} + +using padding_kind_t = mkldnn_padding_kind_t; +namespace padding_kind { + const padding_kind_t padding_zero = mkldnn_padding_zero; +} + +using engine_kind_t = mkldnn_engine_kind_t; +namespace engine_kind { + const engine_kind_t any_engine = mkldnn_any_engine; + const engine_kind_t cpu = mkldnn_cpu; +} + +using primitive_kind_t = mkldnn_primitive_kind_t; +namespace primitive_kind { + const primitive_kind_t undefined = mkldnn_undefined_primitive; + const primitive_kind_t reorder = mkldnn_reorder; + const primitive_kind_t concat = mkldnn_concat; + const primitive_kind_t sum = mkldnn_sum; + const primitive_kind_t convolution = mkldnn_convolution; + const primitive_kind_t deconvolution = mkldnn_deconvolution; + const primitive_kind_t shuffle = mkldnn_shuffle; + const primitive_kind_t eltwise = mkldnn_eltwise; + const primitive_kind_t softmax = mkldnn_softmax; + const primitive_kind_t pooling = mkldnn_pooling; + const primitive_kind_t lrn = mkldnn_lrn; + const primitive_kind_t batch_normalization = mkldnn_batch_normalization; + const primitive_kind_t inner_product = mkldnn_inner_product; + const primitive_kind_t rnn = mkldnn_rnn; +} + +using query_t = mkldnn_query_t; +namespace query { + const query_t undef = mkldnn_query_undef; + + const query_t engine = mkldnn_query_engine; + const query_t primitive_kind = mkldnn_query_primitive_kind; + + const query_t num_of_inputs_s32 = mkldnn_query_num_of_inputs_s32; + const query_t num_of_outputs_s32 = mkldnn_query_num_of_outputs_s32; + + const query_t time_estimate_f64 = mkldnn_query_time_estimate_f64; + const query_t memory_consumption_s64 = mkldnn_query_memory_consumption_s64; + + const query_t scratchpad_engine = mkldnn_query_scratchpad_engine; + + const query_t impl_info_str = mkldnn_query_impl_info_str; + + const query_t some_d = mkldnn_query_some_d; + const query_t op_d = mkldnn_query_op_d; + const query_t convolution_d = mkldnn_query_convolution_d; + const query_t deconvolution_d = mkldnn_query_deconvolution_d; + const query_t shuffle_d = mkldnn_query_shuffle_d; + const query_t eltwise_d = mkldnn_query_eltwise_d; + const query_t softmax_d = mkldnn_query_softmax_d; + const query_t pooling_d = mkldnn_query_pooling_d; + const query_t lrn_d = mkldnn_query_lrn_d; + const query_t batch_normalization_d = mkldnn_query_batch_normalization_d; + const query_t inner_product_d = mkldnn_query_inner_product_d; + const query_t rnn_d = mkldnn_query_rnn_d; + + const query_t some_md = mkldnn_query_some_md; + const query_t src_md = mkldnn_query_src_md; + const query_t diff_src_md = mkldnn_query_diff_src_md; + const query_t weights_md = mkldnn_query_weights_md; + const query_t diff_weights_md = mkldnn_query_diff_weights_md; + const query_t dst_md = mkldnn_query_dst_md; + const query_t diff_dst_md = mkldnn_query_diff_dst_md; + + const query_t workspace_md = mkldnn_query_workspace_md; + const query_t scratchpad_md = mkldnn_query_scratchpad_md; +} + +using blocking_desc_t = mkldnn_blocking_desc_t; +using rnn_packed_desc_t = mkldnn_rnn_packed_desc_t; +using wino_desc_t = mkldnn_wino_desc_t; +using memory_extra_desc_t = mkldnn_memory_extra_desc_t; +using memory_desc_t = mkldnn_memory_desc_t; +using convolution_desc_t = mkldnn_convolution_desc_t; +using deconvolution_desc_t = mkldnn_deconvolution_desc_t; +using shuffle_desc_t = mkldnn_shuffle_desc_t; +using pooling_desc_t = mkldnn_pooling_desc_t; +using eltwise_desc_t = mkldnn_eltwise_desc_t; +using softmax_desc_t = mkldnn_softmax_desc_t; +using lrn_desc_t = mkldnn_lrn_desc_t; +using batch_normalization_desc_t = mkldnn_batch_normalization_desc_t; +using inner_product_desc_t = mkldnn_inner_product_desc_t; + +using rnn_direction_t = mkldnn_rnn_direction_t; +using rnn_cell_desc_t = mkldnn_rnn_cell_desc_t; +using rnn_desc_t = mkldnn_rnn_desc_t; + +/* C op_desc_t, which eventually are just (void*) */ +using c_op_desc_t = mkldnn_op_desc_t; +using const_c_op_desc_t = const_mkldnn_op_desc_t; + +struct op_desc_t { + union { + primitive_kind_t kind; + convolution_desc_t convolution; + deconvolution_desc_t deconvolution; + shuffle_desc_t shuffle; + pooling_desc_t pooling; + eltwise_desc_t eltwise; + softmax_desc_t softmax; + lrn_desc_t lrn; + batch_normalization_desc_t batch_normalization; + inner_product_desc_t inner_product; + rnn_desc_t rnn; + }; + + op_desc_t(const primitive_kind_t &_): kind(_) {} + +# define DECL_CTOR_AND_CONVERTERS(c_type, name) \ + op_desc_t(const c_type &_): name(_) {} \ + static op_desc_t *convert_from_c(c_type *_) \ + { return reinterpret_cast(_); } \ + static const op_desc_t *convert_from_c(const c_type *_) \ + { return reinterpret_cast(_); } + + DECL_CTOR_AND_CONVERTERS(convolution_desc_t, convolution); + DECL_CTOR_AND_CONVERTERS(shuffle_desc_t, shuffle); + DECL_CTOR_AND_CONVERTERS(pooling_desc_t, pooling); + DECL_CTOR_AND_CONVERTERS(eltwise_desc_t, eltwise); + DECL_CTOR_AND_CONVERTERS(softmax_desc_t, softmax); + DECL_CTOR_AND_CONVERTERS(lrn_desc_t, lrn); + DECL_CTOR_AND_CONVERTERS(batch_normalization_desc_t, batch_normalization); + DECL_CTOR_AND_CONVERTERS(inner_product_desc_t, inner_product); + DECL_CTOR_AND_CONVERTERS(rnn_desc_t, rnn); + +# undef DECL_CTOR_AND_CONVERTERS +}; + +using engine_t = mkldnn_engine; +using primitive_desc_iterator_t = mkldnn_primitive_desc_iterator; +using primitive_desc_t = mkldnn_primitive_desc; +using primitive_attr_t = mkldnn_primitive_attr; +using post_ops_t = mkldnn_post_ops; +using memory_t = mkldnn_memory; +using primitive_t = mkldnn_primitive; + +using primitive_arg_index_t = int; + +using stream_flags_t = mkldnn_stream_flags_t; +namespace stream_flags { + const stream_flags_t default_flags = mkldnn_stream_default_flags; +} +using stream_t = mkldnn_stream; + +/* forward declaration of the internal primitive_desc types */ +struct batch_normalization_bwd_pd_t; +struct batch_normalization_fwd_pd_t; +struct batch_normalization_pd_t; +struct concat_pd_t; +struct convolution_bwd_data_pd_t; +struct convolution_bwd_weights_pd_t; +struct convolution_fwd_pd_t; +struct convolution_pd_t; +struct deconvolution_bwd_data_pd_t; +struct deconvolution_bwd_weights_pd_t; +struct deconvolution_fwd_pd_t; +struct deconvolution_pd_t; +struct eltwise_bwd_pd_t; +struct eltwise_fwd_pd_t; +struct eltwise_pd_t; +struct inner_product_bwd_data_pd_t; +struct inner_product_bwd_weights_pd_t; +struct inner_product_fwd_pd_t; +struct inner_product_pd_t; +struct lrn_bwd_pd_t; +struct lrn_fwd_pd_t; +struct lrn_pd_t; +struct pooling_bwd_pd_t; +struct pooling_fwd_pd_t; +struct pooling_pd_t; +struct reorder_pd_t; +struct rnn_bwd_pd_t; +struct rnn_fwd_pd_t; +struct rnn_pd_t; +struct shuffle_pd_t; +struct softmax_bwd_pd_t; +struct softmax_fwd_pd_t; +struct softmax_pd_t; +struct sum_pd_t; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/concat.cpp b/thirdparty/oidn/mkl-dnn/src/common/concat.cpp new file mode 100644 index 0000000000..ed4c35c6e9 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/concat.cpp @@ -0,0 +1,86 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "concat_pd.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; + +status_t mkldnn_concat_primitive_desc_create(primitive_desc_t **concat_pd, + const memory_desc_t *dst_md, int n, int concat_dim, + const memory_desc_t *src_mds, + const primitive_attr_t *attr, + engine_t *engine) { + bool args_ok = !any_null(concat_pd, src_mds) && n > 0; + if (!args_ok) return invalid_arguments; + + const primitive_attr_t dummy_attr; + if (attr == NULL) + attr = &dummy_attr; + + const int ndims = src_mds[0].ndims; + const dims_t &dims = src_mds[0].dims; + const data_type_t dt = src_mds[0].data_type; + + int concat_dim_sz = dims[concat_dim]; + for (int i = 1; i < n; ++i) { + if (src_mds[i].ndims != ndims) return invalid_arguments; + for (int d = 0; d < ndims; ++d) { + if (d == concat_dim) continue; + if (src_mds[i].dims[d] != dims[d]) + return invalid_arguments; + } + if (src_mds[i].data_type != dt) return invalid_arguments; + concat_dim_sz += src_mds[i].dims[concat_dim]; + } + + memory_desc_t dummy_dst_md; + if (dst_md) { + if (dst_md->ndims != ndims) return invalid_arguments; + for (int d = 0; d < ndims; ++d) { + if (dst_md->dims[d] != + (d == concat_dim ? concat_dim_sz : dims[d])) + return invalid_arguments; + } + } else { + dummy_dst_md = src_mds[0]; + dummy_dst_md.dims[concat_dim] = concat_dim_sz; + dummy_dst_md.format_kind = format_kind::any; + dst_md = &dummy_dst_md; + } + + auto c_pd = reinterpret_cast(concat_pd); + + for (auto c = engine->get_concat_implementation_list(); *c; ++c) { + if ((*c)(c_pd, engine, attr, dst_md, n, concat_dim, src_mds) + == success) { + (*c_pd)->init_info(); + (*c_pd)->init_scratchpad_md(); + return success; + } + } + return unimplemented; +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp new file mode 100644 index 0000000000..29311927e2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp @@ -0,0 +1,211 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CONCAT_PD_HPP +#define CONCAT_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "primitive_desc.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +struct concat_pd_t: public primitive_desc_t { + concat_pd_t(engine_t *engine, const primitive_attr_t *attr, + const memory_desc_t *dst_md, int n, int concat_dim, + const memory_desc_t *src_mds) + : primitive_desc_t(engine, attr, primitive_kind::concat) + , n_(n), concat_dim_(concat_dim), dst_md_(*dst_md) + { + src_mds_.reserve(n_); + for (int i = 0; i < n_; ++i) src_mds_.push_back(src_mds[i]); + } + + concat_pd_t(const concat_pd_t &rhs) = default; + + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg >= MKLDNN_ARG_MULTIPLE_SRC + && arg < MKLDNN_ARG_MULTIPLE_SRC + n_inputs()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index < n_inputs() ? &src_mds_[index] : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &dst_md_ : nullptr; } + + virtual int n_inputs() const override { return n_; } + virtual int n_outputs() const override { return 1; } + + int concat_dim() const { return concat_dim_; } + + const memory_desc_t *src_image_md(int index = 0) const + { return index < n_inputs() ? &src_image_mds_[index] : nullptr; } + +protected: + int n_, concat_dim_; + memory_desc_t dst_md_; + nstl::vector src_mds_; + + /* contains images of srcs in the dst memory (if possible) + * Lives here to simplify some implementations. An implementation might + * use this auxiliary array iff init() returned success */ + nstl::vector src_image_mds_; + +protected: + /* inits src_image_mds_ and dst_md_ in simple cases. The call may fail */ + status_t init() { + bool ok = true + && set_default_params() == status::success + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + for (int i = 0; i < n_; ++i) { + const memory_desc_wrapper i_d(&src_mds_[i]); + if (!i_d.is_blocking_desc() || i_d.is_additional_buffer()) + return status::unimplemented; + } + + const int ndims = dst_md_.ndims; + int current_concat_dim_offset = 0; + for (int i = 0; i < n_; ++i) { + const int dim = src_mds_[i].dims[concat_dim_]; + dims_t dims, offsets = {}; + utils::array_copy(dims, dst_md_.dims, ndims); + dims[concat_dim_] = dim; + offsets[concat_dim_] = current_concat_dim_offset; + + memory_desc_t src_img_d; + status_t status = mkldnn_memory_desc_init_submemory(&src_img_d, + &dst_md_, dims, offsets); + if (status != status::success) return status; + src_image_mds_.push_back(src_img_d); + current_concat_dim_offset += dim; + } + + return status::success; + } + + status_t set_default_params() { + if (dst_md_.format_kind != format_kind::any) + return status::success; + + const int ndims = dst_md_.ndims; + + /* The stupidest ever heuristics (but not the same as we had before): + * - Pick the first non-plain format; + * - If all formats are plain or it is not possible to create a + * blocked format for the output, pick the format of the plain input + * - If this fails as well, use plain layout (abcd...) + */ + status_t status = status::unimplemented; + for (int i = 0; i < n_; ++i) { + const memory_desc_wrapper src_d(src_mds_[i]); + if (src_d.is_blocking_desc() && !src_d.is_plain()) { + status = memory_desc_init_by_blocking_desc(dst_md_, + src_d.blocking_desc()); + if (status == status::success) break; + } + } + + if (status == status::success) { + /* check if we can create a sub-memory for the dst */ + bool desired_format_ok = true; + int current_concat_dim_offset = 0; + for (int i = 0; i < n_; ++i) { + const int dim = src_mds_[i].dims[concat_dim_]; + dims_t dims, offsets = {}; + utils::array_copy(dims, dst_md_.dims, ndims); + dims[concat_dim_] = dim; + offsets[concat_dim_] = current_concat_dim_offset; + + memory_desc_t src_img_d; + status_t status = mkldnn_memory_desc_init_submemory(&src_img_d, + &dst_md_, dims, offsets); + if (status != status::success) { + desired_format_ok = false; + break; + } + current_concat_dim_offset += dim; + } + + if (!desired_format_ok) + status = status::unimplemented; + } + + /* if no success so far, try using the format of the first plain input */ + if (status != status::success) { + for (int i = 0; i < n_; ++i) { + const memory_desc_wrapper src_d(src_mds_[i]); + if (src_d.is_blocking_desc() && src_d.is_plain()) { + status = memory_desc_init_by_blocking_desc(dst_md_, + memory_desc_wrapper(src_mds_[0]).blocking_desc()); + if (status == status::success) return status; + } + } + } + + /* the last line of defense: use plain abcd... format */ + if (status != status::success) + status = memory_desc_init_by_strides(dst_md_, nullptr); + + return status; + } +}; + +#define DECLARE_CONCAT_PD_t(impl_name, ...) \ + static status_t create(concat_pd_t **concat_pd, \ + engine_t *engine, const primitive_attr_t *attr, \ + const memory_desc_t *dst_md, int n, int concat_dim, \ + const memory_desc_t *src_mds) { \ + using namespace status; \ + auto _pd = new pd_t(engine, attr, dst_md, n, concat_dim, src_mds); \ + if (_pd == nullptr) return out_of_memory; \ + if (_pd->init() != success) { delete _pd; return unimplemented; } \ + return safe_ptr_assign(*concat_pd, _pd); \ + } \ + virtual status_t create_primitive(primitive_t **p) const override { \ + double ms = get_msec(); \ + auto ret = safe_ptr_assign(*p, new (__VA_ARGS__)(this)); \ + ms = get_msec() - ms; \ + if (mkldnn_verbose()->level >= 2) { \ + printf("mkldnn_verbose,create,%s,%g\n", this->info(), ms); \ + fflush(0); \ + } \ + return ret; \ + } \ + virtual pd_t *clone() const override { return new pd_t(*this); } \ + virtual const char *name() const override { return impl_name; } \ + +#define DECLARE_CONCAT_PD_T(impl_name, ...) \ + DECLARE_CONCAT_PD_t(impl_name, __VA_ARGS__) + +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/convolution.cpp b/thirdparty/oidn/mkl-dnn/src/common/convolution.cpp new file mode 100644 index 0000000000..0c5c02bcd1 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/convolution.cpp @@ -0,0 +1,200 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::alg_kind; +using namespace mkldnn::impl::types; + +namespace mkldnn { +namespace impl { +status_t conv_desc_init(convolution_desc_t *conv_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *bias_desc, const memory_desc_t *dst_desc, + const dims_t strides, const dims_t dilates, + const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + bool args_ok = true + && !any_null(conv_desc, src_desc, weights_desc, dst_desc, strides, + padding_l) + && one_of(alg_kind, convolution_auto, convolution_direct, convolution_winograd) + && one_of(padding_kind, padding_kind::padding_zero); + if (!args_ok) return invalid_arguments; + + if (padding_r == nullptr) padding_r = padding_l; + + auto cd = convolution_desc_t(); + cd.primitive_kind = primitive_kind::convolution; + cd.prop_kind = prop_kind; + cd.alg_kind = alg_kind; + + cd.diff_src_desc = cd.src_desc = zero_md(); + cd.diff_dst_desc = cd.dst_desc = zero_md(); + cd.diff_weights_desc = cd.weights_desc = zero_md(); + cd.diff_bias_desc = cd.bias_desc = zero_md(); + + const bool is_fwd = one_of(prop_kind, forward_training, forward_inference); + const bool with_bias = + bias_desc && bias_desc->format_kind != format_kind::undef; + const bool with_groups = weights_desc->ndims == src_desc->ndims + 1; + + (prop_kind == backward_data ? cd.diff_src_desc : cd.src_desc) = *src_desc; + (is_fwd ? cd.dst_desc : cd.diff_dst_desc) = *dst_desc; + (prop_kind == backward_weights ? cd.diff_weights_desc : cd.weights_desc) = + *weights_desc; + if (with_bias) + (prop_kind == backward_weights ? cd.diff_bias_desc : cd.bias_desc) = + *bias_desc; + + int sp_dims = src_desc->ndims - 2; + utils::array_copy(cd.strides, strides, sp_dims); + utils::array_copy(cd.padding[0], padding_l, sp_dims); + utils::array_copy(cd.padding[1], padding_r, sp_dims); + if (dilates) + utils::array_copy(cd.dilates, dilates, sp_dims); + else + utils::array_set(cd.dilates, 0, sp_dims); + + cd.padding_kind = padding_kind; + cd.accum_data_type = types::default_accum_data_type(src_desc->data_type, + weights_desc->data_type, dst_desc->data_type, prop_kind); + + const int g = with_groups ? weights_desc->dims[0] : 1; + const int bias_dim = prop_kind == backward_data + ? src_desc->dims[1] + : dst_desc->dims[1]; + + bool consistency = true + && memory_desc_wrapper(weights_desc).nelems() + && src_desc->ndims == dst_desc->ndims + && utils::one_of(src_desc->ndims, 3, 4, 5) + && utils::one_of(weights_desc->ndims, src_desc->ndims, + src_desc->ndims + 1) + && (with_bias ? bias_desc->ndims == 1 : true) + && (with_bias ? bias_desc->dims[0] == bias_dim : true) + && src_desc->dims[0] == dst_desc->dims[0] + && src_desc->dims[1] == g * weights_desc->dims[with_groups + 1] + && dst_desc->dims[1] == g * weights_desc->dims[with_groups + 0]; + for (int i = 2; i < src_desc->ndims; ++i) + { + int src = src_desc->dims[i]; + int ker = weights_desc->dims[with_groups + i]; + int dil = cd.dilates[i - 2]; + int pad_l = padding_l[i - 2]; + int pad_r = padding_r[i - 2]; + int str = strides[i - 2]; + int dst = dst_desc->dims[i]; + int ker_range = 1 + (ker - 1) * (dil + 1); + + if (str < 1) return invalid_arguments; + consistency = consistency + && dil >= 0 + && pad_l >= 0 + && pad_r + str > 0 + && (src - ker_range + pad_l + pad_r) / str + 1 == dst; + } + if (!consistency) return invalid_arguments; + + *conv_desc = cd; + return success; +} +} +} + +status_t mkldnn_convolution_forward_desc_init(convolution_desc_t *conv_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *bias_desc, const memory_desc_t *dst_desc, + const dims_t strides, const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return mkldnn::impl::conv_desc_init(conv_desc, prop_kind, alg_kind, src_desc, + weights_desc, bias_desc, dst_desc, strides, nullptr, + padding_l, padding_r, padding_kind); +} + +status_t mkldnn_dilated_convolution_forward_desc_init( + convolution_desc_t *conv_desc, prop_kind_t prop_kind, + alg_kind_t alg_kind, const memory_desc_t *src_desc, + const memory_desc_t *weights_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_desc, const dims_t strides, + const dims_t dilates, const dims_t padding_l, + const dims_t padding_r, padding_kind_t padding_kind) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return mkldnn::impl::conv_desc_init(conv_desc, prop_kind, alg_kind, src_desc, + weights_desc, bias_desc, dst_desc, strides, dilates, + padding_l, padding_r, padding_kind); +} + +status_t mkldnn_convolution_backward_data_desc_init( + convolution_desc_t *conv_desc, alg_kind_t alg_kind, + const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *diff_dst_desc, const dims_t strides, + const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return mkldnn::impl::conv_desc_init(conv_desc, backward_data, alg_kind, diff_src_desc, + weights_desc, nullptr, diff_dst_desc, strides, nullptr, + padding_l, padding_r, padding_kind); +} + +status_t mkldnn_dilated_convolution_backward_data_desc_init( + convolution_desc_t *conv_desc, alg_kind_t alg_kind, + const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *diff_dst_desc, const dims_t strides, + const dims_t dilates, const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return mkldnn::impl::conv_desc_init(conv_desc, backward_data, alg_kind, diff_src_desc, + weights_desc, nullptr, diff_dst_desc, strides, dilates, + padding_l, padding_r, padding_kind); +} + +status_t mkldnn_convolution_backward_weights_desc_init( + convolution_desc_t *conv_desc, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc, + const memory_desc_t *diff_bias_desc, + const memory_desc_t *diff_dst_desc, const dims_t strides, + const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return mkldnn::impl::conv_desc_init(conv_desc, backward_weights, alg_kind, src_desc, + diff_weights_desc, diff_bias_desc, diff_dst_desc, strides, + nullptr, padding_l, padding_r, padding_kind); +} + +status_t mkldnn_dilated_convolution_backward_weights_desc_init( + convolution_desc_t *conv_desc, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc, + const memory_desc_t *diff_bias_desc, + const memory_desc_t *diff_dst_desc, const dims_t strides, + const dims_t dilates, const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return mkldnn::impl::conv_desc_init(conv_desc, backward_weights, alg_kind, src_desc, + diff_weights_desc, diff_bias_desc, diff_dst_desc, strides, + dilates, padding_l, padding_r, padding_kind); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp new file mode 100644 index 0000000000..9604e0acf5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp @@ -0,0 +1,56 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "utils.hpp" + +#include "convolution_pd.hpp" + +namespace mkldnn { +namespace impl { + +using namespace prop_kind; + +memory_desc_t *conv_prop_invariant_src_d(convolution_desc_t *desc) { + return desc->prop_kind == backward_data + ? &desc->diff_src_desc : &desc->src_desc; +} + +memory_desc_t *conv_prop_invariant_wei_d(convolution_desc_t *desc) { + return desc->prop_kind == backward_weights + ? &desc->diff_weights_desc : &desc->weights_desc; +} + +memory_desc_t *conv_prop_invariant_bia_d(convolution_desc_t *desc) { + return desc->prop_kind == backward_weights + ? &desc->diff_bias_desc : &desc->bias_desc; +} + +memory_desc_t *conv_prop_invariant_dst_d(convolution_desc_t *desc) { + return utils::one_of(desc->prop_kind, forward_inference, forward_training) + ? &desc->dst_desc : &desc->diff_dst_desc; +} + +const memory_desc_t *conv_prop_invariant_src_d(const convolution_desc_t *desc) +{ return conv_prop_invariant_src_d(const_cast(desc)); } +const memory_desc_t *conv_prop_invariant_wei_d(const convolution_desc_t *desc) +{ return conv_prop_invariant_wei_d(const_cast(desc)); } +const memory_desc_t *conv_prop_invariant_bia_d(const convolution_desc_t *desc) +{ return conv_prop_invariant_bia_d(const_cast(desc)); } +const memory_desc_t *conv_prop_invariant_dst_d(const convolution_desc_t *desc) +{ return conv_prop_invariant_dst_d(const_cast(desc)); } + +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp new file mode 100644 index 0000000000..b10c36db49 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp @@ -0,0 +1,348 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CONVOLUTION_PD_HPP +#define CONVOLUTION_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +status_t conv_desc_init(convolution_desc_t *conv_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *bias_desc, const memory_desc_t *dst_desc, + const dims_t strides, const dims_t dilates, + const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind); + +memory_desc_t *conv_prop_invariant_src_d(convolution_desc_t *desc); +memory_desc_t *conv_prop_invariant_wei_d(convolution_desc_t *desc); +memory_desc_t *conv_prop_invariant_bia_d(convolution_desc_t *desc); +memory_desc_t *conv_prop_invariant_dst_d(convolution_desc_t *desc); +const memory_desc_t *conv_prop_invariant_src_d(const convolution_desc_t *desc); +const memory_desc_t *conv_prop_invariant_wei_d(const convolution_desc_t *desc); +const memory_desc_t *conv_prop_invariant_bia_d(const convolution_desc_t *desc); +const memory_desc_t *conv_prop_invariant_dst_d(const convolution_desc_t *desc); + +struct convolution_fwd_pd_t; + +struct convolution_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::convolution; + + convolution_pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + {} + + const convolution_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case pkind_traits::query_d: + *(const convolution_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common conv aux functions */ + + dim_t MB() const { return _src_md()->dims[0]; } + + dim_t IC() const { return _src_md()->dims[1]; } + dim_t OC() const { return _dst_md()->dims[1]; } + dim_t G() const { return with_groups() ? _wei_md()->dims[0] : 1; } + + dim_t ID() const { return ndims() >= 5 ? _src_md()->dims[ndims() - 3] : 1; } + dim_t IH() const { return ndims() >= 4 ? _src_md()->dims[ndims() - 2] : 1; } + dim_t IW() const { return _src_md()->dims[ndims() - 1]; } + + dim_t OD() const { return ndims() >= 5 ? _dst_md()->dims[ndims() - 3] : 1; } + dim_t OH() const { return ndims() >= 4 ? _dst_md()->dims[ndims() - 2] : 1; } + dim_t OW() const { return _dst_md()->dims[ndims() - 1]; } + + dim_t KD() const { return ndims() >= 5 ? _wei_md()->dims[ndims() + with_groups() - 3] : 1; } + dim_t KH() const { return ndims() >= 4 ? _wei_md()->dims[ndims() + with_groups() - 2] : 1; } + dim_t KW() const { return _wei_md()->dims[ndims() + with_groups() - 1]; } + + dim_t KSD() const { return ndims() >= 5 ? desc_.strides[ndims() - 5] : 1; } + dim_t KSH() const { return ndims() >= 4 ? desc_.strides[ndims() - 4] : 1; } + dim_t KSW() const { return desc_.strides[ndims() - 3]; } + + dim_t KDD() const { return ndims() >= 5 ? desc_.dilates[ndims() - 5] : 0; } + dim_t KDH() const { return ndims() >= 4 ? desc_.dilates[ndims() - 4] : 1; } + dim_t KDW() const { return desc_.dilates[ndims() - 3]; } + + dim_t padFront() const { return ndims() >= 5 ? desc_.padding[0][ndims() - 5] : 0; } + dim_t padBack() const { return ndims() >= 5 ? desc_.padding[1][ndims() - 5] : 0; } + dim_t padT() const { return ndims() >= 4 ? desc_.padding[0][ndims() - 4] : 0; } + dim_t padB() const { return ndims() >= 4 ? desc_.padding[1][ndims() - 4] : 0; } + dim_t padL() const { return desc_.padding[0][ndims() - 3]; } + dim_t padR() const { return desc_.padding[1][ndims() - 3]; } + + int ndims() const { return _src_md()->ndims; } + + bool with_bias() const { return !memory_desc_wrapper(*_bia_md()).is_zero(); } + bool with_groups() const { return _wei_md()->ndims == ndims() + 1; } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + + bool has_zero_dim_memory() const { + const auto s_d = memory_desc_wrapper(*_src_md()); + const auto d_d = memory_desc_wrapper(*_dst_md()); + return s_d.has_zero_dim() || d_d.has_zero_dim(); + } + +protected: + convolution_desc_t desc_; + const convolution_fwd_pd_t *hint_fwd_pd_; + + bool set_default_formats_common_template( + memory_desc_t &src_md, format_tag_t src_tag, + memory_desc_t &wei_md, format_tag_t wei_tag, + memory_desc_t &dst_md, format_tag_t dst_tag, + memory_desc_t &bia_md) { + using namespace format_tag; + +# define IS_OK(f) \ + do { if ((f) != status::success) return false; } while(0) + if (src_md.format_kind == format_kind::any + && !utils::one_of(src_tag, any, undef)) + IS_OK(memory_desc_init_by_tag(src_md, src_tag)); + if (dst_md.format_kind == format_kind::any + && !utils::one_of(dst_tag, any, undef)) + IS_OK(memory_desc_init_by_tag(dst_md, dst_tag)); + if (wei_md.format_kind == format_kind::any + && !utils::one_of(wei_tag, any, undef)) + IS_OK(memory_desc_init_by_tag(wei_md, wei_tag)); + if (with_bias() && bia_md.format_kind == format_kind::any) + IS_OK(memory_desc_init_by_tag(bia_md, x)); +# undef IS_OK + + return true; + } + + bool set_default_alg_kind(alg_kind_t alg_kind) { + assert(utils::one_of(alg_kind, alg_kind::convolution_direct, + alg_kind::convolution_winograd)); + if (desc_.alg_kind == alg_kind::convolution_auto) + desc_.alg_kind = alg_kind; + return desc_.alg_kind == alg_kind; + } + + bool expect_data_types(data_type_t src_dt, data_type_t wei_dt, + data_type_t bia_dt, data_type_t dst_dt, data_type_t acc_dt) const { + bool ok = true + && (src_dt == data_type::undef || _src_md()->data_type == src_dt) + && (wei_dt == data_type::undef || _wei_md()->data_type == wei_dt) + && (dst_dt == data_type::undef || _dst_md()->data_type == dst_dt) + && (acc_dt == data_type::undef || desc_.accum_data_type == acc_dt); + if (with_bias() && bia_dt != data_type::undef) + ok = ok && _bia_md()->data_type == bia_dt; + return ok; + } + +private: + const memory_desc_t *_src_md() const { return conv_prop_invariant_src_d(&desc_); } + const memory_desc_t *_wei_md() const { return conv_prop_invariant_wei_d(&desc_); } + const memory_desc_t *_bia_md() const { return conv_prop_invariant_bia_d(&desc_); } + const memory_desc_t *_dst_md() const { return conv_prop_invariant_dst_d(&desc_); } +}; + +struct convolution_fwd_pd_t: public convolution_pd_t { + typedef convolution_fwd_pd_t base_class; + typedef convolution_fwd_pd_t hint_class; + + convolution_fwd_pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : convolution_pd_t(engine, adesc, attr, hint_fwd_pd) + , src_md_(desc_.src_desc) + , weights_md_(desc_.weights_desc) + , bias_md_(desc_.bias_desc) + , dst_md_(desc_.dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_WEIGHTS)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_BIAS && with_bias()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &dst_md_ : nullptr; } + virtual const memory_desc_t *weights_md(int index = 0) const override { + if (index == 0) return &weights_md_; + if (index == 1 && with_bias()) return &bias_md_; + return nullptr; + } + + virtual int n_inputs() const override { return 2 + with_bias(); } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t src_md_; + memory_desc_t weights_md_; + memory_desc_t bias_md_; + memory_desc_t dst_md_; + + bool set_default_formats_common(format_tag_t src_tag, + format_tag_t wei_tag, format_tag_t dst_tag) { + return set_default_formats_common_template(src_md_, src_tag, + weights_md_, wei_tag, dst_md_, dst_tag, bias_md_); + } +}; + +struct convolution_bwd_data_pd_t: public convolution_pd_t { + typedef convolution_bwd_data_pd_t base_class; + typedef convolution_fwd_pd_t hint_class; + + convolution_bwd_data_pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : convolution_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_src_md_(desc_.diff_src_desc) + , weights_md_(desc_.weights_desc) + , bias_md_(desc_.bias_desc) + , diff_dst_md_(desc_.diff_dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_src_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_dst_md_ : nullptr; } + virtual const memory_desc_t *weights_md(int index = 0) const override { + if (index == 0) return &weights_md_; + if (index == 1 && with_bias()) return &bias_md_; + return nullptr; + } + + virtual int n_inputs() const override { return 2 + with_bias(); } + virtual int n_outputs() const override { return 1; } + + virtual bool support_bias() const { return false; } + +protected: + memory_desc_t diff_src_md_; + memory_desc_t weights_md_; + memory_desc_t bias_md_; + memory_desc_t diff_dst_md_; + + bool set_default_formats_common(format_tag_t diff_src_tag, + format_tag_t wei_tag, format_tag_t diff_dst_tag) { + return set_default_formats_common_template(diff_src_md_, diff_src_tag, + weights_md_, wei_tag, diff_dst_md_, diff_dst_tag, bias_md_); + } +}; + +struct convolution_bwd_weights_pd_t: public convolution_pd_t { + typedef convolution_bwd_weights_pd_t base_class; + typedef convolution_fwd_pd_t hint_class; + + convolution_bwd_weights_pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : convolution_pd_t(engine, adesc, attr, hint_fwd_pd) + , src_md_(desc_.src_desc) + , diff_weights_md_(desc_.diff_weights_desc) + , diff_bias_md_(desc_.diff_bias_desc) + , diff_dst_md_(desc_.diff_dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_WEIGHTS) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_DIFF_BIAS && with_bias()) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_dst_md_ : nullptr; } + virtual const memory_desc_t *diff_weights_md(int index = 0) const override { + if (index == 0) return &diff_weights_md_; + if (index == 1 && with_bias()) return &diff_bias_md_; + return nullptr; + } + + virtual int n_inputs() const override { return 2; } + virtual int n_outputs() const override { return 1 + with_bias(); } + +protected: + memory_desc_t src_md_; + memory_desc_t diff_weights_md_; + memory_desc_t diff_bias_md_; + memory_desc_t diff_dst_md_; + + bool set_default_formats_common(format_tag_t src_tag, + format_tag_t diff_wei_tag, format_tag_t diff_dst_tag) { + return set_default_formats_common_template(src_md_, src_tag, + diff_weights_md_, diff_wei_tag, diff_dst_md_, diff_dst_tag, + diff_bias_md_); + } +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp b/thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp new file mode 100644 index 0000000000..98063c1c37 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp @@ -0,0 +1,188 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn.h" +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::alg_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t deconv_desc_init(deconvolution_desc_t *deconv_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *bias_desc, const memory_desc_t *dst_desc, + const dims_t strides, const dims_t dilates, const dims_t padding_l, + const dims_t padding_r, padding_kind_t padding_kind) { + bool args_ok = true + && !any_null(deconv_desc, src_desc, weights_desc, dst_desc, strides, + padding_l) + && one_of(alg_kind, deconvolution_direct, deconvolution_winograd) + && one_of(padding_kind, padding_kind::padding_zero); + if (!args_ok) + return invalid_arguments; + + if (padding_r == nullptr) + padding_r = padding_l; + + auto dd = deconvolution_desc_t(); + dd.primitive_kind = primitive_kind::deconvolution; + dd.prop_kind = prop_kind; + dd.alg_kind = alg_kind; + + dd.diff_src_desc = dd.src_desc = zero_md(); + dd.diff_dst_desc = dd.dst_desc = zero_md(); + dd.diff_weights_desc = dd.weights_desc = zero_md(); + dd.diff_bias_desc = dd.bias_desc = zero_md(); + + const bool is_fwd = one_of(prop_kind, forward_training, forward_inference); + const bool with_bias + = bias_desc && bias_desc->format_kind != format_kind::undef; + const bool with_groups = weights_desc->ndims == src_desc->ndims + 1; + + (prop_kind == backward_data ? dd.diff_src_desc : dd.src_desc) = *src_desc; + (is_fwd ? dd.dst_desc : dd.diff_dst_desc) = *dst_desc; + (prop_kind == backward_weights ? dd.diff_weights_desc : dd.weights_desc) + = *weights_desc; + if (with_bias) + (prop_kind == backward_weights ? dd.diff_bias_desc : dd.bias_desc) + = *bias_desc; + + int sp_dims = src_desc->ndims - 2; + utils::array_copy(dd.strides, strides, sp_dims); + utils::array_copy(dd.padding[0], padding_l, sp_dims); + utils::array_copy(dd.padding[1], padding_r, sp_dims); + if (dilates) + utils::array_copy(dd.dilates, dilates, sp_dims); + else + utils::array_set(dd.dilates, 0, sp_dims); + + dd.padding_kind = padding_kind; + dd.accum_data_type = types::default_accum_data_type(src_desc->data_type, + weights_desc->data_type, dst_desc->data_type, prop_kind); + + const int g = with_groups ? weights_desc->dims[0] : 1; + bool consistency = true + && src_desc->ndims == dst_desc->ndims + && utils::one_of(src_desc->ndims, 3, 4, 5) + && utils::one_of(weights_desc->ndims, src_desc->ndims, + src_desc->ndims + 1) + && (with_bias ? bias_desc->ndims == 1 : true) + && (with_bias ? bias_desc->dims[0] == dst_desc->dims[1] : true) + && src_desc->dims[0] == dst_desc->dims[0] + && src_desc->dims[1] == g * weights_desc->dims[with_groups + 1] + && dst_desc->dims[1] == g * weights_desc->dims[with_groups + 0]; + for (int i = 2; i < src_desc->ndims; ++i) { + int src = src_desc->dims[i]; + int ker = weights_desc->dims[with_groups + i]; + int dil = dd.dilates[i - 2]; + int pad = padding_l[i - 2] + padding_r[i - 2]; + int str = strides[i - 2]; + int dst = dst_desc->dims[i]; + int ker_range = 1 + (ker - 1) * (dil + 1); + + consistency + = consistency && (dst - ker_range + pad) / str + 1 == src; + } + if (!consistency) + return invalid_arguments; + + *deconv_desc = dd; + return success; +} +} + +status_t mkldnn_deconvolution_forward_desc_init( + deconvolution_desc_t *deconv_desc, prop_kind_t prop_kind, + alg_kind_t alg_kind, const memory_desc_t *src_desc, + const memory_desc_t *weights_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_desc, const dims_t strides, + const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return deconv_desc_init(deconv_desc, prop_kind, alg_kind, src_desc, + weights_desc, bias_desc, dst_desc, strides, nullptr, padding_l, + padding_r, padding_kind); +} + +status_t mkldnn_dilated_deconvolution_forward_desc_init( + deconvolution_desc_t *deconv_desc, prop_kind_t prop_kind, + alg_kind_t alg_kind, const memory_desc_t *src_desc, + const memory_desc_t *weights_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_desc, const dims_t strides, + const dims_t dilates, const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return deconv_desc_init(deconv_desc, prop_kind, alg_kind, src_desc, + weights_desc, bias_desc, dst_desc, strides, dilates, padding_l, + padding_r, padding_kind); +} + +status_t mkldnn_deconvolution_backward_data_desc_init( + deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind, + const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *diff_dst_desc, const dims_t strides, + const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return deconv_desc_init(deconv_desc, backward_data, alg_kind, diff_src_desc, + weights_desc, nullptr, diff_dst_desc, strides, nullptr, padding_l, + padding_r, padding_kind); +} + +status_t mkldnn_dilated_deconvolution_backward_data_desc_init( + deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind, + const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *diff_dst_desc, const dims_t strides, + const dims_t dilates, const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return deconv_desc_init(deconv_desc, backward_data, alg_kind, diff_src_desc, + weights_desc, nullptr, diff_dst_desc, strides,dilates, padding_l, + padding_r, padding_kind); +} + +status_t mkldnn_deconvolution_backward_weights_desc_init( + deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc, + const memory_desc_t *diff_bias_desc, const memory_desc_t *diff_dst_desc, + const dims_t strides, const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return deconv_desc_init(deconv_desc, backward_weights, alg_kind, src_desc, + diff_weights_desc, diff_bias_desc, diff_dst_desc, strides, nullptr, + padding_l, padding_r, padding_kind); +} + +status_t mkldnn_dilated_deconvolution_backward_weights_desc_init( + deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc, + const memory_desc_t *diff_bias_desc, const memory_desc_t *diff_dst_desc, + const dims_t strides, const dims_t dilates, const dims_t padding_l, + const dims_t padding_r, padding_kind_t padding_kind) { + return deconv_desc_init(deconv_desc, backward_weights, alg_kind, src_desc, + diff_weights_desc, diff_bias_desc, diff_dst_desc, strides, dilates, + padding_l, padding_r, padding_kind); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp new file mode 100644 index 0000000000..539e44bd9b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp @@ -0,0 +1,293 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef DECONVOLUTION_PD_HPP +#define DECONVOLUTION_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "convolution_pd.hpp" +#include "primitive_desc.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +struct deconvolution_fwd_pd_t; + +struct deconvolution_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::deconvolution; + + deconvolution_pd_t(engine_t *engine, + const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + {} + + const deconvolution_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case pkind_traits::query_d: + *(const deconvolution_desc_t **)result = desc(); + break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common deconv aux functions (note that conv_desc_t == deconv_desc_t) */ + + dim_t MB() const { return conv_prop_invariant_src_d(&desc_)->dims[0]; } + + dim_t IC() const { return conv_prop_invariant_src_d(&desc_)->dims[1]; } + dim_t OC() const { return conv_prop_invariant_dst_d(&desc_)->dims[1]; } + dim_t G() const + { return with_groups() ? conv_prop_invariant_wei_d(&desc_)->dims[0] : 1; } + + dim_t ID() const { + return ndims() >= 5 + ? conv_prop_invariant_src_d(&desc_)->dims[ndims() - 3] : 1; + } + dim_t IH() const { + return ndims() >= 4 + ? conv_prop_invariant_src_d(&desc_)->dims[ndims() - 2] : 1; + } + dim_t IW() const { + return conv_prop_invariant_src_d(&desc_)->dims[ndims() - 1]; + } + + dim_t OD() const { + return ndims() >= 5 + ? conv_prop_invariant_dst_d(&desc_)->dims[ndims() - 3] : 1; + } + dim_t OH() const { + return ndims() >= 4 + ? conv_prop_invariant_dst_d(&desc_)->dims[ndims() - 2] : 1; + } + dim_t OW() const { + return conv_prop_invariant_dst_d(&desc_)->dims[ndims() - 1]; + } + + dim_t KD() const { + const int w_ndims = ndims() + with_groups(); + return ndims() >= 5 + ? conv_prop_invariant_wei_d(&desc_)->dims[w_ndims - 3] : 1; + } + dim_t KH() const { + const int w_ndims = ndims() + with_groups(); + return ndims() >= 4 + ? conv_prop_invariant_wei_d(&desc_)->dims[w_ndims - 2] : 1; + } + dim_t KW() const { + const int w_ndims = ndims() + with_groups(); + return conv_prop_invariant_wei_d(&desc_)->dims[w_ndims - 1]; + } + + dim_t KSD() const { return ndims() >= 5 ? desc_.strides[ndims() - 5] : 1; } + dim_t KSH() const { return ndims() >= 4 ? desc_.strides[ndims() - 4] : 1; } + dim_t KSW() const { return desc_.strides[ndims() - 3]; } + + dim_t KDD() const { return ndims() >= 5 ? desc_.dilates[ndims() - 5] : 0; } + dim_t KDH() const { return ndims() >= 4 ? desc_.dilates[ndims() - 4] : 1; } + dim_t KDW() const { return desc_.dilates[ndims() - 3]; } + + dim_t padFront() const + { return ndims() >= 5 ? desc_.padding[0][ndims() - 5] : 0; } + dim_t padBack() const + { return ndims() >= 5 ? desc_.padding[1][ndims() - 5] : 0; } + dim_t padT() const + { return ndims() >= 4 ? desc_.padding[0][ndims() - 4] : 0; } + dim_t padB() const + { return ndims() >= 4 ? desc_.padding[1][ndims() - 4] : 0; } + dim_t padL() const { return desc_.padding[0][ndims() - 3]; } + dim_t padR() const { return desc_.padding[1][ndims() - 3]; } + + bool with_bias() const { + return + !memory_desc_wrapper(*conv_prop_invariant_bia_d(&desc_)).is_zero(); + } + + bool with_groups() const + { return conv_prop_invariant_wei_d(&desc_)->ndims == ndims() + 1; } + + int ndims() const { return conv_prop_invariant_src_d(&desc_)->ndims; } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + + bool has_zero_dim_memory() const { + const auto s_d = memory_desc_wrapper(*conv_prop_invariant_src_d(&desc_)); + const auto d_d = memory_desc_wrapper(*conv_prop_invariant_dst_d(&desc_)); + return s_d.has_zero_dim() || d_d.has_zero_dim(); + } + +protected: + deconvolution_desc_t desc_; + const deconvolution_fwd_pd_t *hint_fwd_pd_; +}; + +struct deconvolution_fwd_pd_t: public deconvolution_pd_t { + typedef deconvolution_fwd_pd_t base_class; + typedef deconvolution_fwd_pd_t hint_class; + + deconvolution_fwd_pd_t(engine_t *engine, + const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : deconvolution_pd_t(engine, adesc, attr, hint_fwd_pd) + , src_md_(desc_.src_desc) + , weights_md_(desc_.weights_desc) + , bias_md_(desc_.bias_desc) + , dst_md_(desc_.dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_WEIGHTS)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_BIAS && with_bias()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &dst_md_ : nullptr; } + virtual const memory_desc_t *weights_md(int index = 0) const override { + if (index == 0) return &weights_md_; + if (index == 1 && with_bias()) return &bias_md_; + return nullptr; + } + + virtual int n_inputs() const override { return 2 + with_bias(); } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t src_md_; + memory_desc_t weights_md_; + memory_desc_t bias_md_; + memory_desc_t dst_md_; +}; + +struct deconvolution_bwd_data_pd_t: public deconvolution_pd_t { + typedef deconvolution_bwd_data_pd_t base_class; + typedef deconvolution_fwd_pd_t hint_class; + + deconvolution_bwd_data_pd_t(engine_t *engine, + const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : deconvolution_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_src_md_(desc_.diff_src_desc) + , weights_md_(desc_.weights_desc) + , diff_dst_md_(desc_.diff_dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_src_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_dst_md_ : nullptr; } + virtual const memory_desc_t *weights_md(int index = 0) const override + { return index == 0 ? &weights_md_ : nullptr; } + + virtual int n_inputs() const override { return 2; } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t diff_src_md_; + memory_desc_t weights_md_; + memory_desc_t diff_dst_md_; +}; + +struct deconvolution_bwd_weights_pd_t: public deconvolution_pd_t { + typedef deconvolution_bwd_weights_pd_t base_class; + typedef deconvolution_fwd_pd_t hint_class; + + deconvolution_bwd_weights_pd_t(engine_t *engine, + const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : deconvolution_pd_t(engine, adesc, attr, hint_fwd_pd) + , src_md_(desc_.src_desc) + , diff_weights_md_(desc_.diff_weights_desc) + , diff_bias_md_(desc_.diff_bias_desc) + , diff_dst_md_(desc_.diff_dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_WEIGHTS) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_DIFF_BIAS && with_bias()) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_dst_md_ : nullptr; } + virtual const memory_desc_t *diff_weights_md(int index = 0) const override { + if (index == 0) return &diff_weights_md_; + if (index == 1 && with_bias()) return &diff_bias_md_; + return nullptr; + } + + virtual int n_inputs() const override { return 2; } + virtual int n_outputs() const override { return 1 + with_bias(); } + +protected: + memory_desc_t src_md_; + memory_desc_t diff_weights_md_; + memory_desc_t diff_bias_md_; + memory_desc_t diff_dst_md_; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp b/thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp new file mode 100644 index 0000000000..f1708fca52 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp @@ -0,0 +1,84 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::alg_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t eltwise_desc_init(eltwise_desc_t *eltwise_desc, prop_kind_t prop_kind, + alg_kind_t alg_kind, const memory_desc_t *data_desc, + const memory_desc_t *diff_data_desc, float alpha, float beta) { + bool args_ok = true + && !any_null(eltwise_desc, data_desc) + && one_of(prop_kind, forward_training, forward_inference, + backward_data) + && one_of(alg_kind, eltwise_relu, eltwise_tanh, eltwise_elu, + eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear, + eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic) + && IMPLICATION(prop_kind == backward_data, diff_data_desc != nullptr); + if (!args_ok) return invalid_arguments; + + auto ed = eltwise_desc_t(); + ed.primitive_kind = primitive_kind::eltwise; + ed.prop_kind = prop_kind; + ed.alg_kind = alg_kind; + + ed.data_desc = *data_desc; + ed.diff_data_desc = + (ed.prop_kind == backward_data) ? *diff_data_desc : zero_md(); + + ed.alpha = alpha; + ed.beta = beta; + + bool consistency = true + && IMPLICATION(ed.prop_kind == backward_data, + array_cmp(ed.diff_data_desc.dims, ed.data_desc.dims, + ed.diff_data_desc.ndims)); + if (!consistency) return invalid_arguments; + + *eltwise_desc = ed; + return success; +} +} + +status_t mkldnn_eltwise_forward_desc_init(eltwise_desc_t *eltwise_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *data_desc, float alpha, float beta) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return eltwise_desc_init(eltwise_desc, prop_kind, alg_kind, data_desc, + nullptr, alpha, beta); +} + +status_t mkldnn_eltwise_backward_desc_init(eltwise_desc_t *eltwise_desc, + alg_kind_t alg_kind, const memory_desc_t *diff_data_desc, + const memory_desc_t *data_desc, float alpha, float beta) { + return eltwise_desc_init(eltwise_desc, backward_data, alg_kind, data_desc, + diff_data_desc, alpha, beta); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp new file mode 100644 index 0000000000..9fd260fcee --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp @@ -0,0 +1,161 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef ELTWISE_PD_HPP +#define ELTWISE_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" + +namespace mkldnn { +namespace impl { + +struct eltwise_fwd_pd_t; + +struct eltwise_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::eltwise; + + eltwise_pd_t(mkldnn::impl::engine_t *engine, + const eltwise_desc_t *adesc, + const primitive_attr_t *attr, + const eltwise_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + , data_md_(desc_.data_desc) + {} + + const eltwise_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::eltwise_d: + *(const eltwise_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common eltwise aux functions */ + + dim_t MB() const { return data_desc().dims[0]; } + dim_t C() const { return data_desc().dims[1]; } + dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; } + dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; } + dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; } + + int ndims() const { return data_desc().ndims; } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + + bool has_zero_dim_memory() const + { return memory_desc_wrapper(desc_.data_desc).has_zero_dim(); } + +protected: + eltwise_desc_t desc_; + const eltwise_fwd_pd_t *hint_fwd_pd_; + + memory_desc_t data_md_; + +private: + const memory_desc_t &data_desc() const { return desc_.data_desc; } +}; + +struct eltwise_fwd_pd_t: public eltwise_pd_t { + typedef eltwise_fwd_pd_t base_class; + typedef eltwise_fwd_pd_t hint_class; + + eltwise_fwd_pd_t(mkldnn::impl::engine_t *engine, + const eltwise_desc_t *adesc, + const primitive_attr_t *attr, + const eltwise_fwd_pd_t *hint_fwd_pd) + : eltwise_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_SRC) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + + virtual int n_inputs() const override { return 1; } + virtual int n_outputs() const override { return 1; } + + bool is_zero_preserved() const + { return math::eltwise_fwd_preserves_zero(desc_.alg_kind); } +}; + +struct eltwise_bwd_pd_t: public eltwise_pd_t { + typedef eltwise_bwd_pd_t base_class; + typedef eltwise_fwd_pd_t hint_class; + + eltwise_bwd_pd_t(engine_t *engine, + const eltwise_desc_t *adesc, + const primitive_attr_t *attr, + const eltwise_fwd_pd_t *hint_fwd_pd) + : eltwise_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_data_md_(desc_.diff_data_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + + virtual int n_inputs() const override { return 2; } + virtual int n_outputs() const override { return 1; } + + bool is_zero_preserved() const { return true; } + +protected: + memory_desc_t diff_data_md_; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/engine.cpp b/thirdparty/oidn/mkl-dnn/src/common/engine.cpp new file mode 100644 index 0000000000..3b3e25456d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/engine.cpp @@ -0,0 +1,75 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn.h" +#include "engine.hpp" +#include "nstl.hpp" + +#include "c_types_map.hpp" +#include "../cpu/cpu_engine.hpp" + +namespace mkldnn { +namespace impl { + +engine_factory_t *engine_factories[] = { + &cpu::engine_factory, + nullptr, +}; + +static inline engine_factory_t *get_engine_factory(engine_kind_t kind) { + for (engine_factory_t **ef = engine_factories; *ef; ef++) + if ((*ef)->kind() == kind) + return *ef; + return nullptr; +} + +} +} + +using namespace mkldnn::impl; +using namespace mkldnn::impl::status; + +size_t mkldnn_engine_get_count(engine_kind_t kind) { + engine_factory_t *ef = get_engine_factory(kind); + return ef != nullptr ? ef->count() : 0; +} + +status_t mkldnn_engine_create(engine_t **engine, + engine_kind_t kind, size_t index) { + if (engine == nullptr) + return invalid_arguments; + + engine_factory_t *ef = get_engine_factory(kind); + if (ef == nullptr || index >= ef->count()) + return invalid_arguments; + + return ef->engine_create(engine, index); +} + +status_t mkldnn_engine_get_kind(engine_t *engine, engine_kind_t *kind) { + if (engine == nullptr) + return invalid_arguments; + *kind = engine->kind(); + return success; +} + +status_t mkldnn_engine_destroy(engine_t *engine) { + /* TODO: engine->dec_ref_count(); */ + delete engine; + return success; +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/engine.hpp b/thirdparty/oidn/mkl-dnn/src/common/engine.hpp new file mode 100644 index 0000000000..8ac8a29de5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/engine.hpp @@ -0,0 +1,119 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef ENGINE_HPP +#define ENGINE_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive.hpp" +#include "utils.hpp" + +/** \brief An abstraction of an execution unit with shared resources + * + * Responsibilities: + * - Provide engine specific memory allocation + * - Provide engine specific primitive_desc_t creators + */ +struct mkldnn_engine: public mkldnn::impl::c_compatible { + mkldnn_engine(mkldnn::impl::engine_kind_t kind) + : kind_(kind) + {} + virtual ~mkldnn_engine() {} + + /** get kind of the current engine */ + virtual mkldnn::impl::engine_kind_t kind() const { return kind_; } + + /** allocate memory */ + virtual mkldnn::impl::status_t memory_create( + mkldnn::impl::memory_t **memory, + const mkldnn::impl::memory_desc_t *md, + void *handle) = 0; + + /** implementation section (typedefs) */ + + // TODO: remove engine? + typedef mkldnn::impl::status_t (*reorder_primitive_desc_create_f)( + mkldnn::impl::reorder_pd_t **reorder_pd, + mkldnn::impl::engine_t *engine, + const mkldnn::impl::primitive_attr_t *attr, + mkldnn::impl::engine_t *src_engine, + const mkldnn::impl::memory_desc_t *src_md, + mkldnn::impl::engine_t *dst_engine, + const mkldnn::impl::memory_desc_t *dst_md); + + typedef mkldnn::impl::status_t (*concat_primitive_desc_create_f)( + mkldnn::impl::concat_pd_t **concat_pd, + mkldnn::impl::engine_t *engine, + const mkldnn::impl::primitive_attr_t *attr, + const mkldnn::impl::memory_desc_t *dst_md, + int n, int concat_dim, + const mkldnn::impl::memory_desc_t *src_mds); + + typedef mkldnn::impl::status_t (*sum_primitive_desc_create_f)( + mkldnn::impl::sum_pd_t **sum_pd, + mkldnn::impl::engine_t *engine, + const mkldnn::impl::primitive_attr_t *attr, + const mkldnn::impl::memory_desc_t *dst_md, + int n, const float *scales, + const mkldnn::impl::memory_desc_t *src_mds); + + typedef mkldnn::impl::status_t (*primitive_desc_create_f)( + mkldnn::impl::primitive_desc_t **, const mkldnn::impl::op_desc_t *, + const mkldnn::impl::primitive_attr_t *attr, + mkldnn::impl::engine_t *, const mkldnn::impl::primitive_desc_t *); + + /* implementation section */ + + /** return the list of reorder implementations. engine guarantees to return + * a NULL-terminated list */ + virtual const reorder_primitive_desc_create_f* + get_reorder_implementation_list() const = 0; + + /** return the list of concat implementations. engine guarantees to return + * a NULL-terminated list */ + virtual const concat_primitive_desc_create_f* + get_concat_implementation_list() const = 0; + + /** return the list of sum implementations. engine guarantees to return + * a NULL-terminated list */ + virtual const sum_primitive_desc_create_f* + get_sum_implementation_list() const = 0; + + /** return the list of implementations. engine guarantees to return a + * NULL-terminated list */ + virtual const primitive_desc_create_f* get_implementation_list() const = 0; + +protected: + mkldnn::impl::engine_kind_t kind_; +}; + +namespace mkldnn { +namespace impl { + +struct engine_factory_t: public c_compatible { + virtual size_t count() const = 0; + virtual engine_kind_t kind() const = 0; + virtual status_t engine_create(engine_t **engine, size_t index) const = 0; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp new file mode 100644 index 0000000000..5a9f58cb1e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp @@ -0,0 +1,106 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t ip_desc_init(inner_product_desc_t *ip_desc, prop_kind_t prop_kind, + const memory_desc_t *src_desc, const memory_desc_t *weights_desc, + const memory_desc_t *bias_desc, const memory_desc_t *dst_desc) { + bool args_ok = !any_null(ip_desc, src_desc, weights_desc, dst_desc); + if (!args_ok) return invalid_arguments; + + auto id = inner_product_desc_t(); + id.primitive_kind = primitive_kind::inner_product; + id.prop_kind = prop_kind; + + id.diff_src_desc = id.src_desc = zero_md(); + id.diff_dst_desc = id.dst_desc = zero_md(); + id.diff_weights_desc = id.weights_desc = zero_md(); + id.diff_bias_desc = id.bias_desc = zero_md(); + + const bool is_fwd = one_of(prop_kind, forward_training, forward_inference); + const bool with_bias = + bias_desc && bias_desc->format_kind != format_kind::undef; + + (prop_kind == backward_data ? id.diff_src_desc : id.src_desc) = *src_desc; + (is_fwd ? id.dst_desc : id.diff_dst_desc) = *dst_desc; + (prop_kind == backward_weights ? id.diff_weights_desc : id.weights_desc) = + *weights_desc; + if (with_bias) + (prop_kind == backward_weights ? id.diff_bias_desc : id.bias_desc) = + *bias_desc; + + id.accum_data_type = types::default_accum_data_type(src_desc->data_type, + weights_desc->data_type, dst_desc->data_type, prop_kind); + + bool consistency = true + && memory_desc_wrapper(weights_desc).nelems() + && one_of(src_desc->ndims, 2, 3, 4, 5) + && dst_desc->ndims == 2 + && weights_desc->ndims == src_desc->ndims + && (with_bias ? bias_desc->ndims == 1 : true) + && (with_bias ? bias_desc->dims[0] == dst_desc->dims[1] : true) + && src_desc->dims[0] == dst_desc->dims[0] + && array_cmp(&src_desc->dims[1], &weights_desc->dims[1], + src_desc->ndims - 1) + && dst_desc->dims[1] == weights_desc->dims[0]; + if (!consistency) return invalid_arguments; + + *ip_desc = id; + return success; +} +} + +status_t mkldnn_inner_product_forward_desc_init(inner_product_desc_t *ip_desc, + prop_kind_t prop_kind, const memory_desc_t *src_desc, + const memory_desc_t *weights_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_desc) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return ip_desc_init(ip_desc, prop_kind, src_desc, weights_desc, bias_desc, + dst_desc); +} + +status_t mkldnn_inner_product_backward_data_desc_init( + inner_product_desc_t *ip_desc, const memory_desc_t *diff_src_desc, + const memory_desc_t *weights_desc, const memory_desc_t *diff_dst_desc) +{ + return ip_desc_init(ip_desc, backward_data, diff_src_desc, weights_desc, + nullptr, diff_dst_desc); +} + +status_t mkldnn_inner_product_backward_weights_desc_init( + inner_product_desc_t *ip_desc, const memory_desc_t *src_desc, + const memory_desc_t *diff_weights_desc, + const memory_desc_t *diff_bias_desc, + const memory_desc_t *diff_dst_desc) { + return ip_desc_init(ip_desc, backward_weights, src_desc, diff_weights_desc, + diff_bias_desc, diff_dst_desc); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp new file mode 100644 index 0000000000..091cf0f5d6 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp @@ -0,0 +1,56 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "utils.hpp" + +#include "inner_product_pd.hpp" + +namespace mkldnn { +namespace impl { + +using namespace prop_kind; + +memory_desc_t *ip_prop_invariant_src_d(inner_product_desc_t *desc) { + return desc->prop_kind == backward_data + ? &desc->diff_src_desc : &desc->src_desc; +} + +memory_desc_t *ip_prop_invariant_wei_d(inner_product_desc_t *desc) { + return desc->prop_kind == backward_weights + ? &desc->diff_weights_desc : &desc->weights_desc; +} + +memory_desc_t *ip_prop_invariant_bia_d(inner_product_desc_t *desc) { + return desc->prop_kind == backward_weights + ? &desc->diff_bias_desc : &desc->bias_desc; +} + +memory_desc_t *ip_prop_invariant_dst_d(inner_product_desc_t *desc) { + return utils::one_of(desc->prop_kind, forward_inference, forward_training) + ? &desc->dst_desc : &desc->diff_dst_desc; +} + +const memory_desc_t *ip_prop_invariant_src_d(const inner_product_desc_t *desc) +{ return ip_prop_invariant_src_d(const_cast(desc)); } +const memory_desc_t *ip_prop_invariant_wei_d(const inner_product_desc_t *desc) +{ return ip_prop_invariant_wei_d(const_cast(desc)); } +const memory_desc_t *ip_prop_invariant_bia_d(const inner_product_desc_t *desc) +{ return ip_prop_invariant_bia_d(const_cast(desc)); } +const memory_desc_t *ip_prop_invariant_dst_d(const inner_product_desc_t *desc) +{ return ip_prop_invariant_dst_d(const_cast(desc)); } + +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp new file mode 100644 index 0000000000..c426de632c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp @@ -0,0 +1,321 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef INNER_PRODUCT_PD_HPP +#define INNER_PRODUCT_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +memory_desc_t *ip_prop_invariant_src_d(inner_product_desc_t *desc); +memory_desc_t *ip_prop_invariant_wei_d(inner_product_desc_t *desc); +memory_desc_t *ip_prop_invariant_bia_d(inner_product_desc_t *desc); +memory_desc_t *ip_prop_invariant_dst_d(inner_product_desc_t *desc); +const memory_desc_t *ip_prop_invariant_src_d(const inner_product_desc_t *desc); +const memory_desc_t *ip_prop_invariant_wei_d(const inner_product_desc_t *desc); +const memory_desc_t *ip_prop_invariant_bia_d(const inner_product_desc_t *desc); +const memory_desc_t *ip_prop_invariant_dst_d(const inner_product_desc_t *desc); + +struct inner_product_fwd_pd_t; + +struct inner_product_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::inner_product; + + inner_product_pd_t(engine_t *engine, + const inner_product_desc_t *adesc, + const primitive_attr_t *attr, + const inner_product_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + {} + + const inner_product_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::inner_product_d: + *(const inner_product_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common inner_product aux functions */ + + dim_t MB() const { return ip_prop_invariant_src_d(&desc_)->dims[0]; } + dim_t IC() const { return ip_prop_invariant_src_d(&desc_)->dims[1]; } + dim_t OC() const { return ip_prop_invariant_dst_d(&desc_)->dims[1]; } + + dim_t ID() const { + return ndims() >= 5 + ? ip_prop_invariant_src_d(&desc_)->dims[ndims() - 3] : 1; + } + dim_t IH() const { + return ndims() >= 4 + ? ip_prop_invariant_src_d(&desc_)->dims[ndims() - 2] : 1; + } + dim_t IW() const { + return ndims() >= 3 + ? ip_prop_invariant_src_d(&desc_)->dims[ndims() - 1] : 1; + } + + dim_t OD() const { + return ndims() >= 5 + ? ip_prop_invariant_dst_d(&desc_)->dims[ndims() - 3] : 1; + } + dim_t OH() const { + return ndims() >= 4 + ? ip_prop_invariant_dst_d(&desc_)->dims[ndims() - 2] : 1; + } + dim_t OW() const { + return ndims() >= 3 + ? ip_prop_invariant_dst_d(&desc_)->dims[ndims() - 1] : 1; + } + + dim_t KD() const { + return ndims() >= 5 + ? ip_prop_invariant_wei_d(&desc_)->dims[ndims() - 3] : 1; + } + dim_t KH() const { + return ndims() >= 4 + ? ip_prop_invariant_wei_d(&desc_)->dims[ndims() - 2] : 1; + } + dim_t KW() const { + return ndims() >= 3 + ? ip_prop_invariant_wei_d(&desc_)->dims[ndims() - 1] : 1; + } + + dim_t IC_total() const { + return utils::array_product(&ip_prop_invariant_src_d(&desc_)->dims[1], + ndims() - 1); + } + + dim_t IC_total_padded() const { + auto src_d = desc()->prop_kind == prop_kind::backward_data + ? memory_desc_wrapper(diff_src_md()) + : memory_desc_wrapper(src_md()); + assert(src_d.is_blocking_desc()); + if (!src_d.is_blocking_desc()) return -1; + return utils::array_product(src_d.padded_dims() + 1, ndims() - 1); + } + + int ndims() const { return ip_prop_invariant_src_d(&desc_)->ndims; } + + bool with_bias() const + { return !memory_desc_wrapper(*ip_prop_invariant_bia_d(&desc_)).is_zero(); } + + bool has_zero_dim_memory() const { + const auto s_d = memory_desc_wrapper(*ip_prop_invariant_src_d(&desc_)); + const auto d_d = memory_desc_wrapper(*ip_prop_invariant_dst_d(&desc_)); + return s_d.has_zero_dim() || d_d.has_zero_dim(); + } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + +protected: + inner_product_desc_t desc_; + const inner_product_fwd_pd_t *hint_fwd_pd_; + + status_t template_set_default_params(memory_desc_t &src_md, + memory_desc_t &weights_md, memory_desc_t &dst_md, + memory_desc_t *bias_md) { + using namespace format_tag; + if (src_md.format_kind == format_kind::any) { + CHECK(memory_desc_init_by_tag(src_md, + utils::pick(ndims() - 2, nc, ncw, nchw, ncdhw))); + } + if (dst_md.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(dst_md, nc)); + if (weights_md.format_kind == format_kind::any) { + CHECK(memory_desc_init_by_tag(weights_md, + utils::pick(ndims() - 2, oi, oiw, oihw, oidhw))); + } + if (bias_md && bias_md->format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(*bias_md, x)); + return status::success; + } +}; + +struct inner_product_fwd_pd_t: public inner_product_pd_t { + typedef inner_product_fwd_pd_t base_class; + typedef inner_product_fwd_pd_t hint_class; + + inner_product_fwd_pd_t(engine_t *engine, + const inner_product_desc_t *adesc, + const primitive_attr_t *attr, + const inner_product_fwd_pd_t *hint_fwd_pd) + : inner_product_pd_t(engine, adesc, attr, hint_fwd_pd) + , src_md_(desc_.src_desc) + , weights_md_(desc_.weights_desc) + , bias_md_(desc_.bias_desc) + , dst_md_(desc_.dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_WEIGHTS)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_BIAS && with_bias()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &dst_md_ : nullptr; } + virtual const memory_desc_t *weights_md(int index = 0) const override { + if (index == 0) return &weights_md_; + if (index == 1 && with_bias()) return &bias_md_; + return nullptr; + } + + virtual int n_inputs() const override { return 2 + with_bias(); } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t src_md_; + memory_desc_t weights_md_; + memory_desc_t bias_md_; + memory_desc_t dst_md_; + + status_t set_default_params() { + return template_set_default_params(src_md_, weights_md_, dst_md_, + &bias_md_); + } +}; + +struct inner_product_bwd_data_pd_t: public inner_product_pd_t { + typedef inner_product_bwd_data_pd_t base_class; + typedef inner_product_fwd_pd_t hint_class; + + inner_product_bwd_data_pd_t(engine_t *engine, + const inner_product_desc_t *adesc, + const primitive_attr_t *attr, + const inner_product_fwd_pd_t *hint_fwd_pd) + : inner_product_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_src_md_(desc_.diff_src_desc) + , weights_md_(desc_.weights_desc) + , diff_dst_md_(desc_.diff_dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_src_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_dst_md_ : nullptr; } + virtual const memory_desc_t *weights_md(int index = 0) const override + { return index == 0 ? &weights_md_ : nullptr; } + + virtual int n_inputs() const override { return 2; } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t diff_src_md_; + memory_desc_t weights_md_; + memory_desc_t diff_dst_md_; + + status_t set_default_params() { + return template_set_default_params(diff_src_md_, weights_md_, + diff_dst_md_, nullptr); + } +}; + +struct inner_product_bwd_weights_pd_t: public inner_product_pd_t { + typedef inner_product_bwd_weights_pd_t base_class; + typedef inner_product_fwd_pd_t hint_class; + + inner_product_bwd_weights_pd_t(engine_t *engine, + const inner_product_desc_t *adesc, + const primitive_attr_t *attr, + const inner_product_fwd_pd_t *hint_fwd_pd) + : inner_product_pd_t(engine, adesc, attr, hint_fwd_pd) + , src_md_(desc_.src_desc) + , diff_weights_md_(desc_.diff_weights_desc) + , diff_bias_md_(desc_.diff_bias_desc) + , diff_dst_md_(desc_.diff_dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_WEIGHTS) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_DIFF_BIAS && with_bias()) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_dst_md_ : nullptr; } + virtual const memory_desc_t *diff_weights_md(int index = 0) const override { + if (index == 0) return &diff_weights_md_; + if (index == 1 && with_bias()) return &diff_bias_md_; + return nullptr; + } + + virtual int n_inputs() const override { return 2; } + virtual int n_outputs() const override { return 1 + with_bias(); } + +protected: + memory_desc_t src_md_; + memory_desc_t diff_weights_md_; + memory_desc_t diff_bias_md_; + memory_desc_t diff_dst_md_; + + status_t set_default_params() { + return template_set_default_params(src_md_, diff_weights_md_, + diff_dst_md_, &diff_bias_md_); + } +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/lrn.cpp b/thirdparty/oidn/mkl-dnn/src/common/lrn.cpp new file mode 100644 index 0000000000..fcf18b556f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/lrn.cpp @@ -0,0 +1,91 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::alg_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t lrn_desc_init(lrn_desc_t *lrn_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *data_desc, const memory_desc_t *diff_data_desc, + dim_t local_size, float alpha, float beta, float k) { + bool args_ok = true + && !any_null(lrn_desc, data_desc) + && one_of(alg_kind, lrn_within_channel, lrn_across_channels) + && one_of(prop_kind, forward_training, forward_inference, backward_data) + && IMPLICATION(prop_kind == backward_data, diff_data_desc != nullptr); + if (!args_ok) return invalid_arguments; + + auto ld = lrn_desc_t(); + ld.primitive_kind = primitive_kind::lrn; + ld.prop_kind = prop_kind; + ld.alg_kind = alg_kind; + + const bool is_fwd = one_of(prop_kind, forward_training, forward_inference); + + ld.data_desc = *data_desc; + if (!is_fwd) + ld.diff_data_desc = *diff_data_desc; + else + ld.diff_data_desc = zero_md(); + ld.local_size = local_size; + ld.lrn_alpha = alpha; + ld.lrn_beta = beta; + ld.lrn_k = k; + + bool consistency = true + && ld.data_desc.ndims == 4; + if (ld.prop_kind == backward_data) + consistency = consistency + && ld.diff_data_desc.ndims == 4 + && array_cmp(ld.diff_data_desc.dims, ld.data_desc.dims, 4); + if (!consistency) return invalid_arguments; + + *lrn_desc = ld; + return success; +} +} + +status_t mkldnn_lrn_forward_desc_init(lrn_desc_t *lrn_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *data_desc, dim_t local_size, float alpha, + float beta, float k) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return lrn_desc_init(lrn_desc, prop_kind, alg_kind, data_desc, nullptr, + local_size, alpha, beta, k); +} + +status_t mkldnn_lrn_backward_desc_init(lrn_desc_t *lrn_desc, + alg_kind_t alg_kind, const memory_desc_t *data_desc, + const memory_desc_t *diff_data_desc, dim_t local_size, float alpha, + float beta, float k) { + return lrn_desc_init(lrn_desc, backward_data, alg_kind, data_desc, + diff_data_desc, local_size, alpha, beta, k); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp new file mode 100644 index 0000000000..90886e9656 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp @@ -0,0 +1,170 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef LRN_PD_HPP +#define LRN_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" + +namespace mkldnn { +namespace impl { + +struct lrn_fwd_pd_t; + +struct lrn_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::lrn; + + lrn_pd_t(engine_t *engine, + const lrn_desc_t *adesc, + const primitive_attr_t *attr, + const lrn_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + , data_md_(desc_.data_desc) + , ws_md_() + {} + + const lrn_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::lrn_d: + *(const lrn_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common lrn aux functions */ + + dim_t MB() const { return data_desc().dims[0]; } + dim_t C() const { return data_desc().dims[1]; } + dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; } + dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; } + dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; } + + int ndims() const { return data_desc().ndims; } + + bool has_zero_dim_memory() const + { return memory_desc_wrapper(desc_.data_desc).has_zero_dim(); } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + +protected: + lrn_desc_t desc_; + const lrn_fwd_pd_t *hint_fwd_pd_; + + memory_desc_t data_md_; + memory_desc_t ws_md_; + +private: + const memory_desc_t &data_desc() const { return desc_.data_desc; } +}; + +struct lrn_fwd_pd_t: public lrn_pd_t { + typedef lrn_fwd_pd_t base_class; + typedef lrn_fwd_pd_t hint_class; + + lrn_fwd_pd_t(engine_t *engine, + const lrn_desc_t *adesc, + const primitive_attr_t *attr, + const lrn_fwd_pd_t *hint_fwd_pd) + : lrn_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_SRC) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr)) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + virtual const memory_desc_t *workspace_md(int index = 0) const override + { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; } + + virtual int n_inputs() const override { return 1; } + virtual int n_outputs() const override + { return 1 + (workspace_md() != nullptr); } +}; + +struct lrn_bwd_pd_t: public lrn_pd_t { + typedef lrn_bwd_pd_t base_class; + typedef lrn_fwd_pd_t hint_class; + + lrn_bwd_pd_t(engine_t *engine, + const lrn_desc_t *adesc, + const primitive_attr_t *attr, + const lrn_fwd_pd_t *hint_fwd_pd) + : lrn_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_data_md_(desc_.diff_data_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr)) + return arg_usage_t::input; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + virtual const memory_desc_t *workspace_md(int index = 0) const override + { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; } + + virtual int n_inputs() const override + { return 2 + (workspace_md() != nullptr); } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t diff_data_md_; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp b/thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp new file mode 100644 index 0000000000..3fddc0bd45 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp @@ -0,0 +1,280 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MATH_UTILS_HPP +#define MATH_UTILS_HPP + +#include +#include + +#include "utils.hpp" +#include "nstl.hpp" +#include "mkldnn_traits.hpp" + +#if defined(MKLDNN_X86_64) +#include "immintrin.h" +#endif + +namespace mkldnn { +namespace impl { +namespace math { + +/** rounds @p f to an integer according to the mxcsr register */ +inline int mxcsr_round(float f) { +#if defined(MKLDNN_X86_64) + return _mm_cvtss_si32(_mm_load_ss(&f)); +#else + return (int)nearbyintf(f); // optimism +#endif +} + +template +inline typename utils::enable_if::value, + typename utils::remove_reference::type>::type +saturate(const acc_t &x) { + return (typename utils::remove_reference::type)x; +} + +template +inline typename utils::enable_if::value, + typename utils::remove_reference::type>::type +saturate(const acc_t &x) { + acc_t v = x; + if (v < (acc_t)nstl::numeric_limits::lowest()) + v = (acc_t)nstl::numeric_limits::lowest(); + if (v > (acc_t)nstl::numeric_limits::max()) + v = (acc_t)nstl::numeric_limits::max(); + return (typename utils::remove_reference::type)v; +} + +template +double saturate(const double &x) { + double v = x; + if (v < (double)nstl::numeric_limits::lowest()) + v = (double)nstl::numeric_limits::lowest(); + if (v > (double)nstl::numeric_limits::max()) + v = (double)nstl::numeric_limits::max(); + return v; +} + +template <> inline int8_t saturate(const uint8_t &x) { + return x <= 127u ? x : 127; +} + +template <> inline uint8_t saturate(const int8_t &x) { + return x >= 0 ? x : 0; +} + +template +typename utils::enable_if::value, out_t>::type +out_round(float v) { return (out_t)mxcsr_round(v); } + +template +typename utils::enable_if::value, out_t>::type +out_round(double v) { return (out_t)mxcsr_round((float)v); } + +template +typename utils::enable_if::value, out_t>::type +out_round(float v) { return v; } + +inline int gcd(int a, int b) { + a = impl::nstl::abs(a); + b = impl::nstl::abs(b); + if (a < b) { int x = a; a = b; b = x; } + + if (b == 0) return a; + + int r; + while ((r = a % b) != 0) { a = b; b = r; } + + return b; +} + +template +inline bool is_pow2(const T& v) { return (v & (v - 1)) == 0; } + +/** returns floor(log2(v)), aka the position of the leftmost non-0 bit */ +inline int ilog2q(size_t v) { + if (v == 0) + return -1; + + int p = 0; +# define CP(pw) do { if (v >= (1ull << pw)) { v >>= pw; p += pw; } } while(0) + CP(32); CP(16); CP(8); CP(4); CP(2); CP(1); +# undef CP + return p; +} + +template ::type> +inline U one_m_square(T x) { + return (U)(1 - x) * (1 + x); +} + +template ::type> +inline U x_m_square(T x) { + return (U)(1 - x) * x; +} + +/* activation */ +template ::type> +inline U relu_fwd(T s, A alpha) { + return s > 0 ? s : (U)(s * alpha); +} +template ::type> +inline U relu_bwd(T dd, T s, A alpha) { + return s > 0 ? dd : (U)(dd * alpha); +} + +template ::type> +inline U tanh_fwd(T s) { + const float e = tanhf((float) s); + return (U)e; +} + +template ::type> +inline U tanh_bwd(T dd, T s) { + const float e = tanh_fwd((float) s); + return (U)(dd * (1 - e) * (1 + e)); +} + +template ::type> +inline U elu_fwd(T s, A alpha) { + return s > 0 ? s : (U)(alpha * (::expm1f((float)s))); +} +template ::type> + inline U elu_bwd(T dd, T s, A alpha) { + return (U)(dd * (s > 0 ? 1 : alpha * ::expf((float)s))); +} + +template ::type> +inline U square_fwd(T s) { + return s * s; +} + +template ::type> +inline U square_bwd(T dd, T s) { + return dd * 2 * s; +} + +template ::type> +inline U abs_fwd(T s) { + return s > 0 ? s : -s; +} + +template ::type> +inline U abs_bwd(T dd, T s) { + return s > 0 ? dd : s < 0 ? -dd : 0; +} + +template ::type> +inline U sqrt_fwd(T s) { + return s > 0 ? (U)(::sqrtf((float)(s))) : 0; +} + +template ::type> +inline U sqrt_bwd(T dd, T s) { + return s > 0 + ? (U)(dd / (2 * ::sqrtf((float)(s)))) + : 0; +} + +template ::type> +inline U linear_fwd(T s, A alpha, A beta) { + return (U)(alpha * s + beta); +} + +template ::type> +inline U linear_bwd(T dd, T s, A alpha, A beta) { + (void) s; + (void) beta; + return (U)(dd * alpha); +} + +template ::type> +inline U bounded_relu_fwd(T s, A alpha) { + s = s > 0 ? s : 0; + return s > alpha ? (U)(alpha) : s; +} + +template ::type> +inline U bounded_relu_bwd(T dd, T s, A alpha) { + return dd * (0 < s && s < alpha ? 1 : 0); +} + +template ::type> +inline U soft_relu_fwd(T s) { + float max_logf = 8.872284e+01; //::logf(FLT_MAX) + return s < max_logf ? (U)(::log1pf(::expf((float)s))) : s; +} + +template ::type> +inline U soft_relu_bwd(T dd, T s) { + return (U)(dd / (1 + ::expf((float)(-s)))); +} + +template ::type> +inline U logistic_fwd(T s) { + U v = (U)(::expf((float) -s)); + return 1 / (1 + v); +} + +template ::type> +inline U logistic_bwd(T dd, T s) { + U v = logistic_fwd(s); + return dd * v * (1 - v); +} + +inline bool eltwise_fwd_preserves_zero(alg_kind_t alg, bool jit_impl = false) { + using namespace alg_kind; + using namespace utils; + const bool preserves_zero = true + && !one_of(alg, eltwise_linear, eltwise_soft_relu, eltwise_logistic) + && IMPLICATION(jit_impl, !one_of(alg, eltwise_elu, eltwise_tanh)); + return preserves_zero; +} + +inline float get_bias(const char *bias, size_t offset, data_type_t data_type) +{ + if (!bias) + return 0.0f; + +#define CASE(dt) \ + case dt: return (float)((const prec_traits
::type *)bias)[offset] + + switch (data_type) { + CASE(data_type::s8); + CASE(data_type::u8); + CASE(data_type::s32); + CASE(data_type::f32); + default: assert(!"unimplemented"); + } + return 0; // never happens (should probably be a NaN) +#undef CASE +} + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory.cpp b/thirdparty/oidn/mkl-dnn/src/common/memory.cpp new file mode 100644 index 0000000000..cea849c96e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/memory.cpp @@ -0,0 +1,238 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::data_type; + +namespace { +bool memory_desc_sanity_check(int ndims,const dims_t dims, + data_type_t data_type, format_kind_t format_kind) { + if (ndims == 0) return true; + + bool ok = true + && dims != nullptr + && 0 < ndims && ndims <= MKLDNN_MAX_NDIMS + && one_of(data_type, f32, s32, s8, u8) + && format_kind != format_kind::undef; + if (!ok) return false; + for (int d = 0; d < ndims; ++d) + if (dims[d] < 0) return false; + + return true; +} + +bool memory_desc_sanity_check(const memory_desc_t *md) { + if (md == nullptr) return false; + return memory_desc_sanity_check(md->ndims, md->dims, md->data_type, + format_kind::any); +} +} + +status_t mkldnn_memory_desc_init_by_tag(memory_desc_t *memory_desc, int ndims, + const dims_t dims, data_type_t data_type, format_tag_t tag) { + if (any_null(memory_desc)) return invalid_arguments; + if (ndims == 0 || tag == format_tag::undef) { + *memory_desc = types::zero_md(); + return success; + } + + format_kind_t format_kind = types::format_tag_to_kind(tag); + + /* memory_desc != 0 */ + bool args_ok = !any_null(memory_desc) + && memory_desc_sanity_check(ndims, dims, data_type, format_kind); + if (!args_ok) return invalid_arguments; + + auto md = memory_desc_t(); + md.ndims = ndims; + array_copy(md.dims, dims, ndims); + md.data_type = data_type; + array_copy(md.padded_dims, dims, ndims); + md.format_kind = format_kind; + + status_t status = success; + if (tag == format_tag::undef) { + status = invalid_arguments; + } else if (tag == format_tag::any) { + // nop + } else if (format_kind == format_kind::blocked) { + status = memory_desc_wrapper::compute_blocking(md, tag); + } else { + assert(!"unreachable"); + status = invalid_arguments; + } + + if (status == success) + *memory_desc = md; + + return status; +} + +status_t mkldnn_memory_desc_init_by_strides(memory_desc_t *memory_desc, + int ndims, const dims_t dims, data_type_t data_type, + const dims_t strides) { + if (any_null(memory_desc)) return invalid_arguments; + if (ndims == 0) { + *memory_desc = types::zero_md(); + return success; + } + + /* memory_desc != 0 */ + bool args_ok = !any_null(memory_desc) + && memory_desc_sanity_check(ndims, dims, data_type, format_kind::any); + if (!args_ok) return invalid_arguments; + + auto md = memory_desc_t(); + md.ndims = ndims; + array_copy(md.dims, dims, ndims); + md.data_type = data_type; + array_copy(md.padded_dims, dims, ndims); + md.format_kind = format_kind::blocked; + + dims_t default_strides = {0}; + if (strides == nullptr) { + default_strides[md.ndims - 1] = 1; + for (int d = md.ndims - 2; d >= 0; --d) + default_strides[d] = default_strides[d + 1] * md.padded_dims[d + 1]; + strides = default_strides; + } else { + /* TODO: add sanity check for the provided strides */ + } + + array_copy(md.format_desc.blocking.strides, strides, md.ndims); + + *memory_desc = md; + + return status::success; +} + +status_t mkldnn_memory_desc_init_submemory(memory_desc_t *md, + const memory_desc_t *parent_md, const dims_t dims, + const dims_t offsets) { + if (any_null(md, parent_md) || !memory_desc_sanity_check(parent_md)) + return invalid_arguments; + + const memory_desc_wrapper src_d(parent_md); + + for (int d = 0; d < src_d.ndims(); ++d) { + if (dims[d] < 0 || offsets[d] < 0 + || (offsets[d] + dims[d] > src_d.dims()[d])) + return invalid_arguments; + } + + if (src_d.format_kind() != format_kind::blocked) + return unimplemented; + + dims_t blocks; + src_d.compute_blocks(blocks); + + memory_desc_t dst_d = *parent_md; + auto &dst_d_blk = dst_d.format_desc.blocking; + + /* TODO: put this into memory_desc_wrapper */ + for (int d = 0; d < src_d.ndims(); ++d) { + /* very limited functionality for now */ + const bool ok = true + && offsets[d] % blocks[d] == 0 /* [r1] */ + && src_d.padded_offsets()[d] == 0 + && (false + || dims[d] % blocks[d] == 0 + || dims[d] < blocks[d]); + if (!ok) + return unimplemented; + + const bool is_right_border = offsets[d] + dims[d] == src_d.dims()[d]; + + dst_d.dims[d] = dims[d]; + dst_d.padded_dims[d] = is_right_border + ? src_d.padded_dims()[d] - offsets[d] : dst_d.dims[d]; + dst_d.padded_offsets[d] = src_d.padded_offsets()[d]; + dst_d.offset0 += /* [r1] */ + offsets[d] / blocks[d] * dst_d_blk.strides[d]; + } + + *md = dst_d; + + return success; +} + +int mkldnn_memory_desc_equal(const memory_desc_t *lhs, + const memory_desc_t *rhs) { + if (lhs == rhs) return 1; + if (any_null(lhs, rhs)) return 0; + return memory_desc_wrapper(*lhs) == memory_desc_wrapper(*rhs); +} + +size_t mkldnn_memory_desc_get_size(const memory_desc_t *md) { + if (md == nullptr) return 0; + return memory_desc_wrapper(*md).size(); +} + +status_t mkldnn_memory_create(memory_t **memory, const memory_desc_t *md, + engine_t *engine, void *handle) { + if (any_null(memory, engine)) return invalid_arguments; + memory_desc_t z_md = types::zero_md(); + return engine->memory_create(memory, md ? md : &z_md, handle); +} + +status_t mkldnn_memory_get_memory_desc(const memory_t *memory, + const memory_desc_t **md) { + if (any_null(memory, md)) return invalid_arguments; + *md = memory->md(); + return success; +} + +status_t mkldnn_memory_get_engine(const memory_t *memory, engine_t **engine) { + if (any_null(memory, engine)) return invalid_arguments; + *engine = memory->engine(); + return success; +} + +status_t mkldnn_memory_get_data_handle(const memory_t *memory, + void **handle) { + if (any_null(handle)) + return invalid_arguments; + if (memory == nullptr) { + *handle = nullptr; + return success; + } + return memory->get_data_handle(handle); +} + +status_t mkldnn_memory_set_data_handle(memory_t *memory, void *handle) { + if (any_null(memory)) return invalid_arguments; + return memory->set_data_handle(handle); +} + +status_t mkldnn_memory_destroy(memory_t *memory) { + delete memory; + return success; +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory.hpp b/thirdparty/oidn/mkl-dnn/src/common/memory.hpp new file mode 100644 index 0000000000..03dfee01ff --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/memory.hpp @@ -0,0 +1,63 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MEMORY_HPP +#define MEMORY_HPP + +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "nstl.hpp" + +struct mkldnn_memory: public mkldnn::impl::c_compatible { + mkldnn_memory(mkldnn::impl::engine_t *engine, + const mkldnn::impl::memory_desc_t *md) + : engine_(engine), md_(*md) {} + virtual ~mkldnn_memory() {} + + /** allocates/initializes memory */ + virtual mkldnn::impl::status_t init() = 0; + + /** returns memory's engine */ + mkldnn::impl::engine_t *engine() const { return engine_; } + /** returns memory's description */ + const mkldnn::impl::memory_desc_t *md() const { return &md_; } + + /** returns data handle */ + virtual mkldnn::impl::status_t get_data_handle(void **handle) const = 0; + + /** sets data handle */ + virtual mkldnn::impl::status_t set_data_handle(void *handle) = 0; + + /** zeros padding */ + virtual mkldnn::impl::status_t zero_pad() const + { return mkldnn::impl::status::success; } + +protected: + mkldnn::impl::engine_t *engine_; + const mkldnn::impl::memory_desc_t md_; + +private: + mkldnn_memory() = delete; + mkldnn_memory(const mkldnn_memory &) = delete; + mkldnn_memory(mkldnn_memory &&) = delete; + mkldnn_memory &operator=(const mkldnn_memory &) = delete; + mkldnn_memory &operator=(mkldnn_memory &&) = delete; +}; + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp new file mode 100644 index 0000000000..8a99be33f3 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp @@ -0,0 +1,212 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include + +#include "c_types_map.hpp" +#include "memory_desc_wrapper.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +status_t fill_blocked(memory_desc_t &md, + std::initializer_list perm, + std::initializer_list inner_blks, + std::initializer_list inner_idxs) { + const bool ok = true + && perm.size() == (size_t)md.ndims + && inner_blks.size() == inner_idxs.size(); + if (!ok) return status::invalid_arguments; + + md.offset0 = 0; + + blocking_desc_t &blk = md.format_desc.blocking; + + dim_t block_size = 1; + dims_t blocks = {0}; + utils::array_set(blocks, 1, md.ndims); + + blk.inner_nblks = (int)inner_blks.size(); + + int iblk = 0; + for (const auto &b: inner_idxs) + blk.inner_idxs[iblk++] = b; + + iblk = 0; + for (const auto &b: inner_blks) { + int dim = blk.inner_idxs[iblk]; + block_size *= b; + blocks[dim] *= b; + blk.inner_blks[iblk++] = b; + } + + utils::array_set(md.padded_offsets, 0, md.ndims); + for (int d = 0; d < md.ndims; ++d) + md.padded_dims[d] = utils::rnd_up(md.dims[d], blocks[d]); + + dim_t stride = block_size; + // if only we use C++14, the initializer_list would have rbegin()/rend()... + for (int d = 0; d < md.ndims; ++d) + stride *= md.padded_dims[d] == 0 ? 1 : md.padded_dims[d] / blocks[d]; + + for (const auto &d: perm) { + if (md.padded_dims[d] == 0) { + blk.strides[d] = 1; + continue; + } + stride /= md.padded_dims[d] / blocks[d]; + blk.strides[d] = stride; + } + + assert(stride == block_size); + + return status::success; +} + +status_t memory_desc_wrapper::compute_blocking(memory_desc_t &memory_desc, + format_tag_t tag) +{ + using namespace format_tag; + + if (memory_desc.ndims == 0) return status::invalid_arguments; + +# define C(tag, ... /* perm, inner_blks, inner_idxs */) \ + case tag: return fill_blocked(memory_desc, __VA_ARGS__) + + switch (tag) { + C(a, {0}, {}, {}); + C(ab, {0, 1}, {}, {}); + C(abc, {0, 1, 2}, {}, {}); + C(abcd, {0, 1, 2, 3}, {}, {}); + C(abcde, {0, 1, 2, 3, 4}, {}, {}); + C(abcdef, {0, 1, 2, 3, 4, 5}, {}, {}); + C(abdec, {0, 1, 3, 4, 2}, {}, {}); + C(acb, {0, 2, 1}, {}, {}); + C(acbde, {0, 2, 1, 3, 4}, {}, {}); + C(acdb, {0, 2, 3, 1}, {}, {}); + C(acdeb, {0, 2, 3, 4, 1}, {}, {}); + C(ba, {1, 0}, {}, {}); + C(bac, {1, 0, 2}, {}, {}); + C(bacd, {1, 0, 2, 3}, {}, {}); + C(bcda, {1, 2, 3, 0}, {}, {}); + C(cba, {2, 1, 0}, {}, {}); + C(cdba, {2, 3, 1, 0}, {}, {}); + C(cdeba, {2, 3, 4, 1, 0}, {}, {}); + C(decab, {3, 4, 2, 0, 1}, {}, {}); + + C(Abc4a, {0, 1, 2}, {4}, {0}); + C(aBc4b, {0, 1, 2}, {4}, {1}); + C(ABc4b16a4b, {0, 1, 2}, {4, 16, 4}, {1, 0, 1}); + C(ABc4b4a, {0, 1, 2}, {4, 4}, {1, 0}); + C(Abcd4a, {0, 1, 2, 3}, {4}, {0}); + C(aBcd4b, {0, 1, 2, 3}, {4}, {1}); + C(ABcd4b4a, {0, 1, 2, 3}, {4, 4}, {1, 0}); + C(aBCd4c16b4c, {0, 1, 2, 3}, {4, 16, 4}, {2, 1, 2}); + C(aBCd4c4b, {0, 1, 2, 3, 4}, {4, 4}, {2, 1}); + C(Abcde4a, {0, 1, 2, 3, 4}, {4}, {0}); + C(aBcde4b, {0, 1, 2, 3, 4}, {4}, {1}); + C(ABcde4b4a, {0, 1, 2, 3, 4}, {4, 4}, {1, 0}); + C(aBCde4c4b, {0, 1, 2, 3, 4}, {4, 4}, {2, 1}); + C(aBcdef4b, {0, 1, 2, 3, 4, 5}, {4}, {1}); + C(aBCdef4c4b, {0, 1, 2, 3, 4, 5}, {4, 4}, {2, 1}); + C(aBdc4b, {0, 1, 3, 2}, {4}, {1}); + C(aBdec4b, {0, 1, 3, 4, 2}, {4}, {1}); + C(aBdefc4b, {0, 1, 3, 4, 5, 2}, {4}, {1}); + C(Acb4a, {0, 2, 1}, {4}, {0}); + C(Acdb4a, {0, 2, 3, 1}, {4}, {0}); + C(Acdeb4a, {0, 2, 3, 4, 1}, {4}, {0}); + + C(Abc16a, {0, 1, 2}, {16}, {0}); + C(ABc16a16b, {0, 1, 2}, {16, 16}, {0, 1}); + C(aBc16b, {0, 1, 2}, {16}, {1}); + C(ABc16b16a, {0, 1, 2}, {16, 16}, {1, 0}); + C(ABc8a16b2a, {0, 1, 2}, {8, 16, 2}, {0, 1, 0}); + C(ABc8a8b, {0, 1, 2}, {8, 8}, {0, 1}); + C(aBc8b, {0, 1, 2}, {8}, {1}); + C(ABc8b16a2b, {0, 1, 2}, {8, 16, 2}, {1, 0, 1}); + C(ABc8b8a, {0, 1, 2}, {8, 8}, {1, 0}); + C(Abcd16a, {0, 1, 2, 3}, {16}, {0}); + C(ABcd16a16b, {0, 1, 2, 3}, {16, 16}, {0, 1}); + C(aBcd16b, {0, 1, 2, 3}, {16}, {1}); + C(ABcd16b16a, {0, 1, 2, 3}, {16, 16}, {1, 0}); + C(aBCd16b16c, {0, 1, 2, 3}, {16, 16}, {1, 2}); + C(aBCd16c16b, {0, 1, 2, 3}, {16, 16}, {2, 1}); + C(ABcd4b16a4b, {0, 1, 2, 3}, {4, 16, 4}, {1, 0, 1}); + C(ABcd8a16b2a, {0, 1, 2, 3}, {8, 16, 2}, {0, 1, 0}); + C(ABcd8a8b, {0, 1, 2, 3}, {8, 8}, {0, 1}); + C(aBcd8b, {0, 1, 2, 3}, {8}, {1}); + C(ABcd8b16a2b, {0, 1, 2, 3}, {8, 16, 2}, {1, 0, 1}); + C(aBCd8b16c2b, {0, 1, 2, 3}, {8, 16, 2}, {1, 2, 1}); + C(ABcd8b8a, {0, 1, 2, 3}, {8, 8}, {1, 0}); + C(aBCd8b8c, {0, 1, 2, 3}, {8, 8}, {1, 2}); + C(aBCd8c16b2c, {0, 1, 2, 3}, {8, 16, 2}, {2, 1, 2}); + C(aBCd8c8b, {0, 1, 2, 3}, {8, 8}, {2, 1}); + C(Abcde16a, {0, 1, 2, 3, 4}, {16}, {0}); + C(ABcde16a16b, {0, 1, 2, 3, 4}, {16, 16}, {0, 1}); + C(aBcde16b, {0, 1, 2, 3, 4}, {16}, {1}); + C(ABcde16b16a, {0, 1, 2, 3, 4}, {16, 16}, {1, 0}); + C(aBCde16b16c, {0, 1, 2, 3, 4}, {16, 16}, {1, 2}); + C(aBCde16c16b, {0, 1, 2, 3, 4}, {16, 16}, {2, 1}); + C(aBCde2c8b4c, {0, 1, 2, 3, 4}, {2, 8, 4}, {2, 1, 2}); + C(aBCde4b4c, {0, 1, 2, 3, 4}, {4, 4}, {1, 2}); + C(aBCde4c16b4c, {0, 1, 2, 3, 4}, {4, 16, 4}, {2, 1, 2}); + C(Abcde8a, {0, 1, 2, 3, 4}, {8}, {0}); + C(ABcde8a8b, {0, 1, 2, 3, 4}, {8, 8}, {0, 1}); + C(aBcde8b, {0, 1, 2, 3, 4}, {8}, {1}); + C(ABcde8b16a2b, {0, 1, 2, 3, 4}, {8, 16, 2}, {1, 0, 1}); + C(aBCde8b16c2b, {0, 1, 2, 3, 4}, {8, 16, 2}, {1, 2, 1}); + C(ABcde8b8a, {0, 1, 2, 3, 4}, {8, 8}, {1, 0}); + C(aBCde8b8c, {0, 1, 2, 3, 4}, {8, 8}, {1, 2}); + C(aBCde8c16b2c, {0, 1, 2, 3, 4}, {8, 16, 2}, {2, 1, 2}); + C(aBCde8c8b, {0, 1, 2, 3, 4}, {8, 8}, {2, 1}); + C(aBcdef16b, {0, 1, 2, 3, 4, 5}, {16}, {1}); + C(aBCdef16b16c, {0, 1, 2, 3, 4, 5}, {16, 16}, {1, 2}); + C(aBCdef16c16b, {0, 1, 2, 3, 4, 5}, {16, 16}, {2, 1}); + C(aBCdef8b8c, {0, 1, 2, 3, 4, 5}, {8, 8}, {1, 2}); + C(aBCdef8c16b2c, {0, 1, 2, 3, 4, 5}, {8, 16, 2}, {2, 1, 2}); + C(aBCdef8c8b, {0, 1, 2, 3, 4, 5}, {8, 8}, {2, 1}); + C(aBdc16b, {0, 1, 3, 2}, {16}, {1}); + C(aBdc8b, {0, 1, 3, 2}, {8}, {1}); + C(aBdec16b, {0, 1, 3, 4, 2}, {16}, {1}); + C(aBdec8b, {0, 1, 3, 4, 2}, {8}, {1}); + C(aBdefc16b, {0, 1, 3, 4, 5, 2}, {16}, {1}); + C(aBdefc8b, {0, 1, 3, 4, 5, 2}, {8}, {1}); + C(Acb16a, {0, 2, 1}, {16}, {0}); + C(Acb8a, {0, 2, 1}, {8}, {0}); + C(aCBd16b16c, {0, 2, 1, 3}, {16, 16}, {1, 2}); + C(aCBde16b16c, {0, 2, 1, 3, 4}, {16, 16}, {1, 2}); + C(Acdb16a, {0, 2, 3, 1}, {16}, {0}); + C(Acdb8a, {0, 2, 3, 1}, {8}, {0}); + C(Acdeb16a, {0, 2, 3, 4, 1}, {16}, {0}); + C(Acdeb8a, {0, 2, 3, 4, 1}, {8}, {0}); + C(BAc16a16b, {1, 0, 2}, {16, 16}, {0, 1}); + C(BAcd16a16b, {1, 0, 2, 3}, {16, 16}, {0, 1}); + default: break; + } + +#undef C + + return status::invalid_arguments; +} + +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp new file mode 100644 index 0000000000..1758f9078a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp @@ -0,0 +1,400 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MEMORY_DESC_WRAPPER_HPP +#define MEMORY_DESC_WRAPPER_HPP + +#include + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "utils.hpp" + +#include "type_helpers.hpp" + +namespace mkldnn { +namespace impl { + +/** thin wrapper class over \struct memory_desc_t which allows easy + * manipulations with underlying C structure, which is taken by reference */ +struct memory_desc_wrapper: public c_compatible { + const memory_desc_t *md_; + + /** constructor which takes a reference to a constant underlying C memory + * descriptor \param md */ + memory_desc_wrapper(const memory_desc_t *md): md_(md) {} + memory_desc_wrapper(const memory_desc_t &md): memory_desc_wrapper(&md) {} + + /* implementing attributes */ + int ndims() const { return md_->ndims; } + const dims_t &dims() const { return md_->dims; } + data_type_t data_type() const { return md_->data_type; } + + const dims_t &padded_dims() const { return md_->padded_dims; } + const dims_t &padded_offsets() const { return md_->padded_offsets; } + dim_t offset0() const { return md_->offset0; } + + format_kind_t format_kind() const { return md_->format_kind; } + + bool is_blocking_desc() const + { return format_kind() == format_kind::blocked; } + bool is_wino_desc() const + { return format_kind() == format_kind::wino; } + bool is_rnn_packed_desc() const + { return format_kind() == format_kind::rnn_packed; } + + const blocking_desc_t &blocking_desc() const { + assert(is_blocking_desc()); + return md_->format_desc.blocking; + } + const wino_desc_t &wino_desc() const { + assert(is_wino_desc()); + return md_->format_desc.wino_desc; + } + const rnn_packed_desc_t &rnn_packed_desc() const { + assert(is_rnn_packed_desc()); + return md_->format_desc.rnn_packed_desc; + } + + const memory_extra_desc_t &extra() const { return md_->extra; } + + /* some useful function */ + + /** returns the number of elements including padding if \param with_padding + * is true, and the number of data elements otherwise */ + dim_t nelems(bool with_padding = false) const { + if (is_zero()) return 0; + return utils::array_product( + with_padding ? padded_dims() : dims(), ndims()); + } + + /** returns true if memory descriptor is zero */ + bool is_zero() const { return ndims() == 0; } + + /** returns true if memory descriptor contains zero as one of its dim */ + bool has_zero_dim() const { return nelems() == 0; } + + /** return the size of data type (a shortcut) */ + size_t data_type_size() const + { return types::data_type_size(data_type()); } + + /** return the size of data type of additional buffer */ + size_t additional_buffer_data_size() const { + if (extra().flags & memory_extra_flags::compensation_conv_s8s8) + return sizeof(int32_t); + return 0; + } + + /** return true if memory format has additional buffer */ + bool is_additional_buffer() const { + return (extra().flags & memory_extra_flags::compensation_conv_s8s8); + } + + /** returns the size of additional buffer */ + size_t additional_buffer_size() const { + if (extra().flags & memory_extra_flags::compensation_conv_s8s8) { + int cmask = extra().compensation_mask; + assert(cmask == 1 || cmask == 3); + dim_t prod = 1; + for (int d = 0; d < ndims(); ++d) + if (cmask & (1<(max_size, + padded_dims()[d] / blocks[d] * bd.strides[d]); + + if (max_size == 1 && bd.inner_nblks != 0) { + max_size = utils::array_product(bd.inner_blks, bd.inner_nblks); + } + + return max_size * data_type_size() + additional_buffer_size(); + } + } + + /** returns true if data is dense in memory */ + bool is_dense(bool with_padding = false) const { + if (utils::one_of(format_kind(), format_kind::undef, format_kind::any)) + return false; + return nelems(with_padding) * data_type_size() == size(); + } + + /** returns true if memory desc is fully defined */ + bool is_defined() const { return format_kind() != format_kind::any; } + + /** returns true if the only (potentially) padded dim is \param dim */ + bool only_padded_dim(int dim) const { + for (int d = 0; d < ndims(); ++d) + if (d != dim && dims()[d] != padded_dims()[d]) + return false; + return true; + } + + /** returns true if memory desc has blocked layout and block dims are 1s */ + bool is_plain() const { + if (!is_blocking_desc()) return false; + return blocking_desc().inner_nblks == 0; + } + + /** returns overall block sizes */ + void compute_blocks(dims_t blocks) const { + if (!is_blocking_desc()) { + utils::array_set(blocks, 0, ndims()); + return; + } + + utils::array_set(blocks, 1, ndims()); + + const auto &bd = blocking_desc(); + for (int iblk = 0; iblk < bd.inner_nblks; ++iblk) + blocks[bd.inner_idxs[iblk]] *= bd.inner_blks[iblk]; + } + + /* comparison section */ + + bool operator==(const memory_desc_wrapper &rhs) const + { return *this->md_ == *rhs.md_; } + bool operator!=(const memory_desc_wrapper &rhs) const + { return !operator==(rhs); } + bool operator==(const memory_desc_t &rhs) const + { return operator==(memory_desc_wrapper(rhs)); } + bool operator!=(const memory_desc_t &rhs) const + { return !operator==(rhs); } + + /** returns true if data (w/o padding if with_padding == false and w/ + * padding otherwise) have the same physical structure, i.e. dimensions, + * strides, and blocked structure. Depending on with_data_type flag + * data_type is taken or not taken into account. dim_start allows to check + * similarity for the logical part of data [dim_start .. ndims()]. + * CAUTION: format kind any and undef are not similar to whatever, hence the + * following statement might be true: lhs == rhs && !lhs.similar_to(rhs) */ + /* TODO: revise */ + bool similar_to(const memory_desc_wrapper &rhs, + bool with_padding = true, bool with_data_type = true, + int dim_start = 0) const; + + /** returns true if one memory can be reordered to another */ + bool consistent_with(const memory_desc_wrapper &rhs) const; + + /** returns true if the memory desc corresponds to the given format tag and + * strides. + * @sa memory_desc_matches_tag */ + bool matches_tag(format_tag_t tag, const dims_t strides = nullptr) const { + return memory_desc_matches_tag(*md_, tag, strides); + } + + /** returns matching tag (or undef if match is not found) + * XXX: This is a workaround that eventually should go away! */ + template + format_tag_t matches_one_of_tag(Tags ...tags) const { + for (const auto tag: {tags...}) { + if (memory_desc_matches_tag(*md_, tag)) + return tag; + } + return format_tag::undef; + } + + /* offset section */ + + /** returns physical offset by logical one. logical offset is represented by + * an array \param pos. if \param is_pos_padded is true \param pos + * represents the position in already padded area */ + dim_t off_v(const dims_t pos, bool is_pos_padded = false) const { + assert(is_blocking_desc()); + const blocking_desc_t &blk = blocking_desc(); + + dims_t pos_copy = {0}; + for (int d = 0; d < ndims(); ++d) + pos_copy[d] = pos[d] + (is_pos_padded ? 0 : padded_offsets()[d]); + + dim_t phys_offset = offset0(); + + if (blk.inner_nblks > 0) { + dim_t blk_stride = 1; + for (int iblk = blk.inner_nblks - 1; iblk >= 0; --iblk) { + const int d = blk.inner_idxs[iblk]; + const dim_t p = pos_copy[d] % blk.inner_blks[iblk]; + + phys_offset += p * blk_stride; + + pos_copy[d] /= blk.inner_blks[iblk]; + + blk_stride *= blk.inner_blks[iblk]; + } + } + + for (int d = 0; d < ndims(); ++d) { + const dim_t p = pos_copy[d]; + phys_offset += p * blk.strides[d]; + } + + return phys_offset; + } + + /** returns physical offset by logical one. logical offset is represented by + * a scalar \param l_offset. if \param is_pos_padded is true, \param + * l_offset represents logical offset in already padded area */ + dim_t off_l(dim_t l_offset, bool is_pos_padded = false) const { + assert(is_blocking_desc()); + dims_t pos; + for (int rd = 0; rd < ndims(); ++rd) { + const int d = ndims() - 1 - rd; + const dim_t cur_dim = is_pos_padded ? padded_dims()[d] : dims()[d]; + pos[d] = l_offset % cur_dim; + l_offset /= cur_dim; + } + return off_v(pos, is_pos_padded); + } + + /** returns physical offset by logical one. logical offset is represented by + * a tuple of indices (\param xn, ..., \param x1, \param x0) */ + template + dim_t off(Args... args) const { + assert(sizeof...(args) == ndims()); + dims_t pos = { args... }; + return off_v(pos, false); + } + + /** returns physical offset by logical one. logical offset is represented by + * a tuple of indices (\param xn, ..., \param x1, \param x0) in already + * padded area */ + template + dim_t off_padding(Args... args) const { + assert(sizeof...(args) == ndims()); + dims_t pos = { args... }; + return off_v(pos, true); + } + + /** returns physical offset by logical one. Logical offset is represented by + * a tuple of block indices (\param bn, ..., \param b1, \param b0). It is a + * user responsibility to adjust the result to get offset within blocks */ + template + dim_t blk_off(Args... args) const { + return _blk_off(args...); + } + + template + dim_t blk_off(T xn, Args... args) const { + return skip_first + ? blk_off(args...) + : blk_off(xn, args...); + } + + /* static functions section */ + /* TODO: replace with non-static, once md_ becomes non-const ref */ + + static status_t compute_blocking(memory_desc_t &memory_desc, + format_tag_t tag); + +private: + /* TODO: put logical_offset in utils */ + template + dim_t logical_offset(T x0) const { return x0; } + + template + dim_t logical_offset(T xn, Args... args) const { + const size_t n_args = sizeof...(args); + return xn * utils::array_product( + &dims()[ndims() - n_args]) + logical_offset(args...); + } + + template + dim_t _blk_off() const { return offset0(); } + + template + dim_t _blk_off(T xc, Args ...args) const { + assert(is_blocking_desc()); + constexpr int dc = ORIG_LEN - sizeof...(args) - 1; + return xc * blocking_desc().strides[dc] + + _blk_off(args...); + } +}; + +inline bool memory_desc_wrapper::similar_to(const memory_desc_wrapper &rhs, + bool with_padding, bool with_data_type, int dim_start) const { + using namespace utils; + + if (one_of(format_kind(), format_kind::undef, format_kind::any)) + return false; + if (is_wino_desc() || is_rnn_packed_desc()) + return false; + + const int ds = dim_start; + const auto &blk = blocking_desc(); + const auto &r_blk = rhs.blocking_desc(); + + return ndims() == rhs.ndims() + && dim_start <= ndims() /* guard */ + && format_kind() == rhs.format_kind() + && IMPLICATION(with_data_type, data_type() == rhs.data_type()) + && array_cmp(dims() + ds, rhs.dims() + ds, ndims() - ds) + && array_cmp(blk.strides + ds, r_blk.strides + ds, ndims() - ds) + && blk.inner_nblks == r_blk.inner_nblks + && array_cmp(blk.inner_blks, r_blk.inner_blks, blk.inner_nblks) + && array_cmp(blk.inner_idxs, r_blk.inner_idxs, blk.inner_nblks) + && IMPLICATION(with_padding, true + && array_cmp(padded_dims() + ds, rhs.padded_dims() + ds, + ndims() - ds) + && array_cmp(padded_offsets() + ds, rhs.padded_offsets() + ds, + ndims() - ds)); +} + +inline bool memory_desc_wrapper::consistent_with( + const memory_desc_wrapper &rhs) const { + if (ndims() == rhs.ndims()) { + for (int d = 0; d < ndims(); ++d) { + if (dims()[d] != rhs.dims()[d]) return false; + } + return true; + } else { + /* TODO: revise. + * is the following possible? + * [1, a, b] <--reorder--> [a, b] + * [a, 1, b] <--reorder--> [a, b] + * not, at least for now */ + return false; + } +} + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp b/thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp new file mode 100644 index 0000000000..ec077b308c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp @@ -0,0 +1,295 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MEMORY_TRACKING_HPP +#define MEMORY_TRACKING_HPP + +#include +#include + +#include "nstl.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace memory_tracking { + +/* Memory tracking capabilities + * + * The main purpose of this header file is to provide uniform way to register + * required memory for a scratchpad at a primitive descriptor creation time + * and then easily access it having only the base address of the scratchpad. + * + * Primitives might contain multiple disjoint parts that require temporary + * buffers (known as scratchpad) during their execution. A primitive descriptor + * should summarize all the needs into one single number -- the buffer size + * that would be requested from a user. At execution time, the corresponding + * primitive will receive a base pointer to a scratchpad. It then needs to + * provide each part of algorithm the corresponding piece of memory. Three main + * challenges here are: + * 1. Track correct offset (from the base scratchpad address) for each piece + * 2. Algorithm might require that different memory pieces to be aligned, so + * the scratchpad size is no more just a sum of size of the corresponding + * subparts. + * 3. While a primitive is responsible for its scratchpad, the implementation + * might use some other basic blocks (e.g. cpu_reducer) that also require + * scratchpad memory. So there should be a simple way of passing the + * information back and force between the main algorithm (a primitive) and + * auxiliary stuff that lives completely separately from it (e.g. reducer). + * + * To address these challenges this header file provides 3 structures: + * 1. registry_t -- the class the stores the information about requested + * memory. The information includes required size and desired + * alignment for each piece. This class is also responsible + * for computing the right offset to a given piece using the + * base pointer. + * This class is basically a ledger with all entries. + * Lives in primitive descriptors. + * + * 2. registrar_t -- the interface to a registry_t to book memory. Used at + * primitive descriptor creation time only. Contains a + * reference to the corresponding *mutable* registry. + * Always modifiable. + * Allows chaining (using prefixes). + * + * 3. grantor_t -- the interface to a registry_t to access memory. Used at + * primitive execution time only. Contains a reference to + * the corresponding *constant* registry and base pointer. + * Always constant. + * Allows chaining (using prefixes). + * + * Both registrar_t and grantor_t allow chaining with extra prefix provided. + * The feature is useful when a primitive offload a part of computations to + * some other primitives which require their own scratchpad space + * (e.g. reducer). Prefixes are used to avoid key collision in cases when + * multiple sub-primitive (e.g. multiple reducers) are used. + * + * A short example below demonstrates how to use aforementioned classes. In it + * the main primitive is convolution that uses scratchpad for keeping padded + * bias. It also needs a reducer, that needs its own space as well. + * + * ``` c++ + * struct reducer_t { + * static void init(registrar_t &scratchpad) { + * // preserve space for the reduction (one page aligned) + * scratchpad.book(key_space, sizeof(float) * 980 * 1024, 4096); + * } + * + * void exec(const grantor_t &scratchpad) { + * // get the pointer to preserved space. scratchpad came from + * // upper primitive (convolution in this example) + * auto space = scratchpad.get(key_reducer_space); + * + * space[:] += ...; + * } + * }; + * + * struct conv_t { + * struct pd_t { + * void init() { + * registrar_t scratchpad(scratchpad_registry_); + * + * // preserve a space for padded bias (using default alignment) + * scratchpad.book(key_conv_padded_bias, 128); + * + * // create a proxy registrar for the reducer All entries made + * // by reducer would live in convolution's registry, but would + * // have their own `prefix`, so no interference with conv's + * // buffers. + * registrar_t reducer_scratchpad(scratchpad, prefix_reducer); + * + * reducer_t::init(reducer_scratchpad); + * } + * + * registry_t scratchpad_registry_; + * } + * + * void exec() { + * // get the base pointer to a scratchpad memory from a user + * void *scratchpad_ptr = this->input(MKLDNN_MEM_SCRATCHPAD); + * + * // create a grantor to the scratchpad (and provide the base + * // pointer). + * grantor_t scratchpad(pd()->scratchpad_registry_, scratchpad_ptr); + * + * // access the padded_bias (need only key name and the grantor) + * auto padded_bias = scratchpad.get(key_conv_padded_bias); + * + * // to give the `right` grantor to reducer we need to add the + * // corresponding prefix, so that reducer would be able to access + * // its keys. The call is very similar to the one in pd_t::init + * // with only difference in types: grantor_t vs registrar_t. + * grantor_t reducer_scratchpad(scratchpad, prefix_reducer); + * reducer->exec(reducer_scratchpad); + * } + * }; + * ``` + */ + + +/* namespace with common keys and prefixes */ +namespace names { +enum { + key_none = 0, + key_bnorm_tmp_mean, + key_bnorm_tmp_var, + key_bnorm_tmp_diff_ss, + key_bnorm_tmp_stats, + key_bnorm_reduction, + key_concat_iptrs, + key_concat_istrides, + key_concat_nelems, + key_concat_optrs, + key_conv_adjusted_scales, + key_conv_bia_reduction, + key_conv_gemm_col, + key_conv_gemm_imtr, + key_conv_int_dat_in_acc_dt, + key_conv_padded_bias, + key_conv_rtus_space, + key_conv_tr_diff_dst, + key_conv_tr_diff_dst_bctx, + key_conv_tr_src, + key_conv_tr_src_bctx, + key_conv_wei_reduction, + key_conv_wei_bia_reduction, + key_conv_wei_bia_reduction_bctx, + key_iprod_int_dat_in_acc_dt, + key_reducer_space, + key_reducer_space_bctx, + key_reorder_wino_plain, + key_reorder_wino_transform_space, + key_reorder_rnn_weights_quantization, + key_reorder_rnn_weights_reduction, + key_rnn_space, + key_rnn_ptrs_bia, + key_rnn_ptrs_wei_layer, + key_rnn_ptrs_wei_iter, + key_softmax_reduction, + key_wino_U, + key_wino_V, + key_wino_M, + key_barrier, +}; + +enum { + prefix_none = 0, + prefix_reducer_bia, + prefix_reducer_wei, +}; +} + +// level 0: 00 00 00 xxx +// level 1: 00 00 aa xxx +// level 2: 00 aa bb xxx +// level 3: aa bb cc xxx +// max # of levels: 3 + 1 (base_level) +// here: +// xxx : [1 .. MAX_KEY) : key +// aa, bb, cc : [1 .. MAX_PREFIX) : prefixes for levels 1, 2, and 3 + +using key_t = uint32_t; +enum { MAX_KEY = (1u << 10), MAX_PREFIX = (1u << 7), }; + +/// generates global key based on a prefix and a local key +inline key_t make_key(key_t prefix, key_t key) { return prefix + key; } + +/// generates global prefix based on the global parent and the local ones +inline key_t make_prefix(key_t parent_prefix, key_t prefix) +{ return MAX_PREFIX * parent_prefix + MAX_KEY * prefix; } + +struct registrar_t; +struct grantor_t; + +struct registry_t { + void book(const key_t &key, size_t size, size_t alignment) { + if (size == 0) return; + assert(offset_map_.count(key) == 0); + + size = utils::rnd_up(size, minimal_alignment); + alignment = nstl::max(alignment, minimal_alignment); + offset_map_[key] = entry_t{size_, size, alignment}; + + size_ += size + alignment - minimal_alignment; + } + + void *get(const key_t &key, void *base_ptr) const { + if (base_ptr == nullptr) { assert(size() == 0); return nullptr; } + if (offset_map_.count(key) != 1) return nullptr; + + const auto &e = offset_map_.at(key); + base_ptr = utils::align_ptr(base_ptr, minimal_alignment); + char *ptr = (char *)base_ptr + e.offset; + return utils::align_ptr(ptr, e.alignment); + } + + size_t size() const + { return size_ > 0 ? size_ + minimal_alignment - 1 : 0; } + + registrar_t registrar(); + grantor_t grantor(void *base_ptr) const; + +protected: + enum { minimal_alignment = 64 }; + struct entry_t { size_t offset, size, alignment; }; + + std::unordered_map offset_map_; + size_t size_ = 0; +}; + +struct registrar_t { + enum { default_alignment = 64 }; + + registrar_t(registry_t ®istry): registry_(registry), prefix_(0) {} + registrar_t(registrar_t &parent, const key_t &prefix) + : registry_(parent.registry_) + , prefix_(make_prefix(parent.prefix_, prefix)) {} + + void book(const key_t &key, size_t size, + size_t alignment = default_alignment) + { registry_.book(make_key(prefix_, key), size, alignment); } + +protected: + registry_t ®istry_; + const key_t prefix_; +}; + +struct grantor_t { + grantor_t(const registry_t ®istry, void *base_ptr) + : registry_(registry), prefix_(0), base_ptr_(base_ptr) {} + grantor_t(const grantor_t &parent, const key_t &prefix) + : registry_(parent.registry_) + , prefix_(make_prefix(parent.prefix_, prefix)) + , base_ptr_(parent.base_ptr_) {} + + template T *get(const key_t &key) const + { return (T *)registry_.get(make_key(prefix_, key), base_ptr_); } + +protected: + const registry_t ®istry_; + const key_t prefix_; + void *base_ptr_; +}; + +inline registrar_t registry_t::registrar() { return registrar_t(*this); } +inline grantor_t registry_t::grantor(void *base_ptr) const +{ return grantor_t(*this, base_ptr); } + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp new file mode 100644 index 0000000000..2ef4a8fddc --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp @@ -0,0 +1,131 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include +#include + +#include "mkldnn_debug.h" +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#define DPRINT(...) do { \ + int l = snprintf(str + written_len, str_len, __VA_ARGS__); \ + if (l < 0) return l; \ + if ((size_t)l >= str_len) return -1; \ + written_len += l; str_len -= l; \ +} while(0) + +int mkldnn_md2fmt_str(char *str, size_t str_len, + const mkldnn_memory_desc_t *mdesc) { + using namespace mkldnn::impl; + + if (str == nullptr || str_len <= 1u) + return -1; + + int written_len = 0; + + if (mdesc == nullptr) { + DPRINT("%s::%s::", + mkldnn_dt2str(data_type::undef), + mkldnn_fmt_kind2str(format_kind::undef)); + return written_len; + } + + memory_desc_wrapper md(mdesc); + + DPRINT("%s:", mkldnn_dt2str(md.data_type())); + + bool padded_dims = false, padded_offsets = false; + for (int d = 0; d < md.ndims(); ++d) { + if (md.dims()[d] != md.padded_dims()[d]) padded_dims = true; + if (md.padded_offsets()[d] != 0) padded_offsets = true; + } + bool offset0 = md.offset0(); + DPRINT("%s%s%s:", + padded_dims ? "p" : "", + padded_offsets ? "o" : "", + offset0 ? "0" : ""); + + DPRINT("%s:", mkldnn_fmt_kind2str(md.format_kind())); + + if (!md.is_blocking_desc()) { + /* TODO: extend */ + DPRINT("%s:", ""); + } else { + const auto &blk = md.blocking_desc(); + + dims_t blocks; + md.compute_blocks(blocks); + + char dim_chars[MKLDNN_MAX_NDIMS + 1]; + + bool plain = true; + for (int d = 0; d < md.ndims(); ++d) { + dim_chars[d] = (blocks[d] == 1 ? 'a' : 'A') + (char)d; + if (blocks[d] != 1) plain = false; + } + + dims_t strides; + utils::array_copy(strides, blk.strides, md.ndims()); + utils::simultaneous_sort(strides, dim_chars, md.ndims(), + [](dim_t a, dim_t b) { return b - a; }); + + dim_chars[md.ndims()] = '\0'; + DPRINT("%s", dim_chars); + + if (!plain) { + for (int iblk = 0; iblk < blk.inner_nblks; ++iblk) { + DPRINT("%d%c", (int)blk.inner_blks[iblk], + 'a' + (char)blk.inner_idxs[iblk]); + } + } + + DPRINT("%s", ":"); + } + + DPRINT("f%lx", (long)md.extra().flags); + + return written_len; +} + +int mkldnn_md2dim_str(char *str, size_t str_len, + const mkldnn_memory_desc_t *mdesc) { + using namespace mkldnn::impl; + + if (str == nullptr || str_len <= 1) + return -1; + + int written_len = 0; + + if (mdesc == nullptr || mdesc->ndims == 0) { + DPRINT("%s", ""); + return written_len; + } + + memory_desc_wrapper md(mdesc); + + for (int d = 0; d < md.ndims() - 1; ++d) + DPRINT("%" PRId64 "x", md.dims()[d]); + DPRINT("%" PRId64, md.dims()[md.ndims() - 1]); + + return written_len; +} + +#undef DPRINT diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp new file mode 100644 index 0000000000..16a8f7ea5e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp @@ -0,0 +1,365 @@ +/******************************************************************************* +* Copyright 2018-2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* DO NOT EDIT, AUTO-GENERATED */ + +#include + +#include "mkldnn_debug.h" +#include "mkldnn_types.h" + +const char *mkldnn_status2str(mkldnn_status_t v) { + if (v == mkldnn_success) return "success"; + if (v == mkldnn_out_of_memory) return "out_of_memory"; + if (v == mkldnn_try_again) return "try_again"; + if (v == mkldnn_invalid_arguments) return "invalid_arguments"; + if (v == mkldnn_not_ready) return "not_ready"; + if (v == mkldnn_unimplemented) return "unimplemented"; + if (v == mkldnn_iterator_ends) return "iterator_ends"; + if (v == mkldnn_runtime_error) return "runtime_error"; + if (v == mkldnn_not_required) return "not_required"; + assert(!"unknown status"); + return "unknown status"; +} + +const char *mkldnn_dt2str(mkldnn_data_type_t v) { + if (v == mkldnn_data_type_undef) return "undef"; + if (v == mkldnn_f32) return "f32"; + if (v == mkldnn_s32) return "s32"; + if (v == mkldnn_s8) return "s8"; + if (v == mkldnn_u8) return "u8"; + assert(!"unknown dt"); + return "unknown dt"; +} + +const char *mkldnn_fmt_kind2str(mkldnn_format_kind_t v) { + if (v == mkldnn_format_kind_undef) return "undef"; + if (v == mkldnn_format_kind_any) return "any"; + if (v == mkldnn_blocked) return "blocked"; + if (v == mkldnn_format_kind_wino) return "wino"; + if (v == mkldnn_format_kind_rnn_packed) return "rnn_packed"; + assert(!"unknown fmt_kind"); + return "unknown fmt_kind"; +} + +const char *mkldnn_fmt_tag2str(mkldnn_format_tag_t v) { + if (v == mkldnn_format_tag_undef) return "undef"; + if (v == mkldnn_format_tag_any) return "format_tag_any"; + if (v == mkldnn_a) return "a"; + if (v == mkldnn_ab) return "ab"; + if (v == mkldnn_abc) return "abc"; + if (v == mkldnn_abcd) return "abcd"; + if (v == mkldnn_abcde) return "abcde"; + if (v == mkldnn_abcdef) return "abcdef"; + if (v == mkldnn_abdec) return "abdec"; + if (v == mkldnn_acb) return "acb"; + if (v == mkldnn_acbde) return "acbde"; + if (v == mkldnn_acdb) return "acdb"; + if (v == mkldnn_acdeb) return "acdeb"; + if (v == mkldnn_ba) return "ba"; + if (v == mkldnn_bac) return "bac"; + if (v == mkldnn_bacd) return "bacd"; + if (v == mkldnn_bcda) return "bcda"; + if (v == mkldnn_cba) return "cba"; + if (v == mkldnn_cdba) return "cdba"; + if (v == mkldnn_cdeba) return "cdeba"; + if (v == mkldnn_decab) return "decab"; + if (v == mkldnn_Abc16a) return "Abc16a"; + if (v == mkldnn_ABc16a16b) return "ABc16a16b"; + if (v == mkldnn_aBc16b) return "aBc16b"; + if (v == mkldnn_ABc16b16a) return "ABc16b16a"; + if (v == mkldnn_Abc4a) return "Abc4a"; + if (v == mkldnn_aBc4b) return "aBc4b"; + if (v == mkldnn_ABc4b16a4b) return "ABc4b16a4b"; + if (v == mkldnn_ABc4b4a) return "ABc4b4a"; + if (v == mkldnn_ABc8a16b2a) return "ABc8a16b2a"; + if (v == mkldnn_ABc8a8b) return "ABc8a8b"; + if (v == mkldnn_aBc8b) return "aBc8b"; + if (v == mkldnn_ABc8b16a2b) return "ABc8b16a2b"; + if (v == mkldnn_ABc8b8a) return "ABc8b8a"; + if (v == mkldnn_Abcd16a) return "Abcd16a"; + if (v == mkldnn_ABcd16a16b) return "ABcd16a16b"; + if (v == mkldnn_aBcd16b) return "aBcd16b"; + if (v == mkldnn_ABcd16b16a) return "ABcd16b16a"; + if (v == mkldnn_aBCd16b16c) return "aBCd16b16c"; + if (v == mkldnn_aBCd16c16b) return "aBCd16c16b"; + if (v == mkldnn_Abcd4a) return "Abcd4a"; + if (v == mkldnn_aBcd4b) return "aBcd4b"; + if (v == mkldnn_ABcd4b16a4b) return "ABcd4b16a4b"; + if (v == mkldnn_ABcd4b4a) return "ABcd4b4a"; + if (v == mkldnn_aBCd4c16b4c) return "aBCd4c16b4c"; + if (v == mkldnn_aBCd4c4b) return "aBCd4c4b"; + if (v == mkldnn_ABcd8a16b2a) return "ABcd8a16b2a"; + if (v == mkldnn_ABcd8a8b) return "ABcd8a8b"; + if (v == mkldnn_aBcd8b) return "aBcd8b"; + if (v == mkldnn_ABcd8b16a2b) return "ABcd8b16a2b"; + if (v == mkldnn_aBCd8b16c2b) return "aBCd8b16c2b"; + if (v == mkldnn_ABcd8b8a) return "ABcd8b8a"; + if (v == mkldnn_aBCd8b8c) return "aBCd8b8c"; + if (v == mkldnn_aBCd8c16b2c) return "aBCd8c16b2c"; + if (v == mkldnn_aBCd8c8b) return "aBCd8c8b"; + if (v == mkldnn_Abcde16a) return "Abcde16a"; + if (v == mkldnn_ABcde16a16b) return "ABcde16a16b"; + if (v == mkldnn_aBcde16b) return "aBcde16b"; + if (v == mkldnn_ABcde16b16a) return "ABcde16b16a"; + if (v == mkldnn_aBCde16b16c) return "aBCde16b16c"; + if (v == mkldnn_aBCde16c16b) return "aBCde16c16b"; + if (v == mkldnn_aBCde2c8b4c) return "aBCde2c8b4c"; + if (v == mkldnn_Abcde4a) return "Abcde4a"; + if (v == mkldnn_aBcde4b) return "aBcde4b"; + if (v == mkldnn_ABcde4b4a) return "ABcde4b4a"; + if (v == mkldnn_aBCde4b4c) return "aBCde4b4c"; + if (v == mkldnn_aBCde4c16b4c) return "aBCde4c16b4c"; + if (v == mkldnn_aBCde4c4b) return "aBCde4c4b"; + if (v == mkldnn_Abcde8a) return "Abcde8a"; + if (v == mkldnn_ABcde8a8b) return "ABcde8a8b"; + if (v == mkldnn_ABcde8b16a2b) return "ABcde8b16a2b"; + if (v == mkldnn_aBCde8b16c2b) return "aBCde8b16c2b"; + if (v == mkldnn_ABcde8b8a) return "ABcde8b8a"; + if (v == mkldnn_aBCde8b8c) return "aBCde8b8c"; + if (v == mkldnn_aBCde8c16b2c) return "aBCde8c16b2c"; + if (v == mkldnn_aBCde8c8b) return "aBCde8c8b"; + if (v == mkldnn_aBcdef16b) return "aBcdef16b"; + if (v == mkldnn_aBCdef16b16c) return "aBCdef16b16c"; + if (v == mkldnn_aBCdef16c16b) return "aBCdef16c16b"; + if (v == mkldnn_aBcdef4b) return "aBcdef4b"; + if (v == mkldnn_aBCdef4c4b) return "aBCdef4c4b"; + if (v == mkldnn_aBCdef8b8c) return "aBCdef8b8c"; + if (v == mkldnn_aBCdef8c16b2c) return "aBCdef8c16b2c"; + if (v == mkldnn_aBCdef8c8b) return "aBCdef8c8b"; + if (v == mkldnn_aBdc16b) return "aBdc16b"; + if (v == mkldnn_aBdc4b) return "aBdc4b"; + if (v == mkldnn_aBdc8b) return "aBdc8b"; + if (v == mkldnn_aBdec16b) return "aBdec16b"; + if (v == mkldnn_aBdec4b) return "aBdec4b"; + if (v == mkldnn_aBdec8b) return "aBdec8b"; + if (v == mkldnn_aBdefc16b) return "aBdefc16b"; + if (v == mkldnn_aBdefc4b) return "aBdefc4b"; + if (v == mkldnn_aBdefc8b) return "aBdefc8b"; + if (v == mkldnn_Acb16a) return "Acb16a"; + if (v == mkldnn_Acb4a) return "Acb4a"; + if (v == mkldnn_Acb8a) return "Acb8a"; + if (v == mkldnn_aCBd16b16c) return "aCBd16b16c"; + if (v == mkldnn_aCBde16b16c) return "aCBde16b16c"; + if (v == mkldnn_Acdb16a) return "Acdb16a"; + if (v == mkldnn_Acdb4a) return "Acdb4a"; + if (v == mkldnn_Acdb8a) return "Acdb8a"; + if (v == mkldnn_Acdeb16a) return "Acdeb16a"; + if (v == mkldnn_Acdeb4a) return "Acdeb4a"; + if (v == mkldnn_Acdeb8a) return "Acdeb8a"; + if (v == mkldnn_BAc16a16b) return "BAc16a16b"; + if (v == mkldnn_BAcd16a16b) return "BAcd16a16b"; + if (v == mkldnn_format_tag_last) return "format_tag_last"; + if (v == mkldnn_x) return "x"; + if (v == mkldnn_nc) return "nc"; + if (v == mkldnn_cn) return "cn"; + if (v == mkldnn_ncw) return "ncw"; + if (v == mkldnn_nwc) return "nwc"; + if (v == mkldnn_nchw) return "nchw"; + if (v == mkldnn_nhwc) return "nhwc"; + if (v == mkldnn_chwn) return "chwn"; + if (v == mkldnn_ncdhw) return "ncdhw"; + if (v == mkldnn_ndhwc) return "ndhwc"; + if (v == mkldnn_oi) return "oi"; + if (v == mkldnn_io) return "io"; + if (v == mkldnn_oiw) return "oiw"; + if (v == mkldnn_wio) return "wio"; + if (v == mkldnn_oihw) return "oihw"; + if (v == mkldnn_hwio) return "hwio"; + if (v == mkldnn_ihwo) return "ihwo"; + if (v == mkldnn_iohw) return "iohw"; + if (v == mkldnn_oidhw) return "oidhw"; + if (v == mkldnn_dhwio) return "dhwio"; + if (v == mkldnn_goiw) return "goiw"; + if (v == mkldnn_goihw) return "goihw"; + if (v == mkldnn_hwigo) return "hwigo"; + if (v == mkldnn_giohw) return "giohw"; + if (v == mkldnn_goidhw) return "goidhw"; + if (v == mkldnn_tnc) return "tnc"; + if (v == mkldnn_ntc) return "ntc"; + if (v == mkldnn_ldsnc) return "ldsnc"; + if (v == mkldnn_ldigo) return "ldigo"; + if (v == mkldnn_ldgoi) return "ldgoi"; + if (v == mkldnn_ldgo) return "ldgo"; + if (v == mkldnn_nCdhw16c) return "nCdhw16c"; + if (v == mkldnn_nCdhw4c) return "nCdhw4c"; + if (v == mkldnn_nCdhw8c) return "nCdhw8c"; + if (v == mkldnn_nChw16c) return "nChw16c"; + if (v == mkldnn_nChw4c) return "nChw4c"; + if (v == mkldnn_nChw8c) return "nChw8c"; + if (v == mkldnn_nCw16c) return "nCw16c"; + if (v == mkldnn_nCw4c) return "nCw4c"; + if (v == mkldnn_nCw8c) return "nCw8c"; + if (v == mkldnn_IOw16o16i) return "IOw16o16i"; + if (v == mkldnn_OIw16i16o) return "OIw16i16o"; + if (v == mkldnn_OIw16o16i) return "OIw16o16i"; + if (v == mkldnn_Oiw16o) return "Oiw16o"; + if (v == mkldnn_OIw4i16o4i) return "OIw4i16o4i"; + if (v == mkldnn_OIw4i4o) return "OIw4i4o"; + if (v == mkldnn_Oiw4o) return "Oiw4o"; + if (v == mkldnn_OIw8i16o2i) return "OIw8i16o2i"; + if (v == mkldnn_OIw8i8o) return "OIw8i8o"; + if (v == mkldnn_OIw8o16i2o) return "OIw8o16i2o"; + if (v == mkldnn_OIw8o8i) return "OIw8o8i"; + if (v == mkldnn_Owi16o) return "Owi16o"; + if (v == mkldnn_Owi4o) return "Owi4o"; + if (v == mkldnn_Owi8o) return "Owi8o"; + if (v == mkldnn_IOhw16o16i) return "IOhw16o16i"; + if (v == mkldnn_Ohwi16o) return "Ohwi16o"; + if (v == mkldnn_Ohwi4o) return "Ohwi4o"; + if (v == mkldnn_Ohwi8o) return "Ohwi8o"; + if (v == mkldnn_OIhw16i16o) return "OIhw16i16o"; + if (v == mkldnn_OIhw16o16i) return "OIhw16o16i"; + if (v == mkldnn_Oihw16o) return "Oihw16o"; + if (v == mkldnn_OIhw4i16o4i) return "OIhw4i16o4i"; + if (v == mkldnn_OIhw4i4o) return "OIhw4i4o"; + if (v == mkldnn_Oihw4o) return "Oihw4o"; + if (v == mkldnn_OIhw8i16o2i) return "OIhw8i16o2i"; + if (v == mkldnn_OIhw8i8o) return "OIhw8i8o"; + if (v == mkldnn_OIhw8o16i2o) return "OIhw8o16i2o"; + if (v == mkldnn_OIhw8o8i) return "OIhw8o8i"; + if (v == mkldnn_Odhwi16o) return "Odhwi16o"; + if (v == mkldnn_Odhwi4o) return "Odhwi4o"; + if (v == mkldnn_Odhwi8o) return "Odhwi8o"; + if (v == mkldnn_OIdhw16i16o) return "OIdhw16i16o"; + if (v == mkldnn_OIdhw16o16i) return "OIdhw16o16i"; + if (v == mkldnn_Oidhw16o) return "Oidhw16o"; + if (v == mkldnn_OIdhw4i4o) return "OIdhw4i4o"; + if (v == mkldnn_Oidhw4o) return "Oidhw4o"; + if (v == mkldnn_OIdhw8i16o2i) return "OIdhw8i16o2i"; + if (v == mkldnn_OIdhw8i8o) return "OIdhw8i8o"; + if (v == mkldnn_OIdhw8o8i) return "OIdhw8o8i"; + if (v == mkldnn_Goiw16g) return "Goiw16g"; + if (v == mkldnn_gIOw16o16i) return "gIOw16o16i"; + if (v == mkldnn_gOIw16i16o) return "gOIw16i16o"; + if (v == mkldnn_gOIw16o16i) return "gOIw16o16i"; + if (v == mkldnn_gOiw16o) return "gOiw16o"; + if (v == mkldnn_gOIw4i16o4i) return "gOIw4i16o4i"; + if (v == mkldnn_gOIw4i4o) return "gOIw4i4o"; + if (v == mkldnn_gOiw4o) return "gOiw4o"; + if (v == mkldnn_gOIw8i16o2i) return "gOIw8i16o2i"; + if (v == mkldnn_gOIw8i8o) return "gOIw8i8o"; + if (v == mkldnn_gOIw8o16i2o) return "gOIw8o16i2o"; + if (v == mkldnn_gOIw8o8i) return "gOIw8o8i"; + if (v == mkldnn_gOwi16o) return "gOwi16o"; + if (v == mkldnn_gOwi4o) return "gOwi4o"; + if (v == mkldnn_gOwi8o) return "gOwi8o"; + if (v == mkldnn_gIOhw16o16i) return "gIOhw16o16i"; + if (v == mkldnn_gOhwi16o) return "gOhwi16o"; + if (v == mkldnn_gOhwi4o) return "gOhwi4o"; + if (v == mkldnn_gOhwi8o) return "gOhwi8o"; + if (v == mkldnn_Goihw16g) return "Goihw16g"; + if (v == mkldnn_gOIhw16i16o) return "gOIhw16i16o"; + if (v == mkldnn_gOIhw16o16i) return "gOIhw16o16i"; + if (v == mkldnn_gOihw16o) return "gOihw16o"; + if (v == mkldnn_gOIhw2i8o4i) return "gOIhw2i8o4i"; + if (v == mkldnn_gOIhw4i16o4i) return "gOIhw4i16o4i"; + if (v == mkldnn_gOIhw4i4o) return "gOIhw4i4o"; + if (v == mkldnn_gOIhw4o4i) return "gOIhw4o4i"; + if (v == mkldnn_gOihw4o) return "gOihw4o"; + if (v == mkldnn_Goihw8g) return "Goihw8g"; + if (v == mkldnn_gOIhw8i16o2i) return "gOIhw8i16o2i"; + if (v == mkldnn_gOIhw8i8o) return "gOIhw8i8o"; + if (v == mkldnn_gOIhw8o16i2o) return "gOIhw8o16i2o"; + if (v == mkldnn_gOIhw8o8i) return "gOIhw8o8i"; + if (v == mkldnn_gOdhwi16o) return "gOdhwi16o"; + if (v == mkldnn_gOdhwi4o) return "gOdhwi4o"; + if (v == mkldnn_gOdhwi8o) return "gOdhwi8o"; + if (v == mkldnn_gOIdhw16i16o) return "gOIdhw16i16o"; + if (v == mkldnn_gOIdhw16o16i) return "gOIdhw16o16i"; + if (v == mkldnn_gOidhw16o) return "gOidhw16o"; + if (v == mkldnn_gOIdhw4i4o) return "gOIdhw4i4o"; + if (v == mkldnn_gOidhw4o) return "gOidhw4o"; + if (v == mkldnn_gOIdhw8i16o2i) return "gOIdhw8i16o2i"; + if (v == mkldnn_gOIdhw8i8o) return "gOIdhw8i8o"; + if (v == mkldnn_gOIdhw8o8i) return "gOIdhw8o8i"; + assert(!"unknown fmt_tag"); + return "unknown fmt_tag"; +} + +const char *mkldnn_prop_kind2str(mkldnn_prop_kind_t v) { + if (v == mkldnn_prop_kind_undef) return "undef"; + if (v == mkldnn_forward_training) return "forward_training"; + if (v == mkldnn_forward_inference) return "forward_inference"; + if (v == mkldnn_forward_scoring) return "forward_scoring"; + if (v == mkldnn_forward) return "forward"; + if (v == mkldnn_backward) return "backward"; + if (v == mkldnn_backward_data) return "backward_data"; + if (v == mkldnn_backward_weights) return "backward_weights"; + if (v == mkldnn_backward_bias) return "backward_bias"; + assert(!"unknown prop_kind"); + return "unknown prop_kind"; +} + +const char *mkldnn_prim_kind2str(mkldnn_primitive_kind_t v) { + if (v == mkldnn_undefined_primitive) return "undef"; + if (v == mkldnn_reorder) return "reorder"; + if (v == mkldnn_shuffle) return "shuffle"; + if (v == mkldnn_concat) return "concat"; + if (v == mkldnn_sum) return "sum"; + if (v == mkldnn_convolution) return "convolution"; + if (v == mkldnn_deconvolution) return "deconvolution"; + if (v == mkldnn_eltwise) return "eltwise"; + if (v == mkldnn_softmax) return "softmax"; + if (v == mkldnn_pooling) return "pooling"; + if (v == mkldnn_lrn) return "lrn"; + if (v == mkldnn_batch_normalization) return "batch_normalization"; + if (v == mkldnn_inner_product) return "inner_product"; + if (v == mkldnn_rnn) return "rnn"; + assert(!"unknown prim_kind"); + return "unknown prim_kind"; +} + +const char *mkldnn_alg_kind2str(mkldnn_alg_kind_t v) { + if (v == mkldnn_alg_kind_undef) return "undef"; + if (v == mkldnn_convolution_direct) return "convolution_direct"; + if (v == mkldnn_convolution_winograd) return "convolution_winograd"; + if (v == mkldnn_convolution_auto) return "convolution_auto"; + if (v == mkldnn_deconvolution_direct) return "deconvolution_direct"; + if (v == mkldnn_deconvolution_winograd) return "deconvolution_winograd"; + if (v == mkldnn_eltwise_relu) return "eltwise_relu"; + if (v == mkldnn_eltwise_tanh) return "eltwise_tanh"; + if (v == mkldnn_eltwise_elu) return "eltwise_elu"; + if (v == mkldnn_eltwise_square) return "eltwise_square"; + if (v == mkldnn_eltwise_abs) return "eltwise_abs"; + if (v == mkldnn_eltwise_sqrt) return "eltwise_sqrt"; + if (v == mkldnn_eltwise_linear) return "eltwise_linear"; + if (v == mkldnn_eltwise_bounded_relu) return "eltwise_bounded_relu"; + if (v == mkldnn_eltwise_soft_relu) return "eltwise_soft_relu"; + if (v == mkldnn_eltwise_logistic) return "eltwise_logistic"; + if (v == mkldnn_pooling_max) return "pooling_max"; + if (v == mkldnn_pooling_avg_include_padding) return "pooling_avg_include_padding"; + if (v == mkldnn_pooling_avg_exclude_padding) return "pooling_avg_exclude_padding"; + if (v == mkldnn_pooling_avg) return "pooling_avg"; + if (v == mkldnn_lrn_across_channels) return "lrn_across_channels"; + if (v == mkldnn_lrn_within_channel) return "lrn_within_channel"; + if (v == mkldnn_vanilla_rnn) return "vanilla_rnn"; + if (v == mkldnn_vanilla_lstm) return "vanilla_lstm"; + if (v == mkldnn_vanilla_gru) return "vanilla_gru"; + if (v == mkldnn_gru_linear_before_reset) return "gru_linear_before_reset"; + assert(!"unknown alg_kind"); + return "unknown alg_kind"; +} + +const char *mkldnn_rnn_direction2str(mkldnn_rnn_direction_t v) { + if (v == mkldnn_unidirectional_left2right) return "unidirectional_left2right"; + if (v == mkldnn_unidirectional_right2left) return "unidirectional_right2left"; + if (v == mkldnn_bidirectional_concat) return "bidirectional_concat"; + if (v == mkldnn_bidirectional_sum) return "bidirectional_sum"; + if (v == mkldnn_unidirectional) return "unidirectional"; + assert(!"unknown rnn_direction"); + return "unknown rnn_direction"; +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp new file mode 100644 index 0000000000..7e5789e2c3 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp @@ -0,0 +1,115 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_THREAD_HPP +#define MKLDNN_THREAD_HPP + +#include "utils.hpp" +#include "z_magic.hpp" + +#define MKLDNN_THR_SEQ 0 +#define MKLDNN_THR_OMP 1 +#define MKLDNN_THR_TBB 2 + +/* Ideally this condition below should never happen (if the library is built + * using regular cmake). For the 3rd-party projects that build the library + * from the sources on their own try to guess the right threading... */ +#if !defined(MKLDNN_THR) +# define MKLDNN_THR MKLDNN_THR_TBB +#endif + +#if MKLDNN_THR == MKLDNN_THR_SEQ +#define MKLDNN_THR_SYNC 1 +inline int mkldnn_get_max_threads() { return 1; } +inline int mkldnn_get_num_threads() { return 1; } +inline int mkldnn_get_thread_num() { return 0; } +inline int mkldnn_in_parallel() { return 0; } +inline void mkldnn_thr_barrier() {} + +#define PRAGMA_OMP(...) + +#elif MKLDNN_THR == MKLDNN_THR_OMP +#include +#define MKLDNN_THR_SYNC 1 + +inline int mkldnn_get_max_threads() { return omp_get_max_threads(); } +inline int mkldnn_get_num_threads() { return omp_get_num_threads(); } +inline int mkldnn_get_thread_num() { return omp_get_thread_num(); } +inline int mkldnn_in_parallel() { return omp_in_parallel(); } +inline void mkldnn_thr_barrier() { +# pragma omp barrier +} + +#define PRAGMA_OMP(...) PRAGMA_MACRO(CHAIN2(omp, __VA_ARGS__)) + +#elif MKLDNN_THR == MKLDNN_THR_TBB +#include "tbb/task_arena.h" +#include "tbb/parallel_for.h" +#define MKLDNN_THR_SYNC 0 + +inline int mkldnn_get_max_threads() +{ return tbb::this_task_arena::max_concurrency(); } +inline int mkldnn_get_num_threads() { return mkldnn_get_max_threads(); } +inline int mkldnn_get_thread_num() +{ return tbb::this_task_arena::current_thread_index(); } +inline int mkldnn_in_parallel() { return 0; } +inline void mkldnn_thr_barrier() { assert(!"no barrier in TBB"); } + +#define PRAGMA_OMP(...) + +#endif + +/* MSVC still supports omp 2.0 only */ +#if defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) +# define collapse(x) +# define PRAGMA_OMP_SIMD(...) +#else +# define PRAGMA_OMP_SIMD(...) PRAGMA_MACRO(CHAIN2(omp, simd __VA_ARGS__)) +#endif // defined(_MSC_VER) && !defined(__INTEL_COMPILER) + +namespace mkldnn { +namespace impl { + +inline bool mkldnn_thr_syncable() { return MKLDNN_THR_SYNC == 1; } + +template +inline void balance211(T n, U team, U tid, T &n_start, T &n_end) { + T n_min = 1; + T &n_my = n_end; + if (team <= 1 || n == 0) { + n_start = 0; + n_my = n; + } else if (n_min == 1) { + // team = T1 + T2 + // n = T1*n1 + T2*n2 (n1 - n2 = 1) + T n1 = utils::div_up(n, (T)team); + T n2 = n1 - 1; + T T1 = n - n2 * (T)team; + n_my = (T)tid < T1 ? n1 : n2; + n_start = (T)tid <= T1 ? tid * n1 : T1 * n1 + ((T)tid - T1) * n2; + } + + n_end += n_start; +} + +} // namespace impl +} // namespace mkldnn + +#include "mkldnn_thread_parallel_nd.hpp" + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp new file mode 100644 index 0000000000..50f9b29622 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp @@ -0,0 +1,277 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_THREAD_PARALLEL_ND_HPP +#define MKLDNN_THREAD_PARALLEL_ND_HPP + +/* This header must be included by mkldnn_thread.hpp only */ + +/* Functions: + * - parallel(nthr, f) - executes f in parallel using at most + * nthr threads. If nthr equals 0 + * mkldnn_get_max_threads() threads is + * used + * - for_nd(ithr, nthr, dims..., f) - multidimensional for loop for already + * created threads + * - parallel_nd(dims..., f) - creates a parallel section and then + * calls for_nd + * - parallel_nd_in_omp(dims..., f) - queries current nthr and ithr and then + * calls for_nd (mostly for convenience) + */ + +namespace mkldnn { +namespace impl { + +/* general parallelization */ +template +void parallel(int nthr, F f) { + if (nthr == 0) nthr = mkldnn_get_max_threads(); +#if MKLDNN_THR == MKLDNN_THR_SEQ + assert(nthr == 1); + f(0, 1); +#elif MKLDNN_THR == MKLDNN_THR_OMP + if (nthr == 1) { f(0, 1); return; } +# pragma omp parallel num_threads(nthr) + f(mkldnn_get_thread_num(), mkldnn_get_num_threads()); +#elif MKLDNN_THR == MKLDNN_THR_TBB + if (nthr == 1) { f(0, 1); return; } + tbb::parallel_for(0, nthr, [&](int ithr) { f(ithr, nthr); }, tbb::static_partitioner()); +#endif +} + +/* for_nd section */ + +template +void for_nd(const int ithr, const int nthr, const T0 &D0, F f) { + T0 start{0}, end{0}; + balance211(D0, nthr, ithr, start, end); + for (T0 d0 = start; d0 < end; ++d0) f(d0); +} + +template +void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1, F f) { + const size_t work_amount = (size_t)D0 * D1; + if (work_amount == 0) return; + size_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + T0 d0{0}; T1 d1{0}; + utils::nd_iterator_init(start, d0, D0, d1, D1); + for (size_t iwork = start; iwork < end; ++iwork) { + f(d0, d1); + utils::nd_iterator_step(d0, D0, d1, D1); + } +} + +template +void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1, + const T2 &D2, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2; + if (work_amount == 0) return; + size_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + T0 d0{0}; T1 d1{0}; T2 d2{0}; + utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2); + for (size_t iwork = start; iwork < end; ++iwork) { + f(d0, d1, d2); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2); + } +} + +template +void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1, + const T2 &D2, const T3 &D3, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2 * D3; + if (work_amount == 0) return; + size_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; + utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2, d3, D3); + for (size_t iwork = start; iwork < end; ++iwork) { + f(d0, d1, d2, d3); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3); + } +} + +template +void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1, + const T2 &D2, const T3 &D3, const T4 &D4, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4; + if (work_amount == 0) return; + size_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0}; + utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2, d3, D3, d4, D4); + for (size_t iwork = start; iwork < end; ++iwork) { + f(d0, d1, d2, d3, d4); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4); + } +} + +template +void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1, + const T2 &D2, const T3 &D3, const T4 &D4, const T5 &D5, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4 * D5; + if (work_amount == 0) return; + size_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0}; T5 d5{0}; + utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2, d3, D3, d4, D4, + d5, D5); + for (size_t iwork = start; iwork < end; ++iwork) { + f(d0, d1, d2, d3, d4, d5); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4, d5, D5); + } +} + +// Skip a lambda function in the parameter pack. +template +constexpr size_t get_work_amount(const T &v) { return 1; } +template +constexpr size_t get_work_amount(const T &v, Args &&...args) +{ return (size_t)v * get_work_amount(utils::forward(args)...); } + +/* parallel_nd and parallel_nd_in_omp section */ + +#if MKLDNN_THR != MKLDNN_THR_TBB +template +void parallel_nd(Args &&...args) { +#if MKLDNN_THR == MKLDNN_THR_SEQ + for_nd(0, 1, utils::forward(args)...); +#elif MKLDNN_THR == MKLDNN_THR_OMP + const bool do_parallel = get_work_amount(utils::forward(args)...) > 1; +# pragma omp parallel if (do_parallel) + { + const int nthr = !do_parallel ? 1 : mkldnn_get_num_threads(); + const int ithr = !do_parallel ? 0 : mkldnn_get_thread_num(); + for_nd(ithr, nthr, utils::forward(args)...); + } +#endif +} +#else // MKLDNN_THR != MKLDNN_THR_TBB + +// gcc 4.8 has a bug with passing parameter pack to lambdas. +// So have to explicitly instantiate all the cases. + +template +void parallel_nd(const T0 &D0, F f) { + const size_t work_amount = (size_t)D0; + if (work_amount == 0) return; + tbb::parallel_for(tbb::blocked_range(0, work_amount), [&](const tbb::blocked_range& r) { + for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) { + f(T0(iwork)); + } + }, tbb::static_partitioner()); +} + +template +void parallel_nd(const T0 &D0, const T1 &D1, F f) { + const size_t work_amount = (size_t)D0 * D1; + if (work_amount == 0) return; + tbb::parallel_for(tbb::blocked_range(0, work_amount), [&](const tbb::blocked_range& r) { + T0 d0{0}; T1 d1{0}; + utils::nd_iterator_init(r.begin(), d0, D0, d1, D1); + for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) { + f(d0, d1); + utils::nd_iterator_step(d0, D0, d1, D1); + } + }, tbb::static_partitioner()); +} + +template +void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2; + if (work_amount == 0) return; + tbb::parallel_for(tbb::blocked_range(0, work_amount), [&](const tbb::blocked_range& r) { + T0 d0{0}; T1 d1{0}; T2 d2{0}; + utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2); + for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) { + f(d0, d1, d2); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2); + } + }, tbb::static_partitioner()); +} + +template +void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, const T3 &D3, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2 * D3; + if (work_amount == 0) return; + tbb::parallel_for(tbb::blocked_range(0, work_amount), [&](const tbb::blocked_range& r) { + T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; + utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2, d3, D3); + for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) { + f(d0, d1, d2, d3); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3); + } + }, tbb::static_partitioner()); +} + +template +void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, const T3 &D3, + const T4 &D4, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4; + if (work_amount == 0) return; + tbb::parallel_for(tbb::blocked_range(0, work_amount), [&](const tbb::blocked_range& r) { + T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0}; + utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2, d3, D3, d4, D4); + for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) { + f(d0, d1, d2, d3, d4); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4); + } + }, tbb::static_partitioner()); +} + +template +void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, const T3 &D3, + const T4 &D4, const T5 &D5, F f) { + const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4 * D5; + if (work_amount == 0) return; + tbb::parallel_for(tbb::blocked_range(0, work_amount), [&](const tbb::blocked_range& r) { + T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0}; T5 d5{0}; + utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2, d3, D3, d4, D4, + d5, D5); + for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) { + f(d0, d1, d2, d3, d4, d5); + utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4, d5, D5); + } + }, tbb::static_partitioner()); +} +#endif + +template +void parallel_nd_in_omp(Args &&...args) { +#if MKLDNN_THR == MKLDNN_THR_SEQ + for_nd(0, 1, utils::forward(args)...); +#elif MKLDNN_THR == MKLDNN_THR_OMP + for_nd(mkldnn_get_thread_num(), mkldnn_get_num_threads(), + utils::forward(args)...); +#elif MKLDNN_THR == MKLDNN_THR_TBB + assert(!"unsupported parallel_nd_in_omp()"); +#endif +} + +} // namespace impl +} // namespace mkldnn + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp new file mode 100644 index 0000000000..aa671a0b6e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp @@ -0,0 +1,77 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef MKLDNN_TRAITS_HPP +#define MKLDNN_TRAITS_HPP + +#include +#include + +#include "mkldnn.h" +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "utils.hpp" +#include "z_magic.hpp" + +namespace mkldnn { +namespace impl { + +template struct prec_traits {}; /* ::type -> float */ +template struct data_traits {}; /* ::data_type -> f32 */ +template struct typesize_traits {}; /* ::data_type_size -> f32 */ +template struct pkind_traits {}; /* ::desc_type, ::query_d */ + +template <> struct prec_traits { typedef float type; }; +template <> struct prec_traits { typedef int32_t type; }; +template <> struct prec_traits { typedef int8_t type; }; +template <> struct prec_traits { typedef uint8_t type; }; + +template <> struct data_traits +{ static constexpr data_type_t data_type = data_type::f32; }; +template <> struct data_traits +{ static constexpr data_type_t data_type = data_type::s32; }; +template <> struct data_traits +{ static constexpr data_type_t data_type = data_type::s8; }; +template <> struct data_traits +{ static constexpr data_type_t data_type = data_type::u8; }; + +template <> struct typesize_traits<4> { typedef float type; }; +template <> struct typesize_traits<2> { typedef int16_t type; }; +template <> struct typesize_traits<1> { typedef uint8_t type; }; + +#define PKIND_TRAITS_INST(op) \ +template <> struct pkind_traits { \ + typedef CONCAT2(op, _desc_t) desc_type; \ + static constexpr query_t query_d = query::CONCAT2(op, _d); \ +} +PKIND_TRAITS_INST(convolution); +PKIND_TRAITS_INST(deconvolution); +PKIND_TRAITS_INST(shuffle); +PKIND_TRAITS_INST(eltwise); +PKIND_TRAITS_INST(softmax); +PKIND_TRAITS_INST(pooling); +PKIND_TRAITS_INST(lrn); +PKIND_TRAITS_INST(batch_normalization); +PKIND_TRAITS_INST(inner_product); +PKIND_TRAITS_INST(rnn); +#undef PKIND_TRAITS_INST + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/nstl.hpp b/thirdparty/oidn/mkl-dnn/src/common/nstl.hpp new file mode 100644 index 0000000000..f89ea999e2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/nstl.hpp @@ -0,0 +1,193 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef NSTL_HPP +#define NSTL_HPP + +#include +#include +#include + +#include +#include + +#include "z_magic.hpp" + +namespace mkldnn { +namespace impl { + +void *malloc(size_t size, int alignment); +void free(void *p); + +struct c_compatible { + enum { default_alignment = 64 }; + static void *operator new(size_t sz) { + return malloc(sz, default_alignment); + } + static void *operator new(size_t sz, void *p) { UNUSED(sz); return p; } + static void *operator new[](size_t sz) { + return malloc(sz, default_alignment); + } + static void operator delete(void *p) { free(p); } + static void operator delete[](void *p) { free(p); } +}; + +namespace nstl { + +template +inline const T abs(const T& a) { + return a >= 0 ? a : -a; +} + +template +inline const T& max(const T& a, const T& b) { + return a > b ? a : b; +} + +template +inline const T& min(const T& a, const T& b) { + return a < b ? a : b; +} + +template void swap(T& t1, T& t2) { + T tmp(t1); + t1 = t2; + t2 = tmp; +} + +// Rationale: MKL-DNN needs numeric limits implementation that does not +// generate dependencies on C++ run-time libraries. + +template struct numeric_limits; + +template<> struct numeric_limits { + static constexpr float lowest() { return -FLT_MAX; } + static constexpr float max() { return FLT_MAX; } +}; + +template<> struct numeric_limits { + static constexpr int lowest() { return INT32_MIN; } + static constexpr int max() { return INT32_MAX; } +}; + +template<> struct numeric_limits { + static constexpr int16_t lowest() { return INT16_MIN; } + static constexpr int16_t max() { return INT16_MAX; } +}; + +template<> struct numeric_limits { + static constexpr int8_t lowest() { return INT8_MIN; } + static constexpr int8_t max() { return INT8_MAX; } +}; + +template<> struct numeric_limits { + static constexpr uint8_t lowest() { return 0; } + static constexpr uint8_t max() { return UINT8_MAX; } +}; + +template struct is_integral +{ static constexpr bool value = false; }; +template<> struct is_integral { static constexpr bool value = true; }; +template<> struct is_integral { static constexpr bool value = true; }; +template<> struct is_integral { static constexpr bool value = true; }; +template<> struct is_integral { static constexpr bool value = true; }; + +template struct is_same +{ static constexpr bool value = false; }; +template struct is_same +{ static constexpr bool value = true; }; + +// Rationale: MKL-DNN needs container implementations that do not generate +// dependencies on C++ run-time libraries. +// +// Implementation philosophy: caller is responsible to check if the operation +// is valid. The only functions that have to return status are those that +// depend on memory allocation or similar operations. +// +// This means that e.g. an operator [] does not have to check for boundaries. +// The caller should have checked the boundaries. If it did not we crash and +// burn: this is a bug in MKL-DNN and throwing an exception would not have been +// recoverable. +// +// On the other hand, insert() or resize() or a similar operation needs to +// return a status because the outcome depends on factors external to the +// caller. The situation is probably also not recoverable also, but MKL-DNN +// needs to be nice and report "out of memory" to the users. + +enum nstl_status_t { + success = 0, + out_of_memory +}; + +template class vector: public c_compatible { +private: + std::vector _impl; +public: + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + typedef typename std::vector::size_type size_type; + vector() {} + vector(size_type n): _impl(n) {} + vector(size_type n, const T &value): _impl(n, value) {} + template + vector(input_iterator first, input_iterator last): _impl(first, last) {} + ~vector() {} + size_type size() const { return _impl.size(); } + T& operator[] (size_type i) { return _impl[i]; } + const T& operator[] (size_type i) const { return _impl[i]; } + iterator begin() { return _impl.begin(); } + const_iterator begin() const { return _impl.begin(); } + iterator end() { return _impl.end(); } + const_iterator end() const { return _impl.end(); } + template + nstl_status_t insert(iterator pos, input_iterator begin, input_iterator end) + { + _impl.insert(pos, begin, end); + return success; + } + void clear() { _impl.clear(); } + void push_back(const T& t) { _impl.push_back(t); } + void resize(size_type count) { _impl.resize(count); } + void reserve(size_type count) { _impl.reserve(count); } +}; + +template class map: public c_compatible { +private: + std::map _impl; +public: + typedef typename std::map::iterator iterator; + typedef typename std::map::const_iterator const_iterator; + typedef typename std::map::size_type size_type; + map() {} + ~map() {} + size_type size() const { return _impl.size(); } + T& operator[](const Key &k) { return _impl[k]; } + const T& operator[](const Key &k) const { return _impl[k]; } + iterator begin() { return _impl.begin(); } + const_iterator begin() const { return _impl.begin(); } + iterator end() { return _impl.end(); } + const_iterator end() const { return _impl.end(); } + template + void clear() { _impl.clear(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/pooling.cpp b/thirdparty/oidn/mkl-dnn/src/common/pooling.cpp new file mode 100644 index 0000000000..be96e654ff --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/pooling.cpp @@ -0,0 +1,114 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::alg_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t pooling_desc_init(pooling_desc_t *pool_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *dst_desc, + const dims_t strides, const dims_t kernel, const dims_t padding_l, + const dims_t padding_r, padding_kind_t padding_kind) { + bool args_ok = true + && !any_null(pool_desc, src_desc, dst_desc, strides, kernel, padding_l) + && one_of(alg_kind, pooling_max, + pooling_avg_include_padding, + pooling_avg_exclude_padding) + && one_of(padding_kind, padding_kind::padding_zero); + if (!args_ok) return invalid_arguments; + + if (padding_r == nullptr) padding_r = padding_l; + + auto pd = pooling_desc_t(); + pd.primitive_kind = primitive_kind::pooling; + pd.prop_kind = prop_kind; + pd.alg_kind = alg_kind; + pd.src_desc.ndims = src_desc->ndims; + + const bool is_fwd = one_of(prop_kind, forward_training, forward_inference); + + pd.diff_src_desc = pd.src_desc = zero_md(); + pd.diff_dst_desc = pd.dst_desc = zero_md(); + + (is_fwd ? pd.src_desc : pd.diff_src_desc) = *src_desc; + (is_fwd ? pd.dst_desc : pd.diff_dst_desc) = *dst_desc; + + int sp_dims = src_desc->ndims - 2; + utils::array_copy(pd.strides, strides, sp_dims); + utils::array_copy(pd.kernel, kernel, sp_dims); + utils::array_copy(pd.padding[0], padding_l, sp_dims); + utils::array_copy(pd.padding[1], padding_r, sp_dims); + + pd.padding_kind = padding_kind; + if (one_of(alg_kind, pooling_max, pooling_avg_include_padding, + pooling_avg_exclude_padding)) { + pd.accum_data_type = types::default_accum_data_type( + src_desc->data_type, dst_desc->data_type); + } else { + pd.accum_data_type = dst_desc->data_type; + } + + bool consistency = true + && utils::one_of(src_desc->ndims, 4, 5) + && utils::one_of(dst_desc->ndims, 4, 5) + && src_desc->dims[0] == dst_desc->dims[0] + && src_desc->dims[1] == dst_desc->dims[1]; + for (int i = 2; i < src_desc->ndims; ++i) + consistency = consistency && ( + (src_desc->dims[i] - kernel[i - 2] + padding_l[i - 2] + + padding_r[i - 2]) / strides[i - 2] + 1 + == dst_desc->dims[i]); + if (!consistency) return invalid_arguments; + + *pool_desc = pd; + return success; +} +} + +status_t mkldnn_pooling_forward_desc_init(pooling_desc_t *pool_desc, + prop_kind_t prop_kind, alg_kind_t alg_kind, + const memory_desc_t *src_desc, const memory_desc_t *dst_desc, + const dims_t strides, const dims_t kernel, const dims_t padding_l, + const dims_t padding_r, padding_kind_t padding_kind) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return pooling_desc_init(pool_desc, prop_kind, alg_kind, src_desc, + dst_desc, strides, kernel, padding_l, padding_r, padding_kind); +} + +status_t mkldnn_pooling_backward_desc_init(pooling_desc_t *pool_desc, + alg_kind_t alg_kind, const memory_desc_t *diff_src_desc, + const memory_desc_t *diff_dst_desc, const dims_t strides, + const dims_t kernel, const dims_t padding_l, const dims_t padding_r, + padding_kind_t padding_kind) { + return pooling_desc_init(pool_desc, prop_kind::backward_data, alg_kind, + diff_src_desc, diff_dst_desc, strides, kernel, padding_l, + padding_r, padding_kind); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp new file mode 100644 index 0000000000..4c9c009412 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp @@ -0,0 +1,238 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef POOLING_PD_HPP +#define POOLING_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" +#include "type_helpers.hpp" + +namespace mkldnn { +namespace impl { + +struct pooling_fwd_pd_t; + +struct pooling_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::pooling; + + pooling_pd_t(engine_t *engine, + const pooling_desc_t *adesc, + const primitive_attr_t *attr, + const pooling_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + , ws_md_() + {} + + const pooling_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::pooling_d: + *(const pooling_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common pooling aux functions */ + + dim_t MB() const { return src_desc().dims[0]; } + dim_t C() const { return src_desc().dims[1]; } + + dim_t ID() const { return ndims() >= 5 ? src_desc().dims[ndims() - 3] : 1; } + dim_t IH() const { return ndims() >= 4 ? src_desc().dims[ndims() - 2] : 1; } + dim_t IW() const { return src_desc().dims[ndims() - 1]; } + + dim_t OD() const { return ndims() >= 5 ? dst_desc().dims[ndims() - 3] : 1; } + dim_t OH() const { return ndims() >= 4 ? dst_desc().dims[ndims() - 2] : 1; } + dim_t OW() const { return dst_desc().dims[ndims() - 1]; } + + dim_t KD() const { return ndims() >= 5 ? desc_.kernel[ndims() - 5] : 1; } + dim_t KH() const { return ndims() >= 4 ? desc_.kernel[ndims() - 4] : 1; } + dim_t KW() const { return desc_.kernel[ndims() - 3]; } + + dim_t KSD() const { return ndims() >= 5 ? desc_.strides[ndims() - 5] : 1; } + dim_t KSH() const { return ndims() >= 4 ? desc_.strides[ndims() - 4] : 1; } + dim_t KSW() const { return desc_.strides[ndims() - 3]; } + + dim_t padFront() const + { return ndims() >= 5 ? desc_.padding[0][ndims() - 5] : 0; } + dim_t padBack() const + { return ndims() >= 5 ? desc_.padding[1][ndims() - 5] : 0; } + dim_t padT() const + { return ndims() >= 4 ? desc_.padding[0][ndims() - 4] : 0; } + dim_t padB() const + { return ndims() >= 4 ? desc_.padding[1][ndims() - 4] : 0; } + dim_t padL() const { return desc_.padding[0][ndims() - 3]; } + dim_t padR() const { return desc_.padding[1][ndims() - 3]; } + + int ndims() const { return src_desc().ndims; } + bool is_3d() const { return ndims() == 5; } + + bool has_zero_dim_memory() const + { return memory_desc_wrapper(src_desc()).has_zero_dim(); } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + +protected: + pooling_desc_t desc_; + const pooling_fwd_pd_t *hint_fwd_pd_; + + memory_desc_t ws_md_; + + void init_default_ws() { + ws_md_ = is_fwd() ? *dst_md() : *diff_dst_md(); + ws_md_.data_type = indices_data_type(); + } + + data_type_t indices_data_type() const { + /* the simplest way to express 256... */ + const int u8_max = nstl::numeric_limits< + typename prec_traits::type>::max(); + return utils::array_product(desc()->kernel, ndims()) <= u8_max + ? data_type::u8 : data_type::s32; + } + +private: + const memory_desc_t &src_desc() const + { return is_fwd() ? desc_.src_desc : desc_.diff_src_desc; } + const memory_desc_t &dst_desc() const + { return is_fwd() ? desc_.dst_desc : desc_.diff_dst_desc; } +}; + +struct pooling_fwd_pd_t: public pooling_pd_t { + typedef pooling_fwd_pd_t base_class; + typedef pooling_fwd_pd_t hint_class; + + pooling_fwd_pd_t(engine_t *engine, + const pooling_desc_t *adesc, + const primitive_attr_t *attr, + const pooling_fwd_pd_t *hint_fwd_pd) + : pooling_pd_t(engine, adesc, attr, hint_fwd_pd) + , src_md_(desc_.src_desc) + , dst_md_(desc_.dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_SRC) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr)) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &dst_md_ : nullptr; } + virtual const memory_desc_t *workspace_md(int index = 0) const override + { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; } + + virtual int n_inputs() const override { return 1; } + virtual int n_outputs() const override + { return 1 + (workspace_md() != nullptr); } + +protected: + memory_desc_t src_md_; + memory_desc_t dst_md_; + + virtual status_t set_default_params() { + if (dst_md()->format_kind != format_kind::any) + return status::success; + + if (src_md()->format_kind != format_kind::blocked) + return status::unimplemented; + + return memory_desc_init_by_blocking_desc(dst_md_, + src_md_.format_desc.blocking); + } +}; + +struct pooling_bwd_pd_t: public pooling_pd_t { + typedef pooling_bwd_pd_t base_class; + typedef pooling_fwd_pd_t hint_class; + + pooling_bwd_pd_t(engine_t *engine, + const pooling_desc_t *adesc, + const primitive_attr_t *attr, + const pooling_fwd_pd_t *hint_fwd_pd) + : pooling_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_src_md_(desc_.diff_src_desc) + , diff_dst_md_(desc_.diff_dst_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_DIFF_DST) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr)) + return arg_usage_t::input; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_src_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_dst_md_ : nullptr; } + virtual const memory_desc_t *workspace_md(int index = 0) const override + { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; } + + virtual int n_inputs() const override + { return 1 + (workspace_md() != nullptr); } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t diff_src_md_; + memory_desc_t diff_dst_md_; + + virtual status_t set_default_params() { + if (diff_src_md()->format_kind != format_kind::any) + return status::success; + + if (diff_dst_md()->format_kind != format_kind::blocked) + return status::unimplemented; + + return memory_desc_init_by_blocking_desc(diff_src_md_, + diff_dst_md_.format_desc.blocking); + } +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive.cpp new file mode 100644 index 0000000000..fdf6522f62 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "primitive_desc.hpp" +#include "primitive.hpp" +#include "type_helpers.hpp" +#include "stream.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::primitive_kind; + +namespace { +// XXX: this is a huge hammer. This disables all and any msan checks on +// primitives outputs. +// +// A proper approach would be an implementation-specific unpoisoning. +void unpoison_outputs(const exec_args_t &args) { + for(const auto &arg: args) { + if (arg.second.is_const) continue; + auto *mem = arg.second.mem; + void *p; + mem->get_data_handle(&p); + size_t s = memory_desc_wrapper(*mem->md()).size(); + msan_unpoison(p, s); + } +} +} + +status_t mkldnn_primitive_desc_destroy(primitive_desc_t *primitive_desc) { + if (primitive_desc) delete primitive_desc; + return success; +} + +status_t mkldnn_primitive_create(primitive_t **primitive, + const primitive_desc_t *primitive_desc) { + if (utils::any_null(primitive, primitive_desc)) + return invalid_arguments; + return primitive_desc->create_primitive(primitive); +} + +status_t mkldnn_primitive_execute(const primitive_t *primitive, + stream_t *stream, int nargs, const mkldnn_exec_arg_t *c_args) { + bool ok = true + && !utils::any_null(primitive, stream) + && primitive->engine() == stream->engine() + && IMPLICATION(nargs > 0, c_args != nullptr); + if (!ok) return invalid_arguments; + + exec_args_t args; + status_t status = cvt_primtive_args(primitive->pd(), nargs, c_args, args); + if (status != status::success) return status; + + exec_ctx_t ctx(stream, std::move(args)); + + if (mkldnn_verbose()->level) { + double ms = get_msec(); + status = primitive->execute(ctx); + ms = get_msec() - ms; + printf("mkldnn_verbose,exec,%s,%g\n", primitive->pd()->info(), ms); + fflush(0); + } else { + status = primitive->execute(ctx); + } + + if (msan_enabled) unpoison_outputs(ctx.args()); + + return status; +} + +status_t mkldnn_primitive_get_primitive_desc(const primitive_t *primitive, + const primitive_desc_t **primitive_desc) { + if (utils::any_null(primitive, primitive_desc)) + return invalid_arguments; + return safe_ptr_assign(*primitive_desc, + primitive->pd()); +} + +status_t mkldnn_primitive_destroy(primitive_t *primitive) { + if (primitive != nullptr) + delete primitive; + return success; +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive.hpp new file mode 100644 index 0000000000..3b506d6d1f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive.hpp @@ -0,0 +1,76 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef PRIMITIVE_HPP +#define PRIMITIVE_HPP + +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "primitive_desc.hpp" +#include "primitive_exec_types.hpp" + +/** \brief A pure virtual primitive class + * + * Primitive contains links to its inputs & outputs, though it does not track + * their readiness on execution step. + * + * @remark @b Rational. + * Dependencies are essential through-out the whole MKL-DNN library, so it + * makes sense to include them on the very low level. On the other hand, + * tracking them should be a task for corresponding essence, like scheduler, + * stream or whatever. Primitive itself should know nothing about the + * environment it is running in. + * + * @note + * To make user experience better we should provide API which allows + * achieving the best (or good enough) performance when creating primitives + * in natural order: i.e. from bottom to top for forward pass and from top to + * bottom for backward pass. Please consider restriction [1] in Level 0. + */ +struct mkldnn_primitive: public mkldnn::impl::c_compatible { + mkldnn_primitive(const mkldnn::impl::primitive_desc_t *pd) + : pd_(pd->clone()) {} + virtual ~mkldnn_primitive() { delete pd_; } + + /** returns primitive's engine */ + mkldnn::impl::engine_t *engine() const { return pd_->engine(); } + /** returns primitive's inputs */ + const mkldnn::impl::primitive_desc_t *pd() const { return pd_; } + /** returns primitive's kind */ + mkldnn::impl::primitive_kind_t kind() const { return pd_->kind(); } + + /** executes primitive with execution context @p ctx */ + virtual mkldnn::impl::status_t execute(const mkldnn::impl::exec_ctx_t &ctx) + const = 0; + +protected: + const mkldnn::impl::primitive_desc_t *pd_; + +private: + mkldnn_primitive() = delete; + mkldnn_primitive(const mkldnn_primitive &) = delete; + mkldnn_primitive(mkldnn_primitive &&) = delete; + mkldnn_primitive &operator=(const mkldnn_primitive &) = delete; + mkldnn_primitive &operator=(mkldnn_primitive &&) = delete; +}; + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp new file mode 100644 index 0000000000..9fd638842c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp @@ -0,0 +1,290 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_attr.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::utils; + +namespace mkldnn { +namespace impl { + +status_t scales_t::set(dim_t count, int mask, const float *scales) { + cleanup(); + + count_ = count; + mask_ = mask; + + if (count_ == 1) { + scales_ = scales_buf_; + utils::array_set(scales_, scales[0], scales_buf_size); + } else { + scales_ = (float *)impl::malloc(count_ * sizeof(*scales_), 64); + if (scales_ == nullptr) + return status::out_of_memory; + + for (dim_t c = 0; c < count_; ++c) + scales_[c] = scales[c]; + } + + return status::success; +} + +} +} + +status_t post_ops_t::append_sum(float scale) { + if (len_ == capacity) + return out_of_memory; + + entry_[len_].kind = primitive_kind::sum; + entry_[len_].sum.scale = scale; + + len_++; + + return success; +} + +status_t post_ops_t::append_eltwise(float scale, alg_kind_t alg, float alpha, + float beta) { + using namespace mkldnn::impl::alg_kind; + bool known_alg = one_of(alg, eltwise_relu, eltwise_tanh, eltwise_elu, + eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear, + eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic); + if (!known_alg) + return invalid_arguments; + + if (len_ == capacity) + return out_of_memory; + + entry_[len_].kind = primitive_kind::eltwise; + entry_[len_].eltwise.scale = scale; + entry_[len_].eltwise.alg = alg; + entry_[len_].eltwise.alpha = alpha; + entry_[len_].eltwise.beta = beta; + + len_++; + + return success; +} + +status_t primitive_attr_t::set_scratchpad_mode( + scratchpad_mode_t scratchpad_mode) { + using namespace mkldnn::impl::scratchpad_mode; + + const bool ok = one_of(scratchpad_mode, library, user); + if (!ok) + return invalid_arguments; + + scratchpad_mode_ = scratchpad_mode; + return success; +} + +status_t primitive_attr_t::set_post_ops(const post_ops_t &post_ops) { + this->post_ops_ = post_ops; + return success; +} + +/* Public C API */ + +status_t mkldnn_primitive_attr_create(primitive_attr_t **attr) { + if (attr == nullptr) + return invalid_arguments; + + return safe_ptr_assign(*attr, + new mkldnn_primitive_attr); +} + +status_t mkldnn_primitive_attr_clone(primitive_attr_t **attr, + const primitive_attr_t *existing_attr) { + if (any_null(attr, existing_attr)) + return invalid_arguments; + + return safe_ptr_assign(*attr, + existing_attr->clone()); +} + +status_t mkldnn_primitive_attr_destroy(primitive_attr_t *attr) { + if (attr) + delete attr; + + return success; +} + +status_t mkldnn_primitive_attr_get_scratchpad_mode( + const primitive_attr_t *attr, scratchpad_mode_t *scratchpad_mode) { + if (any_null(attr, scratchpad_mode)) + return invalid_arguments; + + *scratchpad_mode = attr->scratchpad_mode_; + + return success; +} + +status_t mkldnn_primitive_attr_set_scratchpad_mode( + primitive_attr_t *attr, scratchpad_mode_t scratchpad_mode) { + if (any_null(attr)) + return invalid_arguments; + + return attr->set_scratchpad_mode(scratchpad_mode); +} + +status_t mkldnn_primitive_attr_get_output_scales(const primitive_attr_t *attr, + dim_t *count, int *mask, const float **scales) { + if (any_null(attr, count, mask, scales)) + return invalid_arguments; + + *count = attr->output_scales_.count_; + *mask = attr->output_scales_.mask_; + *scales = attr->output_scales_.scales_; + + return success; +} + +status_t mkldnn_primitive_attr_set_output_scales(primitive_attr_t *attr, + dim_t count, int mask, const float *scales) { + bool ok = !any_null(attr, scales) && count > 0 && mask >= 0; + if (!ok) + return invalid_arguments; + + return attr->output_scales_.set(count, mask, scales); +} + +status_t mkldnn_primitive_attr_get_post_ops(const primitive_attr_t *attr, + const post_ops_t **post_ops) { + if (any_null(attr, post_ops)) + return invalid_arguments; + + *post_ops = &attr->post_ops_; + return success; +} + +status_t mkldnn_primitive_attr_set_post_ops(primitive_attr_t *attr, + const post_ops_t *post_ops) { + if (any_null(attr, post_ops)) + return invalid_arguments; + + return attr->set_post_ops(*post_ops); +} + +status_t mkldnn_post_ops_create(post_ops_t **post_ops) { + if (post_ops == nullptr) + return invalid_arguments; + + return safe_ptr_assign(*post_ops, new mkldnn_post_ops); +} + +status_t mkldnn_post_ops_destroy(post_ops_t *post_ops) { + if (post_ops) + delete post_ops; + + return success; +} + +int mkldnn_post_ops_len(const post_ops_t *post_ops) { + if (post_ops) + return post_ops->len_; + + return 0; +} + +primitive_kind_t mkldnn_post_ops_get_kind(const post_ops_t *post_ops, + int index) { + bool ok = post_ops && 0 <= index && index < post_ops->len_; + if (!ok) + return primitive_kind::undefined; + + return post_ops->entry_[index].kind; +} + +status_t mkldnn_post_ops_append_sum(post_ops_t *post_ops, float scale) { + if (post_ops == nullptr) + return invalid_arguments; + + return post_ops->append_sum(scale); +} + +namespace { +bool simple_get_params_check(const post_ops_t *post_ops, int index, + primitive_kind_t kind) { + bool ok = true + && post_ops != nullptr + && 0 <= index + && index < post_ops->len_ + && post_ops->entry_[index].kind == kind; + return ok; +} +} + +status_t mkldnn_post_ops_get_params_sum(const post_ops_t *post_ops, int index, + float *scale) { + bool ok = true + && simple_get_params_check(post_ops, index, primitive_kind::sum) + && !any_null(scale); + if (!ok) + return invalid_arguments; + + *scale = post_ops->entry_[index].sum.scale; + return success; +} + +status_t mkldnn_post_ops_append_eltwise(post_ops_t *post_ops, float scale, + alg_kind_t kind, float alpha, float beta) { + if (post_ops == nullptr) + return invalid_arguments; + + return post_ops->append_eltwise(scale, kind, alpha, beta); +} + +status_t mkldnn_post_ops_get_params_eltwise(const post_ops_t *post_ops, + int index, float *scale, alg_kind_t *alg, float *alpha, float *beta) { + bool ok = true + && simple_get_params_check(post_ops, index, primitive_kind::eltwise) + && !any_null(scale, alpha, beta); + if (!ok) + return invalid_arguments; + + const auto &e = post_ops->entry_[index].eltwise; + *scale = e.scale; + *alg = e.alg; + *alpha = e.alpha; + *beta = e.beta; + + return success; +} + +status_t mkldnn_primitive_attr_set_rnn_data_qparams( + primitive_attr_t *attr, const float scale, const float shift) { + if (attr == nullptr) + return invalid_arguments; + + return attr->rnn_data_qparams_.set(scale, shift); +} + +status_t mkldnn_primitive_attr_set_rnn_weights_qparams( + primitive_attr_t *attr, dim_t count, int mask, const float *scales) { + bool ok = !any_null(attr, scales) && count > 0 && mask >= 0; + if (!ok) + return invalid_arguments; + + return attr->rnn_weights_qparams_.set(count, mask, scales); +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp new file mode 100644 index 0000000000..e2130c7ab1 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp @@ -0,0 +1,183 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef PRIMITIVE_ATTR_HPP +#define PRIMITIVE_ATTR_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +struct rnn_data_qparams_t : public c_compatible { + rnn_data_qparams_t() : scale_(1.), shift_(0.) {} + bool has_default_values() const { return (scale_ == 1. && shift_ == 0.); } + + status_t set(float scale, float shift) { + scale_ = scale; + shift_ = shift; + return status::success; + } + + float scale_; + float shift_; +}; + +struct scales_t: public c_compatible { + scales_t(): count_(1), mask_(0), scales_(scales_buf_) + { set(1.); } + + scales_t(const scales_t &rhs): scales_t() + { set(rhs.count_, rhs.mask_, rhs.scales_); } + + ~scales_t() { cleanup(); } + + scales_t &operator=(const scales_t &rhs) { + if (&rhs == this) + return *this; + status_t status = set(rhs.count_, rhs.mask_, rhs.scales_); + assert(status == status::success); + (void)status; + return *this; + } + + bool has_default_values() const { + for (dim_t c = 0; c < count_; ++c) { + if(scales_[c] != 1.) return false; + } + return true; + } + + status_t set(dim_t count, int mask, const float *scales); + status_t set(float single_scale) { return this->set(1, 0, &single_scale); } + + dim_t count_; + int mask_; + float *scales_; + +private: + enum { scales_buf_size = 16 }; + float scales_buf_[scales_buf_size]; + + void cleanup() { + if (scales_ != scales_buf_ && scales_ != nullptr) + impl::free(scales_); + + count_ = 1; + mask_ = 0; + scales_ = scales_buf_; + } +}; + +} +} + +struct mkldnn_post_ops: public mkldnn::impl::c_compatible { + struct entry_t { + struct eltwise_t { + mkldnn::impl::alg_kind_t alg; + float scale, alpha, beta; + }; + + mkldnn::impl::primitive_kind_t kind; + union { + struct { float scale; } sum; + eltwise_t eltwise; + }; + + bool is_eltwise(bool require_scale_one = true) const { + using namespace mkldnn::impl; + return kind == primitive_kind::eltwise + && IMPLICATION(require_scale_one, eltwise.scale == 1.f); + } + + bool is_relu(bool require_scale_one = true, + bool require_nslope_zero = true) const { + using namespace mkldnn::impl; + return is_eltwise(require_scale_one) + && eltwise.alg == alg_kind::eltwise_relu + && IMPLICATION(require_nslope_zero, eltwise.alpha == 0.f); + } + + bool is_sum(bool require_scale_one = true) const { + using namespace mkldnn::impl; + return kind == primitive_kind::sum + && IMPLICATION(require_scale_one, sum.scale == 1.f); + } + }; + + mkldnn_post_ops(): len_(0) {} + + mkldnn::impl::status_t append_sum(float scale); + mkldnn::impl::status_t append_eltwise(float scale, + mkldnn::impl::alg_kind_t alg, float alpha, float beta); + + int find(mkldnn::impl::primitive_kind_t kind, int start = 0, + int stop = -1) const { + if (stop == -1) stop = len_; + stop = mkldnn::impl::nstl::min(stop, len_); + for (int idx = start; idx < stop; ++idx) + if (entry_[idx].kind == kind) return idx; + return -1; + } + + bool has_default_values() const { return len_ == 0; } + + bool contain(mkldnn::impl::primitive_kind_t kind, int index) const + { return find(kind, index, index + 1) == index; } + + enum { capacity = 4 }; + + int len_; + entry_t entry_[capacity]; +}; + +struct mkldnn_primitive_attr: public mkldnn::impl::c_compatible { + mkldnn_primitive_attr() + : scratchpad_mode_(mkldnn::impl::scratchpad_mode::library) + {} + + mkldnn_primitive_attr *clone() const + { return new mkldnn_primitive_attr(*this); } + + /** Returns true if the attributes have default values. + * + * @note The scratchpad_mode_ is not take into account */ + bool has_default_values() const { + return true + && output_scales_.has_default_values() + && post_ops_.has_default_values() + && rnn_data_qparams_.has_default_values() + && rnn_weights_qparams_.has_default_values(); + } + + mkldnn::impl::status_t set_scratchpad_mode( + mkldnn::impl::scratchpad_mode_t scratchpad_mode); + mkldnn::impl::status_t set_post_ops( + const mkldnn::impl::post_ops_t &post_ops); + + mkldnn::impl::scratchpad_mode_t scratchpad_mode_; + mkldnn::impl::scales_t output_scales_; + mkldnn::impl::post_ops_t post_ops_; + mkldnn::impl::rnn_data_qparams_t rnn_data_qparams_; + mkldnn::impl::scales_t rnn_weights_qparams_; +}; + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp new file mode 100644 index 0000000000..723c41e05a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp @@ -0,0 +1,78 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "primitive_desc.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::status; + +status_t primitive_desc_t::query(query_t what, int idx, void *result) const { + auto safe_ret_md = [&](const memory_desc_t *_) { + if (_ == nullptr) return not_required; + *(const memory_desc_t **)result = _; + return success; + }; + + switch (what) { + case query::engine: *(engine_t**)result = engine(); break; + case query::primitive_kind: *(primitive_kind_t*)result = kind(); break; + + case query::scratchpad_engine: + *(engine_t**)result = scratchpad_engine(); break; + + case query::memory_consumption_s64: + *(dim_t *)result = scratchpad_size(scratchpad_mode::library); break; + + case query::op_d: + if (idx != 0 || op_desc() == nullptr) return invalid_arguments; + *(const_c_op_desc_t *)result + = static_cast(op_desc()); break; + + case query::src_md: return safe_ret_md(src_md(idx)); + case query::diff_src_md: return safe_ret_md(diff_src_md(idx)); + case query::dst_md: return safe_ret_md(dst_md(idx)); + case query::diff_dst_md: return safe_ret_md(diff_dst_md(idx)); + case query::weights_md: return safe_ret_md(weights_md(idx)); + case query::diff_weights_md: return safe_ret_md(diff_weights_md(idx)); + case query::workspace_md: + if (idx != 0) return status::invalid_arguments; + return safe_ret_md(workspace_md(idx)); + case query::scratchpad_md: + if (idx != 0) return status::invalid_arguments; + return safe_ret_md(scratchpad_md(idx)); + + case query::num_of_inputs_s32: *(int*)result = n_inputs(); break; + case query::num_of_outputs_s32: *(int*)result = n_outputs(); break; + + case query::impl_info_str: *(const char **)result = name(); break; + + default: return unimplemented; + } + return success; +} + +status_t mkldnn_primitive_desc_get_attr(const primitive_desc_t *primitive_desc, + const primitive_attr_t **attr) { + if (utils::any_null(primitive_desc, attr)) + return invalid_arguments; + + *attr = primitive_desc->attr(); + return success; +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp new file mode 100644 index 0000000000..536dcfa1d0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp @@ -0,0 +1,174 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef PRIMITIVE_DESC_HPP +#define PRIMITIVE_DESC_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "primitive_attr.hpp" +#include "verbose.hpp" + +struct mkldnn_primitive_desc: public mkldnn::impl::c_compatible { + using md_t = mkldnn::impl::memory_desc_t; + + mkldnn_primitive_desc(mkldnn::impl::engine_t *engine, + const mkldnn::impl::primitive_attr_t *attr, + mkldnn::impl::primitive_kind_t kind) + : engine_(engine), attr_(*attr), kind_(kind) { info_[0] = '\0'; } + + mkldnn_primitive_desc(mkldnn::impl::engine_t *engine, + mkldnn::impl::primitive_kind_t kind) + : engine_(engine), kind_(kind) { info_[0] = '\0'; } + + virtual mkldnn_primitive_desc *clone() const = 0; + virtual ~mkldnn_primitive_desc() {} + + const mkldnn::impl::primitive_attr_t *attr() const { return &attr_; } + mkldnn::impl::engine_t *engine() const { return engine_; } + mkldnn::impl::primitive_kind_t kind() const { return kind_; } + + virtual void init_info() {} + const char *info() const { return info_; } + + mkldnn::impl::memory_tracking::registry_t &scratchpad_registry() + { return scratchpad_registry_; } + const mkldnn::impl::memory_tracking::registry_t &scratchpad_registry() const + { return scratchpad_registry_; } + virtual mkldnn::impl::engine_t *scratchpad_engine() const + { return engine_; } + + virtual const mkldnn::impl::op_desc_t *op_desc() const { return nullptr; } + + enum class arg_usage_t { unused, input, output }; + virtual arg_usage_t arg_usage( + mkldnn::impl::primitive_arg_index_t arg) const { + using mkldnn::impl::types::is_zero_md; + if (arg == MKLDNN_ARG_SCRATCHPAD && !is_zero_md(scratchpad_md())) + return arg_usage_t::output; + return arg_usage_t::unused; + } + +# define DECLARE_MD_STUB(stub) \ + virtual const mkldnn::impl::memory_desc_t *stub(int idx = 0) const \ + { return nullptr; } + + DECLARE_MD_STUB(input_md); DECLARE_MD_STUB(output_md); + DECLARE_MD_STUB(src_md); DECLARE_MD_STUB(diff_src_md); + DECLARE_MD_STUB(dst_md); DECLARE_MD_STUB(diff_dst_md); + DECLARE_MD_STUB(weights_md); DECLARE_MD_STUB(diff_weights_md); + DECLARE_MD_STUB(workspace_md); +# undef DECLARE_MD_STUB + + const mkldnn::impl::memory_desc_t *scratchpad_md(int idx = 0) const { + return idx == 0 ? &scratchpad_md_ : nullptr; + } + + virtual void init_scratchpad_md() { + auto size = scratchpad_size(mkldnn::impl::scratchpad_mode::user); + mkldnn::impl::dims_t dims = { size }; + mkldnn_memory_desc_init_by_tag(&scratchpad_md_, size ? 1 : 0, dims, + mkldnn::impl::data_type::u8, mkldnn_x); + } + + /** returns the scratchpad size for the given scratchpad mode. */ + mkldnn::impl::dim_t scratchpad_size( + mkldnn::impl::scratchpad_mode_t mode) const { + if (mode != attr_.scratchpad_mode_) return 0; + return scratchpad_registry().size(); + } + + virtual int n_inputs() const { return 0; } + virtual int n_outputs() const { return 0; } + + virtual mkldnn::impl::status_t query(mkldnn::impl::query_t what, int idx, + void *result) const; + + virtual mkldnn::impl::status_t create_primitive( + mkldnn::impl::primitive_t **primitive) const = 0; + + virtual const char *name() const { return "mkldnn_primitive_desc"; } + + /* static magic */ + + template + static mkldnn::impl::status_t create(mkldnn::impl::primitive_desc_t **pd, + const mkldnn::impl::op_desc_t *adesc, + const mkldnn::impl::primitive_attr_t *attr, + mkldnn::impl::engine_t *engine, + const mkldnn::impl::primitive_desc_t *hint_fwd) { + using namespace mkldnn::impl; + using namespace mkldnn::impl::status; + using pd_op_desc_t = typename pkind_traits::desc_type; + if (adesc->kind != pd_t::base_pkind) return invalid_arguments; + assert(hint_fwd ? hint_fwd->kind() == pd_t::base_pkind : true); + auto hint = + reinterpret_cast(hint_fwd); + auto _pd = new pd_t(engine, (const pd_op_desc_t *)adesc, attr, hint); + if (_pd == nullptr) return out_of_memory; + if (_pd->init() != success) { delete _pd; return unimplemented; } + _pd->init_info(); + _pd->init_scratchpad_md(); + *pd = _pd; + return success; + } + +protected: + mkldnn::impl::engine_t *engine_; + mkldnn::impl::primitive_attr_t attr_; + mkldnn::impl::primitive_kind_t kind_; + + mkldnn::impl::memory_desc_t scratchpad_md_; + + char info_[MKLDNN_VERBOSE_BUF_LEN]; + + mkldnn::impl::memory_tracking::registry_t scratchpad_registry_; + +protected: + /** compares ws between fwd_pd and this (make sense to use for bwd_pd) + * Expectation: this already set workspace, and this workspace should + * exactly match the one from fwd_pd */ + bool compare_ws(const mkldnn_primitive_desc *fwd_pd) const { + using namespace mkldnn::impl; + if (!workspace_md()) return true; // the impl lives fine w/o workspace + return fwd_pd && fwd_pd->workspace_md() + && *fwd_pd->workspace_md() == *workspace_md(); + } +}; + +#define DECLARE_COMMON_PD_t(impl_name, ...) \ + virtual pd_t *clone() const override { return new pd_t(*this); } \ + virtual status_t create_primitive(primitive_t **p) const override { \ + double ms = get_msec(); \ + auto ret = safe_ptr_assign(*p, new (__VA_ARGS__)(this)); \ + ms = get_msec() - ms; \ + if (mkldnn_verbose()->level >= 2) { \ + printf("mkldnn_verbose,create,%s,%g\n", this->info(), ms); \ + fflush(0); \ + } \ + return ret; \ + } \ + virtual const char *name() const override { return impl_name; } +#define DECLARE_COMMON_PD_T(impl_name, ...) \ + DECLARE_COMMON_PD_t(impl_name, __VA_ARGS__) + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp new file mode 100644 index 0000000000..43e5a31ef3 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp @@ -0,0 +1,90 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "memory.hpp" +#include "primitive.hpp" +#include "primitive_exec_types.hpp" + +namespace mkldnn { +namespace impl { + +status_t cvt_primtive_args(const primitive_desc_t *pd, int nargs, + const mkldnn_exec_arg_t *c_args, exec_args_t &args) { + using namespace status; + + if (!IMPLICATION(nargs > 0, c_args != nullptr)) return invalid_arguments; + + int n_inputs = 0; + int n_outputs = 0; + + for (int i = 0; i < nargs; ++i) { + primitive_arg_index_t arg = c_args[i].arg; + auto *mem = c_args[i].memory; + + switch (pd->arg_usage(arg)) { + case primitive_desc_t::arg_usage_t::input: + if (args.count(arg) != 0) return invalid_arguments; + args[arg] = {mem, true}; + n_inputs++; + break; + case primitive_desc_t::arg_usage_t::output: + if (args.count(arg) != 0) return invalid_arguments; + args[arg] = {mem, false}; + n_outputs++; + break; + case primitive_desc_t::arg_usage_t::unused: + break; + } + } + + bool scratchpad_required = !types::is_zero_md(pd->scratchpad_md()); + + if (n_inputs != pd->n_inputs()) return invalid_arguments; + if (n_outputs != pd->n_outputs() + (scratchpad_required ? 1 : 0)) + return invalid_arguments; + + return success; +} + +const void *exec_ctx_t::input(primitive_arg_index_t arg) const { + if (args_.count(arg) != 1) return nullptr; + const auto ma = args_.at(arg); + assert(ma.is_const); + void *ptr; + status_t status = ma.mem->get_data_handle(&ptr); + assert(status == status::success); MAYBE_UNUSED(status); + return ptr; +} + +void *exec_ctx_t::output(primitive_arg_index_t arg) const { + if (args_.count(arg) != 1) return nullptr; + const auto ma = args_.at(arg); + assert(!ma.is_const); + void *ptr; + status_t status = ma.mem->get_data_handle(&ptr); + assert(status == status::success); MAYBE_UNUSED(status); + return ptr; +} + +const memory_t *exec_ctx_t::memory(primitive_arg_index_t arg) const { + assert(args_.count(arg) == 1); + const auto ma = args_.at(arg); + assert(!ma.is_const); + return ma.mem; +} + +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp new file mode 100644 index 0000000000..0645891da7 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp @@ -0,0 +1,68 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef PRIMITIVE_EXEC_TYPES_HPP +#define PRIMITIVE_EXEC_TYPES_HPP + +#include + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "memory.hpp" +#include "primitive_desc.hpp" + +namespace mkldnn { +namespace impl { + +struct memory_arg_t { + memory_t *mem; + bool is_const; +}; + +using exec_args_t = std::unordered_map; + +status_t cvt_primtive_args(const primitive_desc_t *pd, int nargs, + const mkldnn_exec_arg_t *c_args, exec_args_t &args); + +/** Primitive execution context (helps passing stream, memories, and events. */ +struct exec_ctx_t { + exec_ctx_t(const exec_ctx_t &) = default; + exec_ctx_t(exec_ctx_t &&) = default; + + exec_ctx_t(stream_t *stream): stream_(stream) {} + exec_ctx_t(stream_t *stream, exec_args_t &&args) + : stream_(stream) + , args_(std::move(args)) {} + + stream_t *stream() const { return stream_; } + const exec_args_t &args() const { return args_; } + + /* tentative solution... TODO: replace with functions return memory_t */ + const void *input(primitive_arg_index_t arg) const; + void *output(primitive_arg_index_t arg) const; + + const memory_t *memory(primitive_arg_index_t arg) const; + +private: + stream_t *stream_; + exec_args_t args_; +}; + +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp new file mode 100644 index 0000000000..5a1cd7d379 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp @@ -0,0 +1,89 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "primitive_desc.hpp" +#include "type_helpers.hpp" +#include "primitive_iterator.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::status; + +status_t mkldnn_primitive_desc_iterator_create( + primitive_desc_iterator_t **iterator, const_c_op_desc_t c_op_desc, + const primitive_attr_t *attr, engine_t *engine, + const primitive_desc_t *hint_fwd_pd) { + const op_desc_t *op_desc = (const op_desc_t *)c_op_desc; + + auto it = new primitive_desc_iterator_t(engine, op_desc, attr, hint_fwd_pd); + if (it == nullptr) return out_of_memory; + + ++(*it); + if (*it == it->end()) { + delete it; + return unimplemented; + } + + *iterator = it; + return success; +} + +status_t mkldnn_primitive_desc_iterator_next( + primitive_desc_iterator_t *iterator) { + if (iterator == nullptr) return invalid_arguments; + ++(*iterator); + return *iterator == iterator->end() ? iterator_ends : success; +} + +primitive_desc_t *mkldnn_primitive_desc_iterator_fetch( + const primitive_desc_iterator_t *iterator) { + if (iterator == nullptr) return nullptr; + return *(*iterator); +} + +status_t mkldnn_primitive_desc_clone(primitive_desc_t **primitive_desc, + const primitive_desc_t *existing_primitive_desc) { + if (utils::any_null(primitive_desc, existing_primitive_desc)) + return invalid_arguments; + return safe_ptr_assign(*primitive_desc, + existing_primitive_desc->clone()); +} + +status_t mkldnn_primitive_desc_iterator_destroy( + primitive_desc_iterator_t *iterator) { + if (iterator != nullptr) + delete iterator; + return success; +} + +status_t mkldnn_primitive_desc_create(primitive_desc_t **primitive_desc, + const_c_op_desc_t c_op_desc, const primitive_attr_t *attr, + engine_t *engine, const primitive_desc_t *hint_fwd_pd) { + const op_desc_t *op_desc = (const op_desc_t *)c_op_desc; + + mkldnn_primitive_desc_iterator it(engine, op_desc, attr, hint_fwd_pd); + ++it; + if (it == it.end()) return unimplemented; + + return safe_ptr_assign(*primitive_desc, *it); +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp new file mode 100644 index 0000000000..4e88ab3aa5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp @@ -0,0 +1,79 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#ifndef PRIMITIVE_ITERATOR_HPP +#define PRIMITIVE_ITERATOR_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "primitive_desc.hpp" +#include "type_helpers.hpp" + +struct mkldnn_primitive_desc_iterator: public mkldnn::impl::c_compatible { + using pd_create_f = mkldnn::impl::engine_t::primitive_desc_create_f; + + mkldnn_primitive_desc_iterator(mkldnn::impl::engine_t *engine, const mkldnn::impl::op_desc_t *op_desc, + const mkldnn::impl::primitive_attr_t *attr, const mkldnn::impl::primitive_desc_t *hint_fwd_pd) + : idx_(-1), engine_(engine), pd_(nullptr), op_desc_(op_desc) + , attr_(attr ? *attr : mkldnn::impl::primitive_attr_t()), hint_fwd_pd_(hint_fwd_pd) + , impl_list_(engine_->get_implementation_list()), last_idx_(0) + { + while (impl_list_[last_idx_] != nullptr) ++last_idx_; + } + ~mkldnn_primitive_desc_iterator() { if (pd_) delete pd_; } + + bool operator==(const mkldnn::impl::primitive_desc_iterator_t& rhs) const + { return idx_ == rhs.idx_ && engine_ == rhs.engine_; } + bool operator!=(const mkldnn::impl::primitive_desc_iterator_t& rhs) const + { return !operator==(rhs); } + + mkldnn::impl::primitive_desc_iterator_t end() const + { return mkldnn_primitive_desc_iterator(engine_, last_idx_); } + + mkldnn::impl::primitive_desc_iterator_t &operator++() { + if (pd_) { delete pd_; pd_ = nullptr; } + while (++idx_ != last_idx_) { + auto s = impl_list_[idx_](&pd_, op_desc_, &attr_, engine_, + hint_fwd_pd_); + if (s == mkldnn::impl::status::success) break; + } + return *this; + } + + mkldnn::impl::primitive_desc_t *operator*() const { + if (*this == end() || pd_ == nullptr) return nullptr; + return pd_->clone(); + } + +protected: + int idx_; + mkldnn::impl::engine_t *engine_; + mkldnn::impl::primitive_desc_t *pd_; + const mkldnn::impl::op_desc_t *op_desc_; + const mkldnn::impl::primitive_attr_t attr_; + const mkldnn::impl::primitive_desc_t *hint_fwd_pd_; + const pd_create_f *impl_list_; + int last_idx_; + +private: + mkldnn_primitive_desc_iterator(mkldnn::impl::engine_t *engine, int last_idx) + : idx_(last_idx), engine_(engine), pd_(nullptr) + , op_desc_(nullptr), hint_fwd_pd_(nullptr) + , impl_list_(nullptr), last_idx_(last_idx) {} +}; + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/query.cpp b/thirdparty/oidn/mkl-dnn/src/common/query.cpp new file mode 100644 index 0000000000..835cd73581 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/query.cpp @@ -0,0 +1,59 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "primitive_desc.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; + +status_t mkldnn_primitive_desc_query(const primitive_desc_t *primitive_desc, + query_t what, int index, void *result) { + if (any_null(primitive_desc, result)) + return invalid_arguments; + + return primitive_desc->query(what, index, result); +} + +const memory_desc_t *mkldnn_primitive_desc_query_md( + const primitive_desc_t *primitive_desc, query_t what, int index) { + const memory_desc_t *res_md = nullptr; + bool args_ok = true + && primitive_desc != nullptr + && (what & query::some_md) == query::some_md + && what != query::some_md + && mkldnn_primitive_desc_query(primitive_desc, + what, index, &res_md) == success; + return args_ok ? res_md : nullptr; +} + +int mkldnn_primitive_desc_query_s32(const primitive_desc_t *primitive_desc, + query_t what, int index) { + int res_s32; + bool args_ok = primitive_desc != nullptr + && one_of(what, query::num_of_inputs_s32, query::num_of_outputs_s32) + && mkldnn_primitive_desc_query(primitive_desc, what, index, &res_s32) + == success; + return args_ok ? res_s32 : 0; +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/reorder.cpp b/thirdparty/oidn/mkl-dnn/src/common/reorder.cpp new file mode 100644 index 0000000000..d11f1a0361 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/reorder.cpp @@ -0,0 +1,68 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "reorder_pd.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; + +status_t mkldnn_reorder_primitive_desc_create( + primitive_desc_t **reorder_pd, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md, + const primitive_attr_t *attr) { + if (any_null(reorder_pd, src_engine, src_md, dst_engine, dst_md)) + return invalid_arguments; + + auto s_ek = src_engine->kind(); + auto d_ek = dst_engine->kind(); + if (!IMPLICATION(s_ek != d_ek, one_of(engine_kind::cpu, s_ek, d_ek))) + return invalid_arguments; + + auto r_pd = reinterpret_cast(reorder_pd); + auto s_mdw = memory_desc_wrapper(*src_md); + auto d_mdw = memory_desc_wrapper(*dst_md); + + if (!s_mdw.consistent_with(d_mdw)) + return invalid_arguments; + + auto e = (s_ek != engine_kind::cpu) ? src_engine : dst_engine; + + const primitive_attr_t dummy_attr; + if (attr == NULL) + attr = &dummy_attr; + + for (auto r = e->get_reorder_implementation_list(); *r; ++r) { + if ((*r)(r_pd, e, attr, src_engine, src_md, dst_engine, dst_md) + == success) { + (*r_pd)->init_info(); + (*r_pd)->init_scratchpad_md(); + return success; + } + } + return unimplemented; +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp new file mode 100644 index 0000000000..963cb0f58a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp @@ -0,0 +1,85 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef REORDER_PD_HPP +#define REORDER_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "primitive_attr.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +struct reorder_pd_t: public primitive_desc_t { + reorder_pd_t(engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) + : primitive_desc_t(engine, attr, primitive_kind::reorder) + , src_engine_(src_engine) + , dst_engine_(dst_engine) + , scratchpad_engine_(nullptr) + , src_md_(*src_md) + , dst_md_(*dst_md) + {} + + virtual const op_desc_t *op_desc() const override { return nullptr; } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_FROM) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_TO) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &src_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &dst_md_ : nullptr; } + + virtual int n_inputs() const override { return 1; } + virtual int n_outputs() const override { return 1; } + + float alpha() const { return attr()->output_scales_.scales_[0]; } + float beta() const { + const int sum_idx = attr()->post_ops_.find(primitive_kind::sum); + return sum_idx == -1 ? 0 : attr()->post_ops_.entry_[sum_idx].sum.scale; + } + virtual mkldnn::impl::engine_t *scratchpad_engine() const override + { return scratchpad_engine_; } + +protected: + engine_t *src_engine_; + engine_t *dst_engine_; + engine_t *scratchpad_engine_; + + memory_desc_t src_md_; + memory_desc_t dst_md_; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/rnn.cpp b/thirdparty/oidn/mkl-dnn/src/common/rnn.cpp new file mode 100644 index 0000000000..36967431a6 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/rnn.cpp @@ -0,0 +1,400 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "cpu/gemm/os_blas.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::types; +using namespace mkldnn::impl::utils; + +namespace { +memory_desc_t copy_maybe_null(const memory_desc_t *md) { + return md ? *md : zero_md(); +} + +rnn_desc_t zero_rnn_desc() { + auto rd = rnn_desc_t(); + rd.src_layer_desc = zero_md(); + rd.src_iter_desc = zero_md(); + rd.weights_layer_desc = zero_md(); + rd.weights_iter_desc = zero_md(); + rd.bias_desc = zero_md(); + rd.dst_layer_desc = zero_md(); + rd.dst_iter_desc = zero_md(); + rd.diff_src_layer_desc = zero_md(); + rd.diff_src_iter_desc = zero_md(); + rd.diff_weights_layer_desc = zero_md(); + rd.diff_weights_iter_desc = zero_md(); + rd.diff_bias_desc = zero_md(); + rd.diff_dst_layer_desc = zero_md(); + rd.diff_dst_iter_desc = zero_md(); + return rd; +} +} + +/* Public C Api */ + +status_t mkldnn_rnn_cell_desc_init(rnn_cell_desc_t *rnn_cell_desc, + mkldnn_alg_kind_t cell_kind, mkldnn_alg_kind_t act_f, + unsigned int flags, float alpha, float clipping) { + using namespace mkldnn::impl::alg_kind; + + bool args_ok = true + && one_of(cell_kind, vanilla_rnn, vanilla_lstm, vanilla_gru, + gru_linear_before_reset) + && IMPLICATION(cell_kind == vanilla_rnn, + one_of(act_f, eltwise_relu, eltwise_tanh, eltwise_logistic)); + if (!args_ok) + return invalid_arguments; + + auto rcd = mkldnn_rnn_cell_desc_t(); + + rcd.cell_kind = cell_kind; + rcd.activation_kind = act_f; + rcd.flags = flags; + rcd.alpha = rcd.flags & mkldnn_rnn_cell_with_relu ? alpha : 0; + rcd.clipping = rcd.flags & mkldnn_rnn_cell_with_clipping ? clipping : 0; + + *rnn_cell_desc = rcd; + + return success; +} + +int mkldnn_rnn_cell_get_gates_count(const rnn_cell_desc_t *rnn_cell_desc) { + switch (rnn_cell_desc->cell_kind) { + case mkldnn::impl::alg_kind::vanilla_rnn: return 1; + case mkldnn::impl::alg_kind::vanilla_gru: return 3; + case mkldnn::impl::alg_kind::gru_linear_before_reset: return 3; + case mkldnn::impl::alg_kind::vanilla_lstm: return 4; + default: assert(!"unknown cell kind"); return 0; + } + return 0; +} + +int mkldnn_rnn_cell_get_states_count(const rnn_cell_desc_t *rnn_cell_desc) { + switch (rnn_cell_desc->cell_kind) { + case mkldnn::impl::alg_kind::vanilla_rnn: return 1; + case mkldnn::impl::alg_kind::vanilla_gru: return 1; + case mkldnn::impl::alg_kind::gru_linear_before_reset: return 1; + case mkldnn::impl::alg_kind::vanilla_lstm: return 2; + default: assert(!"unknown cell kind"); return 0; + } + return 0; +} + +status_t check_data_type_consistency_fwd(const rnn_cell_desc_t *rnn_cell_desc, + prop_kind_t prop_kind, const memory_desc_t *src_layer_desc, + const memory_desc_t *src_iter_desc, + const memory_desc_t *weights_layer_desc, + const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_layer_desc, + const memory_desc_t *dst_iter_desc) { + using namespace data_type; + data_type_t src_layer_dt = src_layer_desc->data_type; + data_type_t dst_layer_dt = dst_layer_desc->data_type; + data_type_t weights_iter_dt = weights_iter_desc->data_type; + data_type_t weights_layer_dt = weights_layer_desc->data_type; + + bool is_f32 = everyone_is(f32, src_layer_dt, dst_layer_dt, weights_iter_dt, + weights_layer_dt) + && IMPLICATION(!is_zero_md(src_iter_desc), + src_iter_desc->data_type == f32) + && IMPLICATION(!is_zero_md(dst_iter_desc), + dst_iter_desc->data_type == f32) + && IMPLICATION(!is_zero_md(bias_desc), bias_desc->data_type == f32); + +#if USE_MKL_PACKED_GEMM + bool is_u8u8u8 = src_layer_dt == u8 + && IMPLICATION(!is_zero_md(src_iter_desc), + src_iter_desc->data_type == u8) + && IMPLICATION(!is_zero_md(dst_iter_desc), + dst_iter_desc->data_type == u8) + && one_of(dst_layer_dt, u8, f32) + && everyone_is(s8, weights_iter_dt, weights_layer_dt) + && IMPLICATION(!is_zero_md(bias_desc), bias_desc->data_type == f32); + + bool is_f32u8f32 = src_layer_dt == u8 + && IMPLICATION(!is_zero_md(src_iter_desc), + src_iter_desc->data_type == f32) + && IMPLICATION(!is_zero_md(dst_iter_desc), + dst_iter_desc->data_type == f32) + && one_of(dst_layer_dt, u8, f32) + && everyone_is(s8, weights_iter_dt, weights_layer_dt) + && IMPLICATION(!is_zero_md(bias_desc), bias_desc->data_type == f32); + + bool is_inference = prop_kind == prop_kind::forward_inference; + bool is_lstm = rnn_cell_desc->cell_kind == mkldnn_vanilla_lstm; + + return (is_f32 || ((is_u8u8u8 || is_f32u8f32) && is_lstm && is_inference)) + ? success + : unimplemented; +#else + return is_f32 ? success : unimplemented; +#endif +} + +status_t check_dim_consistency(const rnn_cell_desc_t *rnn_cell_desc, + rnn_direction_t direction, int L, int D, int T, int N, int S, int G, + int SLC, int SIC, int DLC, int DIC, const memory_desc_t *src_layer_desc, + const memory_desc_t *src_iter_desc, + const memory_desc_t *weights_layer_desc, + const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_layer_desc, + const memory_desc_t *dst_iter_desc) { + bool args_ok; + + // * algorithm specific + args_ok = true + && IMPLICATION(rnn_cell_desc->cell_kind == alg_kind::vanilla_gru, + DIC == SIC); + if (!args_ok) return invalid_arguments; + int extra_bias = + rnn_cell_desc->cell_kind == alg_kind::gru_linear_before_reset; + + // * on num layers + args_ok = true + && L == weights_layer_desc->dims[0] + && L == weights_iter_desc->dims[0] + && IMPLICATION(!is_zero_md(bias_desc), L == bias_desc->dims[0]) + && IMPLICATION(!is_zero_md(src_iter_desc), L == src_iter_desc->dims[0]) + && IMPLICATION(!is_zero_md(dst_iter_desc), L == dst_iter_desc->dims[0]); + if (!args_ok) return invalid_arguments; + + // * on num directions + args_ok = true + && D == weights_layer_desc->dims[1] + && D == weights_iter_desc->dims[1] + && IMPLICATION(!is_zero_md(bias_desc), D == bias_desc->dims[1]) + && IMPLICATION(!is_zero_md(src_iter_desc), D == src_iter_desc->dims[1]) + && IMPLICATION(!is_zero_md(dst_iter_desc), D == dst_iter_desc->dims[1]); + if (!args_ok) return invalid_arguments; + + // * on num iterations + args_ok = true + && T == src_layer_desc->dims[0] + && T == dst_layer_desc->dims[0]; + if (!args_ok) return invalid_arguments; + + // * on mb + args_ok = true + && N == src_layer_desc->dims[1] + && N == dst_layer_desc->dims[1] + && IMPLICATION(!is_zero_md(src_iter_desc), N == src_iter_desc->dims[3]) + && IMPLICATION(!is_zero_md(dst_iter_desc), N == dst_iter_desc->dims[3]); + if (!args_ok) return invalid_arguments; + + // * on num gates + args_ok = true + && G == mkldnn_rnn_cell_get_gates_count(rnn_cell_desc) + && G == weights_layer_desc->dims[3] + && G == weights_iter_desc->dims[3] + && IMPLICATION(!is_zero_md(bias_desc), + G + extra_bias == bias_desc->dims[2]); + if (!args_ok) return invalid_arguments; + + // * on num states + args_ok = true + && S == mkldnn_rnn_cell_get_states_count(rnn_cell_desc) + && IMPLICATION(!is_zero_md(src_iter_desc), S == src_iter_desc->dims[2]) + && IMPLICATION(!is_zero_md(dst_iter_desc), S == dst_iter_desc->dims[2]); + if (!args_ok) return invalid_arguments; + + // * on slc + args_ok = true + && SLC == weights_layer_desc->dims[2] + && SLC == src_layer_desc->dims[2]; + if (!args_ok) return invalid_arguments; + + // * on sic + args_ok = true + && SIC == weights_iter_desc->dims[2] + && IMPLICATION(!is_zero_md(src_iter_desc), + SIC == src_iter_desc->dims[4]); + if (!args_ok) return invalid_arguments; + + // * on dlc + int dlc_multiplier = (direction == mkldnn_bidirectional_concat) ? 2 : 1; + args_ok = true + && DLC == dlc_multiplier * DIC + && DLC == dst_layer_desc->dims[2]; + if (!args_ok) return invalid_arguments; + + // * on dic + args_ok = true + && DIC == weights_layer_desc->dims[4] + && DIC == weights_iter_desc->dims[4] + && IMPLICATION(!is_zero_md(bias_desc), DIC == bias_desc->dims[3]) + && IMPLICATION(!is_zero_md(dst_iter_desc), + DIC == dst_iter_desc->dims[4]); + if (!args_ok) return invalid_arguments; + + // * unrolling/fusion conditions + args_ok = true + && IMPLICATION(L > 1, (dlc_multiplier * SLC) == DLC) + && IMPLICATION(T > 1, SIC == DIC); + if (!args_ok) return invalid_arguments; + + return success; +} + +status_t MKLDNN_API mkldnn_rnn_forward_desc_init(mkldnn_rnn_desc_t *rnn_desc, + prop_kind_t prop_kind, const rnn_cell_desc_t *rnn_cell_desc, + const rnn_direction_t direction, const memory_desc_t *src_layer_desc, + const memory_desc_t *src_iter_desc, + const memory_desc_t *weights_layer_desc, + const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_layer_desc, + const memory_desc_t *dst_iter_desc) { + bool args_ok = true && rnn_cell_desc != nullptr + && !any_null(src_layer_desc, weights_layer_desc, weights_iter_desc, + dst_layer_desc); + if (!args_ok) return invalid_arguments; + + //check dimensions consistency + int L = weights_layer_desc->dims[0]; + int T = src_layer_desc->dims[0]; + int N = src_layer_desc->dims[1]; + const int D = one_of(direction, mkldnn_unidirectional_left2right, + mkldnn_unidirectional_right2left) ? + 1 : + 2; + int G = mkldnn_rnn_cell_get_gates_count(rnn_cell_desc); + int S = mkldnn_rnn_cell_get_states_count(rnn_cell_desc); + int SLC = src_layer_desc->dims[2]; + int SIC = weights_iter_desc->dims[2]; + int DLC = dst_layer_desc->dims[2]; + int DIC = weights_layer_desc->dims[4]; + + CHECK(check_dim_consistency(rnn_cell_desc, direction, L, D, T, N, S, + G, SLC, SIC, DLC, DIC, src_layer_desc, src_iter_desc, + weights_layer_desc, weights_iter_desc, bias_desc, dst_layer_desc, + dst_iter_desc)); + + CHECK(check_data_type_consistency_fwd(rnn_cell_desc, prop_kind, + src_layer_desc, src_iter_desc, weights_layer_desc, + weights_iter_desc, bias_desc, dst_layer_desc, dst_iter_desc)); + + // Create the descriptor + mkldnn_rnn_desc_t rd = zero_rnn_desc(); + + rd.primitive_kind = primitive_kind::rnn; + rd.prop_kind = prop_kind; + rd.cell_desc = *rnn_cell_desc; + rd.direction = direction; + rd.src_layer_desc = copy_maybe_null(src_layer_desc); + rd.src_iter_desc = copy_maybe_null(src_iter_desc); + rd.weights_layer_desc = copy_maybe_null(weights_layer_desc); + rd.weights_iter_desc = copy_maybe_null(weights_iter_desc); + rd.bias_desc = copy_maybe_null(bias_desc); + rd.dst_layer_desc = copy_maybe_null(dst_layer_desc); + rd.dst_iter_desc = copy_maybe_null(dst_iter_desc); + + *rnn_desc = rd; + + return success; +} + +status_t MKLDNN_API mkldnn_rnn_backward_desc_init(mkldnn_rnn_desc_t *rnn_desc, + prop_kind_t prop_kind, const rnn_cell_desc_t *rnn_cell_desc, + const rnn_direction_t direction, const memory_desc_t *src_layer_desc, + const memory_desc_t *src_iter_desc, + const memory_desc_t *weights_layer_desc, + const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc, + const memory_desc_t *dst_layer_desc, const memory_desc_t *dst_iter_desc, + const memory_desc_t *diff_src_layer_desc, + const memory_desc_t *diff_src_iter_desc, + const memory_desc_t *diff_weights_layer_desc, + const memory_desc_t *diff_weights_iter_desc, + const memory_desc_t *diff_bias_desc, + const memory_desc_t *diff_dst_layer_desc, + const memory_desc_t *diff_dst_iter_desc) { + bool args_ok = true + && !any_null(src_layer_desc, weights_layer_desc, weights_iter_desc, + dst_layer_desc, diff_src_layer_desc, + diff_weights_layer_desc, diff_weights_iter_desc, + diff_dst_layer_desc); + if (!args_ok) + return invalid_arguments; + + auto xnor_md = [=](const memory_desc_t *a_md, const memory_desc_t *b_md) { + return is_zero_md(a_md) == is_zero_md(b_md); + }; + + args_ok = args_ok && xnor_md(bias_desc, diff_bias_desc) + && xnor_md(dst_iter_desc, diff_dst_iter_desc) + && xnor_md(src_iter_desc, diff_src_iter_desc); + if (!args_ok) + return invalid_arguments; + + //check dimensions consistency + int L = weights_layer_desc->dims[0]; + int T = src_layer_desc->dims[0]; + int N = src_layer_desc->dims[1]; + const int D = one_of(direction, mkldnn_unidirectional_left2right, + mkldnn_unidirectional_right2left) ? + 1 : + 2; + int G = mkldnn_rnn_cell_get_gates_count(rnn_cell_desc); + int S = mkldnn_rnn_cell_get_states_count(rnn_cell_desc); + int SLC = src_layer_desc->dims[2]; + int SIC = weights_iter_desc->dims[2]; + int DLC = dst_layer_desc->dims[2]; + int DIC = weights_layer_desc->dims[4]; + + status_t st = check_dim_consistency(rnn_cell_desc, direction, L, D, T, N, S, + G, SLC, SIC, DLC, DIC, src_layer_desc, src_iter_desc, + weights_layer_desc, weights_iter_desc, bias_desc, dst_layer_desc, + dst_iter_desc); + if (st != success) return st; + + st = check_dim_consistency(rnn_cell_desc, direction, L, D, T, N, S, + G, SLC, SIC, DLC, DIC, diff_src_layer_desc, diff_src_iter_desc, + diff_weights_layer_desc, diff_weights_iter_desc, diff_bias_desc, + diff_dst_layer_desc, diff_dst_iter_desc); + if (st != success) return st; + + mkldnn_rnn_desc_t rd = zero_rnn_desc(); + + rd.primitive_kind = primitive_kind::rnn; + rd.prop_kind = prop_kind; + rd.cell_desc = *rnn_cell_desc; + rd.direction = direction; + + rd.src_layer_desc = copy_maybe_null(src_layer_desc); + rd.src_iter_desc = copy_maybe_null(src_iter_desc); + rd.weights_layer_desc = copy_maybe_null(weights_layer_desc); + rd.weights_iter_desc = copy_maybe_null(weights_iter_desc); + rd.bias_desc = copy_maybe_null(bias_desc); + rd.dst_layer_desc = copy_maybe_null(dst_layer_desc); + rd.dst_iter_desc = copy_maybe_null(dst_iter_desc); + rd.diff_src_layer_desc = copy_maybe_null(diff_src_layer_desc); + rd.diff_src_iter_desc = copy_maybe_null(diff_src_iter_desc); + rd.diff_weights_layer_desc = copy_maybe_null(diff_weights_layer_desc); + rd.diff_weights_iter_desc = copy_maybe_null(diff_weights_iter_desc); + rd.diff_bias_desc = copy_maybe_null(diff_bias_desc); + rd.diff_dst_layer_desc = copy_maybe_null(diff_dst_layer_desc); + rd.diff_dst_iter_desc = copy_maybe_null(diff_dst_iter_desc); + + *rnn_desc = rd; + + return success; +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp new file mode 100644 index 0000000000..1ee2ba1114 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp @@ -0,0 +1,280 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef RNN_PD_HPP +#define RNN_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" +#include "type_helpers.hpp" + +namespace mkldnn { +namespace impl { + +struct rnn_fwd_pd_t; + +struct rnn_pd_t : public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::rnn; + + rnn_pd_t(engine_t *engine, + const rnn_desc_t *adesc, + const primitive_attr_t *attr, + const rnn_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + , src_layer_md_(desc_.src_layer_desc) + , src_iter_md_(desc_.src_iter_desc) + , weights_layer_md_(desc_.weights_layer_desc) + , weights_iter_md_(desc_.weights_iter_desc) + , bias_md_(desc_.bias_desc) + , dst_layer_md_(desc_.dst_layer_desc) + , dst_iter_md_(desc_.dst_iter_desc) + , ws_md_() + {} + + const rnn_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::rnn_d: *(const rnn_desc_t **)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + virtual const memory_desc_t *src_md(int index = 0) const override { + if (index == 0) return &src_layer_md_; + if (index == 1 && with_src_iter()) return &src_iter_md_; + return nullptr; + } + virtual const memory_desc_t *weights_md(int index = 0) const override { + if (index == 0) return &weights_layer_md_; + if (index == 1) return &weights_iter_md_; + if (index == 2 && with_bias()) return &bias_md_; + return nullptr; + } + virtual const memory_desc_t *dst_md(int index = 0) const override { + if (index == 0) return &dst_layer_md_; + if (index == 1 && with_dst_iter()) return &dst_iter_md_; + return nullptr; + } + virtual const memory_desc_t *workspace_md(int index = 0) const override + { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; } + + /* common pooling aux functions */ + + bool is_training() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::backward); + } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + + dim_t T() const { return desc_.src_layer_desc.dims[0]; } + dim_t MB() const { return desc_.src_layer_desc.dims[1]; } + + dim_t L() const { return desc_.weights_layer_desc.dims[0]; } + dim_t D() const { return desc_.weights_layer_desc.dims[1]; } + + dim_t SIC() const { return desc_.weights_iter_desc.dims[2]; } + + dim_t SLC() const { return desc_.weights_layer_desc.dims[2]; } + dim_t G() const { return desc_.weights_layer_desc.dims[3]; } + dim_t DIC() const { return desc_.weights_layer_desc.dims[4]; } + + dim_t DLC() const { return desc_.dst_layer_desc.dims[2]; } + + bool with_bias() const + { return !memory_desc_wrapper(desc_.bias_desc).is_zero(); } + + bool with_src_iter() const + { return !(memory_desc_wrapper(desc_.src_iter_desc).is_zero()); } + + bool with_dst_iter() const + { return !memory_desc_wrapper(desc_.dst_iter_desc).is_zero(); } + + mkldnn::impl::alg_kind_t cell_kind() const + { return desc_.cell_desc.cell_kind; } + mkldnn::impl::alg_kind_t activation_kind() const + { return desc_.cell_desc.activation_kind; } + + bool is_lbr() const + { return cell_kind() == mkldnn_gru_linear_before_reset; } + + mkldnn_rnn_direction_t direction() const { return desc_.direction; } + +protected: + rnn_desc_t desc_; + const rnn_fwd_pd_t *hint_fwd_pd_; + + memory_desc_t src_layer_md_; + memory_desc_t src_iter_md_; + memory_desc_t weights_layer_md_; + memory_desc_t weights_iter_md_; + memory_desc_t bias_md_; + memory_desc_t dst_layer_md_; + memory_desc_t dst_iter_md_; + + memory_desc_t ws_md_; +}; + +struct rnn_fwd_pd_t: public rnn_pd_t { + typedef rnn_fwd_pd_t base_class; + typedef rnn_fwd_pd_t hint_class; + + rnn_fwd_pd_t(engine_t *engine, + const rnn_desc_t *adesc, + const primitive_attr_t *attr, + const rnn_fwd_pd_t *hint_fwd_pd) + : rnn_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_SRC_LAYER) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_SRC_ITER && with_src_iter()) + return arg_usage_t::input; + + if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS_LAYER, + MKLDNN_ARG_WEIGHTS_ITER)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_BIAS && with_bias()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST_LAYER) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_DST_ITER && with_dst_iter()) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_WORKSPACE && is_training()) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual int n_inputs() const override + { return 3 + with_bias() + with_src_iter(); } + virtual int n_outputs() const override + { return 1 + with_dst_iter() + is_training(); } +}; + +struct rnn_bwd_pd_t : public rnn_pd_t { + typedef rnn_bwd_pd_t base_class; + typedef rnn_fwd_pd_t hint_class; + + rnn_bwd_pd_t(engine_t *engine, + const rnn_desc_t *adesc, + const primitive_attr_t *attr, + const rnn_fwd_pd_t *hint_fwd_pd) + : rnn_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_src_layer_md_(desc_.diff_src_layer_desc) + , diff_src_iter_md_(desc_.diff_src_iter_desc) + , diff_weights_layer_md_(desc_.diff_weights_layer_desc) + , diff_weights_iter_md_(desc_.diff_weights_iter_desc) + , diff_bias_md_(desc_.diff_bias_desc) + , diff_dst_layer_md_(desc_.diff_dst_layer_desc) + , diff_dst_iter_md_(desc_.diff_dst_iter_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_SRC_LAYER, MKLDNN_ARG_DST_LAYER, + MKLDNN_ARG_DIFF_DST_LAYER)) + return arg_usage_t::input; + + if (with_src_iter()) { + if (arg == MKLDNN_ARG_SRC_ITER) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC_ITER) + return arg_usage_t::output; + } + + if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS_LAYER, + MKLDNN_ARG_WEIGHTS_ITER)) + return arg_usage_t::input; + + if (with_bias()) { + if (arg == MKLDNN_ARG_BIAS) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_BIAS) + return arg_usage_t::output; + } + + if (utils::one_of(arg, MKLDNN_ARG_DST_ITER, MKLDNN_ARG_DIFF_DST_ITER) + && with_dst_iter()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_WORKSPACE) + return arg_usage_t::input; + + if (utils::one_of(arg, MKLDNN_ARG_DIFF_SRC_LAYER, + MKLDNN_ARG_DIFF_WEIGHTS_LAYER, + MKLDNN_ARG_DIFF_WEIGHTS_ITER)) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *diff_src_md(int index = 0) const override { + if (index == 0) return &diff_src_layer_md_; + if (index == 1 && with_src_iter()) return &diff_src_iter_md_; + return nullptr; + } + virtual const memory_desc_t *diff_weights_md( + int index = 0) const override { + if (index == 0) return &diff_weights_layer_md_; + if (index == 1) return &diff_weights_iter_md_; + if (index == 2 && with_bias()) return &diff_bias_md_; + return nullptr; + } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override { + if (index == 0) return &diff_dst_layer_md_; + if (index == 1 && with_dst_iter()) return &diff_dst_iter_md_; + return nullptr; + } + + virtual int n_inputs() const override + { return 6 + with_src_iter() + with_bias() + 2 * with_dst_iter(); } + virtual int n_outputs() const override + { return 3 + with_src_iter() + with_bias(); } + +protected: + memory_desc_t diff_src_layer_md_; + memory_desc_t diff_src_iter_md_; + memory_desc_t diff_weights_layer_md_; + memory_desc_t diff_weights_iter_md_; + memory_desc_t diff_bias_md_; + memory_desc_t diff_dst_layer_md_; + memory_desc_t diff_dst_iter_md_; +}; + +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp new file mode 100644 index 0000000000..6bc14fc72a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp @@ -0,0 +1,112 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "scratchpad.hpp" + +namespace mkldnn { +namespace impl { + +/* Allocating memory buffers on a page boundary to reduce TLB/page misses */ +const size_t page_size = 2097152; + +/* + Implementation of the scratchpad_t interface that is compatible with + a concurrent execution +*/ +struct concurent_scratchpad_t : public scratchpad_t { + concurent_scratchpad_t(size_t size) { + size_ = size; + scratchpad_ = (char *) malloc(size, page_size); + assert(scratchpad_ != nullptr); + } + + ~concurent_scratchpad_t() { + free(scratchpad_); + } + + virtual char *get() const { + return scratchpad_; + } + +private: + char *scratchpad_; + size_t size_; +}; + +/* + Implementation of the scratchpad_t interface that uses a global + scratchpad +*/ + +struct global_scratchpad_t : public scratchpad_t { + global_scratchpad_t(size_t size) { + if (size > size_) { + if (scratchpad_ != nullptr) free(scratchpad_); + size_ = size; + scratchpad_ = (char *) malloc(size, page_size); + assert(scratchpad_ != nullptr); + } + reference_count_++; + } + + ~global_scratchpad_t() { + reference_count_--; + if (reference_count_ == 0) { + free(scratchpad_); + scratchpad_ = nullptr; + size_ = 0; + } + } + + virtual char *get() const { + return scratchpad_; + } + +private: + /* + Using thread-local here is unnecessary and even buggy! All threads + actually share the same scratchpad, which is created and queried only + on the main thread. If the scratchpad is queried on some thread other + than the one it was created on (e.g. the application calls the API from + multiple threads), thread-local causes a segfault because the scratchpad + is uninitialized on the current thread. + */ + /*thread_local*/ static char *scratchpad_; + /*thread_local*/ static size_t size_; + /*thread_local*/ static unsigned int reference_count_; +}; + +/*thread_local*/ char *global_scratchpad_t::scratchpad_ = nullptr; +/*thread_local*/ size_t global_scratchpad_t::size_ = 0; +/*thread_local*/ unsigned int global_scratchpad_t::reference_count_ = 0; + + +/* + Scratchpad creation routine +*/ +scratchpad_t *create_scratchpad(size_t size) { +#ifndef MKLDNN_ENABLE_CONCURRENT_EXEC + return new global_scratchpad_t(size); +#else + return new concurent_scratchpad_t(size); +#endif +} + +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp new file mode 100644 index 0000000000..f7a246bc99 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp @@ -0,0 +1,36 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef COMMON_SCRATCHPAD_HPP +#define COMMON_SCRATCHPAD_HPP + +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +struct scratchpad_t { + virtual ~scratchpad_t() {} + virtual char *get() const = 0; +}; + +scratchpad_t *create_scratchpad(size_t size); + +} +} +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp b/thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp new file mode 100644 index 0000000000..e32e735224 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp @@ -0,0 +1,72 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t shuffle_desc_init(shuffle_desc_t *shuffle_desc, prop_kind_t prop_kind, + const memory_desc_t *data_desc, int axis, dim_t group_size) { + bool args_ok = true + && !any_null(shuffle_desc, data_desc) + && one_of(prop_kind, forward_training, forward_inference, + backward, backward_data) + && axis >= 0 && axis < data_desc->ndims + && group_size > 0 && group_size <= data_desc->dims[axis]; + if (!args_ok) return invalid_arguments; + + auto sd = shuffle_desc_t(); + sd.primitive_kind = primitive_kind::shuffle; + sd.prop_kind = prop_kind; + sd.data_desc = *data_desc; + sd.axis = axis; + sd.group_size = group_size; + + bool consistency = true + && sd.data_desc.dims[axis] % sd.group_size == 0; + if (!consistency) return invalid_arguments; + + *shuffle_desc = sd; + return success; +} +} + +status_t mkldnn_shuffle_forward_desc_init(shuffle_desc_t *shuffle_desc, + prop_kind_t prop_kind, const memory_desc_t *data_desc, int axis, + dim_t group_size) { + if (!one_of(prop_kind, forward_training, forward_inference)) + return invalid_arguments; + return shuffle_desc_init(shuffle_desc, prop_kind, data_desc, axis, + group_size); +} + +status_t mkldnn_shuffle_backward_desc_init(shuffle_desc_t *shuffle_desc, + const memory_desc_t *diff_data_desc, int axis, dim_t group_size) { + return shuffle_desc_init(shuffle_desc, backward_data, diff_data_desc, axis, + group_size); +} + +// vim: et ts=5 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp new file mode 100644 index 0000000000..cc5553fe7f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp @@ -0,0 +1,121 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef SHUFFLE_PD_HPP +#define SHUFFLE_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" + +namespace mkldnn { +namespace impl { + +struct shuffle_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::shuffle; + + typedef shuffle_pd_t base_class; + typedef shuffle_pd_t hint_class; + + shuffle_pd_t(engine_t *engine, + const shuffle_desc_t *adesc, + const primitive_attr_t *attr, + const shuffle_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + , data_md_(desc_.data_desc) + {} + + const shuffle_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::shuffle_d: + *(const shuffle_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (is_fwd()) { + if (arg == MKLDNN_ARG_SRC) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + } else { + if (arg == MKLDNN_ARG_DIFF_DST) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + } + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 && is_fwd() ? &data_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 && is_fwd() ? &data_md_ : nullptr; } + + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 && !is_fwd() ? &data_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 && !is_fwd() ? &data_md_ : nullptr; } + + virtual int n_inputs() const override { return 1; } + virtual int n_outputs() const override { return 1; } + + /* shuffle aux functions */ + + dim_t MB() const { return data_md()->dims[0]; } + dim_t C() const { return ndims() >= 2 ? data_md()->dims[1] : 1; } + dim_t D() const { return ndims() >= 5 ? data_md()->dims[ndims() - 3] : 1; } + dim_t H() const { return ndims() >= 4 ? data_md()->dims[ndims() - 2] : 1; } + dim_t W() const { return ndims() >= 3 ? data_md()->dims[ndims() - 1] : 1; } + + int ndims() const { return data_md()->ndims; } + + int axis() const { return desc_.axis; } + dim_t group_size() const { return desc_.group_size; } + dim_t axis_size() const { return data_md()->dims[axis()]; } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + + const memory_desc_t *data_md() const { return &data_md_; } + +protected: + shuffle_desc_t desc_; + const shuffle_pd_t *hint_fwd_pd_; + memory_desc_t data_md_; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/softmax.cpp b/thirdparty/oidn/mkl-dnn/src/common/softmax.cpp new file mode 100644 index 0000000000..82848e3d1f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/softmax.cpp @@ -0,0 +1,68 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "memory_desc_wrapper.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::alg_kind; +using namespace mkldnn::impl::types; + +namespace { +status_t softmax_desc_init(softmax_desc_t *softmax_desc, prop_kind_t prop_kind, + const memory_desc_t *data_desc, const memory_desc_t *diff_desc, int softmax_axis) { + bool args_ok = true + && !any_null(softmax_desc, data_desc) + && 0 <= softmax_axis + && softmax_axis < data_desc->ndims; + if (!args_ok) return invalid_arguments; + + auto sd = softmax_desc_t(); + sd.primitive_kind = primitive_kind::softmax; + sd.prop_kind = prop_kind; + + bool is_bwd = (sd.prop_kind == backward_data); + sd.data_desc = *data_desc; + sd.diff_desc = is_bwd ? *diff_desc : zero_md(); + sd.softmax_axis = softmax_axis; + + *softmax_desc = sd; + return success; +} +} + +status_t mkldnn_softmax_forward_desc_init(softmax_desc_t *softmax_desc, + prop_kind_t prop_kind, const memory_desc_t *data_desc, + int softmax_axis) { + if (!one_of(prop_kind, forward_inference, forward_training)) + return invalid_arguments; + return softmax_desc_init(softmax_desc, prop_kind, data_desc, nullptr, softmax_axis); +} + +status_t mkldnn_softmax_backward_desc_init(softmax_desc_t *softmax_desc, + const memory_desc_t *diff_desc, const mkldnn_memory_desc_t *data_desc, + int softmax_axis) { + return softmax_desc_init(softmax_desc, prop_kind::backward_data, + data_desc, diff_desc, softmax_axis); +} +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp new file mode 100644 index 0000000000..8a16ce901c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp @@ -0,0 +1,161 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef SOFTMAX_PD_HPP +#define SOFTMAX_PD_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "primitive_desc.hpp" + +namespace mkldnn { +namespace impl { + +struct softmax_fwd_pd_t; + +struct softmax_pd_t: public primitive_desc_t { + static constexpr auto base_pkind = primitive_kind::softmax; + + softmax_pd_t(engine_t *engine, + const softmax_desc_t *adesc, + const primitive_attr_t *attr, + const softmax_fwd_pd_t *hint_fwd_pd) + : primitive_desc_t(engine, attr, base_pkind) + , desc_(*adesc) + , hint_fwd_pd_(hint_fwd_pd) + , data_md_(desc_.data_desc) + {} + + const softmax_desc_t *desc() const { return &desc_; } + virtual const op_desc_t *op_desc() const override + { return reinterpret_cast(this->desc()); } + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual status_t query(query_t what, int idx, void *result) const override { + switch (what) { + case query::softmax_d: + *(const softmax_desc_t**)result = desc(); break; + default: return primitive_desc_t::query(what, idx, result); + } + return status::success; + } + + /* common softmax aux functions */ + + dim_t MB() const { return data_desc().dims[0]; } + dim_t C() const { return data_desc().dims[1]; } + dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; } + dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; } + dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; } + + int ndims() const { return data_desc().ndims; } + + bool is_fwd() const { + return utils::one_of(desc_.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + } + +protected: + softmax_desc_t desc_; + const softmax_fwd_pd_t *hint_fwd_pd_; + + memory_desc_t data_md_; + +private: + const memory_desc_t &data_desc() const { return desc_.data_desc; } +}; + +struct softmax_fwd_pd_t: public softmax_pd_t { + typedef softmax_fwd_pd_t base_class; + typedef softmax_fwd_pd_t hint_class; + + softmax_fwd_pd_t(engine_t *engine, + const softmax_desc_t *adesc, + const primitive_attr_t *attr, + const softmax_fwd_pd_t *hint_fwd_pd) + : softmax_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg == MKLDNN_ARG_SRC) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr)) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + + virtual int n_inputs() const override { return 1; } + virtual int n_outputs() const override + { return 1 + (workspace_md() != nullptr); } +}; + +struct softmax_bwd_pd_t: public softmax_pd_t { + typedef softmax_bwd_pd_t base_class; + typedef softmax_fwd_pd_t hint_class; + + softmax_bwd_pd_t(engine_t *engine, + const softmax_desc_t *adesc, + const primitive_attr_t *attr, + const softmax_fwd_pd_t *hint_fwd_pd) + : softmax_pd_t(engine, adesc, attr, hint_fwd_pd) + , diff_data_md_(desc_.diff_desc) + {} + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (utils::one_of(arg, MKLDNN_ARG_DST, MKLDNN_ARG_DIFF_DST)) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DIFF_SRC) + return arg_usage_t::output; + + if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr)) + return arg_usage_t::input; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &data_md_ : nullptr; } + virtual const memory_desc_t *diff_dst_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + virtual const memory_desc_t *diff_src_md(int index = 0) const override + { return index == 0 ? &diff_data_md_ : nullptr; } + + virtual int n_inputs() const override + { return 2 + (workspace_md() != nullptr); } + virtual int n_outputs() const override { return 1; } + +protected: + memory_desc_t diff_data_md_; +}; + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/stream.cpp b/thirdparty/oidn/mkl-dnn/src/common/stream.cpp new file mode 100644 index 0000000000..00af8935c0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/stream.cpp @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "stream.hpp" +#include "utils.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::status; + +/* API */ + +status_t mkldnn_stream_create(stream_t **stream, engine_t *engine, + unsigned flags) { + bool args_ok = true + && !utils::any_null(stream, engine) + && flags == stream_flags::default_flags; + if (!args_ok) + return invalid_arguments; + + return safe_ptr_assign(*stream, new stream_t(engine, flags)); +} + +status_t mkldnn_stream_destroy(stream_t *stream) { + delete stream; + return success; +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/stream.hpp b/thirdparty/oidn/mkl-dnn/src/common/stream.hpp new file mode 100644 index 0000000000..f010e5f6ed --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/stream.hpp @@ -0,0 +1,44 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef STREAM_HPP +#define STREAM_HPP + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" + +struct mkldnn_stream: public mkldnn::impl::c_compatible { + mkldnn_stream(mkldnn::impl::engine_t *engine, unsigned flags) + : engine_(engine), flags_(flags) {} + virtual ~mkldnn_stream() {} + + /** returns stream's engine */ + mkldnn::impl::engine_t *engine() const { return engine_; } + + /** returns stream's kind */ + unsigned flags() const { return flags_; } + +protected: + mkldnn::impl::engine_t *engine_; + unsigned flags_; +}; + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/sum.cpp b/thirdparty/oidn/mkl-dnn/src/common/sum.cpp new file mode 100644 index 0000000000..365663c0f8 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/sum.cpp @@ -0,0 +1,79 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "engine.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "sum_pd.hpp" + +using namespace mkldnn::impl; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::status; + +status_t mkldnn_sum_primitive_desc_create(primitive_desc_t **sum_pd, + const memory_desc_t *dst_md, int n, const float *scales, + const memory_desc_t *src_mds, const primitive_attr_t *attr, + engine_t *engine) { + bool args_ok = !any_null(sum_pd, src_mds, scales) && n > 0; + if (!args_ok) return invalid_arguments; + + const primitive_attr_t dummy_attr; + if (attr == NULL) + attr = &dummy_attr; + + const int ndims = src_mds[0].ndims; + const dims_t &dims = src_mds[0].dims; + const data_type_t dt = src_mds[0].data_type; + + for (int i = 1; i < n; ++i) { + if (src_mds[i].ndims != ndims) return invalid_arguments; + for (int d = 0; d < ndims; ++d) { + if (src_mds[i].dims[d] != dims[d]) + return invalid_arguments; + } + if (src_mds[i].data_type != dt) return invalid_arguments; + } + + memory_desc_t dummy_dst_md; + if (dst_md) { + if (dst_md->ndims != ndims) return invalid_arguments; + for (int d = 0; d < ndims; ++d) { + if (dst_md->dims[d] != dims[d]) + return invalid_arguments; + } + } else { + dummy_dst_md = src_mds[0]; + dummy_dst_md.format_kind = format_kind::any; + dst_md = &dummy_dst_md; + } + + auto s_pd = reinterpret_cast(sum_pd); + + for (auto s = engine->get_sum_implementation_list(); *s; ++s) { + if ((*s)(s_pd, engine, attr, dst_md, n, scales, src_mds) == success) { + (*s_pd)->init_info(); + (*s_pd)->init_scratchpad_md(); + return success; + } + } + return unimplemented; +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp new file mode 100644 index 0000000000..80254667df --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp @@ -0,0 +1,143 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef SUM_PD_HPP +#define SUM_PD_HPP + +#include +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "primitive_desc.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +struct sum_pd_t: public primitive_desc_t { + sum_pd_t(engine_t *engine, const primitive_attr_t *attr, + const memory_desc_t *dst_md, int n, const float *scales, + const memory_desc_t *src_mds) + : primitive_desc_t(engine, attr, primitive_kind::sum) + , n_(n), dst_md_(*dst_md) + { + scales_.reserve(n_); + for (int i = 0; i < n_; ++i) scales_.push_back(scales[i]); + src_mds_.reserve(n_); + for (int i = 0; i < n_; ++i) src_mds_.push_back(src_mds[i]); + } + + virtual void init_info() override { impl::init_info(this, this->info_); } + + virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override { + if (arg >= MKLDNN_ARG_MULTIPLE_SRC + && arg < MKLDNN_ARG_MULTIPLE_SRC + n_inputs()) + return arg_usage_t::input; + + if (arg == MKLDNN_ARG_DST) + return arg_usage_t::output; + + return primitive_desc_t::arg_usage(arg); + } + + virtual const memory_desc_t *src_md(int index = 0) const override + { return index < n_inputs() ? &src_mds_[index] : nullptr; } + virtual const memory_desc_t *dst_md(int index = 0) const override + { return index == 0 ? &dst_md_ : nullptr; } + + virtual int n_inputs() const override { return n_; } + virtual int n_outputs() const override { return 1; } + + const float *scales() const { return &scales_[0]; } + +protected: + int n_; + nstl::vector scales_; + memory_desc_t dst_md_; + nstl::vector src_mds_; + +protected: + /* inits dst_md_ in simple cases. The call may fail. */ + status_t init() { + for (int i = 0; i < n_; ++i) { + const memory_desc_wrapper src_d(&src_mds_[i]); + if (!src_d.is_blocking_desc() || src_d.is_additional_buffer()) + return status::unimplemented; + } + bool ok = true + && set_default_params() == status::success + && attr()->has_default_values(); + return ok ? status::success : status::unimplemented; + } + + status_t set_default_params() { + if (dst_md_.format_kind != format_kind::any) + return status::success; + + /* The stupidest ever heuristics (but not the same as we had before): + * - Pick the first non-plain format; + * - If all formats are plain, pick the format of the first input + */ + for (int i = 0; i < n_; ++i) { + const memory_desc_wrapper src_d(src_mds_[i]); + if (!src_d.is_plain() && src_d.is_blocking_desc()) { + return memory_desc_init_by_blocking_desc(dst_md_, + src_d.blocking_desc()); + } + } + + if (src_mds_[0].format_kind != format_kind::blocked) + return status::unimplemented; + + dst_md_ = src_mds_[0]; + + return status::success; + } +}; + +#define DECLARE_SUM_PD_t(impl_name, ...) \ + static status_t create(sum_pd_t **sum_pd, \ + engine_t *engine, const primitive_attr_t *attr, \ + const memory_desc_t *dst_md, int n, const float *scales, \ + const memory_desc_t *src_mds) { \ + using namespace status; \ + auto _pd = new pd_t(engine, attr, dst_md, n, scales, src_mds); \ + if (_pd == nullptr) return out_of_memory; \ + if (_pd->init() != success) { delete _pd; return unimplemented; } \ + return safe_ptr_assign(*sum_pd, _pd); \ + } \ + virtual status_t create_primitive(primitive_t **p) const override { \ + double ms = get_msec(); \ + auto ret = safe_ptr_assign(*p, new (__VA_ARGS__)(this)); \ + ms = get_msec() - ms; \ + if (mkldnn_verbose()->level >= 2) { \ + printf("mkldnn_verbose,create,%s,%g\n", this->info(), ms); \ + fflush(0); \ + } \ + return ret; \ + } \ + virtual pd_t *clone() const override { return new pd_t(*this); } \ + virtual const char *name() const override { return impl_name; } \ + +#define DECLARE_SUM_PD_T(impl_name, ...) \ + DECLARE_SUM_PD_t(impl_name, __VA_ARGS__) + +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp b/thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp new file mode 100644 index 0000000000..a408f45980 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp @@ -0,0 +1,200 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef TAG_TRAITS_HPP +#define TAG_TRAITS_HPP + +#include + +#include "c_types_map.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +enum class block_dim_t { + _, + _A, _B, + _AB, _BC, +}; + +enum class inner_blk_t { + _, + _4a, _4b, + _8a, _8b, + _16a, _16b, + + _4b4a, _4b4c, _4c4b, + _8a8b, _8b8a, _8b8c, _8c8b, + _16a16b, _16a4b, _16b16a, _16b4c, _16b16c, _16c16b, + + _2c8b4c, _8a16b2a, _4b16a4b, _8b16a2b, _8b16c2b, _4c16b4c, _8c16b2c, +}; + +/** returns the offset within the block for weights blocked over oc and ic */ +template +constexpr int AB_or_BC_blk_off(int x0, int x1) { + using ib = inner_blk_t; + static_assert(utils::one_of(f, ib::_4b4a, ib::_4b4c, ib::_4c4b, ib::_8a8b, + ib::_8b8a, ib::_8b8c, ib::_8c8b, ib::_16a16b, ib::_16a4b, + ib::_16b16a, ib::_16b4c, ib::_16b16c, ib::_16c16b, ib::_2c8b4c, + ib::_8a16b2a, ib::_4b16a4b, ib::_8b16a2b, ib::_8b16c2b, + ib::_4c16b4c, ib::_8c16b2c), + "unexpected inner_blk format"); + return false ? 0 + : (f == ib::_4b4c) ? 4 * x0 + x1 + : (f == ib::_4b4a || f == ib::_4c4b) ? 4 * x1 + x0 + : (f == ib::_8a8b || f == ib::_8b8c) ? 8 * x0 + x1 + : (f == ib::_8b8a || f == ib::_8c8b) ? 8 * x1 + x0 + : (f == ib::_16a16b || f == ib::_16b16c) ? 16 * x0 + x1 + : (f == ib::_16b16a || f == ib::_16c16b) ? 16 * x1 + x0 + : (f == ib::_16a4b || f == ib::_16b4c) ? 4 * x0 + x1 + : (f == ib::_8a16b2a || f == ib::_8b16c2b) ? (x0 / 2) * 32 + x1 * 2 + x0 % 2 + : (f == ib::_4b16a4b || f == ib::_4c16b4c) ? (x1 / 4) * 64 + x0 * 4 + x1 % 4 + : (f == ib::_8b16a2b || f == ib::_8c16b2c) ? (x1 / 2) * 32 + x0 * 2 + x1 % 2 + : (f == ib::_2c8b4c) ? (x1 / 4) * 32 + x0 * 4 + x1 % 4 + : INT_MIN; +} + +template struct inner_blk_traits { + using ib = inner_blk_t; +}; + +template struct tag_traits { + // block_dim_t block_dims; + // inner_blk_t inner_blks; + // int ndims; +}; + +#define DECL_TRAITS(_tag, _blk_fmt, _inner_blk, _ndims) \ +template <> struct tag_traits { \ + static constexpr block_dim_t block_dims = block_dim_t::_blk_fmt; \ + static constexpr inner_blk_t inner_blks = inner_blk_t::_inner_blk; \ + static constexpr int ndims = _ndims; \ +} + +DECL_TRAITS(a, _, _, 1); +DECL_TRAITS(ab, _, _, 2); +DECL_TRAITS(abc, _, _, 3); +DECL_TRAITS(abcd, _, _, 4); +DECL_TRAITS(abcde, _, _, 5); +DECL_TRAITS(abcdef, _, _, 6); +DECL_TRAITS(abdec, _, _, 5); +DECL_TRAITS(acb, _, _, 3); +DECL_TRAITS(acbde, _, _, 5); +DECL_TRAITS(acdb, _, _, 4); +DECL_TRAITS(acdeb, _, _, 5); +DECL_TRAITS(ba, _, _, 2); +DECL_TRAITS(bac, _, _, 3); +DECL_TRAITS(bacd, _, _, 4); +DECL_TRAITS(bcda, _, _, 4); +DECL_TRAITS(cba, _, _, 3); +DECL_TRAITS(cdba, _, _, 4); +DECL_TRAITS(cdeba, _, _, 5); +DECL_TRAITS(decab, _, _, 5); + +DECL_TRAITS(Abc4a, _A, _4a, 3); +DECL_TRAITS(aBc4b, _B, _4b, 3); +DECL_TRAITS(ABc4b16a4b, _AB, _4b16a4b, 3); +DECL_TRAITS(ABc4b4a, _AB, _4b4a, 3); +DECL_TRAITS(Abcd4a, _A, _4a, 4); +DECL_TRAITS(aBcd4b, _B, _4b, 4); +DECL_TRAITS(ABcd4b4a, _AB, _4b4a, 4); +DECL_TRAITS(aBCd4c16b4c, _BC, _4c16b4c, 4); +DECL_TRAITS(aBCd4c4b, _BC, _4c4b, 4); +DECL_TRAITS(Abcde4a, _A, _4a, 5); +DECL_TRAITS(aBcde4b, _B, _4b, 5); +DECL_TRAITS(ABcde4b4a, _AB, _4b4a, 5); +DECL_TRAITS(aBCde4c4b, _BC, _4c4b, 5); +DECL_TRAITS(aBcdef4b, _B, _4b, 6); +DECL_TRAITS(aBCdef4c4b, _BC, _4c4b, 6); +DECL_TRAITS(aBdc4b, _B, _4b, 4); +DECL_TRAITS(aBdec4b, _B, _4b, 5); +DECL_TRAITS(aBdefc4b, _B, _4b, 6); +DECL_TRAITS(Acb4a, _A, _4a, 3); +DECL_TRAITS(Acdb4a, _A, _4a, 4); +DECL_TRAITS(Acdeb4a, _A, _4a, 5); + +DECL_TRAITS(Abc16a, _A, _16a, 3); +DECL_TRAITS(ABc16a16b, _AB, _16a16b, 3); +DECL_TRAITS(aBc16b, _B, _16b, 3); +DECL_TRAITS(ABc16b16a, _AB, _16b16a, 3); +DECL_TRAITS(ABc8a16b2a, _AB, _8a16b2a, 3); +DECL_TRAITS(ABc8a8b, _AB, _8a8b, 3); +DECL_TRAITS(aBc8b, _B, _8b, 3); +DECL_TRAITS(ABc8b16a2b, _AB, _8b16a2b, 3); +DECL_TRAITS(ABc8b8a, _AB, _8b8a, 3); +DECL_TRAITS(Abcd16a, _A, _16a, 4); +DECL_TRAITS(ABcd16a16b, _AB, _16a16b, 4); +DECL_TRAITS(aBcd16b, _B, _16b, 4); +DECL_TRAITS(ABcd16b16a, _AB, _16b16a, 4); +DECL_TRAITS(aBCd16b16c, _BC, _16b16c, 4); +DECL_TRAITS(aBCd16c16b, _BC, _16c16b, 4); +DECL_TRAITS(ABcd4b16a4b, _AB, _4b16a4b, 4); +DECL_TRAITS(ABcd8a16b2a, _AB, _8a16b2a, 4); +DECL_TRAITS(ABcd8a8b, _AB, _8a8b, 4); +DECL_TRAITS(aBcd8b, _B, _8b, 4); +DECL_TRAITS(ABcd8b16a2b, _AB, _8b16a2b, 4); +DECL_TRAITS(aBCd8b16c2b, _BC, _8b16c2b, 4); +DECL_TRAITS(ABcd8b8a, _AB, _8b8a, 4); +DECL_TRAITS(aBCd8b8c, _BC, _8b8c, 4); +DECL_TRAITS(aBCd8c16b2c, _BC, _8c16b2c, 4); +DECL_TRAITS(aBCd8c8b, _BC, _8c8b, 4); +DECL_TRAITS(Abcde16a, _A, _16a, 5); +DECL_TRAITS(ABcde16a16b, _AB, _16a16b, 5); +DECL_TRAITS(aBcde16b, _B, _16b, 5); +DECL_TRAITS(ABcde16b16a, _AB, _16b16a, 5); +DECL_TRAITS(aBCde16b16c, _BC, _16b16c, 5); +DECL_TRAITS(aBCde16c16b, _BC, _16c16b, 5); +DECL_TRAITS(aBCde4c16b4c, _BC, _4c16b4c, 5); +DECL_TRAITS(Abcde8a, _A, _8a, 5); +DECL_TRAITS(ABcde8a8b, _AB, _8a8b, 5); +DECL_TRAITS(aBcde8b, _B, _8b, 5); +DECL_TRAITS(ABcde8b16a2b, _AB, _8b16a2b, 5); +DECL_TRAITS(aBCde8b16c2b, _BC, _8b16c2b, 5); +DECL_TRAITS(ABcde8b8a, _AB, _8b8a, 5); +DECL_TRAITS(aBCde8b8c, _BC, _8b8c, 5); +DECL_TRAITS(aBCde2c8b4c, _BC, _2c8b4c, 5); +DECL_TRAITS(aBCde8c16b2c, _BC, _8c16b2c, 5); +DECL_TRAITS(aBCde4b4c, _BC, _4b4c, 5); +DECL_TRAITS(aBCde8c8b, _BC, _8c8b, 5); +DECL_TRAITS(aBcdef16b, _B, _16b, 6); +DECL_TRAITS(aBCdef16b16c, _BC, _16b16c, 6); +DECL_TRAITS(aBCdef16c16b, _BC, _16c16b, 6); +DECL_TRAITS(aBCdef8b8c, _BC, _8b8c, 6); +DECL_TRAITS(aBCdef8c16b2c, _BC, _8c16b2c, 6); +DECL_TRAITS(aBCdef8c8b, _BC, _8c8b, 6); +DECL_TRAITS(aBdc16b, _B, _16b, 4); +DECL_TRAITS(aBdc8b, _B, _8b, 4); +DECL_TRAITS(aBdec16b, _B, _16b, 5); +DECL_TRAITS(aBdec8b, _B, _8b, 5); +DECL_TRAITS(aBdefc16b, _B, _16b, 6); +DECL_TRAITS(aBdefc8b, _B, _8b, 6); +DECL_TRAITS(Acb16a, _A, _16a, 3); +DECL_TRAITS(Acb8a, _A, _8a, 3); +DECL_TRAITS(aCBd16b16c, _BC, _16b16c, 4); +DECL_TRAITS(aCBde16b16c, _BC, _16b16c, 5); +DECL_TRAITS(Acdb16a, _A, _16a, 4); +DECL_TRAITS(Acdb8a, _A, _8a, 4); +DECL_TRAITS(Acdeb16a, _A, _16a, 5); +DECL_TRAITS(Acdeb8a, _A, _8a, 5); +DECL_TRAITS(BAc16a16b, _AB, _16a16b, 3); +DECL_TRAITS(BAcd16a16b, _AB, _16a16b, 4); + +} // namespace impl +} // namespace mkldnn + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp b/thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp new file mode 100644 index 0000000000..4f06368738 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp @@ -0,0 +1,348 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef TYPE_HELPERS_HPP +#define TYPE_HELPERS_HPP + +#include +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "mkldnn_traits.hpp" +#include "nstl.hpp" +#include "utils.hpp" +#include "math_utils.hpp" + +namespace mkldnn { +namespace impl { + +template +status_t safe_ptr_assign(T * &lhs, T* rhs) { + if (rhs == nullptr) return status::out_of_memory; + lhs = rhs; + return status::success; +} + +template struct is_subset +{ static constexpr bool value = false; }; +template struct is_subset +{ static constexpr bool value = true; }; +template struct is_subset::value, float>::type> +{ static constexpr bool value = true; }; +#define ISSPEC(t1, t2) template <> \ + struct is_subset { static constexpr bool value = true; } +ISSPEC(int16_t, int32_t); +ISSPEC(int8_t, int32_t); +ISSPEC(uint8_t, int32_t); +ISSPEC(int8_t, int16_t); +ISSPEC(uint8_t, int16_t); +#undef ISSPEC + +inline bool operator==(const memory_desc_t &lhs, const memory_desc_t &rhs); + +namespace types { + +inline size_t data_type_size(data_type_t data_type) { + using namespace data_type; + switch (data_type) { + case f32: return sizeof(prec_traits::type); + case s32: return sizeof(prec_traits::type); + case s8: return sizeof(prec_traits::type); + case u8: return sizeof(prec_traits::type); + case data_type::undef: + default: assert(!"unknown data_type"); + } + return 0; /* not supposed to be reachable */ +} + +inline format_kind_t format_tag_to_kind(format_tag_t tag) { + switch (tag) { + case format_tag::undef: return format_kind::undef; + case format_tag::any: return format_kind::any; + case format_tag::last: return format_kind::undef; + default: return format_kind::blocked; + } + + assert(!"unreachable"); + return format_kind::undef; +} + +inline bool memory_extra_desc_is_equal(const memory_extra_desc_t &lhs, + const memory_extra_desc_t &rhs) { + return true + && lhs.flags == rhs.flags + && IMPLICATION(lhs.flags & memory_extra_flags::compensation_conv_s8s8, + lhs.compensation_mask == rhs.compensation_mask) + && IMPLICATION(lhs.flags & memory_extra_flags::scale_adjust, + lhs.scale_adjust == rhs.scale_adjust); +} + +inline bool blocking_desc_is_equal(const blocking_desc_t &lhs, + const blocking_desc_t &rhs, int ndims = MKLDNN_MAX_NDIMS) { + using mkldnn::impl::utils::array_cmp; + return true + && lhs.inner_nblks == rhs.inner_nblks + && array_cmp(lhs.strides, rhs.strides, ndims) + && array_cmp(lhs.inner_blks, rhs.inner_blks, lhs.inner_nblks) + && array_cmp(lhs.inner_idxs, rhs.inner_idxs, lhs.inner_nblks); +} + +inline bool wino_desc_is_equal(const wino_desc_t &lhs, + const wino_desc_t &rhs) { + return lhs.wino_format == rhs.wino_format + && lhs.alpha == rhs.alpha + && lhs.ic == rhs.ic + && lhs.oc == rhs.oc + && lhs.ic_block == rhs.ic_block + && lhs.oc_block == rhs.oc_block + && lhs.ic2_block == rhs.ic2_block + && lhs.oc2_block == rhs.oc2_block + && lhs.r == rhs.r; +} + +inline bool rnn_packed_desc_is_equal( + const rnn_packed_desc_t &lhs, const rnn_packed_desc_t &rhs) { + bool ok = true + && lhs.format == rhs.format + && lhs.n_parts == rhs.n_parts + && lhs.offset_compensation == rhs.offset_compensation + && lhs.size == rhs.size + && lhs.n == rhs.n; + if (!ok) + return false; + + for (int i = 0; i < rhs.n_parts; i++) + ok = ok && lhs.parts[i] == rhs.parts[i]; + for (int i = 0; i < rhs.n_parts; i++) + ok = ok && lhs.part_pack_size[i] == rhs.part_pack_size[i]; + return ok; +} + +inline memory_desc_t zero_md() { + auto zero = memory_desc_t(); + return zero; +} + +inline bool is_zero_md(const memory_desc_t *md) { + return md == nullptr || *md == zero_md(); +} + +inline data_type_t default_accum_data_type(data_type_t src_dt, + data_type_t dst_dt) { + using namespace utils; + using namespace data_type; + + if (one_of(f32, src_dt, dst_dt)) return f32; + if (one_of(s32, src_dt, dst_dt)) return s32; + + if (one_of(s8, src_dt, dst_dt) || one_of(u8, src_dt, dst_dt)) return s32; + + assert(!"unimplemented use-case: no default parameters available"); + return dst_dt; +} + +inline data_type_t default_accum_data_type(data_type_t src_dt, + data_type_t wei_dt, data_type_t dst_dt, prop_kind_t prop_kind) { + using namespace utils; + using namespace data_type; + using namespace prop_kind; + + /* prop_kind doesn't matter */ + if (everyone_is(f32, src_dt, wei_dt, dst_dt)) return f32; + + if (one_of(prop_kind, forward_training, forward_inference)) { + if ((src_dt == u8 || src_dt == s8) + && wei_dt == s8 && one_of(dst_dt, f32, s32, s8, u8)) + return s32; + } else if (prop_kind == backward_data) { + if (one_of(src_dt, f32, s32, s8, u8) && wei_dt == s8 && + one_of(dst_dt, s8, u8)) + return s32; + } + + assert(!"unimplemented use-case: no default parameters available"); + return dst_dt; +} + +} + +inline bool operator==(const memory_desc_t &lhs, const memory_desc_t &rhs) { + using namespace mkldnn::impl::utils; + bool base_equal = true + && lhs.ndims == rhs.ndims + && array_cmp(lhs.dims, rhs.dims, lhs.ndims) + && lhs.data_type == rhs.data_type + && array_cmp(lhs.padded_dims, rhs.padded_dims, lhs.ndims) + && array_cmp(lhs.padded_offsets, rhs.padded_offsets, lhs.ndims) + && lhs.offset0 == rhs.offset0 + && lhs.format_kind == rhs.format_kind; + if (!base_equal) return false; + if (!types::memory_extra_desc_is_equal(lhs.extra, rhs.extra)) return false; + if (lhs.format_kind == format_kind::blocked) + return types::blocking_desc_is_equal(lhs.format_desc.blocking, + rhs.format_desc.blocking, lhs.ndims); + else if (lhs.format_kind == format_kind::wino) + return types::wino_desc_is_equal(lhs.format_desc.wino_desc, + rhs.format_desc.wino_desc); + else if (lhs.format_kind == format_kind::rnn_packed) + return types::rnn_packed_desc_is_equal(lhs.format_desc.rnn_packed_desc, + rhs.format_desc.rnn_packed_desc); + return true; +} + +inline bool operator!=(const memory_desc_t &lhs, const memory_desc_t &rhs) { + return !operator==(lhs, rhs); +} + +inline status_t memory_desc_init_by_strides(memory_desc_t &md, + const dims_t strides) { + return mkldnn_memory_desc_init_by_strides( + &md, md.ndims, md.dims, md.data_type, strides); +} + +inline status_t memory_desc_init_by_tag(memory_desc_t &md, format_tag_t tag, + const dims_t strides = nullptr) { + status_t status = mkldnn_memory_desc_init_by_tag( + &md, md.ndims, md.dims, md.data_type, tag); + if (status != status::success || strides == nullptr) + return status; + + /* TODO: add consistency check */ + + for (int d = 0; d < md.ndims; ++d) + md.format_desc.blocking.strides[d] = strides[d]; + + return status::success; +} + +/** inits memory descriptor based on logical dimensions kept in @p md, and the + * blocking structure @p blk. + * + * @note blk.strides represent the order only (from smaller to bigger) + * + * TODO: move md related functions to one single place + */ +inline status_t memory_desc_init_by_blocking_desc(memory_desc_t &md, + const blocking_desc_t &blk) { + dims_t blocks = {0}; + utils::array_set(blocks, 1, md.ndims); + dim_t block_size = 1; + for (int iblk = 0; iblk < blk.inner_nblks; ++iblk) { + blocks[blk.inner_idxs[iblk]] *= blk.inner_blks[iblk]; + block_size *= blk.inner_blks[iblk]; + } + + for (int d = 0; d < md.ndims; ++d) { + md.padded_dims[d] = utils::rnd_up(md.dims[d], blocks[d]); + md.padded_offsets[d] = 0; + } + md.offset0 = 0; + + md.format_kind = format_kind::blocked; + auto &mblk = md.format_desc.blocking; + mblk = blk; + + const int ndims = nstl::min(MKLDNN_MAX_NDIMS, md.ndims); // make GCC 5 happy + utils::array_copy(mblk.strides, blk.strides, ndims); + + int perm[MKLDNN_MAX_NDIMS]; + for (int d = 0; d < ndims; ++d) perm[d] = d; + + utils::simultaneous_sort(mblk.strides, perm, ndims, + [](stride_t a, stride_t b) { return b - a; }); + + dim_t stride = block_size; + for (int _d = ndims - 1; _d >= 0; --_d) { + const int d = perm[_d]; + md.format_desc.blocking.strides[d] = stride; + stride *= md.padded_dims[d] / blocks[d]; + } + + md.extra = utils::zero(); + + return status::success; +} + +/** returns true if memory desc @p md corresponds to the given format tag and + * strides. + * If strides are not passed (or passed as nullptr) the dense structure is + * assumed (i.e. the one that mkldnn_memory_desc_init_by_tag() returns). + * Strides might contain `0` value, indicating the stride must match the one + * that mkldnn_memory_desc_init_by_tag() returns. + * Strides might contain `-1` values, that would be ignored during the + * comparison. For instance, this can be used if a stride along minibatch + * doesn't matter. */ +inline bool memory_desc_matches_tag(const memory_desc_t &md, format_tag_t tag, + const dims_t strides = nullptr) { + if (md.format_kind != types::format_tag_to_kind(tag)) + return false; + + memory_desc_t md_gold; + status_t status = mkldnn_memory_desc_init_by_tag( + &md_gold, md.ndims, md.dims, md.data_type, tag); + if (status != status::success) return false; + + if (md.format_kind != format_kind::blocked) + return false; // unimplemented yet + + const auto &blk = md.format_desc.blocking; + const auto &blk_gold = md_gold.format_desc.blocking; + + using utils::array_cmp; + bool same_blocks = true + && blk.inner_nblks == blk_gold.inner_nblks + && array_cmp(blk.inner_blks, blk_gold.inner_blks, blk.inner_nblks) + && array_cmp(blk.inner_idxs, blk_gold.inner_idxs, blk.inner_nblks); + + if (!same_blocks) + return false; + + if (strides == nullptr) + return array_cmp(blk.strides, blk_gold.strides, md.ndims); + + for (int d = 0; d < md.ndims; ++d) { + dim_t stride = strides[d]; + if (stride == -1) continue; + if (stride == 0) stride = blk_gold.strides[d]; + if (blk.strides[d] != stride) return false; + } + + return true; +} + +/** returns matching tag (or undef if match is not found) + * XXX: This is a workaround that eventually should go away! */ +template +format_tag_t memory_desc_matches_one_of_tag(const memory_desc_t &md, + Tags ...tags) { + for (const auto tag: {tags...}) { + if (memory_desc_matches_tag(md, tag)) + return tag; + } + return format_tag::undef; +} + +} +} + +#include "memory_desc_wrapper.hpp" + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/utils.cpp b/thirdparty/oidn/mkl-dnn/src/common/utils.cpp new file mode 100644 index 0000000000..d23f4682dc --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/utils.cpp @@ -0,0 +1,135 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#ifdef _WIN32 +#include +#include +#endif +#include +#include +#include + +#include "mkldnn.h" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { + +int getenv(const char *name, char *buffer, int buffer_size) { + if (name == NULL || buffer_size < 0 || (buffer == NULL && buffer_size > 0)) + return INT_MIN; + + int result = 0; + int term_zero_idx = 0; + size_t value_length = 0; + +#ifdef _WIN32 + value_length = GetEnvironmentVariable(name, buffer, buffer_size); +#else + const char *value = ::getenv(name); + value_length = value == NULL ? 0 : strlen(value); +#endif + + if (value_length > INT_MAX) + result = INT_MIN; + else { + int int_value_length = (int)value_length; + if (int_value_length >= buffer_size) { + result = -int_value_length; + } else { + term_zero_idx = int_value_length; + result = int_value_length; +#ifndef _WIN32 + strncpy(buffer, value, value_length); +#endif + } + } + + if (buffer != NULL) + buffer[term_zero_idx] = '\0'; + return result; +} + +int getenv_int(const char *name, int default_value) +{ + int value = default_value; + // # of digits in the longest 32-bit signed int + sign + terminating null + const int len = 12; + char value_str[len]; + if (getenv(name, value_str, len) > 0) + value = atoi(value_str); + return value; +} + +FILE *fopen(const char *filename, const char *mode) { +#ifdef _WIN32 + FILE *fp = NULL; + return ::fopen_s(&fp, filename, mode) ? NULL : fp; +#else + return ::fopen(filename, mode); +#endif +} + +void *malloc(size_t size, int alignment) { + void *ptr; + +#ifdef _WIN32 + ptr = _aligned_malloc(size, alignment); + int rc = ptr ? 0 : -1; +#else + int rc = ::posix_memalign(&ptr, alignment, size); +#endif + + return (rc == 0) ? ptr : 0; +} + +void free(void *p) { +#ifdef _WIN32 + _aligned_free(p); +#else + ::free(p); +#endif +} + +// Atomic operations +int32_t fetch_and_add(int32_t *dst, int32_t val) { +#ifdef _WIN32 + return InterlockedExchangeAdd(reinterpret_cast(dst), val); +#else + return __sync_fetch_and_add(dst, val); +#endif +} + +static int jit_dump_flag = 0; +static bool jit_dump_flag_initialized = false; +bool jit_dump_enabled() { + if (!jit_dump_flag_initialized) { + jit_dump_flag = getenv_int("MKLDNN_JIT_DUMP"); + jit_dump_flag_initialized = true; + } + return jit_dump_flag != 0; +} + +} +} + +mkldnn_status_t mkldnn_set_jit_dump(int enabled) { + using namespace mkldnn::impl::status; + mkldnn::impl::jit_dump_flag = enabled; + mkldnn::impl::jit_dump_flag_initialized = true; + return success; +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/utils.hpp b/thirdparty/oidn/mkl-dnn/src/common/utils.hpp new file mode 100644 index 0000000000..d5a8ec5139 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/utils.hpp @@ -0,0 +1,370 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef UTILS_HPP +#define UTILS_HPP + +#include +#include +#include +#include +#include + +#if defined(__x86_64__) || defined(_M_X64) +#define MKLDNN_X86_64 +#endif + +#define MSAN_ENABLED 0 +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#undef MSAN_ENABLED +#define MSAN_ENABLED 1 +#include +#endif +#endif + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "z_magic.hpp" + +namespace mkldnn { +namespace impl { + +// Sanity check for 64 bits +static_assert(sizeof(void*) == 8, "Intel(R) MKL-DNN supports 64 bit only"); + +#define CHECK(f) do { \ + status_t status = f; \ + if (status != status::success) \ + return status; \ +} while (0) + +#define IMPLICATION(cause, effect) (!(cause) || !!(effect)) + +namespace utils { + +/* a bunch of std:: analogues to be compliant with any msvs version + * + * Rationale: msvs c++ (and even some c) headers contain special pragma that + * injects msvs-version check into object files in order to abi-mismatches + * during the static linking. This makes sense if e.g. std:: objects are passed + * through between application and library, which is not the case for mkl-dnn + * (since there is no any c++-rt dependent stuff, ideally...). */ + +/* SFINAE helper -- analogue to std::enable_if */ +template struct enable_if {}; +template struct enable_if { typedef T type; }; + +/* analogue std::conditional */ +template struct conditional {}; +template struct conditional +{ typedef T type; }; +template struct conditional +{ typedef F type; }; + +template struct conditional3 {}; +template +struct conditional3 { typedef T type; }; +template +struct conditional3 { typedef FT type; }; +template +struct conditional3 { typedef FF type; }; + +template struct conditional_v {}; +template struct conditional_v +{ static constexpr U value = t; }; +template struct conditional_v +{ static constexpr U value = f; }; + +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template +inline T&& forward(typename utils::remove_reference::type &t) +{ return static_cast(t); } +template +inline T&& forward(typename utils::remove_reference::type &&t) +{ return static_cast(t); } + +template +inline typename remove_reference::type zero() +{ auto zero = typename remove_reference::type(); return zero; } + +template +inline bool everyone_is(T val, P item) { return val == item; } +template +inline bool everyone_is(T val, P item, Args... item_others) { + return val == item && everyone_is(val, item_others...); +} + +template +constexpr bool one_of(T val, P item) { return val == item; } +template +constexpr bool one_of(T val, P item, Args... item_others) { + return val == item || one_of(val, item_others...); +} + +template +inline bool any_null(Args... ptrs) { return one_of(nullptr, ptrs...); } + +template +inline void array_copy(T *dst, const T *src, size_t size) { + for (size_t i = 0; i < size; ++i) dst[i] = src[i]; +} +template +inline bool array_cmp(const T *a1, const T *a2, size_t size) { + for (size_t i = 0; i < size; ++i) if (a1[i] != a2[i]) return false; + return true; +} +template +inline void array_set(T *arr, const U& val, size_t size) { + for (size_t i = 0; i < size; ++i) arr[i] = static_cast(val); +} + +namespace product_impl { +template struct int2type{}; + +template +constexpr int product_impl(const T *arr, int2type<0>) { return arr[0]; } + +template +inline T product_impl(const T *arr, int2type) { + return arr[0]*product_impl(arr+1, int2type()); } +} + +template +inline T array_product(const T *arr) { + return product_impl::product_impl(arr, product_impl::int2type()); +} + +template +inline R array_product(const T *arr, size_t size) { + R prod = 1; + for (size_t i = 0; i < size; ++i) prod *= arr[i]; + return prod; +} + +/** sorts an array of values using @p comparator. While sorting the array + * of value, the function permutes an array of @p keys accordingly. + * + * @note The arrays of @p keys can be omitted. In this case the function + * sorts the array of @vals only. + */ +template +inline void simultaneous_sort(T *vals, U *keys, size_t size, F comparator) { + if (size == 0) return; + + for (size_t i = 0; i < size - 1; ++i) { + bool swapped = false; + + for (size_t j = 0; j < size - i - 1; j++) { + if (comparator(vals[j], vals[j + 1]) > 0) { + nstl::swap(vals[j], vals[j + 1]); + if (keys) nstl::swap(keys[j], keys[j + 1]); + swapped = true; + } + } + + if (swapped == false) break; + } +} + +template +inline typename remove_reference::type div_up(const T a, const U b) { + assert(b); + return (a + b - 1) / b; +} + +template +inline typename remove_reference::type rnd_up(const T a, const U b) { + return div_up(a, b) * b; +} + +template +inline typename remove_reference::type rnd_dn(const T a, const U b) { + return (a / b) * b; +} + +template T *align_ptr(T *ptr, uintptr_t alignment) +{ return (T *)(((uintptr_t)ptr + alignment - 1) & ~(alignment - 1)); } + +template +inline U this_block_size(const T offset, const U max, const V block_size) { + assert(offset < max); + // TODO (Roma): can't use nstl::max() due to circular dependency... we + // need to fix this + const T block_boundary = offset + block_size; + if (block_boundary > max) + return max - offset; + else + return block_size; +} + +template +inline T nd_iterator_init(T start) { return start; } +template +inline T nd_iterator_init(T start, U &x, const W &X, Args &&... tuple) { + start = nd_iterator_init(start, utils::forward(tuple)...); + x = start % X; + return start / X; +} + +inline bool nd_iterator_step() { return true; } +template +inline bool nd_iterator_step(U &x, const W &X, Args &&... tuple) { + if (nd_iterator_step(utils::forward(tuple)...) ) { + x = (x + 1) % X; + return x == 0; + } + return false; +} + +template +inline bool nd_iterator_jump(U &cur, const U end, W &x, const Y &X) +{ + U max_jump = end - cur; + U dim_jump = X - x; + if (dim_jump <= max_jump) { + x = 0; + cur += dim_jump; + return true; + } else { + cur += max_jump; + x += max_jump; + return false; + } +} +template +inline bool nd_iterator_jump(U &cur, const U end, W &x, const Y &X, + Args &&... tuple) +{ + if (nd_iterator_jump(cur, end, utils::forward(tuple)...)) { + x = (x + 1) % X; + return x == 0; + } + return false; +} + +template +inline T pick(size_t i, const T &x0) { return x0; } +template +inline T pick(size_t i, const T &x0, Args &&... args) { + return i == 0 ? x0 : pick(i - 1, utils::forward(args)...); +} + +template +T pick_by_prop_kind(prop_kind_t prop_kind, const T &val_fwd_inference, + const T &val_fwd_training, const T &val_bwd_d, const T &val_bwd_w) { + switch (prop_kind) { + case prop_kind::forward_inference: return val_fwd_inference; + case prop_kind::forward_training: return val_fwd_training; + case prop_kind::backward_data: return val_bwd_d; + case prop_kind::backward_weights: return val_bwd_w; + default: assert(!"unsupported prop_kind"); + } + return T(); +} + +template +T pick_by_prop_kind(prop_kind_t prop_kind, + const T &val_fwd, const T &val_bwd_d, const T &val_bwd_w) +{ return pick_by_prop_kind(prop_kind, val_fwd, val_fwd, val_bwd_d, val_bwd_w); } + +template +struct array_offset_calculator { + template + array_offset_calculator(Telem *base, Targs... Fargs) : _dims{ Fargs... } + { + _base_ptr = base; + } + template + inline Telem &operator()(Targs... Fargs) + { + return *(_base_ptr + _offset(1, Fargs...)); + } + +private: + template + inline size_t _offset(size_t const dimension, size_t element) + { + return element; + } + + template + inline size_t _offset(size_t const dimension, size_t theta, size_t element) + { + return element + (_dims[dimension] * theta); + } + + template + inline size_t _offset(size_t const dimension, size_t theta, size_t element, + Targs... Fargs) + { + size_t t_prime = element + (_dims[dimension] * theta); + return _offset(dimension + 1, t_prime, Fargs...); + } + + Telem *_base_ptr; + const int _dims[Tdims]; +}; + +} + +int32_t fetch_and_add(int32_t *dst, int32_t val); +inline void yield_thread() {} + +// Reads an environment variable 'name' and stores its string value in the +// 'buffer' of 'buffer_size' bytes on success. +// +// - Returns the length of the environment variable string value (excluding +// the terminating 0) if it is set and its contents (including the terminating +// 0) can be stored in the 'buffer' without truncation. +// +// - Returns negated length of environment variable string value and writes +// "\0" to the buffer (if it is not NULL) if the 'buffer_size' is to small to +// store the value (including the terminating 0) without truncation. +// +// - Returns 0 and writes "\0" to the buffer (if not NULL) if the environment +// variable is not set. +// +// - Returns INT_MIN if the 'name' is NULL. +// +// - Returns INT_MIN if the 'buffer_size' is negative. +// +// - Returns INT_MIN if the 'buffer' is NULL and 'buffer_size' is greater than +// zero. Passing NULL 'buffer' with 'buffer_size' set to 0 can be used to +// retrieve the length of the environment variable value string. +// +int getenv(const char *name, char *buffer, int buffer_size); +// Reads an integer from the environment +int getenv_int(const char *name, int default_value = 0); +bool jit_dump_enabled(); +FILE *fopen(const char *filename, const char *mode); + +constexpr int msan_enabled = MSAN_ENABLED; +inline void msan_unpoison(void *ptr, size_t size) { +#if MSAN_ENABLED + __msan_unpoison(ptr, size); +#endif +} + +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/common/verbose.cpp b/thirdparty/oidn/mkl-dnn/src/common/verbose.cpp new file mode 100644 index 0000000000..89a57772cf --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/verbose.cpp @@ -0,0 +1,665 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#ifndef _WIN32 +#include +#endif + +#include "mkldnn.h" +#include "mkldnn_version.h" +#include "c_types_map.hpp" +#include "verbose.hpp" +#include "cpu/cpu_isa_traits.hpp" + +#include "batch_normalization_pd.hpp" +#include "pooling_pd.hpp" +#include "concat_pd.hpp" +#include "reorder_pd.hpp" +#include "convolution_pd.hpp" +#include "rnn_pd.hpp" +#include "deconvolution_pd.hpp" +#include "shuffle_pd.hpp" +#include "eltwise_pd.hpp" +#include "softmax_pd.hpp" +#include "inner_product_pd.hpp" +#include "sum_pd.hpp" +#include "lrn_pd.hpp" + +/* MKL-DNN CPU ISA info */ +#define ISA_ANY "No instruction set specific optimizations" +#define SSE42 "Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2)" +#define AVX "Intel(R) Advanced Vector Extensions (Intel(R) AVX)" +#define AVX2 "Intel(R) Advanced Vector Extensions 2 (Intel(R) AVX2)" +#define AVX512_COMMON "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \ + "AVX-512)" +#define AVX512_CORE "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \ + "AVX-512) with AVX512BW, AVX512VL, and AVX512DQ extensions" +#define AVX512_CORE_VNNI "Intel(R) AVX512-Deep Learning Boost (Intel(R) " \ + "AVX512-DL Boost)" +#define AVX512_MIC "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \ + "AVX-512) with AVX512CD, AVX512ER, and AVX512PF extensions" +#define AVX512_MIC_4OPS "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \ + "AVX-512) with AVX512_4FMAPS and AVX512_4VNNIW extensions" + +namespace mkldnn { +namespace impl { + +static verbose_t verbose; +static bool initialized; +static bool version_printed = false; + +const verbose_t *mkldnn_verbose() { +#if !defined(DISABLE_VERBOSE) + if (!initialized) { + const int len = 2; + char val[len] = {0}; + if (getenv("MKLDNN_VERBOSE", val, len) == 1) + verbose.level = atoi(val); + initialized = true; + } + if (!version_printed && verbose.level > 0) { + printf("mkldnn_verbose,info," + "Intel(R) MKL-DNN v%d.%d.%d (Git Hash %s),%s\n", + mkldnn_version()->major, mkldnn_version()->minor, + mkldnn_version()->patch, mkldnn_version()->hash, + get_isa_info()); + version_printed = true; + } +#else + verbose.level = 0; +#endif + return &verbose; +} + +double get_msec() { +#ifdef _WIN32 + static LARGE_INTEGER frequency; + if (frequency.QuadPart == 0) + QueryPerformanceFrequency(&frequency); + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + return 1e+3 * now.QuadPart / frequency.QuadPart; +#else + struct timeval time; + gettimeofday(&time, NULL); + return 1e+3 * time.tv_sec + 1e-3 * time.tv_usec; +#endif +} + +const char *get_isa_info() { + using namespace mkldnn::impl::cpu; + if (mayiuse(avx512_mic_4ops)) return AVX512_MIC_4OPS; + if (mayiuse(avx512_mic)) return AVX512_MIC; + if (mayiuse(avx512_core_vnni)) return AVX512_CORE_VNNI; + if (mayiuse(avx512_core)) return AVX512_CORE; + if (mayiuse(avx512_common)) return AVX512_COMMON; + if (mayiuse(avx2)) return AVX2; + if (mayiuse(avx)) return AVX; + if (mayiuse(sse42)) return SSE42; + return ISA_ANY; +} + +/* init_info section */ +namespace { +#if !defined(DISABLE_VERBOSE) +#define MKLDNN_VERBOSE_DAT_LEN 256 +#define MKLDNN_VERBOSE_AUX_LEN 384 +#define MKLDNN_VERBOSE_PRB_LEN 384 + +#define DECL_DAT_AUX_PRB_STRS() \ + int dat_written = 0, aux_written = 0, prb_written = 0; \ + MAYBE_UNUSED((dat_written * aux_written * prb_written)); \ + char dat_str[MKLDNN_VERBOSE_DAT_LEN] = {'\0'}; MAYBE_UNUSED(dat_str); \ + char aux_str[MKLDNN_VERBOSE_AUX_LEN] = {'\0'}; MAYBE_UNUSED(aux_str); \ + char prb_str[MKLDNN_VERBOSE_PRB_LEN] = {'\0'}; MAYBE_UNUSED(prb_str) + +#define DFMT "%" PRId64 + +void clear_buf(char *buf, int &written) { + /* TODO: do it better */ + buf[0] = '#'; + buf[1] = '\0'; + written = 1; +} + +#define DPRINT(buf, buf_len, written, ...) do { \ + int l = snprintf(buf + written, buf_len - written, __VA_ARGS__); \ + if (l < 0 || written + l > buf_len) { \ + clear_buf(buf, written); \ + } else { \ + written += l; \ + } \ +} while(0) + +// XXX: Outputs strings corresponding to memory formats used for data tensors. +void format_prb_desc_str(char *str, int len, const memory_desc_t *md) { + const auto dims = md->dims; + int written = 0; + if (md->ndims == 1) + DPRINT(str, len, written, + "x" DFMT, dims[0]); + else if (md->ndims == 2) + DPRINT(str, len, written, + "mb" DFMT "ic" DFMT, dims[0], dims[1]); + else if (md->ndims == 3) + DPRINT(str, len, written, + "mb" DFMT "ic" DFMT "iw" DFMT, + dims[0], dims[1], dims[2]); + else if (md->ndims == 4) + DPRINT(str, len, written, + "mb" DFMT "ic" DFMT "ih" DFMT "iw" DFMT, + dims[0], dims[1], dims[2], dims[3]); + else if (md->ndims == 5) + DPRINT(str, len, written, + "mb" DFMT "ic" DFMT "id" DFMT "ih" DFMT "iw" DFMT, + dims[0], dims[1], dims[2], dims[3], dims[4]); + else + mkldnn_md2dim_str(str, len, md); +} + +void verbose_templ(char *buffer, mkldnn_primitive_kind_t prim_kind, + const char *impl_str, mkldnn_prop_kind_t prop_kind, + const char *data_str, const char *aux_str, const char *prb_str) { + MAYBE_UNUSED(verbose_templ); + int written = 0; + DPRINT(buffer, MKLDNN_VERBOSE_BUF_LEN, written, "%s,%s,%s,%s,%s,%s", + mkldnn_prim_kind2str(prim_kind), impl_str, + mkldnn_prop_kind2str(prop_kind), data_str, aux_str, prb_str); +} + +template static void init_info_bnorm(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // data + auto md = s->src_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // diff data + auto md = s->diff_src_md(); + if (md) { + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + } + + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "flags:%u", s->desc()->flags); + + format_prb_desc_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->src_md()); + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_conv(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // src + auto md = s->desc()->prop_kind == prop_kind::backward_data + ? s->diff_src_md() : s->src_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // wei + auto md = s->desc()->prop_kind == prop_kind::backward_weights + ? s->diff_weights_md() : s->weights_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // bia + auto md = s->desc()->prop_kind == prop_kind::backward_weights + ? s->diff_weights_md(1) : s->weights_md(1); + if (md) { + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " bia_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + } + if (1) { // dst + auto md = !s->is_fwd() ? s->diff_dst_md() : s->dst_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind)); + + if (s->ndims() == 5) { + if (s->with_groups()) + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "mb" DFMT "_g" DFMT "ic" DFMT "oc" DFMT + "_id" DFMT "od" DFMT "kd" DFMT "sd" DFMT "dd" DFMT "pd" DFMT + "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT + "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT, + s->MB(), s->G(), s->IC(), s->OC(), + s->ID(), s->OD(), s->KD(), s->KSD(), s->KDD(), s->padFront(), + s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(), + s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL()); + else + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "mb" DFMT "_ic" DFMT "oc" DFMT + "_id" DFMT "od" DFMT "kd" DFMT "sd" DFMT "dd" DFMT "pd" DFMT + "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT + "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT, + s->MB(), s->IC(), s->OC(), + s->ID(), s->OD(), s->KD(), s->KSD(), s->KDD(), s->padFront(), + s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(), + s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL()); + } else { + if (s->with_groups()) + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "mb" DFMT "_g" DFMT "ic" DFMT "oc" DFMT + "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT + "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT, + s->MB(), s->G(), s->IC(), s->OC(), + s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(), + s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL()); + else + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "mb" DFMT "_ic" DFMT "oc" DFMT + "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT + "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT, + s->MB(), s->IC(), s->OC(), + s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(), + s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL()); + } + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_shuffle(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + auto md = s->is_fwd() ? s->src_md() : s->diff_dst_md(); + + if (1) { // data + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "axis:%d group_size:" DFMT, s->axis(), s->group_size()); + + mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, md); + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_eltwise(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // data + auto md = s->src_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // diff data + auto md = s->diff_src_md(); + if (md) { + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + } + + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind)); + + mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->src_md()); + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_iprod(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // src + auto md = s->desc()->prop_kind == prop_kind::backward_data + ? s->diff_src_md() : s->src_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // wei + auto md = s->desc()->prop_kind == prop_kind::backward_weights + ? s->diff_weights_md() : s->weights_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // bia + auto md = s->desc()->prop_kind == prop_kind::backward_weights + ? s->diff_weights_md(1) : s->weights_md(1); + if (md) { + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " bia_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + } + if (1) { // dst + auto md = !s->is_fwd() ? s->diff_dst_md() : s->dst_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "mb" DFMT "ic" DFMT "oc" DFMT, s->MB(), s->IC_total(), s->OC()); + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_lrn(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // data + auto md = s->src_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // diff data + auto md = s->diff_src_md(); + if (md) { + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + } + + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind)); + + format_prb_desc_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->src_md()); + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_mem(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // src + auto md = s->src_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // dst + auto md = s->dst_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "num:%d", s->n_inputs()); + + mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->dst_md()); + + verbose_templ(buffer, s->kind(), s->name(), prop_kind::undef, dat_str, + aux_str, prb_str); +} + +template static void init_info_pool(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // src + auto md = s->is_fwd() ? s->src_md() : s->diff_src_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // dst + auto md = s->is_fwd() ? s->dst_md() : s->diff_dst_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // ws + auto md = s->workspace_md(); + if (md) { + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " ws_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + } + + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind)); + + if (s->is_3d()) { + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "mb" DFMT "ic" DFMT "_" + "id" DFMT "od" DFMT "kd" DFMT "sd" DFMT "pd" DFMT "_" + "ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "ph" DFMT "_" + "iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "pw" DFMT "", + s->MB(), s->C(), + s->ID(), s->OD(), s->KD(), s->KSD(), s->padFront(), + s->IH(), s->OH(), s->KH(), s->KSH(), s->padT(), + s->IW(), s->OW(), s->KW(), s->KSW(), s->padL()); + } else { + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "mb" DFMT "ic" DFMT "_" + "ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "ph" DFMT "_" + "iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "pw" DFMT, + s->MB(), s->C(), + s->IH(), s->OH(), s->KH(), s->KSH(), s->padT(), + s->IW(), s->OW(), s->KW(), s->KSW(), s->padL()); + } + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_softmax(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // data + auto md = s->dst_md(); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // diff data + auto md = s->diff_src_md(); + if (md) { + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + } + + mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->dst_md()); + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +template static void init_info_rnn(pd_t *s, char *buffer) { + DECL_DAT_AUX_PRB_STRS(); + + if (1) { // src layer + auto md = s->is_fwd() ? s->src_md(0) : s->diff_src_md(0); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_layer_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // src iter + auto md = s->is_fwd() ? s->src_md(1) : s->diff_src_md(1); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_iter_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // wei_layer + auto md = s->is_fwd() ? s->weights_md(0) : s->diff_weights_md(0); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_layer_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // wei_iter + auto md = s->is_fwd() ? s->weights_md(1) : s->diff_weights_md(1); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_layer_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // bias + auto md = s->is_fwd() ? s->weights_md(2) : s->diff_weights_md(2); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " bias_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // dst layer + auto md = s->is_fwd() ? s->dst_md(0) : s->diff_dst_md(0); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "dst_layer_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + if (1) { // dst iter + auto md = s->is_fwd() ? s->dst_md(1) : s->diff_dst_md(1); + DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "dst_iter_"); + int l = mkldnn_md2fmt_str(dat_str + dat_written, + MKLDNN_VERBOSE_DAT_LEN - dat_written, md); + if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written); + } + + alg_kind_t alg_kind = s->cell_kind(); + rnn_direction_t rnn_dir = s->direction(); + DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written, + "alg:%s_%s", mkldnn_alg_kind2str(alg_kind), + mkldnn_rnn_direction2str(rnn_dir)); + + DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written, + "l" DFMT "t" DFMT "mb" DFMT + "sic" DFMT "slc" DFMT "dic" DFMT "dlc" DFMT, + s->L(), s->T(), s->MB(), + s->SIC(), s->SLC(), s->DIC(), s->DLC()); + + verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str, + aux_str, prb_str); +} + +#undef DPRINT + +#else // !defined(DISABLE_VERBOSE) + +#define DEFINE_STUB(name) \ + template \ + static void CONCAT2(init_info_, name)(pd_t *s, char *buffer) \ + { UNUSED(s); UNUSED(buffer); } + +DEFINE_STUB(bnorm); +DEFINE_STUB(conv); +DEFINE_STUB(eltwise); +DEFINE_STUB(iprod); +DEFINE_STUB(lrn); +DEFINE_STUB(mem); +DEFINE_STUB(pool); +DEFINE_STUB(softmax); +DEFINE_STUB(rnn); +DEFINE_STUB(shuffle); +#undef DEFINE_STUB + +#endif // !defined(DISABLE_VERBOSE) +} + +void init_info(batch_normalization_pd_t *s, char *b) +{ init_info_bnorm(s, b); } +void init_info(concat_pd_t *s, char *b) +{ init_info_mem(s, b); } +void init_info(convolution_pd_t *s, char *b) +{ init_info_conv(s, b); } +void init_info(deconvolution_pd_t *s, char *b) +{ init_info_conv(s, b); } +void init_info(eltwise_pd_t *s, char *b) +{ init_info_eltwise(s, b); } +void init_info(inner_product_pd_t *s, char *b) +{ init_info_iprod(s, b); } +void init_info(lrn_pd_t *s, char *b) +{ init_info_lrn(s, b); } +void init_info(pooling_pd_t *s, char *b) +{ init_info_pool(s, b); } +void init_info(reorder_pd_t *s, char *b) +{ init_info_mem(s, b); } +void init_info(rnn_pd_t *s, char *b) +{ init_info_rnn(s, b); } +void init_info(shuffle_pd_t *s, char *b) +{ init_info_shuffle(s, b); } +void init_info(softmax_pd_t *s, char *b) +{ init_info_softmax(s, b); } +void init_info(sum_pd_t *s, char *b) +{ init_info_mem(s, b); } + +} +} + +mkldnn_status_t mkldnn_set_verbose(int level) { + using namespace mkldnn::impl::status; + if (level < 0 || level > 2) return invalid_arguments; + mkldnn::impl::verbose.level = level; + mkldnn::impl::initialized = true; + return success; +} + +const mkldnn_version_t *mkldnn_version() { + static mkldnn_version_t ver = { + MKLDNN_VERSION_MAJOR, + MKLDNN_VERSION_MINOR, + MKLDNN_VERSION_PATCH, + MKLDNN_VERSION_HASH}; + return &ver; +} diff --git a/thirdparty/oidn/mkl-dnn/src/common/verbose.hpp b/thirdparty/oidn/mkl-dnn/src/common/verbose.hpp new file mode 100644 index 0000000000..e3049750cb --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/verbose.hpp @@ -0,0 +1,62 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef VERBOSE_HPP +#define VERBOSE_HPP + +#include +#include + +#include "mkldnn_debug.h" +#include "c_types_map.hpp" +#include "utils.hpp" +#include "z_magic.hpp" + +namespace mkldnn { +namespace impl { + +struct verbose_t { + int level; +}; + +const verbose_t *mkldnn_verbose(); +double get_msec(); +const char *get_isa_info(); + +#if !defined(DISABLE_VERBOSE) +#define MKLDNN_VERBOSE_BUF_LEN 1024 +#else +#define MKLDNN_VERBOSE_BUF_LEN 1 +#endif + +void init_info(batch_normalization_pd_t *s, char *buffer); +void init_info(concat_pd_t *s, char *buffer); +void init_info(convolution_pd_t *s, char *buffer); +void init_info(deconvolution_pd_t *s, char *buffer); +void init_info(eltwise_pd_t *s, char *buffer); +void init_info(inner_product_pd_t *s, char *buffer); +void init_info(lrn_pd_t *s, char *buffer); +void init_info(pooling_pd_t *s, char *buffer); +void init_info(reorder_pd_t *s, char *buffer); +void init_info(rnn_pd_t *s, char *buffer); +void init_info(shuffle_pd_t *s, char *buffer); +void init_info(softmax_pd_t *s, char *buffer); +void init_info(sum_pd_t *s, char *buffer); + +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp b/thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp new file mode 100644 index 0000000000..520bd4710b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef Z_MAGIC_HPP +#define Z_MAGIC_HPP + +#define CHAIn2(a,b) a b +#define CHAIN2(a,b) CHAIn2(a,b) + +#define CONCAt2(a,b) a ## b +#define CONCAT2(a,b) CONCAt2(a,b) + +#define STRINGIFy(s) #s +#define STRINGIFY(s) STRINGIFy(s) + +#ifdef _MSC_VER +# define PRAGMA_MACRo(x) __pragma(x) +# define PRAGMA_MACRO(x) PRAGMA_MACRo(x) +#else +# define PRAGMA_MACRo(x) _Pragma(#x) +# define PRAGMA_MACRO(x) PRAGMA_MACRo(x) +#endif + +#define UNUSED(x) ((void)x) +#define MAYBE_UNUSED(x) UNUSED(x) + +#if defined(_WIN32) && !defined(__GNUC__) +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp new file mode 100644 index 0000000000..7cf7822d90 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp @@ -0,0 +1,112 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "cpu_barrier.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace simple_barrier { + +void generate(jit_generator &code, Xbyak::Reg64 reg_ctx, + Xbyak::Reg64 reg_nthr) { +# define BAR_CTR_OFF offsetof(ctx_t, ctr) +# define BAR_SENSE_OFF offsetof(ctx_t, sense) + using namespace Xbyak; + + Xbyak::Reg64 reg_tmp = [&]() { + /* returns register which is neither reg_ctx nor reg_nthr */ + Xbyak::Reg64 regs[] = { util::rax, util::rbx, util::rcx }; + for (size_t i = 0; i < sizeof(regs) / sizeof(regs[0]); ++i) + if (!utils::one_of(regs[i], reg_ctx, reg_nthr)) + return regs[i]; + return regs[0]; /* should not happen */ + }(); + + Label barrier_exit_label, barrier_exit_restore_label, spin_label; + + code.cmp(reg_nthr, 1); + code.jbe(barrier_exit_label); + + code.push(reg_tmp); + + /* take and save current sense */ + code.mov(reg_tmp, code.ptr[reg_ctx + BAR_SENSE_OFF]); + code.push(reg_tmp); + code.mov(reg_tmp, 1); + + if (mayiuse(avx512_mic)) { + code.prefetchwt1(code.ptr[reg_ctx + BAR_CTR_OFF]); + code.prefetchwt1(code.ptr[reg_ctx + BAR_CTR_OFF]); + } + + code.lock(); code.xadd(code.ptr[reg_ctx + BAR_CTR_OFF], reg_tmp); + code.add(reg_tmp, 1); + code.cmp(reg_tmp, reg_nthr); + code.pop(reg_tmp); /* restore previous sense */ + code.jne(spin_label); + + /* the last thread {{{ */ + code.mov(code.qword[reg_ctx + BAR_CTR_OFF], 0); // reset ctx + + // notify waiting threads + code.not_(reg_tmp); + code.mov(code.ptr[reg_ctx + BAR_SENSE_OFF], reg_tmp); + code.jmp(barrier_exit_restore_label); + /* }}} the last thread */ + + code.CodeGenerator::L(spin_label); + code.pause(); + code.cmp(reg_tmp, code.ptr[reg_ctx + BAR_SENSE_OFF]); + code.je(spin_label); + + code.CodeGenerator::L(barrier_exit_restore_label); + code.pop(reg_tmp); + + code.CodeGenerator::L(barrier_exit_label); +# undef BAR_CTR_OFF +# undef BAR_SENSE_OFF +} + +/** jit barrier generator */ +struct jit_t: public jit_generator { + void (*barrier)(ctx_t *ctx, size_t nthr); + + jit_t() { + generate(*this, abi_param1, abi_param2); + ret(); + barrier = reinterpret_cast(const_cast( + this->getCode())); + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_t) +}; + +void barrier(ctx_t *ctx, int nthr) { + static jit_t j; /* XXX: constructed on load ... */ + j.barrier(ctx, nthr); +} + +} + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp new file mode 100644 index 0000000000..0f55e33aa8 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp @@ -0,0 +1,60 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_BARRIER_HPP +#define CPU_BARRIER_HPP + +#include + +#include "jit_generator.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace simple_barrier { + +STRUCT_ALIGN(64, +struct ctx_t { + enum { CACHE_LINE_SIZE = 64 }; + volatile size_t ctr; + char pad1[CACHE_LINE_SIZE - 1 * sizeof(size_t)]; + volatile size_t sense; + char pad2[CACHE_LINE_SIZE - 1 * sizeof(size_t)]; +}); + +inline void ctx_init(ctx_t *ctx) { *ctx = utils::zero(); } +void barrier(ctx_t *ctx, int nthr); + +/** injects actual barrier implementation into another jitted code + * @params: + * code -- jit_generator object where the barrier is to be injected + * reg_ctx -- read-only register with pointer to the barrier context + * reg_nnthr -- read-only register with the # of synchronizing threads + */ +void generate(jit_generator &code, Xbyak::Reg64 reg_ctx, + Xbyak::Reg64 reg_nthr); + +} + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp new file mode 100644 index 0000000000..1ed5ad57b9 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp @@ -0,0 +1,40 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_BATCH_NORMALIZATION_PD_HPP +#define CPU_BATCH_NORMALIZATION_PD_HPP + +#include "batch_normalization_pd.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_batch_normalization_fwd_pd_t: public batch_normalization_fwd_pd_t { + using batch_normalization_fwd_pd_t::batch_normalization_fwd_pd_t; +}; + +struct cpu_batch_normalization_bwd_pd_t: public batch_normalization_bwd_pd_t { + using batch_normalization_bwd_pd_t::batch_normalization_bwd_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp new file mode 100644 index 0000000000..b8d5c4fcaf --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp @@ -0,0 +1,140 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "utils.hpp" + +#include "jit_generator.hpp" + +#include "cpu_batch_normalization_utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { +namespace bnorm_utils { + +void cache_balance(size_t working_set_size, dim_t C_blks, + dim_t &C_blks_per_iter, int64_t &iters) { + int nthrs = mkldnn_get_max_threads(); + int l3_size = get_cache_size(3, true) * nthrs / 2; + + C_blks_per_iter = l3_size / working_set_size; + + if (C_blks_per_iter == 0) + C_blks_per_iter = 1; + if (C_blks_per_iter > C_blks) + C_blks_per_iter = C_blks; + + iters = (C_blks + C_blks_per_iter - 1) / C_blks_per_iter; +} + +bool thread_balance(bool do_blocking, bool spatial_thr_allowed, int ithr, + int nthr, dim_t N, dim_t C_blks, dim_t SP, int &C_ithr, int &C_nthr, + dim_t &C_blk_s, dim_t &C_blk_e, int &N_ithr, int &N_nthr, dim_t &N_s, + dim_t &N_e, int &S_ithr, int &S_nthr, dim_t &S_s, dim_t &S_e) { + if (nthr <= C_blks || !mkldnn_thr_syncable()) { + C_ithr = ithr; C_nthr = nthr; + N_ithr = 0; N_nthr = 1; + S_ithr = 0; S_nthr = 1; + N_s = 0; N_e = N; S_s = 0; S_e = SP; + balance211(C_blks, C_nthr, C_ithr, C_blk_s, C_blk_e); + } else { + if (do_blocking) { + N_nthr = (int)nstl::min(N, nthr); + C_nthr = (int)nstl::min(C_blks, nthr / N_nthr); + S_nthr = (int)nstl::min(SP, nthr / (C_nthr * N_nthr)); + } else { + C_nthr = (int)math::gcd((dim_t)nthr, C_blks); + N_nthr = (int)nstl::min(N, nthr / C_nthr); + S_nthr = (int)nstl::min(SP, nthr / (C_nthr * N_nthr)); + } + + if (!spatial_thr_allowed) + S_nthr = 1; + + if (S_nthr < 1) S_nthr = 1; + if (ithr < C_nthr * N_nthr * S_nthr) { + N_ithr = (ithr / S_nthr) % N_nthr ; + C_ithr = ithr / (N_nthr * S_nthr); + S_ithr = ithr % S_nthr; + balance211(C_blks, C_nthr, C_ithr, C_blk_s, C_blk_e); + balance211(N, N_nthr, N_ithr, N_s, N_e); + balance211(SP, S_nthr, S_ithr, S_s, S_e); + } else { + S_ithr = N_ithr = C_ithr = -ithr; + S_s = S_e = N_s = N_e = C_blk_s = C_blk_e = -1; + } + } + + // spatial_thr_allowed is meant to help maintain + // consistent decisions about spatial threading + // between mutiple invocations of this routine. + // It is caller's responsibility to check the + // return value and pass it as a flag to the + // next call if needed. + if (S_nthr == 1) + spatial_thr_allowed = false; + + return spatial_thr_allowed; +} + +bool is_spatial_thr(const batch_normalization_pd_t *bdesc, int simd_w, + int data_size) { + if (!mkldnn_thr_syncable()) return false; + + dim_t nthr = mkldnn_get_max_threads(); + dim_t SP = bdesc->W() * bdesc->D() * bdesc->H(); + dim_t C_PADDED = memory_desc_wrapper(bdesc->src_md()) + .padded_dims()[1]; + assert(C_PADDED % simd_w == 0); + + size_t data = bdesc->MB() * C_PADDED * SP * data_size; + size_t l3_size_ = get_cache_size(3, true) * nthr / 2; + bool do_blocking = (data >= l3_size_ / 2 && l3_size_ > 0); + dim_t C_blks_per_iter{ 1 }, iters{ 1 }; + dim_t C_blks = C_PADDED / simd_w; + + if (do_blocking) { + int num_tensors = bdesc->is_fwd() ? 1 : 2; + size_t working_set_size + = (bdesc->MB() * SP * simd_w * data_size) * num_tensors; + cache_balance(working_set_size, C_blks, C_blks_per_iter, iters); + } + + // Spatial threading decision made in this function shall be consistent + // with thread_balance() behavior. + C_blks = do_blocking ? C_blks_per_iter : C_blks; + + if (nthr <= C_blks) return false; + + dim_t S_nthr = 1; + if (do_blocking) { + dim_t N_nthr = nstl::min(bdesc->MB(), nthr); + dim_t C_nthr = nstl::min(C_blks, nthr / N_nthr); + S_nthr = nstl::min(SP, nthr / (C_nthr * N_nthr)); + } else { + dim_t C_nthr = math::gcd(nthr, C_blks); + dim_t N_nthr = nstl::min(bdesc->MB(), nthr / C_nthr); + S_nthr = nstl::min(SP, nthr / (C_nthr * N_nthr)); + } + + return S_nthr > 1; +} + +} +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp new file mode 100644 index 0000000000..0daef0716c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp @@ -0,0 +1,43 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_BATCH_NORMALIZATION_UTILS_HPP +#define CPU_BATCH_NORMALIZATION_UTILS_HPP + +#include "batch_normalization_pd.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { +namespace bnorm_utils { + +void cache_balance(size_t working_set_size, dim_t C_blks, + dim_t &C_blks_per_iter, int64_t &iters); + +bool thread_balance(bool do_blocking, bool spatial_thr_allowed, int ithr, + int nthr, dim_t N, dim_t C_blks, dim_t SP, int &C_ithr, int &C_nthr, + dim_t &C_blk_s, dim_t &C_blk_e, int &N_ithr, int &N_nthr, dim_t &N_s, + dim_t &N_e, int &S_ithr, int &S_nthr, dim_t &S_s, dim_t &S_e); + +bool is_spatial_thr(const batch_normalization_pd_t *bdesc, int simd_w, + int data_size); + +} +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp new file mode 100644 index 0000000000..b926491202 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp @@ -0,0 +1,51 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "cpu_engine.hpp" + +/* +#include "cpu/ref_concat.hpp" +#include "cpu/simple_concat.hpp" +*/ + +namespace mkldnn { +namespace impl { +namespace cpu { + +using cpd_create_f = mkldnn::impl::engine_t::concat_primitive_desc_create_f; + +namespace { +#define INSTANCE(...) __VA_ARGS__::pd_t::create +static const cpd_create_f cpu_concat_impl_list[] = { + /* + INSTANCE(simple_concat_t), + INSTANCE(simple_concat_t), + INSTANCE(simple_concat_t), + INSTANCE(simple_concat_t), + INSTANCE(ref_concat_t), + */ + nullptr, +}; +#undef INSTANCE +} + +const cpd_create_f *cpu_engine_t::get_concat_implementation_list() const { + return cpu_concat_impl_list; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp new file mode 100644 index 0000000000..0b01bcf163 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp @@ -0,0 +1,41 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_CONCAT_PD_HPP +#define CPU_CONCAT_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "concat_pd.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_concat_pd_t: public concat_pd_t { + using concat_pd_t::concat_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp new file mode 100644 index 0000000000..52a38a2294 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp @@ -0,0 +1,74 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_CONVOLUTION_PD_HPP +#define CPU_CONVOLUTION_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "convolution_pd.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_convolution_fwd_pd_t: public convolution_fwd_pd_t { + using convolution_fwd_pd_t::convolution_fwd_pd_t; + + bool has_padded_dst() const { + memory_desc_wrapper dst_d(&dst_md_); + return OC() != dst_d.padded_dims()[1]; + } + + bool wants_padded_bias() const { + if (!with_bias()) return false; + return has_padded_dst(); + } + + bool wants_zero_pad_dst(bool jit_impl = true) const { + if (!has_padded_dst()) return false; + const auto &po = attr()->post_ops_; + int idx; + if ((idx = po.find(primitive_kind::eltwise)) == -1) return false; + return !math::eltwise_fwd_preserves_zero(po.entry_[idx].eltwise.alg, + jit_impl); + } +}; + +struct cpu_convolution_bwd_data_pd_t: public convolution_bwd_data_pd_t { + using convolution_bwd_data_pd_t::convolution_bwd_data_pd_t; +}; + +struct cpu_convolution_bwd_weights_pd_t: public convolution_bwd_weights_pd_t { + using convolution_bwd_weights_pd_t::convolution_bwd_weights_pd_t; + + bool wants_padded_bias() const { + if (!with_bias()) return false; + memory_desc_wrapper diff_dst_d(&diff_dst_md_); + return OC() != diff_dst_d.padded_dims()[1]; + } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp new file mode 100644 index 0000000000..164c8601d7 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_DECONVOLUTION_PD_HPP +#define CPU_DECONVOLUTION_PD_HPP + +#include + +#include "deconvolution_pd.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_deconvolution_fwd_pd_t: public deconvolution_fwd_pd_t { + using deconvolution_fwd_pd_t::deconvolution_fwd_pd_t; +}; + +struct cpu_deconvolution_bwd_data_pd_t: public deconvolution_bwd_data_pd_t { + using deconvolution_bwd_data_pd_t::deconvolution_bwd_data_pd_t; +}; + +struct cpu_deconvolution_bwd_weights_pd_t: public deconvolution_bwd_weights_pd_t { + using deconvolution_bwd_weights_pd_t::deconvolution_bwd_weights_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp new file mode 100644 index 0000000000..c52f00026e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp @@ -0,0 +1,45 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_ELTWISE_PD_HPP +#define CPU_ELTWISE_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "eltwise_pd.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_eltwise_fwd_pd_t: public eltwise_fwd_pd_t { + using eltwise_fwd_pd_t::eltwise_fwd_pd_t; +}; + +struct cpu_eltwise_bwd_pd_t: public eltwise_bwd_pd_t { + using eltwise_bwd_pd_t::eltwise_bwd_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp new file mode 100644 index 0000000000..ce0a3667ad --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp @@ -0,0 +1,324 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "type_helpers.hpp" +#include "verbose.hpp" + +#include "cpu_engine.hpp" +#include "cpu_memory.hpp" + +//#include "cpu/rnn/ref_rnn.hpp" + +//#include "cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp" +//#include "cpu/jit_avx512_common_1x1_convolution.hpp" +#include "cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp" +#include "cpu/jit_avx512_common_convolution_winograd.hpp" +//#include "cpu/jit_avx512_core_x8s8s32x_convolution.hpp" +#include "cpu/jit_avx512_common_convolution.hpp" +//#include "cpu/jit_avx2_1x1_convolution.hpp" +//#include "cpu/jit_sse42_1x1_convolution.hpp" +#include "cpu/jit_avx2_convolution.hpp" +#include "cpu/jit_sse42_convolution.hpp" +//#include "cpu/gemm_convolution.hpp" +//#include "cpu/gemm_x8s8s32x_convolution.hpp" +//#include "cpu/ref_convolution.hpp" +//#include "cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp" +//#include "cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp" +//#include "cpu/ref_deconvolution.hpp" +//#include "cpu/ref_shuffle.hpp" +//#include "cpu/jit_uni_eltwise.hpp" +//#include "cpu/ref_eltwise.hpp" +//#include "cpu/ref_softmax.hpp" +#include "cpu/jit_uni_pooling.hpp" +//#include "cpu/jit_uni_i8i8_pooling.hpp" +//#include "cpu/ref_pooling.hpp" +//#include "cpu/nchw_pooling.hpp" +//#include "cpu/nhwc_pooling.hpp" +//#include "cpu/jit_avx512_common_lrn.hpp" +//#include "cpu/jit_uni_lrn.hpp" +//#include "cpu/ref_lrn.hpp" +//#include "cpu/jit_uni_batch_normalization.hpp" +//#include "cpu/ref_batch_normalization.hpp" +//#include "cpu/ncsp_batch_normalization.hpp" +//#include "cpu/nspc_batch_normalization.hpp" +//#include "cpu/ref_inner_product.hpp" +//#include "cpu/gemm_inner_product.hpp" +//#include "cpu/gemm_x8s8s32x_inner_product.hpp" +//#include "cpu/jit_uni_dw_convolution.hpp" +//#include "cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp" +#include "cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +status_t cpu_engine_t::memory_create(memory_t **memory, + const memory_desc_t *md, void *handle) { + auto _memory = new cpu_memory_t(this, md, handle); + if (_memory == nullptr) + return status::out_of_memory; + + status_t status = _memory->init(); + if (status != status::success) { + delete _memory; + return status; + } + + return safe_ptr_assign(*memory, _memory); +} + +using pd_create_f = mkldnn::impl::engine_t::primitive_desc_create_f; + +namespace { +using namespace mkldnn::impl::data_type; + +#define INSTANCE(...) &primitive_desc_t::create<__VA_ARGS__::pd_t> +static const pd_create_f cpu_impl_list[] = { + /* RNN */ + /* + INSTANCE(ref_rnn_fwd_f32_t), + INSTANCE(ref_rnn_fwd_u8s8_t), + INSTANCE(ref_rnn_bwd_f32_t), + */ + /* conv */ + /* + INSTANCE(jit_avx512_common_dw_convolution_fwd_t), + INSTANCE(jit_avx512_common_dw_convolution_bwd_data_t), + INSTANCE(jit_avx512_common_dw_convolution_bwd_weights_t), + INSTANCE(jit_avx512_common_1x1_convolution_fwd_f32_t), + INSTANCE(jit_avx512_common_1x1_convolution_bwd_data_f32_t), + INSTANCE(jit_avx512_common_1x1_convolution_bwd_weights_t), + */ + INSTANCE(jit_avx512_core_fp32_wino_conv_2x3_fwd_t), + INSTANCE(jit_avx512_core_fp32_wino_conv_4x3_fwd_t), + //INSTANCE(jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t), + //INSTANCE(jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t), + INSTANCE(jit_avx512_common_convolution_winograd_fwd_t), + //INSTANCE(jit_avx512_common_convolution_winograd_bwd_data_t), + //INSTANCE(jit_avx512_common_convolution_winograd_bwd_weights_t), + INSTANCE(jit_avx512_common_convolution_fwd_t), + //INSTANCE(jit_avx512_common_convolution_bwd_data_t), + //INSTANCE(jit_avx512_common_convolution_bwd_weights_t), + /* + INSTANCE(jit_avx2_dw_convolution_fwd_t), + INSTANCE(jit_avx2_dw_convolution_bwd_data_t), + INSTANCE(jit_avx2_dw_convolution_bwd_weights_t), + INSTANCE(jit_avx2_1x1_convolution_fwd_t), + INSTANCE(jit_avx2_1x1_convolution_bwd_data_t), + INSTANCE(jit_avx2_1x1_convolution_bwd_weights_t), + INSTANCE(jit_sse42_dw_convolution_fwd_t), + INSTANCE(jit_sse42_dw_convolution_bwd_data_t), + INSTANCE(jit_sse42_dw_convolution_bwd_weights_t), + INSTANCE(jit_sse42_1x1_convolution_fwd_t), + */ + INSTANCE(jit_avx2_convolution_fwd_t), + //INSTANCE(jit_avx2_convolution_bwd_data_t), + //INSTANCE(jit_avx2_convolution_bwd_weights_t), + INSTANCE(jit_sse42_convolution_fwd_t), + /* + INSTANCE(gemm_convolution_fwd_t), + INSTANCE(gemm_convolution_bwd_data_t), + INSTANCE(gemm_convolution_bwd_weights_t), + INSTANCE(ref_convolution_fwd_t), + INSTANCE(ref_convolution_bwd_data_t), + INSTANCE(ref_convolution_bwd_weights_t), + */ + /* conv (int) */ + /* + INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t), + INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t), + INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t), + INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_x8s8s32x_convolution_fwd_t), + INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t), + INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t), + INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t), + INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t), + INSTANCE(ref_convolution_fwd_t), + INSTANCE(ref_convolution_fwd_t), + INSTANCE(ref_convolution_fwd_t), + INSTANCE(ref_convolution_fwd_t), + INSTANCE(ref_convolution_bwd_data_t), + INSTANCE(ref_convolution_bwd_data_t), + INSTANCE(ref_convolution_bwd_data_t), + INSTANCE(ref_convolution_bwd_data_t), + */ + /* deconv */ + /* + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t), + INSTANCE(ref_deconvolution_bwd_weights_t), + INSTANCE(ref_deconvolution_bwd_data_t), + INSTANCE(ref_deconvolution_fwd_t), + */ + /* shuffle */ + /* + INSTANCE(ref_shuffle_t<4>), // f32 or s32 + INSTANCE(ref_shuffle_t<1>), // s8 or u8 + */ + /* eltwise */ + /* + INSTANCE(jit_uni_eltwise_fwd_t), + INSTANCE(jit_uni_eltwise_bwd_t), + INSTANCE(jit_uni_eltwise_fwd_t), + INSTANCE(jit_uni_eltwise_bwd_t), + INSTANCE(jit_uni_eltwise_fwd_t), + INSTANCE(jit_uni_eltwise_bwd_t), + INSTANCE(ref_eltwise_fwd_t), + INSTANCE(ref_eltwise_bwd_t), + */ + /* eltwise (int) */ + /* + INSTANCE(ref_eltwise_fwd_t), + INSTANCE(ref_eltwise_fwd_t), + INSTANCE(ref_eltwise_fwd_t), + INSTANCE(ref_eltwise_bwd_t), + */ + /* softmax */ + /* + INSTANCE(ref_softmax_fwd_t), + INSTANCE(ref_softmax_bwd_t), + */ + /* pool */ + INSTANCE(jit_uni_pooling_fwd_t), + //INSTANCE(jit_uni_pooling_bwd_t), + INSTANCE(jit_uni_pooling_fwd_t), + //INSTANCE(jit_uni_pooling_bwd_t), + INSTANCE(jit_uni_pooling_fwd_t), + //INSTANCE(jit_uni_pooling_bwd_t), + /* + INSTANCE(nchw_pooling_fwd_t), + INSTANCE(nchw_pooling_bwd_t), + INSTANCE(nhwc_pooling_fwd_t), + INSTANCE(nhwc_pooling_bwd_t), + INSTANCE(ref_pooling_fwd_t), + INSTANCE(ref_pooling_bwd_t), + */ + /* pool (int) */ + /* + INSTANCE(jit_uni_i8i8_pooling_fwd_t), + INSTANCE(jit_uni_i8i8_pooling_fwd_t), + INSTANCE(ref_pooling_fwd_t), + INSTANCE(ref_pooling_fwd_t), + INSTANCE(ref_pooling_fwd_t), + INSTANCE(ref_pooling_bwd_t), + */ + /* lrn */ + /* + INSTANCE(jit_avx512_common_lrn_fwd_t), + INSTANCE(jit_avx512_common_lrn_bwd_t), + INSTANCE(jit_uni_lrn_fwd_t), + INSTANCE(jit_uni_lrn_bwd_t), + INSTANCE(jit_uni_lrn_fwd_t), + INSTANCE(ref_lrn_fwd_t), + INSTANCE(ref_lrn_bwd_t), + */ + /* batch normalization */ + /* + INSTANCE(jit_uni_batch_normalization_fwd_t), + INSTANCE(jit_uni_batch_normalization_bwd_t), + INSTANCE(jit_uni_batch_normalization_fwd_t), + INSTANCE(jit_uni_batch_normalization_bwd_t), + INSTANCE(jit_uni_batch_normalization_fwd_t), + INSTANCE(jit_uni_batch_normalization_bwd_t), + INSTANCE(ncsp_batch_normalization_fwd_t), + INSTANCE(ncsp_batch_normalization_bwd_t), + INSTANCE(nspc_batch_normalization_fwd_t), + INSTANCE(nspc_batch_normalization_bwd_t), + INSTANCE(ref_batch_normalization_fwd_t), + INSTANCE(ref_batch_normalization_bwd_t), + INSTANCE(ref_batch_normalization_fwd_t), + */ + /* inner product */ + /* + INSTANCE(gemm_inner_product_fwd_t), + INSTANCE(gemm_inner_product_bwd_data_t), + INSTANCE(gemm_inner_product_bwd_weights_t), + INSTANCE(ref_inner_product_fwd_t), + INSTANCE(ref_inner_product_bwd_data_t), + INSTANCE(ref_inner_product_bwd_weights_t), + */ + /* inner product (int) */ + /* + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(gemm_x8s8s32x_inner_product_fwd_t), + INSTANCE(ref_inner_product_fwd_t), + INSTANCE(ref_inner_product_fwd_t), + INSTANCE(ref_inner_product_fwd_t), + INSTANCE(ref_inner_product_fwd_t), + */ + /* eol */ + nullptr, +}; +#undef INSTANCE +} + +const pd_create_f* cpu_engine_t::get_implementation_list() const { + return cpu_impl_list; +} + +cpu_engine_factory_t engine_factory; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp new file mode 100644 index 0000000000..e4c877ee05 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp @@ -0,0 +1,70 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_ENGINE_HPP +#define CPU_ENGINE_HPP + +#include + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "../common/engine.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +class cpu_engine_t: public engine_t { +public: + cpu_engine_t(): engine_t(engine_kind::cpu) {} + + /* implementation part */ + + virtual status_t memory_create(memory_t **memory, + const memory_desc_t *md, void *handle) override; + + virtual const concat_primitive_desc_create_f* + get_concat_implementation_list() const override; + virtual const reorder_primitive_desc_create_f* + get_reorder_implementation_list() const override; + virtual const sum_primitive_desc_create_f* + get_sum_implementation_list() const override; + virtual const primitive_desc_create_f* + get_implementation_list() const override; +}; + +class cpu_engine_factory_t: public engine_factory_t { +public: + virtual size_t count() const override { return 1; } + virtual engine_kind_t kind() const override { return engine_kind::cpu; } + virtual status_t engine_create(engine_t **engine, + size_t index) const override { + assert(index == 0); + *engine = new cpu_engine_t(); + return status::success; + }; +}; + +extern cpu_engine_factory_t engine_factory; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp new file mode 100644 index 0000000000..5880d3450c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp @@ -0,0 +1,84 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_INNER_PRODUCT_PD_HPP +#define CPU_INNER_PRODUCT_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "inner_product_pd.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace { +inline bool dense_gemm_consitency_check(const memory_desc_wrapper &src_d, + const memory_desc_wrapper &wei_d, const memory_desc_wrapper &dst_d) { + using namespace utils; + + auto strides_compatible = [&]() { + bool ok = true; + auto w_str = wei_d.blocking_desc().strides; + auto d_str = src_d.blocking_desc().strides; + for (int i = 1; i < src_d.ndims() - 1; i++) { + ok = ok && w_str[i] / d_str[i] == w_str[i + 1] / d_str[i + 1]; + } + return ok && one_of(w_str[1] / d_str[1], 1, wei_d.padded_dims()[0]); + }; + return true && src_d.is_blocking_desc() && wei_d.is_blocking_desc() + && src_d.ndims() == wei_d.ndims() + && src_d.blocking_desc().inner_nblks + == wei_d.blocking_desc().inner_nblks + && utils::one_of(src_d.blocking_desc().inner_nblks, 0, 1) + && array_cmp(src_d.blocking_desc().inner_blks, + wei_d.blocking_desc().inner_blks, + wei_d.blocking_desc().inner_nblks) + && array_cmp(src_d.blocking_desc().inner_idxs, + wei_d.blocking_desc().inner_idxs, + wei_d.blocking_desc().inner_nblks) + && strides_compatible() + && dst_d.matches_tag(format_tag::nc) + && src_d.only_padded_dim(1) + && wei_d.only_padded_dim(1) + && src_d.padded_dims()[1] == wei_d.padded_dims()[1] + && src_d.is_dense(true) + && dst_d.is_dense() + && wei_d.is_dense(true); +} +} + +struct cpu_inner_product_fwd_pd_t: public inner_product_fwd_pd_t { + using inner_product_fwd_pd_t::inner_product_fwd_pd_t; +}; + +struct cpu_inner_product_bwd_data_pd_t: public inner_product_bwd_data_pd_t { + using inner_product_bwd_data_pd_t::inner_product_bwd_data_pd_t; +}; + +struct cpu_inner_product_bwd_weights_pd_t: public inner_product_bwd_weights_pd_t { + using inner_product_bwd_weights_pd_t::inner_product_bwd_weights_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp new file mode 100644 index 0000000000..da6e9dac8e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp @@ -0,0 +1,151 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_ISA_TRAITS_HPP +#define CPU_ISA_TRAITS_HPP + +#include + +#define XBYAK64 +#define XBYAK_NO_OP_NAMES +/* in order to make selinux happy memory that would be marked with X-bit should + * be obtained with mmap */ +#define XBYAK_USE_MMAP_ALLOCATOR +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +/* turn off `size_t to other-type implicit casting` warning + * currently we have a lot of jit-generated instructions that + * take uint32_t, but we pass size_t (e.g. due to using sizeof). + * FIXME: replace size_t parameters with the appropriate ones */ +#pragma warning (disable: 4267) +#endif +#include "xbyak/xbyak.h" +#include "xbyak/xbyak_util.h" + +namespace mkldnn { +namespace impl { +namespace cpu { + +typedef enum { + isa_any, + sse41, + sse42, + avx, + avx2, + avx512_common, + avx512_core, + avx512_core_vnni, + avx512_mic, + avx512_mic_4ops, +} cpu_isa_t; + +template struct cpu_isa_traits {}; /* ::vlen -> 32 (for avx2) */ + +template <> struct cpu_isa_traits { + typedef Xbyak::Xmm Vmm; + static constexpr int vlen_shift = 4; + static constexpr int vlen = 16; + static constexpr int n_vregs = 16; +}; +template <> struct cpu_isa_traits { + typedef Xbyak::Ymm Vmm; + static constexpr int vlen_shift = 5; + static constexpr int vlen = 32; + static constexpr int n_vregs = 16; +}; +template <> struct cpu_isa_traits: + public cpu_isa_traits {}; + +template <> struct cpu_isa_traits { + typedef Xbyak::Zmm Vmm; + static constexpr int vlen_shift = 6; + static constexpr int vlen = 64; + static constexpr int n_vregs = 32; +}; +template <> struct cpu_isa_traits: + public cpu_isa_traits {}; + +template <> struct cpu_isa_traits: + public cpu_isa_traits {}; + +template <> struct cpu_isa_traits: + public cpu_isa_traits {}; + +namespace { + +static Xbyak::util::Cpu cpu; +static inline bool mayiuse(const cpu_isa_t cpu_isa) { + using namespace Xbyak::util; + + switch (cpu_isa) { + case sse41: + case sse42: + // FIXME: SSE4.2 is actually NOT required + //return cpu.has(Cpu::tSSE42); + return cpu.has(Cpu::tSSE41); + case avx: + return cpu.has(Cpu::tAVX); + case avx2: + return cpu.has(Cpu::tAVX2); + case avx512_common: + return cpu.has(Cpu::tAVX512F); + case avx512_core: + return true + && cpu.has(Cpu::tAVX512F) + && cpu.has(Cpu::tAVX512BW) + && cpu.has(Cpu::tAVX512VL) + && cpu.has(Cpu::tAVX512DQ); + case avx512_core_vnni: + return true + && cpu.has(Cpu::tAVX512F) + && cpu.has(Cpu::tAVX512BW) + && cpu.has(Cpu::tAVX512VL) + && cpu.has(Cpu::tAVX512DQ) + && cpu.has(Cpu::tAVX512_VNNI); + case avx512_mic: + return true + && cpu.has(Cpu::tAVX512F) + && cpu.has(Cpu::tAVX512CD) + && cpu.has(Cpu::tAVX512ER) + && cpu.has(Cpu::tAVX512PF); + case avx512_mic_4ops: + return true + && mayiuse(avx512_mic) + && cpu.has(Cpu::tAVX512_4FMAPS) + && cpu.has(Cpu::tAVX512_4VNNIW); + case isa_any: + return true; + } + return false; +} +} + +/* whatever is required to generate string literals... */ +#include "z_magic.hpp" +#define JIT_IMPL_NAME_HELPER(prefix, isa, suffix_if_any) \ + (isa == sse42 ? prefix STRINGIFY(sse42) : \ + (isa == avx ? prefix STRINGIFY(avx) : \ + (isa == avx2 ? prefix STRINGIFY(avx2) : \ + (isa == avx512_common ? prefix STRINGIFY(avx512_common) : \ + (isa == avx512_core ? prefix STRINGIFY(avx512_core) : \ + (isa == avx512_mic ? prefix STRINGIFY(avx512_mic) : \ + (isa == avx512_mic_4ops ? prefix STRINGIFY(avx512_mic_4ops) : \ + prefix suffix_if_any))))))) + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp new file mode 100644 index 0000000000..49988f4c2d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp @@ -0,0 +1,42 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_LRN_PD_HPP +#define CPU_LRN_PD_HPP + +#include + +#include "lrn_pd.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_lrn_fwd_pd_t: public lrn_fwd_pd_t { + using lrn_fwd_pd_t::lrn_fwd_pd_t; +}; + +struct cpu_lrn_bwd_pd_t: public lrn_bwd_pd_t { + using lrn_bwd_pd_t::lrn_bwd_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp new file mode 100644 index 0000000000..3c0624cf46 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp @@ -0,0 +1,277 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "mkldnn_traits.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_memory.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl; +using namespace mkldnn::impl::data_type; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::format_tag; + +enum blk_kind_t { a, b, c, ab, ba, bc, cb }; + +template +void typed_zero_pad_blk( + const memory_desc_wrapper &m_d, typename prec_traits
::type *data) { + using data_t = typename prec_traits
::type; + const auto &dims = m_d.dims(); + const auto &pdims = m_d.padded_dims(); + const auto &blk = m_d.blocking_desc(); + auto dim_is_blocked = [&](int dim) { + for (int i = 0; i < blk.inner_nblks; i++) + if (blk.inner_idxs[i] == dim) + return true; + return false; + }; + bool A_blocked = dim_is_blocked(0), B_blocked = dim_is_blocked(1), + C_blocked = dim_is_blocked(2); + + assert(blk.inner_nblks < 4); + assert((A_blocked || B_blocked || C_blocked) || (A_blocked && B_blocked) + || (C_blocked && B_blocked)); + + const int a_tail_s = A_blocked ? dims[0] % blksize : 0; + const int b_tail_s = B_blocked ? dims[1] % blksize : 0; + const int c_tail_s = C_blocked ? dims[2] % blksize : 0; + assert(a_tail_s || b_tail_s || c_tail_s); + + const int A = A_blocked ? pdims[0] / blksize : dims[0]; + const int B = B_blocked ? pdims[1] / blksize : dims[1]; + const int C = C_blocked ? pdims[2] / blksize : dims[2]; + const int D = m_d.ndims() > 3 ? dims[3] : 1; + const int E = m_d.ndims() > 4 ? dims[4] : 1; + const int F = m_d.ndims() > 5 ? dims[5] : 1; + const int inner_blk = blk.inner_nblks == 3 ? blk.inner_blks[2] : 1; + + auto zeroize_tail = [&](data_t *d, const int tail_s) { + for (int b = tail_s; b < blksize; ++b) + d[b] = 0; + }; + auto zeroize_tail_inner = [&](data_t *d, const int tail_s) { + for (int b1 = 0; b1 < blksize; ++b1) + for (int b2 = tail_s; b2 < blksize; ++b2) + d[(b1 / inner_blk) * blksize * inner_blk + inner_blk * b2 + + b1 % inner_blk] + = 0; + }; + auto zeroize_tail_outer = [&](data_t *d, const int tail_s) { + for (int b1 = tail_s; b1 < blksize; ++b1) + for (int b2 = 0; b2 < blksize; ++b2) + d[(b1 / inner_blk) * blksize * inner_blk + inner_blk * b2 + + b1 % inner_blk] + = 0; + }; + + if (c_tail_s) { + parallel_nd(A, B, D, E, F, [&](int a, int b, int d, int e, int f) { + auto x = &data[m_d.blk_off(a, b, C - 1, d, e, f)]; + if (blk_kind == c) + zeroize_tail(x, c_tail_s); + else if (blk_kind == bc) + zeroize_tail_inner(x, c_tail_s); + else if (blk_kind == cb) + zeroize_tail_outer(x, c_tail_s); + }); + } + + if (b_tail_s) { + parallel_nd(A, C, D, E, F, [&](int a, int c, int d, int e, int f) { + auto x = &data[m_d.blk_off(a, B - 1, c, d, e, f)]; + if (blk_kind == b) + zeroize_tail(x, b_tail_s); + else if (blk_kind == ab || blk_kind == cb) + zeroize_tail_inner(x, b_tail_s); + else if (blk_kind == ba || blk_kind == bc) + zeroize_tail_outer(x, b_tail_s); + }); + } + + if (a_tail_s) { + parallel_nd(B, C, D, E, F, [&](int b, int c, int d, int e, int f) { + auto x = &data[m_d.blk_off(A - 1, b, c, d, e, f)]; + if (blk_kind == a) + zeroize_tail(x, a_tail_s); + else if (blk_kind == ba) + zeroize_tail_inner(x, a_tail_s); + else if (blk_kind == ab) + zeroize_tail_outer(x, a_tail_s); + }); + } +} + +/* + * all + */ +template +void typed_zero_pad_generic_blocked( + const memory_desc_wrapper &m_d, typename prec_traits
::type *data) { + const int ndims = m_d.ndims(); + const auto &dims = m_d.dims(); + const auto &pdims = m_d.padded_dims(); + + const ptrdiff_t nelems = (ptrdiff_t)m_d.nelems(true); + + /* [D_0] .. [D_k][D_k+1] .. [D_ndim - 1] + * | \ / + * | --------------------- + * has contiguous + * padding + * + * step <-- D_k+1 * ... * D_ndims-1 + * step_dim <-- k + */ + + ptrdiff_t step = 1; + int step_dim = ndims - 1; + for (; step_dim >= 0; --step_dim) { + if (dims[step_dim] != pdims[step_dim]) + break; + step *= dims[step_dim]; + } + + assert(step_dim >= 0 && "no zero padding is required"); + if (step_dim < 0) + return; + + parallel_nd(nelems / step, [&](ptrdiff_t e1) { + bool need_zero = false; + + ptrdiff_t idx = e1; + for (int d = step_dim; d >= 0; --d) { + if (idx % pdims[d] >= dims[d]) { + need_zero = true; + break; + } + idx /= pdims[d]; + } + + if (need_zero) { + for (ptrdiff_t e0 = 0; e0 < step; ++e0) + data[m_d.off_l(e1 * step + e0, true)] = 0; + } + }); +} + +template +status_t cpu_memory_t::typed_zero_pad() const { + const memory_desc_wrapper mdw(md()); + + if (mdw.format_kind() != format_kind::blocked) + return unimplemented; + + if (mdw.nelems(false) == mdw.nelems(true)) + return success; + + auto *data = (typename prec_traits
::type *)data_; + auto blk = mdw.blocking_desc(); + + auto get_blksize = [&](int ind) { + int blksize = 1; + for (int i = 0; i < blk.inner_nblks; i++) { + if (blk.inner_idxs[i] == ind) + blksize *= blk.inner_blks[i]; + } + return blksize; + }; + const int blksize = get_blksize(blk.inner_idxs[0]); + +# define CASE(blksize_, blk_kind) \ + do { \ + if (blksize == blksize_) { \ + typed_zero_pad_blk(mdw, data); \ + return success; \ + } \ + } while(0) + + switch (blk.inner_nblks) { + case 1: + if (blk.inner_idxs[0] == 0) { + CASE(4, a); + CASE(8, a); + CASE(16, a); + } else if (blk.inner_idxs[0] == 1) { + CASE(4, b); + CASE(8, b); + CASE(16, b); + } + break; + case 2: + case 3: + if (!IMPLICATION(blk.inner_nblks == 3, + blk.inner_idxs[0] == blk.inner_idxs[2])) + break; + + if (blk.inner_idxs[0] == 0 && blk.inner_idxs[1] == 1) { + CASE(4, ab); + CASE(8, ab); + CASE(16, ab); + } else if (blk.inner_idxs[0] == 1 && blk.inner_idxs[1] == 0) { + CASE(4, ba); + CASE(8, ba); + CASE(16, ba); + } + if (blk.inner_idxs[0] == 1 && blk.inner_idxs[1] == 2) { + CASE(4, bc); + CASE(8, bc); + CASE(16, bc); + } else if (blk.inner_idxs[0] == 2 && blk.inner_idxs[1] == 1) { + CASE(4, cb); + CASE(8, cb); + CASE(16, cb); + } + break; + default: break; + } + +# undef CASE + + // the last line of defence + typed_zero_pad_generic_blocked
(mdw, data); + return success; +} + +status_t cpu_memory_t::zero_pad() const { + memory_desc_wrapper mdw(md()); + const bool skip_zeroing = false + || data_ == nullptr + || mdw.is_zero() + || !mdw.is_blocking_desc(); + if (skip_zeroing) return success; + + switch (mdw.data_type()) { + case f32: return typed_zero_pad(); + case s32: return typed_zero_pad(); + case s8: return typed_zero_pad(); + case u8: return typed_zero_pad(); + default: assert(!"memory is undefined"); return unimplemented; + } + return unimplemented; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp new file mode 100644 index 0000000000..2c01bcc6af --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp @@ -0,0 +1,89 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_MEMORY_HPP +#define CPU_MEMORY_HPP + +#include + +#include "c_types_map.hpp" +#include "memory.hpp" +#include "memory_desc_wrapper.hpp" + +#include "cpu_engine.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_memory_t: public memory_t { + cpu_memory_t(cpu_engine_t *engine, const memory_desc_t *md, void *handle) + : memory_t(engine, md) + , own_data_(handle == MKLDNN_NATIVE_HANDLE_ALLOCATE) + , data_((char *)handle) {} + + cpu_memory_t(cpu_engine_t *engine, const memory_desc_t *md) + : cpu_memory_t(engine, md, nullptr) {} + + ~cpu_memory_t() { if (own_data_) free(data_); } + + virtual status_t init() override { + if (own_data_) { + data_ = nullptr; + const size_t size = memory_desc_wrapper(this->md()).size(); + if (size) { + data_ = (char *)malloc(size, 64); + if (data_ == nullptr) + return status::out_of_memory; + } + } + return zero_pad(); + } + + cpu_engine_t *engine() const { return (cpu_engine_t *)memory_t::engine(); } + + virtual status_t get_data_handle(void **handle) const override { + *handle = static_cast(data_); + return status::success; + } + + virtual mkldnn::impl::status_t set_data_handle(void *handle) override { + if (own_data_) { free(data_); own_data_ = false; } + data_ = static_cast(handle); + return zero_pad(); + } + + virtual mkldnn::impl::status_t zero_pad() const override; + +private: + bool own_data_; + char *data_; + + template + mkldnn::impl::status_t typed_zero_pad() const; + + cpu_memory_t(const cpu_memory_t &) = delete; + cpu_memory_t &operator=(const cpu_memory_t &) = delete; + cpu_memory_t &operator=(cpu_memory_t &&) = delete; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp new file mode 100644 index 0000000000..ac2daa415e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp @@ -0,0 +1,40 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_POOLING_PD_HPP +#define CPU_POOLING_PD_HPP + +#include "pooling_pd.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_pooling_fwd_pd_t: public pooling_fwd_pd_t { + using pooling_fwd_pd_t::pooling_fwd_pd_t; +}; + +struct cpu_pooling_bwd_pd_t: public pooling_bwd_pd_t { + using pooling_bwd_pd_t::pooling_bwd_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp new file mode 100644 index 0000000000..56127f36c2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp @@ -0,0 +1,83 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_PRIMITIVE_HPP +#define CPU_PRIMITIVE_HPP + +#include "mkldnn.h" + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "primitive.hpp" +#include "scratchpad.hpp" + +#define CTX_IN_MEM(type, arg) static_cast(ctx.input(arg)) +#define CTX_OUT_MEM(type, arg) static_cast(ctx.output(arg)) + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_memory_t; + +struct cpu_primitive_t: public primitive_t { + cpu_primitive_t(const primitive_desc_t *pd, + bool use_global_scratchpad = false) + : primitive_t(pd) + , scratchpad_buffer_(nullptr) + , global_scratchpad_(nullptr) + { + const size_t scratchpad_size = + this->pd()->scratchpad_size(scratchpad_mode::library); + + if (scratchpad_size) { + if (use_global_scratchpad) + global_scratchpad_ = create_scratchpad(scratchpad_size); + else + scratchpad_buffer_ = malloc(scratchpad_size, 64); + } + } + + virtual ~cpu_primitive_t() { + delete global_scratchpad_; + free(scratchpad_buffer_); + } + +protected: + memory_tracking::grantor_t scratchpad(const exec_ctx_t &ctx) const { + void *ptr = nullptr; + if (pd()->attr()->scratchpad_mode_ == scratchpad_mode::user) { + ptr = CTX_OUT_MEM(void *, MKLDNN_ARG_SCRATCHPAD); + } else { + ptr = global_scratchpad_ + ? global_scratchpad_->get() : scratchpad_buffer_; + } + + return pd()->scratchpad_registry().grantor(ptr); + } + +private: + void *scratchpad_buffer_; + scratchpad_t *global_scratchpad_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp new file mode 100644 index 0000000000..1d41ac5cea --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp @@ -0,0 +1,544 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "mkldnn_thread.hpp" +#include "mkldnn_types.h" +#include "nstl.hpp" +#include "utils.hpp" + +#include "cpu_reducer.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace memory_tracking::names; + +void reduce_balancer_t::balance() { + using namespace nstl; + using namespace utils; + + assert(nthr_ > 0 && job_size_ > 0 && njobs_ > 0 && reduction_size_ > 0); + + const int job_complexity = 1; + + const int min_njobs_per_group = max(1, njobs_ / nthr_); + const int max_njobs_per_group = max(1, + static_cast(max_buffer_size_ / (nthr_ * job_size_))); + + /* initial guess */ + int ngroups = min(njobs_ / min_njobs_per_group, nthr_); + int nthr_per_group = syncable_ ? min(nthr_ / ngroups, reduction_size_) : 1; + int njobs_per_group_ub = div_up(njobs_, ngroups); + + /* rough upper-bound estimation, will be fixed during brute force */ + size_t thread_complexity_ub = njobs_ * job_size_ * reduction_size_; + + /* brute force parameters for the best balance... */ + for (int c_njobs_per_group = min_njobs_per_group; + c_njobs_per_group < njobs_; ++c_njobs_per_group) { + /* current assumption */ + int c_ngroups = min(njobs_ / c_njobs_per_group, nthr_); + int c_nthr_per_group = syncable_ + ? min(nthr_ / c_ngroups, reduction_size_) : 1; + int c_njobs_per_group_ub = div_up(njobs_, c_ngroups); + + if (c_nthr_per_group > 1 && c_njobs_per_group_ub > max_njobs_per_group) + continue; + + int c_thread_reduction_ub = div_up(reduction_size_, c_nthr_per_group); + size_t c_group_size_ub = job_size_ * c_njobs_per_group_ub; + size_t c_thread_complexity_ub = c_group_size_ub * ( + job_complexity * c_thread_reduction_ub + + (c_nthr_per_group != 1)); + + if (c_thread_complexity_ub < thread_complexity_ub) { + ngroups = c_ngroups; + nthr_per_group = c_nthr_per_group; + njobs_per_group_ub = c_njobs_per_group_ub; + thread_complexity_ub = c_thread_complexity_ub; + } + } + + assert(njobs_per_group_ub <= max_njobs_per_group || nthr_per_group == 1); + assert(ngroups * nthr_per_group <= nthr_); + assert((size_t)njobs_per_group_ub * job_size_ * nthr_ <= max_buffer_size_ + || nthr_per_group == 1); /* no reduction buffer overflow */ + assert(IMPLICATION(!syncable_, nthr_per_group == 1)); + + ngroups_ = ngroups; + nthr_per_group_ = nthr_per_group; + njobs_per_group_ub_ = njobs_per_group_ub; +} + +/* reducer jit-ted driver */ + +using namespace Xbyak; + +template +struct reducer_2d_driver_t: public c_compatible { + typedef typename prec_traits::type data_t; + + reducer_2d_driver_t(int n_src, size_t src_ld, + size_t src_step, size_t dst_step, bool nullify_dst) + : n_src_(n_src), src_ld_(src_ld), src_step_(src_step) + , dst_step_(dst_step), nullify_dst_(nullify_dst), ker_(nullptr) {} + virtual ~reducer_2d_driver_t() {} + void operator()(data_t *dst, const data_t *srcs, size_t ny, size_t nx) + { assert(ker_); ker_(dst, srcs, ny, nx); } + +protected: + int n_src_; + size_t src_ld_, src_step_, dst_step_; + bool nullify_dst_; + void (*ker_)(data_t *dst, const data_t *srcs, size_t ny, size_t nx); +}; + +template +struct reducer_2d_driver_f_s_32_t: public reducer_2d_driver_t, + public jit_generator +{ + DECLARE_CPU_JIT_AUX_FUNCTIONS(reducer_2d_driver_f_s_32_t) + + /* cpu specific part */ + using Vmm = typename utils::conditional::type; + const AddressFrame &vmmword = (isa == avx2) ? yword : zword; + void uni_vadd(const Xmm& x1, const Xmm& x2, const Operand& op) + { if (data_type == data_type::f32) vaddps(x1, x2, op); + else vpaddd(x1, x2, op); } + void uni_add(const Xmm& x1, const Operand& op) + { if (data_type == data_type::f32) addss(x1, op); else paddd(x1, op); } + + const int vlen = cpu_isa_traits::vlen; + const int typesize + = sizeof(typename mkldnn::impl::prec_traits::type); + Xbyak::Reg64 reg_dst = abi_param1; + Xbyak::Reg64 reg_src = abi_param2; + Xbyak::Reg64 reg_ny = abi_param3; + Xbyak::Reg64 reg_nx = abi_param4; + + Xbyak::Reg64 reg_x = rax; + Xbyak::Reg64 reg_src_id = r10; + + reducer_2d_driver_f_s_32_t(int n_src, size_t src_ld, size_t src_step, + size_t dst_step, bool nullify_dst) + : reducer_2d_driver_t(n_src, src_ld, src_step, + dst_step, nullify_dst) + { generate(); } + + void nullify_dst(int nloads, int load_len) { + UNUSED(load_len); + for (int i = 0; i < nloads; ++i) + uni_vpxor(Vmm(i), Vmm(i), Vmm(i)); + /* prefetches[dst] ? */ + } + + void load_dst(int nloads, int load_len) { + for (int i = 0; i < nloads; ++i) { + if (load_len == typesize) + movd(Xmm(i), ptr[reg_dst + i * load_len]); + else if (load_len == vlen) + vmovups(Vmm(i), ptr[reg_dst + i * load_len]); + else + assert(!"unsupported"); + } + } + + void store_dst(int nloads, int load_len) { + for (int i = 0; i < nloads; ++i) { + if (load_len == typesize) + movd(ptr[reg_dst + i * load_len], Xmm(i)); + else if (load_len == vlen) + vmovups(ptr[reg_dst + i * load_len], Vmm(i)); + else + assert(!"unsupported"); + } + } + + void accumulate(int nloads, int load_len, size_t base_off) { + for (int i = 0; i < nloads; ++i) { + size_t off = base_off + i * load_len; + + if (load_len == typesize) + uni_add(Xmm(i), ptr[reg_src + off]); + else if (load_len == vlen) + uni_vadd(Vmm(i), Vmm(i), vmmword[reg_src + off]); + else + assert(!"unsupported"); + } + } + + void loop_x() { + const int nloads[] = {cpu_isa_traits::n_vregs, 1, 1}; + const int nbranches = sizeof(nloads) / sizeof(nloads[0]); + + const int load_len[nbranches] = {vlen, vlen, typesize}; + Label loop_x_label[nbranches + 1]; + + mov(reg_x, reg_nx); + + for (int id = 0; id < nbranches; ++id) { + L(loop_x_label[id]); + + cmp(reg_x, nloads[id] * load_len[id]); + jl(loop_x_label[id + 1], T_NEAR); + + if (this->nullify_dst_) + nullify_dst(nloads[id], load_len[id]); + else + load_dst(nloads[id], load_len[id]); + + if (nloads[id] > 1) { + Label loop_srcs; + mov(reg_src_id, this->n_src_); + L(loop_srcs); + + accumulate(nloads[id], load_len[id], 0); + add(reg_src, this->src_ld_ * typesize); + + dec(reg_src_id); + jnz(loop_srcs, T_NEAR); + + sub(reg_src, this->n_src_ * this->src_ld_ * typesize); + } else { + for (int src_id = 0; src_id < this->n_src_; ++src_id) { + const size_t base_off = src_id * this->src_ld_ * typesize; + accumulate(nloads[id], load_len[id], base_off); + } + } + + store_dst(nloads[id], load_len[id]); + + add(reg_src, nloads[id] * load_len[id]); + add(reg_dst, nloads[id] * load_len[id]); + + sub(reg_x, nloads[id] * load_len[id]); + + jmp(loop_x_label[id], T_NEAR); + } + + L(loop_x_label[nbranches]); + + /* restore address registers */ + sub(reg_src, reg_nx); + sub(reg_dst, reg_nx); + } + + void generate() { + assert(isa == avx2 || isa == avx512_common || isa == avx512_mic); + + preamble(); + + shl(reg_nx, 2); + + Label ny_loop; + L(ny_loop); + + loop_x(); + + add(reg_dst, this->dst_step_ * typesize); + add(reg_src, this->src_step_ * typesize); + + dec(reg_ny); + jnz(ny_loop, T_NEAR); + + postamble(); + this->ker_ = reinterpret_castker_)>( + const_cast(this->getCode())); + } +}; + +template +inline reducer_2d_driver_t *create_reduce_2d_drv(int n_src, + size_t src_ld, size_t src_step, size_t dst_step, bool nullify_dst) { + if (mayiuse(avx512_common)) + return new reducer_2d_driver_f_s_32_t(n_src, + src_ld, src_step, dst_step, nullify_dst); + else if (mayiuse(avx2)) + return new reducer_2d_driver_f_s_32_t(n_src, src_ld, + src_step, dst_step, nullify_dst); + assert(!"unimplemented"); + return nullptr; +} + +/* cpu_reducer_t */ + +template +void cpu_reducer_t::conf_t::init_scratchpad( + memory_tracking::registrar_t &scratchpad) const { + if (balancer_.nthr_per_group_ == 1) return; + + const size_t space_size = balancer_.ngroups_ + * (balancer_.nthr_per_group_ - 1) + * cpu_reducer_t::space_per_thread(balancer_); + scratchpad.book(key_reducer_space, sizeof(data_t) * space_size, PAGE_4K); + scratchpad.book(key_reducer_space_bctx, + sizeof(simple_barrier::ctx_t) * balancer_.ngroups_); +} + +template +cpu_reducer_t::cpu_reducer_t(const conf_t &conf) + : conf_(conf), drv_(nullptr) +{ + if (balancer().nthr_per_group_ == 1) return; + + drv_ = create_reduce_2d_drv(balancer().nthr_per_group_ - 1, + space_per_thread(balancer()), 0, 0, false); +} + +template +cpu_reducer_t::~cpu_reducer_t() { delete drv_; } + +template +typename cpu_reducer_t::data_t * +cpu_reducer_t::get_local_ptr(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + const int id_in_grp = balancer().id_in_group(ithr); + + /* threads 0 from each group writes directly to the destination */ + if (id_in_grp == 0) + return dst + balancer().ithr_job_off(ithr) * balancer().job_size_; + + const int grp_id = balancer().group_id(ithr); + const int offset_factor = grp_id * (balancer().nthr_per_group_ - 1) + + (id_in_grp - 1); + + auto space = scratchpad.template get(key_reducer_space); + return space + offset_factor * space_per_thread(balancer()); +} + +template +void cpu_reducer_t::reduce_nolock(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + bool redundant_reduction = balancer().nthr_per_group_ == 1 + || balancer().idle(ithr); + if (redundant_reduction) return; + +#ifdef SIMPLE_IMPL + if (balancer().id_in_group(ithr) != 0) + return; /* only threads 0 do the reduction */ + + const int njobs_in_grp = balancer().ithr_njobs(ithr); + data_t *d = get_local_ptr(ithr, dst, scratchpad); + for (int id_in_grp = 1; id_in_grp < balancer_.nthr_per_group_; ++id_in_grp) + { + const data_t *space = get_local_ptr(ithr + id_in_grp, dst, scratchpad); + for (size_t i = 0; i < (size_t)njobs_in_grp * balancer().job_size_; ++i) + d[i] += space[i]; + } +#else + using namespace utils; + + const int id_in_grp = balancer().id_in_group(ithr); + const int njobs_in_grp = balancer().ithr_njobs(ithr); + const size_t cl = 64 / sizeof(data_t); + + const size_t reduction_size = njobs_in_grp * balancer().job_size_; + size_t start{0}, end{0}; + balance211(div_up(reduction_size, cl), balancer().nthr_per_group_, + id_in_grp, start, end); + + if (start == end) return; + + data_t *d = get_local_ptr(ithr - id_in_grp, dst, scratchpad) + start * cl; + const data_t *space = get_local_ptr(ithr - id_in_grp + 1, dst, scratchpad) + + start * cl; + const size_t len = nstl::min(end * cl, reduction_size) - start * cl; + + (*drv_)(d, space, 1, len); +#endif +} + +template struct cpu_reducer_t; +template struct cpu_reducer_t; + +/* cpu_reducer_2d_t */ + +template +void cpu_reducer_2d_t::conf_t::init_scratchpad( + memory_tracking::registrar_t &scratchpad) const { + if (balancer_.nthr_per_group_ == 1) return; + + const size_t space_size = balancer_.ngroups_ * balancer_.nthr_per_group_ + * cpu_reducer_2d_t::space_per_thread(balancer_); + scratchpad.book(key_reducer_space, sizeof(data_t) * space_size); + scratchpad.book(key_reducer_space_bctx, + sizeof(simple_barrier::ctx_t) * balancer_.ngroups_); +} + +template +cpu_reducer_2d_t::cpu_reducer_2d_t(const conf_t &conf) + : conf_(conf), drv_(nullptr) +{ + if (balancer().nthr_per_group_ == 1) return; + + drv_ = create_reduce_2d_drv(balancer().nthr_per_group_, + space_per_thread(balancer()), conf_.job_size_x_, conf_.dst_x_, + true); +} + +template +cpu_reducer_2d_t::~cpu_reducer_2d_t() { delete drv_; } + +template +typename cpu_reducer_2d_t::data_t *cpu_reducer_2d_t:: +get_local_ptr(int ithr, const memory_tracking::grantor_t &scratchpad) const { + const int id_in_grp = balancer().id_in_group(ithr); + const int grp_id = balancer().group_id(ithr); + const int offset_factor = grp_id * balancer().nthr_per_group_ + id_in_grp; + auto space = scratchpad.template get(key_reducer_space); + return space + offset_factor * space_per_thread(balancer()); +} + +template +int cpu_reducer_2d_t::choose_x_blocking(int nx, int ny, + int nthr_per_grp) const { + // find x_blocking for better balance reducing work between threads + assert(conf_.x_block_ > 0 && nx > conf_.x_block_ + && nx % conf_.x_block_ == 0); + int x_blocking = nx / conf_.x_block_; + int min_x_blocking = + utils::div_up(x_blocking, nstl::max(1, nthr_per_grp / ny)); + while (true) { + if (x_blocking % 2 == 0 && x_blocking >= min_x_blocking * 2) + x_blocking /= 2; + else if (x_blocking % 3 == 0 && x_blocking >= min_x_blocking * 3) + x_blocking /= 3; + else + break; + } + if (x_blocking >= min_x_blocking * 4) x_blocking = 1; + x_blocking *= conf_.x_block_; + return x_blocking; +} + +template +void cpu_reducer_2d_t::reduce_block(const data_t* space_base, + data_t *dst, int job, int start_y, int start_x, + int ny_start, int nx_start, int ny_step, int nx_step) const { + data_t *d = dst + (start_y + ny_start) * conf_.dst_x_ + + start_x + nx_start; + const data_t *space = space_base + job * balancer().job_size_ + + ny_start * conf_.job_size_x_ + nx_start; +#ifdef SIMPLE_IMPL + for (int idg = 0; idg < balancer().nthr_per_group_; ++idg) { + const data_t *w = &space[idg * space_per_thread(balancer())]; + for (int y = 0; y < ny_step; ++y) + for (int x = 0; x < nx_step; ++x) { + d[y * conf_.dst_x_ + x] + = (idg == 0 ? 0 : d[y * conf_.dst_x_ + x]) + + w[y * conf_.job_size_x_ + x]; + } + } +#else + (*drv_)(d, space, ny_step, nx_step); +#endif +} + +template +void cpu_reducer_2d_t::reduce_nolock(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + bool redundant_reduction = balancer().nthr_per_group_ == 1 + || balancer().idle(ithr); + if (redundant_reduction) return; + + const int id_in_grp = balancer().id_in_group(ithr); + const int njobs_in_grp = balancer().ithr_njobs(ithr); + const int njobs_x = utils::div_up(conf_.dst_x_, conf_.job_size_x_); + const int global_job_start = balancer().ithr_job_off(ithr); + + const data_t *space_base = get_local_ptr(ithr - id_in_grp, scratchpad); + + const int pr_grps = nstl::min(njobs_in_grp, balancer().nthr_per_group_); + const int pr_nthr_per_grp = balancer().nthr_per_group_ / pr_grps; + + if (id_in_grp >= pr_grps * pr_nthr_per_grp) + return; /* idle */ + + const int pr_my_grp = id_in_grp / pr_nthr_per_grp; + const int pr_my_id = id_in_grp % pr_nthr_per_grp; + + int pr_job_start{0}, pr_job_end{0}; + balance211(njobs_in_grp, pr_grps, pr_my_grp, pr_job_start, pr_job_end); + + for (int j = pr_job_start; j < pr_job_end; ++j) { + const int global_job = global_job_start + j; + const int j_y = global_job / njobs_x; + const int j_x = global_job % njobs_x; + const int start_y = j_y * conf_.job_size_y_; + const int start_x = j_x * conf_.job_size_x_; + const int ny = nstl::min(conf_.dst_y_ - start_y, conf_.job_size_y_); + const int nx = nstl::min(conf_.dst_x_ - start_x, conf_.job_size_x_); + int x_blocking = choose_x_blocking(nx, ny, pr_nthr_per_grp); + + int nxy_start{0}, nxy_end{0}; + balance211(ny * nx / x_blocking, pr_nthr_per_grp, pr_my_id, + nxy_start, nxy_end); + if (nxy_start == nxy_end) continue; + nxy_start *= x_blocking; + nxy_end *= x_blocking; + + int nxy = nxy_start; + if (nxy % nx != 0) { + int nx_step = nstl::min(nx - nxy % nx, nxy_end - nxy); + reduce_block(space_base, dst, j, start_y, start_x, + nxy / nx, nxy % nx, 1, nx_step); + nxy += nx_step; + } + if ((nxy_end - nxy) > nx) { + int ny_step = (nxy_end - nxy) / nx; + reduce_block(space_base, dst, j, start_y, start_x, + nxy / nx, nxy % nx, ny_step, nx); + nxy += nx * ny_step; + } + if ((nxy_end - nxy) > 0) { + reduce_block(space_base, dst, j, start_y, start_x, + nxy / nx, nxy % nx, 1, nxy_end - nxy); + } + } +} + +template struct cpu_reducer_2d_t; +template struct cpu_reducer_2d_t; + +/* accumulator section */ + +template +cpu_accumulator_1d_t::cpu_accumulator_1d_t(): drv_(nullptr) { + drv_ = create_reduce_2d_drv(1, 0, 0, 0, false); +} + +template +cpu_accumulator_1d_t::~cpu_accumulator_1d_t() { + delete drv_; +} + +template +void cpu_accumulator_1d_t::accumulate(data_t *dst, + const data_t *src, size_t size) { + (*drv_)(dst, src, 1, size); +} + +template struct cpu_accumulator_1d_t; +template struct cpu_accumulator_1d_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp new file mode 100644 index 0000000000..27f5939cd2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp @@ -0,0 +1,334 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REDUCER_HPP +#define CPU_REDUCER_HPP + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "mkldnn_types.h" +#include "nstl.hpp" +#include "type_helpers.hpp" + +#include "cpu_barrier.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +/** class to perform balancing over 3D array + * + * Conceptually the reduction happens according to the picture below: + * + * <--job_size-> + * +-----------+ +-----------+ +-----------+ ^ + * | | | | | | | + * | | | | | | | + * | 1 | | 2 | . . . | njobs | | reduction_size + * | | | | | | | + * | | | | | | | + * +-----------+ +-----------+ +-----------+ v + * + * | | | | | | | | | + * v v v v v v v v v + * ===================================================== vertical reduction + * + * +-----------+ +-----------+ . . . +-----------+ result + * + * In a simple case the result must be contiguous in memory. + * @class cpu_reducer_t is an implementation. + * + * Threads are divided into groups. The groups are independent of each other. + * Each group may work on several jobs (the distribution is not uniform, since + * njobs might be not a multiple of groups). Threads within a group work on + * different parts of the reduction dimension. Thread 0 in each group is called + * master (@sa reduce_balancer_t::master()). + * + * If threading driver does not allow sync between sub-group of threads (e.g. + * Intel(R) TBB) the # of thread per group is enforced to be 1. + */ +struct reduce_balancer_t { + reduce_balancer_t() { init(1, 1, 1, 1, 0); } /* trivial balance */ + reduce_balancer_t(int nthr, int job_size, int njobs, int reduction_size, + size_t max_buffer_size) + { init(nthr, job_size, njobs, reduction_size, max_buffer_size); } + + reduce_balancer_t &init(int nthr, int job_size, int njobs, + int reduction_size, size_t max_buffer_size) + { + syncable_ = mkldnn_thr_syncable(); + nthr_ = nthr; + job_size_ = job_size; + njobs_ = njobs; + reduction_size_ = reduction_size; + max_buffer_size_ = max_buffer_size; + balance(); + return *this; + } + + bool syncable_; + int nthr_; + int job_size_, njobs_, reduction_size_; + + int ngroups_; /** number of independent work (thread) groups */ + int nthr_per_group_; /** number of threads within a single work group */ + int njobs_per_group_ub_; /** the max # of jobs within a work group */ + + bool master(int ithr) const { return id_in_group(ithr) == 0; } + bool idle(int ithr) const { return ithr >= nthr_per_group_ * ngroups_; } + + int group_id(int ithr) const { return ithr / nthr_per_group_; } + int id_in_group(int ithr) const { return ithr % nthr_per_group_; } + + int grp_njobs(int grp) const { + if (grp >= ngroups_) return 0; + return njobs_ / ngroups_ + (grp < njobs_ % ngroups_); + } + int grp_job_off(int grp) const { + if (grp >= ngroups_) return njobs_; + return njobs_ / ngroups_ * grp + nstl::min(grp, njobs_ % ngroups_); + } + + int ithr_njobs(int ithr) const { return grp_njobs(group_id(ithr)); } + int ithr_job_off(int ithr) const { return grp_job_off(group_id(ithr)); } + +private: + size_t max_buffer_size_; + void balance(); +}; + +/** forward declaration of reduce driver */ +template struct reducer_2d_driver_t; + +/** class to perform a reduction over 3D array + * + * Balancing is based on @class reduce_balancer_t. + * Restrictions: the result of the reduction must be contiguous in memory. * + * The reduction happens according to the picture below (once more): + * + * <--job_size-> + * +-----------+ +-----------+ +-----------+ ^ + * | | | | | | | + * | | | | | | | + * | 1 | | 2 | . . . | njobs | | reduction_size + * | | | | | | | + * | | | | | | | + * +-----------+ +-----------+ +-----------+ v + * + * | | | | | | | | | + * v v v v v v v v v + * ===================================================== vertical reduction + * + * +-----------+ +-----------+ . . . +-----------+ (contiguous) result + * + * An example how work might be shared is shown below. + * + * In this example group 0 owns 2 (independent) jobs -- 2 big squares. + * The number of threads per group is also 2 (thread 0 of group 0 and thread 1 + * of group 0). Master threads (i.e. threads with id 0 in corresponding group) + * from each group put the partial result directly into destination memory, + * while all the other threads with-in the group use workspace (on the picture + * the only thread 1). Once intermediate results obtained each group reduces + * corresponding part (own jobs) to the destination memory. + * + * <------- group 0 -------> + * + * +-----------+ +-----------+ ^ + * | | | | | thread 0 of reduces to the dest-memory + * | | | | | group 0 +-----------+ +-----------+ + * |- - - - - -| |- - - - - -| X + * | | | | | thread 1 of reduces to workspace[tid=1]: + * | | | | | group 0 +-----------+ +-----------+ + * +-----------+ +-----------+ v + * | | | | | | + * v v v v v v + * ((barrier)) ============================= + * + * dest-memory: +-----------+ +-----------+ + */ +template +struct cpu_reducer_t { + typedef typename prec_traits::type data_t; + + struct conf_t { + conf_t() = default; + conf_t &init(const reduce_balancer_t &balancer) + { balancer_ = balancer; return *this; } + + void init_scratchpad(memory_tracking::registrar_t &scratchpad) const; + + reduce_balancer_t balancer_; + }; + + cpu_reducer_t(const conf_t &conf); + ~cpu_reducer_t(); + + /** initializes reducer. + * Must be called from a single thread prior to actual usage */ + void init(const memory_tracking::grantor_t &scratchpad) const { + if (balancer().nthr_per_group_ == 1) return; + + auto bctx = scratchpad.template get( + memory_tracking::names::key_reducer_space_bctx); + for (int i = 0; i < balancer().ngroups_; ++i) + simple_barrier::ctx_init(&bctx[i]); + } + + /** for given thread returns the pointer where to put partial results. + * Reduction destination @p dst must be provided as well (master threads + * from each group will use it for partial result to reduce memory + * pressure). + * + * @note: job offset is already applied by get_local_ptr(), which means all + * threads should start writing from the very beginning of returned + * address. + */ + data_t *get_local_ptr(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const; + + /** performs the reduction with built-in synchronization. */ + void reduce(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + bool redundant_reduction = balancer().nthr_per_group_ == 1 + || balancer().idle(ithr); + if (redundant_reduction) return; + + auto bctx = scratchpad.template get( + memory_tracking::names::key_reducer_space_bctx); + simple_barrier::barrier(&bctx[balancer().group_id(ithr)], + balancer().nthr_per_group_); + + reduce_nolock(ithr, dst, scratchpad); + } + + const reduce_balancer_t &balancer() const { return conf_.balancer_; } + +private: + static size_t space_per_thread(const reduce_balancer_t &balancer) + { return balancer.njobs_per_group_ub_ * balancer.job_size_; } + + /* The scratchpad is organized as follows: + * + * data_t space[nthr_][njobs_per_group_ub_][jobs_size_]; + * simple_barrier::ctx_t barriers[groups_]; */ + + const conf_t conf_; + reducer_2d_driver_t *drv_; + + void reduce_nolock(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const; +}; + +template +struct cpu_reducer_2d_t { + typedef typename prec_traits::type data_t; + + struct conf_t { + conf_t() = default; + conf_t &init(const reduce_balancer_t &balancer, int job_size_x, + int job_size_y, int x_block, int dst_x, int dst_y) { + balancer_ = balancer; + job_size_x_ = job_size_x; + job_size_y_ = job_size_y; + x_block_ = x_block; + dst_x_ = dst_x; + dst_y_ = dst_y; + return *this; + } + + void init_scratchpad(memory_tracking::registrar_t &scratchpad) const; + + reduce_balancer_t balancer_; + int job_size_x_, job_size_y_, x_block_, dst_x_, dst_y_; + }; + + cpu_reducer_2d_t(const conf_t &conf); + ~cpu_reducer_2d_t(); + + /** initializes reducer. + * Must be called from a single thread prior to actual usage */ + void init(const memory_tracking::grantor_t &scratchpad) const { + if (balancer().nthr_per_group_ == 1) return; + + auto bctx = scratchpad.template get( + memory_tracking::names::key_reducer_space_bctx); + for (int i = 0; i < balancer().ngroups_; ++i) + simple_barrier::ctx_init(&bctx[i]); + } + + /** for given thread returns the pointer where to put partial results */ + data_t *get_local_ptr(int ithr, + const memory_tracking::grantor_t &scratchpad) const; + + /** performs the reduction with built-in synchronization. */ + void reduce(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + bool redundant_reduction = balancer().nthr_per_group_ == 1 + || balancer().idle(ithr); + if (redundant_reduction) return; + + auto bctx = scratchpad.template get( + memory_tracking::names::key_reducer_space_bctx); + simple_barrier::barrier(&bctx[balancer().group_id(ithr)], + balancer().nthr_per_group_); + + reduce_nolock(ithr, dst, scratchpad); + } + + const reduce_balancer_t &balancer() const { return conf_.balancer_; } + +private: + static size_t space_per_thread(const reduce_balancer_t &balancer) + { return balancer.njobs_per_group_ub_ * balancer.job_size_; } + + /* The scratchpad is organized as follows: + * + * data_t space[nthr_][njobs_per_group_ub_][jobs_size_]; + * simple_barrier::ctx_t barriers[groups_]; */ + + const conf_t conf_; + reducer_2d_driver_t *drv_; + + int choose_x_blocking(int nx, int ny, int nthr_per_grp) const; + void reduce_block(const data_t* space_base, data_t *dst, + int job, int start_y, int start_x, + int ny_start, int nx_start, int ny_step, int nx_step) const; + void reduce_nolock(int ithr, data_t *dst, + const memory_tracking::grantor_t &scratchpad) const; +}; + +/** simple 1d accumulator: y[:] += x[:] */ +template +struct cpu_accumulator_1d_t { + typedef typename prec_traits::type data_t; + + cpu_accumulator_1d_t(); + ~cpu_accumulator_1d_t(); + void accumulate(data_t *dst, const data_t *src, size_t size); + + reducer_2d_driver_t *drv_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp new file mode 100644 index 0000000000..82be70353d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp @@ -0,0 +1,262 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "cpu_engine.hpp" +#include "cpu_primitive.hpp" +#include "cpu_reorder_pd.hpp" +#include "cpu_memory.hpp" +#include "type_helpers.hpp" + +#include "cpu/jit_uni_reorder.hpp" +#include "cpu/simple_reorder.hpp" +#include "cpu/wino_reorder.hpp" +#include "cpu/rnn/rnn_reorders.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using rpd_create_f = mkldnn::impl::engine_t::reorder_primitive_desc_create_f; + +namespace { +using namespace mkldnn::impl::data_type; +using namespace mkldnn::impl::format_tag; + +#define REG_SR(idt, ifmt, odt, ofmt, ...) \ + simple_reorder_t::pd_t::create + +#define REG_SR_BIDIR(idt, ifmt, odt, ofmt) \ + REG_SR(idt, ifmt, odt, ofmt, fmt_order::keep), \ + REG_SR(idt, ifmt, odt, ofmt, fmt_order::reverse) + +#define REG_SR_DIRECT_COPY(idt, odt) \ + REG_SR(idt, any, odt, any, fmt_order::any, spec::direct_copy), \ + REG_SR(idt, any, odt, any, fmt_order::any, spec::direct_copy_except_dim_0) + +static const rpd_create_f cpu_reorder_impl_list[] = { + /* winograd */ + wino_reorder_t::pd_t::create, + //wino_reorder_t::pd_t::create, + + /* rnn reorders */ + rnn_data_reorder_t::pd_t::create, + rnn_weights_reorder_t::pd_t::create, + rnn_weights_reorder_t::pd_t::create, + + /* conv reorders w/ compensation */ + REG_SR(f32, any, s8, hwio, fmt_order::keep, spec::conv_s8s8), + REG_SR(f32, any, s8, hwigo, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, any, s8, hwio, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, any, s8, hwigo, fmt_order::keep, spec::conv_s8s8), + + REG_SR(f32, oiw, s8, OIw4i16o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(f32, goiw, s8, gOIw4i16o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, oiw, s8, OIw4i16o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, goiw, s8, gOIw4i16o4i, fmt_order::keep, spec::conv_s8s8), + + REG_SR(f32, oihw, s8, OIhw4i16o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(f32, goihw, s8, gOIhw4i16o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, oihw, s8, OIhw4i16o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, goihw, s8, gOIhw4i16o4i, fmt_order::keep, spec::conv_s8s8), + + REG_SR(f32, goihw, s8, gOIhw2i8o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, goihw, s8, gOIhw2i8o4i, fmt_order::keep, spec::conv_s8s8), + + REG_SR(f32, goihw, s8, gOIhw4o4i, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, goihw, s8, gOIhw4o4i, fmt_order::keep, spec::conv_s8s8), + + REG_SR(f32, goiw, s8, Goiw16g, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, goiw, s8, Goiw16g, fmt_order::keep, spec::conv_s8s8), + REG_SR(f32, goihw, s8, Goihw16g, fmt_order::keep, spec::conv_s8s8), + REG_SR(s8, goihw, s8, Goihw16g, fmt_order::keep, spec::conv_s8s8), + + /* regular reorders */ + +#if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__)) + /* Direct copy for icc which is faster than jitted code; + * Direct copy for gcc which might or might not be faster than jitted + * code, but still worth it because doesn't require jitting, i.e. much + * faster creation time. This is tentative solution and should be removed + * later (when we will cache jitted code?...). */ + REG_SR_DIRECT_COPY(f32, f32), +#endif + +#ifdef __INTEL_COMPILER + /* direct copy for icc, which is faster than jitted code */ + /* + REG_SR_DIRECT_COPY(f32, s32), + REG_SR_DIRECT_COPY(f32, s8), + REG_SR_DIRECT_COPY(f32, u8), + REG_SR_DIRECT_COPY(s32, f32), + REG_SR_DIRECT_COPY(s32, s32), + REG_SR_DIRECT_COPY(s32, s8), + REG_SR_DIRECT_COPY(s32, u8), + REG_SR_DIRECT_COPY(s8, f32), + REG_SR_DIRECT_COPY(s8, s32), + REG_SR_DIRECT_COPY(s8, s8), + REG_SR_DIRECT_COPY(s8, u8), + REG_SR_DIRECT_COPY(u8, f32), + REG_SR_DIRECT_COPY(u8, s32), + REG_SR_DIRECT_COPY(u8, s8), + REG_SR_DIRECT_COPY(u8, u8), + */ +#endif + + /* jit */ + jit_uni_reorder_create, + + /* fp32: flat <-> blocked with tail */ + /* + REG_SR_BIDIR(f32, any, f32, nCw4c), + REG_SR_BIDIR(f32, any, f32, nCw8c), + REG_SR_BIDIR(f32, any, f32, OIw4i4o), + REG_SR_BIDIR(f32, any, f32, OIw8i8o), + REG_SR_BIDIR(f32, any, f32, OIw8o8i), + REG_SR_BIDIR(f32, any, f32, gOIw4i4o), + REG_SR_BIDIR(f32, any, f32, gOIw8i8o), + REG_SR_BIDIR(f32, any, f32, gOIw8o8i), + + REG_SR_BIDIR(f32, any, f32, nCw16c), + REG_SR_BIDIR(f32, any, f32, OIw16o16i), + REG_SR_BIDIR(f32, any, f32, OIw16i16o), + REG_SR_BIDIR(f32, any, f32, IOw16o16i), + REG_SR_BIDIR(f32, any, f32, gOIw16o16i), + REG_SR_BIDIR(f32, any, f32, gOIw16i16o), + REG_SR_BIDIR(f32, any, f32, gIOw16o16i), + + REG_SR_BIDIR(f32, any, f32, nChw4c), + REG_SR_BIDIR(f32, any, f32, nChw8c), + REG_SR_BIDIR(f32, any, f32, OIhw4i4o), + REG_SR_BIDIR(f32, any, f32, Ohwi8o), + + REG_SR_BIDIR(f32, any, f32, OIhw8i8o), + REG_SR_BIDIR(f32, any, f32, OIhw8o8i), + REG_SR_BIDIR(f32, any, f32, gOIhw4i4o), + REG_SR_BIDIR(f32, any, f32, gOIhw4o4i), + REG_SR_BIDIR(f32, any, f32, gOhwi8o), + REG_SR_BIDIR(f32, any, f32, gOIhw8i8o), + REG_SR_BIDIR(f32, any, f32, gOIhw8o8i), + + REG_SR_BIDIR(f32, any, f32, nChw16c), + REG_SR_BIDIR(f32, any, f32, Oihw4o), + REG_SR_BIDIR(f32, any, f32, Oihw16o), + REG_SR_BIDIR(f32, any, f32, Ohwi4o), + REG_SR_BIDIR(f32, any, f32, Ohwi16o), + REG_SR_BIDIR(f32, any, f32, OIhw16o16i), + REG_SR_BIDIR(f32, any, f32, OIhw16i16o), + REG_SR_BIDIR(f32, any, f32, IOhw16o16i), + REG_SR_BIDIR(f32, any, f32, gOihw4o), + REG_SR_BIDIR(f32, any, f32, gOihw16o), + REG_SR_BIDIR(f32, any, f32, gOhwi4o), + REG_SR_BIDIR(f32, any, f32, gOhwi16o), + REG_SR_BIDIR(f32, any, f32, gOIhw16o16i), + REG_SR_BIDIR(f32, any, f32, gOIhw16i16o), + REG_SR_BIDIR(f32, any, f32, gIOhw16o16i), + + REG_SR_BIDIR(f32, any, f32, nCdhw4c), + REG_SR_BIDIR(f32, any, f32, nCdhw8c), + REG_SR_BIDIR(f32, any, f32, OIdhw4i4o), + REG_SR_BIDIR(f32, any, f32, Odhwi8o), + REG_SR_BIDIR(f32, any, f32, OIdhw8i8o), + REG_SR_BIDIR(f32, any, f32, OIdhw8o8i), + REG_SR_BIDIR(f32, any, f32, gOIdhw4i4o), + REG_SR_BIDIR(f32, any, f32, gOdhwi8o), + REG_SR_BIDIR(f32, any, f32, gOIdhw8i8o), + REG_SR_BIDIR(f32, any, f32, gOIdhw8o8i), + + REG_SR_BIDIR(f32, any, f32, nCdhw16c), + REG_SR_BIDIR(f32, any, f32, Oidhw4o), + REG_SR_BIDIR(f32, any, f32, Oidhw16o), + REG_SR_BIDIR(f32, any, f32, Odhwi16o), + REG_SR_BIDIR(f32, any, f32, OIdhw16o16i), + REG_SR_BIDIR(f32, any, f32, OIdhw16i16o), + REG_SR_BIDIR(f32, any, f32, gOidhw4o), + REG_SR_BIDIR(f32, any, f32, gOidhw16o), + REG_SR_BIDIR(f32, any, f32, gOdhwi16o), + REG_SR_BIDIR(f32, any, f32, gOIdhw16o16i), + REG_SR_BIDIR(f32, any, f32, gOIdhw16i16o), + */ + + /* fp32: blocked <-> blocked with tail */ + REG_SR_BIDIR(f32, nCw8c, f32, nCw16c), + REG_SR_BIDIR(f32, nChw8c, f32, nChw16c), + REG_SR_BIDIR(f32, nCdhw8c, f32, nCdhw16c), + + /* int: flat <-> blocked with tail */ + /* + REG_SR_BIDIR(f32, any, s32, nChw16c), + REG_SR_BIDIR(f32, any, s8, nChw16c), + REG_SR_BIDIR(f32, any, u8, nChw16c), + REG_SR_BIDIR(s32, any, f32, nChw16c), + REG_SR_BIDIR(s32, any, s32, nChw16c), + REG_SR_BIDIR(s32, any, s8, nChw16c), + REG_SR_BIDIR(s32, any, u8, nChw16c), + REG_SR_BIDIR(s8, any, f32, nChw16c), + REG_SR_BIDIR(s8, any, s32, nChw16c), + REG_SR_BIDIR(s8, any, s8, nChw16c), + REG_SR_BIDIR(s8, any, u8, nChw16c), + REG_SR_BIDIR(u8, any, f32, nChw16c), + REG_SR_BIDIR(u8, any, s32, nChw16c), + REG_SR_BIDIR(u8, any, s8, nChw16c), + REG_SR_BIDIR(u8, any, u8, nChw16c), + + REG_SR_BIDIR(f32, any, f32, OIhw4i16o4i), + REG_SR_BIDIR(f32, any, s8, OIhw4i16o4i), + REG_SR_BIDIR(s8, any, f32, OIhw4i16o4i), + REG_SR_BIDIR(s8, any, s8, OIhw4i16o4i), + REG_SR_BIDIR(f32, any, s8, gOIhw4i16o4i), + REG_SR_BIDIR(s8, any, f32, gOIhw4i16o4i), + REG_SR_BIDIR(f32, any, f32, gOIhw4i16o4i), + REG_SR_BIDIR(s8, any, s8, gOIhw4i16o4i), + */ + + /* reference: the last line of defence */ + /* + REG_SR(f32, any, f32, any, fmt_order::any, spec::reference), + REG_SR(f32, any, s32, any, fmt_order::any, spec::reference), + REG_SR(f32, any, s8, any, fmt_order::any, spec::reference), + REG_SR(f32, any, u8, any, fmt_order::any, spec::reference), + + REG_SR(s32, any, f32, any, fmt_order::any, spec::reference), + REG_SR(s32, any, s32, any, fmt_order::any, spec::reference), + REG_SR(s32, any, s8, any, fmt_order::any, spec::reference), + REG_SR(s32, any, u8, any, fmt_order::any, spec::reference), + + REG_SR(s8, any, f32, any, fmt_order::any, spec::reference), + REG_SR(s8, any, s32, any, fmt_order::any, spec::reference), + REG_SR(s8, any, s8, any, fmt_order::any, spec::reference), + REG_SR(s8, any, u8, any, fmt_order::any, spec::reference), + + REG_SR(u8, any, f32, any, fmt_order::any, spec::reference), + REG_SR(u8, any, s32, any, fmt_order::any, spec::reference), + REG_SR(u8, any, u8, any, fmt_order::any, spec::reference), + REG_SR(u8, any, s8, any, fmt_order::any, spec::reference), + */ + + /* eol */ + nullptr, +}; +} + +const rpd_create_f *cpu_engine_t::get_reorder_implementation_list() const { + return cpu_reorder_impl_list; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp new file mode 100644 index 0000000000..1622eb6849 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp @@ -0,0 +1,48 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REORDER_PD_HPP +#define CPU_REORDER_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "reorder_pd.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_reorder_pd_t: public reorder_pd_t { + using reorder_pd_t::reorder_pd_t; + + status_t init() { + const auto &post_ops = attr()->post_ops_; + bool args_ok = IMPLICATION(post_ops.len_ != 0, post_ops.len_ == 1 + && post_ops.entry_[0].kind == primitive_kind::sum); + scratchpad_engine_ = src_engine_; + return args_ok ? status::success : status::unimplemented; + } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp new file mode 100644 index 0000000000..f16587b99f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp @@ -0,0 +1,41 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_SHUFFLE_PD_HPP +#define CPU_SHUFFLE_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "shuffle_pd.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_shuffle_pd_t: public shuffle_pd_t { + using shuffle_pd_t::shuffle_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp new file mode 100644 index 0000000000..3a39eab974 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp @@ -0,0 +1,45 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_SOFTMAX_PD_HPP +#define CPU_SOFTMAX_PD_HPP + +#include + +#include "c_types_map.hpp" +#include "softmax_pd.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_softmax_fwd_pd_t: public softmax_fwd_pd_t { + using softmax_fwd_pd_t::softmax_fwd_pd_t; +}; + +struct cpu_softmax_bwd_pd_t: public softmax_bwd_pd_t { + using softmax_bwd_pd_t::softmax_bwd_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp new file mode 100644 index 0000000000..1ab5d9f174 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp @@ -0,0 +1,48 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "cpu_engine.hpp" + +/* +#include "cpu/ref_sum.hpp" +#include "cpu/simple_sum.hpp" +*/ + +namespace mkldnn { +namespace impl { +namespace cpu { + +using spd_create_f = mkldnn::impl::engine_t::sum_primitive_desc_create_f; + +namespace { +#define INSTANCE(...) __VA_ARGS__::pd_t::create +static const spd_create_f cpu_sum_impl_list[] = { + /* + INSTANCE(simple_sum_t), + INSTANCE(ref_sum_t), + */ + nullptr, +}; +#undef INSTANCE +} + +const spd_create_f *cpu_engine_t::get_sum_implementation_list() const { + return cpu_sum_impl_list; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp new file mode 100644 index 0000000000..0965129f9b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp @@ -0,0 +1,39 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_SUM_PD_HPP +#define CPU_SUM_PD_HPP + +#include "c_types_map.hpp" +#include "sum_pd.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_sum_pd_t: public sum_pd_t { + using sum_pd_t::sum_pd_t; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp new file mode 100644 index 0000000000..a9810dec28 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp @@ -0,0 +1,372 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ +#include + +#include "mkldnn_thread.hpp" +#include "utils.hpp" +#include "gemm_utils_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { +namespace gemm_utils { +#define BM_NOCOPY_AVX 64 +#define BN_NOCOPY_AVX 48 +#define BK_NOCOPY_AVX 384 +#define BN_LARGE_NOCOPY_AVX 192 +#define BM_SMALL_NOCOPY_AVX 16 +#define BN_SMALL_NOCOPY_AVX 1 +#define BK_SMALL_NOCOPY_AVX 4 +// Determine number of threads for each dimension of a 3-D partitioning +// algorithm based on input parameters +// m/n/k - First/second/third parameter for GEMM +// nthrs - total available number of threads +// nthrs_m/nthrs_n/nthrs_k - number of threads to use in each dimension +// BM/BN/BK - blocking values +void calc_nthr_nocopy_avx(int m, int n, int k, + int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k, int *BM, int *BN, + int *BK) +{ + int nthr, nthr_m, nthr_n, nthr_k; + int MB, NB, KB; + + nthr = nthrs; + nthr_m = (m + BM_NOCOPY_AVX - 1) / BM_NOCOPY_AVX; + nthr_n = (n + BN_NOCOPY_AVX - 1) / BN_NOCOPY_AVX; + nthr_k = 1; + + // Partition along K dimension + // - if threading allows having barriers (e.g. OMP) + // - if there is not enough parallelism along M or N + if (mkldnn_thr_syncable()) { + int nthr_other = nthr_k = 1; + while ((nthr_m * nthr_n * nthr_other < nthr) + && (k / (nthr_other + 1) > BK_NOCOPY_AVX)) { + nthr_other++; + if ((nthr / nthr_other) * nthr_other > 0.9 * nthr) + nthr_k = nthr_other; + } + } + nthr /= nthr_k; + + if (nthr_m == 1) + nthr_n = nthr; + if (nthr_n == 1) + nthr_m = nthr; + + // Simple partition reduction + while (nthr_m * nthr_n > nthr) + if (nthr_m > nthr_n) + nthr_m--; + else + nthr_n--; + while (nthr_m * nthr_n < nthr) + if (nthr_m < nthr_n) + nthr_m++; + else + nthr_n++; + + if ((nthr_m * nthr_n > nthr) && (nthr_m > 1) && (nthr_n > 1)) { + + if (nthr_m <= nthr_n) { + nthr_m = (int)sqrt((double)nthr); + if (nthr_m > (m + BM_SMALL_NOCOPY_AVX - 1) / BM_SMALL_NOCOPY_AVX) + nthr_m = (m + BM_SMALL_NOCOPY_AVX - 1) / BM_SMALL_NOCOPY_AVX; + nthr_n = nthr / nthr_m; + + while ((nthr_m > 1) && (nthr_m * nthr_n != nthr)) { + nthr_m--; + nthr_n = nthr / nthr_m; + } + } else { + nthr_n = (int)sqrt((double)nthr); + if (nthr_n > (n + BN_SMALL_NOCOPY_AVX - 1) / BN_SMALL_NOCOPY_AVX) + nthr_n = (n + BN_SMALL_NOCOPY_AVX - 1) / BN_SMALL_NOCOPY_AVX; + nthr_m = nthr / nthr_n; + + while ((nthr_n > 1) && (nthr_m * nthr_n != nthr)) { + nthr_n--; + nthr_m = nthr / nthr_n; + } + } + } + + MB = (m + nthr_m - 1) / nthr_m + BM_SMALL_NOCOPY_AVX - 1; + MB -= MB % BM_SMALL_NOCOPY_AVX; + NB = (n + nthr_n - 1) / nthr_n + BN_SMALL_NOCOPY_AVX - 1; + NB -= NB % BN_SMALL_NOCOPY_AVX; + KB = (k + nthr_k - 1) / nthr_k + BK_SMALL_NOCOPY_AVX - 1; + KB -= KB % BK_SMALL_NOCOPY_AVX; + + if (MB * nthr_m > m) + nthr_m = (m + MB - 1) / MB; + if (NB * nthr_n > n) + nthr_n = (n + NB - 1) / NB; + if (KB * nthr_k > k) + nthr_k = (k + KB - 1) / KB; + + *nthrs_m = nthr_m; + *nthrs_n = nthr_n; + *nthrs_k = nthr_k; + + *BM = MB; + *BN = NB; + *BK = KB; +} +#undef BM_NOCOPY_AVX +#undef BN_NOCOPY_AVX +#undef BK_NOCOPY_AVX +#undef BN_LARGE_NOCOPY_AVX +#undef BM_SMALL_NOCOPY_AVX +#undef BN_SMALL_NOCOPY_AVX +#undef BK_SMALL_NOCOPY_AVX + +#define BM_NOCOPY_AVX512_COMMON 32 +#define BN_NOCOPY_AVX512_COMMON 64 +#define BK_NOCOPY_AVX512_COMMON 192 +#define BN_LARGE_NOCOPY_AVX512_COMMON 192 +#define BM_SMALL_NOCOPY_AVX512_COMMON 16 +#define BN_SMALL_NOCOPY_AVX512_COMMON 1 +#define BK_SMALL_NOCOPY_AVX512_COMMON 4 +// Determine number of threads for each dimension of a 3-D partitioning +// algorithm based on input parameters +// m/n/k - First/second/third parameter for GEMM +// nthrs - total available number of threads +// nthrs_m/nthrs_n/nthrs_k - number of threads to use in each dimension +// BM/BN/BK - blocking values +void calc_nthr_nocopy_avx512_common(int m, + int n, int k, int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k, + int *BM, int *BN, int *BK) +{ + int nthr, nthr_m, nthr_n, nthr_k = 1; + int MB, NB, KB; + nthr = nthrs; + + int counter = 0; + float ratio_float = 1.; + int ratio = 1; + nthr = nthrs; + int nthr_m_gt_n; + + // Partition along K dimension + // - if threading allows having barriers (e.g. OMP) + // - if there is not enough parallelism along M or N + if (mkldnn_thr_syncable()) { + if (n <= 2 * BN_NOCOPY_AVX512_COMMON && + m <= 2 * BM_NOCOPY_AVX512_COMMON * nthr) { + nthr_k = k / BK_NOCOPY_AVX512_COMMON; + if (nthr_k > nthr / 4) + nthr_k = nthr / 4; + if (nthr_k < 1) + nthr_k = 1; + + while ((nthr_k > 1) && (nthr % nthr_k)) { + nthr_k--; + } + nthr /= nthr_k; + } else { + nthr_k = 1; + } + } + nthr_m = (m + BM_NOCOPY_AVX512_COMMON - 1) / BM_NOCOPY_AVX512_COMMON; + nthr_n = (n + BN_NOCOPY_AVX512_COMMON - 1) / BN_NOCOPY_AVX512_COMMON; + + if (nthr_m < 1) + nthr_m = 1; + if (nthr_n < 1) + nthr_n = 1; + + nthr_m_gt_n = nthr_m > nthr_n ? 1 : 0; + ratio_float = (float)nthr_m / nthr_n; + + if (nthr_m_gt_n) + ratio = (int)ratio_float; + else + ratio = (int)(1. / ratio_float); + + // scale down nthr_m and nthr_n if they are too large + while (nthr_m * nthr_n > 4 * nthr) { + nthr_m /= 2; + nthr_n /= 2; + } + + if (nthr_m < 1) + nthr_m = 1; + if (nthr_n < 1) + nthr_n = 1; + + // Simple partition reduction + counter = 0; + while (nthr_m * nthr_n > nthr) { + if (nthr_m > nthr_n) { + if (counter < ratio) + nthr_m--; + else { + nthr_n--; + counter = -1; + } + } else { + if (counter < ratio) + nthr_n--; + else { + nthr_m--; + counter = -1; + } + } + counter++; + } + + // Simple partition increment + counter = 0; + while (nthr_m * nthr_n < 0.95 * nthr) { + if (nthr_m > nthr_n) { + if (counter < ratio) + nthr_m++; + else { + nthr_n++; + counter = -1; + } + } else { + if (counter < ratio) + nthr_n++; + else { + nthr_m++; + counter = -1; + } + } + counter++; + } + + // if nothing works out, then this should work + if ((nthr_m * nthr_n > nthr)) { + + if (nthr_m <= nthr_n) { + nthr_m = (int)sqrt((double)nthr); + if (nthr_m > (m + BM_SMALL_NOCOPY_AVX512_COMMON - 1) + / BM_SMALL_NOCOPY_AVX512_COMMON) + nthr_m = (m + BM_SMALL_NOCOPY_AVX512_COMMON - 1) + / BM_SMALL_NOCOPY_AVX512_COMMON; + nthr_n = nthr / nthr_m; + + while ((nthr_m > 1) && (nthr_m * nthr_n != nthr)) { + nthr_m--; + nthr_n = nthr / nthr_m; + } + } else { + nthr_n = (int)sqrt((double)nthr); + if (nthr_n > (n + BN_SMALL_NOCOPY_AVX512_COMMON - 1) + / BN_SMALL_NOCOPY_AVX512_COMMON) + nthr_n = (n + BN_SMALL_NOCOPY_AVX512_COMMON - 1) + / BN_SMALL_NOCOPY_AVX512_COMMON; + nthr_m = nthr / nthr_n; + + while ((nthr_n > 1) && (nthr_m * nthr_n != nthr)) { + nthr_n--; + nthr_m = nthr / nthr_n; + } + } + } + + MB = (m + nthr_m - 1) / nthr_m + BM_SMALL_NOCOPY_AVX512_COMMON - 1; + MB -= MB % BM_SMALL_NOCOPY_AVX512_COMMON; + NB = (n + nthr_n - 1) / nthr_n + BN_SMALL_NOCOPY_AVX512_COMMON - 1; + NB -= NB % BN_SMALL_NOCOPY_AVX512_COMMON; + KB = (k + nthr_k - 1) / nthr_k + BK_SMALL_NOCOPY_AVX512_COMMON - 1; + KB -= KB % BK_SMALL_NOCOPY_AVX512_COMMON; + + if (MB * nthr_m > m) + nthr_m = (m + MB - 1) / MB; + if (NB * nthr_n > n) + nthr_n = (n + NB - 1) / NB; + if (KB * nthr_k > k) + nthr_k = (k + KB - 1) / KB; + + *nthrs_m = nthr_m; + *nthrs_n = nthr_n; + *nthrs_k = nthr_k; + + *BM = MB; + *BN = NB; + *BK = KB; +} +#undef BM_NOCOPY_AVX512_COMMON +#undef BN_NOCOPY_AVX512_COMMON +#undef BK_NOCOPY_AVX512_COMMON +#undef BN_LARGE_NOCOPY_AVX512_COMMON +#undef BM_SMALL_NOCOPY_AVX512_COMMON +#undef BN_SMALL_NOCOPY_AVX512_COMMON +#undef BK_SMALL_NOCOPY_AVX512_COMMON + +// Partition n values as equally as possible among nthr threads +// and set the offset (t_offset) and number of values (t_block) for ithr +// Assumption: 0 <= ithr < nthr +void partition_unit_diff( + int ithr, int nthr, int n, int *t_offset, int *t_block) +{ + int band = n / nthr; + if (band == 0) + band = 1; + int tail = n - band * nthr; + if (tail < 0) + tail = 0; + + if (ithr < tail) { + band++; + *t_offset = band * ithr; + *t_block = band; + } else { + *t_offset = band * ithr + tail; + *t_block = band; + } + + if (*t_offset >= n) { + *t_offset = 0; + *t_block = 0; + } + + if (*t_offset + *t_block > n) { + *t_block = n - *t_offset; + } +} + +// Sum the m*n values from p_src into p_dst, assuming the two-dimensional +// arrays have leading dimensions ld_src and ld_dst, respectively +template +void sum_two_matrices(int m, int n, + data_t * __restrict p_src, dim_t ld_src, + data_t * __restrict p_dst, dim_t ld_dst) +{ + int i, j; + for (j = 0; j < n; j++) { + for (i = 0; i < m; i++) { + p_dst[i + j * ld_dst] += p_src[i + j * ld_src]; + } + } +} + +template +void sum_two_matrices(int m, int n, + float * __restrict p_src, dim_t ld_src, + float * __restrict p_dst, dim_t ld_dst); + +template +void sum_two_matrices(int m, int n, + double * __restrict p_src, dim_t ld_src, + double * __restrict p_dst, dim_t ld_dst); +} +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp new file mode 100644 index 0000000000..3352298b4a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp @@ -0,0 +1,72 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef GEMM_UTILS_HPP +#define GEMM_UTILS_HPP + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace gemm_utils { +// Alias for any dimension related variable. +typedef ptrdiff_t dim_t; + +template +struct gemm_traits {}; + +template +struct gemm_traits { + static constexpr int m = 8; + static constexpr int n = 6; + static constexpr int BM = 4032; + static constexpr int BN = isTransA ? 96 : 192; + static constexpr int BK = isTransB ? 96 : 512; +}; + +template +struct gemm_traits { + static constexpr int m = 16; + static constexpr int n = 6; + static constexpr int BM = 4032; + static constexpr int BN = isTransA ? 96 : 48; + static constexpr int BK = isTransB ? 96 : 256; +}; + +template +using unroll_factor = gemm_traits; + +template +void sum_two_matrices(int m, int n, + data_t * __restrict p_src, dim_t ld_src, + data_t * __restrict p_dst, dim_t ld_dst); + +void calc_nthr_nocopy_avx512_common(int m, + int n, int k, int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k, + int *BM, int *BN, int *BK); + +void calc_nthr_nocopy_avx(int m, int n, int k, + int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k, int *BM, int *BN, + int *BK); + +void partition_unit_diff( + int ithr, int nthr, int n, int *t_offset, int *t_block); +}; + +} +} +} +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp new file mode 100644 index 0000000000..d7be43e392 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp @@ -0,0 +1,2131 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "ref_gemm_f32.hpp" +#include "gemm_utils_f32.hpp" +#include "jit_avx512_common_gemm_f32.hpp" + +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +#define CACHE_LINE_SIZE 64 + +#define STACKSIZE get_size_of_abi_save_regs() +#ifdef _WIN32 +#define STACK_K_CAPACITY 32 +#else +#define STACK_K_CAPACITY 2048 +#endif +#define SIZE 4 +#define OFFSET 128 +#define BASE_SHIFT 2 +#define SECOND_FETCH unroll_n +#define UNROLL_M 48 +#define UNROLL_N 8 + +namespace avx512_common_gemm_f32 { +using namespace gemm_utils; + +struct xbyak_gemm : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_gemm_f32_xbyak_gemm) + + xbyak_gemm(char isTransA, char isTransB, float beta, bool hasBias = false, + void *code_ptr = nullptr, + size_t code_size = 80 * Xbyak::DEFAULT_MAX_CODE_SIZE) + : jit_generator(code_ptr, code_size) + { + using namespace Xbyak; + + enum { ver_avx512_core, ver_avx512_mic } ver = + mayiuse(avx512_core) ? ver_avx512_core : ver_avx512_mic; + + bool isBeta0 = (beta == 0.0); + bool isBetaN = (!isBeta0 && beta != 1.0); + + // various definitions for convenience + auto ARG_M = abi_param1; + auto ARG_N = abi_param2; + auto K = abi_param3; + auto ARG_ALPHA = abi_param4; +#ifdef _WIN32 + auto ARG_A = ptr[rsp + OFFSET_SHADOWSPACE + STACKSIZE]; + auto ARG_LDA = qword[rsp + OFFSET_SHADOWSPACE + + sizeof(float *) + STACKSIZE]; + const auto stackOffset = OFFSET_SHADOWSPACE + + sizeof(float *) + STACKSIZE; + auto A = rsi; + auto LDA = rdi; +#else + auto ARG_A = r8; + auto ARG_LDA = r9; + const auto stackOffset = STACKSIZE; + auto A = ARG_A; + auto LDA = ARG_LDA; +#endif + auto ARG_B = ptr[rsp + 8 + stackOffset]; + auto ARG_LDB = ptr[rsp + 16 + stackOffset]; + auto ARG_BETA = ptr[rsp + 24 + stackOffset]; + auto ARG_C = ptr[rsp + 32 + stackOffset]; + auto ARG_LDC = ptr[rsp + 40 + stackOffset]; + auto ARG_BIAS = ptr[rsp + 48 + stackOffset]; + auto ARG_WS = ptr[rsp + 56 + stackOffset]; + + auto B = r11; + auto LDB = rbx; + auto LDC = r13; + auto LL = rax; + auto AO1 = abi_param2; + auto BO1 = abi_param4; + auto BO2 = rbp; + auto CO1 = r14; + auto CO2 = r15; + auto LDB3 = r10; + auto LDA4 = abi_param1; + auto AA = r12; + auto BIAS1 = abi_param1; + + auto M = qword[rsp + 0]; + auto N = qword[rsp + 8]; + auto FLAG = qword[rsp + 16]; + auto I = qword[rsp + 24]; + auto C = qword[rsp + 32]; + auto BIAS = qword[rsp + 40]; + auto ALPHA = qword[rsp + 48]; + auto BETA = qword[rsp + 64]; + auto ORIG_A = qword[rsp + 80]; + auto ORIG_SP = qword[rsp + 120]; + + auto ZSTRIDE = zmm4; + auto VALPHA = zmm6; + auto VBETA = zmm7; + auto VBIAS1 = zmm1; + auto VBIAS2 = zmm2; + auto VBIAS3 = zmm3; + + auto PREFETCHSIZEA = ver == ver_avx512_core ? 48 : 80; + auto PREFETCHSIZEB = 16; + + Zmm regs[] = { zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15, + zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23, zmm24, + zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31 }; + + // Function for packing if needed + auto do_pack = [&](int unroll_m) { + Label pack2, pack3, pack4, pack10; + + mov(BO1, A); + lea(AO1, ptr[rsp + 128 + OFFSET * SIZE]); + mov(LL, K); + sar(LL, 2); + jle(pack3, T_NEAR); + align(16); + + L(pack2); + if (!isTransA) { + for (int i = 0; i < 4; i++) { + vmovups(zmm0 | k1, ptr[BO1 + (0 * 16 - OFFSET) * SIZE]); + if (unroll_m > 16) + vmovups(zmm1 | k2, ptr[BO1 + (1 * 16 - OFFSET) * SIZE]); + if (unroll_m > 32) + vmovups(zmm2 | k3, ptr[BO1 + (2 * 16 - OFFSET) * SIZE]); + add(BO1, LDA); + + vmovups(ptr[AO1 + (unroll_m * i + 0 * 16 - OFFSET) * SIZE] + | k1, + zmm0); + if (unroll_m > 16) + vmovups(ptr[AO1 + + (unroll_m * i + 1 * 16 - OFFSET) + * SIZE] + | k2, + zmm1); + if (unroll_m > 32) + vmovups(ptr[AO1 + + (unroll_m * i + 2 * 16 - OFFSET) + * SIZE] + | k3, + zmm2); + } + } else { + for (int i = 0; i < 4; i++) { + kmovw(k4, k1); + vgatherqps(ymm5 | k4, + ptr[BO1 + ZSTRIDE + (i - OFFSET) * SIZE]); + lea(BO2, ptr[BO1 + LDA * 8]); + kshiftrw(k4, k1, 8); + vgatherqps(ymm6 | k4, + ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]); + vshuff64x2(zmm0, zmm5, zmm6, 0x44); + + if (unroll_m > 16) { + lea(BO2, ptr[BO2 + LDA * 8]); + kmovw(k4, k2); + vgatherqps(ymm5 | k4, + ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 8]); + kshiftrw(k4, k2, 8); + vgatherqps(ymm6 | k4, + ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]); + vshuff64x2(zmm1, zmm5, zmm6, 0x44); + } + + if (unroll_m > 32) { + lea(BO2, ptr[BO2 + LDA * 8]); + kmovw(k4, k3); + vgatherqps(ymm5 | k4, + ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 8]); + kshiftrw(k4, k3, 8); + vgatherqps(ymm6 | k4, + ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 8]); + vshuff64x2(zmm2, zmm5, zmm6, 0x44); + } + + vmovups(ptr[AO1 + (unroll_m * i + 0 * 16 - OFFSET) * SIZE], + zmm0 | k1); + if (unroll_m > 16) + vmovups(ptr[AO1 + + (unroll_m * i + 1 * 16 - OFFSET) + * SIZE], + zmm1 | k2); + if (unroll_m > 32) + vmovups(ptr[AO1 + + (unroll_m * i + 2 * 16 - OFFSET) + * SIZE], + zmm2 | k3); + } + add(BO1, 4 * SIZE); + } + add(AO1, unroll_m * 4 * SIZE); + + sub(LL, 1); + jg(pack2, T_NEAR); + align(16); + + L(pack3); + mov(LL, K); + and_(LL, 3); + jle(pack10, T_NEAR); + align(16); + + L(pack4); + if (!isTransA) { + vmovups(zmm0 | k1, ptr[BO1 + (0 * 16 - OFFSET) * SIZE]); + if (unroll_m > 16) + vmovups(zmm1 | k2, ptr[BO1 + (1 * 16 - OFFSET) * SIZE]); + if (unroll_m > 32) + vmovups(zmm2 | k3, ptr[BO1 + (2 * 16 - OFFSET) * SIZE]); + add(BO1, LDA); + } else { + kmovw(k4, k1); + vgatherqps(ymm5 | k4, ptr[BO1 + ZSTRIDE + (0 - OFFSET) * SIZE]); + lea(BO2, ptr[BO1 + LDA * 8]); + kshiftrw(k4, k1, 8); + vgatherqps(ymm6 | k4, ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]); + vshuff64x2(zmm0, zmm5, zmm6, 0x44); + + if (unroll_m > 16) { + lea(BO2, ptr[BO2 + LDA * 8]); + kmovw(k4, k2); + vgatherqps(ymm5 | k4, + ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 8]); + kshiftrw(k4, k2, 8); + vgatherqps(ymm6 | k4, + ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]); + vshuff64x2(zmm1, zmm5, zmm6, 0x44); + } + + if (unroll_m > 32) { + lea(BO2, ptr[BO2 + LDA * 8]); + kmovw(k4, k3); + vgatherqps(ymm5 | k4, + ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 8]); + kshiftrw(k4, k3, 8); + vgatherqps(ymm6 | k4, + ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 8]); + vshuff64x2(zmm2, zmm5, zmm6, 0x44); + } + add(BO1, SIZE); + } + + vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE], + zmm0 | k1); + if (unroll_m > 16) + vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 16 - OFFSET) * SIZE], + zmm1 | k2); + if (unroll_m > 32) + vmovups(ptr[AO1 + (unroll_m * 0 + 2 * 16 - OFFSET) * SIZE], + zmm2 | k3); + + add(AO1, unroll_m * SIZE); + sub(LL, 1); + jg(pack4, T_NEAR); + align(16); + + L(pack10); + }; + + // Function to update C, covering masking and other considerations + auto update = [&](Zmm reg, bool useCO1, int offset, int mask, + bool useScale = false) { + vmulps(reg, reg, VALPHA); + if (!isBeta0) { + if (!useScale) { + switch (mask) { + case 0: + if (useCO1) + vmovups(zmm0, ptr[CO1 + offset * SIZE]); + else + vmovups(zmm0, ptr[CO2 + offset * SIZE]); + break; + case 1: + if (useCO1) + vmovups(zmm0 | k1 | T_z, ptr[CO1 + offset * SIZE]); + else + vmovups(zmm0 | k1 | T_z, ptr[CO2 + offset * SIZE]); + break; + case 2: + if (useCO1) + vmovups(zmm0 | k2 | T_z, ptr[CO1 + offset * SIZE]); + else + vmovups(zmm0 | k2 | T_z, ptr[CO2 + offset * SIZE]); + break; + case 3: + if (useCO1) + vmovups(zmm0 | k3 | T_z, ptr[CO1 + offset * SIZE]); + else + vmovups(zmm0 | k3 | T_z, ptr[CO2 + offset * SIZE]); + break; + } + } else { + switch (mask) { + case 0: + if (useCO1) + vmovups(zmm0, ptr[CO1 + LDC + offset * SIZE]); + else + vmovups(zmm0, ptr[CO2 + LDC + offset * SIZE]); + break; + case 1: + if (useCO1) + vmovups(zmm0 | k1 | T_z, + ptr[CO1 + LDC + offset * SIZE]); + else + vmovups(zmm0 | k1 | T_z, + ptr[CO2 + LDC + offset * SIZE]); + break; + case 2: + if (useCO1) + vmovups(zmm0 | k2 | T_z, + ptr[CO1 + LDC + offset * SIZE]); + else + vmovups(zmm0 | k2 | T_z, + ptr[CO2 + LDC + offset * SIZE]); + break; + case 3: + if (useCO1) + vmovups(zmm0 | k3 | T_z, + ptr[CO1 + LDC + offset * SIZE]); + else + vmovups(zmm0 | k3 | T_z, + ptr[CO2 + LDC + offset * SIZE]); + break; + } + } + if (!isBetaN) { + vaddps(zmm0, reg, zmm0); + } else { + vfmadd132ps(zmm0, reg, VBETA); + } + if (!useScale) { + switch (mask) { + case 0: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], zmm0); + else + vmovups(ptr[CO2 + offset * SIZE], zmm0); + break; + case 1: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], zmm0 | k1); + else + vmovups(ptr[CO2 + offset * SIZE], zmm0 | k1); + break; + case 2: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], zmm0 | k2); + else + vmovups(ptr[CO2 + offset * SIZE], zmm0 | k2); + break; + case 3: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], zmm0 | k3); + else + vmovups(ptr[CO2 + offset * SIZE], zmm0 | k3); + break; + } + } else { + switch (mask) { + case 0: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0); + break; + case 1: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0 | k1); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0 | k1); + break; + case 2: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0 | k2); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0 | k2); + break; + case 3: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0 | k3); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0 | k3); + break; + } + } + } else { + if (!useScale) { + switch (mask) { + case 0: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], reg); + else + vmovups(ptr[CO2 + offset * SIZE], reg); + break; + case 1: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], reg | k1); + else + vmovups(ptr[CO2 + offset * SIZE], reg | k1); + break; + case 2: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], reg | k2); + else + vmovups(ptr[CO2 + offset * SIZE], reg | k2); + break; + case 3: + if (useCO1) + vmovups(ptr[CO1 + offset * SIZE], reg | k3); + else + vmovups(ptr[CO2 + offset * SIZE], reg | k3); + break; + } + } else { + switch (mask) { + case 0: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], reg); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], reg); + break; + case 1: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], reg | k1); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], reg | k1); + break; + case 2: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], reg | k2); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], reg | k2); + break; + case 3: + if (useCO1) + vmovups(ptr[CO1 + LDC + offset * SIZE], reg | k3); + else + vmovups(ptr[CO2 + LDC + offset * SIZE], reg | k3); + break; + } + } + } + vpxorq(reg, reg, reg); + }; + + // Loop with unroll_n - 2 FMAs; called by innerkernel + auto fmaloop = [&](int unroll_m, int unroll_n, int iteration) { + for (int i = 2; i < unroll_n; i++) { + if (ver == ver_avx512_core) { + if (!isTransB) { + switch (i) { + case 2: + vbroadcastss( + zmm3, + ptr[BO1 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + break; + case 3: + vbroadcastss( + zmm3, + ptr[BO1 + LDB3 + + (iteration - OFFSET) * SIZE]); + break; + case 4: + vbroadcastss(zmm3, + ptr[BO2 + (iteration - OFFSET) * SIZE]); + break; + case 5: + vbroadcastss( + zmm3, + ptr[BO2 + LDB * 1 + + (iteration - OFFSET) * SIZE]); + break; + case 6: + vbroadcastss( + zmm3, + ptr[BO2 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + break; + case 7: + vbroadcastss( + zmm3, + ptr[BO2 + LDB3 + + (iteration - OFFSET) * SIZE]); + break; + } + } else { + vbroadcastss(zmm3, ptr[BO1 + (i - OFFSET) * SIZE]); + } + vfmadd231ps(regs[i], zmm3, zmm0); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm3, zmm1); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm3, zmm2); + } else { + if (!isTransB) { + switch (i) { + case 2: + vfmadd231ps(regs[i], zmm0, + zword_b[BO1 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm1, + zword_b[BO1 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm2, + zword_b[BO1 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + break; + case 3: + vfmadd231ps(regs[i], zmm0, + zword_b[BO1 + LDB3 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm1, + zword_b[BO1 + LDB3 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm2, + zword_b[BO1 + LDB3 + + (iteration - OFFSET) * SIZE]); + break; + case 4: + vfmadd231ps(regs[i], zmm0, + zword_b[BO2 + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm1, + zword_b[BO2 + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm2, + zword_b[BO2 + (iteration - OFFSET) * SIZE]); + break; + case 5: + vfmadd231ps(regs[i], zmm0, + zword_b[BO2 + LDB * 1 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm1, + zword_b[BO2 + LDB * 1 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm2, + zword_b[BO2 + LDB * 1 + + (iteration - OFFSET) * SIZE]); + break; + case 6: + vfmadd231ps(regs[i], zmm0, + zword_b[BO2 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm1, + zword_b[BO2 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm2, + zword_b[BO2 + LDB * 2 + + (iteration - OFFSET) * SIZE]); + break; + case 7: + vfmadd231ps(regs[i], zmm0, + zword_b[BO2 + LDB3 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm1, + zword_b[BO2 + LDB3 + + (iteration - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm2, + zword_b[BO2 + LDB3 + + (iteration - OFFSET) * SIZE]); + break; + } + } else { + vfmadd231ps( + regs[i], zmm0, zword_b[BO1 + (i - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[i + 8], zmm1, + zword_b[BO1 + (i - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[i + 16], zmm2, + zword_b[BO1 + (i - OFFSET) * SIZE]); + } + } + } + }; + + // Innerkernel; called by kernel + auto innerkernel = [&](int unroll_m, int unroll_n, bool isDirect, + bool isCopy, bool doCPrefetch, bool isUnmasked = true) { + for (int i = 0; i < 8; i++) { + if (!isDirect) { + prefetcht0(ptr[AO1 + + (PREFETCHSIZEA + i * unroll_m + 0 * 16 - OFFSET) + * SIZE]); + if (unroll_m >= 32) + prefetcht0(ptr[AO1 + + (PREFETCHSIZEA + i * unroll_m + 1 * 16 - OFFSET) + * SIZE]); + if (unroll_m >= 48) + prefetcht0(ptr[AO1 + + (PREFETCHSIZEA + i * unroll_m + 2 * 16 - OFFSET) + * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4 + (16 * 0 * SIZE)]); + if (unroll_m >= 32) + prefetcht0(ptr[AO1 + LDA4 + (16 * 1 * SIZE)]); + if (unroll_m >= 48) + prefetcht0(ptr[AO1 + LDA4 + (16 * 2 * SIZE)]); + } + + if (!isDirect) { + if (i != 0) { + if (isUnmasked || unroll_m > 16) { + vmovups(zmm0, + ptr[AO1 + + (unroll_m * i + 0 * 16 - OFFSET) + * SIZE]); + } else { + vmovups(zmm0 | k1 | T_z, + ptr[AO1 + + (unroll_m * i + 0 * 16 - OFFSET) + * SIZE]); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(zmm1, ptr[AO1 + + (unroll_m * i + 1 * 16 + - OFFSET) + * SIZE]); + } else { + vmovups(zmm1 | k2 | T_z, + ptr[AO1 + + (unroll_m * i + 1 * 16 + - OFFSET) + * SIZE]); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(zmm2, ptr[AO1 + + (unroll_m * i + 2 * 16 + - OFFSET) + * SIZE]); + } else { + vmovups(zmm2 | k3 | T_z, + ptr[AO1 + + (unroll_m * i + 2 * 16 + - OFFSET) + * SIZE]); + } + } + } + } else { + if (isUnmasked || unroll_m > 16) { + vmovups(zmm0, ptr[AO1 + (0 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm0 | k1 | T_z, + ptr[AO1 + (0 * 16 - OFFSET) * SIZE]); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(zmm1, ptr[AO1 + (1 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm1 | k2 | T_z, + ptr[AO1 + (1 * 16 - OFFSET) * SIZE]); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(zmm2, ptr[AO1 + (2 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm2 | k3 | T_z, + ptr[AO1 + (2 * 16 - OFFSET) * SIZE]); + } + } + add(AO1, LDA); + } + + if (ver == ver_avx512_core) { + if (!isTransB) { + vbroadcastss(zmm3, ptr[BO1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(zmm3, ptr[BO1 + (0 - OFFSET) * SIZE]); + } + vfmadd231ps(regs[0], zmm3, zmm0); + if (unroll_m >= 32) + vfmadd231ps(regs[0 + 8], zmm3, zmm1); + if (unroll_m >= 48) + vfmadd231ps(regs[0 + 16], zmm3, zmm2); + } else { + if (!isTransB) { + vfmadd231ps(regs[0], zmm0, + zword_b[BO1 + (i - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[0 + 8], zmm1, + zword_b[BO1 + (i - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[0 + 16], zmm2, + zword_b[BO1 + (i - OFFSET) * SIZE]); + } else { + vfmadd231ps(regs[0], zmm0, + zword_b[BO1 + (0 - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[0 + 8], zmm1, + zword_b[BO1 + (0 - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[0 + 16], zmm2, + zword_b[BO1 + (0 - OFFSET) * SIZE]); + } + } + + if (unroll_n >= i + 1) { + if (!isTransB) { + switch (i) { + case 0: + prefetcht0( + ptr[BO1 + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + case 1: + prefetcht0(ptr[BO1 + LDB + + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + case 2: + prefetcht0(ptr[BO1 + LDB * 2 + + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + case 3: + prefetcht0(ptr[BO1 + LDB3 + + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + case 4: + prefetcht0( + ptr[BO2 + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + case 5: + prefetcht0(ptr[BO2 + LDB + + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + case 6: + prefetcht0(ptr[BO2 + LDB * 2 + + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + case 7: + prefetcht0(ptr[BO2 + LDB3 + + (PREFETCHSIZEB - OFFSET) * SIZE]); + break; + } + } + } + + if (unroll_n >= 2) { + if (ver == ver_avx512_core) { + if (!isTransB) { + vbroadcastss(zmm3, + ptr[BO1 + LDB * 1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(zmm3, ptr[BO1 + (1 - OFFSET) * SIZE]); + } + vfmadd231ps(regs[1], zmm3, zmm0); + if (unroll_m >= 32) + vfmadd231ps(regs[1 + 8], zmm3, zmm1); + if (unroll_m >= 48) + vfmadd231ps(regs[1 + 16], zmm3, zmm2); + } else { + if (!isTransB) { + vfmadd231ps(regs[1], zmm0, + zword_b[BO1 + LDB * 1 + (i - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[1 + 8], zmm1, + zword_b[BO1 + LDB * 1 + + (i - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[1 + 16], zmm2, + zword_b[BO1 + LDB * 1 + + (i - OFFSET) * SIZE]); + } else { + vfmadd231ps(regs[1], zmm0, + zword_b[BO1 + (1 - OFFSET) * SIZE]); + if (unroll_m >= 32) + vfmadd231ps(regs[1 + 8], zmm1, + zword_b[BO1 + (1 - OFFSET) * SIZE]); + if (unroll_m >= 48) + vfmadd231ps(regs[1 + 16], zmm2, + zword_b[BO1 + (1 - OFFSET) * SIZE]); + } + } + } + + if (isCopy) { + if (isUnmasked || unroll_m > 16) { + vmovups(ptr[LDA4 + + (unroll_m * i + 0 * 16 - OFFSET) + * SIZE], + zmm0); + } else { + vmovups(ptr[LDA4 + + (unroll_m * i + 0 * 16 - OFFSET) + * SIZE], + zmm0 | k1); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(ptr[LDA4 + + (unroll_m * i + 1 * 16 - OFFSET) + * SIZE], + zmm1); + } else { + vmovups(ptr[LDA4 + + (unroll_m * i + 1 * 16 - OFFSET) + * SIZE], + zmm1 | k2); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(ptr[LDA4 + + (unroll_m * i + 2 * 16 - OFFSET) + * SIZE], + zmm2); + } else { + vmovups(ptr[LDA4 + + (unroll_m * i + 2 * 16 - OFFSET) + * SIZE], + zmm2 | k3); + } + } + if (i == 7) + sub(LDA4, -unroll_m * 8 * SIZE); + } + fmaloop(unroll_m, unroll_n, i); + + if (i == 1) { + if (doCPrefetch) { + if (ver == ver_avx512_core) + prefetchw(ptr[CO2 + 0 * 16 * SIZE]); + else + prefetcht0(ptr[CO2 + 0 * 16 * SIZE]); + } + } + if (i == 3) { + if (doCPrefetch && unroll_m >= 32) { + if (ver == ver_avx512_core) + prefetchw(ptr[CO2 + 1 * 16 * SIZE]); + else + prefetcht0(ptr[CO2 + 1 * 16 * SIZE]); + } + if (!isTransA) { + if (ver == ver_avx512_core) + prefetcht0(ptr[AA + 16 * 0 * SIZE]); + else + prefetcht2(ptr[AA + 16 * 0 * SIZE]); + } + } + if (i == 5) { + if (doCPrefetch) { + if (unroll_m >= 48) { + if (ver == ver_avx512_core) + prefetchw(ptr[CO2 + 2 * 16 * SIZE]); + else + prefetcht0(ptr[CO2 + 2 * 16 * SIZE]); + } + add(CO2, LDC); + } + if (!isTransA) { + if (unroll_m >= 32) { + if (ver == ver_avx512_core) + prefetcht0(ptr[AA + 16 * 1 * SIZE]); + else + prefetcht2(ptr[AA + 16 * 1 * SIZE]); + } + } + } + + if (isTransB) { + prefetcht0(ptr[BO1 + BO2]); + add(BO1, LDB); + } + } // end of for loop + + if (!isTransB) { + sub(BO1, -8 * SIZE); + if (unroll_n >= 4) + sub(BO2, -8 * SIZE); + } + if (!isTransA) { + if (unroll_m >= 48) { + if (ver == ver_avx512_core) + prefetcht0(ptr[AA + 16 * 2 * SIZE]); + else + prefetcht2(ptr[AA + 16 * 2 * SIZE]); + } + lea(AA, ptr[AA + LDA]); + } + + if (!isDirect) { + if (isUnmasked || unroll_m > 16) { + vmovups(zmm0, + ptr[AO1 + (unroll_m * 8 + 0 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm0 | k1 | T_z, + ptr[AO1 + (unroll_m * 8 + 0 * 16 - OFFSET) * SIZE]); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(zmm1, ptr[AO1 + + (unroll_m * 8 + 1 * 16 - OFFSET) + * SIZE]); + } else { + vmovups(zmm1 | k2 | T_z, + ptr[AO1 + + (unroll_m * 8 + 1 * 16 - OFFSET) + * SIZE]); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(zmm2, ptr[AO1 + + (unroll_m * 8 + 2 * 16 - OFFSET) + * SIZE]); + } else { + vmovups(zmm2 | k3 | T_z, + ptr[AO1 + + (unroll_m * 8 + 2 * 16 - OFFSET) + * SIZE]); + } + } + sub(AO1, -unroll_m * 8 * SIZE); + } + + sub(LL, 1); + }; + + // Main kernel; does prefetching and calls innerkernel + // After calculating results in registers, writes back to C matrix by + // calling update + auto kernel = [&](int unroll_m, int unroll_n, bool isDirect, + bool isCopy, bool isUnmasked = true) { + if (!isDirect) { + lea(AO1, ptr[rsp + 128 + OFFSET * SIZE]); + } else { + mov(AO1, A); + } + + if (isCopy) { + lea(LDA4, ptr[rsp + 128 + OFFSET * SIZE]); + } else { + auto step = ver == ver_avx512_core ? 2 : 4; + lea(LDA4, ptr[LDA * step + (16 - 1 - OFFSET) * SIZE]); + } + + if (isTransB) { + lea(BO2, ptr[LDB * 4 + (16 / 2 - 1 - OFFSET) * SIZE]); + } + + if (!isDirect) { + if (isUnmasked || unroll_m > 16) { + vmovups(zmm0, + ptr[AO1 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm0 | k1 | T_z, + ptr[AO1 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE]); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(zmm1, ptr[AO1 + + (unroll_m * 0 + 1 * 16 - OFFSET) + * SIZE]); + } else { + vmovups(zmm1 | k2 | T_z, + ptr[AO1 + + (unroll_m * 0 + 1 * 16 - OFFSET) + * SIZE]); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(zmm2, ptr[AO1 + + (unroll_m * 0 + 2 * 16 - OFFSET) + * SIZE]); + } else { + vmovups(zmm2 | k3 | T_z, + ptr[AO1 + + (unroll_m * 0 + 2 * 16 - OFFSET) + * SIZE]); + } + } + } + + Label kernel12, kernel13, kernel14, kernel15, kernel16, kernel18; + + mov(LL, K); + sar(LL, 3); + sub(LL, SECOND_FETCH); + jle(kernel13, T_NEAR); + align(16); + + L(kernel12); + innerkernel( + unroll_m, unroll_n, isDirect, isCopy, false, isUnmasked); + jg(kernel12, T_NEAR); + align(16); + + L(kernel13); + lea(CO2, ptr[CO1 + (16 - 1) * SIZE]); + add(LL, unroll_n); + jle(kernel15, T_NEAR); + align(16); + + L(kernel14); + innerkernel(unroll_m, unroll_n, isDirect, isCopy, true, isUnmasked); + jg(kernel14, T_NEAR); + align(16); + + L(kernel15); + mov(LL, K); + and_(LL, 7); + jle(kernel18, T_NEAR); + align(16); + + L(kernel16); + if (isDirect) { + if (isUnmasked || unroll_m > 16) { + vmovups(zmm0, ptr[AO1 + (0 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm0 | k1 | T_z, + ptr[AO1 + (0 * 16 - OFFSET) * SIZE]); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(zmm1, ptr[AO1 + (1 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm1 | k2 | T_z, + ptr[AO1 + (1 * 16 - OFFSET) * SIZE]); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(zmm2, ptr[AO1 + (2 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm2 | k3 | T_z, + ptr[AO1 + (2 * 16 - OFFSET) * SIZE]); + } + } + add(AO1, LDA); + } + + for (int i = 0; i < unroll_n; i++) { + if (!isTransB) { + switch (i) { + case 0: + vbroadcastss(zmm3, ptr[BO1 + (0 - OFFSET) * SIZE]); + break; + case 1: + vbroadcastss( + zmm3, ptr[BO1 + LDB * 1 + (0 - OFFSET) * SIZE]); + break; + case 2: + vbroadcastss( + zmm3, ptr[BO1 + LDB * 2 + (0 - OFFSET) * SIZE]); + break; + case 3: + vbroadcastss( + zmm3, ptr[BO1 + LDB3 + (0 - OFFSET) * SIZE]); + break; + case 4: + vbroadcastss(zmm3, ptr[BO2 + (0 - OFFSET) * SIZE]); + break; + case 5: + vbroadcastss( + zmm3, ptr[BO2 + LDB * 1 + (0 - OFFSET) * SIZE]); + break; + case 6: + vbroadcastss( + zmm3, ptr[BO2 + LDB * 2 + (0 - OFFSET) * SIZE]); + break; + case 7: + vbroadcastss( + zmm3, ptr[BO2 + LDB3 + (0 - OFFSET) * SIZE]); + break; + } + } else { + vbroadcastss(zmm3, ptr[BO1 + (i - OFFSET) * SIZE]); + } + vfmadd231ps(regs[i], zmm3, zmm0); + if (unroll_m >= 32) { + vfmadd231ps(regs[i + 8], zmm3, zmm1); + } + if (unroll_m >= 48) { + vfmadd231ps(regs[i + 16], zmm3, zmm2); + } + } + + if (isCopy) { + if (isUnmasked || unroll_m > 16) { + vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE], + zmm0); + } else { + vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE], + zmm0 | k1); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(ptr[LDA4 + + (unroll_m * 0 + 1 * 16 - OFFSET) + * SIZE], + zmm1); + } else { + vmovups(ptr[LDA4 + + (unroll_m * 0 + 1 * 16 - OFFSET) + * SIZE], + zmm1 | k2); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(ptr[LDA4 + + (unroll_m * 0 + 2 * 16 - OFFSET) + * SIZE], + zmm2); + } else { + vmovups(ptr[LDA4 + + (unroll_m * 0 + 2 * 16 - OFFSET) + * SIZE], + zmm2 | k3); + } + } + sub(LDA4, -unroll_m * SIZE); + } + + if (!isDirect) { + if (isUnmasked || unroll_m > 16) { + vmovups(zmm0, + ptr[AO1 + (unroll_m * 1 + 0 * 16 - OFFSET) * SIZE]); + } else { + vmovups(zmm0 | k1 | T_z, + ptr[AO1 + (unroll_m * 1 + 0 * 16 - OFFSET) * SIZE]); + } + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) { + vmovups(zmm1, ptr[AO1 + + (unroll_m * 1 + 1 * 16 - OFFSET) + * SIZE]); + } else { + vmovups(zmm1 | k2 | T_z, + ptr[AO1 + + (unroll_m * 1 + 1 * 16 - OFFSET) + * SIZE]); + } + } + if (unroll_m >= 48) { + if (isUnmasked) { + vmovups(zmm2, ptr[AO1 + + (unroll_m * 1 + 2 * 16 - OFFSET) + * SIZE]); + } else { + vmovups(zmm2 | k3 | T_z, + ptr[AO1 + + (unroll_m * 1 + 2 * 16 - OFFSET) + * SIZE]); + } + } + sub(AO1, -unroll_m * SIZE); + } + + if (!isTransB) { + sub(BO1, -SIZE); + if (unroll_n >= 4) { + sub(BO2, -SIZE); + } + } else { + add(BO1, LDB); + } + + sub(LL, 1); + jg(kernel16, T_NEAR); + align(16); + + L(kernel18); + vbroadcastss(VALPHA, ALPHA); + + if (isBetaN) { + vbroadcastss(VBETA, BETA); + } + + // Write back the results; all beta cases need to be handled + if (hasBias) { + mov(BIAS1, BIAS); + if (isUnmasked || unroll_m > 16) + vmovups(VBIAS1, ptr[BIAS1 + 0 * SIZE]); + else + vmovups(VBIAS1 | k1 | T_z, ptr[BIAS1 + 0 * SIZE]); + if (unroll_m >= 32) { + if (isUnmasked || unroll_m > 32) + vmovups(VBIAS2, ptr[BIAS1 + 16 * SIZE]); + else + vmovups(VBIAS2 | k2 | T_z, ptr[BIAS1 + 16 * SIZE]); + } + if (unroll_m >= 48) { + if (isUnmasked) + vmovups(VBIAS3, ptr[BIAS1 + 32 * SIZE]); + else + vmovups(VBIAS3 | k3 | T_z, ptr[BIAS1 + 32 * SIZE]); + } + } + + for (int i = 0; i < unroll_n; i++) { + bool useScale = i % 2 != 0; + bool useCO1 = i < 2; + if (i == 2) + lea(CO2, ptr[CO1 + LDC * 2]); + if (i == 4 || i == 6) + lea(CO2, ptr[CO2 + LDC * 2]); + if (hasBias) + vaddps(regs[i], VBIAS1, regs[i]); + if (isUnmasked || unroll_m > 16) { + update(regs[i], useCO1, 0, 0, useScale); + } else { + update(regs[i], useCO1, 0, 1, useScale); + } + if (unroll_m >= 32) { + if (hasBias) + vaddps(regs[i + 8], VBIAS2, regs[i + 8]); + if (isUnmasked || unroll_m > 32) { + update(regs[i + 8], useCO1, 16, 0, useScale); + } else { + update(regs[i + 8], useCO1, 16, 2, useScale); + } + } + if (unroll_m >= 48) { + if (hasBias) + vaddps(regs[i + 16], VBIAS3, regs[i + 16]); + if (isUnmasked) { + update(regs[i + 16], useCO1, 32, 0, useScale); + } else { + update(regs[i + 16], useCO1, 32, 3, useScale); + } + } + } + + switch (unroll_n) { + case 1: add(CO1, LDC); break; + case 2: lea(CO1, ptr[CO1 + LDC * 2]); break; + case 3: lea(CO1, ptr[CO2 + LDC * 1]); break; + case 4: lea(CO1, ptr[CO2 + LDC * 2]); break; + case 5: lea(CO1, ptr[CO2 + LDC * 1]); break; + case 6: lea(CO1, ptr[CO2 + LDC * 2]); break; + case 7: lea(CO1, ptr[CO2 + LDC * 1]); break; + case 8: lea(CO1, ptr[CO2 + LDC * 2]); break; + } + + // Compute next address of B + if (!isTransB) { + lea(rax, ptr[K * SIZE]); + switch (unroll_n) { + case 1: + add(BO1, LDB); + add(BO2, LDB); + break; + case 2: + lea(BO1, ptr[BO1 + LDB * 2]); + lea(BO2, ptr[BO2 + LDB * 2]); + break; + case 3: + lea(BO1, ptr[BO1 + LDB3]); + lea(BO2, ptr[BO2 + LDB3]); + break; + case 4: + lea(BO1, ptr[BO1 + LDB * 4]); + lea(BO2, ptr[BO2 + LDB * 4]); + break; + case 5: + lea(BO1, ptr[BO1 + LDB * 4]); + add(BO1, LDB); + lea(BO2, ptr[BO2 + LDB * 4]); + add(BO2, LDB); + break; + case 6: + lea(BO1, ptr[BO1 + LDB3 * 2]); + lea(BO2, ptr[BO2 + LDB3 * 2]); + break; + case 7: + lea(BO1, ptr[BO1 + LDB * 8]); + sub(BO1, LDB); + lea(BO2, ptr[BO2 + LDB * 8]); + sub(BO2, LDB); + break; + case 8: + lea(BO1, ptr[BO1 + LDB * 8]); + lea(BO2, ptr[BO2 + LDB * 8]); + break; + } + sub(BO1, rax); + sub(BO2, rax); + } else { + mov(rax, LDB); + imul(rax, K); + sub(BO1, rax); + add(BO1, unroll_n * SIZE); + } + }; + + // High-level subroutine; does packing if needed, then splits C matrix. + // Operates on chunks of 48 rows, 8 columns at a time (handling tail + // cases appropriately by doing 32 or 16 rows, and/or with masking, + // and/or fewer columns). + auto subloop = [&](int unroll_m) { + Label l_subloop_20x[8], l_subloop_mask_20x[8]; + Label l_subloop_30x[8], l_subloop_mask_30x[8]; + + Label subloop11, subloop11mask; + Label subloop30, subloop30mask; + Label subloop31, subloop31mask; + Label subloop96; + Label subloop98, subloop98mask; + Label subloop99; + + // Create mask + mov(BO1, rcx); + mov(rcx, M); + sub(rcx, unroll_m - 16); + mov(CO1, 16); + cmp(rcx, 16); + + cmovg(rcx, CO1); + mov(rax, 1); + sal(rax, cl); + sub(rax, 1); + mov(rcx, 0xffff); + + if (unroll_m == 16) { + kmovw(k1, eax); + } else if (unroll_m == 32) { + kmovw(k1, ecx); + kmovw(k2, eax); + } else { + kmovw(k1, ecx); + kmovw(k2, ecx); + kmovw(k3, eax); + } + mov(rcx, BO1); + + and_(rax, 0xffff); + cmp(rax, 0xffff); + jne(subloop96, T_NEAR); + + if (isTransA) { + do_pack(unroll_m); + } + + mov(CO1, C); + add(C, unroll_m * SIZE); + + mov(BO1, B); + if (!isTransB) { + lea(BO2, ptr[B + LDB * 4]); + } + + if (!isTransA) { + lea(AA, ptr[A + (unroll_m + 16 - 1 - OFFSET) * SIZE]); + cmp(M, UNROLL_M); + jg(subloop98, T_NEAR); + + mov(AA, ORIG_A); + lea(AA, ptr[AA + (16 - 1 - OFFSET) * SIZE]); + L(subloop98); + } + + mov(LL, N); + mov(I, LL); + if (!isTransA) { + // If N is too small, skip copy operation + cmp(LL, UNROLL_N * 3); + jle(subloop30, T_NEAR); + + // If A is not aligned to cache line + cmp(FLAG, 0); + je(subloop30, T_NEAR); + } else { + cmp(LL, UNROLL_N); + jl(l_subloop_20x[1], T_NEAR); + } + align(16); + + if (!isTransA) { + kernel(unroll_m, UNROLL_N, true, true); + } else { + kernel(unroll_m, UNROLL_N, false, false); + } + + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jl(l_subloop_20x[1], T_NEAR); + align(16); + + L(subloop11); + kernel(unroll_m, UNROLL_N, false, false); + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jge(subloop11, T_NEAR); + align(16); + + for (int i = 1; i <= 7; i++) { + L(l_subloop_20x[i]); + cmp(I, i); + if (i < 7) { + jne(l_subloop_20x[i + 1], T_NEAR); + } else { + jne(subloop99, T_NEAR); + } + kernel(unroll_m, i, false, false); + jmp(subloop99, T_NEAR); + align(16); + } + + if (!isTransA) { + L(subloop30); + cmp(I, UNROLL_N); + jl(l_subloop_30x[1], T_NEAR); + align(16); + + L(subloop31); + kernel(unroll_m, UNROLL_N, true, false); + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jge(subloop31, T_NEAR); + align(16); + + for (int i = 1; i <= 7; i++) { + L(l_subloop_30x[i]); + cmp(I, i); + if (i < 7) { + jne(l_subloop_30x[i + 1], T_NEAR); + } else { + jne(subloop99, T_NEAR); + } + kernel(unroll_m, i, true, false); + if (i < 7) + jmp(subloop99, T_NEAR); + align(16); + } + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop96); + if (isTransA) { + do_pack(unroll_m); + } + + mov(CO1, C); + add(C, unroll_m * SIZE); + mov(BO1, B); + if (!isTransB) { + lea(BO2, ptr[B + LDB * 4]); + } + + if (!isTransA) { + lea(AA, ptr[A + (unroll_m + 16 - 1 - OFFSET) * SIZE]); + cmp(M, UNROLL_M); + jg(subloop98mask, T_NEAR); + mov(AA, ORIG_A); + lea(AA, ptr[AA + (16 - 1 - OFFSET) * SIZE]); + L(subloop98mask); + } + + mov(LL, N); + mov(I, LL); + if (!isTransA) { + // If N is too small, skip copy operation + cmp(LL, UNROLL_N * 3); + jle(subloop30mask, T_NEAR); + + // If A is not aligned to cache line + cmp(FLAG, 0); + je(subloop30mask, T_NEAR); + } else { + cmp(LL, UNROLL_N); + jl(l_subloop_mask_20x[1], T_NEAR); + } + align(16); + + if (!isTransA) { + kernel(unroll_m, UNROLL_N, true, true, false); + } else { + kernel(unroll_m, UNROLL_N, false, false, false); + } + + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jl(l_subloop_mask_20x[1], T_NEAR); + align(16); + + L(subloop11mask); + kernel(unroll_m, UNROLL_N, false, false, false); + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jge(subloop11mask, T_NEAR); + align(16); + + for (int i = 1; i <= 7; i++) { + L(l_subloop_mask_20x[i]); + cmp(I, i); + if (i < 7) { + jne(l_subloop_mask_20x[i + 1], T_NEAR); + } else { + jne(subloop99, T_NEAR); + } + kernel(unroll_m, i, false, false, false); + jmp(subloop99, T_NEAR); + align(16); + } + + if (!isTransA) { + L(subloop30mask); + cmp(I, UNROLL_N); + jl(l_subloop_mask_30x[1], T_NEAR); + align(16); + + L(subloop31mask); + kernel(unroll_m, UNROLL_N, true, false, false); + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jge(subloop31mask, T_NEAR); + align(16); + + for (int i = 1; i <= 7; i++) { + L(l_subloop_mask_30x[i]); + cmp(I, i); + if (i < 7) { + jne(l_subloop_mask_30x[i + 1], T_NEAR); + } else { + jne(subloop99, T_NEAR); + } + kernel(unroll_m, i, true, false, false); + if (i < 7) + jmp(subloop99, T_NEAR); + align(16); + } + } + + L(subloop99); + // Compute address for A + if (!isTransA) { + add(A, unroll_m * SIZE); + } else { + mov(rax, LDA); + imul(rax, rax, unroll_m); + add(A, rax); + } + + // Compute next address of BIAS + if (hasBias) { + add(BIAS, unroll_m * SIZE); + } + }; + + preamble(); + + Label buffer_in_ws, buffer_allocated; + + // Get the registers + mov(B, ARG_B); + mov(LDB, ARG_LDB); + mov(r15, ARG_BETA); + mov(r12, ARG_C); + if (hasBias) + mov(r10, ARG_BIAS); + mov(LDC, ARG_LDC); + mov(rbp, rsp); + + vmovss(xmm0, ptr[ARG_ALPHA]); + vmovss(xmm1, ptr[r15]); + +#if _WIN32 + mov(A, ARG_A); + mov(LDA, ARG_LDA); +#endif + + cmp(K, STACK_K_CAPACITY); + jg(buffer_in_ws, T_NEAR); + + // Create buffer and align to 4kB page + lea(rax, ptr[K * SIZE]); + imul(rax, rax, 0x30); + add(rax, 256); + sub(rsp, rax); + and_(rsp, -PAGE_4K); + jmp(buffer_allocated, T_NEAR); + + L(buffer_in_ws); + mov(rsp, ARG_WS); + + L(buffer_allocated); + + mov(ORIG_SP, rbp); + mov(M, ARG_M); + mov(N, ARG_N); + mov(C, r12); + if (hasBias) + mov(BIAS, r10); + vmovss(ALPHA, xmm0); + vmovss(BETA, xmm1); + sub(A, -OFFSET * SIZE); + sub(B, -OFFSET * SIZE); + mov(ORIG_A, A); + sal(LDA, BASE_SHIFT); + sal(LDB, BASE_SHIFT); + sal(LDC, BASE_SHIFT); + lea(LDB3, ptr[LDB + LDB * 2]); + + if (isTransA) { + vpbroadcastq(zmm2, LDA); + vpxorq(ZSTRIDE, ZSTRIDE, ZSTRIDE); + mov(rax, -2); + kmovw(k4, eax); + + for (int i = 0; i < 6; i++) { + vpaddq(ZSTRIDE | k4, ZSTRIDE, zmm2); + kshiftlw(k4, k4, 1); + } + vpaddq(ZSTRIDE | k4, ZSTRIDE, zmm2); + } + + // Check A alignment and leading dimension; take copy-based path as + // needed + mov(rax, LDA); + or_(rax, A); + and_(rax, ver == ver_avx512_core ? 0x07 : 0x3f); + mov(FLAG, rax); + + for (int i = 8; i < 16; i++) { + for (int j = 0; j < 3; j++) { + vpxorq(Zmm(i + 8 * j), Zmm(i + 8 * j), Zmm(i + 8 * j)); + } + } + + Label main0, main1, main2, main999; + + cmp(M, 32); + jle(main0, T_NEAR); + align(16); + + L(main1); + subloop(48); + sub(M, UNROLL_M); + cmp(M, 32); + jg(main1, T_NEAR); + align(16); + + L(main0); + cmp(M, 16); + jle(main2, T_NEAR); + + subloop(32); + jmp(main999, T_NEAR); + align(16); + + L(main2); + cmp(M, 0); + jle(main999, T_NEAR); + subloop(16); + align(16); + + L(main999); + // Restore original stack + mov(rsp, ORIG_SP); + + vzeroupper(); + postamble(); + + ker_ = this->getCode(); + } + + typedef void (*ker_t)(dim_t m, dim_t n, dim_t k, + const float *alpha, const float *a, dim_t lda, + const float *b, dim_t ldb, const float *beta, float *c, + dim_t ldc, const float *bias, float *ws); + + void operator()(dim_t m, dim_t n, dim_t k, + const float *alpha, const float *a, dim_t lda, + const float *b, dim_t ldb, const float *beta, float *c, + dim_t ldc, const float *bias, float *ws) const + { + ker_(m, n, k, alpha, a, lda, b, ldb, beta, c, ldc, bias, ws); + } + +private: + ker_t ker_; +}; + +const xbyak_gemm *get_xbyak_gemm( + bool isTransA, bool isTransB, float beta, bool hasBias) { + auto beta_idx = [](float beta) { + return (beta == 0.0) ? 0 : (beta == 1.0 ? 1 : 2); + }; + + // Kernel table [isTransA][isTransB][hasBias][beta (0, 1, other)] + static xbyak_gemm *kernel_table[2][2][2][3]; + static std::once_flag initialized; + std::call_once(initialized, [=]{ + for (bool isTransA: {false, true}) + for (bool isTransB: {false, true}) + for (bool hasBias: {false, true}) + for (float beta: {0.0f, 1.0f, 2.0f}) { + // nocopy sgemm with bias for beta != 0.0 is not supported + if (hasBias && beta != 0.0) + continue; + kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)] = + new xbyak_gemm(isTransA, isTransB, beta, hasBias); + } + }); + + return kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)]; +} + +void sgemm_nocopy_driver(const char *transa, + const char *transb, int m, int n, int k, const float *alpha, + const float *a, dim_t lda, const float *b, dim_t ldb, const float *beta, + float *c, dim_t ldc, const float *bias, float *ws) +{ + bool isTransA = (*transa == 'T' || *transa == 't'); + bool isTransB = (*transb == 'T' || *transb == 't'); + + int Bm, sizeM, Bn, sizeN, Bk, sizeK; + + int i, j; + + if ((m <= 0) || (n <= 0)) + return; + + if ((k <= 0) || (alpha[0] == 0.)) { + + if (beta[0] == 0.) { + for (j = 0; j < n; j++) + for (i = 0; i < m; i++) + c[i + j * ldc] = 0.0; + } else if (beta[0] != 1.) { + for (j = 0; j < n; j++) + for (i = 0; i < m; i++) + c[i + j * ldc] *= beta[0]; + } + + return; + } + + assert(IMPLICATION(bias != nullptr, *beta == 0.0)); + + // XXX: this happens on every thread... + bool hasBias = (bias != nullptr); + auto ker_bn = get_xbyak_gemm(isTransA, isTransB, *beta, hasBias); + auto ker_b1 = get_xbyak_gemm(isTransA, isTransB, 1.0, false); + auto ker_b0 = get_xbyak_gemm(isTransA, isTransB, 0.0, false); + assert(ker_bn && ker_b1 && ker_b0); + + int BM = 4032, BN, BK; + if (mayiuse(avx512_core)) { + BN = isTransA ? 384 : 64; + BK = 384; + } else { + BN = isTransA ? 96 : 64; + BK = isTransB ? 96 : 192; + if (!isTransA && !isTransB) + BK = 128; + } + const float *curA, *curB, *curBias = nullptr; + float *curC; + + for (Bk = 0; Bk < k; Bk += sizeK) { + sizeK = k - Bk; + if (sizeK >= BK * 2) + sizeK = BK; + else { + if (sizeK > BK) + sizeK = (sizeK + 1) / 2; + } + + for (Bm = 0; Bm < m; Bm += sizeM) { + sizeM = m - Bm; + if (sizeM >= BM * 2) + sizeM = BM; + else { + if (sizeM > BM + BM / 2) + sizeM = (sizeM + 1) / 2; + } + + for (Bn = 0; Bn < n; Bn += sizeN) { + sizeN = n - Bn; + if (sizeN >= BN * 2) + sizeN = BN; + else { + if (sizeN > BN + BN / 2) + sizeN = (sizeN + 1) / 2; + } + + if (!isTransA) { + curA = a + Bm + Bk * lda; + } else { + curA = a + Bk + Bm * lda; + } + if (!isTransB) { + curB = b + Bk + Bn * ldb; + } else { + curB = b + Bn + Bk * ldb; + } + curC = c + Bm + (size_t)Bn * ldc; + if (bias != nullptr) { + if (Bk == 0) { + curBias = bias + Bm; + } else { + curBias = nullptr; + } + } + if (Bk == 0) { + if (*beta == 0.0 && bias == nullptr) + (*ker_b0)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK, + alpha, curA, lda, curB, ldb, beta, curC, ldc, + curBias, ws); + else + (*ker_bn)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK, + alpha, curA, lda, curB, ldb, beta, curC, ldc, + curBias, ws); + } else { + (*ker_b1)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK, + alpha, curA, lda, curB, ldb, beta, curC, ldc, + curBias, ws); + } + } + } + } +} + +} + +mkldnn_status_t jit_avx512_common_gemm_f32( + const char *transa, const char *transb, + const int *p_m, const int *p_n, const int *p_k, const float *p_alpha, + const float *A, const int *p_lda, const float *B, const int *p_ldb, + const float *p_beta, float *C, const int *p_ldc, const float *bias) +{ + using namespace mkldnn::impl::utils; + using namespace avx512_common_gemm_f32; + using namespace gemm_utils; + + if (*p_beta != 0 && bias) + return ref_gemm(transa, transb, p_m, p_n, p_k, + p_alpha, A, p_lda, B, p_lda, p_beta, C, p_ldc, bias); + + int nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads(); + + int m = *p_m; + int n = *p_n; + int k = *p_k; + dim_t lda = *p_lda; + dim_t ldb = *p_ldb; + dim_t ldc = *p_ldc; + float beta = *p_beta; + int MB, NB, KB; + + int nthr_m, nthr_n, nthr_k, nthr_mn; + + // Determine threading partitioning + calc_nthr_nocopy_avx512_common( + m, n, k, nthr, &nthr_m, &nthr_n, &nthr_k, &MB, &NB, &KB); + assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_k == 1)); + + // May not happen, but just in case + if (nthr < nthr_m * nthr_n * nthr_k) + nthr = nthr_m * nthr_n * nthr_k; + + nthr_mn = nthr_m * nthr_n; + + unsigned char * ompstatus_ = nullptr; + unsigned char volatile *ompstatus = nullptr; + + float *c_buffers = nullptr; + float *ws_buffers = nullptr; + + if (nthr_k > 1) { + ompstatus_ = (unsigned char *) malloc( + nthr * CACHE_LINE_SIZE, + CACHE_LINE_SIZE); + ompstatus = (unsigned char volatile *) ompstatus_; + assert(ompstatus); + + for (int i = 0; i < nthr; i++) + ompstatus[i * CACHE_LINE_SIZE] = 0; + + c_buffers = (float *)malloc(nthr_m * nthr_n * (nthr_k - 1) * MB * NB + * sizeof(float), PAGE_4K); + } + + const size_t ws_elems_per_thr = (size_t)k * 48 + 64; + const size_t ws_size_per_thr + = rnd_up(ws_elems_per_thr * sizeof(float), PAGE_4K); + if (k > STACK_K_CAPACITY) { + ws_buffers = (float *)malloc(nthr * ws_size_per_thr, PAGE_4K); + } + + parallel_nd(nthr, [&](const int ithr) { + int ithr_m, ithr_n, ithr_k, ithr_mn; + int m_from, m_to, myM; + int n_from, n_to, myN; + int k_from, k_to, myK; + int cbase, ibase; + const float *myA, *myB, *myBias = nullptr; + float *myC = C, myBeta; + float *ws = ws_buffers ? + ws_buffers + ithr * ws_size_per_thr / sizeof(float) : 0; + dim_t ld = ldc; + + int sum_later = (mkldnn_get_num_threads() < nthr_m * nthr_n * nthr_k); + + if (ithr < nthr_m * nthr_n * nthr_k) { + + ithr_mn = ithr % nthr_mn; + ithr_m = ithr_mn % nthr_m; + ithr_n = ithr_mn / nthr_m; + ithr_k = ithr / nthr_mn; + + /* swap ithr_k for performance improvement */ + if (ithr_k == 0) + ithr_k = nthr_k - 1; + else if (ithr_k == nthr_k - 1) + ithr_k = 0; + + m_from = MB * (ithr_m); + m_to = MB * (ithr_m + 1); + if (m_to > m) + m_to = m; + myM = m_to - m_from; + + n_from = NB * (ithr_n); + n_to = NB * (ithr_n + 1); + if (n_to > n) + n_to = n; + myN = n_to - n_from; + + k_from = KB * (ithr_k); + k_to = KB * (ithr_k + 1); + if (k_to > k) + k_to = k; + myK = k_to - k_from; + + cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1); + ibase = (ithr_m + nthr_m * ithr_n) * nthr_k; + + if ((myM > 0) && (myN > 0)) { + + if (*transa == 'N' || *transa == 'n') { + myA = &(A[m_from + k_from * lda]); + } else { + myA = &(A[k_from + m_from * lda]); + } + if (*transb == 'N' || *transb == 'n') { + myB = &(B[k_from + n_from * ldb]); + } else { + myB = &(B[n_from + k_from * ldb]); + } + if (ithr_k == 0) { + myC = &(C[m_from + n_from * ldc]); + myBeta = beta; + ld = ldc; + if (bias) + myBias = &(bias[m_from]); + } else { + myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1); + myBeta = 0.0; + ld = MB; + myBias = nullptr; + } + + sgemm_nocopy_driver(transa, transb, myM, myN, myK, p_alpha, myA, + lda, myB, ldb, &myBeta, myC, ld, myBias, ws); + + if (nthr_k > 1 && !sum_later) + ompstatus[(ibase + ithr_k) * CACHE_LINE_SIZE] = 1; + } + + if (nthr_k > 1 && !sum_later) { + + // sum matrices partitioned along K dimension + int n1, n2; + + partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2); + + if (ithr_k > 0) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1) + + (dim_t)n1 * MB; + /* need to wait until main thread finishes */ + while (ompstatus[ibase * CACHE_LINE_SIZE] != 1) { + }; + + /* my cache is hot */ + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + + for (int ik = 1; ik < nthr_k; ++ik) { + if (ik != ithr_k) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1) + + (dim_t)n1 * MB; + + while (ompstatus[(ibase + ik) * CACHE_LINE_SIZE] != 1) { + }; + + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + } + } + } + }); + + + // handle C summation later + if (nthr_k > 1 && ompstatus[0] == 0) { + + parallel_nd(nthr, [&](const int ithr) { + int ithr_m, ithr_n, ithr_k, ithr_mn; + int m_from, m_to, myM; + int n_from, n_to, myN; + int cbase; + float *myC = C; + + if (ithr < nthr_m * nthr_n * nthr_k) { + + ithr_mn = ithr % nthr_mn; + ithr_m = ithr_mn % nthr_m; + ithr_n = ithr_mn / nthr_m; + ithr_k = ithr / nthr_mn; + + /* swap ithr_k for performance improvement */ + if (ithr_k == 0) + ithr_k = nthr_k - 1; + else if (ithr_k == nthr_k - 1) + ithr_k = 0; + + m_from = MB * (ithr_m); + m_to = MB * (ithr_m + 1); + if (m_to > m) + m_to = m; + myM = m_to - m_from; + + n_from = NB * (ithr_n); + n_to = NB * (ithr_n + 1); + if (n_to > n) + n_to = n; + myN = n_to - n_from; + + cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1); + + if (nthr_k > 1) { + // sum matrices partitioned along K dimension + int n1, n2; + + partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2); + + if (ithr_k > 0) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1) + + (dim_t)n1 * MB; + + /* my cache is hot */ + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + + for (int ik = 1; ik < nthr_k; ++ik) { + if (ik != ithr_k) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1) + + (dim_t)n1 * MB; + + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + } + } + } + }); + } + + free(c_buffers); + free(ompstatus_); + free(ws_buffers); + + return mkldnn_success; +} + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp new file mode 100644 index 0000000000..d581b7fd71 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp @@ -0,0 +1,36 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX512_COMMON_GEMM_F32_HPP +#define JIT_AVX512_COMMON_GEMM_F32_HPP + +#include "mkldnn_types.h" + +namespace mkldnn { +namespace impl { +namespace cpu { + +mkldnn_status_t jit_avx512_common_gemm_f32( + const char *transa, const char *transb, const int *M, + const int *N, const int *K, const float *alpha, const float *A, + const int *lda, const float *B, const int *ldb, const float *beta, + float *C, const int *ldc, const float *bias = nullptr); + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp new file mode 100644 index 0000000000..60d4220837 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp @@ -0,0 +1,2705 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "ref_gemm_f32.hpp" +#include "gemm_utils_f32.hpp" +#include "jit_avx_gemm_f32.hpp" + +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +#define CACHE_LINE_SIZE 64 + +#define STACKSIZE get_size_of_abi_save_regs() +#if _WIN32 +#define STACK_K_CAPACITY 128 +#else +#define STACK_K_CAPACITY 8192 +#endif +#define SIZE 4 +#define OFFSET 32 +#define BASE_SHIFT 2 +#define SECOND_FETCH 14 + +namespace avx_gemm_f32 { +using namespace gemm_utils; + +struct xbyak_gemm : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx_gemm_f32_xbyak_gemm) + + xbyak_gemm(char isTransA, char isTransB, float beta, bool hasBias = false, + void *code_ptr = nullptr, + size_t code_size = 80 * Xbyak::DEFAULT_MAX_CODE_SIZE) + : jit_generator(code_ptr, code_size) + { + using namespace Xbyak; + + const bool is_avx2 = mayiuse(avx2); + assert(IMPLICATION(!is_avx2, mayiuse(avx))); + + const int UNROLL_M = is_avx2 ? 16 : 8; + const int UNROLL_N = 6; + + bool isBeta0 = (beta == 0.0); + bool isBetaN = (!isBeta0 && beta != 1.0); + + // various definitions for convenience + auto ARG_M = abi_param1; + auto ARG_N = abi_param2; + auto K = abi_param3; + auto ARG_ALPHA = abi_param4; +#ifdef _WIN32 + auto ARG_A = ptr[rsp + OFFSET_SHADOWSPACE + STACKSIZE]; + auto ARG_LDA = qword[rsp + OFFSET_SHADOWSPACE + + sizeof(float *) + STACKSIZE]; + const auto stackOffset = OFFSET_SHADOWSPACE + + sizeof(float *) + STACKSIZE; + auto A = rsi; + auto LDA = rdi; +#else + auto ARG_A = r8; + auto ARG_LDA = r9; + const auto stackOffset = STACKSIZE; + auto A = ARG_A; + auto LDA = ARG_LDA; +#endif + auto ARG_B = ptr[rsp + 8 + stackOffset]; + auto ARG_LDB = ptr[rsp + 16 + stackOffset]; + auto ARG_BETA = ptr[rsp + 24 + stackOffset]; + auto ARG_C = ptr[rsp + 32 + stackOffset]; + auto ARG_LDC = ptr[rsp + 40 + stackOffset]; + auto ARG_BIAS = ptr[rsp + 48 + stackOffset]; + auto ARG_WS = ptr[rsp + 56 + stackOffset]; + + auto B = r11; + auto LDB = rbx; + auto LDC = r13; + auto LL = rax; + auto AO1 = abi_param2; + auto BO1 = abi_param4; + auto BO2 = rbp; + auto CO1 = r14; + auto CO2 = r15; + auto LDB3 = r10; + auto LDA4 = abi_param1; + auto AA = r12; + auto BIAS1 = abi_param1; + + auto M = qword[rsp + 0]; + auto N = qword[rsp + 8]; + auto FLAG = qword[rsp + 16]; + auto I = qword[rsp + 24]; + auto C = qword[rsp + 32]; + auto BIAS = qword[rsp + 40]; + auto ALPHA = qword[rsp + 48]; + auto BETA = qword[rsp + 64]; + auto ORIG_A = qword[rsp + 80]; + auto MASK = dword[rsp + 88]; + auto STRIDE = qword[rsp + 120]; + auto ORIG_SP = qword[rsp + 152]; + + auto VALPHA = ymm1; + auto VBETA = ymm2; + auto VMASK = ymm3; + auto VBIAS1 = ymm2; + auto VBIAS2 = ymm4; + + auto PREFETCHSIZEA = 128; + auto PREFETCHSIZEB = (!isTransB) ? -16 : 0; + + // Function for packing if needed + auto do_pack = [&]( + int unroll_m, bool isLoad1Unmasked, bool isLoad2Unmasked) { + Label pack2, pack3, pack4, pack10; + + int regIdx; + Reg64 reg; + + mov(BO1, A); + lea(AO1, ptr[rsp + 256 + OFFSET * SIZE]); + + if (isTransA) { + lea(BO2, ptr[BO1 + LDA * 4]); + lea(CO1, ptr[LDA + LDA * 2]); + vmovupd(ymm7, STRIDE); + } + + mov(LL, K); + sar(LL, 2); + jle(pack3, T_NEAR); + align(16); + + L(pack2); + if (!isTransA) { + for (int i = 0; i < 4; i++) { + regIdx = (i % 2 == 0) ? 4 : 6; + if (isLoad1Unmasked) { + vmovups(Ymm(regIdx), + ptr[BO1 + (0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(Ymm(regIdx), VMASK, + ptr[BO1 + (0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m > 8) { + if (isLoad2Unmasked) { + vmovups(Ymm(regIdx + 1), + ptr[BO1 + (1 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(Ymm(regIdx + 1), VMASK, + ptr[BO1 + (1 * 8 - OFFSET) * SIZE]); + } + } + add(BO1, LDA); + + vmovups(ptr[AO1 + (unroll_m * i + 0 * 8 - OFFSET) * SIZE], + Ymm(regIdx)); + if (unroll_m > 8) { + vmovups(ptr[AO1 + + (unroll_m * i + 1 * 8 - OFFSET) + * SIZE], + Ymm(regIdx + 1)); + } + } + + } else { + if (isLoad1Unmasked) { + for (int i = 0; i < 2; i++) { + reg = (i % 2 == 0) ? BO1 : BO2; + vmovups(xmm0, ptr[reg + (0 * 8 - OFFSET) * SIZE]); + vmovups(xmm1, + ptr[reg + LDA * 1 + (0 * 8 - OFFSET) * SIZE]); + lea(BO2, ptr[reg + LDA * 2]); + vunpcklps(xmm4, xmm0, xmm1); + vunpckhps(xmm5, xmm0, xmm1); + vmovups(xmm0, ptr[BO2 + (0 * 8 - OFFSET) * SIZE]); + vmovups(xmm1, + ptr[BO2 + LDA * 1 + (0 * 8 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 2]); + vunpcklps(xmm6, xmm0, xmm1); + vunpckhps(xmm2, xmm0, xmm1); + + vunpcklpd(xmm0, xmm4, xmm6); + vunpckhpd(xmm1, xmm4, xmm6); + vmovups(ptr[AO1 + + (unroll_m * 0 + i * 4 - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * 1 + i * 4 - OFFSET) + * SIZE], + xmm1); + vunpcklpd(xmm0, xmm5, xmm2); + vunpckhpd(xmm1, xmm5, xmm2); + vmovups(ptr[AO1 + + (unroll_m * 2 + i * 4 - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * 3 + i * 4 - OFFSET) + * SIZE], + xmm1); + } + } else if (is_avx2) { + for (int i = 0; i < 2; i++) { + vmovaps(xmm4, xmm3); + vgatherqps(xmm0, + ptr[BO1 + ymm7 + ((2 * i) - OFFSET) * SIZE], + xmm4); + vmovaps(xmm4, xmm3); + vgatherqps(xmm1, + ptr[BO1 + ymm7 + ((2 * i + 1) - OFFSET) * SIZE], + xmm4); + + vmovups(ptr[AO1 + + (unroll_m * (2 * i) + 0 * 4 - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * (2 * i + 1) + 0 * 4 + - OFFSET) + * SIZE], + xmm1); + } + + lea(BO2, ptr[BO1 + LDA * 4]); + + for (int i = 0; i < 2; i++) { + vextractf128(xmm4, ymm3, 1); + vgatherqps(xmm0, + ptr[BO2 + ymm7 + ((2 * i) - OFFSET) * SIZE], + xmm4); + vextractf128(xmm4, ymm3, 1); + vgatherqps(xmm1, + ptr[BO2 + ymm7 + ((2 * i + 1) - OFFSET) * SIZE], + xmm4); + + vmovups(ptr[AO1 + + (unroll_m * (2 * i) + 1 * 4 - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * (2 * i + 1) + 1 * 4 + - OFFSET) + * SIZE], + xmm1); + } + + lea(BO2, ptr[BO2 + LDA * 4]); + } else { + vxorps(xmm4, xmm4, xmm4); + lea(BO2, ptr[BO1 + LDA * 4]); + + auto el_cp = [&](int section, int ld_step) { + RegExp src_addr = section == 0 ? BO1 : BO2; + if (ld_step == 1 || ld_step == 2) + src_addr = src_addr + LDA * ld_step; + else if (ld_step == 3) + src_addr = src_addr + CO1; + src_addr = src_addr - OFFSET * SIZE; + + vmovups(Xmm(ld_step % 2), ptr[src_addr]); + RegExp dst_addr = AO1 + + (ld_step + section * 4 - OFFSET) * SIZE; + for (int off = 0; off < 4; ++off) + pextrd(ptr[dst_addr + unroll_m * off * SIZE], + Xmm(ld_step % 2), off); + }; + + Label l_end; + el_cp(0, 0); cmp(M, 4 * 0 + 0 + 1); je(l_end, T_NEAR); + el_cp(0, 1); cmp(M, 4 * 0 + 1 + 1); je(l_end, T_NEAR); + el_cp(0, 2); cmp(M, 4 * 0 + 2 + 1); je(l_end, T_NEAR); + el_cp(0, 3); cmp(M, 4 * 0 + 3 + 1); je(l_end, T_NEAR); + el_cp(1, 0); cmp(M, 4 * 1 + 0 + 1); je(l_end, T_NEAR); + el_cp(1, 1); cmp(M, 4 * 1 + 1 + 1); je(l_end, T_NEAR); + el_cp(1, 2); + L(l_end); + + lea(BO2, ptr[BO2 + LDA * 4]); + } + + if (unroll_m >= 16) { + assert(is_avx2); + if (isLoad2Unmasked) { + for (int i = 0; i < 2; i++) { + vmovups(xmm0, ptr[BO2 + (0 * 8 - OFFSET) * SIZE]); + vmovups(xmm1, ptr[BO2 + LDA * 1 + + (0 * 8 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 2]); + vunpcklps(xmm4, xmm0, xmm1); + vunpckhps(xmm5, xmm0, xmm1); + vmovups(xmm0, ptr[BO2 + (0 * 8 - OFFSET) * SIZE]); + vmovups(xmm1, ptr[BO2 + LDA * 1 + + (0 * 8 - OFFSET) * SIZE]); + if (i == 0) + lea(BO2, ptr[BO2 + LDA * 2]); + vunpcklps(xmm6, xmm0, xmm1); + vunpckhps(xmm2, xmm0, xmm1); + + vunpcklpd(xmm0, xmm4, xmm6); + vunpckhpd(xmm1, xmm4, xmm6); + vmovups(ptr[AO1 + + (unroll_m * 0 + (i + 2) * 4 + - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * 1 + (i + 2) * 4 + - OFFSET) + * SIZE], + xmm1); + vunpcklpd(xmm0, xmm5, xmm2); + vunpckhpd(xmm1, xmm5, xmm2); + vmovups(ptr[AO1 + + (unroll_m * 2 + (i + 2) * 4 + - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * 3 + (i + 2) * 4 + - OFFSET) + * SIZE], + xmm1); + } + } else { + for (int i = 0; i < 2; i++) { + vmovaps(xmm4, xmm3); + vgatherqps(xmm0, + ptr[BO2 + ymm7 + ((2 * i) - OFFSET) * SIZE], + xmm4); + vmovaps(xmm4, xmm3); + vgatherqps(xmm1, + ptr[BO2 + ymm7 + + ((2 * i + 1) - OFFSET) * SIZE], + xmm4); + + vmovups(ptr[AO1 + + (unroll_m * (2 * i) + 2 * 4 + - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * (2 * i + 1) + 2 * 4 + - OFFSET) + * SIZE], + xmm1); + } + + lea(BO2, ptr[BO2 + LDA * 4]); + + for (int i = 0; i < 2; i++) { + vextractf128(xmm4, ymm3, 1); + vgatherqps(xmm0, + ptr[BO2 + ymm7 + ((2 * i) - OFFSET) * SIZE], + xmm4); + vextractf128(xmm4, ymm3, 1); + vgatherqps(xmm1, + ptr[BO2 + ymm7 + + ((2 * i + 1) - OFFSET) * SIZE], + xmm4); + + vmovups(ptr[AO1 + + (unroll_m * (2 * i) + 3 * 4 + - OFFSET) + * SIZE], + xmm0); + vmovups(ptr[AO1 + + (unroll_m * (2 * i + 1) + 3 * 4 + - OFFSET) + * SIZE], + xmm1); + } + + lea(BO2, ptr[BO2 + LDA * 4]); + } + } + add(BO1, (4 * SIZE)); + } + + add(AO1, unroll_m * 4 * SIZE); + sub(LL, 1); + jg(pack2, T_NEAR); + align(16); + + L(pack3); + mov(LL, K); + and_(LL, 3); + jle(pack10, T_NEAR); + align(16); + + L(pack4); + if (!isTransA) { + if (isLoad1Unmasked) { + vmovups(ymm4, ptr[BO1 + (0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm4, VMASK, ptr[BO1 + (0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m > 8) { + if (isLoad2Unmasked) { + vmovups(ymm5, ptr[BO1 + (1 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm5, VMASK, + ptr[BO1 + (1 + 8 - OFFSET) * SIZE]); + } + } + add(BO1, LDA); + vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE], + ymm4); + if (unroll_m > 8) { + vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 8 - OFFSET) * SIZE], + ymm5); + } + } else { + if (isLoad1Unmasked) { + for (int i = 0; i < 2; i++) { + reg = (i % 2 == 0) ? BO1 : BO2; + vmovss(Xmm(i + 1), ptr[reg + (0 * 8 - OFFSET) * SIZE]); + vmovss(xmm0, + ptr[reg + LDA * 1 + (0 * 8 - OFFSET) * SIZE]); + lea(BO2, ptr[reg + LDA * 2]); + vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0)); + } + vunpcklpd(xmm1, xmm1, xmm2); + vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 4 - OFFSET) * SIZE], + xmm1); + + for (int i = 0; i < 2; i++) { + vmovss(Xmm(i + 1), ptr[BO2 + (0 * 8 - OFFSET) * SIZE]); + vmovss(xmm0, + ptr[BO2 + LDA * 1 + (0 * 8 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 2]); + vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0)); + } + vunpcklpd(xmm1, xmm1, xmm2); + vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 4 - OFFSET) * SIZE], + xmm1); + } else if (is_avx2) { + vmovaps(xmm4, xmm3); + vgatherqps(xmm1, ptr[BO1 + ymm7 + (0 * 8 - OFFSET) * SIZE], + xmm4); + lea(BO2, ptr[BO1 + LDA * 4]); + vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 4 - OFFSET) * SIZE], + xmm1); + + vextractf128(xmm4, ymm3, 1); + vgatherqps(xmm1, ptr[BO2 + ymm7 + (0 * 8 - OFFSET) * SIZE], + xmm4); + lea(BO2, ptr[BO2 + LDA * 4]); + vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 4 - OFFSET) * SIZE], + xmm1); + } else { + vxorps(xmm4, xmm4, xmm4); + lea(BO2, ptr[BO1 + LDA * 4]); + + auto el_cp = [&](int section, int ld_step) { + RegExp src_addr = section == 0 ? BO1 : BO2; + if (ld_step == 1 || ld_step == 2) + src_addr = src_addr + LDA * ld_step; + else if (ld_step == 3) + src_addr = src_addr + CO1; + src_addr = src_addr - OFFSET * SIZE; + + vmovss(xmm1, ptr[src_addr]); + RegExp dst_addr = AO1 + + (ld_step + section * 4 - OFFSET) * SIZE; + movss(ptr[dst_addr], xmm1); + }; + + Label l_end; + el_cp(0, 0); cmp(M, 4 * 0 + 0 + 1); je(l_end, T_NEAR); + el_cp(0, 1); cmp(M, 4 * 0 + 1 + 1); je(l_end, T_NEAR); + el_cp(0, 2); cmp(M, 4 * 0 + 2 + 1); je(l_end, T_NEAR); + el_cp(0, 3); cmp(M, 4 * 0 + 3 + 1); je(l_end, T_NEAR); + el_cp(1, 0); cmp(M, 4 * 1 + 0 + 1); je(l_end, T_NEAR); + el_cp(1, 1); cmp(M, 4 * 1 + 1 + 1); je(l_end, T_NEAR); + el_cp(1, 2); + L(l_end); + + lea(BO2, ptr[BO2 + LDA * 4]); + } + + if (unroll_m >= 16) { + assert(is_avx2); + if (isLoad2Unmasked) { + for (int i = 0; i < 2; i++) { + vmovss(Xmm(i + 1), + ptr[BO2 + (0 * 8 - OFFSET) * SIZE]); + vmovss(xmm0, ptr[BO2 + LDA * 1 + + (0 * 8 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 2]); + vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0)); + } + vunpcklpd(xmm1, xmm1, xmm2); + } else { + vmovaps(xmm4, xmm3); + vgatherqps(xmm1, + ptr[BO2 + ymm7 + (0 * 8 - OFFSET) * SIZE], + xmm4); + lea(BO2, ptr[BO2 + LDA * 4]); + } + vmovups(ptr[AO1 + (unroll_m * 0 + 2 * 4 - OFFSET) * SIZE], + xmm1); + + if (isLoad2Unmasked) { + for (int i = 0; i < 2; i++) { + vmovss(Xmm(i + 1), + ptr[BO2 + (0 * 8 - OFFSET) * SIZE]); + vmovss(xmm0, ptr[BO2 + LDA * 1 + + (0 * 8 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDA * 2]); + vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0)); + } + vunpcklpd(xmm1, xmm1, xmm2); + } else { + vextractf128(xmm4, ymm3, 1); + vgatherqps(xmm1, + ptr[BO2 + ymm7 + (0 * 8 - OFFSET) * SIZE], + xmm4); + } + vmovups(ptr[AO1 + (unroll_m * 0 + 3 * 4 - OFFSET) * SIZE], + xmm1); + } + add(BO1, SIZE); + } + + add(AO1, unroll_m * SIZE); + sub(LL, 1); + jg(pack4, T_NEAR); + align(16); + + L(pack10); + }; + + // Fused multiply add; may become one or two instructions + auto fma = [&](bool useFma, Ymm reg0, Ymm reg1, Ymm reg2, + bool overWrite = false) { + if (useFma) { + if (is_avx2) { + vfmadd231ps(reg2, reg1, reg0); + } else { + assert(UNROLL_M == 8); + auto tent_vreg = overWrite ? reg1 : ymm1; + vmulps(tent_vreg, reg1, reg0); + vaddps(reg2, reg2, tent_vreg); + } + } else { + if (!overWrite) { + vmulps(ymm15, reg1, reg0); + vaddps(reg2, reg2, ymm15); + } else { + vmulps(reg1, reg1, reg0); + vaddps(reg2, reg2, reg1); + } + } + }; + + // Inner kernel with k=8 + auto innerkernel8 = [&](int unroll_m, int unroll_n, + bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect, + bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02, + Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07, + Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11, Ymm reg12, + Ymm reg13, Ymm reg14, Ymm reg15, Ymm reg16, Ymm reg17, + Ymm reg18, Ymm reg19, Ymm reg20, Ymm reg21, Ymm reg22, + Ymm reg23) { + + Ymm fmareg; + + if (!isDirect) { + prefetcht0(ptr[AO1 + (PREFETCHSIZEA + 0) * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4]); + } + + for (int i = 0; i < 8; i++) { + if (isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm0, VMASK, + ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } + } + add(AO1, LDA); + } + + if (!isTransB) { + vbroadcastss(ymm2, ptr[BO1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg00 : reg12; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg06 : reg18; + fma(useFma, ymm1, ymm2, fmareg); + } + if (i == 0) { + if (!isTransB) { + prefetcht0(ptr[BO1 + PREFETCHSIZEB * SIZE]); + } + } + if (unroll_n >= 2) { + if (!isTransB) { + if (i == 1) { + prefetcht0(ptr[BO1 + LDB + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO1 + LDB * 1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg01 : reg13; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg07 : reg19; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (isCopy) { + vmovups(ptr[LDA4 + (unroll_m * i + 0 * 8 - OFFSET) * SIZE], + ymm0); + if (unroll_m >= 16) { + vmovups(ptr[LDA4 + + (unroll_m * i + 1 * 8 - OFFSET) + * SIZE], + ymm1); + } + if (i == 7) { + sub(LDA4, -unroll_m * 8 * SIZE); + } + } + + if (unroll_n >= 3) { + if (!isTransB) { + if (i == 2) { + prefetcht0( + ptr[BO1 + LDB * 2 + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO1 + LDB * 2 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg02 : reg14; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg08 : reg20; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (i == 7) { + if (!isTransB) { + sub(BO1, -8 * SIZE); + } + } + + if (unroll_n >= 4) { + if (!isTransB) { + if (i == 3) { + prefetcht0(ptr[BO2 + PREFETCHSIZEB * SIZE]); + } + vbroadcastss(ymm2, ptr[BO2 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg03 : reg15; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg09 : reg21; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 5) { + if (!isTransB) { + if (i == 4) { + prefetcht0(ptr[BO2 + LDB + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO2 + LDB * 1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg04 : reg16; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg10 : reg22; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 6) { + if (!isTransB) { + if (i == 5) { + prefetcht0( + ptr[BO2 + LDB * 2 + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO2 + LDB * 2 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg05 : reg17; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg11 : reg23; + fma(useFma, ymm1, ymm2, fmareg); + } + } + if (isTransB) { + prefetcht0(ptr[BO1 + BO2]); + add(BO1, LDB); + } + + if (i == 0) { + if (unroll_m >= 4) { + if (!isDirect) { + prefetcht0( + ptr[AO1 + (PREFETCHSIZEA + 2 * 8) * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4]); + } + } + } + if (i == 1 || i == 2) { + if (unroll_m >= 8) { + if (!isDirect) { + prefetcht0(ptr[AO1 + + (PREFETCHSIZEA + (2 + 2 * i) * 8) + * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4]); + } + } + } + if (i == 3 || i == 4 || i == 5 || i == 6) { + if (unroll_m >= 16) { + if (!isDirect) { + prefetcht0(ptr[AO1 + + (PREFETCHSIZEA + (2 + 2 * i) * 8) + * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4]); + } + } + } + if (i == 7) { + if (!isTransB) { + if (unroll_n >= 4) { + sub(BO2, -8 * SIZE); + } + } + if (!isTransA) { + prefetcht2(ptr[AA]); + lea(AA, ptr[AA + LDA]); + } + } + + if (!isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, + ptr[AO1 + + (unroll_m * (i + 1) + 0 * 8 - OFFSET) + * SIZE]); + } else { + vmaskmovps( + ymm0, VMASK, + ptr[AO1 + + (unroll_m * (i + 1) + 0 * 8 - OFFSET) + * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + + (unroll_m * (i + 1) + 1 * 8 + - OFFSET) + * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + + (unroll_m * (i + 1) + 1 * 8 + - OFFSET) + * SIZE]); + } + } + } + } + + if (!isDirect) { + sub(AO1, -unroll_m * 8 * SIZE); + } + sub(LL, 1); + + }; + + // Inner kernel with k=4 + auto innerkernel4 = [&](int unroll_m, int unroll_n, + bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect, + bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02, + Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07, + Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11, Ymm reg12, + Ymm reg13, Ymm reg14, Ymm reg15, Ymm reg16, Ymm reg17, + Ymm reg18, Ymm reg19, Ymm reg20, Ymm reg21, Ymm reg22, + Ymm reg23) { + + Ymm fmareg; + + if (!isDirect) { + prefetcht0(ptr[AO1 + (PREFETCHSIZEA + 0) * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4]); + } + + for (int i = 0; i < 4; i++) { + if (isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm0, VMASK, + ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } + } + add(AO1, LDA); + } + + if (!isTransB) { + vbroadcastss(ymm2, ptr[BO1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg00 : reg12; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg06 : reg18; + fma(useFma, ymm1, ymm2, fmareg); + } + if (i == 0) { + if (!isTransB) { + prefetcht0(ptr[BO1 + PREFETCHSIZEB * SIZE]); + } + } + if (unroll_n >= 2) { + if (!isTransB) { + if (i == 1) { + prefetcht0(ptr[BO1 + LDB + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO1 + LDB * 1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg01 : reg13; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg07 : reg19; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (isCopy) { + vmovups(ptr[LDA4 + (unroll_m * i + 0 * 8 - OFFSET) * SIZE], + ymm0); + if (unroll_m >= 16) { + vmovups(ptr[LDA4 + + (unroll_m * i + 1 * 8 - OFFSET) + * SIZE], + ymm1); + } + if (i == 3) { + sub(LDA4, -unroll_m * 4 * SIZE); + } + } + + if (unroll_n >= 3) { + if (!isTransB) { + if (i == 2) { + prefetcht0( + ptr[BO1 + LDB * 2 + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO1 + LDB * 2 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg02 : reg14; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg08 : reg20; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (i == 7) { + if (!isTransB) { + sub(BO1, -8 * SIZE); + } + } + + if (unroll_n >= 4) { + if (!isTransB) { + if (i == 3) { + prefetcht0(ptr[BO2 + PREFETCHSIZEB * SIZE]); + } + vbroadcastss(ymm2, ptr[BO2 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg03 : reg15; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg09 : reg21; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 5) { + if (!isTransB) { + if (i == 4) { + prefetcht0(ptr[BO2 + LDB + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO2 + LDB * 1 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg04 : reg16; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg10 : reg22; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 6) { + if (!isTransB) { + if (i == 5) { + prefetcht0( + ptr[BO2 + LDB * 2 + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO2 + LDB * 2 + (i - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg05 : reg17; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg11 : reg23; + fma(useFma, ymm1, ymm2, fmareg); + } + } + if (isTransB) { + prefetcht0(ptr[BO1 + BO2]); + add(BO1, LDB); + } + + if (i == 0) { + if (unroll_m >= 4) { + if (!isDirect) { + prefetcht0( + ptr[AO1 + (PREFETCHSIZEA + 2 * 8) * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4]); + } + } + } + if (i == 1 || i == 2) { + if (unroll_m >= 8) { + if (!isDirect) { + prefetcht0(ptr[AO1 + + (PREFETCHSIZEA + (2 + 2 * i) * 8) + * SIZE]); + } else { + prefetcht0(ptr[AO1 + LDA4]); + } + } + } + if (i == 3) { + if (!isTransB) { + sub(BO1, -4 * SIZE); + if (unroll_n >= 4) { + sub(BO2, -4 * SIZE); + } + } + } + + if (!isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, + ptr[AO1 + + (unroll_m * (i + 1) + 0 * 8 - OFFSET) + * SIZE]); + } else { + vmaskmovps( + ymm0, VMASK, + ptr[AO1 + + (unroll_m * (i + 1) + 0 * 8 - OFFSET) + * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + + (unroll_m * (i + 1) + 1 * 8 + - OFFSET) + * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + + (unroll_m * (i + 1) + 1 * 8 + - OFFSET) + * SIZE]); + } + } + } + } + + if (!isDirect) { + sub(AO1, -unroll_m * 4 * SIZE); + } + + }; + + // Inner kernel with k=2 + auto innerkernel2 = [&](int unroll_m, int unroll_n, + bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect, + bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02, + Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07, + Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11, Ymm reg12, + Ymm reg13, Ymm reg14, Ymm reg15, Ymm reg16, Ymm reg17, + Ymm reg18, Ymm reg19, Ymm reg20, Ymm reg21, Ymm reg22, + Ymm reg23) { + + Ymm fmareg; + + for (int i = 0; i < 2; i++) { + if (isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm0, VMASK, + ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } + } + add(AO1, LDA); + } + + if (!isTransB) { + vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg00 : reg12; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg06 : reg18; + fma(useFma, ymm1, ymm2, fmareg); + } + if (unroll_n >= 2) { + if (!isTransB) { + vbroadcastss( + ymm2, ptr[BO1 + LDB * 1 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg01 : reg13; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg07 : reg19; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 3) { + if (!isTransB) { + if (i == 2) { + prefetcht0( + ptr[BO1 + LDB * 2 + PREFETCHSIZEB * SIZE]); + } + vbroadcastss( + ymm2, ptr[BO1 + LDB * 2 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg02 : reg14; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg08 : reg20; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 4) { + if (!isTransB) { + vbroadcastss(ymm2, ptr[BO2 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg03 : reg15; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg09 : reg21; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 5) { + if (!isTransB) { + vbroadcastss( + ymm2, ptr[BO2 + LDB * 1 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg04 : reg16; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg10 : reg22; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (unroll_n >= 6) { + if (!isTransB) { + vbroadcastss( + ymm2, ptr[BO2 + LDB * 2 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]); + } + fmareg = (i % 2 == 0) ? reg05 : reg17; + fma(useFma, ymm0, ymm2, fmareg); + if (unroll_m >= 16) { + fmareg = (i % 2 == 0) ? reg11 : reg23; + fma(useFma, ymm1, ymm2, fmareg); + } + } + + if (isCopy) { + vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE], + ymm0); + if (unroll_m >= 16) { + vmovups(ptr[LDA4 + + (unroll_m * 0 + 1 * 8 - OFFSET) + * SIZE], + ymm1); + } + sub(LDA4, -unroll_m * SIZE); + } + + if (!isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, ptr[AO1 + + (unroll_m * 1 + 0 * 8 - OFFSET) + * SIZE]); + } else { + vmaskmovps(ymm0, VMASK, + ptr[AO1 + + (unroll_m * 1 + 0 * 8 - OFFSET) + * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, + ptr[AO1 + + (unroll_m * 1 + 1 * 8 - OFFSET) + * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + + (unroll_m * 1 + 1 * 8 - OFFSET) + * SIZE]); + } + } + sub(AO1, -unroll_m * SIZE); + } + + if (!isTransB) { + sub(BO1, -SIZE); + if (unroll_n >= 4) { + sub(BO2, -SIZE); + } + } else { + add(BO1, LDB); + } + } + + }; + + // Inner kernel with k=1 + auto innerkernel1 = [&](int unroll_m, int unroll_n, + bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect, + bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02, + Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07, + Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11) { + + if (isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm0, VMASK, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + (1 * 8 - OFFSET) * SIZE]); + } + } + add(AO1, LDA); + } + + if (!isTransB) { + vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]); + } + fma(useFma, ymm0, ymm2, reg00); + if (unroll_m >= 16) { + fma(useFma, ymm1, ymm2, reg06); + } + + if (unroll_n >= 2) { + if (!isTransB) { + vbroadcastss( + ymm2, ptr[BO1 + LDB * 1 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]); + } + fma(useFma, ymm0, ymm2, reg01); + if (unroll_m >= 16) { + fma(useFma, ymm1, ymm2, reg07); + } + } + + if (unroll_n >= 3) { + if (!isTransB) { + vbroadcastss( + ymm2, ptr[BO1 + LDB * 2 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]); + } + fma(useFma, ymm0, ymm2, reg02); + if (unroll_m >= 16) { + fma(useFma, ymm1, ymm2, reg08); + } + } + + if (unroll_n >= 4) { + if (!isTransB) { + vbroadcastss(ymm2, ptr[BO2 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]); + } + fma(useFma, ymm0, ymm2, reg03); + if (unroll_m >= 16) { + fma(useFma, ymm1, ymm2, reg09); + } + } + + if (unroll_n >= 5) { + if (!isTransB) { + vbroadcastss( + ymm2, ptr[BO2 + LDB * 1 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]); + } + fma(useFma, ymm0, ymm2, reg04); + if (unroll_m >= 16) { + fma(useFma, ymm1, ymm2, reg10); + } + } + + if (unroll_n >= 6) { + if (!isTransB) { + vbroadcastss( + ymm2, ptr[BO2 + LDB * 2 + (0 - OFFSET) * SIZE]); + } else { + vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]); + } + fma(useFma, ymm0, ymm2, reg05); + if (unroll_m >= 16) { + fma(useFma, ymm1, ymm2, reg11); + } + } + + if (isCopy) { + vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE], + ymm0); + if (unroll_m >= 16) { + vmovups(ptr[LDA4 + (unroll_m * 0 + 1 * 8 - OFFSET) * SIZE], + ymm1); + } + sub(LDA4, -unroll_m * SIZE); + } + + if (!isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, + ptr[AO1 + (unroll_m * 1 + 0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm0, VMASK, + ptr[AO1 + (unroll_m * 1 + 0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + + (unroll_m * 1 + 1 * 8 - OFFSET) + * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + + (unroll_m * 1 + 1 * 8 - OFFSET) + * SIZE]); + } + } + sub(AO1, -unroll_m * SIZE); + } + + if (!isTransB) { + sub(BO1, -SIZE); + if (unroll_n >= 4) { + sub(BO2, -SIZE); + } + } else { + add(BO1, LDB); + } + + }; + + // Main kernel; does prefetching and calls innerkernel{1,2,4,8} as + // appropriate + // After calculating results in registers, writes back to C matrix + auto kernel = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy, bool useFma, + Ymm reg00 = Ymm(4), Ymm reg01 = Ymm(5), Ymm reg02 = Ymm(6), + Ymm reg03 = Ymm(7), Ymm reg04 = Ymm(8), Ymm reg05 = Ymm(9), + Ymm reg06 = Ymm(10), Ymm reg07 = Ymm(11), Ymm reg08 = Ymm(12), + Ymm reg09 = Ymm(13), Ymm reg10 = Ymm(14), Ymm reg11 = Ymm(15), + Ymm reg12 = Ymm(4), Ymm reg13 = Ymm(5), Ymm reg14 = Ymm(6), + Ymm reg15 = Ymm(7), Ymm reg16 = Ymm(8), Ymm reg17 = Ymm(9), + Ymm reg18 = Ymm(10), Ymm reg19 = Ymm(11), Ymm reg20 = Ymm(12), + Ymm reg21 = Ymm(13), Ymm reg22 = Ymm(14), Ymm reg23 = Ymm(15)) { + if (!isDirect) { + lea(AO1, ptr[rsp + 256 + OFFSET * SIZE]); + } else { + mov(AO1, A); + } + + if (isCopy) { + lea(LDA4, ptr[rsp + 256 + OFFSET * SIZE]); + } else { + lea(LDA4, ptr[LDA * 8 + (8 - 1 - OFFSET) * SIZE]); + } + + if (isTransB) { + lea(BO2, ptr[LDB * 4 + (8 - 1 - OFFSET) * SIZE]); + lea(BO2, ptr[BO2 + LDB * 2]); + } + + if (!isDirect) { + if (isLoad1Unmasked) { + vmovups(ymm0, + ptr[AO1 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE]); + } else { + vmaskmovps(ymm0, VMASK, + ptr[AO1 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE]); + } + if (unroll_m >= 16) { + if (isLoad2Unmasked) { + vmovups(ymm1, ptr[AO1 + + (unroll_m * 0 + 1 * 8 - OFFSET) + * SIZE]); + } else { + vmaskmovps(ymm1, VMASK, + ptr[AO1 + + (unroll_m * 0 + 1 * 8 - OFFSET) + * SIZE]); + } + } + } + + for (int i = 4; i < 10; i++) { + vxorps(Ymm(i), Ymm(i), Ymm(i)); + vxorps(Ymm(i + 6), Ymm(i + 6), Ymm(i + 6)); + } + + mov(LL, K); + sar(LL, 3); + + Label kernel12, kernel13, kernel14, kernel15; + Label kernel16, kernel17, kernel18; + + sub(LL, SECOND_FETCH); + jle(kernel13, T_NEAR); + align(16); + + L(kernel12); + innerkernel8(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04, + reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12, + reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20, + reg21, reg22, reg23); + jg(kernel12, T_NEAR); + align(16); + + L(kernel13); + prefetcht0(ptr[CO1 + (unroll_m - 1) * SIZE]); + if (unroll_n >= 2) + prefetcht0(ptr[CO1 + LDC + (unroll_m - 1) * SIZE]); + if (unroll_n >= 3) + prefetcht0(ptr[CO1 + LDC * 2 + (unroll_m - 1) * SIZE]); + if (unroll_n >= 4) + prefetcht0(ptr[CO2 + (unroll_m - 1) * SIZE]); + if (unroll_n >= 5) + prefetcht0(ptr[CO2 + LDC + (unroll_m - 1) * SIZE]); + if (unroll_n >= 6) + prefetcht0(ptr[CO2 + LDC * 2 + (unroll_m - 1) * SIZE]); + + add(LL, SECOND_FETCH); + jle(kernel15, T_NEAR); + align(16); + + L(kernel14); + innerkernel8(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04, + reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12, + reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20, + reg21, reg22, reg23); + jg(kernel14, T_NEAR); + align(16); + + L(kernel15); + test(K, 4); + jle(kernel16, T_NEAR); + innerkernel4(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04, + reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12, + reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20, + reg21, reg22, reg23); + + L(kernel16); + test(K, 2); + jle(kernel17, T_NEAR); + innerkernel2(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04, + reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12, + reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20, + reg21, reg22, reg23); + align(16); + + L(kernel17); + if (unroll_m == 16) { + if (unroll_n <= 3) { + vaddps(reg00, reg00, reg12); + vaddps(reg01, reg01, reg13); + vaddps(reg02, reg02, reg14); + vaddps(reg06, reg06, reg18); + vaddps(reg07, reg07, reg19); + vaddps(reg08, reg08, reg20); + } + } + + if (unroll_m <= 8) { + vaddps(reg00, reg00, reg12); + vaddps(reg01, reg01, reg13); + vaddps(reg02, reg02, reg14); + vaddps(reg03, reg03, reg15); + vaddps(reg04, reg04, reg16); + vaddps(reg05, reg05, reg17); + } + + test(K, 1); + jle(kernel18, T_NEAR); + innerkernel1(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04, + reg05, reg06, reg07, reg08, reg09, reg10, reg11); + align(16); + + L(kernel18); + vbroadcastss(VALPHA, ALPHA); + + if (isBetaN) { + vbroadcastss(VBETA, BETA); + } + + // Write back the results; all beta and bias cases need to be + // handled + switch (unroll_n) { + case 1: mov(rax, LDC); break; + case 2: lea(rax, ptr[LDC * 2]); break; + case 3: lea(rax, ptr[LDC + LDC * 2]); break; + case 4: lea(rax, ptr[LDC + LDC * 4]); break; + case 5: + lea(rax, ptr[LDC * 4]); + add(rax, LDC); + break; + case 6: + lea(rax, ptr[LDC + LDC * 2]); + add(rax, rax); + break; + } + + if (hasBias) { + mov(BIAS1, BIAS); + if (isLoad1Unmasked) { + vmovups(VBIAS1, ptr[BIAS1 + 0 * SIZE]); + } else { + vmaskmovps(VBIAS1, VMASK, ptr[BIAS1 + 0 * SIZE]); + } + } + + for (int i = 0; i < unroll_n; i++) { + vmulps(Ymm(i + 4), Ymm(i + 4), VALPHA); + if (!isBeta0) { + if (isLoad1Unmasked) { + switch (i) { + case 0: vmovups(ymm0, ptr[CO1 + 0 * SIZE]); break; + case 1: vmovups(ymm0, ptr[CO1 + LDC + 0 * SIZE]); break; + case 2: + vmovups(ymm0, ptr[CO1 + LDC * 2 + 0 * SIZE]); + break; + case 3: vmovups(ymm0, ptr[CO2 + 0 * SIZE]); break; + case 4: vmovups(ymm0, ptr[CO2 + LDC + 0 * SIZE]); break; + case 5: + vmovups(ymm0, ptr[CO2 + LDC * 2 + 0 * SIZE]); + break; + } + } else { + switch (i) { + case 0: + vmaskmovps(ymm0, VMASK, ptr[CO1 + 0 * SIZE]); + break; + case 1: + vmaskmovps(ymm0, VMASK, ptr[CO1 + LDC + 0 * SIZE]); + break; + case 2: + vmaskmovps( + ymm0, VMASK, ptr[CO1 + LDC * 2 + 0 * SIZE]); + break; + case 3: + vmaskmovps(ymm0, VMASK, ptr[CO2 + 0 * SIZE]); + break; + case 4: + vmaskmovps(ymm0, VMASK, ptr[CO2 + LDC + 0 * SIZE]); + break; + case 5: + vmaskmovps( + ymm0, VMASK, ptr[CO2 + LDC * 2 + 0 * SIZE]); + break; + } + } + + if (!isBetaN) { + vaddps(Ymm(i + 4), ymm0, Ymm(i + 4)); + } else { + fma(useFma, VBETA, ymm0, Ymm(i + 4), true); + } + } + if (hasBias) { + vaddps(Ymm(i + 4), VBIAS1, Ymm(i + 4)); + } + if (isLoad1Unmasked) { + switch (i) { + case 0: vmovups(ptr[CO1 + 0 * SIZE], Ymm(i + 4)); break; + case 1: + vmovups(ptr[CO1 + LDC + 0 * SIZE], Ymm(i + 4)); + break; + case 2: + vmovups(ptr[CO1 + LDC * 2 + 0 * SIZE], Ymm(i + 4)); + break; + case 3: vmovups(ptr[CO2 + 0 * SIZE], Ymm(i + 4)); break; + case 4: + vmovups(ptr[CO2 + LDC + 0 * SIZE], Ymm(i + 4)); + break; + case 5: + vmovups(ptr[CO2 + LDC * 2 + 0 * SIZE], Ymm(i + 4)); + break; + } + } else { + switch (i) { + case 0: + vmaskmovps(ptr[CO1 + 0 * SIZE], VMASK, Ymm(i + 4)); + break; + case 1: + vmaskmovps( + ptr[CO1 + LDC + 0 * SIZE], VMASK, Ymm(i + 4)); + break; + case 2: + vmaskmovps(ptr[CO1 + LDC * 2 + 0 * SIZE], VMASK, + Ymm(i + 4)); + break; + case 3: + vmaskmovps(ptr[CO2 + 0 * SIZE], VMASK, Ymm(i + 4)); + break; + case 4: + vmaskmovps( + ptr[CO2 + LDC + 0 * SIZE], VMASK, Ymm(i + 4)); + break; + case 5: + vmaskmovps(ptr[CO2 + LDC * 2 + 0 * SIZE], VMASK, + Ymm(i + 4)); + break; + } + } + + if (unroll_m >= 16) { + // Re-use ymm4 (VBIAS2) + if (i == 0) { + if (hasBias) { + if (isLoad1Unmasked) { + vmovups(VBIAS2, ptr[BIAS1 + 8 * SIZE]); + } else { + vmaskmovps( + VBIAS2, VMASK, ptr[BIAS1 + 8 * SIZE]); + } + } + } + vmulps(Ymm(i + 10), Ymm(i + 10), VALPHA); + if (!isBeta0) { + if (isLoad2Unmasked) { + switch (i) { + case 0: vmovups(ymm0, ptr[CO1 + 8 * SIZE]); break; + case 1: + vmovups(ymm0, ptr[CO1 + LDC + 8 * SIZE]); + break; + case 2: + vmovups(ymm0, ptr[CO1 + LDC * 2 + 8 * SIZE]); + break; + case 3: vmovups(ymm0, ptr[CO2 + 8 * SIZE]); break; + case 4: + vmovups(ymm0, ptr[CO2 + LDC + 8 * SIZE]); + break; + case 5: + vmovups(ymm0, ptr[CO2 + LDC * 2 + 8 * SIZE]); + break; + } + } else { + switch (i) { + case 0: + vmaskmovps(ymm0, VMASK, ptr[CO1 + 8 * SIZE]); + break; + case 1: + vmaskmovps( + ymm0, VMASK, ptr[CO1 + LDC + 8 * SIZE]); + break; + case 2: + vmaskmovps(ymm0, VMASK, + ptr[CO1 + LDC * 2 + 8 * SIZE]); + break; + case 3: + vmaskmovps(ymm0, VMASK, ptr[CO2 + 8 * SIZE]); + break; + case 4: + vmaskmovps( + ymm0, VMASK, ptr[CO2 + LDC + 8 * SIZE]); + break; + case 5: + vmaskmovps(ymm0, VMASK, + ptr[CO2 + LDC * 2 + 8 * SIZE]); + break; + } + } + if (!isBetaN) { + vaddps(Ymm(i + 10), ymm0, Ymm(i + 10)); + } else { + fma(useFma, VBETA, ymm0, Ymm(i + 10), true); + } + } + if (hasBias) { + vaddps(Ymm(i + 10), VBIAS2, Ymm(i + 10)); + } + if (isLoad2Unmasked) { + switch (i) { + case 0: + vmovups(ptr[CO1 + 8 * SIZE], Ymm(i + 10)); + break; + case 1: + vmovups(ptr[CO1 + LDC + 8 * SIZE], Ymm(i + 10)); + break; + case 2: + vmovups(ptr[CO1 + LDC * 2 + 8 * SIZE], Ymm(i + 10)); + break; + case 3: + vmovups(ptr[CO2 + 8 * SIZE], Ymm(i + 10)); + break; + case 4: + vmovups(ptr[CO2 + LDC + 8 * SIZE], Ymm(i + 10)); + break; + case 5: + vmovups(ptr[CO2 + LDC * 2 + 8 * SIZE], Ymm(i + 10)); + break; + } + } else { + switch (i) { + case 0: + vmaskmovps(ptr[CO1 + 8 * SIZE], VMASK, Ymm(i + 10)); + break; + case 1: + vmaskmovps(ptr[CO1 + LDC + 8 * SIZE], VMASK, + Ymm(i + 10)); + break; + case 2: + vmaskmovps(ptr[CO1 + LDC * 2 + 8 * SIZE], VMASK, + Ymm(i + 10)); + break; + case 3: + vmaskmovps(ptr[CO2 + 8 * SIZE], VMASK, Ymm(i + 10)); + break; + case 4: + vmaskmovps(ptr[CO2 + LDC + 8 * SIZE], VMASK, + Ymm(i + 10)); + break; + case 5: + vmaskmovps(ptr[CO2 + LDC * 2 + 8 * SIZE], VMASK, + Ymm(i + 10)); + break; + } + } + } + if (i == 2) + add(CO1, rax); + } + if (unroll_n >= 4) { + add(CO2, rax); + } + + // Compute next address of B + if (!isTransB) { + lea(rax, ptr[K * SIZE]); + switch (unroll_n) { + case 1: + add(BO1, LDB); + add(BO2, LDB); + break; + case 2: + lea(BO1, ptr[BO1 + LDB * 2]); + lea(BO2, ptr[BO2 + LDB * 2]); + break; + case 3: + lea(BO1, ptr[BO1 + LDB3]); + lea(BO2, ptr[BO2 + LDB3]); + break; + case 4: + lea(BO1, ptr[BO1 + LDB * 4]); + lea(BO2, ptr[BO2 + LDB * 4]); + break; + case 5: + lea(BO1, ptr[BO1 + LDB * 4]); + add(BO1, LDB); + lea(BO2, ptr[BO2 + LDB * 4]); + add(BO2, LDB); + break; + case 6: + lea(BO1, ptr[BO1 + LDB3 * 2]); + lea(BO2, ptr[BO2 + LDB3 * 2]); + break; + } + sub(BO1, rax); + sub(BO2, rax); + } else { + mov(rax, LDB); + imul(rax, K); + sub(BO1, rax); + add(BO1, unroll_n * SIZE); + } + }; + + auto kernel_16x6 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, true); + }; + + auto kernel_16x5 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, true); + }; + + auto kernel_16x4 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, true); + }; + + auto kernel_16x3 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy, + bool useFma = true) { + kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, Ymm(4), Ymm(5), Ymm(6), Ymm(7), + Ymm(8), Ymm(9), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14), + Ymm(15), Ymm(7), Ymm(8), Ymm(9), Ymm(7), Ymm(8), Ymm(9), + Ymm(13), Ymm(14), Ymm(15)); + }; + + auto kernel_16x2 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel_16x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, false); + }; + + auto kernel_16x1 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel_16x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, false); + }; + + auto kernel_8x6 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy, + bool useFma = true) { + kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, Ymm(4), Ymm(5), Ymm(6), Ymm(7), + Ymm(8), Ymm(9), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14), + Ymm(15), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14), + Ymm(15)); + }; + + auto kernel_8x5 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel_8x6(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy); + }; + + auto kernel_8x4 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel_8x6(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy); + }; + + auto kernel_8x3 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy, + bool useFma = true) { + kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, useFma, Ymm(4), Ymm(5), Ymm(6), Ymm(7), + Ymm(8), Ymm(9), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14), + Ymm(15), Ymm(7), Ymm(8), Ymm(9), Ymm(7), Ymm(8), Ymm(9), + Ymm(13), Ymm(14), Ymm(15)); + }; + + auto kernel_8x2 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel_8x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, false); + }; + + auto kernel_8x1 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked, + bool isLoad2Unmasked, bool isDirect, bool isCopy) { + kernel_8x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked, + isDirect, isCopy, false); + }; + + // High-level subroutine; does packing if needed, then splits C matrix. + // Operates on chunks of 16 rows, 6 columns at a time (handling tail + // cases appropriately). + // Masking is used for tail cases where M is not divisible by 8. + auto subloop = [&]( + int unroll_m, bool isLoad1Unmasked, bool isLoad2Unmasked) { + if (isTransA) { + do_pack(unroll_m, isLoad1Unmasked, isLoad2Unmasked); + } + + Label subloop11, subloop11mask; + Label subloop20, subloop21, subloop22, subloop23; + Label subloop24, subloop25; + Label subloop30, subloop31, subloop32, subloop33; + Label subloop34, subloop35; + Label subloop98, subloop98mask; + Label subloop99, subloop99mask; + + mov(CO1, C); + lea(CO2, ptr[CO1 + LDC * 2]); + add(CO2, LDC); + add(C, unroll_m * SIZE); + mov(BO1, B); + if (!isTransB) { + lea(BO2, qword[B + LDB3]); + } + + if (!isTransA) { + lea(AA, ptr[A + (unroll_m * 2 - 1 - OFFSET) * SIZE]); + cmp(M, UNROLL_M); + jg(subloop98, T_NEAR); + + mov(AA, ORIG_A); + lea(AA, ptr[AA + (unroll_m - 1 - OFFSET) * SIZE]); + L(subloop98); + } + + mov(LL, N); + mov(I, LL); + if (!isTransA) { + // If N is too small, skip copy operation + cmp(LL, UNROLL_N * 3); + jle(subloop30, T_NEAR); + + // If A is not aligned to cache line + cmp(FLAG, 0); + je(subloop30, T_NEAR); + } else { + cmp(LL, UNROLL_N); + jl(subloop20, T_NEAR); + } + align(16); + + if (!isTransA) { + if (unroll_m == 16) { + kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked, + isLoad2Unmasked, true, true); + } else { + kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked, + isLoad2Unmasked, true, true); + } + } else { + if (unroll_m == 16) { + kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked, + isLoad2Unmasked, false, false); + } else { + kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked, + isLoad2Unmasked, false, false); + } + } + + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jl(subloop20, T_NEAR); + align(16); + + L(subloop11); + if (unroll_m == 16) { + kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked, + isLoad2Unmasked, false, false); + } else { + kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked, isLoad2Unmasked, + false, false); + } + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jge(subloop11, T_NEAR); + align(16); + + L(subloop20); + cmp(I, 1); + jne(subloop21, T_NEAR); + if (unroll_m == 16) { + kernel_16x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked, + false, false); + } else { + kernel_8x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked, false, + false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop21); + cmp(I, 2); + jne(subloop22, T_NEAR); + if (unroll_m == 16) { + kernel_16x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked, + false, false); + } else { + kernel_8x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked, false, + false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop22); + cmp(I, 3); + jne(subloop23, T_NEAR); + if (unroll_m == 16) { + kernel_16x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked, + false, false); + } else { + kernel_8x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked, false, + false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop23); + cmp(I, 4); + jne(subloop24, T_NEAR); + if (unroll_m == 16) { + kernel_16x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked, + false, false); + } else { + kernel_8x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked, false, + false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop24); + cmp(I, 5); + jne(subloop99, T_NEAR); + if (unroll_m == 16) { + kernel_16x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked, + false, false); + } else { + kernel_8x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked, false, + false); + } + jmp(subloop99, T_NEAR); + align(16); + + if (!isTransA) { + L(subloop30); + cmp(I, UNROLL_N); + jl(subloop25, T_NEAR); + align(16); + + L(subloop31); + if (unroll_m == 16) { + kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked, + isLoad2Unmasked, true, false); + } else { + kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked, + isLoad2Unmasked, true, false); + } + sub(I, UNROLL_N); + cmp(I, UNROLL_N); + jge(subloop31, T_NEAR); + align(16); + + L(subloop25); + cmp(I, 1); + jne(subloop32, T_NEAR); + if (unroll_m == 16) { + kernel_16x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } else { + kernel_8x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop32); + cmp(I, 2); + jne(subloop33, T_NEAR); + if (unroll_m == 16) { + kernel_16x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } else { + kernel_8x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop33); + cmp(I, 3); + jne(subloop34, T_NEAR); + if (unroll_m == 16) { + kernel_16x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } else { + kernel_8x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop34); + cmp(I, 4); + jne(subloop35, T_NEAR); + if (unroll_m == 16) { + kernel_16x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } else { + kernel_8x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } + jmp(subloop99, T_NEAR); + align(16); + + L(subloop35); + cmp(I, 5); + jne(subloop99, T_NEAR); + if (unroll_m == 16) { + kernel_16x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } else { + kernel_8x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked, + true, false); + } + align(16); + } + + L(subloop99); + // Compute address for A + if (!isTransA) { + add(A, unroll_m * SIZE); + } else { + mov(rax, LDA); + imul(rax, rax, unroll_m); + add(A, rax); + } + + // Compute next address of BIAS + if (hasBias) { + add(BIAS, unroll_m * SIZE); + } + }; + + preamble(); + + Label buffer_in_ws, buffer_allocated; + + // Get the registers + mov(B, ARG_B); + mov(LDB, ARG_LDB); + mov(r15, ARG_BETA); + mov(r12, ARG_C); + if (hasBias) + mov(r10, ARG_BIAS); + mov(LDC, ARG_LDC); + mov(rbp, rsp); + + vmovss(xmm0, ptr[ARG_ALPHA]); + vmovss(xmm1, ptr[r15]); + +#if _WIN32 + mov(A, ARG_A); + mov(LDA, ARG_LDA); +#endif + + cmp(K, STACK_K_CAPACITY); + jg(buffer_in_ws, T_NEAR); + + // Create buffer and align to 4kB page + lea(rax, ptr[K * SIZE]); + sal(rax, 4); + add(rax, 256); + sub(rsp, rax); + and_(rsp, -PAGE_4K); + jmp(buffer_allocated, T_NEAR); + + L(buffer_in_ws); + mov(rsp, ARG_WS); + + L(buffer_allocated); + + mov(ORIG_SP, rbp); + mov(M, ARG_M); + mov(N, ARG_N); + mov(C, r12); + if (hasBias) + mov(BIAS, r10); + vmovss(ALPHA, xmm0); + vmovss(BETA, xmm1); + sub(A, -OFFSET * SIZE); + sub(B, -OFFSET * SIZE); + mov(ORIG_A, A); + sal(LDA, BASE_SHIFT); + sal(LDB, BASE_SHIFT); + sal(LDC, BASE_SHIFT); + lea(LDB3, ptr[LDB + LDB * 2]); + + for (int i = 0; i < 8; i++) { + mov(dword[rsp + 88 + i * 4], i); + } + + if (isTransA && is_avx2) { + movq(xmm0, LDA); + vpbroadcastq(ymm1, xmm0); + vinsertf128(ymm0, ymm0, xmm0, 1); + vpermilpd(ymm0, ymm0, 5); + vpaddq(ymm1, ymm1, ymm1); + vperm2f128(ymm1, ymm1, ymm1, 8); + vpaddq(ymm0, ymm0, ymm1); + vmovups(STRIDE, ymm0); + } + + // Check A alignment and leading dimension; take copy-based path as + // needed + mov(rax, LDA); + or_(rax, A); + and_(rax, 0x1f); + mov(FLAG, rax); + + Label main0, main1, main2, main3, main999; + + cmp(M, UNROLL_M); + jl(main0, T_NEAR); + align(16); + + L(main1); + subloop(UNROLL_M, true, true); + sub(M, UNROLL_M); + cmp(M, UNROLL_M); + jge(main1, T_NEAR); + align(16); + + L(main0); + cmp(M, 0); + jle(main999, T_NEAR); + + if (UNROLL_M > 8) { + cmp(M, 8); + jle(main2, T_NEAR); + + sub(M, 8); + vbroadcastss(VMASK, M); + vpcmpgtd(VMASK, VMASK, MASK); + + subloop(16, true, false); + jmp(main999, T_NEAR); + align(16); + + L(main2); + cmp(M, 8); + jne(main3, T_NEAR); + subloop(8, true, true); + jmp(main999, T_NEAR); + } + + align(16); + + L(main3); + vbroadcastss(VMASK, M); + if (is_avx2) { + vpcmpgtd(VMASK, VMASK, MASK); + } else { + auto xmask = Xmm(VMASK.getIdx()); + auto xmm_tmp = xmm4; + + vextractf128(xmm_tmp, VMASK, 1); + vpcmpgtd(xmask, xmask, MASK); + vpcmpgtd(xmm_tmp, xmm_tmp, dword[rsp + 88 + 4 * 4]); // MASK + 4 + vinsertf128(VMASK, VMASK, xmm_tmp, 1); + } + subloop(8, false, false); + align(16); + + L(main999); + // Restore original stack + mov(rsp, ORIG_SP); + + vzeroupper(); + postamble(); + + ker_ = this->getCode(); + } + + typedef void (*ker_t)(dim_t m, dim_t n, dim_t k, + const float *alpha, const float *a, dim_t lda, + const float *b, dim_t ldb, const float *beta, float *c, + dim_t ldc, const float *bias, float *ws); + + void operator()(dim_t m, dim_t n, dim_t k, + const float *alpha, const float *a, dim_t lda, + const float *b, dim_t ldb, const float *beta, float *c, + dim_t ldc, const float *bias, float *ws) const + { + ker_(m, n, k, alpha, a, lda, b, ldb, beta, c, ldc, bias, ws); + } + +private: + ker_t ker_; +}; + +const xbyak_gemm *get_xbyak_gemm( + bool isTransA, bool isTransB, float beta, bool hasBias) { + auto beta_idx = [](float beta) { + return (beta == 0.0) ? 0 : (beta == 1.0 ? 1 : 2); + }; + + // Kernel table [isTransA][isTransB][hasBias][beta (0, 1, other)] + static xbyak_gemm *kernel_table[2][2][2][3]; + static std::once_flag initialized; + std::call_once(initialized, [=]{ + for (bool isTransA: {false, true}) + for (bool isTransB: {false, true}) + for (bool hasBias: {false, true}) + for (float beta: {0.0f, 1.0f, 2.0f}) { + // nocopy sgemm with bias for beta != 0.0 is not supported + if (hasBias && beta != 0.0) + continue; + kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)] = + new xbyak_gemm(isTransA, isTransB, beta, hasBias); + } + }); + + return kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)]; +} + +void sgemm_nocopy_driver(const char *transa, + const char *transb, int m, int n, int k, const float *alpha, + const float *a, dim_t lda, const float *b, dim_t ldb, const float *beta, + float *c, dim_t ldc, const float *bias, float *ws) +{ + bool isTransA = (*transa == 'T' || *transa == 't'); + bool isTransB = (*transb == 'T' || *transb == 't'); + + int Bm, sizeM, Bn, sizeN, Bk, sizeK; + + int i, j; + + if ((m <= 0) || (n <= 0)) + return; + + if ((k <= 0) || (alpha[0] == 0.)) { + + if (beta[0] == 0.) { + for (j = 0; j < n; j++) + for (i = 0; i < m; i++) + c[i + j * ldc] = 0.0; + } else if (beta[0] != 1.) { + for (j = 0; j < n; j++) + for (i = 0; i < m; i++) + c[i + j * ldc] *= beta[0]; + } + + return; + } + + assert(IMPLICATION(bias != nullptr, *beta == 0.0)); + + // XXX: this happens on every thread... + bool hasBias = (bias != nullptr); + auto ker_bn = get_xbyak_gemm(isTransA, isTransB, *beta, hasBias); + auto ker_b1 = get_xbyak_gemm(isTransA, isTransB, 1.0, false); + auto ker_b0 = get_xbyak_gemm(isTransA, isTransB, 0.0, false); + assert(ker_bn && ker_b1 && ker_b0); + + int BM = 4032; + int BN = isTransA ? 96 : 48; + int BK = isTransB ? 96 : 256; + const float *curA, *curB, *curBias = nullptr; + float *curC; + + for (Bk = 0; Bk < k; Bk += sizeK) { + sizeK = k - Bk; + if (sizeK >= BK * 2) + sizeK = BK; + else { + if (sizeK > BK) + sizeK = (sizeK + 1) / 2; + } + + for (Bm = 0; Bm < m; Bm += sizeM) { + sizeM = m - Bm; + if (sizeM >= BM * 2) + sizeM = BM; + else { + if (sizeM > BM + BM / 2) + sizeM = (sizeM + 1) / 2; + } + + for (Bn = 0; Bn < n; Bn += sizeN) { + sizeN = n - Bn; + if (sizeN >= BN * 2) + sizeN = BN; + else { + if (sizeN > BN + BN / 2) + sizeN = (sizeN + 1) / 2; + } + + if (!isTransA) { + curA = a + Bm + Bk * lda; + } else { + curA = a + Bk + Bm * lda; + } + if (!isTransB) { + curB = b + Bk + Bn * ldb; + } else { + curB = b + Bn + Bk * ldb; + } + curC = c + Bm + (size_t)Bn * ldc; + if (bias != nullptr) { + if (Bk == 0) { + curBias = bias + Bm; + } else { + curBias = nullptr; + } + } + if (Bk == 0) { + if (*beta == 0.0 && bias == nullptr) + (*ker_b0)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK, + alpha, curA, lda, curB, ldb, beta, curC, ldc, + curBias, ws); + else + (*ker_bn)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK, + alpha, curA, lda, curB, ldb, beta, curC, ldc, + curBias, ws); + } else { + (*ker_b1)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK, + alpha, curA, lda, curB, ldb, beta, curC, ldc, + curBias, ws); + } + } + } + } +} + +} + +mkldnn_status_t jit_avx_gemm_f32( + const char *transa, const char *transb, + const int *p_m, const int *p_n, const int *p_k, const float *p_alpha, + const float *A, const int *p_lda, const float *B, const int *p_ldb, + const float *p_beta, float *C, const int *p_ldc, const float *bias) +{ + using namespace mkldnn::impl::utils; + using namespace avx_gemm_f32; + using namespace gemm_utils; + + if (*p_beta != 0 && bias) + return ref_gemm(transa, transb, p_m, p_n, p_k, + p_alpha, A, p_lda, B, p_lda, p_beta, C, p_ldc, bias); + + int nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads(); + + int m = *p_m; + int n = *p_n; + int k = *p_k; + dim_t lda = *p_lda; + dim_t ldb = *p_ldb; + dim_t ldc = *p_ldc; + float beta = *p_beta; + int MB, NB, KB; + + int nthr_m, nthr_n, nthr_k, nthr_mn; + + // Determine threading partitioning + calc_nthr_nocopy_avx( + m, n, k, nthr, &nthr_m, &nthr_n, &nthr_k, &MB, &NB, &KB); + assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_k == 1)); + + // May not happen, but just in case + if (nthr < nthr_m * nthr_n * nthr_k) + nthr = nthr_m * nthr_n * nthr_k; + + nthr_mn = nthr_m * nthr_n; + + unsigned char * ompstatus_ = nullptr; + unsigned char volatile *ompstatus = nullptr; + + float *c_buffers = nullptr; + float *ws_buffers = nullptr; + + if (nthr_k > 1) { + ompstatus_ = (unsigned char *) malloc( + nthr * CACHE_LINE_SIZE, + CACHE_LINE_SIZE); + ompstatus = (unsigned char volatile *) ompstatus_; + assert(ompstatus); + + for (int i = 0; i < nthr; i++) + ompstatus[i * CACHE_LINE_SIZE] = 0; + + c_buffers = (float *)malloc(nthr_m * nthr_n * (nthr_k - 1) * MB * NB + * sizeof(float), PAGE_4K); + } + + const size_t ws_elems_per_thr = (size_t)k * 16 + 64; + const size_t ws_size_per_thr + = rnd_up(ws_elems_per_thr * sizeof(float), PAGE_4K); + if (k > STACK_K_CAPACITY) { + ws_buffers = (float *)malloc(nthr * ws_size_per_thr, PAGE_4K); + } + + parallel_nd(nthr, [&](const int ithr) { + int ithr_m, ithr_n, ithr_k, ithr_mn; + int m_from, m_to, myM; + int n_from, n_to, myN; + int k_from, k_to, myK; + int cbase, ibase; + const float *myA, *myB, *myBias = nullptr; + float *myC = C, myBeta; + float *ws = ws_buffers ? + ws_buffers + ithr * ws_size_per_thr / sizeof(float) : 0; + dim_t ld = ldc; + + int sum_later = (mkldnn_get_num_threads() < nthr_m * nthr_n * nthr_k); + + if (ithr < nthr_m * nthr_n * nthr_k) { + + ithr_mn = ithr % nthr_mn; + ithr_m = ithr_mn % nthr_m; + ithr_n = ithr_mn / nthr_m; + ithr_k = ithr / nthr_mn; + + /* swap ithr_k for performance improvement */ + if (ithr_k == 0) + ithr_k = nthr_k - 1; + else if (ithr_k == nthr_k - 1) + ithr_k = 0; + + m_from = MB * (ithr_m); + m_to = MB * (ithr_m + 1); + if (m_to > m) + m_to = m; + myM = m_to - m_from; + + n_from = NB * (ithr_n); + n_to = NB * (ithr_n + 1); + if (n_to > n) + n_to = n; + myN = n_to - n_from; + + k_from = KB * (ithr_k); + k_to = KB * (ithr_k + 1); + if (k_to > k) + k_to = k; + myK = k_to - k_from; + + cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1); + ibase = (ithr_m + nthr_m * ithr_n) * nthr_k; + + if ((myM > 0) && (myN > 0)) { + + if (*transa == 'N' || *transa == 'n') { + myA = &(A[m_from + k_from * lda]); + } else { + myA = &(A[k_from + m_from * lda]); + } + if (*transb == 'N' || *transb == 'n') { + myB = &(B[k_from + n_from * ldb]); + } else { + myB = &(B[n_from + k_from * ldb]); + } + if (ithr_k == 0) { + myC = &(C[m_from + n_from * ldc]); + myBeta = beta; + ld = ldc; + if (bias) + myBias = &(bias[m_from]); + } else { + myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1); + myBeta = 0.0; + ld = MB; + myBias = nullptr; + } + + sgemm_nocopy_driver(transa, transb, myM, myN, myK, p_alpha, myA, + lda, myB, ldb, &myBeta, myC, ld, myBias, ws); + + if (nthr_k > 1 && !sum_later) + ompstatus[(ibase + ithr_k) * CACHE_LINE_SIZE] = 1; + } + + if (nthr_k > 1 && !sum_later) { + + // sum matrices partitioned along K dimension + int n1, n2; + + partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2); + + if (ithr_k > 0) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1) + + (dim_t)n1 * MB; + /* need to wait until main thread finishes */ + while (ompstatus[ibase * CACHE_LINE_SIZE] != 1) { + }; + + /* my cache is hot */ + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + + for (int ik = 1; ik < nthr_k; ++ik) { + if (ik != ithr_k) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1) + + (dim_t)n1 * MB; + + while (ompstatus[(ibase + ik) * CACHE_LINE_SIZE] != 1) { + }; + + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + } + } + } + }); + + // handle C summation later + if (nthr_k > 1 && ompstatus[0] == 0) { + + parallel_nd(nthr, [&](const int ithr) { + int ithr_m, ithr_n, ithr_k, ithr_mn; + int m_from, m_to, myM; + int n_from, n_to, myN; + int cbase; + float *myC = C; + + if (ithr < nthr_m * nthr_n * nthr_k) { + + ithr_mn = ithr % nthr_mn; + ithr_m = ithr_mn % nthr_m; + ithr_n = ithr_mn / nthr_m; + ithr_k = ithr / nthr_mn; + + /* swap ithr_k for performance improvement */ + if (ithr_k == 0) + ithr_k = nthr_k - 1; + else if (ithr_k == nthr_k - 1) + ithr_k = 0; + + m_from = MB * (ithr_m); + m_to = MB * (ithr_m + 1); + if (m_to > m) + m_to = m; + myM = m_to - m_from; + + n_from = NB * (ithr_n); + n_to = NB * (ithr_n + 1); + if (n_to > n) + n_to = n; + myN = n_to - n_from; + + cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1); + + if (nthr_k > 1) { + // sum matrices partitioned along K dimension + int n1, n2; + + partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2); + + if (ithr_k > 0) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1) + + (dim_t)n1 * MB; + + /* my cache is hot */ + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + + for (int ik = 1; ik < nthr_k; ++ik) { + if (ik != ithr_k) { + + myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1) + + (dim_t)n1 * MB; + + sum_two_matrices(myM, n2, myC, MB, + &C[m_from + (n_from + n1) * ldc], ldc); + } + } + } + } + }); + } + + + free(c_buffers); + free(ompstatus_); + free(ws_buffers); + + return mkldnn_success; +} + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp new file mode 100644 index 0000000000..aabf520a3c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX_GEMM_F32_HPP +#define JIT_AVX_GEMM_F32_HPP + +#include "mkldnn_types.h" + +namespace mkldnn { +namespace impl { +namespace cpu { + +mkldnn_status_t jit_avx_gemm_f32( + const char *transa, const char *transb, const int *M, + const int *N, const int *K, const float *alpha, const float *A, + const int *lda, const float *B, const int *ldb, const float *beta, + float *C, const int *ldc, const float *bias = nullptr); + + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp new file mode 100644 index 0000000000..5147885a89 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp @@ -0,0 +1,346 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_types.h" + +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "utils.hpp" + +#include "jit_generator.hpp" + +#include "gemm_utils_f32.hpp" +#include "ref_gemm_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace gemm_utils; + +namespace { + +template +void copy_A( + bool isTransA, int K, const data_t *A, const dim_t lda, data_t *ws) { + for (int k = 0; k < K; k++) { + PRAGMA_OMP_SIMD() + for (int i = 0; i < unroll_factor::m; i++) { + ws[i] = isTransA ? A[i * lda + k] : A[i + k * lda]; + } + ws += unroll_factor::m; + } +} + +template +void kernel_mxn(int K, const data_t *A, const dim_t lda, + const data_t *B, const dim_t ldb, data_t *C, const dim_t ldc, + const data_t alpha, const data_t beta) { + data_t c[unroll_factor::m * unroll_factor::n] = + { static_cast(0.) }; + for (int k = 0; k < K; k++) { + for (int j = 0; j < unroll_factor::n; j++) { + data_t b = isTransB ? B[j + k * ldb] : B[k + j * ldb]; + PRAGMA_OMP_SIMD() + for (int i = 0; i < unroll_factor::m; i++) { + data_t a = isTransA ? A[i * lda + k] : A[i + lda * k]; + c[i + unroll_factor::m * j] += a * b; + } + } + } + for (int j = 0; j < unroll_factor::n; j++) { + PRAGMA_OMP_SIMD() + for (int i = 0; i < unroll_factor::m; i++) { + C[i + j * ldc] = (beta == static_cast(0.)) + ? alpha * c[i + unroll_factor::m * j] + : alpha * c[i + unroll_factor::m * j] + + beta * C[i + j * ldc]; + } + } +} + +template +void block_ker(const int M, const int N, const int K, + const data_t *A, const dim_t lda, const data_t *B, const dim_t ldb, + data_t *C, const dim_t ldc, const data_t alpha, const data_t beta, + data_t *ws, bool do_copy) { + int Nu = rnd_dn(N, unroll_factor::n); + int Mu = rnd_dn(M, unroll_factor::m); + for (int i = 0; i < Mu; i += unroll_factor::m) { + for (int j = 0; j < Nu; j += unroll_factor::n) { + const data_t *b = isTransB ? &B[j] : &B[j * ldb]; + const data_t *a = isTransA ? &A[i * lda] : &A[i]; + if (do_copy) { + if (j == 0) { + copy_A(isTransA, K, a, lda, ws); + } + kernel_mxn( + K, ws, unroll_factor::m, b, ldb, + &C[i + j * ldc], ldc, alpha, beta); + } else { + kernel_mxn( + K, a, lda, b, ldb, &C[i + j * ldc], ldc, alpha, beta); + } + } + } + // tail processing + for (int i = 0; i < M; i++) { + for (int j = Nu; j < N; j++) { + data_t c = beta == static_cast(0.) + ? static_cast(0.) + : beta * C[i + j * ldc]; + for (int p = 0; p < K; p++) { + data_t b = isTransB ? B[j + p * ldb] : B[p + j * ldb]; + data_t a = isTransA ? A[p + i * lda] : A[i + p * lda]; + c += alpha * a * b; + } + C[i + j * ldc] = c; + } + } + for (int i = Mu; i < M; i++) { + for (int j = 0; j < Nu; j++) { + data_t c = beta == static_cast(0.) + ? static_cast(0.) + : beta * C[i + j * ldc]; + for (int p = 0; p < K; p++) { + data_t b = isTransB ? B[j + p * ldb] : B[p + j * ldb]; + data_t a = isTransA ? A[p + i * lda] : A[i + p * lda]; + c += alpha * a * b; + } + C[i + j * ldc] = c; + } + } +} + +template +void gemm_ithr(const int M, const int N, const int K, const data_t alpha, + const data_t *A, const dim_t lda, const data_t *B, const dim_t ldb, + const data_t beta, data_t *C, const dim_t ldc, bool do_copy, + data_t *ws) { + constexpr int BM = gemm_traits::BM; + constexpr int BN = gemm_traits::BN; + constexpr int BK = gemm_traits::BK; + + const data_t *curA; + const data_t *curB; + data_t *curC; + + if ((M <= 0) || (N <= 0)) + return; + + if ((K <= 0) || (alpha == static_cast(0))) { + dim_t MN = N * M; + if (beta == static_cast(0.)) { + for (dim_t j = 0; j < MN; j++) + C[j] = static_cast(0.); + } else if (beta != static_cast(1.)) { + for (dim_t j = 0; j < MN; j++) + C[j] *= beta; + } + return; + } + + for (int Bk = 0; Bk < K; Bk += BK) { + int kb = nstl::min(K - Bk, BK); + for (int Bm = 0; Bm < M; Bm += BM) { + int mb = nstl::min(M - Bm, BM); + for (int Bn = 0; Bn < N; Bn += BN) { + int nb = nstl::min(N - Bn, BN); + curA = isTransA ? A + Bk + Bm * lda : A + Bm + Bk * lda; + curB = isTransB ? B + Bn + Bk * ldb : B + Bk + Bn * ldb; + curC = C + Bm + Bn * ldc; + if (Bk == 0) { + block_ker(mb, nb, kb, curA, lda, + curB, ldb, curC, ldc, alpha, beta, ws, do_copy); + } else { + block_ker(mb, nb, kb, curA, lda, + curB, ldb, curC, ldc, alpha, static_cast(1.0), + ws, do_copy); + } + } + } + } +} + +} + +template +mkldnn_status_t ref_gemm( + const char *transa_, const char *transb_, const int *M_, + const int *N_, const int *K_, const data_t *alpha_, const data_t *A, + const int *lda_, const data_t *B, const int *ldb_, const data_t *beta_, + data_t *C, const int *ldc_, const data_t *bias) { + + bool isTransA = (*transa_ == 'T' || *transa_ == 't'); + bool isTransB = (*transb_ == 'T' || *transb_ == 't'); + const int M = *M_, N = *N_, K = *K_; + const dim_t lda = *lda_, ldb = *ldb_, ldc = *ldc_; + const data_t alpha = *alpha_, beta = *beta_; + + int max_nthr = mkldnn_in_parallel() ? 1 : mkldnn_get_max_threads(); + int nthr_m, nthr_n, nthr_k; + int MB, NB, KB; + // thread balancing over M, N, K & size of blocking dimensions + calc_nthr_nocopy_avx( + M, N, K, max_nthr, &nthr_m, &nthr_n, &nthr_k, &MB, &NB, &KB); + assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_k == 1)); + + data_t *c_buffers = nullptr; + data_t *ws_buffers = nullptr; + if (nthr_k > 1) { + c_buffers = (data_t *)malloc(nthr_m * nthr_n * (nthr_k - 1) * MB * NB + * sizeof(data_t), PAGE_4K); + if (!c_buffers) { + nthr_k = 1; + KB = K; + } + } + + bool do_copy = (NB / unroll_factor::n > 3); + const int nthr_mn = nthr_m * nthr_n; + const int nthr = nthr_mn * nthr_k; + const size_t ws_elems_per_thr = K * unroll_factor::m; + const size_t ws_size_per_thr + = rnd_up(ws_elems_per_thr * sizeof(data_t), PAGE_4K); + if (do_copy) { + ws_buffers = (data_t*)malloc(nthr * ws_size_per_thr, PAGE_4K); + if (!ws_buffers) + do_copy = false; + } + + auto get_thr_block = [&](int &from, int &to, int &myN, int NB, int N, + int ithr) { + from = NB * (ithr); + to = NB * (ithr + 1); + if (to > N) + to = N; + myN = to - from; + }; + + parallel_nd(nthr, [&](const int ithr) { + int ithr_mn = ithr % nthr_mn; + int ithr_m = ithr_mn % nthr_m; + int ithr_n = ithr_mn / nthr_m; + int ithr_k = ithr / nthr_mn; + + int cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1); + + data_t *ws = do_copy + ? ws_buffers + ithr * ws_size_per_thr / sizeof(data_t) + : nullptr; + + int m_from = 0, m_to = 0, myM = 0, n_from = 0, n_to = 0, myN = 0, + k_from = 0, k_to = 0, myK = 0; + + get_thr_block(m_from, m_to, myM, MB, M, ithr_m); + get_thr_block(n_from, n_to, myN, NB, N, ithr_n); + get_thr_block(k_from, k_to, myK, KB, K, ithr_k); + + if (myM > 0 && myN > 0) { + data_t myBeta, *myC; + dim_t ld; + if (ithr_k == 0) { + myC = &(C[m_from + n_from * ldc]); + myBeta = beta; + ld = ldc; + } else { + myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1); + myBeta = 0.0f; + ld = MB; + } + const data_t *myA = isTransA + ? &(A[k_from + m_from * lda]) + : &(A[m_from + k_from * lda]); + const data_t *myB = isTransB + ? &(B[n_from + k_from * ldb]) + : &(B[k_from + n_from * ldb]); + + if (!isTransA) { + if (!isTransB) { + gemm_ithr(myM, myN, myK, alpha, myA, + lda, myB, ldb, myBeta, myC, ld, do_copy, ws); + } else { + gemm_ithr(myM, myN, myK, alpha, myA, + lda, myB, ldb, myBeta, myC, ld, do_copy, ws); + } + } else { + if (!isTransB) { + gemm_ithr(myM, myN, myK, alpha, myA, + lda, myB, ldb, myBeta, myC, ld, do_copy, ws); + } else { + gemm_ithr(myM, myN, myK, alpha, myA, + lda, myB, ldb, myBeta, myC, ld, do_copy, ws); + } + } + } + }); + + if (nthr_k > 1) { + parallel_nd(nthr, [&](const int ithr) { + int ithr_mn = ithr % nthr_mn; + int ithr_m = ithr_mn % nthr_m; + int ithr_k = ithr / nthr_mn; + int ithr_n = ithr_mn / nthr_m; + + int n_from = 0, n_to = 0, myN = 0; + int m_from = 0, m_to = 0, myM = 0; + + int cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1); + + get_thr_block(n_from, n_to, myN, NB, N, ithr_n); + get_thr_block(m_from, m_to, myM, MB, M, ithr_m); + + // sum matrices partitioned along K dimension + int offset = 0, block = 0; + gemm_utils::partition_unit_diff(ithr_k, nthr_k, myN, &offset, + &block); + for (int ik = 1; ik < nthr_k; ++ik) { + data_t *myC = c_buffers + + MB * ((dim_t)NB * (cbase + ik - 1) + offset); + + gemm_utils::sum_two_matrices(myM, block, myC, MB, + &C[m_from + (n_from + offset) * ldc], ldc); + } + }); + } + + if (bias) { + parallel_nd(N, M, [&](int i, int j) { + C[i*ldc + j] += bias[j]; + }); + } + + free(ws_buffers); + free(c_buffers); + + return mkldnn_success; +} + +template mkldnn_status_t ref_gemm( + const char *transa_, const char *transb_, + const int *M_, const int *N_, const int *K_, const float *alpha_, + const float *A, const int *lda_, const float *B, const int *ldb_, + const float *beta_, float *C, const int *ldc_, const float *bias); + +template mkldnn_status_t ref_gemm( + const char *transa_, const char *transb_, + const int *M_, const int *N_, const int *K_, const double *alpha_, + const double *A, const int *lda_, const double *B, const int *ldb_, + const double *beta_, double *C, const int *ldc_, const double *bias); +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp new file mode 100644 index 0000000000..7c90ba6277 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp @@ -0,0 +1,36 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef REF_GEMM_F32_HPP +#define REF_GEMM_F32_HPP + +#include "mkldnn_types.h" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +mkldnn_status_t ref_gemm(const char *transa, const char *transb, const int *M, + const int *N, const int *K, const data_t *alpha, const data_t *A, + const int *lda, const data_t *B, const int *ldb, const data_t *beta, + data_t *C, const int *ldc, const data_t *bias); + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp new file mode 100644 index 0000000000..3dbe07d743 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp @@ -0,0 +1,280 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn.h" + +#include "mkldnn_traits.hpp" +#include "nstl.hpp" + +#include "jit_generator.hpp" + +#include "gemm.hpp" + +#include "f32/jit_avx512_common_gemm_f32.hpp" +#include "f32/jit_avx_gemm_f32.hpp" +#include "f32/ref_gemm_f32.hpp" + +#include "s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp" +#include "s8x8s32/simple_gemm_s8s8s32.hpp" +#include "s8x8s32/ref_gemm_s8x8s32.hpp" + +#include "os_blas.hpp" + +/* USE_MKL USE_CBLAS effect + * ------- --------- ------ + * yes yes use Intel(R) MKL CBLAS + * yes no use jit + * no yes system-dependent CBLAS + * no no use jit + */ + +namespace mkldnn { +namespace impl { +namespace cpu { + +mkldnn_status_t check_gemm_input(const char *transa, const char *transb, + const int *M, const int *N, const int *K, const int *lda, + const int *ldb, const int *ldc, const float *alpha, const float *beta, + const bool with_bias) { + if (utils::any_null(transa, transb, M, N, K, lda, ldb, ldc, alpha, beta)) + return mkldnn_invalid_arguments; + if (with_bias && *beta != 0) + return mkldnn_unimplemented; + bool consistency = true + && utils::one_of(*transa, 'T', 't', 'N', 'n') + && utils::one_of(*transb, 'T', 't', 'N', 'n') + && *M >= 0 + && *N >= 0 + && *K >= 0; + + if (!consistency) + return mkldnn_invalid_arguments; + bool isTransA = utils::one_of(*transa, 'T', 't'); + bool isTransB = utils::one_of(*transb, 'T', 't'); + int nrowA = isTransA ? *K : *M; + int nrowB = isTransB ? *N : *K; + consistency = true + && *lda >= nstl::max(1, nrowA) + && *ldb >= nstl::max(1, nrowB) + && *ldc >= nstl::max(1, *M); + if (!consistency) + return mkldnn_invalid_arguments; + + return mkldnn_success; +} + +mkldnn_status_t check_gemm_x8x8x32_input(const char *offsetc, + const char *transa, const char *transb, const int *M, const int *N, + const int *K, const int *lda, const int *ldb, const int *ldc, + const float *alpha, const float *beta, const bool with_bias) { + if (offsetc == nullptr) + return mkldnn_invalid_arguments; + if (!utils::one_of(*offsetc, 'F', 'f', 'C', 'c', 'R', 'r')) + return mkldnn_invalid_arguments; + + return check_gemm_input(transa, transb, M, N, K, lda, ldb, ldc, alpha, + beta, with_bias); +} + +mkldnn_status_t extended_sgemm(const char *transa, const char *transb, + const int *M, const int *N, const int *K, const float *alpha, + const float *A, const int *lda, const float *B, const int *ldb, + const float *beta, float *C, const int *ldc, + const float *bias, const bool force_jit_gemm) { + mkldnn_status_t status = check_gemm_input(transa, transb, M, N, K, + lda, ldb, ldc, alpha, beta, bias != nullptr); + if (status != mkldnn_success) + return status; + +#ifdef USE_CBLAS + if (!force_jit_gemm) { + bool trA = *transa == 't' || *transa == 'T'; + bool trB = *transb == 't' || *transb == 'T'; + CBLAS_TRANSPOSE Cblas_trA = trA ? CblasTrans : CblasNoTrans; + CBLAS_TRANSPOSE Cblas_trB = trB ? CblasTrans : CblasNoTrans; + cblas_sgemm(CblasColMajor, Cblas_trA, Cblas_trB, + *M, *N, *K, *alpha, A, *lda, B, *ldb, *beta, C, *ldc); + + if (bias) { + // Add bias if necessary (bias is applied to columns of C) + cblas_int incx = 1, incy = 1; + parallel_nd(*N, [&](int n) { + ptrdiff_t offset = (ptrdiff_t)n * (*ldc); + cblas_saxpy(*M, 1.0, bias, incx, C + offset, incy); + }); + } + return mkldnn_success; + } +#endif + + if (mayiuse(avx512_common)) + return jit_avx512_common_gemm_f32(transa, transb, + M, N, K, alpha, A, lda, B, ldb, beta, C, ldc, bias); + else if (mayiuse(avx)) + return jit_avx_gemm_f32(transa, transb, + M, N, K, alpha, A, lda, B, ldb, beta, C, ldc, bias); + else + return ref_gemm(transa, transb, + M, N, K, alpha, A, lda, B, ldb, beta, C, ldc, bias); +} + +template +mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb, + const char *offsetc, const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao, + const b_dt *B, const int *LDB, const int8_t *bo, const float *beta, + int32_t *C, const int *LDC, const int32_t *co) { + mkldnn_status_t status = check_gemm_x8x8x32_input(offsetc, transa, transb, + M, N, K, LDA, LDB, LDC, alpha, beta, false); + if (status != mkldnn_success) + return status; + + if (*M == 0 || *N == 0 || *K == 0) + return mkldnn_success; + +#if USE_MKL_IGEMM + bool OCisR = (*offsetc == 'R' || *offsetc == 'r'); + bool OCisC = (*offsetc == 'C' || *offsetc == 'c'); + bool AisN = (*transa == 'N' || *transa == 'n'); + bool BisN = (*transb == 'N' || *transb == 'n'); + + if (data_traits::data_type == data_type::u8) { + CBLAS_TRANSPOSE Cblas_trA = AisN ? CblasNoTrans : CblasTrans; + CBLAS_TRANSPOSE Cblas_trB = BisN ? CblasNoTrans : CblasTrans; + CBLAS_OFFSET Cblas_offsetc = + OCisR + ? CblasRowOffset + : OCisC + ? CblasColOffset + : CblasFixOffset; + cblas_gemm_s8u8s32(CblasColMajor, Cblas_trA, Cblas_trB, Cblas_offsetc, + *M, *N, *K, *alpha, A, *LDA, *ao, (uint8_t *)B, *LDB, *bo, + *beta, C, *LDC, co); + return mkldnn_success; + } else { + assert(data_traits::data_type == data_type::s8); + // TODO CBLAS implementation of gemm_s8s8s32 goes here. + // mkldnn_gemm_s8s8s32 doesn't support non-zero ao and bo + if (utils::everyone_is(0, *ao, *bo)) { + return simple_gemm_s8s8s32(transa, transb, offsetc, M, + N, K, alpha, A, LDA, ao, (int8_t *)B, LDB, bo, beta, + C, LDC, co); + } else { + return ref_gemm_s8x8s32(transa, transb, offsetc, M, N, K, + alpha, A, LDA, ao, B, LDB, bo, beta, C, LDC, co); + } + } +#else + cpu_isa_t isa = isa_any; + if (mayiuse(avx512_core_vnni)) { + isa = avx512_core_vnni; + } else if (mayiuse(avx512_core)) { + isa = avx512_core; + } + + if (data_traits::data_type == data_type::u8) { + switch (isa) { + case avx512_core: + case avx512_core_vnni: + return jit_avx512_core_gemm_s8u8s32(transa, transb, offsetc, M, + N, K, alpha, A, LDA, ao, (uint8_t *)B, LDB, bo, beta, + C, LDC, co); + default: + return ref_gemm_s8x8s32(transa, transb, offsetc, M, N, K, + alpha, A, LDA, ao, B, LDB, bo, beta, C, LDC, co); + } + } else { + assert(data_traits::data_type == data_type::s8); + // mkldnn_gemm_s8s8s32 doesn't support non-zero ao and bo + if ((mayiuse(avx512_core) || mayiuse(avx512_core_vnni)) + && *ao == 0 && *bo == 0) { + return simple_gemm_s8s8s32(transa, transb, offsetc, M, + N, K, alpha, A, LDA, ao, (int8_t *)B, LDB, bo, beta, + C, LDC, co); + } else { + return ref_gemm_s8x8s32(transa, transb, offsetc, M, N, K, + alpha, A, LDA, ao, B, LDB, bo, beta, C, LDC, co); + } + } +#endif +} + +template +mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb, + const char *offsetc, const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao, + const int8_t *B, const int *LDB, const int8_t *bo, const float *beta, + int32_t *C, const int *LDC, const int32_t *co); + +template +mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb, + const char *offsetc, const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao, + const uint8_t *B, const int *LDB, const int8_t *bo, const float *beta, + int32_t *C, const int *LDC, const int32_t *co); + +} +} +} + +using namespace mkldnn::impl; +using namespace mkldnn::impl::cpu; + +mkldnn_status_t mkldnn_sgemm(const char *transa, const char *transb, + const int64_t *M, const int64_t *N, const int64_t *K, const float *alpha, + const float *A, const int64_t *lda, const float *B, const int64_t *ldb, + const float *beta, float *C, const int64_t *ldc) { + int M_s32 = (int)*M; + int N_s32 = (int)*N; + int K_s32 = (int)*K; + int lda_s32 = (int)*lda; + int ldb_s32 = (int)*ldb; + int ldc_s32 = (int)*ldc; + + return extended_sgemm(transa, transb, &M_s32, &N_s32, &K_s32, + alpha, A, &lda_s32, B, &ldb_s32, beta, C, &ldc_s32); +} + +mkldnn_status_t mkldnn_gemm_s8u8s32(const char *transa, const char *transb, + const char *offsetc, const int64_t *M, const int64_t *N, const int64_t *K, + const float *alpha, const int8_t *A, const int64_t *lda, const int8_t *ao, + const uint8_t *B, const int64_t *ldb, const int8_t *bo, const float *beta, + int32_t *C, const int64_t *ldc, const int32_t *co) { + int M_s32 = (int)*M; + int N_s32 = (int)*N; + int K_s32 = (int)*K; + int lda_s32 = (int)*lda; + int ldb_s32 = (int)*ldb; + int ldc_s32 = (int)*ldc; + return gemm_s8x8s32(transa, transb, offsetc, &M_s32, &N_s32, &K_s32, + alpha, A, &lda_s32, ao, B, &ldb_s32, bo, beta, C, &ldc_s32, co); +} + +mkldnn_status_t mkldnn_gemm_s8s8s32(const char *transa, const char *transb, + const char *offsetc, const int64_t *M, const int64_t *N, const int64_t *K, + const float *alpha, const int8_t *A, const int64_t *lda, const int8_t *ao, + const int8_t *B, const int64_t *ldb, const int8_t *bo, const float *beta, + int32_t *C, const int64_t *ldc, const int32_t *co) { + int M_s32 = (int)*M; + int N_s32 = (int)*N; + int K_s32 = (int)*K; + int lda_s32 = (int)*lda; + int ldb_s32 = (int)*ldb; + int ldc_s32 = (int)*ldc; + + return gemm_s8x8s32(transa, transb, offsetc, &M_s32, &N_s32, &K_s32, + alpha, A, &lda_s32, ao, B, &ldb_s32, bo, beta, C, &ldc_s32, co); +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp new file mode 100644 index 0000000000..dc15ff7130 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp @@ -0,0 +1,58 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef GEMM_HPP +#define GEMM_HPP + +#include "mkldnn_types.h" +#include "os_blas.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +mkldnn_status_t extended_sgemm(const char *transa, const char *transb, + const int *M, const int *N, const int *K, const float *alpha, + const float *A, const int *lda, const float *B, const int *ldb, + const float *beta, float *C, const int *ldc, + const float *bias = nullptr, bool force_jit_gemm = false); + +template +mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb, + const char *offsetc, const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *lda, const int8_t *ao, + const b_dt *B, const int *ldb, const int8_t *bo, const float *beta, + int32_t *c, const int *ldc, const int32_t *co); + +#ifdef USE_CBLAS +#define GEMM_IMPL_STR "gemm:blas" +#else +#define GEMM_IMPL_STR "gemm:jit" +#endif + +#if USE_MKL_IGEMM +#define IGEMM_S8U8S32_IMPL_STR "igemm_s8u8s32:blas" +#define IGEMM_S8S8S32_IMPL_STR "igemm_s8s8s32:blas" +#else +#define IGEMM_S8U8S32_IMPL_STR "igemm_s8u8s32:jit" +#define IGEMM_S8S8S32_IMPL_STR "igemm_s8s8s32:jit" +#endif + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp new file mode 100644 index 0000000000..4d34ede0bd --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp @@ -0,0 +1,86 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef OS_BLAS_HPP +#define OS_BLAS_HPP + +/** \file + * Common stuff respecting USE_MKL and USE_CBLAS compile flags + * + * USE_MKL USE_CBLAS effect + * ------- --------- ------ + * yes yes normal compile: jit *may* be preferred over Intel(R) MKL CBLAS + * yes no jit calls OK; assert if cblas is ever called + * no yes system-dependent CBLAS + * no no gemm convolution (or other blas) N/A; create stubs + */ + +#if defined(USE_MKL) + +#include "mkl_version.h" + +#define USE_MKL_PACKED_GEMM (INTEL_MKL_VERSION >= 20190001) +#define USE_MKL_IGEMM \ + (INTEL_MKL_VERSION >= 20180000 && __INTEL_MKL_BUILD_DATE >= 20170628) + +#include "mkl_cblas.h" +#if !defined(USE_CBLAS) +#define cblas_sgemm(...) assert(!"CBLAS is unavailable") +#endif + +#else /* defined(USE_MKL) */ + +#define USE_MKL_PACKED_GEMM 0 +#define USE_MKL_IGEMM 0 + +#if defined(_SX) +/* TODO: _SX should also define USE_CBLAS in case the later is available */ +extern "C" { +#include "cblas.h" // CHECK: does SX also have a fortran API sgemm? +} + +#elif defined(USE_CBLAS) +#include "cblas.h" // Maybe a system/cmake cblas works for you? +#else +/* put the stubs to make a code compilable but not workable */ +#define cblas_sgemm(...) assert(!"CBLAS is unavailable") +#endif /* defined(_SX) */ + +#endif /* defined(USE_MKL) */ + +namespace mkldnn { +namespace impl { +namespace cpu { + +#if defined(USE_MKL) && defined(USE_CBLAS) +typedef MKL_INT cblas_int; + +#elif defined(USE_CBLAS) +typedef int cblas_int; + +#if defined(_SX) +/* this cblas.h is peculiar... */ +typedef CBLAS_ORDER CBLAS_LAYOUT; +#endif +#endif + +} +} +} + +#endif /* OS_BLAS_HPP */ + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp new file mode 100644 index 0000000000..dde72f4a17 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp @@ -0,0 +1,206 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef COMMON_H +#define COMMON_H + +#define GEMM_CODE_SIZE (4096L * 32) + +#define AVX512_UNROLL_M 48 +#define AVX512_UNROLL_N 8 +#define AVX512_UNROLL_K 1 +#define AVX512_BM 9984 +#define AVX512_BN 384 +#define AVX512_BK 768 +#define AVX512_BK_VNNI 1536 +#define AVX512_BK_TRADITIONAL 384 +#define AVX512_BLOCKING_SMALL_K 48 +#define AVX512_BN_SMALL_K 24 + + +#define PAGESIZE 4096 + +#define PADD_BYTESIZE_ONPAGE(x, size) (((x) * (size) + PAGESIZE - 1) / PAGESIZE) * PAGESIZE +#define NEXT_THR_STRIDE(x, size) (PADD_BYTESIZE_ONPAGE(x, size)) / size + +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +enum { + PARTITION_1D_ROW, + PARTITION_1D_COL, + PARTITION_2D_COL_MAJOR, + PARTITION_2D = PARTITION_2D_COL_MAJOR, +}; + +enum { + COPY_NONE, + COPY_A, +}; + +enum { + NO_OFFSET, + FIX_OFFSET, + COL_OFFSET, + ROW_OFFSET, +}; + +// Alias for any dimension related variable. +typedef long long int dim_t; + +typedef struct { + // Interface arguments. + int transa, transb, offsetc; + dim_t m, n, k; + dim_t lda, ldb, ldc; + const int8_t *a; + const uint8_t *b; + int32_t *c; + const float *alpha, *beta; + + int8_t ao, bo; + const int32_t *co; + + // Kernel parameters. + dim_t um, un, uk, bm, bn, bk; + dim_t bn_small_k, bk_traditional, blocking_small_k; + + int (*copyA)(const dim_t *m, const dim_t *n, const int8_t *a, + const dim_t *lda, const int8_t *alpha, int8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + int (*copyB)(const dim_t *m, const dim_t *n, const uint8_t *a, + const dim_t *lda, const uint8_t *alpha, uint8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + int (*kernel)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + int (*kernel_b)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + int (*kernel_r)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + int (*kernel_c)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + int (*kernel_b0)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + int (*kernel_b0_b)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + int (*kernel_b0_r)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + int (*kernel_b0_c)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + // Gemv kernels + void (*gemv_s8u8s32_kernel)(const dim_t, const dim_t, const float, + const int8_t*, const dim_t, const uint8_t*, + const float, int32_t*); + + void (*gemv_u8s8s32_kernel)(const dim_t, const dim_t, const float, + const uint8_t*, const dim_t, const int8_t*, + const float, int32_t*); + + // Gemv parameters + int swap; + +} blas_t; + + +class jit_avx512_core_u8_copy_an_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_an_kern); + + public: + jit_avx512_core_u8_copy_an_kern(); +}; + +class jit_avx512_core_u8_copy_at_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_at_kern); + + public: + jit_avx512_core_u8_copy_at_kern(); +}; + +class jit_avx512_core_u8_copy_bn_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_bn_kern); + + public: + jit_avx512_core_u8_copy_bn_kern(); +}; + +class jit_avx512_core_u8_copy_bt_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_bt_kern); + + public: + jit_avx512_core_u8_copy_bt_kern(); +}; + +class jit_avx512_core_u8_copy_sum_an_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_an_kern); + + public: + jit_avx512_core_u8_copy_sum_an_kern(); +}; + +class jit_avx512_core_u8_copy_sum_at_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_at_kern); + + public: + jit_avx512_core_u8_copy_sum_at_kern(); +}; + +class jit_avx512_core_u8_copy_sum_bn_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_bn_kern); + + public: + jit_avx512_core_u8_copy_sum_bn_kern(); +}; + +class jit_avx512_core_u8_copy_sum_bt_kern : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_bt_kern); + + public: + jit_avx512_core_u8_copy_sum_bt_kern(); +}; + +} +} +} +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp new file mode 100644 index 0000000000..db9dd9ef97 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp @@ -0,0 +1,28 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +int gemm_s8u8s32_jump_to_gemv_s8u8s32(blas_t *arg); +int gemv_threading_driver(blas_t *arg); + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp new file mode 100644 index 0000000000..e4b8e1cde2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp @@ -0,0 +1,1409 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "common.hpp" +#include "mkldnn_types.h" +#include "nstl.hpp" +#include "utils.hpp" + +#include "jit_avx512_core_gemm_s8u8s32.hpp" +#include "jit_avx512_core_gemm_s8u8s32_kern.hpp" +#include "jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp" +#include "gemv.hpp" + +#if defined(_MSC_VER) +#include +#endif + +namespace mkldnn { +namespace impl { +namespace cpu { + +typedef struct { + int nthrs_m, nthrs_n; + int partition; + int copy_type; +} blas_thread_t; + +static inline void round_to_nearest(int32_t *rounded_val, double fp_val) { + if (fp_val >= 0.) { + fp_val += 0.5; + if (fp_val > INT32_MAX) { + fp_val = INT32_MAX; + } + } else { + fp_val -= 0.5; + if (fp_val < INT32_MIN) { + fp_val = INT32_MIN; + } + } + *rounded_val = (int32_t) fp_val; +} + +static inline void add_results(const dim_t m, const dim_t n, const dim_t k, + const float alpha, const float beta, const int32_t *c_partial_sum, + const dim_t ldcp, int32_t *c_data, const dim_t ldc, + const int32_t *a_row_sum, const int32_t *b_col_sum, const int8_t ao, + const int8_t bo, const int32_t *co, const int offsetc) +{ + for (dim_t j = 0; j < n; ++j) { + for (dim_t i = 0; i < m; ++i) { + int32_t ctemp = c_partial_sum[i + j * ldcp]; + + if (alpha == 1.0f) { + if (beta == 0.0f) { + c_data[i + j * ldc] = ctemp; + } else { + double c_float = (double) beta + * (double) c_data[i + j * ldc]; + c_float += (double) ctemp; + round_to_nearest(&c_data[i + j * ldc], c_float); + } + } else if (alpha == -1.0f) { + if (beta == 0.0f) { + c_data[i + j * ldc] = -ctemp; + } else { + double c_float = (double) beta + * (double) c_data[i + j * ldc]; + c_float -= (double) ctemp; + round_to_nearest(&c_data[i + j * ldc], c_float); + } + } else { + if (beta == 0.0f) { + double c_float = alpha * (double) ctemp; + round_to_nearest(&c_data[i + j * ldc], c_float); + } else { + double c_float = alpha * (double) ctemp + + beta * (double) c_data[i + j * ldc]; + round_to_nearest(&c_data[i + j * ldc], c_float); + } + } + + if (offsetc == FIX_OFFSET) { + c_data[i + j * ldc] += co[0]; + } else if (offsetc == ROW_OFFSET) { + c_data[i + j * ldc] += co[j]; + } else if (offsetc == COL_OFFSET) { + c_data[i + j * ldc] += co[i]; + } + } + } +} + +// TODO Find a better place for those functions. +static inline dim_t ld_padd(const dim_t x) +{ + return ((x + ((2048 / sizeof(int32_t)) - 1)) / (2048 / sizeof(int32_t))) + * (2048 / sizeof(int32_t)) + (64 / sizeof(int32_t)); +} + +void igemm_inner_kernel(const dim_t m, const dim_t n, const dim_t k, + const int8_t *a, const uint8_t *b, float beta, int32_t *c, + const dim_t ldc, const int32_t *a_row_sum, const int32_t *b_col_sum, + const int32_t *co, const int offsetc, const blas_t *arg) +{ + int8_t ao = arg->ao; + int8_t bo = arg->bo; + int32_t co_0 = (offsetc == NO_OFFSET)? 0 : co[0]; + + // Since m and n are limited by blocking, stack overflow may not happen; + // it's up to 32kB +#if !defined(_MSC_VER) + int32_t col_offset[m]; + int32_t row_offset[n]; +#else + int32_t *col_offset = (int32_t *) _alloca(sizeof(*col_offset) * m); + int32_t *row_offset = (int32_t *) _alloca(sizeof(*row_offset) * n); +#endif + + int col_req = 0; + int row_req = 0; + + if ((bo != 0) || (offsetc == COL_OFFSET)) + col_req = 1; + if ((ao != 0) || (offsetc == ROW_OFFSET)) + row_req = 1; + + // It needs one of colum or row offsets, but it doesn't need both + if (((ao != 0) && (bo != 0)) || ((offsetc == FIX_OFFSET) && (co_0 != 0))) { + if ((col_req == 0) && (row_req == 0)) { + if (m <= n) { + col_req = 1; + } else { + row_req = 1; + } + } + } + + if (col_req) { + for (dim_t i = 0; i < m; i++) + col_offset[i] = 0; + + if (offsetc == COL_OFFSET) { + for (dim_t i = 0; i < m; i++) + col_offset[i] += co[i]; + } + + if (bo != 0) { + for (dim_t i = 0; i < m; i++) + col_offset[i] += bo * a_row_sum[i]; + } + } + + if (row_req) { + for (dim_t i = 0; i < n; i++) + row_offset[i] = 0; + + if (offsetc == ROW_OFFSET) { + for (dim_t i = 0; i < n; i++) + row_offset[i] += co[i]; + } + + if (ao != 0) { + for (dim_t i = 0; i < n; i++) + row_offset[i] += ao * b_col_sum[i]; + } + } + + if ((offsetc == FIX_OFFSET) && (co_0 != 0)) { + if (col_req) { + for (dim_t i = 0; i < m; i++) + col_offset[i] += co_0; + } else { + for (dim_t i = 0; i < n; i++) + row_offset[i] += co_0; + } + } + + if ((ao != 0) && (bo != 0)) { + if (col_req) { + for (dim_t i = 0; i < m; i++) + col_offset[i] += (int32_t) k * ao * bo; + } else { + for (dim_t i = 0; i < n; i++) + row_offset[i] += (int32_t) k * ao * bo; + } + } + + if (col_req == 0) { + if (row_req == 0) { + if (beta == 0.0) { + arg->kernel_b0(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } else { + arg->kernel(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } + } else { + if (beta == 0.0) { + arg->kernel_b0_r(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } else { + arg->kernel_r(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } + } + } else { + if (row_req == 0) { + if (beta == 0.0) { + arg->kernel_b0_c(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } else { + arg->kernel_c(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } + } else { + if (beta == 0.0) { + arg->kernel_b0_b(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } else { + arg->kernel_b(&m, &n, &k, NULL, a, b, c, ldc, col_offset, + row_offset); + } + } + } +} + +static inline void *align(void *ptr, size_t alignment) +{ + return (void *) utils::rnd_up((uintptr_t) ptr, alignment); +} + +static int gemm_kernel_driver(const dim_t m, const dim_t n, const dim_t k, + const int8_t *a, const uint8_t *b, int32_t *c, const int32_t *co, + const blas_t *arg) +{ + dim_t lda = arg->lda; + dim_t ldb = arg->ldb; + dim_t ldc = arg->ldc; + int8_t ao = arg->ao; + int8_t bo = arg->bo; + float alpha = *arg->alpha; + float beta = *arg->beta; + + if (m <= 0 || n <= 0) { + return 0; + } + + // Padding along K dimension. + dim_t k_padd = 0; + if (k <= arg->bk_traditional) { + k_padd = utils::rnd_up(k, arg->uk); + k_padd = nstl::max(128LL, k_padd); + } else if (k < 2 * arg->bk) { + k_padd = utils::rnd_up(k / 2, arg->uk); + } else { + k_padd = arg->bk; + } + + // Padding along M dimension. + dim_t m_padd = utils::rnd_up(nstl::min(nstl::max(m, arg->um), arg->bm), + arg->um); + + // Padding along N dimension. + dim_t n_padd = 0; + if (k < arg->blocking_small_k) { + n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un), + arg->bn_small_k), arg->un); + } else { + n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un), arg->bn), + arg->un); + } + + // Padding for temporary buffer for C + dim_t ldc_buf = ld_padd(m_padd); + + dim_t strideAm = (arg->transa == 0)? 1 : lda; + dim_t strideAn = (arg->transa != 0)? 1 : lda; + dim_t strideBm = (arg->transb == 0)? 1 : ldb; + dim_t strideBn = (arg->transb != 0)? 1 : ldb; + + size_t a_buf_nelems = m_padd * k_padd; + size_t b_buf_nelems = k_padd * n_padd; + size_t a_row_sum_nelems = m_padd; + size_t b_col_sum_nelems = n_padd; + + size_t mem_size = a_buf_nelems * sizeof(*a) + PAGE_4K + + b_buf_nelems * sizeof(*b) + PAGE_4K + + a_row_sum_nelems * sizeof(*c) + PAGE_4K + + b_col_sum_nelems * sizeof(*c) + PAGE_4K; + + bool need_c_buffer = alpha != 1.0f || (beta != 1 && beta != 0); + if (need_c_buffer) { + size_t c_buf_nelems = ldc_buf * n_padd; + mem_size += c_buf_nelems * sizeof(*c) + PAGE_4K; + } + + char *mem = (char *) malloc(mem_size, 128); + + if (!mem) { + return -1; + } + + int8_t *bufferA = (int8_t *) align(mem, PAGE_4K); + uint8_t *bufferB = (uint8_t *) align(bufferA + a_buf_nelems, PAGE_4K); + int32_t *a_row_sum = (int32_t *) align(bufferB + b_buf_nelems, PAGE_4K); + int32_t *b_col_sum = (int32_t *) align(a_row_sum + a_row_sum_nelems, + PAGE_4K); + + int32_t *bufferC = NULL; + if (need_c_buffer) { + bufferC = (int32_t *) align(b_col_sum + b_col_sum_nelems, PAGE_4K); + } + + float beta_saved = beta; + + int a_block_copied = 0; + dim_t sizeM = 0; + for (dim_t Bm = 0; Bm < m; Bm += sizeM) { + sizeM = m - Bm; + if (sizeM > m_padd) + sizeM = m_padd; + + dim_t sizeK = 0; + for (dim_t Bk = 0; Bk < k; Bk += sizeK) { + sizeK = k - Bk; + if (sizeK > k_padd) + sizeK = k_padd; + + // Scale C blocks by beta only for the first time + if (Bk == 0) + beta = beta_saved; + else + beta = 1.0f; + + // Apply C offset when to the last k-block of the partial sum. + int offsetc = NO_OFFSET; + if (Bk + sizeK == k) + offsetc = arg->offsetc; + + dim_t sizeN = 0; + for (dim_t Bn = 0; Bn < n; Bn += sizeN) { + sizeN = n - Bn; + if (sizeN > n_padd) + sizeN = n_padd; + + const uint8_t *b_block = b + Bk * strideBm + Bn * strideBn; + arg->copyB(&sizeK, &sizeN, b_block, &ldb, NULL, bufferB, NULL, + NULL, b_col_sum); + + dim_t sizeUM = 0; + for (dim_t Um = 0; Um < sizeM; Um += sizeUM) { + sizeUM = sizeM - Um; + if (sizeUM > arg->um) + sizeUM = arg->um; + + /* + * Use the whole A buffer only if we have multiple B blocks + * for k-dimension, otherwise we are wasting cache to store + * B and C blocks. + */ + dim_t Um_forA = 0; + if (sizeN < n) + Um_forA = Um; + + const int8_t *a_block = a + (Bm + Um) * strideAm + + Bk * strideAn; + if (!a_block_copied) { + arg->copyA(&sizeK, &sizeUM, a_block, &lda, NULL, + bufferA + Um_forA * sizeK, NULL, NULL, + a_row_sum + Um_forA); + } + + int32_t *c_block = c + (Bm + Um) + Bn * ldc; + dim_t co_stride = 0; + if (offsetc == FIX_OFFSET) { + co_stride = 0; + } else if (offsetc == ROW_OFFSET) { + co_stride = Bn; + } else if (offsetc == COL_OFFSET) { + co_stride = Bm + Um; + } + if (need_c_buffer) { + igemm_inner_kernel(sizeUM, sizeN, sizeK, + bufferA + Um_forA * sizeK, bufferB, 0.0f, + bufferC + Um, ldc_buf, a_row_sum + Um_forA, + b_col_sum, NULL, NO_OFFSET, arg); + + // Finish the block adding the necessary alpha, beta + // and offsets. + add_results(sizeUM, sizeN, sizeK, alpha, beta, + bufferC + Um, ldc_buf, c_block, ldc, + a_row_sum + Um_forA, b_col_sum, ao, bo, + co + co_stride, offsetc); + } else { + igemm_inner_kernel(sizeUM, sizeN, sizeK, + bufferA + Um_forA * sizeK, bufferB, beta, + c_block, ldc, a_row_sum + Um_forA, b_col_sum, + co + co_stride, offsetc, arg); + } + } + a_block_copied = 1; + } + a_block_copied = 0; + } + } + + free(mem); + + return 0; +} + +static int kernel_driver_parallel_acopiedbcopy(const dim_t m, const dim_t n, + const dim_t k, const int8_t *bufferA, const uint8_t *b, + const float beta, int32_t *c, const int offsetc, const int32_t *co, + const int32_t *a_row_sum, const blas_t *arg) +{ + dim_t ldb = arg->ldb; + dim_t ldc = arg->ldc; + int8_t ao = arg->ao; + int8_t bo = arg->bo; + float alpha = *arg->alpha; + + if (m <= 0 || n <= 0) { + return 0; + } + + // Padding along N dimension. + dim_t n_padd = 0; + if (k < arg->blocking_small_k) { + n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un), + arg->bn_small_k), arg->un); + } else { + n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un), arg->bn), + arg->un); + } + + // Padding for temporary buffer for C + dim_t ldc_buf = ld_padd(m); + + dim_t strideBn = (arg->transb != 0)? 1 : ldb; + + size_t b_buf_nelems = k * n_padd; + size_t b_col_sum_nelems = n_padd; + + size_t mem_size = b_buf_nelems * sizeof(*b) + PAGE_4K + + b_col_sum_nelems * sizeof(*c) + PAGE_4K; + + bool need_c_buffer = alpha != 1.0f || (beta != 1 && beta != 0); + if (need_c_buffer) { + size_t c_buf_nelems = ldc_buf * n_padd; + mem_size += c_buf_nelems * sizeof(*c) + PAGE_4K; + } + + char *mem = (char *) malloc(mem_size, 128); + + if (!mem) { + return -1; + } + + uint8_t *bufferB = (uint8_t *) align(mem, PAGE_4K); + int32_t *b_col_sum = (int32_t *) align(bufferB + b_buf_nelems, PAGE_4K); + + int32_t *bufferC = NULL; + if (need_c_buffer) { + bufferC = (int32_t *) align(b_col_sum + b_col_sum_nelems, PAGE_4K); + } + + dim_t sizeN = 0; + for (dim_t Bn = 0; Bn < n; Bn += sizeN) { + sizeN = n - Bn; + if (sizeN > n_padd) + sizeN = n_padd; + + // Implement the kernel here. + const uint8_t *b_block = b + Bn * strideBn; + arg->copyB(&k, &sizeN, b_block, &ldb, NULL, bufferB, NULL, NULL, + b_col_sum); + + dim_t co_stride = 0; + if (offsetc == FIX_OFFSET) { + co_stride = 0; + } else if (offsetc == ROW_OFFSET) { + co_stride = Bn; + } else if (offsetc == COL_OFFSET) { + co_stride = 0; + } + int32_t *c_block = c + Bn * ldc; + if (need_c_buffer) { + igemm_inner_kernel(m, sizeN, k, bufferA, bufferB, 0.0f, bufferC, + ldc_buf, a_row_sum, b_col_sum, NULL, NO_OFFSET, arg); + + // Finish the block adding the necessary alpha, beta and offsets. + add_results(m, sizeN, k, alpha, beta, bufferC, ldc_buf, c_block, + ldc, a_row_sum, b_col_sum, ao, bo, co + co_stride, + offsetc); + } else { + igemm_inner_kernel(m, sizeN, k, bufferA, bufferB, beta, c_block, + ldc, a_row_sum, b_col_sum, co + co_stride, offsetc, arg); + } + } + + free(mem); + + return 0; + +} + +#define N2D_MAX_AVX512 384 +#define M2D_MIN_AVX512 384 +#define VECLEN 16 +#define NCONS 1 +static inline void set_thread_opts_avx512(int *p_nthrs, + blas_thread_t *thread_info, const blas_t *arg) +{ + int nthrs = *p_nthrs; + dim_t m = arg->m; + dim_t n = arg->n; + + thread_info->nthrs_m = 0; + thread_info->nthrs_n = 0; + thread_info->copy_type = COPY_NONE; // By default don't do parallel copy. + + int condition_2D_bsrc = -1; + if ((256 * m > nthrs * n) && (nthrs * m < 256 * n)) { + condition_2D_bsrc = 1; + } else { + condition_2D_bsrc = 0; + } + + int condition_1D_copya = 0; + if ((m >= 1000) && (n >= nthrs * N2D_MAX_AVX512 / 4)) { + condition_2D_bsrc = 0; + condition_1D_copya = 1; + } + + // If offset is non-zero, we need to keep 1D_copya to reduce update overhead + if (arg->ao != 0 || arg->bo != 0 || arg->co[0] != 0 + || arg->offsetc != FIX_OFFSET) { + condition_2D_bsrc = 0; + condition_1D_copya = 1; + } + + if (condition_2D_bsrc == 1) { + int nthrs_m = 1; + int nthrs_n = nthrs; + + while ((nthrs_n % 2 == 0) && + (n / nthrs > N2D_MAX_AVX512 || + n / nthrs_n <= N2D_MAX_AVX512 / 2) && + (m / nthrs_m >= 2 * M2D_MIN_AVX512) && + (nthrs_m < 4)) { + nthrs_m *= 2; + nthrs_n /= 2; + } + + thread_info->nthrs_m = nthrs_m; + thread_info->nthrs_n = nthrs_n; + thread_info->partition = PARTITION_2D; + + // Reset the total number of threads that will be used. + *p_nthrs = nthrs_m * nthrs_n; + + } else if (condition_1D_copya && mkldnn_thr_syncable()) { + // Use parallel copy A algorithm + thread_info->copy_type = COPY_A; + thread_info->partition = PARTITION_1D_COL; + } else { + if ((m > n) && (m / nthrs >= VECLEN || n < NCONS * nthrs)) { + thread_info->partition = PARTITION_1D_ROW; + } else { + thread_info->partition = PARTITION_1D_COL; + } + } +} +#undef N2D_MAX_AVX512 +#undef M2D_MIN_AVX512 +#undef VECLEN +#undef NCONS + +static inline void partition_1d(const int ithr, const int nthrs, const dim_t n, + dim_t *t_offset, dim_t *t_block) +{ + dim_t band = n / nthrs; + + dim_t tail = n - (nthrs - 1) * band; + if (tail > (band + 1)) + band++; + tail = n - (nthrs - 1) * band; + + if (ithr < (nthrs - 1)) + *t_block = band; + else + *t_block = tail; + + *t_offset = ithr * band; + + if (*t_offset >= n) { + *t_block = 0; + *t_offset = 0; + } else if ((*t_offset + *t_block) > n) { + *t_block = n - *t_offset; + } +} + +static inline void partition_2d(const int ithr, int *nthrs, const int ithr_i, + const int ithr_j, const int nthrs_m, const int nthrs_n, const dim_t m, + const dim_t n, dim_t *p_m_disp, dim_t *p_m_band, dim_t *p_n_disp, + dim_t *p_n_band) +{ + dim_t m_disp = 0, n_disp = 0; + dim_t m_band = 0, n_band = 0; + + int mdiv = nthrs_m; + int ndiv = nthrs_n; + + dim_t m_bandt = m / mdiv; /* size per thread */ + dim_t n_bandt = n / ndiv; /* size per thread */ + int firstmgroup = mdiv - 1; + int firstngroup = ndiv - 1; + dim_t firstmval = m_bandt; + dim_t firstnval = n_bandt; + + int mthr_used = mdiv; + if (m - (mdiv - 1) * m_bandt > m_bandt + 1) { + if (m - (mdiv - 1) * m_bandt > mdiv) + ++m_bandt; + + firstmval = m_bandt + 1; + mthr_used = (int) (m / firstmval); + + if (mthr_used * firstmval < m) + ++mthr_used; + + firstmgroup = mthr_used - 1; + } + + int nthr_used = ndiv; + if (n - (ndiv - 1) * n_bandt > n_bandt + 1) { + firstnval = n_bandt + 1; + nthr_used = (int) (n / firstnval); + + if (nthr_used * firstnval < n) + ++nthr_used; + + firstngroup = nthr_used - 1; + } + + *nthrs = mthr_used * nthr_used; + + if (ithr < *nthrs) { + if (ithr_i < firstmgroup) { + m_band = firstmval; + m_disp = ithr_i * firstmval; + } else if (ithr_i <= mthr_used - 2) { + m_band = m_bandt; + m_disp = firstmgroup * firstmval + (ithr_i - firstmgroup) * m_bandt; + } else { + m_disp = firstmgroup * firstmval + + (mthr_used - 1 - firstmgroup) * m_bandt; + m_band = nstl::max(0LL, m - m_disp); + } + + if (ithr_j < firstngroup) { + n_band = firstnval; + n_disp = ithr_j * firstnval; + } else if (ithr_j <= nthr_used - 2) { + n_band = n_bandt; + n_disp = firstngroup * firstnval + (ithr_j - firstngroup) * n_bandt; + } else { + n_disp = firstngroup * firstnval + + (nthr_used - 1 - firstngroup) * n_bandt; + n_band = nstl::max(0LL, n - n_disp); + } + m_disp = nstl::max(nstl::min(m_disp, m - 1), 0LL); + n_disp = nstl::max(nstl::min(n_disp, n - 1), 0LL); + } + + if (ithr < *nthrs) { + *p_m_disp = m_disp; + *p_n_disp = n_disp; + *p_m_band = m_band; + *p_n_band = n_band; + } else { + *p_m_disp = 0; + *p_n_disp = 0; + *p_m_band = 0; + *p_n_band = 0; + } + + return; +} + +static inline void decompose_matrices(const int ithr, int *nthrs, dim_t *m, + dim_t *n, dim_t *k, const int8_t **a, const uint8_t **b, int32_t **c, + const int32_t **co, const blas_thread_t *thread_info, const blas_t *arg) +{ + dim_t strideAm = (arg->transa == 0)? 1 : arg->lda; + dim_t strideBn = (arg->transb != 0)? 1 : arg->ldb; + int offsetc = arg->offsetc; + + switch (thread_info->partition) { + case PARTITION_1D_ROW: + { + dim_t offset = 0; + dim_t block = 0; + partition_1d(ithr, *nthrs, arg->m, &offset, &block); + + *m = block; + *n = arg->n; + *k = arg->k; + + // Set matrix A. + *a = arg->a + offset * strideAm; + + // Set matrix B. + *b = arg->b; + + // Set matrix C. + *c = arg->c + offset; + + // Set offset vector for C matrix + dim_t co_stride = 0; + if (offsetc == FIX_OFFSET) { + co_stride = 0; + } else if (offsetc == ROW_OFFSET) { + co_stride = 0; + } else if (offsetc == COL_OFFSET) { + co_stride = offset; + } + *co = arg->co + co_stride; + break; + } + + case PARTITION_1D_COL: + { + dim_t offset = 0; + dim_t block = 0; + partition_1d(ithr, *nthrs, arg->n, &offset, &block); + + *m = arg->m; + *n = block; + *k = arg->k; + + // Set matrix A. + *a = arg->a; + + // Set matrix B. + *b = arg->b + offset * strideBn; + + // Set matrix C. + *c = arg->c + offset * arg->ldc; + + // Set offset vector for C matrix + dim_t co_stride = 0; + if (offsetc == FIX_OFFSET) { + co_stride = 0; + } else if (offsetc == ROW_OFFSET) { + co_stride = offset; + } else if (offsetc == COL_OFFSET) { + co_stride = 0; + } + *co = arg->co + co_stride; + break; + } + + case PARTITION_2D_COL_MAJOR: + { + int nthrs_m = thread_info->nthrs_m; + int nthrs_n = thread_info->nthrs_n; + int ithr_i = ithr % nthrs_m; + int ithr_j = ithr / nthrs_m; + + dim_t m_disp = 0; + dim_t m_band = 0; + dim_t n_disp = 0; + dim_t n_band = 0; + + partition_2d(ithr, nthrs, ithr_i, ithr_j, nthrs_m, nthrs_n, + arg->m, arg->n, &m_disp, &m_band, &n_disp, &n_band); + + *m = m_band; + *n = n_band; + *k = arg->k; + + // Set matrix A. + *a = arg->a + m_disp * strideAm; + + // Set matrix B. + *b = arg->b + n_disp * strideBn; + + // Set matrix C. + *c = arg->c + m_disp + n_disp * arg->ldc; + + // Set offset vector for C matrix + dim_t co_stride = 0; + if (offsetc == FIX_OFFSET) { + co_stride = 0; + } else if (offsetc == ROW_OFFSET) { + co_stride = n_disp; + } else if (offsetc == COL_OFFSET) { + co_stride = m_disp; + } + *co = arg->co + co_stride; + break; + } + } +} + +#define MULTIPLIER 10 +static int parallel_a_copy(const int ithr, const int nthrs, const dim_t m, + const dim_t n, const dim_t k, const int8_t *a, const uint8_t *b, + int32_t *c, const int32_t *co, const blas_t *arg, + char **p_shared_mem) +{ + const dim_t lda = arg->lda; + const dim_t ldb = arg->ldb; + const dim_t strideAm = (arg->transa == 0)? 1 : lda; + const dim_t strideAn = (arg->transa != 0)? 1 : lda; + const dim_t strideBm = (arg->transb == 0)? 1 : ldb; + + // Padding along M dimension. + dim_t m_padd = utils::rnd_up(nstl::min(nstl::max(m, arg->um), arg->bm), + arg->um); + + // Padding along K dimension. + dim_t k_padd = 0; + if (k <= arg->bk_traditional) { + k_padd = utils::rnd_up(k, arg->uk); + k_padd = nstl::max(128LL, k_padd); + } else if (k < 2 * arg->bk) { + k_padd = utils::rnd_up(k / 2, arg->uk); + } else { + k_padd = arg->bk; + } + + m_padd *= nthrs > MULTIPLIER ? MULTIPLIER : nthrs; + if (m_padd > m) { + m_padd = utils::rnd_up(m, arg->um); + } + + size_t a_buf_nelems = m_padd * k_padd; + + // Allocate shared memory for A and its row sum buffers in master thread. + if (ithr == 0) { // If thread master + size_t a_row_sum_nelems = m_padd; + + size_t mem_size = (a_buf_nelems * sizeof(*a) + PAGE_4K) + + a_row_sum_nelems * sizeof(*c) + PAGE_4K; + + *p_shared_mem = (char *) malloc(mem_size, 128); + + } + mkldnn_thr_barrier(); + + char *mem = *p_shared_mem; + int8_t *bufferA = (int8_t *) align(mem, PAGE_4K); + int32_t *a_row_sum = (int32_t *) align(bufferA + a_buf_nelems, PAGE_4K); + + if (!mem) { + return -1; + } + + int result = 0; // Return status + + dim_t sizeK = 0; + for (dim_t Bk = 0; Bk < k; Bk += sizeK) { + sizeK = k - Bk; + if (sizeK > k_padd) + sizeK = k_padd; + + // Scale C blocks by beta only for the first term of partial sum. + float beta = 1.0f; + if (Bk == 0) + beta = *(arg->beta); + + // Apply C offset for the last k-block of the partial sum. + int offsetc = NO_OFFSET; + if (Bk + sizeK == k) + offsetc = arg->offsetc; + + dim_t sizeM = 0; + for (dim_t Bm = 0; Bm < m; Bm += sizeM) { + sizeM = m - Bm; + if (sizeM > m_padd) + sizeM = m_padd; + + if (ithr < nthrs) { + dim_t band = (sizeM + nthrs - 1) / nthrs; + band = utils::rnd_up(band, arg->um); + + dim_t offset = band * ithr; + + // If offset is too large don't use that thread for copying. + if (offset >= sizeM) { + offset = 0; + band = 0; + } + + // Handle the tail of the copy. + if (offset + band > sizeM) { + band = sizeM - offset; + } + + if (band > 0) { + const int8_t *a_block = a + (Bm + offset) * strideAm + + Bk * strideAn; + arg->copyA(&sizeK, &band, a_block, &lda, NULL, + bufferA + offset * sizeK, NULL, NULL, + a_row_sum + offset); + } + } + mkldnn_thr_barrier(); // Wait for finishing parallel copy. + + const uint8_t *b_block = b + Bk * strideBm; + int32_t *c_block = c + Bm; + dim_t co_stride = 0; + if (offsetc == FIX_OFFSET) { + co_stride = 0; + } else if (offsetc == ROW_OFFSET) { + co_stride = 0; + } else if (offsetc == COL_OFFSET) { + co_stride = Bm; + } + + result = kernel_driver_parallel_acopiedbcopy(sizeM, n, sizeK, + bufferA, b_block, beta, c_block, offsetc, co + co_stride, + a_row_sum, arg); + + mkldnn_thr_barrier(); // Wait for kernel computations to finish. + } + } + + // Free memory allocated in master thread + if (ithr == 0) { + free(mem); + } + + return result; +} +#undef MULTIPLIER + +static inline void get_omp_thread_count(dim_t m, dim_t n, dim_t k, + double fp_per_cycle, int *nthrs) +{ + double omp_overhead_small_core = 3.0e+3; + double omp_intercept_big_core = 4.0e+3; + double omp_slope_big_core = 5.0e+2; + + double gemm_cycles = 8.0 * m * n * k / fp_per_cycle; + + int i = *nthrs; + + // Use a different model for omp overheads if nthrs is <= 4 + if (*nthrs <= 4 && omp_overhead_small_core > 0) { + double omp_cycles = omp_overhead_small_core; + if (gemm_cycles < omp_cycles) { + *nthrs = 1; + return; + } else { + while (i > 1) { + if (omp_cycles * i < gemm_cycles * (i - 1)) break; + --i; + } + } + } else { + if (gemm_cycles < (omp_intercept_big_core + 2 * omp_slope_big_core)) { + *nthrs = 1; + return; + } + + // adaptive decrement to march faster· + while (i > 1) { + double omp_cycles = omp_intercept_big_core + i * omp_slope_big_core; + if (omp_cycles * i < gemm_cycles * (i - 1)) + break; + + if (i < 10) + i -= 2; + else if (i < 30) + i -= 4; + else + i -= 8; + } + } + + if (i < 1) + i = 1; + + *nthrs = i; +} + +#define CACHE_LINE_SIZE 64 +static int gemm_threading_driver(blas_t *arg) +{ + if ((arg->m <= 0) || (arg->n <= 0)) + return mkldnn_success; + + if (gemm_s8u8s32_jump_to_gemv_s8u8s32(arg)) { + return mkldnn_success; + } + + int nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads(); + get_omp_thread_count(arg->m, arg->n, arg->k, 64.0, &nthr); + + if (nthr == 1) { + return gemm_kernel_driver(arg->m, arg->n, arg->k, arg->a, arg->b, + arg->c, arg->co, arg); + } + + int *results = (int *) malloc(sizeof(*results) * nthr * CACHE_LINE_SIZE, + PAGE_4K); + + if (!results) { + return -1; + } + + for (int i = 0; i < nthr; i++) { + results[i * CACHE_LINE_SIZE] = 0; // Initialize to success + } + + char *shared_mem = NULL; + + parallel(nthr, [&](const int ithr, const int nthr) { + int nthrs = nthr; + if (nthrs == 1) { + results[0] = gemm_kernel_driver(arg->m, arg->n, arg->k, arg->a, + arg->b, arg->c, arg->co, arg); + } else { + blas_thread_t thread_info; + set_thread_opts_avx512(&nthrs, &thread_info, arg); + + const int8_t *a = NULL; + const uint8_t *b = NULL; + int32_t *c = NULL; + const int32_t *co = NULL; + dim_t m = -1; + dim_t n = -1; + dim_t k = -1; + decompose_matrices(ithr, &nthrs, &m, &n, &k, &a, &b, &c, &co, + &thread_info, arg); + + if (ithr < nthrs) { + switch (thread_info.copy_type) { + case COPY_A: + results[ithr * CACHE_LINE_SIZE] = + parallel_a_copy(ithr, nthrs, m, n, k, a, b, c, co, arg, + &shared_mem); + break; + + default: + case COPY_NONE: + results[ithr * CACHE_LINE_SIZE] = + gemm_kernel_driver(m, n, k, a, b, c, co, arg); + break; + } + } + } + }); + + int result = 0; // Initialize to success + for (int i = 0; i < nthr; i++) { + if (results[i] != 0) { + result = results[i * CACHE_LINE_SIZE]; + break; + } + } + + free(results); + + return result; +} +#undef CACHE_LINE_SIZE + +static jit_avx512_core_u8_copy_an_kern *copy_an; +static jit_avx512_core_u8_copy_at_kern *copy_at; +static jit_avx512_core_u8_copy_bn_kern *copy_bn; +static jit_avx512_core_u8_copy_bt_kern *copy_bt; +static jit_avx512_core_u8_copy_sum_an_kern *copy_sum_an; +static jit_avx512_core_u8_copy_sum_at_kern *copy_sum_at; +static jit_avx512_core_u8_copy_sum_bn_kern *copy_sum_bn; +static jit_avx512_core_u8_copy_sum_bt_kern *copy_sum_bt; +static jit_avx512_core_gemm_s8u8s32_kern *kernel; +static jit_avx512_core_gemm_s8u8s32_kern *kernel_b; +static jit_avx512_core_gemm_s8u8s32_kern *kernel_r; +static jit_avx512_core_gemm_s8u8s32_kern *kernel_c; +static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0; +static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0_b; +static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0_r; +static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0_c; +static jit_avx512_core_gemv_s8u8s32_kern *gemv_s8u8s32_kernel; +static jit_avx512_core_gemv_s8u8s32_kern *gemv_u8s8s32_kernel; + +static void jit_init(blas_t *arg) +{ + static int (*copyAn)(const dim_t *m, const dim_t *n, const int8_t *a, + const dim_t *lda, const int8_t *alpha, int8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*copyAt)(const dim_t *m, const dim_t *n, const int8_t *a, + const dim_t *lda, const int8_t *alpha, int8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*copyBn)(const dim_t *m, const dim_t *n, const uint8_t *a, + const dim_t *lda, const uint8_t *alpha, uint8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*copyBt)(const dim_t *m, const dim_t *n, const uint8_t *a, + const dim_t *lda, const uint8_t *alpha, uint8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*copySumAn)(const dim_t *m, const dim_t *n, const int8_t *a, + const dim_t *lda, const int8_t *alpha, int8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*copySumAt)(const dim_t *m, const dim_t *n, const int8_t *a, + const dim_t *lda, const int8_t *alpha, int8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*copySumBn)(const dim_t *m, const dim_t *n, const uint8_t *a, + const dim_t *lda, const uint8_t *alpha, uint8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*copySumBt)(const dim_t *m, const dim_t *n, const uint8_t *a, + const dim_t *lda, const uint8_t *alpha, uint8_t *b, + const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum); + + static int (*kern)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static int (*kern_b)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static int (*kern_r)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static int (*kern_c)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static int (*kern_b0)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static int (*kern_b0_b)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static int (*kern_b0_r)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static int (*kern_b0_c)(const dim_t *m, const dim_t *n, const dim_t *k, + const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c, + const dim_t ldc, const int32_t *col_offset, + const int32_t *row_offset); + + static void (*gemv_s8u8s32_kern)(const dim_t, const dim_t, const float, + const int8_t*, const dim_t, const uint8_t*, + const float, int32_t*); + + static void (*gemv_u8s8s32_kern)(const dim_t, const dim_t, const float, + const uint8_t*, const dim_t, const int8_t*, + const float, int32_t*); + + if (mayiuse(avx512_core_vnni)) { + arg->um = AVX512_UNROLL_M; + arg->un = AVX512_UNROLL_N; + arg->uk = AVX512_UNROLL_K; + arg->bm = AVX512_BM; + arg->bn = AVX512_BN; + arg->bk = AVX512_BK_VNNI; + + arg->bk_traditional = AVX512_BK_TRADITIONAL; + arg->bn_small_k = AVX512_BN_SMALL_K; + arg->blocking_small_k = AVX512_BLOCKING_SMALL_K; + } else { + arg->um = AVX512_UNROLL_M; + arg->un = AVX512_UNROLL_N; + arg->uk = AVX512_UNROLL_K; + arg->bm = AVX512_BM; + arg->bn = AVX512_BN; + arg->bk = AVX512_BK; + + arg->bk_traditional = AVX512_BK_TRADITIONAL; + arg->bn_small_k = AVX512_BN_SMALL_K; + arg->blocking_small_k = AVX512_BLOCKING_SMALL_K; + } + + static std::once_flag initialized; + std::call_once(initialized, []{ + + copy_an = new jit_avx512_core_u8_copy_an_kern(); + copy_at = new jit_avx512_core_u8_copy_at_kern(); + copy_bn = new jit_avx512_core_u8_copy_bn_kern(); + copy_bt = new jit_avx512_core_u8_copy_bt_kern(); + + copy_sum_an = new jit_avx512_core_u8_copy_sum_an_kern(); + copy_sum_at = new jit_avx512_core_u8_copy_sum_at_kern(); + copy_sum_bn = new jit_avx512_core_u8_copy_sum_bn_kern(); + copy_sum_bt = new jit_avx512_core_u8_copy_sum_bt_kern(); + + kernel = new jit_avx512_core_gemm_s8u8s32_kern(false, false, false); + kernel_b = new jit_avx512_core_gemm_s8u8s32_kern(false, true, true); + kernel_r = new jit_avx512_core_gemm_s8u8s32_kern(false, false, true); + kernel_c = new jit_avx512_core_gemm_s8u8s32_kern(false, true, false); + kernel_b0 = new jit_avx512_core_gemm_s8u8s32_kern(true, false, false); + kernel_b0_b = new jit_avx512_core_gemm_s8u8s32_kern(true, true, true); + kernel_b0_r = new jit_avx512_core_gemm_s8u8s32_kern(true, false, true); + kernel_b0_c = new jit_avx512_core_gemm_s8u8s32_kern(true, true, false); + + gemv_s8u8s32_kernel = new jit_avx512_core_gemv_s8u8s32_kern(); + gemv_u8s8s32_kernel = new jit_avx512_core_gemv_s8u8s32_kern(); + + + copyAn = copy_an->getCode(); + + copyAt = copy_at->getCode(); + + copyBn = copy_bn->getCode(); + + copyBt = copy_bt->getCode(); + + copySumAn = copy_sum_an->getCode(); + + copySumAt = copy_sum_at->getCode(); + + copySumBn = copy_sum_bn->getCode(); + + copySumBt = copy_sum_bt->getCode(); + + kern = kernel->getCode(); + + kern_b = kernel_b->getCode(); + + kern_r = kernel_r->getCode(); + + kern_c = kernel_c->getCode(); + + kern_b0 = kernel_b0->getCode(); + + kern_b0_b = kernel_b0_b->getCode(); + + kern_b0_r = kernel_b0_r->getCode(); + + kern_b0_c = kernel_b0_c->getCode(); + + gemv_s8u8s32_kern = + gemv_s8u8s32_kernel -> generate + (mayiuse(avx512_core_vnni)); + gemv_u8s8s32_kern = + gemv_u8s8s32_kernel -> generate + (mayiuse(avx512_core_vnni)); + }); + + if (arg->bo == 0) { // No need to compute A row sum if bo is zero + if (arg->transa == 0) { + arg->copyA = copyAn; + } else { + arg->copyA = copyAt; + } + } else { + if (arg->transa == 0) { + arg->copyA = copySumAn; + } else { + arg->copyA = copySumAt; + } + } + + if (arg->ao == 0) { // No need to compute B column sum if ao is zero + if (arg->transb == 0) { + arg->copyB = copyBn; + } else { + arg->copyB = copyBt; + } + } else { + if (arg->transb == 0) { + arg->copyB = copySumBn; + } else { + arg->copyB = copySumBt; + } + } + + arg->kernel = kern; + arg->kernel_b = kern_b; + arg->kernel_r = kern_r; + arg->kernel_c = kern_c; + arg->kernel_b0 = kern_b0; + arg->kernel_b0_b = kern_b0_b; + arg->kernel_b0_r = kern_b0_r; + arg->kernel_b0_c = kern_b0_c; + arg -> gemv_s8u8s32_kernel = gemv_s8u8s32_kern; + arg -> gemv_u8s8s32_kernel = gemv_u8s8s32_kern; +} + +mkldnn_status_t jit_avx512_core_gemm_s8u8s32( + const char *transA, const char *transB, const char *offsetC, + const int *m, const int *n, const int *k, + const float *alpha, const int8_t *a, const int *lda, const int8_t *oa, + const uint8_t *b, const int *ldb, const int8_t *ob, + const float *beta, int32_t *c, const int *ldc, const int32_t *oc) +{ + char transa = *transA; + char transb = *transB; + char offsetc = *offsetC; + + blas_t args; + + // Initialize blas structure + args.m = *m; + args.n = *n; + args.k = *k; + args.alpha = alpha; + args.a = a; + args.lda = *lda; + args.b = b; + args.ldb = *ldb; + args.beta = beta; + args.c = c; + args.ldc = *ldc; + args.transa = (transa == 'N' || transa == 'n') ? 0 : 1; + args.transb = (transb == 'N' || transb == 'n') ? 0 : 1; + args.um = 0; + args.un = 0; + args.bm = 0; + args.bn = 0; + args.bk = 0; + args.copyA = NULL; + args.copyB = NULL; + args.kernel = NULL; + args.kernel_b0 = NULL; + args.ao = *oa; + args.bo = *ob; + args.co = oc; + + if (offsetc == 'F' || offsetc == 'f') { + args.offsetc = FIX_OFFSET; + } else if (offsetc == 'R' || offsetc == 'r') { + args.offsetc = ROW_OFFSET; + } else { // offsetc == 'C' || offsetc == 'c' + args.offsetc = COL_OFFSET; + } + + jit_init(&args); + int result = gemm_threading_driver(&args); + + return (result < 0) ? mkldnn_out_of_memory : mkldnn_success; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp new file mode 100644 index 0000000000..b2e2902a12 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp @@ -0,0 +1,38 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX512_CORE_GEMM_S8U8S32_HPP +#define JIT_AVX512_CORE_GEMM_S8U8S32_HPP + +#include +#include "mkldnn_types.h" + +namespace mkldnn { +namespace impl { +namespace cpu { + +mkldnn_status_t jit_avx512_core_gemm_s8u8s32( + const char *transA, const char *transB, const char *offsetC, + const int *m, const int *n, const int *k, + const float *alpha, const int8_t *a, const int *lda, const int8_t *oa, + const uint8_t *b, const int *ldb, const int8_t *ob, + const float *beta, int32_t *c, const int *ldc, const int32_t *oc); + +} +} +} + +#endif // JIT_AVX512_CORE_GEMM_S8U8S32_HPP diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp new file mode 100644 index 0000000000..57554a1852 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp @@ -0,0 +1,539 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_avx512_core_gemm_s8u8s32_kern.hpp" + + +#ifdef _WIN32 +static const bool is_windows = 1; +#else +static const bool is_windows = 0; +#endif + + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; + + + + +// Convert between vector register lengths. +static inline Xmm make_xmm(const Xmm &v) { return Xmm(v.getIdx()); } +static inline Ymm make_ymm(const Xmm &v) { return Ymm(v.getIdx()); } + +// Load from or store to C. +void jit_avx512_core_gemm_s8u8s32_kern::c_load(const Xbyak::Xmm &dst, + const Xbyak::Address &src, int nelems) +{ + switch (nelems) { + default: vmovups(dst, src); break; + case 8: vmovups(make_ymm(dst), src); break; + case 4: vmovups(make_xmm(dst), src); break; + case 2: vmovlps(make_xmm(dst), src); break; + case 1: vmovss(make_xmm(dst), src); break; + } +} +void jit_avx512_core_gemm_s8u8s32_kern::c_store(const Xbyak::Address &dst, + const Xbyak::Xmm &src, int nelems) +{ + switch (nelems) { + default: vmovups(dst, src); break; + case 8: vmovups(dst, make_ymm(src)); break; + case 4: vmovups(dst, make_xmm(src)); break; + case 2: vmovsd(dst, make_xmm(src)); break; + case 1: vmovss(dst, make_xmm(src)); break; + } +} + +// Perform length-4 dot product accumulations of unsigned and signed bytes +// in parallel. +// Use vpdpbusd if VNNI available, otherwise emulate. +void jit_avx512_core_gemm_s8u8s32_kern::dot_product(const Xmm &dst, + const Xmm &src1, const Xmm &src2) +{ + if (vnni) + vpdpbusd(dst, src1, src2); + else { + vpmaddubsw(dp_scratch, src1, src2); + vpmaddwd(dp_scratch, ones, dp_scratch); + vpaddd(dst, dst, dp_scratch); + } +} + +// Inner kernel. +void jit_avx512_core_gemm_s8u8s32_kern::kernel_loop(int unroll_m, int unroll_n, + bool cfetch) +{ + int um_vecs = (unroll_m + 15) >> 4; + Label label_kernel_loop; + + L_aligned(label_kernel_loop); { + for (int h = 0; h < 4; h++) { + for (int j = 0; j < unroll_n; j++) { + const Zmm b = b_regs[j & 1]; + + vpbroadcastd(b, ptr[BO + isize * + (2 * j + 2 * h * unroll_n - offset_b)]); + dot_product(c_regs[0][j], b, a_regs[0]); + + if (j == 1 && !(h & 1)) + prefetch_b(ptr[BO + isize * (prefetch_size_b + + 2 * h * unroll_n - offset_b)]); + else if (j % 3 == 0) + prefetch_a(ptr[AO + isize * (prefetch_size_a + + 32 * (j / 3) + 2 * h * unroll_m - offset_a)]); + + for (int i = 1; i < um_vecs; i++) + dot_product(c_regs[i][j], b, a_regs[i]); + + if (cfetch && (j == std::min(1, unroll_n - 1))) { + if (h == 3) + lea(CO2, ptr[CO2 + LDC]); + else if (h < um_vecs) + prefetch_c(ptr[CO2 + (16 * h * size)]); + } + + if (h == 3 && j == std::min(3, unroll_n - 1)) + lea(AA, ptr[AA + (32 * isize)]); + } + + for (int i = 0; i < um_vecs; i++) + vmovups(a_regs[i], ptr[AO + isize * + (32 * i + 2 * (h + 1) * unroll_m - offset_a)]); + + if (h == 2) + prefetch_x(ptr[AA - (offset_a * isize)]); + } + + add(AO, 8 * isize * unroll_m); + add(BO, 8 * isize * unroll_n); + sub(LoopCount, 1); + jg(label_kernel_loop, T_NEAR); + } +} + +// k remainder loop for kernel. +void jit_avx512_core_gemm_s8u8s32_kern::remainder_kernel(int unroll_m, + int unroll_n, int unroll_k, int bwidth) +{ + if ((unroll_m > IGEMM_UNROLL_M) || (unroll_n > IGEMM_UNROLL_N) + || (unroll_m < 0) || (unroll_n < 0)) + return; + + int um_vecs = (unroll_m + 15) >> 4; + + for (int h = 0; h < unroll_k; h++) { + for (int j = 0; j < unroll_n; j++) { + Zmm b = b_regs[j & 1]; + auto b_src = ptr[BO + (-isize * offset_b + + bwidth * (j + h * unroll_n))]; + + switch (bwidth) { + case 4: + vpbroadcastd(b, b_src); + break; + case 2: + vpbroadcastw(b, b_src); + break; + case 1: + vpbroadcastb(b, b_src); + break; + } + for (int i = 0; i < um_vecs; i++) + dot_product(c_regs[i][j], b, a_regs[i]); + } + + if (unroll_k > 1) { + for (int i = 0; i < um_vecs; i++) + vmovups(a_regs[i], ptr[AO + isize * (32 * i + + (h + 1) * 2 * unroll_m - offset_a)]); + } + } + + add(AO, unroll_k * unroll_m * bwidth); + add(BO, unroll_k * unroll_n * bwidth); +} + +// Inner loop. +void jit_avx512_core_gemm_s8u8s32_kern::innerloop(int unroll_m, int unroll_n) +{ + if ((unroll_m > IGEMM_UNROLL_M) || (unroll_n > IGEMM_UNROLL_N) + || (unroll_m < 0) || (unroll_n < 0)) + return; + + int um_vecs = (unroll_m + 15) >> 4; + int stage1 = unroll_n, stage2 = unroll_n; + + Label label_kernel_loop_1, label_k_main_loop_2, label_kernel_loop_2; + Label label_k_main_loop_3, label_kernel_loop_3; + Label label_k_remainder_loop_begin, label_k_rem_4, label_k_rem_2; + Label label_k_rem_1, label_update_begin; + + mov(AO, A); + for (int i = 0; i < um_vecs; i++) + vmovups(a_regs[i], ptr[AO + isize * (32 * i - offset_a)]); + + mov(LoopCount, K); + sar(LoopCount, 4); + jle(label_k_remainder_loop_begin, T_NEAR); + + // Main k loops, broken into three parts to time C prefetching. + sub(LoopCount, stage1 + stage2); + jle(label_k_main_loop_2, T_NEAR); + + kernel_loop(unroll_m, unroll_n, false); + + L_aligned(label_k_main_loop_2); + lea(CO2, ptr[CO1 + size * (std::min(unroll_m, 16) - 1)]); + add(LoopCount, stage1); + jle(label_k_main_loop_3, T_NEAR); + + kernel_loop(unroll_m, unroll_n, true); + + L_aligned(label_k_main_loop_3); + lea(CO2, ptr[CO1 + size * (std::min(unroll_m, 16) - 1)]); + add(LoopCount, stage2); + jle(label_k_remainder_loop_begin, T_NEAR); + + kernel_loop(unroll_m, unroll_n, true); + + // k remainder handling + L_aligned(label_k_remainder_loop_begin); + mov(LoopCount, K); + test(LoopCount, 8); + je(label_k_rem_4, T_NEAR); + + remainder_kernel(unroll_m, unroll_n, 2, 4); + + L_aligned(label_k_rem_4); + mov(LoopCount, K); + test(LoopCount, 4); + je(label_k_rem_2, T_NEAR); + + remainder_kernel(unroll_m, unroll_n, 1, 4); + + L_aligned(label_k_rem_2); + mov(LoopCount, K); + test(LoopCount, 2); + je(label_k_rem_1, T_NEAR); + + Zmm zero = zmm6; + Zmm tmp = zmm5; + + vpxorq(zero, zero, zero); + for (int i = 0; i < um_vecs; i++) { + Zmm a = a_regs[i]; + vbroadcasti64x4(a, ptr[AO + isize * (16 * i - offset_a)]); + vpunpcklwd(tmp, a, zero); + vpunpckhwd(a, a, zero); + vshufi32x4(a, tmp, a, 0x44); + vshufi32x4(a, a, a, 0xD8); + } + + remainder_kernel(unroll_m, unroll_n, 1, 2); + + L_aligned(label_k_rem_1); + mov(LoopCount, K); + test(LoopCount, 1); + je(label_update_begin, T_NEAR); + + vpxorq(zero, zero, zero); + for (int i = 0; i < um_vecs; i++) { + Zmm a = a_regs[i]; + vbroadcasti32x4(a, ptr[AO + isize * (8 * i - offset_a)]); + vpunpcklbw(tmp, a, zero); + vpunpckhbw(a, a, zero); + vinsertf128(make_ymm(a), make_ymm(tmp), make_xmm(a), 1); + vpunpcklwd(tmp, a, zero); + vpunpckhwd(a, a, zero); + vshufi32x4(a, tmp, a, 0x44); + vshufi32x4(a, a, a, 0xD8); + } + + remainder_kernel(unroll_m, unroll_n, 1, 1); + + // Add offsets and update C. + L_aligned(label_update_begin); + + if (enable_offset_r) { + // Add row offsets. + mov(rax, coffset_ry); + for (int j = 0; j < unroll_n; j++) { + Zmm row_offset = zmm0; + + vbroadcastss(row_offset, ptr[rax + size * j]); + + for (int i = 0; i < um_vecs; i++) + vpaddd(c_regs[i][j], c_regs[i][j], row_offset); + } + add(coffset_ry, size * unroll_n); + } + + if (enable_offset_c) { + // Add column offsets. + mov(rax, coffset_cy); + for (int i = 0; i < um_vecs; i++) { + Zmm col_offset = zmm0; + + c_load(col_offset, ptr[rax + size * 16 * i], unroll_m); + + for (int j = 0; j < unroll_n; j++) + vpaddd(c_regs[i][j], c_regs[i][j], col_offset); + } + } + + Reg64 LDC3 = rax; + lea(LDC3, ptr[LDC + LDC * 2]); + + // C updates. + int c_off_j = 0; + for (int j = 0; j < unroll_n; j++) { + if (j > 0 && (j & 3) == 0) { + lea(CO1, ptr[CO1 + LDC * 4]); + c_off_j += 4; + } + + int jj = j - c_off_j; + + for (int i = 0; i < um_vecs; i++) { + Zmm c = c_regs[i][j]; + Zmm c_old = zmm0; + decltype(LDC * jj) ldc_mult = (jj == 3) ? LDC3 : LDC * jj; + + auto c_mem = ptr[CO1 + ldc_mult + size * 16 * i]; + + if (beta_zero) + c_store(c_mem, c, unroll_m); + else { + c_load(c_old, c_mem, unroll_m); + vpaddd(c_old, c, c_old); + c_store(c_mem, c_old, unroll_m); + } + + vpxorq(c, c, c); + } + } + + lea(CO1, ptr[CO1 + LDC * (unroll_n - c_off_j)]); +} + +// Outer loop. +void jit_avx512_core_gemm_s8u8s32_kern::outerloop(int unroll_x, int unroll_y, + Label *&cur_outerloop_label) +{ + Label label_m_loop, label_n_loop, label_n_remainder_loops[6]; + + L(*cur_outerloop_label); + cur_outerloop_label++; + if (unroll_x >= IGEMM_UNROLL_M) { + mov(J, M); + cmp(J, unroll_x); + jl(*cur_outerloop_label, T_NEAR); // Jump to next outerloop label. + } else { + test(J, unroll_x); + jle(*cur_outerloop_label, T_NEAR); + } + + L_aligned(label_m_loop); { + mov(CO1, C); + add(C, unroll_x * size); + + mov(BO, B); + + mov(AA, K); + imul(AA, AA, unroll_x * isize); + lea(AA, ptr[A + AA + isize * prefetch_size_a]); + + if (enable_offset_c) { + mov(rax, coffset_cx); + mov(coffset_cy, rax); + add(rax, unroll_x * size); + mov(coffset_cx, rax); + } + + if (enable_offset_r) { + mov(rax, coffset_rx); + mov(coffset_ry, rax); + } + + mov(I, N); + cmp(I, unroll_y); + jl(label_n_remainder_loops[0], T_NEAR); + + L_aligned(label_n_loop); { + innerloop(unroll_x, unroll_y); + sub(I, unroll_y); + cmp(I, unroll_y); + jge(label_n_loop, T_NEAR); + } + + align(16); + + int label_idx = 0; + for (int uy = 16; uy > 0; uy >>= 1) { + L(label_n_remainder_loops[label_idx++]); + if (unroll_y > uy) { + test(I, uy); + jle(label_n_remainder_loops[label_idx], T_NEAR); + + innerloop(unroll_x, uy); + align(16); + } + } + L(label_n_remainder_loops[label_idx]); + + mov(A, AO); + if (unroll_x >= IGEMM_UNROLL_M) { + sub(J, unroll_x); + cmp(J, unroll_x); + jge(label_m_loop); + } + } + + align(16); +} + +void jit_avx512_core_gemm_s8u8s32_kern::generate() +{ + // Prologue + preamble(); + sub(rsp, stack_alloc_size); + + if (is_windows) { + mov(A, arg_a); + mov(B, arg_b); + } + + mov(C, arg_c); + mov(LDC, arg_ldc); + + sub(A, -offset_a * isize); + sub(B, -offset_b * isize); + + mov(M, qword[M]); + mov(N, qword[N]); + mov(K, qword[K]); + + lea(LDC, ptr[LDC * size]); + + if (enable_offset_c) { + mov(rax, arg_coffset_c); + mov(coffset_cx, rax); + } + if (enable_offset_r) { + mov(rax, arg_coffset_r); + mov(coffset_rx, rax); + } + + for (int i = 0; i < (max_unroll_m >> 4); i++) { + for (int j = 0; j < max_unroll_n; j++) { + auto &c = c_regs[i][j]; + vpxorq(c, c, c); + } + } + + if (!vnni) { + mov(rax, 1); + movq(make_xmm(ones), rax); + vpbroadcastw(ones, make_xmm(ones)); + } + + Label outerloop_labels[8]; + Label *cur_outerloop_label = &outerloop_labels[0]; + + // Main m loop. + outerloop(IGEMM_UNROLL_M, IGEMM_UNROLL_N, cur_outerloop_label); + + // m remainder loops. + for (int um = 32; um > 0; um >>= 1) + if (IGEMM_UNROLL_M > um) + outerloop(um, IGEMM_UNROLL_N, cur_outerloop_label); + + L(*cur_outerloop_label); + + // Epilogue. + add(rsp, stack_alloc_size); + postamble(); +} + + +jit_avx512_core_gemm_s8u8s32_kern::jit_avx512_core_gemm_s8u8s32_kern(bool + beta_zero_, bool enable_offset_c_, bool enable_offset_r_) : + jit_generator(nullptr, 100000), arg_a(0), arg_b(0), arg_c(0), arg_ldc(0), + arg_coffset_c(0), arg_coffset_r(0), coffset_cx(0), coffset_cy(0), + coffset_rx(0), coffset_ry(0) +{ + beta_zero = beta_zero_; + enable_offset_c = enable_offset_c_; + enable_offset_r = enable_offset_r_; + vnni = mayiuse(avx512_core_vnni); + + // Assign integer registers + M = is_windows ? rcx : rdi; + N = is_windows ? rdx : rsi; + K = is_windows ? r8 : rdx; + A = is_windows ? rsi : r8; + B = r9; + C = r10; + LDC = r11; + I = r12; + J = r13; + LoopCount = rax; + AO = r14; + BO = r15; + CO1 = rbx; + CO2 = rbp; + AA = is_windows ? rdi : rcx; + + // Assign vector registers + dp_scratch = zmm6; + ones = zmm7; + for (int i = 0; i < (max_unroll_m >> 4); i++) + a_regs[i] = Zmm(i); + b_regs[0] = zmm4; + b_regs[1] = zmm5; + + int rn = 0; + for (int i = 0; i < (max_unroll_m >> 4); i++) + for (int j = 0; j < max_unroll_n; j++) + c_regs[i][j] = Zmm(8 + rn++); + + // Assign stack variables. + stack_alloc_size = 32; + auto args_offset = stack_alloc_size + get_size_of_abi_save_regs() + + 8 + (is_windows ? 48 : 0); + + arg_a = ptr[rsp + (args_offset - 16)]; + arg_b = ptr[rsp + (args_offset - 8)]; + arg_c = ptr[rsp + (args_offset + 0)]; + arg_ldc = ptr[rsp + (args_offset + 8)]; + arg_coffset_c = ptr[rsp + (args_offset + 16)]; + arg_coffset_r = ptr[rsp + (args_offset + 24)]; + + coffset_cx = qword[rsp + 0]; + coffset_cy = qword[rsp + 8]; + coffset_rx = qword[rsp + 16]; + coffset_ry = qword[rsp + 24]; + + generate(); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp new file mode 100644 index 0000000000..e8efcc1cc8 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp @@ -0,0 +1,101 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef IGEMM_KERNEL_GENERATOR_HPP +#define IGEMM_KERNEL_GENERATOR_HPP + +#include "jit_generator.hpp" + + +namespace mkldnn { +namespace impl { +namespace cpu { + +class jit_avx512_core_gemm_s8u8s32_kern : public jit_generator { +public: + jit_avx512_core_gemm_s8u8s32_kern(bool beta_zero_, bool enable_offset_c_, + bool enable_offset_r_); + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_gemm_s8u8s32_kern); + +protected: + bool beta_zero; + bool enable_offset_c, enable_offset_r; + bool vnni; + + void prefetch_a(const Xbyak::Address &src) { + prefetcht0(src); + } + void prefetch_b(const Xbyak::Address &src) { + prefetcht0(src); + } + void prefetch_c(const Xbyak::Address &src) { + prefetchw(src); + } + void prefetch_x(const Xbyak::Address &src) { + prefetcht0(src); + } + + void c_load(const Xbyak::Xmm &dst, const Xbyak::Address &src, int nelems); + void c_store(const Xbyak::Address &dst, const Xbyak::Xmm &src, int nelems); + + void dot_product(const Xbyak::Xmm &dst, const Xbyak::Xmm &src1, + const Xbyak::Xmm &src2); + void kernel_loop(int unroll_m, int unroll_n, bool cfetch); + void remainder_kernel(int unroll_m, int unroll_n, int unroll_k, int bwidth); + void innerloop(int unroll_m, int unroll_n); + void outerloop(int unroll_x, int unroll_y, Xbyak::Label *&outerloop_label); + + void generate(); + + +private: + static const int IGEMM_UNROLL_M = 48; + static const int IGEMM_UNROLL_N = 8; + + static const int isize = 2; + static const int size = 4; + + // Prefetch configuration + static const int prefetch_size_a = 32 * 5; + static const int prefetch_size_b = 32 * 4; + + static const int offset_a = 256, offset_b = 256; + static const int max_unroll_m = 48, max_unroll_n = 8; + + // Integer register assignments + Xbyak::Reg64 M, N, K, A, B, C, LDC, I, J, LoopCount; + Xbyak::Reg64 AO, BO, CO1, CO2, AA; + + // Vector register assignments + Xbyak::Zmm dp_scratch, ones, a_regs[max_unroll_m >> 4], b_regs[2]; + Xbyak::Zmm c_regs[max_unroll_m >> 4][max_unroll_n]; + + // Stack variable assignments + int stack_alloc_size; + Xbyak::Address arg_a, arg_b, arg_c, arg_ldc, arg_coffset_c, arg_coffset_r; + Xbyak::Address coffset_cx, coffset_cy, coffset_rx, coffset_ry; + + void L_aligned(Xbyak::Label &label, int alignment = 16) { + align(alignment); + L(label); + } +}; + +} +} +} + +#endif /* header guard */ diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp new file mode 100644 index 0000000000..4f0b10dadd --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp @@ -0,0 +1,290 @@ +/******************************************************************************* + * Copyright 2019 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "gemv.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +int gemm_s8u8s32_jump_to_gemv_s8u8s32(blas_t *arg) { + + blas_t arg_gemv = *arg; + + if ((arg -> offsetc == FIX_OFFSET) && // Fix offset + (arg -> ao == 0) && + (arg -> bo == 0) && + (arg -> co[0] == 0) && + (*(arg -> alpha) == 1.0f) && + ((*(arg -> beta) == 1.0f) || *(arg -> beta) == 0.0f)) { + + if (arg -> n == 1) { + + if (arg -> transa == 1) { // A transpose + arg_gemv.n = arg -> k; + arg_gemv.ldc = 1; + arg_gemv.swap = 0; + if (arg -> transb == 0) { // B non transpose + arg_gemv.ldb = 1; + } + // B transpose arg_gemv.ldb = arg -> ldb + gemv_threading_driver(&arg_gemv); + return 1; + } + } + + if (arg -> m == 1) { + + if (arg -> transb == 0) { // B non transpose + arg_gemv.transa = 1; + arg_gemv.m = arg -> n; + arg_gemv.n = arg -> k; + arg_gemv.a = (int8_t *) arg -> b; + arg_gemv.lda = arg -> ldb; + arg_gemv.b = (uint8_t *) arg -> a; + arg_gemv.swap = 1; + if (arg -> transa == 0) { // A non transpose + arg_gemv.ldb = arg -> lda; + } + else { // A transpose + arg_gemv.ldb = 1; + } + gemv_threading_driver(&arg_gemv); + return 1; + } + } + } + + return 0; +} + + +int gemv_kernel_driver(blas_t *arg) { + + dim_t m = arg -> m; + dim_t n = arg -> n; + uint8_t *a = (uint8_t *) arg -> a; + dim_t lda = arg -> lda; + int8_t *b = (int8_t *) arg -> b; + float beta = *(arg -> beta); + + if (arg -> swap) { + arg -> gemv_u8s8s32_kernel(m, n, 1.0f, a, lda, b, beta, arg -> c); + } + else { + arg -> gemv_s8u8s32_kernel(arg -> m, arg -> n, 1.0f, arg -> a, + arg -> lda, arg -> b, *(arg -> beta), arg -> c); + } + + return 0; +} + +int gemv_threading_driver(blas_t *arg) { + + dim_t nthr_m, nthr_n = 1; + dim_t MB, NB, UM = 16, UN = 64; + dim_t BLOCKM = 192, BLOCKN = 3072; + int status; + dim_t i; + + dim_t nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads(); + + uint8_t *new_x = NULL; + int32_t *tmp_y = NULL, *new_y = NULL; + + dim_t m = arg -> m, n = arg -> n; + + blas_t arg_seq = *arg; + float zero = 0.0f; + + nthr_m = std::min(std::max(m / BLOCKM, (dim_t) 1), nthr); + MB = m / nthr_m; + MB = (((MB / UM) * UM) == MB) ? MB : (MB / UM) * UM + UM; + nthr_m = (((m / MB) * MB) == m) ? m / MB : m / MB + 1; + nthr_m = std::min(std::max(nthr_m, (dim_t) 1), nthr); + + while ((nthr_m * (nthr_n + 1) <= nthr) && ((n / (nthr_n + 1)) >= BLOCKN)) { + nthr_n++; + } + + NB = n / nthr_n; + NB = (((NB / UN) * UN) == NB) ? NB : (NB / UN) * UN + UN; + nthr_n = (((n / NB) * NB) == n) ? n / NB : n / NB + 1; + nthr_n = std::min(std::max(nthr_n, (dim_t) 1), nthr / nthr_m); + + nthr = nthr_m * nthr_n; + + if (arg -> ldb != 1) { + new_x = (uint8_t *)malloc(n, 64); + if (new_x == NULL) + return 1; + for (i = 0; i < n; i++) { + new_x[i] = (arg -> b)[i * arg -> ldb]; + } + arg_seq.b = new_x; + arg_seq.ldb = 1; + } + else new_x = (uint8_t *) arg -> b; + + if (arg -> ldc != 1) { + new_y = (int32_t *) malloc(nthr_m * PADD_BYTESIZE_ONPAGE(MB, sizeof(int32_t)), 64); + if (new_y == NULL) { + if (arg -> ldb != 1) { + free(new_x); + } + return 1; + } + } + + // GEMV computation + if (nthr == 1) { + + if (arg -> ldc != 1) { + if (*(arg -> beta) != 0.0f) { + for (i = 0; i < m; i++) { + new_y[i] = arg -> c[i * arg -> ldc]; + } + } + } + + status = gemv_kernel_driver(&arg_seq); + + if (arg -> ldc != 1) { + for (i = 0; i < m; i++) { + arg -> c[i * arg -> ldc] = new_y[i]; + } + } + + if (arg -> ldb != 1) { + free(new_x); + } + if (arg -> ldc != 1) { + free(new_y); + } + return status; + } + + if (nthr_n > 1) { + tmp_y = (int32_t *) malloc((nthr_n - 1) * PADD_BYTESIZE_ONPAGE(m, sizeof(int32_t)), PAGESIZE); + if (tmp_y == NULL) { + if (arg -> ldb != 1) { + free(new_x); + } + return 1; + } + } + + parallel_nd((int) nthr, [&](const dim_t ithr) { + + dim_t m_from, m_to, myM; + dim_t n_from, n_to, myN; + + dim_t n_id, m_id; + dim_t loc_incy = 1; + int32_t *loc_y; + + blas_t arg_loc = arg_seq; + int j; + + m_id = ithr / nthr_n; + n_id = ithr % nthr_n; + + m_from = MB * m_id; + m_to = MB * (m_id + 1); + if ((m_to > m) || (m_id == nthr_m - 1)) + m_to = m; + + myM = m_to - m_from; + + n_from = NB * n_id; + n_to = NB * (n_id + 1); + if ((n_to > n) || (n_id == nthr_n - 1)) + n_to = n; + + myN = n_to - n_from; + + if (n_id != 0) { + arg_loc.beta = &zero; + loc_y = tmp_y + (NEXT_THR_STRIDE(m, sizeof(int32_t))) * (n_id - 1) + m_from; + } + else { + if (arg -> ldc == 1) { + loc_y = arg_seq.c + m_from; + } + else { + // need to copy the block of c in new_y + loc_y = new_y + m_id * NEXT_THR_STRIDE(MB, sizeof(int32_t)); + if (*(arg -> beta) != 0.0f) { + for (j = 0; j < myM; j++) { + loc_y[j] = arg -> c[(m_from + j) * arg -> ldc]; + } + } + } + } + + arg_loc.m = myM; + arg_loc.n = myN; + arg_loc.a = arg_seq.a + m_from * arg_seq.lda + n_from; + arg_loc.b = arg_seq.b + n_from; + arg_loc.c = loc_y; + arg_loc.ldc = loc_incy; + + gemv_kernel_driver(&arg_loc); + + if ((n_id == 0) && (arg -> ldc != 1)) { + for (j = 0; j < myM; j++) { + arg -> c[(m_from + j) * arg -> ldc] = loc_y[j]; + } + } + + }); + + if (nthr_n > 1) { + parallel_nd((int) nthr_m, [&](const dim_t ithr) { + + dim_t j, j_from, j_to, ii; + int32_t acc; + + j_from = MB * ithr; + j_to = MB * (ithr + 1); + if ((j_to > m) || (ithr == nthr - 1)) + j_to = m; + + for (j = j_from; j < j_to; j++) { + acc = 0; + for (ii = 0; ii < nthr_n - 1; ii++) { + acc += tmp_y[ii * NEXT_THR_STRIDE(m, sizeof(int32_t)) + j]; + } + (arg -> c)[j * arg -> ldc] += acc; + } + }); + free(tmp_y); + } + + if (arg -> ldb != 1) { + free(new_x); + } + + if (arg -> ldc != 1) { + free(new_y); + } + + return 0; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp new file mode 100644 index 0000000000..c57a8c1d12 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp @@ -0,0 +1,411 @@ +/******************************************************************************* + * Copyright 2019 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp" + +#ifdef _WIN32 +#define is_windows 1 +#else +#define is_windows 0 +#endif + +namespace mkldnn { +namespace impl { +namespace cpu { + +void jit_avx512_core_gemv_s8u8s32_kern::vnni(Xbyak::Zmm acc, Xbyak::Zmm b, + Xbyak::Zmm a, Xbyak::Zmm tmp, + Xbyak::Zmm one, bool swap, + int use_vnni) { + + if (use_vnni) { + if (swap) + vpdpbusd(acc, a, b); + else + vpdpbusd(acc, b, a); + } + + else { + if (swap) + vpmaddubsw(tmp, a, b); + else + vpmaddubsw(tmp, b, a); + vpmaddwd(tmp, tmp, one); + vpaddd(acc, tmp, acc); + } + +} + +void jit_avx512_core_gemv_s8u8s32_kern::n_loop_body(int start_a_idx, int start_acc_idx, + int b_idx, int nreg_acc, + Xbyak::Reg64 A, Xbyak::Reg64 lda, + Xbyak::Reg64 X, Xbyak::Zmm tmp, + Xbyak::Zmm one, bool swap, int use_vnni, + int use_mask, Xbyak::Opmask mask_n) { + + int i; + int nreg_A = nreg_acc / 2 + (nreg_acc % 2); + + // load X + j + if (use_mask) + vmovdqu8(Xbyak::Zmm(b_idx) | mask_n | T_z, ptr[X]); + else + vmovdqu8(Xbyak::Zmm(b_idx), ptr[X]); + + xor_(r14, r14); + // load values of A + for (i = 0; i < nreg_A; i++) { + if (use_mask) + vmovdqu8(Xbyak::Zmm(start_a_idx + i) | mask_n | T_z, ptr[A + r14]); + else + vmovdqu8(Xbyak::Zmm(start_a_idx + i), ptr[A + r14]); + add(r14, lda); + } + + for (i = 0; i < nreg_A; i++) { + // vnni (acc, b, a, tmp, one, swap, use_vnni) + vnni(Xbyak::Zmm(start_acc_idx + i), Xbyak::Zmm(b_idx), + Xbyak::Zmm(start_a_idx + i), tmp, one, swap, use_vnni); + } + + for (i = 0; i < nreg_A - (nreg_acc % 2); i++) { + if (use_mask) + vmovdqu8(Xbyak::Zmm(start_a_idx + i) | mask_n | T_z, ptr[A + r14]); + else + vmovdqu8(Xbyak::Zmm(start_a_idx + i), ptr[A + r14]); + add(r14, lda); + } + + for (i = 0; i < nreg_A - (nreg_acc % 2); i++) { + vnni(Xbyak::Zmm(start_acc_idx + i + nreg_A), Xbyak::Zmm(b_idx), + Xbyak::Zmm(start_a_idx + i), tmp, one, swap, use_vnni); + } + +} + +void jit_avx512_core_gemv_s8u8s32_kern::shuffle_and_add(Xbyak::Zmm dest, Xbyak::Zmm A, + Xbyak::Zmm B, Xbyak::Zmm C, + Xbyak::Zmm D) { + + vshufi32x4(dest, A, C, 0x44); + vshufi32x4(A, A, C, 0xEE); + vpaddd(C, dest, A); // C = A0 + A2|A1 + A3|C0 + C2|C1 + C3 + + vshufi32x4(dest, B, D, 0x44); + vshufi32x4(B, B, D, 0xEE); + vpaddd(D, dest, B); // D = B0 + B2|B1 + B3|D0 + D2|D1 + D3 + + vshufi32x4(A, C, D, 0x88); + vshufi32x4(B, C, D, 0xDD); + vpaddd(dest, A, B); // dest = SAi|SBi|SCi|SDi + +} + +void jit_avx512_core_gemv_s8u8s32_kern::update_c(int nreg_acc, Xbyak::Reg64 Y, + int start_a_idx, int start_acc_idx, + Xbyak::Xmm beta, int use_mask, + Xbyak::Opmask mask_m) { + + int l, i, k, j, last_it; + Xbyak::Label store_label; + + l = 0; + for (k = 0; k < nreg_acc; k += 8) { + for (i = 0, j = k; i < 8; i += 4, j += 2) { + if (j < nreg_acc) { + // shuffle per block of 4 registers + shuffle_and_add(Xbyak::Zmm(start_a_idx + l), // dest + Xbyak::Zmm(start_acc_idx + j), // A = acc0 + Xbyak::Zmm(start_acc_idx + 1 + j), // B = acc1 + Xbyak::Zmm(start_acc_idx + 4 + j), // C = acc4 + Xbyak::Zmm(start_acc_idx + 5 + j)); // D = acc5 + + // extract low and high from dest and hadd + vextracti32x8(Xbyak::Ymm(start_a_idx + l + 1), Xbyak::Zmm(start_a_idx + l), 0); + vextracti32x8(Xbyak::Ymm(start_a_idx + l + 2), Xbyak::Zmm(start_a_idx + l), 1); + vphaddd(Xbyak::Ymm(start_a_idx + l), + Xbyak::Ymm(start_a_idx + l + 1), + Xbyak::Ymm(start_a_idx + l + 2)); + } + l++; + } + + vphaddd(Xbyak::Ymm(start_a_idx + l), + Xbyak::Ymm(start_a_idx + l - 2), + Xbyak::Ymm(start_a_idx + l - 1)); + + l++; + } + + // eventually add with C and store new value + vxorps(Xbyak::Ymm(start_a_idx), + Xbyak::Ymm(start_a_idx), + Xbyak::Ymm(start_a_idx)); + vucomiss(beta, Xbyak::Ymm(start_a_idx)); + je(store_label, T_NEAR); + + // beta = 1 + for (k = 0, l = 2; k < nreg_acc; k += 8, l += 3) { + // load Y and add + last_it = (k + 8) > nreg_acc; + if (use_mask && last_it) + vmovdqu32(Xbyak::Ymm(start_a_idx + k / 8) | mask_m | T_z, ptr[Y + (k / 8) * 32]); + else + vmovdqu32(Xbyak::Ymm(start_a_idx + k / 8), ptr[Y + (k / 8) * 32]); + + vpaddd(Xbyak::Ymm(start_a_idx + l), + Xbyak::Ymm(start_a_idx + l), + Xbyak::Ymm(start_a_idx + k / 8)); + } + + // store + aligned_label(store_label); + for (k = 0, l = 2; k < nreg_acc; k += 8, l += 3) { + last_it = (k + 8) > nreg_acc; + if (use_mask && last_it) + vmovdqu32(ptr[Y + (k / 8) * 32], Xbyak::Ymm(start_a_idx + l) | mask_m); + else + vmovdqu32(ptr[Y + (k / 8) * 32], Xbyak::Ymm(start_a_idx + l)); + } + +} + +template +T jit_avx512_core_gemv_s8u8s32_kern::generate(int use_vnni) { + + Xbyak::Opmask mask_n = k1, mask_m = k2; + Xbyak::Label one_label, m_tail_label, m_loop_label, n_loop_label; + Xbyak::Label n_tail_label, update_c_label, end_label; + constexpr unsigned int n_labels = (1 << unroll_m) - 1; + Xbyak::Label m_tail_label_case[n_labels]; + Xbyak::Label n_loop_label_case[n_labels]; + Xbyak::Label n_tail_label_case[n_labels]; + Xbyak::Label update_c_label_case[n_labels]; + + int i, ii; + + Xbyak::Zmm one, tmp; + Xbyak::Reg64 n = abi_param2, m = abi_param1; + Xbyak::Reg64 A = is_windows ? abi_param4 : abi_param3; + Xbyak::Reg64 lda = is_windows ? abi_param3 : abi_param4; + Xbyak::Reg64 X = is_windows ? rdi : r8; + Xbyak::Xmm beta = xmm1; + Xbyak::Reg64 Y = is_windows ? rsi : r9; + + bool swap = !std::is_same::value; + + // Windows: read on the stack lda, X, beta, Y + + int zmm_idx = 1; + int nreg_acc = 1 << unroll_m; + int nreg_A = 1 << (unroll_m - 1); + int nreg_A_acc = nreg_acc + nreg_A; + + if (!use_vnni) { + // set a zmm register to one + tmp = Xbyak::Zmm(0); + one = Xbyak::Zmm(zmm_idx + 1); + zmm_idx += 2; // one + tmp + } + else { + beta = xmm0; + } + + preamble(); + + if (is_windows) { + mov(lda, ptr[rsp + get_size_of_abi_save_regs() + 40]); + mov(X, ptr[rsp + get_size_of_abi_save_regs() + 48]); + movss(beta, ptr[rsp + get_size_of_abi_save_regs() + 56]); + mov(Y, ptr[rsp + get_size_of_abi_save_regs() + 64]); + } + + if (use_vnni && !is_windows) { + movaps(beta, xmm1); + } + + mov(rax, (1 << unroll_n) - 1); + kmovq(k3, rax); + + and_(rax, n); // rax contains n & ((1 << unroll_n) - 1) + mov(rbx, 1); + shlx(rbx, rbx, rax); + sub(rbx, 1); + kmovq(mask_n, rbx); + // mask_n set (AVX512 only), can use rax and rbx again + + // set mask_m for update of the C matrix + // load/store on the C matrix use Ymm so tail according to Ymm size + mov(rax, 7); // 8 * 32 = 256 Ymm size + and_(rax, m); // rax contains m & 7 + mov(rbx, 1); + shlx(rbx, rbx, rax); + sub(rbx, 1); + kmovq(mask_m, rbx); + // mask_m set (AVX512 only), can use rax and rbx again + + // setup register of ones when VNNI instructions not available + if (!use_vnni) { + vmovdqu16(one, ptr[rip + one_label]); + } + + // M loop + // base pointer for A rax contains a + i * lda + // Loop stop when rax >= a + (m & mask_um) * lda = rbx + // loop increment r10 = um * lda + // rbp = Y + i + mov(rax, A); // i = 0 + mov(rbx, m); + and_(rbx, mask_um); + imul(rbx, lda); + add(rbx, A); + mov(r10, lda); + sal(r10, unroll_m); + mov(rbp, Y); + + // N loop + // base pointer for X r11 contains x + j + // Loop stop when r11 >= x + n & mask_un = r12 + // loop increment un + // r13 = rax + j = A + i * lda + j + mov(r12, n); + and_(r12, mask_un); + add(r12, X); + + // M loop + aligned_label(m_loop_label); + cmp(rax, rbx); + jge(m_tail_label, T_NEAR); + + // enter M loop + for(i = 0; i < nreg_acc; i++) { + vpxorq(Xbyak::Zmm(i + zmm_idx + nreg_A), + Xbyak::Zmm(i + zmm_idx + nreg_A), + Xbyak::Zmm(i + zmm_idx + nreg_A)); + } + + // N loop + mov(r11, X); // j = 0 + mov(r13, rax); + aligned_label(n_loop_label); + cmp(r11, r12); + jge(n_tail_label, T_NEAR); + + // enter N loop + + n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, nreg_acc, + r13, lda, r11, tmp, one, swap, use_vnni, 0, mask_n); + + // increment rax with un + add(r11, 1 << unroll_n); + add(r13, 1 << unroll_n); + jmp(n_loop_label, T_NEAR); + // end N loop + + // N tail + aligned_label(n_tail_label); + + ktestq(mask_n, k3); + je(update_c_label, T_NEAR); + n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, nreg_acc, + r13, lda, r11, tmp, one, swap, use_vnni, 1, mask_n); + + // update C matrix + aligned_label(update_c_label); + + update_c(nreg_acc, rbp, zmm_idx, zmm_idx + nreg_A, beta, 0, mask_m); + + // increment rax with um * lda + add(rax, r10); + add(rbp, 1 << (unroll_m + 2)); + jmp(m_loop_label, T_NEAR); + // end M loop + + // M tail + aligned_label(m_tail_label); + + // r10 will contain m_tail = m % unroll_m = m & (1 << unroll_m) - 1 + mov(r10, m); + and_(r10, (1 << unroll_m) - 1); + for (ii = 1; ii < 1 << unroll_m; ii++) { + aligned_label(m_tail_label_case[ii-1]); + cmp(r10, ii); + if (ii == (1 << unroll_m) - 1) + jne(end_label, T_NEAR); + else + jne(m_tail_label_case[ii], T_NEAR); + + // m_tail = i, use i accumulators + + for(i = 0; i < ii; i++) { + vpxorq(Xbyak::Zmm(i + zmm_idx + nreg_A), + Xbyak::Zmm(i + zmm_idx + nreg_A), + Xbyak::Zmm(i + zmm_idx + nreg_A)); + } + + // N loop + mov(r11, X); // j = 0 + mov(r13, rax); + aligned_label(n_loop_label_case[ii - 1]); + cmp(r11, r12); + jge(n_tail_label_case[ii - 1], T_NEAR); + + n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, ii, r13, + lda, r11, tmp, one, swap, use_vnni, 0, mask_n); + + // increment rax with un + add(r11, 1 << unroll_n); + add(r13, 1 << unroll_n); + jmp(n_loop_label_case[ii - 1], T_NEAR); + // end N loop + + // N tail + aligned_label(n_tail_label_case[ii - 1]); + ktestq(mask_n, k3); + je(update_c_label_case[ii - 1], T_NEAR); + n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, ii, r13, + lda, r11, tmp, one, swap, use_vnni, 1, mask_n); + + // update C matrix + aligned_label(update_c_label_case[ii - 1]); + update_c(ii, rbp, zmm_idx, zmm_idx + nreg_A, beta, 1, mask_m); + + if (ii < ((1 << unroll_m) - 1)) + jmp(end_label, T_NEAR); + } + + aligned_label(end_label); + + postamble(); + + if (!use_vnni) { + aligned_label(one_label); + for (i = 0; i < size_vec_reg/8; i++) + dq(0x0001000100010001); + } + + return (T) getCode(); +} + +template jit_avx512_core_gemv_s8u8s32_kern::gemv_s8u8s32_kernel_t +jit_avx512_core_gemv_s8u8s32_kern::generate(int); + +template jit_avx512_core_gemv_s8u8s32_kern::gemv_u8s8s32_kernel_t +jit_avx512_core_gemv_s8u8s32_kern::generate(int); + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp new file mode 100644 index 0000000000..9ea23a5f56 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright 2019 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +class jit_avx512_core_gemv_s8u8s32_kern : jit_generator { + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_gemv_s8u8s32_kern); + + // assumes untoll_{m,n} are a power of 2 + static constexpr unsigned int unroll_m = 4; // real unrolling factor is 2^unroll_m + const int mask_um = 0xFFFFFFF0; + static constexpr unsigned int unroll_n = 6; // real unrolling factor is 2^unroll_n + const int mask_un = 0xFFFFFFC0; + const int size_vec_reg = 64; // bytes + + void aligned_label(Xbyak::Label &label, int alignment = 16) { + align(alignment); + L(label); + } + + void vnni(Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, bool, int); + void n_loop_body(int, int, int, int, Xbyak::Reg64, Xbyak::Reg64, + Xbyak::Reg64, Xbyak::Zmm, Xbyak::Zmm, bool, int, int, Xbyak::Opmask); + void shuffle_and_add(Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm); + void update_c(int, Xbyak::Reg64, int, int, Xbyak::Xmm, int, Xbyak::Opmask); + +public: + jit_avx512_core_gemv_s8u8s32_kern() : jit_generator(nullptr, GEMM_CODE_SIZE) {}; + + // m, n, alpha, a, lda, x, beta, y + typedef void (*gemv_s8u8s32_kernel_t)(const dim_t, const dim_t, const float, + const int8_t*, const dim_t, const uint8_t*, + const float, int32_t*); + typedef void (*gemv_u8s8s32_kernel_t)(const dim_t, const dim_t, const float, + const uint8_t*, const dim_t, const int8_t*, + const float, int32_t*); + + template + T generate(int use_vnni); + +}; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp new file mode 100644 index 0000000000..544cd2ff25 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp @@ -0,0 +1,819 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_an_kern::jit_avx512_core_u8_copy_an_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l170; +Xbyak::Label l1f0; +Xbyak::Label l20; +Xbyak::Label l224; +Xbyak::Label l234; +Xbyak::Label l240; +Xbyak::Label l254; +Xbyak::Label l32c; +Xbyak::Label l34; +Xbyak::Label l388; +Xbyak::Label l3b0; +Xbyak::Label l3c0; +Xbyak::Label l3cc; +Xbyak::Label l3dc; +Xbyak::Label l454; +Xbyak::Label l48c; +Xbyak::Label l4a8; +Xbyak::Label l4b8; +Xbyak::Label l4c4; +Xbyak::Label l4d8; +Xbyak::Label l570; +Xbyak::Label l5c4; +Xbyak::Label l5f0; +Xbyak::Label l60c; +Xbyak::Label l61c; +Xbyak::Label l628; +Xbyak::Label l638; +Xbyak::Label l6b0; +Xbyak::Label l6f4; +Xbyak::Label l720; +Xbyak::Label l73c; +Xbyak::Label l74c; +Xbyak::Label l758; +Xbyak::Label l76c; +Xbyak::Label l804; +Xbyak::Label l858; +Xbyak::Label l88c; +Xbyak::Label l8a4; +Xbyak::Label l8b2; +Xbyak::Label l8bc; +Xbyak::Label l8cc; +Xbyak::Label l944; +Xbyak::Label l98c; +Xbyak::Label l9b0; +Xbyak::Label l9c8; +Xbyak::Label l9d8; + + preamble(); +#ifdef _WIN32 + auto stacksize = get_size_of_abi_save_regs(); + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(M, qword[M]); + mov(N, qword[N]); + mov(LDA, qword[LDA]); + lea(LDA3, ptr[LDA+LDA*2]); + sub(A, -128); + sub(B, -128); + cmp(N, 0x30); + jl(l234, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + add(A, 0x30); + mov(I, M); + sar(I, 0x2); + jle(l170, T_NEAR); + align(4); + +L(l34); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm5); + punpckhwd(xmm2, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movdqu(xword[B-0x60], xmm4); + movdqu(xword[B-0x50], xmm2); + movdqu(xmm0, xword[A1-0x70]); + movdqu(xmm1, xword[A1+LDA*1-0x70]); + movdqu(xmm2, xword[A1+LDA*2-0x70]); + movdqu(xmm3, xword[A1+LDA3*1-0x70]); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm5); + punpckhwd(xmm2, xmm5); + movdqu(xword[B-0x40], xmm0); + movdqu(xword[B-0x30], xmm1); + movdqu(xword[B-0x20], xmm4); + movdqu(xword[B-0x10], xmm2); + movdqu(xmm0, xword[A1-0x60]); + movdqu(xmm1, xword[A1+LDA*1-0x60]); + movdqu(xmm2, xword[A1+LDA*2-0x60]); + movdqu(xmm3, xword[A1+LDA3*1-0x60]); + lea(A1, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm5); + punpckhwd(xmm2, xmm5); + movdqu(xword[B], xmm0); + movdqu(xword[B+0x10], xmm1); + movdqu(xword[B+0x20], xmm4); + movdqu(xword[B+0x30], xmm2); + sub(B, -192); + dec(I); + jg(l34, T_NEAR); + align(4); + +L(l170); + test(M, 0x2); + jle(l1f0, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1-0x70]); + movdqu(xmm2, xword[A1-0x60]); + add(A1, LDA); + movdqu(xmm3, xword[A1-0x80]); + movdqu(xmm4, xword[A1-0x70]); + movdqu(xmm5, xword[A1-0x60]); + add(A1, LDA); + movdqa(xmm6, xmm0); + punpcklbw(xmm0, xmm3); + punpckhbw(xmm6, xmm3); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm6); + movdqa(xmm6, xmm1); + punpcklbw(xmm1, xmm4); + punpckhbw(xmm6, xmm4); + movdqu(xword[B-0x60], xmm1); + movdqu(xword[B-0x50], xmm6); + movdqa(xmm6, xmm2); + punpcklbw(xmm2, xmm5); + punpckhbw(xmm6, xmm5); + movdqu(xword[B-0x40], xmm2); + movdqu(xword[B-0x30], xmm6); + sub(B, -96); + align(4); + +L(l1f0); + test(M, 0x1); + jle(l224, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1-0x70]); + movdqu(xmm2, xword[A1-0x60]); + add(A1, LDA); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movdqu(xword[B-0x60], xmm2); + sub(B, -48); + align(4); + +L(l224); + sub(N, 0x30); + cmp(N, 0x30); + jge(l20, T_NEAR); + align(4); + +L(l234); + cmp(N, 0x20); + jl(l3c0, T_NEAR); + align(4); + +L(l240); + mov(A1, A); + add(A, 0x20); + mov(I, M); + sar(I, 0x2); + jle(l32c, T_NEAR); + align(4); + +L(l254); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm5); + punpckhwd(xmm2, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movdqu(xword[B-0x60], xmm4); + movdqu(xword[B-0x50], xmm2); + movdqu(xmm0, xword[A1-0x70]); + movdqu(xmm1, xword[A1+LDA*1-0x70]); + movdqu(xmm2, xword[A1+LDA*2-0x70]); + movdqu(xmm3, xword[A1+LDA3*1-0x70]); + lea(A1, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm5); + punpckhwd(xmm2, xmm5); + movdqu(xword[B-0x40], xmm0); + movdqu(xword[B-0x30], xmm1); + movdqu(xword[B-0x20], xmm4); + movdqu(xword[B-0x10], xmm2); + sub(B, -128); + dec(I); + jg(l254, T_NEAR); + align(4); + +L(l32c); + test(M, 0x2); + jle(l388, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1-0x70]); + add(A1, LDA); + movdqu(xmm2, xword[A1-0x80]); + movdqu(xmm3, xword[A1-0x70]); + add(A1, LDA); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm2); + punpckhbw(xmm4, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm4); + movdqa(xmm4, xmm1); + punpcklbw(xmm1, xmm3); + punpckhbw(xmm4, xmm3); + movdqu(xword[B-0x60], xmm1); + movdqu(xword[B-0x50], xmm4); + sub(B, -64); + align(4); + +L(l388); + test(M, 0x1); + jle(l3b0, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1-0x70]); + add(A1, LDA); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l3b0); + sub(N, 0x20); + cmp(N, 0x20); + jge(l240, T_NEAR); + align(4); + +L(l3c0); + cmp(N, 0x10); + jl(l4b8, T_NEAR); + align(4); + +L(l3cc); + mov(A1, A); + add(A, 0x10); + mov(I, M); + sar(I, 0x2); + jle(l454, T_NEAR); + align(4); + +L(l3dc); + movdqu(xmm0, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm1, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm2, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm3, xword[A1-0x80]); + add(A1, LDA); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm1, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm1, xmm3); + movdqa(xmm3, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm3, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm1); + punpckhwd(xmm2, xmm1); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm3); + movdqu(xword[B-0x60], xmm4); + movdqu(xword[B-0x50], xmm2); + sub(B, -64); + dec(I); + jg(l3dc, T_NEAR); + align(4); + +L(l454); + test(M, 0x2); + jle(l48c, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm1, xword[A1-0x80]); + add(A1, LDA); + movdqa(xmm2, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm2, xmm1); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm2); + sub(B, -32); + align(4); + +L(l48c); + test(M, 0x1); + jle(l4a8, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + add(A1, LDA); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l4a8); + sub(N, 0x10); + cmp(N, 0x10); + jge(l3cc, T_NEAR); + align(4); + +L(l4b8); + cmp(N, 0x8); + jl(l61c, T_NEAR); + align(4); + +L(l4c4); + mov(A1, A); + add(A, 0x8); + mov(I, M); + sar(I, 0x3); + jle(l570, T_NEAR); + align(4); + +L(l4d8); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + dec(I); + jg(l4d8, T_NEAR); + align(4); + +L(l570); + test(M, 0x4); + jle(l5c4, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l5c4); + test(M, 0x2); + jle(l5f0, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l5f0); + test(M, 0x1); + jle(l60c, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l60c); + sub(N, 0x8); + cmp(N, 0x8); + jge(l4c4, T_NEAR); + align(4); + +L(l61c); + cmp(N, 0x4); + jl(l74c, T_NEAR); + align(4); + +L(l628); + mov(A1, A); + add(A, 0x4); + mov(I, M); + sar(I, 0x3); + jle(l6b0, T_NEAR); + align(4); + +L(l638); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + dec(I); + jg(l638, T_NEAR); + align(4); + +L(l6b0); + test(M, 0x4); + jle(l6f4, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l6f4); + test(M, 0x2); + jle(l720, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l720); + test(M, 0x1); + jle(l73c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l73c); + sub(N, 0x4); + cmp(N, 0x4); + jge(l628, T_NEAR); + align(4); + +L(l74c); + cmp(N, 0x2); + jl(l8b2, T_NEAR); + align(4); + +L(l758); + mov(A1, A); + add(A, 0x2); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l804, T_NEAR); + align(4); + +L(l76c); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm4, eax, 0x0); + punpcklbw(xmm1, xmm2); + punpcklbw(xmm3, xmm4); + punpcklwd(xmm1, xmm3); + punpcklqdq(xmm0, xmm1); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(LDA3); + jg(l76c, T_NEAR); + align(4); + +L(l804); + test(M, 0x4); + jle(l858, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l858); + test(M, 0x2); + jle(l88c, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + punpcklbw(xmm0, xmm1); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l88c); + test(M, 0x1); + jle(l8a4, T_NEAR); + mov(ax, word[A1-0x80]); + mov(word[B-0x80], ax); + sub(B, -2); + align(4); + +L(l8a4); + sub(N, 0x2); + cmp(N, 0x2); + jge(l758, T_NEAR); + align(4); + +L(l8b2); + cmp(N, 0x1); + jl(l9d8, T_NEAR); + align(4); + +L(l8bc); + mov(A1, A); + add(A, 0x1); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l944, T_NEAR); + align(4); + +L(l8cc); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x7); + movq(qword[B-0x80], xmm0); + sub(B, -8); + dec(LDA3); + jg(l8cc, T_NEAR); + align(4); + +L(l944); + test(M, 0x4); + jle(l98c, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l98c); + test(M, 0x2); + jle(l9b0, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + mov(byte[B-0x80], al); + mov(al, byte[A1-0x80]); + add(A1, LDA); + mov(byte[B-0x7f], al); + sub(B, -2); + align(4); + +L(l9b0); + test(M, 0x1); + jle(l9c8, T_NEAR); + mov(al, byte[A1-0x80]); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(l9c8); + sub(N, 0x1); + cmp(N, 0x1); + jge(l8bc, T_NEAR); + align(4); + +L(l9d8); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp new file mode 100644 index 0000000000..1c11fc6cef --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp @@ -0,0 +1,2209 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_at_kern::jit_avx512_core_u8_copy_at_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l1014; +Xbyak::Label l1390; +Xbyak::Label l159c; +Xbyak::Label l173c; +Xbyak::Label l18e4; +Xbyak::Label l1a7c; +Xbyak::Label l1a8c; +Xbyak::Label l1a98; +Xbyak::Label l1ab4; +Xbyak::Label l1c64; +Xbyak::Label l1d74; +Xbyak::Label l1e50; +Xbyak::Label l1f2c; +Xbyak::Label l1ffc; +Xbyak::Label l20; +Xbyak::Label l200c; +Xbyak::Label l2018; +Xbyak::Label l2034; +Xbyak::Label l2110; +Xbyak::Label l21a0; +Xbyak::Label l2210; +Xbyak::Label l2284; +Xbyak::Label l22f0; +Xbyak::Label l2300; +Xbyak::Label l230c; +Xbyak::Label l2324; +Xbyak::Label l2398; +Xbyak::Label l23e8; +Xbyak::Label l242c; +Xbyak::Label l2474; +Xbyak::Label l24b4; +Xbyak::Label l24c4; +Xbyak::Label l24d0; +Xbyak::Label l24e8; +Xbyak::Label l2520; +Xbyak::Label l254c; +Xbyak::Label l2578; +Xbyak::Label l25a8; +Xbyak::Label l25c8; +Xbyak::Label l25d6; +Xbyak::Label l25e0; +Xbyak::Label l25f0; +Xbyak::Label l260c; +Xbyak::Label l262c; +Xbyak::Label l264c; +Xbyak::Label l2668; +Xbyak::Label l2680; +Xbyak::Label l2690; +Xbyak::Label l44; +Xbyak::Label l58c; +Xbyak::Label l8b0; +Xbyak::Label lb14; +Xbyak::Label ld84; +Xbyak::Label lfdc; +Xbyak::Label lfec; +Xbyak::Label lff8; + + preamble(); +#ifdef _WIN32 + auto stacksize = get_size_of_abi_save_regs(); + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(N, qword[N]); + mov(M, qword[M]); + mov(LDA, qword[LDA]); + sub(A, -128); + sub(B, -128); + lea(LDA3, ptr[LDA+LDA*2]); + cmp(N, 0x30); + jl(lfec, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + mov(I, LDA); + shl(I, 0x5); + lea(I, ptr[I+LDA*8]); + lea(I, ptr[I+LDA*8]); + add(A, I); + mov(I, M); + sar(I, 0x4); + jle(l58c, T_NEAR); + align(4); + +L(l44); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B+0x40], xmm1); + movdqu(xword[B+0x100], xmm4); + movdqu(xword[B+0x1c0], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B+0x50], xmm1); + movdqu(xword[B+0x110], xmm4); + movdqu(xword[B+0x1d0], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B+0x60], xmm1); + movdqu(xword[B+0x120], xmm4); + movdqu(xword[B+0x1e0], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x50], xmm0); + movdqu(xword[B+0x70], xmm1); + movdqu(xword[B+0x130], xmm4); + movdqu(xword[B+0x1f0], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x40], xmm0); + movdqu(xword[B+0x80], xmm1); + movdqu(xword[B+0x140], xmm4); + movdqu(xword[B+0x200], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x30], xmm0); + movdqu(xword[B+0x90], xmm1); + movdqu(xword[B+0x150], xmm4); + movdqu(xword[B+0x210], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x20], xmm0); + movdqu(xword[B+0xa0], xmm1); + movdqu(xword[B+0x160], xmm4); + movdqu(xword[B+0x220], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x10], xmm0); + movdqu(xword[B+0xb0], xmm1); + movdqu(xword[B+0x170], xmm4); + movdqu(xword[B+0x230], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B], xmm0); + movdqu(xword[B+0xc0], xmm1); + movdqu(xword[B+0x180], xmm4); + movdqu(xword[B+0x240], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B+0x10], xmm0); + movdqu(xword[B+0xd0], xmm1); + movdqu(xword[B+0x190], xmm4); + movdqu(xword[B+0x250], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B+0x20], xmm0); + movdqu(xword[B+0xe0], xmm1); + movdqu(xword[B+0x1a0], xmm4); + movdqu(xword[B+0x260], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B+0x30], xmm0); + movdqu(xword[B+0xf0], xmm1); + movdqu(xword[B+0x1b0], xmm4); + movdqu(xword[B+0x270], xmm3); + sub(A1, -16); + sub(B, -768); + dec(I); + jg(l44, T_NEAR); + align(4); + +L(l58c); + test(M, 0x8); + jle(l8b0, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B+0x40], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B+0x50], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B+0x60], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x50], xmm0); + movdqu(xword[B+0x70], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x40], xmm0); + movdqu(xword[B+0x80], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x30], xmm0); + movdqu(xword[B+0x90], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x20], xmm0); + movdqu(xword[B+0xa0], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x10], xmm0); + movdqu(xword[B+0xb0], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B], xmm0); + movdqu(xword[B+0xc0], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B+0x10], xmm0); + movdqu(xword[B+0xd0], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B+0x20], xmm0); + movdqu(xword[B+0xe0], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B+0x30], xmm0); + movdqu(xword[B+0xf0], xmm1); + sub(A1, -8); + sub(B, -384); + align(4); + +L(l8b0); + test(M, 0x4); + jle(lb14, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x70], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x60], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x50], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x40], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x30], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x20], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x10], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B+0x10], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B+0x20], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B+0x30], xmm0); + sub(A1, -4); + sub(B, -192); + align(4); + +L(lb14); + test(M, 0x2); + jle(ld84, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x7); + movdqu(xword[B-0x80], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x70], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x60], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x50], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x40], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x30], xmm0); + sub(A1, -2); + sub(B, -96); + align(4); + +L(ld84); + test(M, 0x1); + jle(lfdc, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xf); + movdqu(xword[B-0x80], xmm0); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xf); + movdqu(xword[B-0x70], xmm0); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xf); + movdqu(xword[B-0x60], xmm0); + sub(B, -48); + align(4); + +L(lfdc); + sub(N, 0x30); + cmp(N, 0x30); + jge(l20, T_NEAR); + align(4); + +L(lfec); + cmp(N, 0x20); + jl(l1a8c, T_NEAR); + align(4); + +L(lff8); + mov(A1, A); + mov(I, LDA); + shl(I, 0x5); + add(A, I); + mov(I, M); + sar(I, 0x4); + jle(l1390, T_NEAR); + align(4); + +L(l1014); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B], xmm1); + movdqu(xword[B+0x80], xmm4); + movdqu(xword[B+0x100], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B+0x10], xmm1); + movdqu(xword[B+0x90], xmm4); + movdqu(xword[B+0x110], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B+0x20], xmm1); + movdqu(xword[B+0xa0], xmm4); + movdqu(xword[B+0x120], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x50], xmm0); + movdqu(xword[B+0x30], xmm1); + movdqu(xword[B+0xb0], xmm4); + movdqu(xword[B+0x130], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x40], xmm0); + movdqu(xword[B+0x40], xmm1); + movdqu(xword[B+0xc0], xmm4); + movdqu(xword[B+0x140], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x30], xmm0); + movdqu(xword[B+0x50], xmm1); + movdqu(xword[B+0xd0], xmm4); + movdqu(xword[B+0x150], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x20], xmm0); + movdqu(xword[B+0x60], xmm1); + movdqu(xword[B+0xe0], xmm4); + movdqu(xword[B+0x160], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x10], xmm0); + movdqu(xword[B+0x70], xmm1); + movdqu(xword[B+0xf0], xmm4); + movdqu(xword[B+0x170], xmm3); + sub(A1, -16); + sub(B, -512); + dec(I); + jg(l1014, T_NEAR); + align(4); + +L(l1390); + test(M, 0x8); + jle(l159c, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B+0x10], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B+0x20], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x50], xmm0); + movdqu(xword[B+0x30], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x40], xmm0); + movdqu(xword[B+0x40], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x30], xmm0); + movdqu(xword[B+0x50], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x20], xmm0); + movdqu(xword[B+0x60], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x10], xmm0); + movdqu(xword[B+0x70], xmm1); + sub(A1, -8); + sub(B, -256); + align(4); + +L(l159c); + test(M, 0x4); + jle(l173c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x70], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x60], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x50], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x40], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x30], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x20], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x10], xmm0); + sub(A1, -4); + sub(B, -128); + align(4); + +L(l173c); + test(M, 0x2); + jle(l18e4, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x7); + movdqu(xword[B-0x80], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x70], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x60], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + movdqu(xword[B-0x50], xmm0); + sub(A1, -2); + sub(B, -64); + align(4); + +L(l18e4); + test(M, 0x1); + jle(l1a7c, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xf); + movdqu(xword[B-0x80], xmm0); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xf); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + align(4); + +L(l1a7c); + sub(N, 0x20); + cmp(N, 0x20); + jge(lff8, T_NEAR); + align(4); + +L(l1a8c); + cmp(N, 0x10); + jl(l200c, T_NEAR); + align(4); + +L(l1a98); + mov(A1, A); + mov(I, LDA); + shl(I, 0x4); + add(A, I); + mov(I, M); + sar(I, 0x4); + jle(l1c64, T_NEAR); + align(4); + +L(l1ab4); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x40], xmm1); + movdqu(xword[B], xmm4); + movdqu(xword[B+0x40], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B-0x30], xmm1); + movdqu(xword[B+0x10], xmm4); + movdqu(xword[B+0x50], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B-0x20], xmm1); + movdqu(xword[B+0x20], xmm4); + movdqu(xword[B+0x60], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x50], xmm0); + movdqu(xword[B-0x10], xmm1); + movdqu(xword[B+0x30], xmm4); + movdqu(xword[B+0x70], xmm3); + sub(A1, -16); + sub(B, -256); + dec(I); + jg(l1ab4, T_NEAR); + align(4); + +L(l1c64); + test(M, 0x8); + jle(l1d74, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x40], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B-0x30], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B-0x20], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x50], xmm0); + movdqu(xword[B-0x10], xmm1); + sub(A1, -8); + sub(B, -128); + align(4); + +L(l1d74); + test(M, 0x4); + jle(l1e50, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x70], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x60], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x50], xmm0); + sub(A1, -4); + sub(B, -64); + align(4); + +L(l1e50); + test(M, 0x2); + jle(l1f2c, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x7); + movdqu(xword[B-0x80], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + movdqu(xword[B-0x70], xmm0); + sub(A1, -2); + sub(B, -32); + align(4); + +L(l1f2c); + test(M, 0x1); + jle(l1ffc, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0xf); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l1ffc); + sub(N, 0x10); + cmp(N, 0x10); + jge(l1a98, T_NEAR); + align(4); + +L(l200c); + cmp(N, 0x8); + jl(l2300, T_NEAR); + align(4); + +L(l2018); + mov(A1, A); + lea(A2, ptr[A1+LDA*4]); + lea(I, ptr[A1+LDA*8]); + mov(A, I); + mov(I, M); + sar(I, 0x4); + jle(l2110, T_NEAR); + align(4); + +L(l2034); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + sub(A1, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x60], xmm1); + movdqu(xword[B-0x40], xmm4); + movdqu(xword[B-0x20], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B-0x50], xmm1); + movdqu(xword[B-0x30], xmm4); + movdqu(xword[B-0x10], xmm3); + sub(B, -128); + dec(I); + jg(l2034, T_NEAR); + align(4); + +L(l2110); + test(M, 0x8); + jle(l21a0, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + sub(A1, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x60], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + align(4); + +L(l21a0); + test(M, 0x4); + jle(l2210, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + sub(A1, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + align(4); + +L(l2210); + test(M, 0x2); + jle(l2284, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x7); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l2284); + test(M, 0x1); + jle(l22f0, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x7); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l22f0); + sub(N, 0x8); + cmp(N, 0x8); + jge(l2018, T_NEAR); + align(4); + +L(l2300); + cmp(N, 0x4); + jl(l24c4, T_NEAR); + align(4); + +L(l230c); + mov(A1, A); + lea(A2, ptr[A1+LDA*2]); + lea(I, ptr[A1+LDA*4]); + mov(A, I); + mov(I, M); + sar(I, 0x4); + jle(l2398, T_NEAR); + align(4); + +L(l2324); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + sub(A1, -16); + movdqu(xmm2, xword[A2-0x80]); + movdqu(xmm3, xword[A2+LDA*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movdqu(xword[B-0x60], xmm4); + movdqu(xword[B-0x50], xmm3); + sub(B, -64); + dec(I); + jg(l2324, T_NEAR); + align(4); + +L(l2398); + test(M, 0x8); + jle(l23e8, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + sub(A1, -8); + movq(xmm2, qword[A2-0x80]); + movq(xmm3, qword[A2+LDA*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l23e8); + test(M, 0x4); + jle(l242c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + sub(A1, -4); + movd(xmm2, dword[A2-0x80]); + movd(xmm3, dword[A2+LDA*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l242c); + test(M, 0x2); + jle(l2474, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x3); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l2474); + test(M, 0x1); + jle(l24b4, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x3); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l24b4); + sub(N, 0x4); + cmp(N, 0x4); + jge(l230c, T_NEAR); + align(4); + +L(l24c4); + cmp(N, 0x2); + jl(l25d6, T_NEAR); + align(4); + +L(l24d0); + mov(A1, A); + lea(A2, ptr[A1+LDA*1]); + lea(I, ptr[A1+LDA*2]); + mov(A, I); + mov(I, M); + sar(I, 0x4); + jle(l2520, T_NEAR); + align(4); + +L(l24e8); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + movdqu(xmm1, xword[A2-0x80]); + sub(A2, -16); + movdqa(xmm2, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm2, xmm1); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm2); + sub(B, -32); + dec(I); + jg(l24e8, T_NEAR); + align(4); + +L(l2520); + test(M, 0x8); + jle(l254c, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + movq(xmm1, qword[A2-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l254c); + test(M, 0x4); + jle(l2578, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + movd(xmm1, dword[A2-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l2578); + test(M, 0x2); + jle(l25a8, T_NEAR); + mov(ax, word[A1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x1); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l25a8); + test(M, 0x1); + jle(l25c8, T_NEAR); + mov(al, byte[A1-0x80]); + mov(byte[B-0x80], al); + mov(al, byte[A2-0x80]); + mov(byte[B-0x7f], al); + sub(B, -2); + align(4); + +L(l25c8); + sub(N, 0x2); + cmp(N, 0x2); + jge(l24d0, T_NEAR); + align(4); + +L(l25d6); + cmp(N, 0x1); + jl(l2690, T_NEAR); + align(4); + +L(l25e0); + mov(A1, A); + add(A, LDA); + mov(I, M); + sar(I, 0x4); + jle(l260c, T_NEAR); + align(4); + +L(l25f0); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(I); + jg(l25f0, T_NEAR); + align(4); + +L(l260c); + test(M, 0x8); + jle(l262c, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l262c); + test(M, 0x4); + jle(l264c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l264c); + test(M, 0x2); + jle(l2668, T_NEAR); + mov(ax, word[A1-0x80]); + mov(word[B-0x80], ax); + sub(A1, -2); + sub(B, -2); + align(4); + +L(l2668); + test(M, 0x1); + jle(l2680, T_NEAR); + mov(al, byte[A1-0x80]); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(l2680); + sub(N, 0x1); + cmp(N, 0x1); + jge(l25e0, T_NEAR); + align(4); + +L(l2690); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp new file mode 100644 index 0000000000..56c36ee14a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp @@ -0,0 +1,564 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_bn_kern::jit_avx512_core_u8_copy_bn_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l118; +Xbyak::Label l1a8; +Xbyak::Label l20; +Xbyak::Label l218; +Xbyak::Label l28c; +Xbyak::Label l2f8; +Xbyak::Label l308; +Xbyak::Label l314; +Xbyak::Label l32c; +Xbyak::Label l3a0; +Xbyak::Label l3c; +Xbyak::Label l3f0; +Xbyak::Label l434; +Xbyak::Label l47c; +Xbyak::Label l4bc; +Xbyak::Label l4cc; +Xbyak::Label l4d8; +Xbyak::Label l4f0; +Xbyak::Label l528; +Xbyak::Label l554; +Xbyak::Label l580; +Xbyak::Label l5b0; +Xbyak::Label l5d0; +Xbyak::Label l5de; +Xbyak::Label l5e8; +Xbyak::Label l5f8; +Xbyak::Label l614; +Xbyak::Label l634; +Xbyak::Label l654; +Xbyak::Label l670; +Xbyak::Label l688; +Xbyak::Label l698; + + preamble(); +#ifdef _WIN32 + auto stacksize = get_size_of_abi_save_regs(); + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(N, qword[N]); + mov(M, qword[M]); + mov(LDA, qword[LDA]); + sub(A, -128); + sub(B, -128); + lea(LDA3, ptr[LDA+LDA*2]); + cmp(N, 0x8); + jl(l308, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + lea(A2, ptr[A1+LDA*4]); + lea(I, ptr[A1+LDA*8]); + mov(A, I); + mov(I, M); + sar(I, 0x4); + jle(l118, T_NEAR); + align(4); + +L(l3c); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + sub(A1, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x60], xmm1); + movdqu(xword[B-0x40], xmm4); + movdqu(xword[B-0x20], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B-0x50], xmm1); + movdqu(xword[B-0x30], xmm4); + movdqu(xword[B-0x10], xmm3); + sub(B, -128); + dec(I); + jg(l3c, T_NEAR); + align(4); + +L(l118); + test(M, 0x8); + jle(l1a8, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + sub(A1, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x60], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x70], xmm0); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + align(4); + +L(l1a8); + test(M, 0x4); + jle(l218, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + sub(A1, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + align(4); + +L(l218); + test(M, 0x2); + jle(l28c, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x7); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l28c); + test(M, 0x1); + jle(l2f8, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x7); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l2f8); + sub(N, 0x8); + cmp(N, 0x8); + jge(l20, T_NEAR); + align(4); + +L(l308); + cmp(N, 0x4); + jl(l4cc, T_NEAR); + align(4); + +L(l314); + mov(A1, A); + lea(A2, ptr[A1+LDA*2]); + lea(I, ptr[A1+LDA*4]); + mov(A, I); + mov(I, M); + sar(I, 0x4); + jle(l3a0, T_NEAR); + align(4); + +L(l32c); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + sub(A1, -16); + movdqu(xmm2, xword[A2-0x80]); + movdqu(xmm3, xword[A2+LDA*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movdqu(xword[B-0x60], xmm4); + movdqu(xword[B-0x50], xmm3); + sub(B, -64); + dec(I); + jg(l32c, T_NEAR); + align(4); + +L(l3a0); + test(M, 0x8); + jle(l3f0, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + sub(A1, -8); + movq(xmm2, qword[A2-0x80]); + movq(xmm3, qword[A2+LDA*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l3f0); + test(M, 0x4); + jle(l434, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + sub(A1, -4); + movd(xmm2, dword[A2-0x80]); + movd(xmm3, dword[A2+LDA*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l434); + test(M, 0x2); + jle(l47c, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x3); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l47c); + test(M, 0x1); + jle(l4bc, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x3); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l4bc); + sub(N, 0x4); + cmp(N, 0x4); + jge(l314, T_NEAR); + align(4); + +L(l4cc); + cmp(N, 0x2); + jl(l5de, T_NEAR); + align(4); + +L(l4d8); + mov(A1, A); + lea(A2, ptr[A1+LDA*1]); + lea(I, ptr[A1+LDA*2]); + mov(A, I); + mov(I, M); + sar(I, 0x4); + jle(l528, T_NEAR); + align(4); + +L(l4f0); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + movdqu(xmm1, xword[A2-0x80]); + sub(A2, -16); + movdqa(xmm2, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm2, xmm1); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm2); + sub(B, -32); + dec(I); + jg(l4f0, T_NEAR); + align(4); + +L(l528); + test(M, 0x8); + jle(l554, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + movq(xmm1, qword[A2-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l554); + test(M, 0x4); + jle(l580, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + movd(xmm1, dword[A2-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l580); + test(M, 0x2); + jle(l5b0, T_NEAR); + mov(ax, word[A1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x1); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l5b0); + test(M, 0x1); + jle(l5d0, T_NEAR); + mov(al, byte[A1-0x80]); + mov(byte[B-0x80], al); + mov(al, byte[A2-0x80]); + mov(byte[B-0x7f], al); + sub(B, -2); + align(4); + +L(l5d0); + sub(N, 0x2); + cmp(N, 0x2); + jge(l4d8, T_NEAR); + align(4); + +L(l5de); + cmp(N, 0x1); + jl(l698, T_NEAR); + align(4); + +L(l5e8); + mov(A1, A); + add(A, LDA); + mov(I, M); + sar(I, 0x4); + jle(l614, T_NEAR); + align(4); + +L(l5f8); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(I); + jg(l5f8, T_NEAR); + align(4); + +L(l614); + test(M, 0x8); + jle(l634, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l634); + test(M, 0x4); + jle(l654, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l654); + test(M, 0x2); + jle(l670, T_NEAR); + mov(ax, word[A1-0x80]); + mov(word[B-0x80], ax); + sub(A1, -2); + sub(B, -2); + align(4); + +L(l670); + test(M, 0x1); + jle(l688, T_NEAR); + mov(al, byte[A1-0x80]); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(l688); + sub(N, 0x1); + cmp(N, 0x1); + jge(l5e8, T_NEAR); + align(4); + +L(l698); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp new file mode 100644 index 0000000000..53e99d94de --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp @@ -0,0 +1,501 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_bt_kern::jit_avx512_core_u8_copy_bt_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l120; +Xbyak::Label l14c; +Xbyak::Label l168; +Xbyak::Label l178; +Xbyak::Label l184; +Xbyak::Label l194; +Xbyak::Label l20; +Xbyak::Label l20c; +Xbyak::Label l250; +Xbyak::Label l27c; +Xbyak::Label l298; +Xbyak::Label l2a8; +Xbyak::Label l2b4; +Xbyak::Label l2c8; +Xbyak::Label l34; +Xbyak::Label l360; +Xbyak::Label l3b4; +Xbyak::Label l3e8; +Xbyak::Label l400; +Xbyak::Label l40e; +Xbyak::Label l418; +Xbyak::Label l428; +Xbyak::Label l4a0; +Xbyak::Label l4e8; +Xbyak::Label l50c; +Xbyak::Label l524; +Xbyak::Label l534; +Xbyak::Label lcc; + + preamble(); +#ifdef _WIN32 + auto stacksize = get_size_of_abi_save_regs(); + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(M, qword[M]); + mov(N, qword[N]); + mov(LDA, qword[LDA]); + lea(LDA3, ptr[LDA+LDA*2]); + sub(A, -128); + sub(B, -128); + cmp(N, 0x8); + jl(l178, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + add(A, 0x8); + mov(I, M); + sar(I, 0x3); + jle(lcc, T_NEAR); + align(4); + +L(l34); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + dec(I); + jg(l34, T_NEAR); + align(4); + +L(lcc); + test(M, 0x4); + jle(l120, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l120); + test(M, 0x2); + jle(l14c, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l14c); + test(M, 0x1); + jle(l168, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l168); + sub(N, 0x8); + cmp(N, 0x8); + jge(l20, T_NEAR); + align(4); + +L(l178); + cmp(N, 0x4); + jl(l2a8, T_NEAR); + align(4); + +L(l184); + mov(A1, A); + add(A, 0x4); + mov(I, M); + sar(I, 0x3); + jle(l20c, T_NEAR); + align(4); + +L(l194); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + dec(I); + jg(l194, T_NEAR); + align(4); + +L(l20c); + test(M, 0x4); + jle(l250, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l250); + test(M, 0x2); + jle(l27c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l27c); + test(M, 0x1); + jle(l298, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l298); + sub(N, 0x4); + cmp(N, 0x4); + jge(l184, T_NEAR); + align(4); + +L(l2a8); + cmp(N, 0x2); + jl(l40e, T_NEAR); + align(4); + +L(l2b4); + mov(A1, A); + add(A, 0x2); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l360, T_NEAR); + align(4); + +L(l2c8); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm4, eax, 0x0); + punpcklbw(xmm1, xmm2); + punpcklbw(xmm3, xmm4); + punpcklwd(xmm1, xmm3); + punpcklqdq(xmm0, xmm1); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(LDA3); + jg(l2c8, T_NEAR); + align(4); + +L(l360); + test(M, 0x4); + jle(l3b4, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l3b4); + test(M, 0x2); + jle(l3e8, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + punpcklbw(xmm0, xmm1); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l3e8); + test(M, 0x1); + jle(l400, T_NEAR); + mov(ax, word[A1-0x80]); + mov(word[B-0x80], ax); + sub(B, -2); + align(4); + +L(l400); + sub(N, 0x2); + cmp(N, 0x2); + jge(l2b4, T_NEAR); + align(4); + +L(l40e); + cmp(N, 0x1); + jl(l534, T_NEAR); + align(4); + +L(l418); + mov(A1, A); + add(A, 0x1); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l4a0, T_NEAR); + align(4); + +L(l428); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x7); + movq(qword[B-0x80], xmm0); + sub(B, -8); + dec(LDA3); + jg(l428, T_NEAR); + align(4); + +L(l4a0); + test(M, 0x4); + jle(l4e8, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l4e8); + test(M, 0x2); + jle(l50c, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + mov(byte[B-0x80], al); + mov(al, byte[A1-0x80]); + add(A1, LDA); + mov(byte[B-0x7f], al); + sub(B, -2); + align(4); + +L(l50c); + test(M, 0x1); + jle(l524, T_NEAR); + mov(al, byte[A1-0x80]); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(l524); + sub(N, 0x1); + cmp(N, 0x1); + jge(l418, T_NEAR); + align(4); + +L(l534); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp new file mode 100644 index 0000000000..49a312fc88 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp @@ -0,0 +1,1283 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_sum_an_kern::jit_avx512_core_u8_copy_sum_an_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#define ARG_BIAS 24+stacksize+rsp + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp +#define ARG_BIAS 72+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l1024; +Xbyak::Label l1090; +Xbyak::Label l10d4; +Xbyak::Label l10fc; +Xbyak::Label l111a; +Xbyak::Label l1124; +Xbyak::Label l113c; +Xbyak::Label l11d4; +Xbyak::Label l1234; +Xbyak::Label l1278; +Xbyak::Label l129c; +Xbyak::Label l12bc; +Xbyak::Label l20; +Xbyak::Label l2a0; +Xbyak::Label l3c0; +Xbyak::Label l438; +Xbyak::Label l480; +Xbyak::Label l48c; +Xbyak::Label l4c8; +Xbyak::Label l5c; +Xbyak::Label l6a8; +Xbyak::Label l7b4; +Xbyak::Label l850; +Xbyak::Label l89c; +Xbyak::Label l8a8; +Xbyak::Label l8d0; +Xbyak::Label l9d0; +Xbyak::Label la64; +Xbyak::Label lab8; +Xbyak::Label lae8; +Xbyak::Label laf4; +Xbyak::Label lb14; +Xbyak::Label lc30; +Xbyak::Label lcc8; +Xbyak::Label ld1c; +Xbyak::Label ld54; +Xbyak::Label ld78; +Xbyak::Label ld84; +Xbyak::Label ld9c; +Xbyak::Label le58; +Xbyak::Label lebc; +Xbyak::Label lef8; +Xbyak::Label lf1c; +Xbyak::Label lf3c; +Xbyak::Label lf48; +Xbyak::Label lf60; + + preamble(); + auto stacksize = get_size_of_abi_save_regs(); +#ifdef _WIN32 + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(M, qword[M]); + mov(N, qword[N]); + mov(LDA, qword[LDA]); + lea(LDA3, ptr[LDA+LDA*2]); + sub(A, -128); + sub(B, -128); + cmp(N, 0x30); + jl(l480, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + add(A, 0x30); + vxorps(ymm8, ymm8, ymm8); + vxorps(ymm9, ymm9, ymm9); + vxorps(ymm10, ymm10, ymm10); + vxorps(ymm11, ymm11, ymm11); + vxorps(ymm12, ymm12, ymm12); + vxorps(ymm13, ymm13, ymm13); + vxorps(ymm14, ymm14, ymm14); + vxorps(ymm15, ymm15, ymm15); + mov(I, M); + sar(I, 0x2); + jle(l2a0, T_NEAR); + align(4); + +L(l5c); + vmovdqu(xmm0, xword[A1-0x80]); + vmovdqu(xmm1, xword[A1+LDA*1-0x80]); + vmovdqu(xmm2, xword[A1+LDA*2-0x80]); + vmovdqu(xmm3, xword[A1+LDA3*1-0x80]); + vpunpcklbw(xmm4, xmm0, xmm1); + vpunpckhbw(xmm5, xmm0, xmm1); + vpunpcklbw(xmm6, xmm2, xmm3); + vpunpckhbw(xmm7, xmm2, xmm3); + vpunpcklwd(xmm0, xmm4, xmm6); + vpunpckhwd(xmm1, xmm4, xmm6); + vpunpcklwd(xmm2, xmm5, xmm7); + vpunpckhwd(xmm3, xmm5, xmm7); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm8, ymm8, ymm5); + vmovdqu(xword[B-0x80], xmm0); + vmovdqu(xword[B-0x70], xmm1); + vpmovsxbw(ymm5, xmm2); + vmovhlps(xmm6, xmm2, xmm2); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm9, ymm9, ymm5); + vmovdqu(xword[B-0x60], xmm2); + vmovdqu(xword[B-0x50], xmm3); + vmovdqu(xmm0, xword[A1-0x70]); + vmovdqu(xmm1, xword[A1+LDA*1-0x70]); + vmovdqu(xmm2, xword[A1+LDA*2-0x70]); + vmovdqu(xmm3, xword[A1+LDA3*1-0x70]); + vpunpcklbw(xmm4, xmm0, xmm1); + vpunpckhbw(xmm5, xmm0, xmm1); + vpunpcklbw(xmm6, xmm2, xmm3); + vpunpckhbw(xmm7, xmm2, xmm3); + vpunpcklwd(xmm0, xmm4, xmm6); + vpunpckhwd(xmm1, xmm4, xmm6); + vpunpcklwd(xmm2, xmm5, xmm7); + vpunpckhwd(xmm3, xmm5, xmm7); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm10, ymm10, ymm5); + vmovdqu(xword[B-0x40], xmm0); + vmovdqu(xword[B-0x30], xmm1); + vpmovsxbw(ymm5, xmm2); + vmovhlps(xmm6, xmm2, xmm2); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm11, ymm11, ymm5); + vmovdqu(xword[B-0x20], xmm2); + vmovdqu(xword[B-0x10], xmm3); + vmovdqu(xmm0, xword[A1-0x60]); + vmovdqu(xmm1, xword[A1+LDA*1-0x60]); + vmovdqu(xmm2, xword[A1+LDA*2-0x60]); + vmovdqu(xmm3, xword[A1+LDA3*1-0x60]); + lea(A1, ptr[A1+LDA*4]); + vpunpcklbw(xmm4, xmm0, xmm1); + vpunpckhbw(xmm5, xmm0, xmm1); + vpunpcklbw(xmm6, xmm2, xmm3); + vpunpckhbw(xmm7, xmm2, xmm3); + vpunpcklwd(xmm0, xmm4, xmm6); + vpunpckhwd(xmm1, xmm4, xmm6); + vpunpcklwd(xmm2, xmm5, xmm7); + vpunpckhwd(xmm3, xmm5, xmm7); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm12, ymm12, ymm5); + vmovdqu(xword[B], xmm0); + vmovdqu(xword[B+0x10], xmm1); + vpmovsxbw(ymm5, xmm2); + vmovhlps(xmm6, xmm2, xmm2); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm13, ymm13, ymm5); + vmovdqu(xword[B+0x20], xmm2); + vmovdqu(xword[B+0x30], xmm3); + sub(B, -192); + dec(I); + jg(l5c, T_NEAR); + align(4); + +L(l2a0); + test(M, 0x2); + jle(l3c0, T_NEAR); + vmovdqu(xmm0, xword[A1-0x80]); + vmovdqu(xmm1, xword[A1-0x70]); + vmovdqu(xmm2, xword[A1-0x60]); + add(A1, LDA); + vmovdqu(xmm6, xword[A1-0x80]); + vmovdqu(xmm4, xword[A1-0x70]); + vmovdqu(xmm5, xword[A1-0x60]); + add(A1, LDA); + vpunpcklbw(xmm3, xmm0, xmm6); + vpunpckhbw(xmm0, xmm0, xmm6); + vpmovsxbw(ymm7, xmm3); + vmovhlps(xmm6, xmm3, xmm3); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm7, ymm7, ymm6); + vpmovsxwd(ymm7, xmm7); + vpaddd(ymm8, ymm8, ymm7); + vmovdqu(xword[B-0x80], xmm3); + vpmovsxbw(ymm7, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm7, ymm7, ymm6); + vpmovsxwd(ymm7, xmm7); + vpaddd(ymm9, ymm9, ymm7); + vmovdqu(xword[B-0x70], xmm0); + vpunpcklbw(xmm3, xmm1, xmm4); + vpunpckhbw(xmm0, xmm1, xmm4); + vpmovsxbw(ymm7, xmm3); + vmovhlps(xmm6, xmm3, xmm3); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm7, ymm7, ymm6); + vpmovsxwd(ymm7, xmm7); + vpaddd(ymm10, ymm10, ymm7); + vmovdqu(xword[B-0x60], xmm3); + vpmovsxbw(ymm7, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm7, ymm7, ymm6); + vpmovsxwd(ymm7, xmm7); + vpaddd(ymm11, ymm11, ymm7); + vmovdqu(xword[B-0x50], xmm0); + vpunpcklbw(xmm3, xmm2, xmm5); + vpunpckhbw(xmm0, xmm2, xmm5); + vpmovsxbw(ymm7, xmm3); + vmovhlps(xmm6, xmm3, xmm3); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm7, ymm7, ymm6); + vpmovsxwd(ymm7, xmm7); + vpaddd(ymm12, ymm12, ymm7); + vmovdqu(xword[B-0x40], xmm3); + vpmovsxbw(ymm7, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm7, ymm7, ymm6); + vpmovsxwd(ymm7, xmm7); + vpaddd(ymm13, ymm13, ymm7); + vmovdqu(xword[B-0x30], xmm0); + sub(B, -96); + align(4); + +L(l3c0); + test(M, 0x1); + jle(l438, T_NEAR); + vmovdqu(xmm0, xword[A1-0x80]); + vmovdqu(xmm1, xword[A1-0x70]); + vmovdqu(xmm2, xword[A1-0x60]); + add(A1, LDA); + vpmovsxbd(ymm7, xmm0); + vpaddd(ymm8, ymm8, ymm7); + vmovhlps(xmm7, xmm0, xmm0); + vpmovsxbd(ymm7, xmm7); + vpaddd(ymm9, ymm9, ymm7); + vmovdqu(xword[B-0x80], xmm0); + vpmovsxbd(ymm7, xmm1); + vpaddd(ymm10, ymm10, ymm7); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbd(ymm7, xmm7); + vpaddd(ymm11, ymm11, ymm7); + vmovdqu(xword[B-0x70], xmm1); + vpmovsxbd(ymm7, xmm2); + vpaddd(ymm12, ymm12, ymm7); + vmovhlps(xmm7, xmm2, xmm2); + vpmovsxbd(ymm7, xmm7); + vpaddd(ymm13, ymm13, ymm7); + vmovdqu(xword[B-0x60], xmm2); + sub(B, -48); + align(4); + +L(l438); + mov(A1, qword[ARG_BIAS]); + vmovdqu(yword[A1], ymm8); + vmovdqu(yword[A1+0x20], ymm9); + vmovdqu(yword[A1+0x40], ymm10); + vmovdqu(yword[A1+0x60], ymm11); + vmovdqu(yword[A1+0x80], ymm12); + vmovdqu(yword[A1+0xa0], ymm13); + add(qword[ARG_BIAS], 0xc0); + sub(N, 0x30); + cmp(N, 0x30); + jge(l20, T_NEAR); + vzeroupper(); + align(4); + +L(l480); + cmp(N, 0x20); + jl(l89c, T_NEAR); + align(4); + +L(l48c); + mov(A1, A); + add(A, 0x20); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + pxor(xmm10, xmm10); + pxor(xmm11, xmm11); + pxor(xmm12, xmm12); + pxor(xmm13, xmm13); + pxor(xmm14, xmm14); + pxor(xmm15, xmm15); + mov(I, M); + sar(I, 0x2); + jle(l6a8, T_NEAR); + align(4); + +L(l4c8); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm5); + punpckhwd(xmm2, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x60], xmm4); + pmovsxbw(xmm5, xmm2); + movhlps(xmm6, xmm2); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x50], xmm2); + movdqu(xmm0, xword[A1-0x70]); + movdqu(xmm1, xword[A1+LDA*1-0x70]); + movdqu(xmm2, xword[A1+LDA*2-0x70]); + movdqu(xmm3, xword[A1+LDA3*1-0x70]); + lea(A1, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm5); + punpckhwd(xmm2, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B-0x40], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B-0x30], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B-0x20], xmm4); + pmovsxbw(xmm5, xmm2); + movhlps(xmm6, xmm2); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B-0x10], xmm2); + sub(B, -128); + dec(I); + jg(l4c8, T_NEAR); + align(4); + +L(l6a8); + test(M, 0x2); + jle(l7b4, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1-0x70]); + add(A1, LDA); + movdqu(xmm2, xword[A1-0x80]); + movdqu(xmm3, xword[A1-0x70]); + add(A1, LDA); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm2); + punpckhbw(xmm4, xmm2); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm4); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x70], xmm4); + movdqa(xmm4, xmm1); + punpcklbw(xmm1, xmm3); + punpckhbw(xmm4, xmm3); + pmovsxbw(xmm5, xmm1); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm13, xmm6); + movdqu(xword[B-0x60], xmm1); + pmovsxbw(xmm5, xmm4); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm15, xmm6); + movdqu(xword[B-0x50], xmm4); + sub(B, -64); + align(4); + +L(l7b4); + test(M, 0x1); + jle(l850, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1-0x70]); + add(A1, LDA); + pmovsxbd(xmm5, xmm0); + paddd(xmm8, xmm5); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm9, xmm6); + pshufd(xmm5, xmm0, 0xaa); + pmovsxbd(xmm5, xmm5); + paddd(xmm10, xmm5); + pshufd(xmm6, xmm0, 0xff); + pmovsxbd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x80], xmm0); + pmovsxbd(xmm5, xmm1); + paddd(xmm12, xmm5); + pshufd(xmm6, xmm1, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm13, xmm6); + pshufd(xmm5, xmm1, 0xaa); + pmovsxbd(xmm5, xmm5); + paddd(xmm14, xmm5); + pshufd(xmm6, xmm1, 0xff); + pmovsxbd(xmm6, xmm6); + paddd(xmm15, xmm6); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l850); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + movdqu(xword[A1+0x20], xmm10); + movdqu(xword[A1+0x30], xmm11); + movdqu(xword[A1+0x40], xmm12); + movdqu(xword[A1+0x50], xmm13); + movdqu(xword[A1+0x60], xmm14); + movdqu(xword[A1+0x70], xmm15); + add(qword[ARG_BIAS], 0x80); + sub(N, 0x20); + cmp(N, 0x20); + jge(l48c, T_NEAR); + align(4); + +L(l89c); + cmp(N, 0x10); + jl(lae8, T_NEAR); + align(4); + +L(l8a8); + mov(A1, A); + add(A, 0x10); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + pxor(xmm10, xmm10); + pxor(xmm11, xmm11); + mov(I, M); + sar(I, 0x2); + jle(l9d0, T_NEAR); + align(4); + +L(l8d0); + movdqu(xmm0, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm1, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm2, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm3, xword[A1-0x80]); + add(A1, LDA); + movdqa(xmm4, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm4, xmm1); + movdqa(xmm1, xmm2); + punpcklbw(xmm2, xmm3); + punpckhbw(xmm1, xmm3); + movdqa(xmm3, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm3, xmm2); + movdqa(xmm2, xmm4); + punpcklwd(xmm4, xmm1); + punpckhwd(xmm2, xmm1); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm3); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + pmovsxbw(xmm5, xmm2); + movhlps(xmm6, xmm2); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x60], xmm4); + movdqu(xword[B-0x50], xmm2); + sub(B, -64); + dec(I); + jg(l8d0, T_NEAR); + align(4); + +L(l9d0); + test(M, 0x2); + jle(la64, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + add(A1, LDA); + movdqu(xmm1, xword[A1-0x80]); + add(A1, LDA); + movdqa(xmm2, xmm0); + punpcklbw(xmm0, xmm1); + punpckhbw(xmm2, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + pmovsxbw(xmm5, xmm2); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movhlps(xmm6, xmm2); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm2); + sub(B, -32); + align(4); + +L(la64); + test(M, 0x1); + jle(lab8, T_NEAR); + movdqu(xmm0, xword[A1-0x80]); + add(A1, LDA); + pmovsxbd(xmm5, xmm0); + paddd(xmm8, xmm5); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm9, xmm6); + pshufd(xmm5, xmm0, 0xaa); + pmovsxbd(xmm5, xmm5); + paddd(xmm10, xmm5); + pshufd(xmm6, xmm0, 0xff); + pmovsxbd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(lab8); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + movdqu(xword[A1+0x20], xmm10); + movdqu(xword[A1+0x30], xmm11); + add(qword[ARG_BIAS], 0x40); + sub(N, 0x10); + cmp(N, 0x10); + jge(l8a8, T_NEAR); + align(4); + +L(lae8); + cmp(N, 0x8); + jl(ld78, T_NEAR); + align(4); + +L(laf4); + mov(A1, A); + add(A, 0x8); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + mov(I, M); + sar(I, 0x3); + jle(lc30, T_NEAR); + align(4); + +L(lb14); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + dec(I); + jg(lb14, T_NEAR); + align(4); + +L(lc30); + test(M, 0x4); + jle(lcc8, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(lcc8); + test(M, 0x2); + jle(ld1c, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(ld1c); + test(M, 0x1); + jle(ld54, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + pmovsxbd(xmm5, xmm0); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm8, xmm5); + paddd(xmm9, xmm6); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(ld54); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + add(qword[ARG_BIAS], 0x20); + sub(N, 0x8); + cmp(N, 0x8); + jge(laf4, T_NEAR); + align(4); + +L(ld78); + cmp(N, 0x4); + jl(lf3c, T_NEAR); + align(4); + +L(ld84); + mov(A1, A); + add(A, 0x4); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x3); + jle(le58, T_NEAR); + align(4); + +L(ld9c); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + dec(I); + jg(ld9c, T_NEAR); + align(4); + +L(le58); + test(M, 0x4); + jle(lebc, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(lebc); + test(M, 0x2); + jle(lef8, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(lef8); + test(M, 0x1); + jle(lf1c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(lf1c); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm7); + add(qword[ARG_BIAS], 0x10); + sub(N, 0x4); + cmp(N, 0x4); + jge(ld84, T_NEAR); + align(4); + +L(lf3c); + cmp(N, 0x2); + jl(l111a, T_NEAR); + align(4); + +L(lf48); + mov(A1, A); + add(A, 0x2); + pxor(xmm7, xmm7); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l1024, T_NEAR); + align(4); + +L(lf60); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm4, eax, 0x0); + punpcklbw(xmm1, xmm2); + punpcklbw(xmm3, xmm4); + punpcklwd(xmm1, xmm3); + punpcklqdq(xmm0, xmm1); + pshufd(xmm6, xmm0, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(LDA3); + jg(lf60, T_NEAR); + align(4); + +L(l1024); + test(M, 0x4); + jle(l1090, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l1090); + test(M, 0x2); + jle(l10d4, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + punpcklbw(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l10d4); + test(M, 0x1); + jle(l10fc, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + mov(word[B-0x80], ax); + sub(B, -2); + align(4); + +L(l10fc); + mov(A1, qword[ARG_BIAS]); + movq(qword[A1], xmm7); + add(qword[ARG_BIAS], 0x8); + sub(N, 0x2); + cmp(N, 0x2); + jge(lf48, T_NEAR); + align(4); + +L(l111a); + cmp(N, 0x1); + jl(l12bc, T_NEAR); + align(4); + +L(l1124); + mov(A1, A); + add(A, 0x1); + pxor(xmm7, xmm7); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l11d4, T_NEAR); + align(4); + +L(l113c); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x7); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + dec(LDA3); + jg(l113c, T_NEAR); + align(4); + +L(l11d4); + test(M, 0x4); + jle(l1234, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l1234); + test(M, 0x2); + jle(l1278, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(byte[B-0x80], al); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + mov(byte[B-0x7f], al); + sub(B, -2); + align(4); + +L(l1278); + test(M, 0x1); + jle(l129c, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(l129c); + mov(A1, qword[ARG_BIAS]); + movd(dword[A1], xmm7); + add(qword[ARG_BIAS], 0x4); + sub(N, 0x1); + cmp(N, 0x1); + jge(l1124, T_NEAR); + align(4); + +L(l12bc); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +#undef ARG_BIAS +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp new file mode 100644 index 0000000000..a4f4ff09c6 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp @@ -0,0 +1,3163 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_sum_at_kern::jit_avx512_core_u8_copy_sum_at_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#define ARG_BIAS 24+stacksize+rsp + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp +#define ARG_BIAS 72+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l1750; +Xbyak::Label l1b6c; +Xbyak::Label l1e14; +Xbyak::Label l20; +Xbyak::Label l2068; +Xbyak::Label l226c; +Xbyak::Label l22b8; +Xbyak::Label l22c4; +Xbyak::Label l22f4; +Xbyak::Label l26b4; +Xbyak::Label l28cc; +Xbyak::Label l2a2c; +Xbyak::Label l2b5c; +Xbyak::Label l2c64; +Xbyak::Label l2c94; +Xbyak::Label l2ca0; +Xbyak::Label l2cc8; +Xbyak::Label l2eac; +Xbyak::Label l2fc0; +Xbyak::Label l3078; +Xbyak::Label l3118; +Xbyak::Label l319c; +Xbyak::Label l31c0; +Xbyak::Label l31cc; +Xbyak::Label l31ec; +Xbyak::Label l32e4; +Xbyak::Label l3378; +Xbyak::Label l33dc; +Xbyak::Label l3434; +Xbyak::Label l347c; +Xbyak::Label l349c; +Xbyak::Label l34a8; +Xbyak::Label l34c8; +Xbyak::Label l3558; +Xbyak::Label l35b0; +Xbyak::Label l35f4; +Xbyak::Label l3638; +Xbyak::Label l366c; +Xbyak::Label l368a; +Xbyak::Label l3694; +Xbyak::Label l36a8; +Xbyak::Label l36ec; +Xbyak::Label l3728; +Xbyak::Label l3760; +Xbyak::Label l3794; +Xbyak::Label l37b8; +Xbyak::Label l37d8; +Xbyak::Label l5cc; +Xbyak::Label l6c; +Xbyak::Label l968; +Xbyak::Label lc80; +Xbyak::Label lf1c; +Xbyak::Label lf64; +Xbyak::Label lf70; +Xbyak::Label lfb4; + + preamble(); + auto stacksize = get_size_of_abi_save_regs(); +#ifdef _WIN32 + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(N, qword[N]); + mov(M, qword[M]); + mov(LDA, qword[LDA]); + sub(A, -128); + sub(B, -128); + lea(LDA3, ptr[LDA+LDA*2]); + cmp(N, 0x30); + jl(lf64, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + mov(I, LDA); + shl(I, 0x5); + lea(I, ptr[I+LDA*8]); + lea(I, ptr[I+LDA*8]); + add(A, I); + vxorps(ymm8, ymm8, ymm8); + vxorps(ymm9, ymm9, ymm9); + vxorps(ymm10, ymm10, ymm10); + vxorps(ymm11, ymm11, ymm11); + vxorps(ymm12, ymm12, ymm12); + vxorps(ymm13, ymm13, ymm13); + vxorps(ymm14, ymm14, ymm14); + vxorps(ymm15, ymm15, ymm15); + mov(I, M); + sar(I, 0x3); + jle(l5cc, T_NEAR); + align(4); + +L(l6c); + vmovq(xmm0, qword[A1-0x80]); + vmovq(xmm1, qword[A1+LDA*1-0x80]); + vmovq(xmm2, qword[A1+LDA*2-0x80]); + vmovq(xmm3, qword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + vpunpckldq(xmm1, xmm0, xmm1); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm1, xmm3); + vpunpckhqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x80], xmm0); + vmovdqu(xword[B+0x40], xmm1); + vmovq(xmm2, qword[A2-0x80]); + vmovq(xmm3, qword[A2+LDA*1-0x80]); + vmovq(xmm4, qword[A2+LDA*2-0x80]); + vmovq(xmm5, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpckldq(xmm5, xmm4, xmm5); + vpunpcklqdq(xmm2, xmm3, xmm5); + vpunpckhqdq(xmm3, xmm3, xmm5); + vmovdqu(xword[B-0x70], xmm2); + vmovdqu(xword[B+0x50], xmm3); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm2); + vmovhlps(xmm7, xmm2, xmm2); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm8, ymm8, ymm5); + vpmovsxbw(ymm5, xmm1); + vmovhlps(xmm6, xmm1, xmm1); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm8, ymm8, ymm5); + vmovq(xmm0, qword[A2-0x80]); + vmovq(xmm1, qword[A2+LDA*1-0x80]); + vmovq(xmm2, qword[A2+LDA*2-0x80]); + vmovq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm0, xmm1); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm1, xmm3); + vpunpckhqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x60], xmm0); + vmovdqu(xword[B+0x60], xmm1); + vmovq(xmm2, qword[A2-0x80]); + vmovq(xmm3, qword[A2+LDA*1-0x80]); + vmovq(xmm4, qword[A2+LDA*2-0x80]); + vmovq(xmm5, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpckldq(xmm5, xmm4, xmm5); + vpunpcklqdq(xmm2, xmm3, xmm5); + vpunpckhqdq(xmm3, xmm3, xmm5); + vmovdqu(xword[B-0x50], xmm2); + vmovdqu(xword[B+0x70], xmm3); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm2); + vmovhlps(xmm7, xmm2, xmm2); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm9, ymm9, ymm5); + vpmovsxbw(ymm5, xmm1); + vmovhlps(xmm6, xmm1, xmm1); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm9, ymm9, ymm5); + vmovq(xmm0, qword[A2-0x80]); + vmovq(xmm1, qword[A2+LDA*1-0x80]); + vmovq(xmm2, qword[A2+LDA*2-0x80]); + vmovq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm0, xmm1); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm1, xmm3); + vpunpckhqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x40], xmm0); + vmovdqu(xword[B+0x80], xmm1); + vmovq(xmm2, qword[A2-0x80]); + vmovq(xmm3, qword[A2+LDA*1-0x80]); + vmovq(xmm4, qword[A2+LDA*2-0x80]); + vmovq(xmm5, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpckldq(xmm5, xmm4, xmm5); + vpunpcklqdq(xmm2, xmm3, xmm5); + vpunpckhqdq(xmm3, xmm3, xmm5); + vmovdqu(xword[B-0x30], xmm2); + vmovdqu(xword[B+0x90], xmm3); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm2); + vmovhlps(xmm7, xmm2, xmm2); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm10, ymm10, ymm5); + vpmovsxbw(ymm5, xmm1); + vmovhlps(xmm6, xmm1, xmm1); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm10, ymm10, ymm5); + vmovq(xmm0, qword[A2-0x80]); + vmovq(xmm1, qword[A2+LDA*1-0x80]); + vmovq(xmm2, qword[A2+LDA*2-0x80]); + vmovq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm0, xmm1); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm1, xmm3); + vpunpckhqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x20], xmm0); + vmovdqu(xword[B+0xa0], xmm1); + vmovq(xmm2, qword[A2-0x80]); + vmovq(xmm3, qword[A2+LDA*1-0x80]); + vmovq(xmm4, qword[A2+LDA*2-0x80]); + vmovq(xmm5, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpckldq(xmm5, xmm4, xmm5); + vpunpcklqdq(xmm2, xmm3, xmm5); + vpunpckhqdq(xmm3, xmm3, xmm5); + vmovdqu(xword[B-0x10], xmm2); + vmovdqu(xword[B+0xb0], xmm3); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm2); + vmovhlps(xmm7, xmm2, xmm2); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm11, ymm11, ymm5); + vpmovsxbw(ymm5, xmm1); + vmovhlps(xmm6, xmm1, xmm1); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm11, ymm11, ymm5); + vmovq(xmm0, qword[A2-0x80]); + vmovq(xmm1, qword[A2+LDA*1-0x80]); + vmovq(xmm2, qword[A2+LDA*2-0x80]); + vmovq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm0, xmm1); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm1, xmm3); + vpunpckhqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B], xmm0); + vmovdqu(xword[B+0xc0], xmm1); + vmovq(xmm2, qword[A2-0x80]); + vmovq(xmm3, qword[A2+LDA*1-0x80]); + vmovq(xmm4, qword[A2+LDA*2-0x80]); + vmovq(xmm5, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpckldq(xmm5, xmm4, xmm5); + vpunpcklqdq(xmm2, xmm3, xmm5); + vpunpckhqdq(xmm3, xmm3, xmm5); + vmovdqu(xword[B+0x10], xmm2); + vmovdqu(xword[B+0xd0], xmm3); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm2); + vmovhlps(xmm7, xmm2, xmm2); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm12, ymm12, ymm5); + vpmovsxbw(ymm5, xmm1); + vmovhlps(xmm6, xmm1, xmm1); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm12, ymm12, ymm5); + vmovq(xmm0, qword[A2-0x80]); + vmovq(xmm1, qword[A2+LDA*1-0x80]); + vmovq(xmm2, qword[A2+LDA*2-0x80]); + vmovq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm0, xmm1); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm1, xmm3); + vpunpckhqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B+0x20], xmm0); + vmovdqu(xword[B+0xe0], xmm1); + vmovq(xmm2, qword[A2-0x80]); + vmovq(xmm3, qword[A2+LDA*1-0x80]); + vmovq(xmm4, qword[A2+LDA*2-0x80]); + vmovq(xmm5, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm3, xmm2, xmm3); + vpunpckldq(xmm5, xmm4, xmm5); + vpunpcklqdq(xmm2, xmm3, xmm5); + vpunpckhqdq(xmm3, xmm3, xmm5); + vmovdqu(xword[B+0x30], xmm2); + vmovdqu(xword[B+0xf0], xmm3); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm2); + vmovhlps(xmm7, xmm2, xmm2); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm13, ymm13, ymm5); + vpmovsxbw(ymm5, xmm1); + vmovhlps(xmm6, xmm1, xmm1); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm3); + vmovhlps(xmm7, xmm3, xmm3); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm13, ymm13, ymm5); + sub(A1, -8); + sub(B, -384); + dec(I); + jg(l6c, T_NEAR); + align(4); + +L(l5cc); + test(M, 0x4); + jle(l968, T_NEAR); + vmovd(xmm0, dword[A1-0x80]); + vmovd(xmm1, dword[A1+LDA*1-0x80]); + vmovd(xmm2, dword[A1+LDA*2-0x80]); + vmovd(xmm3, dword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + vpunpckldq(xmm0, xmm0, xmm1); + vpunpckldq(xmm2, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm0, xmm2); + vmovdqu(xword[B-0x80], xmm0); + vmovd(xmm1, dword[A2-0x80]); + vmovd(xmm2, dword[A2+LDA*1-0x80]); + vmovd(xmm3, dword[A2+LDA*2-0x80]); + vmovd(xmm4, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm1, xmm2); + vpunpckldq(xmm3, xmm3, xmm4); + vpunpcklqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x70], xmm1); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm8, ymm8, ymm5); + vmovd(xmm0, dword[A2-0x80]); + vmovd(xmm1, dword[A2+LDA*1-0x80]); + vmovd(xmm2, dword[A2+LDA*2-0x80]); + vmovd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm0, xmm0, xmm1); + vpunpckldq(xmm2, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm0, xmm2); + vmovdqu(xword[B-0x60], xmm0); + vmovd(xmm1, dword[A2-0x80]); + vmovd(xmm2, dword[A2+LDA*1-0x80]); + vmovd(xmm3, dword[A2+LDA*2-0x80]); + vmovd(xmm4, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm1, xmm2); + vpunpckldq(xmm3, xmm3, xmm4); + vpunpcklqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x50], xmm1); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm9, ymm9, ymm5); + vmovd(xmm0, dword[A2-0x80]); + vmovd(xmm1, dword[A2+LDA*1-0x80]); + vmovd(xmm2, dword[A2+LDA*2-0x80]); + vmovd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm0, xmm0, xmm1); + vpunpckldq(xmm2, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm0, xmm2); + vmovdqu(xword[B-0x40], xmm0); + vmovd(xmm1, dword[A2-0x80]); + vmovd(xmm2, dword[A2+LDA*1-0x80]); + vmovd(xmm3, dword[A2+LDA*2-0x80]); + vmovd(xmm4, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm1, xmm2); + vpunpckldq(xmm3, xmm3, xmm4); + vpunpcklqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x30], xmm1); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm10, ymm10, ymm5); + vmovd(xmm0, dword[A2-0x80]); + vmovd(xmm1, dword[A2+LDA*1-0x80]); + vmovd(xmm2, dword[A2+LDA*2-0x80]); + vmovd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm0, xmm0, xmm1); + vpunpckldq(xmm2, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm0, xmm2); + vmovdqu(xword[B-0x20], xmm0); + vmovd(xmm1, dword[A2-0x80]); + vmovd(xmm2, dword[A2+LDA*1-0x80]); + vmovd(xmm3, dword[A2+LDA*2-0x80]); + vmovd(xmm4, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm1, xmm2); + vpunpckldq(xmm3, xmm3, xmm4); + vpunpcklqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B-0x10], xmm1); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm11, ymm11, ymm5); + vmovd(xmm0, dword[A2-0x80]); + vmovd(xmm1, dword[A2+LDA*1-0x80]); + vmovd(xmm2, dword[A2+LDA*2-0x80]); + vmovd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm0, xmm0, xmm1); + vpunpckldq(xmm2, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm0, xmm2); + vmovdqu(xword[B], xmm0); + vmovd(xmm1, dword[A2-0x80]); + vmovd(xmm2, dword[A2+LDA*1-0x80]); + vmovd(xmm3, dword[A2+LDA*2-0x80]); + vmovd(xmm4, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm1, xmm2); + vpunpckldq(xmm3, xmm3, xmm4); + vpunpcklqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B+0x10], xmm1); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm12, ymm12, ymm5); + vmovd(xmm0, dword[A2-0x80]); + vmovd(xmm1, dword[A2+LDA*1-0x80]); + vmovd(xmm2, dword[A2+LDA*2-0x80]); + vmovd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm0, xmm0, xmm1); + vpunpckldq(xmm2, xmm2, xmm3); + vpunpcklqdq(xmm0, xmm0, xmm2); + vmovdqu(xword[B+0x20], xmm0); + vmovd(xmm1, dword[A2-0x80]); + vmovd(xmm2, dword[A2+LDA*1-0x80]); + vmovd(xmm3, dword[A2+LDA*2-0x80]); + vmovd(xmm4, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpunpckldq(xmm1, xmm1, xmm2); + vpunpckldq(xmm3, xmm3, xmm4); + vpunpcklqdq(xmm1, xmm1, xmm3); + vmovdqu(xword[B+0x30], xmm1); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxbw(ymm6, xmm1); + vmovhlps(xmm7, xmm1, xmm1); + vpmovsxbw(ymm7, xmm7); + vphaddw(ymm6, ymm6, ymm7); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm13, ymm13, ymm5); + sub(A1, -4); + sub(B, -192); + align(4); + +L(l968); + test(M, 0x2); + jle(lc80, T_NEAR); + mov(ax, word[A1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + vpinsrw(xmm0, xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrw(xmm0, xmm0, eax, 0x7); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm8, ymm8, ymm5); + vmovdqu(xword[B-0x80], xmm0); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrw(xmm0, xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm9, ymm9, ymm5); + vmovdqu(xword[B-0x70], xmm0); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrw(xmm0, xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm10, ymm10, ymm5); + vmovdqu(xword[B-0x60], xmm0); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrw(xmm0, xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm11, ymm11, ymm5); + vmovdqu(xword[B-0x50], xmm0); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrw(xmm0, xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm12, ymm12, ymm5); + vmovdqu(xword[B-0x40], xmm0); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrw(xmm0, xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + vpinsrw(xmm0, xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + vpmovsxbw(ymm5, xmm0); + vmovhlps(xmm6, xmm0, xmm0); + vpmovsxbw(ymm6, xmm6); + vphaddw(ymm5, ymm5, ymm6); + vpmovsxwd(ymm5, xmm5); + vpaddd(ymm13, ymm13, ymm5); + vmovdqu(xword[B-0x30], xmm0); + sub(A1, -2); + sub(B, -96); + align(4); + +L(lc80); + test(M, 0x1); + jle(lf1c, T_NEAR); + mov(al, byte[A1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0xf); + vpmovsxbd(ymm7, xmm0); + vpaddd(ymm8, ymm8, ymm7); + vmovhlps(xmm7, xmm0, xmm0); + vpmovsxbd(ymm7, xmm7); + vpaddd(ymm9, ymm9, ymm7); + vmovdqu(xword[B-0x80], xmm0); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x0); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x1); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x2); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0xf); + vpmovsxbd(ymm7, xmm0); + vpaddd(ymm10, ymm10, ymm7); + vmovhlps(xmm7, xmm0, xmm0); + vpmovsxbd(ymm7, xmm7); + vpaddd(ymm11, ymm11, ymm7); + vmovdqu(xword[B-0x70], xmm0); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x0); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x1); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x2); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + vpinsrb(xmm0, xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + vpinsrb(xmm0, xmm0, eax, 0xf); + vpmovsxbd(ymm7, xmm0); + vpaddd(ymm12, ymm12, ymm7); + vmovhlps(xmm7, xmm0, xmm0); + vpmovsxbd(ymm7, xmm7); + vpaddd(ymm13, ymm13, ymm7); + vmovdqu(xword[B-0x60], xmm0); + sub(B, -48); + align(4); + +L(lf1c); + mov(A1, qword[ARG_BIAS]); + vmovdqu(yword[A1], ymm8); + vmovdqu(yword[A1+0x20], ymm9); + vmovdqu(yword[A1+0x40], ymm10); + vmovdqu(yword[A1+0x60], ymm11); + vmovdqu(yword[A1+0x80], ymm12); + vmovdqu(yword[A1+0xa0], ymm13); + add(qword[ARG_BIAS], 0xc0); + sub(N, 0x30); + cmp(N, 0x30); + jge(l20, T_NEAR); + vzeroupper(); + align(4); + +L(lf64); + cmp(N, 0x20); + jl(l22b8, T_NEAR); + align(4); + +L(lf70); + mov(A1, A); + mov(I, LDA); + shl(I, 0x5); + add(A, I); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + pxor(xmm10, xmm10); + pxor(xmm11, xmm11); + pxor(xmm12, xmm12); + pxor(xmm13, xmm13); + pxor(xmm14, xmm14); + pxor(xmm15, xmm15); + mov(I, M); + sar(I, 0x4); + jle(l1750, T_NEAR); + align(4); + +L(lfb4); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B+0x80], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B+0x100], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B+0x10], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B+0x90], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B+0x110], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x60], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B+0x20], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B+0xa0], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B+0x120], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x50], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B+0x30], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B+0xb0], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B+0x130], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B-0x40], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B+0x40], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B+0xc0], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B+0x140], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B-0x30], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B+0x50], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B+0xd0], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B+0x150], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B-0x20], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B+0x60], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B+0xe0], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B+0x160], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B-0x10], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B+0x70], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B+0xf0], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B+0x170], xmm3); + sub(A1, -16); + sub(B, -512); + dec(I); + jg(lfb4, T_NEAR); + align(4); + +L(l1750); + test(M, 0x8); + jle(l1b6c, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B+0x10], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x60], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B+0x20], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x50], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B+0x30], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B-0x40], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B+0x40], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B-0x30], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B+0x50], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B-0x20], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B+0x60], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B-0x10], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B+0x70], xmm1); + sub(A1, -8); + sub(B, -256); + align(4); + +L(l1b6c); + test(M, 0x4); + jle(l1e14, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x60], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x50], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movdqu(xword[B-0x40], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm13, xmm5); + movdqu(xword[B-0x30], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movdqu(xword[B-0x20], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm15, xmm5); + movdqu(xword[B-0x10], xmm0); + sub(A1, -4); + sub(B, -128); + align(4); + +L(l1e14); + test(M, 0x2); + jle(l2068, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x7); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + movdqu(xword[B-0x80], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x70], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm12, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm13, xmm6); + movdqu(xword[B-0x60], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + lea(A2, ptr[A2+LDA*4]); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm14, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm15, xmm6); + movdqu(xword[B-0x50], xmm0); + sub(A1, -2); + sub(B, -64); + align(4); + +L(l2068); + test(M, 0x1); + jle(l226c, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xf); + pmovsxbd(xmm5, xmm0); + paddd(xmm8, xmm5); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm9, xmm6); + pshufd(xmm5, xmm0, 0xaa); + pmovsxbd(xmm5, xmm5); + paddd(xmm10, xmm5); + pshufd(xmm6, xmm0, 0xff); + pmovsxbd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x80], xmm0); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xf); + pmovsxbd(xmm5, xmm0); + paddd(xmm12, xmm5); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm13, xmm6); + pshufd(xmm5, xmm0, 0xaa); + pmovsxbd(xmm5, xmm5); + paddd(xmm14, xmm5); + pshufd(xmm6, xmm0, 0xff); + pmovsxbd(xmm6, xmm6); + paddd(xmm15, xmm6); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + align(4); + +L(l226c); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + movdqu(xword[A1+0x20], xmm10); + movdqu(xword[A1+0x30], xmm11); + movdqu(xword[A1+0x40], xmm12); + movdqu(xword[A1+0x50], xmm13); + movdqu(xword[A1+0x60], xmm14); + movdqu(xword[A1+0x70], xmm15); + add(qword[ARG_BIAS], 0x80); + sub(N, 0x20); + cmp(N, 0x20); + jge(lf70, T_NEAR); + align(4); + +L(l22b8); + cmp(N, 0x10); + jl(l2c94, T_NEAR); + align(4); + +L(l22c4); + mov(A1, A); + mov(I, LDA); + shl(I, 0x4); + add(A, I); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + pxor(xmm10, xmm10); + pxor(xmm11, xmm11); + mov(I, M); + sar(I, 0x4); + jle(l26b4, T_NEAR); + align(4); + +L(l22f4); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x40], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B+0x40], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x30], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B+0x10], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B+0x50], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x60], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x20], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B+0x20], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B+0x60], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x50], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x10], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B+0x30], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B+0x70], xmm3); + sub(A1, -16); + sub(B, -256); + dec(I); + jg(l22f4, T_NEAR); + align(4); + +L(l26b4); + test(M, 0x8); + jle(l28cc, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x40], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x30], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x60], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x20], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x50], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x10], xmm1); + sub(A1, -8); + sub(B, -128); + align(4); + +L(l28cc); + test(M, 0x4); + jle(l2a2c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movdqu(xword[B-0x60], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm11, xmm5); + movdqu(xword[B-0x50], xmm0); + sub(A1, -4); + sub(B, -64); + align(4); + +L(l2a2c); + test(M, 0x2); + jle(l2b5c, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x7); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + movdqu(xword[B-0x80], xmm0); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + pinsrw(xmm0, eax, 0x7); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm10, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x70], xmm0); + sub(A1, -2); + sub(B, -32); + align(4); + +L(l2b5c); + test(M, 0x1); + jle(l2c64, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + lea(A2, ptr[A1+LDA*4]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0x7); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x8); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x9); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xa); + mov(al, byte[A2+LDA3*1-0x80]); + lea(A2, ptr[A2+LDA*4]); + pinsrb(xmm0, eax, 0xb); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0xc); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0xd); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0xe); + mov(al, byte[A2+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0xf); + pmovsxbd(xmm5, xmm0); + paddd(xmm8, xmm5); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm9, xmm6); + pshufd(xmm5, xmm0, 0xaa); + pmovsxbd(xmm5, xmm5); + paddd(xmm10, xmm5); + pshufd(xmm6, xmm0, 0xff); + pmovsxbd(xmm6, xmm6); + paddd(xmm11, xmm6); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l2c64); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + movdqu(xword[A1+0x20], xmm10); + movdqu(xword[A1+0x30], xmm11); + add(qword[ARG_BIAS], 0x40); + sub(N, 0x10); + cmp(N, 0x10); + jge(l22c4, T_NEAR); + align(4); + +L(l2c94); + cmp(N, 0x8); + jl(l31c0, T_NEAR); + align(4); + +L(l2ca0); + mov(A1, A); + lea(A2, ptr[A1+LDA*4]); + lea(I, ptr[A1+LDA*8]); + mov(A, I); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + mov(I, M); + sar(I, 0x4); + jle(l2eac, T_NEAR); + align(4); + +L(l2cc8); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + sub(A1, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x60], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x40], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x20], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x50], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x30], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x10], xmm3); + sub(B, -128); + dec(I); + jg(l2cc8, T_NEAR); + align(4); + +L(l2eac); + test(M, 0x8); + jle(l2fc0, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + sub(A1, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x60], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + align(4); + +L(l2fc0); + test(M, 0x4); + jle(l3078, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + sub(A1, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + align(4); + +L(l3078); + test(M, 0x2); + jle(l3118, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x7); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l3118); + test(M, 0x1); + jle(l319c, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x7); + pmovsxbd(xmm5, xmm0); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm8, xmm5); + paddd(xmm9, xmm6); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l319c); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + add(qword[ARG_BIAS], 0x20); + sub(N, 0x8); + cmp(N, 0x8); + jge(l2ca0, T_NEAR); + align(4); + +L(l31c0); + cmp(N, 0x4); + jl(l349c, T_NEAR); + align(4); + +L(l31cc); + mov(A1, A); + lea(A2, ptr[A1+LDA*2]); + lea(I, ptr[A1+LDA*4]); + mov(A, I); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x4); + jle(l32e4, T_NEAR); + align(4); + +L(l31ec); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + sub(A1, -16); + movdqu(xmm2, xword[A2-0x80]); + movdqu(xmm3, xword[A2+LDA*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x60], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x50], xmm3); + sub(B, -64); + dec(I); + jg(l31ec, T_NEAR); + align(4); + +L(l32e4); + test(M, 0x8); + jle(l3378, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + sub(A1, -8); + movq(xmm2, qword[A2-0x80]); + movq(xmm3, qword[A2+LDA*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l3378); + test(M, 0x4); + jle(l33dc, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + sub(A1, -4); + movd(xmm2, dword[A2-0x80]); + movd(xmm3, dword[A2+LDA*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l33dc); + test(M, 0x2); + jle(l3434, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x3); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l3434); + test(M, 0x1); + jle(l347c, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x3); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l347c); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm7); + add(qword[ARG_BIAS], 0x10); + sub(N, 0x4); + cmp(N, 0x4); + jge(l31cc, T_NEAR); + align(4); + +L(l349c); + cmp(N, 0x2); + jl(l368a, T_NEAR); + align(4); + +L(l34a8); + mov(A1, A); + lea(A2, ptr[A1+LDA*1]); + lea(I, ptr[A1+LDA*2]); + mov(A, I); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x4); + jle(l3558, T_NEAR); + align(4); + +L(l34c8); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + movdqu(xmm1, xword[A2-0x80]); + sub(A2, -16); + movdqa(xmm2, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm2, xmm1); + pshufd(xmm6, xmm0, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + pshufd(xmm6, xmm2, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm2); + sub(B, -32); + dec(I); + jg(l34c8, T_NEAR); + align(4); + +L(l3558); + test(M, 0x8); + jle(l35b0, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + movq(xmm1, qword[A2-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + pshufd(xmm6, xmm0, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l35b0); + test(M, 0x4); + jle(l35f4, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + movd(xmm1, dword[A2-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l35f4); + test(M, 0x2); + jle(l3638, T_NEAR); + mov(ax, word[A1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l3638); + test(M, 0x1); + jle(l366c, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(byte[B-0x80], al); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(byte[B-0x7f], al); + sub(B, -2); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + align(4); + +L(l366c); + mov(A1, qword[ARG_BIAS]); + movq(qword[A1], xmm7); + add(qword[ARG_BIAS], 0x8); + sub(N, 0x2); + cmp(N, 0x2); + jge(l34a8, T_NEAR); + align(4); + +L(l368a); + cmp(N, 0x1); + jl(l37d8, T_NEAR); + align(4); + +L(l3694); + mov(A1, A); + add(A, LDA); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x4); + jle(l36ec, T_NEAR); + align(4); + +L(l36a8); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(I); + jg(l36a8, T_NEAR); + align(4); + +L(l36ec); + test(M, 0x8); + jle(l3728, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l3728); + test(M, 0x4); + jle(l3760, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l3760); + test(M, 0x2); + jle(l3794, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + mov(word[B-0x80], ax); + sub(A1, -2); + sub(B, -2); + align(4); + +L(l3794); + test(M, 0x1); + jle(l37b8, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(l37b8); + mov(A1, qword[ARG_BIAS]); + movd(dword[A1], xmm7); + add(qword[ARG_BIAS], 0x4); + sub(N, 0x1); + cmp(N, 0x1); + jge(l3694, T_NEAR); + align(4); + +L(l37d8); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +#undef ARG_BIAS +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp new file mode 100644 index 0000000000..c7f1393c9d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp @@ -0,0 +1,821 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_sum_bn_kern::jit_avx512_core_u8_copy_sum_bn_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#define ARG_BIAS 24+stacksize+rsp + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp +#define ARG_BIAS 72+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l20; +Xbyak::Label l22c; +Xbyak::Label l340; +Xbyak::Label l3f8; +Xbyak::Label l48; +Xbyak::Label l498; +Xbyak::Label l51c; +Xbyak::Label l540; +Xbyak::Label l54c; +Xbyak::Label l56c; +Xbyak::Label l664; +Xbyak::Label l6f8; +Xbyak::Label l75c; +Xbyak::Label l7b4; +Xbyak::Label l7fc; +Xbyak::Label l81c; +Xbyak::Label l828; +Xbyak::Label l848; +Xbyak::Label l8d8; +Xbyak::Label l930; +Xbyak::Label l974; +Xbyak::Label l9b8; +Xbyak::Label l9ec; +Xbyak::Label la0a; +Xbyak::Label la14; +Xbyak::Label la28; +Xbyak::Label la6c; +Xbyak::Label laa8; +Xbyak::Label lae0; +Xbyak::Label lb14; +Xbyak::Label lb38; +Xbyak::Label lb58; + + preamble(); + auto stacksize = get_size_of_abi_save_regs(); +#ifdef _WIN32 + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(N, qword[N]); + mov(M, qword[M]); + mov(LDA, qword[LDA]); + sub(A, -128); + sub(B, -128); + lea(LDA3, ptr[LDA+LDA*2]); + cmp(N, 0x8); + jl(l540, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + lea(A2, ptr[A1+LDA*4]); + lea(I, ptr[A1+LDA*8]); + mov(A, I); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + mov(I, M); + sar(I, 0x4); + jle(l22c, T_NEAR); + align(4); + +L(l48); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + movdqu(xmm2, xword[A1+LDA*2-0x80]); + movdqu(xmm3, xword[A1+LDA3*1-0x80]); + sub(A1, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x60], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x40], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x20], xmm3); + movdqu(xmm0, xword[A2-0x80]); + movdqu(xmm1, xword[A2+LDA*1-0x80]); + movdqu(xmm2, xword[A2+LDA*2-0x80]); + movdqu(xmm3, xword[A2+LDA3*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x50], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x30], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x10], xmm3); + sub(B, -128); + dec(I); + jg(l48, T_NEAR); + align(4); + +L(l22c); + test(M, 0x8); + jle(l340, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + movq(xmm2, qword[A1+LDA*2-0x80]); + movq(xmm3, qword[A1+LDA3*1-0x80]); + sub(A1, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x60], xmm1); + movq(xmm0, qword[A2-0x80]); + movq(xmm1, qword[A2+LDA*1-0x80]); + movq(xmm2, qword[A2+LDA*2-0x80]); + movq(xmm3, qword[A2+LDA3*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + align(4); + +L(l340); + test(M, 0x4); + jle(l3f8, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + movd(xmm2, dword[A1+LDA*2-0x80]); + movd(xmm3, dword[A1+LDA3*1-0x80]); + sub(A1, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A2-0x80]); + movd(xmm1, dword[A2+LDA*1-0x80]); + movd(xmm2, dword[A2+LDA*2-0x80]); + movd(xmm3, dword[A2+LDA3*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + align(4); + +L(l3f8); + test(M, 0x2); + jle(l498, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A1+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A1+LDA3*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x3); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x4); + mov(ax, word[A2+LDA*1-0x80]); + pinsrw(xmm0, eax, 0x5); + mov(ax, word[A2+LDA*2-0x80]); + pinsrw(xmm0, eax, 0x6); + mov(ax, word[A2+LDA3*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x7); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l498); + test(M, 0x1); + jle(l51c, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A2+LDA*2-0x80]); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A2+LDA3*1-0x80]); + pinsrb(xmm0, eax, 0x7); + pmovsxbd(xmm5, xmm0); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm8, xmm5); + paddd(xmm9, xmm6); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l51c); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + add(qword[ARG_BIAS], 0x20); + sub(N, 0x8); + cmp(N, 0x8); + jge(l20, T_NEAR); + align(4); + +L(l540); + cmp(N, 0x4); + jl(l81c, T_NEAR); + align(4); + +L(l54c); + mov(A1, A); + lea(A2, ptr[A1+LDA*2]); + lea(I, ptr[A1+LDA*4]); + mov(A, I); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x4); + jle(l664, T_NEAR); + align(4); + +L(l56c); + movdqu(xmm0, xword[A1-0x80]); + movdqu(xmm1, xword[A1+LDA*1-0x80]); + sub(A1, -16); + movdqu(xmm2, xword[A2-0x80]); + movdqu(xmm3, xword[A2+LDA*1-0x80]); + sub(A2, -16); + movdqa(xmm4, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm4, xmm1); + movdqa(xmm5, xmm2); + punpckldq(xmm2, xmm3); + punpckhdq(xmm5, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + movdqa(xmm3, xmm4); + punpcklqdq(xmm4, xmm5); + punpckhqdq(xmm3, xmm5); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm1); + pmovsxbw(xmm5, xmm4); + movhlps(xmm6, xmm4); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x60], xmm4); + pmovsxbw(xmm5, xmm3); + movhlps(xmm6, xmm3); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x50], xmm3); + sub(B, -64); + dec(I); + jg(l56c, T_NEAR); + align(4); + +L(l664); + test(M, 0x8); + jle(l6f8, T_NEAR); + movq(xmm0, qword[A1-0x80]); + movq(xmm1, qword[A1+LDA*1-0x80]); + sub(A1, -8); + movq(xmm2, qword[A2-0x80]); + movq(xmm3, qword[A2+LDA*1-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklqdq(xmm0, xmm2); + punpckhqdq(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l6f8); + test(M, 0x4); + jle(l75c, T_NEAR); + movd(xmm0, dword[A1-0x80]); + movd(xmm1, dword[A1+LDA*1-0x80]); + sub(A1, -4); + movd(xmm2, dword[A2-0x80]); + movd(xmm3, dword[A2+LDA*1-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + punpckldq(xmm2, xmm3); + punpcklqdq(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l75c); + test(M, 0x2); + jle(l7b4, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1+LDA*1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x1); + mov(ax, word[A2-0x80]); + pinsrw(xmm0, eax, 0x2); + mov(ax, word[A2+LDA*1-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x3); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l7b4); + test(M, 0x1); + jle(l7fc, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A2+LDA*1-0x80]); + pinsrb(xmm0, eax, 0x3); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l7fc); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm7); + add(qword[ARG_BIAS], 0x10); + sub(N, 0x4); + cmp(N, 0x4); + jge(l54c, T_NEAR); + align(4); + +L(l81c); + cmp(N, 0x2); + jl(la0a, T_NEAR); + align(4); + +L(l828); + mov(A1, A); + lea(A2, ptr[A1+LDA*1]); + lea(I, ptr[A1+LDA*2]); + mov(A, I); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x4); + jle(l8d8, T_NEAR); + align(4); + +L(l848); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + movdqu(xmm1, xword[A2-0x80]); + sub(A2, -16); + movdqa(xmm2, xmm0); + punpckldq(xmm0, xmm1); + punpckhdq(xmm2, xmm1); + pshufd(xmm6, xmm0, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + pshufd(xmm6, xmm2, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm2); + sub(B, -32); + dec(I); + jg(l848, T_NEAR); + align(4); + +L(l8d8); + test(M, 0x8); + jle(l930, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + movq(xmm1, qword[A2-0x80]); + sub(A2, -8); + punpckldq(xmm0, xmm1); + pshufd(xmm6, xmm0, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l930); + test(M, 0x4); + jle(l974, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + movd(xmm1, dword[A2-0x80]); + sub(A2, -4); + punpckldq(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l974); + test(M, 0x2); + jle(l9b8, T_NEAR); + mov(ax, word[A1-0x80]); + sub(A1, -2); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A2-0x80]); + sub(A2, -2); + pinsrw(xmm0, eax, 0x1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l9b8); + test(M, 0x1); + jle(l9ec, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + mov(byte[B-0x80], al); + mov(al, byte[A2-0x80]); + pinsrb(xmm0, eax, 0x1); + mov(byte[B-0x7f], al); + sub(B, -2); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + align(4); + +L(l9ec); + mov(A1, qword[ARG_BIAS]); + movq(qword[A1], xmm7); + add(qword[ARG_BIAS], 0x8); + sub(N, 0x2); + cmp(N, 0x2); + jge(l828, T_NEAR); + align(4); + +L(la0a); + cmp(N, 0x1); + jl(lb58, T_NEAR); + align(4); + +L(la14); + mov(A1, A); + add(A, LDA); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x4); + jle(la6c, T_NEAR); + align(4); + +L(la28); + movdqu(xmm0, xword[A1-0x80]); + sub(A1, -16); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(I); + jg(la28, T_NEAR); + align(4); + +L(la6c); + test(M, 0x8); + jle(laa8, T_NEAR); + movq(xmm0, qword[A1-0x80]); + sub(A1, -8); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(laa8); + test(M, 0x4); + jle(lae0, T_NEAR); + movd(xmm0, dword[A1-0x80]); + sub(A1, -4); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(lae0); + test(M, 0x2); + jle(lb14, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + mov(word[B-0x80], ax); + sub(A1, -2); + sub(B, -2); + align(4); + +L(lb14); + test(M, 0x1); + jle(lb38, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrb(xmm0, eax, 0x0); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(lb38); + mov(A1, qword[ARG_BIAS]); + movd(dword[A1], xmm7); + add(qword[ARG_BIAS], 0x4); + sub(N, 0x1); + cmp(N, 0x1); + jge(la14, T_NEAR); + align(4); + +L(lb58); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +#undef ARG_BIAS +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp new file mode 100644 index 0000000000..afe4f1713e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp @@ -0,0 +1,647 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_generator.hpp" +#include "common.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +jit_avx512_core_u8_copy_sum_bt_kern::jit_avx512_core_u8_copy_sum_bt_kern(): jit_generator(nullptr, GEMM_CODE_SIZE) +{ + +#ifndef _WIN32 +#define M rdi +#define N rsi +#define A rdx +#define LDA rcx +#define ALPHA r8 +#define B r9 + +#define I rax +#define A1 r10 +#define A2 r8 +#define LDA3 r11 + +#define ARG_BIAS 24+stacksize+rsp + +#else + +#define M rcx +#define N rdx +#define A r8 +#define LDA r9 +#define ALPHA rax +#define B rdi + +#define I rax +#define A1 rsi +#define A2 r10 +#define LDA3 r11 + +#define ARG_ALPHA 40+stacksize+rsp +#define ARG_B 48+stacksize+rsp +#define ARG_BIAS 72+stacksize+rsp + +#endif + +inLocalLabel(); +{ + +Xbyak::Label l15c; +Xbyak::Label l1f4; +Xbyak::Label l20; +Xbyak::Label l248; +Xbyak::Label l280; +Xbyak::Label l2a4; +Xbyak::Label l2b0; +Xbyak::Label l2c8; +Xbyak::Label l384; +Xbyak::Label l3e8; +Xbyak::Label l40; +Xbyak::Label l424; +Xbyak::Label l448; +Xbyak::Label l468; +Xbyak::Label l474; +Xbyak::Label l48c; +Xbyak::Label l550; +Xbyak::Label l5bc; +Xbyak::Label l600; +Xbyak::Label l628; +Xbyak::Label l646; +Xbyak::Label l650; +Xbyak::Label l668; +Xbyak::Label l700; +Xbyak::Label l760; +Xbyak::Label l7a4; +Xbyak::Label l7c8; +Xbyak::Label l7e8; + + preamble(); + auto stacksize = get_size_of_abi_save_regs(); +#ifdef _WIN32 + mov(ALPHA, ptr[ARG_ALPHA]); + mov(B, ptr[ARG_B]); +#endif + + mov(M, qword[M]); + mov(N, qword[N]); + mov(LDA, qword[LDA]); + lea(LDA3, ptr[LDA+LDA*2]); + sub(A, -128); + sub(B, -128); + cmp(N, 0x8); + jl(l2a4, T_NEAR); + align(4); + +L(l20); + mov(A1, A); + add(A, 0x8); + pxor(xmm8, xmm8); + pxor(xmm9, xmm9); + mov(I, M); + sar(I, 0x3); + jle(l15c, T_NEAR); + align(4); + +L(l40); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x60], xmm0); + movdqu(xword[B-0x50], xmm1); + sub(B, -64); + dec(I); + jg(l40, T_NEAR); + align(4); + +L(l15c); + test(M, 0x4); + jle(l1f4, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + movq(xmm2, qword[A1-0x80]); + add(A1, LDA); + movq(xmm3, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + movdqa(xmm1, xmm0); + punpcklwd(xmm0, xmm2); + punpckhwd(xmm1, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + pmovsxbw(xmm5, xmm1); + movhlps(xmm6, xmm1); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm9, xmm5); + movdqu(xword[B-0x80], xmm0); + movdqu(xword[B-0x70], xmm1); + sub(B, -32); + align(4); + +L(l1f4); + test(M, 0x2); + jle(l248, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + movq(xmm1, qword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm8, xmm5); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm6, xmm6); + pmovsxwd(xmm6, xmm6); + paddd(xmm9, xmm6); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l248); + test(M, 0x1); + jle(l280, T_NEAR); + movq(xmm0, qword[A1-0x80]); + add(A1, LDA); + pmovsxbd(xmm5, xmm0); + pshufd(xmm6, xmm0, 0x55); + pmovsxbd(xmm6, xmm6); + paddd(xmm8, xmm5); + paddd(xmm9, xmm6); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l280); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm8); + movdqu(xword[A1+0x10], xmm9); + add(qword[ARG_BIAS], 0x20); + sub(N, 0x8); + cmp(N, 0x8); + jge(l20, T_NEAR); + align(4); + +L(l2a4); + cmp(N, 0x4); + jl(l468, T_NEAR); + align(4); + +L(l2b0); + mov(A1, A); + add(A, 0x4); + pxor(xmm7, xmm7); + mov(I, M); + sar(I, 0x3); + jle(l384, T_NEAR); + align(4); + +L(l2c8); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x70], xmm0); + sub(B, -32); + dec(I); + jg(l2c8, T_NEAR); + align(4); + +L(l384); + test(M, 0x4); + jle(l3e8, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + movd(xmm2, dword[A1-0x80]); + add(A1, LDA); + movd(xmm3, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + movhlps(xmm6, xmm0); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + align(4); + +L(l3e8); + test(M, 0x2); + jle(l424, T_NEAR); + movd(xmm0, dword[A1-0x80]); + add(A1, LDA); + movd(xmm1, dword[A1-0x80]); + add(A1, LDA); + punpcklbw(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l424); + test(M, 0x1); + jle(l448, T_NEAR); + movd(xmm0, dword[A1-0x80]); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l448); + mov(A1, qword[ARG_BIAS]); + movdqu(xword[A1], xmm7); + add(qword[ARG_BIAS], 0x10); + sub(N, 0x4); + cmp(N, 0x4); + jge(l2b0, T_NEAR); + align(4); + +L(l468); + cmp(N, 0x2); + jl(l646, T_NEAR); + align(4); + +L(l474); + mov(A1, A); + add(A, 0x2); + pxor(xmm7, xmm7); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l550, T_NEAR); + align(4); + +L(l48c); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm4, eax, 0x0); + punpcklbw(xmm1, xmm2); + punpcklbw(xmm3, xmm4); + punpcklwd(xmm1, xmm3); + punpcklqdq(xmm0, xmm1); + pshufd(xmm6, xmm0, 0xd8); + pmovsxbw(xmm5, xmm6); + movhlps(xmm6, xmm6); + pmovsxbw(xmm6, xmm6); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movdqu(xword[B-0x80], xmm0); + sub(B, -16); + dec(LDA3); + jg(l48c, T_NEAR); + align(4); + +L(l550); + test(M, 0x4); + jle(l5bc, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm2, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm3, eax, 0x0); + punpcklbw(xmm0, xmm1); + punpcklbw(xmm2, xmm3); + punpcklwd(xmm0, xmm2); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + align(4); + +L(l5bc); + test(M, 0x2); + jle(l600, T_NEAR); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm0, eax, 0x0); + mov(ax, word[A1-0x80]); + add(A1, LDA); + pinsrw(xmm1, eax, 0x0); + punpcklbw(xmm0, xmm1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l600); + test(M, 0x1); + jle(l628, T_NEAR); + mov(ax, word[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + mov(word[B-0x80], ax); + sub(B, -2); + align(4); + +L(l628); + mov(A1, qword[ARG_BIAS]); + movq(qword[A1], xmm7); + add(qword[ARG_BIAS], 0x8); + sub(N, 0x2); + cmp(N, 0x2); + jge(l474, T_NEAR); + align(4); + +L(l646); + cmp(N, 0x1); + jl(l7e8, T_NEAR); + align(4); + +L(l650); + mov(A1, A); + add(A, 0x1); + pxor(xmm7, xmm7); + mov(LDA3, M); + sar(LDA3, 0x3); + jle(l700, T_NEAR); + align(4); + +L(l668); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x4); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x5); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x6); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x7); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm6); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movq(qword[B-0x80], xmm0); + sub(B, -8); + dec(LDA3); + jg(l668, T_NEAR); + align(4); + +L(l700); + test(M, 0x4); + jle(l760, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x2); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x3); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + movd(dword[B-0x80], xmm0); + sub(B, -4); + align(4); + +L(l760); + test(M, 0x2); + jle(l7a4, T_NEAR); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x0); + mov(byte[B-0x80], al); + mov(al, byte[A1-0x80]); + add(A1, LDA); + pinsrb(xmm0, eax, 0x1); + pmovsxbw(xmm5, xmm0); + phaddw(xmm5, xmm5); + pmovsxwd(xmm5, xmm5); + paddd(xmm7, xmm5); + mov(byte[B-0x7f], al); + sub(B, -2); + align(4); + +L(l7a4); + test(M, 0x1); + jle(l7c8, T_NEAR); + mov(al, byte[A1-0x80]); + pinsrw(xmm0, eax, 0x0); + pmovsxbd(xmm5, xmm0); + paddd(xmm7, xmm5); + mov(byte[B-0x80], al); + sub(B, -1); + align(4); + +L(l7c8); + mov(A1, qword[ARG_BIAS]); + movd(dword[A1], xmm7); + add(qword[ARG_BIAS], 0x4); + sub(N, 0x1); + cmp(N, 0x1); + jge(l650, T_NEAR); + align(4); + +L(l7e8); + + postamble(); +} +outLocalLabel(); + +#undef M +#undef N +#undef A +#undef LDA +#undef ALPHA +#undef B +#undef I +#undef A1 +#undef A2 +#undef LDA3 +#ifdef _WIN32 +#undef ARG_ALPHA +#undef ARG_B +#endif +#undef ARG_BIAS +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp new file mode 100644 index 0000000000..4fc11afcbc --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp @@ -0,0 +1,116 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "../f32/ref_gemm_f32.hpp" +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +mkldnn_status_t ref_gemm_s8x8s32(const char *transa, const char *transb, + const char *offsetc, const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao, + const b_dt *B, const int *LDB, const int8_t *bo, const float *beta, + int32_t *C, const int *LDC, const int32_t *co) { + + if (*M == 0 || *N == 0 || *K == 0) + return mkldnn_success; + + bool OCisR = (*offsetc == 'R' || *offsetc == 'r'); + bool OCisC = (*offsetc == 'C' || *offsetc == 'c'); + bool AisN = (*transa == 'N' || *transa == 'n'); + bool BisN = (*transb == 'N' || *transb == 'n'); + + int m = *M, n = *N, k = *K, lda = *LDA, ldb = *LDB, ldc = *LDC; + size_t sizeA = AisN ? lda * k : lda * m; + size_t sizeB = BisN ? ldb * n : ldb * k; + size_t sizeC = ldc * n; + + double *dA = (double *)malloc(sizeA * sizeof(double), PAGE_4K); + double *dB = (double *)malloc(sizeB * sizeof(double), PAGE_4K); + double *dC = (double *)malloc(sizeC * sizeof(double), PAGE_4K); + + if (utils::any_null(dA, dB, dC)) { + free(dA); + free(dB); + free(dC); + return mkldnn_out_of_memory; + } + + auto da_setter = [=] (int i, int j, double v) { dA[j * lda + i] = v; }; + auto db_setter = [=] (int i, int j, double v) { dB[j * ldb + i] = v; }; + + auto ia_accessor = [=] (int i, int j) { return A[j * lda + i]; }; + auto ib_accessor = [=] (int i, int j) { return B[j * ldb + i]; }; + + const int a_rows = AisN ? m : k; + const int a_cols = AisN ? k : m; + mkldnn::impl::parallel_nd(a_cols, a_rows, [&](int j, int i) { + da_setter(i, j, + static_cast(ia_accessor(i, j)) + static_cast(ao[0])); + }); + + const int b_rows = BisN ? k : n; + const int b_cols = BisN ? n : k; + mkldnn::impl::parallel_nd(b_cols, b_rows, [&](int j, int i) { + db_setter(i, j, + static_cast(ib_accessor(i, j)) + static_cast(bo[0])); + }); + double one = 1.0, zero = 0.0; + ref_gemm(transa, transb, M, N, K, &one, dA, LDA, dB, LDB, &zero, + dC, LDC, nullptr); + + auto i2d = [=] (int32_t v) { return static_cast(v); }; + auto f2d = [=] (float v) { return static_cast(v); }; + + mkldnn::impl::parallel_nd(n, m, [&] (int j, int i) { + double coffset = OCisR ? i2d(co[j]) : OCisC ? i2d(co[i]) : i2d(co[0]); + double val = ((*beta == 0.0f) ? 0.0 : f2d(*beta) * i2d(C[i + j * ldc])) + + f2d(*alpha) * dC[i + j * ldc] + coffset; + C[i + j * ldc] = math::out_round(math::saturate(val)); + }); + + free(dA); + free(dB); + free(dC); + return mkldnn_success; +} + +template mkldnn_status_t ref_gemm_s8x8s32( + const char *transa, const char *transb, const char *offsetc, + const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao, + const uint8_t *B, const int *LDB, const int8_t *bo, + const float *beta, int32_t *C, const int *LDC, const int32_t *co); + +template mkldnn_status_t ref_gemm_s8x8s32( + const char *transa, const char *transb, const char *offsetc, + const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao, + const int8_t *B, const int *LDB, const int8_t *bo, + const float *beta, int32_t *C, const int *LDC, const int32_t *co); + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp new file mode 100644 index 0000000000..6c0370ae99 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp @@ -0,0 +1,38 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef REF_GEMM_S8X8S32_HPP +#define REF_GEMM_S8X8S32_HPP + +#include + +#include "mkldnn_types.h" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +mkldnn_status_t ref_gemm_s8x8s32(const char *transa, const char *transb, + const char *offsetc, const int *M, const int *N, const int *K, + const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao, + const b_dt *B, const int *LDB, const int8_t *bo, const float *beta, + int32_t *C, const int *LDC, const int32_t *co); + +} +} +} +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp new file mode 100644 index 0000000000..de1035f3b2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp @@ -0,0 +1,180 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "common.hpp" +#include "nstl.hpp" +#include "math_utils.hpp" + +#include "../gemm.hpp" +#include "jit_avx512_core_gemm_s8u8s32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +void compensation_init(const char *offsetC, int32_t *compensation, int len, + const int32_t *oc) { + bool OCisC = (*offsetC == 'C' || *offsetC == 'c'); + bool OCisF = (*offsetC == 'F' || *offsetC == 'f'); + + if (OCisF && (*oc) != 0) { + for (int i = 0; i < len; i++) + compensation[i] = *oc; + } else if (OCisC) { + for (int i = 0; i < len; i++) + compensation[i] = oc[i]; + } else { + parallel_nd(len, [=](int i) { compensation[i] = 0; }); + } +} + +void compensation_compute(bool transa, int m, int k, float alpha, + const int8_t *a, int lda, int32_t *compensation) { + if (!transa) { + const int L2_cache_size = get_cache_size(2, true); + const int blocking_factor = nstl::min(k, L2_cache_size / lda + 1); + const int npanels = k / blocking_factor; + const bool has_tile = k % blocking_factor > 0; + + parallel_nd(npanels, m, [&](int j, int i) { + int32_t val = 0; + for (int jb = 0; jb < blocking_factor; jb++) { + val += a[(i + (ptrdiff_t)j * blocking_factor * lda) + + (ptrdiff_t)jb * lda]; + } + if (alpha != 1.0f) { + val = math::out_round(math::saturate( + (double)val * alpha * -128.0)); + } else { + val *= -128; + } + fetch_and_add(&compensation[i], val); + }); + + if (has_tile) { + parallel_nd(m, [=](int i) { + int32_t val = 0; + for (int j = npanels * blocking_factor; j < k; j++) { + val += a[i + (ptrdiff_t)j * lda]; + } + if (alpha != 1.0f) { + val = math::out_round(math::saturate( + (double)val * alpha * -128.0)); + } else { + val *= -128; + } + fetch_and_add(&compensation[i], val); + }); + } + } else { + parallel_nd(m, [=](int i) { + int32_t val = 0; + for (int j = 0; j < k; j++) { + val += a[j + (ptrdiff_t)i * lda]; + } + if (alpha != 1.0f) { + val = math::out_round(math::saturate( + (double)val * alpha * -128.0)); + } else { + val *= -128; + } + compensation[i] += val; + }); + } +} + +void copy_and_shift_b(bool transb, int k, int n, uint8_t *b_u8, int ldb_u8, + const int8_t *b_s8, int ldb_s8) { + const int b_cols = transb ? k : n; + + parallel_nd(b_cols, [=](int j) { + const int b_rows = transb ? n : k; + + uint8_t *pb_u8 = b_u8 + j * ldb_u8; + const int8_t *pb_s8 = b_s8 + j * ldb_s8; + + for (int i = 0; i < b_rows; i++) { + (*pb_u8) = (*pb_s8) + 128; + pb_u8++; + pb_s8++; + } + }); +} + +/** + * gemm_s8s8s32 operation is defined as follows: + * C = alpha * op(A) * (op(B) + B_shift) + beta * C + C_offset + compensation + * + * where + * - compensation is a vector of length m that contains computed compensation + * that may contain C_offset if applicable. The compensation is applied inside + * gemm_s8u8s32 as a C_offset + * - B_shift is a k-by-n matrix, every element of B_shift is equal to 128 + * + * What is the compensation: + * In order to prepare the matrix B for gemm_s8u8s32 call the B_shift is applied: + * C = alpha * op(A) * (op(B) + B_shift) + beta * C + C_offset = + * alpha * op(A) * op(B) + alpha * op(A) * B_shift + beta * C + C_offset + * compensation = -alpha * op(A) * B_shift + * Since B_shift is a matrix, every element of which is equal to 128 then + * - if op(A) = A: compensation contains sum of the elements in each row + * scaled by -128 * alpha + * - if op(A) = A**T: compensation contains sum of the elements in each column + * scaled by -128 * alpha + * + * The rest of parameters is described in mkldnn.h + */ +mkldnn_status_t simple_gemm_s8s8s32( + const char *transA, const char *transB, const char *offsetC, + const int *m, const int *n, const int *k, + const float *alpha, const int8_t *a, const int *lda, const int8_t *oa, + const int8_t *b, const int *ldb, const int8_t *ob, + const float *beta, int32_t *c, const int *ldc, const int32_t *oc) { + if (*oa != 0 || *ob != 0) return mkldnn_unimplemented; + + int M = *m, N = *n, K = *k; + bool transa = (*transA == 'T' || *transA == 't'); + bool transb = (*transB == 'T' || *transB == 't'); + int ld = transb ? N : K; + + uint8_t *b_u8 = (uint8_t *)malloc(sizeof(uint8_t) * K * N, 64); + int32_t *compensation = (int32_t *)malloc(sizeof(int32_t) * M, 64); + + if (utils::any_null(b_u8, compensation)) { + free(b_u8); + free(compensation); + return mkldnn_out_of_memory; + } + + compensation_init(offsetC, compensation, M, oc); + compensation_compute(transa, M, K, *alpha, a, *lda, compensation); + copy_and_shift_b(transb, K, N, b_u8, ld, b, *ldb); + + gemm_s8x8s32(transA, transB, "C", m, n, k, alpha, a, lda, oa, b_u8, + &ld, ob, beta, c, ldc, compensation); + + if ((*offsetC == 'R' || *offsetC == 'r')) + parallel_nd(M, N, + [=](int i, int j) { c[i + (ptrdiff_t)j * *ldc] += oc[j]; }); + + free(b_u8); + free(compensation); + + return mkldnn_success; +} +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp new file mode 100644 index 0000000000..03a3d2f7e0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef SIMPLE_GEMM_S8S8S32_HPP +#define SIMPLE_GEMM_S8S8S32_HPP + +#include +#include "mkldnn_types.h" + +namespace mkldnn { +namespace impl { +namespace cpu { + +mkldnn_status_t simple_gemm_s8s8s32( + const char *transA, const char *transB, const char *offsetC, + const int *m, const int *n, const int *k, + const float *alpha, const int8_t *a, const int *lda, const int8_t *oa, + const int8_t *b, const int *ldb, const int8_t *ob, + const float *beta, int32_t *c, const int *ldc, const int32_t *oc); +} +} +} + +#endif // SIMPLE_GEMM_S8S8S32_HPP diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp new file mode 100644 index 0000000000..604a728b47 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp @@ -0,0 +1,307 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "gemm_convolution.hpp" +#include "utils.hpp" +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" +#include "ref_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +void gemm_convolution_fwd_t::execute_forward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + auto col = scratchpad(ctx).get(key_conv_gemm_col); + + const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_; + + const int M = jcp.os * jcp.od; + const size_t src_step = jcp.ic * jcp.ih * jcp.iw * jcp.id; + const size_t dst_step = jcp.oc * M; + const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks; + + assert(IMPLICATION( + jcp.id != 1, jcp.oh_block == jcp.oh && jcp.ow_block == jcp.ow)); + assert(IMPLICATION(jcp.ow_block != jcp.ow, jcp.oh_block == 1)); + + const int K = jcp.ic * jcp.ks; + const int N = jcp.oc; + + if (jcp.im2col_sz && jcp.id != 1) + parallel_nd(jcp.im2col_sz * jcp.nthr, + [&](ptrdiff_t i) { col[i] = (data_t)0; }); + + const int nb_oh = div_up(jcp.oh, jcp.oh_block); + const int nb_ow = div_up(jcp.ow, jcp.ow_block); + const size_t work_amount = jcp.ngroups * jcp.mb * jcp.od * nb_oh * nb_ow; + parallel(jcp.nthr, [&](const int ithr, const int nthr) { + data_t *_col = col + (ptrdiff_t)ithr * jcp.im2col_sz; + + int g{ 0 }, n{ 0 }, od{ 0 }, ohb{ 0 }, owb{ 0 }; + size_t start = 0, end = 0; + + balance211(work_amount, nthr, ithr, start, end); + nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb, od, jcp.od, ohb, + nb_oh, owb, nb_ow); + for (size_t iwork = start; iwork < end; ++iwork) { + int oh = ohb * jcp.oh_block; + int ow = owb * jcp.ow_block; + const data_t *_src = src + (n * jcp.ngroups + g) * src_step; + const data_t *_weights = weights + g * weights_g_size; + data_t *_dst_im = dst + (n * jcp.ngroups + g) * dst_step; + const int h_step = nstl::min(jcp.oh_block, jcp.oh - oh); + const int w_step = nstl::min(jcp.ow_block, jcp.ow - ow); + if (jcp.im2col_sz) { + if (jcp.id == 1) + jit_gemm_convolution_utils::im2col( + jcp, _src, _col, oh, h_step, ow, w_step); + else + jit_gemm_convolution_utils::im2col_3d(jcp, _src, _col, od); + } + + const data_t one = 1.0; + + const int m = h_step * w_step; + const int LDA = jcp.im2col_sz ? m : M; + data_t *_dst = _dst_im + od * jcp.os + oh * jcp.ow + ow; + + extended_sgemm("N", "N", &m, &N, &K, &one, + jcp.im2col_sz ? _col : _src + od * m, &LDA, _weights, &K, + &this->beta_, _dst, &M); + + data_t *d = _dst; + if (eltwise_) { + // fast branch for ReLU case + if (eltwise_->alg_ == alg_kind::eltwise_relu) { + parallel_nd(jcp.oc, [&](const int oc) { + data_t b = jcp.with_bias ? bias[g * jcp.oc + oc] : 0; + data_t *d_ = d + oc * M; + PRAGMA_OMP_SIMD() + for (int oS = 0; oS < m; ++oS) { + d_[oS] += b; + if (d_[oS] < 0) d_[oS] *= eltwise_->alpha_; + } + }); + } else { + parallel_nd(jcp.oc, [&](const int oc) { + data_t b = jcp.with_bias ? bias[g * jcp.oc + oc] : 0; + data_t *d_ = d + oc * M; + PRAGMA_OMP_SIMD() + for (int oS = 0; oS < m; ++oS) { + d_[oS] += b; + d_[oS] = eltwise_->compute_scalar(d_[oS]); + } + }); + } + } else if (jcp.with_bias) { + parallel_nd(jcp.oc, [&](const int oc) { + data_t b = bias[g * jcp.oc + oc]; + data_t *d_ = d + oc * M; + PRAGMA_OMP_SIMD() + for (int oS = 0; oS < m; ++oS) { + d_[oS] += b; + } + }); + } + nd_iterator_step(g, jcp.ngroups, n, jcp.mb, od, jcp.od, ohb, nb_oh, + owb, nb_ow); + } + }); +} + +void gemm_convolution_bwd_data_t::execute_backward_data( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + auto col = scratchpad(ctx).get(key_conv_gemm_col); + + const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_; + + const int M = jcp.os * jcp.od; + const size_t src_step = jcp.ic * jcp.ih * jcp.iw * jcp.id; + const size_t dst_step = jcp.oc * M; + const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks; + + const int m = jcp.os; + const int K = jcp.oc; + const int N = jcp.ic * jcp.ks; + const int LDC = jcp.im2col_sz ? m : M; + + const size_t work_amount = (size_t)jcp.ngroups * jcp.mb; + + if (jcp.id > 1) { + const ptrdiff_t diff_src_sz = (ptrdiff_t)(work_amount * src_step); + parallel_nd(diff_src_sz, [&](ptrdiff_t i) { diff_src[i] = (data_t)0; }); + } + + parallel(jcp.nthr, [&](const int ithr, const int nthr) { + data_t *_col = col + (ptrdiff_t)ithr * jcp.im2col_sz; + + int g{0}, n{0}; + size_t start = 0, end = 0; + balance211(work_amount, nthr, ithr, start, end); + nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb); + for (size_t iwork = start; iwork < end; ++iwork) { + + data_t *_diff_src = diff_src + (n * jcp.ngroups + g)*src_step; + const data_t *_weights = weights + g * weights_g_size; + for (int od = 0; od < jcp.od; ++od) { + const data_t *_diff_dst = diff_dst + (n * jcp.ngroups + g) + *dst_step + od * m; + + const data_t zero = 0.0, one = 1.0; + extended_sgemm("N", "T", &m, &N, &K, &one, _diff_dst, &M, + _weights, &N, &zero, + jcp.im2col_sz ? _col:_diff_src + od * m, &LDC); + + if (jcp.im2col_sz) { + if (jcp.id == 1) + jit_gemm_convolution_utils::col2im(jcp, _col, + _diff_src); + else + jit_gemm_convolution_utils::col2im_3d(jcp, _col, + _diff_src, od); + } + } + nd_iterator_step(g, jcp.ngroups, n, jcp.mb); + } + }); +} + +void gemm_convolution_bwd_weights_t::execute_backward_weights( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + auto col = scratchpad(ctx).get(key_conv_gemm_col); + auto wei_reduction = scratchpad(ctx).get(key_conv_wei_reduction); + + const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_; + + const int K = jcp.os * jcp.od; + const size_t src_step = jcp.ic * jcp.ih * jcp.iw * jcp.id; + const size_t dst_step = jcp.oc * K; + const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks; + + const int k = jcp.os; + const int N = jcp.oc; + const int M = jcp.ic * jcp.ks; + const int LDA = jcp.im2col_sz ? k : K; + + parallel_nd(jcp.im2col_sz * jcp.nthr, + [&](ptrdiff_t i) { col[i] = (data_t)0; }); + + parallel(jcp.nthr, [&](const int ithr, const int nthr) { + int ithr_g, nthr_g, ithr_mb, nthr_mb; + size_t g_start{0}, g_end{0}, mb_start{0}, mb_end{0}; + + const int mb_for_balance = jcp.need_wei_reduction ? jcp.mb : 1; + jit_gemm_convolution_utils::bwd_weights_balance(ithr, nthr, jcp.ngroups, + mb_for_balance, ithr_g, nthr_g, ithr_mb, nthr_mb); + + assert(IMPLICATION(!jcp.need_wei_reduction, nthr_mb == 1)); + const int need_reduction = nthr_mb != 1; + + if (ithr_g != -1 && ithr_mb != -1) { + balance211((size_t)jcp.ngroups, nthr_g, ithr_g, g_start, g_end); + balance211((size_t)jcp.mb, nthr_mb, ithr_mb, mb_start, mb_end); + + assert(IMPLICATION((g_end - g_start) > 1, need_reduction == 0)); + + data_t *_col = col + (ptrdiff_t)ithr * jcp.im2col_sz; + data_t *weights_reduce_base = wei_reduction + + ithr_g * nthr_mb * weights_g_size; + data_t *weights_reduce = weights_reduce_base + + ithr_mb * weights_g_size; + + for (size_t g = g_start; g < g_end; ++g) { + data_t *_diff_weights = need_reduction + ? weights_reduce : (diff_weights + g * weights_g_size); + for (size_t mb = mb_start; mb < mb_end; ++mb) { + const data_t *_src = src + (mb*jcp.ngroups+g)*src_step; + for (int od = 0; od < jcp.od; ++od) { + const data_t *_diff_dst = diff_dst + + (mb*jcp.ngroups+g)*dst_step + od * k; + + if (jcp.im2col_sz) { + if (jcp.id == 1) + jit_gemm_convolution_utils::im2col( + jcp, _src, _col, 0, jcp.oh, 0, jcp.ow); + else + jit_gemm_convolution_utils::im2col_3d(jcp, _src, + _col, od); + } + + const data_t zero = 0.0, one = 1.0; + extended_sgemm( + "T", "N", &M, &N, &k, &one, + jcp.im2col_sz ? _col : _src + od * k, + &LDA, _diff_dst, &K, + mb == mb_start && od == 0 ? &zero : &one, + _diff_weights, &M); + } + } + } + if (need_reduction) { + mkldnn_thr_barrier(); + data_t *weights_base = diff_weights + g_start * weights_g_size; + jit_gemm_convolution_utils::bwd_weights_reduction_par( + ithr_mb, nthr_mb, jcp, weights_reduce_base, weights_base); + } + } else + if (need_reduction) { mkldnn_thr_barrier(); } + }); + + if (jcp.with_bias) { + parallel_nd(jcp.ngroups, jcp.oc, [&](int g, int oc) { + data_t db = 0; + size_t offset_ = (size_t)g * dst_step + (size_t)oc * K; + for (int mb = 0; mb < jcp.mb; ++mb) + { + size_t offset = offset_ + (size_t)mb * jcp.ngroups * dst_step; + for (int od = 0; od < jcp.od; ++od) + for (int oh = 0; oh < jcp.oh; ++oh) + PRAGMA_OMP_SIMD(reduction(+:db)) + for (int ow = 0; ow < jcp.ow; ++ow) { + db += diff_dst[offset]; + offset++; + } + } + diff_bias[g*jcp.oc+oc] = db; + }); + } +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp new file mode 100644 index 0000000000..302e46369a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp @@ -0,0 +1,250 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_GEMM_CONVOLUTION_HPP +#define CPU_JIT_GEMM_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "gemm_convolution_utils.hpp" +#include "gemm/gemm.hpp" +#include "ref_eltwise.hpp" + +#include "cpu_convolution_pd.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct gemm_convolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats_common(dat_tag(), wei_tag(), dat_tag()) + && post_ops_ok() + && memory_desc_matches_tag(*src_md(), dat_tag()) + && memory_desc_matches_tag(*dst_md(), dat_tag()) + && memory_desc_matches_tag(*weights_md(), wei_tag()); + if (!ok) return status::unimplemented; + + auto scratchpad = scratchpad_registry().registrar(); + return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad, + *desc(), src_md(), weights_md(0), dst_md(), + mkldnn_get_max_threads()); + } + + jit_gemm_conv_conf_t jcp_; + + protected: + format_tag_t dat_tag() const { + using namespace format_tag; + return utils::pick(ndims() - 3, ncw, nchw, ncdhw); + } + + format_tag_t wei_tag() const { + using namespace format_tag; + return with_groups() + ? utils::pick(ndims() - 3, goiw, goihw, goidhw) + : utils::pick(ndims() - 3, oiw, oihw, oidhw); + } + + bool post_ops_ok() const { + auto const &po = attr()->post_ops_; + auto is_eltwise = [&](int idx) + { return po.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return po.entry_[idx].is_sum(); }; + + switch (po.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + return false; + } + }; + + gemm_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd, true) + , eltwise_(nullptr) + { + const auto &post_ops = pd()->attr()->post_ops_; + const data_t one = 1.0, zero = 0.0; + beta_ = post_ops.find(primitive_kind::sum) >= 0 ? one : zero; + + const int entry_idx = post_ops.find(primitive_kind::eltwise); + if (entry_idx != -1) eltwise_ = new ref_eltwise_scalar_fwd_t( + post_ops.entry_[entry_idx].eltwise); + } + + ~gemm_convolution_fwd_t() { delete eltwise_; } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + data_t beta_; + + ref_eltwise_scalar_fwd_t* eltwise_; +}; + +struct gemm_convolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_convolution_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::undef, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats_common(dat_tag(), wei_tag(), dat_tag()) + && memory_desc_matches_tag(*diff_src_md(), dat_tag()) + && memory_desc_matches_tag(*diff_dst_md(), dat_tag()) + && memory_desc_matches_tag(*weights_md(), wei_tag()); + if (!ok) return status::unimplemented; + + auto scratchpad = scratchpad_registry().registrar(); + return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad, + *desc(), diff_src_md(), weights_md(0), diff_dst_md(), + mkldnn_get_max_threads()); + } + + jit_gemm_conv_conf_t jcp_; + + protected: + format_tag_t dat_tag() const { + using namespace format_tag; + return utils::pick(ndims() - 3, ncw, nchw, ncdhw); + } + + format_tag_t wei_tag() const { + using namespace format_tag; + return with_groups() + ? utils::pick(ndims() - 3, goiw, goihw, goidhw) + : utils::pick(ndims() - 3, oiw, oihw, oidhw); + } + }; + + gemm_convolution_bwd_data_t(const pd_t *apd) + : cpu_primitive_t(apd, true) {} + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +struct gemm_convolution_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_convolution_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats_common(dat_tag(), wei_tag(), dat_tag()) + && memory_desc_matches_tag(*src_md(), dat_tag()) + && memory_desc_matches_tag(*diff_dst_md(), dat_tag()) + && memory_desc_matches_tag(*diff_weights_md(), wei_tag()); + if (!ok) return status::unimplemented; + + auto scratchpad = scratchpad_registry().registrar(); + return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad, + *desc(), src_md(), diff_weights_md(0), diff_dst_md(), + mkldnn_get_max_threads()); + } + + jit_gemm_conv_conf_t jcp_; + + protected: + format_tag_t dat_tag() const { + using namespace format_tag; + return utils::pick(ndims() - 3, ncw, nchw, ncdhw); + } + + format_tag_t wei_tag() const { + using namespace format_tag; + return with_groups() + ? utils::pick(ndims() - 3, goiw, goihw, goidhw) + : utils::pick(ndims() - 3, oiw, oihw, oidhw); + } + }; + + gemm_convolution_bwd_weights_t(const pd_t *apd) + : cpu_primitive_t(apd, true) {} + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp new file mode 100644 index 0000000000..f133b1e62b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp @@ -0,0 +1,771 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" +#include "cpu_isa_traits.hpp" + +#include "gemm_convolution_utils.hpp" +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::utils; +using namespace prop_kind; +using namespace data_type; + +namespace jit_gemm_convolution_utils { + +void im2col_3d(const jit_gemm_conv_conf_t &jcp, const float *im, float *col, + int od) +{ + const size_t OHW = jcp.oh * jcp.ow; + const size_t im_step = jcp.ih * jcp.iw * jcp.id; + const size_t col_step = jcp.ks * OHW; + + parallel_nd(jcp.ic, [&](int ic) { + const float *__restrict im_loc = im + ic * im_step; + float *__restrict col_loc = col + ic * col_step; + int id = od * jcp.stride_d - jcp.f_pad; + for (int kd = 0; kd < jcp.kd; ++kd) { + float *__restrict col_ = col_loc + kd * jcp.kh * jcp.kw * OHW; + if (id < 0 || id >= jcp.id) { + int ih_ = -jcp.t_pad; + for (int kh = 0; kh < jcp.kh; ++kh) { + int ih = ih_; + for (int oh = 0; oh < jcp.oh; ++oh) { + if (ih < 0 || ih >= jcp.ih) { + ih += jcp.stride_h; + continue; + } + int iw_ = -jcp.l_pad; + for (int kw = 0; kw < jcp.kw; ++kw) { + int iw = iw_; + for (int ow = 0; ow < jcp.ow; ++ow) { + if (iw < 0 || iw >= jcp.iw) { + iw += jcp.stride_w; + continue; + } + + const size_t col_idx = kw * OHW + oh * jcp.ow + + ow; + + col_[col_idx] = 0; + iw += jcp.stride_w; + } + iw_ += (1 + jcp.dilate_w); + } + ih += jcp.stride_h; + } + ih_ += (1 + jcp.dilate_h); + col_ += jcp.kw * OHW; + } + } else { + const float *__restrict im_ = im_loc + id * jcp.ih * jcp.iw; + int ih_ = -jcp.t_pad; + for (int kh = 0; kh < jcp.kh; ++kh) { + int ih = ih_; + for (int oh = 0; oh < jcp.oh; ++oh) { + if (ih < 0 || ih >= jcp.ih) { + ih += jcp.stride_h; + continue; + } + int iw_ = -jcp.l_pad; + for (int kw = 0; kw < jcp.kw; ++kw) { + int iw = iw_; + for (int ow = 0; ow < jcp.ow; ++ow) { + if (iw < 0 || iw >= jcp.iw) { + iw += jcp.stride_w; + continue; + } + + const size_t col_idx = kw * OHW + oh * jcp.ow + + ow; + const size_t im_idx = ih * jcp.iw + iw; + + col_[col_idx] = im_[im_idx]; + iw += jcp.stride_w; + } + iw_ += (1 + jcp.dilate_w); + } + ih += jcp.stride_h; + } + ih_ += (1 + jcp.dilate_h); + col_ += jcp.kw * OHW; + } + } + id += (1 + jcp.dilate_d); + } + }); +} + +/* col[ic][kh][kw][oh][ow] <-- im2col(im[ic][ih][iw]) */ +void im2col(const jit_gemm_conv_conf_t &jcp, const float *__restrict im, + float *__restrict col, int hs, int hb, int ws, int wb) { + const size_t im_step = jcp.is; + const size_t col_step = jcp.ks * hb * wb; + if (jcp.stride_w == 1) { + // Generated code is more optimized for stride_w == 1 + // because innermost loop is by width + auto ker = [&](int ic, int kh, int kw, int oh) { + const float *__restrict im_ = im + ic * im_step; + float *__restrict col_ + = col + ic * col_step + ((kh * jcp.kw + kw) * hb + oh) * wb; + + const int ih = (oh + hs) * jcp.stride_h - jcp.t_pad + + kh * (1 + jcp.dilate_h); + if (ih < 0 || ih >= jcp.ih) { + for (int ow = 0; ow < wb; ++ow) + col_[ow] = 0.f; + } else { + for (int ow = 0; ow < wb; ++ow) { + const int iw = ow + ws - jcp.l_pad + kw * (1 + jcp.dilate_w); + if (iw < 0 || iw >= jcp.iw) + col_[ow] = 0.f; + else { + const size_t im_idx = ih * jcp.iw + iw; + col_[ow] = im_[im_idx]; + } + } + } + }; + + if (jcp.outer_threading) { + for (int ic = 0; ic < jcp.ic; ic++) + for (int kh = 0; kh < jcp.kh; kh++) + for (int kw = 0; kw < jcp.kw; kw++) + for (int oh = 0; oh < hb; oh++) + ker(ic, kh, kw, oh); + } + else { + parallel_nd(jcp.ic, jcp.kh, jcp.kw, hb, ker); + } + } else if (jcp.ic == 1) { + parallel_nd(jcp.kh, hb, [&](int kh, int oh) { + const int ih = (oh + hs) * jcp.stride_h - jcp.t_pad + + kh * (1 + jcp.dilate_h); + if (ih < 0 || ih >= jcp.ih) + for (int kw = 0; kw < jcp.kw; ++kw) { + for (int ow = 0; ow < wb; ++ow) { + const size_t col_idx + = ((kh * jcp.kw + kw) * hb + oh) * wb + ow; + col[col_idx] = 0; + } + } + else + for (int kw = 0; kw < jcp.kw; ++kw) { + for (int ow = 0; ow < wb; ++ow) { + const int iw = (ow + ws) * jcp.stride_w - jcp.l_pad + + kw * (1 + jcp.dilate_w); + const size_t col_idx + = ((kh * jcp.kw + kw) * hb + oh) * wb + ow; + const size_t im_idx = ih * jcp.iw + iw; + if (iw < 0 || iw >= jcp.iw) + col[col_idx] = 0; + else + col[col_idx] = im[im_idx]; + } + } + }); + } else { + + parallel_nd(jcp.ic, jcp.kh, jcp.kw, hb, + [&](int ic, int kh, int kw, int oh) { + const float *__restrict im_ = im + ic * im_step; + float *__restrict col_ = col + ic * col_step + + ((kh * jcp.kw + kw) * hb + oh) * wb; + + const int ih = (oh + hs) * jcp.stride_h - jcp.t_pad + + kh * (1 + jcp.dilate_h); + if (ih < 0 || ih >= jcp.ih) { + for (int ow = 0; ow < wb; ++ow) + col_[ow] = 0.f; + } else { + for (int ow = 0; ow < wb; ++ow) { + const int iw = (ow + ws) * jcp.stride_w - jcp.l_pad + + kw * (1 + jcp.dilate_w); + const size_t im_idx = ih * jcp.iw + iw; + if (iw < 0 || iw >= jcp.iw) + col_[ow] = 0.f; + else + col_[ow] = im_[im_idx]; + } + } + }); + } +} + +inline int limit(int low, int upper, int value) { + return nstl::max(low, nstl::min(upper, value)); +} + +/* col[kh][kw][ic][oh][ow] <-- im2col_u8(im[ih][iw][ic]) */ +template +void im2col_u8(const jit_gemm_conv_conf_t &jcp, const T *__restrict im, + T *__restrict imtr, uint8_t *__restrict col, int hs, int hb, int ws, + int wb) { + uint8_t shift = jcp.signed_input ? 128 : 0; + const int dh = 1 + jcp.dilate_h; + const int dw = 1 + jcp.dilate_w; + const int sh = jcp.stride_h; + const int sw = jcp.stride_w; + const int im_iw_stride = jcp.ic * jcp.ngroups; + const int im_ih_stride = jcp.iw * im_iw_stride; + const int tp = jcp.t_pad; + const int lp = jcp.l_pad; + + if (jcp.outer_threading && sh == 1 && sw == 1 && dh == 1 && dw == 1) { + /* im[ih][iw][ic] --> imtr[ic][ih][iw] --> col[kh][kw][ic][oh][ow] */ + const int hp = hs - tp; + const int wp = ws - lp; + const int ih_start = limit(0, jcp.ih, hp); + const int ih_end = limit(0, jcp.ih, hp + hb + jcp.kh); + const int iw_start = limit(0, jcp.iw, wp); + const int iw_end = limit(0, jcp.iw, wp + wb + jcp.kw); + + const int ihb = ih_end - ih_start; + const int iwb = iw_end - iw_start; + + const int imtr_ic_stride = ihb * iwb; + const ptrdiff_t imtr_idx_shift = ih_start * iwb + iw_start; + for (int ic = 0; ic < jcp.ic; ic++) { + const ptrdiff_t imtr_idx_ic = ic * imtr_ic_stride - imtr_idx_shift; + for (int ih = ih_start; ih < ih_end; ih++) { + const ptrdiff_t im_idx_ih = ic + ih * im_ih_stride; + const ptrdiff_t imtr_idx_ih = imtr_idx_ic + ih * iwb; + for (int iw = iw_start; iw < iw_end; iw++) + imtr[imtr_idx_ih + iw] = im[im_idx_ih + iw * im_iw_stride]; + } + } + + const int col_ic_str = hb * wb; + const int col_kw_stride = jcp.ic * col_ic_str; + const int col_kh_stride = jcp.kw * col_kw_stride; + + const int oh_init = ih_start - hp; + const int ow_init = iw_start - wp; + for (int kh = 0; kh < jcp.kh; kh++) { + const ptrdiff_t col_idx_kh = kh * col_kh_stride; + const int oh_kh = oh_init - kh; + const int oh_start = limit(0, hb, oh_kh); + const int oh_end = limit(0, hb, oh_kh + ihb); + for (int kw = 0; kw < jcp.kw; kw++) { + const ptrdiff_t col_idx_kw + = col_idx_kh + kw * jcp.ic * col_ic_str; + const int ow_kw = ow_init - kw; + const int imtr_shift = oh_kh * iwb + ow_kw; + const int ow_start = limit(0, wb, ow_kw); + const int ow_end = limit(0, wb, ow_kw + iwb); + for (int ic = 0; ic < jcp.ic; ic++) { + const ptrdiff_t col_idx_ic = col_idx_kw + ic * col_ic_str; + const int imtr_idx_ic = ic * imtr_ic_stride - imtr_shift; + for (int oh = 0; oh < oh_start; oh++) { + const ptrdiff_t col_idx_oh = col_idx_ic + oh * wb; + for (int ow = 0; ow < wb; ++ow) + col[col_idx_oh + ow] = shift; + } + for (int oh = oh_start; oh < oh_end; oh++) { + const ptrdiff_t col_idx_oh = col_idx_ic + oh * wb; + const ptrdiff_t imtr_idx_oh = imtr_idx_ic + oh * iwb; + for (int ow = 0; ow < ow_start; ++ow) + col[col_idx_oh + ow] = shift; + for (int ow = ow_start; ow < ow_end; ++ow) + col[col_idx_oh + ow] + = imtr[imtr_idx_oh + ow] + shift; + for (int ow = ow_end; ow < wb; ++ow) + col[col_idx_oh + ow] = shift; + } + for (int oh = oh_end; oh < hb; oh++) { + const ptrdiff_t col_idx_oh = col_idx_ic + oh * wb; + for (int ow = 0; ow < wb; ++ow) + col[col_idx_oh + ow] = shift; + } + } + } + } + } else { + parallel_nd(jcp.kh, jcp.kw, jcp.ic, hb, + [&](int kh, int kw, int ic, int oh) { + const int hp = tp - kh * dh; + const int ih = (oh + hs) * sh - hp; + const ptrdiff_t col_idx_base + = (((kh * jcp.kw + kw) * jcp.ic + ic) * hb + oh) * wb; + if (ih < 0 || ih >= jcp.ih) + for (int ow = 0; ow < wb; ow++) + col[col_idx_base + ow] = shift; + else { + const int wp = lp - kw * dw; + const int ow_start = limit(0, wb, div_up(wp, sw) - ws); + const int ow_end + = limit(0, wb, div_up(jcp.iw + wp, sw) - ws); + for (int ow = 0; ow < ow_start; ow++) + col[col_idx_base + ow] = shift; + const int iw_base = ws * sw - wp; + const ptrdiff_t im_idx_base = ih * im_ih_stride + ic; + for (int ow = ow_start; ow < ow_end; ow++) { + const int iw = iw_base + ow * sw; + const ptrdiff_t im_idx + = im_idx_base + iw * im_iw_stride; + col[col_idx_base + ow] = im[im_idx] + shift; + } + for (int ow = ow_end; ow < wb; ow++) + col[col_idx_base + ow] = shift; + } + }); + } +} + +template void im2col_u8(const jit_gemm_conv_conf_t &jcp, + const int8_t *__restrict im, int8_t *__restrict imtr, + uint8_t *__restrict col, int hs, int hb, int ws, int wb); +template void im2col_u8(const jit_gemm_conv_conf_t &jcp, + const uint8_t *__restrict im, uint8_t *__restrict imtr, + uint8_t *__restrict col, int hs, int hb, int ws, int wb); + +/* im[ih][iw][ic] <-- col2im_s32(col[oh][ow][kh][kw][ic]) */ +void col2im_s32(const jit_gemm_conv_conf_t &jcp, const int32_t *__restrict col, + int32_t *__restrict im) +{ + parallel(0, [&](const int ithr, const int nthr) { + int h_nthr = nstl::min(jcp.ih, nthr); + int w_nthr = nstl::min(jcp.iw, nthr / h_nthr); + int h_ithr = 1, h_s = 0, h_e = 0, w_ithr = 1, w_s = 0, w_e = 0; + if (ithr < h_nthr * w_nthr) { + h_ithr = ithr / w_nthr; + w_ithr = ithr % w_nthr; + balance211(jcp.ih, h_nthr, h_ithr, h_s, h_e); + balance211(jcp.iw, w_nthr, w_ithr, w_s, w_e); + } else { + h_ithr = w_ithr = -ithr; + h_s = h_e = w_s = w_e = -1; + } + + for (int ih = h_s; ih < h_e; ++ih) { + for (int iw = w_s; iw < w_e; ++iw) { + PRAGMA_OMP_SIMD() + for (int ic = 0; ic < jcp.ic; ++ic) { + im[(ih * jcp.iw + iw) * jcp.ic + ic] = 0; + } + } + } + + // TODO: reduce region: [0.. oh] --> [h_s * sh .. h_e * sh] + for (int oh = 0; oh < jcp.oh; ++oh) { + for (int ow = 0; ow < jcp.ow; ++ow) { + for (int kh = 0; kh < jcp.kh; ++kh) { + const int ih = oh * jcp.stride_h + - jcp.t_pad + kh * (1 + jcp.dilate_h); + if (ih < h_s || ih >= h_e) continue; + + for (int kw = 0; kw < jcp.kw; ++kw) { + const int iw = ow * jcp.stride_w + - jcp.l_pad + kw * (1 + jcp.dilate_w); + if (iw < w_s || iw >= w_e) continue; + + const size_t col_idx = (((oh * jcp.ow + ow) * jcp.kh + + kh) * jcp.kw + kw) * jcp.ic; + const size_t im_idx + = (ih * jcp.iw + iw) * jcp.ic; + PRAGMA_OMP_SIMD() + for (int ic = 0; ic < jcp.ic; ++ic) { + im[im_idx + ic] += col[col_idx + ic]; + } + } + } + } + } + }); +} + +void col2im_3d(const jit_gemm_conv_conf_t &jcp, const float *col, float *im, + int od) +{ + parallel_nd(jcp.ic, [&](int ic) { + const float *__restrict col_ = col + (size_t)ic * jcp.ks * jcp.os; + float *__restrict im_ic = im + (size_t)ic * jcp.ih * jcp.iw * jcp.id; + + int id = od * jcp.stride_d - jcp.f_pad; + for (int kd = 0; kd < jcp.kd; ++kd) { + if (id < 0 || id >= jcp.id) { + col_ += jcp.kh * jcp.kw * jcp.os; + id += (1 + jcp.dilate_d); + continue; + } + + float *__restrict im_ = im_ic + id * jcp.ih * jcp.iw; + + for (int oh = 0; oh < jcp.oh; ++oh) { + for (int kh = 0; kh < jcp.kh; ++kh) { + const int ih = oh * jcp.stride_h - jcp.t_pad + + kh * (1 + jcp.dilate_h); + if (ih < 0 || ih >= jcp.ih) continue; + + for (int ow = 0; ow < jcp.ow; ++ow) { + for (int kw = 0; kw < jcp.kw; ++kw) { + const int iw = ow * jcp.stride_w - jcp.l_pad + + kw * (1 + jcp.dilate_w); + if (iw < 0 || iw >= jcp.iw) continue; + + const size_t col_idx = ((kh*jcp.kw + kw)*jcp.oh+oh)*jcp.ow+ow; + const size_t im_idx = ih*jcp.iw + iw; + im_[im_idx] += col_[col_idx]; + }} + }} + + col_ += jcp.kh * jcp.kw * jcp.os; + id += (1 + jcp.dilate_d); + } + }); +} + +void col2im(const jit_gemm_conv_conf_t &jcp, const float *col, float *im) { + const size_t col_step = jcp.ks * jcp.os; + const size_t im_step = jcp.ih * jcp.iw; + const int iS = jcp.ih * jcp.iw; + + parallel_nd(jcp.ic, [&](int ic) { + float *__restrict im_ = im + ic * im_step; + const float *__restrict col_ = col + ic * col_step; + PRAGMA_OMP_SIMD() + for (int is = 0; is < iS; ++is) im_[is] = 0.; + + for (int kh = 0; kh < jcp.kh; ++kh) { + for (int oh = 0; oh < jcp.oh; ++oh) { + const int ih = + oh * jcp.stride_h - jcp.t_pad + kh * (1 + jcp.dilate_h); + if (ih < 0 || ih >= jcp.ih) continue; + + for (int kw = 0; kw < jcp.kw; ++kw) { + for (int ow = 0; ow < jcp.ow; ++ow) { + const int iw = + ow * jcp.stride_w - jcp.l_pad + kw * (1 + jcp.dilate_w); + if (iw < 0 || iw >= jcp.iw) continue; + + const size_t col_idx = ((kh*jcp.kw + kw)*jcp.oh+oh)*jcp.ow+ow; + const size_t im_idx = ih*jcp.iw + iw; + im_[im_idx] += col_[col_idx]; + } + } + } + } + }); +} + +status_t init_conf(jit_gemm_conv_conf_t &jcp, + memory_tracking::registrar_t &scratchpad, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, int max_threads) { + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + const int ndims = src_d.ndims(); + const int is_1d = ndims == 3; + const int is_3d = ndims == 5; + + jcp.prop_kind = cd.prop_kind; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.id = is_3d ? src_d.dims()[2] : 1; + jcp.ih = is_1d ? 1 : src_d.dims()[ndims - 2]; + jcp.iw = src_d.dims()[ndims - 1]; + jcp.od = is_3d ? dst_d.dims()[2] : 1; + jcp.oh = is_1d ? 1 : dst_d.dims()[ndims - 2]; + jcp.ow = dst_d.dims()[ndims - 1]; + + jcp.kd = is_3d ? weights_d.dims()[with_groups + 2] : 1; + jcp.kh = is_1d ? 1 : weights_d.dims()[with_groups + ndims - 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + + jcp.f_pad = is_3d ? cd.padding[0][0] : 0; + jcp.t_pad = is_1d ? 0 : cd.padding[0][ndims - 4]; + jcp.l_pad = cd.padding[0][ndims - 3]; + + jcp.stride_d = is_3d ? cd.strides[0] : 1; + jcp.stride_h = is_1d ? 1 : cd.strides[ndims - 4]; + jcp.stride_w = cd.strides[ndims - 3]; + + jcp.dilate_d = is_3d ? cd.dilates[0] : 0; + jcp.dilate_h = is_1d ? 0 : cd.dilates[ndims - 4]; + jcp.dilate_w = cd.dilates[ndims - 3]; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef + || cd.diff_bias_desc.format_kind != format_kind::undef; + + jcp.is = jcp.ih * jcp.iw; + jcp.os = jcp.oh * jcp.ow; + jcp.ks = jcp.kh * jcp.kw * jcp.kd; + + jcp.signed_input = src_d.data_type() == data_type::s8; + + jcp.im2col_sz = !everyone_is(true, + jcp.ow == jcp.iw, jcp.oh == jcp.ih, jcp.od == jcp.id, + jcp.stride_w == 1, jcp.stride_h == 1, jcp.stride_d == 1, + jcp.ks == 1, !jcp.signed_input) + ? (ptrdiff_t)jcp.ic * jcp.ks * jcp.os : 0; + + jcp.outer_threading = false; + + bool is_int8_conv = utils::one_of(src_d.data_type(), s32, s8, u8) + && weights_d.data_type() == s8; + + const int vlen = mayiuse(avx512_common) + ? cpu_isa_traits::vlen + : mayiuse(avx) + ? cpu_isa_traits::vlen + : mayiuse(sse42) ? cpu_isa_traits::vlen : 4; + const int simd_w = vlen / (is_int8_conv ? 1 : 4); + + const bool is_bwd_d = jcp.prop_kind == backward_data; + const bool is_bwd_w = jcp.prop_kind == backward_weights; + const bool is_fwd = !is_bwd_d && !is_bwd_w; + jcp.oh_block = is_fwd ? jcp.oh : jcp.ih; + jcp.ow_block = is_fwd ? jcp.ow : jcp.iw; + + using namespace memory_tracking::names; + bool is_depthwise = jcp.ic == 1 && jcp.oc == 1 && jcp.ngroups != 1; + + // TODO: maybe mitigate blocking restriction + const int wei_size = jcp.oc * jcp.ic * jcp.kh * jcp.kw; + const int L2 = get_cache_size(2, true) + / (is_int8_conv ? sizeof(int8_t) : sizeof(float)); + bool is_blocking_applicable = true + && is_fwd && jcp.im2col_sz + && jcp.id == 1 && jcp.od == 1 + && jcp.dilate_h == 0 && jcp.dilate_w == 0 + && !is_depthwise + && wei_size < L2/2; + if (is_blocking_applicable) { + // looking for oh and ow blocking + int h_block{ jcp.oh_block }, w_block{ jcp.ow_block }; + const int ic = jcp.ic; + const int oc = jcp.oc; + const int iw = jcp.iw; + const int ow = jcp.ow; + const int oh = jcp.oh; + const int os = oh * ow; + + // 1. cache requirement + int row_size = ic * ow * jcp.ks + 2 * (ic * iw + oc * ow); + if (is_int8_conv) { + // Heuristic rule: gemm needed a lot of memory for internal usage + row_size *= 5; + // memory for accumulators + row_size += oc * ow * sizeof(uint32_t); + // memory for transposition + row_size += ic * iw; + } + + h_block = nstl::max(1, nstl::min(oh, div_up(L2, row_size))); + if (h_block == 1) { + int col_size = ic * jcp.ks + 2 * (ic + oc); + if (is_int8_conv) { + col_size *= 5; + col_size += oc * sizeof(uint32_t); + col_size += ic; + } + w_block = nstl::max(1, nstl::min(ow, div_up(L2, col_size))); + } + + // 2. threading requirement + if (h_block != oh) + h_block = nstl::max(1, rnd_dn(h_block, 4)); + if (w_block != ow) + w_block = nstl::max(1, rnd_dn(w_block, simd_w)); + + float thr_eff = 0.f; + float thr_eff_treshold = 0.9f; + if (w_block == ow) { + do { + int nb_h = div_up(oh, h_block); + size_t work = jcp.ngroups * jcp.mb * jcp.od * nb_h; + float disb = (float)oh / rnd_up(oh, h_block); + thr_eff = (float)work / rnd_up(work, max_threads); + thr_eff = (thr_eff + disb) / 2.f; + if (thr_eff >= thr_eff_treshold) + break; + h_block = rnd_dn(h_block - 4, 4); + } while (h_block > 0); + } + if (thr_eff < thr_eff_treshold) // we didn't find suitable h_block + { + h_block = 1; + int nb_h = oh; + do { + int nb_w = div_up(ow, w_block); + size_t work_amount = jcp.ngroups * jcp.mb * nb_h * nb_w; + float disb = (float)ow / rnd_up(ow, w_block); + thr_eff = (float)work_amount / rnd_up(work_amount, max_threads); + thr_eff = (thr_eff + disb) / 2.f; + if (thr_eff > thr_eff_treshold) + break; + w_block = rnd_dn(w_block - simd_w, simd_w); + } while (w_block > 0); + } + h_block = nstl::max(1, h_block); + w_block = nstl::max(1, w_block); + const size_t inner_work = div_up(os, simd_w) * div_up(oc, simd_w); + const float inner_thr_eff + = (float)inner_work / rnd_up(inner_work, max_threads); + if (thr_eff >= inner_thr_eff / 2 && h_block > 0 && w_block > 0) { + jcp.oh_block = h_block; + jcp.ow_block = w_block; + jcp.outer_threading = true; + } + // updating jcp.im2col_sz + if (jcp.oh_block != 1) + jcp.ow_block = ow; + jcp.im2col_sz = (ptrdiff_t)ic * jcp.ks * jcp.oh_block * jcp.ow_block; + } + // For threading selection in bwd_d we do: + // 1. Rough estimation of efficiency for inner and outer threading. + // 2. Gemm size estimation in assumption that it does not work + // so effectively for small sizes. + // 64K - this is heuristic gemm size per thread threshold. + const int gemm_thrld = 64 * 1024; + + if (is_int8_conv) { + if (is_fwd) { + if (!jcp.outer_threading) { + bool is_depthwise = jcp.ic == 1 && jcp.oc == 1 && jcp.ngroups != 1; + const size_t outer_work = jcp.ngroups * jcp.mb; + const float outer_thr_eff + = (float)outer_work / rnd_up(outer_work, max_threads); + const size_t inner_work + = div_up(jcp.is, simd_w) * div_up(jcp.ic, simd_w); + const float inner_thr_eff + = (float)inner_work / rnd_up(inner_work, max_threads); + jcp.outer_threading = (is_depthwise + || (jcp.is / max_threads < 64 && jcp.mb != 1)) + && (outer_thr_eff / inner_thr_eff >= 1.f + || (jcp.os * jcp.ic * jcp.oc) / max_threads < gemm_thrld); + } + jcp.nthr = jcp.outer_threading ? max_threads : 1; + scratchpad.book(key_conv_gemm_col, + sizeof(int8_t) * jcp.nthr * jcp.im2col_sz); + scratchpad.book(key_conv_int_dat_in_acc_dt, + sizeof(int32_t) * jcp.nthr * jcp.oh_block * jcp.ow_block * jcp.oc); + scratchpad.book(key_conv_gemm_imtr, + sizeof(int8_t) * jcp.nthr * jcp.is * jcp.ic); + } else if (is_bwd_d) { + bool is_depthwise = jcp.ic == 1 && jcp.oc == 1 && jcp.ngroups != 1; + const size_t outer_work = jcp.ngroups * jcp.mb; + const float outer_thr_eff + = (float)outer_work / rnd_up(outer_work, max_threads); + const size_t inner_work + = div_up(jcp.is, simd_w) * div_up(jcp.ic, simd_w); + const float inner_thr_eff + = (float)inner_work / rnd_up(inner_work, max_threads); + jcp.outer_threading = (is_depthwise + || (jcp.is / max_threads < 64 && jcp.mb != 1)) + && (outer_thr_eff / inner_thr_eff >= 1.f + || (jcp.is * jcp.ic * jcp.oc) / max_threads < gemm_thrld); + + jcp.nthr = jcp.outer_threading ? max_threads : 1; + scratchpad.book(key_conv_gemm_col, + sizeof(int32_t) * jcp.nthr * jcp.im2col_sz); + scratchpad.book(key_conv_int_dat_in_acc_dt, + sizeof(int32_t) * jcp.nthr * jcp.is * jcp.ic); + } else if (is_bwd_w) { + assert(!"unimplemented prop_kind"); + return status::unimplemented; + } + } else { + if (is_fwd) { + if (!jcp.outer_threading) { + const size_t outer_work_amount = jcp.ngroups * jcp.mb * jcp.od; + const float outer_thr_eff = (float)outer_work_amount + / rnd_up(outer_work_amount, max_threads); + const size_t inner_work_amount + = div_up(jcp.os, simd_w) * div_up(jcp.oc, simd_w); + const float inner_thr_eff = (float)inner_work_amount + / rnd_up(inner_work_amount, max_threads); + jcp.outer_threading = jcp.os / max_threads < 512 + && IMPLICATION(jcp.od == 1, jcp.mb != 1 || jcp.ngroups > 2) + && (outer_thr_eff / inner_thr_eff >= 1.f + || (jcp.os * jcp.ic * jcp.oc) / max_threads < gemm_thrld); + } + } else if (is_bwd_d) { + const size_t outer_work_amount = jcp.ngroups * jcp.mb; + const float outer_thr_eff = (float)outer_work_amount + / rnd_up(outer_work_amount, max_threads); + const size_t inner_work + = div_up(jcp.is, simd_w) * div_up(jcp.ic, simd_w); + const float inner_thr_eff = (float)inner_work + / rnd_up(inner_work, max_threads); + jcp.outer_threading = (jcp.os / max_threads < 512 || jcp.ks < 64) + && (jcp.mb != 1 || jcp.ngroups > 2) + && (outer_thr_eff / inner_thr_eff >= 1.f + || (jcp.is * jcp.ic * jcp.oc) / max_threads < gemm_thrld); + } else if (is_bwd_w) + jcp.outer_threading = jcp.os / max_threads < 256 + && (jcp.mb != 1 || jcp.ngroups > 2); + + jcp.nthr = jcp.outer_threading ? max_threads : 1; + scratchpad.book(key_conv_gemm_col, + sizeof(float) * jcp.nthr * jcp.im2col_sz); + + if (is_bwd_w) { + jcp.need_wei_reduction = mkldnn_thr_syncable() + ? jcp.mb != 1 && jcp.nthr != 1 : false; + scratchpad.book(key_conv_wei_reduction, + sizeof(float) * jcp.nthr * jcp.ngroups * weights_d.size()); + } + } + + return status::success; +} + +void bwd_weights_balance(int ithr, int nthr, int ngroups, int mb, int &ithr_g, + int &nthr_g, int &ithr_mb, int &nthr_mb) { + nthr_g = nstl::min(ngroups, nthr); + nthr_mb = nstl::min(mb, nthr / nthr_g); + if (ithr / nthr_mb >= ngroups) { + ithr_g = ithr_mb = -1; + } else { + ithr_g = ithr / nthr_mb; + ithr_mb = ithr % nthr_mb; + } +} + +void bwd_weights_reduction_par(int ithr, int nthr, + const jit_gemm_conv_conf_t &jcp, const float *weights_reduce_ws, + float *weights) { + const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks; + + size_t weights_start{0}, weights_end{0}; + balance211(weights_g_size, nthr, ithr, weights_start, weights_end); + + for (int i = 0; i < nthr; ++i) { + const float *ws_i = weights_reduce_ws + i * weights_g_size; + for (size_t s = weights_start; s < weights_end; ++s) + weights[s] = (i == 0 ? 0 : weights[s]) + ws_i[s]; + } +} + +}; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp new file mode 100644 index 0000000000..e006789344 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp @@ -0,0 +1,66 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_GEMM_CONVOLUTION_UTILS_HPP +#define CPU_JIT_GEMM_CONVOLUTION_UTILS_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_engine.hpp" +#include "jit_primitive_conf.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace jit_gemm_convolution_utils { + +void im2col_3d(const jit_gemm_conv_conf_t &jcp, const float *im, float *col, + int od); +void im2col(const jit_gemm_conv_conf_t &jcp, const float *__restrict im, + float *__restrict col, int hs, int hb, int ws, int wb); +template +void im2col_u8(const jit_gemm_conv_conf_t &jcp, const T *__restrict im, + T* __restrict imtr, uint8_t *__restrict col, + int hs, int hb, int ws, int wb); + +void col2im_s32(const jit_gemm_conv_conf_t &jcp, const int32_t *__restrict col, + int32_t *__restrict im); +void col2im_3d(const jit_gemm_conv_conf_t &jcp, const float *col, float *im, + int od); +void col2im(const jit_gemm_conv_conf_t &jcp, const float *col, float *im); + +status_t init_conf(jit_gemm_conv_conf_t &jcp, + memory_tracking::registrar_t &scratchpad, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, int max_threads); + +void bwd_weights_balance(int ithr, int nthr, int ngroups, int mb, + int &ithr_g, int &nthr_g, int &ithr_mb, int &nthr_mb); +void bwd_weights_reduction_par(int ithr, int nthr, + const jit_gemm_conv_conf_t &jcp, const float *weights_reduce_ws, + float *weights); + +} + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp new file mode 100644 index 0000000000..2872122f0d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp @@ -0,0 +1,156 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" + +#include "gemm_inner_product.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::data_type; +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::primitive_kind; + +template +void gemm_inner_product_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int IC = pd()->IC_total_padded(); + + bool wei_tr = !memory_desc_matches_one_of_tag( + *pd()->weights_md(), hwio, dhwio, io); + + const auto &post_ops = pd()->attr()->post_ops_; + const bool do_relu = post_ops.len_ == 1; + + float alpha = 1.0, beta = 0.0; + extended_sgemm(wei_tr ? "T" : "N", "N", &OC, &MB, &IC, &alpha, weights, + wei_tr ? &IC : &OC, src, &IC, &beta, dst, &OC, bias); + + if (do_relu) { + float nslope = post_ops.entry_[0].eltwise.alpha; + parallel_nd(MB, OC, [&](int mb, int oc) { + size_t dst_off = mb * OC + oc; + if (dst[dst_off] < 0) + dst[dst_off] *= nslope; + }); + } +} + +template +void gemm_inner_product_bwd_data_t::execute_backward_data( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int IC = pd()->IC_total_padded(); + + bool wei_tr = memory_desc_matches_one_of_tag( + *pd()->weights_md(), hwio, dhwio, io); + + float alpha = 1.0, beta = 0.0; + extended_sgemm(wei_tr ? "T" : "N", "N", &IC, &MB, &OC, &alpha, weights, + wei_tr ? &OC : &IC, diff_dst, &OC, &beta, diff_src, &IC); +} + +template +void gemm_inner_product_bwd_weights_t::execute_backward_weights( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1)); + + diff_dst += diff_dst_d.offset0(); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int IC = pd()->IC_total_padded(); + + bool wei_tr = memory_desc_matches_one_of_tag( + *pd()->diff_weights_md(), hwio, dhwio, io); + + float alpha = 1.0, beta = 0.0; + if (wei_tr) + extended_sgemm("N", "T", &OC, &IC, &MB, &alpha, diff_dst, &OC, src, &IC, + &beta, diff_weights, &OC); + else + extended_sgemm("N", "T", &IC, &OC, &MB, &alpha, src, &IC, diff_dst, &OC, + &beta, diff_weights, &IC); + + if (diff_bias) { + diff_bias += diff_bias_d.offset0(); + constexpr int blksize = 8; + const int OC_blocks = OC / blksize; + const int rem_OC = OC % blksize; + parallel(0, [&](const int ithr, const int nthr) { + int oc_st{0}, oc_e{0}; + balance211(OC_blocks, nthr, ithr, oc_st, oc_e); + oc_st = oc_st * blksize; + oc_e = oc_e * blksize; + + PRAGMA_OMP_SIMD() + for (int oc = oc_st; oc < oc_e; ++oc) { + diff_bias[oc] = diff_dst[oc]; + } + + for (int mb = 1; mb < MB; ++mb) { + PRAGMA_OMP_SIMD() + for (int oc = oc_st; oc < oc_e; ++oc) { + diff_bias[oc] += diff_dst[mb * OC + oc]; + } + } + + if (rem_OC != 0 && ithr == nthr-1) { + for (int oc = OC_blocks * blksize; oc < OC; oc++) + diff_bias[oc] = diff_dst[oc]; + for (int mb = 1; mb < MB; ++mb) { + for (int oc = OC_blocks * blksize; oc < OC; oc++) { + diff_bias[oc] += diff_dst[mb * OC + oc]; + } + } + } + }); + } +} + +template struct gemm_inner_product_fwd_t; +template struct gemm_inner_product_bwd_data_t; +template struct gemm_inner_product_bwd_weights_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp new file mode 100644 index 0000000000..acf0a49b9a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp @@ -0,0 +1,157 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_GEMM_INNER_PRODUCT_HPP +#define CPU_GEMM_INNER_PRODUCT_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "gemm/gemm.hpp" + +#include "cpu_inner_product_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct gemm_inner_product_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_inner_product_fwd_pd_t { + using cpu_inner_product_fwd_pd_t::cpu_inner_product_fwd_pd_t; + + DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_inner_product_fwd_t); + + status_t init() { + using namespace utils; + + bool ok = true + && set_default_params() == status::success + && is_fwd() + && !has_zero_dim_memory() + && everyone_is(data_type, + src_md()->data_type, + weights_md()->data_type, + dst_md()->data_type, + with_bias() ? weights_md(1)->data_type : data_type) + && attr()->output_scales_.has_default_values() + && attr()->post_ops_.len_ <= 1 + && IMPLICATION(attr()->post_ops_.len_ == 1, + attr()->post_ops_.entry_[0].is_relu(true, false)) + && dense_gemm_consitency_check(src_md(), weights_md(), + dst_md()); + return ok ? status::success : status::unimplemented; + } + }; + + gemm_inner_product_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct gemm_inner_product_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_inner_product_bwd_data_pd_t { + using cpu_inner_product_bwd_data_pd_t::cpu_inner_product_bwd_data_pd_t; + + DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_inner_product_bwd_data_t); + + status_t init() { + bool ok = true + && set_default_params() == status::success + && desc()->prop_kind == prop_kind::backward_data + && !has_zero_dim_memory() + && utils::everyone_is(data_type, + diff_src_md()->data_type, + weights_md()->data_type, + diff_dst_md()->data_type) + && attr()->has_default_values() + && dense_gemm_consitency_check(diff_src_md(), weights_md(), + diff_dst_md()); + return ok ? status::success : status::unimplemented; + } + }; + + gemm_inner_product_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct gemm_inner_product_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_inner_product_bwd_weights_pd_t { + using cpu_inner_product_bwd_weights_pd_t::cpu_inner_product_bwd_weights_pd_t; + + DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_inner_product_bwd_weights_t); + + status_t init() { + bool ok = true + && set_default_params() == status::success + && desc()->prop_kind == prop_kind::backward_weights + && !has_zero_dim_memory() + && utils::everyone_is(data_type, + src_md()->data_type, + diff_weights_md()->data_type, + diff_dst_md()->data_type, + with_bias() ? diff_weights_md(1)->data_type : data_type) + && attr()->has_default_values() + && dense_gemm_consitency_check(src_md(), diff_weights_md(), + diff_dst_md()); + + return ok ? status::success : status::unimplemented; + } + }; + + gemm_inner_product_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp new file mode 100644 index 0000000000..fed7e4d693 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp @@ -0,0 +1,740 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "utils.hpp" +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" +#include "math_utils.hpp" + +#include "simple_q10n.hpp" + +#include "gemm/gemm.hpp" +#include "gemm_x8s8s32x_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::math; +using namespace mkldnn::impl::memory_tracking::names; + +template +void _gemm_x8s8s32x_convolution_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const { + auto src_base = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto wei_base = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bia_base = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst_base = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + auto scratchpad = this->scratchpad(ctx); + + const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_; + + assert(IMPLICATION( + jcp.id != 1, jcp.oh_block == jcp.oh && jcp.ow_block == jcp.ow)); + assert(IMPLICATION(jcp.ow_block != jcp.ow, jcp.oh_block == 1)); + + parallel(jcp.nthr, [&](const int ithr, const int nthr) { + execute_forward_thr(ithr, nthr, src_base, wei_base, bia_base, dst_base, + scratchpad); + }); +} + +template +_gemm_x8s8s32x_convolution_fwd_t::pp_ker_t::pp_ker_t( + const pd_t *pd) + : ker_(nullptr) + , jcp_(pd->jcp_) + , OC_(pd->jcp_.oc) + , OS_(pd->jcp_.os) + , bias_data_type_(data_type::undef) + , bias_data_type_size_(0) + , scale_idx_mult_(0) + , do_bias_(false) + , do_relu_(false) + , do_sum_(false) +{ + using namespace types; + + const auto dst_md = memory_desc_wrapper(pd->dst_md()); + dst_os_stride_ = dst_md.blk_off(0, 0, 0, 1); + + scale_idx_mult_ = (pd->attr()->output_scales_.mask_ == (1 << 1)); + + auto &post_ops = pd->attr()->post_ops_; + + int entry_idx = -1; + for (int idx = 0; idx < post_ops.len_; ++idx) { + const auto &e = post_ops.entry_[idx]; + if (e.is_relu(true, false)) { + entry_idx = idx; + break; + } + } + do_relu_ = entry_idx >= 0; + + do_signed_scaling_ = jcp_.signed_input; + + do_sum_ = post_ops.contain(primitive_kind::sum, 0); + do_bias_ = pd->with_bias(); + bias_data_type_ = pd->desc()->bias_desc.data_type; + if (do_bias_) { + assert(bias_data_type_ != data_type::undef); + bias_data_type_size_ = data_type_size(bias_data_type_); + } + const size_t vlen_start + = cpu_isa_traits::vlen / sizeof(float); + + for (size_t i = vlen_start; i > 0; i--) { + if (OC_ % i == 0) { + vlen_ = i; + break; + } + } + + if (!mayiuse(avx512_core)) + // use fallback code for older CPUs + return; + else + generate(); +} + +template +void _gemm_x8s8s32x_convolution_fwd_t::pp_ker_t::generate() +{ + using namespace Xbyak; + using namespace utils; + + // TODO: clean-up + Reg64 reg_param = abi_param1; + Reg64 reg_dst = rdx; + Reg64 reg_acc = rax; + Reg64 reg_bias = rbx; + Reg64 reg_scales = rsi; + + Reg64 reg_len = r8; + Reg64 reg_tmp = rcx; // intentional for shifting purposes + Reg64 reg_oc_offset = r9; + Reg64 reg_rem_mask_short = r10; + Reg64 reg_rem_mask_vlen = r11; + Opmask kreg_rem_mask_short = k1; + Opmask kreg_rem_mask_vlen = k3; + Opmask kreg_relu_cmp = k2; + + const size_t vlen = vlen_; + + Zmm vreg_zero = Zmm(0); + Zmm vreg_scale = Zmm(1); + Zmm vreg_nslope = Zmm(2); + Zmm vreg_sum_scale = Zmm(3); + Zmm vreg_signed_scale = Zmm(4); + + size_t def_unroll = 4; + size_t max_unroll = 12; + size_t zmm_step = 2; + if (do_sum_) { + max_unroll = 8; + zmm_step = 3; + } + + auto vreg_dst = [&](int idx) { + return Zmm(5 + idx * zmm_step + 0); + }; + auto vreg_bias = [&](int idx) { + return Zmm(5 + idx * zmm_step + 1); + }; + auto vreg_prev_dst = [&](int idx) { + return Zmm(5 + idx * zmm_step + 2); + }; + + preamble(); + +#define PARAM_OFF(x) offsetof(ker_args, x) + mov(reg_dst, ptr[reg_param + PARAM_OFF(dst)]); + mov(reg_acc, ptr[reg_param + PARAM_OFF(acc)]); + mov(reg_bias, ptr[reg_param + PARAM_OFF(bias)]); + mov(reg_scales, ptr[reg_param + PARAM_OFF(scales)]); + mov(reg_len, ptr[reg_param + PARAM_OFF(len)]); + mov(reg_oc_offset, ptr[reg_param + PARAM_OFF(oc_offset)]); + vbroadcastss(vreg_nslope, ptr[reg_param + PARAM_OFF(nslope)]); + vbroadcastss(vreg_sum_scale, ptr[reg_param + PARAM_OFF(sum_scale)]); + vbroadcastss(vreg_signed_scale, ptr[reg_param + PARAM_OFF(signed_scale)]); + if (scale_idx_mult_ == 0) + vbroadcastss(vreg_scale, dword[reg_scales]); + +#undef PARAM_OFF + + mov(reg_rem_mask_vlen, 1); + shl(reg_rem_mask_vlen, vlen); + sub(reg_rem_mask_vlen, 1); + kmovq(kreg_rem_mask_vlen, reg_rem_mask_vlen); + + if (do_relu_ || dst_type == data_type::u8) + vxorps(vreg_zero, vreg_zero, vreg_zero); + + // Load accumulated value, convert to float, apply sum (if any), + // bias (if any), scaling, and relu (if any); + // then convert to destination type and store + auto compute = [&](size_t offset, int idx, bool apply_mask) { + auto acc_addr = ptr[reg_acc + offset * sizeof(acc_data_t)]; + + if (scale_idx_mult_ > 0) { + assert(scale_idx_mult_ == 1); + auto scale_addr = ptr[reg_scales + offset * sizeof(float)]; + auto vreg_scale_ = vreg_scale; + if (apply_mask) + vreg_scale_ = vreg_scale_ | kreg_rem_mask_short; + else + vreg_scale_ = vreg_scale_ | kreg_rem_mask_vlen; + vmovups(vreg_scale_, scale_addr); + } + + auto vreg_dst_ = vreg_dst(idx); + if (apply_mask) + vreg_dst_ = vreg_dst_ | kreg_rem_mask_short; + else + vreg_dst_ = vreg_dst_ | kreg_rem_mask_vlen; + vcvtdq2ps(vreg_dst_, acc_addr); + + if (do_signed_scaling_) + vmulps(vreg_dst(idx), vreg_dst(idx), vreg_signed_scale); + + if (do_bias_) { + auto bias_addr = ptr[reg_bias + offset * bias_data_type_size_]; + auto vreg_bias_ = vreg_bias(idx); + if (apply_mask) + vreg_bias_ = vreg_bias_ | kreg_rem_mask_short; + else + vreg_bias_ = vreg_bias_ | kreg_rem_mask_vlen; + + switch (bias_data_type_) { + case data_type::s8: + vpmovsxbd(vreg_bias_, bias_addr); + break; + case data_type::u8: + vpmovzxbd(vreg_bias_, bias_addr); + break; + case data_type::s32: + case data_type::f32: + vmovups(vreg_bias_, bias_addr); + break; + default: assert(!"unimplemented"); + } + if (bias_data_type_ != data_type::f32) + vcvtdq2ps(vreg_bias(idx), vreg_bias(idx)); + vaddps(vreg_dst(idx), vreg_dst(idx), vreg_bias(idx)); + } + + vmulps(vreg_dst(idx), vreg_dst(idx), vreg_scale); + + auto dst_addr = ptr[reg_dst + offset * sizeof(dst_data_t)]; + + if (do_sum_) + { + auto vreg_prev_dst_ = vreg_prev_dst(idx); + if (apply_mask) + vreg_prev_dst_ = vreg_prev_dst_ | kreg_rem_mask_short; + else + vreg_prev_dst_ = vreg_prev_dst_ | kreg_rem_mask_vlen; + + switch (dst_type) { + case data_type::f32: + case data_type::s32: vmovups(vreg_prev_dst_, dst_addr); break; + case data_type::s8: vpmovsxbd(vreg_prev_dst_, dst_addr); break; + case data_type::u8: vpmovzxbd(vreg_prev_dst_, dst_addr); break; + default: assert(!"unsupported data type"); + } + if (dst_type != data_type::f32) + vcvtdq2ps(vreg_prev_dst(idx), vreg_prev_dst(idx)); + + vfmadd231ps(vreg_dst(idx), vreg_prev_dst(idx), vreg_sum_scale); + } + + if (do_relu_) { + vcmpps(kreg_relu_cmp, vreg_dst(idx), vreg_zero, _cmp_lt_os); + vmulps(vreg_dst(idx) | kreg_relu_cmp, vreg_dst(idx), vreg_nslope); + } + + if (dst_type != data_type::f32) { + vcvtps2dq(vreg_dst(idx), vreg_dst(idx)); + } + + if (dst_type == data_type::u8) + vpmaxsd(vreg_dst(idx), vreg_dst(idx), vreg_zero); + + switch (dst_type) { + case data_type::s8: + vpmovsdb(dst_addr, vreg_dst_); + break; + case data_type::u8: + vpmovusdb(dst_addr, vreg_dst_); + break; + case data_type::f32: + case data_type::s32: + vmovups(dst_addr, vreg_dst_); + break; + default: assert(!"unimplemented"); + } + }; + + // Advance all pointers by an immediate + auto advance_ptrs_imm = [&](size_t offset) { + add(reg_dst, offset * sizeof(dst_data_t)); + add(reg_acc, offset * sizeof(acc_data_t)); + if (scale_idx_mult_) { + assert(scale_idx_mult_ == 1); + add(reg_scales, offset * sizeof(float)); + } + if (do_bias_) + add(reg_bias, offset * bias_data_type_size_); + }; + + // Advance all pointers by a value stored in a register + auto advance_ptrs_reg = [&](Reg64 offset) { + lea(reg_dst, ptr[reg_dst + offset * sizeof(dst_data_t)]); + lea(reg_acc, ptr[reg_acc + offset * sizeof(acc_data_t)]); + if (scale_idx_mult_) { + assert(scale_idx_mult_ == 1); + lea(reg_scales, ptr[reg_scales + offset * sizeof(float)]); + } + if (do_bias_) + lea(reg_bias, ptr[reg_bias + offset * bias_data_type_size_]); + }; + + // Rewind pointers that point to data that is indexed by output channel + // (bias or per-oc scaling factors) + auto rewind_ptrs = [&]() { + if (do_bias_) + sub(reg_bias, OC_ * bias_data_type_size_); + if (scale_idx_mult_) { + assert(scale_idx_mult_ == 1); + sub(reg_scales, OC_ * sizeof(float)); + } + add(reg_dst, (dst_os_stride_ - OC_) * sizeof(dst_data_t)); + }; + + // <--------- OC ---------------> + // + // ^ ................+..............+-------------+....................... + // | . : not accessed |Prologue loop| . + // | . +--------------+-------------+ . + // . | | . + // O . | Main loop (unrolled) | . + // S . | | . + // . +--------------+-------------+ . + // | . | Epilogue loop|not accessed : . + // v ................+--------------+.............+....................... + + Label prologue_end; + cmp(reg_oc_offset, 0); + je(prologue_end, T_NEAR); + + // Prologue loop + { + mov(reg_tmp, OC_); + sub(reg_tmp, reg_oc_offset); + cmp(reg_tmp, reg_len); + cmovg(reg_tmp, reg_len); + sub(reg_len, reg_tmp); + + Label prologue_loop, prologue_loop_tail, prologue_loop_end; + cmp(reg_tmp, vlen); + jle(prologue_loop_tail, T_NEAR); + L(prologue_loop); { + compute(0, 0, false); + advance_ptrs_imm(vlen); + sub(reg_tmp, vlen); + cmp(reg_tmp, vlen); + jge(prologue_loop, T_NEAR); + } + + L(prologue_loop_tail); + mov(reg_rem_mask_short, 1); + // cl == reg_tmp because reg_tmp <= vlen here + shl(reg_rem_mask_short, cl); + sub(reg_rem_mask_short, 1); + jz(prologue_loop_end, T_NEAR); + + kmovq(kreg_rem_mask_short, reg_rem_mask_short); + compute(0, 0, true); + advance_ptrs_reg(reg_tmp); + + L(prologue_loop_end); + rewind_ptrs(); + } + L(prologue_end); + + // Main loop + Label main_loop_end; + { + cmp(reg_len, OC_); + jle(main_loop_end, T_NEAR); + + Label main_loop; + L(main_loop); { + size_t OC_loop, OC_tail; + if (OC_ < max_unroll * vlen) { + // Fully unroll small loops + OC_loop = 0; + OC_tail = OC_; + } + else { + OC_loop = vlen * def_unroll; + OC_tail = OC_ % OC_loop; + } + + assert(!!OC_loop || !!OC_tail); + + if (OC_tail % vlen) { + int vlen_tail = OC_tail % vlen; + unsigned tail_mask = (1 << vlen_tail) - 1; + mov(reg_tmp, tail_mask); + kmovq(kreg_rem_mask_short, reg_tmp); + } + + if (OC_loop) { + mov(reg_tmp, rnd_dn(OC_, OC_loop)); + Label oc_loop; + L(oc_loop); { + for (size_t offset = 0; offset < OC_loop; offset += vlen) + compute(offset, offset / vlen, false); + advance_ptrs_imm(OC_loop); + sub(reg_tmp, OC_loop); + jnz(oc_loop); + } + } + + if (OC_tail) { + for (size_t offset = 0; offset < OC_tail; offset += vlen) { + bool use_mask = (offset + vlen) > OC_tail; + compute(offset, offset / vlen, use_mask); + } + advance_ptrs_imm(OC_tail); + } + + rewind_ptrs(); + sub(reg_len, OC_); + cmp(reg_len, OC_); + jge(main_loop, T_NEAR); + } + } + L(main_loop_end); + + // Epilogue loop + Label epilogue_end; + { + cmp(reg_len, 0); + je(epilogue_end, T_NEAR); + + Label epilogue_loop, epilogue_loop_tail; + cmp(reg_len, vlen); + jle(epilogue_loop_tail, T_NEAR); + L(epilogue_loop); { + compute(0, 0, false); + sub(reg_len, vlen); + advance_ptrs_imm(vlen); + cmp(reg_len, vlen); + jge(epilogue_loop, T_NEAR); + } + + L(epilogue_loop_tail); + mov(reg_tmp, reg_len); // reg_tmp is rcx, and we need cl for the shift + mov(reg_rem_mask_short, 1); + shl(reg_rem_mask_short, cl); // reg_tmp == rcx and reg_tail < vlen + sub(reg_rem_mask_short, 1); + jz(epilogue_end, T_NEAR); + kmovq(kreg_rem_mask_short, reg_rem_mask_short); + compute(0, 0, true); + } + + L(epilogue_end); + + postamble(); + + ker_ = getCode(); +} + +template +void _gemm_x8s8s32x_convolution_fwd_t::pp_ker_t::operator () + (dst_data_t *dst, const acc_data_t *acc, const char *bias, + const float *scales, float nslope, float sum_scale, float signed_scale, + int g, size_t start, size_t end) +{ + using math::get_bias; + + if (end <= start) + return; + + if (ker_) { + // JIT + ker_args args; + size_t oc_offset = start % OC_; + size_t os_offset = start / OC_; + args.acc = acc + start; + args.dst = dst + os_offset * dst_os_stride_ + oc_offset; + args.bias = bias + (g * jcp_.oc + oc_offset) * bias_data_type_size_; + args.scales = scales + scale_idx_mult_ * (g * jcp_.oc + oc_offset); + args.nslope = nslope; + args.sum_scale = sum_scale; + args.signed_scale = signed_scale; + args.len = end - start; + args.oc_offset = oc_offset; + ker_(&args); + } + else { + // Fallback + const size_t first_oc = start % OC_; + const size_t last_oc = (end - 1) % OC_; + const size_t first_os = start / OC_; + const size_t last_os = (end - 1) / OC_; + for (size_t os = first_os; os <= last_os; os++) { + const size_t start_oc = (os == first_os) ? first_oc : 0; + const size_t end_oc = (os == last_os) ? last_oc : OC_ - 1; + for (size_t oc = start_oc; oc <= end_oc; oc++) { + const size_t acc_off = os * jcp_.oc + oc; + const size_t dst_off = os * dst_os_stride_ + oc; + + float d = (float)(acc[acc_off]); + if (jcp_.signed_input) + d *= signed_scale; + + if (do_bias_) + d += get_bias(bias, g * jcp_.oc + oc, + bias_data_type_); + + d *= scales[(g * jcp_.oc + oc) * scale_idx_mult_]; + if (do_sum_) + d += sum_scale * dst[dst_off]; + if (do_relu_ && d < 0) + d *= nslope; + dst[dst_off] = qz_a1b0()(d); + } + } + } +}; + +template +void _gemm_x8s8s32x_convolution_fwd_t:: +execute_forward_thr(const int ithr, const int nthr, const src_data_t *src_base, + const wei_data_t *wei_base, const char *bia_base, dst_data_t *dst_base, + const memory_tracking::grantor_t &scratchpad) const { + const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_; + + const auto src_md = memory_desc_wrapper(pd()->src_md()); + const size_t src_mb_stride = src_md.blk_off(1); + const size_t src_g_stride = src_md.blk_off(0, 1) * jcp.ic; + + const auto wei_md = memory_desc_wrapper(pd()->weights_md(0)); + const size_t wei_g_stride = pd()->with_groups() ? wei_md.blk_off(1) : 0; + + const auto dst_md = memory_desc_wrapper(pd()->dst_md()); + const size_t dst_mb_stride = dst_md.blk_off(1); + const size_t dst_g_stride = dst_md.blk_off(0, 1) * jcp.oc; + + const float *scales = pd()->attr()->output_scales_.scales_; + + const auto &post_ops = pd()->attr()->post_ops_; + const bool do_sum = post_ops.contain(primitive_kind::sum, 0); + const float sum_scale = do_sum ? post_ops.entry_[0].sum.scale : 0; + + float nslope = 0; + for (int idx = 0; idx < post_ops.len_; ++idx) { + const auto &e = post_ops.entry_[idx]; + if (e.is_relu(true, false)) { + nslope = e.eltwise.alpha; + break; + } + } + + auto col = scratchpad.get(key_conv_gemm_col) + + (ptrdiff_t)ithr * jcp.im2col_sz; + src_data_t *__restrict imtr = scratchpad.get(key_conv_gemm_imtr) + + (ptrdiff_t)ithr * jcp.is * jcp.ic; + auto acc = scratchpad.get(key_conv_int_dat_in_acc_dt) + + (ptrdiff_t)ithr * jcp.oh_block * jcp.ow_block * jcp.oc; + + const ptrdiff_t offset = (ptrdiff_t)jcp.ngroups * jcp.ks * jcp.ic * jcp.oc; + const int32_t *_wei_comp = (const int32_t *)(wei_base + offset); + + int g{ 0 }, n{ 0 }, ohb{ 0 }, owb{ 0 }; + size_t start = 0, end = 0; + + const int nb_oh = div_up(jcp.oh, jcp.oh_block); + const int nb_ow = div_up(jcp.ow, jcp.ow_block); + const size_t work_amount = jcp.ngroups * jcp.mb * nb_oh * nb_ow; + balance211(work_amount, nthr, ithr, start, end); + nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, ohb, + nb_oh, owb, nb_ow); + + for (size_t iwork = start; iwork < end; ++iwork) { + int oh = ohb * jcp.oh_block; + int ow = owb * jcp.ow_block; + const src_data_t *__restrict src = src_base + n * src_mb_stride + + g * src_g_stride; + const wei_data_t *__restrict wei = wei_base + g * wei_g_stride; + dst_data_t *__restrict dst = + dst_base + n * dst_mb_stride + g * dst_g_stride; + const int32_t *wei_comp = _wei_comp + g * jcp.oc; + const int h_step = nstl::min(jcp.oh_block, jcp.oh - oh); + const int w_step = nstl::min(jcp.ow_block, jcp.ow - ow); + + if (jcp.im2col_sz) + jit_gemm_convolution_utils::im2col_u8( + jcp, src, imtr, col, oh, h_step, ow, w_step); + + const int M = jcp.oc; + const int K = jcp.ks * jcp.ic; + const int N = h_step * w_step; + const int LDA = M * jcp.ngroups; + const int LDB = jcp.im2col_sz ? N : K; + const char *BT = jcp.im2col_sz ? "T" : "N"; + const int8_t off_a = 0, off_b = 0; + const int32_t off_c = 0; + const float onef = 1.0, zerof = 0.0; + gemm_s8x8s32("N", BT, jcp.signed_input ? "C" : "F", + &M, &N, &K, &onef, wei, &LDA, &off_a, + jcp.im2col_sz ? col : (uint8_t *)src, &LDB, &off_b, + &zerof, acc, &M, jcp.signed_input ? wei_comp : &off_c); + + auto wei_adj_scale = + (wei_md.extra().flags | memory_extra_flags::scale_adjust) + ? wei_md.extra().scale_adjust : 1.f; + + parallel(0, [&](int ithr, int nthr) { + size_t start, end; + balance211((size_t)N * jcp.oc, nthr, ithr, start, end); + (*pp_ker_)(dst + (oh * jcp.ow + ow) * pp_ker_->dst_os_stride_, + acc, bia_base, scales, nslope, sum_scale, + 1.f / wei_adj_scale, g, start, end); + }); + + nd_iterator_step(n, jcp.mb, g, jcp.ngroups, ohb, nb_oh, + owb, nb_ow); + } +} + +template +void _gemm_u8s8s32x_convolution_bwd_data_t:: +execute_backward_data(const exec_ctx_t &ctx) const { + auto diff_dst_base = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto wei_base = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bia_base = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto diff_src_base = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC); + + auto scratchpad = this->scratchpad(ctx); + + const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_; + + parallel(jcp.nthr, [&](const int ithr, const int nthr) { + execute_backward_data_thr(ithr, nthr, diff_dst_base, wei_base, + bia_base, diff_src_base, scratchpad); + }); +} + +template +void _gemm_u8s8s32x_convolution_bwd_data_t:: +execute_backward_data_thr(const int ithr, const int nthr, + const diff_dst_data_t *diff_dst_base, const wei_data_t *wei_base, + const char *bia_base, diff_src_data_t *diff_src_base, + const memory_tracking::grantor_t &scratchpad) const +{ + const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_; + + const auto diff_dst_md = memory_desc_wrapper(pd()->diff_dst_md()); + const size_t diff_dst_mb_stride = diff_dst_md.blk_off(1); + const size_t diff_dst_g_stride = diff_dst_md.blk_off(0, 1) * jcp.oc; + + const auto wei_md = memory_desc_wrapper(pd()->weights_md(0)); + const size_t wei_g_stride = pd()->with_groups() ? wei_md.blk_off(1) : 0; + + const auto diff_src_md = memory_desc_wrapper(pd()->diff_src_md()); + const size_t diff_src_mb_stride = diff_src_md.blk_off(1); + const size_t diff_src_g_stride = diff_src_md.blk_off(0, 1) * jcp.ic; + const size_t diff_src_os_stride = diff_src_md.blk_off(0, 0, 0, 1); + + /* scale_idx_mult = 1 for per_oc scales and 0, otherwise */ + const int scale_idx_mult = pd()->attr()->output_scales_.mask_ == (1 << 1); + const float *scales = pd()->attr()->output_scales_.scales_; + const size_t work_amount = jcp.ngroups * jcp.mb; + + auto col = scratchpad.get(key_conv_gemm_col) + + (ptrdiff_t)ithr * jcp.im2col_sz; + auto acc = scratchpad.get(key_conv_int_dat_in_acc_dt) + + (ptrdiff_t)ithr * jcp.is * jcp.ic; + + int n{0}, g{0}; + size_t start = 0, end = 0; + + balance211(work_amount, nthr, ithr, start, end); + nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups); + + for (size_t iwork = start; iwork < end; ++iwork) { + const diff_dst_data_t *diff_dst = diff_dst_base + + n * diff_dst_mb_stride + g * diff_dst_g_stride; + const wei_data_t *wei = wei_base + g * wei_g_stride; + diff_src_data_t *diff_src = diff_src_base + n * diff_src_mb_stride + + g * diff_src_g_stride; + + const int M = jcp.ks * jcp.ic; + const int N = jcp.os; + const int K = jcp.oc; + const int8_t off_a = 0, off_b = 0; + const int32_t off_c = 0; + const float onef = 1.0, zerof = 0.0; + const int LD = K * jcp.ngroups; + + gemm_s8x8s32("T", "N", "F", &M, &N, &K, &onef, + wei, &LD, &off_a, diff_dst, &LD, &off_b, + &zerof, jcp.im2col_sz ? col : acc, &M, &off_c); + + if (jcp.im2col_sz) + jit_gemm_convolution_utils::col2im_s32(jcp, col, acc); + + parallel_nd(jcp.is, jcp.ic, [&](int is, int ic) { + float d = (float)acc[is * jcp.ic + ic]; + if (jcp.with_bias) + d += get_bias(bia_base, g * jcp.ic + ic, + pd()->desc()->bias_desc.data_type); + d *= scales[(g * jcp.ic + ic) * scale_idx_mult]; + const size_t diff_src_off = is * diff_src_os_stride + ic; + diff_src[diff_src_off] = + qz_a1b0()(d); + }); + nd_iterator_step(n, jcp.mb, g, jcp.ngroups); + } +} + +using namespace data_type; + +template struct _gemm_x8s8s32x_convolution_fwd_t; +template struct _gemm_x8s8s32x_convolution_fwd_t; +template struct _gemm_x8s8s32x_convolution_fwd_t; +template struct _gemm_x8s8s32x_convolution_fwd_t; + +template struct _gemm_x8s8s32x_convolution_fwd_t; +template struct _gemm_x8s8s32x_convolution_fwd_t; +template struct _gemm_x8s8s32x_convolution_fwd_t; +template struct _gemm_x8s8s32x_convolution_fwd_t; + +template struct _gemm_u8s8s32x_convolution_bwd_data_t; +template struct _gemm_u8s8s32x_convolution_bwd_data_t; +template struct _gemm_u8s8s32x_convolution_bwd_data_t; +template struct _gemm_u8s8s32x_convolution_bwd_data_t; +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp new file mode 100644 index 0000000000..9e77b890d5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp @@ -0,0 +1,266 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef GEMM_X8S8S32X_CONVOLUTION_HPP +#define GEMM_X8S8S32X_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_primitive_conf.hpp" +#include "jit_generator.hpp" +#include "gemm_convolution_utils.hpp" + +#include "gemm/gemm.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct _gemm_x8s8s32x_convolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T(IGEMM_S8U8S32_IMPL_STR, + _gemm_x8s8s32x_convolution_fwd_t); + + status_t init() { + using namespace data_type; + + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, s8, data_type::undef, dst_type, + s32) + && IMPLICATION(with_bias(), utils::one_of( + desc()->bias_desc.data_type, f32, s32, s8, u8)) + && !has_zero_dim_memory() + && set_default_formats_common( + dat_tag(), format_tag::any, dat_tag()) + && post_ops_ok() + && memory_desc_matches_tag(*src_md(), dat_tag()) + && memory_desc_matches_tag(*dst_md(), dat_tag()) + && set_or_check_wei_format(); + if (!ok) return status::unimplemented; + + auto scratchpad = scratchpad_registry().registrar(); + return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad, + *desc(), src_md(), weights_md(0), dst_md(), + mkldnn_get_max_threads()); + } + + jit_gemm_conv_conf_t jcp_; + + protected: + format_tag_t dat_tag() const { return format_tag::nhwc; } + + bool set_or_check_wei_format() { + using namespace format_tag; + + const bool is_src_s8 = src_md_.data_type == data_type::s8; + + memory_desc_t want_wei_md = weights_md_; + memory_desc_init_by_tag(want_wei_md, with_groups() ? hwigo : hwio); + + if (is_src_s8) { + want_wei_md.extra.flags = 0 + | memory_extra_flags::compensation_conv_s8s8 + | memory_extra_flags::scale_adjust; + want_wei_md.extra.compensation_mask = (1 << 0) + + (with_groups() ? (1 << 1) : 0); + want_wei_md.extra.scale_adjust = + mayiuse(avx512_core_vnni) ? 1.f : 0.5f; + } + + if (weights_md_.format_kind == format_kind::any) { + weights_md_ = want_wei_md; + return true; + } + + return weights_md_ == want_wei_md; + } + + bool post_ops_ok() const { + using namespace mkldnn::impl::primitive_kind; + auto const &po = attr()->post_ops_; + auto is_relu = [&](int idx) { + return po.entry_[idx].is_relu(true, false); }; + + switch (po.len_) { + case 0: return true; + case 1: return is_relu(0) || po.contain(sum, 0); + case 2: return po.contain(sum, 0) && is_relu(1); + default: return false; + } + return false; + } + }; + + _gemm_x8s8s32x_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd, true), pp_ker_(nullptr) + { pp_ker_ = new pp_ker_t(pd()); } + ~_gemm_x8s8s32x_convolution_fwd_t() { delete pp_ker_; } + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + // XXX: this is throwaway code that will become unnecessary when we have a + // sufficiently advanced igemm jit generator that supports quantization, + // relu, and whatnot + class pp_ker_t : jit_generator { + public: + DECLARE_CPU_JIT_AUX_FUNCTIONS( + _gemm_x8s8s32x_convolution_fwd_t::pp_kernel); + pp_ker_t(const pd_t *pd); + + void operator()(dst_data_t *dst, const acc_data_t *acc, + const char *bias, const float *scales, + float nslope, float sum_scale, float signed_scale, + int g, size_t start, size_t end); + + size_t dst_os_stride_; + + private: + void generate(); + + struct ker_args { + dst_data_t *dst; + const acc_data_t *acc; + const char *bias; + const float *scales; + float nslope; + float sum_scale; + float signed_scale; + size_t len; + size_t oc_offset; + }; + void(*ker_)(const ker_args *args); + + const jit_gemm_conv_conf_t &jcp_; + size_t OC_; + size_t OS_; + data_type_t bias_data_type_; + size_t bias_data_type_size_; + size_t scale_idx_mult_; + bool do_bias_; + bool do_relu_; + bool do_sum_; + bool do_signed_scaling_; + size_t vlen_; + }; + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + void execute_forward(const exec_ctx_t &ctx) const; + void execute_forward_thr(const int ithr, const int nthr, + const src_data_t *src_base, const wei_data_t *wei_base, + const char *bia_base, dst_data_t *dst_base, + const memory_tracking::grantor_t &scratchpad) const; + + int nthr_; + pp_ker_t *pp_ker_; + +}; + +template +struct _gemm_u8s8s32x_convolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_data_pd_t{ + pd_t(engine_t *engine, + const convolution_desc_t *adesc, const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T(IGEMM_S8U8S32_IMPL_STR, + _gemm_u8s8s32x_convolution_bwd_data_t); + + status_t init() { + using namespace data_type; + + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(dst_type, s8, data_type::undef, u8, s32) + && IMPLICATION(with_bias(), utils::one_of( + desc()->bias_desc.data_type, f32, s32, s8, u8)) + && !has_zero_dim_memory() + && set_default_formats_common(dat_tag(), wei_tag(), dat_tag()) + && attr()->post_ops_.has_default_values() + && memory_desc_matches_tag(*diff_src_md(), dat_tag()) + && memory_desc_matches_tag(*diff_dst_md(), dat_tag()) + && memory_desc_matches_tag(*weights_md(), wei_tag()); + if (!ok) return status::unimplemented; + + auto scratchpad = scratchpad_registry().registrar(); + return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad, + *desc(), diff_src_md(), weights_md(), diff_dst_md(), + mkldnn_get_max_threads()); + } + + virtual bool support_bias() const override { return true; } + + jit_gemm_conv_conf_t jcp_; + + protected: + format_tag_t dat_tag() const { return format_tag::nhwc; } + + format_tag_t wei_tag() const { + return with_groups() ? format_tag::hwigo : format_tag::hwio; + } + }; + + _gemm_u8s8s32x_convolution_bwd_data_t(const pd_t *apd) + : cpu_primitive_t(apd, true) {} + + typedef typename prec_traits::type diff_dst_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type diff_src_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + void execute_backward_data_thr(const int ithr, const int nthr, + const diff_dst_data_t *diff_dst_base, const wei_data_t *wei_base, + const char *bia_base, diff_src_data_t *diff_src_base, + const memory_tracking::grantor_t &scratchpad) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp new file mode 100644 index 0000000000..1e435a233a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp @@ -0,0 +1,453 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" +#include "simple_q10n.hpp" + +#include "gemm/gemm.hpp" +#include "gemm_x8s8s32x_inner_product.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace math; +using namespace format_tag; +using namespace memory_tracking::names; + +template +gemm_x8s8s32x_inner_product_fwd_t::pp_kernel_t::pp_kernel_t( + const pd_t *pd, bool dst_is_acc) + : ker_(nullptr), OC_(pd->OC()) + , bias_data_type_(data_type::undef), bias_data_type_size_(0) + , scale_idx_mult_(0), do_bias_(false), do_relu_(false) +{ + using namespace types; + + scale_idx_mult_ = (pd->attr()->output_scales_.mask_ == (1 << 1)); + + auto &post_ops = pd->attr()->post_ops_; + do_relu_ = post_ops.len_ == 1; + do_bias_ = pd->with_bias(); + bias_data_type_ = pd->desc()->bias_desc.data_type; + if (do_bias_) { + assert(bias_data_type_ != data_type::undef); + bias_data_type_size_ = data_type_size(bias_data_type_); + } + + if (!mayiuse(avx512_core)) + // use fallback code for older CPUs since they do not have optimized + // x8s8s32 GEMM anyways. The configuration variables above are used by + // the fallback code. + return; + else + generate(); +} + +template +void gemm_x8s8s32x_inner_product_fwd_t::pp_kernel_t::generate() +{ + using namespace Xbyak; + using namespace utils; + + // TODO: clean-up + Reg64 reg_param = abi_param1; + Reg64 reg_dst = rdx; + Reg64 reg_acc = rax; + Reg64 reg_bias = rbx; + Reg64 reg_scales = rsi; + + Reg64 reg_len = r8; + Reg64 reg_tmp = rcx; // intentional for shifting purposes + Reg64 reg_oc_offset = r9; + Reg64 reg_rem_mask = r10; + Opmask kreg_rem_mask = k1; + Opmask kreg_relu_cmp = k2; + + const size_t vlen = cpu_isa_traits::vlen / sizeof(float); + + Zmm vreg_zero = Zmm(0); + Zmm vreg_scale = Zmm(1); + Zmm vreg_nslope = Zmm(2); + + auto vreg_dst = [&](int idx) { return Zmm(3 + idx * 2 + 0); }; + auto vreg_bias = [&](int idx) { return Zmm(3 + idx * 2 + 1); }; + + preamble(); + +#define PARAM_OFF(x) offsetof(ker_args, x) + mov(reg_dst, ptr[reg_param + PARAM_OFF(dst)]); + mov(reg_acc, ptr[reg_param + PARAM_OFF(acc)]); + mov(reg_bias, ptr[reg_param + PARAM_OFF(bias)]); + mov(reg_scales, ptr[reg_param + PARAM_OFF(scales)]); + mov(reg_len, ptr[reg_param + PARAM_OFF(len)]); + mov(reg_oc_offset, ptr[reg_param + PARAM_OFF(oc_offset)]); + vbroadcastss(vreg_nslope, ptr[reg_param + PARAM_OFF(nslope)]); + if (scale_idx_mult_ == 0) + vbroadcastss(vreg_scale, dword[reg_scales]); +#undef PARAM_OFF + + if (do_relu_ || dst_type == data_type::u8) + vxorps(vreg_zero, vreg_zero, vreg_zero); + + // Load accumulated value, convert to float, apply bias (if any), scaling, + // and relu (if any); then convert to destination type and store + auto compute = [&](size_t offset, int idx, bool apply_mask) { + auto acc_addr = ptr[reg_acc + offset * sizeof(acc_data_t)]; + + if (scale_idx_mult_ > 0) { + assert(scale_idx_mult_ == 1); + auto scale_addr = ptr[reg_scales + offset * sizeof(float)]; + auto vreg_scale_ = vreg_scale; + if (apply_mask) + vreg_scale_ = vreg_scale_ | kreg_rem_mask; + vmovups(vreg_scale, scale_addr); + } + + auto vreg_dst_ = vreg_dst(idx); + if (apply_mask) + vreg_dst_ = vreg_dst_ | kreg_rem_mask; + vcvtdq2ps(vreg_dst_, acc_addr); + + if (do_bias_) { + auto bias_addr = ptr[reg_bias + offset * bias_data_type_size_]; + auto vreg_bias_ = vreg_bias(idx); + if (apply_mask) + vreg_bias_ = vreg_bias_ | kreg_rem_mask; + + switch (bias_data_type_) { + case data_type::s8: + vpmovsxbd(vreg_bias_, bias_addr); + break; + case data_type::u8: + vpmovzxbd(vreg_bias_, bias_addr); + break; + case data_type::s32: + case data_type::f32: + vmovups(vreg_bias_, bias_addr); + break; + default: assert(!"unimplemented"); + } + if (bias_data_type_ != data_type::f32) + vcvtdq2ps(vreg_bias(idx), vreg_bias(idx)); + vaddps(vreg_dst(idx), vreg_dst(idx), vreg_bias(idx)); + } + + vmulps(vreg_dst(idx), vreg_dst(idx), vreg_scale); + if (do_relu_) { + vcmpps(kreg_relu_cmp, vreg_dst(idx), vreg_zero, _cmp_lt_os); + vmulps(vreg_dst(idx) | kreg_relu_cmp, vreg_dst(idx), vreg_nslope); + } + + if (dst_type == data_type::u8) + vmaxps(vreg_dst(idx), vreg_dst(idx), vreg_zero); + + if (dst_type != data_type::f32) { + vcvtps2dq(vreg_dst(idx), vreg_dst(idx)); + } + + auto dst_addr = ptr[reg_dst + offset * sizeof(dst_data_t)]; + switch (dst_type) { + case data_type::s8: + vpmovsdb(dst_addr, vreg_dst_); + break; + case data_type::u8: + vpmovusdb(dst_addr, vreg_dst_); + break; + case data_type::f32: + case data_type::s32: + vmovups(dst_addr, vreg_dst_); + break; + default: assert(!"unimplemented"); + } + }; + + // Advance all pointers by an immediate + auto advance_ptrs_imm = [&](size_t offset) { + add(reg_dst, offset * sizeof(dst_data_t)); + add(reg_acc, offset * sizeof(acc_data_t)); + if (scale_idx_mult_) { + assert(scale_idx_mult_ == 1); + add(reg_scales, offset * sizeof(float)); + } + if (do_bias_) + add(reg_bias, offset * bias_data_type_size_); + }; + + // Advance all pointers by a value stored in a register + auto advance_ptrs_reg = [&](Reg64 offset) { + lea(reg_dst, ptr[reg_dst + offset * sizeof(dst_data_t)]); + lea(reg_acc, ptr[reg_acc + offset * sizeof(acc_data_t)]); + if (scale_idx_mult_) { + assert(scale_idx_mult_ == 1); + lea(reg_scales, ptr[reg_scales + offset * sizeof(float)]); + } + if (do_bias_) + lea(reg_bias, ptr[reg_bias + offset * bias_data_type_size_]); + }; + + // Rewind pointers that point to data that is indixed by output channel + // (bias or per-oc scaling factors) + auto rewind_ptrs = [&]() { + if (do_bias_) + sub(reg_bias, OC_ * bias_data_type_size_); + if (scale_idx_mult_) { + assert(scale_idx_mult_ == 1); + sub(reg_scales, OC_ * sizeof(float)); + } + }; + + // <-------------------- OC -------------------------------> + // + // ^ +....................+----------------------------------+ + // | : not accessed | Prologue loop | + // | +--------------------+----------------------------------+ + // | | + // M | Main loop (unrolled) | + // B | | + // +--------------------------------+----------------------+ + // | | Epilogue loop | not accessed : + // v +--------------------------------+......................+ + + Label prologue_end; + cmp(reg_oc_offset, 0); + je(prologue_end, T_NEAR); + + // Prologue loop + { + mov(reg_tmp, OC_); + sub(reg_tmp, reg_oc_offset); + cmp(reg_tmp, reg_len); + cmovg(reg_tmp, reg_len); + sub(reg_len, reg_tmp); + + Label prologue_loop, prologue_loop_tail, prologue_loop_end; + cmp(reg_tmp, vlen); + jle(prologue_loop_tail, T_NEAR); // Skips for reg_tmp == 16 too (?) + L(prologue_loop); { + compute(0, 0, false); + advance_ptrs_imm(vlen); + sub(reg_tmp, vlen); + cmp(reg_tmp, vlen); + jge(prologue_loop, T_NEAR); + } + + L(prologue_loop_tail); + mov(reg_rem_mask, 1); + shl(reg_rem_mask, cl); // cl == reg_tmp because reg_tmp <= vlen here + sub(reg_rem_mask, 1); + jz(prologue_loop_end, T_NEAR); + + kmovq(kreg_rem_mask, reg_rem_mask); + compute(0, 0, true); + advance_ptrs_reg(reg_tmp); + + L(prologue_loop_end); + rewind_ptrs(); + } + L(prologue_end); + + // Main loop + Label main_loop_end; + { + cmp(reg_len, OC_); + jle(main_loop_end, T_NEAR); + + Label main_loop; + L(main_loop); { + size_t def_unroll = 4; + size_t max_unroll = 13; + + size_t OC_loop, OC_tail; + if (OC_ < max_unroll * vlen) { + // Fully unroll small loops + OC_loop = 0; + OC_tail = OC_; + } else { + OC_loop = vlen * def_unroll; + OC_tail = OC_ % OC_loop; + } + + assert(!!OC_loop || !!OC_tail); + + if (OC_tail % vlen) { + int vlen_tail = OC_tail % vlen; + unsigned tail_mask = (1 << vlen_tail) - 1; + mov(reg_tmp, tail_mask); + kmovq(kreg_rem_mask, reg_tmp); + } + + if (OC_loop) { + mov(reg_tmp, rnd_dn(OC_, OC_loop)); + Label oc_loop; + L(oc_loop); { + for (size_t offset = 0; offset < OC_loop; offset += vlen) + compute(offset, offset / vlen, false); + advance_ptrs_imm(OC_loop); + sub(reg_tmp, OC_loop); + jnz(oc_loop); + } + } + + if (OC_tail) { + for (size_t offset = 0; offset < OC_tail; offset += vlen) { + bool use_mask = (offset + vlen) > OC_tail; + compute(offset, offset / vlen, use_mask); + } + advance_ptrs_imm(OC_tail); + } + + rewind_ptrs(); + sub(reg_len, OC_); + cmp(reg_len, OC_); + jge(main_loop, T_NEAR); + } + } + L(main_loop_end); + + // Epilogue loop + Label epilogue_end; + { + cmp(reg_len, 0); + je(epilogue_end, T_NEAR); + + Label epilogue_loop, epilogue_loop_tail; + cmp(reg_len, vlen); + jle(epilogue_loop_tail, T_NEAR); // Skips for reg_len == 16 (?) + L(epilogue_loop); { + compute(0, 0, false); + sub(reg_len, vlen); + advance_ptrs_imm(vlen); + cmp(reg_len, vlen); + jge(epilogue_loop, T_NEAR); + } + + L(epilogue_loop_tail); + mov(reg_tmp, reg_len); // reg_tmp is rcx, and we need cl for the shift + mov(reg_rem_mask, 1); + shl(reg_rem_mask, cl); // reg_tmp == rcx and reg_tail < vlen == 16 + sub(reg_rem_mask, 1); + jz(epilogue_end, T_NEAR); + kmovq(kreg_rem_mask, reg_rem_mask); + compute(0, 0, true); + } + + L(epilogue_end); + + postamble(); + + ker_ = getCode(); +} + +template +void gemm_x8s8s32x_inner_product_fwd_t::pp_kernel_t::operator ()( + dst_data_t *dst, const acc_data_t *acc, + const char *bias, const float *scales, float nslope, + size_t start, size_t end) +{ + using math::get_bias; + + if (end <= start) + return; + + if (ker_) { + // JIT + ker_args args; + size_t oc_offset = start % OC_; + args.dst = dst + start; + args.acc = acc + start; + args.bias = bias + oc_offset * bias_data_type_size_; + args.scales = scales + scale_idx_mult_ * oc_offset; + args.nslope = nslope; + args.len = end - start; + args.oc_offset = oc_offset; + ker_(&args); + } else { + // Fallback + size_t oc = start % OC_; + for (size_t i = start; i < end; i++) { + float d = (float)acc[i]; + float b = get_bias(bias, oc, bias_data_type_); + d = d + b; + d *= scales[oc * scale_idx_mult_]; + if (do_relu_ && d < 0) + d *= nslope; + dst[i] = qz_a1b0()(d); + oc = (oc == OC_ - 1) ? 0 : oc + 1; + } + } +}; + +template +void gemm_x8s8s32x_inner_product_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + + bool wei_tr = memory_desc_matches_one_of_tag( + *pd()->weights_md(), oiw, oihw, oidhw, oi); + + const int M = OC; + const int N = MB; + const int K = pd()->IC_total_padded(); + const int8_t off_a = 0, off_b = 0; + const int32_t off_c = 0; + + const float *scales = pd()->attr()->output_scales_.scales_; + + const auto &post_ops = pd()->attr()->post_ops_; + const bool do_relu = post_ops.len_ == 1; + const float nslope = do_relu ? post_ops.entry_[0].eltwise.alpha : 0.f; + + acc_data_t *acc = pd()->dst_is_acc_ + ? (acc_data_t *)dst + : scratchpad(ctx).template get(key_iprod_int_dat_in_acc_dt); + + const float onef = 1.0, zerof = 0.0; + gemm_s8x8s32(wei_tr ? "T" : "N", "N", "F", &M, &N, &K, &onef, weights, + wei_tr ? &K : &M, &off_a, src, &K, &off_b, &zerof, acc, &M, &off_c); + + if (!pd()->attr()->has_default_values() || !pd()->dst_is_acc_ + || pd()->with_bias()) { + const bool force_sequential = MB * OC < 2000; + parallel(force_sequential ? 1 : 0, [&](int ithr, int nthr) { + size_t start, end; + balance211((size_t)OC * MB, nthr, ithr, start, end); + (*pp_kernel_)(dst, acc, bias, scales, nslope, start, end); + }); + } +} + +using namespace data_type; + +template struct gemm_x8s8s32x_inner_product_fwd_t; +template struct gemm_x8s8s32x_inner_product_fwd_t; +template struct gemm_x8s8s32x_inner_product_fwd_t; +template struct gemm_x8s8s32x_inner_product_fwd_t; +template struct gemm_x8s8s32x_inner_product_fwd_t; +template struct gemm_x8s8s32x_inner_product_fwd_t; +template struct gemm_x8s8s32x_inner_product_fwd_t; +template struct gemm_x8s8s32x_inner_product_fwd_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp new file mode 100644 index 0000000000..ac6a5c8f85 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp @@ -0,0 +1,166 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef GEMM_X8S8S32X_INNER_PRODUCT_HPP +#define GEMM_X8S8S32X_INNER_PRODUCT_HPP + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "gemm/gemm.hpp" +#include "jit_generator.hpp" + +#include "cpu_inner_product_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct gemm_x8s8s32x_inner_product_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_inner_product_fwd_pd_t { + using cpu_inner_product_fwd_pd_t::cpu_inner_product_fwd_pd_t; + + DECLARE_COMMON_PD_T(src_type == data_type::u8 + ? IGEMM_S8U8S32_IMPL_STR + : IGEMM_S8S8S32_IMPL_STR, + gemm_x8s8s32x_inner_product_fwd_t); + + status_t init() { + using namespace data_type; + + bool ok = true + && set_default_params() == status::success + && is_fwd() + && !has_zero_dim_memory() + && src_md()->data_type == src_type + && dst_md()->data_type == dst_type + && weights_md()->data_type == s8 + && IMPLICATION(with_bias(), utils::one_of( + weights_md(1)->data_type, f32, s32, s8, u8)) + && attr()->post_ops_.len_ <= 1 + && IMPLICATION(attr()->post_ops_.len_, + attr()->post_ops_.entry_[0].is_relu(true, false)) + && dense_gemm_consitency_check(src_md(), weights_md(), + dst_md()); + if (!ok) return status::unimplemented; + + dst_is_acc_ = utils::one_of(dst_type, s32, f32); + + init_scratchpad(); + + return status::success; + } + + bool dst_is_acc_; + + protected: + status_t set_default_params() { + using namespace format_tag; + if (src_md_.format_kind == format_kind::any) { + CHECK(memory_desc_init_by_tag(src_md_, + utils::pick(ndims() - 2, nc, nwc, nhwc, ndhwc))); + } + if (dst_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(dst_md_, nc)); + if (weights_md_.format_kind == format_kind::any) { + CHECK(memory_desc_init_by_tag(weights_md_, + utils::pick(ndims() - 2, io, wio, hwio, dhwio))); + } + return inner_product_fwd_pd_t::set_default_params(); + } + + private: + void init_scratchpad() { + if (!dst_is_acc_) { + auto scratchpad = scratchpad_registry().registrar(); + scratchpad.book( + memory_tracking::names::key_iprod_int_dat_in_acc_dt, + sizeof(acc_data_t) * MB() * OC()); + } + } + }; + + gemm_x8s8s32x_inner_product_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd, true) + { pp_kernel_ = new pp_kernel_t(apd, pd()->dst_is_acc_); } + ~gemm_x8s8s32x_inner_product_fwd_t() { delete pp_kernel_; } + + typedef typename prec_traits::type data_t; + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + // XXX: this is throwaway code that will become unnecessary when we have a + // sufficiently advanced igemm jit generator that supports quantization, + // relu, and whatnot + class pp_kernel_t: jit_generator { + public: + DECLARE_CPU_JIT_AUX_FUNCTIONS( + gemm_x8s8s32x_inner_product_fwd_t::pp_kernel); + pp_kernel_t(const pd_t *pd, bool dst_is_acc); + + void operator()(dst_data_t *dst, const acc_data_t *acc, + const char *bias, const float *scales, float nslope, + size_t start, size_t end); + private: + void generate(); + + struct ker_args { + dst_data_t *dst; + const acc_data_t *acc; + const char *bias; + const float *scales; + float nslope; + size_t len; + size_t oc_offset; + }; + void (*ker_)(const ker_args *args); + + size_t OC_; + data_type_t bias_data_type_; + size_t bias_data_type_size_; + size_t scale_idx_mult_; + bool do_bias_; + bool do_relu_; + }; + + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + pp_kernel_t *pp_kernel_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp new file mode 100644 index 0000000000..6fa251d465 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp @@ -0,0 +1,674 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* Copyright 2018 YANDEX LLC +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_memory.hpp" + +#include "jit_avx2_1x1_conv_kernel_f32.hpp" + +#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +void jit_avx2_1x1_conv_kernel_f32::generate_bcast_loop(int load_loop_blk) +{ + mov(aux1_reg_bcast_data, reg_bcast_data); + mov(aux_reg_output_data, reg_output_data); + mov(bcast_loop_iter, reg_bcast_loop_work); + + Label bcast_loop, bcast_loop_tail; + + cmp(bcast_loop_iter, jcp.ur); + jl(bcast_loop_tail, T_NEAR); + + L(bcast_loop); { + assert(jcp.bcast_block % jcp.ur == 0); + int num_substeps = jcp.bcast_block / jcp.ur; + assert(num_substeps > 0 && num_substeps < 10); + for (int i = 0; i < num_substeps; i++) { + generate_reduce_loop(load_loop_blk, jcp.ur); + if (i < num_substeps - 1) { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_substep); + } else { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step + - (num_substeps - 1) * jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_step + - (num_substeps - 1) * jcp.bcast_loop_output_substep); + } + } + sub(bcast_loop_iter, jcp.bcast_block); + cmp(bcast_loop_iter, jcp.bcast_block); + jge(bcast_loop, T_NEAR); + } + + L(bcast_loop_tail); + if (jcp.ur_tail) { + Label bcast_loop_tail_out; + cmp(bcast_loop_iter, 0); + jz(bcast_loop_tail_out, T_NEAR); + generate_reduce_loop(load_loop_blk, jcp.ur_tail); + L(bcast_loop_tail_out); + } +} + +void jit_avx2_1x1_conv_kernel_f32::generate_reduce_loop( + int load_loop_blk, int ur) +{ + auto vreg_load = [=](int i) { + return Ymm(ur * load_loop_blk + i); + }; + + auto vreg_accum = [=](int i, int j) { + return Ymm(j * load_loop_blk + i); + }; + + auto bias_ptr = [=](int i) { + return ptr[reg_bias_data + sizeof(float) * jcp.oc_block * i]; + }; + + auto bcast_ptr = [=](int u, int j) { + assert(j < jcp.ur); + assert(u <= jcp.reduce_loop_unroll); + size_t offt; + if (one_of(jcp.prop_kind, + forward_training, forward_inference, backward_data)) + { + assert(jcp.reduce_loop_unroll == (jcp.prop_kind == backward_data) + ? jcp.oc_block : jcp.ic_block); + auto height = (jcp.prop_kind == backward_data) ? jcp.os : jcp.is; + offt = (u == jcp.reduce_loop_unroll) + ? (height + j) * jcp.reduce_loop_unroll + : j * jcp.reduce_loop_unroll + u; + } else + offt = u * jcp.ic_block + j; + return ptr[aux_reg_bcast_data + sizeof(float) * offt]; + }; + + auto load_ptr = [=](int u, int i) { + size_t offt; + size_t u0 = u % jcp.reduce_loop_unroll; + size_t u1 = u / jcp.reduce_loop_unroll; + switch (jcp.prop_kind) { + case backward_data: + offt = (i * jcp.oc_block + u0) * jcp.ic_block; + break; + case backward_weights: + offt = (i * jcp.os + u0) * jcp.oc_block; + break; + default: + offt = (i * jcp.ic + u0) * jcp.oc_block; + } + return ptr[aux_reg_load_data + + u1 * jcp.reduce_loop_load_step + sizeof(float) * offt]; + }; + + auto output_ptr = [=](int i, int j) { + switch (jcp.prop_kind) { + case backward_data: + return ptr[aux_reg_output_data + + (i * jcp.is + j) * jcp.ic_block * sizeof(float)]; + case backward_weights: + return ptr[aux_reg_output_data + + (i ? reg_output_stride * i : 0) // TODO: Xbyak should allow 0 scale + + sizeof(float) * jcp.oc_block * j]; + default: + return ptr[aux_reg_output_data + + (i * jcp.os + j) * jcp.oc_block * sizeof(float)]; + } + }; + + auto init = [=]() { + Label init_done, init_zero; + + if (jcp.with_bias && one_of(jcp.prop_kind, forward_training, + forward_inference)) { + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jz(init_zero); + + for (int i = 0; i < load_loop_blk; i++) + for (int j = 0; j < ur; ++j) + vmovups(vreg_accum(i, j), bias_ptr(i)); + jmp(init_done); + } + + L(init_zero); + for (int i = 0; i < load_loop_blk; ++i) + for (int j = 0; j < ur; ++j) { + auto r = vreg_accum(i, j); + vxorps(r, r, r); + } + + L(init_done); + for (int i = 0; i < load_loop_blk; ++i) + vmovups(vreg_load(i), load_ptr(0, i)); + vbroadcastss(vreg_bcast, bcast_ptr(0, 0)); + }; + + auto store = [=]() { + Label store_noadd; + + if (!jcp.with_sum) { + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jnz(store_noadd, T_NEAR); + } + + for (int j = 0; j < ur; ++j) + for (int i = 0; i < load_loop_blk; ++i) { + auto r = vreg_accum(i, j); + vaddps(r, r, output_ptr(i, j)); + } + + L(store_noadd); + + if (jcp.with_eltwise) { + assert(ur * load_loop_blk < 14); + + Label store_norelu; + test(reg_reduce_pos_flag, FLAG_REDUCE_LAST); + jz(store_norelu, T_NEAR); + + eltwise_injector_->compute_vector_range(0, ur * load_loop_blk); + + L(store_norelu); + } + + for (int j = 0; j < ur; ++j) + for (int i = 0; i < load_loop_blk; ++i) { + vmovups(output_ptr(i, j), vreg_accum(i, j)); + } + }; + + auto fma_block = [=](bool last_block) { + for (int u = 0; u < jcp.reduce_loop_unroll; ++u) { + for (int j = 0; j < ur; ++j) { + for (int i = 0; i < load_loop_blk; ++i) { + if (mayiuse(avx2)) + vfmadd231ps(vreg_accum(i, j), vreg_load(i), vreg_bcast); + else { // Intel(R) Advanced Vector Extensions (Intel(R) AVX) support + vmulps(vtmp, vreg_bcast, vreg_load(i)); + vaddps(vreg_accum(i, j), vreg_accum(i, j), vtmp); + } + if (j == ur - 1 && !(last_block + && u == jcp.reduce_loop_unroll - 1)) + vmovups(vreg_load(i), load_ptr(u + 1, i)); + } + if (j < ur - 1) + vbroadcastss(vreg_bcast, bcast_ptr(u, j + 1)); + } + if (!last_block || u < jcp.reduce_loop_unroll - 1) + vbroadcastss(vreg_bcast, bcast_ptr(u + 1, 0)); + } + }; + + Label reduce_loop, reduce_loop_tail; + + mov(aux_reg_load_data, reg_load_data); + mov(aux_reg_bcast_data, aux1_reg_bcast_data); + + init(); + + mov(reduce_loop_iter, reg_reduce_loop_work); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jle(reduce_loop_tail, T_NEAR); + + L(reduce_loop); { + fma_block(false); + add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step); + add(aux_reg_load_data, jcp.reduce_loop_load_step); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jg(reduce_loop, T_NEAR); + } + + L(reduce_loop_tail); + fma_block(true); + + store(); +} + +void jit_avx2_1x1_conv_kernel_f32::generate_diff_bias_loop(int load_loop_blk) +{ + if (!jcp.with_bias || jcp.prop_kind != backward_weights) + return; + + Label diff_bias_loop, diff_bias_loop_out, diff_bias_init_out; + Label diff_bias_load; + + auto diff_bias_ptr = [=](int i) { + return ptr[reg_diff_bias_data + i * jcp.oc_block * sizeof(float)]; + }; + + auto load_ptr = [=](int u, int i) { + return ptr[aux_reg_load_data + + (i * jcp.os + u) * jcp.oc_block * sizeof(float)]; + }; + + auto diff_bias_reg = [=](int i) { return Ymm(i); }; + + mov(reg_diff_bias_data, ptr[rsp + reg_diff_bias_data_stack_offt]); + cmp(reg_diff_bias_data, 0); + je(diff_bias_loop_out, T_NEAR); + + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jz(diff_bias_load, T_NEAR); + + for (int i = 0; i < load_loop_blk; ++i) { + auto r = diff_bias_reg(i); + vxorps(r, r, r); + } + jmp(diff_bias_init_out, T_NEAR); + + L(diff_bias_load); + for (int i = 0; i < load_loop_blk; ++i) + vmovups(diff_bias_reg(i), diff_bias_ptr(i)); + + L(diff_bias_init_out); + mov(aux_reg_load_data, reg_load_data); + mov(reduce_loop_iter, reg_reduce_loop_work); + L(diff_bias_loop); { + for(int u = 0; u < jcp.reduce_loop_unroll; ++u) + for (int i = 0; i < load_loop_blk; ++i) + vaddps(diff_bias_reg(i), diff_bias_reg(i), load_ptr(u, i)); + assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0); + add(aux_reg_load_data, jcp.reduce_loop_load_step); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jnz(diff_bias_loop, T_NEAR); + } + + for (int i = 0; i < load_loop_blk; i++) + vmovups(diff_bias_ptr(i), diff_bias_reg(i)); + add(reg_diff_bias_data, load_loop_blk * jcp.oc_block * sizeof(float)); + mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data); + + L(diff_bias_loop_out); +} + +void jit_avx2_1x1_conv_kernel_f32::generate() +{ + preamble(); + + mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]); + mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]); + mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]); + if (jcp.with_bias) { + if (jcp.prop_kind == backward_weights) { + sub(rsp, stack_space_needed); + mov(reg_diff_bias_data, ptr[param1 + GET_OFF(bias_data)]); + mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data); + } else + mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]); + } + + mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]); + mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]); + mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]); + mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]); + if (jcp.prop_kind == backward_weights) + mov(reg_output_stride, ptr[param1 + GET_OFF(output_stride)]); + + auto generate_load_loop_body = [=] (int load_loop_blk) { + generate_bcast_loop(load_loop_blk); + add(reg_load_data, load_loop_blk * jcp.load_loop_load_step); + switch (jcp.prop_kind) { + case forward_training: + case forward_inference: + add(reg_bias_data, load_loop_blk * jcp.oc_block * sizeof(float)); + add(reg_output_data, + load_loop_blk * jcp.os * jcp.oc_block * sizeof(float)); + break; + case backward_data: + add(reg_output_data, + load_loop_blk * jcp.is * jcp.ic_block * sizeof(float)); + break; + case backward_weights: + for (int i = 0; i < load_loop_blk; i++) + add(reg_output_data, reg_output_stride); + break; + default: + assert(!"invalid prop_kind"); + } + sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step); + }; + + Label load_loop_blk_8; + Label load_loop_blk_16; + Label load_loop_blk_24; + Label load_loop_blk_end; + + cmp(reg_load_loop_work, 8); + jle(load_loop_blk_8, T_NEAR); + + cmp(reg_load_loop_work, 32); + je(load_loop_blk_16, T_NEAR); + + cmp(reg_load_loop_work, 16); + jle(load_loop_blk_16, T_NEAR); + + L(load_loop_blk_24); { + generate_diff_bias_loop(3); + generate_load_loop_body(3); + cmp(reg_load_loop_work, 32); + je(load_loop_blk_16); + cmp(reg_load_loop_work, 24); + jge(load_loop_blk_24); + } + + cmp(reg_load_loop_work, 8); + jle(load_loop_blk_8, T_NEAR); + + L(load_loop_blk_16); { + generate_diff_bias_loop(2); + generate_load_loop_body(2); + cmp(reg_load_loop_work, 16); + jge(load_loop_blk_16); + } + + L(load_loop_blk_8); { + cmp(reg_load_loop_work, 0); + je(load_loop_blk_end, T_NEAR); + generate_diff_bias_loop(1); + generate_load_loop_body(1); + } + + L(load_loop_blk_end); + + if (jcp.with_bias && jcp.prop_kind == backward_weights) + add(rsp, 8); + + postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +bool jit_avx2_1x1_conv_kernel_f32::post_ops_ok( + jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + + return false; +} + +status_t jit_avx2_1x1_conv_kernel_f32::init_conf(jit_1x1_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr) +{ + if (!mayiuse(avx)) return status::unimplemented; + + // TODO (Roma): this code is duplicated from the generic kernel; maybe the + // configuration struct could do some stuff below + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + const int ndims = src_d.ndims(); + + jcp.prop_kind = cd.prop_kind; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2]; + jcp.iw = src_d.dims()[ndims - 1]; + jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2]; + jcp.ow = dst_d.dims()[ndims - 1]; + + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0]; + jcp.l_pad = cd.padding[0][ndims - 3]; + + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0]; + jcp.stride_w = cd.strides[ndims - 3]; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + jcp.os = jcp.oh * jcp.ow; + jcp.is = jcp.ih * jcp.iw; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + jcp.with_sum = p.find(primitive_kind::sum) != -1; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) { + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + if (!mayiuse(avx2) && jcp.eltwise.alg != alg_kind::eltwise_relu) + return status::unimplemented; + } + + const int is_bwd_d = jcp.prop_kind == backward_data; + + format_tag_t dat_tag = ndims == 3 ? nCw8c : nChw8c; + format_tag_t wei_tag = with_groups + ? utils::pick(2 * ndims - 6 + is_bwd_d, gOIw8i8o, gOIw8o8i, gOIhw8i8o, + gOIhw8o8i) + : utils::pick(2 * ndims - 6 + is_bwd_d, OIw8i8o, OIw8o8i, OIhw8i8o, + OIhw8o8i); + + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + + const int simd_w = 8; + + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + + bool args_ok = true + && jcp.ngroups == 1 + && jcp.src_tag == dat_tag + && jcp.wei_tag == wei_tag + && jcp.dst_tag == dat_tag; + if (!args_ok) return status::unimplemented; + + args_ok = true + && jcp.ih == jcp.oh && jcp.iw == jcp.ow + && jcp.oc % simd_w == 0 && jcp.ic % simd_w == 0 + && jcp.t_pad == 0 && jcp.l_pad == 0 + && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides + && jcp.kh == 1 && jcp.kw == 1; + if (!args_ok) return status::unimplemented; + + // TODO: remove this restriction + // optimized 1x1 bwd_w does not support Intel AVX + if (jcp.prop_kind == backward_weights && !mayiuse(avx2)) + return status::unimplemented; + + jcp.ic_block = jcp.oc_block = simd_w; + + jcp.ur = mayiuse(avx2) ? 4 : 3; // Intel AVX support + + int load_blocking{ 0 }; + int load_blocking_max{ 0 }; + int bcast_blocking{ 0 }; + int bcast_blocking_max{ 0 }; + int reduce_blocking{ 0 }; + + if (one_of(jcp.prop_kind, forward_training, forward_inference)) { + jcp.reduce_dim = jcp.ic; + jcp.reduce_block = jcp.ic_block; + + jcp.load_dim = jcp.oc; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.is; + jcp.bcast_block = jcp.ur; + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.is * sizeof(float); + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float); + + jcp.bcast_loop_output_step = jcp.ur * jcp.oc_block * sizeof(float); + jcp.bcast_loop_output_substep = -1; // unused + jcp.bcast_loop_bcast_step = jcp.ur * jcp.ic_block * sizeof(float); + jcp.bcast_loop_bcast_substep = -1; // unused + + jcp.load_loop_load_step = jcp.ic * jcp.oc_block * sizeof(float); + jcp.load_loop_iter_step = jcp.oc_block; + + load_blocking = 120; // assumes the kernel is jcp.ur x 3 + load_blocking_max = 144; + bcast_blocking = 128; // affects load balancing across threads + bcast_blocking_max = 192; + reduce_blocking = 128; // affects L1$ utilization + } else if (jcp.prop_kind == backward_data) { + jcp.reduce_dim = jcp.oc; + jcp.reduce_block = jcp.oc_block; + + jcp.load_dim = jcp.ic; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.os; + jcp.bcast_block = jcp.ur; + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.os * sizeof(float); + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.ic * sizeof(float); + + jcp.bcast_loop_output_step = jcp.ur * jcp.ic_block * sizeof(float); + jcp.bcast_loop_output_substep = -1; // unused + jcp.bcast_loop_bcast_step = jcp.ur * jcp.oc_block * sizeof(float); + jcp.bcast_loop_bcast_substep = -1; // unused + + jcp.load_loop_load_step = jcp.oc_block * jcp.ic_block * sizeof(float); + jcp.load_loop_iter_step = jcp.ic_block; + + load_blocking = 96; // assumes the kernel is jcp.ur x 3 + load_blocking_max = 144; + bcast_blocking = 128; // affects load balancing across threads + bcast_blocking_max = 196; + reduce_blocking = 64; // affects L1$ utilization + } else if (jcp.prop_kind == backward_weights) { + jcp.reduce_dim = jcp.os; + jcp.reduce_block = 1; + + jcp.load_dim = jcp.oc; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.ic; + jcp.bcast_block = jcp.ic_block; + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.ic_block * sizeof(float); + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float); + + jcp.bcast_loop_output_step = jcp.oc_block * jcp.ic_block * sizeof(float); + jcp.bcast_loop_output_substep = jcp.oc_block * jcp.ur * sizeof(float); + jcp.bcast_loop_bcast_step = jcp.ic_block * jcp.is * sizeof(float); + jcp.bcast_loop_bcast_substep = jcp.ur * sizeof(float); + + jcp.load_loop_load_step = jcp.oc_block * jcp.os * sizeof(float); + jcp.load_loop_iter_step = jcp.oc_block; + + /* --- */ + + load_blocking = div_up(jcp.load_dim, jcp.load_block); + while (true) { + if (load_blocking <= 32) break; + else if (load_blocking % 2 == 0) load_blocking /= 2; + else if (load_blocking % 3 == 0) load_blocking /= 3; + else break; + } + load_blocking *= jcp.load_block; + load_blocking_max = load_blocking; + assert(jcp.load_dim % load_blocking == 0); + + bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block); + while (true) { + if (bcast_blocking <= 9) break; + else if (bcast_blocking % 2 == 0) bcast_blocking /= 2; + else if (bcast_blocking % 3 == 0) bcast_blocking /= 3; + else break; + } + bcast_blocking *= jcp.bcast_block; + bcast_blocking_max = bcast_blocking; + assert(jcp.bcast_dim % bcast_blocking == 0); + + reduce_blocking = 128; // affects L1$ utilization + } else + return status::unimplemented; + + assert(load_blocking); + assert(load_blocking_max); + assert(bcast_blocking); + assert(bcast_blocking_max); + assert(reduce_blocking); + + assert(jcp.bcast_block % jcp.ur == 0); + jcp.ur_tail = jcp.bcast_dim % jcp.ur; + + jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block; + jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block; + jcp.nb_load_blocking = load_blocking / jcp.load_block; + jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block; + jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block; + + jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block); + jcp.nb_load = div_up(jcp.load_dim, jcp.load_block); + jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block); + + return status::success; +} + +void jit_avx2_1x1_conv_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, + const jit_1x1_conv_conf_t &jcp) { + using namespace mkldnn::impl::memory_tracking::names; + + if (jcp.prop_kind != backward_data && jcp.oc != jcp.oc_without_padding) + scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp new file mode 100644 index 0000000000..bfdeb2b18d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp @@ -0,0 +1,110 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX2_1x1_CONV_KERNEL_F32_HPP +#define JIT_AVX2_1x1_CONV_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "cpu_memory.hpp" +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx2_1x1_conv_kernel_f32: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_1x1_conv_kernel_f32) + + jit_avx2_1x1_conv_kernel_f32(jit_1x1_conv_conf_t ajcp, + const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32(this, + jcp.eltwise); + + this->generate(); + jit_ker = (void (*)(jit_1x1_conv_call_s *))this->getCode(); + } + + ~jit_avx2_1x1_conv_kernel_f32() { + delete eltwise_injector_; + } + + static bool post_ops_ok(jit_1x1_conv_conf_t &jcp, + const primitive_attr_t &attr); + + static status_t init_conf(jit_1x1_conv_conf_t &jcp, + const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr); + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_1x1_conv_conf_t &jcp); + + jit_1x1_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker)(jit_1x1_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + using ymm_t = const Xbyak::Ymm; + + reg64_t reg_bcast_data = rax; + reg64_t reg_load_data = rsi; + reg64_t reg_output_data = rbx; + reg64_t aux_reg_bcast_data = rdx; + reg64_t aux1_reg_bcast_data = abi_not_param1; + reg64_t aux_reg_load_data = abi_param1; + reg64_t aux_reg_output_data = rbp; + reg64_t reg_load_loop_work = r9; + reg64_t reg_bcast_loop_work = r10; + reg64_t reg_reduce_loop_work = r11; + reg64_t load_loop_iter = r13; + reg64_t bcast_loop_iter = r14; + reg64_t reduce_loop_iter = r15; + reg64_t imm_addr64 = reduce_loop_iter; + reg64_t reg_reduce_pos_flag = r8; + reg64_t reg_output_stride = r12; + reg64_t reg_bias_data = r12; + reg64_t reg_diff_bias_data = bcast_loop_iter; + + int reg_diff_bias_data_stack_offt = 0; + int stack_space_needed = 8; + + ymm_t vreg_bcast = ymm_t(15); + ymm_t vtmp = ymm_t(14); + + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + void generate_bcast_loop(int load_loop_blk); + void generate_reduce_loop(int load_loop_blk, int ur); + void generate_diff_bias_loop(int load_loop_blk); + + void generate(); +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp new file mode 100644 index 0000000000..f116ac9056 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp @@ -0,0 +1,545 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_generator.hpp" + +#include "jit_avx2_1x1_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +#define data_blk_off(f, n, c, h, w) \ + ((ndims == 3) \ + ? (f).blk_off(n, c, w) \ + : (f).blk_off(n, c, h, w)) + +/* convolution forward */ + +void jit_avx2_1x1_convolution_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + auto rtus_space = scratchpad(ctx).get(key_conv_rtus_space); + + const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast; + const int ndims = dst_d.ndims(); + + const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0]; + const int stride_w = pd()->desc()->strides[ndims - 3]; + const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0]; + const int pad_l = pd()->desc()->padding[0][ndims - 3]; + + auto step = [](int default_step, int remaining, int tail_step) { + assert(default_step <= tail_step); + return remaining < tail_step ? remaining : default_step; + }; + + auto ker = [&](const int ithr, const int nthr) { + // TODO (Roma): remove this restriction + assert(jcp.stride_w == 1 && jcp.stride_h == 1); + + auto p = jit_1x1_conv_call_s(); + auto rp = rtus_driver_t::call_params_t(); + + const int nb_oc = jcp.nb_load; + const int nb_ic = jcp.nb_reduce; + const int nb_ic_blocking = jcp.nb_reduce_blocking; + const int os_block = jcp.bcast_block; + + int start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + int iwork = start; + while (iwork < end) { + int n{0}, g{0}, osb{0}; + nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb, + jcp.nb_bcast); + + int bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb, + jcp.nb_bcast_blocking_max); + bcast_step = nstl::min(bcast_step, end - iwork); + + const int os = osb * os_block; + const int oh = os / jcp.ow; + const int ow = os % jcp.ow; + + const int ih = nstl::max(oh * stride_h - pad_t, 0); + const int iw = nstl::max(ow * stride_w - pad_l, 0); + rp.iw_start = iw; + + p.bcast_dim = this_block_size(os, jcp.os, bcast_step * os_block); + rp.os = p.bcast_dim; + + int ocb = 0; + while (ocb < jcp.nb_load) { + const int load_step = step(jcp.nb_load_blocking, + jcp.nb_load - ocb, jcp.nb_load_blocking_max); + + const int _ocb = g * nb_oc + ocb; + p.load_dim = this_block_size(ocb * jcp.oc_block, jcp.oc, + load_step * jcp.oc_block); + const size_t dst_off = data_blk_off(dst_d, n, _ocb, oh, ow); + + p.output_data = &dst[dst_off]; + + p.bias_data = &bias[_ocb * jcp.oc_block]; + + for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) { + p.first_last_flag = 0 + | (icb == 0 ? FLAG_REDUCE_FIRST : 0) + | (icb + nb_ic_blocking >= nb_ic + ? FLAG_REDUCE_LAST : 0); + + p.reduce_dim = this_block_size(icb * jcp.ic_block, jcp.ic, + nb_ic_blocking * jcp.ic_block); + rp.icb = p.reduce_dim / jcp.reduce_block; + + p.load_data = &weights[pd()->with_groups() + ? weights_d.blk_off(g, ocb, icb) + : weights_d.blk_off(ocb, icb)]; + + const int _icb = g * nb_ic + icb; + if (pd()->rtus_.reduce_src_) { + rp.ws = rtus_space + + ithr * pd()->rtus_.space_per_thread_ + + _icb * jcp.is * jcp.ic_block; + + if (ocb == 0) { + rp.src = src + data_blk_off(src_d, n, _icb, ih, iw); + rtus_driver_->ker_(&rp); + } + + p.bcast_data = rp.ws; + } else + p.bcast_data = src + data_blk_off(src_d, n, _icb, ih, iw); + + kernel_->jit_ker(&p); + } + + ocb += load_step; + } + + iwork += bcast_step; + } + }; + + if (pd()->wants_padded_bias()) { + auto padded_bias = scratchpad(ctx).get(key_conv_padded_bias); + utils::array_copy(padded_bias, bias, jcp.oc_without_padding); + utils::array_set(padded_bias + jcp.oc_without_padding, 0.f, + jcp.oc - jcp.oc_without_padding); + bias = padded_bias; + } + + parallel(0, ker); + + if (pd()->wants_zero_pad_dst()) + ctx.memory(MKLDNN_ARG_DST)->zero_pad(); +} + +/* convolution backward wtr data */ + +void jit_avx2_1x1_convolution_bwd_data_t::execute_backward_data( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + + const auto &jcp = kernel_->jcp; + auto rtus_space = scratchpad(ctx).get(key_conv_rtus_space); + + // TODO (Roma): remove this restriction + assert(jcp.stride_w == 1 && jcp.stride_h == 1); + const int ndims = diff_dst_d.ndims(); + + const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0]; + const int stride_w = pd()->desc()->strides[ndims - 3]; + const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0]; + const int pad_l = pd()->desc()->padding[0][ndims - 3]; + + const int nb_ic = jcp.nb_load; + const int nb_oc = jcp.nb_reduce; + const int os_block = jcp.bcast_block; + const int nb_oc_blocking = jcp.nb_reduce_blocking; + + const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast; + + auto step = [](int default_step, int remaining, int tail_step) { + assert(default_step <= tail_step); + return remaining < tail_step ? remaining : default_step; + }; + + auto ker = [&](const int ithr, const int nthr) { + auto p = jit_1x1_conv_call_s(); + auto rp = rtus_driver_t::call_params_t(); + + int start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + int load_step = 0; + for (int icb = 0; icb < jcp.nb_load; icb += load_step) { + load_step = step(jcp.nb_load_blocking, jcp.nb_load - icb, + jcp.nb_load_blocking_max); + + p.load_dim = this_block_size(icb * jcp.ic_block, jcp.ic, + load_step * jcp.ic_block); + rp.icb = p.load_dim / jcp.ic_block; + + int bcast_step; + for (int iwork = start; iwork < end; iwork += bcast_step) { + int n{0}, g{0}, osb{0}; + nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb, + jcp.nb_bcast); + + bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb, + jcp.nb_bcast_blocking_max); + bcast_step = nstl::min(bcast_step, end - iwork); + + const int os = osb * os_block; + p.bcast_dim = this_block_size(os, jcp.os, + bcast_step * os_block); + rp.os = p.bcast_dim; + + const int oh = os / jcp.ow; + const int ow = os % jcp.ow; + const int ih = nstl::max(oh * stride_h - pad_t, 0); + const int iw = nstl::max(ow * stride_w - pad_l, 0); + rp.iw_start = iw; + + const int _icb = g * nb_ic + icb; + rp.src = diff_src + data_blk_off(diff_src_d, n, _icb, ih, iw); + if (pd()->rtus_.reduce_src_) { + rp.ws = rtus_space + + ithr * pd()->rtus_.space_per_thread_; + p.output_data = rp.ws; + } else + p.output_data = rp.src; + + for (int ocb = 0; ocb < jcp.nb_reduce; + ocb += jcp.nb_reduce_blocking) { + const int _ocb = g * nb_oc + ocb; + size_t diff_dst_off = data_blk_off(diff_dst_d, n, _ocb, oh, + ow); + p.bcast_data = &diff_dst[diff_dst_off]; + + p.load_data = &weights[pd()->with_groups() + ? weights_d.blk_off(g, ocb, icb) + : weights_d.blk_off(ocb, icb)]; + + p.first_last_flag = ocb == 0 ? FLAG_REDUCE_FIRST : 0; + + p.reduce_dim = this_block_size(ocb * jcp.oc_block, jcp.oc, + nb_oc_blocking * jcp.oc_block); + + kernel_->jit_ker(&p); + } + + if (pd()->rtus_.reduce_src_) + rtus_driver_->ker_(&rp); + } + } + }; + + parallel(0, ker); +} + +/* convolution backward wtr weights */ + +jit_avx2_1x1_convolution_bwd_weights_t::jit_avx2_1x1_convolution_bwd_weights_t( + const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr) + , rtus_driver_(nullptr) +{ + kernel_ = new jit_avx2_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr()); + reducer_weights_ = + new cpu_reducer_2d_t(pd()->reducer_wei_conf_); + reducer_bias_ = new cpu_reducer_t(pd()->reducer_bia_conf_); + init_rtus_driver(this); +} + +void jit_avx2_1x1_convolution_bwd_weights_t::execute_backward_weights( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias_in = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + auto scratchpad = this->scratchpad(ctx); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1)); + + const auto &jcp = kernel_->jcp; + auto rtus_space = scratchpad.get(key_conv_rtus_space); + + data_t *diff_bias = pd()->wants_padded_bias() + ? scratchpad.get(key_conv_padded_bias) : diff_bias_in; + + auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad, + prefix_reducer_bia); + auto rb = this->reducer_bias_; + rb->init(reducer_bia_scratchpad); + + auto reducer_wei_scratchpad = memory_tracking::grantor_t(scratchpad, + prefix_reducer_wei); + auto rw = this->reducer_weights_; + rw->init(reducer_wei_scratchpad); + + const int ndims = diff_dst_d.ndims(); + // TODO (Roma): remove this restriction + assert(jcp.stride_w == 1 && jcp.stride_h == 1); + + const int nb_ic = jcp.nb_bcast; + const int nb_ic_blocking = jcp.nb_bcast_blocking; + const int bcast_work = div_up(nb_ic, nb_ic_blocking); + + const int nb_oc = jcp.nb_load; + const int nb_oc_blocking = jcp.nb_load_blocking; + const int load_work = div_up(nb_oc, nb_oc_blocking); + + const int sp_dim = jcp.reduce_dim; + const int mb_sp_work = jcp.mb * sp_dim; + + const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0]; + const int stride_w = pd()->desc()->strides[ndims - 3]; + const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0]; + const int pad_l = pd()->desc()->padding[0][ndims - 3]; + + auto step = [](int default_step, int remaining, int tail_step) { + assert(default_step <= tail_step); + return remaining < tail_step ? remaining : default_step; + }; + + auto oc_ic_sp_loop = [=](int sp_start, int sp_end, bool first_image, + data_t *store_to, size_t store_to_ld, const data_t *diff_dst, + const data_t *src, int ithr) { + auto p = jit_1x1_conv_call_s(); + auto rp = rtus_driver_t::call_params_t(); + + p.output_stride = store_to_ld * sizeof(float); + const int sp_step_def = jcp.nb_reduce_blocking * jcp.reduce_block; + + int oc_b_step = 0; + for (int oc_b = 0; oc_b < nb_oc_blocking; oc_b += oc_b_step) { + oc_b_step = step(12, nb_oc_blocking - oc_b, 18); + p.load_dim = oc_b_step * jcp.oc_block; + + int ic_b_step = 0; + for (int ic_b = 0; ic_b < nb_ic_blocking; ic_b += ic_b_step) { + ic_b_step = step(12, nb_ic_blocking - ic_b, 18); + p.bcast_dim = ic_b_step * jcp.ic_block; + rp.icb = p.bcast_dim / jcp.ic_block; + + p.output_data = store_to + oc_b * store_to_ld + + ic_b * jcp.ic_block * jcp.oc_block; + + /* spatial reduction */ + int sp_step = 0; + for (int sp = sp_start; sp < sp_end; sp += sp_step) { + sp_step = step(sp_step_def, sp_end - sp, 192); + p.reduce_dim = sp_step; + rp.os = p.reduce_dim; + + p.first_last_flag = sp == sp_start && first_image + ? FLAG_REDUCE_FIRST : 0; + + p.load_data = diff_dst + + (oc_b * jcp.reduce_dim + sp) * jcp.oc_block; + + if (pd()->rtus_.reduce_src_) { + const int oh = sp / jcp.ow; + const int ow = sp % jcp.ow; + + const int ih = nstl::max(oh * stride_h - pad_t, 0); + const int iw = nstl::max(ow * stride_w - pad_l, 0); + rp.iw_start = iw; + + rp.ws = rtus_space + + ithr * pd()->rtus_.space_per_thread_ + + (ic_b * jcp.is + sp) * jcp.ic_block; + if (ndims == 3) + rp.src = src + + iw * src_d.blocking_desc().strides[2]; + else + rp.src = src + + ih * src_d.blocking_desc().strides[2] + + iw * src_d.blocking_desc().strides[3]; + + if (oc_b == 0) + rtus_driver_->ker_(&rp); + + p.bcast_data = rp.ws; + } else + p.bcast_data = src + + (ic_b * jcp.reduce_dim + sp) * jcp.ic_block; + + kernel_->jit_ker(&p); + } + } + } + }; + + auto ker = [&](const int ithr, const int nthr) { + assert(nthr == rw->balancer().nthr_); + + const int w_njobs = rw->balancer().ithr_njobs(ithr); + if (w_njobs == 0) return; + + /* setup: independent work (oc, ic) */ + const int w_job_start = rw->balancer().ithr_job_off(ithr); + int g{0}, load_i{0}, bcast_i{0}; + nd_iterator_init(w_job_start, g, jcp.ngroups, load_i, load_work, + bcast_i, bcast_work); + + /* setup: reduction work (mb, sp) */ + int mb_sp_start{0}, mb_sp_end{0}; + balance211(mb_sp_work, rw->balancer().nthr_per_group_, + rw->balancer().id_in_group(ithr), mb_sp_start, mb_sp_end); + int img_start{0}, sp_start{0}; + nd_iterator_init(mb_sp_start, img_start, jcp.mb, sp_start, sp_dim); + + /* independent work */ + for (int iwork = 0; iwork < w_njobs; ++iwork) { + const int oc_b = nb_oc_blocking * load_i; + const int ic_b = nb_ic_blocking * bcast_i; + + const int _ic_b = g * nb_ic + ic_b; + const int _oc_b = g * nb_oc + oc_b; + + data_t *store_to; + size_t store_to_ld; + + if (rw->balancer().nthr_per_group_ == 1) { + const size_t off = pd()->with_groups() + ? diff_weights_d.blk_off(g, oc_b, ic_b) + : diff_weights_d.blk_off(oc_b, ic_b); + store_to = &diff_weights[off]; + store_to_ld = jcp.ic * jcp.oc_block; + } else { + const size_t off = iwork * rw->balancer().job_size_; + store_to = + rw->get_local_ptr(ithr, reducer_wei_scratchpad) + off; + store_to_ld = nb_ic_blocking * jcp.ic_block * jcp.oc_block; + } + + /* reduction work */ + int img = img_start; + int sp = sp_start; + int sp_step = 0; + for (int mb_sp = mb_sp_start; mb_sp < mb_sp_end; mb_sp += sp_step) + { + sp_step = nstl::min(sp_dim - sp, mb_sp_end - mb_sp); + + const bool first_image = img == img_start; + oc_ic_sp_loop(sp, sp + sp_step, first_image, store_to, + store_to_ld, &diff_dst[diff_dst_d.blk_off(img, _oc_b)], + &src[src_d.blk_off(img, _ic_b)], ithr); + + sp = 0; + img += 1; + } + + nd_iterator_step(g, jcp.ngroups, load_i, load_work, bcast_i, + bcast_work); + } + rw->reduce(ithr, diff_weights, reducer_wei_scratchpad); + }; + + auto ker_bias = [&](int ithr, int nthr) { + assert(nthr == rb->balancer().nthr_); + + const int b_job_start = rb->balancer().ithr_job_off(ithr); + const int b_njobs = rb->balancer().ithr_njobs(ithr); + + if (b_njobs == 0) return; + + /* reduction dimension */ + int img_start{0}, img_end{0}; + balance211(jcp.mb, rb->balancer().nthr_per_group_, + rb->balancer().id_in_group(ithr), img_start, img_end); + + /* jobs */ + int g_start{0}, ocb_start{0}; + nd_iterator_init(b_job_start, g_start, jcp.ngroups, ocb_start, nb_oc); + + for (int img = img_start; img < img_end; ++img) { + int g = g_start, ocb = ocb_start; + for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) { + const size_t _oc = g * nb_oc + ocb; + + const data_t *d_dst = &diff_dst[diff_dst_d.blk_off(img, _oc)]; + data_t *d_bias = + rb->get_local_ptr(ithr, diff_bias, reducer_bia_scratchpad) + + b_job_loc * rb->balancer().job_size_; + + if (img == img_start) + for (int o = 0; o < 8; ++o) d_bias[o] = 0.; + + for (int hw = 0; hw < jcp.oh * jcp.ow; ++hw) { + PRAGMA_OMP_SIMD() + for (int o = 0; o < 8; ++o) + d_bias[o] += d_dst[o]; + d_dst += 8; + } + + nd_iterator_step(g, jcp.ngroups, ocb, nb_oc); + } + } + rb->reduce(ithr, diff_bias, reducer_bia_scratchpad); + }; + + parallel(0, [&](const int ithr, const int nthr) { + ker(ithr, nthr); + if (pd()->with_bias()) + ker_bias(ithr, nthr); + }); + + /* TODO: put this in ker_bias */ + if (pd()->wants_padded_bias()) { + assert(jcp.ngroups == 1); + for (int oc = 0; oc < jcp.oc_without_padding; ++oc) + diff_bias_in[oc] = diff_bias[oc]; + } +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp new file mode 100644 index 0000000000..9762242173 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp @@ -0,0 +1,344 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX2_1x1_CONVOLUTION_HPP +#define CPU_JIT_AVX2_1x1_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" +#include "cpu_reducer.hpp" + +#include "jit_avx2_1x1_conv_kernel_f32.hpp" +#include "jit_uni_1x1_conv_utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx2_1x1_convolution_fwd_t: public cpu_primitive_t { + // TODO: (Roma) Code duplication duplication! Remove with templates + // (maybe...)! + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_(), rtus_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_1x1:", avx2, ""), + jit_avx2_1x1_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + const convolution_desc_t *conv_d = desc(); + const memory_desc_t *src_d = src_md(); + rtus_prepare(this, conv_d, src_d, dst_md()); + + status_t status = jit_avx2_1x1_conv_kernel_f32::init_conf(jcp_, + *conv_d, *src_d, *weights_md(), *dst_md(), *attr()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx2_1x1_conv_kernel_f32::init_scratchpad(scratchpad, jcp_); + + rtus_prepare_space_info(this, scratchpad); + + return status::success; + } + + jit_1x1_conv_conf_t jcp_; + reduce_to_unit_stride_t rtus_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, gOIw8i8o, gOIhw8i8o) + : utils::pick(ndims() - 3, OIw8i8o, OIhw8i8o); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + template + friend void init_rtus_driver(conv_t *self); + + jit_avx2_1x1_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr), rtus_driver_(nullptr) + { + kernel_ = new jit_avx2_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr()); + init_rtus_driver(this); + } + + ~jit_avx2_1x1_convolution_fwd_t() { + delete kernel_; + delete rtus_driver_; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx2_1x1_conv_kernel_f32 *kernel_; + rtus_driver_t *rtus_driver_; +}; + +struct jit_avx2_1x1_convolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_(), rtus_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_1x1:", avx2, ""), + jit_avx2_1x1_convolution_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::undef, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + const convolution_desc_t *conv_d = desc(); + const memory_desc_t *diff_src_d = diff_src_md(); + rtus_prepare(this, conv_d, diff_src_d, diff_dst_md()); + + status_t status = jit_avx2_1x1_conv_kernel_f32::init_conf(jcp_, + *conv_d, *diff_src_d, *weights_md(), *diff_dst_md(), + *attr()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx2_1x1_conv_kernel_f32::init_scratchpad(scratchpad, jcp_); + + rtus_prepare_space_info(this, scratchpad); + + return status::success; + } + + jit_1x1_conv_conf_t jcp_; + reduce_to_unit_stride_t rtus_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, gOIw8o8i, gOIhw8o8i) + : utils::pick(ndims() - 3, OIw8o8i, OIhw8o8i); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + template + friend void init_rtus_driver(conv_t *self); + + jit_avx2_1x1_convolution_bwd_data_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr) + , rtus_driver_(nullptr) + { + kernel_ = new jit_avx2_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr()); + init_rtus_driver(this); + } + + ~jit_avx2_1x1_convolution_bwd_data_t() { + delete kernel_; + delete rtus_driver_; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx2_1x1_conv_kernel_f32 *kernel_; + rtus_driver_t *rtus_driver_; +}; + +struct jit_avx2_1x1_convolution_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_(), rtus_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_1x1:", avx2, ""), + jit_avx2_1x1_convolution_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + const convolution_desc_t *conv_d = desc(); + const memory_desc_t *src_d = src_md(); + rtus_prepare(this, conv_d, src_d, diff_dst_md()); + + status_t status = jit_avx2_1x1_conv_kernel_f32::init_conf(jcp_, + *conv_d, *src_d, *diff_weights_md(), *diff_dst_md(), + *attr()); + if (status != status::success) return status; + + init_balancers(); + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx2_1x1_conv_kernel_f32::init_scratchpad(scratchpad, jcp_); + + rtus_prepare_space_info(this, scratchpad); + + auto reducer_bia_scratchpad = memory_tracking::registrar_t( + scratchpad, memory_tracking::names::prefix_reducer_bia); + reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad); + + auto reducer_wei_scratchpad = memory_tracking::registrar_t( + scratchpad, memory_tracking::names::prefix_reducer_wei); + reducer_wei_conf_.init_scratchpad(reducer_wei_scratchpad); + + return status::success; + } + + jit_1x1_conv_conf_t jcp_; + cpu_reducer_t::conf_t reducer_bia_conf_; + cpu_reducer_2d_t::conf_t reducer_wei_conf_; + reduce_to_unit_stride_t rtus_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, gOIw8i8o, gOIhw8i8o) + : utils::pick(ndims() - 3, OIw8i8o, OIhw8i8o); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + + private: + void init_balancers() { + const int ic_block = jcp_.bcast_block; + const int nb_ic = jcp_.nb_bcast; + const int nb_ic_blocking = jcp_.nb_bcast_blocking; + const int bcast_work = utils::div_up(nb_ic, nb_ic_blocking); + + const int oc_block = jcp_.load_block; + const int nb_oc = jcp_.nb_load; + const int nb_oc_blocking = jcp_.nb_load_blocking; + const int load_work = utils::div_up(nb_oc, nb_oc_blocking); + + const int job_size + = nb_oc_blocking * nb_ic_blocking * ic_block * oc_block; + const int njobs_x = bcast_work; + const int njobs_y = jcp_.ngroups * load_work; + + const int max_threads = mkldnn_get_max_threads(); + const size_t max_buffer_size = max_threads * job_size * 8; + + if (with_bias()) { + reducer_bia_conf_.init(reduce_balancer_t(max_threads, + oc_block, jcp_.ngroups * jcp_.oc / oc_block, + jcp_.mb, max_buffer_size)); + } + + reducer_wei_conf_.init( + reduce_balancer_t(max_threads, job_size, njobs_y * njobs_x, + jcp_.mb * jcp_.nb_reduce, max_buffer_size), + job_size / nb_oc_blocking, nb_oc_blocking, ic_block, + nb_ic * ic_block * oc_block, nb_oc); + } + }; + + template + friend void init_rtus_driver(conv_t *self); + + jit_avx2_1x1_convolution_bwd_weights_t(const pd_t *apd); + + ~jit_avx2_1x1_convolution_bwd_weights_t() { + delete kernel_; + delete rtus_driver_; + delete reducer_weights_; + delete reducer_bias_; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx2_1x1_conv_kernel_f32 *kernel_; + cpu_reducer_2d_t *reducer_weights_; + cpu_reducer_t *reducer_bias_; + rtus_driver_t *rtus_driver_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp new file mode 100644 index 0000000000..e24770a2da --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp @@ -0,0 +1,1501 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* Copyright 2018 YANDEX LLC +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "cpu_memory.hpp" + +#include "jit_avx2_conv_kernel_f32.hpp" + +#define GET_OFF(field) offsetof(jit_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +void jit_avx2_conv_fwd_kernel_f32::oh_step_unroll_kw(int ur_w, + int pad_l, int pad_r, int oc_blocks) +{ + int iw = jcp.iw; + int ih = jcp.ih; + int id = jcp.id; + int kw = jcp.kw; + int kh = jcp.kh; + int kd = jcp.kd; + int nb_ic = jcp.nb_ic; + int stride_w = jcp.stride_w; + int dilate_w = jcp.dilate_w + 1; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + + for (int ki = 0; ki < kw; ki++) { + int jj_start = nstl::max(0, div_up(pad_l - ki * dilate_w, stride_w)); + int jj_end = ur_w + - nstl::max(0, div_up(ki*dilate_w+pad_r-(kw-1)*dilate_w, stride_w)); + for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) { + for (int jj = jj_start; jj < jj_end; jj++) { + size_t inp_off; + if (one_of(jcp.src_tag, ncw, nchw, ncdhw)) + inp_off = sizeof(float)*((size_t)ifm2*id*ih*iw + + (ki*dilate_w + jj*stride_w - pad_l)); + else + inp_off = sizeof(float)*((ki*dilate_w + jj*stride_w + - pad_l)*ic_blk + ifm2); + vbroadcastss(Ymm(oc_blocks * ur_w + jj), + make_safe_addr(aux_reg_input, inp_off, reg_long_offt)); + } + + for (int ii = 0; ii < oc_blocks; ii++) { + int ker_off = ii * nb_ic * kd * kh * kw * ic_blk * oc_blk + + ki * ic_blk * oc_blk + ifm2 * oc_blk; + vmovups(ymm15, ptr[aux_reg_kernel + sizeof(float) * ker_off]); + for (int jj = jj_start; jj < jj_end; jj++) + if (mayiuse(avx2)) + vfmadd231ps(Ymm(ur_w * ii + jj), + Ymm(oc_blocks * ur_w + jj), ymm15); + else { // Intel(R) Advanced Vector Extensions (Intel(R) AVX) support + vmulps(ytmp, ymm15, Ymm(oc_blocks * ur_w + jj)); + vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), ytmp); + } + } + } + } +} + +void jit_avx2_conv_fwd_kernel_f32::oh_step_nopad(int ur_w, + int pad_l, int pad_r, char pad_tag, + int oc_blocks, char oc_blocks_tag) +{ + Label kw_loop; + + int iw = jcp.iw; + int ih = jcp.ih; + int id = jcp.id; + int kw = jcp.kw; + int kh = jcp.kh; + int kd = jcp.kd; + int nb_ic = jcp.nb_ic; + int stride_w = jcp.stride_w; + int dilate_w = jcp.dilate_w + 1; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + + xor_(ki_iter, ki_iter); + L(kw_loop); + { + int jj_start = 0; + int jj_end = ur_w; + for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) { + for (int jj = jj_start; jj < jj_end; jj++) { + size_t inp_off; + if (one_of(jcp.src_tag, ncw, nchw, ncdhw)) + inp_off = sizeof(float)*((size_t)ifm2 * id * ih * iw + + (jj * stride_w - pad_l)); + else + inp_off = sizeof(float)*((jj * stride_w - pad_l) * ic_blk + + ifm2); + vbroadcastss(Ymm(oc_blocks * ur_w + jj), + make_safe_addr(aux_reg_input, inp_off, reg_long_offt)); + } + for (int ii = 0; ii < oc_blocks; ii++) { + int aux_kernel_offset = + ii * nb_ic * kd * kh * kw * ic_blk * oc_blk + ifm2 * oc_blk; + vmovups(ymm15, ptr[aux_reg_kernel + + sizeof(float) * aux_kernel_offset]); + for (int jj = jj_start; jj < jj_end; jj++) + if (mayiuse(avx2)) + vfmadd231ps(Ymm(ur_w * ii + jj), + Ymm(oc_blocks * ur_w + jj), ymm15); + else { // Intel AVX support + vmulps(ytmp, ymm15, Ymm(oc_blocks * ur_w + jj)); + vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), ytmp); + } + } + } + add(aux_reg_kernel, sizeof(float) * oc_blk * ic_blk); + add(aux_reg_input, sizeof(float) * (one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? dilate_w : ic_blk * dilate_w)); + + inc(ki_iter); + cmp(ki_iter, kw); + jl(kw_loop, T_NEAR); + } +} + +void jit_avx2_conv_fwd_kernel_f32::width_blk_step(int ur_w, + int pad_l, int pad_r, char pad_tag, + int oc_blocks, char oc_blocks_tag) +{ + int iw = jcp.iw; + int kw = jcp.kw; + int ow = jcp.ow; + int oh = jcp.oh; + int od = jcp.od; + int dilate_h = jcp.dilate_h + 1; + int dilate_w = jcp.dilate_w + 1; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? 1 : ic_blk; + const int inp_off = one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? dilate_w : ic_blk * dilate_w; + + Label init_done, init_first; + + if (!jcp.with_sum) { + test(reg_ci_flag, FLAG_IC_FIRST); + jne(init_first, T_NEAR); + } + + for (int ii = 0; ii < oc_blocks; ii++) { + for (int jj = 0; jj < ur_w; jj++) { + size_t offt = + sizeof(float) * ((size_t)ii * od * oh * ow + jj) * oc_blk; + vmovups(Ymm(ur_w * ii + jj), + make_safe_addr(reg_output, offt, reg_long_offt)); + } + } + + if (jcp.with_sum && jcp.with_bias) { + test(reg_ci_flag, FLAG_IC_FIRST); + je(init_done, T_NEAR); + + for (int ii = 0; ii < oc_blocks; ii++) + for (int jj = 0; jj < ur_w; jj++) + vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), + yword[reg_bias + sizeof(float) * ii * oc_blk]); + } + + jmp(init_done); + + L(init_first); + if (this->jcp.with_bias) { + for (int ii = 0; ii < oc_blocks; ii++) + for (int jj = 0; jj < ur_w; jj++) + vmovups(Ymm(ur_w * ii + jj), + yword[reg_bias + sizeof(float) * ii * oc_blk]); + } else { + for (int ii = 0; ii < oc_blocks; ii++) + for (int jj = 0; jj < ur_w; jj++) + uni_vpxor(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj)); + } + + L(init_done); + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_input, reg_input); + mov(aux_reg_kernel, reg_kernel); + } + + Label skip_kh_loop, skip_kd_loop, kd_loop; + if (jcp.ndims == 5) { + push(reg_output); + push(oi_iter); + + mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]); + mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]); + mov(aux_reg_inp_d, reg_input); + + if ((jcp.dilate_d >= jcp.id) + || (jcp.kd - 1) * (jcp.dilate_d + 1) < jcp.f_pad) { + cmp(reg_ki, 0); + je(skip_kd_loop, T_NEAR); + } + L(kd_loop); + mov(kj, ptr[param1 + GET_OFF(kh_padding)]); + } else { + mov(kj, reg_kh); + } + + if (jcp.ndims == 5) { + mov(aux_reg_input, aux_reg_inp_d); + mov(aux_reg_kernel, aux_reg_ker_d); + } + + if ((jcp.dilate_h >= jcp.ih) + || (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad)) { + cmp(kj, 0); + je(skip_kh_loop, T_NEAR); + } + Label kh_loop; + L(kh_loop); + { + if (jcp.kw >= 5 && pad_l == 0 && pad_r == 0) { + oh_step_nopad(ur_w, pad_l, pad_r, pad_tag, oc_blocks, + oc_blocks_tag); + sub(aux_reg_input, sizeof(float) * kw * inp_off); + add(aux_reg_input, sizeof(float) * iw * dilate_h * inp_mult); + } else { + oh_step_unroll_kw(ur_w, pad_l, pad_r, oc_blocks); + add(aux_reg_kernel, sizeof(float) * kw * oc_blk * ic_blk); + add(aux_reg_input, sizeof(float) * iw * dilate_h * inp_mult); + } + + dec(kj); + cmp(kj, 0); + jg(kh_loop, T_NEAR); + } + + L(skip_kh_loop); + + if (jcp.ndims == 5) { + add(aux_reg_inp_d, + sizeof(float) * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mult); + add(aux_reg_ker_d, sizeof(float) * jcp.kw * jcp.kh * jcp.oc_block + * jcp.ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_loop, T_NEAR); + L(skip_kd_loop); + + pop(oi_iter); + pop(reg_output); + } + + Label regular_store; + + if (jcp.with_eltwise) { + test(reg_ci_flag, FLAG_IC_LAST); + je(regular_store, T_NEAR); + + eltwise_injector_->compute_vector_range(0, oc_blocks * ur_w); + + L(regular_store); + } + + for (int ii = 0; ii < oc_blocks; ii++) { + for (int jj = 0; jj < ur_w; jj++) { + const size_t o_off + = sizeof(float) * ((size_t)ii * od * oh * ow + jj) * oc_blk; + Ymm reg_out = Ymm(ur_w * ii + jj); + vmovups(make_safe_addr(reg_output, o_off, reg_long_offt), reg_out); + } + } +} + +inline void jit_avx2_conv_fwd_kernel_f32::solve_common( + int oc_blocks, char oc_blocks_tag) +{ + int ur_w = jcp.ur_w; + int ur_w_tail = jcp.ur_w_tail; + int n_oi = jcp.ow / ur_w; + int iw = jcp.iw; + int kw = jcp.kw; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + int dilate_w = jcp.dilate_w + 1; + int str_w = jcp.stride_w; + const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : ic_blk; + + int l_pad = jcp.l_pad; + int r_pad = nstl::max(0, (int(jcp.ow) - 1) * str_w + (kw - 1) * dilate_w + - (iw + l_pad - 1)); + int r_pad1 = (ur_w * n_oi - 1) * str_w + (kw - 1) * dilate_w + - (iw + l_pad - 1); + if (r_pad1 > 0) n_oi--; + + if (l_pad > 0) { + n_oi--; + if (n_oi < 0 && r_pad1 > 0) + width_blk_step(ur_w, l_pad, r_pad1, + 'l', oc_blocks, oc_blocks_tag); // "lrpad" + else + width_blk_step(ur_w, l_pad, 0, + 'l', oc_blocks, oc_blocks_tag); // "lpad" + add(reg_input, sizeof(float) * (ur_w * str_w - l_pad) * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_blk); + } + + Label ow_loop; + xor_(oi_iter, oi_iter); + + if (n_oi > 0) { + L(ow_loop); + + width_blk_step(ur_w, 0, 0, + 'm', oc_blocks, oc_blocks_tag); // "middle" + add(reg_input, sizeof(float) * ur_w * str_w * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_blk); + + inc(oi_iter); + cmp(oi_iter, n_oi); + jl(ow_loop, T_NEAR); + } + + if (r_pad1 > 0 && n_oi >=0) { + width_blk_step(ur_w, 0, r_pad1, + 'r', oc_blocks, oc_blocks_tag); // "rpad" + add(reg_input, sizeof(float) * ur_w * str_w * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_blk); + } + + if (ur_w_tail != 0) + width_blk_step(ur_w_tail, 0, r_pad, + 't', oc_blocks, oc_blocks_tag); // "tail" +} + +void jit_avx2_conv_fwd_kernel_f32::generate() +{ + this->preamble(); + + mov(reg_input, ptr[this->param1 + GET_OFF(src)]); + mov(reg_output, ptr[this->param1 + GET_OFF(dst)]); + mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]); + if (jcp.with_bias) + mov(reg_bias, ptr[this->param1 + GET_OFF(bias)]); + mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]); + mov(reg_ci_flag, ptr[this->param1 + GET_OFF(flags)]); + mov(reg_oc_blocks, ptr[this->param1 + GET_OFF(oc_blocks)]); + + int nb_oc_tail = jcp.nb_oc % jcp.nb_oc_blocking; + Label tail, exit; + + if (jcp.nb_oc > jcp.nb_oc_blocking) { + cmp(reg_oc_blocks, jcp.nb_oc_blocking); + jne(nb_oc_tail ? tail : exit, T_NEAR); + + solve_common(jcp.nb_oc_blocking, '0' + jcp.nb_oc_blocking); + jmp(exit, T_NEAR); + + if (nb_oc_tail) { + L(tail); + cmp(reg_oc_blocks, nb_oc_tail); + jne(exit, T_NEAR); + solve_common(nb_oc_tail, '0' + nb_oc_tail); + } + + L(exit); + } else if (jcp.nb_oc == jcp.nb_oc_blocking) { + solve_common(jcp.nb_oc_blocking, '0' + jcp.nb_oc_blocking); + } else { + solve_common(nb_oc_tail, '0' + nb_oc_tail); + } + + this->postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +bool jit_avx2_conv_fwd_kernel_f32::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + + return false; +} + +status_t jit_avx2_conv_fwd_kernel_f32::init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr) +{ + if (!mayiuse(avx)) return status::unimplemented; + + jcp.prop_kind = cd.prop_kind; + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + int ndims = src_d.ndims(); + jcp.ndims = ndims; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + jcp.id = (ndims == 5) ? src_d.dims()[2] : 1; + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2]; + jcp.iw = src_d.dims()[ndims-1]; + jcp.od = (ndims == 5) ? dst_d.dims()[2] : 1; + jcp.oh = (ndims == 3) ? 1 :dst_d.dims()[ndims-2]; + jcp.ow = dst_d.dims()[ndims-1]; + jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1; + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims-2]; + jcp.kw = weights_d.dims()[with_groups + ndims-1]; + + jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0; + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4]; + jcp.l_pad = cd.padding[0][ndims-3]; + jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1; + jcp.stride_h = (ndims == 3) ? 1 :cd.strides[ndims-4]; + jcp.stride_w = cd.strides[ndims-3]; + + jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0; + jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4]; + jcp.dilate_w = cd.dilates[ndims-3]; + + jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1) + - (jcp.ih + jcp.t_pad - 1); + + if (ndims == 3) { + jcp.src_tag = src_d.matches_one_of_tag(ncw, nwc, nCw8c); + jcp.wei_tag = weights_d.matches_one_of_tag( + Owi8o, gOwi8o, OIw8i8o, gOIw8i8o); + jcp.dst_tag = dst_d.matches_one_of_tag(nCw8c); + } else if (ndims == 4) { + jcp.src_tag = src_d.matches_one_of_tag(nchw, nhwc, nChw8c); + jcp.wei_tag = weights_d.matches_one_of_tag( + Ohwi8o, gOhwi8o, OIhw8i8o, gOIhw8i8o); + jcp.dst_tag = dst_d.matches_one_of_tag(nChw8c); + } else if (ndims == 5) { + jcp.src_tag = src_d.matches_one_of_tag(ncdhw, ndhwc, nCdhw8c); + jcp.wei_tag = weights_d.matches_one_of_tag( + Odhwi8o, gOdhwi8o, OIdhw8i8o, gOIdhw8i8o); + jcp.dst_tag = dst_d.matches_one_of_tag(nCdhw8c); + } + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + jcp.with_sum = p.find(primitive_kind::sum) != -1; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) { + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + if (!mayiuse(avx2) && jcp.eltwise.alg != alg_kind::eltwise_relu) + return status::unimplemented; + } + + const int simd_w = 8; + const bool flat = jcp.ic < simd_w; + const bool mimo = !flat; + + + /* Grouped channel offset to support 'non-blocked data' format for + * convolution sizes with '(input_channel / ngroups) < simd' */ + jcp.nonblk_group_off = + one_of(jcp.src_tag, ncw, nchw, ncdhw) && jcp.ngroups > 1 ? jcp.ic : 1; + + bool ok_to_pad_channels = true + && jcp.ngroups == 1; + + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + if (mimo) + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + bool args_ok = true + && IMPLICATION(flat, true + && one_of(jcp.src_tag, ncw, nwc, nchw, nhwc, ncdhw, ndhwc) + && one_of(jcp.wei_tag, Owi8o, gOwi8o, Ohwi8o, gOhwi8o, Odhwi8o, + gOdhwi8o)) + && IMPLICATION(mimo, true + && one_of(jcp.src_tag, nCw8c, nChw8c, nCdhw8c) + && one_of(jcp.wei_tag, OIw8i8o, gOIw8i8o, OIhw8i8o, gOIhw8i8o, + OIdhw8i8o, gOIdhw8i8o)) + && one_of(jcp.dst_tag, nCw8c, nChw8c, nCdhw8c); + if (!args_ok) return status::unimplemented; + + jcp.ur_h = 1; /* no code-unrolling by h so far */ + jcp.ur_w = 3; + + jcp.oc_block = simd_w; + jcp.nb_oc = jcp.oc / jcp.oc_block; + + jcp.nb_oc_blocking = 4; /* the optimal value for the kernel */ + + // Intel AVX and Intel AVX2 kernels need 2 and 1 temporary YMMs, respectively + // Thus, we can only assign 14 or 15 YMMs for data storage + const int num_avail_regs = mayiuse(avx2) ? 15 : 14; + if (!mayiuse(avx2)) { + if ((jcp.nb_oc_blocking + 1) * jcp.ur_w > num_avail_regs) { + // current register assignment requires more YMMs than available + // adjust one of nb_oc_block, ur_w preserving to ur_w >= l_pad + if (jcp.ur_w > jcp.l_pad && jcp.ur_w > 1) + jcp.ur_w -= 1; + else + for (int b = 3; b > 1; b--) + if (jcp.nb_oc % b == 0) { + jcp.nb_oc_blocking = b; + break; + } + } + } + + if (jcp.ow < jcp.ur_w) jcp.ur_w = jcp.ow; + jcp.ur_w_tail = jcp.ow % jcp.ur_w; + + args_ok = true + && jcp.oc % simd_w == 0 + && jcp.l_pad <= jcp.ur_w + && IMPLICATION(jcp.kw > 7, (jcp.t_pad == 0 && jcp.l_pad == 0) + || (jcp.stride_w == 1 && jcp.stride_h == 1)) + && IMPLICATION(mimo, jcp.ic % simd_w == 0); + if (!args_ok) return status::unimplemented; + + int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1)); + + if (r_pad_no_tail > jcp.ur_w * jcp.stride_w && jcp.ow / jcp.ur_w > 1) { + /* recalculate ur_w, nb_oc_blocking and ur_w_tail */ + jcp.ur_w = nstl::min(r_pad_no_tail / jcp.stride_w + jcp.ur_w_tail, + nstl::min(jcp.ow, num_avail_regs / 2)); + jcp.nb_oc_blocking = (num_avail_regs - jcp.ur_w) / jcp.ur_w; + jcp.ur_w_tail = jcp.ow % jcp.ur_w; + /* check again ... */ + r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1)); + if (jcp.ur_w < nstl::max(jcp.l_pad, r_pad_no_tail)) + return status::unimplemented; + } + assert(jcp.nb_oc_blocking > 0); + assert(jcp.ur_w * (jcp.nb_oc_blocking + 1) <= num_avail_regs); + + jcp.ic_block = (jcp.ic % simd_w != 0) ? jcp.ic : simd_w; + jcp.nb_ic = jcp.ic / jcp.ic_block; + + if (one_of(jcp.prop_kind, forward_training, forward_inference)) { + jcp.nb_ic_blocking = 12; + jcp.nb_ic_blocking_max = 16; + } else { + jcp.nb_ic_blocking = 1; + jcp.nb_ic_blocking_max = jcp.nb_ic_blocking; + } + + return status::success; +} + +void jit_avx2_conv_fwd_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + if (jcp.with_bias && jcp.oc != jcp.oc_without_padding) + scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc); +} + +void jit_avx2_conv_bwd_data_kernel_f32::compute_loop(int ur_w, int l_overflow, + int r_overflow) +{ + int kw = jcp.kw; + int kh = jcp.kh; + int kd = jcp.kd; + int iw = jcp.iw; + int ih = jcp.ih; + int id = jcp.id; + int ow = jcp.ow; + + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int nb_ic_block = jcp.nb_ic_blocking; + int stride_w = jcp.stride_w; + int stride_h = jcp.stride_h; + + Label kd_loop, skip_kd_loop; + Label oc_loop, skip_oc_loop; + + for (int ii = 0; ii < nb_ic_block; ii++) + for (int jj = 0; jj < ur_w; jj++) { + uni_vpxor(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), + Ymm(ur_w * ii + jj)); + } + + if (one_of(jcp.ndims, 3, 4)) { + cmp(reg_channel_work, 0); + jle(skip_oc_loop, T_NEAR); + xor_(reg_channel, reg_channel); + + mov(aux_reg_ddst_oc_loop, reg_ddst); + mov(aux_reg_kernel_oc_loop, reg_kernel); + + L(oc_loop); + mov(aux_reg_ddst, aux_reg_ddst_oc_loop); + mov(aux_reg_kernel, aux_reg_kernel_oc_loop); + } + + if (jcp.ndims == 5) { + assert(jcp.nb_oc_blocking == 1); + push(oi_iter); + + mov(reg_ki, ptr[this->param1 + GET_OFF(kd_padding)]); + mov(aux_reg_dst_d, reg_ddst); + mov(aux_reg_ker_d, ptr[this->param1 + GET_OFF(filt)]); + + L(kd_loop); + mov(kj, ptr[this->param1 + GET_OFF(kh_padding)]); + } else { + mov(kj, reg_kh); + } + + if (jcp.ndims == 5) { + mov(aux_reg_ddst, aux_reg_dst_d); + mov(aux_reg_kernel, aux_reg_ker_d); + } + + Label kh_loop, skip_kh_loop; + cmp(kj, 0); + jle(skip_kh_loop, T_NEAR); + L(kh_loop); { + for (int ki = 0; ki < kw; ki++) { + int jj_start = get_iw_start(ki, l_overflow); // 0; + int jj_end = get_iw_end(ur_w, ki, r_overflow); // ur_w; + for (int ofm2 = 0; ofm2 < jcp.oc_block; ofm2++) { + + for (int jj = jj_start ; jj < jj_end; jj += stride_w) { + int aux_output_offset + = (jj + jcp.l_pad - ki) / stride_w * jcp.oc_block + ofm2; + vbroadcastss(Ymm(nb_ic_block * ur_w + jj / stride_w), + ptr[aux_reg_ddst + + sizeof(float) * aux_output_offset]); + } + + for (int ii = 0; ii < nb_ic_block; ii++) { + int aux_kernel_offset + = ii * kd * kh * kw * jcp.ic_block * jcp.oc_block + + ki * jcp.ic_block * jcp.oc_block + + ofm2 * jcp.ic_block; + vmovups(ymm15, + ptr[aux_reg_kernel + + sizeof(float) * aux_kernel_offset]); + for (int jj = jj_start; jj < jj_end; jj += stride_w) + vfmadd231ps(Ymm(ur_w * ii + jj), + Ymm(nb_ic_block * ur_w + jj / stride_w), ymm15); + } + } + } + add(aux_reg_kernel, sizeof(float) * stride_h * kw * oc_block + * ic_block); + sub(aux_reg_ddst, sizeof(float) * ow * oc_block); + + dec(kj); + cmp(kj, 0); + jg(kh_loop, T_NEAR); + } + L(skip_kh_loop); + + if (jcp.ndims == 5) { + sub(aux_reg_dst_d, + sizeof(float) * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block); + add(aux_reg_ker_d, + sizeof(float) * jcp.kw * jcp.kh * oc_block * ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_loop, T_NEAR); + L(skip_kd_loop); + + pop(oi_iter); + } + + if (one_of(jcp.ndims, 3, 4)) { + int ddst_oc_shift = sizeof(float) * jcp.od * jcp.oh * jcp.ow + * jcp.oc_block; + int kernel_oc_shift = sizeof(float) * jcp.kd * jcp.kh * jcp.kw + * jcp.ic * jcp.oc_block; + + add(aux_reg_ddst_oc_loop, ddst_oc_shift); + add(aux_reg_kernel_oc_loop, kernel_oc_shift); + + inc(reg_channel); + cmp(reg_channel, reg_channel_work); + jl(oc_loop, T_NEAR); + + L(skip_oc_loop); + mov(reg_channel, ptr[param1 + GET_OFF(channel)]); + } + + Label no_update_label; + cmp(reg_channel, 0); + je(no_update_label, T_NEAR); + for (int ii = 0; ii < nb_ic_block; ii++) { + for (int jj = 0; jj < ur_w; jj++) { + size_t offt = + sizeof(float) * ((size_t)ii * id * ih * iw + jj) * ic_block; + vmovups(Ymm(15), + make_safe_addr(reg_dsrc, offt, reg_long_offt)); + vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), + Ymm(15)); + + } + } + L(no_update_label); + + for (int ii = 0; ii < nb_ic_block; ii++) + for (int jj = 0; jj < ur_w; jj++) { + size_t offt = + sizeof(float) * ((size_t)ii * id * ih * iw + jj) * ic_block; + vmovups(make_safe_addr(reg_dsrc, offt, reg_long_offt), + Ymm(ur_w * ii + jj)); + } +} + +void jit_avx2_conv_bwd_data_kernel_f32::generate() { + preamble(); + + mov(reg_dsrc, ptr[this->param1 + GET_OFF(src)]); + mov(reg_ddst, ptr[this->param1 + GET_OFF(dst)]); + mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]); + mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]); + mov(reg_channel, ptr[param1 + GET_OFF(channel)]); + mov(reg_channel_work, ptr[param1 + GET_OFF(ch_blocks)]); + + int ddst_shift = sizeof(float) * (jcp.ur_w / jcp.stride_w) * jcp.ic_block; + int dsrc_shift = sizeof(float) * jcp.ur_w * jcp.oc_block; + + int l_overflow = nstl::max(0, (jcp.kw - 1 - jcp.l_pad) / jcp.stride_w); + int r_overflow = nstl::max(0, (jcp.kw - 1 + - nstl::max(0, jcp.r_pad)) / jcp.stride_w); + int r_overflow1 = nstl::max(0, (jcp.kw - 1 + - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail) / jcp.stride_w); + + int n_oi = jcp.iw / jcp.ur_w; + if (r_overflow1 > 0) + n_oi--; + + if (jcp.ur_w == jcp.iw) { + compute_loop(jcp.ur_w, l_overflow, r_overflow); + } else if (n_oi == 0) { + compute_loop(jcp.ur_w, l_overflow, r_overflow1); + add(reg_dsrc, dsrc_shift); + add(reg_ddst, ddst_shift); + if (jcp.ur_w_tail != 0) + compute_loop(jcp.ur_w_tail, 0, r_overflow); + } else { + xor_(oi_iter, oi_iter); + if (l_overflow > 0) { + compute_loop(jcp.ur_w, l_overflow, 0); + add(reg_dsrc, dsrc_shift); + add(reg_ddst, ddst_shift); + inc(oi_iter); + } + + if ((l_overflow <= 0 && n_oi > 0) || (l_overflow > 0 && n_oi > 1)) { + Label ow_loop; + L(ow_loop); { + compute_loop(jcp.ur_w, 0, 0); + add(reg_dsrc, dsrc_shift); + add(reg_ddst, ddst_shift); + inc(oi_iter); + cmp(oi_iter, n_oi); jl(ow_loop, T_NEAR); + } + } + + if (r_overflow1 > 0 ) { + compute_loop(jcp.ur_w, 0, r_overflow1); + add(reg_dsrc, dsrc_shift); + add(reg_ddst, ddst_shift); + } + + if (jcp.ur_w_tail != 0) + compute_loop(jcp.ur_w_tail, 0, r_overflow); + } + + this->postamble(); +} + +status_t jit_avx2_conv_bwd_data_kernel_f32::init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d) +{ + if (!mayiuse(avx2)) return status::unimplemented; + + const bool with_groups = weights_d.ndims() == diff_src_d.ndims() + 1; + + int ndims = diff_src_d.ndims(); + jcp.ndims = ndims; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = diff_src_d.dims()[0]; + + jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = diff_src_d.dims()[1] / jcp.ngroups; + + jcp.id = (ndims == 5) ? diff_src_d.dims()[2] : 1; + jcp.ih = (ndims == 3) ? 1 : diff_src_d.dims()[ndims-2]; + jcp.iw = diff_src_d.dims()[ndims-1]; + jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1; + jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2]; + jcp.ow = diff_dst_d.dims()[ndims-1]; + + jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1; + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims - 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + + jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0; + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4]; + jcp.l_pad = cd.padding[0][ndims-3]; + + jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1; + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4]; + jcp.stride_w = cd.strides[ndims-3]; + + jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0; + jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4]; + jcp.dilate_w = cd.dilates[ndims-3]; + + const int simd_w = 8; + + /* derivatives */ + jcp.idp = jcp.id + 2 * jcp.f_pad; + jcp.ihp = jcp.ih + 2 * jcp.t_pad; + jcp.iwp = jcp.iw + 2 * jcp.l_pad; + jcp.ohp = jcp.oh; /* do we really need */ + jcp.owp = jcp.ow; /* padded output ??? */ + + bool ok_to_pad_channels = true + && jcp.ngroups == 1; + + /* gemm-based convolution performs better in these cases */ + if (jcp.ic < simd_w && jcp.kw > 3 && jcp.stride_w > 1) + return status::unimplemented; + + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + jcp.ic_block = (jcp.ic % simd_w) ? 1 : simd_w; + jcp.nb_ic = jcp.ic / jcp.ic_block; + + jcp.oc_block = simd_w; + if (jcp.oc % jcp.oc_block) return status::unimplemented; + jcp.nb_oc = jcp.oc / jcp.oc_block; + + jcp.ur_h = 1; /* no code-unrolling by h so far */ + jcp.nb_ic_blocking = 1; + jcp.nb_oc_blocking = 1; + jcp.ur_w = 1; + + if(one_of(ndims, 3, 4) && jcp.ow < 40) + jcp.nb_oc_blocking = jcp.ow < 15 ? 4 : 2; + + if (ndims == 3) { + jcp.src_tag = diff_src_d.matches_one_of_tag(nCw8c); + jcp.wei_tag = weights_d.matches_one_of_tag(OIw8i8o, gOIw8o8i); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCw8c); + } else if (ndims == 4) { + jcp.src_tag = diff_src_d.matches_one_of_tag(nChw8c); + jcp.wei_tag = weights_d.matches_one_of_tag(OIhw8o8i, gOIhw8o8i); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(nChw8c); + } else if (ndims == 5) { + jcp.src_tag = diff_src_d.matches_one_of_tag(nCdhw8c); + jcp.wei_tag = weights_d.matches_one_of_tag(OIdhw8o8i, gOIdhw8o8i); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCdhw8c); + } + + bool args_ok = true + && one_of(jcp.src_tag, nCw8c, nChw8c, nCdhw8c) + && one_of(jcp.wei_tag, gOIw8o8i, OIw8i8o, gOIhw8o8i, OIhw8o8i, + gOIdhw8o8i, OIdhw8o8i) + && one_of(jcp.dst_tag, nCw8c, nChw8c, nCdhw8c) + && jcp.stride_w == jcp.stride_h + && jcp.stride_d == 1 + && jcp.dilate_d == 0 + && jcp.dilate_h == 0 + && jcp.dilate_w == 0 + && jcp.ic % simd_w == 0 + && jcp.oc % simd_w == 0 + && jcp.od == (jcp.idp - jcp.kd) / jcp.stride_d + 1 + && jcp.oh == (jcp.ihp - jcp.kh) / jcp.stride_h + 1 + && jcp.ow == (jcp.iwp - jcp.kw) / jcp.stride_w + 1; + if (!args_ok) return status::unimplemented; + jcp.r_pad = (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad; + jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad; + int l_overflow = nstl::max(0, (jcp.kw - 1 - jcp.l_pad) / jcp.stride_w); + + const int max_regs = 15; /* Maximun number of registers available for + result accumulation and delta dst data. + One additional register is reserved for weights + data. */ + + /* Find the best blocking with maximum number of fma instructions + per ur_w * nb_ic_blocking compute loops. Number of required registers + is num_regs = ur_w * nb_ic_blocking + ur_w / stride_w <= max_regs. + ur_w must be divisible by stride_w */ + if (jcp.stride_w + 1 > max_regs) /* Minimal possible registers + distribution exceeds max_regs */ + return status::unimplemented; + + int best_nfmas = 0; + for (int b = 1; b <= 4; b++) + { + if (jcp.nb_ic % b != 0) + continue; + + for (int u = jcp.stride_w; + u * b + u / jcp.stride_w <= max_regs && u < jcp.iw + jcp.stride_w; + u += jcp.stride_w) + { + int ur_w = nstl::min(u, jcp.iw); + /* maximum 1 step with l_overflow so far */ + if (l_overflow * jcp.stride_w > ur_w && ur_w != jcp.iw) + continue; + int nfmas = utils::div_up(ur_w, jcp.stride_w) * b; + if (nfmas > best_nfmas + || (nfmas == best_nfmas && jcp.ur_w < ur_w)) { + jcp.ur_w = ur_w; + jcp.nb_ic_blocking = b; + best_nfmas = nfmas; + } + } + } + if (best_nfmas == 0) /* can't find appropriate blocking */ + return status::unimplemented; + + jcp.ur_w_tail = jcp.iw % jcp.ur_w; + + int r_overflow_no_tail = nstl::max(0, (jcp.kw - 1 - jcp.ur_w_tail + - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail) / jcp.stride_w); + /* maximum 1 ur_w block with r_overflow so far */ + if (r_overflow_no_tail * jcp.stride_w > jcp.ur_w) + return status::unimplemented; + + if ((jcp.iw > jcp.ur_w) && (jcp.ur_w % jcp.stride_w != 0)) + return status::unimplemented; + + return status::success; +} + +void jit_avx2_conv_bwd_data_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + UNUSED(scratchpad); + UNUSED(jcp); +} + +void jit_avx2_conv_bwd_weights_kernel_f32::generate() { + this->preamble(); + + mov(reg_input, ptr[this->param1 + GET_OFF(src)]); + mov(reg_output, ptr[this->param1 + GET_OFF(dst)]); + mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]); + compute_oh_loop_common(); + this->postamble(); +} + +status_t jit_avx2_conv_bwd_weights_kernel_f32::init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &diff_weights_d, + const memory_desc_wrapper &diff_dst_d) { + if (!mayiuse(avx2)) return status::unimplemented; + + const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1; + int ndims = src_d.ndims(); + jcp.ndims = ndims; + + jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + jcp.id = (ndims == 5) ? src_d.dims()[2] : 1; + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2]; + jcp.iw = src_d.dims()[ndims-1]; + jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1; + jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2]; + jcp.ow = diff_dst_d.dims()[ndims-1]; + + jcp.kd = (ndims == 5) ? diff_weights_d.dims()[with_groups + 2] : 1; + jcp.kh = (ndims == 3) ? 1 : diff_weights_d.dims()[with_groups + ndims-2]; + jcp.kw = diff_weights_d.dims()[with_groups + ndims-1]; + + jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0; + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4]; + jcp.l_pad = cd.padding[0][ndims-3]; + + jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1; + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4]; + jcp.stride_w = cd.strides[ndims-3]; + + jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0; + jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4]; + jcp.dilate_w = cd.dilates[ndims-3]; + + if (ndims == 3) { + jcp.src_tag = src_d.matches_one_of_tag(ncw, nwc, nCw8c); + jcp.wei_tag = diff_weights_d.matches_one_of_tag( + Owi8o, gOwi8o, OIw8i8o, gOIw8i8o); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCw8c); + } else if (ndims == 4) { + jcp.src_tag = src_d.matches_one_of_tag(nchw, nhwc, nChw8c); + jcp.wei_tag = diff_weights_d.matches_one_of_tag( + Ohwi8o, gOhwi8o, OIhw8i8o, gOIhw8i8o); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(nChw8c); + } else if (ndims == 5) { + jcp.src_tag = src_d.matches_one_of_tag(ncdhw, ndhwc, nCdhw8c); + jcp.wei_tag = diff_weights_d.matches_one_of_tag( + Odhwi8o, gOdhwi8o, OIdhw8i8o, gOIdhw8i8o); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCdhw8c); + } + jcp.with_bias = cd.diff_bias_desc.format_kind != format_kind::undef; + + const bool flat = jcp.ic == 3; + const bool mimo = !flat; + + const int simd_w = 8; + + jcp.b_pad = nstl::max( + 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad); + jcp.r_pad = nstl::max( + 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad); + + int back_pad = nstl::max(0, (jcp.od - 1) * jcp.stride_d + jcp.kd - jcp.id + - jcp.f_pad); + if (ndims == 5) + if (jcp.f_pad != 0 || back_pad != 0) + return status::unimplemented; + + const int max_h_pad = ((jcp.kh - 1) * (jcp.dilate_h + 1) + 1); + const int max_w_pad = ((jcp.kw - 1) * (jcp.dilate_w + 1) + 1); + const bool boundaries_ok = true + && jcp.t_pad < max_h_pad && jcp.b_pad < max_h_pad + && jcp.l_pad < max_w_pad && jcp.r_pad < max_w_pad; + if (!boundaries_ok) + return status::unimplemented; + + bool ok_to_pad_channels = true + && jcp.ngroups == 1; + + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + if (mimo) + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + bool args_ok = true + && IMPLICATION(flat, true + && one_of(jcp.src_tag, ncw, nwc, nchw, nhwc, ncdhw, ndhwc) + && one_of(jcp.wei_tag, Owi8o, gOwi8o, Ohwi8o, gOhwi8o, Odhwi8o, + gOdhwi8o)) + && IMPLICATION(mimo, true + && one_of(jcp.src_tag, nCw8c, nChw8c, nCdhw8c) + && one_of(jcp.wei_tag, OIw8i8o, gOIw8i8o, OIhw8i8o, gOIhw8i8o, + OIdhw8i8o, gOIdhw8i8o)) + && one_of(jcp.dst_tag, nCw8c, nChw8c, nCdhw8c) + && IMPLICATION(mimo, jcp.ic % simd_w == 0) + && jcp.oc % simd_w == 0 + && jcp.kw < 14 + && jcp.kh <= jcp.t_pad + jcp.ih /* [bwd_w:r1] */ + && jcp.kh <= jcp.ih /* [bwd_w:r2] */ + && jcp.kd <= jcp.f_pad + jcp.id + && jcp.kd <= jcp.id + && jcp.t_pad < jcp.kh /* XXX: must fix the kernel! */ + && jcp.dilate_d == 0 + && jcp.dilate_h == 0 + && jcp.dilate_w == 0; + if (!args_ok) return status::unimplemented; + + jcp.ic_block = (jcp.ic % simd_w != 0) ? jcp.ic : simd_w; + jcp.nb_ic = jcp.ic / jcp.ic_block; + + jcp.oc_block = simd_w; + jcp.nb_oc = jcp.oc / jcp.oc_block; + jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1; + + return status::success; +} + +void jit_avx2_conv_bwd_weights_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + if (jcp.with_bias && jcp.oc != jcp.oc_without_padding) + scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc); +} + +inline void jit_avx2_conv_bwd_weights_kernel_f32::od_step_comeback_pointers() +{ + Label kd_comeback_loop; + mov(kj, jcp.kd); //FIXME (Anton): this works only if f_pad = back_pad = 0 + L(kd_comeback_loop); { + const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? 1 : jcp.ic_block; + sub(aux_reg_input, sizeof(float) * jcp.iw * jcp.ih * inp_mult); + sub(aux_reg_kernel, sizeof(float) * jcp.kw * jcp.kh * jcp.ic_block + * jcp.oc_block); + dec(kj); + cmp(kj, 0); + jg(kd_comeback_loop, T_NEAR); + } +} + +inline void jit_avx2_conv_bwd_weights_kernel_f32::oh_step_comeback_pointers() +{ + mov(kj, reg_kh); + Label kh_comeback_loop; + L(kh_comeback_loop); { + const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? 1 : jcp.ic_block; + sub(reg_input, sizeof(float) * jcp.iw * inp_mult); + sub(reg_kernel, sizeof(float) * jcp.kw * jcp.ic_block * jcp.oc_block); + dec(kj); + cmp(kj, 0); + jg(kh_comeback_loop, T_NEAR); + } +} + +inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_ic_block_step( + int ur_w, int pad_l, int pad_r, int ic_block_step, int input_offset, + int kernel_offset, int output_offset) +{ + const int kw = jcp.kw; + const int ic_block = jcp.ic_block; + const int oc_block = jcp.oc_block; + for (int i_kw = 0; i_kw < kw; i_kw++) + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) { + size_t off + = sizeof(float) * (i_kw * ic_block + i_ic) * jcp.oc_block + + kernel_offset; + vmovups(Ymm(i_kw * ic_block_step + i_ic), yword[reg_kernel + off]); + } + + for (int i_ur = 0; i_ur < ur_w; i_ur++) { + vmovups(Ymm(kw * ic_block_step + 0), + yword[reg_output + + sizeof(float) * i_ur * oc_block + output_offset]); + + for (int i_kw = 0; i_kw < kw; i_kw++) { + int i_iw = i_ur * jcp.stride_w + i_kw; + if (i_iw - pad_l < 0 + || i_iw > (ur_w - 1) * jcp.stride_w + kw - 1 - pad_r) + continue; + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) { + size_t i_off = (size_t)input_offset + sizeof(float)*( + one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? (i_iw - pad_l) + i_ic + * ((size_t)jcp.id * jcp.ih * jcp.iw) + : (i_iw - pad_l) * ic_block + i_ic); + vbroadcastss(Ymm(kw * ic_block_step + 1), + make_safe_addr(reg_input, i_off, reg_long_offt)); + vfmadd231ps(Ymm(i_kw * ic_block_step + i_ic), + Ymm(kw * ic_block_step + 0), + Ymm(kw * ic_block_step + 1)); + } + } + } + + for (int i_kw = 0; i_kw < kw; i_kw++) + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) { + size_t off + = sizeof(float) * (i_kw * ic_block + i_ic) * jcp.oc_block + + kernel_offset; + vmovups(yword[reg_kernel + off], + Ymm(i_kw * ic_block_step + i_ic)); + } +} + +inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_step_disp() +{ + int ic_block_step; + if (one_of(jcp.src_tag, ncw, nchw, ncdhw)) { + ic_block_step = jcp.kw >= 5 ? 1 : jcp.ic_block; + } else { + ic_block_step = jcp.kw > 7 ? 1 + : jcp.kw > 3 ? 2 + : jcp.kw > 1 ? 4 : 8; + } + + const int max_ur_w = jcp.ow > 56 ? 14 : 28; + + if (jcp.ow <= max_ur_w) + compute_oh_step_unroll_ow(ic_block_step, max_ur_w); + else + compute_oh_step_common(ic_block_step, max_ur_w); + + if (jcp.ndims == 5) { + od_step_comeback_pointers(); + mov(reg_input, aux_reg_input); + mov(reg_kernel, aux_reg_kernel); + } else { + oh_step_comeback_pointers(); + } +} + +inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_step_unroll_ow( + int ic_block_step, int max_ur_w) +{ + UNUSED(max_ur_w); + + const int ic_block = jcp.ic_block; + const int oc_block = jcp.oc_block; + int inp_mul = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : jcp.ic_block; + Label kd_loop; + + const int r_pad + = nstl::max(0, + (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad); + + if (jcp.ndims == 5) { + mov(aux_reg_input, reg_input); + mov(aux_reg_kernel, reg_kernel); + mov(ki, jcp.kd); + L(kd_loop); + mov(reg_input, aux_reg_input); + mov(reg_kernel, aux_reg_kernel); + } + + mov(kj, reg_kh); + Label kh_loop; + L(kh_loop); { + xor_(b_ic, b_ic); + Label ic_block_loop; + L(ic_block_loop); { + compute_ic_block_step(jcp.ow, jcp.l_pad, r_pad, ic_block_step, 0, + 0, 0); + size_t inp_icblk_stride = sizeof(float) * ic_block_step + * (one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? jcp.id*jcp.ih*jcp.iw : 1); + safe_add(reg_input, inp_icblk_stride, reg_long_offt); + add(reg_kernel, sizeof(float) * ic_block_step * oc_block); + add(b_ic, ic_block_step); + cmp(b_ic, ic_block); + jl(ic_block_loop, T_NEAR); + } + if(one_of(jcp.src_tag, ncw, nchw, ncdhw)) { + size_t offt = sizeof(float) * jcp.id * jcp.ih * jcp.iw * ic_block; + safe_sub(reg_input, offt, reg_long_offt); + add(reg_input, sizeof(float) * jcp.iw); + } else { + add(reg_input, sizeof(float) * (jcp.iw - 1) * ic_block); + } + add(reg_kernel, sizeof(float) * (jcp.kw - 1) * ic_block * oc_block); + dec(kj); + cmp(kj, 0); + jg(kh_loop, T_NEAR); + } + + if (jcp.ndims == 5) { + add(aux_reg_input, sizeof(float) * jcp.ih * jcp.iw * inp_mul); + add(aux_reg_kernel, sizeof(float) * jcp.kh * jcp.kw * ic_block + * oc_block); + dec(ki); + cmp(ki, 0); + jg(kd_loop, T_NEAR); + } + +} + +inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_step_common( + int ic_block_step, int max_ur_w) +{ + const int ic_block = jcp.ic_block; + const int oc_block = jcp.oc_block; + const int stride_w = jcp.stride_w; + int inp_mul = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : jcp.ic_block; + Label kd_loop; + + const int r_pad = jcp.r_pad; + + int ur_w = nstl::min(jcp.ow, max_ur_w); + int ur_w_trips = jcp.ow / ur_w; + int ur_w_tail = jcp.ow % ur_w; + if ((ur_w_tail == 0 && r_pad != 0) || r_pad >= ur_w_tail) { + if (ur_w_trips > 1) { + ur_w_tail += ur_w; + ur_w_trips--; + } else { + ur_w_tail += (ur_w - ur_w / 2); + ur_w = ur_w / 2; + } + } + const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : ic_block; + + int input_comeback = (ur_w_trips * ur_w * stride_w - jcp.l_pad) * inp_mult; + int output_comeback = ur_w_trips * ur_w * oc_block; + + if (jcp.ndims == 5) { + mov(aux_reg_input, reg_input); + mov(aux_reg_kernel, reg_kernel); + mov(ki, jcp.kd); + L(kd_loop); + mov(reg_input, aux_reg_input); + mov(reg_kernel, aux_reg_kernel); + } + + mov(kj, reg_kh); + Label kh_loop; + L(kh_loop); { + xor_(b_ic, b_ic); + Label ic_block_loop; + L(ic_block_loop); { + if (jcp.l_pad != 0) { + ur_w_trips--; + compute_ic_block_step(ur_w, + jcp.l_pad, 0, ic_block_step, 0, 0, 0); + add(reg_input, sizeof(float) + * (ur_w * stride_w - jcp.l_pad) * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_block); + } + + if (ur_w_trips > 0) { + xor_(reg_ur_w_trips, reg_ur_w_trips); + Label ow_block_loop; + L(ow_block_loop); { + compute_ic_block_step(ur_w, 0, 0, ic_block_step, 0, 0, 0); + add(reg_input, sizeof(float) * ur_w * stride_w * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_block); + + inc(reg_ur_w_trips); + cmp(reg_ur_w_trips, ur_w_trips); + jl(ow_block_loop, T_NEAR); + } + } + + if (ur_w_tail > 0) + compute_ic_block_step(ur_w_tail, + 0, r_pad, ic_block_step, 0, 0, 0); + + sub(reg_input, sizeof(float) * input_comeback); + sub(reg_output, sizeof(float) * output_comeback); + + size_t inp_icblk_stride = sizeof(float) * ic_block_step + * (one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? jcp.id*jcp.ih*jcp.iw : 1); + safe_add(reg_input, inp_icblk_stride, reg_long_offt); + add(reg_kernel, sizeof(float) * ic_block_step * oc_block); + + add(b_ic, ic_block_step); + cmp(b_ic, jcp.ic_block); + jl(ic_block_loop, T_NEAR); + } + if (one_of(jcp.src_tag, ncw, nchw, ncdhw)) { + size_t offt = sizeof(float) * jcp.id * jcp.ih * jcp.iw * ic_block; + safe_sub(reg_input, offt, reg_long_offt); + add(reg_input, sizeof(float) * jcp.iw); + } else { + add(reg_input, sizeof(float) * (jcp.iw - 1) * ic_block); + } + add(reg_kernel, sizeof(float) * (jcp.kw - 1) * ic_block * oc_block); + dec(kj); + cmp(kj, 0); + jg(kh_loop, T_NEAR); + } + + if (jcp.ndims == 5) { + add(aux_reg_input, sizeof(float) * jcp.ih * jcp.iw * inp_mul); + add(aux_reg_kernel, sizeof(float) * jcp.kh * jcp.kw * ic_block + * oc_block); + dec(ki); + cmp(ki, 0); + jg(kd_loop, T_NEAR); + } + +} + +inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_loop_common() +{ + const int icoc_block = jcp.ic_block * jcp.oc_block; + const int t_pad = jcp.t_pad; + const int stride_h = jcp.stride_h; + const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) + ? 1 : jcp.ic_block; + int b_pad = jcp.b_pad; + + Label oh_tpad_loop, oh_loop, oh_loop_end; + + mov(reg_kh, jcp.kh); + xor_(reg_ih_count, reg_ih_count); + xor_(reg_oj, reg_oj); + if (t_pad > 0) { + assert(jcp.kh <= t_pad + jcp.ih); /* [bwd_w:r1] */ + mov(reg_kh, jcp.kh <= t_pad + jcp.ih ? jcp.kh - t_pad : jcp.ih); + add(reg_kernel, sizeof(float) * t_pad * jcp.kw * icoc_block); + + L(oh_tpad_loop); { + compute_oh_step_disp(); + add(reg_output, sizeof(float) * jcp.ow * jcp.oc_block); + sub(reg_kernel, sizeof(float) * stride_h * jcp.kw * icoc_block); + + inc(reg_oj); + add(reg_ih_count, stride_h); + add(reg_kh, stride_h); + + /* the overlap between input and kernel may not reach kernel size. + * so far we do not support that (until we put constant here) */ + const int final_inp_ker_overlap = jcp.kh; /* [bwd_w:r2] */ + cmp(reg_kh, final_inp_ker_overlap); + jl(oh_tpad_loop, T_NEAR); + } + + if (t_pad % stride_h != 0) { + int inp_corr = stride_h - t_pad % stride_h; + add(reg_kernel, sizeof(float) * inp_corr * jcp.kw * icoc_block); + add(reg_input, sizeof(float) * inp_corr * jcp.iw * inp_mult); + } + } + cmp(reg_ih_count, jcp.ih + t_pad - jcp.kh + 1); + jge(oh_loop_end, T_NEAR); + cmp(reg_oj, jcp.oh); + jge(oh_loop, T_NEAR); + + mov(reg_kh, jcp.kh); + L(oh_loop); { + compute_oh_step_disp(); + add(reg_input, sizeof(float) * stride_h * jcp.iw * inp_mult); + add(reg_output, sizeof(float) * jcp.ow * jcp.oc_block); + + inc(reg_oj); + add(reg_ih_count, stride_h); + + cmp(reg_ih_count, jcp.ih + t_pad - jcp.kh + 1); + jge(oh_loop_end, T_NEAR); + + cmp(reg_oj, jcp.oh); + jl(oh_loop, T_NEAR); + } + L(oh_loop_end); + if (b_pad > 0) { + Label oh_bpad_loop, oh_bpad_loop_end; + cmp(reg_oj, jcp.oh); + jge(oh_bpad_loop_end, T_NEAR); + + mov(reg_kh, jcp.ih + t_pad); + sub(reg_kh, reg_ih_count); + L(oh_bpad_loop); { + compute_oh_step_disp(); + add(reg_input, sizeof(float) * stride_h * jcp.iw * inp_mult); + add(reg_output, sizeof(float) * jcp.ow * jcp.oc_block); + + sub(reg_kh, stride_h); + cmp(reg_kh, 0); + jle(oh_bpad_loop_end, T_NEAR); + + inc(reg_oj); + cmp(reg_oj, jcp.oh); + jl(oh_bpad_loop, T_NEAR); + } + L(oh_bpad_loop_end); + } +} + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp new file mode 100644 index 0000000000..412c50c9ee --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp @@ -0,0 +1,225 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX2_CONV_KERNEL_F32_HPP +#define JIT_AVX2_CONV_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "cpu_memory.hpp" +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx2_conv_fwd_kernel_f32: public jit_generator { + jit_avx2_conv_fwd_kernel_f32(jit_conv_conf_t ajcp, + const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32(this, + jcp.eltwise); + + this->generate(); + jit_ker = (void (*)(jit_conv_call_s *))this->getCode(); + } + + ~jit_avx2_conv_fwd_kernel_f32() { + delete eltwise_injector_; + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_conv_fwd_kernel_f32) + + static bool post_ops_ok(jit_conv_conf_t &jcp, + const primitive_attr_t &attr); + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr); + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + jit_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker)(jit_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + reg64_t reg_input = rax; + reg64_t aux_reg_input = r8; + reg64_t reg_kernel = rdx; + reg64_t aux_reg_kernel = r9; + reg64_t reg_output = rsi; + reg64_t reg_bias = rbx; + + reg64_t aux_reg_inp_d = r11; + reg64_t aux_reg_ker_d = abi_not_param1; + + reg64_t reg_ki = rsi; + reg64_t kj = r10; + reg64_t oi_iter = r11; + reg64_t ki_iter = r12; + reg64_t reg_kh = abi_not_param1; + reg64_t reg_oc_blocks = r14; + reg64_t imm_addr64 = r15; + reg64_t reg_long_offt = r15; + Xbyak::Reg32 reg_ci_flag = r13d; + + Xbyak::Ymm ytmp = Xbyak::Ymm(14); + + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + inline void oh_step_unroll_kw(int ur_w, int pad_l, int pad_r, + int oc_blocks); + inline void oh_step_nopad(int ur_w, int pad_l, int pad_r, + char pad_label, int oc_blocks, char oc_blocks_label); + inline void width_blk_step(int ur_w, int pad_l, int pad_r, + char pad_label, int oc_blocks, char oc_blocks_label); + inline void solve_common(int oc_blocks, char oc_blocks_label); + + void generate(); +}; + +struct jit_avx2_conv_bwd_data_kernel_f32: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_conv_bwd_data_kernel_f32) + + jit_avx2_conv_bwd_data_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp) + { + this->generate(); + jit_ker = (void (*)(jit_conv_call_s *))this->getCode(); + } + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d); + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + jit_conv_conf_t jcp; + void (*jit_ker)(jit_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + + reg64_t reg_ddst = rax; + reg64_t aux_reg_ddst = r8; + reg64_t reg_kernel = rdx; + reg64_t aux_reg_kernel = r10; + reg64_t reg_dsrc = rsi; + reg64_t aux_reg_ddst_oc_loop = rbx; // used in ndims < 5 case only + reg64_t aux_reg_kernel_oc_loop = abi_not_param1; /* used in ndims < 5 + case only */ + + reg64_t aux_reg_dst_d = r12; // used in ndims == 5 case only + reg64_t aux_reg_ker_d = r14; // used in ndims == 5 case only + + reg64_t reg_ki = abi_not_param1; // used in ndims == 5 case only + reg64_t kj = r11; + reg64_t oi_iter = r12; + reg64_t reg_kh = r14; + reg64_t reg_channel = r13; // used in ndims < 5 case only + reg64_t reg_channel_work = r9; // used in ndims < 5 case only + reg64_t reg_long_offt = r15; + + inline void compute_loop(int ur_w, int l_overflow, int r_overflow); + + void generate(); + + inline int get_iw_start(int ki, int l_overflow) + { + int res = (jcp.iw - 1 + jcp.r_pad) % jcp.stride_w + + l_overflow * jcp.stride_w + - (jcp.kw - 1 - ki) * (jcp.dilate_w + 1); + while (res < 0) + res += jcp.stride_w; + + return res; + } + + inline int get_iw_end(int ur_w, int ki, int r_overflow) + { + if (utils::one_of(ur_w, jcp.iw, jcp.ur_w_tail)) + ur_w += nstl::min(0, jcp.r_pad); // remove negative padding + int res = (ur_w - 1 + jcp.l_pad) % jcp.stride_w + + r_overflow * jcp.stride_w - ki * (jcp.dilate_w + 1); + while (res < 0) + res += jcp.stride_w; + + return ur_w - res; + } +}; + +struct jit_avx2_conv_bwd_weights_kernel_f32: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_conv_bwd_weights_kernel_f32) + + jit_avx2_conv_bwd_weights_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp) + { + this->generate(); + jit_ker = (void (*)(jit_conv_call_s *))this->getCode(); + } + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &diff_weights_d, + const memory_desc_wrapper &diff_dst_d); + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + jit_conv_conf_t jcp; + void (*jit_ker)(jit_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + reg64_t reg_input = rax; + reg64_t reg_kernel = rdx; + reg64_t reg_output = rsi; + reg64_t b_ic = abi_not_param1; + reg64_t kj = r8; + reg64_t reg_kh = r9; + reg64_t reg_ur_w_trips = r10; + reg64_t reg_tmp = r11; + reg64_t reg_oj = r15; + reg64_t reg_ih_count = rbx; + reg64_t aux_reg_input = r12; + reg64_t aux_reg_kernel = r13; + reg64_t ki = r14; + reg64_t reg_long_offt = r11; + + inline void od_step_comeback_pointers(); + inline void oh_step_comeback_pointers(); + inline void compute_ic_block_step(int ur_w, int pad_l, int pad_r, + int ic_block_step, int input_offset, int kernel_offset, + int output_offset); + inline void compute_oh_step_disp(); + inline void compute_oh_step_unroll_ow(int ic_block_step, int max_ur_w); + inline void compute_oh_step_common(int ic_block_step, int max_ur_w); + inline void compute_oh_loop_common(); + + void generate(); +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp new file mode 100644 index 0000000000..13f61e84fe --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp @@ -0,0 +1,410 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx2_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +#define src_blk_off(f, n, c, d, h, w) \ + (pd()->ndims() == 3) \ + ? (f).blk_off(n, c, w) \ + : (pd()->ndims() == 4) \ + ? (f).blk_off(n, c, h, w) \ + : (f).blk_off(n, c, d, h, w) + +#define wht_blk_off_(f, g, ...) \ + pd()->with_groups() ? (f).blk_off(g, __VA_ARGS__) : (f).blk_off(__VA_ARGS__) +#define wht_blk_off(f, g, oc, ic, kd, kh, kw) \ + (pd()->ndims() == 3) \ + ? wht_blk_off_(f, g, oc, ic, kw) \ + : (pd()->ndims() == 4) \ + ? wht_blk_off_(f, g, oc, ic, kh, kw) \ + : wht_blk_off_(f, g, oc, ic, kd, kh, kw) + +void jit_avx2_convolution_fwd_t::execute_forward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const auto &jcp = kernel_->jcp; + + int ocb_work = div_up(jcp.nb_oc, jcp.nb_oc_blocking); + const size_t work_amount = jcp.mb * jcp.ngroups * ocb_work * jcp.od + * jcp.oh; + + auto ker = [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + int icbb = 0; + while (icbb < jcp.nb_ic) { + int icb_step = jcp.nb_ic_blocking; + int icb_step_rem = jcp.nb_ic - icbb; + if (icb_step_rem < jcp.nb_ic_blocking_max) + icb_step = icb_step_rem; + + size_t n{0}, g{0}, ocbb{0}, oh{0}, od{0}; + nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work, + od, jcp.od, oh, jcp.oh); + for (size_t iwork = start; iwork < end; ++iwork) { + int ocb = ocbb * jcp.nb_oc_blocking; + int ocb_num = jcp.nb_oc_blocking; + + for (int icb = icbb; icb < icbb + icb_step; ++icb) { + auto par_conv = jit_conv_call_s(); + + const int ij = oh * jcp.stride_h; + const int i_t_overflow = nstl::max(0, jcp.t_pad - ij); + const int i_b_overflow = nstl::max(jcp.ih, ij + + (jcp.kh-1) * (jcp.dilate_h+1) - jcp.t_pad+1) - jcp.ih; + + const int dj = od * jcp.stride_d; + const int d_t_overflow = nstl::max(0, jcp.f_pad - dj); + const int d_b_overflow = nstl::max(jcp.id, dj + + (jcp.kd-1) * (jcp.dilate_d+1) - jcp.f_pad+1) - jcp.id; + + const size_t _oc = g * jcp.nb_oc + ocb; + const size_t _ic = g * jcp.nb_ic * jcp.nonblk_group_off + icb; + + const int ih = nstl::max(ij - jcp.t_pad + + div_up(i_t_overflow, + (jcp.dilate_h+1)) * (jcp.dilate_h + 1), 0); + + const int id = nstl::max(dj - jcp.f_pad + + div_up(d_t_overflow, + (jcp.dilate_d+1)) * (jcp.dilate_d + 1), 0); + + par_conv.src = &src[src_blk_off(src_d, n, + jcp.ic == 3 ? 0 : _ic, id, ih, 0)]; + + par_conv.dst = &dst[src_blk_off(dst_d, n, _oc, od, oh, 0)]; + + const int wh = div_up(i_t_overflow, (jcp.dilate_h + 1)); + const int wd = div_up(d_t_overflow, (jcp.dilate_d + 1)); + par_conv.filt = &weights[wht_blk_off(weights_d, g, ocb, + jcp.ic == 3 ? 0 : icb, wd, wh, 0)]; + + if (icb == 0) { + if (bias) + par_conv.bias = + &bias[bias_d.blk_off(_oc * jcp.oc_block)]; + par_conv.flags |= FLAG_IC_FIRST; + } + + if (jcp.with_eltwise && icb + 1 == jcp.nb_ic) { + par_conv.flags |= FLAG_IC_LAST; + } + + par_conv.oc_blocks = + nstl::min(ocb + ocb_num, jcp.nb_oc) - ocb; + + par_conv.kw_padding = 0; + const int kh_padding = jcp.kh + - div_up(i_t_overflow, (jcp.dilate_h + 1)) + - div_up(i_b_overflow, (jcp.dilate_h + 1)); + par_conv.kh_padding = nstl::max(0, kh_padding); + + const int kd_padding = jcp.kd + - div_up(d_t_overflow, (jcp.dilate_d + 1)) + - div_up(d_b_overflow, (jcp.dilate_d + 1)); + par_conv.kd_padding = nstl::max(0, kd_padding); + + kernel_->jit_ker(&par_conv); + } + nd_iterator_step(n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work, + od, jcp.od, oh, jcp.oh); + } + icbb += icb_step; + } + }; + + if (pd()->wants_padded_bias()) { + auto padded_bias = scratchpad(ctx).get(key_conv_padded_bias); + utils::array_copy(padded_bias, bias, jcp.oc_without_padding); + utils::array_set(padded_bias + jcp.oc_without_padding, 0.f, + jcp.oc - jcp.oc_without_padding); + bias = padded_bias; + } + + parallel(0, ker); + + if (pd()->wants_zero_pad_dst()) + ctx.memory(MKLDNN_ARG_DST)->zero_pad(); +} + +void jit_avx2_convolution_bwd_data_t::execute_backward_data( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + + int icb_work = jcp.nb_ic / jcp.nb_ic_blocking; + int ih_block_size = jcp.ih; + int num_ih_blocks = utils::div_up(jcp.ih, ih_block_size); + size_t work_amount = jcp.mb * jcp.ngroups * icb_work * num_ih_blocks; + if (work_amount < (size_t)2 * mkldnn_get_max_threads()) { + ih_block_size = 1; + num_ih_blocks = utils::div_up(jcp.ih, ih_block_size); + work_amount *= num_ih_blocks; + } + + auto ker = [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + size_t n{0}, g{0}, icbb{0}, ihb{0}; + nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, icbb, icb_work, + ihb, num_ih_blocks); + for (size_t iwork = start; iwork < end; ++iwork) { + for (int oc = 0; oc < jcp.nb_oc; oc += jcp.nb_oc_blocking) + for (int id = 0; id < jcp.id; ++id) { + auto par_conv = jit_conv_call_s(); + + const int idp = jcp.id + 2 * jcp.f_pad; + const int d_t_overflow = nstl::max(0, + jcp.kd - 1 - id - jcp.f_pad); + const int back_pad = idp - jcp.id - jcp.f_pad; + const int d_b_overflow = nstl::max(0, + jcp.kd - 1 - (jcp.id - 1 - id) - back_pad); + const int od = id + jcp.f_pad - d_b_overflow; + + int ih_start = ihb * ih_block_size; + int ih_end = nstl::min(jcp.ih, ih_start + ih_block_size); + for (int ih = ih_start; ih < ih_end; ++ih) { + + const int i_t_overflow = nstl::max(0, (jcp.kh - 1 + - ih - jcp.t_pad) / jcp.stride_h); + const int i_b_overflow = nstl::max(0, (jcp.kh - jcp.ih + + ih - jcp.b_pad) / jcp.stride_h); + int overflow_kh_hi = jcp.kh - 1 - abs((jcp.ih - 1 + + jcp.b_pad - ih) % jcp.stride_h); + int overflow_kh_lo = (ih + jcp.t_pad) % jcp.stride_h; + + par_conv.kd_padding = jcp.kd - d_t_overflow - d_b_overflow; + par_conv.kh_padding = (overflow_kh_hi - overflow_kh_lo) + / jcp.stride_h + 1 - i_t_overflow - i_b_overflow; + par_conv.kw_padding = 0; + + const int k_lo = overflow_kh_lo + + i_b_overflow * jcp.stride_h; + const int oh = (ih + jcp.t_pad - k_lo) / jcp.stride_h; + + par_conv.src = &diff_src[src_blk_off(diff_src_d, n, + /*jcp.ic == 3 ? 0 :*/ + g * jcp.nb_ic + jcp.nb_ic_blocking * icbb, id, ih, 0)]; + par_conv.dst = &diff_dst[src_blk_off(diff_dst_d, + n, g * jcp.nb_oc + oc, od, oh, 0)]; + par_conv.filt = &weights[wht_blk_off(weights_d, g, oc, + jcp.ic == 3 ? 0 : jcp.nb_ic_blocking * icbb, + d_b_overflow, k_lo, 0)]; + + par_conv.src_prf = nullptr; + par_conv.dst_prf = nullptr; + par_conv.filt_prf = nullptr; + par_conv.channel = oc; + par_conv.ch_blocks = nstl::min(jcp.nb_oc - oc, + jcp.nb_oc_blocking); + + kernel_->jit_ker(&par_conv); + } + } + nd_iterator_step(n, jcp.mb, g, jcp.ngroups, icbb, icb_work, ihb, + num_ih_blocks); + } + }; + + parallel(0, ker); +} + +void jit_avx2_convolution_bwd_weights_t::execute_backward_weights( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias_in = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + auto scratchpad = this->scratchpad(ctx); + + data_t *diff_bias = pd()->wants_padded_bias() + ? scratchpad.get(key_conv_padded_bias) : diff_bias_in; + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + + const auto &jcp = kernel_->jcp; + + auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad, + prefix_reducer_bia); + auto rb = this->reducer_bias_; + rb->init(reducer_bia_scratchpad); + + auto reducer_wei_scratchpad = memory_tracking::grantor_t(scratchpad, + prefix_reducer_wei); + auto rw = this->reducer_weights_; + rw->init(reducer_wei_scratchpad); + + auto ker = [&](int ithr, int nthr) { + assert(nthr == rw->balancer().nthr_); + + const int w_job_start = rw->balancer().ithr_job_off(ithr); + const int w_njobs = rw->balancer().ithr_njobs(ithr); + + if (w_njobs == 0) return; + + /* reduction dimension */ + int img_od_start{0}, img_od_end{0}, img{0}, od_s{0}; + balance211(jcp.mb * jcp.od, rw->balancer().nthr_per_group_, + rw->balancer().id_in_group(ithr), img_od_start, img_od_end); + + int img_start = img_od_start, img_end = img_od_end; + nd_iterator_init(img_start, img, jcp.mb, od_s, jcp.od); + const int img_first = img; + + /* jobs */ + int g_start{0}, ocb_start{0}, icb_start{0}; + nd_iterator_init(w_job_start, g_start, jcp.ngroups, ocb_start, + jcp.nb_oc, icb_start, jcp.nb_ic); + + while (img_start < img_end) { + int g = g_start, ocb = ocb_start, icb = icb_start; + + const int work_rem = img_end - img_start; + const int od_e = od_s + work_rem > jcp.od ? jcp.od : od_s + work_rem; + const int id_s = od_s * jcp.stride_d; + const int idp = jcp.id + jcp.f_pad + jcp.back_pad; + + if (id_s < idp - jcp.back_pad - jcp.kd + 1) + for (int w_job_loc = 0; w_job_loc < w_njobs; ++w_job_loc) { + const size_t _oc = g * jcp.nb_oc + ocb; + const size_t _ic = g * jcp.nb_ic + icb; + + /* TODO: put dw <-- 0 in kernel */ + if (img == img_first) + array_set(rw->get_local_ptr(ithr, diff_weights, + reducer_wei_scratchpad) + + w_job_loc * rw->balancer().job_size_, 0, + rw->balancer().job_size_); + + for (int od = od_s; od < od_e; ++od) { + const int id = od * jcp.stride_d; + if (id >= jcp.id - jcp.back_pad - jcp.kd + 1) break; + + auto par_conv = jit_conv_call_s(); + par_conv.src = &src[src_blk_off(src_d, img, _ic, id, 0, 0)]; + par_conv.dst = + &diff_dst[src_blk_off(diff_dst_d, img, _oc, od, 0, 0)]; + par_conv.filt = rw->get_local_ptr(ithr, diff_weights, + reducer_wei_scratchpad) + + w_job_loc * rw->balancer().job_size_; + + kernel_->jit_ker(&par_conv); + } + nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_oc, icb, + jcp.nb_ic); + } + nd_iterator_jump(img_start, img_end, img, jcp.mb, od_s, jcp.od); + } + rw->reduce(ithr, diff_weights, reducer_wei_scratchpad); + }; + + auto ker_bias = [&](int ithr, int nthr) { + assert(nthr == rb->balancer().nthr_); + + const int b_job_start = rb->balancer().ithr_job_off(ithr); + const int b_njobs = rb->balancer().ithr_njobs(ithr); + + if (b_njobs == 0) return; + + /* reduction dimension */ + int img_start{0}, img_end{0}; + balance211(jcp.mb, rb->balancer().nthr_per_group_, + rb->balancer().id_in_group(ithr), img_start, img_end); + + /* jobs */ + int g_start{0}, ocb_start{0}; + nd_iterator_init(b_job_start, g_start, jcp.ngroups, ocb_start, + jcp.nb_oc); + + for (int img = img_start; img < img_end; ++img) { + int g = g_start, ocb = ocb_start; + for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) { + const size_t _oc = g * jcp.nb_oc + ocb; + + const data_t *d_dst = &diff_dst[diff_dst_d.blk_off(img, _oc)]; + data_t *d_bias = rb->get_local_ptr(ithr, diff_bias, + reducer_bia_scratchpad) + + b_job_loc * rb->balancer().job_size_; + + if (img == img_start) + for (int o = 0; o < 8; ++o) + d_bias[o] = 0.; + + for (int dhw = 0; dhw < jcp.od * jcp.oh * jcp.ow; ++dhw) { + PRAGMA_OMP_SIMD() + for (int o = 0; o < 8; ++o) + d_bias[o] += d_dst[o]; + d_dst += 8; + } + + nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_oc); + } + } + rb->reduce(ithr, diff_bias, reducer_bia_scratchpad); + }; + + parallel(0, [&](const int ithr, const int nthr) { + ker(ithr, nthr); + if (pd()->with_bias()) + ker_bias(ithr, nthr); + }); + + /* TODO: put this in ker_bias */ + if (pd()->wants_padded_bias()) { + assert(jcp.ngroups == 1); + for (int oc = 0; oc < jcp.oc_without_padding; ++oc) + diff_bias_in[oc] = diff_bias[oc]; + } +} + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp new file mode 100644 index 0000000000..bb65bce79c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp @@ -0,0 +1,302 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX2_CONVOLUTION_HPP +#define CPU_JIT_AVX2_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_reducer.hpp" + +#include "jit_avx2_conv_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx2_convolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx2, ""), + jit_avx2_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx2_conv_fwd_kernel_f32::init_conf(jcp_, + *desc(), src_md(), weights_md(), dst_md(), *attr()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx2_conv_fwd_kernel_f32::init_scratchpad(scratchpad, jcp_); + + return status::success; + } + + jit_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + const bool flat = IC() < 8; + auto src_tag = flat + ? utils::pick(ndims() - 3, ncw, nchw, ncdhw) + : utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto dst_tag = + utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(2 * ndims() - 6 + flat, gOIw8i8o, gOwi8o, + gOIhw8i8o, gOhwi8o, gOIdhw8i8o, gOdhwi8o) + : utils::pick(2 * ndims() - 6 + flat, OIw8i8o, Owi8o, + OIhw8i8o, Ohwi8o, OIdhw8i8o, Odhwi8o); + + return set_default_formats_common(src_tag, wei_tag, dst_tag); + } + }; + + jit_avx2_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) + { kernel_ = new jit_avx2_conv_fwd_kernel_f32(pd()->jcp_, *pd()->attr()); } + ~jit_avx2_convolution_fwd_t() { delete kernel_; } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx2_conv_fwd_kernel_f32 *kernel_; +}; + +struct jit_avx2_convolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx2, ""), + jit_avx2_convolution_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::undef, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx2_conv_bwd_data_kernel_f32::init_conf( + jcp_, *desc(), *diff_src_md(), *weights_md(), + *diff_dst_md()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx2_conv_bwd_data_kernel_f32::init_scratchpad(scratchpad, + jcp_); + + return status::success; + } + + jit_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, gOIw8o8i, gOIhw8o8i, gOIdhw8o8i) + : utils::pick(ndims() - 3, OIw8o8i, OIhw8o8i, OIdhw8o8i); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + jit_avx2_convolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) + { kernel_ = new jit_avx2_conv_bwd_data_kernel_f32(pd()->jcp_); } + ~jit_avx2_convolution_bwd_data_t() { delete kernel_; } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx2_conv_bwd_data_kernel_f32 *kernel_; +}; + +struct jit_avx2_convolution_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx2, ""), + jit_avx2_convolution_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx2_conv_bwd_weights_kernel_f32::init_conf( + jcp_, *desc(), *src_md(), *diff_weights_md(), + *diff_dst_md()); + if (status != status::success) return status; + + init_balancers(); + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx2_conv_bwd_weights_kernel_f32::init_scratchpad(scratchpad, + jcp_); + + auto reducer_bia_scratchpad = memory_tracking::registrar_t( + scratchpad, memory_tracking::names::prefix_reducer_bia); + reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad); + + auto reducer_wei_scratchpad = memory_tracking::registrar_t( + scratchpad, memory_tracking::names::prefix_reducer_wei); + reducer_wei_conf_.init_scratchpad(reducer_wei_scratchpad); + + return status::success; + } + + jit_conv_conf_t jcp_; + cpu_reducer_t::conf_t reducer_bia_conf_; + cpu_reducer_t::conf_t reducer_wei_conf_; + + protected: + bool set_default_formats() { + using namespace format_tag; + const bool flat = IC() == 3; + + auto src_tag = flat + ? utils::pick(ndims() - 3, ncw, nchw, ncdhw) + : utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto dst_tag = + utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(2 * ndims() - 6 + flat, gOIw8i8o, gOwi8o, + gOIhw8i8o, gOhwi8o, gOIdhw8i8o, gOdhwi8o) + : utils::pick(2 * ndims() - 6 + flat, OIw8i8o, Owi8o, + OIhw8i8o, Ohwi8o, OIdhw8i8o, Odhwi8o); + + return set_default_formats_common(src_tag, wei_tag, dst_tag); + } + + private: + void init_balancers() { + const int max_threads = mkldnn_get_max_threads(); + const size_t max_buffer_size = 1<<21; /* just a heuristic */ + + if(with_bias()) { + reducer_bia_conf_.init(reduce_balancer_t(max_threads, + jcp_.oc_block, jcp_.ngroups * jcp_.nb_oc, jcp_.mb, + max_buffer_size)); + } + + reducer_wei_conf_.init(reduce_balancer_t(max_threads, + jcp_.kd * jcp_.kh * jcp_.kw + * jcp_.ic_block * jcp_.oc_block, + jcp_.ngroups * jcp_.nb_ic * jcp_.nb_oc, + jcp_.mb * jcp_.od, max_buffer_size)); + } + }; + + jit_avx2_convolution_bwd_weights_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr) + , reducer_weights_(nullptr) + , reducer_bias_(nullptr) + { + kernel_ = new jit_avx2_conv_bwd_weights_kernel_f32(pd()->jcp_); + reducer_bias_ = + new cpu_reducer_t(pd()->reducer_bia_conf_); + reducer_weights_ = + new cpu_reducer_t(pd()->reducer_wei_conf_); + } + + ~jit_avx2_convolution_bwd_weights_t() { + delete kernel_; + delete reducer_weights_; + delete reducer_bias_; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx2_conv_bwd_weights_kernel_f32 *kernel_; + cpu_reducer_t *reducer_weights_, *reducer_bias_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp new file mode 100644 index 0000000000..635b83b2bf --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp @@ -0,0 +1,1255 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_memory.hpp" +#include "cpu_barrier.hpp" + +#include "jit_uni_1x1_conv_utils.hpp" +#include "jit_avx512_common_1x1_conv_kernel.hpp" + +#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +void jit_avx512_common_1x1_conv_kernel::bcast_loop(int load_loop_blk) +{ + mov(aux1_reg_bcast_data, reg_bcast_data); + mov(aux_reg_bcast_data, reg_bcast_data); + + mov(aux_reg_output_data, reg_output_data); + mov(bcast_loop_iter, EVEX_compress_addr(rsp, bcast_loop_work_offt)); + + if (jcp.ver == ver_4fma) + { + Label bcast_loop; + Label bcast_loop_wraparound; + Label bcast_loop_out; + Label bcast_loop_ur_full; + + cmp(bcast_loop_iter, jcp.ur); + jle(bcast_loop_wraparound, T_NEAR); + + L(bcast_loop); { + assert(jcp.bcast_block % jcp.ur == 0); + int num_substeps = jcp.bcast_block / jcp.ur; + assert(num_substeps > 0 && num_substeps < 10); + for (int i = 0; i < num_substeps; i++) { + reduce_loop(load_loop_blk, jcp.ur, i, false); + if (i < num_substeps - 1) { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_substep); + } + else { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step + - (num_substeps - 1) * jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_step + - (num_substeps - 1) * jcp.bcast_loop_output_substep); + } + } + sub(bcast_loop_iter, jcp.bcast_block); + cmp(bcast_loop_iter, jcp.bcast_block); + jg(bcast_loop, T_NEAR); + } + + L(bcast_loop_wraparound); + if (jcp.ur_tail) { + je(bcast_loop_ur_full, T_NEAR); + reduce_loop(load_loop_blk, jcp.ur_tail, 0, true); + jmp(bcast_loop_out, T_NEAR); + } + L(bcast_loop_ur_full); + reduce_loop(load_loop_blk, jcp.ur, 0, true); + L(bcast_loop_out); + } + else + { + Label bcast_loop; + Label bcast_loop_tail; + + cmp(bcast_loop_iter, jcp.ur); + jl(bcast_loop_tail, T_NEAR); + + L(bcast_loop); { + assert(jcp.bcast_block % jcp.ur == 0); + int num_substeps = jcp.bcast_block / jcp.ur; + assert(num_substeps > 0 && num_substeps < 10); + for (int i = 0; i < num_substeps; i++) { + reduce_loop(load_loop_blk, jcp.ur, i, false); + if (i < num_substeps - 1) { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_substep); + } + else { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step + - (num_substeps - 1) * jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_step + - (num_substeps - 1) * jcp.bcast_loop_output_substep); + } + } + sub(bcast_loop_iter, jcp.bcast_block); + cmp(bcast_loop_iter, jcp.bcast_block); + jge(bcast_loop, T_NEAR); + } + + L(bcast_loop_tail); + if (jcp.ur_tail) { + Label bcast_loop_tail_out; + cmp(bcast_loop_iter, 0); + jz(bcast_loop_tail_out, T_NEAR); + reduce_loop(load_loop_blk, jcp.ur_tail, 0, true); + L(bcast_loop_tail_out); + } + } +} + +void jit_avx512_common_1x1_conv_kernel::reduce_loop(int load_loop_blk, + int ur, int substep, bool wraparound) +{ + auto vreg_load = [=](int i_load, int i_fma) { + return Zmm(utils::rnd_up(ur * load_loop_blk, jcp.fma_step) + + jcp.fma_step * i_load + i_fma); + }; + + auto vreg_accum = [=](int i_load, int i_ur) { + return Zmm(i_ur * load_loop_blk + i_load); + }; + + auto bias_ptr = [=](int i_load) { + return EVEX_compress_addr(reg_bias_data, + jcp.typesize_out * jcp.oc_block * i_load); + }; + + auto bcast_ptr = [=](int i_reduce, int i_ur, bool bcast) { + assert(i_ur < jcp.ur); + assert(i_reduce <= jcp.reduce_loop_unroll); + int offt; + if (one_of(jcp.prop_kind, forward_training, forward_inference, + backward_data)) { + assert(jcp.reduce_loop_unroll == jcp.reduce_block); + offt = (i_reduce == jcp.reduce_loop_unroll) + ? (jcp.bcast_dim + i_ur) * jcp.reduce_loop_unroll + : i_ur * jcp.reduce_loop_unroll + i_reduce; + } else { + if (jcp.transpose_src) { + const int reduce_group = i_reduce / 4; + const int reduce_shift = i_reduce % 4; + offt = 4 * (reduce_group * jcp.ic_block + i_ur) + reduce_shift; + } + else + offt = i_reduce * jcp.ic_block + i_ur; + } + return EVEX_compress_addr(aux_reg_bcast_data, jcp.typesize_in * offt, + bcast); + }; + + auto load_ptr = [=](int i_reduce, int i_load) { + int offt; + int u0 = i_reduce % jcp.reduce_loop_unroll; + int u1 = i_reduce / jcp.reduce_loop_unroll; + offt = (i_load * jcp.reduce_dim + u0) * jcp.load_block; + return EVEX_compress_addr(aux_reg_load_data, + u1 * jcp.reduce_loop_load_step + + jcp.typesize_in * offt); + }; + + auto output_ptr = [=](int i_load, int i_ur) { + if (one_of(jcp.prop_kind, forward_training, forward_inference, + backward_data)) + return EVEX_compress_addr(aux_reg_output_data, + (i_load * jcp.bcast_dim + i_ur) * jcp.load_block + * jcp.typesize_out); + else + return ptr[aux_reg_output_data + + (i_load + ? reg_output_stride * i_load + : 0) // TODO: Xbyak should allow 0 scale + + jcp.typesize_out * jcp.load_block * i_ur]; + }; + + auto init = [=]() { + Label init_done; + Label init_zero; + + if (jcp.with_sum) { + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + for (int i_ur = 0; i_ur < ur; ++i_ur) { + mic_prefetcht1(output_ptr(i_load, i_ur)); + } + } + } + + if (jcp.with_bias + && one_of(jcp.prop_kind, forward_training, forward_inference)) { + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jz(init_zero, T_NEAR); + + for (int i_load = 0; i_load < load_loop_blk; i_load++) + for (int i_ur = 0; i_ur < ur; ++i_ur) + vmovups(vreg_accum(i_load, i_ur), bias_ptr(i_load)); + jmp(init_done, T_NEAR); + } + + L(init_zero); + for (int i_load = 0; i_load < load_loop_blk; ++i_load) + for (int i_ur = 0; i_ur < ur; ++i_ur) { + auto r = vreg_accum(i_load, i_ur); + vpxord(r, r, r); + } + L(init_done); + }; + + auto store = [=]() { + Label store_noadd; + if (!jcp.with_sum) { + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jnz(store_noadd, T_NEAR); + } + + for (int i_ur = 0; i_ur < ur; ++i_ur) + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + auto r = vreg_accum(i_load, i_ur); + vaddps(r, r, output_ptr(i_load, i_ur)); + } + + L(store_noadd); + if (jcp.with_eltwise) { + Label store_noeltwise; + test(reg_reduce_pos_flag, FLAG_REDUCE_LAST); + jz(store_noeltwise, T_NEAR); + + eltwise_injector_->compute_vector_range(0, ur * load_loop_blk); + + L(store_noeltwise); + } + + auto store_output = [=](bool output_is_aligned) { + for (int i_ur = 0; i_ur < ur; ++i_ur) + for (int i_load = 0; i_load < load_loop_blk; ++i_load) + if (output_is_aligned && jcp.use_vmovntps) + vmovntps(output_ptr(i_load, i_ur), + vreg_accum(i_load, i_ur)); + else + vmovups(output_ptr(i_load, i_ur), + vreg_accum(i_load, i_ur)); + }; + + Label unaligned_store, end_store; + test(aux_reg_output_data, cpu_isa_traits::vlen - 1); + jnz(unaligned_store, T_NEAR); + store_output(true); + jmp(end_store, T_NEAR); + L(unaligned_store); { + store_output(false); + } + L(end_store); + }; + + auto prefetch_callback = [=](int ur, int i_reduce, int i_ur, int i_load, + bool last_block, bool wraparound, int reduce_step) + { + bool pf_ker_l1 = true; + bool pf_ker_l2 = wraparound; + int n_ops = (jcp.reduce_loop_unroll / reduce_step) * ur * load_loop_blk; + int i_op = (i_reduce / reduce_step) * ur * load_loop_blk + + i_ur * load_loop_blk + i_load; + + int n_pf_ker_l1 = pf_ker_l1 ? jcp.reduce_block : 0; + int n_pf_ker_l2 = pf_ker_l2 && wraparound ? jcp.reduce_block : 0; + int n_pf_out_l1 = jcp.use_vmovntps ? 0 : ur; + + int pf_inp_ops = n_ops / 2; // # of operations during which to pf input + int pf_inp_trigger; + if (jcp.prop_kind == backward_weights) + pf_inp_trigger = nstl::max(1, pf_inp_ops / jcp.reduce_block); + else + pf_inp_trigger = nstl::max(1, pf_inp_ops / ur); + + int n_other_pf = + load_loop_blk * (n_pf_ker_l1 + n_pf_ker_l2 + n_pf_out_l1); + int n_other_pf_ops = n_ops - pf_inp_ops; + int other_pf_trigger + = n_other_pf ? nstl::max(1, n_other_pf_ops / n_other_pf) : 0; + + if (i_op < pf_inp_ops && i_op % pf_inp_trigger == 0) { + // input prefetches have the highest priority b/c the + // first iteration of the kernel block touches all the + // cache lines + int i_pf = i_op / pf_inp_trigger; + auto pf_reg = wraparound && last_block + ? reg_bcast_data + : (last_block ? aux1_reg_bcast_data + : aux_reg_bcast_data); + int offt = i_pf; + if (jcp.prop_kind == backward_weights) { + offt += wraparound && last_block + ? 0 + : (last_block ? jcp.is : jcp.reduce_block); + offt *= jcp.bcast_block; + } else { + offt += wraparound && last_block + ? 0 + : (last_block ? jcp.ur : jcp.bcast_dim); + offt *= jcp.reduce_block; + } + mic_prefetcht0(ptr[pf_reg + offt * jcp.typesize_in]); + } else if (i_op >= pf_inp_ops && n_other_pf) { + // remaining prefetches are spread among the rest of the + // operations; prefetches for output take priority + // TODO: spread L2 prefetches among L1 prefetches + i_op -= pf_inp_ops; + if (i_op % other_pf_trigger == 0) { + int i_pf = i_op / (load_loop_blk * other_pf_trigger); + if (i_pf < n_pf_ker_l2) { + int offt = (i_pf + (i_load + 1) * jcp.reduce_dim) + * jcp.load_block; + mic_prefetcht1(ptr[aux_reg_load_data + + offt * jcp.typesize_in]); + } else if (i_pf < n_pf_ker_l2 + n_pf_ker_l1) { + i_pf -= n_pf_ker_l2; + auto pf_reg = last_block ? reg_load_data + : aux_reg_load_data; + int offt = (i_pf + i_load * jcp.reduce_dim + + (last_block + ? (wraparound ? jcp.reduce_dim : 0) + : jcp.reduce_block)) + * jcp.load_block; + mic_prefetcht0(ptr[pf_reg + offt * jcp.typesize_in]); + } else if (i_pf < n_pf_ker_l1 + n_pf_ker_l2 + n_pf_out_l1) { + i_pf -= n_pf_ker_l1 + n_pf_ker_l2; + int offt = i_pf * jcp.load_block; + mic_prefetcht0(ptr[aux_reg_output_data + + offt * jcp.typesize_out]); + } + } + } + }; + + auto fma_block = [=](bool last_block) { + assert(jcp.reduce_loop_unroll % jcp.fma_step == 0); + + int reduce_step = jcp.fma_step; + + for (int i_reduce = 0; i_reduce < jcp.reduce_loop_unroll; + i_reduce += reduce_step) { + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + // if transposed input data used and if spatial size is + // not divided by transpose step (4) then for last reduce step + // we should load only needed load_registers data + // and clear remaining + if (jcp.transpose_src && jcp.is % jcp.fma_step && last_block + && i_reduce == jcp.reduce_loop_unroll - reduce_step) { + Label load_all; + Label load_finish; + test(reg_reduce_pos_flag, FLAG_SP_LAST); + jz(load_all, T_NEAR); + + const int n_loads = jcp.is % jcp.fma_step; + for (int i_fma = 0; i_fma < jcp.fma_step; i_fma++) { + if (i_fma < n_loads) + vmovups(vreg_load(i_load, i_fma), + load_ptr(i_reduce + i_fma, i_load)); + else + vpxord(vreg_load(i_load, i_fma), + vreg_load(i_load, i_fma), + vreg_load(i_load, i_fma)); + } + jmp(load_finish); + + L(load_all); + for (int i_fma = 0; i_fma < jcp.fma_step; i_fma++) { + vmovups(vreg_load(i_load, i_fma), + load_ptr(i_reduce + i_fma, i_load)); + } + L(load_finish); + } else { + for (int i_fma = 0; i_fma < jcp.fma_step; i_fma++) { + vmovups(vreg_load(i_load, i_fma), + load_ptr(i_reduce + i_fma, i_load)); + } + } + } + + for (int i_ur = 0; i_ur < ur; ++i_ur) { + if (jcp.ver == ver_avx512_core && jcp.expl_bcast + && load_loop_blk > 1) + vbroadcastss(vreg_bcast, bcast_ptr(i_reduce, i_ur, false)); + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + if (jcp.ver == ver_4fma) + v4fmaddps(vreg_accum(i_load, i_ur), + vreg_load(i_load, 0), + bcast_ptr(i_reduce, i_ur, false)); + else if (jcp.ver == ver_avx512_core && jcp.expl_bcast + && load_loop_blk > 1) + vfmadd231ps(vreg_accum(i_load, i_ur), + vreg_load(i_load, 0), vreg_bcast); + else + vfmadd231ps(vreg_accum(i_load, i_ur), + vreg_load(i_load, 0), + bcast_ptr(i_reduce, i_ur, true)); + prefetch_callback(ur, i_reduce, i_ur, i_load, + last_block, wraparound, reduce_step); + } + } + } + }; + Label reduce_loop; + Label reduce_loop_tail; + + mov(aux_reg_load_data, reg_load_data); + + mov(aux_reg_bcast_data, aux1_reg_bcast_data); + init(); + + mov(reduce_loop_iter, reg_reduce_loop_work); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jle(reduce_loop_tail, T_NEAR); + + L(reduce_loop); { + fma_block(false); + add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step); + add(aux_reg_load_data, jcp.reduce_loop_load_step); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jg(reduce_loop, T_NEAR); + } + + L(reduce_loop_tail); + fma_block(true); + + store(); +} + +void jit_avx512_common_1x1_conv_kernel::generate() +{ + preamble(); + + mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]); + mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]); + mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]); + + sub(rsp, stack_space_needed); + + if (jcp.with_bias) + mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]); + + mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]); + mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]); + mov(EVEX_compress_addr(rsp, bcast_loop_work_offt), reg_bcast_loop_work); + mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]); + mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]); + if (one_of(jcp.prop_kind, forward_training, forward_inference)) + mov(reg_relu_ns, reinterpret_cast(&jcp.eltwise.alpha)); + if (jcp.prop_kind == backward_weights) + mov(reg_output_stride, ptr[param1 + GET_OFF(output_stride)]); + + auto load_loop_body = [=](int load_loop_blk) { + bcast_loop(load_loop_blk); + add(reg_load_data, load_loop_blk * jcp.load_loop_load_step); + switch (jcp.prop_kind) { + case forward_training: + case forward_inference: + add(reg_bias_data, + load_loop_blk * jcp.load_block * jcp.typesize_out); + add(reg_output_data, + load_loop_blk * jcp.bcast_dim * jcp.load_block * + jcp.typesize_out); + break; + case backward_data: + add(reg_output_data, + load_loop_blk * jcp.bcast_dim * jcp.load_block * + jcp.typesize_out); + break; + case backward_weights: + for (int i_load = 0; i_load < load_loop_blk; i_load++) + add(reg_output_data, reg_output_stride); + break; + default: + assert(!"invalid prop_kind"); + } + sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step); + }; + + const int simd_w = 16; + + Label load_loop_blk[7]; + + static const int ur_cases_fma_embd_bcast[] = { 2, 4, 5, 8, 14, 32 }; + static const int ur_cases_fma_expl_bcast[] = { 2, 5, 6, 9, 14, 32 }; + static const int ur_cases_4fma[] = { 2, 4, 6, 12, 32 }; + + const int size_ur_cases_fma + = (jcp.ver == ver_avx512_core && jcp.expl_bcast) ? + sizeof(ur_cases_fma_expl_bcast) : + sizeof(ur_cases_fma_embd_bcast); + const int size_ur_cases_4fma = sizeof(ur_cases_4fma); + + const int *ur_cases_fma = (jcp.ver == ver_avx512_core && jcp.expl_bcast) ? + ur_cases_fma_expl_bcast : + ur_cases_fma_embd_bcast; + const int *ur_cases = jcp.ver == ver_4fma ? ur_cases_4fma : ur_cases_fma; + const int num_ur_cases = + (jcp.ver == ver_4fma ? size_ur_cases_4fma : size_ur_cases_fma) + / sizeof(*ur_cases); + + for (int ur_idx = num_ur_cases - 1; ur_idx > 0; ur_idx--) { + int label_idx = num_ur_cases - ur_idx - 1; + if (jcp.ur <= ur_cases[ur_idx]) { + cmp(reg_load_loop_work, simd_w * (label_idx + 1)); + jle(load_loop_blk[label_idx], T_NEAR); + } + } + + for (int ur_idx = 0; ur_idx < num_ur_cases; ur_idx++) { + if (jcp.ur <= ur_cases[ur_idx]) { + int label_idx = num_ur_cases - ur_idx - 1; + L(load_loop_blk[label_idx]); + { + if (label_idx == 0) { + cmp(reg_load_loop_work, 0); + je(load_loop_blk[num_ur_cases], T_NEAR); + } + load_loop_body(label_idx + 1); + if (label_idx - 1 > 0) { + cmp(reg_load_loop_work, 2 * label_idx * simd_w); + je(load_loop_blk[label_idx - 1], T_NEAR); + } + cmp(reg_load_loop_work, (label_idx + 1) * simd_w); + jge(load_loop_blk[label_idx]); + } + for (int idx = label_idx - 1; idx > 0; --idx) { + cmp(reg_load_loop_work, simd_w * (idx + 1)); + je(load_loop_blk[idx], T_NEAR); + } + if (ur_idx < num_ur_cases - 2) { + cmp(reg_load_loop_work, simd_w); + jle(load_loop_blk[0], T_NEAR); + } + } + } + L(load_loop_blk[num_ur_cases]); + + add(rsp, stack_space_needed); + + postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +bool jit_avx512_common_1x1_conv_kernel::post_ops_ok( + jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + + return false; +} + +status_t jit_avx512_common_1x1_conv_kernel::init_conf(jit_1x1_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr, int nthreads, bool reduce_src) { + if (!mayiuse(avx512_common)) return status::unimplemented; + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + const int simd_w = cpu_isa_traits::vlen / sizeof(float); + const int ndims = src_d.ndims(); + + jcp.prop_kind = cd.prop_kind; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc_without_padding = dst_d.dims()[1] / jcp.ngroups; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + bool ok_to_pad_channels = true + && jcp.ngroups == 1 + && src_d.data_type() == data_type::f32; + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2]; + jcp.iw = src_d.dims()[ndims - 1]; + jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2]; + jcp.ow = dst_d.dims()[ndims - 1]; + + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0]; + jcp.l_pad = cd.padding[0][ndims - 3]; + + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0]; + jcp.stride_w = cd.strides[ndims - 3]; + + jcp.with_bias = pick_by_prop_kind(jcp.prop_kind, cd.bias_desc.format_kind, + format_kind::undef, cd.diff_bias_desc.format_kind) + != format_kind::undef; + + jcp.os = jcp.oh * jcp.ow; + jcp.is = jcp.ih * jcp.iw; + jcp.tr_is = rnd_up(jcp.is, 4); + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + jcp.with_sum = p.find(primitive_kind::sum) != -1; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) { + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + if (dst_d.data_type() == data_type::s32) return status::unimplemented; + } + + auto dat_tag = pick(ndims - 3, nCw16c, nChw16c); + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + + bool args_ok = true + && jcp.ngroups == 1 + && jcp.src_tag == dat_tag + && jcp.dst_tag == dat_tag; + if (!args_ok) return status::unimplemented; + + args_ok = true + && jcp.oc % simd_w == 0 && jcp.ic % simd_w == 0 + && jcp.t_pad == 0 && jcp.l_pad == 0 + && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides + && jcp.kh == 1 && jcp.kw == 1; + if (!args_ok) return status::unimplemented; + + jcp.ic_block = jcp.oc_block = simd_w; + jcp.transpose_src = false; + + if (everyone_is(data_type::f32, src_d.data_type(), + weights_d.data_type(), dst_d.data_type())) + { + const int is_bwd_d = jcp.prop_kind == backward_data; + format_tag_t wei_tag = with_groups + ? pick(2 * ndims - 6 + is_bwd_d, gOIw16i16o, gIOw16o16i, + gOIhw16i16o, gIOhw16o16i) + : pick(2 * ndims - 6 + is_bwd_d, OIw16i16o, IOw16o16i, + OIhw16i16o, IOhw16o16i); + + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + if (jcp.wei_tag != wei_tag) + return status::unimplemented; + + if (jcp.prop_kind != backward_weights && mayiuse(avx512_mic_4ops) && + ((jcp.prop_kind == backward_data) ? jcp.oc_block : jcp.ic_block) % 4 + == 0) { + jcp.ver = ver_4fma; + jcp.fma_step = 4; + } else if (jcp.prop_kind == backward_weights && mayiuse(avx512_mic_4ops) + && !reduce_src + /* Heuristic condition for relation of src size to oc. Otherwise + the src transposition overhead exceed the benefit from 4fma + */ + && ((jcp.is * jcp.ic) / jcp.oc <= 2048) + && mkldnn_thr_syncable() + ) + { + jcp.transpose_src = true; + jcp.ver = ver_4fma; + jcp.fma_step = 4; + } else { + jcp.ver = (mayiuse(avx512_core)) ? ver_avx512_core : ver_fma; + jcp.fma_step = 1; + } + jcp.typesize_in = sizeof(prec_traits::type); + jcp.typesize_out = sizeof(prec_traits::type); + } else { + return status::unimplemented; + } + + /* once all the formats are set, check the padding consistency */ + args_ok = true + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= dst_d.padded_dims()[1] + && jcp.ic <= weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= weights_d.padded_dims()[with_groups + 0]; + if (!args_ok) return status::unimplemented; + + const int SMALL_SPATIAL = 10; + const int BIG_SPATIAL = 28; + const int BIG_REDUCE_DIM = 1024; + const int BIG_LOAD_DIM = 256; + + int load_blocking{ 0 }; + int load_blocking_max{ 0 }; + int bcast_blocking{ 0 }; + int bcast_blocking_max{ 0 }; + int reduce_blocking{ 0 }; + int reduce_blocking_max{ 0 }; + + jcp.load_grp_count = 1; + + const int L1_capacity = get_cache_size(1, true) / sizeof(float); + const int L2_size = get_cache_size(2, true) / sizeof(float); + const int L2_capacity = (L2_size * 3) / 4; + + if (one_of(jcp.prop_kind, forward_training, forward_inference, + backward_data)) { + if (one_of(jcp.prop_kind, forward_training, forward_inference)) { + jcp.reduce_dim = jcp.ic; + jcp.reduce_block = jcp.ic_block; + + jcp.load_dim = jcp.oc; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.is; + } else { + jcp.reduce_dim = jcp.oc; + jcp.reduce_block = jcp.oc_block; + + jcp.load_dim = jcp.ic; + jcp.load_block = jcp.ic_block; + + jcp.bcast_dim = jcp.os; + } + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.bcast_dim * jcp.typesize_in; + + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.load_block * jcp.typesize_in; + jcp.load_loop_load_step + = jcp.reduce_dim * jcp.load_block * jcp.typesize_in; + + // adjusting registry blocking + int max_regs, min_regs, size_treshold, ur_step; + const int spatial + = (one_of(jcp.prop_kind, forward_training, forward_inference)) ? + jcp.oh : + jcp.ih; + if (jcp.ver == ver_avx512_core && (8 * jcp.mb) / nthreads >= 1) { + max_regs = 9; + min_regs = 6; + size_treshold = 14; + ur_step = 1; + jcp.expl_bcast = true; + + if (jcp.load_dim > 128 && jcp.load_dim < BIG_LOAD_DIM + && spatial > SMALL_SPATIAL && spatial < BIG_SPATIAL) { + max_regs = 6; + min_regs = 5; + } + } else { + max_regs = jcp.ver == ver_4fma ? 28 : 30; + min_regs = 9; + size_treshold = jcp.ver == ver_4fma ? 28 : 14; + ur_step = jcp.ver == ver_4fma ? 4 : 1; + jcp.expl_bcast = false; + jcp.use_vmovntps = true; + } + jcp.ur = 1; + for (int ur_w = max_regs; ur_w >= min_regs; ur_w -= ur_step) { + if ((spatial >= size_treshold && spatial % ur_w == 0) + || (spatial < size_treshold && jcp.os % ur_w == 0)) { + jcp.ur = ur_w; + break; + } + } + if (jcp.ur == 1) { + jcp.ur = nstl::min(max_regs, jcp.os); + int os_tail = jcp.os % max_regs; + for (int i = max_regs; i >= min_regs; i -= ur_step) { + int i_tail = jcp.os % i; + if (i_tail > os_tail || i_tail == 0) { + jcp.ur = i; + os_tail = i_tail; + if (i_tail == 0) + break; + } + } + } + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.bcast_dim * jcp.typesize_in; + + jcp.bcast_block = jcp.ur; + + jcp.bcast_loop_output_step = jcp.ur * jcp.load_block * jcp.typesize_out; + jcp.bcast_loop_output_substep = -1; // unused + jcp.bcast_loop_bcast_step = jcp.ur * jcp.reduce_block * jcp.typesize_in; + jcp.bcast_loop_bcast_substep = -1; // unused + + jcp.load_loop_iter_step = jcp.load_block; + + if (jcp.prop_kind == backward_data) + jcp.loop_order = loop_lbr; + else + jcp.loop_order = reduce_src ? loop_blr : loop_lbr; + + int nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block); + int nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block); + int nb_load = div_up(jcp.load_dim, jcp.load_block); + + if (jcp.ver == ver_avx512_core && jcp.expl_bcast) { + if (jcp.load_dim <= BIG_LOAD_DIM && spatial > SMALL_SPATIAL + && spatial < BIG_SPATIAL) + reduce_blocking = nstl::min(jcp.reduce_dim, 80); + else if (spatial > SMALL_SPATIAL) + reduce_blocking = nstl::min(jcp.reduce_dim, 512); + else + reduce_blocking = nstl::min(jcp.reduce_dim, 256); + + if ((jcp.mb > 28 && spatial >= 28) + || (jcp.mb > 112 && spatial >= 17)) + jcp.use_vmovntps = true; + else + jcp.use_vmovntps = false; + } else { + + reduce_blocking = nb_reduce; + if (spatial <= SMALL_SPATIAL && jcp.reduce_dim >= BIG_REDUCE_DIM) + reduce_blocking = 16; + else if (spatial > SMALL_SPATIAL + && jcp.reduce_dim >= BIG_REDUCE_DIM) + reduce_blocking = 8; + reduce_blocking = best_divider(nb_reduce, 1, reduce_blocking, true); + reduce_blocking *= jcp.reduce_block; + } + + // Check input data cache aliasing. + // For other ISA constants may be updated. + // 64 * 1024 is chosen due to 1MB L2 16-way cache. + // 7 is empirical value. It is about half of 16. + // So we leave about half of the set for other data - weights, dst + int way_size = (64 * 1024) / jcp.typesize_in; + int max_hits = 7; + if (jcp.bcast_dim * reduce_blocking > way_size * max_hits) { + int nrb = reduce_blocking / simd_w; + int sp = jcp.bcast_dim; + int wl = way_size / simd_w; + for (int start_off = 0; start_off < jcp.ur; start_off++) { + for (int off = start_off, hits = 0; off < sp * nrb; off += wl) { + if (off % sp >= jcp.ur || ++hits < max_hits) + continue; + int max_r_blocking = simd_w * nstl::max(1, (off + wl) / sp); + reduce_blocking + = nstl::min(reduce_blocking, max_r_blocking); + break; + } + } + } + + if (reduce_blocking < jcp.reduce_dim) { + jcp.use_vmovntps = false; + if (jcp.prop_kind == backward_data) + jcp.loop_order = reduce_src ? loop_lbr : loop_rlb; + else + jcp.loop_order = reduce_src ? loop_rbl : loop_rlb; + } + load_blocking = jcp.load_dim; + + int load_size = jcp.load_dim * jcp.reduce_dim; + int bcast_size = jcp.mb * jcp.ngroups * jcp.bcast_dim * jcp.reduce_dim; + + if (jcp.ver == ver_avx512_core && nthreads <= 28 && jcp.mb < nthreads + && nb_load * nb_bcast > nthreads) { + // Some heuristic here + float calc_koef = 0.01, best_cost = FLT_MAX; + int n_lgc = nthreads; + float ratio = (float)load_size / (float)bcast_size; + int best_lgc = ratio > 1 ? n_lgc : 1; + auto calc_job_cost = [&](int lb, int tg, float mem_k) { + int bb_size = jcp.mb * div_up(nb_bcast, tg); + float calc_size = (float)(bb_size * jcp.ur) + * (lb * jcp.load_block) * jcp.reduce_dim; + float mem_size = (float)(bb_size * jcp.ur + lb * jcp.load_block) + * jcp.reduce_dim; + return calc_koef * calc_size + mem_k * mem_size; + }; + for (int lgc, ilgc = 0; ilgc < n_lgc; ilgc++) { + lgc = ratio > 1 ? n_lgc - ilgc : ilgc + 1; + int min_lb = nb_load / lgc; + int max_lb = div_up(nb_load, lgc); + int min_tg = nthreads / lgc; + int max_tg = div_up(nthreads, lgc); + // Some heuristic here + float mem_koef = (max_tg == 1) ? 1.f : 1.3f; + float job_cost = 0.; + if (nthreads % lgc < nb_load % lgc) { + job_cost = calc_job_cost(max_lb, min_tg, mem_koef); + } else { + auto job_cost1 = calc_job_cost(max_lb, max_tg, mem_koef); + auto job_cost2 = calc_job_cost(min_lb, min_tg, mem_koef); + job_cost = nstl::max(job_cost1, job_cost2); + } + + if (job_cost < best_cost) { + best_lgc = lgc; + best_cost = job_cost; + } + } + jcp.load_grp_count = best_lgc; + load_blocking = div_up(nb_load, jcp.load_grp_count) * jcp.load_block; + } else { + jcp.load_grp_count = div_up(nthreads, jcp.mb * jcp.ngroups * nb_bcast); + jcp.load_grp_count = best_divider( + nthreads, jcp.load_grp_count, 2 * jcp.load_grp_count, false); + } + + if (jcp.ver == ver_avx512_core && jcp.expl_bcast && jcp.bcast_dim <= 64 + && load_size >= L2_size) { + jcp.load_grp_count = nstl::max(jcp.load_grp_count, 4); + } else if (jcp.bcast_dim <= 49 && jcp.mb <= nthreads + && jcp.load_dim > 512 && jcp.load_dim / jcp.reduce_dim >= 4) { + jcp.load_grp_count = nstl::max(jcp.load_grp_count, 2); + load_blocking = jcp.load_block; + } + + if (jcp.ver == ver_4fma && jcp.bcast_dim * jcp.mb < jcp.load_dim + && jcp.oh * jcp.ow > 64 + && IMPLICATION(reduce_src, jcp.load_dim < 1024)) { + /* Looking for best loading dimension blocking + * to get the best thread and data read/write efficiency + * by finding the optimal 'load_chunk' value + * Example: + * for 72 threads and convolution with mb=1, ih=iw=7, oc = 512 + * the 'best' load_chunk value should be 1 + * TODO: remove heuristic constants in above condition + * TODO: check this blocking for other ISA + */ + float best_eff = -1.f; + int best_lgc = 1; + + for (int load_chunk = 1; load_chunk <= nb_load; load_chunk++) { + int lgc = div_up(nb_load, load_chunk); + if (lgc > nthreads) + continue; + int thr_per_grp = div_up(nthreads, lgc); + int bcast_per_thr = div_up(jcp.mb * nb_bcast, thr_per_grp) + * jcp.bcast_block; + int load_per_thr = load_chunk * simd_w; + float data_norm = (bcast_per_thr + load_per_thr) / 2.f; + float data_eff = (bcast_per_thr * load_per_thr) + / (data_norm * data_norm); + float thr_eff_over_grp = (float)nstl::max(1, nthreads / lgc) + / div_up(nthreads, lgc); + float thr_eff_in_grp = ((float)jcp.mb * nb_bcast) + / rnd_up(jcp.mb * nb_bcast, thr_per_grp); + float thr_eff = thr_eff_over_grp * thr_eff_in_grp; + float load_eff = (float)nb_load / rnd_up(nb_load, lgc); + float overall_eff = data_eff + thr_eff + load_eff; + if (overall_eff > best_eff) { + best_eff = overall_eff; + best_lgc = lgc; + } + } + jcp.load_grp_count = best_lgc; + load_blocking + = div_up(nb_load, jcp.load_grp_count) * jcp.load_block; + } + bcast_blocking = div_up(jcp.mb * jcp.ngroups * nb_bcast, + div_up(nthreads, jcp.load_grp_count)) + * jcp.bcast_block; + bcast_blocking = nstl::min(jcp.bcast_dim, bcast_blocking); + bcast_blocking = rnd_up(bcast_blocking, jcp.bcast_block); + + int space_for_bcast + = (L2_capacity - /* kernel_size - */ + 2 * jcp.load_block * reduce_blocking + - jcp.ur * reduce_blocking - 3 * 1024); + if (jcp.reduce_dim * jcp.bcast_dim > L2_capacity) + space_for_bcast /= 2; + + int bcast_in_cache + = nstl::max(jcp.bcast_block, space_for_bcast / reduce_blocking); + bcast_blocking = nstl::min( + bcast_blocking, rnd_dn(bcast_in_cache, jcp.bcast_block)); + + load_blocking_max = load_blocking; + bcast_blocking_max = bcast_blocking * 3 / 2; + reduce_blocking_max = reduce_blocking; + + } else if (jcp.prop_kind == backward_weights) { + + jcp.use_vmovntps = false; + if (jcp.is > SMALL_SPATIAL * SMALL_SPATIAL && jcp.ver == ver_4fma) + jcp.use_vmovntps = true; + + if (jcp.transpose_src) + jcp.reduce_dim = jcp.tr_is; + else + jcp.reduce_dim = jcp.is; + + if (jcp.ver == ver_4fma) { + // reduce_block should be divided by fma_step + jcp.reduce_block = best_divider(jcp.reduce_dim, 4, 16, true, 4); + } else { + jcp.reduce_block = best_divider(jcp.reduce_dim, 7, 16, true); + if (jcp.reduce_dim % jcp.reduce_block != 0) + jcp.reduce_block = best_divider(jcp.iw, 4, jcp.iw, false); + if (jcp.reduce_block > 256) { + jcp.reduce_block = 1; + } + + } + + jcp.load_dim = jcp.oc; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.ic; + jcp.bcast_block = jcp.ic_block; + + if (jcp.ver == ver_avx512_core && jcp.reduce_block <= 19) { + // if reduce_block is big then generated JIT code may be big + // for small values of ur because reduce_loop_unroll = reduce_block + jcp.ur = jcp.bcast_block / 2; + jcp.expl_bcast = true; + } else { + jcp.ur = jcp.bcast_block; + jcp.expl_bcast = false; + } + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.ic_block * jcp.typesize_in; + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.oc_block * jcp.typesize_in; + + jcp.bcast_loop_output_step = + jcp.oc_block * jcp.ic_block * jcp.typesize_out; + jcp.bcast_loop_output_substep = + jcp.oc_block * jcp.ur * jcp.typesize_out; + jcp.bcast_loop_bcast_step = + jcp.ic_block * jcp.reduce_dim * jcp.typesize_in; + jcp.bcast_loop_bcast_substep = jcp.ur * jcp.typesize_in; + + jcp.load_loop_load_step = jcp.oc_block * jcp.os * jcp.typesize_in; + jcp.load_loop_iter_step = jcp.oc_block; + + /* --- */ + balance(jcp, nthreads); + + load_blocking = div_up(jcp.load_dim, jcp.load_block); + load_blocking = best_divider(load_blocking, 16, load_blocking, false); + load_blocking *= jcp.load_block; + + load_blocking_max = load_blocking; + assert(jcp.load_dim % load_blocking == 0); + + int max_bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block); + int min_bcast_blocking = 5; + + bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block); + bcast_blocking = best_divider( + bcast_blocking, min_bcast_blocking, max_bcast_blocking, false); + bcast_blocking *= jcp.bcast_block; + bcast_blocking_max = bcast_blocking; + assert(jcp.bcast_dim % bcast_blocking == 0); + + // for reduction balance + if (jcp.ver == ver_avx512_core) { + int max_reduce_blocking + = nstl::min(L1_capacity / jcp.ur, jcp.reduce_dim); + int min_reduce_blocking = nstl::min( + L1_capacity / jcp.ur, nstl::max(jcp.iw, jcp.ih)); + reduce_blocking = best_divider(jcp.reduce_dim, min_reduce_blocking, + max_reduce_blocking, true); + reduce_blocking + = nstl::max(rnd_dn(reduce_blocking, jcp.reduce_block), + jcp.reduce_block); + } else { + int max_reduce_blocking = L2_capacity + / ((bcast_blocking + load_blocking) * jcp.reduce_block); + max_reduce_blocking = nstl::min(max_reduce_blocking, + (L1_capacity / (jcp.bcast_block)) / jcp.reduce_block); + + int num_jobs = div_up(jcp.load_dim, load_blocking) + * div_up(jcp.bcast_dim, bcast_blocking); + int threads_per_job = nstl::max(1, nthreads / num_jobs); + reduce_blocking = div_up(jcp.mb * jcp.reduce_dim, jcp.reduce_block); + reduce_blocking = div_up(reduce_blocking, threads_per_job); + + reduce_blocking = best_divider(reduce_blocking, + max_reduce_blocking - 2, max_reduce_blocking, true); + reduce_blocking *= jcp.reduce_block; + } + + reduce_blocking_max = rnd_dn(reduce_blocking * 3 / 2, jcp.reduce_block); + } else + return status::unimplemented; + + assert(load_blocking); + assert(load_blocking_max); + assert(bcast_blocking); + assert(bcast_blocking_max); + assert(reduce_blocking); + assert(reduce_blocking_max); + assert(load_blocking % jcp.load_block == 0); + assert(reduce_blocking % jcp.reduce_block == 0); + assert(load_blocking_max % jcp.load_block == 0); + assert(reduce_blocking_max % jcp.reduce_block == 0); + if (jcp.ver == ver_4fma) { + assert(jcp.reduce_loop_unroll % jcp.fma_step == 0); + assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0); + } + + assert(jcp.bcast_block % jcp.ur == 0); + assert(jcp.reduce_dim % jcp.reduce_block == 0); + + jcp.ur_tail = jcp.bcast_dim % jcp.ur; + + jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block; + jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block; + jcp.nb_load_blocking = load_blocking / jcp.load_block; + jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block; + jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block; + jcp.nb_reduce_blocking_max = reduce_blocking_max / jcp.reduce_block; + + jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block); + jcp.nb_load = div_up(jcp.load_dim, jcp.load_block); + jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block); + + return status::success; +} + +void jit_avx512_common_1x1_conv_kernel::init_scratchpad( + memory_tracking::registrar_t &scratchpad, + const jit_1x1_conv_conf_t &jcp) { + using namespace mkldnn::impl::memory_tracking::names; + + if (jcp.prop_kind != backward_data && jcp.with_bias + && jcp.oc != jcp.oc_without_padding) + scratchpad.book(key_conv_padded_bias, jcp.typesize_out * jcp.oc); + + if (jcp.prop_kind == backward_weights) { + const size_t wei_size = (size_t)jcp.ngroups * jcp.oc * jcp.ic; + scratchpad.book(key_conv_wei_reduction, + jcp.typesize_out * wei_size * (jcp.nthr_mb - 1)); + } + + if (jcp.transpose_src) { + const size_t tr_src_size = + (size_t)jcp.nthr_mb * jcp.ngroups * jcp.ic * jcp.tr_is; + scratchpad.book(key_conv_tr_src, jcp.typesize_out * tr_src_size); + scratchpad.book(key_conv_tr_src_bctx, + sizeof(simple_barrier::ctx_t) * jcp.nthr); + } +} + +void jit_avx512_common_1x1_conv_kernel::balance(jit_1x1_conv_conf_t &jcp, + int nthreads) +{ + // initialize jcp reduction threading properties + jcp.nthr = jcp.nthr_mb = jcp.nthr_g = jcp.nthr_oc_b = jcp.nthr_ic_b = 1; + if (nthreads < jcp.ngroups) { + /* simplification... fortunately it doesn't hurt much */ + return; + } + const int nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block); + const int nb_load = div_up(jcp.load_dim, jcp.load_block); + const int nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block); + + jcp.nthr_g = jcp.ngroups; + const int nthr = nthreads / jcp.nthr_g; + + auto calc_mem_cost = [=](int nthr_mb, int nthr_oc_b, int nthr_ic_b) { + /* calculate per thread memory cost (read/write). high level + * optimizer tries to minimize memory consumption. few notes: (n1) + * unclear why, but that essentially helps first convolution... + * (n2) assuming the reduction over minibatch is always there: + * - instead of 8 it should be 5 here (write ~= 2 read): + * kernel: temporal workspace 1 write + * reduction: 1 read from workspace and 1 write to the diff_wei + * - but experiments showed 8 works better than 5 or 6... */ + int bcast_koeff = 1; + int load_koeff = 1; + int output_koeff = 12; + if (jcp.transpose_src) { + bcast_koeff = 5; + load_koeff = 1; + output_koeff = 8; + } + return 0 + + (size_t)bcast_koeff * div_up(jcp.mb * nb_reduce, nthr_mb) + * div_up(jcp.ngroups, jcp.nthr_g) + * div_up(nb_bcast, nthr_ic_b) * jcp.ic_block * jcp.reduce_block + / jcp.stride_h / jcp.stride_w /* (n1) */ + + (size_t)load_koeff * div_up(jcp.mb * nb_reduce, nthr_mb) + * div_up(jcp.ngroups, jcp.nthr_g) + * div_up(nb_load, nthr_oc_b) * jcp.oc_block * jcp.reduce_block + + (size_t)output_koeff /* (n2) */ + * div_up(jcp.ngroups, jcp.nthr_g) * div_up(nb_load, nthr_oc_b) + * div_up(nb_bcast, nthr_ic_b) * jcp.ic_block + * jcp.oc_block; + }; + + int nthr_mb = 1, nthr_oc_b = 1, nthr_ic_b = 1; + auto best_mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b); + + /* step 1: find the best thread distribution with lowest memory cost */ + const int nthr_mb_max = nstl::min(nthr, jcp.mb * nb_reduce); + for (nthr_mb = 1; nthr_mb <= nthr_mb_max; ++nthr_mb) { + const int nthr_par = nthr / nthr_mb; + const int nthr_oc_b_max = nstl::min(nthr_par, nb_load); + for (nthr_oc_b = 1; nthr_oc_b <= nthr_oc_b_max; ++nthr_oc_b) { + nthr_ic_b = nstl::min(nthr_par / nthr_oc_b, nb_bcast); + auto mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b); + if (mem_cost <= best_mem_cost) { + best_mem_cost = mem_cost; + jcp.nthr_mb = nthr_mb; + jcp.nthr_oc_b = nthr_oc_b; + jcp.nthr_ic_b = nthr_ic_b; + } + } + + if (!mkldnn_thr_syncable()) { assert(nthr_mb == 1); break; } + } + if (jcp.nthr_mb > nthreads / 2 && jcp.nthr_mb < nthreads) + jcp.nthr_mb = nstl::min(jcp.mb, nthreads); + + jcp.nthr = jcp.nthr_mb * jcp.nthr_g * jcp.nthr_oc_b * jcp.nthr_ic_b; + assert(jcp.nthr <= nthreads); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp new file mode 100644 index 0000000000..d2ae017943 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp @@ -0,0 +1,108 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX512_COMMON_1x1_CONV_KERNEL_HPP +#define JIT_AVX512_COMMON_1x1_CONV_KERNEL_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx512_common_1x1_conv_kernel : public jit_generator { + jit_avx512_common_1x1_conv_kernel(jit_1x1_conv_conf_t ajcp, + const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32( + this, jcp.eltwise); + + this->generate(); + jit_ker = (void (*)(jit_1x1_conv_call_s *)) this->getCode(); + } + + ~jit_avx512_common_1x1_conv_kernel() { + delete eltwise_injector_; + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_1x1_conv_kernel) + + static bool post_ops_ok(jit_1x1_conv_conf_t &jcp, + const primitive_attr_t &attr); + + static status_t init_conf(jit_1x1_conv_conf_t &jcp, + const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr, + int nthreads, bool reduce_src); + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_1x1_conv_conf_t &jcp); + + jit_1x1_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker)(jit_1x1_conv_call_s *); + + private: + using reg64_t = const Xbyak::Reg64; + using zmm_t = const Xbyak::Zmm; + + reg64_t reg_bcast_data = r8; + reg64_t reg_load_data = r10; + reg64_t reg_output_data = r9; + reg64_t aux_reg_bcast_data = r14; + reg64_t aux1_reg_bcast_data = rbx; + reg64_t aux_reg_load_data = r15; + reg64_t imm_addr64 = aux_reg_load_data; + reg64_t aux_reg_output_data = abi_not_param1; + reg64_t reg_load_loop_work = rsi; + reg64_t reg_reduce_loop_work = r11; + reg64_t bcast_loop_iter = rdx; + reg64_t reduce_loop_iter = abi_param1; + reg64_t reg_reduce_pos_flag = rax; + reg64_t reg_output_stride = r13; + reg64_t reg_bias_data = r12; + reg64_t reg_relu_ns = r13; + reg64_t reg_bcast_loop_work = aux1_reg_bcast_data; + + Xbyak::Zmm vreg_bcast = Xbyak::Zmm(31); + + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + int bcast_loop_work_offt = 0; + int stack_space_needed = 16; + + void bcast_loop(int load_loop_blk); + void reduce_loop(int load_loop_blk, int ur, int substep, bool wraparound); + + void generate(); + static void balance(jit_1x1_conv_conf_t &jcp, int nthreads); +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp new file mode 100644 index 0000000000..54d58c8a39 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp @@ -0,0 +1,816 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_generator.hpp" + +#include "jit_avx512_common_1x1_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +#define data_blk_off(f, n, c, h, w) \ + ((ndims == 3) \ + ? (f).blk_off(n, c, w) \ + : (f).blk_off(n, c, h, w)) + + +namespace { +template +void balance2D(U nthr, U ithr, T ny, T &ny_start, T &ny_end, + T nx, T &nx_start, T &nx_end, T nx_divider) +{ + const int grp_count = nstl::min(nx_divider, nthr); + const int grp_size_big = nthr / grp_count + 1; + const int grp_size_small = nthr / grp_count; + const int n_grp_big = nthr % grp_count; + const int threads_in_big_groups = n_grp_big * grp_size_big; + + const int ithr_bound_distance = ithr - threads_in_big_groups; + T grp, grp_ithr, grp_nthr; + if (ithr_bound_distance < 0) { // ithr in first groups + grp = ithr / grp_size_big; + grp_ithr = ithr % grp_size_big; + grp_nthr = grp_size_big; + } else { // ithr in last groups + grp = n_grp_big + ithr_bound_distance / grp_size_small; + grp_ithr = ithr_bound_distance % grp_size_small; + grp_nthr = grp_size_small; + } + + balance211(nx, grp_count, grp, nx_start, nx_end); + balance211(ny, grp_nthr, grp_ithr, ny_start, ny_end); +} +} +/* convolution forward */ + +template +void jit_avx512_common_1x1_convolution_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + auto scratchpad = this->scratchpad(ctx); + + const auto &jcp = kernel_->jcp; + if (pd()->wants_padded_bias()) { + auto padded_bias = scratchpad.template get( + key_conv_padded_bias); + utils::array_copy(padded_bias, bias, jcp.oc_without_padding); + utils::array_set(padded_bias + jcp.oc_without_padding, 0.f, + jcp.oc - jcp.oc_without_padding); + bias = padded_bias; + } + + parallel(0, [&](const int ithr, const int nthr) { + execute_forward_thr(ithr, nthr, src, weights, bias, dst, scratchpad); + }); + + if (pd()->wants_zero_pad_dst()) + ctx.memory(MKLDNN_ARG_DST)->zero_pad(); +} + +template +void jit_avx512_common_1x1_convolution_fwd_t:: +execute_forward_thr(const int ithr, const int nthr, const src_data_t *src, + const wei_data_t *weights, const dst_data_t *bias, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + auto rtus_space = scratchpad.get(key_conv_rtus_space); + + const int ndims = src_d.ndims(); + const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0]; + const int stride_w = pd()->desc()->strides[ndims - 3]; + const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0]; + const int pad_l = pd()->desc()->padding[0][ndims - 3]; + + const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast; + + auto step = [](int default_step, int remaining, int tail_step) { + assert(default_step <= tail_step); + return remaining < tail_step ? remaining : default_step; + }; + + auto p = jit_1x1_conv_call_s(); + + auto rp = rtus_driver_t::call_params_t(); + + const int nb_oc = jcp.nb_load; + const int nb_ic = jcp.nb_reduce; + const int nb_ic_blocking = jcp.nb_reduce_blocking; + const int os_block = jcp.bcast_block; + + int bcast_start{0}, bcast_end{0}, ocb_start{0}, ocb_end{0}; + balance2D(nthr, ithr, work_amount, bcast_start, bcast_end, + jcp.nb_load, ocb_start, ocb_end, jcp.load_grp_count); + + auto init_bcast = [&](int iwork, int &n, int &g, int &bcast_step, + int &oh, int &ow, int &ih, int &iw) + { + int osb{0}; + nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb, + jcp.nb_bcast); + bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb, + jcp.nb_bcast_blocking_max); + bcast_step = nstl::min(bcast_step, bcast_end - iwork); + + const int os = osb * os_block; + oh = os / jcp.ow; + ow = os % jcp.ow; + + ih = nstl::max(oh * stride_h - pad_t, 0); + iw = nstl::max(ow * stride_w - pad_l, 0); + rp.iw_start = iw; + + p.bcast_dim = this_block_size(os, jcp.os, + bcast_step * os_block); + rp.os = p.bcast_dim; + }; + + auto init_load = [&](int ocb, int &load_step) + { + load_step = step(jcp.nb_load_blocking, ocb_end - ocb, + jcp.nb_load_blocking_max); + p.load_dim = this_block_size(ocb * jcp.oc_block, + ocb_end * jcp.oc_block, load_step * jcp.oc_block); + }; + + auto init_reduce = [&](int icb) + { + const int nb_ic_blocking_step = + nstl::min(icb + nb_ic_blocking, nb_ic) - icb; + p.first_last_flag = 0 + | (icb == 0 ? FLAG_REDUCE_FIRST : 0) + | (icb + nb_ic_blocking_step >= nb_ic + ? FLAG_REDUCE_LAST : 0); + + p.reduce_dim = this_block_size(icb * jcp.ic_block, + jcp.ic, nb_ic_blocking_step * jcp.ic_block); + rp.icb = p.reduce_dim / jcp.reduce_block; + }; + + auto inner_ker = [&](int ocb, int icb, int n, int g, int oh, int ow, + int ih, int iw) + { + + const int _ocb = g * nb_oc + ocb; + const size_t dst_off = data_blk_off(dst_d, n, _ocb, oh, ow); + + p.output_data = &dst[dst_off]; + p.bias_data = &bias[_ocb * jcp.oc_block]; + p.load_data = &weights[pd()->with_groups() + ? weights_d.blk_off(g, ocb, icb) + : weights_d.blk_off(ocb, icb)]; + + const int _icb = g * nb_ic + icb; + if (pd()->rtus_.reduce_src_) { + rp.ws = rtus_space + ithr * pd()->rtus_.space_per_thread_ + + _icb * jcp.is * jcp.ic_block; + if (ocb == ocb_start) { + rp.src = src + data_blk_off(src_d, n, _icb, ih, iw); + rtus_driver_->ker_(&rp); + } + p.bcast_data = rp.ws; + } else + p.bcast_data = src + data_blk_off(src_d, n, _icb, ih, iw); + + kernel_->jit_ker(&p); + }; + + if (jcp.loop_order == loop_rlb) { + for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) { + init_reduce(icb); + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + inner_ker(ocb, icb, n, g, oh, ow, ih, iw); + iwork += bcast_step; + } + ocb += load_step; + } + } + } else if (jcp.loop_order == loop_lbr) { + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) { + init_reduce(icb); + inner_ker(ocb, icb, n, g, oh, ow, ih, iw); + } + iwork += bcast_step; + } + ocb += load_step; + } + } else if (jcp.loop_order == loop_rbl) { + for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) { + init_reduce(icb); + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + inner_ker(ocb, icb, n, g, oh, ow, ih, iw); + ocb += load_step; + } + iwork += bcast_step; + } + } + } else if (jcp.loop_order == loop_blr) { + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) { + init_reduce(icb); + inner_ker(ocb, icb, n, g, oh, ow, ih, iw); + } + ocb += load_step; + } + iwork += bcast_step; + } + } else { + assert(!"unsupported loop order"); + } +} + + +template struct jit_avx512_common_1x1_convolution_fwd_t; +/* convolution backward wtr data */ + +template +void jit_avx512_common_1x1_convolution_bwd_data_t::execute_backward_data(const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + + const auto &jcp = kernel_->jcp; + auto rtus_space = scratchpad(ctx).template get( + key_conv_rtus_space); + + const int ndims = diff_src_d.ndims(); + + // TODO (Roma): remove this restriction + assert(jcp.stride_w == 1 && jcp.stride_h == 1); + + const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0]; + const int stride_w = pd()->desc()->strides[ndims - 3]; + const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0]; + const int pad_l = pd()->desc()->padding[0][ndims - 3]; + + const int nb_ic = jcp.nb_load; + const int nb_oc = jcp.nb_reduce; + const int os_block = jcp.bcast_block; + const int nb_oc_blocking = jcp.nb_reduce_blocking; + + const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast; + + auto step = [](int default_step, int remaining, int tail_step) { + assert(default_step <= tail_step); + return remaining < tail_step ? remaining : default_step; + }; + + parallel(0, [&](const int ithr, const int nthr) { + auto p = jit_1x1_conv_call_s(); + auto rp = rtus_driver_t::call_params_t(); + + int bcast_start{0}, bcast_end{0}, icb_start{0}, icb_end{0}; + balance2D(nthr, ithr, work_amount, bcast_start, bcast_end, + jcp.nb_load, icb_start, icb_end, jcp.load_grp_count); + + bool reduce_outer = (jcp.loop_order == loop_rbl + || jcp.loop_order == loop_rlb); + int nboc_outer = reduce_outer ? nb_oc : 1; + int ocb_outer_step = reduce_outer ? nb_oc_blocking : 1; + + int nboc_inner = reduce_outer ? 1 : nb_oc; + int ocb_inner_step = reduce_outer ? 1 : nb_oc_blocking; + + for (int ocb_outer = 0; ocb_outer < nboc_outer; + ocb_outer += ocb_outer_step) { + size_t cur_ocb_outer = + nstl::min(ocb_outer + ocb_outer_step, nboc_outer) - ocb_outer; + + int load_step = 0; + for (int icb = icb_start; icb < icb_end; icb += load_step) { + load_step = step(jcp.nb_load_blocking, jcp.nb_load - icb, + jcp.nb_load_blocking_max); + + p.load_dim = this_block_size(icb * jcp.ic_block, + icb_end * jcp.ic_block, load_step * jcp.ic_block); + rp.icb = p.load_dim / jcp.ic_block; + + int bcast_step; + for (int iwork = bcast_start; iwork < bcast_end; + iwork += bcast_step) + { + int n{0}, g{0}, osb{0}; + nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb, + jcp.nb_bcast); + + bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb, + jcp.nb_bcast_blocking_max); + bcast_step = nstl::min(bcast_step, bcast_end - iwork); + + const int os = osb * os_block; + p.bcast_dim = this_block_size(os, jcp.os, + bcast_step * os_block); + rp.os = p.bcast_dim; + + const int oh = os / jcp.ow; + const int ow = os % jcp.ow; + const int ih = nstl::max(oh * stride_h - pad_t, 0); + const int iw = nstl::max(ow * stride_w - pad_l, 0); + rp.iw_start = iw; + + const int _icb = g * nb_ic + icb; + rp.src = diff_src + data_blk_off(diff_src_d, n, _icb, ih, iw); + if (pd()->rtus_.reduce_src_) { + rp.ws = rtus_space + + ithr * pd()->rtus_.space_per_thread_; + p.output_data = rp.ws; + } else + p.output_data = rp.src; + + for (int ocb_inner = 0; ocb_inner < nboc_inner; + ocb_inner += ocb_inner_step) { + int cur_ocb_inner = + nstl::min(ocb_inner + ocb_inner_step, nboc_inner) - + ocb_inner; + + int ocb = reduce_outer ? ocb_outer : ocb_inner; + int nb_oc_blocking_step = reduce_outer + ? cur_ocb_outer : cur_ocb_inner; + const int _ocb = g * nb_oc + ocb; + size_t diff_dst_off = data_blk_off(diff_dst_d, n, _ocb, oh, ow); + p.bcast_data = &diff_dst[diff_dst_off]; + + p.load_data = &weights[pd()->with_groups() + ? weights_d.blk_off(g, ocb, icb) + : weights_d.blk_off(ocb, icb)]; + + p.first_last_flag = ocb == 0 ? FLAG_REDUCE_FIRST : 0; + + p.reduce_dim = this_block_size(ocb * jcp.oc_block, + jcp.oc, nb_oc_blocking_step * jcp.oc_block); + + kernel_->jit_ker(&p); + } + if (pd()->rtus_.reduce_src_) + rtus_driver_->ker_(&rp); + } + } + } + }); +} + +template struct jit_avx512_common_1x1_convolution_bwd_data_t; + +/* convolution backward wtr weights */ + +#define wht_blk_off(d, g, ...) \ + (pd()->with_groups() \ + ? (d).blk_off((g), __VA_ARGS__) \ + : (d).blk_off(__VA_ARGS__)) + +jit_avx512_common_1x1_convolution_bwd_weights_t :: + jit_avx512_common_1x1_convolution_bwd_weights_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr), acc_ker_(nullptr), reducer_bias_(nullptr) + , trans_kernel_(nullptr), rtus_driver_(nullptr) +{ + kernel_ = new jit_avx512_common_1x1_conv_kernel(pd()->jcp_, *pd()->attr()); + acc_ker_ = new cpu_accumulator_1d_t(); + reducer_bias_ = new cpu_reducer_t(pd()->reducer_bia_conf_); + init_rtus_driver(this); + + const auto &jcp = kernel_->jcp; + + if (jcp.transpose_src) { + auto tp = jit_transpose4x16_src_t(); + tp.src_pf0_distance = 4; + tp.tr_src_pf0_distance = 0; + tp.src_pf1 = true; + tp.tr_src_pf1 = false; + trans_kernel_ = new jit_transpose4x16_src(&jcp, &tp); + } +} + +void jit_avx512_common_1x1_convolution_bwd_weights_t::execute_backward_weights( + const exec_ctx_t &ctx) const +{ + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias_in = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + + const auto &jcp = kernel_->jcp; + + const auto scratchpad = this->scratchpad(ctx); + + auto rtus_space = scratchpad.get(key_conv_rtus_space); + data_t *diff_bias = pd()->wants_padded_bias() + ? scratchpad.get(key_conv_padded_bias) : diff_bias_in; + auto wei_reduction = scratchpad.get(key_conv_wei_reduction); + + /* prepare src transposition barriers */ + auto tr_src = scratchpad.get(key_conv_tr_src); + auto tr_src_bctx = scratchpad.get( + key_conv_tr_src_bctx); + if (jcp.transpose_src) { + for (int i = 0; i < jcp.nthr; ++i) + simple_barrier::ctx_init(&tr_src_bctx[i]); + } + + const int ndims = src_d.ndims(); + const int wei_size = jcp.ngroups * jcp.oc * jcp.ic; + + simple_barrier::ctx_t reduction_barrier; + simple_barrier::ctx_init(&reduction_barrier); + + const auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad, + prefix_reducer_bia); + auto rb = this->reducer_bias_; + rb->init(reducer_bia_scratchpad); + + // TODO (Roma): remove this restriction + assert(jcp.stride_w == 1 && jcp.stride_h == 1); + + const int nb_ic = jcp.nb_bcast; + const int nb_ic_blocking = jcp.nb_bcast_blocking; + + const int nb_oc = jcp.nb_load; + const int nb_oc_blocking = jcp.nb_load_blocking; + + const int sp_nb = jcp.nb_reduce; + const int mb_sp_work = jcp.mb * sp_nb; + + const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0]; + const int stride_w = pd()->desc()->strides[ndims - 3]; + const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0]; + const int pad_l = pd()->desc()->padding[0][ndims - 3]; + + auto step = [](int default_step, int remaining, int tail_step) { + assert(default_step <= tail_step); + return remaining < tail_step ? remaining : default_step; + }; + + // TODO: use memory descriptor with the same fmt as src + // (or use a macro :)) + auto tr_src_off = [&](int img, int icb, int is) { + const size_t tr_chn_size = jcp.tr_is * jcp.ic_block; + const size_t tr_img_size = tr_chn_size * nb_ic * jcp.ngroups; + return img * tr_img_size + icb * tr_chn_size + is * jcp.ic_block; + }; + + auto uker_trans = [&](int ithr_mb, int img, int sp_b_start, int sp_size, + int g_start, int g_work, int ic_b_start, int ic_b_work, + int ithr, int nthr, int first_ic_b) + { + const int work_amount = g_work * ic_b_work; + + int start{ 0 }, end{ 0 }; + balance211(work_amount, nthr, ithr, start, end); + + int g{ 0 }, ic_b{ 0 }; + nd_iterator_init(start, g, g_work, ic_b, ic_b_work); + g += g_start; + const int ic_b_tr = g * nb_ic + first_ic_b + ic_b; + ic_b += ic_b_start; + + const int _ic = g * nb_ic + ic_b; + + const int is = sp_b_start * jcp.reduce_block; + const int ih = is / jcp.iw; + const int iw = is % jcp.iw; + + const int src1_off = data_blk_off(src_d, img, _ic, ih, iw); + data_t *src1 = (data_t *)&src[src1_off]; + data_t *tr_src1 = &tr_src[tr_src_off(ithr_mb, ic_b_tr, is)]; + + assert(jcp.ic_block == 16); + const int src_stride = jcp.is * jcp.ic_block; + const int tr_src_stride = jcp.tr_is * jcp.ic_block; + + const int my_work = end - start; + for (int iwork = 0; iwork < my_work; iwork++) { + auto par_trans = jit_src_transpose_s(); + assert(sp_size % 4 == 0 || sp_size % 4 == jcp.is % 4); + par_trans.size = sp_size; + par_trans.src = src1; + par_trans.tr_src = tr_src1; + par_trans.src_prf = src1 + 64 * 16; + par_trans.tr_src_prf = tr_src1 + 80 * 16; + trans_kernel_->jit_ker(&par_trans); + + src1 += src_stride; + tr_src1 += tr_src_stride; + } + }; + + auto ker = [&](const int ithr, const int nthr) { + assert(nthr == jcp.nthr); + assert(IMPLICATION(!mkldnn_thr_syncable(), jcp.nthr_mb == 1)); + + const int ithr_ic_b = ithr % jcp.nthr_ic_b; + const int ithr_oc_b = ithr / jcp.nthr_ic_b % jcp.nthr_oc_b; + const int ithr_g = ithr / jcp.nthr_ic_b / jcp.nthr_oc_b % jcp.nthr_g; + const int ithr_mb = ithr / jcp.nthr_ic_b / jcp.nthr_oc_b / + jcp.nthr_g; + + const int ithr_but_oc + = (ithr_mb * jcp.nthr_g + ithr_g) * jcp.nthr_ic_b + ithr_ic_b; + + /* reduction dimension */ + int mb_sp_b_start{ 0 }, mb_sp_b_end{ 0 }; + if (jcp.transpose_src && jcp.nthr_mb < jcp.mb / 2) { + // it's preferable to parallelize by mb if possible + int img_start{ 0 }, img_end{ 0 }; + balance211(jcp.mb, jcp.nthr_mb, ithr_mb, img_start, img_end); + mb_sp_b_start = img_start * sp_nb; + mb_sp_b_end = img_end * sp_nb; + } + else { + balance211(mb_sp_work, jcp.nthr_mb, ithr_mb, mb_sp_b_start, + mb_sp_b_end); + } + + /* independent dimensions */ + int g_start{ 0 }, oc_b_start{ 0 }, ic_b_start{ 0 }; + int g_end{ 0 }, oc_b_end{ 0 }, ic_b_end{ 0 }; + + balance211(jcp.ngroups, jcp.nthr_g, ithr_g, g_start, g_end); + balance211(jcp.nb_load, jcp.nthr_oc_b, ithr_oc_b, oc_b_start, + oc_b_end); + balance211(jcp.nb_bcast, jcp.nthr_ic_b, ithr_ic_b, ic_b_start, + ic_b_end); + + const int g_work = g_end - g_start; + const int oc_b_work = oc_b_end - oc_b_start; + const int ic_b_work = ic_b_end - ic_b_start; + + data_t *diff_wei = ithr_mb == 0 + ? diff_weights : wei_reduction + (ithr_mb - 1) * wei_size; + + int sp_b_step = 0; + for (int mb_sp_b = mb_sp_b_start; mb_sp_b < mb_sp_b_end; + mb_sp_b += sp_b_step) { + int img{ 0 }, sp_b{ 0 }; + nd_iterator_init(mb_sp_b, img, jcp.mb, sp_b, sp_nb); + sp_b_step = step(jcp.nb_reduce_blocking, + nstl::min(sp_nb - sp_b, mb_sp_b_end - mb_sp_b), + jcp.nb_reduce_blocking_max); + + for (int g = g_start; g < g_end; ++g) { + int load_step = 0; + int bcast_step = 0; + for (int ic_b = ic_b_start; ic_b < ic_b_end; + ic_b += bcast_step) { + bcast_step = step(nb_ic_blocking, ic_b_end - ic_b, + jcp.nb_bcast_blocking_max); + if (jcp.transpose_src) { + if (jcp.nthr_oc_b > 1) + simple_barrier::barrier( + &tr_src_bctx[ithr_but_oc], jcp.nthr_oc_b); + const int sp_size + = nstl::min(sp_b_step * jcp.reduce_block, + jcp.is - sp_b * jcp.reduce_block); + uker_trans(ithr_mb, img, sp_b, sp_size, g, 1, ic_b, + bcast_step, ithr_oc_b, jcp.nthr_oc_b, ic_b_start); + if (jcp.nthr_oc_b > 1) + simple_barrier::barrier( + &tr_src_bctx[ithr_but_oc], jcp.nthr_oc_b); + } + + for (int oc_b = oc_b_start; oc_b < oc_b_end; + oc_b += load_step) { + load_step = step(nb_oc_blocking, oc_b_end - oc_b, + jcp.nb_load_blocking_max); + const int _ic_b = g * nb_ic + ic_b; + const int _ic_b_tr = g * nb_ic + ic_b_start; + const int _oc_b = g * nb_oc + oc_b; + + data_t *store_to; + + const size_t off + = wht_blk_off(diff_weights_d, g, oc_b, ic_b); + store_to = diff_wei + off; + + const data_t *diff_src = jcp.transpose_src ? + &tr_src[tr_src_off(ithr_mb, _ic_b_tr, 0)] : + &src[src_d.blk_off(img, _ic_b)]; + + int sp_b_end = sp_b + sp_b_step; + const data_t *pdiff_dst + = &diff_dst[diff_dst_d.blk_off(img, _oc_b)]; + const data_t *local_src = diff_src; + + auto p = jit_1x1_conv_call_s(); + auto rp = rtus_driver_t::call_params_t(); + + p.output_stride + = jcp.ic * jcp.oc_block * jcp.typesize_out; + + p.load_dim = load_step * jcp.oc_block; + + p.bcast_dim = bcast_step * jcp.ic_block; + rp.icb = bcast_step; + p.output_data = store_to; + + p.reduce_dim = sp_b_step * jcp.reduce_block; + rp.os = p.reduce_dim; + + p.first_last_flag = 0 + | (mb_sp_b == mb_sp_b_start ? FLAG_REDUCE_FIRST : 0) + | (sp_b_end == sp_nb ? FLAG_SP_LAST : 0); + + int sp = sp_b * jcp.reduce_block; + p.load_data = pdiff_dst + sp * jcp.oc_block; + + if (pd()->rtus_.reduce_src_) { + const int oh = sp / jcp.ow; + const int ow = sp % jcp.ow; + + const int ih = nstl::max(oh * stride_h - pad_t, 0); + const int iw = nstl::max(ow * stride_w - pad_l, 0); + rp.iw_start = iw; + + rp.ws = rtus_space + + ithr * pd()->rtus_.space_per_thread_ + + sp * jcp.ic_block; + + if (ndims == 3) + rp.src = local_src + iw + * src_d.blocking_desc().strides[2]; + else + rp.src = local_src + ih + * src_d.blocking_desc().strides[2] + + iw * src_d.blocking_desc().strides[3]; + rtus_driver_->ker_(&rp); + + p.bcast_data = rp.ws; + } else + p.bcast_data = local_src + sp * jcp.ic_block; + + kernel_->jit_ker(&p); + } + } + } + } + + /* diff_weights[:] += sum(wei_reduction[thr_mb][:]) */ + if (jcp.nthr_mb > 1) { + simple_barrier::barrier(&reduction_barrier, jcp.nthr); + const int work = g_work * oc_b_work * ic_b_work; + int start{ 0 }, end{ 0 }; + balance211(work, jcp.nthr_mb, ithr_mb, start, end); + if (start == end) + return; + + for (int thr_mb = 1; thr_mb < jcp.nthr_mb; ++thr_mb) { + int w = start; + int sub_g_start{ 0 }, sub_oc_b_start{ 0 }, + sub_ic_b_start{ 0 }; + nd_iterator_init(w, sub_g_start, g_work, sub_oc_b_start, + oc_b_work, sub_ic_b_start, ic_b_work); + while (w < end) { + const int g = g_start + sub_g_start; + const int oc_b = oc_b_start + sub_oc_b_start; + const int ic_b = ic_b_start + sub_ic_b_start; + + const int acc_size + = nstl::min(end - w, ic_b_work - sub_ic_b_start) + * jcp.ic_block * jcp.oc_block; + + const size_t off + = wht_blk_off(diff_weights_d, g, oc_b, ic_b); + data_t *d = diff_weights + off; + data_t *s = wei_reduction + (thr_mb - 1) * wei_size + off; + + acc_ker_->accumulate(d, s, acc_size); + + nd_iterator_jump(w, end, sub_g_start, g_work, + sub_oc_b_start, oc_b_work, sub_ic_b_start, + ic_b_work); + } + } + } + }; + + auto ker_bias = [&](int ithr, int nthr) { + assert(nthr == rb->balancer().nthr_); + + const int b_job_start = rb->balancer().ithr_job_off(ithr); + const int b_njobs = rb->balancer().ithr_njobs(ithr); + + if (b_njobs == 0) + return; + + /* reduction dimension */ + int img_start{ 0 }, img_end{ 0 }; + + balance211(jcp.mb, rb->balancer().nthr_per_group_, + rb->balancer().id_in_group(ithr), img_start, img_end); + + /* jobs */ + int g_start{ 0 }, ocb_start{ 0 }; + nd_iterator_init( + b_job_start, g_start, jcp.ngroups, ocb_start, jcp.nb_load); + + for (int img = img_start; img < img_end; ++img) { + int g = g_start, ocb = ocb_start; + for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) { + const size_t _oc = g * jcp.nb_load + ocb; + + const data_t *d_dst = &diff_dst[diff_dst_d.blk_off(img, _oc)]; + data_t *d_bias = rb->get_local_ptr(ithr, diff_bias, + reducer_bia_scratchpad) + + b_job_loc * rb->balancer().job_size_; + + if (img == img_start) + for (int o = 0; o < 16; ++o) + d_bias[o] = 0.; + + for (int hw = 0; hw < jcp.oh * jcp.ow; ++hw) { + PRAGMA_OMP_SIMD() + for (int o = 0; o < 16; ++o) + d_bias[o] += d_dst[o]; + d_dst += 16; + } + + nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_load); + } + } + rb->reduce(ithr, diff_bias, reducer_bia_scratchpad); + }; + + parallel(jcp.nthr, [&](const int ithr, const int nthr) { + ker(ithr, jcp.nthr); + if (pd()->with_bias()) + ker_bias(ithr, jcp.nthr); + }); + + /* TODO: put this in ker_bias */ + if (pd()->wants_padded_bias()) { + assert(jcp.ngroups == 1); + utils::array_copy(diff_bias_in, diff_bias, jcp.oc_without_padding); + } +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp new file mode 100644 index 0000000000..2e9fda76d6 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp @@ -0,0 +1,344 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_COMMON_1x1_CONVOLUTION_HPP +#define CPU_JIT_AVX512_COMMON_1x1_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" +#include "cpu_reducer.hpp" + +#include "jit_avx512_common_1x1_conv_kernel.hpp" +#include "jit_uni_1x1_conv_utils.hpp" +#include "jit_transpose_src_utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_avx512_common_1x1_convolution_fwd_t : public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_(), rtus_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_1x1:", avx512_common, ""), + jit_avx512_common_1x1_convolution_fwd_t); + + status_t init() { + using namespace utils; + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, wei_type, dst_type, dst_type, + data_type::undef) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + const convolution_desc_t *conv_d = desc(); + const memory_desc_t *src_d = src_md(); + rtus_prepare(this, conv_d, src_d, dst_md()); + + status_t status = jit_avx512_common_1x1_conv_kernel::init_conf( + jcp_, *conv_d, *src_d, *weights_md(), *dst_md(), *attr(), + mkldnn_get_max_threads(), rtus_.reduce_src_); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_common_1x1_conv_kernel::init_scratchpad(scratchpad, + jcp_); + + rtus_prepare_space_info(this, scratchpad); + + return status::success; + } + + jit_1x1_conv_conf_t jcp_; + reduce_to_unit_stride_t rtus_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c); + auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(), + OIw16i16o, gOIw16i16o, OIhw16i16o, gOIhw16i16o); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + template + friend void init_rtus_driver(conv_t *self); + + jit_avx512_common_1x1_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr), rtus_driver_(nullptr) + { + kernel_ = + new jit_avx512_common_1x1_conv_kernel(pd()->jcp_, *pd()->attr()); + init_rtus_driver(this); + } + + ~jit_avx512_common_1x1_convolution_fwd_t() { + delete kernel_; + delete rtus_driver_; + } + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + + private: + void execute_forward(const exec_ctx_t &ctx) const; + void execute_forward_thr(const int ithr, const int nthr, + const src_data_t *src, const wei_data_t *weights, + const dst_data_t *bias, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_common_1x1_conv_kernel *kernel_; + rtus_driver_t *rtus_driver_; +}; + +using jit_avx512_common_1x1_convolution_fwd_f32_t + = jit_avx512_common_1x1_convolution_fwd_t; + +template +struct jit_avx512_common_1x1_convolution_bwd_data_t : public cpu_primitive_t { + struct pd_t : public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_(), rtus_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_1x1:", avx512_common, ""), + jit_avx512_common_1x1_convolution_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(diff_src_type, wei_type, data_type::undef, + diff_dst_type, data_type::undef) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + const convolution_desc_t *conv_d = desc(); + const memory_desc_t *diff_src_d = diff_src_md(); + rtus_prepare(this, conv_d, diff_src_d, diff_dst_md()); + + status_t status = jit_avx512_common_1x1_conv_kernel::init_conf( + jcp_, *conv_d, *diff_src_d, *weights_md(), *diff_dst_md(), + *attr(), mkldnn_get_max_threads(), rtus_.reduce_src_); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_common_1x1_conv_kernel::init_scratchpad(scratchpad, + jcp_); + + rtus_prepare_space_info(this, scratchpad); + + return status::success; + } + + // TODO (Roma): structs conf header cleanup + jit_1x1_conv_conf_t jcp_; + reduce_to_unit_stride_t rtus_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c); + auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(), + IOw16o16i, gIOw16o16i, IOhw16o16i, gIOhw16o16i); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + template + friend void init_rtus_driver(conv_t *self); + + jit_avx512_common_1x1_convolution_bwd_data_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr), rtus_driver_(nullptr) + { + kernel_ = new jit_avx512_common_1x1_conv_kernel(pd()->jcp_, + *pd()->attr()); + init_rtus_driver(this); + } + + ~jit_avx512_common_1x1_convolution_bwd_data_t() { + delete kernel_; + delete rtus_driver_; + } + + typedef typename prec_traits::type diff_dst_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type diff_src_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + + private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_common_1x1_conv_kernel *kernel_; + rtus_driver_t *rtus_driver_; +}; + +using jit_avx512_common_1x1_convolution_bwd_data_f32_t + = jit_avx512_common_1x1_convolution_bwd_data_t; + +struct jit_avx512_common_1x1_convolution_bwd_weights_t : public cpu_primitive_t +{ + struct pd_t : public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_(), rtus_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_1x1:", avx512_common, ""), + jit_avx512_common_1x1_convolution_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + const convolution_desc_t *conv_d = desc(); + const memory_desc_t *src_d = src_md(); + rtus_prepare(this, conv_d, src_d, diff_dst_md()); + + status_t status = jit_avx512_common_1x1_conv_kernel::init_conf( + jcp_, *conv_d, *src_d, *diff_weights_md(), *diff_dst_md(), + *attr(), mkldnn_get_max_threads(), rtus_.reduce_src_); + if (status != status::success) return status; + + init_balancers(); + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_common_1x1_conv_kernel::init_scratchpad(scratchpad, + jcp_); + + auto reducer_bia_scratchpad = memory_tracking::registrar_t( + scratchpad, memory_tracking::names::prefix_reducer_bia); + reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad); + + rtus_prepare_space_info(this, scratchpad); + + return status::success; + } + + // TODO (Roma): structs conf header cleanup + jit_1x1_conv_conf_t jcp_; + cpu_reducer_t::conf_t reducer_bia_conf_; + reduce_to_unit_stride_t rtus_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c); + auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(), + OIw16i16o, gOIw16i16o, OIhw16i16o, gOIhw16i16o); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + + private: + void init_balancers() { + const size_t max_buffer_size = jcp_.nthr * 3 * 5 * 5 * 16 * 16; + if (with_bias()) { + reducer_bia_conf_.init(reduce_balancer_t(jcp_.nthr, + jcp_.oc_block, jcp_.ngroups * jcp_.nb_load, + jcp_.mb, max_buffer_size)); + } + } + }; + + template + friend void init_rtus_driver(conv_t *self); + + jit_avx512_common_1x1_convolution_bwd_weights_t(const pd_t *apd); + + ~jit_avx512_common_1x1_convolution_bwd_weights_t() { + delete kernel_; + delete acc_ker_; + delete reducer_bias_; + delete rtus_driver_; + delete trans_kernel_; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + + private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_common_1x1_conv_kernel *kernel_; + cpu_accumulator_1d_t *acc_ker_; + cpu_reducer_t *reducer_bias_; + jit_transpose4x16_src *trans_kernel_; + rtus_driver_t *rtus_driver_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp new file mode 100644 index 0000000000..235fb02fef --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp @@ -0,0 +1,4539 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_barrier.hpp" + +#include "jit_avx512_common_conv_kernel.hpp" + +#define GET_OFF(field) offsetof(jit_conv_call_s, field) +#define KNx_L2_EFFECTIVE_CAPACITY ((512-64)*1024) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; +using namespace Xbyak; + +namespace { + +constexpr auto small_spatial = 14; +unsigned int L1_cache_size = get_cache_size(1, true); + +inline void pick_loop_order(jit_conv_conf_t &jcp) { + using namespace prop_kind; + assert(one_of(jcp.prop_kind, + forward_training, forward_inference, backward_data)); + auto w = (jcp.prop_kind == backward_data) ? jcp.iw : jcp.ow; + auto h = (jcp.prop_kind == backward_data) ? jcp.ih : jcp.oh; + + // ow-threading is currently implemented for forward only + // TODO: single code for fwd and bwd after ow-thr for bwd + // meaningless switch was removed + if (jcp.prop_kind == backward_data) { + jcp.loop_order = (w <= small_spatial && h <= small_spatial) + ? loop_cgn : loop_gnc; + } else { + jcp.loop_order = (w <= small_spatial && h <= small_spatial) + ? loop_cwgn : loop_gncw; + } +} + +inline bool is_1stconv(const jit_conv_conf_t &jcp) { + if (mayiuse(avx512_core)) + return (jcp.ic < 16 && jcp.ngroups == 1); + else + return one_of(jcp.ic, 1, 3); +} + +inline bool is_ow_threading_on(const jit_conv_conf_t &jcp) { + return (jcp.nb_ow > 1); +} + +inline bool is_owb_prefetching(const jit_conv_conf_t &jcp) { + return (jcp.ver == ver_4fma && is_ow_threading_on(jcp)); +} + +} + +template +void _jit_avx512_common_conv_fwd_kernel::prepare_output(int ur_w) +{ + for (int k = 0; k < jcp.nb_oc_blocking; k++) + for (int j = 0; j < ur_w; j++) { + Vmm vmm = vmm_out(j, k); + vpxord(vmm, vmm, vmm); + if (!is_owb_prefetching(jcp)) { + size_t aux_output_offset = get_output_offset(j, k); + mic_prefetcht1(EVEX_compress_addr_safe(reg_out_prf, + aux_output_offset, reg_out_long_offt)); + } + } +} + +template +void _jit_avx512_common_conv_fwd_kernel::store_output(int ur_w) +{ + Label no_update_label, store_label, eltwise_label; + + mov(reg_channel, ptr[param1 + GET_OFF(channel)]); + if (jcp.with_bias) { + mov(reg_bias, ptr[param1 + GET_OFF(bias)]); + } + + if (!jcp.with_sum) { + cmp(reg_channel, 0); + je(no_update_label, T_NEAR); + } + + for (int k = 0; k < jcp.nb_oc_blocking; k++) + for (int j = 0; j < ur_w; j++) { + Vmm vmm = vmm_out(j, k); + size_t aux_output_offset = get_output_offset(j, k); + vaddps(vmm, + make_safe_addr(reg_out, aux_output_offset, reg_out_long_offt)); + } + + if (!jcp.with_sum) { + jmp(eltwise_label, T_NEAR); + } else { + cmp(reg_channel, 0); + jne(eltwise_label, T_NEAR); + } + + L(no_update_label); + if (jcp.with_bias) { + for (int k = 0; k < jcp.nb_oc_blocking; k++) { + int bias_offset = jcp.typesize_out * k * jcp.oc_block; + for (int j = 0; j < ur_w; j++) { + Vmm vmm = vmm_out(j, k); + vaddps(vmm, EVEX_compress_addr(reg_bias, bias_offset)); + } + mic_prefetcht1(EVEX_compress_addr(reg_bias, bias_offset + 64)); + } + } + + L(eltwise_label); + if (jcp.with_eltwise) { + cmp(reg_channel, jcp.nb_ic - 1); + jl(store_label, T_NEAR); + + if (ur_w == jcp.ur_w) { + eltwise_injector_->compute_vector_range(0, + jcp.nb_oc_blocking * jcp.ur_w); + } else { + for (int k = 0; k < jcp.nb_oc_blocking; k++) + eltwise_injector_->compute_vector_range(k * jcp.ur_w, + k * jcp.ur_w + ur_w); + } + } + + L(store_label); + for (int k = 0; k < jcp.nb_oc_blocking; k++) + for (int j = 0; j < ur_w; j++) { + Vmm vmm = vmm_out(j, k); + size_t aux_output_offset = (size_t)typesize * + ((size_t)k * jcp.od * jcp.oh * jcp.ow + j) * jcp.oc_block; + vmovups(EVEX_compress_addr_safe(reg_out, aux_output_offset, + reg_out_long_offt), vmm); + if (!is_owb_prefetching(jcp)) + mic_prefetcht0(EVEX_compress_addr_safe(reg_out_prf, + aux_output_offset, reg_out_long_offt)); + } +} + +template +void _jit_avx512_common_conv_fwd_kernel::compute_loop_4fma_1st(int ur_w, + int pad_l, int pad_r) +{ +} + +template<> +void _jit_avx512_common_conv_fwd_kernel::compute_loop_4fma_1st(int ur_w, + int pad_l, int pad_r) +{ + assert(jcp.dilate_d == 0 && jcp.dilate_h == 0 && jcp.dilate_w == 0); + + int iw = jcp.iw; + int ih = jcp.ih; + int kw = jcp.kw; + int stride_w = jcp.stride_w; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + + Label kh_label, kd_label; + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_inp, reg_inp); + mov(aux_reg_ker, reg_ker); + mov(aux_reg_inp_prf, reg_inp_prf); + } + + size_t max_input_offset = (size_t)jcp.typesize_in + * ((size_t)(kw + ur_w * stride_w - pad_l) + + (size_t)ic_block * iw * ih * jcp.id); + assert(reg_inp_prf == reg_long_offt); + if (max_input_offset > INT_MAX) push(reg_inp_prf); + + if (jcp.ndims == 5) { + push(reg_out_prf); + push(reg_out); + + mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]); + mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]); + mov(aux_reg_inp_d, reg_inp); + mov(aux_reg_inp_d_prf, reg_inp_prf); + + L(kd_label); + } + mov(reg_kj, reg_kh); + if (jcp.ndims == 5) { + mov(aux_reg_inp, aux_reg_inp_d); + mov(aux_reg_ker, aux_reg_ker_d); + mov(aux_reg_inp_prf, aux_reg_inp_d_prf); + } + + L(kh_label); + for (int ki = 0; ki < kw; ki += 4) { + for (int ic = 0; ic < ic_block; ic++) { + for (int i = 0; i < 4; i++) { + int aux_ker_offset + = jcp.typesize_in + * ((ki + i) * oc_block + + ic * kw * jcp.kh * jcp.kd * oc_block); + if (ki + i < kw) + vmovups(vmm_ker(i), + EVEX_compress_addr(aux_reg_ker, aux_ker_offset)); + else + vpxord(vmm_ker(i), vmm_ker(i), vmm_ker(i)); + } + + int j_start = get_ow_start(ki, pad_l); + int j_end = get_ow_end(ur_w, ki, pad_r); + + for (int j = j_start, prf_count=0; j < j_end; j++) { + size_t aux_input_offset = (size_t)jcp.typesize_in + * ((size_t)(ki + j * stride_w + - pad_l) + (size_t)ic * iw * ih * jcp.id); + v4fmaddps(vmm_out(j, 0), vmm_ker(0), + EVEX_compress_addr_safe(aux_reg_inp, aux_input_offset, + reg_long_offt)); + if (ki + prf_count < kw && prf_count < 4 + && ((ki < 2 && j % 4) || j % 2)) { + int aux_ker_offset = jcp.typesize_in + * ((ki + prf_count) * oc_block + + ic * kw * jcp.kh * jcp.kd * oc_block + kw * oc_block); + mic_prefetcht0(EVEX_compress_addr(aux_reg_ker, + aux_ker_offset)); + prf_count++; + } + if (ki == 0 + && j % (64 / (stride_w * jcp.typesize_in)) == 0) { + mic_prefetcht0(EVEX_compress_addr_safe(aux_reg_inp_prf, + aux_input_offset, reg_long_offt)); + } + if (ki == 1 + && j % (64 / (stride_w * jcp.typesize_in)) == 0) { + mic_prefetcht0(EVEX_compress_addr_safe(aux_reg_inp, + aux_input_offset+jcp.typesize_in * iw, reg_long_offt)); + } + } + } + } + add(aux_reg_ker, jcp.typesize_in * kw * oc_block); + add(aux_reg_inp, jcp.typesize_in * iw); + add(aux_reg_inp_prf, jcp.typesize_in * iw); + + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + + if (jcp.ndims == 5) { + add(aux_reg_inp_d, typesize * jcp.ih * jcp.iw); + add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * oc_block); + add(aux_reg_inp_d_prf, typesize * jcp.ih * jcp.iw); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_label, T_NEAR); + + pop(reg_out); + pop(reg_out_prf); + } + + if (max_input_offset > INT_MAX) pop(reg_inp_prf); +} + +template +void _jit_avx512_common_conv_fwd_kernel::compute_loop_4fma(int ur_w, + int pad_l, int pad_r) +{ +} + +template<> +void _jit_avx512_common_conv_fwd_kernel::compute_loop_4fma(int ur_w, + int pad_l, int pad_r) +{ + int stride_w = jcp.stride_w; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + Label kh_label, last_iter_label, loop_end_label, kd_label; + int ker_load_number = 4; + int shift_kernel_ptr = typesize * jcp.kw * jcp.oc_block * jcp.ic_block; + int shift_input_ptr = typesize * (jcp.dilate_h + 1) * jcp.iw * jcp.ic_block; + + bool check_last_kh = (jcp.kh > 3); + bool pref_current_inp = (jcp.iw < 14 || jcp.iw > 28); + + int oi_ipref_t0 = get_ow_start(0, pad_l); + int ow_end_ipref = get_ow_end(ur_w, 0, pad_r); + + assert(jcp.oc % jcp.nb_oc_blocking == 0); + + auto kernel_offset = [=](int ocb, int ic, int ki) { + int blk_idx = ocb * jcp.nb_ic * jcp.kh * jcp.kw * jcp.kd + ki; + int blk_offset = blk_idx * jcp.oc_block * jcp.ic_block; + int ic_offset = ic * jcp.oc_block; + return typesize * (blk_offset + ic_offset); + }; + auto kernel_loads = [=](int ki, int ic, int kk) { + for (int ii = 0; ii < ker_load_number; ii++) { + int aux_kernel_offset = kernel_offset(kk, ic + ii, ki); + vmovups(vmm_ker(ii), + EVEX_compress_addr(aux_reg_ker, aux_kernel_offset)); + } + }; + auto prefetch_inp_next_kh = [&](int ki, int ki_start, int cnt0, int cnt1) { + if (cnt1 >= ker_load_number && cnt0 >= ker_load_number + && ki >= ki_start && oi_ipref_t0 < ow_end_ipref) { + int aux_inp_offset + = typesize + * ((oi_ipref_t0 * stride_w - pad_l) * ic_block + + (jcp.dilate_h + 1) * jcp.iw * ic_block); + prefetcht0(EVEX_compress_addr(aux_reg_inp, + aux_inp_offset)); + oi_ipref_t0++; + } + }; + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_inp, reg_inp); + mov(aux_reg_ker, reg_ker); + mov(aux_reg_ker_prf, reg_ker_prf); + mov(aux_reg_inp_prf, reg_inp_prf); + } + + if (jcp.ndims == 5) { + push(reg_out_prf); + push(reg_out); + + mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]); + mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]); + mov(aux_reg_inp_d, reg_inp); + mov(aux_reg_inp_d_prf, reg_inp_prf); + mov(aux_reg_ker_d_prf, reg_ker_prf); + L(kd_label); + mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]); + } else { + mov(reg_kj, reg_kh); + } + if (jcp.ndims == 5) { + mov(aux_reg_inp, aux_reg_inp_d); + mov(aux_reg_ker, aux_reg_ker_d); + mov(aux_reg_ker_prf, aux_reg_ker_d_prf); + mov(aux_reg_inp_prf, aux_reg_inp_d_prf); + } + + align(16); + L(kh_label); + int kw = jcp.kw; + if (check_last_kh) { + for (int ki = 0; ki < kw; ki++) + for (int ic = 0; ic < ic_block; ic += 4) + for (int kk = 0; kk < jcp.nb_oc_blocking; kk++) { + bool last_kernel_loads = (kk == jcp.nb_oc_blocking - 1 + && ki == kw - 1 && (ic + 4) == ic_block); + + if (last_kernel_loads) { + cmp(reg_kj, 1); + je(last_iter_label, T_NEAR); + } + + kernel_loads(ki, ic, kk); + for (int oi = get_ow_start(ki, pad_l), prf_count_t1 = 0, + prf_count_t0 = 0; + oi < get_ow_end(ur_w, ki, pad_r); oi++) { + int aux_input_offset = typesize + * ((ki * (jcp.dilate_w + 1) + oi * stride_w + - pad_l) * ic_block + + ic); + v4fmaddps(vmm_out(oi, kk), vmm_ker(0), + EVEX_compress_addr(aux_reg_inp, aux_input_offset)); + + if (oi % 2) { + if (prf_count_t0 < 4) { + int aux_kernel_prf; + if (last_kernel_loads) + aux_kernel_prf= kernel_offset(0, + prf_count_t0 + ic + 4 + - ic_block, 0) + typesize * kw + * oc_block * ic_block; + else + aux_kernel_prf = kernel_offset(kk, ic + 4 + + prf_count_t0, ki); + mic_prefetcht0(EVEX_compress_addr(aux_reg_ker, + aux_kernel_prf)); + prf_count_t0++; + } else if (prf_count_t1 < 4) { + mic_prefetcht1(EVEX_compress_addr( + aux_reg_ker_prf, kernel_offset(kk, ic + + prf_count_t1, ki))); + prf_count_t1++; + } + } else + prefetch_inp_next_kh(ki, 2, prf_count_t0, + prf_count_t1); + } + + if (last_kernel_loads) { + jmp(loop_end_label, T_NEAR); + + L(last_iter_label); + + kernel_loads(ki, ic, kk); + for (int oi = get_ow_start(ki, pad_l), prf_count_t1 = 0, + prf_count_t0 = 0; + oi < get_ow_end(ur_w, ki, pad_r); oi++) { + int aux_input_offset = typesize + * ((ki * (jcp.dilate_w + 1) + oi * stride_w + - pad_l) * ic_block + + ic); + v4fmaddps(vmm_out(oi, kk), vmm_ker(0), + EVEX_compress_addr(aux_reg_inp, + aux_input_offset)); + if (oi % 2) { + if (prf_count_t0 < 4) { + mic_prefetcht0(EVEX_compress_addr( + aux_reg_ker_prf, kernel_offset(0, + prf_count_t0, 0))); + prf_count_t0++; + } else if (prf_count_t1 < 4) { + mic_prefetcht1(EVEX_compress_addr( + aux_reg_ker_prf, kernel_offset(kk, + ic + prf_count_t1, ki))); + prf_count_t1++; + } + } + } + L(loop_end_label); + } + } + } else { + for (int ki = 0; ki < kw; ki++) + for (int ic = 0; ic < ic_block; ic += 4) + for (int kk = 0; kk < jcp.nb_oc_blocking; kk++) { + kernel_loads(ki, ic, kk); + for (int oi = get_ow_start(ki, pad_l), + prf_count_t1 = 0, prf_count_t0 = 0; + oi < get_ow_end(ur_w, ki, pad_r); oi++) { + int aux_input_offset = typesize + * ((ki * (jcp.dilate_w + 1) + oi * stride_w + - pad_l) * ic_block + ic); + v4fmaddps(vmm_out(oi, kk), vmm_ker(0), + EVEX_compress_addr(aux_reg_inp, + aux_input_offset)); + + if (!is_owb_prefetching(jcp)) { + if ((oi % 2) && (prf_count_t1 < 4)) { + mic_prefetcht1(EVEX_compress_addr( + aux_reg_ker_prf, kernel_offset(kk, + ic + prf_count_t1, ki))); + prf_count_t1++; + } + } else { + if (!(ki == 0 && ic == 0) + && !(ki == kw-1 && ic == 0) && + (oi % 2) && (prf_count_t1 < 4) + ) { + mic_prefetcht0(EVEX_compress_addr( + aux_reg_ker, kernel_offset(kk, + ic + 4 + prf_count_t0, ki))); + prf_count_t0++; + } + } + if (!is_owb_prefetching(jcp)) { + if (pref_current_inp) { + if (ki == 0 && ic == 0 && kk == 0) + mic_prefetcht0(EVEX_compress_addr( + aux_reg_inp, + aux_input_offset + shift_input_ptr)); + } else { + if (ki == 1 && ic == 0 && kk == 0) + mic_prefetcht1(EVEX_compress_addr( + aux_reg_inp_prf, aux_input_offset)); + } + } else { + int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block; + int inp_shift + = jcp.typesize_in * ur_w * stride_w * inp_mult; + bool kk_pref_slot = kk ? oi % 2 : !(oi % 2); + if (ki == 0 && ic == 0 && kk_pref_slot) + mic_prefetcht1(EVEX_compress_addr( + aux_reg_inp, + aux_input_offset + inp_shift)); + + if (ki == kw - 1 && ic == 0 && kk_pref_slot) + mic_prefetcht0(EVEX_compress_addr( + aux_reg_inp, + aux_input_offset + inp_shift)); + } + } + } + } + + add(aux_reg_ker, shift_kernel_ptr); + add(aux_reg_inp, shift_input_ptr); + add(aux_reg_ker_prf, shift_kernel_ptr); + add(aux_reg_inp_prf, shift_input_ptr); + + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + + if (jcp.ndims == 5) { + add(aux_reg_inp_d, + typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * jcp.ic_block); + add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * jcp.oc_block + * jcp.ic_block); + add(aux_reg_inp_d_prf, + typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * jcp.ic_block); + add(aux_reg_ker_d_prf, typesize * jcp.kw * jcp.kh * jcp.oc_block + * jcp.ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_label, T_NEAR); + + pop(reg_out); + pop(reg_out_prf); + } +} + +template +void _jit_avx512_common_conv_fwd_kernel::compute_loop_fma(int ur_w, + int pad_l, int pad_r) +{ + bool prf_ker = true; + bool prf_inp = true; + int ih = jcp.ih; + int stride_w = jcp.stride_w; + int id = jcp.id; + int iw = jcp.iw; + int kw = jcp.kw; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int nb_oc_block = jcp.nb_oc_blocking; + Label kh_label, kd_label; + + int ker_pipeline_depth = 4; + assert(ker_reg_base_idx + ker_pipeline_depth <= 32); + assert(oc_block >= ker_pipeline_depth); + + int num_ker_loads = ic_block * nb_oc_block * kw; + int num_ker_prfs = prf_ker ? num_ker_loads : 0; + int num_inp_prfs = prf_inp ? + ur_w * nstl::min(kw, stride_w) + nstl::max(0, kw - stride_w) : + 0; + if (jcp.is_1stconv && prf_inp) { + num_inp_prfs = div_up(num_inp_prfs, jcp.simd_w) * ic_block; + } + int num_prfs = num_ker_prfs + num_inp_prfs; + int num_fmas = num_ker_loads * ur_w; + int prf_inst_spacing + = (prf_ker || prf_inp) ? nstl::max(1, num_fmas / num_prfs) : 1; + int prf_inst_trigger = (num_fmas % prf_inst_spacing) / 2; + int inp_mul = !jcp.is_1stconv ? ic_block : 1; + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_inp, reg_inp); + mov(aux_reg_ker, reg_ker); + mov(aux_reg_inp_prf, reg_inp_prf); + mov(aux_reg_ker_prf, reg_ker_prf); + } + + size_t max_input_offset = (size_t)jcp.typesize_in * ic_block * iw * ih * id; + assert(reg_inp_prf == reg_long_offt); + if (max_input_offset > INT_MAX) push(reg_inp_prf); + + + if (jcp.ndims == 5) { + push(reg_out_prf); + push(reg_out); + + mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]); + mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]); + mov(aux_reg_inp_d, reg_inp); + mov(aux_reg_inp_d_prf, reg_inp_prf); + mov(aux_reg_ker_d_prf, reg_ker_prf); + + L(kd_label); + mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]); + } else { + mov(reg_kj, reg_kh); + } + + if (jcp.ndims == 5) { + mov(aux_reg_inp, aux_reg_inp_d); + mov(aux_reg_ker, aux_reg_ker_d); + mov(aux_reg_ker_prf, aux_reg_ker_d_prf); + mov(aux_reg_inp_prf, aux_reg_inp_d_prf); + } + + align(16); + L(kh_label); + { + int step = 0; + int ker_prfs = 0; + for (int ki = 0; ki < kw; ki++) { + for (int ic = 0; ic < ic_block; ic++) { + int aux_kernel_offset = 0; + if (step == 0) { + for (int i = 0; i < ker_pipeline_depth; i++) { + aux_kernel_offset = get_kernel_offset(ki, ic, 0, i); + vmovups(vmm_ker(i), EVEX_compress_addr( + aux_reg_ker, aux_kernel_offset)); + } + } else if (step < num_ker_loads - ker_pipeline_depth + 1) { + int load_offset = ker_pipeline_depth - 1; + int ker_load_reg_idx + = (step + load_offset) % ker_pipeline_depth; + aux_kernel_offset + = get_kernel_offset(ki, ic, 0, load_offset); + vmovups(vmm_ker(ker_load_reg_idx), + EVEX_compress_addr(aux_reg_ker, aux_kernel_offset)); + } + + bool ker_prf_inserted = false; + Vmm vmm_kernel = vmm_ker(step % ker_pipeline_depth); + int j_start = get_ow_start(ki, pad_l); + int j_end = get_ow_end(ur_w, ki, pad_r); + for (int j = j_start; j < j_end; j++) { + size_t aux_input_offset = get_input_offset(ki, ic, j, pad_l); + auto addr = EVEX_compress_addr_safe(aux_reg_inp, + aux_input_offset, reg_long_offt, true); + vfmadd231ps(vmm_out(j, 0), vmm_kernel, addr); + int fma_idx = step * ur_w + j; + int prf_slot_idx = fma_idx / prf_inst_spacing; + if (fma_idx % prf_inst_spacing == prf_inst_trigger) { + if (prf_ker && !ker_prf_inserted + && ker_prfs < num_ker_prfs) { + int ker_prf_offset + = jcp.typesize_in * ker_prfs * jcp.oc_block; + mic_prefetcht2(EVEX_compress_addr( + aux_reg_ker_prf, ker_prf_offset)); + ker_prf_inserted = true; + ker_prfs++; + } else if (prf_inp) { + int inp_prf_idx = prf_slot_idx - ker_prfs; + if (inp_prf_idx < num_inp_prfs) { + size_t inp_prf_stride = nstl::max(kw, stride_w); + size_t inp_prf_offset; + if (!jcp.is_1stconv) { + inp_prf_offset + = ic_block * jcp.typesize_in + * ((inp_prf_idx / kw) + * inp_prf_stride + + (inp_prf_idx % kw)); + } else { + size_t ic_prf_stride = + (size_t)jcp.typesize_in * iw * ih * id; + size_t iw_prf_stride + = jcp.typesize_in * jcp.simd_w; + inp_prf_offset = ((inp_prf_idx / ic_block) + * iw_prf_stride + + (inp_prf_idx % ic_block) + * ic_prf_stride); + } + mic_prefetcht0(EVEX_compress_addr_safe( + aux_reg_inp_prf, inp_prf_offset, + reg_long_offt)); + } + } + } + } + step++; + } + } + add(aux_reg_ker, jcp.typesize_in * kw * oc_block * ic_block); + if (prf_ker) + add(aux_reg_ker_prf, jcp.typesize_in * kw * oc_block * ic_block); + add(aux_reg_inp, jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mul); + if (prf_inp) + add(aux_reg_inp_prf, + jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mul); + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + } + + + if (jcp.ndims == 5) { + add(aux_reg_inp_d, + typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mul); + add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * jcp.oc_block + * jcp.ic_block); + add(aux_reg_inp_d_prf, + typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mul); + add(aux_reg_ker_d_prf, typesize * jcp.kw * jcp.kh * jcp.oc_block + * jcp.ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_label, T_NEAR); + + pop(reg_out); + pop(reg_out_prf); + } + if (max_input_offset > INT_MAX) pop(reg_inp_prf); +} + +template +void _jit_avx512_common_conv_fwd_kernel::compute_loop_fma_core(int ur_w, + int pad_l, int pad_r) +{ + int kw = jcp.kw; + int stride_w = jcp.stride_w; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int nb_oc_block = jcp.nb_oc_blocking; + Label kh_label, kd_label; + int shift_kernel_ptr = jcp.typesize_in * jcp.kw * jcp.oc_block + * jcp.ic_block; + int inp_mul = !jcp.is_1stconv ? ic_block : 1; + int shift_input_ptr = jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw + * inp_mul; + + + auto input_offset = [=](int oi, int ic, int ki) { + return (size_t)jcp.typesize_in + * ((size_t)(ki * (jcp.dilate_w + 1) + oi * stride_w - pad_l) + * inp_mul + (size_t)ic + * (!jcp.is_1stconv ? 1 : (size_t)jcp.iw * jcp.ih * jcp.id)); + }; + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_inp, reg_inp); + mov(aux_reg_ker, reg_ker); + } + + if (jcp.ndims == 5) { + push(reg_out); + + mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]); + mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]); + mov(aux_reg_inp_d, reg_inp); + + L(kd_label); + mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]); + } else { + mov(reg_kj, reg_kh); + } + + if (jcp.ndims == 5) { + mov(aux_reg_inp, aux_reg_inp_d); + mov(aux_reg_ker, aux_reg_ker_d); + } + + L(kh_label); + { + for (int ki = 0; ki < kw; ki++) { + int jj_start = get_ow_start(ki, pad_l); + int jj_end = get_ow_end(ur_w, ki, pad_r); + for (int ic = 0; ic < ic_block; ic++) { + if (jcp.kernel_kind == expl_bcast) { + for (int jj = jj_start; jj < jj_end; jj++) { + size_t aux_input_offset = input_offset(jj, ic, ki); + vbroadcastss(vmm_inp(jj, nb_oc_block), + EVEX_compress_addr_safe(aux_reg_inp, + aux_input_offset, reg_long_offt)); + } + } + for (int ii = 0; ii < nb_oc_block; ii++) { + int aux_kernel_offset = jcp.typesize_in + * (ii * jcp.nb_ic * jcp.kh * jcp.kw * jcp.kd * ic_block + * oc_block + ki * ic_block * oc_block + ic * oc_block); + if (jj_end - jj_start > 0) + vmovups(vmm_wei, EVEX_compress_addr(aux_reg_ker, + aux_kernel_offset)); + for (int jj = jj_start; jj < jj_end; jj++) + if (jcp.kernel_kind == expl_bcast) + vfmadd231ps(vmm_out(jj, ii), + vmm_inp(jj, nb_oc_block), vmm_wei); + else { + size_t aux_input_offset = input_offset(jj, ic, ki); + vfmadd231ps(vmm_out(jj, ii), vmm_wei, + EVEX_compress_addr_safe(aux_reg_inp, + aux_input_offset, reg_long_offt, true)); + } + } + } + } + add(aux_reg_ker, shift_kernel_ptr); + add(aux_reg_inp, shift_input_ptr); + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + } + + if (jcp.ndims == 5) { + add(aux_reg_inp_d, + typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mul); + add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * jcp.oc_block + * jcp.ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_label, T_NEAR); + + pop(reg_out); + } +} + +template +void _jit_avx512_common_conv_fwd_kernel::compute_loop(int ur_w, + int pad_l, int pad_r) +{ + if (jcp.ndims == 5) push(reg_oi); + + prepare_output(ur_w); + + Label skip_compute_loop; + if (jcp.ndims == 5) { + if ((jcp.dilate_d >= jcp.id) + || (jcp.kd - 1) * (jcp.dilate_d + 1) < nstl::max(jcp.f_pad, jcp.back_pad)) { + mov(reg_kj, ptr[param1 + GET_OFF(kd_padding)]); + cmp(reg_kj, 0); + je(skip_compute_loop, T_NEAR); + } + } + if ((jcp.dilate_h >= jcp.ih) + || (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad)) { + mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]); + cmp(reg_kj, 0); + je(skip_compute_loop, T_NEAR); + } + + if (jcp.ver == ver_4fma) + if(jcp.is_1stconv) + compute_loop_4fma_1st(ur_w, pad_l, pad_r); + else + compute_loop_4fma(ur_w, pad_l, pad_r); + else if (jcp.ver == ver_fma) + if ((jcp.is_1stconv && jcp.kernel_kind != expl_bcast) + || mayiuse(avx512_mic)) + compute_loop_fma(ur_w, pad_l, pad_r); + else + if (jcp.kernel_kind == embd_bcast && jcp.nb_oc_blocking == 1) + compute_loop_fma(ur_w, pad_l, pad_r); + else + compute_loop_fma_core(ur_w, pad_l, pad_r); + else + assert(!"unknown convolution version"); + + L(skip_compute_loop); + store_output(ur_w); + if (jcp.ndims == 5) pop(reg_oi); +} + +template +void _jit_avx512_common_conv_fwd_kernel::generate() +{ + int iw = jcp.iw; + int ow = jcp.ow; + int ow_block = jcp.ow_block; + int nb_ow = jcp.nb_ow; + int kw = jcp.kw; + int l_pad = jcp.l_pad; + int ur_w = jcp.ur_w; + int ur_w_tail = jcp.ur_w_tail; + int dilate_w = jcp.dilate_w + 1; + int stride_w = jcp.stride_w; + + int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block; + int inp_shift_pad = jcp.typesize_in * (ur_w * stride_w - l_pad) * inp_mult; + int inp_shift = jcp.typesize_in * ur_w * stride_w * inp_mult; + int inp_shift_pad_second_block = -1 * jcp.typesize_in * l_pad * inp_mult; + int out_shift = jcp.typesize_out * ur_w * jcp.oc_block; + + preamble(); + mov(reg_inp, ptr[param1 + GET_OFF(src)]); + mov(reg_out, ptr[param1 + GET_OFF(dst)]); + mov(reg_ker, ptr[param1 + GET_OFF(filt)]); + mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]); + mov(reg_kh, ptr[param1 + GET_OFF(kh_padding)]); + + int r_pad = nstl::max( + 0, (ow - 1) * stride_w + (kw - 1) * dilate_w - (iw + l_pad - 1)); + int n_oi = ow / ur_w; + int r_pad1 = (ur_w * n_oi - 1) * stride_w + (kw - 1) * dilate_w + - (iw + l_pad - 1); + + if (!is_ow_threading_on(jcp)) { + // ow is being processed as a whole - with left and right paddings + if (r_pad1 > 0) n_oi--; + + if (ow == ur_w) { + mov(reg_inp_prf, ptr[param1 + GET_OFF(src_prf)]); + mov(reg_out_prf, ptr[param1 + GET_OFF(dst_prf)]); + compute_loop(ur_w, l_pad, r_pad); + } else { + mov(reg_inp_prf, reg_inp); + mov(reg_out_prf, reg_out); + if (n_oi == 0) { + add(reg_inp_prf, inp_shift_pad); + add(reg_out_prf, out_shift); + compute_loop(ur_w, l_pad, r_pad1); + add(reg_inp, inp_shift_pad); + add(reg_out, out_shift); + if (ur_w_tail != 0) { + add(reg_inp_prf, inp_shift); + add(reg_out_prf, out_shift); + compute_loop(ur_w_tail, 0, r_pad); + } + } else { + xor_(reg_oi, reg_oi); + if (l_pad > 0) { + add(reg_inp_prf, inp_shift_pad); + add(reg_out_prf, out_shift); + compute_loop(ur_w, l_pad, 0); + add(reg_inp, inp_shift_pad); + add(reg_out, out_shift); + inc(reg_oi); + } + if ((l_pad <= 0 && n_oi > 0) || (l_pad > 0 && n_oi > 1)) { + Label ow_loop_label; + L(ow_loop_label); + { + add(reg_inp_prf, inp_shift); + add(reg_out_prf, out_shift); + compute_loop(ur_w, 0, 0); + add(reg_inp, inp_shift); + add(reg_out, out_shift); + inc(reg_oi); + cmp(reg_oi, n_oi); + jl(ow_loop_label, T_NEAR); + } + } + if (r_pad1 > 0) { + add(reg_inp_prf, inp_shift); + add(reg_out_prf, out_shift); + compute_loop(ur_w, 0, r_pad1); + add(reg_inp, inp_shift); + add(reg_out, out_shift); + } + if (ur_w_tail != 0) { + add(reg_inp_prf, inp_shift); + add(reg_out_prf, out_shift); + compute_loop(ur_w_tail, 0, r_pad); + } + } + } + } else { + // ow block is only processed. + // Number of block is passed as parameter owb, + // and padding processing depends on this number. + + Label end_label, last_oi_label, middle_ow_blocks_label, tail_label; + Label oi_loop_label, oi_loop_start_label, oi_loop_end_label; + + assert(ow_block % ur_w == 0); + int n_oi_not_last_ow_block = ow_block / ur_w; + // to simplify code (and general regs usage), + // size of ow block must be >= 2 * ur_w + assert(n_oi_not_last_ow_block > 1); + int n_oi_next_last_ow_block = n_oi_not_last_ow_block; + int n_oi_first_ow_block = n_oi_not_last_ow_block; + + int n_oi_last_ow_block = (ow - ow_block * (nb_ow-1)) / ur_w; + + // prepare right padding + bool next_last_ow_block_padded = r_pad1 > 0 && n_oi_last_ow_block == 0; + bool first_ow_block_padded = next_last_ow_block_padded && jcp.nb_ow == 2; + bool last_ow_block_padded = r_pad1 > 0 && n_oi_last_ow_block > 0; + + if (last_ow_block_padded) n_oi_last_ow_block--; + else if (first_ow_block_padded) n_oi_first_ow_block--; + else if (next_last_ow_block_padded) n_oi_next_last_ow_block--; + + mov(reg_owb, ptr[param1 + GET_OFF(owb)]); + cmp(reg_owb, 0); // is that the first ow-block ? + jg(middle_ow_blocks_label, T_NEAR); + + // the first ow block, compute left padding + + mov(reg_oi, n_oi_first_ow_block); + mov(reg_inp_prf, reg_inp); + mov(reg_out_prf, reg_out); + + if (l_pad > 0) { + mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]); + add(reg_inp_prf, inp_shift_pad); + add(reg_out_prf, out_shift); + compute_loop(ur_w, l_pad, 0); + add(reg_inp, inp_shift_pad); + add(reg_out, out_shift); + dec(reg_oi); + } + jmp(oi_loop_label, T_NEAR); + + // middle or last ow block entry + + L(middle_ow_blocks_label); + + if (l_pad > 0) { + // just to consider left padding, not compute + add(reg_inp, inp_shift_pad_second_block); + add(reg_inp_prf, inp_shift_pad_second_block); + } + + // set number of iteration for oi-loop + cmp(reg_owb, jcp.nb_ow - 1); // last ow-block ? + mov(reg_oi, n_oi_last_ow_block); + je(oi_loop_label, T_NEAR); + cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ? + mov(reg_oi, n_oi_next_last_ow_block); + je(oi_loop_label, T_NEAR); + mov(reg_oi, n_oi_not_last_ow_block); // other middle ow-blocks + + // oi loop w/o padding + L(oi_loop_label); + mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]); + L(oi_loop_start_label); + cmp(reg_oi, 0); + jle(oi_loop_end_label, T_NEAR); + + add(reg_inp_prf, inp_shift); + add(reg_out_prf, out_shift); + compute_loop(ur_w, 0, 0); + add(reg_inp, inp_shift); + add(reg_out, out_shift); + dec(reg_oi); + jmp(oi_loop_start_label, T_NEAR); + L(oi_loop_end_label); + + mov(reg_owb, ptr[param1 + GET_OFF(owb)]); + + cmp(reg_owb, 0); // first ow-block ? + if (first_ow_block_padded) { + je(last_oi_label, T_NEAR); + } else { + je(end_label, T_NEAR); + } + cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ? + jl(end_label, T_NEAR); + if (next_last_ow_block_padded) { + je(last_oi_label, T_NEAR); + } else { + je(end_label, T_NEAR); + } + // that is last block + if (!last_ow_block_padded) { + jmp(tail_label, T_NEAR); + } + + // last oi block with right padding + L(last_oi_label); + mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]); + add(reg_inp_prf, inp_shift); + add(reg_out_prf, out_shift); + compute_loop(ur_w, 0, r_pad1); + add(reg_inp, inp_shift); + add(reg_out, out_shift); + + mov(reg_owb, ptr[param1 + GET_OFF(owb)]); + cmp(reg_owb, jcp.nb_ow - 1); // last ow_block? + jl(end_label, T_NEAR); + + L(tail_label); + mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]); + if (ur_w_tail != 0) { + add(reg_inp_prf, inp_shift); + add(reg_out_prf, out_shift); + compute_loop(ur_w_tail, 0, r_pad); + } + L(end_label); + } + postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +bool jit_avx512_common_conv_fwd_kernel::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + + return false; +} + +status_t jit_avx512_common_conv_fwd_kernel::init_conf( + jit_conv_conf_t &jcp, const convolution_desc_t &cd, + memory_desc_t &src_md, memory_desc_t &weights_md, + memory_desc_t &dst_md, memory_desc_t &bias_md, + const primitive_attr_t &attr, int nthreads) +{ + using namespace prop_kind; + + if (!mayiuse(avx512_common)) + return status::unimplemented; + + const memory_desc_wrapper src_d(&src_md); + const memory_desc_wrapper weights_d(&weights_md); + const memory_desc_wrapper dst_d(&dst_md); + const memory_desc_wrapper bias_d(&bias_md); + + const int regs = 28; + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + int ndims = src_d.ndims(); + + jcp = zero(); + jcp.ndims = ndims; + jcp.prop_kind = cd.prop_kind; + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.id = (ndims == 5) ? src_d.dims()[2] : 1; + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2]; + jcp.iw = src_d.dims()[ndims-1]; + jcp.od = (ndims == 5) ? dst_d.dims()[2] : 1; + jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[ndims-2]; + jcp.ow = dst_d.dims()[ndims-1]; + jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1; + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims-2]; + jcp.kw = weights_d.dims()[with_groups + ndims-1]; + jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0; + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4]; + jcp.l_pad = cd.padding[0][ndims-3]; + jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1; + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4]; + jcp.stride_w = cd.strides[ndims-3]; + + jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0; + jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4]; + jcp.dilate_w = cd.dilates[ndims-3]; + + jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1) + - (jcp.ih + jcp.t_pad - 1); + jcp.back_pad = (jcp.od - 1) * jcp.stride_d + + (jcp.kd - 1) * (jcp.dilate_d + 1) - (jcp.id + jcp.f_pad - 1); + + jcp.is_1stconv = is_1stconv(jcp); + + bool ok_to_pad_channels = true + && jcp.ngroups == 1 + && src_d.data_type() == data_type::f32; + + const int full_simd_w = cpu_isa_traits::vlen / sizeof(float); + jcp.simd_w = full_simd_w; + bool ok_to_try_xmm = true + && mayiuse(avx512_core) + && src_d.data_type() == data_type::f32 + && !jcp.is_1stconv + && !ok_to_pad_channels + && (jcp.ic % jcp.simd_w != 0 || jcp.oc % jcp.simd_w != 0) + && (jcp.ic % 8 != 0 || jcp.oc % 8 != 0); + if (ok_to_try_xmm) + jcp.simd_w = 4; + + jcp.oc_block = jcp.simd_w; + jcp.ic_block = jcp.is_1stconv ? jcp.ic : jcp.simd_w; + jcp.aligned_threads = 0; + + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, jcp.oc_block); + jcp.ic = rnd_up(jcp.ic, jcp.ic_block); + } + bool args_ok = true + && jcp.oc % jcp.oc_block == 0 + && jcp.ic % jcp.ic_block == 0; + if (!args_ok) + return status::unimplemented; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + jcp.with_sum = p.find(primitive_kind::sum) != -1; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) { + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + if (dst_d.data_type() == data_type::s32) return status::unimplemented; + } + + auto src_tag = jcp.is_1stconv + ? pick(ndims - 3, ncw, nchw, ncdhw) + : ((jcp.simd_w == 4) + ? pick(ndims - 3, nCw4c, nChw4c, nCdhw4c) + : pick(ndims - 3, nCw16c, nChw16c, nCdhw16c)); + auto dst_tag = (jcp.simd_w == 4) + ? pick(ndims - 3, nCw4c, nChw4c, nCdhw4c) + : pick(ndims - 3, nCw16c, nChw16c, nCdhw16c); + auto wei_tag = with_groups + ? ((jcp.simd_w == 4) + ? pick(ndims - 3, gOIw4i4o, gOIhw4i4o, gOIdhw4i4o) + : pick(ndims - 3, gOIw16i16o, gOIhw16i16o, gOIdhw16i16o)) + : ((jcp.simd_w == 4) + ? pick(ndims - 3, OIw4i4o, OIhw4i4o, OIdhw4i4o) + : pick(ndims - 3, OIw16i16o, OIhw16i16o, OIdhw16i16o)); + + if (src_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(src_md, src_tag)); + jcp.src_tag = src_tag; + } else { + jcp.src_tag = src_d.matches_one_of_tag(src_tag); + } + if (jcp.src_tag != src_tag) + return status::unimplemented; + + if (dst_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(dst_md, dst_tag)); + jcp.dst_tag = dst_tag; + } else { + jcp.dst_tag = dst_d.matches_one_of_tag(dst_tag); + } + if (jcp.dst_tag != dst_tag) + return status::unimplemented; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + if (jcp.with_bias) { + if (bias_d.format_kind() == format_kind::any) + CHECK(memory_desc_init_by_tag(bias_md, x)); + } + + if (mayiuse(avx512_common) && + src_d.data_type() == data_type::f32 + && weights_d.data_type() == data_type::f32 + && dst_d.data_type() == data_type::f32) { + jcp.ver = ver_fma; + jcp.typesize_in = sizeof(float); + jcp.typesize_out = sizeof(float); + if (mayiuse(avx512_mic_4ops)) + jcp.ver = ver_4fma; + + if (jcp.is_1stconv) { + // TODO: fix & remove constraints below + bool not_for_4fma + = IMPLICATION(everyone_is(0, jcp.l_pad, jcp.t_pad), + nstl::max(jcp.kw, jcp.kh) < 7); + bool is_dilated + = !everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w); + if (one_of(true, not_for_4fma, is_dilated)) + jcp.ver = ver_fma; + if (jcp.ver == ver_4fma) { + wei_tag = with_groups + ? ((jcp.simd_w == 4) + ? pick(ndims - 3, gOiw4o, gOihw4o, gOidhw4o) + : pick(ndims - 3, gOiw16o, gOihw16o, gOidhw16o)) + : ((jcp.simd_w == 4) + ? pick(ndims - 3, Oiw4o, Oihw4o, Oidhw4o) + : pick(ndims - 3, Oiw16o, Oihw16o, Oidhw16o)); + } else { + wei_tag = with_groups + ? ((jcp.simd_w == 4) + ? pick(ndims - 3, gOwi4o, gOhwi4o, gOdhwi4o) + : pick(ndims - 3, gOwi16o, gOhwi16o, gOdhwi16o)) + : ((jcp.simd_w == 4) + ? pick(ndims - 3, Owi4o, Ohwi4o, Odhwi4o) + : pick(ndims - 3, Owi16o, Ohwi16o, Odhwi16o)); + } + } + } else { + return status::unimplemented; + } + + if (weights_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(weights_md, wei_tag)); + jcp.wei_tag = wei_tag; + } else { + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + } + if (jcp.wei_tag != wei_tag) + return status::unimplemented; + + if (jcp.is_1stconv) { + jcp.ur_w = nstl::min(jcp.ow, regs); + } else { + // avx512_core guard - just to avoid possible regression for other archs + if (jcp.ver == ver_fma && mayiuse(avx512_core)) { + jcp.ur_w = nstl::min(jcp.ow, regs); + } else { + for (int ur_w = regs; ur_w > 0; --ur_w) { + if (jcp.ow % ur_w == 0) { + jcp.ur_w = ur_w; + break; + } + } + } + if ((ndims == 5 && jcp.ur_w <= 8) || (jcp.ur_w <= 1)) { + jcp.ur_w = nstl::min(jcp.ow, regs); + } + } + // TODO (Tanya): currently applied to Segnet convolutions only. + // Need to try for other topologies + if (jcp.ow > 150 && jcp.ur_w < regs/2) + jcp.ur_w = regs; + + int n_oi = (jcp.ow / jcp.ur_w); + int r_pad = (jcp.ur_w * n_oi - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1); + if (jcp.l_pad > 0 && r_pad > 0) + n_oi--; + + bool large_code_size = jcp.ur_w != jcp.ow && jcp.l_pad > 0 && r_pad > 0 + && ((jcp.l_pad <= 0 && n_oi > 0) || (jcp.l_pad > 0 && n_oi > 1)); + if (large_code_size) { + const int max_code_size = 24 * 1024; + const int num_ops_per_reg = 6 + jcp.ic_block * jcp.kw; + int mult = 1; + if (jcp.l_pad > 0) mult += 1; + if (r_pad > 0) mult += 1; + for (int ur_w = jcp.ur_w; ur_w > regs/2; --ur_w) { + if (ur_w * mult * num_ops_per_reg * 9.0 < max_code_size) { + jcp.ur_w = ur_w; + break; + } + } + } + + /* Grouped channel offset to support 'non-blocked data' format for + * convolution sizes with '(input_channel / ngroups) < simd' */ + jcp.nonblk_group_off + = (jcp.ngroups > 1 && one_of(jcp.src_tag, ncw, nchw, ncdhw)) ? + jcp.ic : + 1; + + jcp.nb_ic = jcp.ic / jcp.ic_block; + jcp.nb_oc = jcp.oc / jcp.oc_block; + jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1; + + auto is_ow_threading_applicable = [=]() { + return (true && !jcp.is_1stconv && one_of(jcp.ndims, 3, 4) + && IMPLICATION(mayiuse(avx512_mic), + jcp.ver == ver_4fma + && IMPLICATION(jcp.mb != 1, + jcp.ih == 1 && jcp.kh == 1))); + }; + + if (jcp.ver == ver_4fma && !jcp.is_1stconv) { + if ((jcp.kw <= 5 && jcp.kh <= 5 && jcp.kw == jcp.kh && jcp.ow <= 8 + && jcp.oh <= 8 && jcp.ow == jcp.oh) + || (jcp.stride_h != 1 && jcp.ur_w < jcp.ow)) { + if (jcp.nb_oc % 2 == 0) { + jcp.nb_oc_blocking = 2; + jcp.ur_w = nstl::min(jcp.ow, regs / jcp.nb_oc_blocking); + } + } else { + for (int i = jcp.nb_oc; i > 0; i--) + if (i * jcp.ur_w <= regs && jcp.nb_oc % i == 0) { + jcp.nb_oc_blocking = i; + break; + } + } + if (jcp.ver == ver_4fma && is_ow_threading_applicable()) { + if (jcp.nb_oc % 2 == 0 && jcp.ur_w < jcp.ow + && jcp.ow != 2 * jcp.ur_w) { + jcp.nb_oc_blocking = 2; + jcp.ur_w = nstl::min(jcp.ow, regs / jcp.nb_oc_blocking); + } + } + } + + jcp.ow_block = jcp.ow; + + auto get_thr_eff = [=](int nb_oc_blocking, int ow_block) { + int nb_ow = div_up(jcp.ow, ow_block); + int nb_oc_chunks = div_up(jcp.nb_oc, nb_oc_blocking); + int work_amount = jcp.mb * jcp.oh * nb_oc_chunks * nb_ow; + float disbalance = (float)jcp.ow / rnd_up(jcp.ow, ow_block); + float thr_eff = disbalance * (float)work_amount + / rnd_up(work_amount, nthreads); + return thr_eff; + }; + + auto get_ow_block = [=](int nb_oc_blocking, int ur_w, float &eff) { + int res_ow_block = jcp.ow; + eff = get_thr_eff(nb_oc_blocking, res_ow_block); + if (!is_ow_threading_applicable()) + return res_ow_block; + + int L2_part = (get_cache_size(2) * 7 / 8) / typesize; + if (jcp.ver == ver_4fma) + L2_part /= 2; + int size_src_chunk = jcp.ic_block * ur_w * jcp.kh; + int size_dst_chunk = jcp.oc_block * nb_oc_blocking * ur_w; + int size_wei_chunk = jcp.oc_block * nb_oc_blocking * jcp.ic_block + * jcp.kw * jcp.kh; + int nurw_cache = (L2_part - 2 * size_wei_chunk) + / (2 * size_dst_chunk + 2 * size_src_chunk); + // current design of generate() requires ow_block >= 2 * ur_w + int ow_block_cache = ur_w * nstl::max(2, nurw_cache); + + int ow_block_thr = ow_block_cache; + eff = get_thr_eff(nb_oc_blocking, ow_block_thr); + + int max_nb_ow = div_up(jcp.ow, 2 * ur_w); + int start_nb_ow = div_up(jcp.ow, ow_block_thr); + for (int nb_ow = start_nb_ow; nb_ow <= max_nb_ow; nb_ow++) { + int ow_block + = nstl::min(rnd_up(div_up(jcp.ow, nb_ow), ur_w), jcp.ow); + float eff_threshold = (jcp.ver == ver_4fma) ? 0.8f : 0.9f; + if (ow_block < nb_oc_blocking * jcp.oc_block && eff > eff_threshold) + break; + if (div_up(jcp.ow, ow_block) != nb_ow) + continue; + float thr_eff = get_thr_eff(nb_oc_blocking, ow_block); + float eff_step = (jcp.ver == ver_4fma) ? 1.1f : 1.f; + if (ow_block >= 2 * ur_w && thr_eff > eff_step * eff) { + ow_block_thr = ow_block; + eff = thr_eff; + } + eff_threshold = (jcp.ver == ver_4fma) ? 0.9f : 0.98f; + if (eff > eff_threshold) + break; + } + res_ow_block = nstl::min(jcp.ow, nstl::max(2 * ur_w, ow_block_thr)); + eff = get_thr_eff(nb_oc_blocking, res_ow_block); + return res_ow_block; + }; + + + if (jcp.ver == ver_fma && mayiuse(avx512_core)) { + int try_nb_oc_blocking = 2; + unsigned int ker_inp_size = typesize * div_up(jcp.iw, jcp.stride_w) + * jcp.ic_block * jcp.kh * jcp.kd; + unsigned int ker_out_size = typesize * jcp.ow * jcp.oc_block + * try_nb_oc_blocking; + unsigned int ker_wei_size = typesize * jcp.kh * jcp.kw * jcp.ic_block + * jcp.oc_block * try_nb_oc_blocking * jcp.kd; + unsigned int ker_total_size = ker_inp_size + ker_out_size + + ker_wei_size; + + bool embd_bcast_condition = true + && (jcp.kw == 3 && jcp.ow <= 28 && ker_total_size < L1_cache_size) + && !(jcp.kw == 3 && jcp.ow == 13 && jcp.ic >= 192) + && !(jcp.kw == 3 && jcp.ow == 28 && jcp.ic >= 512); + + if (jcp.mb == 1) { + unsigned int inp_size = jcp.mb * div_up(jcp.ih, jcp.stride_h) + * div_up(jcp.iw, jcp.stride_w) * jcp.ic; + unsigned int wei_size = jcp.ic * jcp.oc * jcp.kh * jcp.kw; + + // Estimate whether we need to limit the number of threads + // and calculate this number. Includes some heuristic. + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking; + int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.oh; + int job_size_min = work_amount / nthreads; + int job_size_max = div_up(work_amount, nthreads); + int ch_max = rnd_up(jcp.oh, job_size_max); + int ch_min = (job_size_min == 0) + ? jcp.oh + : rnd_up(jcp.oh, job_size_min); + bool not_aligned_max = ch_max % jcp.oh != 0 && ch_max / jcp.oh < 2 + && (jcp.oh != 8 || ch_max / jcp.oh > 1); + bool not_aligned_min = ch_min % jcp.oh != 0 && ch_min / jcp.oh < 2 + && (jcp.oh != 8 || ch_min / jcp.oh > 1); + bool eligible_case = (jcp.stride_h == 1 && jcp.stride_w == 1) + || nthreads > oc_chunks; + if (jcp.loop_order == loop_cgn && oc_chunks > 1 && nthreads > 1 + && wei_size / inp_size > 24 + && (not_aligned_max || not_aligned_min) + && eligible_case) { + // Try to find nthreads > mkldnn_get_max_threads() / 2 such + // that oc_chunks is a multiple of nthreads, or nthreads is a + // multiple of oc_chunks. Otherwise, keep default value. + // TODO: implement a task-based alternative without throttling. + jcp.aligned_threads = nthreads; + for (int i = nthreads; i > nthreads / 2; i--) { + if (oc_chunks % i == 0 || i % oc_chunks == 0) { + jcp.aligned_threads = i; + break; + } + } + } + } + + if (jcp.kw > 3 + || (jcp.stride_w == 1 && jcp.stride_h == 1 + && embd_bcast_condition) + || ((jcp.stride_w != 1 || jcp.stride_h != 1) + && ((jcp.mb <= 16 && (jcp.oc <= 192 || jcp.oh <= 10) + && embd_bcast_condition))) + || (jcp.mb == 1 + && (jcp.ur_w >= jcp.ow || jcp.is_1stconv + || (jcp.ow <= 147 && jcp.oc <= 96)))) { + jcp.kernel_kind = embd_bcast; + jcp.ur_w = nstl::min(jcp.ow, regs); + jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1; + if (ker_total_size < L1_cache_size && jcp.ow <= 8 && jcp.kh <= 3 + && jcp.kw <= 3 && jcp.nb_oc % try_nb_oc_blocking == 0 + && IMPLICATION(jcp.is_1stconv, jcp.mb == 1) + && IMPLICATION(jcp.mb == 1, jcp.ur_w < jcp.ow)) { + jcp.nb_oc_blocking = try_nb_oc_blocking; + jcp.ur_w = nstl::min(jcp.ow, 31 / (jcp.nb_oc_blocking + 1)); + } + } else { + jcp.kernel_kind = expl_bcast; + jcp.nb_ic_blocking = 1; + if (IMPLICATION(jcp.is_1stconv, jcp.mb > 1)) { + float best_thr_eff = 0.f; + int best_nb_oc_blocking = 1; + for (int i = nstl::min(jcp.nb_oc, 5); i > 0; i--) { + if (jcp.nb_oc % i == 0) { + float thr_eff; + int ur_w = nstl::min(jcp.ow, 31 / (i + 1)); + get_ow_block(i, ur_w, thr_eff); + if (thr_eff > 1.05f * best_thr_eff) { + best_nb_oc_blocking = i; + best_thr_eff = thr_eff; + } + } + } + jcp.nb_oc_blocking = best_nb_oc_blocking; + jcp.ur_w = nstl::min(jcp.ow, 31 / (jcp.nb_oc_blocking + 1)); + } + } + } + + jcp.ur_w_tail = jcp.ow % jcp.ur_w; + + args_ok = true + && jcp.l_pad <= jcp.ur_w + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= dst_d.padded_dims()[1] + && jcp.ic <= weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= weights_d.padded_dims()[with_groups + 0]; + if (!args_ok) + return status::unimplemented; + + int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) + - (jcp.iw + jcp.l_pad - 1)); + if (r_pad_no_tail > jcp.ur_w) + return status::unimplemented; + + pick_loop_order(jcp); + + jcp.nb_ic_L2 = jcp.nb_ic; + + float thr_eff; + jcp.ow_block = get_ow_block(jcp.nb_oc_blocking, jcp.ur_w, thr_eff); + jcp.nb_ow = div_up(jcp.ow, jcp.ow_block); + + const int L2_size = get_cache_size(2, true) / sizeof(float); + // Source and output data needs to fit in L2, + // leaving some space for weights and prefetching. + int h_L2 = int(((0.6f * L2_size) / jcp.simd_w + - nstl::min(0, jcp.kh - jcp.stride_h) * jcp.iw) + / (jcp.stride_h * jcp.iw + jcp.ow)); + jcp.h_blocking = nstl::max(1, nstl::min(jcp.oh, h_L2)); + + if (jcp.ver == ver_4fma) { + if (!is_ow_threading_on(jcp)) { + for (int divf = 2, temp_nb = jcp.nb_ic_L2; divf <= jcp.nb_ic; + divf++) { + size_t l2_src + = (size_t)jcp.iw * jcp.ic_block * jcp.ih * temp_nb * jcp.id; + size_t l2_dst = (size_t)jcp.ow * jcp.oc_block * jcp.nb_oc_blocking + * jcp.oh * jcp.od; + size_t l2_filt = (size_t)jcp.kw * jcp.oc_block * jcp.ic_block + * jcp.kh * jcp.nb_oc_blocking * temp_nb * jcp.kd; + if (4 * (l2_src + l2_dst + l2_filt) > KNx_L2_EFFECTIVE_CAPACITY) { + if (jcp.kh == 3 && jcp.oh == 7) { + jcp.nb_ic_L2 = 1; + break; + } + temp_nb = (jcp.nb_ic_L2 % divf == 0 ? jcp.nb_ic_L2 / divf + : jcp.nb_ic_L2); + } else { + jcp.nb_ic_L2 = temp_nb; + break; + } + } + } else if (jcp.ic > 64) { + jcp.nb_ic_L2 = 2; /* according to performance data*/ + } + } + + return status::success; +} + +void jit_avx512_common_conv_fwd_kernel::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + if (jcp.with_bias && jcp.oc != jcp.oc_without_padding) + scratchpad.book(key_conv_padded_bias, jcp.typesize_out * jcp.oc); +} + +void jit_avx512_common_conv_bwd_data_kernel_f32::prepare_output(int ur_w) +{ + for (int k = 0; k < jcp.nb_ic_blocking; k++) { + for (int j = 0; j < ur_w; j++) { + Zmm zmm = zmm_out(j, k); + vpxord(zmm, zmm, zmm); + size_t aux_src_offset + = (size_t)typesize * ((size_t)k * jcp.ih * jcp.iw * jcp.id + j) + * jcp.ic_block; + mic_prefetcht1(EVEX_compress_addr_safe(reg_src_prf, aux_src_offset, + reg_long_offt)); + } + } +} + +void jit_avx512_common_conv_bwd_data_kernel_f32::store_output(int ur_w) +{ + Label no_update_label; + + mov(reg_channel, ptr[param + GET_OFF(channel)]); + cmp(reg_channel, 0); + je(no_update_label, T_NEAR); + for (int k = 0; k < jcp.nb_ic_blocking; k++) { + for (int j = 0; j < ur_w; j++) { + Zmm zmm = zmm_out(j, k); + size_t aux_src_offset = (size_t)typesize + * ((size_t)k * jcp.ih * jcp.iw * jcp.id + j) * jcp.ic_block; + vaddps(zmm, EVEX_compress_addr_safe(reg_src, aux_src_offset, + reg_long_offt)); + } + } + + L(no_update_label); + for (int k = 0; k < jcp.nb_ic_blocking; k++) { + for (int j = 0; j < ur_w; j++) { + Zmm zmm = zmm_out(j, k); + size_t aux_src_offset = (size_t)typesize + * ((size_t)k * jcp.ih * jcp.iw * jcp.id + j) * jcp.ic_block; + vmovups(EVEX_compress_addr_safe(reg_src, aux_src_offset, + reg_long_offt), zmm); + mic_prefetcht0(EVEX_compress_addr_safe(reg_src_prf, aux_src_offset, + reg_long_offt)); + } + } +} + +void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop_4fma( + int ur_w, int l_overflow, int r_overflow) +{ + int ow = jcp.ow; + int kw = jcp.kw; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + Label kh_label, last_iter_label, loop_end_label, kd_label; + int ker_load_number = 4; + int shift_ker_ptr = typesize * kw * oc_block * ic_block; + int shift_dst_ptr = typesize * ow * oc_block; + int ii_dpref_t0 = get_iw_start(0, l_overflow); + int iw_end_ipref = get_iw_end(ur_w, 0, r_overflow); + + bool check_last_kh = (jcp.kh > 3); + auto kernel_offset = [=](int icb, int oc, int ki) { + int blk_idx = icb * jcp.kh * jcp.kw * jcp.kd + ki; + int blk_offset = blk_idx * jcp.oc_block * jcp.ic_block; + int oc_offset = oc * jcp.oc_block; + return typesize * (blk_offset + oc_offset); + }; + auto kernel_loads = [=](int ki, int oc, int kk) { + for (int ii = 0; ii < ker_load_number; ii++) { + int aux_kernel_offset = kernel_offset(kk, oc + ii, ki); + vmovups(zmm_ker(ii), + EVEX_compress_addr(aux_reg_ker, aux_kernel_offset)); + } + }; + auto prefetch_dst_next_kh = [&](int ki, int ki_start, int cnt0, int cnt1) { + if (cnt1 >= ker_load_number && cnt0 >= ker_load_number + && ki >= ki_start && ii_dpref_t0 < iw_end_ipref) { + int aux_dst_offset = typesize * ((ii_dpref_t0 + + jcp.l_pad) * oc_block + jcp.ow * oc_block); + prefetcht0(EVEX_compress_addr(aux_reg_dst, aux_dst_offset)); + ii_dpref_t0++; + } + }; + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_dst, reg_dst); + mov(aux_reg_ker, reg_ker); + mov(aux_reg_dst_prf, reg_dst_prf); + mov(aux_reg_ker_prf, reg_ker_prf); + } + + if (jcp.ndims == 5) { + push(reg_src_prf); + push(reg_src); + + mov(reg_ki, ptr[param + GET_OFF(kd_padding)]); + mov(aux_reg_dst_d, reg_dst); + mov(aux_reg_ker_d, ptr[param + GET_OFF(filt)]); + mov(aux_reg_dst_d_prf, reg_dst_prf); + mov(aux_reg_ker_d_prf, reg_ker_prf); + + L(kd_label); + mov(reg_kj, ptr[param + GET_OFF(kh_padding)]); + } else { + mov(reg_kj, reg_kh); + } + + if (jcp.ndims == 5) { + mov(aux_reg_dst, aux_reg_dst_d); + mov(aux_reg_ker, aux_reg_ker_d); + mov(aux_reg_dst_prf, aux_reg_dst_d_prf); + mov(aux_reg_ker_prf, aux_reg_ker_d_prf); + } + + align(16); + L(kh_label); + if (check_last_kh) { + for (int ki = 0; ki < kw; ki++) + for (int oc = 0; oc < oc_block; oc += 4) + for (int kk = 0; kk < jcp.nb_ic_blocking; kk++) { + bool last_kernel_loads = (kk == jcp.nb_ic_blocking - 1 + && ki == kw - 1 && (oc + 4) == oc_block); + + if (last_kernel_loads) { + cmp(reg_kj, 1); + je(last_iter_label, T_NEAR); + } + + kernel_loads(ki, oc, kk); + for (int ii = get_iw_start(ki, l_overflow), + prf_count_t0 = 0, prf_count_t1 = 0; + ii < get_iw_end(ur_w, ki, r_overflow); ii++) { + int aux_dst_offset = typesize + * ((ii + jcp.l_pad - ki) * oc_block + oc); + v4fmaddps(zmm_out(ii, kk), zmm_ker(0), + EVEX_compress_addr(aux_reg_dst, aux_dst_offset)); + + if (ii % 2) { + if (prf_count_t0 < 4) { + int aux_kernel_prf; + if (last_kernel_loads) + aux_kernel_prf= kernel_offset(0, prf_count_t0 + + oc + 4 - oc_block, 0) + typesize * kw + * oc_block * ic_block; + else + aux_kernel_prf = kernel_offset(kk, oc + 4 + + prf_count_t0, ki); + mic_prefetcht0(EVEX_compress_addr(aux_reg_ker, + aux_kernel_prf)); + prf_count_t0++; + } else if (prf_count_t1 < 4) { + mic_prefetcht1(EVEX_compress_addr(aux_reg_ker_prf, + kernel_offset(kk, oc + prf_count_t1, ki))); + prf_count_t1++; + } + } else + prefetch_dst_next_kh(ki, 2, prf_count_t0, prf_count_t1); + } + if (last_kernel_loads) { + jmp(loop_end_label, T_NEAR); + + L(last_iter_label); + + kernel_loads(ki, oc, kk); + for (int ii = get_iw_start(ki, l_overflow), + prf_count_t0 = 0, prf_count_t1 = 0; + ii < get_iw_end(ur_w, ki, r_overflow); ii++) { + int aux_dst_offset = typesize + * ((ii + jcp.l_pad - ki) * oc_block + oc); + v4fmaddps(zmm_out(ii, kk), zmm_ker(0), + EVEX_compress_addr(aux_reg_dst, aux_dst_offset)); + if (ii % 2) { + if (prf_count_t0 < 4) { + mic_prefetcht0(EVEX_compress_addr(aux_reg_ker_prf, + kernel_offset(0, prf_count_t0, 0))); + prf_count_t0++; + } else if (prf_count_t1 < 4) { + mic_prefetcht1(EVEX_compress_addr(aux_reg_ker_prf, + kernel_offset(kk, oc + prf_count_t1, ki))); + prf_count_t1++; + } + } + } + L(loop_end_label); + } + } + } else { + for (int ki = 0; ki < kw; ki++) + for (int oc = 0; oc < oc_block; oc += 4) + for (int kk = 0; kk < jcp.nb_ic_blocking; kk++) { + kernel_loads(ki, oc, kk); + + for (int ii = get_iw_start(ki, l_overflow), prf_count_t1 = 0; + ii < get_iw_end(ur_w, ki, r_overflow); ii++) { + int aux_dst_offset = typesize + * ((ii + jcp.l_pad - ki) * oc_block + oc); + v4fmaddps(zmm_out(ii, kk), zmm_ker(0), + EVEX_compress_addr(aux_reg_dst, aux_dst_offset)); + if ((ii % 2) && (prf_count_t1 < 4)) { + mic_prefetcht1(EVEX_compress_addr( + aux_reg_ker_prf, kernel_offset(kk, + oc + prf_count_t1, ki))); + prf_count_t1++; + } + if ( ki == 1 && oc == 0 && kk == 0) + mic_prefetcht1(EVEX_compress_addr( + aux_reg_dst_prf, aux_dst_offset)); + } + } + } + + add(aux_reg_ker, shift_ker_ptr); + sub(aux_reg_dst, shift_dst_ptr); + add(aux_reg_ker_prf, shift_ker_ptr); + sub(aux_reg_dst_prf, shift_dst_ptr); + + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + + if (jcp.ndims == 5) { + sub(aux_reg_dst_d, typesize * (jcp.oh * ow) * ic_block); + add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * oc_block * ic_block); + sub(aux_reg_dst_d_prf, typesize * (jcp.oh * ow) * ic_block); + add(aux_reg_ker_d_prf, typesize * jcp.kw * jcp.kh *oc_block * ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_label, T_NEAR); + + pop(reg_src); + pop(reg_src_prf); + } +} + +void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop_fma( + int ur_w, int l_overflow, int r_overflow) +{ + Label kh_label, kd_label; + int kw = jcp.kw; + int ow = jcp.ow; + + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int l_pad = jcp.l_pad; + int dilate_w = jcp.dilate_w + 1; + int stride_w = jcp.stride_w; + int stride_h = jcp.stride_h; + + int ker_pipeline_depth = 4; + assert(ker_reg_base_idx + ker_pipeline_depth <= 32); + assert(oc_block >= ker_pipeline_depth); + + int num_ker_loads = oc_block * kw; + int num_inp_prfs = ur_w * nstl::min(kw, stride_w) + + nstl::max(0, kw - stride_w); + int num_prfs = num_ker_loads + num_inp_prfs; + int num_fmas = num_ker_loads * ur_w / stride_w; + int prf_inst_spacing = nstl::max(1, num_fmas / num_prfs); + int prf_inst_trigger = (num_fmas % prf_inst_spacing) / 2; + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_dst, reg_dst); + mov(aux_reg_ker, reg_ker); + + mov(aux_reg_dst_prf, reg_dst_prf); + mov(aux_reg_ker_prf, reg_ker_prf); + } + + if (jcp.ndims == 5) { + push(reg_src_prf); + push(reg_src); + + mov(reg_ki, ptr[param + GET_OFF(kd_padding)]); + mov(aux_reg_dst_d, reg_dst); + mov(aux_reg_ker_d, ptr[param + GET_OFF(filt)]); + mov(aux_reg_dst_d_prf, reg_dst_prf); + mov(aux_reg_ker_d_prf, reg_ker_prf); + + L(kd_label); + mov(reg_kj, ptr[param + GET_OFF(kh_padding)]); + } else { + mov(reg_kj, reg_kh); + } + + if (jcp.ndims == 5) { + mov(aux_reg_dst, aux_reg_dst_d); + mov(aux_reg_ker, aux_reg_ker_d); + mov(aux_reg_dst_prf, aux_reg_dst_d_prf); + mov(aux_reg_ker_prf, aux_reg_ker_d_prf); + } + + L(kh_label); { + int step = 0; + int ker_prfs = 0; + for (int ki = 0; ki < kw; ki++) { + for (int oc = 0; oc < oc_block; oc++) { + if (step == 0) { + for (int i = 0; i < ker_pipeline_depth; i++) { + int aux_kernel_offset = typesize * ((oc + i) * oc_block + + ki * ic_block * oc_block); + vmovups(zmm_ker(i), EVEX_compress_addr( + aux_reg_ker, aux_kernel_offset)); + } + } else if (step < num_ker_loads - ker_pipeline_depth + 1) { + int load_offset = ker_pipeline_depth - 1; + int ker_load_reg_idx + = (step + load_offset) % ker_pipeline_depth; + int aux_kernel_offset = typesize * ((oc + load_offset) + * oc_block + ki * ic_block * oc_block); + vmovups(zmm_ker(ker_load_reg_idx), + EVEX_compress_addr(aux_reg_ker, aux_kernel_offset)); + } + + bool ker_prf_inserted = false; + auto zmm_kernel = zmm_ker(step % ker_pipeline_depth); + + int jj_start = get_iw_start(ki, l_overflow); + int jj_end = get_iw_end(ur_w, ki, r_overflow); + assert(stride_w != 1 + || jj_start == nstl::max(0, + l_overflow - (kw - 1 - ki) * dilate_w)); + assert(stride_w != 1 + || jj_end == ur_w - nstl::max(0, + r_overflow - ki * dilate_w)); + + for (int jj = jj_start; jj < jj_end; jj += stride_w) { + assert((jj + l_pad - ki * dilate_w) % stride_w == 0); + int aux_dst_offset = typesize * + (((jj + l_pad - ki * dilate_w) + / stride_w) * jcp.oc_block + oc); + vfmadd231ps(zmm_out(jj, 0), zmm_kernel, + EVEX_compress_addr(aux_reg_dst, aux_dst_offset, true)); + + int fma_idx = (step * ur_w + jj) / stride_w; + int prf_slot_idx = fma_idx / prf_inst_spacing; + if (fma_idx % prf_inst_spacing == prf_inst_trigger) { + if (!ker_prf_inserted && ker_prfs < num_ker_loads) { + int ker_prf_offset = typesize + * ker_prfs * jcp.oc_block; + mic_prefetcht1(EVEX_compress_addr( + aux_reg_ker_prf, ker_prf_offset)); + ker_prf_inserted = true; + ker_prfs++; + } else { + int inp_prf_idx = prf_slot_idx - ker_prfs; + if (inp_prf_idx < num_inp_prfs) { + int inp_prf_offset + = ic_block * typesize + * ((inp_prf_idx / kw) * kw + + (inp_prf_idx % kw)); + mic_prefetcht0(EVEX_compress_addr( + aux_reg_dst_prf, inp_prf_offset)); + } + } + } + } + step++; + } + } + + add(aux_reg_ker, typesize * stride_h * kw * oc_block * ic_block); + sub(aux_reg_dst, typesize * (jcp.dilate_h + 1) * ow * oc_block); + add(aux_reg_ker_prf, typesize * stride_h * kw * oc_block * ic_block); + sub(aux_reg_dst_prf, typesize * (jcp.dilate_h + 1) * ow * oc_block); + + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + } + if (jcp.ndims == 5) { + sub(aux_reg_dst_d, + typesize * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block); + add(aux_reg_ker_d, typesize * jcp.stride_d * jcp.kw * jcp.kh + * oc_block * ic_block); + sub(aux_reg_dst_d_prf, + typesize * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block); + add(aux_reg_ker_d_prf, typesize * jcp.stride_d * jcp.kw * jcp.kh + * oc_block * ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_label, T_NEAR); + } + + if (jcp.ndims == 5) + { + pop(reg_src); + pop(reg_src_prf); + } +} + +void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop_fma_core( + int ur_w, int l_overflow, int r_overflow) +{ + int kw = jcp.kw; + int ow = jcp.ow; + int dilate_w = jcp.dilate_w + 1; + int stride_w = jcp.stride_w; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int nb_ic_block = jcp.nb_ic_blocking; + Label kh_label, kd_label; + + int shift_ker_ptr = typesize * kw * oc_block * ic_block; + int shift_dst_ptr = typesize * (jcp.dilate_h + 1) * ow * oc_block; + + auto output_offset = [=](int oi, int oc, int ki) { + return typesize * + (((oi + jcp.l_pad - ki * dilate_w) / stride_w) * oc_block + oc); + }; + auto kernel_offset = [=](int icb, int oc, int ki) { + int blk_idx = icb * jcp.kh * jcp.kw * jcp.kd + ki; + int blk_offset = blk_idx * jcp.oc_block * jcp.ic_block; + int oc_offset = oc * jcp.oc_block; + return typesize * (blk_offset + oc_offset); + }; + + if (one_of(jcp.ndims, 3, 4)) { + mov(aux_reg_dst, reg_dst); + mov(aux_reg_ker, reg_ker); + } + + if (jcp.ndims == 5) { + push(reg_src_prf); + push(reg_src); + + mov(reg_ki, ptr[param + GET_OFF(kd_padding)]); + mov(aux_reg_dst_d, reg_dst); + mov(aux_reg_ker_d, ptr[param + GET_OFF(filt)]); + + L(kd_label); + mov(reg_kj, ptr[param + GET_OFF(kh_padding)]); + } else { + mov(reg_kj, reg_kh); + } + + if (jcp.ndims == 5) { + mov(aux_reg_dst, aux_reg_dst_d); + mov(aux_reg_ker, aux_reg_ker_d); + } + + L(kh_label); + { + for (int ki = 0; ki < kw; ki++) { + int jj_start = get_iw_start(ki, l_overflow); + int jj_end = get_iw_end(ur_w, ki, r_overflow); + for (int oc = 0; oc < oc_block; oc++) { + if (jcp.kernel_kind == expl_bcast) { + for (int jj = jj_start; jj < jj_end; jj++) { + int aux_output_offset = output_offset(jj, oc, ki); + vbroadcastss(zmm_inp(jj, nb_ic_block), + ptr[aux_reg_dst + aux_output_offset]); + } + } + for (int ii = 0; ii < nb_ic_block; ii++) { + int aux_kernel_offset = kernel_offset(ii, oc, ki); + if (jj_end - jj_start > 0) + vmovups(zmm_wei, EVEX_compress_addr(aux_reg_ker, + aux_kernel_offset)); + for (int jj = jj_start; jj < jj_end; jj += stride_w) + if (jcp.kernel_kind == expl_bcast) + vfmadd231ps(zmm_out(jj, ii), + zmm_inp(jj, nb_ic_block), zmm_wei); + else + vfmadd231ps(zmm_out(jj, ii), zmm_wei, + EVEX_compress_addr(aux_reg_dst, + output_offset(jj, oc, ki), true)); + } + } + } + add(aux_reg_ker, shift_ker_ptr); + sub(aux_reg_dst, shift_dst_ptr); + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + } + + if (jcp.ndims == 5) { + sub(aux_reg_dst_d, + typesize * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block); + add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * oc_block * ic_block); + + dec(reg_ki); + cmp(reg_ki, 0); + jg(kd_label, T_NEAR); + + pop(reg_src); + pop(reg_src_prf); + } +} + +inline void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop( + int ur_w, int l_overflow, int r_overflow) +{ + if (jcp.ndims == 5) push(reg_oi); + + prepare_output(ur_w); + + Label skip_compute_loop; + if (jcp.ndims == 5) { + mov(reg_kj, ptr[param + GET_OFF(kd_padding)]); + cmp(reg_kj, 0); + je(skip_compute_loop, T_NEAR); + } + mov(reg_kj, ptr[param + GET_OFF(kh_padding)]); + cmp(reg_kj, 0); + je(skip_compute_loop, T_NEAR); + + if (jcp.ver == ver_4fma) + compute_loop_4fma(ur_w, l_overflow, r_overflow); + else if (jcp.ver == ver_fma) + if (mayiuse(avx512_mic)) + compute_loop_fma(ur_w, l_overflow, r_overflow); + else + if (jcp.kernel_kind == embd_bcast && jcp.nb_ic_blocking == 1) + compute_loop_fma(ur_w, l_overflow, r_overflow); + else + compute_loop_fma_core(ur_w, l_overflow, r_overflow); + else + assert("!unknown convolution version"); + + L(skip_compute_loop); + store_output(ur_w); + if (jcp.ndims == 5) pop(reg_oi); +} + +void jit_avx512_common_conv_bwd_data_kernel_f32::generate() +{ + int iw = jcp.iw; + int kw = jcp.kw; + int ur_w = jcp.ur_w; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int ur_w_tail = jcp.ur_w_tail; + int dilate_w = jcp.dilate_w + 1; + int stride_w = jcp.stride_w; + + int dst_shift = jcp.typesize_in * (ur_w / stride_w) * ic_block; + int src_shift = jcp.typesize_out * ur_w * oc_block; + + preamble(); + + mov(reg_src, ptr[param + GET_OFF(src)]); + mov(reg_dst, ptr[param + GET_OFF(dst)]); + mov(reg_ker, ptr[param + GET_OFF(filt)]); + + mov(reg_kh, ptr[param + GET_OFF(kh_padding)]); + mov(reg_src_prf, ptr[param + GET_OFF(src_prf)]); + mov(reg_dst_prf, ptr[param + GET_OFF(dst_prf)]); + mov(reg_ker_prf, ptr[param + GET_OFF(filt_prf)]); + + int l_overflow = nstl::max(0, ((kw - 1) * dilate_w - jcp.l_pad) / stride_w); + int r_overflow = nstl::max(0, ((kw - 1) * dilate_w + - nstl::max(0, jcp.r_pad)) / stride_w); + int r_overflow1 = nstl::max(0, ((kw - 1) * dilate_w + - nstl::max(0, jcp.r_pad) - ur_w_tail) / stride_w); + + int n_oi = iw / ur_w; + if (r_overflow1 > 0) n_oi--; + + if (ur_w == iw) { + compute_loop(ur_w, l_overflow, r_overflow); + } else if (n_oi == 0) { + compute_loop(ur_w, l_overflow, r_overflow1); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + add(reg_src_prf, src_shift); + add(reg_dst_prf, dst_shift); + if (ur_w_tail != 0) + compute_loop(ur_w_tail, 0, r_overflow); + } else { + xor_(reg_oi, reg_oi); + if (l_overflow > 0) { + compute_loop(ur_w, l_overflow, 0); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + add(reg_src_prf, src_shift); + add(reg_dst_prf, dst_shift); + + inc(reg_oi); + } + if ((l_overflow <= 0 && n_oi > 0) + || (l_overflow > 0 && n_oi > 1)) { + Label ow_loop_label; + L(ow_loop_label); { + compute_loop(ur_w, 0, 0); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + add(reg_src_prf, src_shift); + add(reg_dst_prf, dst_shift); + + inc(reg_oi); + cmp(reg_oi, n_oi); + jl(ow_loop_label, T_NEAR); + } + } + if (r_overflow1 > 0) { + compute_loop(ur_w, 0, r_overflow1); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + add(reg_src_prf, src_shift); + add(reg_dst_prf, dst_shift); + } + if (ur_w_tail != 0) { + compute_loop(ur_w_tail, 0, r_overflow); + } + } + + postamble(); +} + +status_t jit_avx512_common_conv_bwd_data_kernel_f32::init_conf( + jit_conv_conf_t &jcp, + const convolution_desc_t &cd, + const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d) +{ + if (!mayiuse(avx512_common)) return status::unimplemented; + + jcp = zero(); + + jcp.simd_w = cpu_isa_traits::vlen / sizeof(float); + const bool with_groups = weights_d.ndims() == diff_src_d.ndims() + 1; + int ndims = diff_src_d.ndims(); + + jcp.ndims = ndims; + jcp.prop_kind = cd.prop_kind; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = diff_src_d.dims()[0]; + + jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = diff_src_d.dims()[1] / jcp.ngroups; + + jcp.id = (ndims == 5) ? diff_src_d.dims()[2] : 1; + jcp.ih = (ndims == 3) ? 1 : diff_src_d.dims()[ndims-2]; + jcp.iw = diff_src_d.dims()[ndims-1]; + jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1; + jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2]; + jcp.ow = diff_dst_d.dims()[ndims-1]; + + jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1; + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims - 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + + jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0; + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4]; + jcp.l_pad = cd.padding[0][ndims-3]; + + jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1; + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4]; + jcp.stride_w = cd.strides[ndims-3]; + + jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0; + jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4]; + jcp.dilate_w = cd.dilates[ndims-3]; + if ((jcp.dilate_w != 0 && jcp.stride_w != 1) + || (jcp.dilate_d != 0 && jcp.stride_d != 1) + || (jcp.dilate_h != 0 && jcp.stride_h != 1)) + return status::unimplemented; + + jcp.r_pad = (jcp.ow - 1) * jcp.stride_w + (jcp.kw - 1) * (jcp.dilate_w + 1) + - (jcp.iw + jcp.l_pad - 1); + jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1) + - (jcp.ih + jcp.t_pad - 1); + jcp.back_pad = (jcp.od - 1) * jcp.stride_d + + (jcp.kd - 1) * (jcp.dilate_d + 1) - (jcp.id + jcp.f_pad - 1); + + jcp.aligned_threads = 0; + + jcp.is_1stconv = false; + + jcp.oc_block = jcp.simd_w; + jcp.ic_block = jcp.is_1stconv ? jcp.ic : jcp.simd_w; + + bool ok_to_pad_channels = true + && jcp.ngroups == 1 + && diff_src_d.data_type() == data_type::f32; + + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, jcp.oc_block); + jcp.ic = rnd_up(jcp.ic, jcp.ic_block); + } + + auto dat_tag = pick(ndims - 3, nCw16c, nChw16c, nCdhw16c); + auto wei_tag = with_groups + ? pick(ndims - 3, gOIw16o16i, gOIhw16o16i, gOIdhw16o16i) + : pick(ndims - 3, OIw16o16i, OIhw16o16i, OIdhw16o16i); + jcp.src_tag = diff_src_d.matches_one_of_tag(dat_tag); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag); + + bool args_ok = true + && jcp.oc % jcp.oc_block == 0 + && jcp.ic % jcp.ic_block == 0 + && jcp.src_tag == dat_tag + && jcp.dst_tag == dat_tag; + if (!args_ok) + return status::unimplemented; + + jcp.nb_ic = jcp.ic / jcp.ic_block; + jcp.nb_oc = jcp.oc / jcp.oc_block; + + jcp.ur_w = jcp.stride_w; + + int regs = 28; + if (jcp.iw <= regs) + jcp.ur_w = jcp.iw; + else { + for (int ur_w = regs; ur_w > 0; --ur_w) + if (ur_w % jcp.stride_w == 0) { + jcp.ur_w = ur_w; + break; + } + } + int l_overflow = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1) + - jcp.l_pad) / jcp.stride_w); + int r_overflow1 = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1) + - nstl::max(0, jcp.r_pad) - jcp.iw % jcp.ur_w) / jcp.stride_w); + int n_oi = jcp.iw / jcp.ur_w; + if (r_overflow1 > 0) n_oi--; + + if (mayiuse(avx512_common) + && diff_dst_d.data_type() == data_type::f32 + && weights_d.data_type() == data_type::f32 + && diff_src_d.data_type() == data_type::f32) { + jcp.ver = ver_fma; + jcp.typesize_in = sizeof(float); + jcp.typesize_out = sizeof(float); + if (mayiuse(avx512_mic_4ops) + && jcp.stride_w == 1 && jcp.stride_h == 1 && jcp.stride_d == 1) { + jcp.ver = ver_4fma; + } + } else { + return status::unimplemented; + } + + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + if (jcp.wei_tag != wei_tag) + return status::unimplemented; + + if (!utils::everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w) + && jcp.ver != ver_fma) + return status::unimplemented; + + jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1; + if (jcp.ver == ver_4fma) { + if (jcp.kw == 3 && jcp.kh == 3 && jcp.iw == 7 && jcp.ih == 7) { + jcp.nb_ic_blocking = 2; + } else { + for (int i = jcp.nb_ic; i > 0; i--) + if (i * jcp.ur_w <= regs && jcp.nb_ic % i == 0) { + jcp.nb_ic_blocking = i; + break; + } + } + } + + jcp.loop_order = loop_gnc; + + bool large_code_size = (jcp.ur_w != jcp.ow) + && ((l_overflow <= 0 && n_oi > 0) ||(l_overflow > 0 && n_oi > 1)) + && (r_overflow1 > 0) && (l_overflow > 0); + if (large_code_size) { + const int max_code_size = 24 * 1024; + const int num_ops_per_reg = 6 + jcp.oc_block * jcp.kw; + int mult = 1; + if (l_overflow > 0) mult += 1; + if (r_overflow1 > 0) mult += 1; + for (int ur_w = jcp.ur_w; ur_w > regs/2; --ur_w) { + if ((ur_w / jcp.stride_w) * mult * num_ops_per_reg * 9.2 + < max_code_size) { + if (ur_w % jcp.stride_w == 0) { + jcp.ur_w = ur_w; + break; + } + } + } + } + + if (jcp.ver == ver_fma && mayiuse(avx512_core)) { + int try_nb_ic_blocking = 2; + unsigned int ker_inp_size = typesize * jcp.iw * jcp.ic_block + * try_nb_ic_blocking * jcp.kh; + unsigned int ker_out_size = typesize * jcp.ow * jcp.oc_block; + unsigned int ker_wei_size = typesize * jcp.kh * jcp.kw * jcp.ic_block + * jcp.oc_block * try_nb_ic_blocking; + unsigned int ker_total_size = ker_inp_size + ker_out_size + + ker_wei_size; + if (!(jcp.kw == 1 || (jcp.kw == 5 && jcp.iw < 8) + || (jcp.kw < 5 && ((jcp.iw <= 5 || (jcp.iw > 8 && jcp.iw <= 13)) + || ker_total_size > L1_cache_size ))) + || jcp.stride_h > 1 || jcp.stride_d > 1) { + jcp.kernel_kind = embd_bcast; + jcp.ur_w = nstl::min(jcp.iw, regs); + jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1; + if (!(jcp.kw > 3 || (jcp.kw == 3 && ker_total_size < L1_cache_size + && jcp.ow > 8)) && jcp.stride_h == 1) + if (jcp.nb_ic % try_nb_ic_blocking == 0) { + jcp.nb_ic_blocking = try_nb_ic_blocking; + jcp.ur_w = 31 / (jcp.nb_ic_blocking + 1); + if (jcp.iw < jcp.ur_w) jcp.ur_w = jcp.iw; + } + } else { + jcp.kernel_kind = expl_bcast; + jcp.nb_oc_blocking = 1; + jcp.nb_ic_blocking = 4; + if (jcp.nb_ic < jcp.nb_ic_blocking) jcp.nb_ic_blocking = jcp.nb_ic; + if (jcp.nb_ic % jcp.nb_ic_blocking != 0) + for (int i = jcp.nb_ic_blocking; i > 0; i--) + if (jcp.nb_ic % i == 0) { + jcp.nb_ic_blocking = i; + break; + } + jcp.ur_w = 31 / (jcp.nb_ic_blocking + 1); + if (jcp.iw < jcp.ur_w) jcp.ur_w = jcp.iw; + } + } + jcp.ur_w_tail = jcp.iw % jcp.ur_w; + + if (l_overflow * jcp.stride_w > jcp.ur_w) + return status::unimplemented; + int r_overflow_no_tail = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1) + - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail) / jcp.stride_w); + if (r_overflow_no_tail * jcp.stride_w > jcp.ur_w) + return status::unimplemented; + if ((jcp.iw > jcp.ur_w) && (jcp.ur_w % jcp.stride_w != 0)) + return status::unimplemented; + + pick_loop_order(jcp); + + jcp.nb_oc_L2 = jcp.nb_oc; + if (jcp.ver == ver_4fma && (jcp.kh < 5 && jcp.kw < 5)) { + for (int divf = 2, temp_nb = jcp.nb_oc_L2; divf <= jcp.nb_oc; + divf++) { + size_t l2_src = jcp.iw * jcp.ic_block * jcp.nb_ic_blocking * jcp.ih + * jcp.id; + size_t l2_dst = jcp.ow * jcp.oc_block * temp_nb * jcp.oh * jcp.od; + size_t l2_filt = jcp.kw * jcp.oc_block * jcp.ic_block * jcp.kh + * jcp.kd * jcp.nb_ic_blocking * temp_nb; + if (4 * (l2_src + l2_dst + l2_filt) > KNx_L2_EFFECTIVE_CAPACITY) { + if (jcp.kh == 3 && jcp.ih == 7) { + jcp.nb_oc_L2 = 1; + break; + } + temp_nb = (jcp.nb_oc_L2 % divf == 0 ? jcp.nb_oc_L2 / divf + : jcp.nb_oc_L2); + } else { + jcp.nb_oc_L2 = temp_nb; + break; + } + } + } + + args_ok = true + && jcp.ic <= diff_src_d.padded_dims()[1] + && jcp.oc <= diff_dst_d.padded_dims()[1] + && jcp.ic <= weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= weights_d.padded_dims()[with_groups + 0]; + if (!args_ok) return status::unimplemented; + + return status::success; +} + +void jit_avx512_common_conv_bwd_data_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + UNUSED(scratchpad); + UNUSED(jcp); +} + +const int jit_avx512_common_conv_bwd_weights_kernel_f32::max_ur_w = 28; + +void jit_avx512_common_conv_bwd_weights_kernel_f32::od_step_comeback_pointers() +{ + Label kd_comeback_label; + + /* 'depth' loop count bound by 'kd_work_size' */ + mov(kj, reg_kd_count); + L(kd_comeback_label); { + int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block; + int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw; + sub(reg_input, + jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih * iw * inp_mult); + sub(reg_kernel, + jcp.typesize_out * jcp.kh * jcp.kw * jcp.ic_block * jcp.oc_block); + dec(kj); + cmp(kj, 0); + jg(kd_comeback_label, T_NEAR); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::oh_step_comeback_pointers() +{ + Label kh_comeback_label, kd_comeback_label; + mov(kj, reg_kh); + L(kh_comeback_label); { + int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block; + int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw; + sub(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mult); + sub(reg_kernel, + jcp.typesize_out * jcp.kw * jcp.ic_block * jcp.oc_block); + dec(kj); + cmp(kj, 0); + jg(kh_comeback_label, T_NEAR); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_ic_block_step_fma( + int ur_w, int pad_l, int pad_r, + int ic_block_step, int input_offset, int kernel_offset, + int output_offset, bool input_wraparound) +{ + + int kw = jcp.kw; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + for (int i_kw = 0; i_kw < kw; i_kw++) + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) + vmovups(Zmm(i_kw * ic_block_step + i_ic), + EVEX_compress_addr(reg_kernel, typesize * (i_kw * ic_block + + i_ic) * jcp.oc_block + kernel_offset)); + + for (int i_ur = 0; i_ur < ur_w; i_ur++) { + if (i_ur == 0) { + vmovups(Zmm(kw * ic_block_step + (i_ur + 0) % 4), + EVEX_compress_addr(reg_output, typesize * (i_ur + 0) + * oc_block + output_offset)); + if (ur_w > 1) vmovups(Zmm(kw * ic_block_step + (i_ur + 1) % 4), + EVEX_compress_addr(reg_output, typesize * (i_ur + 1) * oc_block + + output_offset)); + if (ur_w > 2) vmovups(Zmm(kw * ic_block_step + (i_ur + 2) % 4), + EVEX_compress_addr(reg_output, typesize * (i_ur + 2) * oc_block + + output_offset)); + if (ur_w > 3) vmovups(Zmm(kw * ic_block_step + (i_ur + 3) % 4), + EVEX_compress_addr(reg_output, typesize * (i_ur + 3) * oc_block + + output_offset)); + } else if (i_ur + 3 < ur_w) + vmovups(Zmm(kw * ic_block_step + (i_ur + 3) % 4), + EVEX_compress_addr(reg_output, typesize * (i_ur + 3) * oc_block + + output_offset)); + + for (int i_kw = 0; i_kw < kw; i_kw++) { + int i_iw = i_ur * jcp.stride_w + i_kw * (jcp.dilate_w + 1); + if (i_iw - pad_l < 0 || i_iw > (ur_w - 1) * jcp.stride_w + + (kw - 1) * (jcp.dilate_w + 1) - pad_r) continue; + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) { + const size_t i_offset = (size_t)input_offset + + (size_t)typesize * (jcp.ver == ver_4fma + ? (i_iw - pad_l + i_ic * jcp.tr_iw) + : (jcp.is_1stconv + ? (i_iw - pad_l) + (size_t)i_ic + * ((size_t)jcp.ih*jcp.iw*jcp.id) + : (i_iw - pad_l) * ic_block + i_ic)); + vfmadd231ps(Zmm(i_kw * ic_block_step + i_ic), + Zmm(kw * ic_block_step + i_ur % 4), + EVEX_compress_addr_safe(reg_input, i_offset, reg_long_offt, + true)); + } + } + } + + for (int i_kw = 0; i_kw < kw; i_kw++) + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) + vmovups(EVEX_compress_addr(reg_kernel, typesize + * (i_kw * ic_block + i_ic) * jcp.oc_block + kernel_offset), + Zmm(i_kw * ic_block_step + i_ic)); +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_ic_block_step_4fma( + int ur_w, int pad_l, int pad_r, + int ic_block_step, int input_offset, int kernel_offset, + int output_offset, bool input_wraparound) +{ + // TODO: add prefetches to fma version as well + + assert(jcp.ver == ver_4fma); + + int kw = jcp.kw; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + + auto zmm_ker = [=](int i_kw, int i_ic) { + return Zmm(i_kw * ic_block_step + i_ic); + }; + + auto ker_addr = [=](int i_kw, int i_ic) { + size_t local_offset + = jcp.typesize_out * (i_kw * ic_block + i_ic) * jcp.oc_block; + return EVEX_compress_addr(reg_kernel, local_offset + kernel_offset); + }; + + auto inp_addr = [=](int i_iw, int i_ic, ptrdiff_t extra_offset = 0) { + int stride = jcp.tr_iw * (jcp.is_1stconv ? jcp.ih : 1); + int local_offset = jcp.typesize_in * (i_iw + i_ic * stride); + return EVEX_compress_addr(reg_input, + local_offset + input_offset + extra_offset); + }; + + auto zmm_out = [=](int i_iw) { + // TODO: move reg calc to global member funcs + const int out_zmm_base_idx = 28; + return Zmm(out_zmm_base_idx + i_iw % 4); + }; + + auto out_addr = [=](int i_ur) { + return EVEX_compress_addr(reg_output, + jcp.typesize_in * i_ur * oc_block + output_offset); + }; + + auto pf_callback = [=](int i_ur, int i_kw, int i_ic) { + assert(i_ur % 4 == 0); + if (i_ur == 0) + prefetcht1(ker_addr(i_kw, i_ic)); + if (i_ur + 4 >= ur_w) + prefetcht0(ker_addr(i_kw, i_ic)); + + const ptrdiff_t next_input_block_offset + = jcp.typesize_in * ic_block_step * jcp.tr_iw; + if (i_ur % 16 == 4 && i_kw == 0) { + if (i_ur + 16 < ur_w) + prefetcht0(inp_addr(i_ur + 16, i_ic)); + else + prefetcht0(inp_addr(0, i_ic, next_input_block_offset)); + } + if (i_ur % 16 == 4 && i_kw == 1) { + if (input_wraparound) + prefetcht1(inp_addr(i_ur, i_ic, -input_offset)); + else + prefetcht1(inp_addr(i_ur, i_ic, next_input_block_offset)); + } + }; + + for (int i_kw = 0; i_kw < kw; i_kw++) + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) { + auto zmm = zmm_ker(i_kw, i_ic); + vpxord(zmm, zmm, zmm); + } + + for (int i_ur = 0; i_ur < ur_w; i_ur += 4) { + + for (int i = 0; i < 4; i++) { + auto zmm = zmm_out(i_ur + i); + if (i_ur + i < ur_w) + vmovups(zmm, out_addr(i_ur + i)); + else + vpxord(zmm, zmm, zmm); + prefetcht0(out_addr(i_ur + i + 4)); + } + + for (int i_kw = 0; i_kw < kw; i_kw++) + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) { + int i_iw = i_ur + i_kw; + v4fmaddps(zmm_ker(i_kw, i_ic), + zmm_out(i_ur), inp_addr(i_iw, i_ic)); + pf_callback(i_ur, i_kw, i_ic); + } + } + + for (int i_kw = 0; i_kw < kw; i_kw++) + for (int i_ic = 0; i_ic < ic_block_step; i_ic++) { + auto addr = ker_addr(i_kw, i_ic); + auto zmm = zmm_ker(i_kw, i_ic); + vaddps(zmm, zmm, addr); + vmovups(addr, zmm); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_ic_block_step( + int ur_w, int pad_l, int pad_r, + int ic_block_step, int input_offset, int kernel_offset, + int output_offset, bool input_wraparound) +{ + if (jcp.ver == ver_4fma) + compute_ic_block_step_4fma(ur_w, pad_l, pad_r, + ic_block_step, input_offset, kernel_offset, output_offset, + input_wraparound); + else if (jcp.ver == ver_fma) + compute_ic_block_step_fma(ur_w, pad_l, pad_r, + ic_block_step, input_offset, kernel_offset, output_offset, + input_wraparound); + else + assert(!"unknown convolution version"); +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32 + ::compute_oh_step_unroll_ow_icblock( + int ic_block_step, int max_ur_w) +{ + UNUSED(max_ur_w); + + Label kh_label, kd_label; + + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int inp_mul = !jcp.is_1stconv ? ic_block : 1; + int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw; + int ow = jcp.ow; + + int r_pad = nstl::max(0, (ow - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1)); + int l_pad = jcp.l_pad; + + if (jcp.ndims == 5) { + L(kd_label); + mov(reg_input, aux_reg_input); + mov(reg_kernel, aux_reg_kernel); + } + + mov(kj, reg_kh); + L(kh_label); + { + for (int i_b_ic = 0; i_b_ic < jcp.ic_block; i_b_ic += ic_block_step) { + const int input_offset = jcp.typesize_in + * (jcp.ver == ver_4fma ? i_b_ic * iw : i_b_ic); + compute_ic_block_step(jcp.ur_w, l_pad, r_pad, ic_block_step, + input_offset, jcp.typesize_out * i_b_ic * jcp.oc_block, 0, + i_b_ic + ic_block_step >= jcp.ic_block); + } + add(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mul); + add(reg_kernel, jcp.typesize_out * jcp.kw * ic_block * oc_block); + dec(kj); + cmp(kj, 0); + jg(kh_label, T_NEAR); + } + + if (jcp.ndims == 5) { + add(aux_reg_input, + jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih * iw * inp_mul); + add(aux_reg_kernel, jcp.typesize_out * jcp.kh * jcp.kw * ic_block + * oc_block); + dec(ki); + cmp(ki, 0); + jg(kd_label, T_NEAR); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32 + ::compute_oh_step_unroll_ow( + int ic_block_step, int max_ur_w) +{ + Label kh_label, ic_block_label, kd_label; + + UNUSED(max_ur_w); + + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + + int ow = jcp.ow; + + int r_pad = nstl::max(0, + (ow - 1) * jcp.stride_w + (jcp.kw - 1) * (jcp.dilate_w + 1) + - (jcp.iw + jcp.l_pad - 1)); + int l_pad = jcp.l_pad; + + if (jcp.ndims == 5) { + L(kd_label); + mov(reg_input, aux_reg_input); + mov(reg_kernel, aux_reg_kernel); + } + + mov(kj, reg_kh); + L(kh_label); + { + xor_(b_ic, b_ic); + L(ic_block_label); { + compute_ic_block_step(ow, l_pad, r_pad, ic_block_step, + 0, 0, 0); + size_t inp_icblk_stride = jcp.is_1stconv + ? (size_t)jcp.ih * jcp.iw * jcp.id + : (jcp.ver == ver_4fma ? jcp.tr_iw : 1); + size_t input_offset + = inp_icblk_stride * jcp.typesize_in * ic_block_step; + safe_add(reg_input, input_offset, reg_long_offt); + add(reg_kernel, jcp.typesize_out * ic_block_step * oc_block); + add(b_ic, ic_block_step); + cmp(b_ic, jcp.ic_block); + jl(ic_block_label, T_NEAR); + } + + if (jcp.is_1stconv) { + size_t input_offset + = (size_t)jcp.typesize_in * jcp.id * jcp.ih * jcp.iw * ic_block; + safe_sub(reg_input, input_offset, reg_long_offt); + add(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw); + } else if (jcp.ver != ver_4fma) { + add(reg_input, jcp.typesize_in + * ((jcp.dilate_h + 1) * jcp.iw - 1) * ic_block); + } + add(reg_kernel, jcp.typesize_out * (jcp.kw - 1) * ic_block * oc_block); + dec(kj); + cmp(kj, 0); + jg(kh_label, T_NEAR); + } + if (jcp.ndims == 5) { + add(aux_reg_input, jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih + * jcp.iw * (jcp.is_1stconv ? 1 : ic_block)); + add(aux_reg_kernel, jcp.typesize_out * jcp.kh * jcp.kw * ic_block + * oc_block); + dec(ki); + cmp(ki, 0); + jg(kd_label, T_NEAR); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32 + ::compute_oh_step_common( + int ic_block_step, int max_ur_w) +{ + Label kh_label, ic_block_label, ow_block_label, kd_label; + + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + + int ow = jcp.ow; + int r_pad = nstl::max(0, (ow - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1)); + int l_pad = jcp.ver == ver_4fma ? 0 : jcp.l_pad; + + int ur_w = nstl::min(ow, max_ur_w); + int ur_w_trips = ow / ur_w; + int ur_w_tail = ow % ur_w; + if ((ur_w_tail == 0 && r_pad != 0) + || r_pad >= ur_w_tail) { + if (ur_w_trips > 1) { + ur_w_tail += ur_w; + ur_w_trips--; + } else { + ur_w_tail += (ur_w - ur_w / 2); + ur_w = ur_w / 2; + } + } + + int inp_mult = (jcp.is_1stconv || jcp.ver == ver_4fma) ? 1 : ic_block; + int input_comeback = (ur_w_trips * ur_w * jcp.stride_w - l_pad) * inp_mult; + int output_comeback = ur_w_trips * ur_w * oc_block; + + if (jcp.ndims == 5) { + L(kd_label); + mov(reg_input, aux_reg_input); + mov(reg_kernel, aux_reg_kernel); + } + + mov(kj, reg_kh); + L(kh_label); { + xor_(b_ic, b_ic); + L(ic_block_label); { + if (l_pad != 0) { + ur_w_trips--; + compute_ic_block_step(ur_w, l_pad, 0, ic_block_step, 0, 0, 0); + add(reg_input, jcp.typesize_in * (ur_w * jcp.stride_w - l_pad) + * inp_mult); + add(reg_output, jcp.typesize_in * ur_w * oc_block); + } + + if (ur_w_trips > 0) { + xor_(reg_ur_w_trips, reg_ur_w_trips); + L(ow_block_label); { + compute_ic_block_step(ur_w, 0, 0, ic_block_step, 0, 0, 0); + add(reg_input, jcp.typesize_in * ur_w * jcp.stride_w + * inp_mult); + add(reg_output, jcp.typesize_in * ur_w * oc_block); + + inc(reg_ur_w_trips); + cmp(reg_ur_w_trips, ur_w_trips); + jl(ow_block_label, T_NEAR); + } + } + + if (ur_w_tail > 0) compute_ic_block_step(ur_w_tail, 0, r_pad, + ic_block_step, 0, 0, 0); + + sub(reg_input, jcp.typesize_in * input_comeback); + sub(reg_output, jcp.typesize_in * output_comeback); + int inp_icblk_stride = jcp.is_1stconv + ? jcp.ih * jcp.iw * jcp.id + : (jcp.ver == ver_4fma ? jcp.tr_iw : 1); + size_t input_offset + = inp_icblk_stride * jcp.typesize_in * ic_block_step; + safe_add(reg_input, input_offset, reg_long_offt); + add(reg_kernel, jcp.typesize_out * ic_block_step * oc_block); + + add(b_ic, ic_block_step); + cmp(b_ic, jcp.ic_block); + jl(ic_block_label, T_NEAR); + } + if (jcp.is_1stconv) { + size_t input_offset + = (size_t)jcp.typesize_in * jcp.id * jcp.ih * jcp.iw * ic_block; + safe_sub(reg_input, input_offset, reg_long_offt); + add(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw); + } else if (jcp.ver != ver_4fma) { + add(reg_input, jcp.typesize_in + * ((jcp.dilate_h + 1 ) * jcp.iw - 1) * ic_block); + } + add(reg_kernel, jcp.typesize_out * (jcp.kw - 1) * ic_block * oc_block); + dec(kj); + cmp(kj, 0); + jg(kh_label, T_NEAR); + } + if (jcp.ndims == 5) { + add(aux_reg_input, jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih + * jcp.iw * (jcp.is_1stconv ? 1 : ic_block)); + add(aux_reg_kernel, jcp.typesize_out * jcp.kh * jcp.kw * ic_block + * oc_block); + dec(ki); + cmp(ki, 0); + jg(kd_label, T_NEAR); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32 + ::compute_oh_step_disp() +{ + int ic_block_step = jcp.kw <= 3 ? 8 : (jcp.kw <= 7 ? 4 : 2); + if (jcp.is_1stconv) { + bool large_code = jcp.kw >= 7 && (jcp.l_pad > 0 || jcp.t_pad > 0); + ic_block_step + = (jcp.kw * jcp.ic_block <= 28 && !large_code) ? jcp.ic_block : 1; + } + + bool too_large_to_unroll + = (jcp.kw > 1 || jcp.kh > 1 || jcp.kd > 1) + && (jcp.stride_w > 1 || jcp.stride_h > 1 || jcp.stride_d > 1); + + int ow = jcp.ow; + if (jcp.ndims == 5) { + /* NOTE: reg_kd_count = aux_reg_input = r12. The following order of + * 'movs' must be guaranteed. */ + mov(ki, reg_kd_count); + push(reg_kd_count); + mov(aux_reg_input, reg_input); + mov(aux_reg_kernel, reg_kernel); + } + + if (jcp.kw <= 3 && ow <= 16 && !too_large_to_unroll) + compute_oh_step_unroll_ow_icblock(ic_block_step, max_ur_w); + else if (ow <= max_ur_w) + compute_oh_step_unroll_ow(ic_block_step, max_ur_w); + else + compute_oh_step_common(ic_block_step, max_ur_w); + + if (jcp.ndims == 5) { + mov(reg_input, aux_reg_input); + mov(reg_kernel, aux_reg_kernel); + pop(reg_kd_count); + od_step_comeback_pointers(); + } else { + oh_step_comeback_pointers(); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::maybe_zero_kernel() +{ + Label skip_zeroing, zeroing_loop; + + mov(reg_tmp, ptr[param + GET_OFF(channel)]); + cmp(reg_tmp, 0); + jz(skip_zeroing, T_NEAR); + + Zmm zero = Zmm(0); + vpxord(zero, zero, zero); + xor_(reg_tmp, reg_tmp); + L(zeroing_loop); { + assert(jcp.oc_block * jcp.typesize_out + == cpu_isa_traits::vlen); + for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) + vmovups(ptr[reg_kernel + reg_tmp + ic1 * jcp.oc_block + * jcp.typesize_out], zero); + add(reg_tmp, jcp.ic_block * jcp.oc_block * jcp.typesize_out); + cmp(reg_tmp, jcp.ic_block * jcp.oc_block * jcp.kw * jcp.kh * jcp.kd + * jcp.typesize_out); + jnz(zeroing_loop); + } + + L(skip_zeroing); +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::bias_kernel() +{ + Label skip_bias, bias_loop, skip_load_bias; + + mov(reg_tmp, ptr[param + GET_OFF(flags)]); + test(reg_tmp,reg_tmp); + jne(skip_bias, T_NEAR); + + mov(reg_bias, ptr[param + GET_OFF(bias)]); + mov(reg_output, ptr[param + GET_OFF(dst)]); + vpxord(Zmm(1), Zmm(1), Zmm(1)); + + mov(reg_tmp, ptr[param + GET_OFF(channel)]); + cmp(reg_tmp, 0); + jne(skip_load_bias, T_NEAR); + vmovups(Zmm(1), ptr[reg_bias]); + + L(skip_load_bias); + + mov(reg_oi, ptr[param + GET_OFF(d_worksize)]); + sub(reg_oi, ptr[param + GET_OFF(d_index)]); + mov(reg_tmp, jcp.oc_block * jcp.ow * jcp.oh * jcp.typesize_out); + imul(reg_oi, reg_tmp); + + xor_(reg_tmp, reg_tmp); + L(bias_loop); { + vmovups(Zmm(0), ptr[reg_output + reg_tmp]); + vaddps(Zmm(1), Zmm(1), Zmm(0)); + add(reg_tmp, jcp.oc_block * jcp.typesize_out); + cmp(reg_tmp, reg_oi); + jl(bias_loop); + } + vmovups(EVEX_compress_addr(reg_bias,0), Zmm(1)); + + L(skip_bias); +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32 + ::compute_oh_loop_common() +{ + int b_pad = jcp.b_pad; + int t_pad = jcp.t_pad; + bool is_dilated = jcp.dilate_h != 0; + int dilate_h = jcp.dilate_h + 1; + int stride_h = jcp.stride_h; + const int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block; + int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw; + Label oh_label, oh_label_end, oh_tpad_label, oh_tpad_tail_label, + oh_bpad_label, oh_bpad_label_end, od_label, od_label_end, + oh_dilate_label_shift, oh_dilate_label_noshift, oh_dilate_label_end; + + int ow = jcp.ow; + + mov(reg_kh, jcp.kh); + xor_(reg_ih_count, reg_ih_count); + xor_(reg_oj, reg_oj); + /* Compute 'top' edge */ + if (t_pad > 0) { + const int kh_range = 1 + (jcp.kh - 1) * dilate_h; + const int overflow + = nstl::max(0, jcp.kh - div_up(t_pad + jcp.ih, dilate_h)); + const int underflow = div_up(t_pad, dilate_h); + const int initial_inp_ker_overlap = jcp.kh - overflow - underflow; + mov(reg_kh, initial_inp_ker_overlap); + add(reg_kernel, jcp.typesize_out * underflow * jcp.kw * jcp.ic_block + * jcp.oc_block); + // generate loop to process kernel while it remains within t_pad + ih + if (kh_range < t_pad + jcp.ih) { + if (is_dilated) { + const int tail = t_pad % dilate_h; + const int shift = tail == 0 ? 0 : dilate_h - tail; + mov(reg_tmp, shift); + if (tail != 0) + add(reg_input, jcp.typesize_in * shift * iw * inp_mult); + } + L(oh_tpad_label); { + compute_oh_step_disp(); + add(reg_output, jcp.typesize_in * ow * jcp.oc_block); + if (is_dilated) { + inc(reg_tmp); + cmp(reg_tmp, dilate_h); + jl(oh_dilate_label_shift, T_NEAR); + // unshift input as new kernel element enters + sub(reg_input, jcp.typesize_in * (dilate_h - 1) * iw * inp_mult); + xor_(reg_tmp, reg_tmp); + } + // kernel overlap only changes when (t_pad + oj) % dilate_h == 0 + sub(reg_kernel, jcp.typesize_out * stride_h * jcp.kw + * jcp.ic_block * jcp.oc_block); + add(reg_kh, stride_h); + if (is_dilated) { + jmp(oh_dilate_label_noshift, T_NEAR); + L(oh_dilate_label_shift); + // shift input as old kernel element progresses + add(reg_input, jcp.typesize_in * stride_h * iw * inp_mult); + L(oh_dilate_label_noshift); + } + inc(reg_oj); + add(reg_ih_count, stride_h); + + // final number of kernel elements that overlap with input + const int final_inp_ker_overlap + = nstl::min(jcp.kh, div_up(jcp.ih, dilate_h)); + cmp(reg_kh, final_inp_ker_overlap); + jl(oh_tpad_label, T_NEAR); + } + } + // need second loop to process kernel if it is larger than the input + // (does not apply to dilations as they must have unit stride) + if (kh_range >= jcp.ih + (t_pad % stride_h == 0 ? stride_h : + t_pad % stride_h)) { + assert(!is_dilated); + mov(reg_kh, jcp.ih); + L(oh_tpad_tail_label); { + compute_oh_step_disp(); + add(reg_output, jcp.typesize_in * ow * jcp.oc_block); + sub(reg_kernel, jcp.typesize_out * stride_h * jcp.kw + * jcp.ic_block * jcp.oc_block); + + inc(reg_oj); + add(reg_ih_count, stride_h); + + cmp(reg_ih_count, nstl::min(t_pad, jcp.oh * stride_h)); + jl(oh_tpad_tail_label, T_NEAR); + } + } + // correct any excess shifts to kernel and input + // (does not apply to dilations as they must have unit stride, + // kernel must fit inside input, and padding is smaller than input) + if (t_pad <= jcp.oh * stride_h) { + // kernel has moved beyond padding (adjust for stride effects) + if (t_pad % stride_h != 0) { + assert(!is_dilated); + int inp_corr = stride_h - t_pad % stride_h; + add(reg_kernel, jcp.typesize_out * inp_corr * jcp.kw + * jcp.ic_block * jcp.oc_block); + add(reg_input, jcp.typesize_in * inp_corr * iw * inp_mult); + } + } else { + // kernel still overlaps padding (complete reset) + assert(!is_dilated); + sub(reg_kernel, jcp.typesize_out * (t_pad - jcp.oh * stride_h) + * jcp.kw * jcp.ic_block * jcp.oc_block); + } + } + + cmp(reg_ih_count, jcp.ihp - b_pad - (jcp.kh - 1) * dilate_h); + jge(oh_label_end, T_NEAR); + cmp(reg_oj, jcp.oh); + jge(oh_label, T_NEAR); + + /* Compute middle block(s) */ + mov(reg_kh, jcp.kh); + L(oh_label); { + compute_oh_step_disp(); + add(reg_input, jcp.typesize_in * stride_h * iw * inp_mult); + add(reg_output, jcp.typesize_in * ow * jcp.oc_block); + + inc(reg_oj); + add(reg_ih_count, stride_h); + + cmp(reg_ih_count, jcp.ihp - b_pad - (jcp.kh - 1) * dilate_h); + jge(oh_label_end, T_NEAR); + + cmp(reg_oj, jcp.oh); + jl(oh_label, T_NEAR); + } + L(oh_label_end); + + /* Compute bottom edge */ + if (b_pad > 0) { + cmp(reg_oj, jcp.oh); + jge(oh_bpad_label_end, T_NEAR); + + if (is_dilated) { + mov(reg_kh, jcp.kh - 1); // assumes unit stride for dilations + mov(reg_tmp, 0); + } else { + mov(reg_kh, jcp.ihp - b_pad); + sub(reg_kh, reg_ih_count); + } + L(oh_bpad_label); + { + compute_oh_step_disp(); + add(reg_input, jcp.typesize_in * stride_h * iw * inp_mult); + add(reg_output, jcp.typesize_in * ow * jcp.oc_block); + if (is_dilated) { + inc(reg_tmp); + cmp(reg_tmp, dilate_h); + jl(oh_dilate_label_end, T_NEAR); + xor_(reg_tmp, reg_tmp); + } + sub(reg_kh, stride_h); + cmp(reg_kh, 0); + jle(oh_bpad_label_end, T_NEAR); + if (is_dilated) + L(oh_dilate_label_end); + + inc(reg_oj); + cmp(reg_oj, jcp.oh); + jl(oh_bpad_label, T_NEAR); + } + L(oh_bpad_label_end); + } +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_d_loop_common() { + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + const int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block; + int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw; + int ow = jcp.ow; + const int input_backpad_overlap + = div_up(jcp.id + jcp.f_pad - (jcp.kd - 1), jcp.stride_d); + + const size_t filter_shift + = jcp.typesize_out * jcp.kh * jcp.kw * ic_block * oc_block; + const size_t input_shift = jcp.typesize_in * jcp.ih * iw * inp_mult; + const size_t output_shift = jcp.typesize_in * jcp.oh * ow * jcp.oc_block; + + Label d_loop_label, loop_end_label, common_block_label, fpad_end_label, + backpad_end_label, backpad_label; + + if (jcp.with_bias) bias_kernel(); + + /* initially offset 'kd' by f_pad */ + add(reg_kernel, ptr[param + GET_OFF(kd_offset)]); + + mov(reg_input_d, ptr[param + GET_OFF(src)]); + mov(reg_output_d, ptr[param + GET_OFF(dst)]); + mov(reg_d_index, ptr[param + GET_OFF(d_index)]); + mov(reg_kd_count, ptr[param + GET_OFF(kd_padding)]); + + cmp(reg_d_index, ptr[param + GET_OFF(d_worksize)]); + jge(loop_end_label, T_NEAR); + + L(d_loop_label); + + mov(reg_input, reg_input_d); + mov(reg_output, reg_output_d); + + push(reg_input_d); + push(reg_output_d); + push(reg_d_index); + + compute_oh_loop_common(); + + pop(reg_d_index); + pop(reg_output_d); + pop(reg_input_d); + + /* Compute 'front' edge */ + if (jcp.f_pad > 0) { + + /* Check if within fpad region */ + cmp(reg_d_index, div_up(jcp.f_pad, jcp.stride_d)); + jge(fpad_end_label, T_NEAR); + + /* Fpad steps */ + sub(reg_kernel, filter_shift * jcp.stride_d); + add(reg_kd_count, jcp.stride_d); + + /* Final number of kernel elements that overlap with input */ + const int inp_ker_overlap = nstl::min(jcp.kd, jcp.id); + cmp(reg_kd_count, inp_ker_overlap); + jl(common_block_label, T_NEAR); + + /* Correct any excess shifts to kernel and input */ + if (jcp.f_pad <= jcp.od * jcp.stride_d) { + /* Filter has moved beyond padding (adjust for stride effects) */ + if (jcp.f_pad % jcp.stride_d != 0) { + int inp_corr = jcp.stride_d - jcp.f_pad % jcp.stride_d; + add(reg_kernel, filter_shift * inp_corr); + add(reg_input_d, input_shift * inp_corr); + } + } else { + /* Filter still overlaps padding (complete reset) */ + sub(reg_kernel, (jcp.f_pad - jcp.od * jcp.stride_d) * filter_shift); + } + + /* Apply correction */ + mov(reg_kd_count, jcp.kd); + jmp(common_block_label); + + L(fpad_end_label); + } + + /* Compute bottom edge */ + if (jcp.back_pad > 0) { + + /* Check if within back_pad region */ + cmp(reg_d_index, input_backpad_overlap - 1); + jl(backpad_end_label, T_NEAR); + jg(backpad_label, T_NEAR); + + /* Execute overlap correction between the filter and the initial + * back_pad region. */ + mov(reg_kd_count, + jcp.id + jcp.f_pad - input_backpad_overlap * jcp.stride_d); + jmp(backpad_end_label, T_NEAR); + + L(backpad_label); + sub(reg_kd_count, jcp.stride_d); + cmp(reg_kd_count, 0); + jle(loop_end_label, T_NEAR); + + L(backpad_end_label); + } + + /* Compute middle block */ + add(reg_input_d, input_shift * jcp.stride_d); + + /* Execute common block and loop */ + L(common_block_label); + add(reg_output_d, output_shift); + inc(reg_d_index); + cmp(reg_d_index, ptr[param + GET_OFF(d_worksize)]); + jl(d_loop_label, T_NEAR); + + L(loop_end_label); +} + +bool jit_avx512_common_conv_bwd_weights_kernel_f32::compute_full_spat_loop() { + // FIXME: use register mapping from the class declaration + bool ok = jcp.ver == ver_4fma + && everyone_is(0, jcp.dilate_h, jcp.dilate_w) + && everyone_is(1, jcp.stride_h, jcp.stride_w); + if (!ok) return false; + if (jcp.l_pad != jcp.kw / 2 || jcp.t_pad != jcp.kh / 2) + return false; + + // General code layout: + // + // Blocking over OH -- top level + // (Reduces L2 pressure; not very useful right now) + // Loop over all KHxKW kernel -- emit_kh_kw_loop() + // Loop over OH block -- emit_h_loop() + // Loop over OW blocks -- emit_fma_block() + // (Supports both fully unrolled and partially unrolled versions to + // reduce code size) + // Loop over OW block -- emit_fma_step() + + int max_working_set_size = 128 * 1024; + int pad_ow = jcp.ow; + + int inp_row_size = jcp.ic_block * jcp.tr_iw * jcp.typesize_in; + int out_row_size = jcp.oc_block * pad_ow * jcp.typesize_in; + int row_size = inp_row_size + out_row_size; + + int h_block_size = jcp.oh; + int working_set_size = row_size * h_block_size; + + if (working_set_size > max_working_set_size) { + int opt_working_set_size = 48 * 1024; + assert(opt_working_set_size < max_working_set_size); + + while (working_set_size > opt_working_set_size) { + for (int i = 2; i <= h_block_size; i++) + if (i == h_block_size) + h_block_size = h_block_size / 2; + else if (h_block_size % i == 0) { + h_block_size = h_block_size / i; + break; + } + working_set_size = row_size * h_block_size; + + if (h_block_size == 1 && working_set_size > opt_working_set_size) + return false; + } + } + + // NB1: t_pad <= oh_block_size and b_pad <= last_oh_block_size (see below) + if (h_block_size < nstl::max(1, jcp.t_pad) + || jcp.b_pad > (jcp.oh % h_block_size == 0 ? h_block_size + : jcp.oh % h_block_size)) + return false; + + // check that we can use simple arithmetic for prefetch address + // calculations + // TODO: we need some traits for this check (Roma) + int cache_line_size = 64; + assert(jcp.ic_block * typesize == 64); + assert(jcp.oc_block * typesize == 64); + + int num_inp_l2_pfs = jcp.tr_iw * h_block_size; + int avg_h_loop_len = h_block_size; + int num_inp_l2_pfs_per_fma_block + = div_up(num_inp_l2_pfs, avg_h_loop_len * jcp.kw * jcp.kh); + int num_out_l2_pfs = pad_ow * h_block_size; + int num_out_l2_pfs_per_fma_block + = div_up(num_out_l2_pfs, avg_h_loop_len * jcp.kw * jcp.kh); + + Opmask reg_h_block = k1; // 32-bit only on Intel(R) Xeon Phi(TM) processors + Reg64 reg_kh = rax; + Reg64 reg_kw = rbx; + Reg64 reg_tmp = abi_not_param1; + Reg32 reg_tmp_w = reg_tmp.cvt32(); + Reg64 reg_ohs = rdx; + Reg64 reg_ihs = rsi; + Reg64 reg_h = r8; + Reg64 reg_i = r9; + Reg64 reg_j = r10; + + Reg64 reg_inp = r13; + Reg64 reg_out = r14; + Reg64 reg_ker = r15; + + Reg64 reg_inp_pf_l1 = rbp; + + Reg64 reg_inp_pf_l2 = r11; + Reg64 reg_out_pf_l2 = r12; + + Xmm reg_inp_pf_save = xmm17; + Xmm reg_out_pf_save = xmm18; + + Reg64 reg_inp_save = abi_param1; + Reg64 reg_out_save = reg_tmp; + + auto zmm_out = [&](int oi) { return Zmm(24 + oi % 8); }; + auto zmm_ker = [&](int ic1) { return Zmm(ic1); }; + auto inp_addr = [&](int oi, int ic1) { + return ptr[reg_inp + (ic1 * jcp.tr_iw + oi) * jcp.typesize_in]; + }; + auto out_addr = [&](int oi, int oj = 0) { + assert(jcp.ver == ver_4fma); + return ptr[reg_out + + ((oi + oj * jcp.ow) * jcp.oc_block) * jcp.typesize_in]; + }; + auto ker_addr = [&](int ic1) { + return ptr[reg_ker + ic1 * jcp.oc_block * jcp.typesize_out]; + }; + + auto emit_block = [&](int h_block_size, + bool is_last_block, bool is_last_kh_kw_iter, bool is_last_row) + { + // TODO: add an fma version (Roma) + auto pad_ow = jcp.ow; + + int ow4u = rnd_up(pad_ow, 4); + int def_step_size = 16; + + bool has_w_tail = (pad_ow % def_step_size != 0 + || pad_ow % 4 != 0); + bool full_w_unroll = pad_ow / def_step_size < 2 + has_w_tail; + + auto emit_step = [&](int ur_ow, + int num_inp_l1_pfs_per_fma_step, + int num_inp_l2_pfs_per_fma_step, + int num_out_l2_pfs_per_fma_step, bool is_w_tail) + { + bool block_wraparound = is_w_tail && is_last_row; + + assert(ur_ow % 4 == 0); + int tail_size = ow4u % ur_ow; + int this_ur_ow + = (is_w_tail && tail_size) ? tail_size : ur_ow; + int ow_last_chunk4 = pad_ow % 4; + int ow_zero_tail4 = ow_last_chunk4 + ? 4 - ow_last_chunk4 : 0; + + auto emit_out_pf = [&](int oi) { +#if 1 + if (oi + def_step_size < ur_ow || !block_wraparound) + mic_prefetcht0(ptr[reg_out + + ((def_step_size + oi) + * jcp.oc_block * jcp.typesize_in)]); + else { + assert(block_wraparound); + assert(oi + def_step_size >= ur_ow); + mic_prefetcht0(ptr[reg_out_save + + ((oi + def_step_size - ur_ow) + * jcp.oc_block * jcp.typesize_in)]); + } +#else + // XXX: This is an alternative prefetching strategy that + // always prefetches the next row. Keeping it here for + // future experiments (Roma) + if (!block_wraparound) + mic_prefetcht0(ptr[reg_out + + (jcp.ow + oi) * jcp.oc_block * jcp.typesize_in]); + else + mic_prefetcht0(ptr[reg_out + reg_ohs + - ((h_block_size - 1) * jcp.ow + - oi) * jcp.oc_block * jcp.typesize_in]); +#endif + if (oi < num_out_l2_pfs_per_fma_step) + mic_prefetcht1(ptr[reg_out_pf_l2 + + oi * jcp.oc_block * jcp.typesize_in]); + }; + + auto emit_inp_pf = [&](int oi4, int ic1) { + int pf_slot_idx = ic1 + oi4 / 4 * jcp.ic_block; + int num_pf_slots = jcp.ic_block * ur_ow / 4; + + int num_pfs = num_inp_l1_pfs_per_fma_step + + num_inp_l2_pfs_per_fma_step; + int pf_freq = nstl::max(1, num_pf_slots / num_pfs); + + if (pf_slot_idx % pf_freq) + return; + + int pf_idx = pf_slot_idx / pf_freq; + + if (pf_idx < num_inp_l2_pfs_per_fma_step) + mic_prefetcht1(ptr[reg_inp_pf_l2 + + pf_idx * jcp.ic_block * jcp.typesize_in]); + else { + pf_idx -= num_inp_l2_pfs_per_fma_step; + // prefetch the 'tail' of the cache line because most of + // the accesses are not aligned + mic_prefetcht0(ptr[reg_inp_pf_l1 + + pf_idx * jcp.ic_block * jcp.typesize_in + + cache_line_size - jcp.typesize_in]); + } + }; + + auto numloads = 4; + + int steps = this_ur_ow; + for (int oi4 = 0; oi4 < steps; oi4 += numloads) { + for (int oi1 = 0; oi1 < numloads; oi1++) { + int oi = oi4 + oi1; + if (!is_w_tail || oi < (this_ur_ow - ow_zero_tail4)) { + vmovups(zmm_out(oi), out_addr(oi)); + emit_out_pf(oi); + } else { + auto zmm = zmm_out(oi); + vpxord(zmm, zmm, zmm); + } + } + + for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) { + if (jcp.ver == ver_4fma) { + v4fmaddps(zmm_ker(ic1), + zmm_out(oi4), inp_addr(oi4, ic1)); + } else { + assert(!"unknown convolution version"); + } + emit_inp_pf(oi4, ic1); + } + } + }; + + // Input is transposed and padded but we only access about jcp.iw + // elements so use that to compute the # of cache lines in each 'row' + int num_inp_l1_pfs + = div_up(jcp.iw * jcp.typesize_in, cache_line_size) * jcp.ic_block; + + if (full_w_unroll) { + emit_step(ow4u, num_inp_l1_pfs, + num_inp_l2_pfs_per_fma_block, + num_out_l2_pfs_per_fma_block, true); + add(reg_inp_pf_l2, num_inp_l2_pfs_per_fma_block * cache_line_size); + add(reg_out_pf_l2, num_out_l2_pfs_per_fma_block * cache_line_size); + } else { + Label w_loop; + int num_w_iters = pad_ow / def_step_size; + int num_w_iters_full = num_w_iters + has_w_tail; + int num_inp_l1_pfs_per_fma_step + = div_up(num_inp_l1_pfs, num_w_iters_full); + int num_inp_l2_pfs_per_fma_step + = div_up(num_inp_l2_pfs_per_fma_block, num_w_iters_full); + int num_out_l2_pfs_per_fma_step + = div_up(num_out_l2_pfs_per_fma_block, num_w_iters_full); + mov(reg_i, num_w_iters); + L(w_loop); { + emit_step(def_step_size, num_inp_l1_pfs_per_fma_step, + num_inp_l2_pfs_per_fma_step, + num_out_l2_pfs_per_fma_step, false); + add(reg_inp, def_step_size * jcp.typesize_in); + add(reg_out, def_step_size * jcp.oc_block * jcp.typesize_in); + add(reg_inp_pf_l1, + num_inp_l1_pfs_per_fma_step * cache_line_size); + add(reg_inp_pf_l2, + num_inp_l2_pfs_per_fma_step * cache_line_size); + add(reg_out_pf_l2, + num_out_l2_pfs_per_fma_step * cache_line_size); + sub(reg_i, 1); + jnz(w_loop); + } + if (has_w_tail) { + emit_step(def_step_size, num_inp_l1_pfs_per_fma_step, + num_inp_l2_pfs_per_fma_step, + num_out_l2_pfs_per_fma_step, true); + add(reg_inp_pf_l2, + num_inp_l2_pfs_per_fma_step * cache_line_size); + add(reg_out_pf_l2, + num_out_l2_pfs_per_fma_step * cache_line_size); + } + // reset reg_inp and reg_out because emit_h_loop expects + // unmodified pointers + int w_offset = num_w_iters * def_step_size; + sub(reg_inp, w_offset * jcp.typesize_in); + sub(reg_out, w_offset * jcp.oc_block * jcp.typesize_in); + } + }; + + auto emit_h_loop = [&](int h_block_size, + bool is_last_block, bool is_last_kh_kw_iter) + { + Label h_loop, skip_h_loop; + mov(reg_j, 1); + cmp(reg_j, reg_h); + je(skip_h_loop, T_NEAR); + L(h_loop); { + + lea(reg_inp_pf_l1, + ptr[reg_inp + jcp.tr_iw * jcp.ic_block * jcp.typesize_in]); + emit_block(h_block_size, + is_last_block, is_last_kh_kw_iter, false); + + add(reg_inp, jcp.tr_iw * jcp.ic_block * jcp.typesize_in); + add(reg_out, pad_ow * jcp.oc_block * jcp.typesize_in); + add(reg_j, 1); + cmp(reg_j, reg_h); + jb(h_loop); + } + + L(skip_h_loop); + + for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) + mic_prefetcht0(ker_addr(ic1)); + + lea(reg_inp_pf_l1, ptr[reg_inp_save + reg_kw * jcp.typesize_in]); + emit_block(h_block_size, is_last_block, is_last_kh_kw_iter, true); + }; + + auto emit_kh_kw_loop = [&](bool is_first_block, bool is_last_block, + int h_block_size) + { + xor_(reg_kh, reg_kh); + Label kh_loop, kh_loop_end; + + int last_oh_block_size + = jcp.oh - rnd_up(jcp.oh - h_block_size, h_block_size); + int oh_block_size = (is_last_block) ? last_oh_block_size : h_block_size; + // NB1: t_pad <= oh_block_size and b_pad <= last_oh_block_size + int ih_block_size = oh_block_size - 1 + jcp.kh + - is_first_block * jcp.t_pad - is_last_block * jcp.b_pad; + + L(kh_loop); { + // determine starting indices for this block + if (is_first_block) { + xor_(reg_tmp, reg_tmp); + mov(reg_ohs, jcp.t_pad); + sub(reg_ohs, reg_kh); + cmovb(reg_ohs, reg_tmp); + + mov(reg_ihs, reg_ohs); + sub(reg_ihs, jcp.t_pad); + add(reg_ihs, reg_kh); + } else { + xor_(reg_ohs, reg_ohs); + mov(reg_ihs, reg_kh); + } + + // determine effective size of block based on padding + mov(reg_tmp, oh_block_size); + sub(reg_tmp, reg_ohs); + mov(reg_h, ih_block_size); + sub(reg_h, reg_ihs); + cmp(reg_tmp, reg_h); + cmovb(reg_h, reg_tmp); + + Label kh_loop_work; + cmp(reg_h, 0); + jg(kh_loop_work, T_NEAR); + + // empty h loop for this jcp.kh: + // - set the output to 0 if necessary + // - move ker pt + // - jump to the end + sub(reg_h, 1); + Label skip_ker_zeroing; + + // The reg_ker ptr has highest bit set if the output needs to be + // zeroed. Those who have byte-aligned their data will suffer the + // consiquences :( + // TODO: move the flag to a mask register? (Roma) + test(reg_ker, 1); + jz(skip_ker_zeroing, T_NEAR); + + Label zeroing_loop; + vpxord(zmm0, zmm0, zmm0); + and_(reg_ker, ~1); // temporarily clear the zeroing flag + mov(reg_tmp, jcp.kw); + L(zeroing_loop); { + for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) + vmovups(ker_addr(ic1), zmm0); + add(reg_ker, jcp.oc_block * jcp.ic_block * jcp.typesize_out); + sub(reg_tmp, 1); + jnz(zeroing_loop, T_NEAR); + } + // restore the zeroing flag (it will be cleared after the end of + // emit_kh_kw_loop, but we may need it until then) + or_(reg_ker, 1); + jmp(kh_loop_end, T_NEAR); + + L(skip_ker_zeroing); + add(reg_ker, jcp.oc_block * jcp.ic_block * jcp.kw + * jcp.typesize_out); + jmp(kh_loop_end, T_NEAR); + + L(kh_loop_work); + + mul_by_const(reg_ihs, reg_tmp, + jcp.tr_iw * jcp.ic_block * jcp.typesize_in); + mul_by_const(reg_ohs, reg_tmp, + pad_ow * jcp.oc_block * jcp.typesize_in); + + add(reg_inp, reg_ihs); + add(reg_out, reg_ohs); + + Label kw_loop; + xor_(reg_kw, reg_kw); + L(kw_loop); { + for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) { + auto zmm = zmm_ker(ic1); + vpxord(zmm, zmm, zmm); + mic_prefetcht1(ker_addr(ic1)); + } + + mov(reg_out_save, reg_out); + mov(reg_inp_save, reg_inp); + lea(reg_inp, ptr[reg_inp + reg_kw * jcp.typesize_in]); + +#if 0 + // XXX: Generate code with special prefetches when switching + // blocks or at the end of the last block. Disabled to reduce + // code size and because there's no performance benefit (Roma) + Label regular_h_loop, end_h_loop; + cmp(reg_kw, jcp.kw - 1); + jne(regular_h_loop, T_NEAR); + cmp(reg_kh, jcp.kh - 1); + jne(regular_h_loop, T_NEAR); + + emit_h_loop(oh_block_size, is_last_block, true); + jmp(end_h_loop, T_NEAR); + + L(regular_h_loop); + emit_h_loop(oh_block_size, is_last_block, false); + + L(end_h_loop); +#else + emit_h_loop(oh_block_size, is_last_block, false); +#endif + + mov(reg_out, reg_out_save); + mov(reg_inp, reg_inp_save); + + Label do_store; + // The reg_ker ptr has highest bit set if the output needs to + // be zeroed. Those who have byte-aligned their data will + // suffer the consiquences :( + mov(reg_tmp, reg_ker); + and_(reg_ker, ~1); + test(reg_tmp, 1); + jnz(do_store, T_NEAR); + + for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) { + auto zmm = zmm_ker(ic1); + if (jcp.ver == ver_4fma) { + vaddps(zmm, ker_addr(ic1)); + } else { + assert(!"unknown convolution version"); + } + } + + L(do_store); + for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) { + auto zmm = zmm_ker(ic1); + vmovups(ker_addr(ic1), zmm); + } + + mov(reg_ker, reg_tmp); + add(reg_ker, jcp.ic_block * jcp.oc_block * jcp.typesize_out); + add(reg_kw, 1); + cmp(reg_kw, jcp.kw); + jl(kw_loop); + } + + sub(reg_inp, reg_ihs); + sub(reg_out, reg_ohs); + + + L(kh_loop_end); + add(reg_kh, 1); + cmp(reg_kh, jcp.kh); + jl(kh_loop); + } + }; + + mov(reg_inp, ptr[param + GET_OFF(src)]); + mov(reg_out, ptr[param + GET_OFF(dst)]); + mov(reg_ker, ptr[param + GET_OFF(filt)]); + mov(reg_inp_pf_l2, ptr[param + GET_OFF(src_prf)]); + mov(reg_out_pf_l2, ptr[param + GET_OFF(dst_prf)]); + mov(reg_tmp, ptr[param + GET_OFF(channel)]); + or_(reg_ker, reg_tmp); + + bool single_kh_kw_loop = (h_block_size == jcp.oh); + + size_t inp_row_step = jcp.tr_iw * jcp.ic_block * jcp.typesize_in; + size_t first_inp_block_step = inp_row_step * (h_block_size - jcp.t_pad); + size_t inp_block_step = inp_row_step * h_block_size; + size_t out_block_step = pad_ow * jcp.oc_block * jcp.typesize_in + * h_block_size; + + if (!single_kh_kw_loop) { + // Save the original prefetch pointers from the OpenMP driver + vmovq(reg_inp_pf_save, reg_inp_pf_l2); + vmovq(reg_out_pf_save, reg_out_pf_l2); + mov(reg_inp_pf_l2, reg_inp); + add(reg_inp_pf_l2, first_inp_block_step); + mov(reg_out_pf_l2, reg_out); + add(reg_out_pf_l2, out_block_step); + } + emit_kh_kw_loop(true, single_kh_kw_loop, h_block_size); + + if (!single_kh_kw_loop) { + size_t ker_reset_offset + = jcp.oc_block * jcp.ic_block * jcp.typesize_out * jcp.kw * jcp.kh; + sub(reg_ker, ker_reset_offset); + and_(reg_ker, ~1); // Clear the zeroing flag for subsequent updates + + add(reg_inp, first_inp_block_step); + add(reg_out, out_block_step); + mov(reg_inp_pf_l2, reg_inp); + add(reg_inp_pf_l2, inp_block_step); + mov(reg_out_pf_l2, reg_out); + add(reg_out_pf_l2, out_block_step); + + int num_innermost_iters = div_up(jcp.oh, h_block_size) - 2; + if (num_innermost_iters > 0) { + Label h_block_loop; + + mov(reg_tmp_w, num_innermost_iters); + kmovw(reg_h_block, reg_tmp_w); + L(h_block_loop); { + emit_kh_kw_loop(false, false, h_block_size); + sub(reg_ker, ker_reset_offset); + add(reg_inp, inp_row_step * h_block_size); + add(reg_out, out_block_step); + mov(reg_inp_pf_l2, reg_inp); + add(reg_inp_pf_l2, inp_block_step); + mov(reg_out_pf_l2, reg_out); + add(reg_out_pf_l2, out_block_step); + kmovw(reg_tmp_w, reg_h_block); + sub(reg_tmp_w, 1); + kmovw(reg_h_block, reg_tmp_w); + jnz(h_block_loop); + } + } + + // Restore the original prefetch pointers that came from the OpenMP + // driver + vmovq(reg_inp_pf_l2, reg_inp_pf_save); + vmovq(reg_out_pf_l2, reg_out_pf_save); + emit_kh_kw_loop(false, true, h_block_size); + } + + return true; +} + +bool jit_avx512_common_conv_bwd_weights_kernel_f32 + ::flat_4ops_compute() { + const auto &j = jcp; + const bool ok = j.ver == ver_4fma && j.is_1stconv + && everyone_is(0, j.dilate_h, j.dilate_w); + if (!ok) return false; + + Reg64 reg_ptr_tr_src = r8; + Reg64 reg_ptr_dst = r9; + Reg64 reg_ptr_wei = r10; + Reg64 reg_ptr_bia = r11; + + Reg64 reg_kh_step = rax; + Reg64 reg_oh = abi_not_param1; + Reg64 reg_kh = rdx; + + Reg32 reg_flag_save = ebx; + Reg32 reg_flag = esi; + + Zmm vbia(31); + + auto zmm_wei = [&](int kh, int kw) { + return Zmm(8 + kh * j.kw + kw); + }; + auto zmm_dst = [&](int ow) { + return Zmm(ow % 8); + }; + + auto addr_tr_src = [&](int kh, int iw) { + return ptr[reg_ptr_tr_src + + (kh * j.stride_w * j.tr_ld + iw) * jcp.typesize_in]; + }; + auto addr_dst = [&](int ow) { + return ptr[reg_ptr_dst + ow * jcp.oc_block * jcp.typesize_in]; + }; + auto addr_wei = [&](int kh, int kw) { + return ptr[reg_ptr_wei + (kh * j.kw + kw) * j.oc_block + * jcp.typesize_out]; + }; + + auto emit_fma_block = [&](int kh_step) { + for (int kh = 0; kh < kh_step; ++kh) { + for (int kw = 0; kw < j.kw; ++kw) { + auto vwei = zmm_wei(kh, kw); + vpxord(vwei, vwei, vwei); + } + } + + for (int ow = 0; ow < j.ow; ow += 4) { + for (int _ow = ow; _ow < ow + 4; ++_ow) { + auto vdst = zmm_dst(_ow); + if (_ow < j.ow) + vmovups(vdst, addr_dst(_ow)); + else + vpxord(vdst, vdst, vdst); + } + + for (int kh = 0; kh < kh_step; ++kh) { + for (int kw = 0; kw < j.kw; ++kw) { + const int iw = ow + (kw % j.stride_w) * j.tr_ld + + (kw / j.stride_w); + v4fmaddps(zmm_wei(kh, kw), zmm_dst(ow), + addr_tr_src(kh, iw)); + if (1 && kh == 0 && kw < 4) { + prefetcht1(ptr[reg_ptr_dst + + (j.ow + ow + kw) * jcp.oc_block + * jcp.typesize_in]); + } + if (j.with_bias && kh_step == 1) { /* [bwd_w:b:r1] */ + const int off = kw + 4 - j.kw; + if (off >= 0 && ow + off < j.ow) + vaddps(vbia, vbia, zmm_dst(ow + off)); + } + } + } + } + + Label l_store; + test(reg_flag, FLAG_MB_FIRST); + jnz(l_store, T_NEAR); + for (int kh = 0; kh < kh_step; ++kh) { + for (int kw = 0; kw < j.kw; ++kw) + vaddps(zmm_wei(kh, kw), addr_wei(kh, kw)); + } + L(l_store); + for (int kh = 0; kh < kh_step; ++kh) { + for (int kw = 0; kw < j.kw; ++kw) + vmovups(addr_wei(kh, kw), zmm_wei(kh, kw)); + } + }; + + auto emit_kh_loop = [&]() { + const int kh_step_rem = j.kh % j.kh_step; + xor_(reg_kh, reg_kh); + mov(reg_kh_step, j.kh_step); + + Label l_kh_loop; + L(l_kh_loop); { + Label l_done; + + if (kh_step_rem != 0) { + Label l_keep_kh_step; + cmp(reg_kh, j.kh - j.kh_step); + jle(l_keep_kh_step, T_NEAR); + + mov(reg_kh_step, kh_step_rem); + emit_fma_block(kh_step_rem); + jmp(l_done, T_NEAR); + + L(l_keep_kh_step); + } + + emit_fma_block(j.kh_step); + + L(l_done); + + add(reg_ptr_tr_src, j.kh_step * j.stride_w * j.tr_ld + * jcp.typesize_in); + add(reg_ptr_wei, j.kh_step * j.kw * j.oc_block * jcp.typesize_out); + add(reg_kh, j.kh_step); + + cmp(reg_kh, j.kh); + jl(l_kh_loop, T_NEAR); + } + + const int kh_steps = rnd_up(j.kh, j.kh_step); + sub(reg_ptr_tr_src, kh_steps * j.stride_w * j.tr_ld * jcp.typesize_in); + sub(reg_ptr_wei, kh_steps * j.kw * j.oc_block * jcp.typesize_out); + }; + + auto emit_oh_loop = [&]() { + mov(reg_oh, j.oh); + + Label l_oh_loop; + L(l_oh_loop); { + Label l_restore_mb_flag, l_jump; + + cmp(reg_oh, j.oh); + je(l_restore_mb_flag, T_NEAR); + + and_(reg_flag, ~FLAG_MB_FIRST); + jmp(l_jump, T_NEAR); + + L(l_restore_mb_flag); + mov(reg_flag, reg_flag_save); + + L(l_jump); + + emit_kh_loop(); + + add(reg_ptr_tr_src, j.stride_h * j.stride_w * j.tr_ld + * jcp.typesize_in); + add(reg_ptr_dst, j.ow * j.oc_block * jcp.typesize_in); + + dec(reg_oh); + jnz(l_oh_loop, T_NEAR); + } + }; + + auto emit_bia_store = [&]() { + if (!j.with_bias) return; + + Label l_bia_store, l_bia_skip; + test(reg_flag, FLAG_IC_FIRST); + jz(l_bia_skip); + + test(reg_flag, FLAG_MB_FIRST); + jnz(l_bia_store, T_NEAR); + vaddps(vbia, ptr[reg_ptr_bia]); + L(l_bia_store); + vmovups(ptr[reg_ptr_bia], vbia); + L(l_bia_skip); + }; + + mov(reg_ptr_tr_src, ptr[param + GET_OFF(src)]); + mov(reg_ptr_dst, ptr[param + GET_OFF(dst)]); + mov(reg_ptr_wei, ptr[param + GET_OFF(filt)]); + mov(reg_ptr_bia, ptr[param + GET_OFF(bias)]); + mov(reg_flag_save, ptr[param + GET_OFF(flags)]); + + vpxord(vbia, vbia, vbia); + emit_oh_loop(); + emit_bia_store(); + + return true; +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_loop() +{ + if (flat_4ops_compute()) + return; + if (compute_full_spat_loop()) + return; + + maybe_zero_kernel(); + + if (jcp.ndims == 5) compute_d_loop_common(); + else compute_oh_loop_common(); +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::generate() +{ + preamble(); + + mov(reg_input, ptr[param + GET_OFF(src)]); + mov(reg_output, ptr[param + GET_OFF(dst)]); + mov(reg_kernel, ptr[param + GET_OFF(filt)]); + + compute_loop(); + + postamble(); +} + +status_t jit_avx512_common_conv_bwd_weights_kernel_f32::init_conf( + jit_conv_conf_t &jcp, const convolution_desc_t &cd, + memory_desc_t &src_md, memory_desc_t &diff_weights_md, + memory_desc_t &diff_bias_md, memory_desc_t &diff_dst_md) { + if (!mayiuse(avx512_common)) + return status::unimplemented; + + const memory_desc_wrapper src_d(&src_md); + const memory_desc_wrapper diff_weights_d(&diff_weights_md); + const memory_desc_wrapper diff_bias_d(&diff_bias_md); + const memory_desc_wrapper diff_dst_d(&diff_dst_md); + + const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1; + int ndims = src_d.ndims(); + + jcp = zero(); + + jcp.simd_w = cpu_isa_traits::vlen / sizeof(float); + jcp.ndims = ndims; + jcp.prop_kind = cd.prop_kind; + + jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + jcp.id = (ndims == 5) ? src_d.dims()[2] : 1; + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2]; + jcp.iw = src_d.dims()[ndims-1]; + jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1; + jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2]; + jcp.ow = diff_dst_d.dims()[ndims-1]; + + jcp.kd = (ndims == 5) ? diff_weights_d.dims()[with_groups + 2] : 1; + jcp.kh = (ndims == 3) ? 1 : diff_weights_d.dims()[with_groups + ndims-2]; + jcp.kw = diff_weights_d.dims()[with_groups + ndims-1]; + + jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0; + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4]; + jcp.l_pad = cd.padding[0][ndims-3]; + + jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1; + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4]; + jcp.stride_w = cd.strides[ndims-3]; + + jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0; + jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4]; + jcp.dilate_w = cd.dilates[ndims-3]; + + const int kh_range = 1 + (jcp.kh - 1) * (jcp.dilate_h + 1); + bool ok = true + // general condition to simplify dilations + && IMPLICATION(jcp.dilate_d != 0, jcp.stride_d == 1) + && IMPLICATION(jcp.dilate_h != 0, jcp.stride_h == 1) + && IMPLICATION(jcp.dilate_w != 0, jcp.stride_w == 1) + // special condition to simplify dilations in compute_oh_loop_common + && IMPLICATION(jcp.dilate_h != 0, kh_range <= jcp.ih); + if (!ok) + return status::unimplemented; + + jcp.r_pad = nstl::max(0, (jcp.ow - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1)); + jcp.b_pad = nstl::max(0, (jcp.oh - 1) * jcp.stride_h + + (jcp.kh - 1) * (jcp.dilate_h + 1) - (jcp.ih + jcp.t_pad - 1)); + jcp.back_pad = nstl::max(0, (jcp.od - 1) * jcp.stride_d + + (jcp.kd - 1) * (jcp.dilate_d + 1) - (jcp.id + jcp.f_pad - 1)); + + /* XXX: currently, does not support dilation_d > 0 */ + if (ndims == 5) + if (jcp.dilate_d > 0) + return status::unimplemented; + + jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad; + jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad; + jcp.ohp = jcp.oh; + jcp.owp = jcp.ow; + jcp.aligned_threads = 0; + + /* check for the 1st convolution */ + jcp.is_1stconv = is_1stconv(jcp); + + jcp.oc_block = jcp.simd_w; + + bool ok_to_pad_channels = true + && jcp.ngroups == 1 + && src_d.data_type() == data_type::f32; + + if (ok_to_pad_channels) + jcp.oc = rnd_up(jcp.oc, jcp.simd_w); + + if (jcp.oc % jcp.oc_block) + return status::unimplemented; + + auto dst_tag = pick(ndims - 3, nCw16c, nChw16c, nCdhw16c); + auto wei_tag = with_groups + ? pick(ndims - 3, gOIw16i16o, gOIhw16i16o, gOIdhw16i16o) + : pick(ndims - 3, OIw16i16o, OIhw16i16o, OIdhw16i16o); + + if (diff_dst_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(diff_dst_md, dst_tag)); + jcp.dst_tag = dst_tag; + } else { + jcp.dst_tag = diff_dst_d.matches_one_of_tag(dst_tag); + } + if (jcp.dst_tag != dst_tag) + return status::unimplemented; + + /* conditions on bias memory */ + jcp.with_bias = cd.diff_bias_desc.format_kind != format_kind::undef; + if (jcp.with_bias) { + if (diff_bias_d.format_kind() == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_bias_md, x)); + } + + jcp.nb_oc = jcp.oc / jcp.oc_block; + + /* kernel applicability check wrt boundaries + * the conditions are quite general across the kernels we have, + * but ideally the check should belong to a specific kernel... */ + const int max_pad = ((jcp.kh - 1) * (jcp.dilate_h + 1) + 1) / 2; + const bool boundaries_ok = true + && jcp.t_pad <= max_pad + && jcp.b_pad <= max_pad + && IMPLICATION(jcp.f_pad > 0, jcp.kd < jcp.id + jcp.f_pad) + && jcp.f_pad < jcp.kd; + if (!boundaries_ok) + return status::unimplemented; + + /* yet another common check */ + if (jcp.kw > 14) + return status::unimplemented; + + /* setting register strategy */ + for (int ur_w = nstl::min(max_ur_w, jcp.ow); ur_w > 0; --ur_w) { + if (jcp.ow % ur_w == 0) { jcp.ur_w = ur_w; break; } + } + + if (jcp.is_1stconv) { + auto src_tag = pick(ndims - 3, ncw, nchw, ncdhw); + if (src_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(src_md, src_tag)); + jcp.src_tag = src_tag; + } else { + jcp.src_tag = src_d.matches_one_of_tag(src_tag); + if (jcp.ic == 1 && jcp.src_tag != src_tag) + jcp.src_tag = src_d.matches_one_of_tag( + pick(ndims - 3, nwc, nhwc, ndhwc)); + } + if (jcp.src_tag == format_tag::undef) + return status::unimplemented; + + const bool src_ok = true + && utils::everyone_is(data_type::f32, + src_d.data_type(), diff_weights_d.data_type(), + diff_dst_d.data_type()) + && one_of(jcp.ic, 1, 2, 3) + && jcp.ngroups == 1; + if (!src_ok) + return status::unimplemented; + + const int tr_ld = rnd_up(div_up(jcp.iw + jcp.l_pad + jcp.r_pad, + jcp.stride_w), 16); + const int kh_step = nstl::max((28 - jcp.with_bias) / jcp.kw, 1); + const int kh_step_rem = jcp.kh % kh_step; + + const auto wei_4fma_tag = with_groups + ? pick(ndims - 3, gOiw16o, gOihw16o, gOidhw16o) + : pick(ndims - 3, Oiw16o, Oihw16o, Oidhw16o); + + auto current_wei_tag = format_tag::undef; + if (diff_weights_d.format_kind() != format_kind::any) + current_wei_tag = diff_weights_d.matches_one_of_tag(wei_4fma_tag); + + const bool use_4fma = true + && one_of(ndims, 3, 4) + && mayiuse(avx512_mic_4ops) + && mkldnn_thr_syncable() + && everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w) + && everyone_is(0, jcp.l_pad, jcp.r_pad, jcp.t_pad, jcp.b_pad) + && jcp.kw <= 28 - jcp.with_bias + && jcp.stride_w == 4 + && tr_ld / jcp.simd_w <= 4 /* [bwd_w:tr_src:r1] */ + && IMPLICATION(jcp.with_bias, kh_step_rem == 1) /* [bwd_w:b:r1] */ + && IMPLICATION(diff_weights_d.format_kind() != format_kind::any, + current_wei_tag == wei_4fma_tag); + + if (use_4fma) { + jcp.ver = ver_4fma; + jcp.kh_step = kh_step; + jcp.tr_ld = tr_ld; + jcp.ic_block = 1; + if (diff_weights_d.format_kind() == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_weights_md, wei_4fma_tag)); + jcp.wei_tag = wei_4fma_tag; + } else { + jcp.ver = ver_fma; + jcp.ic_block = jcp.ic; + + wei_tag = with_groups + ? pick(ndims - 3, gOwi16o, gOhwi16o, gOdhwi16o) + : pick(ndims - 3, Owi16o, Ohwi16o, Odhwi16o); + + if (diff_weights_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(diff_weights_md, wei_tag)); + jcp.wei_tag = wei_tag; + } else { + jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag); + } + if (jcp.wei_tag != wei_tag) + return status::unimplemented; + } + + jcp.nb_ic = jcp.ic / jcp.ic_block; + } else { + auto src_tag = pick(ndims - 3, nCw16c, nChw16c, nCdhw16c); + if (src_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(src_md, src_tag)); + jcp.src_tag = src_tag; + } else { + jcp.src_tag = src_d.matches_one_of_tag(src_tag); + } + if (jcp.src_tag != src_tag) + return status::unimplemented; + + if (diff_weights_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(diff_weights_md, wei_tag)); + jcp.wei_tag = wei_tag; + } else { + jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag); + } + if (jcp.wei_tag != wei_tag) + return status::unimplemented; + + jcp.ic_block = jcp.simd_w; + if (ok_to_pad_channels) + jcp.ic = rnd_up(jcp.ic, jcp.ic_block); + jcp.nb_ic = jcp.ic / jcp.ic_block; + if ((mayiuse(avx512_mic) || mayiuse(avx512_core)) + && utils::everyone_is(data_type::f32, + src_d.data_type(), diff_weights_d.data_type(), + diff_dst_d.data_type())) { + jcp.ver = ver_fma; + if (one_of(ndims, 3, 4) && mayiuse(avx512_mic_4ops) && jcp.stride_w == 1 && + everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w) && + mkldnn_thr_syncable()) { + jcp.ver = ver_4fma; + } + } else { + return status::unimplemented; + } + if (jcp.ver == ver_4fma) { + jcp.ur_w = jcp.ow; + // XXX, BUGBUGBUG, but not a FIXME: this assumes that it's OK to + // cross the right boundary. The only requirement is not to have + // NaNs there because another multiplicand is always guaranteed to + // be zero. This also may require the top-level driver to allocate + // four extra guarding elements at the very end of the buffer. + // I'm not proud of this hack, but it improves performance by + // about 5-10% depending on the dimensions (Roma) + + const int tr_round = 4; + + jcp.tr_iw = rnd_up(jcp.iw + jcp.kw - 1, tr_round); + jcp.tr_src_num_guard_elems = tr_round; // upper bound + } + } + + if (utils::one_of(jcp.ver, ver_4fma, ver_fma)) { + jcp.typesize_in = sizeof(float); + jcp.typesize_out = sizeof(float); + } else + return status::unimplemented; + + bool args_ok = true + && jcp.ic % jcp.ic_block == 0 + && jcp.oc % jcp.oc_block == 0 + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= diff_dst_d.padded_dims()[1] + && jcp.ic <= diff_weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= diff_weights_d.padded_dims()[with_groups + 0]; + if (!args_ok) return status::unimplemented; + + { // balancing + int nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b; + balance(jcp, nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b); + jcp.nthr = nthr; + jcp.nthr_mb = nthr_mb; + jcp.nthr_g = nthr_g; + jcp.nthr_oc_b = nthr_oc_b; + jcp.nthr_ic_b = nthr_ic_b; + } + + return status::success; +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + if (jcp.ver == ver_4fma) { + if (jcp.is_1stconv) { + const size_t tr_src_size = + jcp.nthr / jcp.nthr_oc_b * jcp.ih * jcp.stride_w * jcp.tr_ld; + scratchpad.book(key_conv_tr_src, jcp.typesize_in * tr_src_size); + } else { + // XXX: See the comment about tr_iw and guarding elements in + // jit_avx512_common_conv_bwd_weights_kernel_f32::init_conf() + const size_t max_nthr = jcp.nthr_mb * jcp.ngroups * jcp.nb_ic; + const size_t min_tr_src_size_per_thr + = jcp.ih * jcp.ic_block * jcp.tr_iw; + const size_t tr_src_size = max_nthr * min_tr_src_size_per_thr + + jcp.tr_src_num_guard_elems; + scratchpad.book(key_conv_tr_src, jcp.typesize_in * tr_src_size); + } + + /* prepare synchronization contexts */ + if (jcp.nthr_oc_b > 1) { + const int tr_src_bctx_size = jcp.nthr / jcp.nthr_oc_b; + scratchpad.book(key_conv_tr_src_bctx, + sizeof(simple_barrier::ctx_t) * tr_src_bctx_size); + } + } + + if (jcp.nthr_mb > 1) { + const int wei_size = jcp.ngroups * jcp.oc * jcp.ic + * jcp.kh * jcp.kw * jcp.kd; + const int bia_size = jcp.ngroups * jcp.oc; + const size_t wei_bia_reduction_size = wei_size + bia_size; + + scratchpad.book(key_conv_wei_bia_reduction, + jcp.typesize_out * wei_bia_reduction_size * (jcp.nthr_mb - 1)); + scratchpad.book(key_conv_wei_bia_reduction_bctx, + sizeof(simple_barrier::ctx_t)); + } + + if (jcp.with_bias && jcp.oc != jcp.oc_without_padding) + scratchpad.book(key_conv_padded_bias, jcp.typesize_out * jcp.oc); +} + +void jit_avx512_common_conv_bwd_weights_kernel_f32::balance( + const jit_conv_conf_t &j, int &nthr_, int &nthr_mb_, int &nthr_g_, + int &nthr_oc_b_, int &nthr_ic_b_) +{ + nthr_ = nthr_mb_ = nthr_g_ = nthr_oc_b_ = nthr_ic_b_ = 1; + + const int max_threads = mkldnn_get_max_threads(); + + if (max_threads < j.ngroups) { + /* simplification... fortunately it doesn't hurt much */ + return; + } + + if (!mkldnn_thr_syncable() && j.ver == ver_4fma) { + // should not happen -- the driver is not ready + // for TBB-like non-synchronous threading yet + return; + } + + if (j.ver == ver_4fma && j.is_1stconv) { + nthr_g_ = 1; + nthr_oc_b_ = 1; + nthr_ic_b_ = nstl::min(j.nb_ic, max_threads); + nthr_mb_ = nstl::min(max_threads / nthr_ic_b_, j.mb); + nthr_ = nthr_mb_ * nthr_oc_b_ * nthr_ic_b_ * nthr_g_; + return; + } + + nthr_g_ = j.ngroups; + const int nthr = max_threads / nthr_g_; + + auto calc_mem_cost = [=](int nthr_mb, int nthr_oc_b, int nthr_ic_b) { + /* calculate per thread memory cost (read/write). high level optimizer + * tries to minimize memory consumption. few notes: + * (n1) unclear why, but that essentially helps first convolution... + * (n2) assuming the reduction over minibatch is always there: + * - instead of 8 it should be 5 here (write ~= 2 read): + * kernel: temporal workspace 1 write + * reduction: 1 read from workspace and 1 write to the diff_wei + * - but experiments showed 8 works better than 5 or 6... */ + + const int src_coef = j.ver == ver_4fma ? 4 : 1; + const int dst_coef = 1; + const int wei_coef = 8; + + return 0 + + src_coef + * div_up(j.mb, nthr_mb) * div_up(j.ngroups, nthr_g_) + * div_up(j.nb_ic, nthr_ic_b) * j.ic_block * j.ih * j.iw * j.id + / j.stride_d / j.stride_h / j.stride_w /* (n1) */ + + dst_coef + * div_up(j.mb, nthr_mb) * div_up(j.ngroups, nthr_g_) + * div_up(j.nb_oc, nthr_oc_b) * j.oc_block * j.oh * j.ow * j.od + + wei_coef /* (n2) */ + * div_up(j.ngroups, nthr_g_) + * div_up(j.nb_oc, nthr_oc_b) * div_up(j.nb_ic, nthr_ic_b) + * j.kh * j.kw * j.kd * j.ic_block * j.oc_block; + }; + + int best_mem_cost = calc_mem_cost(nthr_mb_, nthr_oc_b_, nthr_ic_b_); + + /* step 1: find the best thread distribution with lowest memory cost */ + const int nthr_mb_max = nstl::min(nthr, j.mb * j.od); + for (int nthr_mb = 1; nthr_mb <= nthr_mb_max; ++nthr_mb) { + const int nthr_par = nthr / nthr_mb; + const int nthr_oc_b_max = nstl::min(nthr_par, j.nb_oc); + for (int nthr_oc_b = 1; nthr_oc_b <= nthr_oc_b_max; ++nthr_oc_b) { + int nthr_ic_b = nstl::min(nthr_par / nthr_oc_b, j.nb_ic); + + int mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b); + if (mem_cost <= best_mem_cost) { + best_mem_cost = mem_cost; + nthr_mb_ = nthr_mb; + nthr_oc_b_ = nthr_oc_b; + nthr_ic_b_ = nthr_ic_b; + } + } + + if (!mkldnn_thr_syncable()) { assert(nthr_mb == 1); break; } + } + + if (!mayiuse(avx512_mic)) { + auto calc_comp_cost = [=](int nthr_mb, int nthr_oc_b, int nthr_ic_b) { + return 1 + * div_up(j.mb, nthr_mb) + * div_up(j.ngroups, nthr_g_) + * div_up(j.nb_oc, nthr_oc_b) + * div_up(j.nb_ic, nthr_ic_b); + }; + + /* step 2: search for a thread distribution with lower compute cost. + * the constrains: + * - memory cost cannot exceed 110% of the best found in the step 1 + * - unless compute cost is 133% lower than the current best case + * note: both constants were found empirically */ + int best_comp_cost = calc_comp_cost(nthr_mb_, nthr_oc_b_, nthr_ic_b_); + for (int nthr_mb = 1; nthr_mb <= nthr_mb_max; ++nthr_mb) { + const int nthr_par = nthr / nthr_mb; + const int nthr_oc_b_max = nstl::min(nthr_par, j.nb_oc); + for (int nthr_oc_b = 1; nthr_oc_b <= nthr_oc_b_max; ++nthr_oc_b) { + int nthr_ic_b = nstl::min(nthr_par / nthr_oc_b, j.nb_ic); + int mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b); + int comp_cost = calc_comp_cost(nthr_mb, nthr_oc_b, nthr_ic_b); + + const bool opt1 = comp_cost <= best_comp_cost + && mem_cost < 1.1 * best_mem_cost; + const bool opt2 = 4 * comp_cost <= 3 * best_comp_cost; + + if (opt1 || opt2) { + best_comp_cost = comp_cost; + nthr_mb_ = nthr_mb; + nthr_oc_b_ = nthr_oc_b; + nthr_ic_b_ = nthr_ic_b; + } + } + + if (!mkldnn_thr_syncable()) { assert(nthr_mb == 1); break; } + } + } + + if (nthr_mb_ > max_threads/2 && nthr_mb_ < max_threads) + nthr_mb_ = nstl::min(j.mb * j.od, max_threads); + nthr_ = nthr_mb_ * nthr_g_ * nthr_oc_b_ * nthr_ic_b_; + + assert(nthr_ <= max_threads); + assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_mb_ == 1)); +} + +template struct _jit_avx512_common_conv_fwd_kernel; +template struct _jit_avx512_common_conv_fwd_kernel; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp new file mode 100644 index 0000000000..f76770797a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp @@ -0,0 +1,423 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX512_COMMON_CONV_KERNEL_F32_HPP +#define JIT_AVX512_COMMON_CONV_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct _jit_avx512_common_conv_fwd_kernel : public jit_generator { + + _jit_avx512_common_conv_fwd_kernel(jit_conv_conf_t ajcp, + const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32( + this, jcp.eltwise); + + generate(); + jit_ker_ = (void (*)(jit_conv_call_s *))getCode(); + } + + ~_jit_avx512_common_conv_fwd_kernel() { + delete eltwise_injector_; + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_common_conv_fwd_kernel) + + jit_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker_)(jit_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + enum { + typesize = sizeof(float), + ker_reg_base_idx = 28, + }; + + reg64_t param = abi_param1; + reg64_t reg_inp = r8; + reg64_t reg_ker = r9; + reg64_t reg_out = r10; + + reg64_t reg_inp_prf = r11; + reg64_t reg_ker_prf = r12; + reg64_t reg_out_prf = r13; + reg64_t reg_owb = r12; + + reg64_t aux_reg_inp = r14; + reg64_t aux_reg_ker = r15; + + reg64_t aux_reg_inp_prf = rsi; + reg64_t aux_reg_ker_prf = rdx; + + reg64_t reg_channel = rsi; + reg64_t reg_bias = rdx; + + reg64_t aux_reg_ker_d = r9; + reg64_t aux_reg_inp_d = rbx; + reg64_t aux_reg_inp_d_prf = r13; + reg64_t aux_reg_ker_d_prf = abi_not_param1; + reg64_t reg_ki = r10; + + reg64_t reg_kj = rax; + reg64_t reg_relu_ns = rax; + reg64_t reg_oi = rbx; + reg64_t reg_kh = abi_not_param1; + + reg64_t reg_tmp = rbp; + + reg64_t reg_ic_loop = rdx; + reg64_t reg_inp_loop = rsi; + + reg64_t reg_init_flag = r13; + reg64_t reg_bias_ptr = param; + + reg64_t aux_reg_ic = r12; + reg64_t reg_binp = rax; + reg64_t reg_bout = r11; + reg64_t aux1_reg_inp = rbx; + reg64_t aux_reg_out = abi_not_param1; + + reg64_t reg_long_offt = r11; + reg64_t reg_out_long_offt = r14; + + inline Vmm vmm_ker(int i_ic) { + assert(i_ic < 4); + return Vmm(ker_reg_base_idx + i_ic); + } + + inline Vmm vmm_out(int i_ur, int i_oc) { + int idx = i_ur + i_oc * jcp.ur_w; + assert(idx < ker_reg_base_idx); + return Vmm(idx); + } + + inline Vmm vmm_inp(int i_ic, int nb_x_blocking) { + int idx = i_ic + nb_x_blocking * jcp.ur_w; + assert(idx < 31); + return Vmm(idx); + } + + Xbyak::Reg64 imm_addr64 = r15; + Vmm vmm_wei = Vmm(31); + + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + inline void prepare_output(int ur_w); + inline void store_output(int ur_w); + inline void compute_loop_fma(int ur_w, int pad_l, int pad_r); + inline void compute_loop_fma_core(int ur_w, int pad_l, int pad_r); + inline void compute_loop_4fma(int ur_w, int pad_l, int pad_r); + inline void compute_loop_4fma_1st(int ur_w, int pad_l, int pad_r); + inline void compute_loop(int ur_w, int pad_l, int pad_r); + + void generate(); + + inline size_t get_output_offset(int oi, int n_oc_block) { + return (size_t)jcp.typesize_out * ((size_t)n_oc_block * jcp.oh + * jcp.ow * jcp.od + oi) * jcp.oc_block; + } + + inline size_t get_input_offset(int ki, int ic, int oi, int pad_l) { + size_t iw_str = !jcp.is_1stconv ? jcp.ic_block : 1; + size_t ic_str = !jcp.is_1stconv ? 1 : (size_t)jcp.iw * jcp.ih * jcp.id; + return (size_t)jcp.typesize_in * ((size_t)(ki * (jcp.dilate_w + 1) + + oi * jcp.stride_w - pad_l) * iw_str + ic * ic_str); + } + + inline int get_kernel_offset(int ki,int ic,int n_oc_block,int ker_number) { + return jcp.typesize_in * jcp.oc_block + * (n_oc_block * jcp.nb_ic * jcp.ic_block * jcp.kh * jcp.kw * jcp.kd + + (ic + ker_number) + ki * jcp.ic_block); + } + + inline int get_ow_start(int ki, int pad_l) { + return nstl::max(0, + utils::div_up(pad_l - ki * (jcp.dilate_w + 1), jcp.stride_w)); + } + + inline int get_ow_end(int ur_w, int ki, int pad_r) { + return ur_w - nstl::max(0, utils::div_up(pad_r + - (jcp.kw - 1 - ki) + * (jcp.dilate_w + 1), + jcp.stride_w)); + } +}; + +struct jit_avx512_common_conv_fwd_kernel { + + jit_avx512_common_conv_fwd_kernel(jit_conv_conf_t ajcp, + const primitive_attr_t &attr) : + jit_ker(nullptr), + zmm_kernel_(nullptr), + xmm_kernel_(nullptr) { + int ch_block = ajcp.is_depthwise ? ajcp.ch_block : ajcp.oc_block; + switch (ch_block) { + case 16: + zmm_kernel_ = + new _jit_avx512_common_conv_fwd_kernel( + ajcp, attr); + jit_ker = zmm_kernel_->jit_ker_; + return; + case 4: + xmm_kernel_ = + new _jit_avx512_common_conv_fwd_kernel( + ajcp, attr); + jit_ker = xmm_kernel_->jit_ker_; + return; + default: + assert(!"invalid channel blocking"); + } + } + + ~jit_avx512_common_conv_fwd_kernel() { + delete xmm_kernel_; + delete zmm_kernel_; + } + + enum { + typesize = sizeof(float) + }; + + static bool post_ops_ok(jit_conv_conf_t &jcp, + const primitive_attr_t &attr); + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, + memory_desc_t &src_pd, + memory_desc_t &weights_pd, + memory_desc_t &dst_pd, + memory_desc_t &bias_pd, + const primitive_attr_t &attr, + int nthreads); + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + void(*jit_ker)(jit_conv_call_s *); + _jit_avx512_common_conv_fwd_kernel *zmm_kernel_; + _jit_avx512_common_conv_fwd_kernel *xmm_kernel_; +}; + +struct jit_avx512_common_conv_bwd_data_kernel_f32: public jit_generator { + + jit_avx512_common_conv_bwd_data_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp) + { + generate(); + jit_ker = (void (*)(jit_conv_call_s *))getCode(); + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_conv_bwd_data_kernel_f32) + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, + const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d); + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + jit_conv_conf_t jcp; + void (*jit_ker)(jit_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + enum { + typesize = sizeof(float), + ker_reg_base_idx = 28, + }; + + reg64_t param = abi_param1; + reg64_t reg_dst = r8; + reg64_t reg_ker = r9; + reg64_t reg_src = r10; + + reg64_t reg_dst_prf = r11; + reg64_t reg_ker_prf = r12; + reg64_t reg_src_prf = r13; + + reg64_t aux_reg_dst = r14; + reg64_t aux_reg_ker = r15; + + reg64_t aux_reg_dst_prf = rsi; + reg64_t aux_reg_ker_prf = rdx; + + reg64_t aux_reg_dst_d_prf = r13; + reg64_t aux_reg_dst_d = rbx; + reg64_t aux_reg_ker_d_prf = abi_not_param1; + reg64_t aux_reg_ker_d = r9; + reg64_t reg_ki = r10; + + reg64_t reg_kj = rax; + reg64_t reg_oi = rbx; + reg64_t reg_kh = abi_not_param1; + + reg64_t reg_channel = rsi; + + reg64_t reg_tmp = rbp; + reg64_t reg_long_offt = r14; + + inline Xbyak::Zmm zmm_ker(int i_ic) { + assert(i_ic < 4); + return Xbyak::Zmm(ker_reg_base_idx + i_ic); + } + inline Xbyak::Zmm zmm_inp(int i_ic, int nb_x_blocking) { + int idx = i_ic + nb_x_blocking * jcp.ur_w; + assert(idx < 31); + return Xbyak::Zmm(idx); + } + inline Xbyak::Zmm zmm_out(int i_ur, int i_oc) { + int idx = i_ur + i_oc * jcp.ur_w; + assert(idx < ker_reg_base_idx); + return Xbyak::Zmm(idx); + } + + Xbyak::Zmm zmm_wei = Xbyak::Zmm(31); + + inline void prepare_output(int ur_w); + inline void store_output(int ur_w); + inline void compute_loop_4fma(int ur_w, int l_overflow, int r_overflow); + inline void compute_loop_fma(int ur_w, int l_overflow, int r_overflow); + inline void compute_loop_fma_core(int ur_w, int l_overflow, int r_overflow); + inline void compute_loop(int ur_w, int l_overflow, int r_overflow); + void generate(); + + inline int get_iw_start(int ki, int l_overflow) + { + int res = (jcp.iw - 1 + jcp.r_pad) % jcp.stride_w + + l_overflow * jcp.stride_w + - (jcp.kw - 1 - ki) * (jcp.dilate_w + 1); + while (res < 0) + res += jcp.stride_w; + + return res; + } + + inline int get_iw_end(int ur_w, int ki, int r_overflow) + { + if (utils::one_of(ur_w, jcp.iw, jcp.ur_w_tail)) + ur_w += nstl::min(0, jcp.r_pad); // remove negative padding + int res = (ur_w - 1 + jcp.l_pad) % jcp.stride_w + + r_overflow * jcp.stride_w - ki * (jcp.dilate_w + 1); + while (res < 0) + res += jcp.stride_w; + + return ur_w - res; + } +}; + +struct jit_avx512_common_conv_bwd_weights_kernel_f32 : public jit_generator { + + jit_avx512_common_conv_bwd_weights_kernel_f32(jit_conv_conf_t ajcp) + : jcp(ajcp) + { + generate(); + jit_ker = (void (*)(jit_conv_call_s *))getCode(); + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_conv_bwd_weights_kernel_f32) + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, + memory_desc_t &src_md, + memory_desc_t &diff_weights_md, + memory_desc_t &diff_bias_md, + memory_desc_t &diff_dst_md); + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + jit_conv_conf_t jcp; + void (*jit_ker)(jit_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + enum {typesize = sizeof(float)}; + static const int max_ur_w; + + reg64_t param = abi_param1; + reg64_t reg_input = rax; + reg64_t reg_kernel = rdx; + reg64_t reg_output = rsi; + reg64_t b_ic = abi_not_param1; + reg64_t kj = r8; + reg64_t reg_kh = r9; + reg64_t reg_ur_w_trips = r10; + reg64_t reg_oj = r15; + reg64_t reg_ih_count = rbx; + reg64_t reg_tmp = r14; + reg64_t reg_long_offt = r14; + + reg64_t ki = r11; + reg64_t reg_kd_count = r12; + reg64_t reg_oi = r12; + reg64_t reg_d_index = r13; + reg64_t reg_input_d = r15; + reg64_t reg_output_d = rbx; + reg64_t aux_reg_input = r12; + reg64_t aux_reg_kernel = r13; + reg64_t reg_bias = rbx; + + inline void bias_kernel(); + inline void maybe_zero_kernel(); + inline void compute_oh_step_unroll_ow_icblock(int ic_block_step, + int max_ur_w); + inline void od_step_comeback_pointers(); + inline void oh_step_comeback_pointers(); + inline void compute_oh_step_unroll_ow(int ic_block_step, int max_ur_w); + inline void compute_ic_block_step(int ur_w, + int pad_l, int pad_r, int ic_block_step, + int input_offset, int kernel_offset, int output_offset, + bool input_wraparound = false); + inline void compute_ic_block_step_fma(int ur_w, + int pad_l, int pad_r, int ic_block_step, + int input_offset, int kernel_offset, int output_offset, + bool input_wraparound); + inline void compute_ic_block_step_4fma(int ur_w, + int pad_l, int pad_r, int ic_block_step, + int input_offset, int kernel_offset, int output_offset, + bool input_wraparound); + inline void compute_oh_step_common(int ic_block_step, int max_ur_w); + inline void compute_oh_step_disp(); + inline void compute_oh_loop_common(); + inline void compute_d_loop_common(); + + inline bool compute_full_spat_loop(); + inline bool flat_4ops_compute(); + + inline void compute_loop(); + + void generate(); + + static void balance(const jit_conv_conf_t &j, int &nthr, int &nthr_mb, + int &nthr_g, int &nthr_oc_b, int &nthr_ic_b); +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp new file mode 100644 index 0000000000..1bdcd0d6a8 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp @@ -0,0 +1,1163 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "cpu_memory.hpp" + +#include + +#include "jit_avx512_common_conv_winograd_kernel_f32.hpp" + +#ifndef KERNEL_SIZE_THRESHOLD +#define KERNEL_SIZE_THRESHOLD 16 +#endif + +#define MIN_REQUIRED_DIMN_REG_BLOCK 14 + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace { + +using namespace mkldnn::impl::utils; + +unsigned int L1_cache_size = get_cache_size(1, true); +unsigned int L2_cache_size = get_cache_size(2, true); +unsigned int LLC_data_size = get_cache_size(3, false); + +// the test funtion takes jcp, the candidate and the current best. +// it returns true if the new candidate is better +int get_divisor_satisfying_cond(jit_conv_winograd_conf_t &jcp, int number, + int default_best, bool (*test)(jit_conv_winograd_conf_t &, int, int)) +{ + int best_divisor = default_best; + auto test_num + = [&best_divisor, test](jit_conv_winograd_conf_t &jcp, int num) { + if (test(jcp, num, best_divisor)) { + best_divisor = num; + } + }; + + for (int divisor = 1; divisor <= ::sqrt(number); divisor++) { + if (number % divisor == 0) { + test_num(jcp, divisor); + test_num(jcp, number / divisor); + } + } + + return best_divisor; +} + +namespace { +bool is_winograd_faster_than_direct(const jit_conv_winograd_conf_t &jcp) { + if (jcp.ver == ver_4fma) + return jcp.mb >= 32; + else + return jcp.mb >= 16; +} +} + +/* assumes 512 bits registers */ +/* TODO: add support for strides */ +/* TODO: handle the prefetch distance automatically */ +typedef enum cache_t_ { L1, L2, L3 } cache_t; + +template +struct prefetcher_t { + prefetcher_t(jit_generator *generator, Xbyak::Reg64 reg_base_addr, + cache_t cache_type, size_t block_size, /* in number of elements*/ + int nb_instructions_in_block, int fma_ipc) + : cg_(generator) + , reg_base_addr_(reg_base_addr) + , cache_type_(cache_type) + , cache_block_size_(block_size) + { + nb_cache_lines_to_prefetch_ = cache_block_size_ / (64 / sizeof(data_t)); + prefetch_spread_ + = div_up(nb_instructions_in_block, nb_cache_lines_to_prefetch_); + prefetch_blk_ + = div_up(nb_cache_lines_to_prefetch_, nb_instructions_in_block); + + /* assumption: when fetch in Li, data is already in L(i+1) */ + int cache_latency; + switch (cache_type_) { + case L1: cache_latency = 14; break; + case L2: + case L3: + default: cache_latency = 250; break; + } + + prefetch_distance_ = div_up(cache_latency, nb_cache_lines_to_prefetch_); + } + + void prefetch(int instruction_number) + { + if (instruction_number % prefetch_spread_ == 0) { + for (int i = 0; (i < prefetch_blk_) + && (prefetches_issued_ < nb_cache_lines_to_prefetch_); + i++, prefetches_issued_++) { + prefetch_inst_(cg_->EVEX_compress_addr( + reg_base_addr_, (cache_block_size_ * prefetch_distance_) + * sizeof(data_t) + + (prefetches_issued_ * 64))); + } + } + } + +private: + void prefetch_inst_(const Xbyak::Address &addr) + { + switch (cache_type_) { + case L1: cg_->prefetcht0(addr); break; + case L2: cg_->prefetcht1(addr); break; + case L3: cg_->prefetcht2(addr); break; + default: + break; // TODO: raise an exception or put an assert + } + } + + jit_generator *cg_; + Xbyak::Reg64 reg_base_addr_; + cache_t cache_type_; + int cache_block_size_ = 0; + int nb_cache_lines_to_prefetch_ = 0; + int prefetches_issued_ = 0; + int prefetch_spread_ = 0; + int prefetch_blk_ = 0; + int prefetch_distance_ = 0; +}; + +// utilities to support kernel parameter selection +bool check_cond1(int dimN_reg_block, int dimK_block, int dimK_reg_block, + int dimM_block, int dimM_simd_block, float C) +{ + float lhs = (dimM_block * dimN_reg_block * dimM_simd_block + + dimM_block * dimK_block * dimK_reg_block + * dimM_simd_block + + dimK_block * dimN_reg_block * dimK_reg_block) + * (float)sizeof(float); + float rhs = C * L1_cache_size; + return (lhs < rhs); +} + +bool check_cond1_bis(int dimN_reg_block, int dimK_block, int dimK_reg_block, + int dimM_block, int dimM_simd_block, float C) +{ + float lhs = (dimM_block * dimK_block * dimK_reg_block * dimM_simd_block + + dimK_block * dimN_reg_block * dimK_reg_block) + * (float)sizeof(float); + float rhs = C * L1_cache_size; + return (lhs < rhs); +} + +bool check_cond2(int nb_dimN_reg_block, int dimN_reg_block, int dimK_nb_block, + int dimK_block, int dimK_reg_block, int dimM_block, int dimM_simd_block, + float C) +{ + float lhs = (nb_dimN_reg_block * dimM_block * dimN_reg_block * dimM_simd_block + + dimK_nb_block * dimM_block * dimK_block * dimK_reg_block + * dimM_simd_block + + nb_dimN_reg_block * dimK_nb_block * dimK_block + * dimN_reg_block * dimK_reg_block) + * (float)sizeof(float); + float rhs = C * L2_cache_size; + return (lhs < rhs); +} +} + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::utils; +using namespace Xbyak; + +void _jit_avx512_common_conv_winograd_data_kernel_f32::gemm_loop_generate( + bool is_beta_zero) +{ + // const int dimK_simd_block = jcp.dimK_reg_block; + + // for (int dimM_block =0; dimM_block < jcp.dimM_block; dimM_block++) + // for (int dimK_block = 0; dimK_block < jcp.dimK_block; dimK_block++) + // for (int dimK_reg_block= 0; dimK_reg_block < jcp.dimK_reg_block; + // dimK_reg_block++) + // for (int tile =0; tile < jcp.dimN_reg_block; tile++) + // C[dimM_block][tile] += + // A[dimM_block][dimK_block][dimK_reg_block] * + // broadcast(B[dimK_block][tile][dimK_reg_block]); + // 1) We do register blocking on A[dimM_block][dimK_block][dimK_reg_block], + // so we load it before the loop on tile + // 2) the loop on tile must be fully unrolled. Don't know about the one on + // dimK_reg_block. I think it should be + + auto inner_loops = [=]() { + Label dimM_block_loop, dimK_block_loop; + const int inc_dimK_reg_block = jcp.ver == ver_4fma ? 4 : 1; + const int fma_ipc = jcp.ver == ver_4fma ? 1 : 2; + + prefetcher_t L1_pf(this, reg_srcB, L1, + jcp.dimN_reg_block * jcp.dimK_reg_block, + jcp.dimK_reg_block * jcp.dimN_reg_block / inc_dimK_reg_block, + fma_ipc); + prefetcher_t L2_pf(this, reg_srcB, L2, + jcp.dimN_reg_block * jcp.dimK_reg_block, + jcp.dimK_reg_block * jcp.dimN_reg_block / inc_dimK_reg_block, + fma_ipc); + + if (jcp.dimM_block > 1) { + mov(reg_dimM_block_loop_cnt, jcp.dimM_block); + L(dimM_block_loop); + } + { + // First, we zero the accumulators if first nb_ic iteration, + // otherwise we load them + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + Zmm zmm(jcp.zmm_start + tile); + if (is_beta_zero) + vpxord(zmm, zmm, zmm); + else + vmovups(zmm, zword[reg_dstC + 64 * tile]); + } + + if (jcp.dimK_block > 1) { + mov(reg_dimK_block_loop_cnt, jcp.dimK_block); + L(dimK_block_loop); + } + { + auto load_A = [=](int reg_idx, int offset) { + for (int i = 0; i < inc_dimK_reg_block; i++) + vmovups(Zmm(reg_idx + i), + zword[reg_srcA + 64 * (offset + i)]); + }; + + // Used when doing double buffering + int next = 0; + if (jcp.double_buffering) { + load_A(next, 0); + } + for (int dimK_reg_block = 0; + dimK_reg_block < jcp.dimK_reg_block; + dimK_reg_block += inc_dimK_reg_block) { + int current; + /* Loading the next vector from A */ + current = next; + if (jcp.double_buffering) { + next = (dimK_reg_block + inc_dimK_reg_block) + % (2 * inc_dimK_reg_block); + load_A(next, dimK_reg_block + inc_dimK_reg_block); + } else { + next = 0; + load_A(next, dimK_reg_block); + } + /* Performing the fmas */ + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + Zmm zmm(jcp.zmm_start + tile); + if (jcp.ver != ver_avx512_core) + L1_pf.prefetch( + dimK_reg_block * jcp.dimN_reg_block + tile); + if (jcp.ver == ver_4fma) + v4fmaddps(zmm, Zmm(current), + EVEX_compress_addr(reg_srcB, + 64 * tile + dimK_reg_block * 4)); + else + vfmadd231ps(zmm, Zmm(current), + EVEX_compress_addr(reg_srcB, + 64 * tile + dimK_reg_block * 4, + true)); + if (jcp.ver != ver_avx512_core) + L2_pf.prefetch( + dimK_reg_block * jcp.dimN_reg_block + tile); + } + } + + add(reg_srcA, jcp.dimK_reg_block * 64); + add(reg_srcB, jcp.dimN_reg_block * 64); + if (jcp.dimK_block > 1) { + sub(reg_dimK_block_loop_cnt, 1); + jnz(dimK_block_loop); + } + } + + + auto store_output = [=](bool output_is_aligned) { + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + Zmm zmm(jcp.zmm_start + tile); + if (output_is_aligned + && jcp.dimK_nb_block == 1 + && (jcp.dimN * jcp.dimM * alpha * alpha + * sizeof(float) > 2 * LLC_data_size)) + vmovntps(zword[reg_dstC + 64 * tile], zmm); + else + vmovups(zword[reg_dstC + 64 * tile], zmm); + } + }; + + Label unaligned_store, end_store; + test(reg_dstC, cpu_isa_traits::vlen - 1); + jnz(unaligned_store, T_NEAR); + store_output(true); + jmp(end_store, T_NEAR); + L(unaligned_store); { + store_output(false); + } + L(end_store); + + if (jcp.dimM_block > 1) { + sub(reg_srcB, jcp.dimK_block * jcp.dimN_reg_block * 64); + add(reg_dstC, jcp.dimN_reg_block * 64); + sub(reg_dimM_block_loop_cnt, 1); + jnz(dimM_block_loop); + } + } + }; + + /* Preamble */ + preamble(); + + /* kernel */ + inner_loops(); + + /* Postamble */ + postamble(); + ret(); +} + +status_t _jit_avx512_common_conv_winograd_data_kernel_f32::init_conf_common( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d) +{ + + if (mayiuse(avx512_core)) + return status::unimplemented; + else if (!mayiuse(avx512_common)) + return status::unimplemented; + else if (mayiuse(avx512_mic_4ops)) + jcp.ver = ver_4fma; + else + jcp.ver = ver_fma; + + jcp.nthr = mkldnn_get_max_threads(); + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = dst_d.dims()[2]; + jcp.ow = dst_d.dims()[3]; + jcp.kh = weights_d.dims()[with_groups + 2]; + jcp.kw = weights_d.dims()[with_groups + 3]; + jcp.t_pad = cd.padding[0][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + jcp.r_pad = nstl::max( + 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad); + jcp.b_pad = nstl::max( + 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad); + jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad; + jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad; + jcp.ohp = jcp.oh; + jcp.owp = jcp.ow; + + bool ok_to_pad_channels = jcp.ngroups == 1; + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto, + is_winograd_faster_than_direct(jcp))) + return status::unimplemented; + + // Checking conditions not supported by these kernels + if (jcp.ngroups != 1) + return status::unimplemented; + if ((jcp.kh != 3) || (jcp.kw != 3)) + return status::unimplemented; + if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0)) + return status::unimplemented; + if ((jcp.stride_h != 1) || (jcp.stride_w != 1)) + return status::unimplemented; + if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0) + return status::unimplemented; + + format_tag_t dat_tag = nChw16c; + format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o; + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + + if (jcp.src_tag != dat_tag) return status::unimplemented; + if (jcp.wei_tag != wei_tag) return status::unimplemented; + if (jcp.dst_tag != dat_tag) return status::unimplemented; + + bool layout_consistency = true + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= dst_d.padded_dims()[1] + && jcp.ic <= weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= weights_d.padded_dims()[with_groups + 0]; + if (!layout_consistency) return status::unimplemented; + + return status::success; +} + + +status_t set_wsched_DATA_W_S_G_D_avx512_common(jit_conv_winograd_conf_t &jcp) { + + auto test_cond_dimN_reg_block = [](jit_conv_winograd_conf_t &jcp, + int dimN_reg_block, int current_best) { + return (dimN_reg_block >= MIN_REQUIRED_DIMN_REG_BLOCK) + && (dimN_reg_block < jcp.nb_reg) + && (dimN_reg_block < current_best); + }; + jcp.dimN_reg_block = get_divisor_satisfying_cond( + jcp, jcp.dimN, jcp.dimN, test_cond_dimN_reg_block); + + if (jcp.dimN_reg_block >= jcp.nb_reg) { + auto test_cond_dimN_reg_block = [](jit_conv_winograd_conf_t &jcp, + int dimN_reg_block, int current_best) { + return (dimN_reg_block < jcp.nb_reg) + && (dimN_reg_block > current_best); + }; + + jcp.dimN_reg_block = get_divisor_satisfying_cond( + jcp, jcp.dimN, 1, test_cond_dimN_reg_block); + } + + //********************* Choosing dimK_block **********************// + auto test_cond1_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond1(jcp.dimN_reg_block, dimK_block, jcp.dimK_reg_block, + 1, jcp.dimM_simd_block, .75f) + && (dimK_block > current_best); + }; + + auto test_cond1_bis_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond1_bis(jcp.dimN_reg_block, dimK_block, + jcp.dimK_reg_block, 1, jcp.dimM_simd_block, .9f) + && (dimK_block > current_best); + }; + + jcp.dimK_block = get_divisor_satisfying_cond( + jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_bis_dimK_block); + // If we are not able to use streams, we fall back to condition [1] + if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block) + jcp.dimK_block = get_divisor_satisfying_cond( + jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_dimK_block); + jcp.dimK_nb_block = (jcp.dimK / jcp.dimK_reg_block) / jcp.dimK_block; + + //********************* Choosing dimM_block **********************// + jcp.dimM_simd_block = 16; + /*XXX: Why C=0.5 here but C=0.75 for dimK_block?*/ + auto test_cond1_dimM_block = []( + jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) { + return check_cond1(jcp.dimN_reg_block, jcp.dimK_block, + jcp.dimK_reg_block, dimM_block, jcp.dimM_simd_block, .5f) + && (dimM_block > current_best); + }; + + auto test_cond1_bis_dimM_block = []( + jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) { + return check_cond1_bis(jcp.dimN_reg_block, jcp.dimK_block, + jcp.dimK_reg_block, dimM_block, jcp.dimM_simd_block, .3f) + && (dimM_block > current_best); + }; + + if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block) + jcp.dimM_block = get_divisor_satisfying_cond( + jcp, jcp.dimM / jcp.dimM_simd_block, 1, test_cond1_dimM_block); + else + jcp.dimM_block = get_divisor_satisfying_cond(jcp, + jcp.dimM / jcp.dimM_simd_block, 1, test_cond1_bis_dimM_block); + jcp.dimM_nb_block = (jcp.dimM / jcp.dimM_simd_block) / jcp.dimM_block; + + //******************* Choosing dimN_block *******************// + auto test_cond2_dimN_block = []( + jit_conv_winograd_conf_t &jcp, int dimN_block, int current_best) { + return check_cond2(dimN_block, jcp.dimN_reg_block, jcp.dimK_nb_block, + jcp.dimK_block, jcp.dimK_reg_block, jcp.dimM_block, + jcp.dimM_simd_block, .5f) + && (dimN_block > current_best); + }; + + jcp.dimN_block = get_divisor_satisfying_cond( + jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond2_dimN_block); + jcp.dimN_nb_block = jcp.dimN / (jcp.dimN_reg_block * jcp.dimN_block); + jcp.sched_policy = WSCHED_DATA_W_S_G_D; + return status::success; +} + +status_t _jit_avx512_common_conv_winograd_data_kernel_f32::init_conf_kernel( + jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK) +{ + jcp.dimK_reg_block = 16; + jcp.dimM_simd_block = 16; + + // TODO: replace double buffering with nuple buffering to maximize register + // usage. + // the choice of the number of buffers will then come after choosing + // dimN_reg_block + jcp.double_buffering = true; + if (jcp.double_buffering) + jcp.zmm_start = 2 * ((jcp.ver == ver_4fma) ? 4 : 2); + else + jcp.zmm_start = 1; + jcp.nb_reg = 32 - jcp.zmm_start; + + jcp.dimN = dimN; + jcp.dimK = dimK; + jcp.dimM = dimM; + + jcp.sched_policy = WSCHED_INVALID; + set_wsched_DATA_W_S_G_D_avx512_common(jcp); + + assert(jcp.sched_policy == WSCHED_DATA_W_S_G_D); + return status::success; +} + +bool jit_avx512_common_conv_winograd_fwd_kernel_f32::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_relu(0) || is_sum(0); // relu or sum + case 2: return (is_sum(0) && is_relu(1)) || + (is_relu(0) && is_sum(1)); // sum->relu or relu->sum + case 3: return is_relu(0) && is_sum(1) && is_relu(2); // relu->sum->relu + default: return false; + } + + return false; +} + +status_t jit_avx512_common_conv_winograd_fwd_kernel_f32::init_conf( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, const primitive_attr_t &attr) { + status_t st = init_conf_common(jcp, cd, src_d, weights_d, dst_d); + + if (st != status::success) + return st; + + // Winograd specific initialization + jcp.itiles = (jcp.ow + tile_size - 1) / tile_size; + jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size; + jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + const int eltwise_ind = p.find(primitive_kind::eltwise, 0, 1); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) jcp.eltwise = p.entry_[eltwise_ind].eltwise; + jcp.with_sum = p.find(primitive_kind::sum, 0) != -1; + + status_t res = init_conf_kernel(jcp, jcp.oc, jcp.ntiles, jcp.ic); + jcp.ic_simd_block = jcp.dimK_reg_block; + jcp.ic_block = jcp.dimK_block; + jcp.nb_ic = jcp.dimK_nb_block; + jcp.oc_simd_block = jcp.dimM_simd_block; + jcp.oc_block = jcp.dimM_block; + jcp.nb_oc = jcp.dimM_nb_block; + jcp.tile_block_ur = jcp.dimN_reg_block; + jcp.nb_tile_block_ur = jcp.dimN_block; + jcp.tile_block = jcp.dimN_nb_block; + jcp.tile_4fma_padding = 0; // only relevant for backward weights + + return res; +} + +status_t jit_avx512_common_conv_winograd_bwd_data_kernel_f32::init_conf( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d) +{ + status_t st = init_conf_common(jcp, cd, diff_src_d, weights_d, diff_dst_d); + + if (st != status::success) + return st; + + jcp.itiles = (jcp.iw + tile_size - 1) / tile_size; + jcp.jtiles = (jcp.ih + tile_size - 1) / tile_size; + jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles; + + status_t res = init_conf_kernel(jcp, jcp.ic, jcp.ntiles, jcp.oc); + jcp.oc_simd_block = jcp.dimK_reg_block; + jcp.oc_block = jcp.dimK_block; + jcp.nb_oc = jcp.dimK_nb_block; + jcp.ic_simd_block = jcp.dimM_simd_block; + jcp.ic_block = jcp.dimM_block; + jcp.nb_ic = jcp.dimM_nb_block; + jcp.tile_block_ur = jcp.dimN_reg_block; + jcp.nb_tile_block_ur = jcp.dimN_block; + jcp.tile_block = jcp.dimN_nb_block; + jcp.tile_4fma_padding = 0; // only relevant for backward weights + + return res; +} + +void jit_avx512_common_conv_winograd_bwd_weights_kernel_f32::transpose_ker_generate() +{ + auto load_B = [=](int reg_idx, int offset) { + for (int i = 0; i < 4; i++) { + vmovups(Zmm(reg_idx + i), zword[reg_origB + (offset + i) * jcp.dimN_reg_block * sizeof(float)]); + } + }; + + preamble(); + int curr = 0; + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + int origB_offset = (j * alpha + i) * jcp.dimK_4fma; + size_t transB_offset = (size_t)(j * alpha + i) * jcp.dimK_nb_block * + jcp.dimN_block * jcp.dimK_block * jcp.dimK_reg_block * + jcp.dimK_4fma * jcp.dimN_reg_block * sizeof(float); + mov(reg_transB_idx, transB_offset); + for (int tb = 0; tb < jcp.dimK_4fma; tb+=4) { + /*double buffering to hide load latencies*/ + int next = (curr + 4) % 8; + if (i == 0 && tb == 0) { + load_B(0, origB_offset); + } + if (tb + 4 < (jcp.dimK_4fma -1)) { + load_B(next, origB_offset + 4); + } else if (i < alpha - 1) { + load_B(next, origB_offset + jcp.dimK_4fma); + } + + vunpcklps(Zmm(8), Zmm(curr), Zmm(curr + 1)); + vunpcklps(Zmm(9), Zmm(curr + 2), Zmm(curr + 3)); + vunpckhps(Zmm(curr), Zmm(curr), Zmm(curr + 1)); + vunpckhps(Zmm(curr + 1), Zmm(curr + 2), Zmm(curr + 3)); + + vunpcklpd(Zmm(curr + 2), Zmm(8), Zmm(9)); + vunpckhpd(Zmm(curr + 3), Zmm(8), Zmm(9)); + + vunpcklpd(Zmm(8), Zmm(curr), Zmm(curr + 1)); + vunpckhpd(Zmm(9), Zmm(curr), Zmm(curr + 1)); + + vmovntps(zword[reg_transB + reg_transB_idx + + sizeof(float) * tb * jcp.dimN_reg_block], + Zmm(curr+2)); + vmovntps(zword[reg_transB + reg_transB_idx + + sizeof(float) * (tb + 1) * jcp.dimN_reg_block], + Zmm(curr+3)); + vmovntps(zword[reg_transB + reg_transB_idx + + sizeof(float) * (tb + 2) * jcp.dimN_reg_block], + Zmm(8)); + vmovntps(zword[reg_transB + reg_transB_idx + + sizeof(float) * (tb + 3) * jcp.dimN_reg_block], + Zmm(9)); + curr = next; + + } + } + } + postamble(); + ret(); +} +void jit_avx512_common_conv_winograd_bwd_weights_kernel_f32::gemm_loop_generate( + bool is_first_tile) +{ + // for (int ofm2 = 0; ofm2 < jcp.oc_block; ofm2++) + // for (int ifm2 = 0; ifm2 < jcp.ic_block; ifm2++) + // for (int nb_tile_block_ur = 0; nb_tile_block_ur < + // jcp.nb_tile_block_ur; nb_tile_block_ur++) + // for (int tile_block_ur = 0; tile_block_ur < + // jcp.tile_block_ur; tile_block_ur++) + // for (int ifm3 = 0; ifm3 < jcp.ic_reg_block; ++ifm3) + // U[ofm2][ifm2][ofm3][ifm3][0:oc_simd_block] += + // M[ofm2][ofm3][nb_tile_block_ur][tile_block_ur][0:oc_simd_block] + // * + // broadcast(V[ifm2][nb_tile_block_ur][ifm3][tile_block_ur]) + auto inner_loops = [=]() { + int inc_fma = jcp.ver == ver_4fma ? 4 : 1; + const int fma_ipc = jcp.ver == ver_4fma ? 1 : 2; + prefetcher_t L1_pf(this, reg_srcB, L1, + jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma, + jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma + / inc_fma, + fma_ipc); + prefetcher_t L2_pf(this, reg_srcB, L2, + jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma, + jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma + / inc_fma, + fma_ipc); + + auto load_A = [=](int reg_idx, int offset) { + for (int i = 0; i < inc_fma; i++) { + vmovups(Zmm(reg_idx + i), + zword[reg_srcA + + sizeof(float) * jcp.dimM_simd_block * (offset + i)]); + } + }; + + Label dimM_block_loop, dimK_block_loop, dimN_block_loop; + if (jcp.dimM_block > 1) { + mov(reg_dimM_block_loop_cnt, jcp.dimM_block); + L(dimM_block_loop); + } + { /************* OC_block (M) loop ***********/ + if (jcp.dimN_block > 1) { + mov(reg_dimN_block_loop_cnt, jcp.dimN_block); + L(dimN_block_loop); + } + { /*************** IC_block (N) loop *********/ + for (int dimN_reg_block = 0; + dimN_reg_block < jcp.dimN_reg_block; ++dimN_reg_block) { + Zmm zmm(jcp.zmm_start + dimN_reg_block); + if (is_first_tile) + vpxord(zmm, zmm, zmm); + else + vmovups(zmm, zword[reg_dstC + + dimN_reg_block * jcp.dimM_simd_block * + sizeof(float)]); + } + + if (jcp.dimK_block > 1) { + mov(reg_dimK_block_loop_cnt, jcp.dimK_block); + L(dimK_block_loop); + } + { /************* nb_tile_ur(K) loop ********/ + int next = 0; + if (jcp.double_buffering) { + load_A(next, 0); + } + for (int dimK_reg_block = 0; + dimK_reg_block < jcp.dimK_reg_block; + dimK_reg_block++) { + int srcB_offset = dimK_reg_block * jcp.dimK_4fma + * jcp.dimN_reg_block; + for (int dimK_4fma = 0; dimK_4fma < jcp.dimK_4fma; + dimK_4fma += inc_fma) { + int current = next; + if (jcp.double_buffering) { + next = (dimK_reg_block * jcp.dimK_4fma + + dimK_4fma + inc_fma) + % (2 * inc_fma); + load_A(next, dimK_reg_block * jcp.dimK_4fma + + dimK_4fma + inc_fma); + } else { + next = 0; + load_A(next, dimK_reg_block * jcp.dimK_4fma + + dimK_4fma); + } + for (int dimN_reg_block = 0; + dimN_reg_block < jcp.dimN_reg_block; + ++dimN_reg_block) { + L1_pf.prefetch(srcB_offset / inc_fma + + dimK_4fma / inc_fma + * jcp.dimN_reg_block + + dimN_reg_block); + L2_pf.prefetch(srcB_offset / inc_fma + + dimK_4fma / inc_fma + * jcp.dimN_reg_block + + dimN_reg_block); + if (jcp.ver == ver_4fma) { + int srcB_trans_offset = (dimK_4fma / 4) * 64 + + dimK_4fma % 4; + v4fmaddps( + Zmm(jcp.zmm_start + dimN_reg_block), + Zmm(current), + EVEX_compress_addr(reg_srcB, + sizeof(float) * ( + srcB_offset + + srcB_trans_offset + + (dimN_reg_block % 4) * 16 + + (dimN_reg_block / 4) * 4))); + } else { + vfmadd231ps( + Zmm(jcp.zmm_start + dimN_reg_block), + Zmm(current), + EVEX_compress_addr(reg_srcB, + sizeof(float) * (srcB_offset + dimN_reg_block), + true)); + } + } + } + } + } + + add(reg_srcA, jcp.dimK_reg_block * jcp.dimK_4fma + * jcp.dimM_simd_block * sizeof(float)); + add(reg_srcB, jcp.dimK_reg_block * jcp.dimN_reg_block + * jcp.dimK_4fma * sizeof(float)); + if (jcp.dimK_block > 1) { + sub(reg_dimK_block_loop_cnt, 1); + jnz(dimK_block_loop); + } + + /******** Write C back to memory *******/ + for (int dimN_reg_block = 0; + dimN_reg_block < jcp.dimN_reg_block; ++dimN_reg_block) { + Zmm zmm(jcp.zmm_start + dimN_reg_block); + vmovups(zword[reg_dstC + + dimN_reg_block * jcp.dimM_simd_block * sizeof(float)], + zmm); + } + + sub(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block * + jcp.dimK_4fma * jcp.dimM_simd_block * sizeof(float)); + add(reg_dstC, jcp.dimN_reg_block * jcp.dimM_simd_block + * sizeof(float)); + if (jcp.dimN_block > 1) { + sub(reg_dimN_block_loop_cnt, 1); + jnz(dimN_block_loop); + } + } + + if (jcp.dimM_block > 1) { + sub(reg_srcB, jcp.dimN_block * jcp.dimK_block + * jcp.dimK_reg_block * jcp.dimN_reg_block + * jcp.dimK_4fma * sizeof(float)); + add(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block + * jcp.dimK_4fma * jcp.dimM_simd_block * sizeof(float)); + sub(reg_dimM_block_loop_cnt, 1); + jnz(dimM_block_loop); + } + } + }; + + /* Preamble */ + // register used to handle long fma encoding + preamble(); + mov(reg_srcA, reg_srcA_const); + inner_loops(); + + /* Postamble */ + postamble(); + ret(); +} + +namespace { +bool check_cond1_wu(int dimM_block, int dimM_simdw, int dimK_block, + int dimK_reg_block, int dimK_4fma, int dimN_reg_block, float C) +{ + float lhs = 1.0f * dimM_block * dimN_reg_block * dimM_simdw; + lhs += dimM_block * dimK_block * dimK_reg_block * dimK_4fma * dimM_simdw; + lhs += dimK_block * dimN_reg_block * dimK_reg_block * dimK_4fma; + lhs *= sizeof(float); + float rhs = C * L1_cache_size; + return (lhs <= rhs); +} + +bool check_cond1bis_wu(int dimM_block, int dimM_simdw, int dimK_block, + int dimK_reg_block, int dimK_4fma, int dimN_reg_block, float C) +{ + float lhs = 1.0f * dimM_block * dimK_block * dimK_reg_block * dimK_4fma + * dimM_simdw; + lhs += dimK_block * dimN_reg_block * dimK_reg_block * dimK_4fma; + lhs *= sizeof(float); + float rhs = C * L1_cache_size; + return (lhs <= rhs); +} + +bool check_cond2bis_wu(int dimM_block, int dimM_simdw, int dimK_block, + int dimK_reg_block, int dimK_4fma, int dimN_block, int dimN_reg_block, + float C) +{ + float lhs = 1.0f * dimM_block * dimM_simdw * dimK_block * dimK_reg_block + * dimK_4fma; + lhs += dimK_block * dimK_reg_block * dimK_4fma * dimN_block + * dimN_reg_block; + lhs *= sizeof(float); + float rhs = C * L2_cache_size; + return (lhs <= rhs); +} + +bool check_cond2_wu(int dimM_block, int dimM_simdw, int dimK_block, + int dimK_reg_block, int dimK_4fma, int dimN_block, int dimN_reg_block, + float C) +{ + float lhs = 1.0f * dimM_block * dimM_simdw * dimN_block * dimN_reg_block; + lhs += dimM_block * dimM_simdw * dimK_block * dimK_reg_block * dimK_4fma; + lhs += dimK_block * dimK_reg_block * dimK_4fma * dimN_block + * dimN_reg_block; + lhs *= sizeof(float); + float rhs = C * L2_cache_size; + return (lhs <= rhs); +} +} // namespace + +status_t set_wsched_WEI_S_D_G_W_avx512_common(jit_conv_winograd_conf_t &jcp) +{ + /*************** Choose dimN_reg_block (ic_simd_block) + * *******************************/ + jcp.dimN = jcp.ic; + /*Hardcoded to 16 because N = ic for bwd weights and + innermost dimension for ic is assumed 16 in src transforms. This + choice covers load latencies while maintaining simplicity of kernel + for POR topologies. FIXME in future??: Will not work for future topologies + when ic%16 != 0*/ + jcp.dimN_reg_block = jcp.ic_simd_block; + + /****************************** Choose dimK_block + * **************************/ + // No freedom for choosing dimM_simd_block because ic_simd_block + // is determined by input data format + jcp.dimM_simd_block = jcp.oc_simd_block; + + auto test_cond1bis_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond1bis_wu(1, jcp.dimM_simd_block, dimK_block, 1, + jcp.dimK_4fma, jcp.dimN_reg_block, 0.4f) + && (dimK_block > current_best); + }; + + auto test_cond1_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond1_wu(1, jcp.dimM_simd_block, dimK_block, 1, + jcp.dimK_4fma, jcp.dimN_reg_block, 0.4f) + && (dimK_block > current_best); + }; + + auto test_cond2bis_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond2bis_wu(1, jcp.dimM_simd_block, dimK_block, 1, + jcp.dimK_4fma, 1, jcp.dimN_reg_block, 0.5f) + && (dimK_block > current_best); + }; + + auto test_cond2_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond2_wu(1, jcp.dimM_simd_block, dimK_block, 1, + jcp.dimK_4fma, 1, jcp.dimN_reg_block, 0.1f) + && (dimK_block > current_best); + }; + + jcp.dimK_block = get_divisor_satisfying_cond( + jcp, jcp.dimK / jcp.dimK_4fma, 1, test_cond2bis_dimK_block); + if (jcp.dimK_block < jcp.dimK / jcp.dimK_4fma) + jcp.dimK_block = get_divisor_satisfying_cond( + jcp, jcp.dimK / jcp.dimK_4fma, 1, test_cond2_dimK_block); + + jcp.dimK_reg_block = get_divisor_satisfying_cond( + jcp, jcp.dimK_block, 1, test_cond1bis_dimK_block); + if (jcp.dimK_reg_block < jcp.dimK_block) { + jcp.dimK_reg_block = get_divisor_satisfying_cond( + jcp, jcp.dimK_block, 1, test_cond1_dimK_block); + } + jcp.dimK_block /= jcp.dimK_reg_block; + jcp.dimK_nb_block + = jcp.dimK / jcp.dimK_4fma / jcp.dimK_reg_block / jcp.dimK_block; + jcp.tile_block_ur = jcp.dimK_reg_block; + jcp.nb_tile_block_ur = jcp.dimK_block; + jcp.tile_block = jcp.dimK_nb_block; + + /***************************** Chose dimN block + * ****************************/ + auto test_cond2_dimN_block = []( + jit_conv_winograd_conf_t &jcp, int dimN_block, int current_best) { + return check_cond2_wu(1, jcp.dimM_simd_block, jcp.dimK_block, + jcp.dimK_reg_block, jcp.dimK_4fma, dimN_block, + jcp.dimN_reg_block, 0.5f) + && (dimN_block > current_best); + }; + + jcp.dimN_block = get_divisor_satisfying_cond( + jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond2_dimN_block); + jcp.ic_block = jcp.dimN_block; + jcp.dimN_nb_block = jcp.dimN / jcp.dimN_reg_block / jcp.dimN_block; + jcp.nb_ic = jcp.dimN_nb_block; + + /********************************* Choose dimM block + * ************************/ + jcp.dimM = jcp.oc; + + auto test_cond1_dimM_block = []( + jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) { + return check_cond1_wu(dimM_block, jcp.dimM_simd_block, 1, + jcp.dimK_reg_block, jcp.dimK_4fma, jcp.dimN_reg_block, + 1.0f) + && (dimM_block > current_best) + && (jcp.dimM / jcp.dimM_simd_block / dimM_block) >= 2; + }; + + jcp.dimM_block = get_divisor_satisfying_cond( + jcp, jcp.dimM / jcp.dimM_simd_block, 1, test_cond1_dimM_block); + jcp.dimM_nb_block = (jcp.dimM / jcp.dimM_simd_block) / jcp.dimM_block; + + jcp.sched_policy = WSCHED_WEI_S_D_G_W; + return status::success; +} + +status_t jit_avx512_common_conv_winograd_bwd_weights_kernel_f32::init_conf( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &diff_dst_d, + const memory_desc_wrapper &diff_weights_d) +{ + jcp.nthr = mkldnn_get_max_threads(); + + const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1; + + jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = diff_dst_d.dims()[2]; + jcp.ow = diff_dst_d.dims()[3]; + jcp.kh = diff_weights_d.dims()[with_groups + 2]; + jcp.kw = diff_weights_d.dims()[with_groups + 3]; + jcp.t_pad = cd.padding[0][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + jcp.r_pad = nstl::max( + 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad); + jcp.b_pad = nstl::max( + 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad); + jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad; + jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad; + jcp.ohp = jcp.oh; + jcp.owp = jcp.ow; + jcp.with_bias = (cd.diff_bias_desc.format_kind != format_kind::undef); + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + + bool ok_to_pad_channels = jcp.ngroups == 1; + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + if (mayiuse(avx512_core)) + return status::unimplemented; + if (!mayiuse(avx512_common)) + return status::unimplemented; + else if (mayiuse(avx512_mic_4ops)) + jcp.ver = ver_4fma; + else + jcp.ver = ver_fma; + + if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto, + is_winograd_faster_than_direct(jcp))) + return status::unimplemented; + // Winograd specific initialization + jcp.itiles = (jcp.ow + tile_size - 1) / tile_size; + jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size; + jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles; + + // Winograd kernel works only for 3x3 convolution with stride 1 + if (jcp.ngroups != 1) + return status::unimplemented; + if ((jcp.kh != 3) || (jcp.kw != 3)) + return status::unimplemented; + if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0)) + return status::unimplemented; + if ((jcp.stride_h != 1) || (jcp.stride_w != 1)) + return status::unimplemented; + if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0) + return status::unimplemented; + + format_tag_t dat_tag = nChw16c; + format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o; + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag); + + if (jcp.src_tag != dat_tag) return status::unimplemented; + if (jcp.wei_tag != wei_tag) return status::unimplemented; + if (jcp.dst_tag != dat_tag) return status::unimplemented; + + bool layout_consistency = true + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= diff_dst_d.padded_dims()[1] + && jcp.ic <= diff_weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= diff_weights_d.padded_dims()[with_groups + 0]; + if (!layout_consistency) return status::unimplemented; + + /*************************** New Kernel Parameters + * *****************************/ + jcp.ic_simd_block = simd_w; + jcp.oc_simd_block = simd_w; + jcp.dimK_4fma = 1; + jcp.tile_4fma_padding = 0; + +#define MAX_4FMA_UR 8 + if (jcp.ver == ver_4fma) { + auto test_cond_4fma = [](jit_conv_winograd_conf_t &jcp, int dimK_4fma, + int current_best) { + return (dimK_4fma % 4 == 0) && (dimK_4fma <= MAX_4FMA_UR) + && (dimK_4fma > current_best); + }; + jcp.dimK_4fma = get_divisor_satisfying_cond( + jcp, jcp.itiles * jcp.jtiles, 4, test_cond_4fma); + if (jcp.dimK_4fma == 1) + jcp.dimK_4fma = 4; + if ((jcp.itiles * jcp.jtiles) % jcp.dimK_4fma != 0) + jcp.tile_4fma_padding = jcp.dimK_4fma + - ((jcp.itiles * jcp.jtiles) % jcp.dimK_4fma); + } + + jcp.tile_4fma = jcp.dimK_4fma; + /*NOTE: When (itiles * jtiles) % dimK_4fma != 0, transpose in diff_src + * transform + * will not work correctly, this is solved by applying padding.*/ + jcp.dimK = jcp.mb * (jcp.itiles * jcp.jtiles + jcp.tile_4fma_padding); + jcp.dimN = jcp.ic; + jcp.dimM = jcp.oc; + + jcp.double_buffering = true; + if (jcp.double_buffering) + jcp.zmm_start = jcp.ver == ver_4fma ? 8 : 2; + else + jcp.zmm_start = jcp.ver == ver_4fma ? 4 : 1; + jcp.nb_reg = 32 - jcp.zmm_start; + + jcp.sched_policy = WSCHED_INVALID; + status_t res = set_wsched_WEI_S_D_G_W_avx512_common(jcp); + assert(jcp.sched_policy == WSCHED_WEI_S_D_G_W); + + jcp.tile_block_ur = jcp.dimK_reg_block; + jcp.nb_tile_block_ur = jcp.dimK_block; + jcp.tile_block = jcp.dimK_nb_block; + + jcp.ic_block = jcp.dimN_block; + jcp.nb_ic = jcp.dimN_nb_block; + + jcp.oc_block = jcp.dimM_block; + jcp.nb_oc = jcp.dimM_nb_block; + + return res; + +} +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp new file mode 100644 index 0000000000..6c117143f5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp @@ -0,0 +1,179 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX512_COMMON_CONV_WINOGRAD_KERNEL_F32_HPP +#define JIT_AVX512_COMMON_CONV_WINOGRAD_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "cpu_memory.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +//alpha determines the output tile_size +constexpr int alpha = 6; +constexpr int tile_size = 4; +//simd length used for vectorization +constexpr int simd_w = 16; + +struct _jit_avx512_common_conv_winograd_data_kernel_f32 : public jit_generator { + _jit_avx512_common_conv_winograd_data_kernel_f32( + jit_conv_winograd_conf_t ajcp) + : jcp(ajcp) + { + //******************* First iter kernel ********************// + this->gemm_loop_generate(true); + gemm_loop_ker_first_iter + = (decltype(gemm_loop_ker_first_iter)) this->getCode(); + + //************** Subsequent iterations kernel **************// + if (jcp.dimK_nb_block > 1) { + align(); + const Xbyak::uint8 *addr = getCurr(); + this->gemm_loop_generate(false); + gemm_loop_ker = (decltype(gemm_loop_ker))addr; + } + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_common_conv_winograd_data_kernel_f32) + + static status_t init_conf_common(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d); + + static status_t init_conf_kernel( + jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK); + + jit_conv_winograd_conf_t jcp; + void (*gemm_loop_ker)(float *, const float *, const float *); + void (*gemm_loop_ker_first_iter)(float *, const float *, const float *); + +protected: + using reg64_t = const Xbyak::Reg64; + enum { typesize = sizeof(float) }; + + void gemm_loop_generate(bool is_beta_zero); + + /* registers used for GEMM */ + reg64_t reg_dstC = abi_param1; + reg64_t reg_srcA = abi_param2; + reg64_t reg_srcB = abi_param3; + + reg64_t reg_dimM_block_loop_cnt = r10; + reg64_t reg_dimK_block_loop_cnt = r11; +}; + +struct jit_avx512_common_conv_winograd_fwd_kernel_f32 + : _jit_avx512_common_conv_winograd_data_kernel_f32 { + using _jit_avx512_common_conv_winograd_data_kernel_f32:: + _jit_avx512_common_conv_winograd_data_kernel_f32; + + static bool post_ops_ok(jit_conv_conf_t &jcp, const primitive_attr_t &attr); + + static status_t init_conf(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, const primitive_attr_t &attr); +}; + +struct jit_avx512_common_conv_winograd_bwd_data_kernel_f32 + : public _jit_avx512_common_conv_winograd_data_kernel_f32 { + using _jit_avx512_common_conv_winograd_data_kernel_f32:: + _jit_avx512_common_conv_winograd_data_kernel_f32; + + static status_t init_conf(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d); +}; + +struct jit_avx512_common_conv_winograd_bwd_weights_kernel_f32 + : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_common_conv_winograd_bwd_weights_kernel_f32) + + jit_avx512_common_conv_winograd_bwd_weights_kernel_f32( + jit_conv_winograd_conf_t ajcp) + : jcp(ajcp) + { + + //******************* First iter kernel ********************// + { + align(); + const Xbyak::uint8 *addr = getCurr(); + this->gemm_loop_generate(true); + gemm_loop_ker_first_iter = (decltype(gemm_loop_ker_first_iter))addr; + } + + if (jcp.tile_block > 1) { + align(); + const Xbyak::uint8 *addr = getCurr(); + this->gemm_loop_generate(false); + gemm_loop_ker = (decltype(gemm_loop_ker))addr; + } + + if (jcp.ver == ver_4fma) { + align(); + const Xbyak::uint8 *addr = getCurr(); + this->transpose_ker_generate(); + transpose_4fma_ker = (decltype(transpose_4fma_ker))addr; + } + } + + static status_t init_conf(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &diff_dst_d, + const memory_desc_wrapper &diff_weights_d); + + jit_conv_winograd_conf_t jcp; + void (*gemm_loop_ker)(float *, const float *, const float *); + void (*gemm_loop_ker_first_iter)(float *, const float *, const float *); + void (*transpose_4fma_ker)(float *, float *); + +private: + using reg64_t = const Xbyak::Reg64; + enum { typesize = sizeof(float) }; + + void gemm_loop_generate(bool is_first_tile); + void transpose_ker_generate(); + + reg64_t reg_origB = abi_param2; + reg64_t reg_transB = abi_param1; + + reg64_t reg_dstC = abi_param1; + reg64_t reg_srcA_const = abi_param2; + reg64_t reg_srcB = abi_param3; + + reg64_t reg_sp = rsp; + reg64_t reg_srcA = r9; + reg64_t reg_nb_ic = r10; + reg64_t reg_loop_cpt = r11; + reg64_t reg_transB_idx = r13; + + /* Registers used by new kernel */ + reg64_t reg_dimM_block_loop_cnt = r10; + reg64_t reg_dimK_block_loop_cnt = r12; + reg64_t reg_dimN_block_loop_cnt = r11; +}; +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp new file mode 100644 index 0000000000..abddc19221 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp @@ -0,0 +1,1526 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx512_common_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +using namespace nstl; + +using jit_conv_ker_t = void (*)(jit_conv_call_s *); + +#define PIPELINE(field) \ + do { \ + p.field = p.field ## _prf; \ + p.field ## _prf = field; \ + } while (0) + +inline void jit_conv_ker_pipeline(jit_conv_ker_t ker, jit_conv_call_s &p, + const void *src, const void *dst, const void *filt, const void *bias, + int channel, int kh_padding) +{ + PIPELINE(src); + PIPELINE(dst); + PIPELINE(filt); + PIPELINE(bias); + PIPELINE(channel); + PIPELINE(kh_padding); + + if (p.src) + ker(&p); +} +// The special case for the driver with ow-parallelization (FWD) +// TODO: implement it for BWD_D and BWD_W too +inline void jit_conv_ker_pipeline_ow_thr(jit_conv_ker_t ker, jit_conv_call_s &p, + const void *src, const void *dst, const void *filt, const void *bias, + int channel, int kh_padding, int owb) +{ + PIPELINE(src); + PIPELINE(dst); + PIPELINE(filt); + PIPELINE(bias); + PIPELINE(channel); + PIPELINE(kh_padding); + PIPELINE(owb); + + if (p.src) + ker(&p); +} + +inline void jit_conv_3d_ker_pipeline(jit_conv_ker_t ker, jit_conv_call_s &p, + const void *src, const void *dst, const void *filt, const void *bias, + int channel, int kh_padding, int kd_padding) +{ + PIPELINE(src); + PIPELINE(dst); + PIPELINE(filt); + PIPELINE(bias); + PIPELINE(channel); + PIPELINE(kh_padding); + PIPELINE(kd_padding); + + if (p.src) + ker(&p); +} +// The special case for the driver with ow-parallelization (FWD) +// TODO: implement it for BWD_D and BWD_W too +inline void jit_conv_3d_ker_pipeline_ow_thr(jit_conv_ker_t ker, + jit_conv_call_s &p, const void *src, const void *dst, const void *filt, + const void *bias, int channel, int kh_padding, int kd_padding, int owb) +{ + PIPELINE(src); + PIPELINE(dst); + PIPELINE(filt); + PIPELINE(bias); + PIPELINE(channel); + PIPELINE(kh_padding); + PIPELINE(kd_padding); + PIPELINE(owb); + + if (p.src) + ker(&p); +} + +void jit_conv_3d_ker_bwd_w_pipeline(jit_conv_ker_t ker, jit_conv_call_s &p, + const void *src, const void *dst, const void *filt, const void *bias, + int channel, int d_index, int d_worksize, + int kd_padding /* kd_work_size */, size_t kd_offset) { + PIPELINE(src); + PIPELINE(dst); + PIPELINE(filt); + PIPELINE(bias); + PIPELINE(channel); + PIPELINE(kd_padding); + PIPELINE(d_worksize); + PIPELINE(d_index); + PIPELINE(kd_offset); + + if (p.src) + ker(&p); +} +#define wht_blk_off(d, g, ...) \ + (pd()->with_groups() \ + ? (d).blk_off((g), __VA_ARGS__) \ + : (d).blk_off(__VA_ARGS__)) + +template +void jit_avx512_common_convolution_fwd_t::prepare_padded_bias(const dst_data_t *&bias, + const memory_tracking::grantor_t &scratchpad) const { + if (!pd()->wants_padded_bias()) return; + + auto padded_bias = scratchpad.template get( + key_conv_padded_bias); + utils::array_copy(padded_bias, bias, pd()->jcp_.oc_without_padding); + utils::array_set(padded_bias + pd()->jcp_.oc_without_padding, + (dst_data_t)0, pd()->jcp_.oc - pd()->jcp_.oc_without_padding); + bias = padded_bias; +} + +template +void jit_avx512_common_convolution_fwd_t:: +execute_forward_1d(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + prepare_padded_bias(bias, this->scratchpad(ctx)); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = pd()->jcp_; + assert(jcp.nb_oc % jcp.nb_oc_blocking == 0); + + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking; + int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.nb_ow; + + int nthr; + if (jcp.aligned_threads) + nthr = jcp.aligned_threads; + else + nthr = mkldnn_get_max_threads(); + + parallel(nthr, [&](const int ithr, const int nthr) { + int start{0}, end{0}, start_copy; + balance211(work_amount, nthr, ithr, start, end); + start_copy = start; + + auto par_conv = jit_conv_call_s(); + size_t src_c_stride = src_d.blk_off(0, 1); + size_t wht_ic_stride = wht_blk_off(weights_d, 0, 0, 1); + + for (int icb_l2 = 0 ; icb_l2 < jcp.nb_ic; icb_l2 += jcp.nb_ic_L2) { + start = start_copy; + int n{0}, g{0}, occ{0}, owb{0}; + + if (jcp.loop_order == loop_cwgn) { + int dummy{0}; + nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow, + g, jcp.ngroups, n, jcp.mb, dummy, 1); + } else if (jcp.loop_order == loop_gncw) { + int dummy{0}; + nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb, occ, + oc_chunks, owb, jcp.nb_ow, dummy, 1); + } else { + assert(!"unsupported loop order"); + } + + while (start < end) { + int ocb = occ * jcp.nb_oc_blocking; + int g_ocb = g * jcp.nb_oc + ocb; + int g_oc = g_ocb * jcp.oc_block; + int g_icb = g * jcp.nb_ic * jcp.nonblk_group_off; + + int ow_s = owb * jcp.ow_block; + int iw_s = ow_s * jcp.stride_w; + auto bias_w = bias ? bias + g_oc : nullptr; + auto dst_w = dst + dst_d.blk_off(n, g_ocb, ow_s); + auto src_w = src + src_d.blk_off(n, g_icb + icb_l2, iw_s); + auto wht_w = weights + wht_blk_off(weights_d, g, ocb, icb_l2); + + for (int icb = icb_l2; + icb < min(jcp.nb_ic, icb_l2 + jcp.nb_ic_L2); ++icb) { + jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker, par_conv, + src_w, dst_w, wht_w, bias_w, icb, 1, owb); + + src_w += src_c_stride; + wht_w += wht_ic_stride; + } + if (jcp.loop_order == loop_cwgn) { + int dummy{0}; + nd_iterator_jump(start, end, occ, oc_chunks, owb, jcp.nb_ow, + g, jcp.ngroups, n, jcp.mb, dummy, 1); + } else if (jcp.loop_order == loop_gncw) { + int dummy{0}; + nd_iterator_jump(start, end, g, jcp.ngroups, n, jcp.mb, + occ, oc_chunks, owb, jcp.nb_ow, dummy, 1); + } else { + assert(!"unsupported loop order"); + } + } + } + jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker, par_conv, + src, dst, weights, bias, 0, 0, 0); + }); +} + +template +void jit_avx512_common_convolution_fwd_t:: +execute_forward_2d(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + prepare_padded_bias(bias, this->scratchpad(ctx)); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = pd()->jcp_; + assert(jcp.nb_oc % jcp.nb_oc_blocking == 0); + + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking; + int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.oh * jcp.nb_ow; + + int nthr; + if (jcp.aligned_threads) + nthr = jcp.aligned_threads; + else + nthr = mkldnn_get_max_threads(); + + parallel(nthr, [&](const int ithr, const int nthr) { + int start{0}, end{0}, start_copy; + balance211(work_amount, nthr, ithr, start, end); + start_copy = start; + + auto par_conv = jit_conv_call_s(); + size_t src_h_stride = src_d.blk_off(0, 0, 1); + size_t src_c_stride = src_d.blk_off(0, 1); + size_t dst_h_stride = dst_d.blk_off(0, 0, 1); + size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1); + size_t wht_ic_stride = wht_blk_off(weights_d, 0, 0, 1); + + for (int icb_l2 = 0 ; icb_l2 < jcp.nb_ic; icb_l2 += jcp.nb_ic_L2) { + start = start_copy; + int n{0}, g{0}, occ{0}, oh_s{0}, owb{0}; + + if (jcp.loop_order == loop_cwgn) + nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow, + g, jcp.ngroups, n, jcp.mb, oh_s, jcp.oh); + else if (jcp.loop_order == loop_gncw) + nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb, + occ, oc_chunks, owb, jcp.nb_ow, oh_s, jcp.oh); + else + assert(!"unsupported loop order"); + + while (start < end) { + int ocb = occ * jcp.nb_oc_blocking; + int g_ocb = g * jcp.nb_oc + ocb; + int g_oc = g_ocb * jcp.oc_block; + int g_icb = g * jcp.nb_ic * jcp.nonblk_group_off; + + int work_rem = end - start; + + int ow_s = owb * jcp.ow_block; + int iw_s = ow_s * jcp.stride_w; + int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem; + auto bias_w = bias ? bias + g_oc : nullptr; + + for (int oh_b = oh_s; oh_b < oh_e; oh_b += jcp.h_blocking) { + int ih_b = -jcp.t_pad + oh_b * jcp.stride_h; + + auto dst_w = dst + dst_d.blk_off(n, g_ocb, oh_b, ow_s); + auto src_w + = src + src_d.blk_off(n, g_icb + icb_l2, ih_b, iw_s); + auto wht_w + = weights + wht_blk_off(weights_d, g, ocb, icb_l2); + + for (int icb = icb_l2; + icb < min(jcp.nb_ic, icb_l2 + jcp.nb_ic_L2); + ++icb) { + auto src_c = src_w; + auto dst_c = dst_w; + for (int oj = oh_b, ij = ih_b; + oj < min(oh_e, oh_b + jcp.h_blocking); + ++oj, ij += jcp.stride_h) { + int dilate_h = jcp.dilate_h + 1; + int i_t_overflow = div_up(max(0, -ij), dilate_h); + int i_b_overflow = div_up(max(0, ij - jcp.ih + + (jcp.kh - 1) * dilate_h + 1), dilate_h); + int kh_padding = nstl::max( + 0, jcp.kh - i_t_overflow - i_b_overflow); + + auto aux_src = src_c + + i_t_overflow * dilate_h * src_h_stride; + auto aux_wht = wht_w + i_t_overflow * wht_h_stride; + + jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker, + par_conv, aux_src, dst_c, aux_wht, bias_w, icb, + kh_padding, owb); + + src_c += src_h_stride * jcp.stride_h; + dst_c += dst_h_stride; + } + src_w += src_c_stride; + wht_w += wht_ic_stride; + } + } + + if (jcp.loop_order == loop_cwgn) + nd_iterator_jump(start, end, occ, oc_chunks, owb, jcp.nb_ow, + g, jcp.ngroups, n, jcp.mb, oh_s, jcp.oh); + else if (jcp.loop_order == loop_gncw) + nd_iterator_jump(start, end, g, jcp.ngroups, n, jcp.mb, occ, + oc_chunks, owb, jcp.nb_ow, oh_s, jcp.oh); + else + assert(!"unsupported loop order"); + } + } + + jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker, par_conv, + src, dst, weights, bias, 0, 0, 0); + }); +} + +template +void jit_avx512_common_convolution_fwd_t:: +execute_forward_3d(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + prepare_padded_bias(bias, this->scratchpad(ctx)); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const auto &jcp = pd()->jcp_; + assert(jcp.nb_oc % jcp.nb_oc_blocking == 0); + + parallel(0, [&](const int ithr, const int nthr) { + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking; + int start{0}, end{0}, start_copy; + int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.od * jcp.oh + * jcp.nb_ow; + balance211(work_amount, nthr, ithr, start, end); + start_copy = start; + + auto par_conv = jit_conv_call_s(); + size_t src_d_stride = src_d.blk_off(0, 0, 1); + size_t src_h_stride = src_d.blk_off(0, 0, 0, 1); + size_t src_c_stride = src_d.blk_off(0, 1); + size_t dst_h_stride = dst_d.blk_off(0, 0, 0, 1); + size_t wht_d_stride = wht_blk_off(weights_d, 0, 0, 0, 1); + size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 0, 1); + size_t wht_ic_stride = wht_blk_off(weights_d, 0, 0, 1); + + for (int icb_l2 = 0 ; icb_l2 < jcp.nb_ic; icb_l2 += jcp.nb_ic_L2) { + start = start_copy; + int n{0}, g{0}, occ{0}, oh_s{0}, od_s{0}, owb{0}; + + if (jcp.loop_order == loop_cwgn) + nd_iterator_init(start, + occ, oc_chunks, owb, jcp.nb_ow, g, jcp.ngroups, n, jcp.mb, + od_s, jcp.od, oh_s, jcp.oh); + else if (jcp.loop_order == loop_gncw) + nd_iterator_init(start, + g, jcp.ngroups, n, jcp.mb, occ, oc_chunks, owb, jcp.nb_ow, + od_s, jcp.od, oh_s, jcp.oh); + else + assert(!"unsupported loop order"); + + while (start < end) { + int ocb = occ * jcp.nb_oc_blocking; + int g_ocb = g * jcp.nb_oc + ocb; + int g_oc = g_ocb * jcp.oc_block; + int g_icb = g * jcp.nb_ic * jcp.nonblk_group_off; + + int work_rem = end - start; + int ih_s = -jcp.t_pad + oh_s * jcp.stride_h; + int ow_s = owb * jcp.ow_block; + int iw_s = ow_s * jcp.stride_w; + int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem; + + int id_s = -jcp.f_pad + od_s * jcp.stride_d; + + int dilate_d = jcp.dilate_d + 1; + int d_t_overflow = div_up(max(0, -id_s), dilate_d); + int d_b_overflow = div_up( + max(0, id_s - jcp.id + (jcp.kd - 1) * dilate_d + 1), + dilate_d); + int kd_padding = nstl::max(0, + jcp.kd - d_t_overflow - d_b_overflow); + + auto bias_w = bias ? bias + bias_d.blk_off(g_oc) : 0; + auto dst_w = dst + dst_d.blk_off(n, g_ocb, od_s, oh_s, ow_s); + auto src_w = src + src_d.blk_off(n, g_icb + icb_l2, id_s, ih_s, + iw_s) + d_t_overflow * dilate_d * src_d_stride; + auto wht_w = weights + wht_blk_off(weights_d, g, ocb, icb_l2) + + d_t_overflow * wht_d_stride; + + for (int icb = icb_l2; + icb < min(jcp.nb_ic, icb_l2 + jcp.nb_ic_L2); ++icb) { + auto src_c = src_w; + auto dst_c = dst_w; + for (int oj = oh_s, ij = ih_s; + oj < oh_e; ++oj, ij += jcp.stride_h) + { + int dilate_h = jcp.dilate_h + 1; + int i_t_overflow = div_up(max(0, -ij), dilate_h); + int i_b_overflow = div_up( + max(0, ij - jcp.ih + (jcp.kh - 1) * dilate_h + + 1), + dilate_h); + int kh_padding = nstl::max(0, + jcp.kh - i_t_overflow - i_b_overflow); + jit_conv_3d_ker_pipeline_ow_thr(kernel_->jit_ker, + par_conv, + src_c + i_t_overflow * dilate_h * src_h_stride, + dst_c, wht_w + i_t_overflow * wht_h_stride, + bias_w, icb, kh_padding, kd_padding, owb); + + src_c += src_h_stride * jcp.stride_h; + dst_c += dst_h_stride; + } + src_w += src_c_stride; + wht_w += wht_ic_stride; + } + + if (jcp.loop_order == loop_cwgn) + nd_iterator_jump(start, end, + occ, oc_chunks, owb, jcp.nb_ow, g, jcp.ngroups, n, jcp.mb, + od_s, jcp.od, oh_s, jcp.oh); + else if (jcp.loop_order == loop_gncw) + nd_iterator_jump(start, end, + g, jcp.ngroups, n, jcp.mb, occ, oc_chunks, owb, jcp.nb_ow, + od_s, jcp.od, oh_s, jcp.oh); + else + assert(!"unsupported loop order"); + } + } + jit_conv_3d_ker_pipeline(kernel_->jit_ker, par_conv, + src, dst, weights, bias, 0, 0, 0); + }); +} + +template struct jit_avx512_common_convolution_fwd_t; + +template +void jit_avx512_common_convolution_bwd_data_t::execute_backward_data_1d(const exec_ctx_t &ctx) const +{ + auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + + parallel(0, [&](const int ithr, const int nthr) { + int start{0}, end{0}, start_copy; + int ic_chunks = jcp.nb_ic / jcp.nb_ic_blocking; + int work_amount = jcp.ngroups * jcp.mb * ic_chunks * jcp.ih; + balance211(work_amount, nthr, ithr, start, end); + start_copy = start; + + auto par_conv = jit_conv_call_s(); + size_t diff_dst_c_stride = diff_dst_d.blk_off(0, 1); + size_t wht_oc_stride = wht_blk_off(weights_d, 0, 1); + + for (int ocb_l2 = 0; ocb_l2 < jcp.nb_oc; ocb_l2 += jcp.nb_oc_L2) { + start = start_copy; + int n{0}, g{0}, icc{0}; + if (jcp.loop_order == loop_cgn) { + int dummy{0}; + nd_iterator_init(start, icc, ic_chunks, g, jcp.ngroups, n, + jcp.mb, dummy, 1); + } else if (jcp.loop_order == loop_gnc) { + int dummy{0}; + nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb, icc, + ic_chunks, dummy, 1); + } else { + assert(!"unsupported loop order"); + } + + while (start < end) { + int icb = icc * jcp.nb_ic_blocking; + int g_icb = g * jcp.nb_ic + icb; + int g_ocb = g * jcp.nb_oc; + + auto diff_src_w = diff_src + diff_src_d.blk_off(n, g_icb); + auto diff_dst_w = diff_dst + + diff_dst_d.blk_off(n, g_ocb + ocb_l2); + auto wht_w = weights + wht_blk_off(weights_d, g, ocb_l2, icb); + + for (int ocb = ocb_l2; + ocb < min(jcp.nb_oc, ocb_l2 + jcp.nb_oc_L2); ++ocb) { + jit_conv_ker_pipeline(kernel_->jit_ker, par_conv, + diff_src_w, diff_dst_w, wht_w, 0, ocb, 1); + diff_dst_w += diff_dst_c_stride; + wht_w += wht_oc_stride; + } + + if (jcp.loop_order == loop_cgn) { + int dummy{0}; + nd_iterator_jump(start, end, icc, ic_chunks, g, jcp.ngroups, + n, jcp.mb, dummy, 1); + } else if (jcp.loop_order == loop_gnc) { + int dummy{0}; + nd_iterator_jump(start, end, g, jcp.ngroups, n, jcp.mb, icc, + ic_chunks, dummy, 1); + } else { + assert(!"unsupported loop order"); + } + } + } + + jit_conv_ker_pipeline(kernel_->jit_ker, par_conv, + diff_src, diff_dst, weights, 0, 0, 1); + }); +} + +template +void jit_avx512_common_convolution_bwd_data_t::execute_backward_data_2d(const exec_ctx_t &ctx) const +{ + auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + + parallel(0, [&](const int ithr, const int nthr) { + int start{0}, end{0}, start_copy; + int ic_chunks = jcp.nb_ic / jcp.nb_ic_blocking; + int work_amount = jcp.ngroups * jcp.mb * ic_chunks * jcp.ih; + balance211(work_amount, nthr, ithr, start, end); + start_copy = start; + + auto par_conv = jit_conv_call_s(); + size_t diff_src_h_stride = diff_src_d.blk_off(0, 0, 1); + size_t diff_dst_h_stride = diff_dst_d.blk_off(0, 0, 1); + size_t diff_dst_c_stride = diff_dst_d.blk_off(0, 1); + size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1); + size_t wht_oc_stride = wht_blk_off(weights_d, 0, 1); + + bool is_fast_path = jcp.dilate_h == 0 && jcp.stride_h == 1; + + for (int ocb_l2 = 0; ocb_l2 < jcp.nb_oc; ocb_l2 += jcp.nb_oc_L2) { + start = start_copy; + int n{0}, g{0}, icc{0}, ih_s{0}; + if (jcp.loop_order == loop_cgn) + nd_iterator_init(start, + icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, ih_s, jcp.ih); + else if (jcp.loop_order == loop_gnc) + nd_iterator_init(start, + g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, ih_s, jcp.ih); + else + assert(!"unsupported loop order"); + + while (start < end) { + int icb = icc * jcp.nb_ic_blocking; + int g_icb = g * jcp.nb_ic + icb; + int g_ocb = g * jcp.nb_oc; + + int work_rem = end - start; + int ih_e = ih_s + work_rem > jcp.ih ? jcp.ih : ih_s + work_rem; + + auto diff_src_w = diff_src + diff_src_d.blk_off(n, g_icb); + auto diff_dst_w = diff_dst + + diff_dst_d.blk_off(n, g_ocb + ocb_l2); + auto wht_w = weights + wht_blk_off(weights_d, g, ocb_l2, icb); + + for (int ocb = ocb_l2; + ocb < min(jcp.nb_oc, ocb_l2 + jcp.nb_oc_L2); ++ocb) { + for (int ij = ih_s; ij < ih_e; ++ij) { + int oj, k_len, k_lo; + if (is_fast_path) { // dilate == 0 && stride == 1 + int i_t_overflow = max(0, jcp.kh - 1 - ij + - jcp.t_pad); + int i_b_overflow = max(0, jcp.kh - jcp.ih + ij + - jcp.b_pad); + k_len = jcp.kh - i_t_overflow - i_b_overflow; + k_lo = i_b_overflow; + oj = ij + jcp.t_pad - i_b_overflow; + } else if (jcp.dilate_h != 0) { // stride == 1 + int dilate_h = jcp.dilate_h + 1; + // Note: use div_up to account for "holes" in filter + int i_t_overflow + = div_up(max(0, (jcp.kh - 1) * dilate_h + - ij - jcp.t_pad), dilate_h); + int i_b_overflow + = div_up(max(0, (jcp.kh - 1) * dilate_h + 1 + - jcp.ih + ij - jcp.b_pad), dilate_h); + k_len = jcp.kh - i_t_overflow - i_b_overflow; + k_lo = i_b_overflow; + oj = ij + jcp.t_pad - i_b_overflow * dilate_h; + } else { // dilate == 0 + int i_t_overflow = max(0, (jcp.kh - 1 - ij + - jcp.t_pad) / jcp.stride_h); + int i_b_overflow = max(0, (jcp.kh - jcp.ih + ij + - jcp.b_pad) / jcp.stride_h); + int overflow_kh_hi = jcp.kh - 1 - abs((jcp.ih - 1 + + jcp.b_pad - ij) % jcp.stride_h); + int overflow_kh_lo = (ij + jcp.t_pad) + % jcp.stride_h; + + k_len = (overflow_kh_hi - overflow_kh_lo) + / jcp.stride_h + 1 - i_t_overflow + - i_b_overflow; + k_lo = overflow_kh_lo + i_b_overflow * jcp.stride_h; + oj = (ij + jcp.t_pad - k_lo) / jcp.stride_h; + } + assert(k_len >= 0); + + jit_conv_ker_pipeline(kernel_->jit_ker, par_conv, + diff_src_w + ij * diff_src_h_stride, + diff_dst_w + oj * diff_dst_h_stride, + wht_w + k_lo * wht_h_stride, + 0, ocb, k_len); + } + diff_dst_w += diff_dst_c_stride; + wht_w += wht_oc_stride; + } + + if (jcp.loop_order == loop_cgn) + nd_iterator_jump(start, end, + icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, ih_s, jcp.ih); + else if (jcp.loop_order == loop_gnc) + nd_iterator_jump(start, end, + g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, ih_s, jcp.ih); + else + assert(!"unsupported loop order"); + } + } + + jit_conv_ker_pipeline(kernel_->jit_ker, par_conv, + diff_src, diff_dst, weights, 0, 0, 1); + }); +} + +template +void jit_avx512_common_convolution_bwd_data_t::execute_backward_data_3d(const exec_ctx_t &ctx) const +{ + auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + + parallel(0, [&](const int ithr, const int nthr) { + int start{0}, end{0}, start_copy; + int ic_chunks = jcp.nb_ic / jcp.nb_ic_blocking; + int work_amount = jcp.ngroups * jcp.mb * ic_chunks * jcp.id * jcp.ih; + balance211(work_amount, nthr, ithr, start, end); + start_copy = start; + + auto par_conv = jit_conv_call_s(); + size_t diff_src_h_stride = diff_src_d.blk_off(0, 0, 0, 1); + size_t diff_src_d_stride = diff_src_d.blk_off(0, 0, 1); + size_t diff_dst_h_stride = diff_dst_d.blk_off(0, 0, 0, 1); + size_t diff_dst_d_stride = diff_dst_d.blk_off(0, 0, 1); + size_t diff_dst_c_stride = diff_dst_d.blk_off(0, 1); + size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 0, 1); + size_t wht_d_stride = wht_blk_off(weights_d, 0, 0, 0, 1); + size_t wht_oc_stride = wht_blk_off(weights_d, 0, 1); + + bool is_fast_path_d = jcp.dilate_d == 0 && jcp.stride_d == 1; + bool is_fast_path_h = jcp.dilate_h == 0 && jcp.stride_h == 1; + + for (int ocb_l2 = 0; ocb_l2 < jcp.nb_oc; ocb_l2 += jcp.nb_oc_L2) { + start = start_copy; + int n{0}, g{0}, icc{0}, ih_s{0}, id_s{0}; + if (jcp.loop_order == loop_cgn) + nd_iterator_init(start, + icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, id_s, jcp.id, + ih_s, jcp.ih); + else if (jcp.loop_order == loop_gnc) + nd_iterator_init(start, + g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, id_s, jcp.id, + ih_s, jcp.ih); + else + assert(!"unsupported loop order"); + + while (start < end) { + int icb = icc * jcp.nb_ic_blocking; + int g_icb = g * jcp.nb_ic + icb; + int g_ocb = g * jcp.nb_oc; + + int work_rem = end - start; + int ih_e = ih_s + work_rem > jcp.ih ? jcp.ih : ih_s + work_rem; + int d_len = 0, d_lo = 0, d_oj = 0; + if (is_fast_path_d) { // dilate == 0 && stride == 1 + int d_t_overflow = max(0, jcp.kd - 1 - id_s + - jcp.f_pad); + int d_b_overflow = max(0, jcp.kd - jcp.id + id_s + - jcp.back_pad); + d_len = jcp.kd - d_t_overflow - d_b_overflow; + d_lo = d_b_overflow; + d_oj = id_s + jcp.f_pad - d_b_overflow; + } else if (jcp.dilate_d != 0) { // stride == 1 + int dilate_d = jcp.dilate_d + 1; + // Note: use div_up to account for "holes" in filter + int d_t_overflow = div_up(max(0, (jcp.kd - 1) * dilate_d + - id_s - jcp.f_pad), dilate_d); + int d_b_overflow = div_up(max(0, (jcp.kd - 1) * dilate_d + 1 + - jcp.id + id_s - jcp.back_pad), dilate_d); + d_len = jcp.kd - d_t_overflow - d_b_overflow; + d_lo = d_b_overflow; + d_oj = id_s + jcp.f_pad - d_b_overflow * dilate_d; + } else { // dilate == 0 + int d_t_overflow = max(0, (jcp.kd - 1 - id_s + - jcp.f_pad) / jcp.stride_d); + int d_b_overflow = max(0, (jcp.kd - jcp.id + id_s + - jcp.back_pad) / jcp.stride_d); + int overflow_kd_hi = jcp.kd - 1 - abs((jcp.id - 1 + + jcp.back_pad - id_s) % jcp.stride_d); + int overflow_kd_lo = (id_s + jcp.f_pad) + % jcp.stride_d; + + d_len = (overflow_kd_hi - overflow_kd_lo) + / jcp.stride_d + 1 - d_t_overflow + - d_b_overflow; + d_lo = overflow_kd_lo + d_b_overflow * jcp.stride_d; + d_oj = (id_s + jcp.f_pad - d_lo) / jcp.stride_d; + } + assert(d_len >= 0); + + auto diff_src_w = diff_src + diff_src_d.blk_off(n, g_icb) + + id_s * diff_src_d_stride; + auto diff_dst_w = diff_dst + + diff_dst_d.blk_off(n, g_ocb + ocb_l2) + + d_oj * diff_dst_d_stride; + auto wht_w = weights + wht_blk_off(weights_d, g, ocb_l2, icb) + + d_lo * wht_d_stride; + + for (int ocb = ocb_l2; + ocb < min(jcp.nb_oc, ocb_l2 + jcp.nb_oc_L2); ++ocb) { + for (int ij = ih_s; ij < ih_e; ++ij) { + int oj, k_len, k_lo; + if (is_fast_path_h) { // dilate == 0 && stride == 1 + int i_t_overflow = max(0, jcp.kh - 1 - ij + - jcp.t_pad); + int i_b_overflow = max(0, jcp.kh - jcp.ih + ij + - jcp.b_pad); + k_len = jcp.kh - i_t_overflow - i_b_overflow; + k_lo = i_b_overflow; + oj = ij + jcp.t_pad - i_b_overflow; + } else if (jcp.dilate_h != 0) { // stride == 1 + int dilate_h = jcp.dilate_h + 1; + // Note: use div_up to account for "holes" in filter + int i_t_overflow + = div_up(max(0, (jcp.kh - 1) * dilate_h + - ij - jcp.t_pad), dilate_h); + int i_b_overflow + = div_up(max(0, (jcp.kh - 1) * dilate_h + 1 + - jcp.ih + ij - jcp.b_pad), dilate_h); + k_len = jcp.kh - i_t_overflow - i_b_overflow; + k_lo = i_b_overflow; + oj = ij + jcp.t_pad - i_b_overflow * dilate_h; + } else { // dilate == 0 + int i_t_overflow = max(0, (jcp.kh - 1 - ij + - jcp.t_pad) / jcp.stride_h); + int i_b_overflow = max(0, (jcp.kh - jcp.ih + ij + - jcp.b_pad) / jcp.stride_h); + int overflow_kh_hi = jcp.kh - 1 - abs((jcp.ih - 1 + + jcp.b_pad - ij) % jcp.stride_h); + int overflow_kh_lo = (ij + jcp.t_pad) + % jcp.stride_h; + + k_len = (overflow_kh_hi - overflow_kh_lo) + / jcp.stride_h + 1 - i_t_overflow + - i_b_overflow; + k_lo = overflow_kh_lo + i_b_overflow * jcp.stride_h; + oj = (ij + jcp.t_pad - k_lo) / jcp.stride_h; + } + assert(k_len >= 0); + + jit_conv_3d_ker_pipeline(kernel_->jit_ker, par_conv, + diff_src_w + ij * diff_src_h_stride, + diff_dst_w + oj * diff_dst_h_stride, + wht_w + k_lo * wht_h_stride, + 0, ocb, k_len, d_len); + } + diff_dst_w += diff_dst_c_stride; + wht_w += wht_oc_stride; + } + + if (jcp.loop_order == loop_cgn) + nd_iterator_jump(start, end, + icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, id_s, jcp.id, + ih_s, jcp.ih); + else if (jcp.loop_order == loop_gnc) + nd_iterator_jump(start, end, + g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, id_s, jcp.id, + ih_s, jcp.ih); + else + assert(!"unsupported loop order"); + } + } + + jit_conv_3d_ker_pipeline(kernel_->jit_ker, par_conv, + diff_src, diff_dst, weights, 0, 0, 1, 1); + }); +} + +template struct jit_avx512_common_convolution_bwd_data_t; + +template +jit_avx512_common_convolution_bwd_weights_t:: +jit_avx512_common_convolution_bwd_weights_t(const pd_t *apd) + : cpu_primitive_t(apd), kernel_(nullptr) + , trans_kernel_(nullptr), acc_ker_(nullptr), reducer_bias_(nullptr) +{ + const auto &j = pd()->jcp_; + + nthr_ = j.nthr; + nthr_mb_ = j.nthr_mb; + nthr_g_ = j.nthr_g; + nthr_oc_b_ = j.nthr_oc_b; + nthr_ic_b_ = j.nthr_ic_b; + + kernel_ = new jit_avx512_common_conv_bwd_weights_kernel_f32(j); + + if (j.ver == ver_4fma) + trans_kernel_ = create_trans_src(&j); + + if (nthr_mb_ > 1) + acc_ker_ = new cpu_accumulator_1d_t(); + + reducer_bias_ = + new cpu_reducer_t(pd()->reducer_bia_conf_); +} + +template +struct jit_avx512_common_convolution_bwd_weights_t::thread_info_t { + const src_data_t *src; + const diff_dst_data_t *diff_dst; + const diff_weights_data_t *diff_weights; + diff_weights_data_t *diff_bias; + + const memory_tracking::grantor_t scratchpad; + + src_data_t *tr_src; + simple_barrier::ctx_t *tr_src_bctx; + + diff_dst_data_t *tr_diff_dst; + simple_barrier::ctx_t *tr_diff_dst_bctx; + + diff_weights_data_t *wei_bia_reduction; + simple_barrier::ctx_t *wei_bia_reduction_bctx; + + int ithr; + int ithr_ic_b, ithr_oc_b, ithr_g, ithr_mb; + int ithr_but_oc; + int ithr_but_ic; + + int img_start = 0, img_end = 0, img_work; + int g_start = 0, g_end = 0, g_work; + int oc_b_start = 0, oc_b_end = 0, oc_b_work; + int ic_b_start = 0, ic_b_end = 0, ic_b_work; + + thread_info_t(const jit_avx512_common_convolution_bwd_weights_t *self, + const exec_ctx_t &ctx, int ithr) + : scratchpad(self->scratchpad(ctx)), ithr(ithr) + { + diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + diff_weights = CTX_OUT_MEM(diff_weights_data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + diff_bias = self->pd()->wants_padded_bias() + ? scratchpad.template get( + key_conv_padded_bias) + : CTX_OUT_MEM(diff_weights_data_t *, MKLDNN_ARG_DIFF_BIAS); + + tr_src = scratchpad.template get(key_conv_tr_src); + tr_src_bctx = scratchpad.template get( + key_conv_tr_src_bctx); + + tr_diff_dst = scratchpad.template get( + key_conv_tr_diff_dst); + tr_diff_dst_bctx = scratchpad.template get( + key_conv_tr_diff_dst_bctx); + + wei_bia_reduction = scratchpad.template get( + key_conv_wei_bia_reduction); + wei_bia_reduction_bctx = scratchpad.template get( + key_conv_wei_bia_reduction_bctx); + + ithr_ic_b = ithr % self->nthr_ic_b_; + ithr_oc_b = ithr / self->nthr_ic_b_ % self->nthr_oc_b_; + ithr_g = ithr / self->nthr_ic_b_ / self->nthr_oc_b_ % self->nthr_g_; + ithr_mb = ithr / self->nthr_ic_b_ / self->nthr_oc_b_ / self->nthr_g_; + + ithr_but_oc = (ithr_mb * self->nthr_g_ + ithr_g) * self->nthr_ic_b_ + + ithr_ic_b; + + ithr_but_ic = (ithr_mb * self->nthr_g_ + ithr_g) * self->nthr_oc_b_ + + ithr_oc_b; + + const auto &jcp = self->kernel_->jcp; + + /* reduction dimension */ + balance211(jcp.mb*jcp.od, self->nthr_mb_, ithr_mb, img_start, img_end); + img_work = img_end - img_start; + + /* independent dimensions */ + balance211(jcp.ngroups, self->nthr_g_, ithr_g, g_start, g_end); + g_work = g_end - g_start; + + balance211(jcp.nb_oc, self->nthr_oc_b_, ithr_oc_b, oc_b_start, + oc_b_end); + oc_b_work = oc_b_end - oc_b_start; + + balance211(jcp.nb_ic, self->nthr_ic_b_, ithr_ic_b, ic_b_start, + ic_b_end); + ic_b_work = ic_b_end - ic_b_start; + } +}; + +template +void jit_avx512_common_convolution_bwd_weights_t::compute_diff_weights(const thread_info_t *ti) const { + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + + const auto &jcp = kernel_->jcp; + const int wei_size = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh*jcp.kw*jcp.kd; + + diff_weights_data_t *diff_wei = ti->ithr_mb == 0 + ? (diff_weights_data_t*)ti->diff_weights + : ti->wei_bia_reduction + (ti->ithr_mb - 1) * wei_size; + diff_weights_data_t *diff_bia = ti->ithr_mb == 0 + ? (diff_weights_data_t*)ti->diff_bias + : ti->wei_bia_reduction + (nthr_mb_ - 1) * wei_size + + (ti->ithr_mb - 1) * jcp.ngroups * jcp.oc; + + // TODO: use memory descriptor with the same fmt as src (or use a macro :)) + auto tr_src_off = [&](int ithr_mb, int ic, int ij) { + const size_t tr_row_size = jcp.tr_iw * jcp.ic_block; + const size_t tr_chn_size = tr_row_size * jcp.ih; + const size_t tr_img_size = tr_chn_size * jcp.nb_ic * jcp.ngroups; + + return ti->ithr_mb * tr_img_size + ic * tr_chn_size + ij * tr_row_size; + }; + + auto uker_trans = [&](int img) { + const int work_amount = ti->g_work * ti->ic_b_work * jcp.ih; + + int start{0}, end{0}; + balance211(work_amount, nthr_oc_b_, ti->ithr_oc_b, start, end); + const int my_work = end - start; + + int g{0}, ic_b{0}, j{0}; + nd_iterator_init(start, g, ti->g_work, ic_b, ti->ic_b_work, j, jcp.ih); + g += ti->g_start; + ic_b += ti->ic_b_start; + + const int _ic = g * jcp.nb_ic + ic_b; + src_data_t *src1 = (src_data_t*)&ti->src[src_d.blk_off(img, _ic, j)]; + src_data_t *tr_src1 = &ti->tr_src[tr_src_off(ti->ithr_mb, _ic, j)]; + + assert(jcp.ic_block == 16); + const int src_stride = jcp.iw * jcp.ic_block; + const int tr_src_stride = jcp.tr_iw * jcp.ic_block; + + const int pf_depth = 2; + struct { src_data_t *src, *tr_src; } pf_circ_buf[pf_depth]; + + for (int iwork = 0; iwork < my_work + pf_depth - 1; iwork++) { + pf_circ_buf[iwork % pf_depth] = {src1, tr_src1}; + + if (iwork >= pf_depth - 1) { + int old_idx = (iwork - pf_depth + 1) % pf_depth; + auto ctx = jit_trans_src_t::ctx_t(); + ctx.src = pf_circ_buf[old_idx].src; + ctx.tr_src = pf_circ_buf[old_idx].tr_src; + ctx.src_prf = src1; + ctx.tr_src_prf = tr_src1; + (*trans_kernel_)(&ctx); + } + src1 += src_stride; + tr_src1 += tr_src_stride; + } +#if 0 + // reference transposition + const int l_pad = jcp.l_pad; + const int iwlp = l_pad + jcp.iw; + const int tr_iw = jcp.tr_iw; + + for (size_t iwork = start; iwork < end; iwork++) { + PRAGMA_OMP_SIMD() +# pragma unroll + for (int i = 0; i < l_pad; i++) + for (int j = 0; j < jcp.ic_block; j++) + tr_src1[j * jcp.tr_iw + i] = (src_data_t)0.0; + + PRAGMA_OMP_SIMD() +# pragma unroll + for (int i = l_pad; i < iwlp; i++) + for (int j = 0; j < jcp.ic_block; j++) + tr_src1[j * jcp.tr_iw + i] + = (src_data_t)src1[(i - l_pad) * 16 + j]; + + PRAGMA_OMP_SIMD() +# pragma unroll + for (int i = iwlp; i < tr_iw; i++) + for (int j = 0; j < jcp.ic_block; j++) + tr_src1[j * jcp.tr_iw + i] = (src_data_t)0.0; + + src1 += src_stride; + tr_src1 += tr_src_stride; + } +#endif + }; + + if (jcp.is_1stconv && jcp.ver == ver_4fma) { + /* prepare contexts */ + auto tr_ctx = jit_trans_src_t::ctx_t(); + tr_ctx.tr_src = ti->tr_src + + ti->ithr_but_oc * jcp.ih * jcp.stride_w * jcp.tr_ld; + + assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_oc_b_ == 1)); + tr_ctx.nthr_oc_b = nthr_oc_b_; + int ih_start{0}, ih_end{0}; + balance211(jcp.ih, nthr_oc_b_, ti->ithr_oc_b, ih_start, ih_end); + tr_ctx.tr_src_ih_start = ih_start; + tr_ctx.tr_src_ih_end = ih_end; + tr_ctx.tr_src_bctx = ti->tr_src_bctx + ti->ithr_but_oc; + + auto p = jit_conv_call_s(); + p.src = tr_ctx.tr_src; + + /* zero diff_bias if applicable */ + if (jcp.with_bias && ti->ithr_ic_b == 0) { + assert(jcp.oc_block == 16); + for (int oc_b = ti->ic_b_start; oc_b < ti->oc_b_end; ++oc_b) { + diff_weights_data_t *db = &diff_bia[oc_b * 16]; + for (int o = 0; o < 16; ++o) + db[o] = 0; + } + } + + for (int img = ti->img_start; img < ti->img_end; ++img) { + p.flags = (img == ti->img_start) * FLAG_MB_FIRST; + + for (int g = ti->g_start; g < ti->g_end; ++g) { + for (int ic_b = ti->ic_b_start; ic_b < ti->ic_b_end; ++ic_b) { + const int _ic = g * jcp.nb_ic + ic_b; + tr_ctx.src = &ti->src[src_d.blk_off(img, _ic)]; + + (*trans_kernel_)(&tr_ctx); + + if (ic_b == 0) + p.flags |= FLAG_IC_FIRST; + else + p.flags &= ~FLAG_IC_FIRST; + + for (int oc_b = ti->oc_b_start; oc_b < ti->oc_b_end; ++oc_b) { + const int _oc = g * jcp.nb_oc + oc_b; + p.dst = &ti->diff_dst[diff_dst_d.blk_off(img, _oc)]; + + const size_t off = + wht_blk_off(diff_weights_d, g, oc_b, ic_b); + p.filt = diff_wei + off; + p.bias = diff_bia + _oc * jcp.oc_block; + + kernel_->jit_ker(&p); + } + } + } + } + } else { + for (int img = ti->img_start; img < ti->img_end; ++img) { + auto p = jit_conv_call_s(); + + if (jcp.ver == ver_4fma) { + /* tr_src[nb_ic][ih][16][~iw~] <- src[nb_ic][ih][iw][16] */ + using simple_barrier::barrier; + if (nthr_oc_b_ > 1) + barrier(&ti->tr_src_bctx[ti->ithr_but_oc], nthr_oc_b_); + uker_trans(img); + if (nthr_oc_b_ > 1) + barrier(&ti->tr_src_bctx[ti->ithr_but_oc], nthr_oc_b_); + } + + for (int g = ti->g_start; g < ti->g_end; ++g) { + for (int oc_b = ti->oc_b_start; oc_b < ti->oc_b_end; ++oc_b) { + for (int ic_b = ti->ic_b_start; ic_b < ti->ic_b_end; ++ic_b) { + const int _oc = g * jcp.nb_oc + oc_b; + const int _ic = g * jcp.nb_ic + ic_b; + + jit_conv_ker_pipeline(kernel_->jit_ker, p, + jcp.ver == ver_4fma + ? &ti->tr_src[tr_src_off(ti->ithr_mb, _ic, 0)] + : &ti->src[src_d.blk_off(img, _ic)], + &ti->diff_dst[diff_dst_d.blk_off(img, _oc)], + diff_wei + wht_blk_off(diff_weights_d, g, oc_b, ic_b), + 0, (img == ti->img_start), 0); + + } + } + } + + const int _oc = ti->g_start * jcp.nb_oc + ti->oc_b_start; + const int _ic = ti->g_start * jcp.nb_ic + ti->ic_b_start; + jit_conv_ker_pipeline(kernel_->jit_ker, p, + jcp.ver == ver_4fma + ? &ti->tr_src[tr_src_off(ti->ithr_mb, _ic, 0)] + : &ti->src[src_d.blk_off(img + 1, _ic)], + &ti->diff_dst[diff_dst_d.blk_off(img + 1, _oc)], + diff_wei + wht_blk_off( + diff_weights_d, ti->g_start, + ti->oc_b_start, ti->ic_b_start), + 0, 0, 0); + } + } +} + +template +void jit_avx512_common_convolution_bwd_weights_t::compute_diff_weights_3d(const thread_info_t *ti) const +{ + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + + const auto &jcp = kernel_->jcp; + const int wei_size + = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw * jcp.kd; + + diff_weights_data_t *diff_wei = ti->ithr_mb == 0 + ? (diff_weights_data_t*)ti->diff_weights + : ti->wei_bia_reduction + (ti->ithr_mb - 1) * wei_size; + diff_weights_data_t *diff_bia = ti->ithr_mb == 0 + ? (diff_weights_data_t*)ti->diff_bias + : ti->wei_bia_reduction + (nthr_mb_ - 1) * wei_size + + (ti->ithr_mb - 1) * jcp.ngroups * jcp.oc; + + const int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block; + const int input_step = jcp.ih * jcp.iw * inp_mult; + const int output_step = jcp.ow * jcp.oh * jcp.oc_block; + int img{0}, od_s{0}; + int img_start = ti->img_start, img_end = ti->img_end; + nd_iterator_init(img_start, img, jcp.mb, od_s, jcp.od); + const int img_first = img; + + while (img_start < img_end) { + auto p = jit_conv_call_s(); + + int work_rem = img_end - img_start; + const int od_e = od_s + work_rem > jcp.od ? jcp.od : od_s + work_rem; + const int id_s = od_s * jcp.stride_d; + const int ik_overlap = nstl::max(0, id_s - jcp.f_pad); + const int kd_front_pad = nstl::max(0, jcp.f_pad - id_s); + const int kd_back_pad + = nstl::max(0, id_s - jcp.f_pad - jcp.id + jcp.kd); + int kd_pad_off = nstl::min(jcp.kd - 1, kd_front_pad) * jcp.kh * jcp.kw + * jcp.ic_block * jcp.oc_block * jcp.typesize_out; + + for (int g = ti->g_start; g < ti->g_end; ++g) { + for (int oc_b = ti->oc_b_start; oc_b < ti->oc_b_end; ++oc_b) { + for (int ic_b = ti->ic_b_start; ic_b < ti->ic_b_end; ++ic_b) { + const int _oc = g * jcp.nb_oc + oc_b; + const int _ic = g * jcp.nb_ic + ic_b; + + auto src = &ti->src[src_d.blk_off(img, _ic) + + ik_overlap * input_step]; + auto dst = &ti->diff_dst[diff_dst_d.blk_off(img, _oc) + + od_s * output_step]; + + jit_conv_3d_ker_bwd_w_pipeline(kernel_->jit_ker, p, src, dst, + diff_wei + wht_blk_off(diff_weights_d, g, oc_b, ic_b), + diff_bia + _oc * 16, (img == img_first), od_s, od_e, + jcp.kd - kd_front_pad - kd_back_pad, kd_pad_off); + + if (ic_b == 0) p.flags = 0; + else p.flags = 1; + } + } + } + + const int _oc = ti->g_start * jcp.nb_oc + ti->oc_b_start; + const int _ic = ti->g_start * jcp.nb_ic + ti->ic_b_start; + jit_conv_3d_ker_bwd_w_pipeline(kernel_->jit_ker, p, + &ti->src[src_d.blk_off(img + 1, _ic)], + &ti->diff_dst[diff_dst_d.blk_off(img + 1, _oc)], + diff_wei + wht_blk_off(diff_weights_d, ti->g_start, + ti->oc_b_start, ti->ic_b_start), + diff_bia, 0, 0, 0, 0, 0); + nd_iterator_jump(img_start, img_end, img, jcp.mb, od_s, jcp.od); + } +} + +template +void jit_avx512_common_convolution_bwd_weights_t::reduce_diff_weights(const thread_info_t *ti) const { + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + + const auto &jcp = kernel_->jcp; + const int wei_size = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw; + const int bia_size = jcp.ngroups * jcp.oc; + const diff_weights_data_t *diff_bias_ws + = ti->wei_bia_reduction + (nthr_mb_ - 1) * wei_size; + + /* diff_weights[:] += sum(wei_reduction_[thr_mb][:]) */ + simple_barrier::barrier(ti->wei_bia_reduction_bctx, nthr_); + + const int ic_b_kh_work = ti->ic_b_work * jcp.kh; + const int work = ti->g_work * ti->oc_b_work * ic_b_kh_work; + + int start{0}, end{0}; + balance211(work, nthr_mb_, ti->ithr_mb, start, end); + if (start == end) return; + + for (int thr_mb = 1; thr_mb < nthr_mb_; ++thr_mb) { + int w = start; + int sub_g_start{0}, sub_oc_b_start{0}, sub_ic_b_kh_start{0}; + nd_iterator_init(w, sub_g_start, ti->g_work, sub_oc_b_start, + ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work); + while (w < end) { + const int g = ti->g_start + sub_g_start; + const int oc_b = ti->oc_b_start + sub_oc_b_start; + const int ic_b = ti->ic_b_start + sub_ic_b_kh_start / jcp.kh; + const int kh = sub_ic_b_kh_start % jcp.kh; + + const int acc_size + = nstl::min(end - w, ic_b_kh_work - sub_ic_b_kh_start) + * jcp.kw * jcp.ic_block * jcp.oc_block; + + const size_t off + = wht_blk_off(diff_weights_d, g, oc_b, ic_b, kh); + + diff_weights_data_t *d + = (diff_weights_data_t *)ti->diff_weights + off; + diff_weights_data_t *s + = ti->wei_bia_reduction + (thr_mb - 1) * wei_size + off; + + acc_ker_->accumulate(d, s, acc_size); + + nd_iterator_jump(w, end, sub_g_start, ti->g_work, sub_oc_b_start, + ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work); + } + + if (jcp.with_bias && jcp.is_1stconv && jcp.ver == ver_4fma) { + if (ti->ithr == 0) + acc_ker_->accumulate((diff_weights_data_t *)ti->diff_bias, + diff_bias_ws, bia_size); + diff_bias_ws += bia_size; + } + } +} + +template +void jit_avx512_common_convolution_bwd_weights_t::reduce_diff_weights_3d(const thread_info_t *ti) const { + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + + const auto &jcp = kernel_->jcp; + const int wei_size = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw + * jcp.kd; + + /* diff_weights[:] += sum(wei_reduction_[thr_mb][:]) */ + simple_barrier::barrier(ti->wei_bia_reduction_bctx, nthr_); + + const int ic_b_kh_work = ti->ic_b_work * jcp.kd; + const int work = ti->g_work * ti->oc_b_work * ic_b_kh_work; + + int start{0}, end{0}; + balance211(work, nthr_mb_, ti->ithr_mb, start, end); + if (start == end) return; + + for (int thr_mb = 1; thr_mb < nthr_mb_; ++thr_mb) { + int w = start; + int sub_g_start{0}, sub_oc_b_start{0}, sub_ic_b_kh_start{0}; + nd_iterator_init(w, sub_g_start, ti->g_work, sub_oc_b_start, + ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work); + while (w < end) { + const int g = ti->g_start + sub_g_start; + const int oc_b = ti->oc_b_start + sub_oc_b_start; + const int ic_b = ti->ic_b_start + sub_ic_b_kh_start / jcp.kd; + const int kd = sub_ic_b_kh_start % jcp.kd; + + const int acc_size + = nstl::min(end - w, ic_b_kh_work - sub_ic_b_kh_start) + * jcp.kw * jcp.ic_block * jcp.oc_block * jcp.kh; + + const size_t off + = wht_blk_off(diff_weights_d, g, oc_b, ic_b, kd); + diff_weights_data_t *d + = (diff_weights_data_t *)ti->diff_weights + off; + diff_weights_data_t *s + = ti->wei_bia_reduction + (thr_mb - 1) * wei_size + off; + acc_ker_->accumulate(d, s, acc_size); + + nd_iterator_jump(w, end, sub_g_start, ti->g_work, sub_oc_b_start, + ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work); + } + } +} + +template +void jit_avx512_common_convolution_bwd_weights_t::compute_diff_bias(const thread_info_t *ti) const { + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + + auto rb = this->reducer_bias_; + assert(nthr_ == rb->balancer().nthr_); + + const auto reducer_bia_scratchpad = memory_tracking::grantor_t( + ti->scratchpad, prefix_reducer_bia); + + const auto &jcp = kernel_->jcp; + + if (jcp.with_bias && jcp.is_1stconv && jcp.ver == ver_4fma) return; + + const int b_job_start = rb->balancer().ithr_job_off(ti->ithr); + const int b_njobs = rb->balancer().ithr_njobs(ti->ithr); + + if (b_njobs == 0) return; + + /* reduction dimension */ + int img_start{0}, img_end{0}; + balance211(jcp.mb, rb->balancer().nthr_per_group_, + rb->balancer().id_in_group(ti->ithr), img_start, img_end); + + /* jobs */ + int g_start{0}, ocb_start{0}; + nd_iterator_init(b_job_start, g_start, jcp.ngroups, ocb_start, jcp.nb_oc); + for (int img = img_start; img < img_end; ++img) { + int g = g_start, ocb = ocb_start; + for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) { + const size_t _oc = g * jcp.nb_oc + ocb; + + const diff_dst_data_t *d_dst + = &ti->diff_dst[diff_dst_d.blk_off(img, _oc)]; + diff_weights_data_t *d_bias = rb->get_local_ptr(ti->ithr, + ti->diff_bias, reducer_bia_scratchpad) + + b_job_loc * rb->balancer().job_size_; + + if (img == img_start) + for (int o = 0; o < 16; ++o) + d_bias[o] = 0; + for (int hw = 0; hw < jcp.oh * jcp.ow * jcp.od; ++hw) { + PRAGMA_OMP_SIMD() + for (int o = 0; o < 16; ++o) + d_bias[o] += d_dst[o]; + d_dst += 16; + } + + nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_oc); + } + } + + rb->reduce(ti->ithr, ti->diff_bias, reducer_bia_scratchpad); +} + +template +void jit_avx512_common_convolution_bwd_weights_t::compute_diff_bias_3d(const thread_info_t *ti) const { + + const auto &jcp = kernel_->jcp; + + const size_t wei_size = (size_t)jcp.ngroups * jcp.oc * jcp.ic * jcp.kh + * jcp.kw * jcp.kd; + const int bia_size = jcp.ngroups * jcp.oc; + const diff_weights_data_t *diff_bias_ws + = ti->wei_bia_reduction + (size_t)(nthr_mb_ - 1) * wei_size; + + if (nthr_mb_ > 1) mkldnn_thr_barrier(); + + if (ti->ithr == 0) + { + for (int thr_mb = 1; thr_mb < nthr_mb_; ++thr_mb) { + acc_ker_->accumulate(ti->diff_bias, diff_bias_ws, bia_size); + diff_bias_ws += bia_size; + } + } +} + +template +void jit_avx512_common_convolution_bwd_weights_t::prepare_scratchpad_data(const exec_ctx_t &ctx) const +{ + const auto &j = pd()->jcp_; + auto scratchpad = this->scratchpad(ctx); + + if (j.ver == ver_4fma) { + if (!j.is_1stconv) { + // XXX: See the comment about tr_iw and guarding elements in + // jit_avx512_common_conv_bwd_weights_kernel_f32::init_conf() + const int max_nthr = j.nthr_mb * j.ngroups * j.nb_ic; + const int min_tr_src_size_per_thr = j.ih * j.ic_block * j.tr_iw; + + auto tr_src = scratchpad.template get(key_conv_tr_src); + /* to avoid NaNs in computations we zero tail num_guard_elems for + * each possible thread group */ + + for (int ithr = 1; ithr <= max_nthr; ++ithr) { + src_data_t *ts = &tr_src[ithr * min_tr_src_size_per_thr]; + for (int i = 0; i < j.tr_src_num_guard_elems; ++i) + ts[i] = 0; + } + } + + if (j.nthr_oc_b > 1) { + const int tr_src_bctx_size = j.nthr / j.nthr_oc_b; + auto tr_src_bctx = scratchpad.template get( + key_conv_tr_src_bctx); + for (int i = 0; i < tr_src_bctx_size; ++i) + simple_barrier::ctx_init(&tr_src_bctx[i]); + } + } + + if (nthr_mb_ > 1) { + simple_barrier::ctx_init(scratchpad.template get( + key_conv_wei_bia_reduction_bctx)); + } + + const auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad, + prefix_reducer_bia); + auto rb = this->reducer_bias_; + rb->init(reducer_bia_scratchpad); +} + +template +void jit_avx512_common_convolution_bwd_weights_t::execute_backward_weights(const exec_ctx_t &ctx) const { + prepare_scratchpad_data(ctx); + + parallel(nthr_, [&](const int ithr, const int nthr) { + assert(nthr_ == nthr); + + thread_info_t thread_info(this, ctx, ithr); + + if (utils::one_of(pd()->ndims(), 3, 4)) { + compute_diff_weights(&thread_info); + if (nthr_mb_ > 1) reduce_diff_weights(&thread_info); + if (pd()->with_bias()) compute_diff_bias(&thread_info); + } else if (pd()->ndims() == 5) { + compute_diff_weights_3d(&thread_info); + if (nthr_mb_ > 1) reduce_diff_weights_3d(&thread_info); + if (pd()->with_bias()) compute_diff_bias_3d(&thread_info); + } else { + assert(false); + } + }); + + /* TODO: put that into compute_diff_bias() */ + if (pd()->wants_padded_bias()) { + auto diff_bias = scratchpad(ctx).template get( + key_conv_padded_bias); + auto diff_bias_in = CTX_OUT_MEM(diff_weights_data_t *, MKLDNN_ARG_DIFF_BIAS); + for (int oc = 0; oc < pd()->jcp_.oc_without_padding; ++oc) + diff_bias_in[oc] = diff_bias[oc]; + } +} + +template struct jit_avx512_common_convolution_bwd_weights_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp new file mode 100644 index 0000000000..3341c3ebe0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp @@ -0,0 +1,302 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_COMMON_CONVOLUTION_HPP +#define CPU_JIT_AVX512_COMMON_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_barrier.hpp" +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" +#include "cpu_reducer.hpp" + +#include "jit_transpose_src_utils.hpp" +#include "jit_avx512_common_conv_kernel.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_avx512_common_convolution_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""), + jit_avx512_common_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, wei_type, dst_type, dst_type, + data_type::undef) + && !has_zero_dim_memory(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx512_common_conv_fwd_kernel::init_conf( + jcp_, *desc(), src_md_, weights_md_, dst_md_, bias_md_, + *attr(), mkldnn_get_max_threads()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_common_conv_fwd_kernel::init_scratchpad(scratchpad, + jcp_); + + return status; + } + + jit_conv_conf_t jcp_; + }; + + jit_avx512_common_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + { + kernel_ = new jit_avx512_common_conv_fwd_kernel(pd()->jcp_, + *pd()->attr()); + } + ~jit_avx512_common_convolution_fwd_t() { delete kernel_; } + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + if (pd()->ndims() == 3) + execute_forward_1d(ctx); + else if (pd()->ndims() == 4) + execute_forward_2d(ctx); + else if (pd()->ndims() == 5) + execute_forward_3d(ctx); + else + assert(false); + + if (pd()->wants_zero_pad_dst()) + ctx.memory(MKLDNN_ARG_DST)->zero_pad(); + + return status::success; + } + +private: + void prepare_padded_bias(const dst_data_t *&bias, + const memory_tracking::grantor_t &scratchpad) const; + void execute_forward_1d(const exec_ctx_t &ctx) const; + void execute_forward_2d(const exec_ctx_t &ctx) const; + void execute_forward_3d(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_common_conv_fwd_kernel *kernel_; +}; + +template +struct jit_avx512_common_convolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""), + jit_avx512_common_convolution_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(diff_src_type, wei_type, + data_type::undef, diff_dst_type, data_type::undef) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = + jit_avx512_common_conv_bwd_data_kernel_f32::init_conf(jcp_, + *desc(), *diff_src_md(), *weights_md(), *diff_dst_md()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_common_conv_bwd_data_kernel_f32::init_scratchpad( + scratchpad, jcp_); + + return status::success; + } + + jit_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c); + auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(), + OIw16o16i, gOIw16o16i, OIhw16o16i, gOIhw16o16i, + OIdhw16o16i, gOIdhw16o16i); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + jit_avx512_common_convolution_bwd_data_t(const pd_t *apd) + : cpu_primitive_t(apd) + { kernel_ = new jit_avx512_common_conv_bwd_data_kernel_f32(pd()->jcp_); } + ~jit_avx512_common_convolution_bwd_data_t() { delete kernel_; }; + + typedef typename prec_traits::type diff_dst_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type diff_src_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + if (pd()->ndims() == 3) + execute_backward_data_1d(ctx); + else if (pd()->ndims() == 4) + execute_backward_data_2d(ctx); + else if (pd()->ndims() == 5) + execute_backward_data_3d(ctx); + else + assert(false); + return status::success; + } + +private: + void execute_backward_data_1d(const exec_ctx_t &ctx) const; + void execute_backward_data_2d(const exec_ctx_t &ctx) const; + void execute_backward_data_3d(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_common_conv_bwd_data_kernel_f32 *kernel_; +}; + +template +struct jit_avx512_common_convolution_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""), + jit_avx512_common_convolution_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, diff_weights_type, + diff_weights_type, diff_dst_type, data_type::undef) + && !has_zero_dim_memory(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx512_common_conv_bwd_weights_kernel_f32:: + init_conf(jcp_, *desc(), src_md_, diff_weights_md_, + diff_bias_md_, diff_dst_md_); + if (status != status::success) return status; + + init_balancers(); + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_common_conv_bwd_weights_kernel_f32::init_scratchpad( + scratchpad, jcp_); + + auto reducer_bia_scratchpad = memory_tracking::registrar_t( + scratchpad, memory_tracking::names::prefix_reducer_bia); + reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad); + + return status; + } + + jit_conv_conf_t jcp_; + typename cpu_reducer_t::conf_t reducer_bia_conf_; + + private: + void init_balancers() { + const size_t max_buffer_size = jcp_.nthr * 3 * 5 * 5 * 16 * 16; + if (with_bias()) { + reducer_bia_conf_.init(reduce_balancer_t(jcp_.nthr, + jcp_.oc_block, jcp_.ngroups * jcp_.nb_oc, jcp_.mb, + max_buffer_size)); + } + } + }; + + jit_avx512_common_convolution_bwd_weights_t(const pd_t *apd); + ~jit_avx512_common_convolution_bwd_weights_t() { + delete kernel_; + if (trans_kernel_) + delete trans_kernel_; + if (acc_ker_) + delete acc_ker_; + delete reducer_bias_; + } + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type diff_dst_data_t; + typedef typename prec_traits::type diff_weights_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + void prepare_scratchpad_data(const exec_ctx_t &ctx) const; + struct thread_info_t; + void compute_diff_weights(const thread_info_t *) const; + void compute_diff_weights_3d(const thread_info_t *) const; + void reduce_diff_weights(const thread_info_t *) const; + void reduce_diff_weights_3d(const thread_info_t *) const; + void compute_diff_bias(const thread_info_t *) const; + void compute_diff_bias_3d(const thread_info_t *) const; + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + int nthr_, nthr_mb_, nthr_g_, nthr_oc_b_, nthr_ic_b_; + + jit_avx512_common_conv_bwd_weights_kernel_f32 *kernel_; + jit_trans_src_t *trans_kernel_; + cpu_accumulator_1d_t *acc_ker_; + cpu_reducer_t *reducer_bias_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp new file mode 100644 index 0000000000..62247c0264 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp @@ -0,0 +1,1215 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifdef __INTEL_COMPILER +#include +#endif + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx512_common_convolution_winograd.hpp" + +#ifndef _MSC_VER +#define pragma_unroll _Pragma("unroll") +#else +#define pragma_unroll +#endif + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace memory_tracking::names; + +namespace { + +unsigned int LLC_cache_size = get_cache_size(3, false); + +void inline load_ps(float *dest, const float *src_mem) { +#ifdef __INTEL_COMPILER + __m512 *Iv512 = (__m512 *)dest; + Iv512[0] = _mm512_load_ps(src_mem); +#else + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) dest[v] = src_mem[v]; +#endif +} + +void inline store_output(float *dest, const float *data, bool streamout) { +#ifdef __INTEL_COMPILER + if (streamout) + _mm512_stream_ps(dest, *((__m512 *)data)); + else + _mm512_store_ps(dest, *((__m512 *)data)); +#else + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) + dest[v] = data[v]; +#endif +} + +void inline accum_output( + float *dest, float *data, bool streamout, bool with_relu_postsum) { +#ifdef __INTEL_COMPILER + __m512 _data = _mm512_loadu_ps(data); + __m512 _dest = _mm512_loadu_ps(dest); + _data = _mm512_add_ps(_data, _dest); + if (with_relu_postsum) + _data = _mm512_max_ps(_data, _mm512_setzero_ps()); + if (streamout) + _mm512_stream_ps(dest, _data); + else + _mm512_store_ps(dest, _data); +#else + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) + data[v] += dest[v]; + + if (with_relu_postsum) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) + if (data[v] < 0.f) + data[v] = 0.f; + } + + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) + dest[v] = data[v]; +#endif +} +} + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::utils; + +void trans_W_4x4_3x3(float Fw_[6][6][16][16], float F[3][3][16][16]) { + float Fw[6][16]; + float T[6][3][16]; + float t0[16]; + float t1[16]; + float t2[16]; + + for (int j = 0; j < 16; j++) { +#pragma unroll + for (int i = 0; i < 3; i++) { + PRAGMA_OMP_SIMD() + for (int k = 0; k < 16; k++) { + t0[k] = 0.26890756302521f * F[2][i][j][k]; + t1[k] = -t0[k] - 0.688403361344538f * F[0][i][j][k]; + t2[k] = t0[k] + 0.119514472455649f * F[0][i][j][k]; + + T[0][i][k] = 1.13777777777778f * F[0][i][j][k]; + T[1][i][k] = t1[k] - 0.430252100840336f * F[1][i][j][k]; + T[2][i][k] = t1[k] + 0.430252100840336f * F[1][i][j][k]; + T[3][i][k] = t2[k] + 0.179271708683473f * F[1][i][j][k]; + T[4][i][k] = t2[k] - 0.179271708683473f * F[1][i][j][k]; + T[5][i][k] = F[2][i][j][k]; + } + } +#pragma unroll + for (int i = 0; i < 6; i++) { + PRAGMA_OMP_SIMD() + for (int k = 0; k < 16; k++) { + t0[k] = 0.26890756302521f * T[i][2][k]; + t1[k] = -t0[k] - 0.688403361344538f * T[i][0][k]; + t2[k] = t0[k] + 0.119514472455649f * T[i][0][k]; + + Fw[0][k] = 1.13777777777778f * T[i][0][k]; + Fw[1][k] = t1[k] - 0.430252100840336f * T[i][1][k]; + Fw[2][k] = t1[k] + 0.430252100840336f * T[i][1][k]; + Fw[3][k] = t2[k] + 0.179271708683473f * T[i][1][k]; + Fw[4][k] = t2[k] - 0.179271708683473f * T[i][1][k]; + Fw[5][k] = T[i][2][k]; +#pragma unroll + for (int l = 0; l < 6; l++) { + Fw_[i][l][j][k] = Fw[l][k]; + } + } + } + } +} + +void trans_O_4x4_3x3(float Mw[6][6][16], float O[4][4][16]) { + float T[4][6][16]; + float t0[16]; + float t1[16]; + float t2[16]; + float t3[16]; + +#pragma unroll + for (int i = 0; i < 6; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + t0[v] = Mw[1][i][v] + Mw[2][i][v]; + t1[v] = Mw[3][i][v] + Mw[4][i][v]; + t2[v] = Mw[1][i][v] - Mw[2][i][v]; + t3[v] = Mw[3][i][v] - Mw[4][i][v]; + + T[0][i][v] = t0[v] + t1[v] + Mw[0][i][v]; + T[1][i][v] = t2[v] * 0.625f + t3[v] * 1.5f; + T[2][i][v] = t0[v] * 0.390625f + t1[v] * 2.25f; + T[3][i][v] = t2[v] * 0.244140625f + t3[v] * 3.375f + Mw[5][i][v]; + } + } +#pragma unroll + for (int i = 0; i < 4; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + t0[v] = T[i][1][v] + T[i][2][v]; + t1[v] = T[i][3][v] + T[i][4][v]; + t2[v] = T[i][1][v] - T[i][2][v]; + t3[v] = T[i][3][v] - T[i][4][v]; + + O[i][0][v] = t0[v] + t1[v] + T[i][0][v]; + O[i][1][v] = t2[v] * 0.625f + t3[v] * 1.5f; + O[i][2][v] = t0[v] * 0.390625f + t1[v] * 2.25f; + O[i][3][v] = t2[v] * 0.244140625f + t3[v] * 3.375f + T[i][5][v]; + } + } +} + + +void trans_W_3x3_4x4(float Fw[6][6][16], float F[4][6][16]) +{ + const float rcp3 = 1.0f / 3.0f; + const float rcp4 = 1.0f / 4.0f; + const float rcp6 = 1.0f / 6.0f; + const float rcp12 = 1.0f / 12.0f; + const float rcp24 = 1.0f / 24.0f; + float t0[16]; + float t1[16]; + float t2[16]; + float t3[16]; + float t4[16]; + float T[6][4][16]; + +pragma_unroll + for (int i = 0; i < 4; i++) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < 16; j++) { + t0[j] = F[2][i][j] * rcp6; + t1[j] = F[0][i][j] * -rcp6 - t0[j]; + t2[j] = F[0][i][j] * rcp24 + t0[j]; + t3[j] = (F[1][i][j] + F[3][i][j]) * rcp6; + t4[j] = F[1][i][j] * rcp12 + F[3][i][j] * rcp3; + + T[0][i][j] = F[0][i][j] * rcp4; + T[1][i][j] = t1[j] - t3[j]; + T[2][i][j] = t1[j] + t3[j]; + T[3][i][j] = t2[j] + t4[j]; + T[4][i][j] = t2[j] - t4[j]; + T[5][i][j] = F[3][i][j]; + } + } +pragma_unroll + for (int i = 0; i < 6; i++) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < 16; j++) { + t0[j] = T[i][2][j] * rcp6; + t1[j] = T[i][0][j] * -rcp6 - t0[j]; + t2[j] = T[i][0][j] * rcp24 + t0[j]; + t3[j] = (T[i][1][j] + T[i][3][j]) * rcp6; + t4[j] = T[i][1][j] * rcp12 + T[i][3][j] * rcp3; + + Fw[i][0][j] = T[i][0][j] * rcp4; + Fw[i][1][j] = t1[j] - t3[j]; + Fw[i][2][j] = t1[j] + t3[j]; + Fw[i][3][j] = t2[j] + t4[j]; + Fw[i][4][j] = t2[j] - t4[j]; + Fw[i][5][j] = T[i][3][j]; + } + } +} + +void trans_O_3x3_4x4(float Mw[6][6][16][16], float M[3][3][16][16]) +{ + float T[4][6][16]; + float M_[3][16]; + float t0[16]; + float t1[16]; + float t2[16]; + + for (int j = 0; j < 16; j++) { +pragma_unroll + for (int i = 0; i < 6; i++) { + PRAGMA_OMP_SIMD() + for (int l = 0; l < 16; l++) { + t0[l] = Mw[1][i][j][l] + Mw[2][i][j][l]; + t1[l] = Mw[3][i][j][l] + Mw[4][i][j][l]; + t2[l] = t1[l] * 4.0f + Mw[5][i][j][l]; + + T[0][i][l] = Mw[0][i][j][l] + t0[l] + t1[l]; + T[1][i][l] = (Mw[1][i][j][l] - Mw[2][i][j][l]) + + 2.0f * (Mw[3][i][j][l] - Mw[4][i][j][l]); + T[2][i][l] = t0[l] + t2[l]; + } + } +pragma_unroll + for (int i = 0; i < 3; i++) { + PRAGMA_OMP_SIMD() + for (int l = 0; l < 16; l++) { + t0[l] = T[i][1][l] + T[i][2][l]; + t1[l] = T[i][3][l] + T[i][4][l]; + t2[l] = t1[l] * 4.0f + T[i][5][l]; + + M_[0][l] = T[i][0][l] + t0[l] + t1[l]; + M_[1][l] = (T[i][1][l] - T[i][2][l]) + + 2.0f * (T[i][3][l] - T[i][4][l]); + M_[2][l] = t0[l] + t2[l]; + + for (int k = 0; k < 3; k++) { + M[i][k][j][l] = M_[k][l]; + } + } + } + } +} + +void trans_I_4x4_3x3(float Iw[6][6][16], float I[6][6][16]) +{ + float T[6][6][16]; + float t0[16]; + float t1[16]; + float t2[16]; + float t3[16]; + float t4[16]; + float t5[16]; + +pragma_unroll + for (int i = 0; i < 6; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + t0[v] = I[2][i][v] * -2.25f + I[4][i][v]; + t1[v] = I[1][i][v] * -2.25f + I[3][i][v]; + t2[v] = I[2][i][v] * -0.390625f + I[4][i][v]; + t3[v] = I[1][i][v] * -0.390625f + I[3][i][v]; + t4[v] = I[0][i][v] * 0.87890625f + I[4][i][v]; + t5[v] = I[1][i][v] * 0.87890625f + I[5][i][v]; + + T[0][i][v] = I[2][i][v] * -2.640625f + t4[v]; + T[1][i][v] = t1[v] * 0.625f + t0[v]; + T[2][i][v] = t1[v] * -0.625f + t0[v]; + T[3][i][v] = t3[v] * 1.5f + t2[v]; + T[4][i][v] = t3[v] * -1.5f + t2[v]; + T[5][i][v] = I[3][i][v] * -2.640625f + t5[v]; + } + } + +pragma_unroll + for (int i = 0; i < 6; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + t0[v] = T[i][2][v] * -2.25f + T[i][4][v]; + t1[v] = T[i][1][v] * -2.25f + T[i][3][v]; + t2[v] = T[i][2][v] * -0.390625f + T[i][4][v]; + t3[v] = T[i][1][v] * -0.390625f + T[i][3][v]; + t4[v] = T[i][0][v] * 0.87890625f + T[i][4][v]; + t5[v] = T[i][1][v] * 0.87890625f + T[i][5][v]; + + Iw[i][0][v] = T[i][2][v] * -2.640625f + t4[v]; + Iw[i][1][v] = t1[v] * 0.625f + t0[v]; + Iw[i][2][v] = t1[v] * -0.625f + t0[v]; + Iw[i][3][v] = t3[v] * 1.5f + t2[v]; + Iw[i][4][v] = t3[v] * -1.5f + t2[v]; + Iw[i][5][v] = T[i][3][v] * -2.640625f + t5[v]; + } + } +} + +void trans_W_3x3_4x4_wu(float Fw[6][6][16], float F[4][6][16]) +{ + float T[6][4][16]; + float t0[16]; + float t1[16]; + float t2[16]; + float t3[16]; + float t4[16]; + +pragma_unroll + for (int i = 0; i < 4; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + t0[v] = F[2][i][v] * 0.26890756302521f; + t1[v] = F[0][i][v] * -0.688403361344538f - t0[v]; + t2[v] = F[0][i][v] * 0.119514472455649f + t0[v]; + t3[v] = F[1][i][v] * 0.430252100840336f + + F[3][i][v] * 0.168067226890756f; + t4[v] = F[1][i][v] * 0.179271708683473f + + F[3][i][v] * 0.403361344537815f; + + T[0][i][v] = F[0][i][v] * 1.13777777777778f; + T[1][i][v] = t1[v] - t3[v]; + T[2][i][v] = t1[v] + t3[v]; + T[3][i][v] = t2[v] + t4[v]; + T[4][i][v] = t2[v] - t4[v]; + T[5][i][v] = F[3][i][v]; + } + } +pragma_unroll + for (int i = 0; i < 6; i++) { + for (int v = 0; v < 16; v++) { + t0[v] = T[i][2][v] * 0.26890756302521f; + t1[v] = T[i][0][v] * -0.688403361344538f - t0[v]; + t2[v] = T[i][0][v] * 0.119514472455649f + t0[v]; + t3[v] = T[i][1][v] * 0.430252100840336f + + T[i][3][v] * 0.168067226890756f; + t4[v] = T[i][1][v] * 0.179271708683473f + + T[i][3][v] * 0.403361344537815f; + + Fw[i][0][v] = T[i][0][v] * 1.13777777777778f; + Fw[i][1][v] = t1[v] - t3[v]; + Fw[i][2][v] = t1[v] + t3[v]; + Fw[i][3][v] = t2[v] + t4[v]; + Fw[i][4][v] = t2[v] - t4[v]; + Fw[i][5][v] = T[i][3][v]; + } + } +} + +void trans_O_3x3_4x4_wu(float Mw[6][6][16][16], float M[3][3][16][16]) +{ + float T[3][6][16]; + float t0[16]; + float t1[16]; + float t2[16]; + float M_[3][16]; + + for (int j = 0; j < 16; j++) { +pragma_unroll + for (int i = 0; i < 6; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + t0[v] = Mw[1][i][j][v] + Mw[2][i][j][v]; + t1[v] = Mw[3][i][j][v] + Mw[4][i][j][v]; + t2[v] = t1[v] * 2.25f + Mw[5][i][j][v]; + + T[0][i][v] = Mw[0][i][j][v] + t0[v] + t1[v]; + T[1][i][v] = 0.625f * (Mw[1][i][j][v] - Mw[2][i][j][v]) + + 1.5f * (Mw[3][i][j][v] - Mw[4][i][j][v]); + T[2][i][v] = t0[v] * 0.390625f + t2[v]; + } + } +pragma_unroll + for (int i = 0; i < 3; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + t0[v] = T[i][1][v] + T[i][2][v]; + t1[v] = T[i][3][v] + T[i][4][v]; + t2[v] = t1[v] * 2.25f + T[i][5][v]; + + M_[0][v] = T[i][0][v] + t0[v] + t1[v]; + M_[1][v] = 0.625f * (T[i][1][v] - T[i][2][v]) + + 1.5f * (T[i][3][v] - T[i][4][v]); + M_[2][v] = t0[v] * 0.390625f + t2[v]; + } + +pragma_unroll + for (int k = 0; k < 3; k++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < 16; v++) { + M[i][k][j][v] = M_[k][v]; + } + } + } + } +} + +template +void input_transform_data(int image, const jit_conv_winograd_conf_t &jcp, + float *inp, float *tinp, bool streamout = true) +{ + const int inpw = is_fwd ? jcp.iw : jcp.ow; + const int inph = is_fwd ? jcp.ih : jcp.oh; + const int l_pad = is_fwd ? jcp.l_pad : jcp.iw + jcp.r_pad - jcp.ow; + const int t_pad = is_fwd ? jcp.t_pad : jcp.ih + jcp.t_pad - jcp.oh; + const int wp_max = inpw + l_pad; + const int hp_max = inph + t_pad; + float Iw[alpha][alpha][simd_w]; + float I[alpha][alpha][simd_w]; + + array_offset_calculator input(inp, + jcp.mb, jcp.dimK/simd_w, inph, inpw, + simd_w); + array_offset_calculator output(tinp, + jcp.dimN_nb_block, alpha, alpha, + jcp.dimN_block, jcp.dimK_nb_block, jcp.dimK_block, + jcp.dimN_reg_block, jcp.dimK_reg_block); + + int tile_base_index = image * jcp.itiles * jcp.jtiles; + int tile_block_ur = tile_base_index % jcp.tile_block_ur; + int nb_tile_block_ur = + (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur; + int tile_block = + (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur; + + for (int tj = 0; tj < jcp.jtiles; tj++) { + for (int ti = 0; ti < jcp.itiles; ti++) { + for (int j = 0; j < alpha; j++) { + int ydim = tj * tile_size + j; + if ((t_pad <= ydim) && (ydim < hp_max)) { + float *pinp_j = inp + (ydim - t_pad) * inpw * 16 ; + for (int i = 0; i < alpha; i++) { + int xdim = ti * tile_size + i; + if ((l_pad <= xdim) && (xdim < wp_max)) { + float *pinp_i = pinp_j + (xdim - l_pad) * 16; + load_ps(I[j][i], pinp_i); + } else { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = 0.0f; + } + } + } + } else { + for (int i = 0; i < alpha; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = 0.0f; + } + } + } + } + + trans_I_4x4_3x3(Iw, I); + + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + store_output(&(output(tile_block, j, i, + nb_tile_block_ur, 0, 0, + tile_block_ur, 0)), + Iw[j][i], streamout); + } + } + tile_block_ur++; + if (tile_block_ur >= jcp.tile_block_ur) { + tile_block_ur = 0; + nb_tile_block_ur++; + } + if (nb_tile_block_ur >= jcp.nb_tile_block_ur) { + nb_tile_block_ur = 0; + tile_block++; + } + } + } +} + +template +void weight_transform_data(const jit_conv_winograd_conf_t &jcp, + float *wp, float *twp) +{ + const int kh = 3; + const int kw = 3; + array_offset_calculator input(wp, + jcp.oc/jcp.oc_simd_block, + jcp.ic/jcp.ic_simd_block, + jcp.kh, jcp.kw, + simd_w, simd_w); + array_offset_calculator output(twp, + jcp.dimM_nb_block, + alpha, alpha, + jcp.dimK_nb_block, + jcp.dimM_block, jcp.dimK_block, + simd_w, simd_w); + float Fw[alpha][alpha][simd_w][simd_w]; + float F[kh][kw][simd_w][simd_w]; + + for (int j = 0; j < kh; j++) { + for (int i = 0; i < kw; i++) { + for (int v1 = 0; v1 < simd_w; v1++) { + float *base_inp = is_fwd + ? &(input(0, 0, j, i, v1, 0)) + : &(input(0, 0, 2 - j, 2 - i, v1, 0)); + PRAGMA_OMP_SIMD() + for (int v2 = 0; v2 < simd_w; v2++) { + if (is_fwd) + F[j][i][v1][v2] = *(base_inp + v2); + else + F[j][i][v2][v1] = *(base_inp + v2); + } + } + } + } + + trans_W_4x4_3x3(Fw, F); + + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + for (int v1 = 0; v1 < simd_w; v1++) { + PRAGMA_OMP_SIMD() + for (int v2 = 0; v2 < simd_w; v2++) { + output(0, j, i, 0, 0, 0, v1, v2) = Fw[j][i][v1][v2]; + } + } + } + } +} + +template +void output_transform_data(int image, const jit_conv_winograd_conf_t &jcp, + const post_ops_t &p_ops, float *toutp, float *pout_b, float *bias, + bool streamout = true) { + float Ow[alpha][alpha][simd_w]; + float O[tile_size][tile_size][simd_w]; + int outw = is_fwd ? jcp.ow : jcp.iw; + int outh = is_fwd ? jcp.oh : jcp.ih; + + /* Prepare for PostOps */ + bool with_relu_postsum = p_ops.find(primitive_kind::eltwise, 1) != -1; + + array_offset_calculator input(toutp, + jcp.dimN_nb_block, jcp.dimM_nb_block, + alpha, alpha, + jcp.dimN_block, jcp.dimM_block, + jcp.dimN_reg_block, jcp.dimM_simd_block); + + int tile_base_index = image * jcp.itiles * jcp.jtiles; + int tile_block_ur = tile_base_index % jcp.tile_block_ur; + int nb_tile_block_ur = + (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur; + int tile_block = + (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur; + + for (int tj = 0; tj < jcp.jtiles; tj++) { + for (int ti = 0; ti < jcp.itiles; ti++) { + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + Ow[j][i][v] = input(tile_block, 0, + j, i, + nb_tile_block_ur, 0, + tile_block_ur, v); + } + } + } + + trans_O_4x4_3x3(Ow, O); + + for (int j = 0; j < tile_size; j++) { + int ydim = tj * tile_size + j; + if (ydim < outh) { + float *pout_j = pout_b + ydim * outw * simd_w; + for (int i = 0; i < tile_size; i++) { + int xdim = ti * tile_size + i; + if (xdim < outw) { + float *pout_i = pout_j + xdim * simd_w; + if (is_fwd) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + O[j][i][v] += with_bias ? bias[v] : 0.f; + O[j][i][v] = true + && with_relu_presum && O[j][i][v] < 0.f + ? O[j][i][v] + * jcp.eltwise.alpha + : O[j][i][v]; + } + } + if (with_sum) + accum_output(pout_i, O[j][i], streamout, + with_relu_postsum); + else + store_output(pout_i, O[j][i], streamout); + } + } + } + } + tile_block_ur++; + if (tile_block_ur >= jcp.tile_block_ur) { + tile_block_ur = 0; + nb_tile_block_ur++; + } + if (nb_tile_block_ur >= jcp.nb_tile_block_ur) { + nb_tile_block_ur = 0; + tile_block++; + } + } + } +} + +template +void diff_src_transform_bwd_weights(int image, jit_conv_winograd_conf_t conv, + float *inp, float *tinp, float *Iw_temp, + void (*transpose_4fma_ker)(float *, float *)) +{ + + const int ifwp = conv.iw + conv.l_pad; + const int ifhp = conv.ih + conv.t_pad; + float I[alpha][alpha][simd_w]; + float Iw[alpha][alpha][simd_w]; + + array_offset_calculator Iw_trans_temp(Iw_temp, + alpha, alpha, conv.tile_4fma, simd_w); + array_offset_calculator input(inp, + conv.mb, conv.ic/simd_w, conv.ih, conv.iw, simd_w); + array_offset_calculator output(tinp, + conv.nb_ic, alpha, alpha, + conv.tile_block, conv.ic_block, + conv.nb_tile_block_ur, conv.tile_block_ur, + conv.ic_simd_block * conv.tile_4fma); + + int tile_base_index = + image * (conv.itiles * conv.jtiles + conv.tile_4fma_padding); + int tile_4fma = 0; + int tile_block_ur = (tile_base_index / conv.tile_4fma) % conv.tile_block_ur; + int nb_tile_block_ur = + (tile_base_index / conv.tile_4fma / conv.tile_block_ur) + % conv.nb_tile_block_ur; + int tile_block = (tile_base_index / conv.tile_4fma / conv.tile_block_ur) + / conv.nb_tile_block_ur; + + for (int tj = 0; tj < conv.jtiles; tj++) { + for (int ti = 0; ti < conv.itiles; ti++) { + for (int j = 0; j < alpha; j++) { + int ydim = tj * tile_size + j; + if ((conv.t_pad <= ydim) && ydim < ifhp) { + for (int i = 0; i < alpha; i++) { + int xdim = ti * tile_size + i; + if ((conv.l_pad <= xdim) && xdim < ifwp) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = input(0, 0, + ydim - conv.t_pad, + xdim - conv.l_pad, v); + } + } else { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = 0.0f; + } + } + } + } else { + for (int i = 0; i < alpha; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = 0.0f; + } + } + } + } + trans_I_4x4_3x3(Iw, I); + + if (ver_4fma) { + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + float *Iw_temp_base = &(Iw_trans_temp(j, i, + tile_4fma, 0)); + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + Iw_temp_base[v] = Iw[j][i][v]; + } + } + } + tile_4fma++; + if (tile_4fma == conv.tile_4fma) { + float *outp = &(output(0, 0, 0, + tile_block, 0, + nb_tile_block_ur, tile_block_ur, 0)); + transpose_4fma_ker(outp, (float *)Iw_temp); + tile_4fma = 0; + tile_block_ur++; + } + } else { + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + store_output(&(output(0, j, i, + tile_block, 0, + nb_tile_block_ur, tile_block_ur, 0)), + Iw[j][i], true); + } + } + tile_block_ur++; + } + + if (tile_block_ur == conv.tile_block_ur) { + tile_block_ur = 0; + ++nb_tile_block_ur; + } + if (nb_tile_block_ur == conv.nb_tile_block_ur) { + nb_tile_block_ur = 0; + tile_block++; + } + } + } + + if (ver_4fma && tile_4fma < conv.tile_4fma && conv.tile_4fma_padding != 0) { + + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + for (int tb = tile_4fma; tb < conv.tile_4fma; tb++) { + float *Iw_temp_base = &(Iw_trans_temp(j, i, tb, 0)); + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + Iw_temp_base[v] = 0; + } + } + } + } + float *outp = &(output(0, 0, 0, + tile_block, 0, + nb_tile_block_ur, tile_block_ur, 0)); + transpose_4fma_ker(outp, (float *)Iw_temp); + } +} + +template +void diff_dst_transform_bwd_weights(int image, jit_conv_winograd_conf_t conv, + float *inp, float *tinp, float *dbias) +{ + + const int total_tiles = conv.itiles * conv.jtiles + conv.tile_4fma_padding; + float I[alpha][alpha][simd_w]; + float Iw[alpha][alpha][simd_w]; + + array_offset_calculator input(inp, + conv.mb, conv.oc/simd_w, conv.oh, conv.ow, conv.oc_simd_block); + array_offset_calculator output(tinp, + conv.nb_oc, alpha, alpha, + conv.tile_block, conv.oc_block, + conv.nb_tile_block_ur, + conv.tile_block_ur * conv.tile_4fma, conv.oc_simd_block); + + int tile_base_index = image * total_tiles; + int tile_block_ur = tile_base_index % (conv.tile_block_ur * conv.tile_4fma); + int nb_tile_block_ur = + (tile_base_index / conv.tile_block_ur / conv.tile_4fma) + % conv.nb_tile_block_ur; + int tile_block = (tile_base_index / conv.tile_block_ur / conv.tile_4fma) + / conv.nb_tile_block_ur; + + for (int tj = 0; tj < conv.jtiles; tj++) { + for (int ti = 0; ti < conv.itiles; ti++) { + for (int j = 0; j < alpha; j++) { + int ydim = tj * tile_size + j; + if (ydim < conv.oh) { + for (int i = 0; i < alpha; i++) { + int xdim = ti * tile_size + i; + if (xdim < conv.ow) { + float *input_base = &(input(0, 0, ydim, xdim, 0)); + + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = input_base[v]; + } + if (with_bias && j < tile_size && i < tile_size) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + dbias[v] += input_base[v]; + } + } + } else { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = 0.0f; + } + } + } + } else { + for (int i = 0; i < alpha; i++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + I[j][i][v] = 0.0f; + } + } + } + } + + trans_W_3x3_4x4_wu(Iw, I); + + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + store_output(&(output(0, j, i, + tile_block, 0, + nb_tile_block_ur, + tile_block_ur, 0)), + Iw[j][i], true); + } + } + tile_block_ur++; + if (tile_block_ur >= conv.tile_block_ur * conv.tile_4fma) { + tile_block_ur = 0; + nb_tile_block_ur++; + } + if (nb_tile_block_ur >= conv.nb_tile_block_ur) { + nb_tile_block_ur = 0; + tile_block++; + } + } + } +} + +void diff_weights_transform_bwd_weights(jit_conv_winograd_conf_t conv, + float *wp, float *twp) +{ + const int kh = 3; + const int kw = 3; + float Fw[alpha][alpha][simd_w][simd_w]; + float F[kh][kw][simd_w][simd_w]; + + array_offset_calculator input(twp, + conv.nb_ic, conv.nb_oc, + alpha, alpha, + conv.oc_block, conv.ic_block, + conv.ic_simd_block, conv.oc_simd_block); + array_offset_calculator output(wp, + conv.oc/simd_w, conv.ic/simd_w, + conv.kh, conv.kw, + conv.ic_simd_block, conv.oc_simd_block); + + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + for (int v = 0; v < conv.ic_simd_block; v++) { + PRAGMA_OMP_SIMD() + for (int k = 0; k < conv.oc_simd_block; k++) { + Fw[j][i][v][k] = input(0, 0, j, i, 0, 0, v, k); + } + } + } + } + + trans_O_3x3_4x4_wu(Fw, F); + + for (int j = 0; j < kh; j++) { + for (int i = 0; i < kw; i++) { + for (int v = 0; v < conv.ic_simd_block; v++) { + store_output(&(output(0, 0, j, i, v, 0)), + F[j][i][v], true); + } + } + } +} + +template +void _jit_avx512_common_convolution_winograd_t::_execute_data_W_S_G_D( + float *inp_ptr, float *out_ptr, float *wei_ptr, float *bias_ptr, + const memory_tracking::grantor_t &scratchpad) const { + const auto &jcp = kernel_->jcp; + const auto &p_ops = attr_->post_ops_; + + const int inph = is_fwd ? jcp.ih : jcp.oh; + const int inpw = is_fwd ? jcp.iw : jcp.ow; + const int outh = is_fwd ? jcp.oh : jcp.ih; + const int outw = is_fwd ? jcp.ow : jcp.iw; + + /* Note that jcp.with_eltwise is true for both fused conv+relu primitive + * and conv primitive with PostOps with relu before sum + * (PostOps relu after sum is handled later) */ + auto output_transform = jcp.with_bias + ? (jcp.with_eltwise + ? (jcp.with_sum + ? output_transform_data + : output_transform_data) + : (jcp.with_sum + ? output_transform_data + : output_transform_data)) + : (jcp.with_eltwise + ? (jcp.with_sum + ? output_transform_data + : output_transform_data) + : (jcp.with_sum + ? output_transform_data + : output_transform_data)); + + /* Notation: + FWD: dimM:oc, dimN:ntiles, dimK:ic, + BWD: dimM:ic, dimN:ntiles, dimK:oc, + FWD/BWD: V: src/diff_dst transform, U:weight transform, + M:dst/diff_src transform */ + array_offset_calculator input(inp_ptr, + jcp.mb, jcp.dimK/jcp.dimK_reg_block, inph, inpw, + jcp.dimK_reg_block); + array_offset_calculator output(out_ptr, + jcp.mb, jcp.dimM/jcp.dimM_simd_block, outh, outw, + jcp.dimM_simd_block); + array_offset_calculator weights(wei_ptr, + jcp.oc/jcp.oc_simd_block, jcp.ic/jcp.ic_simd_block, jcp.kh, jcp.kw, + jcp.ic_simd_block, jcp.oc_simd_block); + array_offset_calculator bias(bias_ptr, + jcp.dimM/jcp.dimM_simd_block, jcp.dimM_simd_block); + + array_offset_calculator M(is_fwd + ? scratchpad.template get(key_wino_M) + : scratchpad.template get(key_wino_V), + jcp.dimN_nb_block, jcp.dimM_nb_block, + alpha, alpha, + jcp.dimN_block, jcp.dimM_block, + jcp.dimN_reg_block, jcp.dimM_simd_block); + array_offset_calculator U( + scratchpad.template get(key_wino_U), + jcp.dimM_nb_block, + alpha, alpha, + jcp.dimK_nb_block, + jcp.dimM_block, jcp.dimK_block, + jcp.dimK_reg_block, jcp.dimM_simd_block); + array_offset_calculator V(is_fwd + ? scratchpad.template get(key_wino_V) + : scratchpad.template get(key_wino_M), + jcp.dimN_nb_block, alpha, alpha, + jcp.dimN_block, jcp.dimK_nb_block, + jcp.dimK_block, jcp.dimN_reg_block, jcp.dimK_reg_block); + + bool V_streamout = jcp.dimN * jcp.dimK * alpha * alpha * sizeof(float) + > 2 * LLC_cache_size ? true : false; + + const bool output_is_aligned = ((size_t)out_ptr & (64 - 1)) == 0; + + const bool wants_padded_bias = jcp.with_bias + && jcp.oc_without_padding != jcp.oc; + float last_slice_bias[simd_w] = {0}; + if (wants_padded_bias) { + for (int oc = 0; oc < jcp.oc_without_padding % jcp.oc_simd_block; ++oc) + last_slice_bias[oc] = bias(jcp.dimM / jcp.dimM_simd_block - 1, oc); + } + + { + parallel_nd(jcp.mb, jcp.dimK_nb_block, jcp.dimK_block, + [&](int img, int K_blk1, int K_blk2) { + input_transform_data(img, jcp, + &(input(img, K_blk1 * jcp.dimK_block + K_blk2, 0, 0, 0)), + &(V(0, 0, 0, 0, K_blk1, K_blk2, 0, 0)), V_streamout); + }); + + parallel_nd(jcp.nb_oc, jcp.nb_ic, jcp.oc_block, jcp.ic_block, + [&](int ofm1, int ifm1, int ofm2, int ifm2) { + float *U_base_ptr = is_fwd + ? &(U(ofm1, 0, 0, ifm1, ofm2, ifm2, 0, 0)) + : &(U(ifm1, 0, 0, ofm1, ifm2, ofm2, 0, 0)); + weight_transform_data(jcp, + &(weights(ofm1 * jcp.oc_block + ofm2, + ifm1 * jcp.ic_block + ifm2, 0, 0, 0, 0)), U_base_ptr); + }); + + parallel_nd(jcp.dimN_nb_block, alpha, alpha, jcp.dimM_nb_block, jcp.dimN_block, + [&](int N_blk1, int oj, int oi, int M_blk1, int N_blk2) { + + kernel_->gemm_loop_ker_first_iter( + (float *)&(M(N_blk1, M_blk1, oj, oi, + N_blk2, 0, 0, 0)), + (const float *)&(U(M_blk1, oj, oi, + 0, 0, 0, 0, 0)), + (const float *)&(V(N_blk1, oj, oi, + N_blk2, 0, 0, 0, 0))); + for (int K_blk1 = 1; K_blk1 < jcp.dimK_nb_block; K_blk1++) { + kernel_->gemm_loop_ker( + (float *)&(M(N_blk1, M_blk1, oj, oi, + N_blk2, 0, 0, 0)), + (const float *)&(U(M_blk1, oj, oi, + K_blk1, 0, 0, 0, 0)), + (const float *)&(V(N_blk1, oj, oi, + N_blk2, K_blk1, + 0, 0, 0))); + } + + }); + + parallel_nd(jcp.mb, jcp.dimM_nb_block, jcp.dimM_block, + [&](int img, int M_blk1, int M_blk2) { + + const int M_blk = M_blk1 * jcp.dimM_block + M_blk2; + + float *bias_ptr = wants_padded_bias + && M_blk == jcp.dimM / jcp.dimM_simd_block - 1 + ? last_slice_bias : &bias(M_blk, 0); + + output_transform(img, jcp, p_ops, + &(M(0, M_blk1, 0, 0, 0, M_blk2, 0, 0)), + &(output(img, M_blk, 0, 0, 0)), + bias_ptr, output_is_aligned); + + }); + + } +} + +template struct _jit_avx512_common_convolution_winograd_t; +template struct _jit_avx512_common_convolution_winograd_t; + +void jit_avx512_common_convolution_winograd_bwd_weights_t:: +_maybe_execute_diff_bias_copy(float *diff_bias, + const memory_tracking::grantor_t &scratchpad) const { + if (pd()->wants_padded_bias()) { + auto padded_bias = scratchpad.get(key_conv_padded_bias); + for (int oc = 0; oc < pd()->jcp_.oc_without_padding; ++oc) + diff_bias[oc] = padded_bias[oc]; + } +} + +void jit_avx512_common_convolution_winograd_bwd_weights_t:: +_execute_backward_weights_S_D_G_W(const exec_ctx_t &ctx, + const memory_tracking::grantor_t &scratchpad) const { + auto ptr_diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST); + auto ptr_src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC); + auto ptr_diff_weights = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS); + auto ptr_diff_bias = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_BIAS); + + const auto &jcp = kernel_->jcp; + const int nthreads = jcp.nthr; + + auto diff_src_transform_bwd_weights_ver = jcp.ver == ver_4fma ? + diff_src_transform_bwd_weights : + diff_src_transform_bwd_weights; + auto diff_dst_transform_bwd_weights_ver = jcp.with_bias + ? diff_dst_transform_bwd_weights + : diff_dst_transform_bwd_weights; + + array_offset_calculator src((float *)ptr_src, + jcp.mb, jcp.ic/simd_w, jcp.ih, jcp.iw, simd_w); + array_offset_calculator diff_dst((float *)ptr_diff_dst, + jcp.mb, jcp.oc/simd_w, jcp.oh, jcp.ow, simd_w); + array_offset_calculator diff_weights(ptr_diff_weights, + jcp.oc/simd_w, jcp.ic/simd_w, jcp.kh, jcp.kw, simd_w, simd_w); + array_offset_calculator diff_bias(pd()->wants_padded_bias() + ? scratchpad.get(key_conv_padded_bias) : ptr_diff_bias, + jcp.oc/simd_w, simd_w); + + array_offset_calculator U( + scratchpad.get(key_wino_U), + jcp.nb_ic, jcp.nb_oc, + alpha, alpha, + jcp.oc_block, jcp.ic_block, + jcp.ic_simd_block, jcp.oc_simd_block); + + array_offset_calculator M( + scratchpad.get(key_wino_M), + jcp.nb_oc, alpha, alpha, + jcp.tile_block, jcp.oc_block, + jcp.nb_tile_block_ur, jcp.tile_block_ur * jcp.tile_4fma, + jcp.oc_simd_block); + array_offset_calculator V( + scratchpad.get(key_wino_V), + jcp.nb_ic, alpha, alpha, + jcp.tile_block, jcp.ic_block, + jcp.nb_tile_block_ur, jcp.tile_block_ur, + jcp.ic_simd_block * jcp.tile_4fma); + + const int trans_buffer_size = alpha * alpha * jcp.tile_4fma + * jcp.ic_simd_block; + array_offset_calculator trans_buffer( + scratchpad.get(key_conv_tr_src), + nthreads, + trans_buffer_size); + + array_offset_calculator diff_bias_prv( + scratchpad.get(key_conv_bia_reduction), + nthreads, + jcp.oc); + +PRAGMA_OMP(parallel num_threads(nthreads)) + { + if (jcp.with_bias) { + parallel_nd_in_omp(nthreads, jcp.oc, [&](int ithr, int ofm) { + diff_bias_prv(ithr, ofm) = 0.0f; + }); + +PRAGMA_OMP(for nowait) + for (int bofm = 0; bofm < jcp.oc / simd_w; bofm++) { + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) + diff_bias(bofm, v) = 0.0f; + } + } + + const int ithread = mkldnn_get_thread_num(); + + parallel_nd_in_omp(jcp.mb, jcp.nb_ic, jcp.ic_block, + [&](int img, int ifm1, int ifm2) { + float *transb = jcp.ver == ver_4fma + ? &(trans_buffer(ithread, 0)) + : NULL; + diff_src_transform_bwd_weights_ver(img, jcp, + &(src(img, ifm1 * jcp.ic_block + ifm2, + 0, 0, 0)), + &(V(ifm1, 0, 0, 0, ifm2, 0, 0, 0)), + transb, + kernel_->transpose_4fma_ker); + }); + + parallel_nd_in_omp(jcp.mb, jcp.nb_oc, jcp.oc_block, + [&](int img, int ofm1, int ofm2) { + float *dbias = jcp.with_bias + ? &(diff_bias_prv(ithread, + simd_w * (ofm1 * jcp.oc_block + ofm2))) + : NULL; + diff_dst_transform_bwd_weights_ver(img, jcp, + &(diff_dst(img, ofm1 * jcp.oc_block + ofm2, + 0, 0, 0)), + &(M(ofm1, 0, 0, 0, ofm2, 0, 0, 0)), + dbias); + }); + +PRAGMA_OMP(barrier) + + for (int ifm1 = 0; ifm1 < jcp.nb_ic; ifm1++) { + parallel_nd_in_omp(alpha, alpha, jcp.nb_oc, + [&](int oj, int oi, int ofm1) { + kernel_->gemm_loop_ker_first_iter( + (float *)&(U(ifm1, ofm1, oj, oi, + 0, 0, 0, 0)), + (const float *)&(M(ofm1, oj, oi, + 0, 0, 0, 0, 0)), + (const float *)&(V(ifm1, oj, oi, + 0, 0, 0, 0, 0))); + for (int tile_block = 1; tile_block < jcp.tile_block; + tile_block++) { + kernel_->gemm_loop_ker((float *)&(U(ifm1, ofm1, + oj, oi, + 0, 0, 0, 0)), + (const float *)&(M(ofm1, oj, oi, tile_block, + 0, 0, 0, 0)), + (const float *)&(V(ifm1, oj, oi, tile_block, + 0, 0, 0, 0))); + } + }); + } + +PRAGMA_OMP(barrier) + + parallel_nd_in_omp(jcp.nb_ic, jcp.nb_oc, jcp.oc_block, jcp.ic_block, + [&](int ifm1, int ofm1, int ofm2, int ifm2) { + diff_weights_transform_bwd_weights(jcp, + &(diff_weights(ofm1 * jcp.oc_block + ofm2, + ifm1 * jcp.ic_block + ifm2, 0, 0, 0, 0)), + &(U(ifm1, ofm1, 0, 0, ofm2, ifm2, 0, 0))); + }); + + if (jcp.with_bias) { +PRAGMA_OMP(for) + for (int ofm1 = 0; ofm1 < jcp.oc / simd_w; ofm1++) { + for (int ithr = 0; ithr < nthreads; ithr++) { + float* base_bias_ptr = &(diff_bias(ofm1, 0)); + float* base_bias_prv_ptr = &(diff_bias_prv( + ithr * jcp.oc + ofm1 * simd_w)); + PRAGMA_OMP_SIMD() + for (int ofm2 = 0; ofm2 < simd_w; ofm2++) { + base_bias_ptr[ofm2] += base_bias_prv_ptr[ofm2]; + } + } + } + } + } + + _maybe_execute_diff_bias_copy(ptr_diff_bias, scratchpad); +} + +} +} +} +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp new file mode 100644 index 0000000000..6c76f37c72 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp @@ -0,0 +1,318 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_COMMON_CONVOLUTION_WINOGRAD_HPP +#define CPU_JIT_AVX512_COMMON_CONVOLUTION_WINOGRAD_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_avx512_common_conv_winograd_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace winograd_avx512_common { +inline void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_winograd_conf_t &jcp) { + using namespace memory_tracking::names; + + size_t U_sz = (size_t)alpha * alpha * jcp.ic * jcp.oc; + size_t V_sz = (size_t)alpha * alpha * jcp.mb * jcp.ic + * (jcp.itiles * jcp.jtiles + jcp.tile_4fma_padding); + size_t M_sz = (size_t)alpha * alpha * jcp.mb * jcp.oc + * (jcp.itiles * jcp.jtiles + jcp.tile_4fma_padding); + + scratchpad.book(key_wino_U, sizeof(float) * U_sz, PAGE_2M); + scratchpad.book(key_wino_V, sizeof(float) * V_sz, PAGE_2M); + scratchpad.book(key_wino_M, sizeof(float) * M_sz, PAGE_2M); + + if (jcp.sched_policy == WSCHED_WEI_S_D_G_W) { + const int nthr = mkldnn_get_max_threads(); + + size_t tr_src_sz = jcp.ver != ver_4fma ? 0 : (size_t)nthr + * alpha * alpha * jcp.tile_4fma * jcp.ic_simd_block; + scratchpad.book(key_conv_tr_src, sizeof(float) * tr_src_sz, PAGE_2M); + + size_t br_sz = jcp.with_bias ? nthr * jcp.oc : 0; + scratchpad.book(key_conv_bia_reduction, sizeof(float) * br_sz, PAGE_2M); + + size_t padded_bias_sz = + jcp.with_bias && jcp.oc_without_padding != jcp.oc ? jcp.oc : 0; + scratchpad.book(key_conv_padded_bias, sizeof(float) * padded_bias_sz); + } +} +} + +template +struct _jit_avx512_common_convolution_winograd_t { + _jit_avx512_common_convolution_winograd_t( + const jit_conv_winograd_conf_t &jcp, const primitive_attr_t *attr) + : kernel_(nullptr), attr_(attr) { + kernel_ = new _jit_avx512_common_conv_winograd_data_kernel_f32(jcp); + } + + ~_jit_avx512_common_convolution_winograd_t() { delete kernel_; } + + protected: + void _execute_data_W_S_G_D(float *inp_ptr, float *out_ptr, + float *wei_ptr, float *bias_ptr, + const memory_tracking::grantor_t &scratchpad) const; + _jit_avx512_common_conv_winograd_data_kernel_f32 *kernel_; + const primitive_attr_t *attr_; +}; + +struct jit_avx512_common_convolution_winograd_fwd_t + : _jit_avx512_common_convolution_winograd_t + , public cpu_primitive_t + { + struct pd_t : public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_wino:", avx512_common, ""), + jit_avx512_common_convolution_winograd_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx512_common_conv_winograd_fwd_kernel_f32:: + init_conf(jcp_, *desc(), *src_md(), *weights_md(), *dst_md(), + *attr()); + if (status != status::success) return status; + set_default_alg_kind(alg_kind::convolution_winograd); + + auto scratchpad = scratchpad_registry().registrar(); + winograd_avx512_common::init_scratchpad(scratchpad, jcp_); + + return status; + } + + jit_conv_winograd_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + auto wei_tag = with_groups() ? gOIhw16i16o : OIhw16i16o; + return set_default_formats_common(nChw16c, wei_tag, nChw16c); + } + }; + + jit_avx512_common_convolution_winograd_fwd_t(const pd_t *apd) + : _jit_avx512_common_convolution_winograd_t(apd->jcp_, apd->attr()) + , cpu_primitive_t(apd, true) {} + + ~jit_avx512_common_convolution_winograd_fwd_t(){}; + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override + { + auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(float *, MKLDNN_ARG_DST); + this->_execute_data_W_S_G_D((float *)src, dst, (float *)weights, + (float *)bias, this->scratchpad(ctx)); + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +struct jit_avx512_common_convolution_winograd_bwd_data_t + : _jit_avx512_common_convolution_winograd_t, + public cpu_primitive_t { + struct pd_t : public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_wino:", avx512_common, ""), + jit_avx512_common_convolution_winograd_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && expect_data_types(data_type::f32, data_type::f32, + data_type::undef, data_type::f32, data_type::f32) + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && !has_zero_dim_memory() + && set_default_formats() + && mkldnn_thr_syncable(); + if (!ok) return status::unimplemented; + + status_t status = + jit_avx512_common_conv_winograd_bwd_data_kernel_f32::init_conf( + jcp_, *desc(), *diff_src_md(), *weights_md(), + *diff_dst_md()); + if (status != status::success) return status; + set_default_alg_kind(alg_kind::convolution_winograd); + + auto scratchpad = scratchpad_registry().registrar(); + winograd_avx512_common::init_scratchpad(scratchpad, jcp_); + + return status; + } + + jit_conv_winograd_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + auto wei_tag = with_groups() ? gOIhw16i16o : OIhw16i16o; + return set_default_formats_common(nChw16c, wei_tag, nChw16c); + } + }; + + jit_avx512_common_convolution_winograd_bwd_data_t(const pd_t *apd) + : _jit_avx512_common_convolution_winograd_t(apd->jcp_, apd->attr()) + , cpu_primitive_t(apd, true) {} + + ~jit_avx512_common_convolution_winograd_bwd_data_t(){}; + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC); + this->_execute_data_W_S_G_D((float *)diff_dst, diff_src, + (float *)weights, nullptr, this->scratchpad(ctx)); + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +struct jit_avx512_common_convolution_winograd_bwd_weights_t + : public cpu_primitive_t { + struct pd_t : public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, + hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_wino:", avx512_common, ""), + jit_avx512_common_convolution_winograd_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats() + && mkldnn_thr_syncable(); + if (!ok) return status::unimplemented; + + status_t status = + jit_avx512_common_conv_winograd_bwd_weights_kernel_f32:: + init_conf(jcp_, *desc(), *src_md(), *diff_dst_md(), + *diff_weights_md()); + if (status != status::success) return status; + set_default_alg_kind(alg_kind::convolution_winograd); + + auto scratchpad = scratchpad_registry().registrar(); + winograd_avx512_common::init_scratchpad(scratchpad, jcp_); + + return status; + } + + jit_conv_winograd_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + auto wei_tag = with_groups() ? gOIhw16i16o : OIhw16i16o; + return set_default_formats_common(nChw16c, wei_tag, nChw16c); + } + }; + + jit_avx512_common_convolution_winograd_bwd_weights_t(const pd_t *apd) + : cpu_primitive_t(apd, true), kernel_(nullptr) + { + kernel_ = new jit_avx512_common_conv_winograd_bwd_weights_kernel_f32( + pd()->jcp_); + } + + ~jit_avx512_common_convolution_winograd_bwd_weights_t() + { delete kernel_; } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override + { + _execute_backward_weights_S_D_G_W(ctx, scratchpad(ctx)); + return status::success; + } + +private: + void _execute_backward_weights_S_D_G_W(const exec_ctx_t &ctx, + const memory_tracking::grantor_t &scratchpad) const; + void _maybe_execute_diff_bias_copy(float *diff_bias, + const memory_tracking::grantor_t &scratchpad) const; + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_avx512_common_conv_winograd_bwd_weights_kernel_f32 *kernel_; +}; + +void trans_W_4x4_3x3(float Fw_[6][6][16][16], float F[3][3][16][16]); +void trans_O_4x4_3x3(float Mw[6][6][16], float O[4][4][16]); +void trans_W_3x3_4x4(float Fw[6][6][16], float F[4][6][16]); +void trans_O_3x3_4x4(float Mw[6][6][16][16], float M[3][3][16][16]); +void trans_I_4x4_3x3(float Iw[6][6][16], float I[6][6][16]); +void trans_W_3x3_4x4_wu(float Fw[6][6][16], float F[4][6][16]); +void trans_O_3x3_4x4_wu(float Mw[6][6][16][16], float M[3][3][16][16]); + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp new file mode 100644 index 0000000000..d4a451c021 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp @@ -0,0 +1,853 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx512_common_lrn.hpp" + +#include "jit_generator.hpp" + +#define FWD_RBC 4 +#define BWD_RBC 3 + +#define XMM_SIZE (4*sizeof(float)) +#define ZMM_SIZE (vlen) +#define BUFFER_BLOCK (XMM_SIZE + ZMM_SIZE + XMM_SIZE) +#define BUFFER_NEXT_OFFSET (XMM_SIZE + ZMM_SIZE) +#define SRC_PREV_OFFSET (vlen - XMM_SIZE) + +#define IRB_LOOP(statement) for(int irb = 0; irb < loop_size; irb++) { \ + statement;\ +} + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +enum params { vsize = 16, vlen = 64}; + +typedef struct { + const float *src; + float *dst, *ws0, *ws1; +} jit_args_fwd_t; + +typedef struct { + const float *src, *diff_dst, *ws0, *ws1; + float *diff_src; +} jit_args_bwd_t; + +struct nChw16c_across { +/* version: + * -1: channels 0..15, + * 1: channels C-16 .. C-1, + * 0: other channels + * 3: channels only for this kernel(without prev and next) + */ + int H, W, version; + nChw16c_across(int h, int w, int v) : H(h), W(w), version(v) {} +}; + +struct jit_avx512_common_lrn_fwd_t::jit_avx512_common_lrn_kernel_f32: + public jit_generator { + int HW, W; + bool is_first; + bool is_last; + bool is_single; + + Reg64 src = rax; + Reg64 dst = r8; + Reg64 scratch0 = rdx; + Reg64 scratch1 = rsi; + Reg64 imm_addr64 = rbx; + + Zmm zalpha = zmm0; + Xmm xalpha = xmm0; + Zmm zk = zmm1; + Xmm xk = xmm1; + + Reg64 param = abi_param1; + Reg64 t = rsp; + Reg64 hw = r9; + + int xsrc_prev = 2; + int zsrc = 7; + int xsrc_next = 3; + int zc = 7; + + int za = 2; + int zb = 3; + int zd = 5; + int ze = 6; + int zsum = 4; + int zdst = 2; + int zbase = 3; + int zsum2 = 5; + + prop_kind_t pk; + int use_h_parallelism; + + float alpha, k; + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_lrn_kernel_f32) + + void (*ker)(jit_args_fwd_t *); + void operator()(jit_args_fwd_t *arg) { ker(arg); } + + enum { + prf0_offt = 1*FWD_RBC, + prf2_offt = 8*FWD_RBC + }; + + inline void compute_loop(int loop_size_param) + { + // loop_size - param for IRB_LOOP macro + int loop_size = FWD_RBC; + + auto xreg = [=](int irb, int i) { + return Xmm(irb*3 + i); + }; + + auto zreg = [=](int irb, int i) { + return Zmm(irb*7 + i); + }; + + if (!is_first && !is_single) { + IRB_LOOP(mic_prefetcht0(ptr[src + (irb + prf0_offt - HW)*vlen])); + IRB_LOOP(mic_prefetcht2(ptr[src + (irb + prf2_offt - HW)*vlen])); + } + IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(src, (irb + prf0_offt)*vlen))); + IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(src, (irb + prf2_offt)*vlen))); + if (!is_last && !is_single) { + IRB_LOOP(mic_prefetcht0(ptr[src + (irb + prf0_offt + HW)*vlen])); + IRB_LOOP(mic_prefetcht2(ptr[src + (irb + prf2_offt + HW)*vlen])); + } + if (pk != prop_kind::forward_inference) { + IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(scratch0, + (irb + prf0_offt)*vlen))); + IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(scratch0, + (irb + prf2_offt)*vlen))); + } + IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(dst, (irb + prf0_offt)*vlen))); + IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(dst, (irb + prf2_offt)*vlen))); + if (pk != prop_kind::forward_inference) { + IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(scratch1, + (irb + prf0_offt) * vlen))); + IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(scratch1, + (irb + prf2_offt) * vlen))); + } + + loop_size = loop_size_param; + if (loop_size == 0) + return; + if (!is_first && !is_single) { + IRB_LOOP(vmovups(xreg(irb, xsrc_prev), + ptr[src + (irb - HW) * vlen + SRC_PREV_OFFSET])); + } + IRB_LOOP(vmovups(zreg(irb, zsrc), EVEX_compress_addr(src,irb*vlen))); + if (!is_last && !is_single) { + IRB_LOOP(vmovups(xreg(irb, xsrc_next), + ptr[src + (irb + HW) * vlen])); + } + + if (!is_first && !is_single) { + IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK], + xreg(irb, xsrc_prev))); + } + IRB_LOOP(vmovups(EVEX_compress_addr(t, irb*BUFFER_BLOCK + XMM_SIZE), + zreg(irb, zsrc))); + if (!is_last && !is_single) { + IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET], + xreg(irb, xsrc_next))); + } + + IRB_LOOP(vmovups(zreg(irb, za), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE - 2*sizeof(float)))); + IRB_LOOP(vmovups(zreg(irb, zb), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE - sizeof(float)))); + IRB_LOOP(vmovups(zreg(irb, zd), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE + sizeof(float)))); + IRB_LOOP(vmovups(zreg(irb, ze), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE + 2*sizeof(float)))); + + assert(zc == zsrc); + IRB_LOOP(vmulps(zreg(irb, zsum), zreg(irb, zc), zreg(irb, zc))); + + IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, za), zreg(irb, za))); + IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, zb), zreg(irb, zb))); + IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, zd), zreg(irb, zd))); + IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, ze), zreg(irb, ze))); + + IRB_LOOP(vfmadd132ps(zreg(irb, zsum), zk, zalpha)); + + IRB_LOOP(vmovaps(zreg(irb, zbase), zreg(irb, zsum))); + + IRB_LOOP(vmulps(zreg(irb, zsum2), zreg(irb, zsum), zreg(irb, zsum))); + IRB_LOOP(vmulps(zreg(irb, zsum), zreg(irb, zsum), zreg(irb, zsum2))); + + IRB_LOOP(vsqrtps(zreg(irb, zsum), zreg(irb, zsum))); + IRB_LOOP(vsqrtps(zreg(irb, zsum), zreg(irb, zsum))); + + if (pk != prop_kind::forward_inference) { + IRB_LOOP(vmovups(EVEX_compress_addr(scratch0, irb*vlen), + zreg(irb, zsum))); + } + IRB_LOOP(vdivps(zreg(irb, zdst), zreg(irb, zsrc), zreg(irb, zsum))); + IRB_LOOP(vmovups(EVEX_compress_addr(dst, irb*vlen), zreg(irb, zdst))); + if (pk != prop_kind::forward_inference) { + /* ws1 = zdst / zbase = zsrc / (zbase^1.75) */ + IRB_LOOP(vdivps(zreg(irb, zsum), zreg(irb, zdst), zreg(irb, zbase))); + IRB_LOOP(vmovups(EVEX_compress_addr(scratch1, irb*vlen), + zreg(irb, zsum))); + } + } + + jit_avx512_common_lrn_kernel_f32( + const struct nChw16c_across &J, + prop_kind_t prop_kind, + int use_h_parallel, + float A, + float K, + void *code_ptr = nullptr, + size_t code_size = 2 * Xbyak::DEFAULT_MAX_CODE_SIZE) + : jit_generator(code_ptr, code_size) + , pk(prop_kind) + , use_h_parallelism(use_h_parallel) + , alpha(A) + , k(K) + { + this->preamble(); + + mov(src, ptr[param + 0]); + mov(dst, ptr[param + 8]); + if (pk != prop_kind::forward_inference) + { + mov(scratch0, ptr[param + 16]); + mov(scratch1, ptr[param + 24]); + } + is_first = J.version == -1 || J.version == -2; + is_last = J.version == +1 || J.version == -2; + is_single = J.version == 3; + + W = J.W; + HW = J.W*J.H; + int LSB = use_h_parallelism ? W : HW; + + sub(t, FWD_RBC*BUFFER_BLOCK); + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + vbroadcastss(zalpha, xalpha); + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + vbroadcastss(zk, xk); + + if (is_first || is_single) { + vxorps(xmm2, xmm2, xmm2); + for(int irb = 0; irb < FWD_RBC; irb++) { + vmovups(ptr[t + irb*BUFFER_BLOCK], xmm2); + } + } + if (is_last || is_single) { + vxorps(xmm2, xmm2, xmm2); + for(int irb = 0; irb < FWD_RBC; irb++) { + vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET], + xmm2); + } + } + + int LSREST = LSB % FWD_RBC; + int LS = LSB - LSREST; + + Label lrn_loop; + + if (LS > 0) { + mov(hw, LS); + + L(lrn_loop); + { + compute_loop(FWD_RBC); + + add(src, FWD_RBC*vlen); + add(dst, FWD_RBC*vlen); + if (pk != prop_kind::forward_inference) + { + add(scratch0, FWD_RBC*vlen); + add(scratch1, FWD_RBC*vlen); + } + + for(int irb = 0; irb < FWD_RBC; irb++) + dec(hw); + cmp(hw, 0); + jne(lrn_loop, T_NEAR); + } + } + + compute_loop(LSREST); + + add(t, FWD_RBC*BUFFER_BLOCK); + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); + } +}; + +status_t jit_avx512_common_lrn_fwd_t::pd_t::init() { + using namespace prop_kind; + using namespace alg_kind; + + const memory_desc_wrapper data_d(src_md()); + bool ok = true + && mayiuse(avx512_common) + && is_fwd() + && !has_zero_dim_memory() + && everyone_is(data_type::f32, data_d.data_type()) + && data_d.ndims() == 4 + && data_d.dims()[1] % vsize == 0 + && attr()->has_default_values(); + if (!ok) return unimplemented; + + if (desc()->prop_kind == forward_training) { + dims_t ws_dims = { MB(), C(), H(), 2*W() }; + mkldnn_memory_desc_init_by_tag(&ws_md_, 4, ws_dims, data_type::f32, + format_tag::nChw16c); + } + + bool args_ok_across = true + && desc()->alg_kind == lrn_across_channels + && desc()->local_size == 5 + && desc()->lrn_beta == 0.75 + && data_d.matches_tag(format_tag::nChw16c); + + return args_ok_across ? success : unimplemented; +} + +jit_avx512_common_lrn_fwd_t::jit_avx512_common_lrn_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + , use_h_parallelism(0), ker_(nullptr), ker_first_(nullptr) + , ker_last_(nullptr) { + using namespace alg_kind; + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + const int ls = pd()->desc()->local_size; + const float alpha = pd()->desc()->lrn_alpha / ls; + const float k = pd()->desc()->lrn_k; + + auto pk = pd()->desc()->prop_kind; + + use_h_parallelism = H > 28 ? 1 : 0; + + if (C / vsize == 1) { + ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 3), pk, + use_h_parallelism, alpha, k); + } else { + ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 0), pk, + use_h_parallelism, alpha, k); + ker_first_ = new jit_avx512_common_lrn_kernel_f32( + nChw16c_across(H, W, -1), pk, use_h_parallelism, alpha, k); + ker_last_ = new jit_avx512_common_lrn_kernel_f32( + nChw16c_across(H, W, +1), pk, use_h_parallelism, alpha, k); + } +} + +jit_avx512_common_lrn_fwd_t::~jit_avx512_common_lrn_fwd_t() +{ delete ker_; delete ker_first_; delete ker_last_; } + +void jit_avx512_common_lrn_fwd_t::execute_forward(const exec_ctx_t &ctx) const +{ + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(data_t *, MKLDNN_ARG_WORKSPACE); + + const int N = pd()->MB(); + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + + parallel(0, [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + const int C16 = C / vsize; + const size_t work_amount = use_h_parallelism ? N*C16*H : N*C16; + + balance211(work_amount, nthr, ithr, start, end); + if (use_h_parallelism) { + int n{0}, c16{0}, h{0}; + nd_iterator_init(start, n, N, c16, C16, h, H); + for (size_t iwork = start; iwork < end; ++iwork) { + auto offset = n*C*H*W + c16*H*W*vsize + + h*W*vsize; + auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize + + h*2*W*vsize; + auto ws_offset1 = ws_offset0 + W*vsize; + + jit_args_fwd_t args; + args.src = &src[offset]; + args.dst = &dst[offset]; + args.ws0 = &ws[ws_offset0]; + args.ws1 = &ws[ws_offset1]; + + if (C16 == 1) + (*ker_)(&args); + else if (c16 == 0) + (*ker_first_)(&args); + else if (c16 == C16 - 1) + (*ker_last_)(&args); + else + (*ker_)(&args); + nd_iterator_step(n, N, c16, C16, h, H); + } + } else { + int n{0}, c16{0}; + nd_iterator_init(start, n, N, c16, C16); + for (size_t iwork = start; iwork < end; ++iwork) { + auto offset = n*C*H*W + c16*H*W*vsize; + auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize; + auto ws_offset1 = ws_offset0 + H*W*vsize; + + jit_args_fwd_t args; + args.src = &src[offset]; + args.dst = &dst[offset]; + args.ws0 = &ws[ws_offset0]; + args.ws1 = &ws[ws_offset1]; + + if (C16 == 1) + (*ker_)(&args); + else if (c16 == 0) + (*ker_first_)(&args); + else if (c16 == C16 - 1) + (*ker_last_)(&args); + else + (*ker_)(&args); + + nd_iterator_step(n, N, c16, C16); + } + } + }); +} + +struct jit_avx512_common_lrn_bwd_t::jit_avx512_common_lrn_kernel_f32: + public jit_generator { + int HW, W; + bool is_first; + bool is_last; + bool is_single; + + Reg64 src = rax; + Reg64 diffsrc = r8; + Reg64 diffdst = r9; + Reg64 workspace0 = rdx; + Reg64 workspace1 = rsi; + Reg64 imm_addr64 = rbx; + + Zmm znalphabeta = zmm0; + Xmm xnalphabeta = xmm0; + + Reg64 param = abi_param1; + Reg64 t = rsp; + Reg64 hw = r10; + + int xws1_prev = 1; + int xdiffdst_prev = 2; + int zws1 = 1; + + int zsrc = 1; + int zdiffdst = 5; + int zdiffsrc = 6; + + int xws1_next = 1; + int xdiffdst_next = 3; + + int za = 1; + int zb = 2; + int zd = 3; + int ze = 4; + int zws0 = 2; + + float nalphabeta; + + int use_h_parallelism; + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_lrn_kernel_f32) + + void (*ker)(jit_args_bwd_t *); + void operator()(jit_args_bwd_t *arg) { ker(arg); } + + enum { + prf0_offt = 1*BWD_RBC, + prf2_offt = 8*BWD_RBC + }; + + inline void compute_loop(int loop_size_param, int prefetchL1, + int prefetchL2) + { + // loop_size - param for IRB_LOOP macro + int loop_size = loop_size_param; + + auto xreg = [=](int irb, int i) { + return Xmm(irb*6 + i); + }; + + auto zreg = [=](int irb, int i) { + return Zmm(irb*6 + i); + }; + +// ---- prefetching ------------------------------------------- + if (!is_first && !is_single) { + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[workspace1 + (irb + prf0_offt + - 2 * HW) * vlen])); + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[diffdst + (irb + prf0_offt + - HW) * vlen])); + } + + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[src + (irb + prf0_offt)*vlen])); + if (prefetchL2) + IRB_LOOP(mic_prefetcht2(ptr[src + (irb + prf2_offt)*vlen])); + + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[workspace1 + (irb + prf0_offt)*vlen])); + + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[diffdst + (irb + prf0_offt)*vlen])); + + if (!is_last && !is_single) { + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[workspace1 + (irb + prf0_offt + + 2 * HW) * vlen])); + if (prefetchL2) + IRB_LOOP(mic_prefetcht2(ptr[workspace1 + (irb + prf2_offt + + 2 * HW) * vlen])); + + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[diffdst + (irb + prf0_offt + + HW) * vlen])); + if (prefetchL2) + IRB_LOOP(mic_prefetcht2(ptr[diffdst + (irb + prf2_offt + + HW) * vlen])); + } + if (prefetchL1) + IRB_LOOP(mic_prefetcht0(ptr[workspace0 + (irb + prf0_offt)*vlen])); + if (prefetchL2) + IRB_LOOP(mic_prefetcht2(ptr[workspace0 + (irb + prf2_offt)*vlen])); +// ----------------------------------------------------------- + + if (loop_size_param == 0) + return; + + if (!is_first && !is_single) { + IRB_LOOP(vmovups(xreg(irb, xws1_prev), ptr[workspace1 + (irb + - 2 * HW) * vlen + SRC_PREV_OFFSET])); + IRB_LOOP(vmovups(xreg(irb, xdiffdst_prev), ptr[diffdst + (irb + - HW) * vlen + SRC_PREV_OFFSET])); + IRB_LOOP(vmulps(xreg(irb, xdiffdst_prev), xreg(irb, xdiffdst_prev), + xreg(irb, xws1_prev))); + } + + IRB_LOOP(vmovups(zreg(irb, zws1), + EVEX_compress_addr(workspace1, irb*vlen))); + IRB_LOOP(vmovups(zreg(irb, zdiffdst), + EVEX_compress_addr(diffdst, irb*vlen))); + IRB_LOOP(vmulps(zreg(irb, zdiffsrc), zreg(irb, zdiffdst), + zreg(irb, zws1))); + + if (!is_last && !is_single) { + IRB_LOOP(vmovups(xreg(irb, xws1_next), ptr[workspace1 + (irb + + 2 * HW) * vlen])); + IRB_LOOP(vmovups(xreg(irb, xdiffdst_next), ptr[diffdst + (irb + + HW) * vlen])); + IRB_LOOP(vmulps(xreg(irb, xdiffdst_next), xreg(irb, xdiffdst_next), + xreg(irb, xws1_next))); + } + + if (!is_first && !is_single) { + IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK], + xreg(irb, xdiffdst_prev))); + } + IRB_LOOP(vmovups(EVEX_compress_addr(t, irb*BUFFER_BLOCK + XMM_SIZE), + zreg(irb, zdiffsrc))); + if (!is_last && !is_single) { + IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET], + xreg(irb, xdiffdst_next))); + } + + IRB_LOOP(vmovups(zreg(irb, za), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE - 2*sizeof(float)))); + IRB_LOOP(vmovups(zreg(irb, zb), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE - 1*sizeof(float)))); + IRB_LOOP(vmovups(zreg(irb, zd), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE + 1*sizeof(float)))); + IRB_LOOP(vmovups(zreg(irb, ze), EVEX_compress_addr(t, irb*BUFFER_BLOCK + + XMM_SIZE + 2*sizeof(float)))); + IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc), + zreg(irb, za))); + assert(zsrc == za); + IRB_LOOP(vmovups(zreg(irb, zsrc), EVEX_compress_addr(src, irb*vlen))); + IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc), + zreg(irb, zb))); + IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc), + zreg(irb, zd))); + IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc), + zreg(irb, ze))); + IRB_LOOP(vmulps(zreg(irb, zsrc), zreg(irb, zsrc), znalphabeta)); + + IRB_LOOP(vmovups(zreg(irb, zws0), + EVEX_compress_addr(workspace0, irb*vlen))); + IRB_LOOP(vdivps(zreg(irb, zdiffdst), zreg(irb, zdiffdst), + zreg(irb, zws0))); + IRB_LOOP(vfmadd213ps(zreg(irb, zdiffsrc), zreg(irb, zsrc), + zreg(irb, zdiffdst))); + + Label unaligned_store, end_store; + test(diffsrc, vlen - 1); + jnz(unaligned_store, T_NEAR); + IRB_LOOP(uni_vmovntps(EVEX_compress_addr(diffsrc, irb*vlen), + zreg(irb, zdiffsrc))); + jmp(end_store, T_NEAR); + L(unaligned_store); { + IRB_LOOP(uni_vmovups(EVEX_compress_addr(diffsrc, irb*vlen), + zreg(irb, zdiffsrc))); + } + L(end_store); + } + + jit_avx512_common_lrn_kernel_f32( + const struct nChw16c_across &J, + float A, + float B, + int use_h_parallel, + void *code_ptr = nullptr, + size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE) + : jit_generator(code_ptr, code_size) + , nalphabeta(-2*A*B) + , use_h_parallelism(use_h_parallel) + { + this->preamble(); + + mov(src, ptr[param + 0]); + mov(diffdst, ptr[param + 8]); + mov(workspace0, ptr[param + 16]); + mov(workspace1, ptr[param + 24]); + mov(diffsrc, ptr[param + 32]); + + W = J.W; + HW = J.H*J.W; + int LSB = this->use_h_parallelism ? W : HW; + + sub(t, BWD_RBC*BUFFER_BLOCK); + mov(imm_addr64, float2int(this->nalphabeta)); + movq(xnalphabeta, imm_addr64); + vbroadcastss(znalphabeta, xnalphabeta); + + is_first = J.version == -1 || J.version == -2; + is_last = J.version == +1 || J.version == +2; + is_single = J.version == 3; + + if (is_first || is_single) { + vxorps(xmm1, xmm1, xmm1); + for(int irb = 0; irb < BWD_RBC; irb++) { + vmovups(ptr[t + irb*BUFFER_BLOCK], xmm1); + } + } + if (is_last || is_single) { + vxorps(xmm1, xmm1, xmm1); + for(int irb = 0; irb < BWD_RBC; irb++) { + vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET], xmm1); + } + } + + int LSREST = LSB % BWD_RBC; + int LS = LSB - LSREST; + + Label lrn_loop; + + if (LS > 0) { + mov(hw, LS); + + L(lrn_loop); + { + compute_loop(BWD_RBC, 1, 1); + + add(src, BWD_RBC*vlen); + add(diffsrc, BWD_RBC*vlen); + add(diffdst, BWD_RBC*vlen); + add(workspace0, BWD_RBC*vlen); + add(workspace1, BWD_RBC*vlen); + + for(int irb = 0; irb < BWD_RBC; irb++) + dec(hw); + cmp(hw, 0); + jne(lrn_loop, T_NEAR); + } + } + + compute_loop(LSREST, 1, this->use_h_parallelism ? 0 : 1); + + add(t, BWD_RBC*BUFFER_BLOCK); + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); + } + +}; + +status_t jit_avx512_common_lrn_bwd_t::pd_t::init() { + using namespace alg_kind; + + const memory_desc_wrapper data_d(src_md()); + bool ok = true + && mayiuse(avx512_common) + && !is_fwd() + && utils::everyone_is(data_type::f32, data_d.data_type()) + && !has_zero_dim_memory() + && data_d.ndims() == 4 + && data_d.dims()[1] % vsize == 0 + && attr()->has_default_values(); + if (!ok) return unimplemented; + + dims_t ws_dims = { MB(), C(), H(), 2*W() }; + mkldnn_memory_desc_init_by_tag(&ws_md_, 4, ws_dims, data_type::f32, + format_tag::nChw16c); + + if (!compare_ws(hint_fwd_pd_)) return unimplemented; + + bool args_ok_across = true + && desc()->alg_kind == lrn_across_channels + && desc()->local_size == 5 + && desc()->lrn_beta == 0.75 + && data_d.matches_tag(format_tag::nChw16c); + + return args_ok_across ? success : unimplemented; +} + +jit_avx512_common_lrn_bwd_t::jit_avx512_common_lrn_bwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + , use_h_parallelism(0), ker_(nullptr), ker_first_(nullptr) + , ker_last_(nullptr) { + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + const int ls = pd()->desc()->local_size; + const float alpha = pd()->desc()->lrn_alpha / ls; + const float beta = pd()->desc()->lrn_beta; + + use_h_parallelism = H > 28 ? 1 : 0; + + if (C / vsize == 1) { + ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 3), + alpha, beta, use_h_parallelism); + } else { + ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 0), + alpha, beta, use_h_parallelism); + ker_first_ = new jit_avx512_common_lrn_kernel_f32( + nChw16c_across(H, W, -1), alpha, beta, use_h_parallelism); + ker_last_ = new jit_avx512_common_lrn_kernel_f32( + nChw16c_across(H, W, +1), alpha, beta, use_h_parallelism); + } +} + +jit_avx512_common_lrn_bwd_t::~jit_avx512_common_lrn_bwd_t() +{ delete ker_; delete ker_first_; delete ker_last_; } + +void jit_avx512_common_lrn_bwd_t::execute_backward(const exec_ctx_t &ctx) const +{ + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto ws = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WORKSPACE); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const int N = pd()->MB(); + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + + parallel(0, [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + const int C16 = C / vsize; + const size_t work_amount = use_h_parallelism ? N*C16*H : N*C16; + + balance211(work_amount, nthr, ithr, start, end); + if (use_h_parallelism) { + int n{0}, c16{0}, h{0}; + nd_iterator_init(start, n, N, h, H, c16, C16); + for (size_t iwork = start; iwork < end; ++iwork) { + auto offset = n*C*H*W + c16*H*W*vsize + + h*W*vsize; + auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize + + h*2*W*vsize; + auto ws_offset1 = ws_offset0 + W*vsize; + + jit_args_bwd_t args; + args.src = &src[offset]; + args.diff_dst = &diff_dst[offset]; + args.ws0 = &ws[ws_offset0]; + args.ws1 = &ws[ws_offset1]; + args.diff_src = &diff_src[offset]; + + if (C16 == 1) + (*ker_)(&args); + else if (c16 == 0) + (*ker_first_)(&args); + else if (c16 == C16 - 1) + (*ker_last_)(&args); + else + (*ker_)(&args); + nd_iterator_step(n, N, h, H, c16, C16); + } + } else { + int n{0}, c16{0}; + nd_iterator_init(start, n, N, c16, C16); + for (size_t iwork = start; iwork < end; ++iwork) { + auto offset = n*C*H*W + c16*H*W*vsize; + auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize; + auto ws_offset1 = ws_offset0 + H*W*vsize; + + jit_args_bwd_t args; + args.src = &src[offset]; + args.diff_dst = &diff_dst[offset]; + args.ws0 = &ws[ws_offset0]; + args.ws1 = &ws[ws_offset1]; + args.diff_src = &diff_src[offset]; + + if (C16 == 1) + (*ker_)(&args); + else if (c16 == 0) + (*ker_first_)(&args); + else if (c16 == C16 - 1) + (*ker_last_)(&args); + else + (*ker_)(&args); + + nd_iterator_step(n, N, c16, C16); + } + } + }); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp new file mode 100644 index 0000000000..37fbb9b3e5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp @@ -0,0 +1,96 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_COMMON_LRN_HPP +#define CPU_JIT_AVX512_COMMON_LRN_HPP + +#include "c_types_map.hpp" + +#include "cpu_isa_traits.hpp" +#include "cpu_lrn_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx512_common_lrn_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_lrn_fwd_pd_t { + using cpu_lrn_fwd_pd_t::cpu_lrn_fwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""), + jit_avx512_common_lrn_fwd_t); + + status_t init(); + }; + + jit_avx512_common_lrn_fwd_t(const pd_t *apd); + ~jit_avx512_common_lrn_fwd_t(); + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + int use_h_parallelism; + struct jit_avx512_common_lrn_kernel_f32; + jit_avx512_common_lrn_kernel_f32 *ker_, *ker_first_, *ker_last_; +}; + +struct jit_avx512_common_lrn_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_lrn_bwd_pd_t { + using cpu_lrn_bwd_pd_t::cpu_lrn_bwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""), + jit_avx512_common_lrn_bwd_t); + + status_t init(); + }; + + jit_avx512_common_lrn_bwd_t(const pd_t *apd); + ~jit_avx512_common_lrn_bwd_t(); + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + int use_h_parallelism; + struct jit_avx512_common_lrn_kernel_f32; + jit_avx512_common_lrn_kernel_f32 *ker_, *ker_first_, *ker_last_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp new file mode 100644 index 0000000000..c58d3fa0a6 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp @@ -0,0 +1,1103 @@ +/******************************************************************************* + * Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx512_core_fp32_wino_conv_2x3.hpp" +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::format_kind; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; +using namespace Xbyak; + +/// SRC TRANSFORMS ///////////////////////////////////////////////////////////// +struct jit_avx512_core_fp32_wino_conv_2x3_src_trans_t: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS( + jit_avx512_core_fp32_wino_conv_2x3_src_trans_t) + + jit_conv_conf_2x3_wino_t jcp; + + struct call_params_t { + const void *src; + const void *wino_src; + const void *v_y_masks; + const void *v_x_masks; + }; + void (*ker_)(const call_params_t *); + + jit_avx512_core_fp32_wino_conv_2x3_src_trans_t( + jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr) + : jcp(ajcp) { + generate(); + ker_ = + reinterpret_cast(const_cast(getCode())); + } + + void generate(); + + Zmm vreg_inp(int i) { + assert(i < jcp.alpha * jcp.alpha); + return Zmm(31 - i); + } + + Zmm vreg_tmp(int i) { + assert(i < jcp.alpha * jcp.alpha); + return Zmm(15 - i); + } + + Zmm vreg_out(int i) { + assert(i < jcp.alpha * jcp.alpha); + return Zmm(31 - i); + } + + Opmask y_mask = Opmask(1); + Opmask r_mask = Opmask(2); + Opmask x_mask(int id) { + assert (id < 4); + return Opmask(3 + id); + } + + Reg64 reg_ptr_v_y_masks = r12; + Reg64 reg_ptr_v_x_masks = r11; + + Reg64 reg_aux_ptr_src = r10; + Reg64 reg_aux_ptr_dst = r9; + + Reg64 reg_ic_block = r8; + +}; + +void jit_avx512_core_fp32_wino_conv_2x3_src_trans_t::generate() { + Label ic_block_label; + + const int load_block = 16; + int out_offset = 0, inp_offset = 0; + preamble(); + +#define READ_PARAM(reg, field) \ + mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)]) + READ_PARAM(reg_aux_ptr_src, src); + READ_PARAM(reg_aux_ptr_dst, wino_src); + READ_PARAM(reg_ptr_v_y_masks, v_y_masks); + READ_PARAM(reg_ptr_v_x_masks, v_x_masks); +#undef READ_PARAM + + for (int i = 0; i < jcp.alpha; i++) { + kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(int16_t) * i]); + } + mov(reg_ic_block, jcp.ic / load_block); + L(ic_block_label); + { + for (int y = 0; y < jcp.alpha; y++) { + kmovw(y_mask, ptr[reg_ptr_v_y_masks + sizeof(int16_t) * y]); + for (int x = 0; x < jcp.alpha; x++) { + Zmm zmm = vreg_inp(y * jcp.alpha + x); + + vxorps(zmm, zmm, zmm); + kandw(r_mask, y_mask, x_mask(x)); + inp_offset = sizeof(float) + * ((-jcp.t_pad + y) * jcp.iw * load_block + + (-jcp.l_pad + x) * load_block); + vmovups(zmm | r_mask, + EVEX_compress_addr(reg_aux_ptr_src, inp_offset)); + } + } + for (int y = 0; y < jcp.alpha; y++) { + vsubps(vreg_tmp(y * jcp.alpha + 0), vreg_inp(y * jcp.alpha + 0), + vreg_inp(y * jcp.alpha + 2)); + vaddps(vreg_tmp(y * jcp.alpha + 1), vreg_inp(y * jcp.alpha + 1), + vreg_inp(y * jcp.alpha + 2)); + vsubps(vreg_tmp(y * jcp.alpha + 2), vreg_inp(y * jcp.alpha + 2), + vreg_inp(y * jcp.alpha + 1)); + vsubps(vreg_tmp(y * jcp.alpha + 3), vreg_inp(y * jcp.alpha + 1), + vreg_inp(y * jcp.alpha + 3)); + } + for (int x = 0; x < jcp.alpha; x++) { + vsubps(vreg_out(x + 0 * jcp.alpha), vreg_tmp(x + jcp.alpha * 0), + vreg_tmp(x + jcp.alpha * 2)); + vaddps(vreg_out(x + 1 * jcp.alpha), vreg_tmp(x + jcp.alpha * 1), + vreg_tmp(x + jcp.alpha * 2)); + vsubps(vreg_out(x + 2 * jcp.alpha), vreg_tmp(x + jcp.alpha * 2), + vreg_tmp(x + jcp.alpha * 1)); + vsubps(vreg_out(x + 3 * jcp.alpha), vreg_tmp(x + jcp.alpha * 1), + vreg_tmp(x + jcp.alpha * 3)); + } + + for (int i = 0; i < 16; i++) { + out_offset = sizeof(float) * (jcp.inp_stride * i); + vmovups(EVEX_compress_addr(reg_aux_ptr_dst, out_offset), + vreg_out(i)); + } + + add(reg_aux_ptr_src, sizeof(float) * jcp.ih * jcp.iw * load_block); + add(reg_aux_ptr_dst, sizeof(float) * load_block); + } + dec(reg_ic_block); + cmp(reg_ic_block, 0); + jg(ic_block_label, T_NEAR); + postamble(); +} + +/// DST TRANSFORMS ///////////////////////////////////////////////////////////// +struct jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS( + jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t) + + jit_conv_conf_2x3_wino_t jcp; + const primitive_attr_t &attr_; + + struct call_params_t { + const void *wino_dst; + const void *dst; + const void *v_y_masks; + const void *v_x_masks; + + const void *bias; + const void *scales; + }; + void (*ker_)(const call_params_t *); + + jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t( + jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr) { + generate(); + ker_ = reinterpret_cast( + const_cast(getCode())); + } + + void generate(); + bool maybe_relu(int position); + + Zmm vreg_inp(int i) { // 16 + assert(i < jcp.alpha * jcp.alpha); + return Zmm(31 - i); + } + + Zmm vreg_stg(int id) { // 8 + const int id_reg_stg = jcp.alpha * jcp.alpha + id; + assert(id_reg_stg < jcp.alpha * jcp.alpha + 8); + return Zmm(31 - id_reg_stg); + } + + Zmm vreg_out(int id) { // 4 + const int id_reg_out = jcp.alpha * jcp.alpha + 8 + id; + assert(id_reg_out < jcp.alpha * jcp.alpha + 12); + return Zmm(31 - id_reg_out); + } + + Zmm vreg_tmp(int id) { // 2 + const int id_reg_tmp = jcp.alpha * jcp.alpha + 12 + id; + assert(id_reg_tmp < jcp.alpha * jcp.alpha + 14); + return Zmm(31 - id_reg_tmp); + } + + Zmm vreg_zero = Zmm(0); + Zmm vreg_prev_dst = Zmm(0); + Zmm vreg_bias = Zmm(2); + + Opmask y_mask = Opmask(1); + Opmask r_mask = Opmask(2); + Opmask x_mask(int id) { + assert (id < 4); + return Opmask(3 + id); + } + + Reg64 reg_ptr_v_y_masks = r12; + Reg64 reg_ptr_v_x_masks = r11; + + Reg64 reg_aux_ptr_src = r10; + Reg64 reg_aux_ptr_dst = r9; + + Reg64 reg_oc_block = r8; + + Reg64 reg_ptr_bias = rbx; + Reg64 reg_ptr_scales = abi_not_param1; + Reg64 reg_ptr_sum_scale = rdx; +}; + +bool jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t::maybe_relu(int position) { + using namespace primitive_kind; + const auto &p = attr_.post_ops_; + + if (position == 0) { + /* relu before sum */ + return false + || p.contain(eltwise, 0); + } else if (position == 1) { + /* relu after sum */ + const int sum_idx = p.contain(sum, 0) + ? 0 : (p.contain(sum, 1) ? 1 : -1); + if (sum_idx == -1) + return false; + + return false + || p.contain(eltwise, sum_idx + 1); + } + + return false; +} + +void jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t::generate() { + Label oc_block_label; + + const int load_block = 16; + + auto loop_body = [=]() { + const auto &p = attr_.post_ops_; + const int sum_idx = p.find(primitive_kind::sum); + const float *p_sum_scale = (sum_idx != -1) + ? &p.entry_[sum_idx].sum.scale + : nullptr; + if (p_sum_scale && *p_sum_scale != 1.f) + mov(reg_ptr_sum_scale, (size_t)p_sum_scale); + + for (int i = 0; i < 16; i++) { + int internal_offset = sizeof(float) * jcp.out_stride * i; + vmovups(vreg_inp(i), + EVEX_compress_addr(reg_aux_ptr_src, internal_offset)); + } + for (int y = 0; y < jcp.alpha; y++) { + vaddps(vreg_tmp(0), vreg_inp(y * 4 + 0), vreg_inp(y * 4 + 1)); + vaddps(vreg_stg(y * 2), vreg_tmp(0), vreg_inp(y * 4 + 2)); + + vsubps(vreg_tmp(1), vreg_inp(y * 4 + 1), vreg_inp(y * 4 + 2)); + vsubps(vreg_stg(y * 2+1), vreg_tmp(1), vreg_inp(y * 4 + 3)); + } + for (int x = 0; x < jcp.m; x++) { + vaddps(vreg_tmp(0), vreg_stg(x), vreg_stg(x+2 * 1)); + vaddps(vreg_out(x), vreg_tmp(0), vreg_stg(x+2 * 2)); + + vsubps(vreg_tmp(1), vreg_stg(x+2 * 1), vreg_stg(x+2 * 2)); + vsubps(vreg_out(x+2), vreg_tmp(1), vreg_stg(x+2 * 3)); + } + + + if (jcp.with_bias) { + auto bias_addr = ptr [ reg_ptr_bias ]; + vmovups(vreg_bias, bias_addr); + } + for (int y = 0; y < jcp.m; y++) { + kmovw(y_mask, ptr[ reg_ptr_v_y_masks + sizeof(int16_t) * y ]); + for (int x = 0; x < jcp.m; x++) { + kandw(r_mask, y_mask, x_mask(x)); + + int i = y * jcp.m + x; + int offset = sizeof(float) * + (y * jcp.ow * jcp.oc_block + x * jcp.oc_block); + Address addr = EVEX_compress_addr(reg_aux_ptr_dst, offset); + + Zmm zmm = vreg_out(i); + if (jcp.with_bias) + vaddps(zmm, zmm, vreg_bias); + vmulps(zmm, zmm, ptr [reg_ptr_scales]); + + if (maybe_relu(0)) { + vxorps(vreg_zero, vreg_zero, vreg_zero); + vmaxps(zmm, vreg_zero, zmm); + } + if (p_sum_scale) { // post_op: sum + vxorps(vreg_prev_dst, vreg_prev_dst, vreg_prev_dst); + vmovups(vreg_prev_dst | r_mask, addr); + if (*p_sum_scale == 1.f) + vaddps(zmm, vreg_prev_dst); + else + vfmadd231ps(zmm, vreg_prev_dst, + zword_b[reg_ptr_sum_scale]); + } + if (maybe_relu(1)) { + vxorps(vreg_zero, vreg_zero, vreg_zero); + vmaxps(zmm, vreg_zero, zmm); + } + + vmovups(addr, zmm | r_mask); + } + } + }; + + preamble(); + +#define READ_PARAM(reg, field) \ + mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)]) + READ_PARAM(reg_aux_ptr_src, wino_dst); + READ_PARAM(reg_aux_ptr_dst, dst); + READ_PARAM(reg_ptr_v_y_masks, v_y_masks); + READ_PARAM(reg_ptr_v_x_masks, v_x_masks); + READ_PARAM(reg_ptr_bias, bias); + READ_PARAM(reg_ptr_scales, scales); +#undef READ_PARAM + + for (int i = 0; i < jcp.alpha * jcp.alpha; i++) + vxorps(vreg_inp(i), vreg_inp(i), vreg_inp(i)); + + for (int i = 0; i < jcp.alpha; i++) + kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(int16_t) * i]); + + int oc_blocks = 1; + oc_blocks = jcp.oc / load_block; + mov(reg_oc_block, oc_blocks); + L(oc_block_label); + { + loop_body(); + add(reg_aux_ptr_src, sizeof(float) * load_block); + add(reg_aux_ptr_dst, sizeof(float) * jcp.oh * jcp.ow * load_block); + + add(reg_ptr_scales, jcp.is_oc_scale * sizeof(float) * load_block); + add(reg_ptr_bias, jcp.typesize_bia * load_block); + } + dec(reg_oc_block); + cmp(reg_oc_block, 0); + jg(oc_block_label, T_NEAR); + + sub(reg_ptr_scales, jcp.is_oc_scale * sizeof(float) * load_block); + sub(reg_ptr_bias, oc_blocks * jcp.typesize_bia * load_block); + + postamble(); + +} + +/// GEMM kernel //////////////////////////////////////////////////////////////// +struct jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t) + jit_conv_conf_2x3_wino_t jcp; + + struct call_params_t { + const void *src; + const void *dst; + const void *wei; + const void *dst_b; + }; + void (*ker_)(const call_params_t *); + + void generate(); + static bool post_ops_ok(jit_conv_conf_2x3_wino_t &jcp, + const primitive_attr_t &attr); + + jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t( + jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr) + : jcp(ajcp) { + generate(); + ker_ = reinterpret_cast( + const_cast(getCode())); + } + + static status_t init_conf( + jit_conv_conf_2x3_wino_t &jcp, const convolution_desc_t &cd, + memory_desc_t &src_md, memory_desc_t &weights_md, + memory_desc_t &dst_md, memory_desc_t &bias_md, + const primitive_attr_t &attr, + memory_desc_t& expect_wei_md); + + Zmm vreg_out(int n, int m) { + const int id_reg_out = n * jcp.m_block + m; + assert(id_reg_out < jcp.n2_block * jcp.m_block); + return Zmm(31 - id_reg_out); + } + Zmm vreg_wei(int i) { + assert (31 - jcp.n2_block * jcp.m_block - i > 1); + return Zmm(31 - jcp.n2_block * jcp.m_block - i); + } + + Zmm vreg_src = Zmm(0); + Zmm vreg_one = Zmm(1); + Zmm vreg_tmp = Zmm(2); + + Reg64 reg_ptr_src = r15; + + Reg64 reg_aux_dst = r12; + Reg64 reg_aux_dst2 = r11; + Reg64 reg_aux_wei = r10; + Reg64 reg_aux_wei2 = r9; + Reg64 reg_aux_src = r8; + Reg64 reg_aux_src2 = rax; + + Reg64 reg_mb = rbx; + Reg64 reg_nnb = rdx; + Reg64 reg_K = rsi; + +}; + +bool jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t::post_ops_ok( + jit_conv_conf_2x3_wino_t &jcp, const primitive_attr_t &attr) { + using namespace primitive_kind; + const auto &p = attr.post_ops_; + + auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); }; + + switch (p.len_) { + case 0: return true; + case 1: return is_relu(0) || p.contain(sum, 0); + case 2: return (p.contain(sum, 0) && is_relu(1)) || + (p.contain(sum, 1) && is_relu(0)); + case 3: return is_relu(0) && p.contain(sum, 1) && is_relu(2); + default: return false; + } + + return false; +} + +void jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t::generate() { + Label nnb_loop_label, K_loop_label, mb_loop_label; + + preamble(); +#define READ_PARAM(reg, field) \ + mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)]) + READ_PARAM(reg_ptr_src, src); + READ_PARAM(reg_aux_dst, dst); + READ_PARAM(reg_aux_wei, wei); +#undef READ_PARAM + + if (!jcp.small_mb) { + mov(reg_nnb, jcp.n_chunks); + L(nnb_loop_label); + } + mov(reg_aux_dst2, reg_aux_dst); + mov(reg_aux_src, reg_ptr_src); + mov(reg_mb, jcp.M / jcp.m_block); + L(mb_loop_label); + { + int nb2 = 0; + for (nb2 = 0; nb2 < jcp.n2_block; nb2++) { + for (int m = 0; m < jcp.m_block; m++) { + vxorps(vreg_out(nb2, m), vreg_out(nb2, m), vreg_out(nb2, m)); + } + } + mov(reg_aux_src2, reg_aux_src); + mov(reg_aux_wei2, reg_aux_wei); + + mov(reg_K, jcp.k_chunks); + L(K_loop_label); { + int wei_offset = 0; + for (int _i = 0; _i < jcp.k2_block; _i++) { + for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) { + if (jcp.small_mb) { + int wei_offset = sizeof(float) + * ((nb2 * jcp.nb_ic * jcp.ic_block + * jcp.oc_block) + + _i * jcp.oc_block); + vmovups(vreg_wei(nb2), + EVEX_compress_addr(reg_aux_wei2, wei_offset)); + } else { + vmovups(vreg_wei(nb2), + EVEX_compress_addr(reg_aux_wei2, + sizeof(float) * wei_offset)); + wei_offset += jcp.oc_block; + } + } + for (int m = 0; m < jcp.m_block; m++) { + int inp_offset = sizeof(float) * (m * jcp.K + _i); + if (jcp.n2_block > 1) { + vbroadcastss(vreg_src, + EVEX_compress_addr(reg_aux_src2, inp_offset)); + for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) + vfmadd231ps(vreg_out(nb2, m), vreg_wei(nb2), + vreg_src); + } else { + vfmadd231ps(vreg_out(0, m), vreg_wei(0), + EVEX_compress_addr(reg_aux_src2, inp_offset, true)); + } + } + } + add(reg_aux_src2, sizeof(float) * jcp.ic_block); + if (jcp.small_mb) + add(reg_aux_wei2, sizeof(float) * jcp.oc_block * jcp.ic_block); + else + add(reg_aux_wei2, + sizeof(float) * jcp.k2_block * jcp.n2_block + * jcp.oc_block); + } + dec(reg_K); + cmp(reg_K, 0); + jg(K_loop_label, T_NEAR); + + for (int m = 0; m < jcp.m_block; m++) { + int nb2 = 0; + for (nb2 = 0; nb2 < jcp.n2_block; nb2++) { + int offset = sizeof(float) * + (m * jcp.N + nb2 * jcp.oc_block); + vmovups(EVEX_compress_addr(reg_aux_dst2,offset), + vreg_out(nb2, m)); + } + } + add(reg_aux_src, sizeof(float) * jcp.m_block * jcp.K); + add(reg_aux_dst2, sizeof(float) * jcp.m_block * jcp.N); + } + dec(reg_mb); + cmp(reg_mb, 0); + jg(mb_loop_label, T_NEAR); + + if (!jcp.small_mb) { + add(reg_aux_dst, sizeof(float) * jcp.n2_block * jcp.oc_block); + add(reg_aux_wei, + sizeof(float) * jcp.k_chunks * jcp.ic_block * jcp.n2_block + * jcp.oc_block); + + dec(reg_nnb); + cmp(reg_nnb, 0); + jg(nnb_loop_label, T_NEAR); + } + postamble(); +} + +namespace { +bool is_winograd_faster_than_direct(const jit_conv_conf_2x3_wino_t &jcp) { + return jcp.mb >= 4; +} +} + +status_t jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t ::init_conf( + jit_conv_conf_2x3_wino_t &jcp, const convolution_desc_t &cd, + memory_desc_t &src_md, memory_desc_t &wei_md, + memory_desc_t &dst_md, memory_desc_t &bias_md, + const primitive_attr_t &attr, memory_desc_t &expect_wei_md) { + const memory_desc_wrapper src_d(&src_md); + const memory_desc_wrapper wei_d(&wei_md); + const memory_desc_wrapper dst_d(&dst_md); + const memory_desc_wrapper bias_d(&bias_md); + + const bool with_groups = wei_d.ndims() == src_d.ndims() + 1; + + jcp.nthr = mkldnn_get_max_threads(); + + jcp.ngroups = with_groups ? wei_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = dst_d.dims()[2]; + jcp.ow = dst_d.dims()[3]; + jcp.kh = wei_d.dims()[with_groups + 2]; + jcp.kw = wei_d.dims()[with_groups + 3]; + jcp.t_pad = cd.padding[0][0]; + jcp.b_pad = cd.padding[1][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.r_pad = cd.padding[1][1]; + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + + jcp.m = 2; + jcp.r = 3; + jcp.alpha = jcp.m + jcp.r - 1; + int simdw = 16; + + format_tag_t dat_tag = format_tag::nChw16c; + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + + if (jcp.src_tag != dat_tag) return status::unimplemented; + if (jcp.dst_tag != dat_tag) return status::unimplemented; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + bool ok_to_pad_channels = jcp.ngroups == 1; + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simdw); + jcp.ic = rnd_up(jcp.ic, simdw); + } + + jcp.ver = ver_avx512_core; + if (!(mayiuse(avx512_core))) + return status::unimplemented; + + if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto, + is_winograd_faster_than_direct(jcp))) + return status::unimplemented; + + if (src_d.data_type() != data_type::f32) + return status::unimplemented; + if (wei_d.data_type() != data_type::f32) + return status::unimplemented; + if (dst_d.data_type() != data_type::f32) + return status::unimplemented; + + jcp.ic_block = simdw; + jcp.oc_block = simdw; + + bool ok = true && jcp.kh == 3 && jcp.kw == 3 && jcp.ngroups == 1 + && jcp.oc % jcp.oc_block == 0 && jcp.ic % jcp.ic_block == 0 + && jcp.stride_h == 1 && jcp.stride_w == 1 && jcp.dilate_h == 0 + && jcp.dilate_w == 0 && jcp.t_pad == jcp.b_pad + && jcp.l_pad == jcp.r_pad && jcp.t_pad < 2 && jcp.t_pad >= 0 + && jcp.l_pad < 2 && jcp.l_pad >= 0; + if (!ok) + return status::unimplemented; + + const int L2_cap = get_cache_size(2, true) / sizeof(float); + const int L3_capacity = get_cache_size(3, false) / sizeof(float); + int a = jcp.alpha; + int aa = a * a; + int mb = jcp.mb; + int ic = jcp.ic; + int oc = jcp.oc; + int ih = jcp.ih; + int iw = jcp.iw; + auto wei_sz = (float)aa * ic * oc; + auto inp_sz = (float)mb * ih * iw * ic; + auto sp_sz = (float)mb * ih * iw; + + /* Heuristics here. Numbers '28','196' is an observation from data. */ + if (wei_sz / inp_sz > 5) + jcp.small_mb = true; + else + jcp.small_mb = false; + + if (mb > nstl::min(jcp.nthr, 28) + || (!jcp.small_mb + && (wei_sz >= 0.9f * L2_cap + || inp_sz > L2_cap * jcp.nthr + L3_capacity)) + || (jcp.small_mb && sp_sz > 196)) + return status::unimplemented; + + jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef; + jcp.dst_dt = cd.dst_desc.data_type; + + jcp.typesize_bia + = jcp.with_bias ? types::data_type_size(bias_d.data_type()) : 0; + + jcp.nb_oc = jcp.oc / jcp.oc_block; + jcp.nb_ic = jcp.ic / jcp.ic_block; + + const int skx_free_regs = 30; + + auto find_m_n2_blocks = [=](int xb, int yb, int &M, int &m_block, + int &n2_block, float ®_eff) { + M = (xb * yb) / jcp.alpha; + int max_m_block = m_block = nstl::min(M, skx_free_regs); + int max_n2_block = n2_block = nstl::min(jcp.nb_oc, skx_free_regs); + reg_eff = 0; + for (int im = max_m_block; im > 0; im--) { + for (int in2 = max_n2_block; in2 > 0; in2--) { + int used_regs = in2 * im + in2; + float cur_reg_eff = ((float)in2 * im) / (im + in2) / 2.5f; + if (M % im || jcp.nb_oc % in2 || used_regs > skx_free_regs + || cur_reg_eff <= reg_eff) + continue; + reg_eff = cur_reg_eff; + m_block = im; + n2_block = in2; + } + } + }; + + int oh = jcp.oh; + int ow = jcp.ow; + int nb_oc = jcp.nb_oc; + int Z = ic + oc; + int Y = ic * oc; + const int L3_cap_per_core = get_cache_size(3, true) / sizeof(float); + + /* Selecting xb and yb blocking */ + int min_yb = jcp.alpha; + int min_xb = jcp.alpha; + int max_yb = nstl::max(min_yb, rnd_up(ih, 2)); + int max_xb = nstl::max(min_xb, rnd_up(iw, 2)); + float best_eff = 0.f; + for (int ix = max_xb; ix >= min_xb; ix -= 2) { + if (rnd_up(ow, ix) < iw - 2) + continue; + for (int iy = max_yb; iy >= min_yb; iy -= 2) { + if (rnd_up(oh, iy) < ih - 2) + continue; + int ex_y = rnd_up(oh, iy); + int ex_x = rnd_up(ow, ix); + float work_eff = (float)(ih * iw) / (ex_y * ex_x); + + int M, m_block, n2_b; + float reg_eff, thr_eff, par_eff, mem_eff, req_mem; + + find_m_n2_blocks(ix, iy, M, m_block, n2_b, reg_eff); + + /* outer parallelization */ + int nblocks = mb * div_up(ih, iy) * div_up(iw, ix); + thr_eff = (float)nblocks / rnd_up(nblocks, jcp.nthr); + + mem_eff = 1.f; + req_mem = (((float)ix + 2) * (iy + 2) + aa * M) * Z + aa * Y; + if (req_mem > L2_cap / 2) { + if (req_mem > ((L2_cap + L3_cap_per_core) * 4) / 7) + mem_eff /= (n2_b + 1) / 2.f; + else + mem_eff /= (n2_b + 1) / 3.f; + } + + float outer_eff = thr_eff + work_eff + reg_eff + mem_eff; + + /* inner parallelization */ + int bsz = iy * ix / a; + int gemmw = aa * (nb_oc / n2_b); + int bsz_r = rnd_up(bsz, jcp.nthr); + int gemmw_r = rnd_up(gemmw, jcp.nthr); + thr_eff = ((float)Z * bsz / bsz_r + Y * gemmw / gemmw_r) / (Z + Y); + + req_mem = (float)ix * iy * (ic + simdw * n2_b) + simdw * n2_b * ic; + mem_eff = nstl::min(1.f, L2_cap / req_mem); + int M_per_thr = nstl::max(2, div_up(aa, jcp.nthr)); + int oc_per_thr = + nstl::min(oc, div_up(aa * (nb_oc / n2_b), jcp.nthr)); + req_mem = (float)aa * oc_per_thr * ic + M_per_thr * M * Z; + if (req_mem > L2_cap) + mem_eff = 0.1f; + par_eff = 1 / (2.f * nblocks); + + float inner_eff = thr_eff + work_eff + mem_eff + par_eff; + + float eff = jcp.small_mb ? inner_eff : outer_eff; + if (eff > best_eff) { + best_eff = eff; + jcp.yb = iy; + jcp.xb = ix; + jcp.M = M; + jcp.m_block = m_block; + jcp.n2_block = n2_b; + } + } + } + + assert(jcp.xb % 2 == 0 && jcp.yb % 2 == 0); + + jcp.inp_stride = jcp.M * jcp.ic; + jcp.out_stride = jcp.M * jcp.oc; + jcp.wei_stride = jcp.ic * jcp.oc; + jcp.bia_stride = jcp.oc; + + jcp.N = jcp.oc; + jcp.K = jcp.ic; + + jcp.n_block = jcp.oc_block; + jcp.k_block = jcp.ic_block; + + assert(jcp.M % jcp.m_block == 0); + assert(jcp.nb_oc % jcp.n2_block == 0); + + jcp.n_chunks = jcp.nb_oc / jcp.n2_block; + jcp.k2_block = jcp.ic_block; + jcp.k_chunks = jcp.K / jcp.k2_block; + + const auto &oscales = attr.output_scales_; + jcp.is_oc_scale = oscales.mask_ == 1 << 1; + assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0)); + + /* re-create weights primitive descriptor + and set weights wino_blocking */ + expect_wei_md.format_kind = format_kind::wino; + expect_wei_md.data_type = data_type::f32; + mkldnn_wino_desc_t &wd = expect_wei_md.format_desc.wino_desc; + wd.wino_format + = jcp.small_mb ? mkldnn_wino_wei_aaOio : mkldnn_wino_wei_aaOBiOo; + wd.r = jcp.r; + wd.alpha = jcp.alpha; + wd.ic = jcp.ic; + wd.oc = jcp.oc; + wd.ic_block = jcp.ic_block; + wd.oc_block = jcp.oc_block; + wd.oc2_block = jcp.n2_block; + wd.ic2_block = 1; + wd.adj_scale = 1.f; + size_t max_size = sizeof(float) * jcp.alpha * jcp.alpha * jcp.ic * jcp.oc; + wd.size = max_size; + + return status::success; +} +//////////////////////////////////////////////////////////////////////////////// + +status_t jit_avx512_core_fp32_wino_conv_2x3_fwd_t + ::pd_t::jit_conf(memory_desc_t& expect_wei_md) { + return jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t::init_conf( + jcp_, *this->desc(), this->src_md_, this->weights_md_, + this->dst_md_,this->bias_md_, *this->attr(), expect_wei_md); +} + +jit_avx512_core_fp32_wino_conv_2x3_fwd_t:: + jit_avx512_core_fp32_wino_conv_2x3_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) +{ + kernel_ = new jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t( + pd()->jcp_, *pd()->attr()); + src_trans_ = new jit_avx512_core_fp32_wino_conv_2x3_src_trans_t( + pd()->jcp_, *pd()->attr()); + dst_trans_ = new jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t( + pd()->jcp_, *pd()->attr()); +} + +jit_avx512_core_fp32_wino_conv_2x3_fwd_t + ::~jit_avx512_core_fp32_wino_conv_2x3_fwd_t() { + delete kernel_; + delete src_trans_; + delete dst_trans_; +} + +void jit_avx512_core_fp32_wino_conv_2x3_fwd_t::execute_forward_mbN( + const float *src, const float *wei, const float *bia, float *dst, + const memory_tracking::grantor_t &scratchpad) const +{ + const auto &jcp = kernel_->jcp; + const auto &oscales = pd()->attr()->output_scales_; + + const size_t wino_size_offset = + (size_t)(pd()->jcp_.yb / 2) * (pd()->jcp_.xb / 2) + (pd()->jcp_.xb); + const size_t size_wino_src = wino_size_offset * pd()->jcp_.ic * 16; + const size_t size_wino_dst = wino_size_offset * pd()->jcp_.oc * 16; + + if (pd()->wants_padded_bias()) { + auto padded_bias = scratchpad.get(key_conv_padded_bias); + utils::array_copy(padded_bias, bia, jcp.oc_without_padding); + utils::array_set(padded_bias + jcp.oc_without_padding, 0.f, + jcp.oc - jcp.oc_without_padding); + bia = padded_bias; + } + + auto ptr_V = scratchpad.get(key_wino_V); + auto ptr_M = scratchpad.get(key_wino_M); + + parallel_nd(jcp.mb, div_up(jcp.oh,jcp.yb), div_up(jcp.ow, jcp.xb), + [&](int mb, int tile_y_b, int tile_x_b) { + int tile_y = tile_y_b * jcp.yb; + int tile_x = tile_x_b * jcp.xb; + + int ithr = mkldnn_get_thread_num(); + auto wino_src = ptr_V + size_wino_src * ithr; + auto wino_dst = ptr_M + size_wino_dst * ithr; + + auto src_trans_p = + jit_avx512_core_fp32_wino_conv_2x3_src_trans_t + ::call_params_t(); + auto dst_trans_p = + jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t + ::call_params_t(); + auto gemm_p = jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t :: + call_params_t(); + + /* transformation of input tensor to winograd domain */ + for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) { + for (int x_in_block = 0; x_in_block < jcp.xb; + x_in_block += 2) { + + unsigned short v_y_masks[4], v_x_masks[4]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (y_in_block / 2) * (jcp.xb / 2) + + (x_in_block / 2); + + int v_ys = nstl::max(0, jcp.t_pad - y); + int v_ye = nstl::min(jcp.alpha, + nstl::max(0, jcp.ih + jcp.t_pad - y)); + + int v_xs = nstl::max(0, jcp.l_pad - x); + int v_xe = nstl::min(jcp.alpha, + nstl::max(0, jcp.iw + jcp.l_pad - x)); + +#pragma unroll(4) + for (int i = 0; i < jcp.alpha; i++) { + v_y_masks[i] = (i < v_ys || i >= v_ye) ? 0 : 0xffff; + v_x_masks[i] = (i < v_xs || i >= v_xe) ? 0 : 0xffff; + } + auto local_s = src + + mb * jcp.nb_ic * jcp.ih * jcp.iw + * jcp.ic_block + + y * jcp.iw * jcp.ic_block + x * jcp.ic_block; + auto local_w = wino_src + m * jcp.ic; + + src_trans_p.src = local_s; + src_trans_p.wino_src = local_w; + src_trans_p.v_y_masks = v_y_masks; + src_trans_p.v_x_masks = v_x_masks; + + src_trans_->ker_(&src_trans_p); + } + } + /* gemms */ + for (int tile_ij = 0; tile_ij < 16; tile_ij++) { + int offset = (tile_ij + ithr) % 16; + gemm_p.src = wino_src + jcp.inp_stride * offset; + gemm_p.dst = wino_dst + jcp.out_stride * offset; + gemm_p.wei = wei + jcp.wei_stride * offset; + + kernel_->ker_(&gemm_p); + } + + /* transformation from winograd domain to output tensor */ + for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) { + for (int x_in_block = 0; x_in_block < jcp.xb; + x_in_block += 2) { + unsigned short v_y_masks[2], v_x_masks[2]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (y_in_block / 2) * (jcp.xb / 2) + + (x_in_block / 2); + +#pragma unroll(2) + for (int i = 0; i < jcp.m; i++) { + v_x_masks[i] = (x + i < jcp.ow) ? 0xffff : 0; + v_y_masks[i] = (y + i < jcp.oh) ? 0xffff : 0; + } + auto local_d = dst + + mb * jcp.nb_oc * jcp.oh * jcp.ow + * jcp.oc_block + + y * jcp.ow * jcp.oc_block + x * jcp.oc_block; + auto local_w = wino_dst + m * jcp.oc; + + auto scales = oscales.scales_; + dst_trans_p.dst = local_d; + dst_trans_p.wino_dst = local_w; + dst_trans_p.v_y_masks = v_y_masks; + dst_trans_p.v_x_masks = v_x_masks; + + dst_trans_p.scales = scales; + dst_trans_p.bias = bia; + + dst_trans_->ker_(&dst_trans_p); + } + } + }); +} + +void jit_avx512_core_fp32_wino_conv_2x3_fwd_t::execute_forward_small_mb( + const float *src, const float *wei, const float *bia, float *dst, + const memory_tracking::grantor_t &scratchpad) const +{ + const auto &jcp = kernel_->jcp; + const auto &oscales = pd()->attr()->output_scales_; + + if (pd()->wants_padded_bias()) { + auto padded_bias = scratchpad.get(key_conv_padded_bias); + utils::array_copy(padded_bias, bia, jcp.oc_without_padding); + utils::array_set(padded_bias + jcp.oc_without_padding, 0.f, + jcp.oc - jcp.oc_without_padding); + bia = padded_bias; + } + + auto ptr_V = scratchpad.get(key_wino_V); + auto ptr_M = scratchpad.get(key_wino_M); + + for (int mb = 0; mb < jcp.mb; mb++) { + for (int tile_y = 0; tile_y < jcp.oh; tile_y += jcp.yb) { + for (int tile_x = 0; tile_x < jcp.ow; tile_x += jcp.xb) { + /* transformation of input tensor to winograd domain */ + parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2), + [&](int y_in_block_b, int x_in_block_b) { + int y_in_block = y_in_block_b * 2; + int x_in_block = x_in_block_b * 2; + + auto src_trans_p = jit_avx512_core_fp32_wino_conv_2x3_src_trans_t :: + call_params_t(); + + unsigned short v_y_masks[4], v_x_masks[4]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2); + + int v_ys = nstl::max(0, jcp.t_pad - y); + int v_ye = nstl::min( + jcp.alpha, nstl::max(0, jcp.ih + jcp.t_pad - y)); + + int v_xs = nstl::max(0, jcp.l_pad - x); + int v_xe = nstl::min( + jcp.alpha, nstl::max(0, jcp.iw + jcp.l_pad - x)); + +#pragma unroll(4) + for (int i = 0; i < jcp.alpha; i++) { + v_y_masks[i] = (i < v_ys || i >= v_ye) ? 0 : 0xffff; + v_x_masks[i] = (i < v_xs || i >= v_xe) ? 0 : 0xffff; + } + auto local_s = src + + mb * jcp.nb_ic * jcp.ih * jcp.iw * jcp.ic_block + + y * jcp.iw * jcp.ic_block + x * jcp.ic_block; + auto local_w = ptr_V + m * jcp.ic; + + src_trans_p.src = local_s; + src_trans_p.wino_src = local_w; + src_trans_p.v_y_masks = v_y_masks; + src_trans_p.v_x_masks = v_x_masks; + + src_trans_->ker_(&src_trans_p); + }); + + /* gemms */ + parallel_nd(16, jcp.n_chunks, [&](int tile_ij, int nnb) { + auto gemm_p = jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t :: + call_params_t(); + + gemm_p.src = ptr_V + jcp.inp_stride * tile_ij; + gemm_p.dst = ptr_M + jcp.out_stride * tile_ij + + nnb * jcp.n2_block * jcp.n_block; + gemm_p.wei = wei + jcp.wei_stride * tile_ij + + nnb * jcp.n2_block * jcp.n_block * jcp.K; + + kernel_->ker_(&gemm_p); + }); + + /* transformation from winograd domain to output tensor */ + + parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2), + [&](int y_in_block_b, int x_in_block_b) { + int y_in_block = y_in_block_b * 2; + int x_in_block = x_in_block_b * 2; + + auto dst_trans_p = jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t :: + call_params_t(); + + unsigned short v_y_masks[2], v_x_masks[2]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2); + +#pragma unroll(2) + for (int i = 0; i < jcp.m; i++) { + v_x_masks[i] = (x + i < jcp.ow) ? 0xffff : 0; + v_y_masks[i] = (y + i < jcp.oh) ? 0xffff : 0; + } + auto local_d = dst + + mb * jcp.nb_oc * jcp.oh * jcp.ow * jcp.oc_block + + y * jcp.ow * jcp.oc_block + x * jcp.oc_block; + auto local_w = ptr_M + m * jcp.oc; + + auto scales = oscales.scales_; + dst_trans_p.dst = local_d; + dst_trans_p.wino_dst = local_w; + dst_trans_p.v_y_masks = v_y_masks; + dst_trans_p.v_x_masks = v_x_masks; + + dst_trans_p.scales = scales; + dst_trans_p.bias = bia; + + dst_trans_->ker_(&dst_trans_p); + }); + }}} +} + +} // namespace cpu +} // namespace impl +} // namespace mkldnn diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp new file mode 100644 index 0000000000..7e38b07f5a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp @@ -0,0 +1,144 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_FP32_WINO_CONV_2x3_HPP +#define CPU_JIT_AVX512_CORE_FP32_WINO_CONV_2x3_HPP + +#include + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_primitive_conf.hpp" +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t; +struct jit_avx512_core_fp32_wino_conv_2x3_src_trans_t; +struct jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t; + +struct jit_avx512_core_fp32_wino_conv_2x3_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_fp32_wino_2x3:", avx512_core, ""), + jit_avx512_core_fp32_wino_conv_2x3_fwd_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::forward_inference + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && set_default_formats(); + if (!ok) return status::unimplemented; + + memory_desc_t expect_wei_md = *weights_md(); + status_t jit_conf_result = jit_conf(expect_wei_md); + if (jit_conf_result != status::success) return jit_conf_result; + set_default_alg_kind(alg_kind::convolution_winograd); + + if (weights_md_.format_kind == format_kind::any) + weights_md_ = expect_wei_md; + if (weights_md_ != expect_wei_md) + return status::unimplemented; + + init_scratchpad(); + + return status::success; + } + + jit_conv_conf_2x3_wino_t jcp_; + + protected: + status_t jit_conf(memory_desc_t& expect_wei_md); + + void init_scratchpad() { + using namespace memory_tracking::names; + + auto scratchpad = scratchpad_registry().registrar(); + + int wino_size_offset = (jcp_.yb / 2) * (jcp_.xb / 2) + jcp_.xb; + + size_t V_sz = (size_t)jcp_.ic * 16 * wino_size_offset * jcp_.nthr; + scratchpad.book(key_wino_V, sizeof(float) * V_sz, PAGE_4K); + + size_t M_sz = (size_t)jcp_.oc * 16 * wino_size_offset * jcp_.nthr; + scratchpad.book(key_wino_M, sizeof(float) * M_sz, PAGE_4K); + + if (wants_padded_bias()) { + assert(jcp_.ngroups == 1); + scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp_.oc); + } + } + + bool set_default_formats() { + using namespace format_tag; + return set_default_formats_common(nChw16c, any, nChw16c); + } + }; + + jit_avx512_core_fp32_wino_conv_2x3_fwd_t(const pd_t *apd); + ~jit_avx512_core_fp32_wino_conv_2x3_fwd_t(); + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC); + auto wei = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS); + auto bia = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(float *, MKLDNN_ARG_DST); + + if (pd()->jcp_.small_mb) + execute_forward_small_mb(src, wei, bia, dst, this->scratchpad(ctx)); + else + execute_forward_mbN(src, wei, bia, dst, this->scratchpad(ctx)); + + return status::success; + } + +private: + void execute_forward_small_mb(const float *src, const float *wei, + const float *bia, float *dst, + const memory_tracking::grantor_t &scratchpad) const; + void execute_forward_mbN(const float *src, const float *wei, + const float *bia, float *dst, + const memory_tracking::grantor_t &scratchpad) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t *kernel_; + jit_avx512_core_fp32_wino_conv_2x3_src_trans_t *src_trans_; + jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t *dst_trans_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp new file mode 100644 index 0000000000..96325e3ade --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp @@ -0,0 +1,1020 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifdef __INTEL_COMPILER +#include +#endif + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx512_core_fp32_wino_conv_4x3.hpp" + +#ifndef _MSC_VER +#define pragma_unroll _Pragma("unroll") +#else +#define pragma_unroll +#endif + + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +template +void _jit_avx512_core_fp32_wino_conv_4x3_t +::weight_transform_data(const jit_conv_winograd_conf_t &jcp, + float *wp, float *twp) const +{ + float G[] = {0.26890756302521f, 0.688403361344538f, 0.119514472455649f, + 1.13777777777778f, 0.430252100840336f, 0.179271708683473f}; + const int kh = 3; + const int kw = 3; + float Fw[alpha][alpha][simd_w][simd_w]; + float F[kh][kw][simd_w][simd_w]; + float T[alpha][3][simd_w]; + auto p = jit_wino_transform_call_s(); + + p.src = wp; + p.dst = twp; + p.G = G; + p.M = F; + p.Mw = Fw; + p.T = T; + + kernel_->weights_transform_data_ker(&p); +} + +template +void _jit_avx512_core_fp32_wino_conv_4x3_t::output_transform_data +(int image, const jit_conv_winograd_conf_t &jcp, + const post_ops_t &p_ops, float *toutp, float *pout_b, float *bias) const { + + float G[] = {0.625f, 1.5f, 0.390625f, 2.25f, 0.244140625f, 3.375f}; + float Ow[alpha][alpha][simd_w]; + float O[tile_size][tile_size][simd_w]; + float T[tile_size][alpha][simd_w]; + + auto p = jit_wino_transform_call_s(); + p.src = toutp; + p.dst = pout_b; + p.G = G; + p.M = O; + p.Mw = Ow; + p.T = T; + p.bias = bias; + + int tile_base_index = image * jcp.itiles * jcp.jtiles; + int tile_block_ur = tile_base_index % jcp.tile_block_ur; + int nb_tile_block_ur = + (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur; + int tile_block = + (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur; + + for (int tj = 0; tj < jcp.jtiles; tj++) { + for (int ti = 0; ti < jcp.itiles; ti++) { + + p.tile_block_ur = tile_block_ur; + p.nb_tile_block_ur = nb_tile_block_ur; + p.tile_block = tile_block; + p.tj = tj; + p.ti = ti; + + kernel_->output_transform_data_ker(&p); + + tile_block_ur++; + if (tile_block_ur >= jcp.tile_block_ur) { + tile_block_ur = 0; + nb_tile_block_ur++; + } + if (nb_tile_block_ur >= jcp.nb_tile_block_ur) { + nb_tile_block_ur = 0; + tile_block++; + } + } + } +} + +template +void _jit_avx512_core_fp32_wino_conv_4x3_t +::output_transform_tileblock_data(int tile_block, + const jit_conv_winograd_conf_t &jcp, const post_ops_t &p_ops, + float *toutp, float *outp, float *bias) const { + + float G[] = {0.625f, 1.5f, 0.390625f, 2.25f, 0.244140625f, 3.375f}; + float Ow[alpha][alpha][simd_w]; + float O[tile_size][tile_size][simd_w]; + float T[tile_size][alpha][simd_w]; + + auto p = jit_wino_transform_call_s(); + p.src = toutp; + p.dst = outp; + p.G = G; + p.M = O; + p.Mw = Ow; + p.T = T; + p.bias = bias; + + int outw = is_fwd ? jcp.ow : jcp.iw; + int outh = is_fwd ? jcp.oh : jcp.ih; + + int tile_index = tile_block * jcp.nb_tile_block_ur * jcp.tile_block_ur; + + for (int nb_tile_block_ur = 0; + nb_tile_block_ur < jcp.nb_tile_block_ur; + nb_tile_block_ur++) { + + for (int tile_block_ur = 0; tile_block_ur < jcp.tile_block_ur; + tile_block_ur++) { + int img = tile_index / (jcp.jtiles * jcp.itiles); + int ti = tile_index % jcp.itiles; + int tj = (tile_index / jcp.itiles) % jcp.jtiles; + + p.tile_block_ur = tile_block_ur; + p.nb_tile_block_ur = nb_tile_block_ur; + p.tile_block = tile_block; + p.tj = tj; + p.ti = ti; + p.dst = outp + img * (jcp.dimM / jcp.dimM_simd_block) + * outh * outw * jcp.dimM_simd_block; + + kernel_->output_transform_data_ker(&p); + + tile_index++; + } + } +} + + +template +void _jit_avx512_core_fp32_wino_conv_4x3_t + ::input_transform_data(int image, const jit_conv_winograd_conf_t &jcp, + float *inp, float *tinp) const +{ + float G[] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f, + 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f}; + + float Iw[alpha][alpha][simd_w]; + float I[alpha][alpha][simd_w]; + float T[alpha][alpha][simd_w]; + + auto p = jit_wino_transform_call_s(); + + p.src = inp; + p.dst = tinp; + p.G = G; + p.M = I; + p.Mw = Iw; + p.T = T; + + int tile_base_index = image * jcp.itiles * jcp.jtiles; + int tile_block_ur = tile_base_index % jcp.tile_block_ur; + int nb_tile_block_ur = + (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur; + int tile_block = + (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur; + + for (int tj = 0; tj < jcp.jtiles; tj++) { + for (int ti = 0; ti < jcp.itiles; ti++) { + + p.tile_block_ur = tile_block_ur; + p.nb_tile_block_ur = nb_tile_block_ur; + p.tile_block = tile_block; + p.tj = tj; + p.ti = ti; + + kernel_->input_transform_data_ker(&p); + + tile_block_ur++; + if (tile_block_ur >= jcp.tile_block_ur) { + tile_block_ur = 0; + nb_tile_block_ur++; + } + if (nb_tile_block_ur >= jcp.nb_tile_block_ur) { + nb_tile_block_ur = 0; + tile_block++; + } + } + } +} + +template +void _jit_avx512_core_fp32_wino_conv_4x3_t + ::input_transform_tileblock_data(int tile_block, + const jit_conv_winograd_conf_t &jcp, + float *inp, float *tinp) const +{ + float G[] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f, + 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f}; + float Iw[alpha][alpha][simd_w]; + float I[alpha][alpha][simd_w]; + float T[alpha][alpha][simd_w]; + + const int inph = is_fwd ? jcp.ih : jcp.oh; + const int inpw = is_fwd ? jcp.iw : jcp.ow; + + array_offset_calculator input(inp, + jcp.mb, jcp.dimK / simd_w, inph, inpw, simd_w); + array_offset_calculator output(tinp, + alpha, alpha, + jcp.dimN_block, jcp.dimK_nb_block, jcp.dimK_block, + jcp.dimN_reg_block, jcp.dimK_reg_block); + + auto p = jit_wino_transform_call_s(); + + p.dst = tinp; + p.G = G; + p.M = I; + p.Mw = Iw; + p.T = T; + + + int tile_index = tile_block * jcp.nb_tile_block_ur * jcp.tile_block_ur; + + for (int nb_tile_block_ur = 0; + nb_tile_block_ur < jcp.nb_tile_block_ur; + nb_tile_block_ur++) { + + for (int tile_block_ur = 0; tile_block_ur < jcp.tile_block_ur; + tile_block_ur++) { + + int img = tile_index / (jcp.jtiles * jcp.itiles); + int ti = tile_index % jcp.itiles; + int tj = (tile_index / jcp.itiles) % jcp.jtiles; + float *pinp_b = &(input(img, 0, 0, 0, 0)); + + p.src = pinp_b; + p.tile_block_ur = tile_block_ur; + p.nb_tile_block_ur = nb_tile_block_ur; + p.tj = tj; + p.ti = ti; + + kernel_->input_transform_data_ker(&p); + + tile_index++; + } + } +} + +template +void _jit_avx512_core_fp32_wino_conv_4x3_t::_execute_data_W_S_G_D( + float *inp_ptr, float *out_ptr, float *wei_ptr, float *bias_ptr, + const memory_tracking::grantor_t &scratchpad) const { + const auto &jcp = kernel_->jcp; + const auto &p_ops = attr_->post_ops_; + + const int inph = is_fwd ? jcp.ih : jcp.oh; + const int inpw = is_fwd ? jcp.iw : jcp.ow; + const int outh = is_fwd ? jcp.oh : jcp.ih; + const int outw = is_fwd ? jcp.ow : jcp.iw; + + /* Notation: + FWD: dimM:oc, dimN:ntiles, dimK:ic, + BWD: dimM:ic, dimN:ntiles, dimK:oc, + FWD/BWD: V: src/diff_dst transform, U:weight transform, + M:dst/diff_src transform */ + array_offset_calculator input(inp_ptr, + jcp.mb, jcp.dimK/jcp.dimK_reg_block, inph, inpw, + jcp.dimK_reg_block); + array_offset_calculator output(out_ptr, + jcp.mb, jcp.dimM/jcp.dimM_simd_block, outh, outw, + jcp.dimM_simd_block); + array_offset_calculator weights(wei_ptr, + jcp.oc/jcp.oc_simd_block, jcp.ic/jcp.ic_simd_block, jcp.kh, jcp.kw, + jcp.ic_simd_block, jcp.oc_simd_block); + array_offset_calculator bias(bias_ptr, + jcp.dimM/jcp.dimM_simd_block, jcp.dimM_simd_block); + + array_offset_calculator M(is_fwd + ? scratchpad.template get(key_wino_M) + : scratchpad.template get(key_wino_V), + jcp.dimN_nb_block, jcp.dimM_nb_block, + alpha, alpha, + jcp.dimN_block, jcp.dimM_block * jcp.dimM_reg_block, + jcp.dimN_reg_block, jcp.dimM_simd_block); + + auto wino_wei = (jcp.prop_kind == prop_kind::forward_inference) + ? wei_ptr + : scratchpad.template get(key_wino_U); + + array_offset_calculator U(wino_wei, + jcp.dimM_nb_block, + alpha, alpha, + jcp.dimK_nb_block, + jcp.dimM_block * jcp.dimM_reg_block, jcp.dimK_block, + jcp.dimK_reg_block, jcp.dimM_simd_block); + array_offset_calculator V(is_fwd + ? scratchpad.template get(key_wino_V) + : scratchpad.template get(key_wino_M), + jcp.dimN_nb_block, alpha, alpha, + jcp.dimN_block, jcp.dimK_nb_block, + jcp.dimK_block, jcp.dimN_reg_block, jcp.dimK_reg_block); + + const bool wants_padded_bias = jcp.with_bias + && jcp.oc_without_padding != jcp.oc; + float last_slice_bias[simd_w] = {0}; + if (wants_padded_bias) { + for (int oc = 0; oc < jcp.oc_without_padding % jcp.oc_simd_block; ++oc) + last_slice_bias[oc] = bias(jcp.dimM / jcp.dimM_simd_block - 1, oc); + } + + { + + parallel_nd(jcp.mb, jcp.dimK_nb_block, jcp.dimK_block, + [&](int img, int K_blk1, int K_blk2) { + input_transform_data(img, jcp, + &(input(img, K_blk1 * jcp.dimK_block + K_blk2, + 0, 0, 0)), + &(V(0, 0, 0, 0, K_blk1, K_blk2, 0, 0))); + }); + + if (jcp.prop_kind != prop_kind::forward_inference) { + parallel_nd(jcp.nb_oc, jcp.nb_ic, (jcp.oc_block * jcp.oc_reg_block), + (jcp.ic_block * jcp.ic_reg_block), + [&](int ofm1, int ifm1, int ofm2, int ifm2) { + float *U_base_ptr = is_fwd + ? &(U(ofm1, 0, 0, ifm1, ofm2, ifm2, 0, 0)) + : &(U(ifm1, 0, 0, ofm1, ifm2, ofm2, 0, 0)); + weight_transform_data(jcp, + &(weights( + ofm1 * jcp.oc_block * jcp.oc_reg_block + ofm2, + ifm1 * jcp.ic_block * jcp.ic_reg_block + ifm2, + 0, 0, 0, 0)), + U_base_ptr); + }); + } + + parallel_nd(jcp.dimN_nb_block, alpha, alpha, jcp.dimM_nb_block, + [&](int N_blk1, int oj, int oi, int M_blk1) { + for (int K_blk1 = 0; K_blk1 < jcp.dimK_nb_block; + K_blk1++) + for (int N_blk2 = 0; N_blk2 < jcp.dimN_block; N_blk2++) + kernel_->gemm_loop_ker( + (float *)&(M(N_blk1, M_blk1, oj, oi, + N_blk2, 0, 0, 0)), + (const float *)&(U(M_blk1, oj, oi, + K_blk1, 0, 0, 0, 0)), + (const float *)&(V(N_blk1, oj, oi, + N_blk2, K_blk1, 0, 0, 0)), K_blk1); + }); + + parallel_nd(jcp.mb, jcp.dimM_nb_block, (jcp.dimM_block * jcp.dimM_reg_block), + [&](int img, int M_blk1, int M_blk2) { + const int M_blk = + M_blk1 * jcp.dimM_block * jcp.dimM_reg_block + M_blk2; + + float *bias_ptr = wants_padded_bias + && M_blk == jcp.dimM / jcp.dimM_simd_block - 1 + ? last_slice_bias : &bias(M_blk, 0); + output_transform_data(img, jcp, p_ops, + &(M(0, M_blk1, 0, 0, 0, M_blk2, 0, 0)), + &(output(img, M_blk, 0, 0, 0)), bias_ptr); + }); + + } +} + +template +void _jit_avx512_core_fp32_wino_conv_4x3_t::_execute_data_W_SGD( + float *inp_ptr, float *out_ptr, float *wei_ptr, float *bias_ptr, + const memory_tracking::grantor_t &scratchpad) const { + const auto &jcp = kernel_->jcp; + const auto &p_ops = attr_->post_ops_; + + const int inph = is_fwd ? jcp.ih : jcp.oh; + const int inpw = is_fwd ? jcp.iw : jcp.ow; + const int outh = is_fwd ? jcp.oh : jcp.ih; + const int outw = is_fwd ? jcp.ow : jcp.iw; + + array_offset_calculator input(inp_ptr, + jcp.mb, jcp.dimK/jcp.dimK_reg_block, inph, inpw, jcp.dimK_reg_block); + array_offset_calculator output(out_ptr, + jcp.mb, jcp.dimM/jcp.dimM_simd_block, outh, outw, jcp.dimM_simd_block); + array_offset_calculator weights(wei_ptr, + jcp.oc/jcp.oc_simd_block, jcp.ic/jcp.ic_simd_block, jcp.kh, jcp.kw, + jcp.ic_simd_block, jcp.oc_simd_block); + array_offset_calculator bias(bias_ptr, + jcp.oc/jcp.oc_simd_block, jcp.oc_simd_block); + + auto wino_wei = (jcp.prop_kind == prop_kind::forward_inference) + ? wei_ptr + : scratchpad.template get(key_wino_U); + + array_offset_calculator U(wino_wei, + jcp.dimM_nb_block, + alpha, alpha, + jcp.dimK_nb_block, + jcp.dimM_block * jcp.dimM_reg_block, jcp.dimK_block, + jcp.dimK_reg_block, jcp.dimM_simd_block); + + array_offset_calculator M(is_fwd + ? scratchpad.template get(key_wino_M) + : scratchpad.template get(key_wino_V), + 0, jcp.dimM_nb_block, alpha, alpha, + jcp.dimN_block, jcp.dimM_block * jcp.dimM_reg_block, + jcp.dimN_reg_block, jcp.dimM_simd_block); + array_offset_calculator V(is_fwd + ? scratchpad.template get(key_wino_V) + : scratchpad.template get(key_wino_M), + 0, alpha, alpha, jcp.dimN_block, + jcp.dimK_nb_block, jcp.dimK_block, + jcp.dimN_reg_block, jcp.dimK_reg_block); + + const bool wants_padded_bias = jcp.with_bias + && jcp.oc_without_padding != jcp.oc; + float last_slice_bias[simd_w] = {0}; + if (wants_padded_bias) { + for (int oc = 0; oc < jcp.oc_without_padding % jcp.oc_simd_block; ++oc) + last_slice_bias[oc] = bias(jcp.dimM / jcp.dimM_simd_block - 1, oc); + } + + if (jcp.prop_kind != prop_kind::forward_inference) { + + parallel_nd(jcp.nb_oc, jcp.nb_ic, (jcp.oc_block * jcp.oc_reg_block), (jcp.ic_block * jcp.ic_reg_block), + [&](int ofm1, int ifm1, int ofm2, int ifm2) { + float *U_base_ptr = is_fwd + ? &(U(ofm1, 0, 0, ifm1, ofm2, ifm2, 0, 0)) + : &(U(ifm1, 0, 0, ofm1, ifm2, ofm2, 0, 0)); + weight_transform_data(jcp, + &(weights( + ofm1 * jcp.oc_block * jcp.oc_reg_block + ofm2, + ifm1 * jcp.ic_block * jcp.ic_reg_block + ifm2, + 0, 0, 0, 0)), + U_base_ptr); + }); + } + + parallel_nd(jcp.tile_block, [&](int tile_block) { + int ithr = mkldnn_get_thread_num(); + + for (int K_blk1 = 0; K_blk1 < jcp.dimK_nb_block; K_blk1++) { + for (int K_blk2 = 0; K_blk2 < jcp.dimK_block; K_blk2++) { + + input_transform_tileblock_data( + tile_block, jcp, + &(input(0, K_blk1 * jcp.dimK_block + K_blk2, 0, 0, 0)), + &(V(ithr, 0, 0, 0, K_blk1, K_blk2, 0, 0))); + } + } + + for (int oj = 0; oj < alpha; oj++) { + for (int oi = 0; oi < alpha; oi++) { + for (int M_blk1 = 0; M_blk1 < jcp.dimM_nb_block; M_blk1++) + for (int K_blk1 = 0; K_blk1 < jcp.dimK_nb_block; K_blk1++) + for (int N_blk = 0; N_blk < jcp.dimN_block; N_blk++) + kernel_->gemm_loop_ker( + (float *)&(M(ithr, M_blk1, oj, oi, + N_blk, 0, 0, 0)), + (const float *)&(U(M_blk1, oj, oi, K_blk1, + 0, 0, 0, 0)), + (const float *)&(V(ithr, oj, oi, + N_blk, K_blk1, 0, 0, 0)), K_blk1); + } + } + + for (int M_blk1 = 0; M_blk1 < jcp.dimM_nb_block; M_blk1++) { + for (int M_blk2 = 0; M_blk2 < jcp.dimM_block * jcp.dimM_reg_block; + M_blk2++) { + const int M_blk = + M_blk1 * jcp.dimM_block * jcp.dimM_reg_block + M_blk2; + + float *bias_ptr = wants_padded_bias + && M_blk == jcp.dimM / jcp.dimM_simd_block - 1 + ? last_slice_bias : &bias(M_blk, 0); + + output_transform_tileblock_data(tile_block, jcp, p_ops, + &(M(ithr, M_blk1, 0, 0, 0, M_blk2, 0, 0)), + &(output(0, M_blk, 0, 0, 0)), bias_ptr); + } + } + }); +} + +template struct _jit_avx512_core_fp32_wino_conv_4x3_t; +template struct _jit_avx512_core_fp32_wino_conv_4x3_t; + +namespace { + +void subarray_sum(size_t num_arrs, float *output, size_t nelems, + float *input_ptrs[], size_t input_starts[], size_t input_ends[]) { + using namespace nstl; + const size_t block_size = 16 * 1024 / sizeof(float); + const size_t blocks_number = nelems / block_size; + const size_t tail = nelems % block_size; + +PRAGMA_OMP(parallel) + { + const int ithr = mkldnn_get_thread_num(); + const int nthr = mkldnn_get_num_threads(); + size_t start{ 0 }, end{ 0 }; + balance211(blocks_number, nthr, ithr, start, end); + + for (size_t nb = start; nb < end; ++nb) { + size_t start_e = nb * block_size; + size_t end_e = start_e + block_size; + size_t input_start = max(start_e, min(input_starts[0], end_e)); + size_t input_end = max(start_e, min(input_ends[0], end_e)); + + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < input_start; e++) { + output[e] = 0.f; + } + + PRAGMA_OMP_SIMD() + for (size_t e = input_start; e < input_end; e++) { + output[e] = input_ptrs[0][e]; + } + + PRAGMA_OMP_SIMD() + for (size_t e = input_end; e < end_e; e++) { + output[e] = 0.f; + } + + for (size_t a = 1; a < num_arrs; a++) { + input_start = max(start_e, input_starts[a]); + input_end = min(input_ends[a], end_e); + + PRAGMA_OMP_SIMD() + for (size_t e = input_start; e < input_end; e++) { + output[e] += input_ptrs[a][e]; + } + } + } + + if (tail != 0 && ithr == nthr - 1) { + size_t start_e = nelems - tail; + size_t end_e = nelems; + size_t input_start = max(start_e, min(input_starts[0], end_e)); + size_t input_end = max(start_e, min(input_ends[0], end_e)); + + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < input_start; e++) { + output[e] = 0.f; + } + + PRAGMA_OMP_SIMD() + for (size_t e = input_start; e < input_end; e++) { + output[e] = input_ptrs[0][e]; + } + + PRAGMA_OMP_SIMD() + for (size_t e = input_end; e < end_e; e++) { + output[e] = 0.f; + } + + for (size_t a = 1; a < num_arrs; a++) { + input_start = max(start_e, input_starts[a]); + input_end = min(input_ends[a], end_e); + + PRAGMA_OMP_SIMD() + for (size_t e = input_start; e < input_end; e++) { + output[e] += input_ptrs[a][e]; + } + } + } + } +} + +const int max_threads_number = 1024; + +// Sum to the first buffer array +void array_sum(size_t num_arrs, float *output, + size_t nelems, float *input_ptrs[], bool reduce_to_first = true) { + const size_t block_size = 16 * 1024 / sizeof(float); + const size_t blocks_number = nelems / block_size; + const size_t tail = nelems % block_size; + +PRAGMA_OMP(parallel) + { + const size_t ithr = mkldnn_get_thread_num(); + const size_t nthr = mkldnn_get_num_threads(); + size_t start{ 0 }, end{ 0 }; + balance211(blocks_number, nthr, ithr, start, end); + + for (size_t nb = start; nb < end; ++nb) { + size_t start_e = nb * block_size; + size_t end_e = start_e + block_size; + if (!reduce_to_first) { + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] = input_ptrs[0][e]; + } + } + for (size_t a = 1; a < num_arrs; a++) { + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] += input_ptrs[a][e]; + } + } + } + + if (tail != 0 && ithr == nthr - 1) { + size_t start_e = nelems - tail; + size_t end_e = nelems; + if (!reduce_to_first) { + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] = input_ptrs[0][e]; + } + } + for (size_t a = 1; a < num_arrs; a++) { + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] += input_ptrs[a][e]; + } + } + } + } +} +} //bwdw namespace + +void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t:: +_execute_backward_weights_SDGtWo(const float *ptr_src, + const float *ptr_diff_dst, float *ptr_diff_weights, + float *ptr_diff_bias, + const memory_tracking::grantor_t &scratchpad) const { + const auto &jcp = kernel_->jcp; + const int nthreads = jcp.nthr; + + array_offset_calculator src((float *)ptr_src, + jcp.mb, jcp.ic / simd_w, jcp.ih, jcp.iw, simd_w); + array_offset_calculator diff_dst((float *)ptr_diff_dst, + jcp.mb, jcp.oc / simd_w, jcp.oh, jcp.ow, simd_w); + array_offset_calculator diff_weights(ptr_diff_weights, + jcp.oc / simd_w, jcp.ic / simd_w, jcp.kh, jcp.kw, simd_w, simd_w); + + array_offset_calculator Us(scratchpad.get(key_wino_U), + 0, alpha, alpha, + jcp.oc_block, jcp.ic_block, + jcp.ic_simd_block, + jcp.oc_reg_block, + jcp.oc_simd_block); + + const int U_sz = nthreads * alpha * alpha * jcp.oc / jcp.nb_oc + * jcp.ic / jcp.nb_ic; + array_offset_calculatordiff_weights_prv( + scratchpad.get(key_wino_U) + U_sz, + 0, jcp.oc / simd_w, jcp.ic / simd_w, jcp.kh, jcp.kw, simd_w, simd_w); + + array_offset_calculator M(scratchpad.get(key_wino_M), + 0, alpha, alpha, + jcp.oc_block, + jcp.nb_tile_block_ur, + jcp.tile_block_ur, + jcp.oc_reg_block, + jcp.oc_simd_block); + + array_offset_calculator V(scratchpad.get(key_wino_V), + 0, alpha, alpha, + jcp.ic_block, + jcp.nb_tile_block_ur, + jcp.tile_block_ur, + jcp.ic_simd_block); + + array_offset_calculator diff_bias_prv( + scratchpad.get(key_conv_bia_reduction), nthreads, jcp.oc); + + auto trans_ker_p = jit_wino_transform_call_s(); + float I[alpha][alpha][simd_w]; + float T[alpha][alpha][simd_w]; + float G_I_3x3_4x4[9] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f, + 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f}; + float G_W_3x3_4x4[8] = {0.26890756302521f, -0.688403361344538f, 0.119514472455649f, + 0.430252100840336f, 0.168067226890756f, 0.179271708683473f, 0.403361344537815f, + 1.13777777777778f}; + float G_O_3x3_4x4[4] = {2.25f, 0.625f, 1.5f, 0.390625f}; + +PRAGMA_OMP(parallel num_threads(nthreads) firstprivate(trans_ker_p, I, T)) +{ + if (jcp.with_bias) { + parallel_nd_in_omp(nthreads, jcp.oc / simd_w, + [&](int ithr, int ofm){ + float *pdbias = &(diff_bias_prv(ithr, ofm * simd_w)); + PRAGMA_OMP_SIMD() + for (int v = 0; v < simd_w; v++) { + pdbias[v] = 0.0f; + } + }); + } + + int ithr = mkldnn_get_thread_num(); + for (int ifm1 = 0; ifm1 < jcp.nb_ic; ++ifm1) { + int first_tblk = 0; +PRAGMA_OMP(for) + for (int tblk1 = 0; tblk1 < jcp.tile_block; ++tblk1) { + int tile_index = tblk1 * jcp.nb_tile_block_ur * jcp.tile_block_ur; + int img = tile_index / (jcp.itiles * jcp.jtiles); + trans_ker_p.ti = tile_index % jcp.itiles; + trans_ker_p.tj = (tile_index / jcp.itiles) % jcp.jtiles; + trans_ker_p.M = I; + trans_ker_p.T = T; + trans_ker_p.G = G_I_3x3_4x4; + for (int ifm2 = 0; ifm2 < jcp.ic_block; ++ifm2) { + int ifm = ifm1 * jcp.ic_block + ifm2; + trans_ker_p.src = (float *)&(src(img, ifm, 0, 0, 0)); + trans_ker_p.dst = (float *)&(V(ithr, 0, 0, ifm2, 0, 0, 0)); + kernel_->src_transform(&trans_ker_p); + } + + for (int ofm1 = 0; ofm1 < jcp.nb_oc; ++ofm1) { + trans_ker_p.G = G_W_3x3_4x4; + for (int ofm2 = 0; ofm2 < jcp.oc_block; ++ofm2) { + int ofm = (ofm1 * jcp.oc_block + ofm2) * jcp.oc_reg_block; + trans_ker_p.src = (float *)&(diff_dst(img, ofm, 0, 0, 0)); + trans_ker_p.dst = (float *)&(M(ithr, 0, 0, ofm2, 0, 0, 0, 0)); + if (jcp.with_bias && ifm1 == 0) { + trans_ker_p.bias = (float *)&(diff_bias_prv(ithr, ofm * simd_w)); + kernel_->diff_dst_transform_wbias(&trans_ker_p); + } else { + kernel_->diff_dst_transform(&trans_ker_p); + } + } + + for (int oj = 0; oj < alpha; ++oj) { + for (int oi = 0; oi < alpha; ++oi) { + kernel_->gemm_loop_ker_first_iter( + &(Us(ithr, oj, oi, 0, 0, 0, 0, 0)), + &(M(ithr, oj, oi, 0, 0, 0, 0, 0)), + &(V(ithr, oj, oi, 0, 0, 0, 0))); + } + } + trans_ker_p.G = G_O_3x3_4x4; + for (int ofm2 = 0; ofm2 < jcp.oc_block; ++ofm2) { + for (int ofm3 = 0; ofm3 < jcp.oc_reg_block; ++ofm3) { + int ofm = (ofm1 * jcp.oc_block + ofm2) * jcp.oc_reg_block + + ofm3; + for (int ifm2 = 0; ifm2 < jcp.ic_block; ++ifm2) { + int ifm = ifm1 * jcp.ic_block + ifm2; + trans_ker_p.src = (float *)&(Us(ithr, 0, 0, + ofm2, ifm2, 0, ofm3, 0)); + trans_ker_p.dst = (float *)&(diff_weights_prv(ithr, + ofm, ifm, 0, 0, 0, 0)); + if (first_tblk == 0) { + kernel_->diff_weights_transform(&trans_ker_p); + } else { + kernel_->diff_weights_transform_accum(&trans_ker_p); + } + } + } + } + } + ++first_tblk; + } + } +} + + // Reduce diff-weights + { + float *output = ptr_diff_weights; + float *input_base = scratchpad.get(key_wino_U) + U_sz; + int nelems = jcp.oc * jcp.ic * jcp.kh * jcp.kw; + float *input_ptrs[max_threads_number]; + for (int i = 0; i < nthreads; ++i) { + input_ptrs[i] = input_base + nelems * i; + } + array_sum(nthreads, output, nelems, input_ptrs, false); + + if (jcp.with_bias) { + output = ptr_diff_bias; + input_base = scratchpad.get(key_conv_bia_reduction); + for (int i = 0; i < nthreads; ++i) { + input_ptrs[i] = input_base + jcp.oc * i; + } + array_sum(nthreads, output, jcp.oc_without_padding, input_ptrs, + false); + } + } +} + +void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t:: +_execute_backward_weights_S_D_Giot_W(const float *ptr_src, + const float *ptr_diff_dst, float *ptr_diff_weights, + float *ptr_diff_bias, + const memory_tracking::grantor_t &scratchpad) const { + const auto &jcp = kernel_->jcp; + const int nthreads = jcp.nthr; + + array_offset_calculator src((float *)ptr_src, + jcp.mb, jcp.ic / simd_w, jcp.ih, jcp.iw, simd_w); + array_offset_calculator diff_dst((float *)ptr_diff_dst, + jcp.mb, jcp.oc / simd_w, jcp.oh, jcp.ow, simd_w); + array_offset_calculator diff_weights((float *)ptr_diff_weights, + jcp.oc / simd_w, jcp.ic / simd_w, jcp.kh, jcp.kw, simd_w, simd_w); + array_offset_calculator diff_bias((float *)ptr_diff_bias, jcp.oc); + + array_offset_calculator U(scratchpad.get(key_wino_U), + jcp.nb_ic, jcp.nb_oc, + alpha, alpha, + jcp.oc_block, jcp.ic_block, + jcp.ic_simd_block, + jcp.oc_reg_block, + jcp.oc_simd_block); + + const int U_size = jcp.oc * jcp.ic * alpha * alpha; + array_offset_calculator Us( + scratchpad.get(key_wino_U) + U_size, + 0, jcp.nb_ic, jcp.nb_oc, + alpha, alpha, + jcp.oc_block, jcp.ic_block, + jcp.ic_simd_block, + jcp.oc_reg_block, + jcp.oc_simd_block); + + array_offset_calculator M(scratchpad.get(key_wino_M), + jcp.nb_oc, + jcp.tile_block, + alpha, alpha, + jcp.oc_block, + jcp.nb_tile_block_ur, + jcp.tile_block_ur , + jcp.oc_reg_block, + jcp.oc_simd_block); + + array_offset_calculator V(scratchpad.get(key_wino_V), + jcp.nb_ic, + jcp.tile_block, + alpha, alpha, + jcp.ic_block, + jcp.nb_tile_block_ur, jcp.tile_block_ur, + jcp.ic_simd_block); + + array_offset_calculator diff_bias_prv( + scratchpad.get(key_conv_bia_reduction), nthreads, jcp.oc); + + size_t input_starts[max_threads_number] = {0}; + size_t input_ends[max_threads_number] = {0}; + size_t first_tblk = 0; + + auto trans_ker_p = jit_wino_transform_call_s(); + float G_I_3x3_4x4[9] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f, + 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f}; + float G_W_3x3_4x4[8] = {0.26890756302521f, -0.688403361344538f, + 0.119514472455649f, 0.430252100840336f, 0.168067226890756f, + 0.179271708683473f, 0.403361344537815f, 1.13777777777778f}; + float G_O_3x3_4x4[4] = {2.25f, 0.625f, 1.5f, 0.390625f}; + float I[alpha][alpha][simd_w]; + float T[alpha][alpha][simd_w]; + +PRAGMA_OMP(parallel firstprivate(first_tblk, trans_ker_p, I, T)) +{ + if (jcp.with_bias) { + parallel_nd_in_omp(nthreads, jcp.oc, [&](int ithr, int ofm) { + diff_bias_prv(ithr, ofm) = 0.0f; + }); + } + + trans_ker_p.G = G_I_3x3_4x4; + trans_ker_p.M = I; + trans_ker_p.T = T; + + parallel_nd_in_omp(jcp.nb_ic, jcp.ic_block, jcp.mb, + [&](int ifm1, int ifm2, int img){ + size_t ifm = ifm1 * jcp.ic_block + ifm2; + size_t tile_base_index = img * (jcp.itiles * jcp.jtiles); + size_t tblk3 = tile_base_index % jcp.tile_block_ur; + size_t tblk2 = (tile_base_index / jcp.tile_block_ur) + % jcp.nb_tile_block_ur; + size_t tblk1 = (tile_base_index / jcp.tile_block_ur) + / jcp.nb_tile_block_ur; + trans_ker_p.tile_count = tblk2 * jcp.tile_block_ur + tblk3; + trans_ker_p.src = (float *)&(src(img, ifm, 0, 0, 0)); + trans_ker_p.dst = (float *)&(V(ifm1, tblk1, 0, 0, ifm2, 0, 0, 0)); + kernel_->src_transform(&trans_ker_p); + }); + + int ithr = mkldnn_get_thread_num(); + trans_ker_p.G = G_W_3x3_4x4; + parallel_nd_in_omp(jcp.nb_oc, jcp.oc_block, jcp.mb, + [&](int ofm1, int ofm2, int img){ + int ofm = (ofm1 * jcp.oc_block + ofm2) * jcp.oc_reg_block; + size_t tile_base_index = img * (jcp.itiles * jcp.jtiles); + size_t tblk3 = tile_base_index % jcp.tile_block_ur; + size_t tblk2 = (tile_base_index / jcp.tile_block_ur) + % jcp.nb_tile_block_ur; + size_t tblk1 = (tile_base_index / jcp.tile_block_ur) + / jcp.nb_tile_block_ur; + trans_ker_p.tile_count = tblk2 * jcp.tile_block_ur + tblk3; + trans_ker_p.src = (float *)&(diff_dst(img, ofm, 0, 0, 0)); + trans_ker_p.dst = (float *)&(M(ofm1, tblk1, 0, 0, ofm2, 0, 0, 0, 0)); + if (jcp.with_bias) { + trans_ker_p.bias = (float *)&(diff_bias_prv(ithr, ofm * simd_w)); + kernel_->diff_dst_transform_wbias(&trans_ker_p); + } else { + kernel_->diff_dst_transform(&trans_ker_p); + } + }); + + PRAGMA_OMP(barrier) + + parallel_nd_in_omp(jcp.nb_ic, jcp.nb_oc, alpha, alpha, jcp.tile_block, + [&](int ifm1, int ofm1, int oj, int oi, int tblk1){ + if (first_tblk == 0) { + input_starts[ithr] = + (float *)&(Us(ithr, ifm1, ofm1, oj, oi, 0, 0, 0, + 0, 0)) + - (float *)&(Us(ithr, 0, 0, 0, 0, 0, 0, + 0, 0, 0)); + input_ends[ithr] = input_starts[ithr] + + jcp.oc_block * jcp.ic_block + * jcp.ic_simd_block * jcp.oc_reg_block + * jcp.oc_simd_block; + } + else if (tblk1 == 0) { + input_ends[ithr] += jcp.oc_block * jcp.ic_block + * jcp.ic_simd_block * jcp.oc_reg_block + * jcp.oc_simd_block; + } + + if (first_tblk == 0 || tblk1 == 0) { + kernel_->gemm_loop_ker_first_iter( + &(Us(ithr, ifm1, ofm1, oj, oi, + 0, 0, 0, 0, 0)), + &(M(ofm1, tblk1, oj, oi, 0, 0, 0, 0, 0)), + &(V(ifm1, tblk1, oj, oi, 0, 0, 0, 0))); + } else { + kernel_->gemm_loop_ker( + &(Us(ithr, ifm1, ofm1, oj, oi, + 0, 0, 0, 0, 0)), + &(M(ofm1, tblk1, oj, oi, 0, 0, 0, 0, 0)), + &(V(ifm1, tblk1, oj, oi, 0, 0, 0, 0))); + } + ++first_tblk; + }); +} + + // Reduce diff-weights + { + float *output = &(U(0, 0, 0, 0, 0, 0, 0, 0, 0)); + size_t nelems = jcp.ic * jcp.oc * alpha * alpha; + float *input_ptrs[max_threads_number]; + for (int i = 0; i < nthreads; ++i) + input_ptrs[i] = output + nelems * (i + 1); + subarray_sum(nthreads, output, nelems, input_ptrs, + input_starts, input_ends); + } + + trans_ker_p.G = G_O_3x3_4x4; +PRAGMA_OMP(parallel firstprivate(trans_ker_p)) + { + parallel_nd_in_omp(jcp.nb_ic, jcp.nb_oc, jcp.oc_block, jcp.ic_block, jcp.oc_reg_block, + [&](int ifm1, int ofm1, int ofm2, int ifm2, int ofm3){ + int ofm = (ofm1 * jcp.oc_block + ofm2) + * jcp.oc_reg_block + ofm3; + int ifm = ifm1 * jcp.ic_block + ifm2; + trans_ker_p.src = (float *)&(U(ifm1, ofm1, 0, 0, + ofm2, ifm2, 0, ofm3, 0)); + trans_ker_p.dst = (float *)&(diff_weights(ofm, ifm, + 0, 0, 0, 0)); + kernel_->diff_weights_transform(&trans_ker_p); + }); + } + + if (jcp.with_bias) { + parallel_nd(jcp.oc / simd_w, [&](int ofm1) { + float* pbias = &(diff_bias(ofm1 * simd_w)); + float *pbias_prv = &(diff_bias_prv(0, ofm1 * simd_w)); + + const int blk_sz = ofm1 == jcp.oc / simd_w - 1 + ? jcp.oc_without_padding - ofm1 * simd_w : simd_w; + + PRAGMA_OMP_SIMD() + for (int ofm2 = 0; ofm2 < blk_sz; ++ofm2) { + pbias[ofm2] = pbias_prv[ofm2]; + } + + for (int ithr = 1; ithr < nthreads; ++ithr) { + pbias_prv = &(diff_bias_prv(ithr, ofm1 * simd_w)); + PRAGMA_OMP_SIMD() + for (int ofm2 = 0; ofm2 < blk_sz; ++ofm2) { + pbias[ofm2] += pbias_prv[ofm2]; + } + } + }); + } +} + +} +} +} +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp new file mode 100644 index 0000000000..f1a56aac70 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp @@ -0,0 +1,386 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_FP32_WINO_CONV_4x3_HPP +#define CPU_JIT_AVX512_CORE_FP32_WINO_CONV_4x3_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace winograd_avx512_core { +inline void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_winograd_conf_t &jcp) { + using namespace utils; + using namespace memory_tracking::names; + + size_t U_sz = (size_t)alpha * alpha * jcp.ic * jcp.oc; + size_t V_sz = (size_t)alpha * alpha * jcp.mb * jcp.ic * jcp.itiles + * jcp.jtiles; + size_t M_sz = (size_t)alpha * alpha * jcp.mb * jcp.oc * jcp.itiles + * jcp.jtiles; + + switch (jcp.sched_policy) { + case WSCHED_DATA_W_SGD: + V_sz = (size_t)jcp.nthr * alpha * alpha * jcp.nb_tile_block_ur + * jcp.tile_block_ur * jcp.ic; + M_sz = (size_t)jcp.nthr * alpha * alpha * jcp.nb_tile_block_ur + * jcp.tile_block_ur * jcp.oc; + break; + case WSCHED_WEI_SDGtWo: + U_sz = (size_t)jcp.nthr * (alpha * alpha * jcp.oc + * (jcp.ic / jcp.nb_ic) + jcp.ic * jcp.oc * jcp.kh * jcp.kw); + M_sz = (size_t)jcp.nthr * alpha * alpha * (jcp.ntiles / jcp.tile_block) + * (jcp.oc / jcp.nb_oc); + V_sz = (size_t)jcp.nthr * alpha * alpha * (jcp.ntiles / jcp.tile_block) + * (jcp.ic / jcp.nb_ic); + break; + case WSCHED_WEI_S_D_Giot_W: + U_sz = (size_t)(jcp.nthr + 1) * alpha * alpha * jcp.ic * jcp.oc; + M_sz = (size_t)alpha * alpha * jcp.oc * jcp.ntiles; + V_sz = (size_t)alpha * alpha * jcp.ic * jcp.ntiles; + break; + default: break; + } + + scratchpad.book(key_wino_U, sizeof(float) * U_sz, PAGE_2M); + scratchpad.book(key_wino_V, sizeof(float) * V_sz, PAGE_2M); + scratchpad.book(key_wino_M, sizeof(float) * M_sz, PAGE_2M); + + if (one_of(jcp.sched_policy, WSCHED_WEI_SDGtWo, WSCHED_WEI_S_D_Giot_W)) { + size_t br_sz = (size_t)jcp.nthr * jcp.oc; + scratchpad.book(key_conv_bia_reduction, sizeof(float) * br_sz, PAGE_2M); + } +} +} + +template +struct _jit_avx512_core_fp32_wino_conv_4x3_t { + + _jit_avx512_core_fp32_wino_conv_4x3_t( + const jit_conv_winograd_conf_t &jcp, const primitive_attr_t *attr) + : kernel_(nullptr), attr_(attr) { + kernel_ = new _jit_avx512_core_fp32_wino_conv_4x3_data_kernel(jcp); + } + + ~_jit_avx512_core_fp32_wino_conv_4x3_t() { delete kernel_; } + + protected: + void weight_transform_data(const jit_conv_winograd_conf_t &jcp, + float *wp, float *twp) const; + void input_transform_data(int image, + const jit_conv_winograd_conf_t &jcp, + float *inp, float *tinp) const; + void input_transform_tileblock_data(int tile_block, + const jit_conv_winograd_conf_t &jcp, + float *inp, float *tinp) const; + void output_transform_data(int image, + const jit_conv_winograd_conf_t &jcp, + const post_ops_t &p_ops, float *toutp, float *pout_b, + float *bias) const; + void output_transform_tileblock_data(int tile_block, + const jit_conv_winograd_conf_t &jcp, const post_ops_t &p_ops, + float *toutp, float *outp, float *bias) const; + void _execute_data_W_S_G_D(float *inp_ptr, float *out_ptr, + float *wei_ptr, float *bias_ptr, + const memory_tracking::grantor_t &scratchpad) const; + void _execute_data_W_SGD(float *inp_ptr, float *out_ptr, + float *wei_ptr, float *bias_ptr, + const memory_tracking::grantor_t &scratchpad) const; + _jit_avx512_core_fp32_wino_conv_4x3_data_kernel *kernel_; + const primitive_attr_t *attr_; +}; + +struct jit_avx512_core_fp32_wino_conv_4x3_fwd_t + : _jit_avx512_core_fp32_wino_conv_4x3_t + , public cpu_primitive_t + { + struct pd_t : public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_wino_4x3:", avx512_core, ""), + jit_avx512_core_fp32_wino_conv_4x3_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel:: + init_conf(jcp_, *desc(), src_md_, weights_md_, dst_md_, + *attr()); + if (status != status::success) return status; + set_default_alg_kind(alg_kind::convolution_winograd); + + auto scratchpad = scratchpad_registry().registrar(); + winograd_avx512_core::init_scratchpad(scratchpad, jcp_); + + return status; + } + + jit_conv_winograd_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + auto wei_fmt = desc()->prop_kind == prop_kind::forward_training + ? (with_groups() ? gOIhw16i16o : OIhw16i16o) : any; + return set_default_formats_common(nChw16c, wei_fmt, nChw16c); + } + }; + + jit_avx512_core_fp32_wino_conv_4x3_fwd_t(const pd_t *apd) + : _jit_avx512_core_fp32_wino_conv_4x3_t(apd->jcp_, apd->attr()) + , cpu_primitive_t(apd, true) + {} + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(float *, MKLDNN_ARG_DST); + + auto scratchpad = this->scratchpad(ctx); + + switch ((pd()->jcp_).sched_policy) { + case WSCHED_DATA_W_S_G_D: + this->_execute_data_W_S_G_D((float *)src, dst, (float *)weights, + (float *)bias, scratchpad); + break; + case WSCHED_DATA_W_SGD: + this->_execute_data_W_SGD((float *)src, dst, (float *)weights, + (float *)bias, scratchpad); + break; + default: + break; + } + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +struct jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t + : _jit_avx512_core_fp32_wino_conv_4x3_t, + public cpu_primitive_t { + struct pd_t : public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_wino_4x3:", avx512_core, ""), + jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t); + + status_t init() { + bool ok = true + && mkldnn_thr_syncable() + && desc()->prop_kind == prop_kind::backward_data + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && expect_data_types(data_type::f32, data_type::f32, + data_type::undef, data_type::f32, data_type::f32) + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx512_core_fp32_wino_conv_4x3_bwd_data_kernel + ::init_conf(jcp_, *desc(), *diff_src_md(), *weights_md(), + *diff_dst_md()); + if (status != status::success) return status; + set_default_alg_kind(alg_kind::convolution_winograd); + + auto scratchpad = scratchpad_registry().registrar(); + winograd_avx512_core::init_scratchpad(scratchpad, jcp_); + + return status; + } + + jit_conv_winograd_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + auto wei_fmt = with_groups() ? gOIhw16i16o : OIhw16i16o; + return set_default_formats_common(nChw16c, wei_fmt, nChw16c); + } + }; + + jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t(const pd_t *apd) + : _jit_avx512_core_fp32_wino_conv_4x3_t(apd->jcp_, apd->attr()) + , cpu_primitive_t(apd, true) + {} + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC); + + auto scratchpad = this->scratchpad(ctx); + + switch ((pd()->jcp_).sched_policy) { + case WSCHED_DATA_W_S_G_D: + this->_execute_data_W_S_G_D((float *)diff_dst, diff_src, + (float *)weights, NULL, scratchpad); + break; + + case WSCHED_DATA_W_SGD: + this->_execute_data_W_SGD((float *)diff_dst, diff_src, + (float *)weights, NULL, scratchpad); + break; + + default: + break; + } + + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +struct jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t + : public cpu_primitive_t { + struct pd_t : public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_wino_4x3:", avx512_core, ""), + jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t); + + status_t init() { + bool ok = true + && mkldnn_thr_syncable() + && desc()->prop_kind == prop_kind::backward_weights + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && set_default_formats(); + if (!ok) + return status::unimplemented; + + status_t status = + jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel:: + init_conf(jcp_, *desc(), *src_md(), *diff_dst_md(), + *diff_weights_md()); + if (status != status::success) return status; + set_default_alg_kind(alg_kind::convolution_winograd); + + auto scratchpad = scratchpad_registry().registrar(); + winograd_avx512_core::init_scratchpad(scratchpad, jcp_); + + return status; + } + + jit_conv_winograd_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + auto wei_fmt = with_groups() ? gOIhw16i16o : OIhw16i16o; + return set_default_formats_common(nChw16c, wei_fmt, nChw16c); + } + }; + + jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t(const pd_t *apd) + : cpu_primitive_t(apd, true) + , kernel_(nullptr) + { + kernel_ = new jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel( + pd()->jcp_); + } + + ~jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t() + { + delete kernel_; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_BIAS); + + switch (kernel_->jcp.sched_policy) { + case WSCHED_WEI_SDGtWo: + _execute_backward_weights_SDGtWo(src, diff_dst, diff_weights, + diff_bias, scratchpad(ctx)); + break; + case WSCHED_WEI_S_D_Giot_W: + _execute_backward_weights_S_D_Giot_W(src, diff_dst, diff_weights, + diff_bias, scratchpad(ctx)); + break; + default: + assert(kernel_->jcp.sched_policy != WSCHED_INVALID); + break; + } + return status::success; + } + +private: + void _execute_backward_weights_SDGtWo(const float *src, + const float *diff_dst, float *diff_weights, float *diff_bias, + const memory_tracking::grantor_t &scratchpad) const; + void _execute_backward_weights_S_D_Giot_W(const float *src, + const float *diff_dst, float *diff_weights, float *diff_bias, + const memory_tracking::grantor_t &scratchpad) const; + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel *kernel_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp new file mode 100644 index 0000000000..0d64a2d13a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp @@ -0,0 +1,2596 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include + +#include "jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp" + +#define GET_OFF(field) offsetof(jit_wino_transform_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace { + +using namespace mkldnn::impl::utils; + +unsigned int L1_cache_size = get_cache_size(1, true); +unsigned int L2_cache_size = get_cache_size(2, true); +unsigned int LLC_data_size = get_cache_size(3, false); + +// the test funtion takes jcp, the candidate and the current best. +// it returns true if the new candidate is better +int get_divisor_satisfying_cond(jit_conv_winograd_conf_t &jcp, int number, + int default_best, bool (*test)(jit_conv_winograd_conf_t &, int, int)) +{ + int best_divisor = default_best; + auto test_num + = [&best_divisor, test](jit_conv_winograd_conf_t &jcp, int num) { + if (test(jcp, num, best_divisor)) { + best_divisor = num; + } + }; + + for (int divisor = 1; divisor <= ::sqrt(number); divisor++) { + if (number % divisor == 0) { + test_num(jcp, divisor); + test_num(jcp, number / divisor); + } + } + + return best_divisor; +} + +namespace { +bool is_winograd_faster_than_direct(const jit_conv_winograd_conf_t &jcp) { + /* Determines if current winograd implementation is faster than direct. + Following conditions are empirical and based on performance data */ + unsigned int ncores_per_socket = + cpu.getNumCores(Xbyak::util::IntelCpuTopologyLevel::CoreLevel); + unsigned int nthreads = mkldnn_get_max_threads(); + + if (jcp.prop_kind == prop_kind::forward_inference) { + return jcp.mb >= 4; + } else if (nthreads > ncores_per_socket) { + double src_dst_transforms_per_core = alpha * alpha + * (jcp.ic + jcp.oc) + * jcp.mb * ((jcp.oh + tile_size - 1) / tile_size) + * ((jcp.ow + tile_size - 1) / tile_size) + * sizeof(float) / 1024. / 1024. / nthreads; + double wei_transform = alpha * alpha + * jcp.ic * jcp.oc * sizeof(float) /1024. / 1024.; + + if (jcp.prop_kind == prop_kind::backward_weights) { + if (src_dst_transforms_per_core < 0.3 + || (src_dst_transforms_per_core <= 28 && wei_transform < 4)) + return false; + else + return true; + } else { + if (src_dst_transforms_per_core < 2.0 || wei_transform < 0.02) + return false; + } + } + + return jcp.mb > 8; +} +} + +/* assumes 512 bits registers */ +/* TODO: add support for strides */ +/* TODO: handle the prefetch distance automatically */ +typedef enum cache_t_ { L1, L2, L3 } cache_t; + +template +struct prefetcher_t { + prefetcher_t(jit_generator *generator, Xbyak::Reg64 reg_base_addr, + cache_t cache_type, size_t block_size, /* in number of elements*/ + int nb_instructions_in_block, int fma_ipc) + : cg_(generator) + , reg_base_addr_(reg_base_addr) + , cache_type_(cache_type) + , cache_block_size_(block_size) + { + nb_cache_lines_to_prefetch_ = cache_block_size_ / (64 / sizeof(data_t)); + prefetch_spread_ + = div_up(nb_instructions_in_block, nb_cache_lines_to_prefetch_); + prefetch_blk_ + = div_up(nb_cache_lines_to_prefetch_, nb_instructions_in_block); + + /* assumption: when fetch in Li, data is already in L(i+1) */ + int cache_latency; + switch (cache_type_) { + case L1: cache_latency = 14; break; + case L2: cache_latency = 250; break; + case L3: cache_latency = 250; break; + } + + prefetch_distance_ = div_up(cache_latency, nb_cache_lines_to_prefetch_); + } + + void prefetch(int instruction_number) + { + if (instruction_number % prefetch_spread_ == 0) { + for (int i = 0; (i < prefetch_blk_) + && (prefetches_issued_ < nb_cache_lines_to_prefetch_); + i++, prefetches_issued_++) { + prefetch_inst_(cg_->EVEX_compress_addr( + reg_base_addr_, (cache_block_size_ * prefetch_distance_) + * sizeof(data_t) + + (prefetches_issued_ * 64))); + } + } + } + +private: + void prefetch_inst_(const Xbyak::Address &addr) + { + switch (cache_type_) { + case L1: cg_->prefetcht0(addr); break; + case L2: cg_->prefetcht1(addr); break; + case L3: cg_->prefetcht2(addr); break; + default: + break; // TODO: raise an exception or put an assert + } + } + + jit_generator *cg_; + Xbyak::Reg64 reg_base_addr_; + cache_t cache_type_; + int cache_block_size_ = 0; + int nb_cache_lines_to_prefetch_ = 0; + int prefetches_issued_ = 0; + int prefetch_spread_ = 0; + int prefetch_blk_ = 0; + int prefetch_distance_ = 0; +}; + +// utilities to support kernel parameter selection +bool check_L2_block_per_thread(jit_conv_winograd_conf_t &jcp, + int dimN_block, float C2_min, float C2_max) { + float block_size = alpha * alpha * (2*(jcp.oc + jcp.ic) + * dimN_block * jcp.dimN_reg_block + + div_up(jcp.ic * jcp.oc,mkldnn_get_max_threads())) * (float)sizeof(float); + float L2_lb = C2_min * L2_cache_size; + float L2_ub = C2_max * L2_cache_size; + return (block_size > L2_lb && block_size < L2_ub); +} + +bool check_L1_block_gemm(jit_conv_winograd_conf_t &jcp, int dimK_block, + int dimM_block, float C1_min, float C1_max) { + float gemm_block_size = (dimM_block * jcp.dimM_simd_block * dimK_block + * jcp.dimK_reg_block * jcp.dimM_reg_block + + dimK_block * jcp.dimK_reg_block * jcp.dimN_reg_block + + dimM_block * jcp.dimM_simd_block * jcp.dimN_reg_block) + * (float)sizeof(float); + float L1_lb = C1_min * L1_cache_size; + float L1_ub = C1_max * L1_cache_size; + return (gemm_block_size > L1_lb && gemm_block_size < L1_ub); +} +bool check_cond1(int dimN_reg_block, int dimK_block, int dimK_reg_block, + int dimM_block, int dimM_reg_block, int dimM_simd_block, float C) +{ + float lhs = (dimM_block * dimN_reg_block * dimM_simd_block * dimM_reg_block + + dimM_block * dimK_block * dimK_reg_block + * dimM_simd_block * dimM_reg_block + + dimK_block * dimN_reg_block * dimK_reg_block) + * (float)sizeof(float); + float rhs = C * L1_cache_size; + return (lhs < rhs); +} +bool check_cond1_bis(int dimN_reg_block, int dimK_block, int dimK_reg_block, + int dimM_block, int dimM_reg_block, int dimM_simd_block, float C) +{ + float lhs = (dimM_block * dimM_reg_block * dimK_block * dimK_reg_block + * dimM_simd_block + dimK_block * dimN_reg_block * dimK_reg_block) + * (float)sizeof(float); + float rhs = C * L1_cache_size; + return (lhs < rhs); +} +bool check_cond2(int nb_dimN_reg_block, int dimN_reg_block, int dimK_nb_block, + int dimK_block, int dimK_reg_block, int dimM_block, int dimM_reg_block, + int dimM_simd_block, float C) +{ + float lhs = (nb_dimN_reg_block * dimM_block * dimN_reg_block + * dimM_simd_block * dimM_reg_block + + dimK_nb_block * dimM_block * dimK_block * dimK_reg_block + * dimM_simd_block * dimM_reg_block + + nb_dimN_reg_block * dimK_nb_block * dimK_block + * dimN_reg_block * dimK_reg_block) + * (float)sizeof(float); + float rhs = C * L2_cache_size; + return (lhs < rhs); +} + +bool check_kernel_cond(int dimM_block, int dimM_reg_block, int dimM_simd_block, + int dimN_block, int dimN_reg_block, int dimK, float C1, float C2) +{ + float A_size = dimM_block * dimM_reg_block * dimM_simd_block * dimK + * (float)sizeof(float); + float B_size = dimN_block * dimN_reg_block * dimK + * (float)sizeof(float); + return (A_size > C1 * L2_cache_size && B_size > C2 * L2_cache_size); +} +} + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::utils; +using namespace Xbyak; + +void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::gemm_loop_generate() +{ + // for (int dimM_block =0; dimM_block < jcp.dimM_block; dimM_block++) + // for (int dimM_reg_block =0; dimM_reg_block < jcp.dimM_reg_block; + // dimM_reg_block++) // unrolled + // for (int dimK_block = 0; dimK_block < jcp.dimK_block; dimK_block++) + // for (int dimK_reg_block= 0; dimK_reg_block < jcp.dimK_reg_block; + // dimK_reg_block++) // unrolled + // for (int tile =0; tile < jcp.dimN_reg_block; tile++) + // C[dimM_block][dimM_reg_block][tile] += + // A[dimM_block][dimM_reg_block][dimK_block][dimK_reg_block] + // * broadcast(B[dimK_block][tile][dimK_reg_block]); + // Notes: + // jcp.kernel_kind defines embedded or explicit broadcast + // dimM_reg_block=1 for embedded bcast kernel + + auto zmm_srcA = [=]() { + return Xbyak::Zmm(0); + }; + auto zmm_srcB = [=](int tile) { + int idx = 1 + tile; + assert(idx < 1 + jcp.dimN_reg_block); + return Xbyak::Zmm(idx); + }; + auto zmm_dstC = [=](int dimM_reg_block, int tile) { + int idx{0}; + if (jcp.kernel_kind == embd_bcast) + idx = 1 + tile; + else + idx = 1 + jcp.dimN_reg_block + + dimM_reg_block * jcp.dimN_reg_block + tile; + assert(idx < 32); + return Xbyak::Zmm(idx); + }; + + auto prepare_output = [=]() { + for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block; + dimM_reg_block++) { + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + Zmm zmm = zmm_dstC(dimM_reg_block, tile); + vpxord(zmm, zmm, zmm); + } + } + }; + auto store_output = [=](bool output_is_aligned) { + Label save; + cmp(reg_is_beta_zero, 0); + je(save, T_NEAR); + + for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block; + dimM_reg_block++) { + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + Zmm zmm = zmm_dstC(dimM_reg_block,tile); + int output_offset + = jcp.dimN_reg_block * dimM_reg_block * 64 + tile * 64; + vaddps(zmm, zmm, EVEX_compress_addr(reg_dstC, output_offset)); + } + } + + L(save); + for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block; + dimM_reg_block++) { + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + Zmm zmm = zmm_dstC(dimM_reg_block,tile); + int output_offset + = jcp.dimN_reg_block * dimM_reg_block * 64 + tile * 64; + + // In W_SGD, output will be reused. + if (output_is_aligned + && jcp.dimK_nb_block == 1 + && jcp.sched_policy == WSCHED_DATA_W_S_G_D + && (jcp.dimN * jcp.dimM * alpha * alpha + * sizeof(float) > 2 * LLC_data_size)) + vmovntps(EVEX_compress_addr(reg_dstC, output_offset), zmm); + else vmovups(EVEX_compress_addr(reg_dstC, output_offset), zmm); + } + } + }; + + auto inner_loops = [=]() { + Label dimM_block_loop, dimK_block_loop; + + if (jcp.dimM_block > 1) { + mov(reg_dimM_block_loop_cnt, jcp.dimM_block); + L(dimM_block_loop); + } + + prepare_output(); + + if (jcp.dimK_block > 1) { + mov(reg_dimK_block_loop_cnt, jcp.dimK_block); + L(dimK_block_loop); + } + + for (int dimK_reg_block = 0; + dimK_reg_block < jcp.dimK_reg_block; + dimK_reg_block ++) { + + if (jcp.kernel_kind == expl_bcast) { + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + vbroadcastss(zmm_srcB(tile), + ptr[reg_srcB + 64 * tile + dimK_reg_block * 4]); + } + } + + /* Performing the fmas */ + + for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block; + dimM_reg_block++) { + + vmovups(zmm_srcA(), + zword[reg_srcA + + jcp.dimK_reg_block * jcp.dimK_block * 64 + * dimM_reg_block + + dimK_reg_block * 64] + ); + + for (int tile = 0; tile < jcp.dimN_reg_block; tile++) { + if (jcp.kernel_kind == expl_bcast) + vfmadd231ps(zmm_dstC(dimM_reg_block, tile), zmm_srcA(), + zmm_srcB(tile)); + else + vfmadd231ps(zmm_dstC(dimM_reg_block, tile), zmm_srcA(), + EVEX_compress_addr(reg_srcB, + 64 * tile + dimK_reg_block * 4, true)); + } + } + } + add(reg_srcA, jcp.dimK_reg_block * 64); + add(reg_srcB, jcp.dimN_reg_block * 64); + if (jcp.dimK_block > 1) { + sub(reg_dimK_block_loop_cnt, 1); + jnz(dimK_block_loop); + } + + Label unaligned_store, end_store; + test(reg_dstC, cpu_isa_traits::vlen - 1); + jnz(unaligned_store, T_NEAR); + store_output(true); + jmp(end_store, T_NEAR); + L(unaligned_store); { + store_output(false); + } + L(end_store); + + if (jcp.dimM_block > 1) { + sub(reg_srcB, jcp.dimK_block * jcp.dimN_reg_block * 64); + add(reg_dstC, jcp.dimM_reg_block * jcp.dimN_reg_block * 64); + if (jcp.kernel_kind == expl_bcast) { + add(reg_srcA, + (jcp.dimM_reg_block-1) * jcp.dimK_reg_block * 64 + * jcp.dimK_block); + } + sub(reg_dimM_block_loop_cnt, 1); + jnz(dimM_block_loop); + } + }; + + /* Preamble */ + preamble(); + + /* kernel */ + inner_loops(); + + /* Postamble */ + postamble(); + ret(); +} + +void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel + ::weights_transform_data_ker_generate() +{ + bool is_fwd = one_of(jcp.prop_kind, + mkldnn_forward_training, mkldnn_forward_inference); + int kh = jcp.kh; + int kw = jcp.kw; + + auto zmm_temp = Xbyak::Zmm(31); + auto zmm_zero = Xbyak::Zmm(30); + + auto zmm_M = [=](int i) { + return Xbyak::Zmm(i); + }; + auto zmm_MT = [=](int i) { + return Xbyak::Zmm(i + simd_w); + }; + + auto zmm_G = [=](int i) { + return Xbyak::Zmm(i); + }; + auto zmm_F = [=](int i) { + return Xbyak::Zmm(alpha + i); + }; + auto zmm_T = [=](int i) { + return Xbyak::Zmm(alpha + 3 + i); + }; + auto zmm_t = [=](int i) { + return Xbyak::Zmm(2 * alpha + 3 + i); + }; + + auto zmm_load = [=](int i) { + return Xbyak::Zmm(i); + }; + + auto init_G = [=]() { + mov(wreg_temp, ptr[param1 + GET_OFF(G)]); + for (int i = 0; i < alpha; i++) { + vbroadcastss(zmm_G(i), ptr[wreg_temp + i * typesize]); + } + vpxord(zmm_zero, zmm_zero, zmm_zero); + }; + + auto trans16x16 = [=]() { + for (int i = 0; i < simd_w; i+=2 ) { + vmovups(zmm_M(i), ptr[wreg_M + i * simd_w * 4]); + vmovups(zmm_M(i+1), ptr[wreg_M + (i + 1) * simd_w * 4]); + vunpcklps(zmm_MT(i), zmm_M(i), zmm_M(i+1)); + vunpckhps(zmm_MT(i+1), zmm_M(i), zmm_M(i+1)); + } + for (int i = 0; i < simd_w; i+=4 ) { + vunpcklpd(zmm_M(i), zmm_MT(i), zmm_MT(i+2)); + vunpckhpd(zmm_M(i+1), zmm_MT(i), zmm_MT(i+2)); + vunpcklpd(zmm_M(i+2), zmm_MT(i+1), zmm_MT(i+3)); + vunpckhpd(zmm_M(i+3), zmm_MT(i+1), zmm_MT(i+3)); + } + for (int i = 0; i < simd_w; i += 8) { + vshuff32x4(zmm_MT(i), zmm_M(i), zmm_M(i + 4), 0x88); + vshuff32x4(zmm_MT(i+1), zmm_M(i+1), zmm_M(i + 5), 0x88); + vshuff32x4(zmm_MT(i+2), zmm_M(i+2), zmm_M(i + 6), 0x88); + vshuff32x4(zmm_MT(i+3), zmm_M(i+3), zmm_M(i + 7), 0x88); + vshuff32x4(zmm_MT(i+4), zmm_M(i), zmm_M(i + 4), 0xdd); + vshuff32x4(zmm_MT(i+5), zmm_M(i+1), zmm_M(i + 5), 0xdd); + vshuff32x4(zmm_MT(i+6), zmm_M(i+2), zmm_M(i + 6), 0xdd); + vshuff32x4(zmm_MT(i+7), zmm_M(i+3), zmm_M(i + 7), 0xdd); + } + { + int i = 0; + int mask = 0x88; + vshuff32x4(zmm_M(0), zmm_MT(i), zmm_MT(i + 8), mask); + vmovups(ptr[wreg_MT + 0 * 16 * 4], zmm_M(0)); + vshuff32x4(zmm_M(1), zmm_MT(i + 1), zmm_MT(i + 9), mask); + vmovups(ptr[wreg_MT + 1 * 16 * 4], zmm_M(1)); + vshuff32x4(zmm_M(2), zmm_MT(i + 2), zmm_MT(i + 10), mask); + vmovups(ptr[wreg_MT + 2 * 16 * 4], zmm_M(2)); + vshuff32x4(zmm_M(3), zmm_MT(i + 3), zmm_MT(i + 11), mask); + vmovups(ptr[wreg_MT + 3 * 16 * 4], zmm_M(3)); + vshuff32x4(zmm_M(4), zmm_MT(i + 4), zmm_MT(i + 12), mask); + vmovups(ptr[wreg_MT + 4 * 16 * 4], zmm_M(4)); + vshuff32x4(zmm_M(5), zmm_MT(i + 5), zmm_MT(i + 13), mask); + vmovups(ptr[wreg_MT + 5 * 16 * 4], zmm_M(5)); + vshuff32x4(zmm_M(6), zmm_MT(i + 6), zmm_MT(i + 14), mask); + vmovups(ptr[wreg_MT + 6 * 16 * 4], zmm_M(6)); + vshuff32x4(zmm_M(7), zmm_MT(i + 7), zmm_MT(i + 15), mask); + vmovups(ptr[wreg_MT + 7 * 16 * 4], zmm_M(7)); + mask = 0xdd; + vshuff32x4(zmm_M(8), zmm_MT(i), zmm_MT(i + 8), mask); + vmovups(ptr[wreg_MT + 8 * 16 * 4], zmm_M(8)); + vshuff32x4(zmm_M(9), zmm_MT(i + 1), zmm_MT(i + 9), mask); + vmovups(ptr[wreg_MT + 9 * 16 * 4], zmm_M(9)); + vshuff32x4(zmm_M(10), zmm_MT(i + 2), zmm_MT(i + 10), mask); + vmovups(ptr[wreg_MT + 10 * 16 * 4], zmm_M(10)); + vshuff32x4(zmm_M(11), zmm_MT(i + 3), zmm_MT(i + 11), mask); + vmovups(ptr[wreg_MT + 11 * 16 * 4], zmm_M(11)); + vshuff32x4(zmm_M(12), zmm_MT(i + 4), zmm_MT(i + 12), mask); + vmovups(ptr[wreg_MT + 12 * 16 * 4], zmm_M(12)); + vshuff32x4(zmm_M(13), zmm_MT(i + 5), zmm_MT(i + 13), mask); + vmovups(ptr[wreg_MT + 13 * 16 * 4], zmm_M(13)); + vshuff32x4(zmm_M(14), zmm_MT(i + 6), zmm_MT(i + 14), mask); + vmovups(ptr[wreg_MT + 14 * 16 * 4], zmm_M(14)); + vshuff32x4(zmm_M(15), zmm_MT(i + 7), zmm_MT(i + 15), mask); + vmovups(ptr[wreg_MT + 15 * 16 * 4], zmm_M(15)); + } + }; + + auto load_src = [=]() { + mov(wreg_src, ptr[param1 + GET_OFF(src)]); + mov(wreg_F, ptr[param1 + GET_OFF(M)]); + for (int j = 0; j < kh; j++) { + for (int i = 0; i < kw; i++) { + if (is_fwd) { + for (int v1 = 0; v1 < simd_w; v1++) { + int offset_src = (j * kw * simd_w * simd_w + + i * simd_w * simd_w + v1 * simd_w) * typesize; + int offset_F = (j * kw * simd_w * simd_w + + i * simd_w * simd_w + v1 * simd_w) * typesize; + vmovups(zmm_temp, ptr[wreg_src + offset_src]); + vmovups(ptr[wreg_F + offset_F], zmm_temp); + } + } else { + int offset_src = ((2 - j) * kw * simd_w * simd_w + + (2 - i) * simd_w * simd_w) * typesize; + int offset_F = (j * kw * simd_w * simd_w + + i * simd_w * simd_w) * typesize; + lea(wreg_M, ptr[wreg_src + offset_src]); + lea(wreg_MT, ptr[wreg_F + offset_F]); + trans16x16(); + } + } + } + }; + + auto store_dst = [=]() { + mov(wreg_dst, ptr[param1 + GET_OFF(dst)]); + mov(wreg_Fw, ptr[param1 + GET_OFF(Mw)]); + + Label Loop_j; + mov(wreg_cnt_j, 0); + mov(wreg_dst_aux, wreg_dst); + mov(wreg_Fw_aux, wreg_Fw); + + int dim5 = jcp.dimK_nb_block * (jcp.dimM_block * jcp.dimM_reg_block) + * jcp.dimK_block * simd_w * simd_w; + + L(Loop_j); + { + for (int i = 0; i < alpha; i++) { + // touch pages + vmovups(zmm_load(0), ptr[wreg_Fw_aux + + (i * simd_w * simd_w) * typesize]); + mov(wreg_dst_idx, i * dim5 * typesize); + vmovntps(ptr[wreg_dst_aux + wreg_dst_idx], zmm_load(0)); + } + for (int i = 0; i < alpha; i++) { + for (int v1 = 1; v1 < simd_w; v1++) { + int offset_Fw = (i * simd_w * simd_w + v1 * simd_w) + * typesize; + vmovups(zmm_load(v1), ptr[wreg_Fw_aux + offset_Fw]); + } + mov(wreg_dst_idx, i * dim5 * typesize); + for (int v1 = 1; v1 < simd_w; v1++) { + int offset_dst = v1 * simd_w * typesize; + vmovntps(ptr[wreg_dst_aux + wreg_dst_idx + offset_dst], + zmm_load(v1)); + } + } + add(wreg_Fw_aux, alpha * simd_w * simd_w * typesize); + add(wreg_dst_aux, alpha * dim5 * typesize); + add(wreg_cnt_j, 1); + cmp(wreg_cnt_j, alpha); + jl(Loop_j, T_NEAR); + } + }; + + auto trans_W_4x4_3x3 = [=]() { + auto fma4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) { + vmovups(dst, a); + vfmadd231ps(dst, b, c); + }; + auto fms4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) { + vmulps(zmm_temp, b, c); + vsubps(dst, a, zmm_temp); + }; + auto fnms4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) { + vsubps(dst, zmm_zero, a); + vfnmadd231ps(dst, b, c); + }; + + mov(wreg_Fw, ptr[param1 + GET_OFF(Mw)]); + mov(wreg_F, ptr[param1 + GET_OFF(M)]); + mov(wreg_T, ptr[param1 + GET_OFF(T)]); + + Label Loop_j; + mov(wreg_cnt_j, 0); + L(Loop_j); + mov(wreg_F_aux, wreg_F); + mov(wreg_Fw_aux, wreg_Fw); + mov(wreg_temp, wreg_cnt_j); + shl(wreg_temp, 4 + 2); + lea(wreg_F_aux, ptr[wreg_F + wreg_temp]); + lea(wreg_Fw_aux, ptr[wreg_Fw + wreg_temp]); + + for (int i = 0; i < 3; i++) { + for (int idx = 0; idx < 3; idx ++) { + vmovups(zmm_F(idx), ptr[wreg_F_aux + (idx * 3 * simd_w + * simd_w + i * simd_w * simd_w) * typesize]); + } + vmulps(zmm_t(0), zmm_G(0), zmm_F(2)); + fnms4(zmm_t(1), zmm_t(0), zmm_G(1), zmm_F(0)); + fma4(zmm_t(2), zmm_t(0), zmm_G(2), zmm_F(0)); + + vmulps(zmm_T(0), zmm_G(3), zmm_F(0)); + fms4(zmm_T(1), zmm_t(1), zmm_G(4), zmm_F(1)); + fma4(zmm_T(2), zmm_t(1), zmm_G(4), zmm_F(1)); + fma4(zmm_T(3), zmm_t(2), zmm_G(5), zmm_F(1)); + fms4(zmm_T(4), zmm_t(2), zmm_G(5), zmm_F(1)); + vmovaps(zmm_T(5), zmm_F(2)); + + for (int idx = 0; idx < 6; idx ++) { + vmovups(ptr[wreg_T + (idx * 3 * simd_w + i * simd_w) + * typesize], zmm_T(idx)); + } + } + for (int i = 0; i < 6; i++) { + + for (int idx = 0; idx < 3; idx ++) { + vmovups(zmm_T(idx), ptr[wreg_T + + (i * 3 * simd_w + idx * simd_w) * typesize]); + } + vmulps(zmm_t(0), zmm_G(0), zmm_T(2)); + fnms4(zmm_t(1), zmm_t(0), zmm_G(1), zmm_T(0)); + fma4(zmm_t(2), zmm_t(0), zmm_G(2), zmm_T(0)); + + vmulps(zmm_F(0), zmm_G(3), zmm_T(0)); + fms4(zmm_F(1), zmm_t(1), zmm_G(4), zmm_T(1)); + fma4(zmm_F(2), zmm_t(1), zmm_G(4), zmm_T(1)); + fma4(zmm_F(3), zmm_t(2), zmm_G(5), zmm_T(1)); + fms4(zmm_F(4), zmm_t(2), zmm_G(5), zmm_T(1)); + vmovaps(zmm_F(5), zmm_T(2)); + + for (int l = 0; l < 6; l++) { + vmovups(ptr[wreg_Fw_aux + (i * 6 * simd_w * simd_w + + l * simd_w * simd_w) * typesize], zmm_F(l)); + } + } + add(wreg_cnt_j, 1); + cmp(wreg_cnt_j, 16); + jl(Loop_j, T_NEAR); + }; + + auto inner_loops = [=]() { + load_src(); + init_G(); + trans_W_4x4_3x3(); + store_dst(); + }; + + preamble(); + inner_loops(); + postamble(); +} + +void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel + ::output_transform_data_ker_generate() +{ + bool is_fwd = one_of(jcp.prop_kind, + mkldnn_forward_training, mkldnn_forward_inference); + int outw = is_fwd ? jcp.ow : jcp.iw; + int outh = is_fwd ? jcp.oh : jcp.ih; + bool not_tiled = jcp.sched_policy == WSCHED_DATA_W_S_G_D; + bool with_bias = jcp.with_bias; + bool with_relu = jcp.with_eltwise; + bool with_relu_postsum = jcp.with_relu_postsum; + bool with_sum = jcp.with_sum; + + auto zmm_zero = Xbyak::Zmm(0); + auto zmm_temp = Xbyak::Zmm(31); + auto zmm_G = [=](int i) { + return Xbyak::Zmm(1 + i); + }; + auto zmm_O = [=](int i) { + return Xbyak::Zmm(1 + alpha + i); + }; + auto zmm_T = [=](int i) { + return Xbyak::Zmm(1 + 2 * alpha + i); + }; + auto zmm_t = [=](int i) { + return Xbyak::Zmm(1 + 3 * alpha + i); + }; + + auto init_G = [=]() { + mov(oreg_temp, ptr[param1 + GET_OFF(G)]); + for (int i = 0; i < 6; i++) { + vbroadcastss(zmm_G(i), ptr[oreg_temp + i * typesize]); + } + }; + + auto load_src = [=]() { + mov(oreg_Ow, ptr[param1 + GET_OFF(Mw)]); + mov(oreg_src, ptr[param1 + GET_OFF(src)]); + + mov(oreg_nb_tile_block_ur, ptr[param1 + GET_OFF(nb_tile_block_ur)]); + imul(oreg_nb_tile_block_ur, oreg_nb_tile_block_ur, + (jcp.dimM_block * jcp.dimM_reg_block) * jcp.dimN_reg_block + * jcp.dimM_simd_block * typesize); + add(oreg_src, oreg_nb_tile_block_ur); + + mov(oreg_tile_block_ur, ptr[param1 + GET_OFF(tile_block_ur)]); + imul(oreg_tile_block_ur, oreg_tile_block_ur, + jcp.dimM_simd_block * typesize); + add(oreg_src, oreg_tile_block_ur); + + if (not_tiled) { + mov(oreg_tile_block, ptr[param1 + GET_OFF(tile_block)]); + imul(oreg_tile_block, oreg_tile_block, + jcp.dimM_nb_block * alpha * alpha * jcp.dimN_block + * (jcp.dimM_block * jcp.dimM_reg_block) * jcp.dimN_reg_block + * jcp.dimM_simd_block * typesize); + add(oreg_src, oreg_tile_block); + } + + int last4dim = jcp.dimN_block * (jcp.dimM_block * jcp.dimM_reg_block) + * jcp.dimN_reg_block * jcp.dimM_simd_block * typesize; + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + int j_base_offset = j * alpha * last4dim; + int i_base_offset = i * last4dim; + vmovups(zmm_temp, ptr[oreg_src + j_base_offset + i_base_offset]); + vmovups(ptr[oreg_Ow + (j * alpha * simd_w + i * simd_w) + * typesize], zmm_temp); + } + } + }; + + auto store_dst = [=]() { + vpxord(zmm_zero, zmm_zero, zmm_zero); + mov(oreg_dst, ptr[param1 + GET_OFF(dst)]); + mov(oreg_O, ptr[param1 + GET_OFF(M)]); + mov(oreg_ydim, ptr[param1 + GET_OFF(tj)]); + shl(oreg_ydim, 2); // tj * tile_size (==4) + mov(oreg_xdim, ptr[param1 + GET_OFF(ti)]); + shl(oreg_xdim, 2); // ti * tilesize (==4) + + if (with_bias) + mov(oreg_bias, ptr[param1 + GET_OFF(bias)]); + + auto store_one = [=](int j, int i, bool is_aligned) { + auto zmm_O = Xbyak::Zmm(31); + auto zmm_relu_ns = Xbyak::Zmm(30); + auto xmm_relu_ns = Xbyak::Xmm(30); + int offset = (j * tile_size * simd_w + i * simd_w) * typesize; + + vmovups(zmm_O, ptr[oreg_O + offset]); + if (is_fwd) { + if (with_bias) { + vaddps(zmm_O, zmm_O, ptr[oreg_bias]); + } + if (with_relu) { + if (jcp.eltwise.alpha == 0) { + vmaxps(zmm_O, zmm_O, zmm_zero); + } else { + Opmask kmask = Opmask(7); + mov(imm_addr64, float2int(jcp.eltwise.alpha)); + vmovq(xmm_relu_ns, imm_addr64); + vbroadcastss(zmm_relu_ns, xmm_relu_ns); + vcmpps(kmask, zmm_O, zmm_zero, _cmp_lt_os); + vmulps(zmm_O | kmask, zmm_O, zmm_relu_ns); + } + } + } + if (with_sum) { + vaddps(zmm_O, zmm_O, ptr[oreg_out_j + oreg_temp]); + if (with_relu_postsum) // orig: with_relu_postsum + vmaxps(zmm_O, zmm_O, zmm_zero); + } + if (is_aligned) + vmovntps(ptr[oreg_out_j + oreg_temp], zmm_O); + else + vmovups(ptr[oreg_out_j + oreg_temp], zmm_O); + }; + + auto i_loop = [=](int j, bool is_aligned) { + for (int i = 0; i < tile_size; i++) { + Label next; + mov(oreg_temp, oreg_xdim); + add(oreg_temp, i); + cmp(oreg_temp, outw); + jge(next, T_NEAR); + shl(oreg_temp, 4 + 2); // * 16 * 4 + + store_one(j, i, is_aligned); + + L(next); + } + }; + + + for (int j = 0; j < tile_size; j++) { + Label next, unaligned; + mov(oreg_temp, oreg_ydim); + add(oreg_temp, j); + cmp(oreg_temp, outh); + jge(next, T_NEAR); + + mov(oreg_out_j, oreg_dst); + imul(oreg_temp, oreg_temp, outw * simd_w * typesize); + add(oreg_out_j, oreg_temp); + + test(oreg_dst, 63); + jnz(unaligned, T_NEAR); + + i_loop(j, true); + jmp(next, T_NEAR); + + L(unaligned); + i_loop(j, false); + + L(next); + } + }; + + auto trans_O_4x4_3x3 = [=]() { + auto fma2 = [=](Zmm dst, Zmm v1, Zmm u1, Zmm v2, Zmm u2){ + vmulps(dst, v1, u1); + vfmadd231ps(dst, v2, u2); + }; + mov(oreg_Ow, ptr[param1 + GET_OFF(Mw)]); + mov(oreg_T, ptr[param1 + GET_OFF(T)]); + mov(oreg_O, ptr[param1 + GET_OFF(M)]); + + for (int i = 0; i < alpha; i++) { + for (int j = 0; j < alpha; j++) { + vmovups(zmm_O(j), ptr[oreg_Ow + (j * alpha * simd_w + + i * simd_w) * typesize]); + } + + vaddps(zmm_t(0), zmm_O(1), zmm_O(2)); + vaddps(zmm_t(1), zmm_O(3), zmm_O(4)); + vsubps(zmm_t(2), zmm_O(1), zmm_O(2)); + vsubps(zmm_t(3), zmm_O(3), zmm_O(4)); + + vaddps(zmm_T(0), zmm_t(0), zmm_t(1)); + vaddps(zmm_T(0), zmm_T(0), zmm_O(0)); + fma2(zmm_T(1), zmm_t(2), zmm_G(0), zmm_t(3), zmm_G(1)); + fma2(zmm_T(2), zmm_t(0), zmm_G(2), zmm_t(1), zmm_G(3)); + fma2(zmm_T(3), zmm_t(2), zmm_G(4), zmm_t(3), zmm_G(5)); + vaddps(zmm_T(3), zmm_T(3), zmm_O(5)); + + for (int j = 0; j < tile_size; j++) { + vmovups(ptr[oreg_T + (j * alpha * simd_w + + i * simd_w) * typesize], zmm_T(j)); + } + } + for (int j = 0; j < tile_size; j++) { + for (int i = 0; i < alpha; i++) { + vmovups(zmm_T(i), ptr[oreg_T + (j * alpha * simd_w + + i * simd_w) * typesize]); + } + vaddps(zmm_t(0), zmm_T(1), zmm_T(2)); + vaddps(zmm_t(1), zmm_T(3), zmm_T(4)); + vsubps(zmm_t(2), zmm_T(1), zmm_T(2)); + vsubps(zmm_t(3), zmm_T(3), zmm_T(4)); + + vaddps(zmm_O(0), zmm_t(0), zmm_t(1)); + vaddps(zmm_O(0), zmm_O(0), zmm_T(0)); + fma2(zmm_O(1), zmm_t(2), zmm_G(0), zmm_t(3), zmm_G(1)); + fma2(zmm_O(2), zmm_t(0), zmm_G(2), zmm_t(1), zmm_G(3)); + fma2(zmm_O(3), zmm_t(2), zmm_G(4), zmm_t(3), zmm_G(5)); + vaddps(zmm_O(3), zmm_O(3), zmm_T(5)); + + for (int i = 0; i < tile_size; i++) { + vmovups(ptr[oreg_O + (j * tile_size * simd_w + + i * simd_w) * typesize], zmm_O(i)); + } + } + }; + + auto inner_loops = [=]() { + init_G(); + load_src(); + trans_O_4x4_3x3(); + store_dst(); + }; + + preamble(); + inner_loops(); + postamble(); +} + +void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel + ::input_transform_data_ker_generate() +{ + bool is_fwd = one_of(jcp.prop_kind, + mkldnn_forward_training, mkldnn_forward_inference); + int inpw = is_fwd ? jcp.iw : jcp.ow; + int inph = is_fwd ? jcp.ih : jcp.oh; + int l_pad = is_fwd ? jcp.l_pad : jcp.iw + jcp.r_pad - jcp.ow; + int t_pad = is_fwd ? jcp.t_pad : jcp.ih + jcp.t_pad - jcp.oh; + int wp_max = inpw + l_pad; + int hp_max = inph + t_pad; + bool not_tiled = jcp.sched_policy == WSCHED_DATA_W_S_G_D; + int G_size = 9; + + auto zmm_zero = Xbyak::Zmm(0); + auto zmm_temp = Xbyak::Zmm(31); + auto zmm_G = [=](int i) { + return Xbyak::Zmm(1 + i); + }; + auto zmm_I = [=](int i) { + return Xbyak::Zmm(1 + G_size + i); + }; + auto zmm_T = [=](int i) { + return Xbyak::Zmm(1 + G_size + alpha + i); + }; + auto zmm_t = [=](int i) { + return Xbyak::Zmm(1 + G_size + 2 * alpha + i); + }; + + auto init_G = [=]() { + mov(ireg_temp, ptr[param1 + GET_OFF(G)]); + for (int i = 0; i < G_size; i++) { + vbroadcastss(zmm_G(i), ptr[ireg_temp + i * typesize]); + } + }; + + auto load_src = [=]() { + mov(ireg_src, ptr[param1 + GET_OFF(src)]); // base addr of inp + mov(ireg_I, ptr[param1 + GET_OFF(M)]); + + xor_(ireg_zero, ireg_zero); + vpxord(zmm_zero, zmm_zero, zmm_zero); + + mov(ireg_ydim, ptr[param1 + GET_OFF(tj)]); + shl(ireg_ydim, 2); // tj * tile_size (==4) + mov(ireg_xdim, ptr[param1 + GET_OFF(ti)]); + shl(ireg_xdim, 2); // ti * tilesize (==4) + + for (int j = 0; j < alpha; j++) { + mov(ireg_temp, ireg_ydim); + add(ireg_temp, j); + + mov(ireg_mask_j, 0xffff); + cmp(ireg_temp, t_pad); + cmovl(ireg_mask_j, ireg_zero); + cmp(ireg_temp, hp_max); + cmovge(ireg_mask_j, ireg_zero); + + sub(ireg_temp, t_pad); + imul(ireg_temp, ireg_temp, inpw * simd_w * typesize); + mov(ireg_inp_j, ireg_src); + add(ireg_inp_j, ireg_temp); + + for (int i = 0; i < alpha; i++) { + + mov(ireg_temp, ireg_xdim); + add(ireg_temp, i); + + mov(ireg_mask, 0xffff); + cmp(ireg_temp, l_pad); + cmovl(ireg_mask, ireg_zero); + cmp(ireg_temp, wp_max); + cmovge(ireg_mask, ireg_zero); + and_(ireg_mask, ireg_mask_j); + + sub(ireg_temp, l_pad); + shl(ireg_temp, 4 + 2); + + vpxord(zmm_temp, zmm_temp, zmm_temp); + Opmask kmask = Opmask(7); + kmovw(kmask, ireg_mask_32); + vmovups(zmm_temp | kmask, ptr[ireg_inp_j + ireg_temp]); + vmovups(ptr[ireg_I + (j * alpha * simd_w + i * simd_w) + * typesize], zmm_temp); + } + } + }; + + auto store_Iw = [=]() { + + mov(ireg_Iw, ptr[param1 + GET_OFF(Mw)]); + mov(ireg_output, ptr[param1 + GET_OFF(dst)]); + + bool streamout + = jcp.dimN * jcp.dimK * alpha * alpha * sizeof(float) + > 2 * LLC_data_size + ? true : false; + + if (not_tiled) { + mov(ireg_tile_block, ptr[param1 + GET_OFF(tile_block)]); + imul(ireg_tile_block, ireg_tile_block, + alpha * alpha * jcp.dimN_block * jcp.dimK_nb_block + * jcp.dimK_block * jcp.dimN_reg_block * jcp.dimK_reg_block + * typesize); + } + + mov(ireg_nb_tile_block_ur, ptr[param1 + GET_OFF(nb_tile_block_ur)]); + imul(ireg_nb_tile_block_ur, ireg_nb_tile_block_ur, + jcp.dimK_nb_block * jcp.dimK_block * jcp.dimN_reg_block + * jcp.dimK_reg_block * typesize); + + mov(ireg_tile_block_ur, ptr[param1 + GET_OFF(tile_block_ur)]); + imul(ireg_tile_block_ur, ireg_tile_block_ur, + jcp.dimK_reg_block * typesize); + + add(ireg_output, ireg_nb_tile_block_ur); + add(ireg_output, ireg_tile_block_ur); + if (not_tiled) + add(ireg_output, ireg_tile_block); + + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + vmovups(zmm_temp,ptr[ireg_Iw + (j * alpha * simd_w + + i * simd_w) * typesize]); + + int j_base_offset = + j * alpha * jcp.dimN_block * jcp.dimK_nb_block + * jcp.dimK_block * jcp.dimN_reg_block * jcp.dimK_reg_block + * typesize; + int i_base_offset = + i * jcp.dimN_block * jcp.dimK_nb_block * jcp.dimK_block + * jcp.dimN_reg_block * jcp.dimK_reg_block * typesize; + + if (not_tiled && streamout) + vmovntps(ptr[ireg_output + j_base_offset + i_base_offset], + zmm_temp); + else + vmovups(ptr[ireg_output + j_base_offset + i_base_offset], + zmm_temp); + } + } + }; + + auto fma4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) { + vmulps(zmm_temp, a, b); + vaddps(dst, zmm_temp, c); + }; + + auto trans_I_4x4_3x3 = [=]() { + mov(ireg_Iw, ptr[param1 + GET_OFF(Mw)]); + mov(ireg_T, ptr[param1 + GET_OFF(T)]); + mov(ireg_I, ptr[param1 + GET_OFF(M)]); + + mov(ireg_output, ptr[param1 + GET_OFF(dst)]); // for prefetch + for (int i = 0; i < alpha; i++) { + for (int idx = 0; idx < alpha; idx++) { + vmovups(zmm_I(idx), ptr[ireg_I + (idx * alpha * simd_w + + i * simd_w) * typesize]); + int j_base_offset = + i * alpha * jcp.dimN_block * jcp.dimK_nb_block + * jcp.dimK_block * jcp.dimN_reg_block * jcp.dimK_reg_block + * typesize; + int idx_base_offset = + idx * jcp.dimN_block * jcp.dimK_nb_block * jcp.dimK_block + * jcp.dimN_reg_block * jcp.dimK_reg_block * typesize; + prefetcht0(ptr[ireg_output + j_base_offset + idx_base_offset]); + } + + fma4(zmm_t(0), zmm_I(2), zmm_G(0), zmm_I(4)); + fma4(zmm_t(1), zmm_I(1), zmm_G(0), zmm_I(3)); + fma4(zmm_t(2), zmm_I(2), zmm_G(1), zmm_I(4)); + fma4(zmm_t(3), zmm_I(1), zmm_G(1), zmm_I(3)); + fma4(zmm_t(4), zmm_I(0), zmm_G(2), zmm_I(4)); + fma4(zmm_t(5), zmm_I(1), zmm_G(2), zmm_I(5)); + + fma4(zmm_T(0), zmm_I(2), zmm_G(3), zmm_t(4)); + fma4(zmm_T(1), zmm_t(1), zmm_G(4), zmm_t(0)); + fma4(zmm_T(2), zmm_t(1), zmm_G(5), zmm_t(0)); + fma4(zmm_T(3), zmm_t(3), zmm_G(6), zmm_t(2)); + fma4(zmm_T(4), zmm_t(3), zmm_G(7), zmm_t(2)); + fma4(zmm_T(5), zmm_I(3), zmm_G(8), zmm_t(5)); + + for (int idx = 0; idx < alpha; idx++) { + vmovups(ptr[ireg_T + (idx * alpha * simd_w + i * simd_w) + * typesize],zmm_T(idx)); + } + } + for (int i = 0; i < alpha; i++) { + for (int idx = 0; idx < alpha; idx++) { + vmovups(zmm_T(idx), ptr[ireg_T + (i * alpha * simd_w + idx + * simd_w) * typesize]); + } + + fma4(zmm_t(0), zmm_T(2), zmm_G(0), zmm_T(4)); + fma4(zmm_t(1), zmm_T(1), zmm_G(0), zmm_T(3)); + fma4(zmm_t(2), zmm_T(2), zmm_G(1), zmm_T(4)); + fma4(zmm_t(3), zmm_T(1), zmm_G(1), zmm_T(3)); + fma4(zmm_t(4), zmm_T(0), zmm_G(2), zmm_T(4)); + fma4(zmm_t(5), zmm_T(1), zmm_G(2), zmm_T(5)); + + fma4(zmm_I(0), zmm_T(2), zmm_G(3), zmm_t(4)); + fma4(zmm_I(1), zmm_t(1), zmm_G(4), zmm_t(0)); + fma4(zmm_I(2), zmm_t(1), zmm_G(5), zmm_t(0)); + fma4(zmm_I(3), zmm_t(3), zmm_G(6), zmm_t(2)); + fma4(zmm_I(4), zmm_t(3), zmm_G(7), zmm_t(2)); + fma4(zmm_I(5), zmm_T(3), zmm_G(8), zmm_t(5)); + + for (int idx = 0; idx < alpha; idx++) { + vmovups(ptr[ireg_Iw + (i * alpha * simd_w + idx * simd_w) + * typesize],zmm_I(idx)); + } + } + }; + + auto inner_loops = [=]() { + init_G(); + load_src(); + trans_I_4x4_3x3(); + store_Iw(); + }; + + preamble(); + inner_loops(); + postamble(); +} + +status_t _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::init_conf_common( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d) +{ + if (!mayiuse(avx512_core)) { + return status::unimplemented; + } + + jcp.nthr = mkldnn_get_max_threads(); + + jcp.ver = ver_avx512_core; + jcp.prop_kind = cd.prop_kind; + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = dst_d.dims()[2]; + jcp.ow = dst_d.dims()[3]; + jcp.kh = weights_d.dims()[with_groups + 2]; + jcp.kw = weights_d.dims()[with_groups + 3]; + jcp.t_pad = cd.padding[0][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + jcp.r_pad = nstl::max( + 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad); + jcp.b_pad = nstl::max( + 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad); + jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad; + jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad; + jcp.ohp = jcp.oh; + jcp.owp = jcp.ow; + + bool ok_to_pad_channels = jcp.ngroups == 1; + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + // Checking conditions not supported by these kernels + if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto, + is_winograd_faster_than_direct(jcp))) + return status::unimplemented; + + if (jcp.ngroups != 1) + return status::unimplemented; + if ((jcp.kh != 3) || (jcp.kw != 3)) + return status::unimplemented; + if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0)) + return status::unimplemented; + if ((jcp.stride_h != 1) || (jcp.stride_w != 1)) + return status::unimplemented; + if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0) + return status::unimplemented; + + format_tag_t dat_tag = nChw16c; + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + + if (jcp.src_tag != dat_tag) return status::unimplemented; + if (jcp.dst_tag != dat_tag) return status::unimplemented; + + if (!one_of(weights_d.format_kind(), format_kind::any, format_kind::wino)) { + format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o; + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + if (jcp.wei_tag != wei_tag) + return status::unimplemented; + } + + bool layout_consistency = true + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= dst_d.padded_dims()[1] + && (one_of(weights_d.format_kind(), + format_kind::any, format_kind::wino) + || (jcp.ic <= weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= weights_d.padded_dims()[with_groups + 0])); + if (!layout_consistency) + return status::unimplemented; + + return status::success; +} + +void set_kernel_dims_reg_block(jit_conv_winograd_conf_t &jcp) { + + /* ----------- dimM reg block ---------------------*/ + auto test_cond_dimM_reg_block = [](jit_conv_winograd_conf_t &jcp, + int dimM_reg_block, int current_best) { + int max_dimM_reg_block = jcp.kernel_kind == embd_bcast ? 1 : 4; + return (dimM_reg_block >= 1) + && (dimM_reg_block <= max_dimM_reg_block ) + && (dimM_reg_block > current_best); + }; + jcp.dimM_reg_block = get_divisor_satisfying_cond(jcp, + jcp.dimM/jcp.dimM_simd_block, 1, test_cond_dimM_reg_block); + + /* ----------- dimN reg block ---------------------*/ + + auto test_cond_dimN_reg_block = [](jit_conv_winograd_conf_t &jcp, + int dimN_reg_block, int current_best) { + return jcp.kernel_kind == embd_bcast + ? dimN_reg_block < jcp.nb_reg && dimN_reg_block > current_best + : dimN_reg_block >= 1 + && (dimN_reg_block * jcp.dimM_reg_block + dimN_reg_block) + < jcp.nb_reg + && dimN_reg_block > current_best; + }; + jcp.dimN_reg_block = get_divisor_satisfying_cond(jcp, + jcp.dimN, 1, test_cond_dimN_reg_block); +} + +status_t set_wsched_DATA_W_SGD_avx512_core(jit_conv_winograd_conf_t &jcp) { + if (jcp.ver != ver_avx512_core) + return status::unimplemented; + + jcp.kernel_kind = embd_bcast; + + set_kernel_dims_reg_block(jcp); + + /*-------------- L2 blocking for dimN block ---------*/ + + auto test_cond_dimN_block = [](jit_conv_winograd_conf_t &jcp, + int dimN_block, int current_best) { + return check_L2_block_per_thread(jcp, dimN_block, 0.1, 2.0) + && (dimN_block > current_best) + && ((jcp.dimN / dimN_block / jcp.dimN_reg_block) + >= 1.5 * mkldnn_get_max_threads()); + }; + + jcp.dimN_block = get_divisor_satisfying_cond( + jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond_dimN_block); + jcp.dimN_nb_block = jcp.dimN / jcp.dimN_block / jcp.dimN_reg_block; + + if (check_L2_block_per_thread(jcp, jcp.dimN_block, 0.1, 3.2) + && (jcp.dimN_nb_block >= 1.5 * mkldnn_get_max_threads())) { + + /* ------------------- L1 blocking for GEMM --------------*/ + /* -------------------- Choose dimK block ----------------*/ + + auto test_cond_dimK_block = [](jit_conv_winograd_conf_t &jcp, + int dimK_block, int current_best) { + return check_L1_block_gemm(jcp, dimK_block, 1, 0.1, 0.5) + && (dimK_block > current_best); + }; + + jcp.dimK_block = get_divisor_satisfying_cond( + jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond_dimK_block); + + if (check_L1_block_gemm(jcp, jcp.dimK_block, 1, 0.1, 1.0)) { + jcp.dimK_nb_block = jcp.dimK / jcp.dimK_block / jcp.dimK_reg_block; + + /* -------------- Choose dimM block -------------------*/ + auto test_cond_dimM_block = [](jit_conv_winograd_conf_t &jcp, + int dimM_block, int current_best) { + return check_L1_block_gemm(jcp, jcp.dimK_block, dimM_block, + 0.2, 0.5) && (dimM_block > current_best); + }; + + jcp.dimM_block = get_divisor_satisfying_cond(jcp, + jcp.dimM / (jcp.dimM_simd_block * jcp.dimM_reg_block), 1, + test_cond_dimM_block); + jcp.dimM_nb_block = jcp.dimM / jcp.dimM_block / jcp.dimM_reg_block + / jcp.dimM_simd_block; + + jcp.sched_policy = WSCHED_DATA_W_SGD; + return status::success; + } + + } + return status::unimplemented; +} + +void set_kernel_blocking_DATA_W_S_G_D(jit_conv_winograd_conf_t &jcp) { + + set_kernel_dims_reg_block(jcp); + + //********************* Choosing dimK_block **********************// + auto test_cond1_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond1(jcp.dimN_reg_block, dimK_block, jcp.dimK_reg_block, + 1, jcp.dimM_reg_block, jcp.dimM_simd_block, .75f) + && (dimK_block > current_best); + }; + + auto test_cond1_bis_dimK_block = []( + jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) { + return check_cond1_bis(jcp.dimN_reg_block, dimK_block, + jcp.dimK_reg_block, 1, jcp.dimM_reg_block, + jcp.dimM_simd_block, .9f) + && (dimK_block > current_best); + }; + + jcp.dimK_block = get_divisor_satisfying_cond( + jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_bis_dimK_block); + // If we are not able to use streams, we fall back to condition [1] + if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block) + jcp.dimK_block = get_divisor_satisfying_cond( + jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_dimK_block); + jcp.dimK_nb_block = (jcp.dimK / jcp.dimK_reg_block) / jcp.dimK_block; + + //********************* Choosing dimM_block **********************// + auto test_cond1_dimM_block = []( + jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) { + return check_cond1(jcp.dimN_reg_block, jcp.dimK_block, + jcp.dimK_reg_block, dimM_block, jcp.dimM_reg_block, + jcp.dimM_simd_block, .5f) + && (dimM_block > current_best); + }; + + auto test_cond1_bis_dimM_block = []( + jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) { + return check_cond1_bis(jcp.dimN_reg_block, jcp.dimK_block, + jcp.dimK_reg_block, dimM_block, jcp.dimM_reg_block, + jcp.dimM_simd_block, .3f) + && (dimM_block > current_best); + }; + + if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block) + jcp.dimM_block = get_divisor_satisfying_cond( + jcp, jcp.dimM / (jcp.dimM_simd_block*jcp.dimM_reg_block), 1, + test_cond1_dimM_block); + else + jcp.dimM_block = get_divisor_satisfying_cond(jcp, + jcp.dimM / (jcp.dimM_simd_block*jcp.dimM_reg_block), 1, + test_cond1_bis_dimM_block); + jcp.dimM_nb_block = jcp.dimM / (jcp.dimM_simd_block * jcp.dimM_block + * jcp.dimM_reg_block); + + //******************* Choosing dimN_block *******************// + auto test_cond2_dimN_block = []( + jit_conv_winograd_conf_t &jcp, int dimN_block, int current_best) { + return check_cond2(dimN_block, jcp.dimN_reg_block, jcp.dimK_nb_block, + jcp.dimK_block, jcp.dimK_reg_block, jcp.dimM_block, + jcp.dimM_reg_block, jcp.dimM_simd_block, .9f) + && (dimN_block > current_best); + }; + + jcp.dimN_block = get_divisor_satisfying_cond( + jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond2_dimN_block); + jcp.dimN_nb_block = jcp.dimN / (jcp.dimN_reg_block * jcp.dimN_block); +} + +status_t set_wsched_DATA_W_S_G_D_avx512_core(jit_conv_winograd_conf_t &jcp) { + + jcp.kernel_kind = expl_bcast; + set_kernel_blocking_DATA_W_S_G_D(jcp); + if (!(check_kernel_cond(jcp.dimM_block, jcp.dimM_reg_block, + jcp.dimM_simd_block, jcp.dimN_block, jcp.dimN_reg_block, jcp.dimK, + .1f, .35f))) { + jcp.kernel_kind = embd_bcast; + set_kernel_blocking_DATA_W_S_G_D(jcp); + } + jcp.sched_policy = WSCHED_DATA_W_S_G_D; + return status::success; +} + +status_t _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::init_conf_kernel( + jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK) +{ + jcp.nb_reg = 32; + jcp.dimN = dimN; + jcp.dimK = dimK; + jcp.dimM = dimM; + jcp.sched_policy = WSCHED_INVALID; + + jcp.dimK_reg_block = 16; + jcp.dimM_simd_block = 16; + + if (jcp.kernel_kind == embd_bcast) { + jcp.dimM_reg_block = 1; + } + + if (!(set_wsched_DATA_W_SGD_avx512_core(jcp) == status::success)) + set_wsched_DATA_W_S_G_D_avx512_core(jcp); + + assert(jcp.sched_policy != WSCHED_INVALID); + return status::success; +} + +bool jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_relu(0) || is_sum(0); // relu or sum + case 2: return (is_sum(0) && is_relu(1)) + || (is_relu(0) && is_sum(1)); // sum->relu or relu->sum + case 3: return is_relu(0) && is_sum(1) && is_relu(2); // relu->sum->relu + default: return false; + } + + return false; +} + +status_t jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel::init_conf( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_t &src_md, memory_desc_t &weights_md, + const memory_desc_t &dst_md, const primitive_attr_t &attr) { + + status_t st = init_conf_common(jcp, cd, src_md, weights_md, dst_md); + + if (st != status::success) + return st; + + // Winograd specific initialization + jcp.itiles = (jcp.ow + tile_size - 1) / tile_size; + jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size; + jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + const int eltwise_ind = p.find(primitive_kind::eltwise, 0, 1); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + + jcp.with_sum = p.find(primitive_kind::sum, 0) != -1; + jcp.with_relu_postsum = p.find(primitive_kind::eltwise, 1) != -1; + + status_t res = init_conf_kernel(jcp, jcp.oc, jcp.ntiles, jcp.ic); + + jcp.ic_simd_block = jcp.dimK_reg_block; + jcp.ic_block = jcp.dimK_block; + jcp.nb_ic = jcp.dimK_nb_block; + jcp.oc_simd_block = jcp.dimM_simd_block; + jcp.oc_block = jcp.dimM_block; + jcp.oc_reg_block = jcp.dimM_reg_block; + jcp.ic_reg_block = 1; + jcp.nb_oc = jcp.dimM_nb_block; + jcp.tile_block_ur = jcp.dimN_reg_block; + jcp.nb_tile_block_ur = jcp.dimN_block; + jcp.tile_block = jcp.dimN_nb_block; + + /* re-create weights primitive descriptor + and set weights wino_blocking */ + if (cd.prop_kind == mkldnn_forward_inference) { + memory_desc_t expect_wei_md = weights_md; + + expect_wei_md.format_kind = format_kind::wino; + expect_wei_md.data_type = data_type::f32; + mkldnn_wino_desc_t &wd = expect_wei_md.format_desc.wino_desc; + wd.wino_format = mkldnn_wino_wei_OBaaIBOIio; + wd.r = 3; + wd.alpha = 6; + + wd.ic = jcp.ic; + wd.oc = jcp.oc; + wd.ic_block = jcp.dimK_reg_block; + wd.oc_block = jcp.dimM_simd_block; + wd.ic2_block = jcp.dimK_block; + wd.oc2_block = jcp.dimM_block * jcp.dimM_reg_block; + size_t max_size = sizeof(float) * wd.alpha * wd.alpha * jcp.ic * jcp.oc; + wd.size = max_size; + wd.adj_scale = 1.f; + + if (weights_md.format_kind == format_kind::any) + weights_md = expect_wei_md; + if (weights_md != expect_wei_md) + return status::unimplemented; + } + + return res; +} + +status_t jit_avx512_core_fp32_wino_conv_4x3_bwd_data_kernel::init_conf( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d) +{ + status_t st = init_conf_common(jcp, cd, diff_src_d, weights_d, diff_dst_d); + + if (st != status::success) + return st; + + jcp.itiles = (jcp.iw + tile_size - 1) / tile_size; + jcp.jtiles = (jcp.ih + tile_size - 1) / tile_size; + jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles; + + status_t res = init_conf_kernel(jcp, jcp.ic, jcp.ntiles, jcp.oc); + + jcp.oc_simd_block = jcp.dimK_reg_block; + jcp.oc_block = jcp.dimK_block; + jcp.nb_oc = jcp.dimK_nb_block; + jcp.ic_simd_block = jcp.dimM_simd_block; + jcp.ic_block = jcp.dimM_block; + jcp.ic_reg_block = jcp.dimM_reg_block; + jcp.oc_reg_block = 1; + jcp.nb_ic = jcp.dimM_nb_block; + jcp.tile_block_ur = jcp.dimN_reg_block; + jcp.nb_tile_block_ur = jcp.dimN_block; + jcp.tile_block = jcp.dimN_nb_block; + + return res; +} + +void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel:: +src_transform_generate() { + constexpr int G_size = 9; + const size_t ifwp = jcp.iw + jcp.l_pad; + const size_t ifhp = jcp.ih + jcp.t_pad; + + auto zmm_G = [=](int i) { + return Xbyak::Zmm(i); + }; + auto zmm_I = [=](int i) { + return Xbyak::Zmm(G_size + i); + }; + auto zmm_T = [=](int i) { + return Xbyak::Zmm(G_size + alpha + i); + }; + auto zmm_t = [=](int i) { + return Xbyak::Zmm(G_size + 2 * alpha + i); + }; + + auto init_G = [=]() { + mov(reg_G, ptr[reg_transp + GET_OFF(G)]); + for (int i = 0; i < G_size; i++) { + vbroadcastss(zmm_G(i), ptr[reg_G + i * typesize]); + } + }; + + auto load_src = [=]() { + mov(reg_I, ptr[reg_transp + GET_OFF(M)]); + xor_(reg_zero, reg_zero); + + mov(reg_ydim, reg_tj); + shl(reg_ydim, 2); //tj * tile_size(=4) + + for (int j = 0; j < alpha; j++) { + /* check if tile index is within physical spatial boundaries*/ + mov(reg_maskj, 0xffff); + cmp(reg_ydim, jcp.t_pad); + cmovl(reg_maskj, reg_zero); + cmp(reg_ydim, ifhp); + cmovge(reg_maskj, reg_zero); + + /*address offset for tile in src*/ + mov(reg_src_offset, reg_ydim); + sub(reg_src_offset, jcp.t_pad); // tj*tile_size - t_pad + imul(reg_src_offset, reg_src_offset, jcp.iw); + + mov(reg_xdim, reg_ti); + shl(reg_xdim, 2); // xdim = ti * tile_size + + add(reg_src_offset, reg_xdim); + sub(reg_src_offset, jcp.l_pad); + imul(reg_src_offset, reg_src_offset, simd_w * typesize); + for (int i = 0; i < alpha; i++) { + /* check if tile index is within physical spatial boundaries*/ + mov(reg_maski, 0xffff); + cmp(reg_xdim, jcp.l_pad); + cmovl(reg_maski, reg_zero); + cmp(reg_xdim, ifwp); + cmovge(reg_maski, reg_zero); + and_(reg_maski, reg_maskj); + + Opmask kmask_src = Xbyak::Opmask(7); + auto zmm_src = Xbyak::Zmm(31); + kmovw(kmask_src, reg_maski_32); + vpxord(zmm_src, zmm_src, zmm_src); + vmovups(zmm_src | kmask_src, ptr[reg_src + reg_src_offset]); + vmovups(ptr[reg_I], zmm_src); + + add(reg_xdim, 1); //xdim = ti * tile_size + i + add(reg_src_offset, simd_w * typesize); + add(reg_I, simd_w * typesize); + } + add(reg_ydim, 1); + } + }; + + auto fma4 = [=](Xbyak::Zmm dst, Xbyak::Zmm a, Xbyak::Zmm b, Xbyak::Zmm c) { + vmovups(dst, c); + vfmadd231ps(dst, a, b); + }; + + auto trans_I_3x3_4x4 = [=]() { + //Use 24 registers + mov(reg_I, ptr[reg_transp + GET_OFF(M)]); + mov(reg_T, ptr[reg_transp + GET_OFF(T)]); + for (int i = 0; i < alpha; i++) { + for (int j = 0; j < alpha; j++) { + size_t I_off = (j * alpha + i) * simd_w * typesize; + vmovups(zmm_I(j), ptr[reg_I + I_off]); + } + + fma4(zmm_t(0), zmm_I(2), zmm_G(0), zmm_I(4)); + fma4(zmm_t(1), zmm_I(1), zmm_G(0), zmm_I(3)); + fma4(zmm_t(2), zmm_I(2), zmm_G(1), zmm_I(4)); + fma4(zmm_t(3), zmm_I(1), zmm_G(1), zmm_I(3)); + fma4(zmm_t(4), zmm_I(0), zmm_G(2), zmm_I(4)); + fma4(zmm_t(5), zmm_I(1), zmm_G(2), zmm_I(5)); + + fma4(zmm_T(0), zmm_I(2), zmm_G(3), zmm_t(4)); + fma4(zmm_T(1), zmm_t(1), zmm_G(4), zmm_t(0)); + fma4(zmm_T(2), zmm_t(1), zmm_G(5), zmm_t(0)); + fma4(zmm_T(3), zmm_t(3), zmm_G(6), zmm_t(2)); + fma4(zmm_T(4), zmm_t(3), zmm_G(7), zmm_t(2)); + fma4(zmm_T(5), zmm_I(3), zmm_G(8), zmm_t(5)); + + for (int j = 0; j < alpha; j++) { + vmovups(ptr[reg_T + (j * alpha + i) * simd_w * typesize], + zmm_T(j)); + } + + } + + for (int j = 0; j < alpha; j++) { + for (int i = 0; i < alpha; i++) { + vmovups(zmm_T(i), ptr[reg_T + (j * alpha + i) * simd_w * typesize]); + } + + fma4(zmm_t(0), zmm_T(2), zmm_G(0), zmm_T(4)); + fma4(zmm_t(1), zmm_T(1), zmm_G(0), zmm_T(3)); + fma4(zmm_t(2), zmm_T(2), zmm_G(1), zmm_T(4)); + fma4(zmm_t(3), zmm_T(1), zmm_G(1), zmm_T(3)); + fma4(zmm_t(4), zmm_T(0), zmm_G(2), zmm_T(4)); + fma4(zmm_t(5), zmm_T(1), zmm_G(2), zmm_T(5)); + + fma4(zmm_I(0), zmm_T(2), zmm_G(3), zmm_t(4)); + fma4(zmm_I(1), zmm_t(1), zmm_G(4), zmm_t(0)); + fma4(zmm_I(2), zmm_t(1), zmm_G(5), zmm_t(0)); + fma4(zmm_I(3), zmm_t(3), zmm_G(6), zmm_t(2)); + fma4(zmm_I(4), zmm_t(3), zmm_G(7), zmm_t(2)); + fma4(zmm_I(5), zmm_T(3), zmm_G(8), zmm_t(5)); + + for (int i = 0; i < alpha; i++) { + size_t dst_off = (j * alpha * jcp.ic_block + * jcp.nb_tile_block_ur * jcp.tile_block_ur + + i * jcp.ic_block * jcp.nb_tile_block_ur * jcp.tile_block_ur) + * simd_w * typesize; + vmovups(ptr[reg_dst + dst_off], zmm_I(i)); + } + } + }; + + auto compute_transform_SDGtWo = [=]() { + mov(reg_ti, ptr[reg_transp + GET_OFF(ti)]); + mov(reg_tj, ptr[reg_transp + GET_OFF(tj)]); + mov(reg_src, ptr[reg_transp + GET_OFF(src)]); + mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]); + xor_(reg_tile_count, reg_tile_count); + Label loop_mb, loop_jtiles, loop_itiles, done; + L(loop_mb); + { + L(loop_jtiles); + { + L(loop_itiles); + { + load_src(); + + trans_I_3x3_4x4(); + + add(reg_tile_count, 1); + cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur); + jge(done); + + add(reg_dst, simd_w * typesize); + add(reg_ti, 1); + cmp(reg_ti, jcp.itiles); + jl(loop_itiles); + } + xor_(reg_ti, reg_ti); + add(reg_tj, 1); + cmp(reg_tj, jcp.jtiles); + jl(loop_jtiles); + } + xor_(reg_tj, reg_tj); + add(reg_src, jcp.ic * jcp.iw * jcp.ih * typesize); + jmp(loop_mb); + } + L(done); + }; + + auto compute_transform = [=]() { + mov(reg_src, ptr[reg_transp + GET_OFF(src)]); + xor_(reg_ti, reg_ti); + xor_(reg_tj, reg_tj); + + mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]); + mov(reg_tile_count, ptr[reg_transp + GET_OFF(tile_count)]); + imul(reg_temp, reg_tile_count, simd_w * typesize); + add(reg_dst, reg_temp); + + Label loop_jtiles, loop_itiles, next_tile_block, next_tile; + L(loop_jtiles); + + { + L(loop_itiles); + { + load_src(); + + trans_I_3x3_4x4(); + + add(reg_tile_count, 1); + cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur); + jge(next_tile_block); + add(reg_dst, simd_w * typesize); + jmp(next_tile); + + L(next_tile_block); + sub(reg_dst, (jcp.nb_tile_block_ur * jcp.tile_block_ur - 1) + * simd_w * typesize); + size_t tblk_off = alpha * alpha * jcp.ic_block + * jcp.nb_tile_block_ur * jcp.tile_block_ur + * simd_w * typesize; + add(reg_dst, tblk_off); + xor_(reg_tile_count, reg_tile_count); + + L(next_tile); + add(reg_ti, 1); + cmp(reg_ti, jcp.itiles); + jl(loop_itiles); + } + xor_(reg_ti, reg_ti); + add(reg_tj, 1); + cmp(reg_tj, jcp.jtiles); + jl(loop_jtiles); + } + }; + + preamble(); + init_G(); + if (jcp.sched_policy == WSCHED_WEI_SDGtWo) + compute_transform_SDGtWo(); + else + compute_transform(); + postamble(); +} + +void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel:: +diff_dst_transform_generate(bool with_bias) { + + constexpr int G_size = 8; + auto zmm_G = [](int i) { + return Xbyak::Zmm(31); + }; + + auto zmm_src = [=](int j, int i) { + return Xbyak::Zmm(G_size + j * 4 + i); + }; + + auto zmm_bias = Xbyak::Zmm(31); + + auto load_src = [=]() { + if (with_bias) vmovups(zmm_bias, ptr[reg_bias]); + mov(reg_ydim, reg_tj); + shl(reg_ydim, 2); //tj * tile_size(=4) + for (int j = 0; j < tile_size; j++) { + /* check if tile index is within physical spatial boundaries*/ + mov(reg_maskj, 0xffff); + cmp(reg_ydim, jcp.oh); + cmovge(reg_maskj, reg_zero); + + /*address offset for tile in src*/ + mov(reg_src_offset, reg_ydim); + imul(reg_src_offset, reg_src_offset, jcp.ow); + + mov(reg_xdim, reg_ti); + shl(reg_xdim, 2); // xdim = ti * tile_size + + add(reg_src_offset, reg_xdim); + imul(reg_src_offset, reg_src_offset, simd_w * typesize); + for (int i = 0; i < tile_size; i++) { + /* check if tile index is within physical spatial boundaries*/ + mov(reg_maski, 0xffff); + cmp(reg_xdim, jcp.ow); + cmovge(reg_maski, reg_zero); + and_(reg_maski, reg_maskj); + + Opmask kmask_src = Xbyak::Opmask(7); + kmovw(kmask_src, reg_maski_32); + vpxord(zmm_src(j, i), zmm_src(j, i), zmm_src(j, i)); + vmovups(zmm_src(j, i) | kmask_src, ptr[reg_src + reg_src_offset]); + if (with_bias) vaddps(zmm_bias | kmask_src, zmm_bias, + ptr[reg_src + reg_src_offset]); + + add(reg_xdim, 1); //xdim = ti * tile_size + i + add(reg_src_offset, simd_w * typesize); + } + add(reg_ydim, 1); + } + if(with_bias) vmovups(ptr[reg_bias], zmm_bias); + }; + + auto zmm_t = [=](int i) { + return Xbyak::Zmm(G_size + 16 + i); + }; + + auto zmm_T = [=](int j, int i) { + return Xbyak::Zmm(j * 4 + i); + }; + + auto movps = [=](Xbyak::Reg64 reg_dst, size_t dst_off, Xbyak::Zmm a) { + if (jcp.sched_policy == WSCHED_WEI_SDGtWo) + vmovups(ptr[reg_dst + dst_off], a); + else + vmovntps(ptr[reg_dst + dst_off], a); + }; + + auto trans_W_3x3_4x4 = [=]() { + mov(reg_G, ptr[reg_transp + GET_OFF(G)]); + for (int i = 0; i < tile_size; i++) { + vbroadcastss(zmm_G(0), ptr[reg_G]); + vmulps(zmm_t(0), zmm_src(2, i), zmm_G(0)); + + vbroadcastss(zmm_G(1), ptr[reg_G + typesize]); + vmovups(zmm_t(1), zmm_t(0)); + vfmsub231ps(zmm_t(1), zmm_src(0, i), zmm_G(1)); + + vbroadcastss(zmm_G(2), ptr[reg_G + 2 * typesize]); + vmovups(zmm_t(2), zmm_t(0)); + vfmadd231ps(zmm_t(2), zmm_src(0, i), zmm_G(2)); + + vbroadcastss(zmm_G(3), ptr[reg_G + 3 * typesize]); + vmulps(zmm_t(3), zmm_src(1, i), zmm_G(3)); + + vbroadcastss(zmm_G(4), ptr[reg_G + 4 * typesize]); + vfmadd231ps(zmm_t(3), zmm_src(3, i), zmm_G(4)); + + vbroadcastss(zmm_G(5), ptr[reg_G + 5 * typesize]); + vmulps(zmm_t(4), zmm_src(1, i), zmm_G(5)); + + vbroadcastss(zmm_G(6), ptr[reg_G + 6 * typesize]); + vfmadd231ps(zmm_t(4), zmm_src(3, i), zmm_G(6)); + + vbroadcastss(zmm_G(7), ptr[reg_G + 7 * typesize]); + vmulps(zmm_T(0, i), zmm_src(0, i), zmm_G(7)); + vsubps(zmm_T(1, i), zmm_t(1), zmm_t(3)); + vaddps(zmm_T(2, i), zmm_t(1), zmm_t(3)); + vaddps(zmm_T(3, i), zmm_t(2), zmm_t(4)); + vsubps(zmm_T(4, i), zmm_t(2), zmm_t(4)); + vmovups(zmm_T(5, i), zmm_src(3, i)); + } + + for (int j = 0; j < alpha; j++) { + vbroadcastss(zmm_G(0), ptr[reg_G]); + vmulps(zmm_t(0), zmm_T(j, 2), zmm_G(0)); + + vbroadcastss(zmm_G(1), ptr[reg_G + typesize]); + vmovups(zmm_t(1), zmm_t(0)); + vfmsub231ps(zmm_t(1), zmm_T(j, 0), zmm_G(1)); + + vbroadcastss(zmm_G(2), ptr[reg_G + 2 * typesize]); + vmovups(zmm_t(2), zmm_t(0)); + vfmadd231ps(zmm_t(2), zmm_T(j, 0), zmm_G(2)); + + vbroadcastss(zmm_G(3), ptr[reg_G + 3 * typesize]); + vmulps(zmm_t(3), zmm_T(j, 1), zmm_G(3)); + + vbroadcastss(zmm_G(4), ptr[reg_G + 4 * typesize]); + vfmadd231ps(zmm_t(3), zmm_T(j, 3), zmm_G(4)); + + vbroadcastss(zmm_G(5), ptr[reg_G + 5 * typesize]); + vmulps(zmm_t(4), zmm_T(j, 1), zmm_G(5)); + + vbroadcastss(zmm_G(6), ptr[reg_G + 6 * typesize]); + vfmadd231ps(zmm_t(4), zmm_T(j, 3), zmm_G(6)); + + vbroadcastss(zmm_G(7), ptr[reg_G + 7 * typesize]); + vmulps(zmm_t(0), zmm_T(j, 0), zmm_G(7)); + vsubps(zmm_t(5), zmm_t(1), zmm_t(3)); + vaddps(zmm_t(1), zmm_t(1), zmm_t(3)); + vaddps(zmm_t(6), zmm_t(2), zmm_t(4)); + vsubps(zmm_t(2), zmm_t(2), zmm_t(4)); + vmovups(zmm_t(3), zmm_T(j, 3)); + + int alpha_offset = (jcp.oc / jcp.nb_oc) + * (jcp.ntiles / jcp.tile_block) * typesize; + int dst_off = j * alpha * alpha_offset; + movps(reg_dst, dst_off, zmm_t(0)); + dst_off += alpha_offset; + movps(reg_dst, dst_off, zmm_t(5)); + dst_off += alpha_offset; + movps(reg_dst, dst_off, zmm_t(1)); + dst_off += alpha_offset; + movps(reg_dst, dst_off, zmm_t(6)); + dst_off += alpha_offset; + movps(reg_dst, dst_off, zmm_t(2)); + dst_off += alpha_offset; + movps(reg_dst, dst_off, zmm_t(3)); + } + + }; + auto compute_transform_SDGtWo = [=]() { + mov(reg_src, ptr[reg_transp + GET_OFF(src)]); + mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]); + if (with_bias) mov(reg_bias, ptr[reg_transp + GET_OFF(bias)]); + + xor_(reg_zero, reg_zero); + xor_(reg_oc_ur, reg_oc_ur); + Label loop_mb, loop_jtiles, loop_itiles, loop_oc_ur, tiles_done; + + L(loop_oc_ur); + { + mov(reg_ti, ptr[reg_transp + GET_OFF(ti)]); + mov(reg_tj, ptr[reg_transp + GET_OFF(tj)]); + xor_(reg_tile_count, reg_tile_count); + L(loop_mb); + { + L(loop_jtiles); + { + L(loop_itiles); + { + load_src(); + + trans_W_3x3_4x4(); + + add(reg_tile_count, 1); + cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur); + jge(tiles_done); + + add(reg_dst, jcp.oc_reg_block * simd_w * typesize); + add(reg_ti, 1); + cmp(reg_ti, jcp.itiles); + jl(loop_itiles); + } + xor_(reg_ti, reg_ti); + add(reg_tj, 1); + cmp(reg_tj, jcp.jtiles); + jl(loop_jtiles); + } + xor_(reg_tj, reg_tj); + add(reg_src, jcp.oc * jcp.ow * jcp.oh * typesize); + jmp(loop_mb); + } + + L(tiles_done); + mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]); + add(reg_dst, simd_w * typesize); + mov(reg_src, ptr[reg_transp + GET_OFF(src)]); + add(reg_src, jcp.oh * jcp.ow * simd_w * typesize); + + if (with_bias) add(reg_bias, simd_w * typesize); + add(reg_oc_ur, 1); + cmp(reg_oc_ur, jcp.oc_reg_block); + jl(loop_oc_ur); + } + }; + + auto compute_transform = [=]() { + mov(reg_src, ptr[reg_transp + GET_OFF(src)]); + mov(reg_G, ptr[reg_transp + GET_OFF(G)]); + if (with_bias) mov(reg_bias, ptr[reg_transp + GET_OFF(bias)]); + + mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]); + mov(reg_tile_count, ptr[reg_transp + GET_OFF(tile_count)]); + imul(reg_temp, reg_tile_count, jcp.oc_reg_block * simd_w * typesize); + add(reg_dst, reg_temp); + + xor_(reg_zero, reg_zero); + xor_(reg_oc_ur, reg_oc_ur); + Label loop_mb, loop_jtiles, loop_itiles, loop_oc_ur, next_tile_block, next_tile; + + L(loop_oc_ur); + { + xor_(reg_ti, reg_ti); + xor_(reg_tj, reg_tj); + + L(loop_jtiles); + { + L(loop_itiles); + { + load_src(); + + trans_W_3x3_4x4(); + + add(reg_tile_count, 1); + cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur); + jge(next_tile_block); + add(reg_dst, jcp.oc_reg_block * simd_w * typesize); + jmp(next_tile); + + L(next_tile_block); + sub(reg_dst, (jcp.nb_tile_block_ur * jcp.tile_block_ur - 1) + * jcp.oc_reg_block * simd_w * typesize); + int tblk_off = alpha * alpha * (jcp.oc/jcp.nb_oc) + * (jcp.ntiles/jcp.tile_block) * typesize; + add(reg_dst, tblk_off); + xor_(reg_tile_count, reg_tile_count); + + L(next_tile); + add(reg_ti, 1); + cmp(reg_ti, jcp.itiles); + jl(loop_itiles); + } + xor_(reg_ti, reg_ti); + add(reg_tj, 1); + cmp(reg_tj, jcp.jtiles); + jl(loop_jtiles); + } + + mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]); + mov(reg_tile_count, ptr[reg_transp + GET_OFF(tile_count)]); + imul(reg_temp, reg_tile_count, jcp.oc_reg_block * simd_w * typesize); + add(reg_dst, reg_temp); + add(reg_dst, simd_w * typesize); + mov(reg_src, ptr[reg_transp + GET_OFF(src)]); + add(reg_src, jcp.oh * jcp.ow * simd_w * typesize); + + if (with_bias) add(reg_bias, simd_w * typesize); + add(reg_oc_ur, 1); + cmp(reg_oc_ur, jcp.oc_reg_block); + jl(loop_oc_ur); + } + }; + + preamble(); + if (jcp.sched_policy == WSCHED_WEI_SDGtWo) { + compute_transform_SDGtWo(); + } else { + compute_transform(); + } + postamble(); +} + +void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel:: +diff_weights_transform_generate(bool first_tile) { + int G_size = 4; + + auto zmm_G = [](int i) { + return Xbyak::Zmm(i); + }; + + auto init_G = [=]() { + mov(reg_G, ptr[reg_transp + GET_OFF(G)]); + for (int i = 0; i < G_size; i++) + vbroadcastss(zmm_G(i), ptr[reg_G + i * typesize]); + }; + + auto zmm_src = [=](int i) { + return Xbyak::Zmm(G_size + i); + }; + + auto load_src = [=](int i) { + for (int j = 0; j < alpha; j++) { + size_t alpha_offset = jcp.oc_block * jcp.oc_reg_block + * jcp.ic_block * simd_w * simd_w * typesize; + size_t src_off = (j * alpha + i) * alpha_offset; + vmovups(zmm_src(j), EVEX_compress_addr(reg_src, src_off)); + } + }; + + auto zmm_t = [=](int i) { + return Xbyak::Zmm(G_size + 6 + i); + }; + + auto zmm_T = [=](int j, int i) { + return Xbyak::Zmm(G_size + 6 + 3 + j * 6 + i); + }; + + auto zmm_dst = [=](int i) { + return Xbyak::Zmm(G_size + i); + }; + + auto zmm_temp = Xbyak::Zmm(31); + + auto store_dst = [=](int j) { + for (int i = 0; i < jcp.kw; i++) { + size_t dst_off = (j * jcp.kw + i) * simd_w * simd_w * typesize; + + if (!first_tile) { + vmovups(zmm_temp, EVEX_compress_addr(reg_dst, dst_off)); + vaddps(zmm_dst(i), zmm_dst(i), zmm_temp); + } + vmovntps(EVEX_compress_addr(reg_dst, dst_off), zmm_dst(i)); + } + }; + + auto compute_transform = [=] () { + mov(reg_src, ptr[reg_transp + GET_OFF(src)]); + mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]); + + xor_(reg_ic_simd, reg_ic_simd); + Label loop_ic_simd; + L(loop_ic_simd); + { + for (int i = 0; i < alpha; i++) { + load_src(i); + + vaddps(zmm_t(0), zmm_src(1), zmm_src(2)); + vaddps(zmm_t(1), zmm_src(3), zmm_src(4)); + vmovups(zmm_t(2), zmm_src(5)); + vfmadd231ps(zmm_t(2), zmm_t(1), zmm_G(0)); + + vaddps(zmm_T(0, i), zmm_src(0), zmm_t(0)); + vaddps(zmm_T(0, i), zmm_T(0, i), zmm_t(1)); + vsubps(zmm_T(1, i), zmm_src(1), zmm_src(2)); + vmulps(zmm_T(1, i), zmm_T(1, i), zmm_G(1)); + vsubps(zmm_temp, zmm_src(3), zmm_src(4)); + vfmadd231ps(zmm_T(1, i), zmm_temp, zmm_G(2)); + vmovups(zmm_T(2, i), zmm_t(2)); + vfmadd231ps(zmm_T(2, i), zmm_t(0), zmm_G(3)); + } + + for (int j = 0; j < jcp.kh; j++) { + vaddps(zmm_t(0), zmm_T(j, 1), zmm_T(j, 2)); + vaddps(zmm_t(1), zmm_T(j, 3), zmm_T(j, 4)); + vmovups(zmm_t(2), zmm_T(j, 5)); + vfmadd231ps(zmm_t(2), zmm_t(1), zmm_G(0)); + + vaddps(zmm_dst(0), zmm_T(j, 0), zmm_t(0)); + vaddps(zmm_dst(0), zmm_dst(0), zmm_t(1)); + vsubps(zmm_dst(1), zmm_T(j, 1), zmm_T(j, 2)); + vmulps(zmm_dst(1), zmm_dst(1), zmm_G(1)); + vsubps(zmm_temp, zmm_T(j, 3), zmm_T(j, 4)); + vfmadd231ps(zmm_dst(1), zmm_temp, zmm_G(2)); + vmovups(zmm_dst(2), zmm_t(2)); + vfmadd231ps(zmm_dst(2), zmm_t(0), zmm_G(3)); + + store_dst(j); + } + + add(reg_src, jcp.oc_reg_block * simd_w * typesize); + add(reg_dst, simd_w * typesize); + add(reg_ic_simd, 1); + cmp(reg_ic_simd, simd_w); + jl(loop_ic_simd); + } + }; + preamble(); + push(reg_EVEX_max_8b_offt); + mov(reg_EVEX_max_8b_offt, 2 * EVEX_max_8b_offt); + init_G(); + compute_transform(); + pop(reg_EVEX_max_8b_offt); + postamble(); +} + +void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::gemm_loop_generate( + bool is_first_tile) +{ + auto zmm_srcA = [=]() { + return Xbyak::Zmm(0); + }; + + auto zmm_srcB = [=] (size_t N_ur){ + return Xbyak::Zmm(N_ur + 1); + }; + + auto broadcastB = [=](size_t K_ur) { + for (int N_bcast = 0; N_bcast < jcp.dimN_bcast_ur; N_bcast++) { + size_t srcB_off = (K_ur * jcp.dimN_reg_block + N_bcast) + * sizeof(float); + vbroadcastss(zmm_srcB(N_bcast), EVEX_compress_addr(reg_srcB, srcB_off)); + } + }; + + auto load_srcA = [=] (size_t K_ur, int M_ur) { + size_t srcA_off = (K_ur * jcp.dimM_reg_block * jcp.dimM_simd_block + + M_ur * jcp.dimM_simd_block) * sizeof(float); + vmovups(zmm_srcA(), EVEX_compress_addr(reg_srcA, srcA_off)); + }; + + auto zmm_dstC = [=](size_t M_reg_ur, int N_bcast){ + size_t idx = 1 // zmm_srcA + + jcp.dimN_bcast_ur // zmm_srcB + + M_reg_ur * jcp.dimN_bcast_ur + N_bcast; + assert(idx < 32); + return Xbyak::Zmm(idx); + }; + auto prepare_accumm = [=](){ + for (int M_reg_ur = 0; M_reg_ur < jcp.dimM_reg_block; M_reg_ur++) { + for (int N_bcast = 0; N_bcast < jcp.dimN_bcast_ur; N_bcast++) { + Zmm zmm = zmm_dstC(M_reg_ur, N_bcast); + vpxord(zmm, zmm, zmm); + } + } + }; + + auto store_dstC = [=](){ + /******** Write C back to memory *******/ + for (int M_reg = 0; M_reg < jcp.dimM_reg_block; M_reg++) { + for (int N_ur = 0; N_ur < jcp.dimN_bcast_ur; ++N_ur) { + Zmm zmm = zmm_dstC(M_reg, N_ur); + size_t C_off = (N_ur * jcp.dimM_reg_block * jcp.dimM_simd_block + + M_reg * jcp.dimM_simd_block) * sizeof(float); + if (!is_first_tile) { + vmovups(Xbyak::Zmm(0), EVEX_compress_addr(reg_dstC, C_off)); + vaddps(zmm, zmm, Xbyak::Zmm(0)); + } + vmovups(EVEX_compress_addr(reg_dstC, C_off), zmm); + } + } + }; + + auto inner_loops = [=]() { + Label dimM_block_loop, dimK_block_loop, dimN_block_loop, dimN_bcast_ur; + + mov(reg_dimM_block_loop_cnt, jcp.dimM_block); + L(dimM_block_loop); + { /************* OC_block (M) loop ***********/ + mov(reg_dimN_block_loop_cnt, jcp.dimN_block); + L(dimN_block_loop); + { /*************** IC_block (N) loop *********/ + + mov(reg_nb_dimN_bcast_ur, jcp.dimN_reg_block/jcp.dimN_bcast_ur); + L(dimN_bcast_ur); + { + prepare_accumm(); + + mov(reg_dimK_block_loop_cnt, jcp.dimK_block); + L(dimK_block_loop); + { + /************* nb_tile_ur(K) loop ********/ + for (int K_ur = 0; K_ur < jcp.dimK_reg_block; K_ur++) { + + broadcastB(K_ur); + + for (int M_reg_ur = 0; M_reg_ur < jcp.dimM_reg_block; M_reg_ur++) { + load_srcA(K_ur, M_reg_ur); + for (int N_bcast = 0; N_bcast < jcp.dimN_bcast_ur; ++N_bcast) { + vfmadd231ps(zmm_dstC(M_reg_ur, N_bcast), zmm_srcA(), + zmm_srcB(N_bcast)); + } + } + } + add(reg_srcA, jcp.dimK_reg_block + * jcp.dimM_reg_block * jcp.dimM_simd_block + * sizeof(float)); + add(reg_srcB, jcp.dimK_reg_block + * jcp.dimN_reg_block + * sizeof(float)); + sub(reg_dimK_block_loop_cnt, 1); + jnz(dimK_block_loop); + } + + store_dstC(); + + sub(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block + * jcp.dimM_reg_block * jcp.dimM_simd_block + * sizeof(float)); + sub(reg_srcB, jcp.dimK_block * jcp.dimK_reg_block + * jcp.dimN_reg_block + * sizeof(float)); + add(reg_srcB, jcp.dimN_bcast_ur * sizeof(float)); + add(reg_dstC, jcp.dimN_bcast_ur + * jcp.dimM_reg_block * jcp.dimM_simd_block + * sizeof(float)); + sub(reg_nb_dimN_bcast_ur, 1); + jnz(dimN_bcast_ur); + } + + sub(reg_srcB, jcp.dimN_reg_block * sizeof(float)); + add(reg_srcB, jcp.dimK_block + * jcp.dimK_reg_block + * jcp.dimN_reg_block * sizeof(float)); + sub(reg_dimN_block_loop_cnt, 1); + jnz(dimN_block_loop); + } + + sub(reg_srcB, jcp.dimN_block + * jcp.dimK_block * jcp.dimK_reg_block + * jcp.dimN_reg_block + * sizeof(float)); + add(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block + * jcp.dimM_reg_block * jcp.dimM_simd_block + * sizeof(float)); + sub(reg_dimM_block_loop_cnt, 1); + jnz(dimM_block_loop); + } + }; + + /* Preamble */ + preamble(); + + inner_loops(); + + /* Postamble */ + postamble(); + ret(); +} + +namespace { + +void set_jcp_WEI_params(jit_conv_winograd_conf_t &jcp) { +/*M params*/ + jcp.dimM_nb_block = jcp.dimM / jcp.dimM_block / jcp.dimM_reg_block + / jcp.dimM_simd_block; + jcp.oc_reg_block = jcp.dimM_reg_block; + jcp.oc_block = jcp.dimM_block; + jcp.nb_oc = jcp.dimM_nb_block; + /*N params*/ + jcp.dimN_nb_block = jcp.dimN / jcp.dimN_block / jcp.dimN_reg_block; + jcp.ic_block = jcp.dimN_block; + jcp.nb_ic = jcp.dimN_nb_block; + + /*K params*/ + jcp.dimK_nb_block = jcp.dimK / jcp.dimK_block / jcp.dimK_reg_block; + jcp.tile_block_ur = jcp.dimK_reg_block; + jcp.nb_tile_block_ur = jcp.dimK_block; + jcp.tile_block = jcp.dimK_nb_block; +} + +status_t set_wsched_WEI_SDGtWo(jit_conv_winograd_conf_t &jcp) { + + size_t K_blk_ur, N_blk, M_blk; + /* IS this strategy feasible? */ + auto test_MV_large_enough = [](jit_conv_winograd_conf_t &jcp) { + size_t M_sz = alpha * alpha * jcp.dimM * jcp.dimK * sizeof(float); + size_t V_sz = alpha * alpha * jcp.dimN * jcp.dimK * sizeof(float); + size_t nthreads = mkldnn_get_max_threads(); + return (((V_sz + M_sz) / nthreads) >= 2 * L2_cache_size) + && (jcp.dimK / nthreads >= 1.0); + }; + + auto test_min_dimK_L1 = [](jit_conv_winograd_conf_t &jcp, int dimK_block_ur, + int max_block=1) { + size_t L1_block_M = jcp.dimM_reg_block * jcp.dimM_simd_block * dimK_block_ur * sizeof(float); + size_t L1_block_N = jcp.dimN_reg_block * dimK_block_ur * sizeof(float); + size_t M_L2_block = alpha * alpha * jcp.dimM * dimK_block_ur * sizeof(float); + size_t nthreads = mkldnn_get_max_threads(); + bool load_balance=true; + if (!(jcp.dimK % nthreads)) { + load_balance = ((jcp.dimK / dimK_block_ur) % nthreads == 0); + } + return (L1_block_M + L1_block_N >= 0.1 * L1_cache_size) + && (L1_block_M + L1_block_N <= 0.5 * L1_cache_size) + && load_balance + && (M_L2_block < L2_cache_size); + }; + + auto test_dimK_ur = [](jit_conv_winograd_conf_t &jcp, int dimK_ur, + int useless_arg=0) { + return (dimK_ur >= 2) && (dimK_ur <= 8); + }; + + auto blocking_ok = [&](){ + size_t M_L2_block = alpha * alpha * M_blk * jcp.dimM_reg_block * jcp.dimM_simd_block + * K_blk_ur * sizeof(float); + size_t V_L2_block = alpha * alpha * N_blk * jcp.dimN_reg_block + * K_blk_ur * sizeof(float); + size_t U_L2_block = alpha * alpha * M_blk * jcp.dimM_reg_block * jcp.dimM_simd_block + * N_blk * jcp.dimN_reg_block * sizeof(float); + size_t L2_block = M_L2_block + V_L2_block + U_L2_block; + /*Replace 2.375 with L2+L3 cache size*/ + return (L2_block > 0.1 * L2_cache_size) && (L2_block <= 1.2 * L2_cache_size); + }; + + if (test_MV_large_enough(jcp)) { + if ((jcp.dimM/jcp.dimM_simd_block) % 2 == 0) { + jcp.dimM_reg_block = 2; + } else { + jcp.dimM_reg_block = 1; + } + jcp.dimM_simd_block = jcp.oc_simd_block; + jcp.dimN_reg_block = jcp.ic_simd_block; + jcp.dimN_bcast_ur = 8; + /*dimK_block and dimK_ur*/ + size_t min_dimK_block_ur = get_divisor_satisfying_cond(jcp, jcp.dimK, 1, test_min_dimK_L1); + + jcp.dimM_block = jcp.dimM/jcp.dimM_reg_block/jcp.dimM_simd_block; + jcp.dimN_block = jcp.dimN/jcp.dimN_reg_block; + for (K_blk_ur = min_dimK_block_ur; K_blk_ur >= 1; --K_blk_ur) { + if (test_min_dimK_L1(jcp, K_blk_ur) && !(jcp.dimK % K_blk_ur)) { + for (N_blk = jcp.dimN_block; N_blk >= 1; --N_blk) { + if (!(jcp.dimN_block % N_blk)) { + for (M_blk = jcp.dimM_block; M_blk >= 1; --M_blk) { + if (!(jcp.dimM_block % M_blk) && blocking_ok()) { + jcp.dimK_reg_block = get_divisor_satisfying_cond(jcp, K_blk_ur, 1, test_dimK_ur); + if (!test_dimK_ur(jcp, jcp.dimK_reg_block)) return status::unimplemented; + jcp.dimK_block = K_blk_ur / jcp.dimK_reg_block; + jcp.dimN_block = N_blk; + jcp.dimM_block = M_blk; + jcp.sched_policy = WSCHED_WEI_SDGtWo; + set_jcp_WEI_params(jcp); + jcp.nthr = nstl::min(mkldnn_get_max_threads(), + jcp.tile_block); + return status::success; + } + } + } + } + } + } + } + return status::unimplemented; +} + +status_t set_wsched_WEI_S_D_Giot_W(jit_conv_winograd_conf_t &jcp) { + if ((jcp.dimM/jcp.dimM_simd_block) % 2 == 0) { + jcp.dimM_reg_block = 2; + } else { + jcp.dimM_reg_block = 1; + } + jcp.dimN_bcast_ur = 8; + jcp.dimN_reg_block = jcp.ic_simd_block; + jcp.dimM_simd_block = jcp.oc_simd_block; + jcp.dimN_block = jcp.dimN / jcp.dimN_reg_block; + jcp.dimM_block = jcp.dimM / jcp.dimM_reg_block / jcp.dimM_simd_block; + float C1 = 0.0, C2 = 0.0; + float C1_max = 0.5, C2_max = 1.4; + int N_blk, M_blk, K_blk_ur; + + auto test_dimK_ur = [](jit_conv_winograd_conf_t &jcp, int dimK_ur, + int useless_arg=0) { + return (dimK_ur >= 2) && (dimK_ur <= 8); + }; + + auto blocking_ok = [&]() -> bool { + size_t L1_block_M = jcp.dimM_reg_block * jcp.dimM_simd_block * K_blk_ur * sizeof(float); + size_t L1_block_N = jcp.dimN_reg_block * K_blk_ur * sizeof(float); + bool L1_cond = ((L1_block_N + L1_block_M) >= C1 * L1_cache_size) + && ((L1_block_N + L1_block_M) <= C1_max * L1_cache_size); + + size_t nb_N_blk = jcp.dimN/N_blk/jcp.dimN_reg_block; + size_t nb_M_blk = jcp.dimM/M_blk/jcp.dimM_reg_block/jcp.dimM_simd_block; + size_t nb_K_blk = jcp.dimK / K_blk_ur; + size_t nthreads = mkldnn_get_max_threads(); + bool load_balance = (nb_K_blk * nb_N_blk * nb_M_blk) >= nthreads; + if (!(nb_K_blk % nthreads)) { + load_balance = load_balance && (nb_K_blk % nthreads == 0); + } + + size_t V_L2_block = alpha * alpha * N_blk * jcp.dimN_reg_block * K_blk_ur * sizeof(float); + + size_t L2_block = V_L2_block; + /*Replace 2.375 with L2+L3 cache size*/ + bool L2_cond = (L2_block >= C2 * L2_cache_size) && (L2_block <= C2_max * L2_cache_size); + return L1_cond && load_balance && L2_cond; + }; + + for (K_blk_ur = jcp.dimK; K_blk_ur >= 1; --K_blk_ur) { + if (jcp.dimK % K_blk_ur == 0) { + for (N_blk = jcp.dimN_block; N_blk >= 1; --N_blk) { + if (jcp.dimN_block % N_blk == 0) { + for (M_blk = jcp.dimM_block; M_blk >= 1; --M_blk) { + if (jcp.dimM_block % M_blk == 0) { + if (blocking_ok()) { + jcp.dimN_block = N_blk; + jcp.dimM_block = M_blk; + jcp.dimK_reg_block = get_divisor_satisfying_cond(jcp, K_blk_ur, 1, test_dimK_ur); + jcp.dimK_block = K_blk_ur / jcp.dimK_reg_block; + jcp.sched_policy = WSCHED_WEI_S_D_Giot_W; + set_jcp_WEI_params(jcp); + return status::success; + } + } + } + } + } + } + } + jcp.dimK_reg_block = 1; + jcp.dimK_block = 1; + jcp.sched_policy = WSCHED_WEI_S_D_Giot_W; + set_jcp_WEI_params(jcp); + return status::success; +} +} // namespace +status_t jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::init_conf( + jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &diff_dst_d, + const memory_desc_wrapper &diff_weights_d) { + if (!mayiuse(avx512_core)) + return status::unimplemented; + else + jcp.ver = ver_avx512_core; + + jcp.nthr = mkldnn_get_max_threads(); + + jcp.prop_kind = cd.prop_kind; + const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1; + jcp.mb = src_d.dims()[0]; + jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1; + jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = diff_dst_d.dims()[2]; + jcp.ow = diff_dst_d.dims()[3]; + jcp.kh = diff_weights_d.dims()[with_groups + 2]; + jcp.kw = diff_weights_d.dims()[with_groups + 3]; + jcp.t_pad = cd.padding[0][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + jcp.r_pad = nstl::max( + 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad); + jcp.b_pad = nstl::max( + 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad); + jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad; + jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad; + jcp.ohp = jcp.oh; + jcp.owp = jcp.ow; + jcp.with_bias = (cd.diff_bias_desc.format_kind != format_kind::undef); + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + + bool ok_to_pad_channels = jcp.ngroups == 1; + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + } + + // Winograd specific initialization + jcp.itiles = (jcp.ow + tile_size - 1) / tile_size; + jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size; + jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles; + + // Winograd kernel works only for 3x3 convolution with stride 1 + if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto, + is_winograd_faster_than_direct(jcp))) + return status::unimplemented; + + if (jcp.ngroups != 1) + return status::unimplemented; + if ((jcp.kh != 3) || (jcp.kw != 3)) + return status::unimplemented; + if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0)) + return status::unimplemented; + if ((jcp.stride_h != 1) || (jcp.stride_w != 1)) + return status::unimplemented; + if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0) + return status::unimplemented; + + format_tag_t dat_tag = nChw16c; + format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o; + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag); + + if (jcp.src_tag != dat_tag) return status::unimplemented; + if (jcp.wei_tag != wei_tag) return status::unimplemented; + if (jcp.dst_tag != dat_tag) return status::unimplemented; + + bool layout_consistency = true + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= diff_dst_d.padded_dims()[1] + && jcp.ic <= diff_weights_d.padded_dims()[with_groups + 1] + && jcp.oc <= diff_weights_d.padded_dims()[with_groups + 0]; + if (!layout_consistency) return status::unimplemented; + + /******************Kernel blocking Parameters ***********/ + jcp.ic_simd_block = simd_w; + jcp.oc_simd_block = simd_w; + + jcp.dimK = jcp.ntiles; + jcp.dimN = jcp.ic; + jcp.dimM = jcp.oc; + jcp.dimM_simd_block = jcp.oc_simd_block; + jcp.dimN_reg_block = jcp.ic_simd_block; + jcp.sched_policy = WSCHED_INVALID; + status_t res = set_wsched_WEI_SDGtWo(jcp); + if (res == status::unimplemented) { + res = set_wsched_WEI_S_D_Giot_W(jcp); + assert(res == status::success); + } + return res; +} +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp new file mode 100644 index 0000000000..025a554d92 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp @@ -0,0 +1,291 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX512_CORE_FP32_WINO_CONV_4x3_KERNEL_HPP +#define JIT_AVX512_CORE_FP32_WINO_CONV_4x3_KERNEL_HPP + +#include "c_types_map.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" + +#include "jit_avx512_common_conv_winograd_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct _jit_avx512_core_fp32_wino_conv_4x3_data_kernel + : public jit_generator { + _jit_avx512_core_fp32_wino_conv_4x3_data_kernel( + jit_conv_winograd_conf_t ajcp) + : jcp(ajcp) { + { + this->weights_transform_data_ker_generate(); + weights_transform_data_ker + = (decltype(weights_transform_data_ker)) this->getCode(); + } + { + align(); + const Xbyak::uint8 *addr = getCurr(); + this->input_transform_data_ker_generate(); + input_transform_data_ker = (decltype(input_transform_data_ker))addr; + } + { + align(); + const Xbyak::uint8 *addr = getCurr(); + this->output_transform_data_ker_generate(); + output_transform_data_ker + = (decltype(output_transform_data_ker))addr; + } + { + align(); + const Xbyak::uint8 *addr = getCurr(); + this->gemm_loop_generate(); + gemm_loop_ker = (decltype(gemm_loop_ker))addr; + } + } + + DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_core_fp32_wino_conv_4x3_data_kernel) + + static status_t init_conf_common(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d); + + static status_t init_conf_kernel( + jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK); + + jit_conv_winograd_conf_t jcp; + void (*gemm_loop_ker)(float *, const float *, const float *, const int); + void (*input_transform_data_ker)(jit_wino_transform_call_s *); + void (*output_transform_data_ker)(jit_wino_transform_call_s *); + void (*weights_transform_data_ker)(jit_wino_transform_call_s *); + +protected: + using reg64_t = const Xbyak::Reg64; + using reg32_t = const Xbyak::Reg32; + enum { typesize = sizeof(float) }; + + void gemm_loop_generate(); + void input_transform_data_ker_generate(); + void output_transform_data_ker_generate(); + void weights_transform_data_ker_generate(); + + /* registers used for GEMM */ + reg64_t reg_dstC = abi_param1; + reg64_t reg_srcA = abi_param2; + reg64_t reg_srcB = abi_param3; + reg64_t reg_is_beta_zero = abi_param4; + + reg64_t reg_dimM_block_loop_cnt = r10; + reg64_t reg_dimK_block_loop_cnt = r11; + + /* registers used for transforms*/ + reg64_t param = abi_param1; + + /* registers used for output_transform_data_ker */ + reg64_t oreg_temp = abi_not_param1; + reg64_t oreg_Ow = r9; + reg64_t oreg_src = r11; + reg64_t oreg_tile_block = r12; + reg64_t oreg_tile_block_ur = r13; + reg64_t oreg_nb_tile_block_ur = r14; + reg64_t oreg_O = r8; + reg64_t oreg_T = r10; + reg64_t oreg_dst = r11; + reg64_t oreg_ydim = r14; + reg64_t oreg_xdim = r15; + reg64_t oreg_out_j = r12; + reg64_t oreg_bias = rbx; + reg64_t imm_addr64 = rax; + + /* registers used for input_transform_data_ker */ + reg64_t ireg_temp = abi_not_param1; + reg64_t ireg_jtiles = rax; + reg64_t ireg_itiles = rbx; + reg64_t ireg_I = r8; + reg64_t ireg_src = r13; + reg64_t ireg_ydim = r14; + reg64_t ireg_xdim = r15; + reg64_t ireg_inp_j = r12; + reg64_t ireg_inp_i = rdx; + reg64_t ireg_mask_j = r11; + reg64_t ireg_mask = rsi; + reg32_t ireg_mask_32 = esi; + reg64_t ireg_zero = r9; + reg64_t ireg_Iw = r9; + reg64_t ireg_T = r10; + reg64_t ireg_tile_block = r12; + reg64_t ireg_tile_block_ur = r13; + reg64_t ireg_nb_tile_block_ur = r14; + reg64_t ireg_output = r15; + + /* registers used for wei transform */ + reg64_t wreg_temp = abi_not_param1; + reg64_t wreg_F = r8; + reg64_t wreg_src = r9; + reg64_t wreg_MT = r15; + reg64_t wreg_M = r14; + reg64_t wreg_dst = r10; + reg64_t wreg_dst_aux = r9; + reg64_t wreg_dst_idx = r8; + reg64_t wreg_Fw = r11; + reg64_t wreg_T = r12; + reg64_t wreg_cnt_j = rdx; + reg64_t wreg_F_aux = r14; + reg64_t wreg_Fw_aux = r15; +}; + +struct jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel + : _jit_avx512_core_fp32_wino_conv_4x3_data_kernel { + using _jit_avx512_core_fp32_wino_conv_4x3_data_kernel:: + _jit_avx512_core_fp32_wino_conv_4x3_data_kernel; + + static bool post_ops_ok(jit_conv_conf_t &jcp, const primitive_attr_t &attr); + + static status_t init_conf(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_t &src_md, + memory_desc_t &weights_md, const memory_desc_t &dst_md, + const primitive_attr_t &attr); +}; + +struct jit_avx512_core_fp32_wino_conv_4x3_bwd_data_kernel + : public _jit_avx512_core_fp32_wino_conv_4x3_data_kernel { + using _jit_avx512_core_fp32_wino_conv_4x3_data_kernel:: + _jit_avx512_core_fp32_wino_conv_4x3_data_kernel; + + static status_t init_conf(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d); +}; + +struct jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel + : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS( + _jit_avx512_core_conv_winograd_bwd_weights_kernel_f32) + + jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel( + jit_conv_winograd_conf_t ajcp) + : jcp(ajcp) + { + //******************* First iter kernel ********************// + this->gemm_loop_generate(true); + gemm_loop_ker_first_iter = (decltype(gemm_loop_ker_first_iter))this->getCode(); + + align(); + const Xbyak::uint8 *addr = getCurr(); + this->src_transform_generate(); + src_transform = (decltype(src_transform))addr; + + if (jcp.with_bias) { + align(); + addr = getCurr(); + this->diff_dst_transform_generate(true); + diff_dst_transform_wbias = (decltype(diff_dst_transform_wbias))addr; + } + + align(); + addr = getCurr(); + this->diff_dst_transform_generate(false); + diff_dst_transform = (decltype(diff_dst_transform))addr; + + if (jcp.sched_policy != WSCHED_WEI_SDGtWo && jcp.tile_block > 1) { + align(); + addr = getCurr(); + this->gemm_loop_generate(false); + gemm_loop_ker = (decltype(gemm_loop_ker))addr; + } + + align(); + addr = getCurr(); + this->diff_weights_transform_generate(true); + diff_weights_transform = (decltype(diff_weights_transform))addr; + + if (jcp.sched_policy == WSCHED_WEI_SDGtWo) { + align(); + addr = getCurr(); + this->diff_weights_transform_generate(false); + diff_weights_transform_accum = + (decltype(diff_weights_transform_accum))addr; + }; + } + + static status_t init_conf(jit_conv_winograd_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &diff_dst_d, + const memory_desc_wrapper &diff_weights_d); + + jit_conv_winograd_conf_t jcp; + void (*gemm_loop_ker)(float *, const float *, const float *); + void (*gemm_loop_ker_first_iter)(float *, const float *, const float *); + void (*src_transform)(jit_wino_transform_call_s *); + void (*diff_dst_transform)(jit_wino_transform_call_s *); + void (*diff_dst_transform_wbias)(jit_wino_transform_call_s *); + void (*diff_weights_transform)(jit_wino_transform_call_s *); + void (*diff_weights_transform_accum)(jit_wino_transform_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + using reg32_t = const Xbyak::Reg32; + enum { typesize = sizeof(float) }; + + void src_transform_generate(); + void diff_dst_transform_generate(bool with_bias); + void diff_weights_transform_generate(bool first_tile); + + /*registers common to transforms*/ + reg64_t reg_transp = abi_param1; + reg64_t reg_ti = rbx; + reg64_t reg_tj = abi_not_param1; + reg64_t reg_src = r8; + reg64_t reg_dst = r9; + reg64_t reg_G = rsi; /*TODO: check if this is ok*/ + reg64_t reg_temp = rsi; + + /*registers common to src/diff_dst transform*/ + reg64_t reg_I = r10; + reg64_t reg_ydim = r11; + reg64_t reg_xdim = r12; + reg64_t reg_src_offset = r13; + reg64_t reg_zero = r14; + reg64_t reg_tile_count = r15; + reg64_t reg_maski = rsi; + reg32_t reg_maski_32 = esi; + reg64_t reg_maskj = rdx; + + reg64_t reg_T = rax; + reg64_t reg_oc_ur = rax; + reg64_t reg_ic_simd = r14; + reg64_t reg_bias = r10; + + void gemm_loop_generate(bool is_first_tile); + + reg64_t reg_dstC = abi_param1; + reg64_t reg_srcA = abi_param2; + reg64_t reg_srcB = abi_param3; + + reg64_t reg_dimM_block_loop_cnt = r9; + reg64_t reg_dimN_block_loop_cnt = r10; + reg64_t reg_nb_dimN_bcast_ur = r11; + reg64_t reg_dimK_block_loop_cnt = r12; +}; +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp new file mode 100644 index 0000000000..002010ffa2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp @@ -0,0 +1,1284 @@ +/******************************************************************************* + * Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx512_core_u8s8s32x_wino_convolution.hpp" +#include "jit_generator.hpp" + +#include + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; +using namespace Xbyak; + +namespace { + // Below scales are applied to source and weights data accordingly + // because this winograd implementation + // transforms source which may increase values up to 4x + // and transforms weights which may increase values up to 9/4x + const float adj_src_scale = 1.f / 4.f; + const float adj_wei_scale = 4.f / 9.f; + // Winograd transforms need ic and oc to be multiples of 16 + const int load_block = 16; +} + +/// SRC TRANSFORMS ///////////////////////////////////////////////////////////// +struct jit_avx512_core_u8s8s32x_wino_conv_src_trans_t: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS( + jit_avx512_core_u8s8s32x_wino_conv_src_trans_t) + + jit_conv_conf_2x3_wino_t jcp; + const primitive_attr_t &attr_; + + struct call_params_t { + const void *src; + const void *wino_src; + const void *v_y_masks; + const void *v_x_masks; + }; + void (*ker_)(const call_params_t *); + + jit_avx512_core_u8s8s32x_wino_conv_src_trans_t( + jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), unsign_val_in_wino_domain(5) { + generate(); + ker_ = reinterpret_cast(const_cast(getCode())); + } + void generate(); + + int reg_inp_ind(int i) { + assert(i < jcp.alpha * jcp.alpha); + return (31 - i); + } + + Xmm vreg_inp(int i) { + return Xmm(reg_inp_ind(i)); + } + + Zmm zmm_inp(int i) { + return Zmm(reg_inp_ind(i)); + } + + Xmm vreg_tmp(int i) { + assert(i < jcp.alpha * jcp.alpha); + return Xmm(15 - i); + } + Xmm vreg_out(int i) { + assert(i < jcp.alpha * jcp.alpha); + return Xmm(31 - i); + } + + Opmask y_mask = Opmask(1); + Opmask r_mask = Opmask(2); + Opmask x_mask(int id) { + assert(id < 4); + return Opmask(3 + id); + } + + Reg64 reg_ptr_src = r14; + Reg64 reg_ptr_dst = r13; + + Reg64 reg_ptr_v_y_masks = r12; + Reg64 reg_ptr_v_x_masks = r11; + + Reg64 reg_aux_ptr_src = r10; + Reg64 reg_aux_ptr_dst = r9; + + Reg64 reg_ic_block = r8; + + int unsign_val_in_wino_domain; + + Reg64 reg_scratch_src_alpha = rdx; + Xmm xmm_src_alpha = Xmm(0); + Zmm zmm_src_alpha = Zmm(0); + + Reg64 reg_shift = rax; + Xmm xmm_shift = Xmm(1); + Xmm xmm_zero = Xmm(0); + + Reg64 reg_maskx = rbx; + Reg64 reg_masky = rsi; + Reg64 reg_nomask = reg_maskx; +}; + +void jit_avx512_core_u8s8s32x_wino_conv_src_trans_t::generate() { + Label ic_block_label; + Label end_label; + Label mask_label; + Label nomask_label; + + auto load_src = [=](bool mask) { + for (int y = 0; y < jcp.alpha; y++) { + if (mask) + kmovw(y_mask, ptr[reg_ptr_v_y_masks + sizeof(uint16_t) * y]); + for (int x = 0; x < jcp.alpha; x++) { + Zmm zmm_i = zmm_inp(y * jcp.alpha + x); + Xmm vreg_i = vreg_inp(y * jcp.alpha + x); + int inp_offset = sizeof(uint8_t) + * ((-jcp.t_pad + y) * jcp.iw * jcp.ic + + (-jcp.l_pad + x) * jcp.ic); + if (mask) { + kandw(r_mask, y_mask, x_mask(x)); + vmovdqu8(vreg_i | r_mask | T_z, + EVEX_compress_addr(reg_aux_ptr_src, inp_offset)); + } else { + vmovdqu8(vreg_i, + EVEX_compress_addr(reg_aux_ptr_src, inp_offset)); + } + vpmovzxbd(zmm_i, vreg_i); // to int32 + vcvtdq2ps(zmm_i, zmm_i); // to fp32 + vmulps(zmm_i, zmm_i, zmm_src_alpha); // *alpha + vcvtps2dq(zmm_i, zmm_i); // to int32 + vpmovusdb(vreg_i, zmm_i); // to u8 + } + } + }; + + preamble(); + +# define READ_PARAM(reg, field) \ + mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)]) + READ_PARAM(reg_ptr_src, src); + READ_PARAM(reg_ptr_dst, wino_src); + READ_PARAM(reg_ptr_v_y_masks, v_y_masks); + READ_PARAM(reg_ptr_v_x_masks, v_x_masks); +# undef READ_PARAM + + mov(reg_maskx, ptr[reg_ptr_v_x_masks]); + mov(reg_masky, ptr[reg_ptr_v_y_masks]); + test(reg_maskx, reg_maskx); + jz(end_label, T_NEAR); // skip kernel if x mask is all 0's + test(reg_masky, reg_masky); + jz(end_label, T_NEAR); // skip kernel if y mask is all 0's + and_(reg_maskx, reg_masky); + mov(reg_nomask, reg_maskx); + not_(reg_nomask); // zero if x and y masks are all 1's + + xor_(reg_shift, reg_shift); + mov(reg_shift.cvt8(), (int8_t)-128); + + mov(reg_aux_ptr_src, reg_ptr_src); + mov(reg_aux_ptr_dst, reg_ptr_dst); + + for (int i = 0; i < jcp.alpha; i++) { + kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(uint16_t) * i]); + } + + mov(reg_scratch_src_alpha, float2int(adj_src_scale)); + + mov(reg_ic_block, jcp.ic / load_block); + L(ic_block_label); + { + vmovq(xmm_src_alpha, reg_scratch_src_alpha); + vbroadcastss(zmm_src_alpha, xmm_src_alpha); + + test(reg_nomask, reg_nomask); + jz(nomask_label, T_NEAR); + load_src(true); + jmp(mask_label, T_NEAR); + L(nomask_label); + load_src(false); + L(mask_label); + + for(int y = 0; y < 4; y++) { + vpsubb(vreg_tmp(y*4+0), vreg_inp(y*4+0), vreg_inp(y*4+2)); + vpaddb(vreg_tmp(y*4+1), vreg_inp(y*4+1), vreg_inp(y*4+2)); + vpsubb(vreg_tmp(y*4+2), vreg_inp(y*4+2), vreg_inp(y*4+1)); + vpsubb(vreg_tmp(y*4+3), vreg_inp(y*4+1), vreg_inp(y*4+3)); + } + for(int x = 0;x < 4; x++) { + vpsubb(vreg_out(x+0*4), vreg_tmp(x+4*0), vreg_tmp(x+4*2)); + vpaddb(vreg_out(x+1*4), vreg_tmp(x+4*1), vreg_tmp(x+4*2)); + vpsubb(vreg_out(x+2*4), vreg_tmp(x+4*2), vreg_tmp(x+4*1)); + vpsubb(vreg_out(x+3*4), vreg_tmp(x+4*1), vreg_tmp(x+4*3)); + } + + vmovd(xmm_shift, reg_shift.cvt32()); + vpxor(xmm_zero, xmm_zero, xmm_zero); + vpshufb(xmm_shift, xmm_shift, xmm_zero); + + for (int i = 0; i < 16; i++) { + int out_offset = sizeof(uint8_t) * (jcp.inp_stride * i); + if (i != unsign_val_in_wino_domain) + vpsubb(vreg_out(i), vreg_out(i), Xmm(1)); + vmovups(EVEX_compress_addr(reg_aux_ptr_dst, out_offset), vreg_out(i)); + } + + add(reg_aux_ptr_src, sizeof(uint8_t) * load_block); + add(reg_aux_ptr_dst, sizeof(uint8_t) * load_block); + } + dec(reg_ic_block); + jnz(ic_block_label, T_NEAR); + + L(end_label); + postamble(); +} + +/// DST TRANSFORMS ///////////////////////////////////////////////////////////// +struct jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS( + jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t) + + jit_conv_conf_2x3_wino_t jcp; + const primitive_attr_t &attr_; + + struct call_params_t { + const void *wino_dst; + const void *dst; + const void *v_y_masks; + const void *v_x_masks; + + const void *bias; + const void *scales; + }; + void (*ker_)(const call_params_t *); + + jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t( + jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr) { + generate(); + ker_ = reinterpret_cast(const_cast(getCode())); + } + + void generate(); + bool maybe_relu(int position); + + Zmm vreg_inp(int i) { // 16 + assert(i < jcp.alpha * jcp.alpha); + return Zmm(31 - i); + } + Zmm vreg_stg(int id) { // 8 + const int id_reg_stg = jcp.alpha * jcp.alpha + id; + assert(id < 8); + return Zmm(31 - id_reg_stg); + } + Zmm vreg_out(int id) { // 4 + const int id_reg_out = jcp.alpha * jcp.alpha + 8 + id; + assert(id < 4); + return Zmm(31 - id_reg_out); + } + Xmm xmm_out(int id) { // 4 + const int id_reg_out = jcp.alpha * jcp.alpha + 8 + id; + assert(id < 4); + return Xmm(31 - id_reg_out); + } + Zmm vreg_tmp(int id) { // 2 + const int id_reg_tmp = jcp.alpha * jcp.alpha + 12 + id; + assert(id < 2); + return Zmm(31 - id_reg_tmp); + } + + Zmm vreg_zero = Zmm(0); + Zmm vreg_bias = Zmm(1); + Zmm vreg_prev_dst = Zmm(2); + Zmm zmm_bias_alpha = Zmm(2); + Xmm xmm_bias_alpha = Xmm(2); + + Opmask y_mask = Opmask(1); + Opmask r_mask = Opmask(2); + Opmask x_mask(int id) { + assert(id < 4); + return Opmask(3 + id); + } + + Reg64 reg_scratch_bias_alpha = r15; + + Reg64 reg_ptr_src = r14; + Reg64 reg_ptr_dst = r13; + + Reg64 reg_ptr_v_y_masks = r12; + Reg64 reg_ptr_v_x_masks = r11; + + Reg64 reg_aux_ptr_src = r10; + Reg64 reg_aux_ptr_dst = r9; + + Reg64 reg_oc_block = r8; + + Reg64 reg_ptr_bias = rbx; + Reg64 reg_ptr_scales = abi_not_param1; + Reg64 reg_ptr_sum_scale = rdx; +}; + +bool jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::maybe_relu(int position) { + using namespace primitive_kind; + const auto &p = attr_.post_ops_; + + if (position == 0) { + /* relu before sum */ + return false + || p.contain(eltwise, 0) + || (jcp.dst_dt == data_type::u8 && !p.contain(sum, 0)); + } else if (position == 1) { + /* relu after sum */ + const int sum_idx = p.contain(sum, 0) + ? 0 : (p.contain(sum, 1) ? 1 : -1); + if (sum_idx == -1) + return false; + + return false + || p.contain(eltwise, sum_idx + 1) + || jcp.dst_dt == data_type::u8; + } + + return false; +} + +void jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::generate() { + Label oc_block_label; + + auto loop_body = [=]() { + const auto &p = attr_.post_ops_; + const int sum_idx = p.find(primitive_kind::sum); + const float *p_sum_scale = (sum_idx != -1) + ? &p.entry_[sum_idx].sum.scale + : nullptr; + if (p_sum_scale && *p_sum_scale != 1.f) + mov(reg_ptr_sum_scale, (size_t)p_sum_scale); + + for(int i = 0; i < 16; i++) { + int internal_offset = sizeof(int32_t) * jcp.out_stride * i; + vmovups(vreg_inp(i), + EVEX_compress_addr(reg_aux_ptr_src, internal_offset)); + } + for(int y = 0; y < jcp.alpha; y++) { + vpaddd(vreg_tmp(0), vreg_inp(y*4 + 0), vreg_inp(y*4 + 1)); + vpaddd(vreg_stg(y*2), vreg_tmp(0), vreg_inp(y*4 + 2)); + + vpsubd(vreg_tmp(1), vreg_inp(y*4 + 1), vreg_inp(y*4 + 2)); + vpsubd(vreg_stg(y*2+1), vreg_tmp(1), vreg_inp(y*4 + 3)); + } + for(int x = 0; x < jcp.m; x++) { + vpaddd(vreg_tmp(0), vreg_stg(x), vreg_stg(x+2*1)); + vpaddd(vreg_out(x), vreg_tmp(0), vreg_stg(x+2*2)); + + vpsubd(vreg_tmp(1), vreg_stg(x+2*1), vreg_stg(x+2*2)); + vpsubd(vreg_out(x+2), vreg_tmp(1), vreg_stg(x+2*3)); + } + + + if (jcp.with_bias) { + vmovq(xmm_bias_alpha, reg_scratch_bias_alpha); + vbroadcastss(zmm_bias_alpha, xmm_bias_alpha); + + auto bias_addr = ptr [ reg_ptr_bias ]; + switch (jcp.bia_dt) { + case data_type::f32: + case data_type::s32: vmovups(vreg_bias, bias_addr); break; + case data_type::s8: vpmovsxbd(vreg_bias, bias_addr); break; + case data_type::u8: vpmovzxbd(vreg_bias, bias_addr); break; + default: assert(!"unsupported dst data type"); + } + if (jcp.bia_dt != data_type::f32) + vcvtdq2ps(vreg_bias, vreg_bias); + vmulps(vreg_bias, vreg_bias, zmm_bias_alpha); // *alpha + } + for(int y = 0; y < jcp.m; y++) { + kmovw(y_mask, ptr[ reg_ptr_v_y_masks + sizeof(uint16_t) * y ]); + for(int x = 0; x < jcp.m; x++) { + kandw(r_mask, y_mask, x_mask(x)); + + int i = y * jcp.m + x; + int offset = jcp.typesize_out * + (y * jcp.ow * jcp.oc + x * jcp.oc); + Address addr = EVEX_compress_addr(reg_aux_ptr_dst, offset); + + Zmm zmm = vreg_out(i); + Xmm xmm = xmm_out(i); + vcvtdq2ps(zmm, zmm); + if (jcp.with_bias) + vaddps(zmm, zmm, vreg_bias); + vmulps(zmm, zmm, ptr [reg_ptr_scales]); + if (maybe_relu(0)) + vmaxps(zmm, vreg_zero, zmm); + if (p_sum_scale) { // post_op: sum + vpxord(vreg_prev_dst, vreg_prev_dst, vreg_prev_dst); + switch (jcp.dst_dt) { + case data_type::f32: + case data_type::s32: + vmovups(vreg_prev_dst | r_mask, addr); break; + case data_type::s8: + vpmovsxbd(vreg_prev_dst | r_mask, addr); break; + case data_type::u8: + vpmovzxbd(vreg_prev_dst | r_mask, addr); break; + default: assert(!"unknown dst_dt"); + } + if (jcp.dst_dt != data_type::f32) + vcvtdq2ps(vreg_prev_dst, vreg_prev_dst); + if (*p_sum_scale == 1.f) + vaddps(zmm, vreg_prev_dst); + else + vfmadd231ps(zmm, vreg_prev_dst, + zword_b[reg_ptr_sum_scale]); + } + if (maybe_relu(1)) + vmaxps(zmm, vreg_zero, zmm); + if (jcp.dst_dt != data_type::f32) + vcvtps2dq(zmm, zmm); + switch (jcp.dst_dt) { + case data_type::f32: + case data_type::s32: + vmovups(addr, zmm | r_mask); break; + case data_type::s8: + vpmovsdb(xmm, zmm); vmovups(addr, xmm | r_mask); break; + case data_type::u8: + vpmovusdb(xmm, zmm); vmovups(addr, xmm | r_mask); break; + default: assert(!"unknown dst_dt"); + } + } + } + }; + + preamble(); + +# define READ_PARAM(reg, field) \ + mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)]) + READ_PARAM(reg_ptr_src, wino_dst); + READ_PARAM(reg_ptr_dst, dst); + READ_PARAM(reg_ptr_v_y_masks, v_y_masks); + READ_PARAM(reg_ptr_v_x_masks, v_x_masks); + READ_PARAM(reg_ptr_bias, bias); + READ_PARAM(reg_ptr_scales, scales); +# undef READ_PARAM + + if (jcp.with_bias) + mov(reg_scratch_bias_alpha, float2int(adj_src_scale * adj_wei_scale)); + + mov(reg_aux_ptr_src, reg_ptr_src); + mov(reg_aux_ptr_dst, reg_ptr_dst); + + vpxord(vreg_zero, vreg_zero, vreg_zero); + + for (int i = 0; i < jcp.m; i++) + kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(uint16_t) * i]); + + int oc_blocks = jcp.oc / load_block; + mov(reg_oc_block, oc_blocks); + L(oc_block_label); { + loop_body(); + add(reg_aux_ptr_src, sizeof(int32_t) * load_block); + add(reg_aux_ptr_dst, jcp.typesize_out * load_block); + + add(reg_ptr_scales, jcp.is_oc_scale * sizeof(float) * load_block); + add(reg_ptr_bias, sizeof(jcp.typesize_bia) * load_block); + } + dec(reg_oc_block); + jnz(oc_block_label, T_NEAR); + + postamble(); + +} + +/// GEMM kernel //////////////////////////////////////////////////////////////// +struct jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t) + jit_conv_conf_2x3_wino_t jcp; + const primitive_attr_t &attr_; + + struct call_params_t { + const void *src; + const void *dst; + const void *wei; + const void *dst_b; + }; + void (*ker_)(const call_params_t *); + + void generate(); + static bool post_ops_ok(jit_conv_conf_2x3_wino_t &jcp, + const primitive_attr_t &attr); + + jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t( + jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr) + { + generate(); + ker_ = reinterpret_cast(const_cast(getCode())); + } + + static status_t init_conf( + jit_conv_conf_2x3_wino_t &jcp, const convolution_desc_t &cd, + memory_desc_t &src_md, memory_desc_t &weights_md, + memory_desc_t &dst_md, memory_desc_t &bias_md, + const primitive_attr_t &attr); + + Zmm vreg_out(int n, int m) { + const int id_reg_out = n * jcp.m_block + m; + assert(id_reg_out < jcp.n2_block * jcp.m_block); + return Zmm(31 - id_reg_out); + } + Zmm vreg_wei(int i) { + assert(31 - jcp.n2_block * jcp.m_block - i + > (jcp.ver == ver_vnni ? 0 : 2)); + return Zmm(31 - jcp.n2_block * jcp.m_block - i); + } + + Zmm vreg_src = Zmm(0); + Zmm vreg_one = Zmm(1); + Zmm vreg_tmp = Zmm(2); + + Reg64 reg_ptr_src = r15; + + Reg64 reg_aux_dst_b = r13; + Reg64 reg_aux_dst = r12; + Reg64 reg_aux_dst2 = r11; + Reg64 reg_aux_wei = r10; + Reg64 reg_aux_wei2 = r9; + Reg64 reg_aux_src = r8; + Reg64 reg_aux_src2 = rax; + Reg64 reg_mb = rbx; + Reg64 reg_nnb = abi_not_param1; + Reg64 reg_scratch = rdx; + Reg64 reg_K = rsi; +}; + +bool jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::post_ops_ok( + jit_conv_conf_2x3_wino_t &jcp, const primitive_attr_t &attr) { + using namespace primitive_kind; + const auto &p = attr.post_ops_; + + auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); }; + + switch (p.len_) { + case 0: return true; + case 1: return is_relu(0) || p.contain(sum, 0); + case 2: return (p.contain(sum, 0) && is_relu(1)) || + (p.contain(sum, 1) && is_relu(0)); + case 3: return is_relu(0) && p.contain(sum, 1) && is_relu(2); + default: return false; + } + + return false; +} + +void jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::generate() { + Label nnb_loop_label, K_loop_label, mb_loop_label; + + auto compute = [=](Zmm vreg_acc, Zmm vreg_wei, Zmm vreg_src) { + if (jcp.ver == ver_vnni) { + vpdpbusd(vreg_acc, vreg_src, vreg_wei); + } else { + vpmaddubsw(vreg_tmp, vreg_src, vreg_wei); + vpmaddwd(vreg_tmp, vreg_tmp, vreg_one); + vpaddd(vreg_acc, vreg_acc, vreg_tmp); + } + }; + + preamble(); +# define READ_PARAM(reg, field) \ + mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)]) + READ_PARAM(reg_ptr_src, src); + READ_PARAM(reg_aux_dst, dst); + READ_PARAM(reg_aux_wei, wei); + READ_PARAM(reg_aux_dst_b, dst_b); +# undef READ_PARAM + + if (jcp.ver != ver_vnni) { + xor_(reg_scratch, reg_scratch); + Reg16 _t = reg_scratch.cvt16(); + mov(_t, 0x1); + vpbroadcastw(vreg_one, _t); + } + + if (!jcp.small_mb) { + mov(reg_nnb, jcp.n_chunks); + L(nnb_loop_label); + } + mov(reg_aux_dst2, reg_aux_dst); + mov(reg_aux_src, reg_ptr_src); + mov(reg_mb, jcp.M / jcp.m_block); + L(mb_loop_label); + { + for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) { + for (int m = 0; m < jcp.m_block; m++) { + int offset = jcp.typesize_acc * nb2 * jcp.n_block; + vmovups(vreg_out(nb2, m), + EVEX_compress_addr(reg_aux_dst_b, offset)); + } + } + mov(reg_aux_src2, reg_aux_src); + mov(reg_aux_wei2, reg_aux_wei); + mov(reg_K, jcp.k_chunks); + L(K_loop_label); + { + for (int k = 0; k < jcp.k2_block; k += 4) { + for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) { + int wei_offset + = jcp.typesize_in * (nb2 * jcp.n_block * jcp.K); + vmovups(vreg_wei(nb2), + EVEX_compress_addr(reg_aux_wei2, wei_offset)); + } + for (int m = 0; m < jcp.m_block; m++) { + int inp_offset = jcp.typesize_in * m * jcp.K; + vpbroadcastd(vreg_src, + EVEX_compress_addr(reg_aux_src2, inp_offset)); + for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) + compute(vreg_out(nb2, m), vreg_wei(nb2), vreg_src); + } + add(reg_aux_src2, jcp.typesize_in * 4); + add(reg_aux_wei2, jcp.typesize_in * 4 * jcp.n_block); + } + } + dec(reg_K); + jnz(K_loop_label, T_NEAR); + + for (int m = 0; m < jcp.m_block; m++) { + for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) { + int offset = jcp.typesize_acc * (m * jcp.N + nb2 * jcp.n_block); + vmovups(EVEX_compress_addr(reg_aux_dst2, offset), + vreg_out(nb2, m)); + } + } + add(reg_aux_src, jcp.typesize_in * jcp.m_block * jcp.K); + add(reg_aux_dst2, jcp.typesize_acc * jcp.m_block * jcp.N); + } + dec(reg_mb); + jnz(mb_loop_label, T_NEAR); + + if (!jcp.small_mb) { + add(reg_aux_dst, jcp.typesize_acc * jcp.n2_block * jcp.n_block); + add(reg_aux_dst_b, jcp.typesize_acc * jcp.n2_block * jcp.n_block); + add(reg_aux_wei, jcp.typesize_in * jcp.n2_block * jcp.n_block * jcp.K); + + dec(reg_nnb); + jnz(nnb_loop_label, T_NEAR); + } + + postamble(); +} +namespace { +bool is_winograd_faster_than_direct(const jit_conv_conf_2x3_wino_t &jcp) { + if (jcp.ver == ver_vnni) { + return (jcp.mb <= mkldnn_get_max_threads() + && (jcp.mb > 4 + && jcp.ic > 64 + && !(jcp.oc > 128 && jcp.ih < 14))) + || jcp.mb > mkldnn_get_max_threads(); + } + return true; +} +} + +status_t jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t +::init_conf(jit_conv_conf_2x3_wino_t &jcp, + const convolution_desc_t &cd, memory_desc_t &src_md, + memory_desc_t &wei_md, memory_desc_t &dst_md, + memory_desc_t &bias_md, const primitive_attr_t &attr) { + const memory_desc_wrapper src_d(&src_md); + const memory_desc_wrapper wei_d(&wei_md); + const memory_desc_wrapper dst_d(&dst_md); + const memory_desc_wrapper bias_d(&bias_md); + + const bool with_groups = wei_d.ndims() == src_d.ndims() + 1; + + jcp.nthr = mkldnn_get_max_threads(); + + jcp.ngroups = with_groups ? wei_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = dst_d.dims()[2]; + jcp.ow = dst_d.dims()[3]; + jcp.kh = wei_d.dims()[with_groups + 2]; + jcp.kw = wei_d.dims()[with_groups + 3]; + jcp.t_pad = cd.padding[0][0]; + jcp.b_pad = cd.padding[1][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.r_pad = cd.padding[1][1]; + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + + jcp.ver = ver_avx512_core; + if (!(mayiuse(avx512_core) && + src_d.data_type() == data_type::u8 + && wei_d.data_type() == data_type::s8 + && one_of(dst_d.data_type(), data_type::f32, data_type::s32, + data_type::s8, data_type::u8))) + return status::unimplemented; + if (mayiuse(avx512_core_vnni)) + jcp.ver = ver_vnni; + + if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto, + is_winograd_faster_than_direct(jcp))) + return status::unimplemented; + + // block sizes needed for GEMM kernel + jcp.ic_block = 4; + jcp.oc_block = 16; + + bool ok = true + && jcp.ngroups == 1 + && jcp.oc % load_block == 0 && jcp.ic % load_block == 0 + && jcp.oc % jcp.oc_block == 0 && jcp.ic % jcp.ic_block == 0 + && everyone_is(3, jcp.kh, jcp.kw) + && everyone_is(1, jcp.stride_h, jcp.stride_w) + && everyone_is(0, jcp.dilate_h, jcp.dilate_w) + && jcp.t_pad == jcp.b_pad && jcp.l_pad == jcp.r_pad + && one_of(jcp.t_pad, 0, 1) + && one_of(jcp.l_pad, 0, 1); + if (!ok) return status::unimplemented; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef; + jcp.dst_dt = cd.dst_desc.data_type; + + jcp.typesize_in = types::data_type_size(src_d.data_type()); + jcp.typesize_out = types::data_type_size(dst_d.data_type()); + jcp.typesize_acc = sizeof(int32_t); + jcp.typesize_bia = jcp.with_bias + ? types::data_type_size(bias_d.data_type()) + : 0; + + jcp.nb_oc = jcp.oc / jcp.oc_block; + jcp.nb_ic = jcp.ic / jcp.ic_block; + + jcp.m = 2; + jcp.r = 3; + jcp.alpha = jcp.m + jcp.r - 1; + + int aa = jcp.alpha * jcp.alpha; + int L1_cap = get_cache_size(1, true); + int L2_cap = get_cache_size(2, true); + // need 1 extra reg for bcast, and 2 tmp regs for non-vnni + int free_regs = jcp.ver == ver_vnni ? 31 : 29; + + auto get_thr_eff = [&](int small_mb, int ix, int iy, int n2_b) { + float thr_eff; + float Z = (float)jcp.ic + jcp.oc; + float Y = (float)jcp.ic * jcp.oc; + if (small_mb == 0) { // outer par + int nblocks = jcp.mb * div_up(jcp.oh, iy) * div_up(jcp.ow, ix); + thr_eff = (float)nblocks / rnd_up(nblocks, jcp.nthr); + } else { // inner par + int tranw = iy * ix / jcp.alpha; + int gemmw = aa * (jcp.nb_oc / n2_b); + int tranw_r = rnd_up(tranw, jcp.nthr); + int gemmw_r = rnd_up(gemmw, jcp.nthr); + thr_eff = (Z * tranw / tranw_r + Y * gemmw / gemmw_r) / (Z + Y); + } + return thr_eff; + }; + + auto get_mem_eff = [&](int small_mb, int ix, int iy, int n2_b) { + float mem_eff, req_mem; + int M = ix * iy / jcp.alpha; + if (small_mb == 0) { // outer parallelization strategy + // memory for wino transforms (other memory has poor reuse) + req_mem = (float)aa * M * (jcp.ic + jcp.typesize_acc * jcp.oc); + mem_eff = req_mem < L1_cap ? 1.f : req_mem < L2_cap ? 0.5f : 0.f; + } else { // inner parallelization strategy + // memory used during gemm + int N = jcp.oc_block * n2_b; + req_mem = (float)jcp.ic * (M + N) + jcp.typesize_acc * M * N; + mem_eff = nstl::min(1.f, L2_cap / req_mem); + // memory used during wino transforms + int M_per_thr = div_up(M, jcp.nthr); + req_mem = (float)aa * M_per_thr + * (jcp.ic + jcp.typesize_acc * jcp.oc); + if (req_mem > L2_cap) + mem_eff = 0.1f; + } + return mem_eff; + }; + + auto get_tot_eff = [&](int small_mb, float thr_eff, float work_eff, + float mem_eff, float reg_eff) { + // these coefficients are chosen empirically + float mem_fac = 0.1f, reg_fac = 0.2f; + // normalized overhead relative to memory and register components + float tot_eff = 1.f + mem_fac * mem_eff + reg_fac * reg_eff; + // thread and work components affect all others + tot_eff *= thr_eff * work_eff; + return tot_eff; + }; + + auto find_m_n2_blocks = [&](bool small_mb, int ix, int iy, float work_eff, + int &m_block, int &n2_block, float &tot_eff) { + int M = (ix * iy) / jcp.alpha; + int max_m_block = nstl::min(M, free_regs); + int max_n2_block = nstl::min(jcp.nb_oc, free_regs); + tot_eff = 0.f; + for (int im = max_m_block; im > 0; im--) { + if (M % im) + continue; + for (int in2 = max_n2_block; in2 > 0; in2--) { + int used_regs = (im + 1) * in2; + float mem_eff = get_mem_eff(small_mb, ix, iy, in2); + float reg_eff = (float)(im * in2) / (im + in2); + float thr_eff = get_thr_eff(small_mb, ix, iy, in2); + float cur_tot_eff = get_tot_eff( + small_mb, thr_eff, work_eff, mem_eff, reg_eff); + if (jcp.nb_oc % in2 || used_regs > free_regs + || cur_tot_eff <= tot_eff) + continue; + tot_eff = cur_tot_eff; + m_block = im; + n2_block = in2; + } + } + }; + + /* Selecting xb and yb blocking */ + int min_yb = jcp.m; + int min_xb = jcp.m; + int max_yb = nstl::max(min_yb, rnd_up(jcp.oh, 2)); + int max_xb = nstl::max(min_xb, rnd_up(jcp.ow, 2)); + float best_eff = 0.f; + for (int ix = min_xb; ix <= max_xb; ix += 2) { + assert(rnd_up(jcp.ow, ix) >= jcp.iw - 2); + for (int iy = max_yb; iy >= min_yb; iy -= 2) { + assert(rnd_up(jcp.oh, iy) >= jcp.ih - 2); + + int m_b[2]; + int n2_b[2]; + bool small_mb; + float inner_eff, outer_eff, work_eff; + + int tiled_area = rnd_up(jcp.oh, iy) * rnd_up(jcp.ow, ix); + work_eff = (float)jcp.oh * jcp.ow / tiled_area; + if (best_eff > 0.f && work_eff < 4.f / 9.f) + continue; // no gain from Winograd transformation + + /* outer parallelization */ + find_m_n2_blocks(0, ix, iy, work_eff, m_b[0], n2_b[0], outer_eff); + + /* inner parallelization */ + find_m_n2_blocks(1, ix, iy, work_eff, m_b[1], n2_b[1], inner_eff); + + small_mb = inner_eff > outer_eff; + float eff = small_mb ? inner_eff : outer_eff; + if (eff > best_eff) { + best_eff = eff; + jcp.yb = iy; + jcp.xb = ix; + jcp.m_block = m_b[small_mb]; + jcp.n2_block = n2_b[small_mb]; + jcp.small_mb = small_mb; + } + } + } + + assert((jcp.m_block + 1) * jcp.n2_block <= free_regs); + assert(jcp.xb % 2 == 0 && jcp.yb % 2 == 0); + + jcp.mb_block = 1; + if (jcp.small_mb) { + // For small mb harness, set mb_block as large as possible subject to + // the constraint that winograd activations fit into available L3 cache + int L3_cap = get_cache_size(3, true); + int M = jcp.xb * jcp.yb / 4; + int wino_src_size = 16 * M * jcp.ic * jcp.typesize_in; + int wino_dst_size = 16 * M * jcp.oc * jcp.typesize_acc; + int max_mb_block = nstl::min( + jcp.mb, jcp.nthr * L3_cap / (wino_src_size + wino_dst_size)); + for (int i = max_mb_block; i > 1; i--) { + if (jcp.mb % i == 0) { + jcp.mb_block = i; + break; + } + } + } + jcp.nb_mb = jcp.mb / jcp.mb_block; + + jcp.M = jcp.mb_block * jcp.xb * jcp.yb / 4; + jcp.N = jcp.oc; + jcp.K = jcp.ic; + + jcp.inp_stride = jcp.M * jcp.ic; + jcp.out_stride = jcp.M * jcp.oc; + jcp.wei_stride = jcp.ic * jcp.oc; + jcp.bia_stride = jcp.oc; + + jcp.n_block = jcp.oc_block; + jcp.k_block = jcp.ic_block; + + jcp.n_chunks = (jcp.N / jcp.n_block) / jcp.n2_block; + + // We need jcp.k2_block to be a multiple of jcp.k_block = jcp.ic_block = 4 + // and jcp.K = jcp.ic to be a multiple of jcp.k2_block. Since jcp.ic is + // a multiple of load_block = 16, we just use that for now. + jcp.k2_block = load_block; + jcp.k_chunks = jcp.K / jcp.k2_block; + + const auto &oscales = attr.output_scales_; + jcp.is_oc_scale = oscales.mask_ == 1 << 1; + assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0)); + + /* re-create weights primitive descriptor + and set weights wino_blocking */ + memory_desc_t expect_wei_md = wei_md; + + expect_wei_md.format_kind = format_kind::wino; + expect_wei_md.data_type = data_type::s8; + mkldnn_wino_desc_t &wd = expect_wei_md.format_desc.wino_desc; + wd.wino_format = mkldnn_wino_wei_aaOIoi; + wd.r = jcp.r; + wd.alpha = jcp.alpha; + wd.ic = jcp.ic; + wd.oc = jcp.oc; + wd.ic_block = jcp.ic_block; + wd.oc_block = jcp.oc_block; + wd.oc2_block = jcp.n2_block; + wd.ic2_block = 1; + wd.adj_scale = adj_wei_scale; + + size_t max_size = types::data_type_size(data_type::s8) * + jcp.alpha * jcp.alpha * jcp.ic * jcp.oc; + max_size += types::data_type_size(data_type::s32) * + jcp.alpha * jcp.alpha * jcp.oc; + wd.size = max_size; + + if (wei_md.format_kind == format_kind::any) + wei_md = expect_wei_md; + if (wei_md != expect_wei_md) + return status::unimplemented; + + const int tilesize = jcp.alpha * jcp.alpha; + const int numtiles = jcp.M; + const int alltiles = numtiles * tilesize; + + jcp.size_wino_src + = utils::rnd_up(jcp.typesize_in * alltiles * jcp.ic, PAGE_4K) + / jcp.typesize_in; + jcp.size_wino_wei = tilesize * jcp.oc * jcp.ic; + jcp.size_wino_dst = alltiles * jcp.oc; + + return status::success; +} +//////////////////////////////////////////////////////////////////////////////// + +template +status_t jit_avx512_core_u8s8s32x_wino_convolution_fwd_t:: + pd_t::jit_conf() { + return jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::init_conf( + jcp_, *this->desc(), this->src_md_, this->weights_md_, + this->dst_md_,this->bias_md_, *this->attr()); +} + +template +void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t::pd_t:: +init_scratchpad() { + auto scratchpad = this->scratchpad_registry().registrar(); + + int nthr_multiplier = jcp_.small_mb ? 1 : jcp_.nthr; + scratchpad.book(key_wino_V, + sizeof(src_data_t) * jcp_.size_wino_src * nthr_multiplier, PAGE_4K); + scratchpad.book(key_wino_M, + sizeof(acc_data_t) * jcp_.size_wino_dst * nthr_multiplier, PAGE_4K); + + dim_t scale_count = attr()->output_scales_.count_; + scratchpad.book(key_conv_adjusted_scales, + sizeof(float) * nstl::max(scale_count, 16)); +} + +template +jit_avx512_core_u8s8s32x_wino_convolution_fwd_t:: + jit_avx512_core_u8s8s32x_wino_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) +{ + kernel_ = new jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t( + pd()->jcp_, *pd()->attr()); + src_trans_ = new jit_avx512_core_u8s8s32x_wino_conv_src_trans_t( + pd()->jcp_, *pd()->attr()); + dst_trans_ = new jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t( + pd()->jcp_, *pd()->attr()); +} + +template +jit_avx512_core_u8s8s32x_wino_convolution_fwd_t:: + ~jit_avx512_core_u8s8s32x_wino_convolution_fwd_t() { + delete kernel_; + delete src_trans_; + delete dst_trans_; +} + +template +const float *jit_avx512_core_u8s8s32x_wino_convolution_fwd_t:: +adjust_oscales(const memory_tracking::grantor_t &scratchpad) const { + const float *oscales = pd()->attr()->output_scales_.scales_; + auto loc_scales = scratchpad.template get(key_conv_adjusted_scales); + size_t count = pd()->attr()->output_scales_.count_; + float factor = 1.f / (adj_src_scale * adj_wei_scale); + if (count == 1) + utils::array_set(loc_scales, oscales[0] * factor, 16); + else + for (size_t c = 0; c < count; c++) loc_scales[c] = oscales[c] * factor; + return loc_scales; +} + +template +void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const auto &jcp = kernel_->jcp; + if (jcp.small_mb) + execute_forward_small_mb(src, weights, bias, dst, this->scratchpad(ctx)); + else + execute_forward_mbN(src, weights, bias, dst, this->scratchpad(ctx)); +} + +template +void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t:: +execute_forward_mbN(const src_data_t *src, const wei_data_t *wei, + const char *bia, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + const auto &jcp = kernel_->jcp; + const float *oscales = adjust_oscales(scratchpad); + + auto dst_bias = (const acc_data_t *)(wei + jcp.size_wino_wei); + auto wino_src_base = scratchpad.template get(key_wino_V); + auto wino_dst_base = scratchpad.template get(key_wino_M); + + parallel_nd(jcp.mb, div_up(jcp.oh, jcp.yb), div_up(jcp.ow, jcp.xb), + [&](int mb, int tile_y_b, int tile_x_b) { + + int tile_y = tile_y_b * jcp.yb; + int tile_x = tile_x_b * jcp.xb; + + int ithr = mkldnn_get_thread_num(); + auto wino_src = wino_src_base + jcp.size_wino_src * ithr; + auto wino_dst = wino_dst_base + jcp.size_wino_dst * ithr; + + auto src_trans_p = + jit_avx512_core_u8s8s32x_wino_conv_src_trans_t::call_params_t(); + auto dst_trans_p = + jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::call_params_t(); + auto gemm_p = + jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::call_params_t(); + + /* transformation of input tensor to winograd domain */ + for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) { + for (int x_in_block = 0; x_in_block < jcp.xb; x_in_block += 2) { + uint16_t v_y_masks[4], v_x_masks[4]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2); + + int v_ys = nstl::max(0, jcp.t_pad - y); + int v_ye = nstl::min(jcp.alpha, + nstl::max(0, jcp.ih + jcp.t_pad - y)); + + int v_xs = nstl::max(0, jcp.l_pad - x); + int v_xe = nstl::min(jcp.alpha, + nstl::max(0, jcp.iw + jcp.l_pad - x)); + +#pragma unroll(4) + for (int i = 0; i < jcp.alpha; i++) { + v_y_masks[i] = uint16_t(i < v_ys || i >= v_ye ? 0 : 0xffff); + v_x_masks[i] = uint16_t(i < v_xs || i >= v_xe ? 0 : 0xffff); + } + auto local_s = src + + mb * jcp.ih * jcp.iw * jcp.ic + + y * jcp.iw * jcp.ic + x * jcp.ic; + auto local_w = wino_src + m * jcp.ic; + + src_trans_p.src = local_s; + src_trans_p.wino_src = local_w; + src_trans_p.v_y_masks = v_y_masks; + src_trans_p.v_x_masks = v_x_masks; + + src_trans_->ker_(&src_trans_p); + } + } + /* gemms */ + for (int tile_ij = 0; tile_ij < 16; tile_ij++) { + // start threads at different GEMMs to help bring weights into LLC + int offset = (tile_ij + ithr) % 16; + gemm_p.src = wino_src + jcp.inp_stride * offset; + gemm_p.dst = wino_dst + jcp.out_stride * offset; + gemm_p.wei = wei + jcp.wei_stride * offset; + gemm_p.dst_b = dst_bias + jcp.bia_stride * offset; + + kernel_->ker_(&gemm_p); + } + + /* transformation from winograd domain to output tensor */ + for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) { + for (int x_in_block = 0; x_in_block < jcp.xb; x_in_block += 2) { + uint16_t v_y_masks[2], v_x_masks[2]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2); + +#pragma unroll(2) + for (int i = 0; i < jcp.m; i++) { + v_x_masks[i] = uint16_t(x + i < jcp.ow ? 0xffff : 0); + v_y_masks[i] = uint16_t(y + i < jcp.oh ? 0xffff : 0); + } + auto local_d = dst + + mb * jcp.oh * jcp.ow * jcp.oc + + y * jcp.ow * jcp.oc + x * jcp.oc; + auto local_w = wino_dst + m * jcp.oc; + + auto scales = oscales; + dst_trans_p.dst = local_d; + dst_trans_p.wino_dst = local_w; + dst_trans_p.v_y_masks = v_y_masks; + dst_trans_p.v_x_masks = v_x_masks; + + dst_trans_p.scales = scales; + dst_trans_p.bias = bia; + + dst_trans_->ker_(&dst_trans_p); + } + } + }); +} + +template +void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t:: +execute_forward_small_mb(const src_data_t *src, const wei_data_t *wei, + const char *bia, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + const auto &jcp = kernel_->jcp; + const float *oscales = adjust_oscales(scratchpad); + + auto dst_bias = (const acc_data_t *)(wei + jcp.size_wino_wei); + auto wino_src = scratchpad.template get(key_wino_V); + auto wino_dst = scratchpad.template get(key_wino_M); + + for (int mbb = 0; mbb < jcp.nb_mb; mbb++) { + for (int tile_y = 0; tile_y < jcp.oh; tile_y += jcp.yb) { + for (int tile_x = 0; tile_x < jcp.ow; tile_x += jcp.xb) { + /* transformation of input tensor to winograd domain */ + parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2), jcp.mb_block, + [&](int y_in_block_b, int x_in_block_b, int mb) { + int y_in_block = y_in_block_b * 2; + int x_in_block = x_in_block_b * 2; + + auto src_trans_p = + jit_avx512_core_u8s8s32x_wino_conv_src_trans_t::call_params_t(); + + uint16_t v_y_masks[4], v_x_masks[4]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (mb * (jcp.yb / 2) + (y_in_block / 2)) * (jcp.xb / 2) + + (x_in_block / 2); + + int v_ys = nstl::max(0, jcp.t_pad - y); + int v_ye = nstl::min( + jcp.alpha, nstl::max(0, jcp.ih + jcp.t_pad - y)); + + int v_xs = nstl::max(0, jcp.l_pad - x); + int v_xe = nstl::min( + jcp.alpha, nstl::max(0, jcp.iw + jcp.l_pad - x)); + +#pragma unroll(4) + for (int i = 0; i < jcp.alpha; i++) { + v_y_masks[i] = uint16_t(i < v_ys || i >= v_ye ? 0 : 0xffff); + v_x_masks[i] = uint16_t(i < v_xs || i >= v_xe ? 0 : 0xffff); + } + auto local_s = src + + (mbb * jcp.mb_block + mb) * jcp.ih * jcp.iw * jcp.ic + + y * jcp.iw * jcp.ic + x * jcp.ic; + auto local_w = wino_src + m * jcp.ic; + + src_trans_p.src = local_s; + src_trans_p.wino_src = local_w; + src_trans_p.v_y_masks = v_y_masks; + src_trans_p.v_x_masks = v_x_masks; + + src_trans_->ker_(&src_trans_p); + }); + + /* gemms */ + parallel_nd(16, jcp.n_chunks, [&](int tile_ij, int nnb) { + auto gemm_p = jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t:: + call_params_t(); + + gemm_p.src = wino_src + jcp.inp_stride * tile_ij; + gemm_p.dst = wino_dst + jcp.out_stride * tile_ij + + nnb * jcp.n2_block * jcp.n_block; + gemm_p.wei = wei + jcp.wei_stride * tile_ij + + nnb * jcp.n2_block * jcp.n_block * jcp.K; + gemm_p.dst_b = dst_bias + jcp.bia_stride * tile_ij + + nnb * jcp.n2_block * jcp.n_block; + + kernel_->ker_(&gemm_p); + }); + + /* transformation from winograd domain to output tensor */ + parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2), jcp.mb_block, + [&](int y_in_block_b, int x_in_block_b, int mb) { + int y_in_block = y_in_block_b * 2; + int x_in_block = x_in_block_b * 2; + + auto dst_trans_p = + jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::call_params_t(); + + uint16_t v_y_masks[2], v_x_masks[2]; + + int y = y_in_block + tile_y; + int x = x_in_block + tile_x; + int m = (mb * (jcp.yb / 2) + (y_in_block / 2)) * (jcp.xb / 2) + + (x_in_block / 2); + +#pragma unroll(2) + for (int i = 0; i < jcp.m; i++) { + v_x_masks[i] = uint16_t(x + i < jcp.ow ? 0xffff : 0); + v_y_masks[i] = uint16_t(y + i < jcp.oh ? 0xffff : 0); + } + auto local_d = dst + + (mbb * jcp.mb_block + mb) * jcp.oh * jcp.ow * jcp.oc + + y * jcp.ow * jcp.oc + x * jcp.oc; + auto local_w = wino_dst + m * jcp.oc; + + auto scales = oscales; + dst_trans_p.dst = local_d; + dst_trans_p.wino_dst = local_w; + dst_trans_p.v_y_masks = v_y_masks; + dst_trans_p.v_x_masks = v_x_masks; + + dst_trans_p.scales = scales; + dst_trans_p.bias = bia; + + dst_trans_->ker_(&dst_trans_p); + }); + }}} +} + +template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t; +template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t; +template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t; +template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t; + +} // namespace cpu +} // namespace impl +} // namespace mkldnn diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp new file mode 100644 index 0000000000..9e6e57b051 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp @@ -0,0 +1,128 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_U8S8S32X_WINO_CONVOLUTION_HPP +#define CPU_JIT_AVX512_CORE_U8S8S32X_WINO_CONVOLUTION_HPP + +#include + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_primitive_conf.hpp" +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t; +struct jit_avx512_core_u8s8s32x_wino_conv_src_trans_t; +struct jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t; + +template +struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_int8_wino:", avx512_core, ""), + jit_avx512_core_u8s8s32x_wino_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && utils::one_of(desc()->alg_kind, + alg_kind::convolution_auto, + alg_kind::convolution_winograd) + && expect_data_types(data_type::u8, data_type::s8, + data_type::undef, dst_data_type, data_type::s32) + && IMPLICATION(with_bias(), utils::one_of( + desc()->bias_desc.data_type, data_type::f32, + data_type::s32, data_type::s8, data_type::u8)) + && !has_zero_dim_memory() + && set_default_formats(); + + if (!ok) return status::unimplemented; + + status_t status = jit_conf(); + if (status != status::success) return status; + set_default_alg_kind(alg_kind::convolution_winograd); + + init_scratchpad(); + + return status; + } + + jit_conv_conf_2x3_wino_t jcp_; + + protected: + status_t jit_conf(); + void init_scratchpad(); + + bool set_default_formats() { + using namespace format_tag; + return set_default_formats_common(nhwc, any, nhwc); + } + }; + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type acc_data_t; + typedef typename prec_traits::type dst_data_t; + + jit_avx512_core_u8s8s32x_wino_convolution_fwd_t(const pd_t *apd); + ~jit_avx512_core_u8s8s32x_wino_convolution_fwd_t(); + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + const float *adjust_oscales(const memory_tracking::grantor_t &scratchpad) + const; + void execute_forward(const exec_ctx_t &ctx) const; + void execute_forward_small_mb(const src_data_t *src, const wei_data_t *wei, + const char *bia, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const; + void execute_forward_mbN(const src_data_t *src, const wei_data_t *wei, + const char *bia, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t *kernel_; + jit_avx512_core_u8s8s32x_wino_conv_src_trans_t *src_trans_; + jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t *dst_trans_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp new file mode 100644 index 0000000000..f4ec29ab00 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp @@ -0,0 +1,820 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_memory.hpp" + +#include "jit_uni_1x1_conv_utils.hpp" +#include "jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp" + +#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +bool jit_avx512_core_x8s8s32x_1x1_conv_kernel::maybe_eltwise(int position) +{ + using namespace primitive_kind; + const auto &p = attr_.post_ops_; + + if (position == 0) { + /* eltwise before sum */ + return p.contain(eltwise, 0); + } else if (position == 1) { + /* eltwise after sum */ + return p.contain(sum, 0) && p.contain(eltwise, 1); + } + + return false; +} + +void jit_avx512_core_x8s8s32x_1x1_conv_kernel::bcast_loop(int load_loop_blk) +{ + mov(aux1_reg_bcast_data, reg_bcast_data); + mov(aux_reg_bcast_data, reg_bcast_data); + + mov(aux_reg_output_data, reg_output_data); + mov(bcast_loop_iter, EVEX_compress_addr(rsp, bcast_loop_work_off)); + + Label bcast_loop; + Label bcast_loop_tail; + + cmp(bcast_loop_iter, jcp.ur); + jl(bcast_loop_tail, T_NEAR); + + L(bcast_loop); { + assert(jcp.bcast_block % jcp.ur == 0); + int num_substeps = jcp.bcast_block / jcp.ur; + assert(num_substeps > 0 && num_substeps < 10); + for (int i = 0; i < num_substeps; i++) { + reduce_loop(load_loop_blk, jcp.ur, i, false); + if (i < num_substeps - 1) { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_substep); + } + else { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step + - (num_substeps - 1) * jcp.bcast_loop_bcast_substep); + int output_offset = jcp.bcast_loop_output_step + - (num_substeps - 1) * jcp.bcast_loop_output_substep; + + add(aux_reg_output_data, output_offset); + } + } + sub(bcast_loop_iter, jcp.bcast_block); + cmp(bcast_loop_iter, jcp.bcast_block); + jge(bcast_loop, T_NEAR); + } + + L(bcast_loop_tail); + if (jcp.ur_tail) { + Label bcast_loop_tail_out; + cmp(bcast_loop_iter, 0); + jz(bcast_loop_tail_out, T_NEAR); + reduce_loop(load_loop_blk, jcp.ur_tail, 0, true); + L(bcast_loop_tail_out); + } +} + +void jit_avx512_core_x8s8s32x_1x1_conv_kernel::cvt2ps(data_type_t type_in, + zmm_t zmm_in, const Xbyak::Operand &op, bool mask_flag) { + zmm_t zmm = mask_flag ? zmm_in | ktail_mask | T_z : zmm_in; + switch (type_in) { + case data_type::f32: + case data_type::s32: vmovups(zmm, op); break; + case data_type::s8: vpmovsxbd(zmm, op); break; + case data_type::u8: vpmovzxbd(zmm, op); break; + default: assert(!"unsupported data type"); + } + if (type_in != data_type::f32) + vcvtdq2ps(zmm_in, zmm_in); +} + +void jit_avx512_core_x8s8s32x_1x1_conv_kernel::reduce_loop(int load_loop_blk, + int ur, int substep, bool wraparound) +{ + auto vreg_load = [=](int i_load) { + return Zmm(ur * load_loop_blk + i_load); + }; + + auto vreg_accum = [=](int i_load, int i_ur) { + return Zmm(i_ur * load_loop_blk + i_load); + }; + + auto zmm_bias_alpha = [=]() { + return Zmm(ur * load_loop_blk); + }; + + auto xmm_bias_alpha = [=]() { + return Xmm(ur * load_loop_blk); + }; + auto bias_ptr = [=](int i_load) { + return EVEX_compress_addr(reg_bias_data, + jcp.typesize_bia * jcp.oc_block * i_load); + }; + + auto comp_ptr = [=](int i_load) { + return EVEX_compress_addr(reg_comp_data, + sizeof(int32_t) * jcp.oc_block * i_load); + }; + + auto scale_ptr = [=](int i_load) { + return EVEX_compress_addr(reg_ptr_scales, + jcp.is_oc_scale * (sizeof(float) * jcp.oc_block * i_load)); + }; + + auto bcast_ptr = [=](int i_reduce, int i_ur, bool bcast) { + assert(i_ur < jcp.ur); + assert(i_reduce <= jcp.reduce_loop_unroll); + assert(jcp.reduce_loop_unroll == jcp.reduce_block); + + int offt = (jcp.ic_without_padding * i_ur + i_reduce); + + return EVEX_compress_addr(aux_reg_bcast_data, jcp.typesize_in * offt, + bcast); + }; + + auto load_ptr = [=](int i_reduce, int i_load) { + int u0 = i_reduce % jcp.reduce_loop_unroll; + int u1 = i_reduce / jcp.reduce_loop_unroll; + + int offt = (i_load * jcp.reduce_dim + u0) * jcp.load_block; + + return EVEX_compress_addr(aux_reg_load_data, + u1 * jcp.reduce_loop_load_step + + jcp.typesize_in * offt); + }; + + auto output_ptr = [=](int i_load, int i_ur) { + return EVEX_compress_addr(aux_reg_output_data, + jcp.typesize_out * (jcp.oc_without_padding * i_ur + + i_load * jcp.load_block)); + }; + + auto init = [=]() { + for (int i_load = 0; i_load < load_loop_blk; ++i_load) + for (int i_ur = 0; i_ur < ur; ++i_ur) { + auto r = vreg_accum(i_load, i_ur); + vpxord(r, r, r); + } + if (jcp.signed_input) { + xor_(reg_scratch, reg_scratch); + Reg8 _t8 = reg_scratch.cvt8(); + mov(_t8, (int8_t)-128); + vpbroadcastb(zmm_shift, _t8); + } + }; + + auto store = [=](const bool mask_flag_in) { + const auto &p = attr_.post_ops_; + const int sum_idx = p.find(primitive_kind::sum); + const float *p_sum_scale = (sum_idx != -1) + ? &p.entry_[sum_idx].sum.scale + : nullptr; + mov(EVEX_compress_addr(rsp, reg_bcast_data_off), reg_bcast_data); + mov(reg_ptr_scales, EVEX_compress_addr(rsp, reg_ptr_sum_scale_off)); + if (p_sum_scale && *p_sum_scale != 1.f) { + mov(EVEX_compress_addr(rsp, reg_load_data_off), reg_load_data); + mov(reg_ptr_sum_scale, (size_t)p_sum_scale); + } + if (jcp.signed_input && jcp.ver != ver_vnni) { + mov(reg_scratch, float2int(jcp.wei_adj_scale)); + vmovq(xmm_bias_alpha(), reg_scratch); + vbroadcastss(zmm_bias_alpha(), xmm_bias_alpha()); + } + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + const bool mask_flag = mask_flag_in && i_load == load_loop_blk - 1; + auto zmm_bias = zmm_tmp; + auto zmm_comp = zmm_bcast; + if (jcp.with_bias) { + if (jcp.signed_input) + mov(reg_bias_data, + EVEX_compress_addr(rsp,reg_bias_data_off)); + cvt2ps(jcp.bia_dt, zmm_bias, bias_ptr(i_load), mask_flag); + if (jcp.signed_input && jcp.ver != ver_vnni) + vmulps(zmm_bias, zmm_bias, zmm_bias_alpha()); + } + if (jcp.signed_input) { + mov(reg_comp_data, EVEX_compress_addr(rsp, reg_comp_data_off)); + cvt2ps(data_type::s32, zmm_comp, comp_ptr(i_load), mask_flag); + } + + for (int i_ur = 0; i_ur < ur; ++i_ur) { + auto r = vreg_accum(i_load, i_ur); + vcvtdq2ps(r, r); + if (jcp.signed_input) + vaddps(r, r, zmm_comp); + if (jcp.with_bias) + vaddps(r, r, zmm_bias); + + zmm_t mask_zmm = mask_flag ? r | ktail_mask | T_z : r; + vmulps(mask_zmm, r, scale_ptr(i_load)); + } + } + + if (maybe_eltwise(0)) + eltwise_injector_->compute_vector_range(0, ur * load_loop_blk); + + if (p_sum_scale) { // post_op: sum + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + const bool mask_flag = mask_flag_in && + i_load == load_loop_blk - 1; + for (int i_ur = 0; i_ur < ur; ++i_ur) { + vpxord(zmm_zero, zmm_zero, zmm_zero); + auto zmm_prev_dst = zmm_zero; + + auto r = vreg_accum(i_load, i_ur); + cvt2ps(jcp.dst_dt, zmm_prev_dst, output_ptr(i_load, i_ur), + mask_flag); + + if (*p_sum_scale == 1.f) + vaddps(r, zmm_prev_dst); + else + vfmadd231ps(r, zmm_prev_dst, zword_b[reg_ptr_sum_scale]); + } + } + } + + if (maybe_eltwise(1)) + eltwise_injector_->compute_vector_range(0, ur * load_loop_blk); + + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + const bool mask_flag = mask_flag_in && + i_load == load_loop_blk - 1; + for (int i_ur = 0; i_ur < ur; ++i_ur) { + auto r = vreg_accum(i_load, i_ur); + if (jcp.dst_dt == data_type::u8) { + vpxord(zmm_zero, zmm_zero, zmm_zero); + vmaxps(r, zmm_zero, r); + } + if (jcp.dst_dt != data_type::f32) + vcvtps2dq(r, r); + } + for (int i_ur = 0; i_ur < ur; ++i_ur) { + auto r = vreg_accum(i_load, i_ur); + zmm_t r_zmm = mask_flag ? r | ktail_mask : r; + + switch (jcp.dst_dt) { + case data_type::f32: + case data_type::s32: + vmovups(output_ptr(i_load, i_ur), r_zmm); break; + case data_type::s8: + vpmovsdb(output_ptr(i_load, i_ur), r_zmm); break; + case data_type::u8: + vpmovusdb(output_ptr(i_load, i_ur), r_zmm); break; + default: assert(!"unknown dst_dt"); + } + } + } + mov(reg_bcast_data, EVEX_compress_addr(rsp, reg_bcast_data_off)); + if (p_sum_scale && *p_sum_scale != 1.f) + mov(reg_load_data, EVEX_compress_addr(rsp, reg_load_data_off)); + }; + + auto compute = [=](Zmm vreg_acc, Zmm vreg_wei, Zmm vreg_src) { + if (jcp.ver == ver_vnni) { + vpdpbusd(vreg_acc, vreg_src, vreg_wei); + } else { + vpmaddubsw(zmm_tmp, vreg_src, vreg_wei); + vpmaddwd(zmm_tmp, zmm_tmp, zmm_one); + vpaddd(vreg_acc, vreg_acc, zmm_tmp); + } + }; + + auto fma_block = [=](bool last_block) { + int reduce_step = 4; + int tail_size = jcp.ic_without_padding % reduce_step; + int loop_unroll = last_block && jcp.ic != jcp.ic_without_padding + ? rnd_up(jcp.ic_without_padding % jcp.ic_block, reduce_step) + : jcp.reduce_loop_unroll; + for (int i_reduce = 0; i_reduce < loop_unroll; + i_reduce += reduce_step) { + for (int i_load = 0; i_load < load_loop_blk; ++i_load) + vmovups(vreg_load(i_load), load_ptr(i_reduce, i_load)); + for (int i_ur = 0; i_ur < ur; ++i_ur) { + if (last_block && tail_size != 0 + && i_reduce == loop_unroll - reduce_step) { + Xmm xmm_bcast = Xmm(zmm_bcast.getIdx()); + for (int r = 0; r < tail_size; ++r) + vpinsrb(xmm_bcast, xmm_bcast, ptr[aux_reg_bcast_data + + jcp.ic_without_padding * i_ur + i_reduce + r], r); + vpbroadcastd(zmm_bcast, xmm_bcast); + } else { + vpbroadcastd(zmm_bcast, bcast_ptr(i_reduce, i_ur, false)); + } + if (jcp.signed_input) + vpsubb(zmm_bcast, zmm_bcast, zmm_shift); + for (int i_load = 0; i_load < load_loop_blk; ++i_load) { + compute(vreg_accum(i_load, i_ur), + vreg_load(i_load), zmm_bcast); + } + } + } + }; + + Label reduce_loop; + Label reduce_loop_tail; + + mov(aux_reg_load_data, reg_load_data); + + mov(aux_reg_bcast_data, aux1_reg_bcast_data); + init(); + + mov(reduce_loop_iter, reg_reduce_loop_work); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jle(reduce_loop_tail, T_NEAR); + + L(reduce_loop); { + fma_block(false); + add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step); + add(aux_reg_load_data, jcp.reduce_loop_load_step); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jg(reduce_loop, T_NEAR); + } + + L(reduce_loop_tail); + if (jcp.ic != jcp.ic_without_padding) { + fma_block(true); + } else { + fma_block(false); + } + + if (jcp.oc_without_padding != jcp.oc) { + Label end_store, common_store; + mov(EVEX_compress_addr(rsp, reg_bcast_data_off), reg_bcast_data); + + /*Check if it is the last load_loop_blk*/ + sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step); + cmp(reg_load_loop_work, 0); + jg(common_store, T_NEAR); + + /*Check if it is the last ocb*/ + test(reg_reduce_pos_flag, FLAG_OC_LAST); + jz(common_store, T_NEAR); + + store(true); + jmp(end_store, T_NEAR); + + L(common_store); + store(false); + + L(end_store); + + add(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step); + } else { + store(false); + } +} + +void jit_avx512_core_x8s8s32x_1x1_conv_kernel::generate() +{ + preamble(); + + xor_(reg_scratch, reg_scratch); + Reg16 _t = reg_scratch.cvt16(); + mov(_t, 0x1); + vpbroadcastw(zmm_one, _t); + + sub(rsp, stack_space_needed); + + if (jcp.oc_without_padding != jcp.oc) { + int tail_size = jcp.oc_without_padding % jcp.oc_block; + int mask = (1 << tail_size) - 1; + Reg32 regw_tmp = reg_last_load.cvt32(); + mov(regw_tmp, mask); + kmovw(ktail_mask, regw_tmp); + } + + if (jcp.with_bias) + mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]); + if (jcp.signed_input) { + mov(EVEX_compress_addr(rsp, reg_bias_data_off), reg_bias_data); + mov(reg_comp_data, ptr[param1 + GET_OFF(compensation)]); + mov(EVEX_compress_addr(rsp, reg_comp_data_off), reg_comp_data); + } + mov(reg_ptr_scales, ptr[param1 + GET_OFF(scales)]); + mov(EVEX_compress_addr(rsp, reg_ptr_sum_scale_off), reg_ptr_scales); + mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]); + mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]); + mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]); + + mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]); + mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]); + mov(EVEX_compress_addr(rsp, bcast_loop_work_off), reg_bcast_loop_work); + mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]); + mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]); + + + auto load_loop_body = [=](int load_loop_blk) { + bcast_loop(load_loop_blk); + add(reg_load_data, load_loop_blk * jcp.load_loop_load_step); + if (jcp.with_bias) { + if (jcp.signed_input) + mov(reg_bias_data, EVEX_compress_addr(rsp, reg_bias_data_off)); + add(reg_bias_data, + load_loop_blk * jcp.load_block * jcp.typesize_bia); + if (jcp.signed_input) + mov(EVEX_compress_addr(rsp, reg_bias_data_off), reg_bias_data); + } + if (jcp.signed_input) { + mov(reg_comp_data, EVEX_compress_addr(rsp, reg_comp_data_off)); + add(reg_comp_data, + load_loop_blk * jcp.load_block * sizeof(int32_t)); + mov(EVEX_compress_addr(rsp, reg_comp_data_off), reg_comp_data); + } + mov(EVEX_compress_addr(rsp, reg_bcast_data_off), reg_bcast_data); + mov(reg_ptr_scales, EVEX_compress_addr(rsp, reg_ptr_sum_scale_off)); + add(reg_ptr_scales, + jcp.is_oc_scale * load_loop_blk * jcp.load_block * sizeof(float)); + mov(EVEX_compress_addr(rsp, reg_ptr_sum_scale_off), reg_ptr_scales); + mov(reg_bcast_data, EVEX_compress_addr(rsp, reg_bcast_data_off)); + add(reg_output_data, + load_loop_blk * jcp.load_block * jcp.typesize_out); + sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step); + }; + + const int simd_w = 16; + + Label load_loop_blk[7]; + + static const int ur_cases_fma_expl_bcast[] = { 2, 5, 6, 9, 14, 32 }; + const int size_ur_cases_fma = sizeof(ur_cases_fma_expl_bcast); + const int *ur_cases_fma = ur_cases_fma_expl_bcast; + const int *ur_cases = ur_cases_fma; + const int num_ur_cases = (size_ur_cases_fma) / sizeof(*ur_cases); + + for (int ur_idx = num_ur_cases - 1; ur_idx > 0; ur_idx--) { + int label_idx = num_ur_cases - ur_idx - 1; + if (jcp.ur <= ur_cases[ur_idx]) { + cmp(reg_load_loop_work, simd_w * (label_idx + 1)); + jle(load_loop_blk[label_idx], T_NEAR); + } + } + + for (int ur_idx = 0; ur_idx < num_ur_cases; ur_idx++) { + if (jcp.ur <= ur_cases[ur_idx]) { + int label_idx = num_ur_cases - ur_idx - 1; + L(load_loop_blk[label_idx]); + { + if (label_idx == 0) { + cmp(reg_load_loop_work, 0); + je(load_loop_blk[num_ur_cases], T_NEAR); + } + + for (int _i = 1; _i <= label_idx + 1; _i++) { + prefetcht0(ptr [ reg_load_data + _i * jcp.ic * jcp.oc_block ]); + prefetcht1(ptr [ reg_output_data + _i * jcp.oc_block ]); + } + + load_loop_body(label_idx + 1); + if (label_idx - 1 > 0) { + cmp(reg_load_loop_work, 2 * label_idx * simd_w); + je(load_loop_blk[label_idx - 1], T_NEAR); + } + cmp(reg_load_loop_work, (label_idx + 1) * simd_w); + jge(load_loop_blk[label_idx]); + } + for (int idx = label_idx - 1; idx > 0; --idx) { + cmp(reg_load_loop_work, simd_w * (idx + 1)); + je(load_loop_blk[idx], T_NEAR); + } + if (ur_idx < num_ur_cases - 2) { + cmp(reg_load_loop_work, simd_w); + jle(load_loop_blk[0], T_NEAR); + } + } + } + L(load_loop_blk[num_ur_cases]); + + add(rsp, stack_space_needed); + + postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +bool jit_avx512_core_x8s8s32x_1x1_conv_kernel::post_ops_ok( + jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) { + using namespace primitive_kind; + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + + switch (p.len_) { + case 0: return true; + case 1: return is_eltwise(0) || p.contain(sum, 0); + case 2: return (p.contain(sum, 0) && is_eltwise(1)) + || (p.contain(sum, 1) && is_eltwise(0)); + default: return false; + } + + return false; +} + +status_t jit_avx512_core_x8s8s32x_1x1_conv_kernel::init_conf( + jit_1x1_conv_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, const memory_desc_wrapper &bias_d, + const primitive_attr_t &attr, int nthreads, bool reduce_src) { + if (!mayiuse(avx512_core)) return status::unimplemented; + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + if (!one_of(src_d.data_type(), data_type::u8, data_type::s8) + || weights_d.data_type() != data_type::s8 + || !one_of(dst_d.data_type(), + data_type::f32, data_type::s32, data_type::s8, data_type::u8)) + return status::unimplemented; + jcp.ver = ver_avx512_core; + if (mayiuse(avx512_core_vnni)) + jcp.ver = ver_vnni; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ic_without_padding = jcp.ic; + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = dst_d.dims()[2]; + jcp.ow = dst_d.dims()[3]; + jcp.kh = weights_d.dims()[with_groups + 2]; + jcp.kw = weights_d.dims()[with_groups + 3]; + jcp.t_pad = cd.padding[0][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + jcp.signed_input = (src_d.data_type() == data_type::s8) ? true : false; + + jcp.os = jcp.oh * jcp.ow; + jcp.is = jcp.ih * jcp.iw; + jcp.tr_is = rnd_up(jcp.is, 4); + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + + format_tag_t dat_tag = format_tag::nhwc; + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + + bool args_ok = true + && jcp.ngroups == 1 + && jcp.src_tag == dat_tag + && jcp.dst_tag == dat_tag; + if (!args_ok) return status::unimplemented; + + const int simd_w = 16; + + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.ic, simd_w); + + args_ok = true + && jcp.oc % simd_w == 0 && jcp.ic % simd_w == 0 + && jcp.t_pad == 0 && jcp.l_pad == 0 + && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides + && jcp.kh == 1 && jcp.kw == 1; + if (!args_ok) return status::unimplemented; + + jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef; + jcp.dst_dt = cd.dst_desc.data_type; + + jcp.ic_block = jcp.oc_block = simd_w; + + jcp.typesize_in = types::data_type_size(src_d.data_type()); + jcp.typesize_out = types::data_type_size(dst_d.data_type()); + jcp.typesize_bia = jcp.with_bias + ? types::data_type_size(bias_d.data_type()) + : 0; + + const int SMALL_SPATIAL = 7 * 7; + const int BIG_REDUCE_DIM = 1024; + + int load_blocking = 0; + int load_blocking_max = 0; + int bcast_blocking = 0; + int bcast_blocking_max = 0; + int reduce_blocking = 0; + int reduce_blocking_max = 0; + jcp.load_grp_count = 1; + jcp.use_vmovntps = false; + + const int L2_size = get_cache_size(2, true) / sizeof(jcp.typesize_in); + const int L2_capacity = (L2_size * 3) / 4; + + int size_treshold = 28; + int max_regs = 0; + int min_regs = 6; + if (jcp.ver == ver_vnni) + max_regs = ((jcp.oh > size_treshold && jcp.ow > size_treshold) + && (jcp.oc < 128 || jcp.ic < 128)) ? min_regs : 9; + else + max_regs = 8; + jcp.expl_bcast = true; + + if (jcp.mb == 1 && jcp.ic > 128 + && (jcp.oh <= size_treshold && jcp.ow <= size_treshold)) { + if (jcp.os <= SMALL_SPATIAL && jcp.oc * jcp.ic < L2_size) + max_regs = min_regs; // mobilenet_v2 performance improvement + jcp.ur = nstl::min(max_regs, jcp.os); + } else { + const int spatial = jcp.oh; + jcp.ur = 1; + for (int ur_w = max_regs; ur_w >= min_regs; ur_w--) { + if ((spatial >= size_treshold && spatial % ur_w == 0) + || (spatial < size_treshold && jcp.os % ur_w == 0)) { + jcp.ur = ur_w; + break; + } + } + if (jcp.ur == 1) { + jcp.ur = nstl::min(max_regs, jcp.os); + int os_tail = jcp.os % max_regs; + for (int i = max_regs; i >= min_regs; i--) { + int i_tail = jcp.os % i; + if (i_tail > os_tail || i_tail == 0) { + jcp.ur = i; + os_tail = i_tail; + if (i_tail == 0) + break; + } + } + } + } + + jcp.reduce_dim = jcp.ic; + jcp.reduce_block = jcp.ic_block; + + jcp.load_dim = jcp.oc; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.is; + + jcp.bcast_block = jcp.ur; + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.typesize_in; + + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.load_block * jcp.typesize_in; + + jcp.bcast_loop_output_step = jcp.ur * jcp.oc_without_padding * jcp.typesize_out; + jcp.bcast_loop_output_substep = -1; // unused + jcp.bcast_loop_bcast_step = jcp.ur * jcp.ic_without_padding * jcp.typesize_in; + jcp.bcast_loop_bcast_substep = -1; // unused + + jcp.load_loop_load_step + = jcp.reduce_dim * jcp.load_block * jcp.typesize_in; + + jcp.load_loop_iter_step = jcp.load_block; + + jcp.loop_order = reduce_src ? loop_blr : loop_lbr; + + int nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block); + int nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block); + + reduce_blocking = nb_reduce; + if (jcp.bcast_dim <= SMALL_SPATIAL && jcp.reduce_dim >= BIG_REDUCE_DIM) + reduce_blocking = 64; + else if (jcp.bcast_dim > SMALL_SPATIAL && jcp.reduce_dim >= BIG_REDUCE_DIM) + reduce_blocking = 16; + reduce_blocking = best_divider(nb_reduce, 1, reduce_blocking, true); + reduce_blocking *= jcp.reduce_block; + + bool cmp_reduce = reduce_blocking <= jcp.reduce_dim; + if (cmp_reduce) + jcp.loop_order = reduce_src ? loop_rbl : loop_rlb; + load_blocking = jcp.load_dim; + + jcp.load_grp_count = div_up(nthreads, jcp.mb * jcp.ngroups * nb_bcast); + jcp.load_grp_count = best_divider( + nthreads, jcp.load_grp_count, 2 * jcp.load_grp_count, false); + + if (jcp.bcast_dim <= SMALL_SPATIAL && jcp.load_dim * jcp.reduce_dim >= L2_size) { + jcp.load_grp_count = nstl::max(jcp.load_grp_count, 4); + } else if (jcp.bcast_dim <= SMALL_SPATIAL && jcp.mb <= nthreads + && jcp.load_dim > 512 && jcp.load_dim / jcp.reduce_dim >= 4) { + jcp.load_grp_count = nstl::max(jcp.load_grp_count, 2); // + load_blocking = jcp.load_block; + } + + bcast_blocking = div_up(jcp.mb * jcp.ngroups * nb_bcast, + div_up(nthreads, jcp.load_grp_count)) * jcp.bcast_block; + bcast_blocking = nstl::min(jcp.bcast_dim, bcast_blocking); + bcast_blocking = rnd_up(bcast_blocking, jcp.bcast_block); + + int space_for_bcast + = (L2_capacity - /* kernel_size - */ + 2 * jcp.load_block * reduce_blocking + - jcp.ur * reduce_blocking - 3 * 1024); + if (jcp.reduce_dim * jcp.bcast_dim > L2_capacity) + space_for_bcast /= 2; + + int bcast_in_cache + = nstl::max(jcp.bcast_block, space_for_bcast / reduce_blocking); + bcast_blocking = nstl::min( + bcast_blocking, rnd_dn(bcast_in_cache, jcp.bcast_block)); + + load_blocking_max = load_blocking; + bcast_blocking_max = bcast_blocking * 3 / 2; + reduce_blocking_max = reduce_blocking; + + assert(load_blocking); + assert(load_blocking_max); + assert(bcast_blocking); + assert(bcast_blocking_max); + assert(reduce_blocking); + assert(reduce_blocking_max); + assert(load_blocking % jcp.load_block == 0); + assert(reduce_blocking % jcp.reduce_block == 0); + assert(load_blocking_max % jcp.load_block == 0); + assert(reduce_blocking_max % jcp.reduce_block == 0); + + assert(jcp.reduce_loop_unroll % 4 == 0); + assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0); + + assert(jcp.bcast_block % jcp.ur == 0); + assert(jcp.reduce_dim % jcp.reduce_block == 0); + + jcp.ur_tail = jcp.bcast_dim % jcp.ur; + + jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block; + jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block; + jcp.nb_load_blocking = load_blocking / jcp.load_block; + jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block; + jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block; + jcp.nb_reduce_blocking_max = reduce_blocking_max / jcp.reduce_block; + + jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block); + jcp.nb_load = div_up(jcp.load_dim, jcp.load_block); + jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block); + + // miniumum size of load dim chunk for work distribution within threads + jcp.nb_load_chunk = 1; + // peformance improvements for googlenet_v3, mb=1; + // TODO: generalize this condition and rewrite it in appropriate manner + if (jcp.mb == 1 && jcp.nb_load % 4 == 0 && jcp.ic / jcp.oc >= 4 + && jcp.ic * jcp.oc <= L2_size) { + jcp.nb_load_chunk = 4; + jcp.load_grp_count = nstl::max(jcp.nb_load / 4, jcp.load_grp_count); + } + + const auto &oscales = attr.output_scales_; + jcp.is_oc_scale = oscales.mask_ == 1 << 1; + assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0)); + + jcp.wei_adj_scale = + (weights_d.extra().flags | memory_extra_flags::scale_adjust) + ? weights_d.extra().scale_adjust : 1.f; + + return status::success; +} + +void jit_avx512_core_x8s8s32x_1x1_conv_kernel::init_scratchpad( + memory_tracking::registrar_t &scratchpad, + const jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) { + using namespace mkldnn::impl::memory_tracking::names; + + if (jcp.signed_input && jcp.ver != ver_vnni) { + dim_t count = nstl::max(attr.output_scales_.count_, 16); + scratchpad.book(key_conv_adjusted_scales, sizeof(float) * count); + } +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp new file mode 100644 index 0000000000..22e9732a1f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp @@ -0,0 +1,131 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_AVX512_CORE_X8S8S32X_1X1_CONV_KERNEL_HPP +#define JIT_AVX512_CORE_X8S8S32X_1X1_CONV_KERNEL_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_avx512_core_x8s8s32x_1x1_conv_kernel: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_x8s8s32x_1x1_conv_fwd_ker_t) + jit_avx512_core_x8s8s32x_1x1_conv_kernel(jit_1x1_conv_conf_t ajcp, + const primitive_attr_t &attr) : jcp(ajcp), attr_(attr), + eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32( + this, jcp.eltwise); + + this->generate(); + jit_ker = (void (*)(jit_1x1_conv_call_s *)) this->getCode(); + } + + ~jit_avx512_core_x8s8s32x_1x1_conv_kernel() { + delete eltwise_injector_; + } + + static bool post_ops_ok(jit_1x1_conv_conf_t &jcp, + const primitive_attr_t &attr); + + static status_t init_conf(jit_1x1_conv_conf_t &jcp, + const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, + const memory_desc_wrapper &bias_d, + const primitive_attr_t &attr, + int nthreads, bool reduce_src); + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr); + + bool maybe_eltwise(int position); + + jit_1x1_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker)(jit_1x1_conv_call_s *); + + private: + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + using reg64_t = const Xbyak::Reg64; + using zmm_t = const Xbyak::Zmm; + using mask_t = const Xbyak::Opmask; + + reg64_t reg_bcast_data = r8; + reg64_t reg_ptr_scales = r8; + reg64_t reg_output_data = r9; + reg64_t reg_load_data = r10; + reg64_t reg_ptr_sum_scale = r10; + reg64_t reg_reduce_loop_work = r11; + reg64_t reg_bias_data = r12; + reg64_t reg_comp_data = r12; + reg64_t reg_scratch = r13; + reg64_t aux_reg_bcast_data = r14; + reg64_t aux_reg_load_data = r15; + reg64_t imm_addr64 = r15; + reg64_t reg_reduce_pos_flag = rax; + reg64_t aux1_reg_bcast_data = rbx; + reg64_t reg_bcast_loop_work = rbx; + reg64_t bcast_loop_iter = rdx; // Note: Fix me + reg64_t reg_load_loop_work = rsi; + reg64_t aux_reg_output_data = abi_not_param1; + reg64_t reduce_loop_iter = abi_param1; + + reg64_t reg_last_load = r8; + mask_t ktail_mask = k6; + + mask_t vmask = k7; + + Xbyak::Zmm zmm_tmp = Xbyak::Zmm(28); + Xbyak::Zmm zmm_one = Xbyak::Zmm(29); + Xbyak::Zmm zmm_zero = Xbyak::Zmm(30); + Xbyak::Zmm zmm_bcast = Xbyak::Zmm(31); + Xbyak::Zmm zmm_shift = Xbyak::Zmm(30); + + Xbyak::Zmm zmm_bias_alpha = Xbyak::Zmm(31); + Xbyak::Xmm xmm_bias_alpha = Xbyak::Xmm(31); + + int bcast_loop_work_off = 0; + int reg_bias_data_off = 8; + int reg_bcast_data_off = 16; + int reg_load_data_off = 24; + int reg_ptr_sum_scale_off = 32; + int reg_comp_data_off = 40; + int stack_space_needed = 48; + + void bcast_loop(int load_loop_blk); + void reduce_loop(int load_loop_blk, int ur, int substep, bool wraparound); + + void generate(); + void cvt2ps(data_type_t type_in, zmm_t zmm_in, const Xbyak::Operand &op, + bool mask_flag); +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp new file mode 100644 index 0000000000..0bf09fc677 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp @@ -0,0 +1,292 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_generator.hpp" + +#include "jit_avx512_core_x8s8s32x_1x1_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +namespace { +template +void balance2D(U nthr, U ithr, T ny, T &ny_start, T &ny_end, + T nx, T &nx_start, T &nx_end, T nx_divider) +{ + const T grp_size = utils::div_up(nthr, nx_divider); + const T grp_count = utils::div_up(nthr, grp_size); + + T grp = ithr / grp_size; + T grp_ithr = ithr % grp_size; + T grp_nthr = grp_size; + T first_grps = nthr % grp_count; + if (first_grps > 0 && grp >= first_grps) { + ithr -= first_grps * grp_size; + grp_nthr--; + grp = ithr / grp_nthr + first_grps; + grp_ithr = ithr % grp_nthr; + } + balance211(nx, grp_count, grp, nx_start, nx_end); + balance211(ny, grp_nthr, grp_ithr, ny_start, ny_end); +} +} + +/* convolution forward */ +template +void jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const +{ + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + auto scratchpad = this->scratchpad(ctx); + + if (pd()->jcp_.signed_input && pd()->jcp_.ver != ver_vnni) { + auto local_scales = scratchpad.template get( + key_conv_adjusted_scales); + auto scales = pd()->attr()->output_scales_.scales_; + size_t count = pd()->attr()->output_scales_.count_; + float factor = 1.f / pd()->jcp_.wei_adj_scale; + if (count == 1) { + utils::array_set(local_scales, scales[0] * factor, 16); + } else { + for (size_t c = 0; c < count; c++) + local_scales[c] = scales[c] * factor; + } + } + + parallel(kernel_->jcp.nthr, [&](const int ithr, const int nthr) { + execute_forward_thr(ithr, nthr, src, weights, bias, dst, scratchpad); + }); +} + +template +void jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t +::execute_forward_thr(const int ithr, const int nthr, const src_data_t *src, + const wei_data_t *weights, const char *bias, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const { + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const size_t bia_dt_size = pd()->with_bias() + ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0; + + const auto &jcp = kernel_->jcp; + auto rtus_space = scratchpad.get(key_conv_rtus_space); + auto local_scales = scratchpad.get(key_conv_adjusted_scales); + + const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast; + + const int stride_h = pd()->desc()->strides[0]; + const int stride_w = pd()->desc()->strides[1]; + const int pad_t = pd()->desc()->padding[0][0]; + const int pad_l = pd()->desc()->padding[0][1]; + + const auto &oscales = pd()->attr()->output_scales_; + + int offset = jcp.ngroups * (jcp.oc / jcp.oc_block) * (jcp.ic / jcp.ic_block) + * jcp.oc_block * jcp.ic_block; + wei_data_t *w = const_cast(weights); + int32_t* compensation = (jcp.signed_input) + ? reinterpret_cast(w + offset) : 0; + + auto step = [](int default_step, int remaining, int tail_step) { + assert(default_step <= tail_step); + return remaining < tail_step ? remaining : default_step; + }; + + auto p = jit_1x1_conv_call_s(); + + auto rp = rtus_driver_t::call_params_t(); + const int nb_oc = jcp.nb_load; + const int os_block = jcp.bcast_block; + + int bcast_start{0}, bcast_end{0}, ocb_start{0}, ocb_end{0}; + balance2D(nthr, ithr, work_amount, bcast_start, bcast_end, + jcp.nb_load / jcp.nb_load_chunk, ocb_start, ocb_end, + jcp.load_grp_count); + if (jcp.nb_load_chunk > 1) { + ocb_start *= jcp.nb_load_chunk; + ocb_end *= jcp.nb_load_chunk; + } + + auto init_bcast = [&](int iwork, int &n, int &g, int &bcast_step, + int &oh, int &ow, int &ih, int &iw) + { + int osb{0}; + nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb, + jcp.nb_bcast); + bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb, + jcp.nb_bcast_blocking_max); + bcast_step = nstl::min(bcast_step, bcast_end - iwork); + + const int os = osb * os_block; + oh = os / jcp.ow; + ow = os % jcp.ow; + + ih = nstl::max(oh * stride_h - pad_t, 0); + iw = nstl::max(ow * stride_w - pad_l, 0); + rp.iw_start = iw; + + p.bcast_dim = this_block_size(os, jcp.os, + bcast_step * os_block); + rp.os = p.bcast_dim; + }; + + auto init_load = [&](int ocb, int &load_step) + { + load_step = step(jcp.nb_load_blocking, ocb_end - ocb, + jcp.nb_load_blocking_max); + p.load_dim = this_block_size(ocb * jcp.oc_block, + ocb_end * jcp.oc_block, load_step * jcp.oc_block); + + if (ocb + load_step >= nb_oc) + p.first_last_flag |= FLAG_OC_LAST; + else + p.first_last_flag &= ~FLAG_OC_LAST; + + }; + + auto init_reduce = [&]() + { + p.reduce_dim = this_block_size(0, jcp.ic, jcp.ic); + rp.icb = p.reduce_dim / jcp.reduce_block; + }; + + auto inner_ker = [&](int ocb, int n, int g, int oh, int ow, + int ih, int iw) + { + const int icb = 0; // Start from the first IC block + const int _ocb = g * nb_oc + ocb; + const int _icb = g; + + const size_t dst_off = dst_d.blk_off(n, _ocb * jcp.oc_block, oh, ow); + + p.output_data = &dst[dst_off]; + p.load_data = &weights[pd()->with_groups() + ? weights_d.blk_off(g, ocb, icb) + : weights_d.blk_off(ocb, icb)]; + p.bias_data = &bias[_ocb * jcp.oc_block * bia_dt_size]; + p.compensation = (jcp.signed_input) + ? &compensation[_ocb * jcp.oc_block] : 0; + p.scales = (jcp.signed_input && jcp.ver != ver_vnni) + ? &local_scales[jcp.is_oc_scale * _ocb * jcp.oc_block] + : &oscales.scales_[jcp.is_oc_scale * _ocb * jcp.oc_block]; + if (pd()->rtus_.reduce_src_) { + rp.ws = rtus_space + ithr * pd()->rtus_.space_per_thread_ + + _icb * jcp.is * jcp.ic_block; + if (ocb == ocb_start) { + rp.src = src + src_d.blk_off(n, _icb * jcp.ic_block, ih, iw); + rtus_driver_->ker_(&rp); + } + p.bcast_data = rp.ws; + } else + p.bcast_data = src + src_d.blk_off(n, _icb * jcp.ic_block, ih, iw); + + kernel_->jit_ker(&p); + }; + + if (jcp.loop_order == loop_rlb) { + init_reduce(); + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + inner_ker(ocb, n, g, oh, ow, ih, iw); + iwork += bcast_step; + } + ocb += load_step; + } + } else if (jcp.loop_order == loop_lbr) { + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + init_reduce(); + inner_ker(ocb, n, g, oh, ow, ih, iw); + iwork += bcast_step; + } + ocb += load_step; + } + } else if (jcp.loop_order == loop_rbl) { + init_reduce(); + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + inner_ker(ocb, n, g, oh, ow, ih, iw); + ocb += load_step; + } + iwork += bcast_step; + } + } else if (jcp.loop_order == loop_blr) { + int iwork = bcast_start; + while (iwork < bcast_end) { + int n, g, bcast_step, oh, ow, ih, iw; + init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw); + int ocb = ocb_start; + while (ocb < ocb_end) { + int load_step; + init_load(ocb, load_step); + init_reduce(); + inner_ker(ocb, n, g, oh, ow, ih, iw); + ocb += load_step; + } + iwork += bcast_step; + } + } else { + assert(!"unsupported loop order"); + } +} + +using namespace data_type; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; +template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp new file mode 100644 index 0000000000..ad9027ac17 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp @@ -0,0 +1,159 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_1X1_CONVOLUTION_HPP +#define CPU_JIT_AVX512_CORE_X8S8S32X_1X1_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp" +#include "jit_uni_1x1_conv_utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t : public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_(), rtus_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_int8_1x1:", avx512_core, ""), + jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t< + src_type, dst_type>); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, data_type::s8, data_type::undef, + dst_type, data_type::s32) + && IMPLICATION(with_bias(), utils::one_of( + desc()->bias_desc.data_type, data_type::f32, + data_type::s32, data_type::s8, data_type::u8)) + && !has_zero_dim_memory() + && set_default_formats_common(dat_tag(), format_tag::any, + dat_tag()) + && set_or_check_wei_format(); + if (!ok) return status::unimplemented; + + const convolution_desc_t *conv_d = desc(); + const memory_desc_t *src_d = src_md(); + rtus_prepare(this, conv_d, src_d, dst_md()); + + status_t status = jit_avx512_core_x8s8s32x_1x1_conv_kernel:: + init_conf(jcp_, *conv_d, *src_d, *weights_md(), *dst_md(), + *weights_md(1), *attr(), mkldnn_get_max_threads(), + rtus_.reduce_src_); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_core_x8s8s32x_1x1_conv_kernel::init_scratchpad( + scratchpad, jcp_, *attr()); + + rtus_prepare_space_info(this, scratchpad); + + return status::success; + } + + jit_1x1_conv_conf_t jcp_; + reduce_to_unit_stride_t rtus_; + + protected: + format_tag_t dat_tag() const { return format_tag::nhwc; } + + bool set_or_check_wei_format() { + using namespace format_tag; + + const bool is_src_s8 = src_md_.data_type == data_type::s8; + format_tag_t wei_tag = with_groups() ? gOIhw4i16o4i : OIhw4i16o4i; + + memory_desc_t want_wei_md = weights_md_; + memory_desc_init_by_tag(want_wei_md, wei_tag); + if (is_src_s8) { + want_wei_md.extra.flags = 0 + | memory_extra_flags::compensation_conv_s8s8 + | memory_extra_flags::scale_adjust; + want_wei_md.extra.compensation_mask = (1 << 0) + + (with_groups() ? (1 << 1) : 0); + want_wei_md.extra.scale_adjust = + mayiuse(avx512_core_vnni) ? 1.f : 0.5f; + } + + if (weights_md_.format_kind == format_kind::any) { + weights_md_ = want_wei_md; + return true; + } + + return weights_md_ == want_wei_md; + } + }; + + template + friend void init_rtus_driver(conv_t *self); + + jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr), rtus_driver_(nullptr) + { + kernel_ = new jit_avx512_core_x8s8s32x_1x1_conv_kernel(pd()->jcp_, + *pd()->attr()); + init_rtus_driver(this); + } + + ~jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t() { + delete kernel_; + delete rtus_driver_; + } + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + + private: + void execute_forward(const exec_ctx_t &ctx) const; + void execute_forward_thr(const int ithr, const int nthr, + const src_data_t *src, const wei_data_t *weights, + const char *bias, dst_data_t *dst, + const memory_tracking::grantor_t &scratchpad) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_core_x8s8s32x_1x1_conv_kernel *kernel_; + rtus_driver_t *rtus_driver_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp new file mode 100644 index 0000000000..e89d068302 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp @@ -0,0 +1,140 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_1X1_DECONVOLUTION_HPP +#define CPU_JIT_AVX512_CORE_X8S8S32X_1X1_DECONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" +#include "type_helpers.hpp" +#include "primitive_iterator.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_deconvolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_uni_1x1_conv_utils.hpp" +#include "jit_avx512_core_x8s8s32x_1x1_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t + : public cpu_primitive_t { + struct pd_t : public cpu_deconvolution_fwd_pd_t { + pd_t(engine_t *engine, const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : cpu_deconvolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , conv_pd_(nullptr) {} + + pd_t(const pd_t &other) + : cpu_deconvolution_fwd_pd_t(other) + , conv_pd_(other.conv_pd_->clone()) + {} + + ~pd_t() { delete conv_pd_; } + + DECLARE_COMMON_PD_T(conv_pd_->name(), + jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t); + + status_t init_convolution() { + convolution_desc_t cd; + status_t status; + + auto dd = desc(); + status = conv_desc_init(&cd, prop_kind::forward_training, + alg_kind::convolution_direct, &(dd->src_desc), + &(dd->weights_desc), &(dd->bias_desc), &(dd->dst_desc), + dd->strides, dd->dilates, dd->padding[0], dd->padding[1], + dd->padding_kind); + + if (status == status::success) { + status = mkldnn_primitive_desc::create( + &conv_pd_, (op_desc_t *)&cd, &attr_, engine_, nullptr); + } + + if (status == status::success) + status = set_default_params(); + + return status; + }; + + status_t init() { + bool ok = true + && is_fwd() + && desc()->alg_kind == alg_kind::deconvolution_direct + && !has_zero_dim_memory() + && desc()->src_desc.data_type == src_type + && desc()->dst_desc.data_type == dst_type + && desc()->weights_desc.data_type == data_type::s8 + && IMPLICATION(with_bias(), utils::one_of( + desc()->bias_desc.data_type, data_type::f32, + data_type::s32, data_type::s8, data_type::u8)) + && desc()->accum_data_type == data_type::s32; + if (!ok) return status::unimplemented; + + CHECK(init_convolution()); + + return status::success; + } + + virtual void init_scratchpad_md() override { + const auto conv_1x1_pd = static_cast(conv_pd_); + scratchpad_md_ = *conv_1x1_pd->scratchpad_md(); + } + + protected: + status_t set_default_params() { + auto conv_1x1_pd_ = static_cast(conv_pd_); + src_md_ = *conv_1x1_pd_->src_md(); + dst_md_ = *conv_1x1_pd_->dst_md(); + weights_md_ = *conv_1x1_pd_->weights_md(); + if (with_bias()) + bias_md_ = *conv_1x1_pd_->weights_md(1); + return status::success; + } + + using conv_pd_t = typename jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t + ::pd_t; + friend jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t; + primitive_desc_t *conv_pd_; + }; + + jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); } + + ~jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t() + { delete conv_p_; } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + return conv_p_->execute(ctx); + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + primitive_t *conv_p_; +}; + +} +} +} + +#endif /* CPU_JIT_AVX512_CORE_X8S8S32X_1X1_DECONVOLUTION_HPP */ diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp new file mode 100644 index 0000000000..10e98a00c4 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp @@ -0,0 +1,1182 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_memory.hpp" + +#include "jit_avx512_core_x8s8s32x_conv_kernel.hpp" + +#define GET_OFF(field) offsetof(jit_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; +using namespace Xbyak; + +namespace { +void pick_loop_order(jit_conv_conf_t &jcp, int nthr) +{ + jcp.loop_order = loop_cwgn; + if (jcp.ngroups > 1) { + jcp.loop_order = loop_ngcw; + if (jcp.mb < nthr) + jcp.loop_order = jcp.ndims == 3 ? loop_nwcg : loop_nhwcg; + } +} +} + +template +bool _jit_avx512_core_x8s8s32x_fwd_kernel::maybe_eltwise(int position) +{ + using namespace primitive_kind; + const auto &p = attr_.post_ops_; + + if (position == 0) { + /* eltwise before sum */ + return p.contain(eltwise, 0); + } else if (position == 1) { + /* eltwise after sum */ + return p.contain(sum, 0) && p.contain(eltwise, 1); + } + + return false; +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::prepare_output(int ur_w) +{ + int nb_oc_block + = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking; + for (int k = 0; k < nb_oc_block; k++) + for (int j = 0; j < ur_w; j++) { + Vmm vmm = vmm_out(j, k); + vpxord(vmm, vmm, vmm); + } + if (jcp.signed_input) { + xor_(reg_scratch, reg_scratch); + if (jcp.is_depthwise && !jcp.is_fast_depthwise) { + Reg32 _t32 = reg_scratch.cvt32(); + mov(_t32, (uint32_t)128); + vpbroadcastd(vmm_shift, _t32); + } else { + Reg8 _t8 = reg_scratch.cvt8(); + mov(_t8, (int8_t)128); + vpbroadcastb(vmm_shift, _t8); + } + } +} + +template +const Vmm _jit_avx512_core_x8s8s32x_fwd_kernel:: + vmm_mask(const Vmm vmm_in, bool mask_flag, bool store) { + return vmm_in; +} + +template<> +const Zmm _jit_avx512_core_x8s8s32x_fwd_kernel:: + vmm_mask(const Zmm zmm_in, bool mask_flag, bool store) { + return mask_flag ? (store ? zmm_in | ktail_mask : zmm_in | ktail_mask | T_z) + : zmm_in; +} + + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::cvt2ps(data_type_t type_in, + const Vmm vmm_in, const Operand &op, bool mask_flag) { + //const Vmm vmm = mask_flag ? vmm_in | ktail_mask | T_z : vmm_in; + const Vmm vmm = vmm_mask(vmm_in, mask_flag); + switch (type_in) { + case data_type::f32: + case data_type::s32: vmovups(vmm, op); break; + case data_type::s8: vpmovsxbd(vmm, op); break; + case data_type::u8: vpmovzxbd(vmm, op); break; + default: assert(!"unsupported data type"); + } + if (type_in != data_type::f32) + vcvtdq2ps(vmm_in, vmm_in); +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::compute_eltwise(int ur_w) { + int nb_oc_block + = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking; + if (ur_w == jcp.ur_w) + eltwise_injector_->compute_vector_range(0, nb_oc_block * jcp.ur_w); + else + for (int k = 0; k < nb_oc_block; k++) + eltwise_injector_->compute_vector_range(k * jcp.ur_w, + k * jcp.ur_w + ur_w); +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::store_output( + int ur_w, bool last_oc_block_flag) { + int nb_oc_block + = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking; + int oc_block = jcp.is_depthwise ? jcp.ch_block : jcp.oc_block; + + mov(reg_bias, ptr[param1 + GET_OFF(bias)]); + mov(reg_ptr_scales, ptr[param1 + GET_OFF(scales)]); + if (jcp.signed_input) + mov(reg_compensation, ptr[param1 + GET_OFF(compensation)]); + + const auto &p = attr_.post_ops_; + const int sum_idx = p.find(primitive_kind::sum); + const float *p_sum_scale = nullptr; + if (sum_idx != -1) { + const auto &p_entry = p.entry_[sum_idx]; + p_sum_scale = &p_entry.sum.scale; + } + + if (p_sum_scale && *p_sum_scale != 1.f) + mov(reg_ptr_sum_scale, (size_t)p_sum_scale); + + if (jcp.signed_input && jcp.ver != ver_vnni) { + /* put 'wei_adj_scale = 0.5' for bias calculation */ + mov(reg_bias_alpha, float2int(jcp.wei_adj_scale)); + vmovq(xmm_bias_alpha(), reg_bias_alpha); + vbroadcastss(vmm_bias_alpha(), xmm_bias_alpha()); + } + + for (int k = 0; k < nb_oc_block; k++) { + const bool mask_flag = last_oc_block_flag && k == nb_oc_block - 1; + int scale_offset = jcp.is_oc_scale * (sizeof(float) * k * oc_block); + if (jcp.with_bias) { + int bias_offset = jcp.typesize_bia * k * oc_block; + auto bias_addr = EVEX_compress_addr(reg_bias, bias_offset); + + cvt2ps(jcp.bia_dt, vmm_bias, bias_addr, mask_flag); + if (jcp.signed_input && jcp.ver != ver_vnni) + /* bias *= 0.5 */ + vmulps(vmm_bias, vmm_bias, vmm_bias_alpha()); + } + if (jcp.signed_input) { + int comp_offset = sizeof(int32_t) * k * oc_block; + auto comp_addr = EVEX_compress_addr(reg_compensation, comp_offset); + + cvt2ps(data_type::s32, vmm_comp, comp_addr, mask_flag); + } + /* add to zmm_accum: compensation, bias and permute */ + for (int j = 0; j < ur_w; j++) { + Vmm vmm = vmm_out(j, k); + if (jcp.is_fast_depthwise) + vpermd(zmm_out(j, k), zmm_permute, zmm_out(j, k)); + vcvtdq2ps(vmm, vmm); + if (jcp.signed_input) + vaddps(vmm, vmm, vmm_comp); + if (jcp.with_bias) + vaddps(vmm, vmm, vmm_bias); + + const Vmm vmm_k = vmm_mask(vmm, mask_flag); + vmulps(vmm_k, vmm, + EVEX_compress_addr(reg_ptr_scales, scale_offset)); + } + } + + /* Do post-ops */ + if (maybe_eltwise(0)) compute_eltwise(ur_w); + if (p_sum_scale) { // post_op: sum + for (int k = 0; k < nb_oc_block; k++) { + const bool mask_flag = last_oc_block_flag && k == nb_oc_block - 1; + for (int j = 0; j < ur_w; j++) { + int aux_output_offset + = jcp.typesize_out + * (k * oc_block + + j * jcp.oc_without_padding * jcp.ngroups); + auto addr = EVEX_compress_addr(reg_out, aux_output_offset); + Vmm vmm = vmm_out(j, k); + cvt2ps(jcp.dst_dt, vmm_prev_dst, addr, mask_flag); + if (*p_sum_scale == 1.f) + vaddps(vmm, vmm_prev_dst); + else + vfmadd231ps(vmm, vmm_prev_dst, zword_b[reg_ptr_sum_scale]); + } + } + } + if (maybe_eltwise(1)) compute_eltwise(ur_w); + + /* write out register to output_addr */ + for (int k = 0; k < nb_oc_block; k++) { + const bool mask_flag = last_oc_block_flag && k == nb_oc_block - 1; + for (int j = 0; j < ur_w; j++) { + Vmm vmm = vmm_out(j, k); + if (jcp.dst_dt == data_type::u8) { + vpxord(vmm_zero, vmm_zero, vmm_zero); + vmaxps(vmm, vmm_zero, vmm); + } + + if (jcp.dst_dt != data_type::f32) { + /* Note: using Zmm for rounding in Xmm/Ymm kernel + because there is no instruction to do rounding + from Xmm/Ymm -> Xmm/Ymm. + Embedded rounding is not supported for Xmm. + TODO: maybe avoid Zmm if it helps performance.*/ + Zmm zmm = zmm_out(j, k); + vcvtps2dq(zmm, zmm); + } + } + + for (int j = 0; j < ur_w; j++) { + int aux_output_offset = jcp.typesize_out + * (k * oc_block + j * jcp.oc_without_padding * jcp.ngroups); + auto addr = EVEX_compress_addr(reg_out, aux_output_offset); + + Vmm vmm = vmm_out(j, k); + const Vmm r_vmm = vmm_mask(vmm, mask_flag, true); + + switch (jcp.dst_dt) { + case data_type::f32: + case data_type::s32: vmovups(addr, r_vmm); break; + case data_type::s8: vpmovsdb(addr, r_vmm); break; + case data_type::u8: vpmovusdb(addr, r_vmm); break; + default: assert(!"unknown dst_dt"); + } + } + } + +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::compute_ker_dw( + int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag, bool h_padded) { + assert(!"invalid group blocking for depthwise convolution"); +} + +template <> +void _jit_avx512_core_x8s8s32x_fwd_kernel::compute_ker_dw( + int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag, bool h_padded) { + + auto input_spatial_index = [=](int oi, int ki) { + return (ki * (jcp.dilate_w + 1) + oi * jcp.stride_w - pad_l); + }; + + auto input_offset2 = [=](int ii, int ci) { + return jcp.typesize_in * (ii * jcp.ngroups + ci * jcp.ch_block); + }; + + auto input_offset3 = [=](int oi, int ci, int ki) { + return jcp.typesize_in * input_offset2(input_spatial_index(oi, ki), ci); + }; + + auto kernel_offset = [=](int ci, int ki) { + return jcp.typesize_in * ((ci * jcp.kh * jcp.kw + ki) * jcp.ch_block); + }; + + auto compute = [=](Zmm vreg_acc, Zmm vreg_wei, Zmm vreg_src) { + // okay for depthwise since src is zero-extended + if (jcp.ver == ver_vnni) { + vpdpbusd(vreg_acc, vreg_src, vreg_wei); + } else { + vpmaddwd(zmm_tmp, vreg_src, vreg_wei); + vpaddd(vreg_acc, vreg_acc, zmm_tmp); + } + }; + + int ii_start = 0; + int ii_end = -1; + if (jcp.is_resrc_depthwise && !h_padded) { + // find bounds of input spatial indices + bool first = true; + for (int ki = 0; ki < jcp.kw; ki++) { + int oi_start = get_ow_start(ki, pad_l); + int oi_end = get_ow_end(ur_w, ki, pad_r); + for (int oi = oi_start; oi < oi_end; oi++) { + int ii = input_spatial_index(oi, ki); + if (first || ii < ii_start) + ii_start = ii; + if (first || ii > ii_end) + ii_end = ii; + first = false; + } + } + } + + if (jcp.signed_input) { + vpxord(zmm_shifted_zero, zmm_shifted_zero, zmm_shifted_zero); + vpaddb(zmm_shifted_zero, zmm_shifted_zero, vmm_shift); + } + for (int ci = 0; ci < jcp.nb_ch_blocking; ci++) { + const bool mask_flag = last_ic_block_flag != no_last_block + && ci == jcp.nb_ch_blocking - 1; + if (jcp.is_resrc_depthwise && !h_padded) { + // now we can load input once and reuse up to jcp.kw times + for (int ii = ii_start; ii <= ii_end; ii++) { + int aux_input_offset = input_offset2(ii, ci); + const Zmm zmm_inp_tmp = zmm_inp(ii, jcp.nb_ch_blocking); + const Zmm zmm_inp_msk = mask_flag + ? zmm_inp_tmp | ktail_mask | T_z + : zmm_inp_tmp; + if (jcp.is_fast_depthwise) { + assert(!mask_flag); + vbroadcasti32x4(zmm_inp_msk, + EVEX_compress_addr(aux_reg_inp, aux_input_offset)); + } else { + vpmovzxbd(zmm_inp_msk, + EVEX_compress_addr(aux_reg_inp, aux_input_offset)); + } + if (jcp.signed_input) + vpaddb(zmm_inp_tmp, zmm_inp_tmp, vmm_shift); + } + } + for (int ki = 0; ki < jcp.kw; ki++) { + int aux_kernel_offset = kernel_offset(ci, ki); + if (jcp.is_fast_depthwise) { + vbroadcasti32x4(zmm_wei, + EVEX_compress_addr(aux_reg_ker, aux_kernel_offset)); + vmovdqu8(zmm_wei | kblend_mask | T_z, zmm_wei); + } else { + vpmovsxbd(zmm_wei, + EVEX_compress_addr(aux_reg_ker, aux_kernel_offset)); + } + if (h_padded) { + assert(jcp.signed_input); + for (int oi = 0; oi < ur_w; oi++) + compute(zmm_out(oi, ci), zmm_wei, zmm_shifted_zero); + } else { + const Zmm r_zmm_src = mask_flag ? zmm_src | ktail_mask : zmm_src; + int oi_start = get_ow_start(ki, pad_l); + int oi_end = get_ow_end(ur_w, ki, pad_r); + int start_ = jcp.signed_input ? 0 : oi_start; + int end_ = jcp.signed_input ? ur_w : oi_end; + for (int oi = start_; oi < end_; oi++) { + if (oi >= oi_start && oi < oi_end) { + if (jcp.is_resrc_depthwise) { + int ii = input_spatial_index(oi, ki); + zmm_src = zmm_inp(ii, jcp.nb_ch_blocking); + } else { + int aux_input_offset = input_offset3(oi, ci, ki); + if (jcp.is_fast_depthwise) { + assert(!mask_flag); + vbroadcasti32x4(r_zmm_src, + EVEX_compress_addr(aux_reg_inp, + aux_input_offset)); + } else { + vpmovzxbd(r_zmm_src, + EVEX_compress_addr(aux_reg_inp, + aux_input_offset)); + } + if (jcp.signed_input) + vpaddb(zmm_src, zmm_src, vmm_shift); + } + } else if (jcp.signed_input) { + zmm_src = zmm_shifted_zero; + } + compute(zmm_out(oi, ci), zmm_wei, zmm_src); + } + } + } + } +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::compute_ker(int ur_w, int pad_l, + int pad_r, ic_block_t last_ic_block_flag, bool h_padded) { + if (jcp.is_depthwise) + return compute_ker_dw(ur_w, pad_l, pad_r, last_ic_block_flag, h_padded); + + int kw = jcp.kw; + int stride_w = jcp.stride_w; + int ic_block = jcp.ic_block; + int oc_block = jcp.oc_block; + int ch_block_all = jcp.ch_block * ic_block * oc_block; + + int nb_oc_block = jcp.nb_oc_blocking; + + auto input_offset = [=](int oi, int ic, int ki) { + return jcp.typesize_in + * ((ki * (jcp.dilate_w + 1) + oi * stride_w - pad_l) + * jcp.ic_without_padding * jcp.ngroups + 4 * ic); + }; + auto kernel_offset = [=](int ii, int ic, int ki) { + return jcp.typesize_in + * ((ii * jcp.nb_ic * jcp.kh * jcp.kw + ki) * ch_block_all + + 4 * ic * oc_block); + }; + auto compute = [=](Vmm vreg_acc, Vmm vreg_wei, Vmm vreg_src) { + if (jcp.ver == ver_vnni) { + vpdpbusd(vreg_acc, vreg_src, vreg_wei); + } else { + vpmaddubsw(vmm_tmp, vreg_src, vreg_wei); + vpmaddwd(vmm_tmp, vmm_tmp, vmm_one); + vpaddd(vreg_acc, vreg_acc, vmm_tmp); + } + }; + + for (int ki = 0; ki < kw; ki++) { + int jj_start = get_ow_start(ki, pad_l); + int jj_end = get_ow_end(ur_w, ki, pad_r); + int tail_size = jcp.ic_without_padding % 4; + int _start = (jcp.signed_input) ? 0 : jj_start; + int _end = (jcp.signed_input) ? ur_w : jj_end; + /* Skip the last loads of input if (ic%16)/4 < ic_block/4 */ + int icb = (last_ic_block_flag != no_last_block) + ? div_up((jcp.ic_without_padding % ic_block), 4) + : ic_block / 4; + for (int ic = 0; ic < icb; ic++) { + if (h_padded == true) { + /* fill padded area with shifted values */ + Vmm inp = vmm_inp(0,nb_oc_block); + vpxord(inp, inp, inp); + vpaddb(inp, inp, vmm_shift); + } else { + for (int jj = _start; jj < _end; jj++) { + int aux_input_offset = input_offset(jj, ic, ki); + if (jj >= jj_start && jj < jj_end) { + if (last_ic_block_flag == last_sp_block + && tail_size != 0 && ic == icb - 1) { + Xmm xmm_tmp = Xmm(vmm_inp(jj, nb_oc_block).getIdx()); + for (int r = 0; r < tail_size; ++r) + vpinsrb(xmm_tmp, xmm_tmp, + ptr[aux_reg_inp + aux_input_offset + r], r); + vpbroadcastd(vmm_inp(jj, nb_oc_block), xmm_tmp); + } else { + vpbroadcastd(vmm_inp(jj, nb_oc_block), + EVEX_compress_addr( + aux_reg_inp, aux_input_offset)); + } + if (jcp.signed_input) + vpaddb(vmm_inp(jj, nb_oc_block), + vmm_inp(jj, nb_oc_block), vmm_shift); + } else { + /* fill padded area with shifted values */ + if (jcp.signed_input) { + Vmm inp = vmm_inp(jj, nb_oc_block); + vpxord(inp, inp, inp); + vpaddb(inp, inp, vmm_shift); + } + } + } + } + for (int ii = 0; ii < nb_oc_block; ii++) { + int aux_kernel_offset = kernel_offset(ii, ic, ki); + vmovups(vmm_wei, + EVEX_compress_addr(aux_reg_ker, aux_kernel_offset)); + for (int jj = _start; jj < _end; jj++) { + Vmm inp = (h_padded == true) + ? vmm_inp(0,nb_oc_block) : vmm_inp(jj, nb_oc_block); + compute(vmm_out(jj, ii), vmm_wei, inp); + } + } + } + } +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::kh_loop( + int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag) { + Label kh_label, skip_kh_loop; + Label t_overflow_label, no_t_overflow_label, + b_overflow_label, no_b_overflow_label; + + int ch_block_all = jcp.ch_block * jcp.ic_block * jcp.oc_block; + int shift_kernel_ptr = jcp.typesize_in * jcp.kw * ch_block_all; + int shift_input_ptr = jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw + * jcp.ic_without_padding * jcp.ngroups; + + mov(aux_reg_inp, reg_inp); + mov(aux_reg_ker, reg_ker); + + if (jcp.signed_input && jcp.ndims > 3) { + mov(reg_overflow, ptr[param1 + GET_OFF(t_overflow)]); + cmp(reg_overflow, 0); + je(no_t_overflow_label, T_NEAR); + L(t_overflow_label); { + compute_ker(ur_w, pad_l, pad_r, last_ic_block_flag, true); + + add(aux_reg_ker, shift_kernel_ptr); + dec(reg_overflow); + cmp(reg_overflow, 0); + jg(t_overflow_label, T_NEAR); + } + L(no_t_overflow_label); + } + mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]); + if ((jcp.signed_input) || (!jcp.signed_input && + (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad))) { + cmp(reg_kj, 0); + je(skip_kh_loop, T_NEAR); + } + L(kh_label); { + compute_ker(ur_w, pad_l, pad_r, last_ic_block_flag, false); + + add(aux_reg_ker, shift_kernel_ptr); + add(aux_reg_inp, shift_input_ptr); + dec(reg_kj); + cmp(reg_kj, 0); + jg(kh_label, T_NEAR); + } + L(skip_kh_loop); + if (jcp.signed_input && jcp.ndims > 3) { + mov(reg_overflow, ptr[param1 + GET_OFF(b_overflow)]); + cmp(reg_overflow, 0); + je(no_b_overflow_label, T_NEAR); + L(b_overflow_label); { + compute_ker(ur_w, pad_l, pad_r, last_ic_block_flag, true); + + add(aux_reg_ker, shift_kernel_ptr); + dec(reg_overflow); + cmp(reg_overflow, 0); + jg(b_overflow_label, T_NEAR); + } + L(no_b_overflow_label); + } +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::icb_loop( + int ur_w, int pad_l, int pad_r, bool is_last_sp_block) +{ + prepare_output(ur_w); + + // IC loop + Label icb_label; + mov(reg_icb, jcp.nb_ic); + L(icb_label); + if (jcp.ngroups % jcp.ch_block != 0 || jcp.ic_without_padding != jcp.ic) { + Label common_ker, end_ker; + + cmp(reg_icb, 1); // The last IC block + jne(common_ker, T_NEAR); + + kh_loop(ur_w, pad_l, pad_r, + is_last_sp_block ? last_sp_block : last_ic_block); + jmp(end_ker, T_NEAR); + + L(common_ker); + kh_loop(ur_w, pad_l, pad_r, no_last_block); + + L(end_ker); + } else { + kh_loop(ur_w, pad_l, pad_r, no_last_block); + } + // End of IC Loop + int inp_step = jcp.ic_block; + int ker_step = jcp.kh * jcp.kw * jcp.oc_block * jcp.ic_block; + add(reg_inp, jcp.typesize_in * inp_step); + add(reg_ker, jcp.typesize_in * ker_step); + + dec(reg_icb); + cmp(reg_icb, 0); + jg(icb_label, T_NEAR); + + sub(reg_inp, jcp.typesize_in * inp_step * jcp.nb_ic); + sub(reg_ker, jcp.typesize_in * ker_step * jcp.nb_ic); + + if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) { + Label common_store, end_store; + + if (jcp.is_depthwise) + cmp(reg_oc_blocks, jcp.nb_ch - jcp.nb_ch_blocking); + else + cmp(reg_oc_blocks, jcp.nb_oc - jcp.nb_oc_blocking); + + jne(common_store, T_NEAR); + + store_output(ur_w, true); // last oc block + jmp(end_store, T_NEAR); + + L(common_store); + store_output(ur_w, false); + + L(end_store); + } else { + store_output(ur_w, false); + } +} + +template +void _jit_avx512_core_x8s8s32x_fwd_kernel::generate() +{ + Label permute_index_table; + int inp_shift_pad = jcp.typesize_in * (jcp.ur_w * jcp.stride_w - jcp.l_pad) + * jcp.ic_without_padding * jcp.ngroups; + int inp_shift_pad_second_block = -1 * jcp.typesize_in * jcp.l_pad + * jcp.ic_without_padding * jcp.ngroups; + int inp_shift = jcp.typesize_in * + (jcp.ur_w * jcp.stride_w * jcp.ic_without_padding + * jcp.ngroups); + int out_shift = jcp.typesize_out * + (jcp.ur_w * jcp.oc_without_padding * jcp.ngroups); + preamble(); + + if (jcp.is_depthwise) { + int idx = jcp.max_regs_ur - 1; + if (!jcp.is_resrc_depthwise) + zmm_src = Zmm(++idx); + if (jcp.ver != ver_vnni) + zmm_tmp = Zmm(++idx); + if (jcp.is_fast_depthwise) + zmm_permute = Zmm(++idx); + if (jcp.signed_input) { + zmm_shifted_zero = Zmm(++idx); + ++idx; // due to extra register used for shifts and compensations + } + assert(idx == ker_dw_reg_base_idx); + } + + if (!jcp.is_depthwise && jcp.ver != ver_vnni) { + xor_(reg_scratch, reg_scratch); + Reg16 _t16 = reg_scratch.cvt16(); + mov(_t16, 0x1); + vpbroadcastw(vmm_one, _t16); + } + + mov(reg_inp, ptr[param1 + GET_OFF(src)]); + mov(reg_out, ptr[param1 + GET_OFF(dst)]); + mov(reg_ker, ptr[param1 + GET_OFF(filt)]); + + if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) { + int tail_size = jcp.is_depthwise + ? jcp.ngroups % jcp.ch_block + : jcp.oc_without_padding % jcp.oc_block; + int mask = (1 << tail_size) - 1; + mov(reg_oc_blocks, ptr[param1 + GET_OFF(oc_blocks)]); + Reg32 regw_tmp = reg_oi.cvt32(); + mov(regw_tmp, mask); + kmovw(ktail_mask, regw_tmp); + } + if (jcp.is_fast_depthwise) { + // prepare mask register for blending weights + mov(reg_scratch, 0x8888444422221111); + kmovq(kblend_mask, reg_scratch); + // load permute indices from data section + mov(reg_scratch, permute_index_table); + vmovdqu32(zmm_permute, ptr[reg_scratch]); + } + + int r_pad = nstl::max(0, (jcp.ow - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) + - (jcp.iw + jcp.l_pad - 1)); + int n_oi = jcp.ow / jcp.ur_w; + int r_pad1 = (jcp.ur_w * n_oi - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1); + + if (jcp.nb_ow == 1) { + if (r_pad1 > 0 || jcp.ur_w_tail == 0) + n_oi--; + + xor_(reg_oi, reg_oi); + if (jcp.ow == jcp.ur_w) { + icb_loop(jcp.ur_w, jcp.l_pad, r_pad, true); + } else { + if (n_oi == 0) { + icb_loop(jcp.ur_w, jcp.l_pad, r_pad1, jcp.ur_w_tail == 0); + add(reg_inp, inp_shift_pad); + add(reg_out, out_shift); + if (jcp.ur_w_tail != 0) { + icb_loop(jcp.ur_w_tail, 0, r_pad, true); + } + } else { + if (jcp.l_pad > 0) { + icb_loop(jcp.ur_w, jcp.l_pad, 0, false); + add(reg_inp, inp_shift_pad); + add(reg_out, out_shift); + + inc(reg_oi); + } + if ((jcp.l_pad <= 0 && n_oi > 0) || (jcp.l_pad > 0 && n_oi > 1)) + { + Label ow_loop_label; + L(ow_loop_label); { + icb_loop(jcp.ur_w, 0, 0, false); + add(reg_inp, inp_shift); + add(reg_out, out_shift); + + inc(reg_oi); + cmp(reg_oi, n_oi); + jl(ow_loop_label, T_NEAR); + } + } + if (r_pad1 > 0 || jcp.ur_w_tail == 0) { + icb_loop(jcp.ur_w, 0, r_pad1, jcp.ur_w_tail == 0); + add(reg_inp, inp_shift); + add(reg_out, out_shift); + } + if (jcp.ur_w_tail != 0) { + icb_loop(jcp.ur_w_tail, 0, r_pad, true); + } + } + } + } else { + // ow block is only processed. + // Number of block is passed as parameter owb, + // and padding processing depends on this number. + Label end_label, last_oi_label, middle_ow_blocks_label, tail_label, + oi_loop_label, oi_loop_end_label; + + assert(jcp.ow_block % jcp.ur_w == 0); + int n_oi_not_last_ow_block = jcp.ow_block / jcp.ur_w; + // to simplify code (and general regs usage), + // size of ow block must be >= 2 * ur_w + assert(n_oi_not_last_ow_block > 1); + int n_oi_next_last_ow_block = n_oi_not_last_ow_block; + int n_oi_first_ow_block = n_oi_not_last_ow_block; + int n_oi_last_ow_block + = (jcp.ow - jcp.ow_block * (jcp.nb_ow - 1)) / jcp.ur_w; + // prepare right padding + bool next_last_ow_block_padded = r_pad1 > 0 && n_oi_last_ow_block == 0; + bool first_ow_block_padded + = next_last_ow_block_padded && jcp.nb_ow == 2; + bool last_ow_block_padded + = (r_pad1 > 0 || jcp.ur_w_tail == 0) && n_oi_last_ow_block > 0; + + if (last_ow_block_padded) n_oi_last_ow_block--; + else if (first_ow_block_padded) n_oi_first_ow_block--; + else if (next_last_ow_block_padded) n_oi_next_last_ow_block--; + + mov(reg_owb, ptr[param1 + GET_OFF(owb)]); + cmp(reg_owb, 0); // is that the first ow-block ? + jg(middle_ow_blocks_label, T_NEAR); + + // the first ow block, compute left padding + mov(reg_oi, n_oi_first_ow_block); + if (jcp.l_pad > 0) { + icb_loop(jcp.ur_w, jcp.l_pad, 0, false); + add(reg_inp, inp_shift_pad); + add(reg_out, out_shift); + + dec(reg_oi); + } + jmp(oi_loop_label, T_NEAR); + + // middle or last ow block entry + L(middle_ow_blocks_label); + + if (jcp.l_pad > 0) { + // just to consider left padding, not compute + add(reg_inp, inp_shift_pad_second_block); + } + + // set number of iteration for oi-loop + if (n_oi_last_ow_block != n_oi_not_last_ow_block) { + cmp(reg_owb, jcp.nb_ow - 1); // last ow-block ? + mov(reg_oi, n_oi_last_ow_block); + je(oi_loop_label, T_NEAR); + } + + if (n_oi_next_last_ow_block != n_oi_not_last_ow_block) { + cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ? + + mov(reg_oi, n_oi_next_last_ow_block); + je(oi_loop_label, T_NEAR); + } + mov(reg_oi, n_oi_not_last_ow_block); // other middle ow-blocks + + // oi loop w/o padding + L(oi_loop_label); { + cmp(reg_oi, 0); + jle(oi_loop_end_label, T_NEAR); + + icb_loop(jcp.ur_w, 0, 0, false); + + add(reg_inp, inp_shift); + add(reg_out, out_shift); + dec(reg_oi); + + jmp(oi_loop_label, T_NEAR); + } + L(oi_loop_end_label); + + mov(reg_owb, ptr[param1 + GET_OFF(owb)]); + cmp(reg_owb, 0); // first ow-block ? + if (first_ow_block_padded) + je(last_oi_label, T_NEAR); + else + je(end_label, T_NEAR); + + cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ? + jl(end_label, T_NEAR); + if (next_last_ow_block_padded) + je(last_oi_label, T_NEAR); + else + je(end_label, T_NEAR); + + // that is last block + if (!last_ow_block_padded) + jmp(tail_label, T_NEAR); + + // last oi block with right padding + L(last_oi_label); + icb_loop(jcp.ur_w, 0, r_pad1, jcp.ur_w_tail == 0); + add(reg_inp, inp_shift); + add(reg_out, out_shift); + + mov(reg_owb, ptr[param1 + GET_OFF(owb)]); + cmp(reg_owb, jcp.nb_ow - 1); // last ow_block? + jl(end_label, T_NEAR); + + // ur_w tail + L(tail_label); + if (jcp.ur_w_tail != 0) { + icb_loop(jcp.ur_w_tail, 0, r_pad, true); + } + L(end_label); + } + postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); + + if (jcp.is_fast_depthwise) { + align(64); + L(permute_index_table); + const uint32_t _idx[] + = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; + for (size_t i = 0; i < sizeof(_idx) / sizeof(_idx[0]); ++i) + dd(_idx[i]); + } +} + +bool jit_avx512_core_x8s8s32x_fwd_kernel::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) +{ + using namespace primitive_kind; + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + + switch (p.len_) { + case 0: return true; + case 1: return is_eltwise(0) || p.contain(sum, 0); + case 2: return (p.contain(sum, 0) && is_eltwise(1)) || + (p.contain(sum, 1) && is_eltwise(0)); + default: return false; + } + + return false; +} + +status_t jit_avx512_core_x8s8s32x_fwd_kernel::init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, memory_desc_t &src_md, + memory_desc_t &weights_md, memory_desc_t &dst_md, + memory_desc_t &bias_md, const primitive_attr_t &attr, + int nthreads) +{ + using namespace prop_kind; + + const memory_desc_wrapper src_d(&src_md); + const memory_desc_wrapper weights_d(&weights_md); + const memory_desc_wrapper dst_d(&dst_md); + const memory_desc_wrapper bias_d(&bias_md); + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + int ndims = src_d.ndims(); + bool is_1d = ndims == 3; + + if (!(mayiuse(avx512_core) + && one_of(src_d.data_type(), data_type::u8, data_type::s8) + && weights_d.data_type() == data_type::s8 + && one_of(dst_d.data_type(), data_type::f32, data_type::s32, + data_type::s8, data_type::u8))) + return status::unimplemented; + + jcp = zero(); + jcp.ndims = ndims; + jcp.prop_kind = cd.prop_kind; + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.ic_without_padding = jcp.ic; + jcp.ih = is_1d ? 1 : src_d.dims()[ndims - 2]; + jcp.iw = src_d.dims()[ndims - 1]; + jcp.oh = is_1d ? 1 : dst_d.dims()[ndims - 2]; + jcp.ow = dst_d.dims()[ndims - 1]; + jcp.kh = is_1d ? 1 : weights_d.dims()[with_groups + ndims - 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + jcp.t_pad = is_1d ? 0 : cd.padding[0][ndims - 4]; + jcp.l_pad = cd.padding[0][ndims - 3]; + jcp.stride_h = is_1d ? 1 : cd.strides[ndims - 4]; + jcp.stride_w = cd.strides[ndims - 3]; + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + jcp.ur_h = 1; /* no code-unrolling by h so far */ + + jcp.dilate_h = is_1d ? 0 : cd.dilates[ndims - 4]; + jcp.dilate_w = cd.dilates[ndims - 3]; + + jcp.signed_input = (src_d.data_type() == data_type::s8) ? true : false; + jcp.is_depthwise = true && with_groups && everyone_is(1, jcp.ic, jcp.oc); + + if (jcp.is_depthwise) { + jcp.ch_block = 16; + jcp.ic_block = 1; + jcp.oc_block = 1; + } else { + jcp.ch_block = 1; + jcp.ic_block = 16; + jcp.oc_block = 16; + + if (jcp.ngroups == 1) { + /* For non grouped convolutions, pad channels by 16 if needed */ + jcp.oc = rnd_up(jcp.oc, jcp.oc_block); + jcp.ic = rnd_up(jcp.ic, jcp.ic_block); + } else if (!is_1d && jcp.ngroups != 1 && jcp.ic % jcp.ic_block != 0) { + /* For grouped convolutions, MKL-DNN doesn't support padding. + Use Ymm when channels per group is multiple of 8, + Xmm when channels per group is multiple of 4 */ + jcp.ic_block = jcp.ic % 8 == 0 ? 8 : 4; + jcp.oc_block = jcp.ic_block; + } + if (jcp.ic % jcp.ic_block !=0 || jcp.oc % jcp.oc_block != 0) + return status::unimplemented; + } + + jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1) + - (jcp.ih + jcp.t_pad - 1); + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + + jcp.ver = mayiuse(avx512_core_vnni) ? ver_vnni : ver_avx512_core; + jcp.is_fast_depthwise = true && jcp.is_depthwise && jcp.ver == ver_vnni + && jcp.ngroups % jcp.ch_block == 0; // for groups not multiple of 16 + // would require byte masking + // for load from src + jcp.is_resrc_depthwise = jcp.is_depthwise && jcp.stride_w < jcp.kw + && jcp.kw < 4 && jcp.dilate_w == 0; + if (jcp.is_depthwise) { + jcp.max_regs_ur = 31 - jcp.is_fast_depthwise - !jcp.is_resrc_depthwise + - 2 * jcp.signed_input - (jcp.ver != ver_vnni); + } else { + jcp.max_regs_ur = jcp.ver == ver_vnni ? 31 : 28; + } + + auto set_or_check_wei_format = [&]() { + using namespace format_tag; + format_tag_t wei_tag; + if (jcp.ic_block == 16 || jcp.ch_block == 16) { + if (is_1d) { + wei_tag = with_groups + ? jcp.is_depthwise ? Goiw16g : gOIw4i16o4i + : OIw4i16o4i; + } else { + wei_tag = with_groups + ? jcp.is_depthwise ? Goihw16g : gOIhw4i16o4i + : OIhw4i16o4i; + } + } else if (with_groups && jcp.ic_block == 8) { + wei_tag = gOIhw2i8o4i; + } else + wei_tag = gOIhw4o4i; + + memory_desc_t want_wei_md = weights_md; + memory_desc_init_by_tag(want_wei_md, wei_tag); + if (jcp.signed_input) { + want_wei_md.extra.flags = 0 + | memory_extra_flags::compensation_conv_s8s8 + | memory_extra_flags::scale_adjust; + want_wei_md.extra.compensation_mask = (1 << 0) + + (with_groups && !jcp.is_depthwise ? (1 << 1) : 0); + want_wei_md.extra.scale_adjust = + mayiuse(avx512_core_vnni) ? 1.f : 0.5f; + } + + if (weights_md.format_kind == format_kind::any) { + weights_md = want_wei_md; + return true; + } + + return weights_md == want_wei_md; + }; + + if (!set_or_check_wei_format()) + return status::unimplemented; + + format_tag_t dat_tag = utils::pick(ndims - 3, + format_tag::nwc, format_tag::nhwc); + + if (src_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(src_md, dat_tag)); + jcp.src_tag = dat_tag; + } else { + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + } + if (jcp.src_tag != dat_tag) + return status::unimplemented; + + if (dst_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(dst_md, dat_tag)); + jcp.dst_tag = dat_tag; + } else { + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + } + if (jcp.dst_tag != dat_tag) + return status::unimplemented; + + if (jcp.with_bias) { + if (bias_d.format_kind() == format_kind::any) + CHECK(memory_desc_init_by_tag(bias_md, format_tag::x)); + } + + jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef; + jcp.dst_dt = cd.dst_desc.data_type; + + jcp.typesize_in = types::data_type_size(src_d.data_type()); + jcp.typesize_out = types::data_type_size(dst_d.data_type()); + jcp.typesize_bia = jcp.with_bias + ? types::data_type_size(bias_d.data_type()) + : 0; + + jcp.nb_ch = div_up(jcp.ngroups, jcp.ch_block); + jcp.nb_ic = jcp.ic / jcp.ic_block; + jcp.nb_oc = jcp.oc / jcp.oc_block; + + // Try to use 4 channel-groups at a time to avoid false sharing (depthwise) + int nb_ch_blocking = 4; + for ( /* init above */ ; nb_ch_blocking > 1; nb_ch_blocking--) + if (jcp.nb_ch % nb_ch_blocking == 0) + break; + jcp.nb_ch_blocking = jcp.is_depthwise ? nb_ch_blocking : 1; + + // If OC blocking is incommensurate with the number of OC blocks (general + // requirement for all convolutions), or if it results in an unrolling + // factor smaller than the left padding (special requirement for SSD:fc6), + // then search for a smaller OC blocking that satisfies both constraints. + auto is_oc_blocking_ok = [&](int block) { + int ur_w = nstl::min(jcp.ow, jcp.max_regs_ur / (block + 1)); + return jcp.nb_oc % block == 0 + && jcp.l_pad <= ur_w && jcp.ow % ur_w != 1; + }; + + // choose nb_oc work chunk size for distribution within threads + int max_threading_nb_oc_chunk = 4; + // Performance improvements for googlenet_v3 and resnet_50 with mb = 1; + // TODO: generalize this condition and rewrite it in appropriate manner + if (jcp.ver == ver_vnni && jcp.mb == 1 && jcp.kh == 3 && jcp.kw == 3 + && jcp.stride_w == 1 && jcp.ic % 64 == 0) + max_threading_nb_oc_chunk = 2; + jcp.nb_oc_blocking_thr_chunk = + nstl::min(max_threading_nb_oc_chunk, jcp.nb_oc); + for (; jcp.nb_oc_blocking_thr_chunk > 1; jcp.nb_oc_blocking_thr_chunk--) { + if (is_oc_blocking_ok(jcp.nb_oc_blocking_thr_chunk)) + break; + } + + // choose oc blocking for computational kernel + jcp.nb_oc_blocking = jcp.nb_oc_blocking_thr_chunk; + // Performance improvements for googlenet_v3 with mb = 1; + // TODO: generalize this condition and rewrite it in appropriate manner + const int size_treshold_for_nb_oc_blocking_reduction = 17; + if (jcp.mb == 1 && jcp.ow <= size_treshold_for_nb_oc_blocking_reduction + && jcp.stride_w == 1 + && !(jcp.kh == 1 && jcp.kw == 3) + && !(jcp.kh >= 7 && jcp.oc % 64 == 0)) { + const int max_nb_oc_blocking = 2; + jcp.nb_oc_blocking = nstl::min(max_nb_oc_blocking, jcp.nb_oc); + for (; jcp.nb_oc_blocking > 1; jcp.nb_oc_blocking--) + if (jcp.nb_oc_blocking_thr_chunk % jcp.nb_oc_blocking == 0 + && is_oc_blocking_ok(jcp.nb_oc_blocking)) + break; + } + + if (jcp.is_resrc_depthwise) + jcp.ur_w = (jcp.max_regs_ur - jcp.kw + jcp.stride_w) + / (jcp.nb_ch_blocking + jcp.stride_w); + else + jcp.ur_w + = jcp.max_regs_ur / (jcp.is_depthwise ? jcp.nb_ch_blocking + : jcp.nb_oc_blocking + 1); + if (jcp.ow < jcp.ur_w) + jcp.ur_w = jcp.ow; + jcp.ur_w_tail = jcp.ow % jcp.ur_w; + + jcp.ow_block = jcp.ow; + int base_work_amount = jcp.mb * jcp.nb_ch * jcp.oh + * (jcp.nb_oc / jcp.nb_oc_blocking_thr_chunk); + float best_thr_eff + = (float)base_work_amount / rnd_up(base_work_amount, nthreads); + int max_nb_ow = div_up(jcp.ow, 2 * jcp.ur_w); + for (int nb_ow = 1; nb_ow <= max_nb_ow; nb_ow++) { + int ow_block + = nstl::min(rnd_up(div_up(jcp.ow, nb_ow), jcp.ur_w), jcp.ow); + if (ow_block < jcp.nb_oc_blocking_thr_chunk * jcp.oc_block + && best_thr_eff > 0.8f) + break; + if (div_up(jcp.ow, ow_block) != nb_ow) + continue; + auto work_amount = base_work_amount * nb_ow; + float thr_eff = (float)work_amount / rnd_up(work_amount, nthreads); + if (ow_block >= 2 * jcp.ur_w && thr_eff > 1.1f * best_thr_eff) { + jcp.ow_block = ow_block; + best_thr_eff = thr_eff; + } + if (best_thr_eff > 0.9f) + break; + } + jcp.nb_ow = div_up(jcp.ow, jcp.ow_block); + + bool args_ok = true + && jcp.oc % jcp.oc_block == 0 + && jcp.l_pad <= jcp.ur_w + && IMPLICATION(!jcp.is_1stconv, jcp.ic % jcp.ic_block == 0); + if (!args_ok) + return status::unimplemented; + + int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) + - (jcp.iw + jcp.l_pad - 1)); + if (r_pad_no_tail > jcp.ur_w) + return status::unimplemented; + + pick_loop_order(jcp, nthreads); + + jcp.nb_ic_L2 = jcp.nb_ic; + + const auto &oscales = attr.output_scales_; + jcp.is_oc_scale = oscales.mask_ == 1 << 1; + + assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0)); + + jcp.wei_adj_scale = + (weights_d.extra().flags | memory_extra_flags::scale_adjust) + ? weights_d.extra().scale_adjust : 1.f; + + return status::success; +} + +void jit_avx512_core_x8s8s32x_fwd_kernel::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp, + const primitive_attr_t &attr) { + if (jcp.signed_input && jcp.ver != ver_vnni) { + dim_t count = nstl::max(attr.output_scales_.count_, (dim_t)jcp.ic_block); + scratchpad.book(key_conv_adjusted_scales, sizeof(float) * count); + } +} + +template struct _jit_avx512_core_x8s8s32x_fwd_kernel; +template struct _jit_avx512_core_x8s8s32x_fwd_kernel; +template struct _jit_avx512_core_x8s8s32x_fwd_kernel; +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp new file mode 100644 index 0000000000..d8a05ad53e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp @@ -0,0 +1,239 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_CONV_KERNEL_HPP +#define CPU_JIT_AVX512_CORE_X8S8S32X_CONV_KERNEL_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct _jit_avx512_core_x8s8s32x_fwd_kernel : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_core_x8s8s32x_conv_fwd_ker_t) + + enum { STATE_FIRST_DST_LOAD = 0x1U }; + + _jit_avx512_core_x8s8s32x_fwd_kernel(jit_conv_conf_t ajcp, + const primitive_attr_t &attr) : jcp(ajcp), attr_(attr), + eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32( + this, jcp.eltwise); + + generate(); + jit_ker_ = (void (*)(jit_conv_call_s *))getCode(); + } + + ~_jit_avx512_core_x8s8s32x_fwd_kernel() { + delete eltwise_injector_; + } + + jit_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker_)(jit_conv_call_s *); + +private: + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + enum { + typesize = sizeof(float), + ker_reg_base_idx = 28, + ker_dw_reg_base_idx = 30, + }; + typedef enum { + no_last_block, + last_ic_block, + last_sp_block, + } ic_block_t; + + /* data regs */ + const Xbyak::Reg64 reg_ptr_scales = rax; + const Xbyak::Reg64 reg_inp = r8; + const Xbyak::Reg64 reg_ker = r9; + const Xbyak::Reg64 reg_out = r10; + const Xbyak::Reg64 aux_reg_inp = r11; + const Xbyak::Reg64 reg_ptr_sum_scale = r11; + const Xbyak::Reg64 aux_reg_ker = r12; + const Xbyak::Reg64 reg_compensation = r14; + /* counter regs */ + const Xbyak::Reg64 reg_bias_alpha = abi_not_param1; + const Xbyak::Reg64 reg_oi = rbx; + const Xbyak::Reg64 reg_bias = rdx; + const Xbyak::Reg64 reg_oc_blocks = rsi; + const Xbyak::Reg64 reg_owb = aux_reg_ker; + const Xbyak::Reg64 reg_scratch = reg_compensation; + const Xbyak::Reg64 reg_kj = reg_ptr_scales; + const Xbyak::Reg64 reg_overflow = reg_ptr_scales; + const Xbyak::Reg64 reg_icb = reg_bias; + + const Xbyak::Opmask ktail_mask = Xbyak::Opmask(2); + const Xbyak::Opmask kblend_mask = Xbyak::Opmask(3); + + const Vmm vmm_wei = Vmm(31); + /* used during bias section of store_output */ + const Vmm vmm_comp = Vmm(30); // only for signed input + const Vmm vmm_bias = Vmm(31); + /* used during post_op sum section of store_output */ + const Vmm vmm_prev_dst = Vmm(31); + /* used during write-out section of store_output */ + const Vmm vmm_zero = Vmm(31); + + /* used in compute_ker (but set during prepare_output) */ + const Vmm vmm_shift = vmm_comp; // only for signed input + /* used in compute_ker (but only for pre-VNNI machines) */ + const Vmm vmm_tmp = Vmm(28); // not used for depthwise + const Vmm vmm_one = Vmm(29); // set at start of kernel, not used for depthwise. + + /* registers use only for depthwise + groups are always blocked by 16(padded if needed), + hence use only Zmm registers */ + const Xbyak::Zmm zmm_wei = Xbyak::Zmm(31); + Xbyak::Zmm zmm_tmp; + Xbyak::Zmm zmm_src; + Xbyak::Zmm zmm_shifted_zero; + Xbyak::Zmm zmm_permute; + + Vmm vmm_out(int i_ur, int i_oc) { + int idx = i_ur + i_oc * jcp.ur_w; + assert(idx < (jcp.is_depthwise + ? ker_dw_reg_base_idx : ker_reg_base_idx)); + return Vmm(idx); + } + Xbyak::Zmm zmm_out(int i_ur, int i_oc) { + int idx = i_ur + i_oc * jcp.ur_w; + assert(idx < (jcp.is_depthwise + ? ker_dw_reg_base_idx : ker_reg_base_idx)); + return Xbyak::Zmm(idx); + } + Vmm vmm_inp(int i_ic, int nb_x_blocking) { + int idx = i_ic + nb_x_blocking * jcp.ur_w; + assert(idx < 31); + return Vmm(idx); + } + Xbyak::Zmm zmm_inp(int i_ic, int nb_x_blocking) { + int idx = i_ic + nb_x_blocking * jcp.ur_w; + assert(idx < 31); + return Xbyak::Zmm(idx); + } + Vmm vmm_bias_alpha() { + int nb_c_block = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking; + return Vmm(nb_c_block * jcp.ur_w); + } + Xbyak::Xmm xmm_bias_alpha() { + int nb_c_block = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking; + return Xbyak::Xmm(nb_c_block * jcp.ur_w); + } + int get_ow_start(int ki, int pad_l) { + return nstl::max(0, + utils::div_up(pad_l - ki * (jcp.dilate_w + 1), jcp.stride_w)); + } + int get_ow_end(int ur_w, int ki, int pad_r) { + return ur_w - nstl::max(0, utils::div_up(pad_r + - (jcp.kw - 1 - ki) + * (jcp.dilate_w + 1), + jcp.stride_w)); + } + + bool maybe_eltwise(int position); + void prepare_output(int ur_w); + void store_output(int ur_w, bool last_oc_block_flag); + void compute_ker_dw( + int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag, bool h_padded); + void compute_ker(int ur_w, int pad_l, int pad_r, + ic_block_t last_ic_block_flag, bool h_padded = false); + void compute_eltwise(int ur_w); + void kh_loop(int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag); + void icb_loop( + int ur_w, int pad_l, int pad_r, bool is_last_spatial_block); + void generate(); + void cvt2ps(data_type_t type_in, Vmm ymm_in, const Xbyak::Operand &op, + bool mask_flag); + const Vmm vmm_mask(const Vmm vmm_in, bool mask_flag, bool store = false); +}; + +struct jit_avx512_core_x8s8s32x_fwd_kernel { + + jit_avx512_core_x8s8s32x_fwd_kernel(jit_conv_conf_t ajcp, + const primitive_attr_t &attr) : + jit_ker(nullptr), + zmm_kernel_(nullptr), + ymm_kernel_(nullptr), + xmm_kernel_(nullptr) { + int ch_block = ajcp.is_depthwise ? ajcp.ch_block : ajcp.ic_block; + switch (ch_block) { + case 16: + zmm_kernel_ = + new _jit_avx512_core_x8s8s32x_fwd_kernel( + ajcp, attr); + jit_ker = zmm_kernel_->jit_ker_; + return; + case 8: + ymm_kernel_ = + new _jit_avx512_core_x8s8s32x_fwd_kernel( + ajcp, attr); + jit_ker = ymm_kernel_->jit_ker_; + return; + case 4: + xmm_kernel_ = + new _jit_avx512_core_x8s8s32x_fwd_kernel( + ajcp, attr); + jit_ker = xmm_kernel_->jit_ker_; + return; + default: + assert(!"invalid channel blocking"); + } + } + + ~jit_avx512_core_x8s8s32x_fwd_kernel() { + delete xmm_kernel_; + delete ymm_kernel_; + delete zmm_kernel_; + } + + static bool post_ops_ok(jit_conv_conf_t &jcp, + const primitive_attr_t &attr); + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, + memory_desc_t &src_pd, + memory_desc_t &weights_pd, + memory_desc_t &dst_pd, + memory_desc_t &bias_pd, + const primitive_attr_t &attr, + int nthreads); + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp, const primitive_attr_t &attr); + + void (*jit_ker)(jit_conv_call_s *); + _jit_avx512_core_x8s8s32x_fwd_kernel *zmm_kernel_; + _jit_avx512_core_x8s8s32x_fwd_kernel *ymm_kernel_; + _jit_avx512_core_x8s8s32x_fwd_kernel *xmm_kernel_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp new file mode 100644 index 0000000000..cdbf333d5e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp @@ -0,0 +1,423 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_avx512_core_x8s8s32x_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +using namespace nstl; + +using jit_conv_ker_t = void (*)(jit_conv_call_s *); + +#define wht_blk_off(d, g, ...) \ + (pd()->with_groups() \ + ? (d).blk_off((g), __VA_ARGS__) \ + : (d).blk_off(__VA_ARGS__)) + +template +void jit_avx512_core_x8s8s32x_convolution_fwd_t::execute_forward_1d(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const size_t bia_dt_size = pd()->with_bias() + ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0; + + const auto &jcp = pd()->jcp_; + assert(jcp.nb_oc % jcp.nb_oc_blocking == 0); + assert(jcp.nb_ch % jcp.nb_ch_blocking == 0); + + const float *oscales = pd()->attr()->output_scales_.scales_; + if (jcp.signed_input && jcp.ver != ver_vnni) { + auto local_scales = scratchpad(ctx).template get( + key_conv_adjusted_scales); + size_t count = pd()->attr()->output_scales_.count_; + float factor = 1.f / pd()->jcp_.wei_adj_scale; + if (count == 1) { + utils::array_set(local_scales, oscales[0] * factor, 16); + } else { + for (size_t c = 0; c < count; c++) + local_scales[c] = oscales[c] * factor; + } + oscales = local_scales; + } + + size_t offset = weights_d.size() - weights_d.additional_buffer_size(); + auto w = const_cast(weights); + int32_t* compensation = (jcp.signed_input) + ? reinterpret_cast(&w[offset]) : 0; + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking; + int nb_groups = jcp.nb_ch / jcp.nb_ch_blocking; + int group_block = jcp.ch_block; + int work_amount = jcp.mb * nb_groups * oc_chunks * jcp.nb_ow; + + parallel(0, [&](const int ithr, const int nthr) { + + int start{ 0 }, end{ 0 }; + balance211(work_amount, nthr, ithr, start, end); + + auto p = jit_conv_call_s(); + + int n{ 0 }, gg{ 0 }, occ{ 0 }, owb{ 0 }; + switch (jcp.loop_order) { + case loop_cwgn: + nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow, gg, + nb_groups, n, jcp.mb); + break; + case loop_gncw: + nd_iterator_init(start, gg, nb_groups, n, jcp.mb, occ, oc_chunks, + owb, jcp.nb_ow); + break; + case loop_ngcw: + nd_iterator_init(start, n, jcp.mb, gg, nb_groups, occ, oc_chunks, + owb, jcp.nb_ow); + break; + case loop_nwcg: + nd_iterator_init(start, n, jcp.mb, owb, jcp.nb_ow, occ, oc_chunks, + gg, nb_groups); + break; + default: assert(!"unsupported loop order"); + } + while (start < end) { + int ocb = occ * jcp.nb_oc_blocking; + int gb = gg * jcp.nb_ch_blocking; + int g = gb * group_block; + int g_oc = (g * jcp.nb_oc + ocb) * jcp.oc_block; + int g_ic = g * jcp.nb_ic * jcp.ic_block; + int ow_s = owb * jcp.ow_block; + int iw_s = ow_s * jcp.stride_w; + + p.bias = bias ? bias + (bias_d.blk_off(g_oc) * bia_dt_size) : 0; + p.compensation = (jcp.signed_input) ? compensation + g_oc : 0; + p.dst = dst + dst_d.blk_off(n, g_oc, ow_s); + p.src = src + src_d.blk_off(n, g_ic, iw_s); + p.filt = weights + wht_blk_off(weights_d, gb, ocb, 0); + p.scales = &oscales[jcp.is_oc_scale * g_oc]; + p.oc_blocks = jcp.is_depthwise ? gb : ocb; + p.kh_padding = jcp.kh; + p.t_overflow = 0; + p.b_overflow = 0; + p.owb = owb; + + kernel_->jit_ker(&p); + + ++start; + switch (jcp.loop_order) { + case loop_cwgn: + nd_iterator_step(occ, oc_chunks, owb, jcp.nb_ow, gg, nb_groups, + n, jcp.mb); + break; + case loop_gncw: + nd_iterator_step(gg, nb_groups, n, jcp.mb, occ, oc_chunks, owb, + jcp.nb_ow); + break; + case loop_ngcw: + nd_iterator_step(n, jcp.mb, gg, nb_groups, occ, oc_chunks, owb, + jcp.nb_ow); + break; + case loop_nwcg: + nd_iterator_step(n, jcp.mb, owb, jcp.nb_ow, occ, oc_chunks, gg, + nb_groups); + break; + default: assert(!"unsupported loop order"); + } + } + }); +} + +template +void jit_avx512_core_x8s8s32x_convolution_fwd_t::execute_forward_2d(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const size_t bia_dt_size = pd()->with_bias() + ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0; + + const auto &jcp = pd()->jcp_; + assert(jcp.ch_block == 1); + assert(jcp.nb_ch_blocking == 1); + assert(jcp.nb_oc % jcp.nb_oc_blocking == 0); + assert(jcp.nb_ch % jcp.nb_ch_blocking == 0); + + const float *oscales = pd()->attr()->output_scales_.scales_; + if (jcp.signed_input && jcp.ver != ver_vnni) { + auto local_scales = scratchpad(ctx).template get( + key_conv_adjusted_scales); + size_t count = pd()->attr()->output_scales_.count_; + float factor = 1.f / pd()->jcp_.wei_adj_scale; + if (count == 1) { + utils::array_set(local_scales, oscales[0] * factor, 16); + } else { + for (size_t c = 0; c < count; c++) + local_scales[c] = oscales[c] * factor; + } + oscales = local_scales; + } + + size_t offset = weights_d.size() - weights_d.additional_buffer_size(); + auto w = const_cast(weights); + int32_t* compensation = (jcp.signed_input) + ? reinterpret_cast(&w[offset]) : 0; + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking_thr_chunk; + int nb_groups = jcp.nb_ch; + int work_amount = jcp.mb * nb_groups * oc_chunks * jcp.oh * jcp.nb_ow; + + parallel(0, [&](const int ithr, const int nthr) { + + int start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + auto p = jit_conv_call_s(); + + size_t src_h_stride = src_d.blk_off(0, 0, 1); + size_t dst_h_stride = dst_d.blk_off(0, 0, 1); + size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1); + + int n{ 0 }, g{ 0 }, occ{ 0 }, oh_s{ 0 }, owb{ 0 }; + switch (jcp.loop_order) { + case loop_cwgn: + nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow, g, + nb_groups, n, jcp.mb, oh_s, jcp.oh); + break; + case loop_ngcw: + nd_iterator_init(start, n, jcp.mb, g, nb_groups, occ, oc_chunks, + owb, jcp.nb_ow, oh_s, jcp.oh); + break; + case loop_nhwcg: + nd_iterator_init(start, n, jcp.mb, oh_s, jcp.oh, owb, jcp.nb_ow, + occ, oc_chunks, g, nb_groups); + break; + default: assert(!"unsupported loop order"); + } + while (start < end) { + for (int occ1 = 0; occ1 < jcp.nb_oc_blocking_thr_chunk; + occ1 += jcp.nb_oc_blocking) { + int ocb = occ * jcp.nb_oc_blocking_thr_chunk + occ1; + int g_oc = (g * jcp.nb_oc + ocb) * jcp.oc_block; + + int g_ic = g * jcp.nb_ic * jcp.ic_block; + + int work_rem = end - start; + int ih_s = -jcp.t_pad + oh_s * jcp.stride_h; + int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem; + if (jcp.loop_order == loop_nhwcg) + oh_e = oh_s + 1; // step instead + int ow_s = owb * jcp.ow_block; + int iw_s = ow_s * jcp.stride_w; + + auto bias_w = bias + ? bias + (bias_d.blk_off(g_oc) * bia_dt_size) + : 0; + int32_t *compensation_w = (jcp.signed_input) + ? compensation + g_oc : 0; + + auto dst_w = dst + dst_d.blk_off(n, g_oc, oh_s, ow_s); + auto src_w = src + src_d.blk_off(n, g_ic, ih_s, iw_s); + auto wht_w = weights + wht_blk_off(weights_d, g, ocb, 0); + + auto scales = &oscales[jcp.is_oc_scale * g_oc]; + + for (int oj = oh_s, ij = ih_s; oj < oh_e; + ++oj, ij += jcp.stride_h) { + int dilate_h = jcp.dilate_h + 1; + int i_t_overflow = nstl::min(jcp.kh, + div_up(max(0, -ij), dilate_h)); + int i_b_overflow = nstl::min(jcp.kh, div_up( + max(0, ij - jcp.ih + (jcp.kh - 1) * dilate_h + 1), + dilate_h)); + int kh_padding = nstl::max(0, + jcp.kh - i_t_overflow - i_b_overflow); + + size_t wei_stride = (!jcp.signed_input) + ? i_t_overflow * wht_h_stride : 0; + p.src = src_w + i_t_overflow * dilate_h * src_h_stride; + p.dst = dst_w; + p.filt = wht_w + wei_stride; + p.bias = bias_w; + p.compensation = compensation_w; + p.oc_blocks = ocb; + p.kh_padding = kh_padding; + p.scales = scales; + p.t_overflow = i_t_overflow; + p.b_overflow = i_b_overflow; + p.owb = owb; + + kernel_->jit_ker(&p); + src_w += src_h_stride * jcp.stride_h; + dst_w += dst_h_stride; + } + } + switch (jcp.loop_order) { + case loop_cwgn: + nd_iterator_jump(start, end, occ, oc_chunks, owb, jcp.nb_ow, g, + nb_groups, n, jcp.mb, oh_s, jcp.oh); + break; + case loop_ngcw: + nd_iterator_jump(start, end, n, jcp.mb, g, nb_groups, occ, + oc_chunks, owb, jcp.nb_ow, oh_s, jcp.oh); + break; + case loop_nhwcg: + ++start; + nd_iterator_step(n, jcp.mb, oh_s, jcp.oh, owb, jcp.nb_ow, occ, + oc_chunks, g, nb_groups); + break; + default: assert(!"unsupported loop order"); + } + } + }); +} + +template +void jit_avx512_core_x8s8s32x_convolution_fwd_t::execute_forward_2d_dw(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const size_t bia_dt_size = pd()->with_bias() + ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0; + + const auto &jcp = pd()->jcp_; + assert(jcp.ic_block == 1); + assert(jcp.oc_block == 1); + assert(jcp.nb_ic == 1); + assert(jcp.nb_oc == 1); + assert(jcp.nb_oc_blocking == 1); + assert(jcp.nb_ch % jcp.nb_ch_blocking == 0); + + const float *oscales = pd()->attr()->output_scales_.scales_; + if (jcp.signed_input && jcp.ver != ver_vnni) { + auto local_scales = scratchpad(ctx).template get( + key_conv_adjusted_scales); + size_t count = pd()->attr()->output_scales_.count_; + float factor = 1.f / pd()->jcp_.wei_adj_scale; + if (count == 1) { + utils::array_set(local_scales, oscales[0] * factor, 16); + } else { + for (size_t c = 0; c < count; c++) + local_scales[c] = oscales[c] * factor; + } + oscales = local_scales; + } + + size_t offset = weights_d.size() - weights_d.additional_buffer_size(); + auto w = const_cast(weights); + int32_t* compensation = (jcp.signed_input) + ? reinterpret_cast(&w[offset]) : 0; + int nb_groups = jcp.nb_ch / jcp.nb_ch_blocking; + int group_block = jcp.ch_block; + + parallel_nd(jcp.mb, jcp.oh, jcp.nb_ow, nb_groups, + [&](int n, int oh_s, int owb, int gg) { + + auto p = jit_conv_call_s(); + + size_t src_h_stride = src_d.blk_off(0, 0, 1); + size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1); + + int gb = gg * jcp.nb_ch_blocking; + int g = gb * group_block; + + int ih_s = -jcp.t_pad + oh_s * jcp.stride_h; + int ow_s = owb * jcp.ow_block; + int iw_s = ow_s * jcp.stride_w; + + auto bias_w = bias ? bias + (bias_d.blk_off(g) * bia_dt_size) : 0; + int32_t *compensation_w = jcp.signed_input ? compensation + g : 0; + + auto dst_w = dst + dst_d.blk_off(n, g, oh_s, ow_s); + auto src_w = src + src_d.blk_off(n, g, ih_s, iw_s); + auto wht_w = weights + wht_blk_off(weights_d, gb, 0); + + auto scales = &oscales[jcp.is_oc_scale * g]; + + int dilate_h = jcp.dilate_h + 1; + int i_t_overflow = nstl::min(jcp.kh, div_up(max(0, -ih_s), dilate_h)); + int i_b_overflow = nstl::min(jcp.kh, + div_up(max(0, ih_s - jcp.ih + (jcp.kh - 1) * dilate_h + 1), + dilate_h)); + int kh_padding = nstl::max(0, jcp.kh - i_t_overflow - i_b_overflow); + + size_t wei_stride = jcp.signed_input ? 0 : i_t_overflow * wht_h_stride; + p.src = src_w + i_t_overflow * dilate_h * src_h_stride; + p.dst = dst_w; + p.filt = wht_w + wei_stride; + p.bias = bias_w; + p.compensation = compensation_w; + p.oc_blocks = gb; + p.kh_padding = kh_padding; + p.scales = scales; + p.t_overflow = i_t_overflow; + p.b_overflow = i_b_overflow; + p.owb = owb; + + kernel_->jit_ker(&p); + }); +} + +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::s8, data_type::u8>; +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::u8, data_type::u8>; +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::s8, data_type::s8>; +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::u8, data_type::s8>; +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::s8, data_type::s32>; +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::u8, data_type::s32>; +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::s8, data_type::f32>; +template struct jit_avx512_core_x8s8s32x_convolution_fwd_t< + data_type::u8, data_type::f32>; +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp new file mode 100644 index 0000000000..203ebdf942 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp @@ -0,0 +1,115 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_CONVOLUTION_HPP +#define CPU_JIT_AVX512_CORE_X8S8S32X_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_avx512_core_x8s8s32x_conv_kernel.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_avx512_core_x8s8s32x_convolution_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_int8:", avx512_core, ""), + jit_avx512_core_x8s8s32x_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, data_type::s8, data_type::undef, + dst_type, data_type::s32) + && IMPLICATION(with_bias(), utils::one_of(bias_md_.data_type, + data_type::f32, data_type::s32, data_type::s8, + data_type::u8)) + && !has_zero_dim_memory(); + if (!ok) return status::unimplemented; + + status_t status = jit_avx512_core_x8s8s32x_fwd_kernel::init_conf( + jcp_, *desc(), src_md_, weights_md_, dst_md_, bias_md_, + *attr(), mkldnn_get_max_threads()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_core_x8s8s32x_fwd_kernel::init_scratchpad(scratchpad, + jcp_, *attr()); + + return status; + } + + jit_conv_conf_t jcp_; + }; + + jit_avx512_core_x8s8s32x_convolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + { + kernel_ = new jit_avx512_core_x8s8s32x_fwd_kernel(pd()->jcp_, + *pd()->attr()); + } + + ~jit_avx512_core_x8s8s32x_convolution_fwd_t() { delete kernel_; } + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override + { + const auto &_pd = pd(); + if (_pd->ndims() == 3) + execute_forward_1d(ctx); + else if (_pd->jcp_.is_depthwise) + execute_forward_2d_dw(ctx); + else + execute_forward_2d(ctx); + return status::success; + } + +private: + void execute_forward_1d(const exec_ctx_t &ctx) const; + void execute_forward_2d(const exec_ctx_t &ctx) const; + void execute_forward_2d_dw(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_avx512_core_x8s8s32x_fwd_kernel *kernel_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp new file mode 100644 index 0000000000..142af1f541 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp @@ -0,0 +1,1034 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_avx512_core_x8s8s32x_deconvolution.hpp" + +#define GET_OFF(field) offsetof(jit_deconv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; +using namespace Xbyak; + +using namespace nstl; + +#define wht_blk_off(d, g, ...) \ + (pd()->with_groups() ? (d).blk_off((g), __VA_ARGS__) : \ + (d).blk_off(__VA_ARGS__)) + +status_t jit_avx512_core_x8s8s32x_deconv_fwd_kernel::init_conf( + jit_conv_conf_t &jcp, const deconvolution_desc_t &cd, + memory_desc_t &src_md, memory_desc_t &weights_md, + memory_desc_t &dst_md, const bool with_bias, + memory_desc_t &bias_md, const primitive_attr_t &attr) { + const memory_desc_wrapper src_d(&src_md); + const memory_desc_wrapper dst_d(&dst_md); + const memory_desc_wrapper weights_d(&weights_md); + const memory_desc_wrapper bias_d(&bias_md); + + if (!(mayiuse(avx512_core) + && one_of(src_d.data_type(), data_type::u8, data_type::s8) + && weights_d.data_type() == data_type::s8 + && one_of(dst_d.data_type(), data_type::f32, data_type::s32, + data_type::s8, data_type::u8))) + return status::unimplemented; + + jcp = zero(); + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + jcp.signed_input = src_d.data_type() == data_type::s8; + const int ndims = jcp.ndims = dst_d.ndims(); + const bool is_1d = ndims == 3; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + jcp.oc_without_padding = dst_d.dims()[1] / jcp.ngroups; + jcp.ic_without_padding = src_d.dims()[1] / jcp.ngroups; + jcp.is_depthwise = true && with_groups + && utils::everyone_is(1, jcp.ic_without_padding, + jcp.oc_without_padding); + + /* TODO: future work, on hold until depthwise specialized kernel is + * implemented. */ + if (jcp.is_depthwise && jcp.signed_input) + return status::unimplemented; + + format_tag_t dat_tag = utils::pick(ndims - 3, + format_tag::nwc, format_tag::nhwc); + + if (src_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(src_md, dat_tag)); + jcp.src_tag = dat_tag; + } else { + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + } + if (jcp.src_tag != dat_tag) + return status::unimplemented; + + if (dst_d.format_kind() == format_kind::any) { + CHECK(memory_desc_init_by_tag(dst_md, dat_tag)); + jcp.dst_tag = dat_tag; + } else { + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + } + if (jcp.dst_tag != dat_tag) + return status::unimplemented; + + auto set_or_check_wei_format = [&]() { + using namespace format_tag; + + format_tag_t wei_tag = is_1d + ? (jcp.is_depthwise + ? Goiw16g : (with_groups ? gOIw4i16o4i : OIw4i16o4i)) + : (jcp.is_depthwise + ? Goihw16g : (with_groups ? gOIhw4i16o4i : OIhw4i16o4i)); + + memory_desc_t want_wei_md = weights_md; + memory_desc_init_by_tag(want_wei_md, wei_tag); + if (jcp.signed_input && !jcp.is_depthwise) { + want_wei_md.extra.flags = 0 + | memory_extra_flags::compensation_conv_s8s8 + | memory_extra_flags::scale_adjust; + want_wei_md.extra.compensation_mask = (1 << 0) + + (with_groups && !jcp.is_depthwise ? (1 << 1) : 0); + want_wei_md.extra.scale_adjust = + mayiuse(avx512_core_vnni) ? 1.f : 0.5f; + } + + if (weights_md.format_kind == format_kind::any) { + weights_md = want_wei_md; + return true; + } + + return weights_md == want_wei_md; + }; + + if (!set_or_check_wei_format()) + return status::unimplemented; + + jcp.with_bias = with_bias; + if (jcp.with_bias) { + if (bias_d.format_kind() == format_kind::any) + CHECK(memory_desc_init_by_tag(bias_md, format_tag::x)); + } + + jcp.prop_kind = cd.prop_kind; + jcp.mb = src_d.dims()[0]; + jcp.ih = is_1d ? 1 : src_d.dims()[ndims - 2]; + jcp.iw = src_d.dims()[ndims - 1]; + jcp.oh = is_1d ? 1 : dst_d.dims()[ndims - 2]; + jcp.ow = dst_d.dims()[ndims - 1]; + jcp.kh = is_1d ? 1 : weights_d.dims()[with_groups + ndims - 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + jcp.t_pad = is_1d ? 0 : cd.padding[0][ndims - 4]; + jcp.l_pad = cd.padding[0][ndims - 3]; + jcp.stride_h = is_1d ? 1 : cd.strides[ndims - 4]; + jcp.stride_w = cd.strides[ndims - 3]; + + if (jcp.is_depthwise) { + jcp.ch_block = 16; + jcp.oc_block = 1; + jcp.ic_block = 1; + } else { + jcp.ch_block = 1; + jcp.oc_block = 16; + jcp.ic_block = 16; + + if (jcp.ngroups == 1) { + jcp.oc = utils::rnd_up(jcp.oc_without_padding, jcp.oc_block); + jcp.ic = utils::rnd_up(jcp.ic_without_padding, jcp.ic_block); + } + if (jcp.ic % jcp.ic_block != 0) + return status::unimplemented; + } + + jcp.dilate_h = is_1d ? 0 : cd.dilates[ndims - 4]; + jcp.dilate_w = cd.dilates[ndims - 3]; + + if (!IMPLICATION(jcp.dilate_h, jcp.stride_h == 1) + || !IMPLICATION(jcp.dilate_w, jcp.stride_w == 1)) + return status::unimplemented; + + /* padding: bottom and right */ + jcp.b_pad = (jcp.ih - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1) + - (jcp.oh + jcp.t_pad - 1); + jcp.r_pad = (jcp.iw - 1) * jcp.stride_w + (jcp.kw - 1) * (jcp.dilate_w + 1) + - (jcp.ow + jcp.l_pad - 1); + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + + jcp.ver = ver_avx512_core; + if (mayiuse(avx512_core_vnni)) + jcp.ver = ver_vnni; + const auto &oscales = attr.output_scales_; + jcp.is_oc_scale = oscales.mask_ == 1 << 1; + + assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0)); + + jcp.dst_dt = dst_d.data_type(); + jcp.bia_dt = jcp.with_bias ? bias_d.data_type() : data_type::undef; + jcp.typesize_bia + = jcp.with_bias ? types::data_type_size(bias_d.data_type()) : 0; + jcp.typesize_in = types::data_type_size(src_d.data_type()); + jcp.typesize_out = types::data_type_size(dst_d.data_type()); + + jcp.nb_ch = div_up(jcp.ngroups, jcp.ch_block); + jcp.nb_oc = jcp.oc / jcp.oc_block; + jcp.nb_ic = jcp.ic / jcp.ic_block; + + /* kernel blocking params */ + const int regs = jcp.ver == ver_vnni ? 30 : 28; + jcp.nb_oc_blocking = nstl::min(4, jcp.nb_oc); + for (; jcp.nb_oc_blocking > 1; jcp.nb_oc_blocking--) + if (jcp.nb_oc % jcp.nb_oc_blocking == 0 + && jcp.l_pad <= regs / (jcp.nb_oc_blocking + 1)) + break; + + jcp.ur_w = regs / (jcp.nb_oc_blocking + 1); + int l_overflow = max( + 0, ((jcp.kw - 1) * (jcp.dilate_w + 1) - jcp.l_pad) / jcp.stride_w); + + if (jcp.ow < jcp.ur_w) { + jcp.ur_w = jcp.ow; + jcp.ur_w_tail = 0; + } else { + for (; jcp.ur_w >= 1; jcp.ur_w--) { + /* ur_w should be multiple of stride_w in order + to simplify logic for get_ow_start and get_ow_end */ + bool is_multiple_of_stride = jcp.ur_w % jcp.stride_w == 0; + + /* boundary conditions: + These conditions ensure all elements close to boundary + are computed in a single call of compute loop */ + bool left_boundary_covered = jcp.ur_w >= l_overflow * jcp.stride_w; + jcp.ur_w_tail = jcp.ow % jcp.ur_w; + int r_overflow_no_tail + = max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1) + - max(0, jcp.r_pad) - jcp.ur_w_tail) + / jcp.stride_w); + bool right_boundary_covered + = jcp.ur_w >= r_overflow_no_tail * jcp.stride_w; + + if (is_multiple_of_stride && left_boundary_covered + && right_boundary_covered) + break; + else if (jcp.ur_w == 1) + /* The boundary conditions above are also important + to maintain simplicity of calls to icb_loop, + if those conditions are not satisfied, + then special cases will need to be added + to use correct l_overflow/r_overflow values + when different iterations of compute loop + work on the locations close to boundary. + So to keep code simple, return unimplemented + for extreme case when a good ur_w cannot be found. + */ + return status::unimplemented; + } + } + + jcp.wei_adj_scale = + (weights_d.extra().flags | memory_extra_flags::scale_adjust) + ? weights_d.extra().scale_adjust : 1.f; + + jcp.loop_order = jcp.ngroups > 1 ? loop_ngc : loop_cgn; + return status::success; +} + +bool jit_avx512_core_x8s8s32x_deconv_fwd_kernel::maybe_eltwise(int position) { + using namespace primitive_kind; + const auto &p = attr_.post_ops_; + + if (position == 0) { + /* eltwise before sum */ + return p.contain(eltwise, 0); + } else if (position == 1) { + /* eltwise after sum */ + return p.contain(sum, 0) && p.contain(eltwise, 1); + } + return false; +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::compute_eltwise(int ur_w) { + int nb_oc_block + = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking; + eltwise_injector_->compute_vector_range(0, nb_oc_block * ur_w); +} + +bool jit_avx512_core_x8s8s32x_deconv_fwd_kernel::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) { + using namespace primitive_kind; + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + + switch (p.len_) { + case 0: return true; + case 1: return is_eltwise(0) || p.contain(sum, 0); + case 2: + return (p.contain(sum, 0) && is_eltwise(1)) + || (p.contain(sum, 1) && is_eltwise(0)); + default: return false; + } + + return false; +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp, + const primitive_attr_t &attr) { + if (jcp.signed_input && jcp.ver != ver_vnni) { + dim_t count = nstl::max(attr.output_scales_.count_, 16); + scratchpad.book(key_conv_adjusted_scales, sizeof(float) * count); + } +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::compute_ker(int ur_w, + int l_overflow, int r_overflow, ker_block_t last_ic_block_flag, + bool h_padded) { + + const int ch_block_all = jcp.ch_block * jcp.ic_block * jcp.oc_block; + const int ur_w_stride = jcp.signed_input ? 1 : jcp.stride_w; + + auto src_offset = [=](int oj, int icb, int ki) { + return jcp.typesize_in + * (((oj + jcp.l_pad - ki * (jcp.dilate_w + 1)) / jcp.stride_w) + * jcp.ngroups * jcp.ic_without_padding + + icb * 4); + }; + + auto kernel_offset = [=](int ocb, int icb, int ki) { + return jcp.typesize_in + * (ocb * jcp.nb_ic * jcp.kh * jcp.kw * ch_block_all + + icb * jcp.oc_block * jcp.ic_block / 4 + + ki * ch_block_all); + }; + + auto compute = [=](zmm_t vreg_acc, zmm_t vreg_wei, zmm_t vreg_src) { + if (jcp.ver == ver_vnni) { + vpdpbusd(vreg_acc, vreg_src, vreg_wei); + } else if (jcp.is_depthwise) { + vpmulld(zmm_tmp, vreg_src, vreg_wei); + vpaddd(vreg_acc, vreg_acc, zmm_tmp); + } else { + vpmaddubsw(zmm_tmp, vreg_src, vreg_wei); + vpmaddwd(zmm_tmp, zmm_tmp, zmm_one); + vpaddd(vreg_acc, vreg_acc, zmm_tmp); + } + }; + + for (int ki = 0; ki < jcp.kw; ki++) { + + int jj_start = get_ow_start(ki, l_overflow); + int jj_end = get_ow_end(ur_w, ki, r_overflow); + + int _start = (jcp.signed_input) ? 0 : jj_start; + int _end = (jcp.signed_input) ? ur_w : jj_end; + + int tail_size = jcp.ic_without_padding % 4; + int n_ic_blocks = jcp.is_depthwise ? + 1 : + (last_ic_block_flag & ~no_last_block ? + div_up(jcp.ic_without_padding % jcp.ic_block, + 4) : + jcp.ic_block / 4); + + for (int icb1 = 0; icb1 < n_ic_blocks; icb1++) { + if (h_padded == true) { + /* fill padded area with shifted values */ + Zmm inp = zmm_inp(0, jcp.nb_oc_blocking); + vpxord(inp, inp, inp); + vpsubb(inp, inp, zmm_shift); + } else { + + for (int jj = _start; jj < _end; jj += ur_w_stride) { + + int aux_src_off = src_offset(jj, icb1, ki); + + if (jj >= jj_start && jj < jj_end + && ((jj + jcp.l_pad - ki) % jcp.stride_w == 0)) { + if (jcp.is_depthwise) { + vpmovzxbd(zmm_inp(jj, jcp.nb_oc_blocking), + EVEX_compress_addr( + aux_reg_src, aux_src_off)); + } else if ((last_ic_block_flag & last_sp_block) + && tail_size != 0 && icb1 == n_ic_blocks - 1) { + xmm_t xmm_tmp = xmm_t( + zmm_inp(jj, jcp.nb_oc_blocking).getIdx()); + for (int r = 0; r < tail_size; ++r) + vpinsrb(xmm_tmp, xmm_tmp, + ptr[aux_reg_src + aux_src_off + r], r); + vpbroadcastd( + zmm_inp(jj, jcp.nb_oc_blocking), xmm_tmp); + } else { + vpbroadcastd(zmm_inp(jj, jcp.nb_oc_blocking), + EVEX_compress_addr( + aux_reg_src, aux_src_off)); + } + if (jcp.signed_input) + vpsubb(zmm_inp(jj, jcp.nb_oc_blocking), + zmm_inp(jj, jcp.nb_oc_blocking), zmm_shift); + } else { + /* fill padded area with shifted values */ + if (jcp.signed_input) { + Zmm inp = zmm_inp(jj, jcp.nb_oc_blocking); + vpxord(inp, inp, inp); + vpsubb(inp, inp, zmm_shift); + } + } + } + } + for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) { + int aux_filt_off = kernel_offset(ocb, icb1, ki); + + if (_end - _start > 0) { + if (jcp.is_depthwise) + vpmovsxbd(zmm_wei, + EVEX_compress_addr(aux_reg_filt, aux_filt_off)); + else + vmovups(zmm_wei, + EVEX_compress_addr(aux_reg_filt, aux_filt_off)); + } + for (int jj = _start; jj < _end; jj += ur_w_stride) { + Zmm inp = (h_padded == true) ? + zmm_inp(0, jcp.nb_oc_blocking) : + zmm_inp(jj, jcp.nb_oc_blocking); + compute(zmm_out(jj, ocb), zmm_wei, inp); + } + } + } + } +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::kh_loop(int ur_w, + int l_overflow, int r_overflow, ker_block_t last_ic_block_flag) { + + int ch_block_all = jcp.ch_block * jcp.ic_block * jcp.oc_block; + int shift_src_ih = jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw + * jcp.ngroups * jcp.ic_without_padding; + const int stride_h = jcp.signed_input ? 1 : jcp.stride_h; + int shift_filt_kh = jcp.typesize_in * jcp.kw * ch_block_all * stride_h; + + Label kh_loop_label, skip_kh_loop; + Label t_overflow_label, no_t_overflow_label, b_overflow_label, + no_b_overflow_label; + + mov(aux_reg_src, reg_src); + mov(aux_reg_filt, reg_filt); + + if (jcp.signed_input && jcp.ndims > 3) { + /* Weights are transposed, so first compute 'bottom' padding. */ + mov(reg_overflow, ptr[param1 + GET_OFF(b_overflow)]); + cmp(reg_overflow, 0); + je(no_b_overflow_label, T_NEAR); + L(b_overflow_label); { + compute_ker(ur_w, 0, 0, last_ic_block_flag, true); + + add(aux_reg_filt, shift_filt_kh); + dec(reg_overflow); + cmp(reg_overflow, 0); + jg(b_overflow_label, T_NEAR); + } + L(no_b_overflow_label); + } + + mov(reg_kh, ptr[param1 + GET_OFF(kh_padding)]); + + if (jcp.signed_input || ((!jcp.signed_input) + && ((min(jcp.t_pad, jcp.b_pad) < 0) + || ((jcp.kh - 1) * (jcp.dilate_h + 1) + < nstl::max(jcp.t_pad, jcp.b_pad))))) { + cmp(reg_kh, 0); + je(skip_kh_loop, T_NEAR); + } + + L(kh_loop_label); { + compute_ker(ur_w, l_overflow, r_overflow, last_ic_block_flag, false); + sub(aux_reg_src, shift_src_ih); + add(aux_reg_filt, shift_filt_kh); + dec(reg_kh); + + /* Insert weight compensation in stride 'holes' */ + if (jcp.signed_input && jcp.stride_h > 1) { + Label kh_comp_loop; + + cmp(reg_kh, 0); + je(skip_kh_loop, T_NEAR); + mov(reg_comp_strides, jcp.stride_h - 1); + L(kh_comp_loop); + { + compute_ker( + ur_w, 0, 0, last_ic_block_flag, true); + add(aux_reg_filt, shift_filt_kh); + dec(reg_comp_strides); + cmp(reg_comp_strides, 0); + jg(kh_comp_loop, T_NEAR); + } + } + cmp(reg_kh, 0); + jg(kh_loop_label, T_NEAR); + } + L(skip_kh_loop); + if (jcp.signed_input && jcp.ndims > 3) { + mov(reg_overflow, ptr[param1 + GET_OFF(t_overflow)]); + cmp(reg_overflow, 0); + je(no_t_overflow_label, T_NEAR); + L(t_overflow_label); { + compute_ker(ur_w, 0, 0, last_ic_block_flag, true); + + add(aux_reg_filt, shift_filt_kh); + dec(reg_overflow); + cmp(reg_overflow, 0); + jg(t_overflow_label, T_NEAR); + } + L(no_t_overflow_label); + } +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::prepare_output(int ur_w) { + for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) { + for (int ur = 0; ur < ur_w; ur++) { + zmm_t zmm = zmm_out(ur, ocb); + vpxord(zmm, zmm, zmm); + } + } + if (jcp.signed_input) { + xor_(reg_scratch, reg_scratch); + Reg8 _t8 = reg_scratch.cvt8(); + mov(_t8, (int8_t)-128); + vpbroadcastb(zmm_shift, _t8); + } +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::cvt2ps( + data_type_t type_in, zmm_t zmm_in, const Operand &op, bool mask_flag) { + zmm_t zmm = mask_flag ? zmm_in | ktail_mask | T_z : zmm_in; + switch (type_in) { + case data_type::f32: + case data_type::s32: vmovups(zmm, op); break; + case data_type::s8: vpmovsxbd(zmm, op); break; + case data_type::u8: vpmovzxbd(zmm, op); break; + default: assert(!"unsupported data type"); + } + if (type_in != data_type::f32) + vcvtdq2ps(zmm_in, zmm_in); +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::store_output( + int ur_w, bool last_oc_block) { + mov(reg_bias, ptr[param1 + GET_OFF(bias)]); + mov(reg_ptr_scales, ptr[param1 + GET_OFF(scales)]); + + if (jcp.signed_input) + mov(reg_compensation, ptr[param1 + GET_OFF(compensation)]); + + const auto &p = attr_.post_ops_; + const int sum_idx = p.find(primitive_kind::sum); + const float *p_sum_scale + = (sum_idx != -1) ? &p.entry_[sum_idx].sum.scale : nullptr; + if (p_sum_scale && *p_sum_scale != 1.f) + mov(reg_ptr_sum_scale, (size_t)p_sum_scale); + + if (jcp.with_bias && jcp.signed_input && jcp.ver != ver_vnni) { + mov(reg_bias_alpha, float2int(jcp.wei_adj_scale)); + vmovq(xmm_bias_alpha(), reg_bias_alpha); + vbroadcastss(zmm_bias_alpha(), xmm_bias_alpha()); + } + + for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) { + const bool mask_flag = last_oc_block && ocb == jcp.nb_oc_blocking - 1; + int scale_offset + = jcp.is_oc_scale * (sizeof(float) * ocb * jcp.oc_block); + + auto zmm_bias = zmm_tmp; + if (jcp.with_bias) { + int bias_offset = jcp.typesize_bia * ocb * jcp.oc_block; + auto bias_addr = EVEX_compress_addr(reg_bias, bias_offset); + cvt2ps(jcp.bia_dt, zmm_bias, bias_addr, mask_flag); + if (jcp.signed_input && jcp.ver != ver_vnni) + vmulps(zmm_bias, zmm_bias, zmm_bias_alpha()); + } + if (jcp.signed_input) { + int comp_offset = sizeof(int32_t) * ocb * jcp.oc_block; + auto comp_addr = EVEX_compress_addr(reg_compensation, comp_offset); + cvt2ps(data_type::s32, zmm_comp, comp_addr, mask_flag); + } + + for (int ur = 0; ur < ur_w; ur++) { + zmm_t zmm = zmm_out(ur, ocb); + vcvtdq2ps(zmm, zmm); + if (jcp.signed_input) + vaddps(zmm, zmm, zmm_comp); + if (jcp.with_bias) + vaddps(zmm, zmm, zmm_bias); + zmm_t mask_zmm = mask_flag ? zmm | ktail_mask | T_z : zmm; + vmulps(mask_zmm, zmm, + EVEX_compress_addr(reg_ptr_scales, scale_offset)); + } + } + if (maybe_eltwise(0)) + compute_eltwise(ur_w); + if (p_sum_scale) { // post_op: sum + for (int k = 0; k < jcp.nb_oc_blocking; k++) { + const bool mask_flag + = last_oc_block == 1 && k == jcp.nb_oc_blocking - 1; + for (int j = 0; j < ur_w; j++) { + int aux_output_offset + = jcp.typesize_out + * (k * jcp.oc_block + + j * jcp.oc_without_padding * jcp.ngroups); + auto addr = EVEX_compress_addr(reg_dst, aux_output_offset); + Zmm zmm = zmm_out(j, k); + cvt2ps(jcp.dst_dt, zmm_prev_dst, addr, mask_flag); + if (*p_sum_scale == 1.f) + vaddps(zmm, zmm_prev_dst); + else + vfmadd231ps(zmm, zmm_prev_dst, zword_b[reg_ptr_sum_scale]); + } + } + } + if (maybe_eltwise(1)) + compute_eltwise(ur_w); + + for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) { + const bool mask_flag = last_oc_block && ocb == jcp.nb_oc_blocking - 1; + for (int ur = 0; ur < ur_w; ur++) { + zmm_t zmm = zmm_out(ur, ocb); + if (jcp.dst_dt == data_type::u8) { + vpxord(zmm_zero, zmm_zero, zmm_zero); + vmaxps(zmm, zmm_zero, zmm); + } + if (jcp.dst_dt != data_type::f32) + vcvtps2dq(zmm, zmm); + } + for (int ur = 0; ur < ur_w; ur++) { + int aux_dst_off = jcp.typesize_out + * (ur * jcp.ngroups * jcp.oc_without_padding + + ocb * jcp.oc_block); + auto addr = EVEX_compress_addr(reg_dst, aux_dst_off); + + zmm_t zmm = zmm_out(ur, ocb); + zmm_t r_zmm = mask_flag ? zmm | ktail_mask : zmm; + switch (jcp.dst_dt) { + case data_type::f32: + case data_type::s32: vmovups(addr, r_zmm); break; + case data_type::s8: vpmovsdb(addr, r_zmm); break; + case data_type::u8: vpmovusdb(addr, r_zmm); break; + default: assert(!"unknown dst_dt"); + } + } + } +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::icb_loop( + int ur_w, int l_overflow, int r_overflow, bool is_last_sp_block) { + + int shift_src_icb = jcp.typesize_in * jcp.ic_block; + int shift_filt_icb + = jcp.typesize_in * jcp.kh * jcp.kw * jcp.ic_block * jcp.oc_block; + + prepare_output(ur_w); + + Label skip_icb_loop, icb_loop_label; + + mov(reg_icb, jcp.nb_ic); + L(icb_loop_label); { + + if (jcp.ic_without_padding != jcp.ic) { + Label common_ker, end_ker; + cmp(reg_icb, 1); + jg(common_ker, T_NEAR); + + kh_loop(ur_w, l_overflow, r_overflow, + is_last_sp_block ? last_sp_block : last_ic_block); + jmp(end_ker, T_NEAR); + + L(common_ker); + kh_loop(ur_w, l_overflow, r_overflow, no_last_block); + + L(end_ker); + } else { + kh_loop(ur_w, l_overflow, r_overflow, no_last_block); + } + + add(reg_src, shift_src_icb); + add(reg_filt, shift_filt_icb); + dec(reg_icb); + cmp(reg_icb, 0); + jg(icb_loop_label, T_NEAR); + } + + /* come-back pointers */ + sub(reg_src, jcp.nb_ic * shift_src_icb); + sub(reg_filt, jcp.nb_ic * shift_filt_icb); + L(skip_icb_loop); + + if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) { + Label common_store, end_store; + mov(reg_oc_blocks, ptr[param1 + GET_OFF(oc_blocks)]); + if (jcp.is_depthwise) + cmp(reg_oc_blocks, jcp.nb_ch - 1); + else + cmp(reg_oc_blocks, jcp.nb_oc - jcp.nb_oc_blocking); + jne(common_store, T_NEAR); + + store_output(ur_w, true); + jmp(end_store, T_NEAR); + + L(common_store); + store_output(ur_w, false); + + L(end_store); + + } else { + store_output(ur_w, false); + } +} + +void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::generate() { + preamble(); + + xor_(reg_scratch, reg_scratch); + Reg16 _t = reg_scratch.cvt16(); + mov(_t, 0x1); + vpbroadcastw(zmm_one, _t); + + if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) { + int tail_size = jcp.is_depthwise ? + jcp.ngroups % jcp.ch_block : + jcp.oc_without_padding % jcp.oc_block; + int mask = (1 << tail_size) - 1; + Reg32 regw_tmp = reg_nur_w.cvt32(); + mov(regw_tmp, mask); + kmovw(ktail_mask, regw_tmp); + } + + mov(reg_src, ptr[param1 + GET_OFF(src)]); + mov(reg_filt, ptr[param1 + GET_OFF(filt)]); + mov(reg_dst, ptr[param1 + GET_OFF(dst)]); + + int dst_shift = jcp.typesize_out * jcp.ur_w * jcp.ngroups + * jcp.oc_without_padding; + int src_shift = jcp.typesize_in * (jcp.ur_w / jcp.stride_w) * jcp.ngroups + * jcp.ic_without_padding; + + int l_overflow = max( + 0, ((jcp.kw - 1) * (jcp.dilate_w + 1) - jcp.l_pad) / jcp.stride_w); + int r_overflow + = max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1) - max(0, jcp.r_pad)) + / jcp.stride_w); + + int r_overflow1 + = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1) + - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail) + / jcp.stride_w); + int nur_w = jcp.ow / jcp.ur_w; + if (r_overflow1 > 0) + nur_w--; + + if (jcp.ur_w == jcp.ow) { + icb_loop(jcp.ur_w, l_overflow, r_overflow, true); + } else if (nur_w == 0) { + icb_loop(jcp.ur_w, l_overflow, r_overflow1, jcp.ur_w_tail == 0); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + if (jcp.ur_w_tail != 0) + icb_loop(jcp.ur_w_tail, 0, r_overflow, true); + } else { + xor_(reg_nur_w, reg_nur_w); + if (l_overflow > 0) { + icb_loop(jcp.ur_w, l_overflow, 0, false); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + inc(reg_nur_w); + } + if ((l_overflow <= 0 && nur_w > 0) || (l_overflow > 0 && nur_w > 1)) { + Label ow_loop_label; + L(ow_loop_label); + { + icb_loop(jcp.ur_w, 0, 0, false); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + inc(reg_nur_w); + cmp(reg_nur_w, nur_w); + jl(ow_loop_label, T_NEAR); + } + } + if (r_overflow1 > 0) { + icb_loop(jcp.ur_w, 0, r_overflow1, jcp.ur_w_tail == 0); + add(reg_src, src_shift); + add(reg_dst, dst_shift); + } + if (jcp.ur_w_tail != 0) { + icb_loop(jcp.ur_w_tail, 0, r_overflow, true); + } + } + postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +template +void _jit_avx512_core_x8s8s32x_deconvolution_fwd_t::execute_forward_1d(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + auto &jcp = kernel_->jcp; + + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking; + int nb_groups = jcp.nb_ch; + + const float *oscales = pd()->attr()->output_scales_.scales_; + if (jcp.signed_input && jcp.ver != ver_vnni) { + auto local_scales + = scratchpad(ctx).template get(key_conv_adjusted_scales); + size_t count = pd()->attr()->output_scales_.count_; + float factor = 1.f / pd()->jcp_.wei_adj_scale; + if (count == 1) { + utils::array_set(local_scales, oscales[0] * factor, 16); + } else { + for (size_t c = 0; c < count; c++) + local_scales[c] = oscales[c] * factor; + } + oscales = local_scales; + } + size_t offset = (size_t)jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw; + auto w = const_cast(weights); + int32_t *compensation + = (jcp.signed_input) ? reinterpret_cast(&w[offset]) : 0; + + parallel(0, [&](const int ithr, const int nthr) { + int start{ 0 }, end{ 0 }; + int work_amount = jcp.mb * nb_groups * oc_chunks; + balance211(work_amount, nthr, ithr, start, end); + + auto p = jit_deconv_call_s(); + + int n{ 0 }, g{ 0 }, occ{ 0 }; + if (jcp.loop_order == loop_ngc) + nd_iterator_init(start, n, jcp.mb, g, nb_groups, occ, oc_chunks); + else if (jcp.loop_order == loop_cgn) + nd_iterator_init(start, occ, oc_chunks, g, nb_groups, n, jcp.mb); + else + assert(!"unsupported loop order"); + while (start < end) { + + int ocb = occ * jcp.nb_oc_blocking; + int g_oc = (g * jcp.ch_block * jcp.nb_oc + ocb) * jcp.oc_block; + int g_ic = g * jcp.ch_block * jcp.ic; + + p.dst = dst + dst_d.blk_off(n, g_oc); + p.src = src + src_d.blk_off(n, g_ic); + p.filt = weights + wht_blk_off(weights_d, g, ocb, 0); + p.bias = jcp.with_bias ? + bias + (bias_d.blk_off(g_oc) * jcp.typesize_bia) : + 0; + p.compensation = (jcp.signed_input) ? compensation + g_oc : 0; + p.scales = &oscales[jcp.is_oc_scale * g_oc]; + p.t_overflow = 0; + p.b_overflow = 0; + p.kh_padding = jcp.kh; + p.oc_blocks = jcp.is_depthwise ? g : ocb; + + kernel_->jit_ker(&p); + + ++start; + if (jcp.loop_order == loop_ngc) + nd_iterator_step(n, jcp.mb, g, nb_groups, occ, oc_chunks); + else if (jcp.loop_order == loop_cgn) + nd_iterator_step(occ, oc_chunks, g, nb_groups, n, jcp.mb); + else + assert(!"unsupported loop order"); + } + }); +} + +template +void _jit_avx512_core_x8s8s32x_deconvolution_fwd_t::execute_forward_2d(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + auto &jcp = kernel_->jcp; + + int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking; + int nb_groups = jcp.nb_ch; + + size_t src_h_stride = src_d.blk_off(0, 0, 1); + size_t dst_h_stride = dst_d.blk_off(0, 0, 1); + size_t wht_kh_stride = wht_blk_off(weights_d, 0, 0, 0, 1); + + const float *oscales = pd()->attr()->output_scales_.scales_; + if (jcp.signed_input && jcp.ver != ver_vnni) { + auto local_scales + = scratchpad(ctx).template get(key_conv_adjusted_scales); + size_t count = pd()->attr()->output_scales_.count_; + float factor = 1.f / pd()->jcp_.wei_adj_scale; + if (count == 1) { + utils::array_set(local_scales, oscales[0] * factor, 16); + } else { + for (size_t c = 0; c < count; c++) + local_scales[c] = oscales[c] * factor; + } + oscales = local_scales; + } + size_t offset = (size_t)jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw; + auto w = const_cast(weights); + int32_t *compensation + = (jcp.signed_input) ? reinterpret_cast(&w[offset]) : 0; + + parallel(0, [&](const int ithr, const int nthr) { + int start{ 0 }, end{ 0 }; + int work_amount = jcp.mb * nb_groups * oc_chunks * jcp.oh; + balance211(work_amount, nthr, ithr, start, end); + + auto p = jit_deconv_call_s(); + + /*loop order = cgn*/ + int n{ 0 }, g{ 0 }, occ{ 0 }, oh_s{ 0 }; + if (jcp.loop_order == loop_ngc) + nd_iterator_init(start, n, jcp.mb, g, nb_groups, occ, oc_chunks, + oh_s, jcp.oh); + else if (jcp.loop_order == loop_cgn) + nd_iterator_init(start, occ, oc_chunks, g, nb_groups, n, jcp.mb, + oh_s, jcp.oh); + else + assert(!"unsupported loop order"); + while (start < end) { + + int ocb = occ * jcp.nb_oc_blocking; + int g_oc = (g * jcp.ch_block * jcp.nb_oc + ocb) * jcp.oc_block; + int g_ic = g * jcp.ch_block * jcp.ic; + int work_rem = end - start; + int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem; + + auto dst_w = dst + dst_d.blk_off(n, g_oc); + auto src_w = src + src_d.blk_off(n, g_ic); + auto wht_w = weights + wht_blk_off(weights_d, g, ocb, 0); + auto bias_w = jcp.with_bias ? + bias + (bias_d.blk_off(g_oc) * jcp.typesize_bia) : + 0; + int32_t *compensation_w + = (jcp.signed_input) ? compensation + g_oc : 0; + + auto scales = &oscales[jcp.is_oc_scale * g_oc]; + for (int oj = oh_s; oj < oh_e; oj++) { + int ih_max = 0, kh_lo = 0, kh_len = 0; + if (jcp.dilate_h != 0 && jcp.stride_h == 1) { + /* dilation */ + int dilate_h = jcp.dilate_h + 1; + // Note: use div_up to account for "holes" in filter + int o_t_overflow = div_up( + max(0, (jcp.kh - 1) * dilate_h - oj - jcp.t_pad), + dilate_h); + int o_b_overflow + = div_up(max(0, (jcp.kh - 1) * dilate_h + 1 - jcp.oh + + oj - jcp.b_pad), + dilate_h); + kh_len = jcp.kh - o_t_overflow - o_b_overflow; + kh_lo = o_b_overflow; + ih_max = oj + jcp.t_pad - o_b_overflow * dilate_h; + } else { + int o_t_overflow = max( + 0, (jcp.kh - (oj + 1 + jcp.t_pad)) / jcp.stride_h); + int o_b_overflow + = max(0, ((oj + jcp.kh) - (jcp.oh + jcp.b_pad)) + / jcp.stride_h); + int overflow_kh_hi = jcp.kh - 1 + - abs(jcp.oh + jcp.b_pad - (oj + 1)) % jcp.stride_h; + int overflow_kh_lo = (oj + jcp.t_pad) % jcp.stride_h; + + kh_len = (overflow_kh_hi - overflow_kh_lo) / jcp.stride_h + + 1 - o_t_overflow - o_b_overflow; + kh_lo = overflow_kh_lo + o_b_overflow * jcp.stride_h; + ih_max = (oj + jcp.t_pad - kh_lo) / jcp.stride_h; + } + + int wei_stride + = (!jcp.signed_input) ? kh_lo * wht_kh_stride : 0; + p.src = src_w + ih_max * src_h_stride; + p.dst = dst_w + oj * dst_h_stride; + p.filt = wht_w + wei_stride; + p.bias = bias_w; + p.compensation = compensation_w; + p.t_overflow = max( + 0, jcp.kh - (kh_lo + max(0, kh_len - 1) * jcp.stride_h + + 1)); + p.b_overflow = kh_lo; + p.kh_padding = kh_len; + p.scales = scales; + p.oc_blocks = jcp.is_depthwise ? g : ocb; + kernel_->jit_ker(&p); + } + if (jcp.loop_order == loop_ngc) + nd_iterator_jump(start, end, n, jcp.mb, g, nb_groups, occ, + oc_chunks, oh_s, jcp.oh); + else if (jcp.loop_order == loop_cgn) + nd_iterator_jump(start, end, occ, oc_chunks, g, nb_groups, n, + jcp.mb, oh_s, jcp.oh); + else + assert(!"unsupported loop order"); + } + }); +} + +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t; +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp new file mode 100644 index 0000000000..901038fa48 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp @@ -0,0 +1,237 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX512_CORE_U8S8S32X_DECONVOLUTION_HPP +#define CPU_JIT_AVX512_CORE_U8S8S32X_DECONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "cpu_primitive.hpp" +#include "cpu_memory.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "nstl.hpp" + +#include "cpu_deconvolution_pd.hpp" +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +typedef enum { + no_last_block = 0x1U, + last_ic_block = 0x2U, + last_sp_block = 0x4U, +} ker_block_t; + +struct jit_avx512_core_x8s8s32x_deconv_fwd_kernel : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_x8s8s32x_deconv_fwd_ker_t); + + jit_avx512_core_x8s8s32x_deconv_fwd_kernel( + const jit_conv_conf_t &ajcp, const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32( + this, jcp.eltwise); + generate(); + jit_ker = (void (*)(jit_deconv_call_s *))getCode(); + } + + ~jit_avx512_core_x8s8s32x_deconv_fwd_kernel() { + delete eltwise_injector_; + } + + static bool post_ops_ok(jit_conv_conf_t &jcp, + const primitive_attr_t &attr); + + static status_t init_conf(jit_conv_conf_t &jcp, + const deconvolution_desc_t &cd, + memory_desc_t &src_md, + memory_desc_t &weights_md, + memory_desc_t &dst_md, + const bool with_bias, + memory_desc_t &bias_md, + const primitive_attr_t &attr); + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp, const primitive_attr_t &attr); + + const jit_conv_conf_t &jcp; + const primitive_attr_t &attr_; + void (*jit_ker)(jit_deconv_call_s *); +private: + jit_uni_eltwise_injector_f32 *eltwise_injector_; + using reg64_t = const Xbyak::Reg64; + using zmm_t = const Xbyak::Zmm; + using xmm_t = const Xbyak::Xmm; + + reg64_t reg_src = r8; + reg64_t reg_filt = r9; + reg64_t reg_dst = r10; + reg64_t param1 = abi_param1; + reg64_t reg_kh = abi_not_param1; + reg64_t reg_nur_w = rbx; + reg64_t reg_bias = rdx; + reg64_t reg_icb = reg_bias; + reg64_t reg_ptr_scales = rax; + reg64_t reg_oc_blocks = rsi; + + reg64_t aux_reg_src = r11; + reg64_t aux_reg_filt = r12; + + reg64_t reg_compensation = r14; + reg64_t reg_scratch = r14; + reg64_t reg_ptr_sum_scale = r11; + reg64_t reg_bias_alpha = abi_not_param1; + reg64_t reg_overflow = rax; + reg64_t reg_comp_strides = reg_overflow; + + Xbyak::Opmask ktail_mask = Xbyak::Opmask(2); + zmm_t zmm_tmp = zmm_t(28); + zmm_t zmm_one = zmm_t(29); + /* used during write-out section of store_output */ + zmm_t zmm_zero = zmm_t(31); + zmm_t zmm_wei = zmm_t(31); + + /* signed input */ + zmm_t zmm_shift = zmm_t(30); + zmm_t zmm_comp = zmm_t(30); + zmm_t zmm_bias = zmm_t(31); + zmm_t zmm_prev_dst = zmm_t(31); + + zmm_t zmm_out(int i_ur, int i_oc) { + int idx = i_ur * jcp.nb_oc_blocking + i_oc; + assert(idx < 31); + return zmm_t(idx); + } + zmm_t zmm_inp(int i_ic, int nb_x_blocking) { + int idx = i_ic + nb_x_blocking * jcp.ur_w; + assert(idx < 31); + return zmm_t(idx); + } + zmm_t zmm_bias_alpha() { + return zmm_t(jcp.nb_oc_blocking * jcp.ur_w); + } + xmm_t xmm_bias_alpha() { + return xmm_t(jcp.nb_oc_blocking * jcp.ur_w); + } + + int get_ow_start(int ki, int l_overflow) { + int res = (jcp.ow - 1 + jcp.r_pad) % jcp.stride_w + + l_overflow * jcp.stride_w + - (jcp.kw - 1 - ki) * (jcp.dilate_w + 1); + while (res < 0) + res += jcp.stride_w; + return res; + } + + int get_ow_end(int ur_w, int ki, int r_overflow) { + if (utils::one_of(ur_w, jcp.ow, jcp.ur_w_tail)) + ur_w += nstl::min(0, jcp.r_pad); // remove negative padding + int res = (ur_w - 1 + jcp.l_pad) % jcp.stride_w + + r_overflow * jcp.stride_w - ki * (jcp.dilate_w + 1); + while (res < 0) + res += jcp.stride_w; + return ur_w - res; + } + bool maybe_eltwise(int position); + void compute_eltwise(int ur_w); + void prepare_output(int ur_w); + void store_output(int ur_w, bool last_oc_block); + void compute_ker(int ur_w, int l_overflow, int r_overflow, + ker_block_t last_ic_block_flag, bool h_padded = false); + void kh_loop(int ur_w, int pad_l, int pad_r, ker_block_t last_ker_block); + void icb_loop(int ur_w, int pad_l, int pad_r, bool last_block); + void generate(); + void cvt2ps(data_type_t type_in, zmm_t zmm_in, const Xbyak::Operand &op, + bool mask_flag); +}; + +template +struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_deconvolution_fwd_pd_t { + using cpu_deconvolution_fwd_pd_t::cpu_deconvolution_fwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_deconvolution:", avx512_core, ""), + _jit_avx512_core_x8s8s32x_deconvolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && (desc()->alg_kind & alg_kind::deconvolution_direct) + && desc()->src_desc.data_type == src_type + && desc()->dst_desc.data_type == dst_type + && IMPLICATION(with_bias(), utils::one_of( + desc()->bias_desc.data_type, data_type::f32, + data_type::s32, data_type::s8, data_type::u8)) + && desc()->accum_data_type == data_type::s32; + if (!ok) return status::unimplemented; + + status_t status = jit_avx512_core_x8s8s32x_deconv_fwd_kernel:: + init_conf(jcp_, *desc(), src_md_, weights_md_, dst_md_, + with_bias(), bias_md_, *attr()); + + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_avx512_core_x8s8s32x_deconv_fwd_kernel::init_scratchpad(scratchpad, + jcp_, *attr()); + + return status::success; + } + + jit_conv_conf_t jcp_; + }; + + _jit_avx512_core_x8s8s32x_deconvolution_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + { + kernel_ = new jit_avx512_core_x8s8s32x_deconv_fwd_kernel(pd()->jcp_, + *pd()->attr()); + } + + ~_jit_avx512_core_x8s8s32x_deconvolution_fwd_t() { delete kernel_; } + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + if(pd()->ndims() == 3) + execute_forward_1d(ctx); + else + execute_forward_2d(ctx); + return status::success; + } + +private: + void execute_forward_1d(const exec_ctx_t &ctx) const; + void execute_forward_2d(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_avx512_core_x8s8s32x_deconv_fwd_kernel *kernel_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp new file mode 100644 index 0000000000..c09592d5c9 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp @@ -0,0 +1,773 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_AVX2_GENERATOR_HPP +#define CPU_JIT_AVX2_GENERATOR_HPP + +#include + +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_isa_traits.hpp" +#include "jit_utils/jit_utils.hpp" + +#if defined(_WIN32) && !defined(__GNUC__) +# define STRUCT_ALIGN(al, ...) __declspec(align(al)) __VA_ARGS__ +#else +# define STRUCT_ALIGN(al, ...) __VA_ARGS__ __attribute__((__aligned__(al))) +#endif + +#if defined(_WIN32) +# define OFFSET_SHADOWSPACE 0x28 +#endif + +#define DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_name) \ + const char *name() const override { return STRINGIFY(jit_name); } \ + const char *source_file() const override { return __FILE__; } + +namespace mkldnn { +namespace impl { +namespace cpu { + +// TODO: move this to jit_generator class? +namespace { + +typedef enum { + PAGE_4K = 4096, + PAGE_2M = 2097152, +} cpu_page_size_t; + +// TODO: move this somewhere else? Although this is only used by jit kernels +// (Roma) +static inline int float2int(float x) { + union { + float vfloat; + int vint; + } cvt; + cvt.vfloat = x; + return cvt.vint; +} + +// TODO: A GPR class that hides ABI details from the JIT kernels and allows +// numbering registers from 0 to 14 (x86_64) / 6 (x32) (gpr0, gpr1, ...) and +// stack register (sr). +// +// This will allow using syntax like this: +// +// param = gpr0; +// reg_input = gpr0; +// reg_output = gpr1; +// ... +// +// #ifndef XBYAK64 +// mov(param, ptr[sr]) +// #endif +// +// (Roma) + +#ifdef XBYAK64 +constexpr Xbyak::Operand::Code abi_save_gpr_regs[] = { + Xbyak::Operand::RBX, Xbyak::Operand::RBP, Xbyak::Operand::R12, + Xbyak::Operand::R13, Xbyak::Operand::R14, Xbyak::Operand::R15, +#ifdef _WIN32 + Xbyak::Operand::RDI, Xbyak::Operand::RSI, +#endif +}; + +#ifdef _WIN32 +static const Xbyak::Reg64 abi_param1(Xbyak::Operand::RCX), + abi_param2(Xbyak::Operand::RDX), + abi_param3(Xbyak::Operand::R8), + abi_param4(Xbyak::Operand::R9), + abi_not_param1(Xbyak::Operand::RDI); +#else +static const Xbyak::Reg64 abi_param1(Xbyak::Operand::RDI), + abi_param2(Xbyak::Operand::RSI), + abi_param3(Xbyak::Operand::RDX), + abi_param4(Xbyak::Operand::RCX), + abi_param5(Xbyak::Operand::R8), + abi_param6(Xbyak::Operand::R9), + abi_not_param1(Xbyak::Operand::RCX); +#endif +#endif + +inline unsigned int get_cache_size(int level, bool per_core = true){ + unsigned int l = level - 1; + // Currently, if XByak is not able to fetch the cache topology + // we default to 32KB of L1, 512KB of L2 and 1MB of L3 per core. + if (cpu.getDataCacheLevels() == 0){ + const int L1_cache_per_core = 32000; + const int L2_cache_per_core = 512000; + const int L3_cache_per_core = 1024000; + int num_cores = per_core ? 1 : mkldnn_get_max_threads(); + switch(l){ + case(0): return L1_cache_per_core * num_cores; + case(1): return L2_cache_per_core * num_cores; + case(2): return L3_cache_per_core * num_cores; + default: return 0; + } + } + if (l < cpu.getDataCacheLevels()) { + return cpu.getDataCacheSize(l) + / (per_core ? cpu.getCoresSharingDataCache(l) : 1); + } else + return 0; +} + +} + +class jit_generator : public Xbyak::CodeGenerator +{ +private: + const size_t xmm_len = 16; +#ifdef _WIN32 + const size_t xmm_to_preserve_start = 6; + const size_t xmm_to_preserve = 10; +#else + const size_t xmm_to_preserve_start = 0; + const size_t xmm_to_preserve = 0; +#endif + + const size_t num_abi_save_gpr_regs + = sizeof(abi_save_gpr_regs) / sizeof(abi_save_gpr_regs[0]); + + const size_t size_of_abi_save_regs + = num_abi_save_gpr_regs * rax.getBit() / 8 + + xmm_to_preserve * xmm_len; + +public: + enum { + _cmp_eq_oq = 0u, + _cmp_lt_os = 1u, + _cmp_le_os = 2u, + _cmp_neq_uq = 4u, + _cmp_nlt_us = 5u, + _cmp_nle_us = 6u, + + _op_floor = 1u, + _op_mxcsr = 4u, + }; + + Xbyak::Reg64 param1 = abi_param1; + const int EVEX_max_8b_offt = 0x200; + const Xbyak::Reg64 reg_EVEX_max_8b_offt = rbp; + + inline size_t get_size_of_abi_save_regs() { + return size_of_abi_save_regs; + } + + void preamble() { + if (xmm_to_preserve) { + sub(rsp, xmm_to_preserve * xmm_len); + for (size_t i = 0; i < xmm_to_preserve; ++i) + movdqu(ptr[rsp + i * xmm_len], Xbyak::Xmm(xmm_to_preserve_start + i)); + } + for (size_t i = 0; i < num_abi_save_gpr_regs; ++i) + push(Xbyak::Reg64(abi_save_gpr_regs[i])); + if (mayiuse(avx512_common)) { + mov(reg_EVEX_max_8b_offt, 2 * EVEX_max_8b_offt); + } + } + + void mic_prefetcht0(Xbyak::Address a) { + if (mayiuse(avx512_mic)) + prefetcht0(a); + } + + void mic_prefetcht1(Xbyak::Address a) { + if (mayiuse(avx512_mic)) + prefetcht1(a); + } + + void mic_prefetcht2(Xbyak::Address a) { + if (mayiuse(avx512_mic)) + prefetcht2(a); + } + + void uni_vzeroupper() { + if (mayiuse(avx) && !mayiuse(avx512_mic)) + vzeroupper(); + } + + void postamble() { + for (size_t i = 0; i < num_abi_save_gpr_regs; ++i) + pop(Xbyak::Reg64(abi_save_gpr_regs[num_abi_save_gpr_regs - 1 - i])); + if (xmm_to_preserve) { + for (size_t i = 0; i < xmm_to_preserve; ++i) + movdqu(Xbyak::Xmm(xmm_to_preserve_start + i), ptr[rsp + i * xmm_len]); + add(rsp, xmm_to_preserve * xmm_len); + } + uni_vzeroupper(); + ret(); + } + + template + Xbyak::Address EVEX_compress_addr(Xbyak::Reg64 base, + T raw_offt, bool bcast = false) + { + using Xbyak::Zmm; + using Xbyak::Reg64; + using Xbyak::Address; + using Xbyak::RegExp; + + assert(raw_offt <= INT_MAX); + auto offt = static_cast(raw_offt); + + int scale = 0; + + if (EVEX_max_8b_offt <= offt && offt < 3 * EVEX_max_8b_offt) { + offt = offt - 2 * EVEX_max_8b_offt; + scale = 1; + } else if (3 * EVEX_max_8b_offt <= offt && offt < 5 * EVEX_max_8b_offt) { + offt = offt - 4 * EVEX_max_8b_offt; + scale = 2; + } + + auto re = RegExp() + base + offt; + if (scale) + re = re + reg_EVEX_max_8b_offt * scale; + + if (bcast) + return zword_b [re]; + else + return zword [re]; + } + + Xbyak::Address make_safe_addr(const Xbyak::Reg64 ®_out, size_t offt, + const Xbyak::Reg64 &tmp_reg, bool bcast = false) { + if (offt > INT_MAX) { + mov(tmp_reg, offt); + return bcast ? ptr_b[reg_out + tmp_reg] : ptr[reg_out + tmp_reg]; + } else { + return bcast ? ptr_b[reg_out + offt] : ptr[reg_out + offt]; + } + } + + Xbyak::Address EVEX_compress_addr_safe(const Xbyak::Reg64 &base, + size_t raw_offt, const Xbyak::Reg64 ®_offt, bool bcast = false) { + if (raw_offt > INT_MAX) { + return make_safe_addr(base, raw_offt, reg_offt, bcast); + } else { + return EVEX_compress_addr(base, raw_offt, bcast); + } + } + + void safe_add(const Xbyak::Reg64 &base, size_t raw_offt, + const Xbyak::Reg64 ®_offt) { + if (raw_offt > INT_MAX) { + mov(reg_offt, raw_offt); + add(base, reg_offt); + } else { + add(base, raw_offt); + } + } + + void safe_sub(const Xbyak::Reg64 &base, size_t raw_offt, + const Xbyak::Reg64 ®_offt) { + if (raw_offt > INT_MAX) { + mov(reg_offt, raw_offt); + sub(base, reg_offt); + } else { + sub(base, raw_offt); + } + } + + // Disallow char-based labels completely + void L(const char *label) = delete; + void L(Xbyak::Label& label) { Xbyak::CodeGenerator::L(label); } + + void uni_vpxor(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + assert(x1.getIdx() == x2.getIdx()); + pxor(x2, op); + } + void uni_vpxor(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op) { + if (mayiuse(avx2)) { + vpxor(x1, x2, op); + } else { + vxorps(x1, x2, op); + } + } + void uni_vpxor(const Xbyak::Zmm &x1, const Xbyak::Zmm &x2, + const Xbyak::Operand &op) { + vpxord(x1, x2, op); + } + + void uni_vmovss(const Xbyak::Address& addr, const Xbyak::Xmm &x) { + movss(addr, x); + } + void uni_vmovss(const Xbyak::Address& addr, const Xbyak::Ymm &x) { + vmovss(addr, x); + } + void uni_vmovss(const Xbyak::Xmm &x, const Xbyak::Address& addr) { + movss(x, addr); + } + void uni_vmovss(const Xbyak::Ymm &x, const Xbyak::Address& addr) { + vmovss(x, addr); + } + + void uni_vmovsd(const Xbyak::Address& addr, const Xbyak::Xmm &x) { + movsd(addr, x); + } + void uni_vmovsd(const Xbyak::Address& addr, const Xbyak::Ymm &x) { + vmovsd(addr, x); + } + void uni_vmovsd(const Xbyak::Xmm &x, const Xbyak::Address& addr) { + movsd(x, addr); + } + void uni_vmovsd(const Xbyak::Ymm &x, const Xbyak::Address& addr) { + vmovsd(x, addr); + } + + void uni_vmovdqu(const Xbyak::Address &addr, const Xbyak::Xmm &x) { + movdqu(addr, x); + } + void uni_vmovdqu(const Xbyak::Address &addr, const Xbyak::Ymm &x) { + vmovdqu(addr, x); + } + void uni_vmovdqu(const Xbyak::Address &addr, const Xbyak::Zmm &x) { + vmovdqu32(addr, x); + } + + void uni_vmovdqu(const Xbyak::Xmm &x, const Xbyak::Address &addr) { + movdqu(x, addr); + } + void uni_vmovdqu(const Xbyak::Ymm &x, const Xbyak::Address &addr) { + vmovdqu(x, addr); + } + void uni_vmovdqu(const Xbyak::Zmm &x, const Xbyak::Address &addr) { + vmovdqu32(x, addr); + } + + void uni_vmovups(const Xbyak::Address &addr, const Xbyak::Xmm &x) { + movups(addr, x); + } + void uni_vmovups(const Xbyak::Address &addr, const Xbyak::Ymm &x) { + vmovups(addr, x); + } + + void uni_vmovups(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + movups(x, op); + } + void uni_vmovups(const Xbyak::Ymm &x, const Xbyak::Operand &op) { + vmovups(x, op); + } + + void uni_vmovntps(const Xbyak::Address &addr, const Xbyak::Xmm &x) { + movntps(addr, x); + } + void uni_vmovntps(const Xbyak::Address &addr, const Xbyak::Ymm &x) { + vmovntps(addr, x); + } + + void uni_vbroadcastss(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + movss(x, op); + shufps(x, x, 0x0); + } + void uni_vbroadcastss(const Xbyak::Ymm &x, const Xbyak::Operand &op) { + if (op.isMEM() || mayiuse(avx2)) { + vbroadcastss(x, op); + } else { + Xbyak::Xmm t(x.getIdx()); + if (t.getIdx() != op.getIdx()) movss(t, op); + vinsertf128(x, x, t, 1); + vshufps(x, x, x, 0); + } + } + + void uni_vpbroadcastd(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + movsd(x, op); + pshufd(x, x, 0x0); + } + void uni_vpbroadcastd(const Xbyak::Ymm &x, const Xbyak::Operand &op) { + if (mayiuse(avx2)) { + vpbroadcastd(x, op); + } else { + Xbyak::Xmm t(x.getIdx()); + if (t.getIdx() != op.getIdx()) movsd(t, op); + vinsertf128(x, x, t, 1); + vshufps(x, x, x, 0); + } + } + + void uni_vrcpss(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + rcpss(x, op); + } + void uni_vrcpss(const Xbyak::Ymm &x1, const Xbyak::Xmm &x2) { + Xbyak::Xmm x1_(x1.getIdx()); + Xbyak::Xmm x2_(x2.getIdx()); + vrcpss(x1_, x1_, x2_); + } + void uni_vrcpss(const Xbyak::Ymm &x, const Xbyak::Address &op) { + Xbyak::Xmm x_(x.getIdx()); + vrcpss(x_, x_, op); + } + + void uni_vrcpps(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + rcpps(x, op); + } + void uni_vrcpps(const Xbyak::Ymm &x, const Xbyak::Operand &op) { + vrcpps(x, op); + } + void uni_vrcpps(const Xbyak::Zmm &x, const Xbyak::Operand &op) { + vrcp14ps(x, op); + } + + void uni_vdivps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + assert(x.getIdx() == op1.getIdx()); + divps(x, op2); + } + void uni_vdivps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + vdivps(x, op1, op2); + } + + void uni_vdivps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2, const Xbyak::Xmm &buf) { + movups(buf, op1); + divps(buf, op2); + if (x.getIdx() != buf.getIdx()) { + movups(x, buf); + } + } + + void uni_vdivps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2, const Xbyak::Ymm &buf) { + vdivps(x, op1, op2); + } + + void uni_vaddps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + assert(x.getIdx() == op1.getIdx()); + addps(x, op2); + } + void uni_vaddps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + vaddps(x, op1, op2); + } + + void uni_vpsignd(const Xbyak::Xmm& x1, const Xbyak::Xmm& x2, + const Xbyak::Operand& op) { + assert(x1.getIdx() == x2.getIdx()); + psignd(x1, op); + } + void uni_vpsignd(const Xbyak::Ymm& x1, const Xbyak::Ymm& x2, + const Xbyak::Operand& op) { + vpsignd(x1, x2, op); + } + + void uni_vsubps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + assert(x.getIdx() == op1.getIdx()); + subps(x, op2); + } + void uni_vsubps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + vsubps(x, op1, op2); + } + + void uni_vsubps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2, const Xbyak::Xmm &buf) { + movups(buf, op1); + subps(buf, op2); + if (x.getIdx() != buf.getIdx()) { + movups(x, buf); + } + } + + void uni_vsubps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2, const Xbyak::Ymm &buf) { + vsubps(x, op1, op2); + } + + void uni_vmulps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + assert(x.getIdx() == op1.getIdx()); + mulps(x, op2); + } + void uni_vmulps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + vmulps(x, op1, op2); + } + + void uni_vfmadd213ps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + mulps(x1, x2); + addps(x1, op); + } + void uni_vfmadd213ps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op) { + vfmadd213ps(x1, x2, op); + } + + void uni_vfmadd231ps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + mulps(x2, op); + addps(x1, x2); + } + void uni_vfmadd231ps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op) { + vfmadd231ps(x1, x2, op); + } + + void uni_vfnmadd231ps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + mulps(x2, op); + subps(x1, x2); + } + + void uni_vfnmadd231ps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op) { + vfnmadd231ps(x1, x2, op); + } + + void uni_vsqrtps(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + sqrtps(x, op); + } + void uni_vsqrtps(const Xbyak::Ymm &x, const Xbyak::Operand &op) { + vsqrtps(x, op); + } + + void uni_vpaddd(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + assert(x1.getIdx() == x2.getIdx()); + paddd(x2, op); + } + void uni_vpaddd(const Xbyak::Ymm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + vpaddd(x1, x2, op); + } + + void uni_vandps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op = Xbyak::Operand()) { + assert(x1.getIdx() == x2.getIdx()); + andps(x1, op); + } + void uni_vandps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op = Xbyak::Operand()) { + if (!mayiuse(avx512_common) || x1.getBit() < 512) + vandps(x1, x2, op); + else + vpandd(x1, x2, op); + } + + void uni_vorps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op = Xbyak::Operand()) { + assert(x1.getIdx() == x2.getIdx()); + orps(x1, op); + } + void uni_vorps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op = Xbyak::Operand()) { + if (!mayiuse(avx512_common) || x1.getBit() < 512) + vorps(x1, x2, op); + else + vpord(x1, x2, op); + } + + void uni_vpslld(const Xbyak::Xmm &x, const Xbyak::Operand &op, + const int imm) { + assert(x.getIdx() == op.getIdx()); + pslld(x, imm); + } + void uni_vpslld(const Xbyak::Ymm &x, const Xbyak::Operand &op, + const int imm) { + vpslld(x, op, imm); + } + + void uni_vpsrld(const Xbyak::Xmm &x, const Xbyak::Operand &op, + const int imm) { + assert(x.getIdx() == op.getIdx()); + psrld(x, imm); + } + void uni_vpsrld(const Xbyak::Ymm &x, const Xbyak::Operand &op, + const int imm) { + vpsrld(x, op, imm); + } + + void uni_vmaxps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + assert(x.getIdx() == op1.getIdx()); + maxps(x, op2); + } + void uni_vmaxps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + vmaxps(x, op1, op2); + } + + void uni_vminps(const Xbyak::Xmm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + assert(x.getIdx() == op1.getIdx()); + minps(x, op2); + } + void uni_vminps(const Xbyak::Ymm &x, const Xbyak::Operand &op1, + const Xbyak::Operand &op2 = Xbyak::Operand()) { + vminps(x, op1, op2); + } + + void uni_vcmpgtps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + assert(x1.getIdx() == x2.getIdx()); + cmpps(x1, op, _cmp_nle_us); + } + + void uni_vcmpgtps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op) { + vcmpgtps(x1, x2, op); + } + + void uni_vcmpgeps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op) { + assert(x1.getIdx() == x2.getIdx()); + cmpps(x1, op, _cmp_nlt_us); + } + + void uni_vcmpgeps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op) { + vcmpps(x1, x2, op, _cmp_nlt_us); + } + + void uni_vtestps(const Xbyak::Xmm &x1, const Xbyak::Operand &op) { + ptest(x1, op); + } + + void uni_vtestps(const Xbyak::Ymm &x1, const Xbyak::Operand &op) { + assert(!(x1.isZMM() || op.isZMM())); + vtestps(x1, op); + } + + void uni_vblendvps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, + const Xbyak::Operand &op, const Xbyak::Xmm &msk) { + assert(x1.getIdx() == x2.getIdx()); + assert(msk.getIdx() == 0); + blendvps(x1, op); + } + void uni_vblendvps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, + const Xbyak::Operand &op, const Xbyak::Ymm &msk) { + vblendvps(x1, x2, op, msk); + } + + void uni_vroundps(const Xbyak::Xmm &x, const Xbyak::Operand &op, + const int imm) { + roundps(x, op, imm); + } + void uni_vroundps(const Xbyak::Ymm &x, const Xbyak::Operand &op, + const int imm) { + vroundps(x, op, imm); + } + + void uni_vcvtps2dq(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + cvtps2dq(x, op); + } + void uni_vcvtps2dq(const Xbyak::Ymm &x, const Xbyak::Operand &op) { + vcvtps2dq(x, op); + } + + void uni_vcvtdq2ps(const Xbyak::Xmm &x, const Xbyak::Operand &op) { + cvtdq2ps(x, op); + } + void uni_vcvtdq2ps(const Xbyak::Ymm &x, const Xbyak::Operand &op) { + vcvtdq2ps(x, op); + } + + void uni_vmovmskps(const Xbyak::Reg &x1, const Xbyak::Xmm &x2) { + movmskps(x1.cvt64(), x2); + } + void uni_vmovmskps(const Xbyak::Reg &x1, const Xbyak::Ymm &x2) { + vmovmskps(x1, x2); + } + + void uni_vpackssdw(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, const Xbyak::Operand &op){ + assert(x1.getIdx() == x1.getIdx()); + packssdw(x1, op); + } + void uni_vpackssdw(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, const Xbyak::Operand &op){ + vpackssdw(x1, x2, op); + } + + void uni_vpackuswb(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, const Xbyak::Operand &op){ + assert(x1.getIdx() == x1.getIdx()); + packuswb(x1, op); + } + void uni_vpackuswb(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, const Xbyak::Operand &op){ + vpackuswb(x1, x2, op); + } + + + void mul_by_const(const Xbyak::Reg &out, + const Xbyak::Reg64 &tmp, int value) { + // Generates a shift + add sequence for multiplicating contents of the + // out register by a known JIT-time value. Clobbers the tmp register. + // + // Pros compared to mul/imul: + // - does not require using known registers + // - not microcoded on Intel(R) Xeon Phi(TM) processors + // Still, there are probably a lot of cases when mul/imul is faster on + // Intel(R) Core(TM) processors. Not intended for critical path. + + // TODO: detect when overflow is emminent (Roma) + // TODO: detect when using mul/imul is a better option (Roma) + + int p = 0; // the current power of 2 + int old_p = 0; // the last seen power of 2 such that value[old_p] != 0 + + xor_(tmp, tmp); + while (value) { + if (value & 1) { + int shift = p - old_p; + if (shift) { + shl(out, shift); + old_p = p; + } + add(tmp, out); + } + value >>= 1; + p++; + } + mov(out, tmp); + } + +public: + jit_generator( + void *code_ptr = nullptr, + size_t code_size = 256 * 1024 + ) : Xbyak::CodeGenerator(code_size, code_ptr) + { + } + virtual ~jit_generator() {} + + virtual const char *name() const = 0; + virtual const char *source_file() const = 0; + + const Xbyak::uint8 *getCode() { + const Xbyak::uint8 *code = CodeGenerator::getCode(); + size_t code_size = getSize(); + jit_utils::register_jit_code(code, code_size, name(), source_file()); + return code; + } + + template const F getCode() { + return (const F)getCode(); + } +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp new file mode 100644 index 0000000000..56d7f592e2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp @@ -0,0 +1,481 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_PRIMITIVE_CONF_HPP +#define JIT_PRIMITIVE_CONF_HPP + +#include + +#include "common/primitive_attr.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +/* convolution */ +enum conv_version_t {ver_unused, ver_fma, ver_avx512_core, ver_4fma, ver_vnni}; +enum conv_loop_order_t {loop_cgn, loop_gnc, loop_ngc, loop_gncw, loop_cwgn, + loop_ngcw, loop_nhwcg, loop_nwcg}; +enum conv_1x1_loop_order_t {loop_rbl, loop_rlb, loop_lbr, loop_lrb, loop_blr, + loop_brl}; +enum conv_kernel_kind_t {embd_bcast, expl_bcast}; + +enum { + FLAG_MB_FIRST = 1 << 0, FLAG_MB_LAST = 1 << 1, + FLAG_OC_FIRST = 1 << 2, FLAG_OC_LAST = 1 << 3, + FLAG_IC_FIRST = 1 << 4, FLAG_IC_LAST = 1 << 5, + FLAG_SP_FIRST = 1 << 6, FLAG_SP_LAST = 1 << 7, + FLAG_REDUCE_FIRST = 1<<8, FLAG_REDUCE_LAST = 1<<9, + FLAG_ZERO_FILTER = 1 << 0, /* Controls whether the inner kernel skips + loading weights-data from memory; this + needs to happen on the first Group/16 + iteration. */ + FLAG_ZERO_BIAS = 1 << 1, /* Controls whether the inner kernel skip + loading bias data from memory */ + FLAG_COMPUTE_BIAS = 1 << 2, /* Controls bias computation during execution + pass */ +}; + +struct jit_conv_conf_t { + prop_kind_t prop_kind; + conv_version_t ver; + conv_loop_order_t loop_order; + + int simd_w; + int ndims; + int mb; + int ngroups, ic, oc, oc_without_padding, ic_without_padding; + int id, ih, iw, od, oh, ow; + int f_pad, l_pad, t_pad; + int back_pad, r_pad, b_pad; + int kd, kh, kw; + int stride_d, stride_h, stride_w; + int dilate_d, dilate_h, dilate_w; + format_tag_t src_tag, wei_tag, dst_tag; // temporary workaround + bool with_bias; + bool with_sum; + bool with_eltwise; + + post_ops_t::entry_t::eltwise_t eltwise; + + int nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b; + + int idp, ihp, iwp, ohp, owp; + int nb_ic, ic_block; + int nb_oc, oc_block; + int nb_ow, ow_block; + int nb_oc_blocking; /* used in jit kernels for nb_oc work bloking taking + into account vector registers distribution */ + int nb_oc_blocking_thr_chunk; /* used for distibution of nb_oc work + within threads */ + int nb_ic_blocking, nb_ic_blocking_max; // blocking of nb_ic work + int nb_ic_L2; + int h_blocking; + int nb_oc_L2; + int ur_h, ur_w; + int ur_w_tail; + bool is_1stconv; + int nonblk_group_off; + /* fma avx512_core */ + conv_kernel_kind_t kernel_kind; + /* 4fma */ + int tr_iw; + int tr_src_num_guard_elems; + /* 1st conv: 4fma */ + int tr_ld; + int kh_step; + /* 4vnni */ + int typesize_in; + int typesize_out; + int typesize_bia; + int typesize_acc; + /* avx512_u8s8u8 */ + int ic_nb1, ic_nb2; + int oc_nb1; + int ur_ow_max, ur_ow, ur_ow_tail; + int ur_ow_nsteps; + data_type_t bia_dt; + data_type_t dst_dt; + /* avx512: max possible value is nregs(32) - aux_regs(4) */ + int src_offsets[28]; + int src_count; + bool expl_bcast; + bool large_spatial; + int is_oc_scale; + int max_regs_ur; // maximum accumulation registers + // dw conv + int nb_ch, ch_block, nb_ch_blocking; + bool is_depthwise, is_fast_depthwise, is_resrc_depthwise; + int aligned_threads; + // large spatial + int oh_blk_size; + // s8s8 convolution + bool signed_input; + float wei_adj_scale; +}; + +struct jit_conv_conf_2x3_wino_t { + conv_version_t ver; + + int m; + int r; + int alpha; + int tile_h, tile_w; + + int mb; + int ngroups, ic, oc, oc_without_padding; + int ih, iw, oh, ow; + int l_pad, t_pad; + int r_pad, b_pad; + int kh, kw; + int stride_h, stride_w; + int dilate_h, dilate_w; + + int nb_ic, ic_block; + int nb_oc, oc_block; + + int w_block_size, h_block_size; + + data_type_t bia_dt; + data_type_t dst_dt; + + int is_oc_scale; + int typesize_in; + int typesize_out; + int typesize_bia; + int typesize_acc; + + format_tag_t src_tag, dst_tag; // temporary workaround + bool with_bias; + bool small_mb; + + int xb, yb; + int inp_stride; + int out_stride; + int wei_stride; + int bia_stride; + + int M, N, K; + int m_block, n_block, k_block; + int n2_block, n_chunks; + int k2_block, k_chunks; + + int mb_block, nb_mb; + + size_t size_wino_src, size_wino_wei, size_wino_dst; + + int nthr; +}; + +/* + Winograd sched policy: + + Computation Unit: + W: weights transform + S: src transform + D: dst transform + G: gemm + + Thread grouping by: + i: nb_ic + o: nb_oc + t: tile_block + e: element in tile + + Note: 'i' and 'o' are omited if + i. not comblined with t or + ii. with discrete transforms + + Current policies supported: +*/ +enum winograd_sched_t { + WSCHED_INVALID = 0, + + /* Forward & backward-data */ + /* W_S_G_D implements discrete transforms */ + WSCHED_DATA_W_S_G_D, + /* W_SGD implements tiled transforms s.t. GEMM could reuse data in L2*/ + WSCHED_DATA_W_SGD, + + /* Backward-weights */ + WSCHED_WEI_S_D_G_W, + WSCHED_WEI_SDGtWo, + WSCHED_WEI_S_D_Giot_W, + WSCHED_WEI_SDGt_W, +}; + +struct jit_conv_winograd_conf_t : public jit_conv_conf_t { + int itiles; + int jtiles; + int ntiles; + int ic_simd_block=16; + int tile_4fma_padding; + int tile_4fma; + int oc_simd_block=16; + int oc_reg_block; + int ic_reg_block; + int tile_block; + int tile_block_ur; + int nb_tile_block_ur; + + bool double_buffering; + bool with_relu_postsum; + int zmm_start; + int nb_reg; + + int dimK; + int dimK_4fma; + int dimK_reg_block; + int dimK_block; + int dimK_nb_block; + + int dimM; + int dimM_reg_block; + int dimM_simd_block; + int dimM_block; + int dimM_nb_block; + + int dimN; + int dimN_reg_block; + int dimN_bcast_ur; + int dimN_block; + int dimN_nb_block; + + winograd_sched_t sched_policy; +}; + +struct jit_conv_call_s { + const void *src; /* hack, non-const for backward_data */ + const void *dst; /* hack, non-const for forward */ + const void *filt; /* hack, non-const for backward_weights */ + const void *bias; /* hack, non-const for backward_bias */ + const void *src_prf; + const void *dst_prf; + const void *filt_prf; + const void *bias_prf; + const void *scales; + const void *acc_s32; + const void *compensation; + size_t kd_offset; + size_t kd_offset_prf; + size_t d_index; + size_t d_index_prf; + size_t d_worksize; + size_t d_worksize_prf; + size_t kd_padding; + size_t kd_padding_prf; + size_t kh_padding; + size_t kh_padding_prf; + size_t owb; + size_t owb_prf; + size_t kw_padding; + size_t channel; + size_t channel_prf; + size_t oc_blocks; + size_t ur_w; + size_t ur_str_w; + size_t ch_blocks; + size_t t_overflow; + size_t b_overflow; + int flags; +}; + +struct jit_deconv_call_s { + const void *src; /* hack, non-const for backward_data */ + const void *dst; /* hack, non-const for forward */ + const void *filt; /* hack, non-const for backward_weights */ + const void *bias; /* hack, non-const for backward_bias */ + const void *scales; + const void *compensation; + size_t t_overflow; + size_t b_overflow; + size_t kh_padding; + size_t oc_blocks; +}; + +struct jit_dw_conv_call_s { + const void *input; + const void *output; + const void *filter; + const void *bias; + size_t kh_count; + size_t oh_count; + size_t oh_index; + size_t filter_pad_off; + unsigned char + exec_flags; /* Flags passed by driver execution to inner kernel */ +}; + +struct jit_wino_transform_call_s { + size_t tile_block; + size_t tile_block_ur; + size_t nb_tile_block_ur; + size_t tile_count; + size_t tj; + size_t ti; + void *src; + void *dst; + void *Mw; + void *M; + void *T; + void *G; + void *bias; +}; + +struct jit_1x1_conv_conf_t { + prop_kind_t prop_kind; + conv_version_t ver; + + int mb; + int ngroups, ic, oc, oc_without_padding, ic_without_padding; + int iw, ih, ow, oh; + int l_pad, t_pad; + int kh, kw; + int stride_h, stride_w; + format_tag_t src_tag, wei_tag, dst_tag; // temporary workaround + bool with_bias; + bool with_sum; + bool with_eltwise; + + post_ops_t::entry_t::eltwise_t eltwise; + + int is, os; + int ic_block, oc_block; + + int ur, ur_tail; + + int reduce_dim, reduce_block, nb_reduce, + nb_reduce_blocking, nb_reduce_blocking_max; + int load_dim, load_block, nb_load, + nb_load_blocking, nb_load_blocking_max, nb_load_chunk; + int bcast_dim, bcast_block, nb_bcast, + nb_bcast_blocking, nb_bcast_blocking_max; + + int reduce_loop_unroll, reduce_loop_bcast_step, reduce_loop_load_step; + int load_loop_load_step, load_loop_iter_step; + int bcast_loop_output_step, bcast_loop_output_substep; + int bcast_loop_bcast_step, bcast_loop_bcast_substep; + int fma_step; + int load_grp_count; + conv_1x1_loop_order_t loop_order; + bool use_vmovntps; + /* avx512 core */ + bool expl_bcast; + /* 4vnni */ + int typesize_in; + int typesize_out; + int typesize_bia; + int typesize_acc; + /* 4fma */ + bool transpose_src; + int tr_is; + int nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b; + int is_oc_scale; + data_type_t bia_dt; + data_type_t dst_dt; + bool signed_input; + float wei_adj_scale; +}; + +struct jit_gemm_conv_conf_t { + prop_kind_t prop_kind; + + int mb; + int ngroups, ic, oc; + int iw, ih, id, ow, oh, od; + int l_pad, t_pad, f_pad; + int kh, kw, kd; + int stride_h, stride_w, stride_d; + int dilate_h, dilate_w, dilate_d; + bool with_bias; + + int is, os, ks; + int ic_block, oc_block; + + int nthr; + ptrdiff_t im2col_sz; + bool need_wei_reduction; + bool signed_input; + int oh_block; + int ow_block; + bool outer_threading; +}; + +struct jit_1x1_conv_call_s { + const void *bcast_data; + const void *load_data; + const void *output_data; + const void *bias_data; // used in forward and backward_weights only + const void *acc_s32; + const void *scales; + const void *compensation; + + size_t load_dim; + size_t bcast_dim; + size_t reduce_dim; + + size_t output_stride; // used in backward_weights only + + size_t first_last_flag; +}; + +/* pooling */ +struct jit_pool_conf_t { + int ndims; + int mb, c; + int id, ih, iw, od, oh, ow; + int stride_d, stride_h, stride_w; + int kd, kh, kw; + int f_pad, t_pad, l_pad; + alg_kind_t alg; + bool is_training; + bool pad_w_is_null; + bool is_backward; + bool simple_alg; + data_type_t ind_dt; + + int c_block, c_tail, nb_c; + int ur_c, ur_c_tail; + int ur_w; + int ur_w_tail; + size_t tail[4]; + data_type_t src_dt; + data_type_t dst_dt; +}; + +struct jit_pool_call_s { + const float *src; + const float *dst; + const void *indices; + const float *src_prf; + const float *dst_prf; + const void *indices_prf; + size_t oh; + size_t kd_padding; + size_t kh_padding; + size_t kh_padding_shift; + size_t kd_padding_shift; + size_t kw_padding; + const float* init_value; + float ker_area_h; +}; + + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp new file mode 100644 index 0000000000..94d2101d6e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp @@ -0,0 +1,677 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "cpu_memory.hpp" + +#include "jit_sse42_1x1_conv_kernel_f32.hpp" + +#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +void jit_sse42_1x1_conv_kernel_f32::generate_bcast_loop(int load_loop_blk) +{ + mov(aux1_reg_bcast_data, reg_bcast_data); + mov(aux_reg_output_data, reg_output_data); + mov(bcast_loop_iter, reg_bcast_loop_work); + + Label bcast_loop; + Label bcast_loop_tail; + + cmp(bcast_loop_iter, jcp.ur); + jl(bcast_loop_tail, T_NEAR); + + L(bcast_loop); { + assert(jcp.bcast_block % jcp.ur == 0); + int num_substeps = jcp.bcast_block / jcp.ur; + assert(num_substeps > 0 && num_substeps < 10); + for (int i = 0; i < num_substeps; i++) { + generate_reduce_loop(load_loop_blk, jcp.ur); + if (i < num_substeps - 1) { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_substep); + } else { + add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step + - (num_substeps - 1) * jcp.bcast_loop_bcast_substep); + add(aux_reg_output_data, jcp.bcast_loop_output_step + - (num_substeps - 1) * jcp.bcast_loop_output_substep); + } + } + sub(bcast_loop_iter, jcp.bcast_block); + cmp(bcast_loop_iter, jcp.bcast_block); + jge(bcast_loop, T_NEAR); + } + + L(bcast_loop_tail); + if (jcp.ur_tail) { + Label bcast_loop_tail_out; + cmp(bcast_loop_iter, 0); + jz(bcast_loop_tail_out, T_NEAR); + generate_reduce_loop(load_loop_blk, jcp.ur_tail); + L(bcast_loop_tail_out); + } +} + +void jit_sse42_1x1_conv_kernel_f32::generate_reduce_loop( + int load_loop_blk, int ur) +{ + auto reg_load = [=](int i, int n) { + return Xmm(2*ur * load_loop_blk + 2*i + n + 1); + }; + + auto reg_accum = [=](int i, int j, int n) { + return Xmm(2*j * load_loop_blk + 2*i + n + 1); + }; + + auto bias_ptr = [=](int i, int n) { + return ptr[reg_bias_data + sizeof(float) * jcp.oc_block * i + n*4*sizeof(float)]; + }; + + auto bcast_ptr = [=](int u, int j) { + assert(j < jcp.ur); + assert(u <= jcp.reduce_loop_unroll); + size_t offt; + if (one_of(jcp.prop_kind, + forward_training, forward_inference, backward_data)) { + assert(jcp.reduce_loop_unroll == (jcp.prop_kind == backward_data) + ? jcp.oc_block : jcp.ic_block); + auto height = (jcp.prop_kind == backward_data) ? jcp.os : jcp.is; + offt = (u == jcp.reduce_loop_unroll) + ? (height + j) * jcp.reduce_loop_unroll + : j * jcp.reduce_loop_unroll + u; + } else + offt = u * jcp.ic_block + j; + return ptr[aux_reg_bcast_data + sizeof(float) * offt]; + }; + + auto load_ptr = [=](int u, int i, int n) { + size_t offt; + size_t u0 = u % jcp.reduce_loop_unroll; + size_t u1 = u / jcp.reduce_loop_unroll; + switch (jcp.prop_kind) { + case backward_data: + offt = (i * jcp.oc_block + u0) * jcp.ic_block; + break; + case backward_weights: + offt = (i * jcp.os + u0) * jcp.oc_block; + break; + default: + offt = (i * jcp.ic + u0) * jcp.oc_block; + } + return ptr[aux_reg_load_data + + u1 * jcp.reduce_loop_load_step + sizeof(float) * offt + n * 4 * sizeof(float)]; + }; + + auto output_ptr = [=](int i, int j, int n) { + switch (jcp.prop_kind) { + case backward_data: + return ptr[aux_reg_output_data + + (i * jcp.is + j) * jcp.ic_block * sizeof(float) + n * 4 * sizeof(float)]; + case backward_weights: + return ptr[aux_reg_output_data + + (i ? reg_output_stride * i : 0) // TODO: Xbyak should allow 0 scale + + sizeof(float) * jcp.oc_block * j + n * 4 * sizeof(float)]; + default: + return ptr[aux_reg_output_data + + (i * jcp.os + j) * jcp.oc_block * sizeof(float) + n*4*sizeof(float)]; + } + }; + + auto init = [=]() { + Label init_done; + Label init_zero; + + if (jcp.with_bias && one_of(jcp.prop_kind, forward_training, + forward_inference)) { + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jz(init_zero); + + for (int i = 0; i < load_loop_blk; i++) + for (int j = 0; j < ur; ++j) { + movups(reg_accum(i, j, 0), bias_ptr(i, 0)); + movups(reg_accum(i, j, 1), bias_ptr(i, 1)); + } + jmp(init_done); + } + + L(init_zero); + for (int i = 0; i < load_loop_blk; ++i) + for (int j = 0; j < ur; ++j) { + auto r0 = reg_accum(i, j, 0); + auto r1 = reg_accum(i, j, 1); + xorps(r0, r0); + xorps(r1, r1); + } + + L(init_done); + + // load weights + for (int i = 0; i < load_loop_blk; ++i) { + movups(reg_load(i, 0), load_ptr(0, i, 0)); + movups(reg_load(i, 1), load_ptr(0, i, 1)); + } + + movss(reg_bcast, bcast_ptr(0, 0)); + shufps(reg_bcast, reg_bcast, 0); + }; // init() + + auto store = [=]() { + Label store_noadd; + + if (!jcp.with_sum) { + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jnz(store_noadd, T_NEAR); + } + + for (int j = 0; j < ur; ++j) + for (int i = 0; i < load_loop_blk; ++i) { + auto r0 = reg_accum(i, j, 0); + auto r1 = reg_accum(i, j, 1); + addps(r0, output_ptr(i, j, 0)); + addps(r1, output_ptr(i, j, 1)); + } + + L(store_noadd); + + if (jcp.with_eltwise) { + assert(ur * load_loop_blk < 14); + + Label store_norelu; + test(reg_reduce_pos_flag, FLAG_REDUCE_LAST); + jz(store_norelu, T_NEAR); + + eltwise_injector_->compute_vector_range(1, + 2 * ur * load_loop_blk + 1); + + L(store_norelu); + } + + for (int j = 0; j < ur; ++j) + for (int i = 0; i < load_loop_blk; ++i) { + movups(output_ptr(i, j, 0), reg_accum(i, j, 0)); + movups(output_ptr(i, j, 1), reg_accum(i, j, 1)); + } + }; + + auto fma_block = [=](bool last_block) { + for (int u = 0; u < jcp.reduce_loop_unroll; ++u) { + for (int j = 0; j < ur; ++j) { + for (int i = 0; i < load_loop_blk; ++i) { + mulps(reg_load(i, 0), reg_bcast); + mulps(reg_load(i, 1), reg_bcast); + addps(reg_accum(i, j, 0), reg_load(i, 0)); + addps(reg_accum(i, j, 1), reg_load(i, 1)); + + if (j == ur - 1 && !(last_block && u == jcp.reduce_loop_unroll - 1)) { + movups(reg_load(i, 0), load_ptr(u + 1, i, 0)); + movups(reg_load(i, 1), load_ptr(u + 1, i, 1)); + } + } + if (j < ur - 1) { + movss(reg_bcast, bcast_ptr(u, j + 1)); + shufps(reg_bcast, reg_bcast, 0); + } + } // for ur + if (!last_block || u < jcp.reduce_loop_unroll - 1) { + movss(reg_bcast, bcast_ptr(u + 1, 0)); + shufps(reg_bcast, reg_bcast, 0); + } + } // for reduce_loop_unroll + }; + + Label reduce_loop; + Label reduce_loop_tail; + + mov(aux_reg_load_data, reg_load_data); + mov(aux_reg_bcast_data, aux1_reg_bcast_data); + + init(); + + mov(reduce_loop_iter, reg_reduce_loop_work); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jle(reduce_loop_tail, T_NEAR); + + L(reduce_loop); { + fma_block(false); + add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step); + add(aux_reg_load_data, jcp.reduce_loop_load_step); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jg(reduce_loop, T_NEAR); + } + + L(reduce_loop_tail); + fma_block(true); + + store(); +} // reduce_loop() + +void jit_sse42_1x1_conv_kernel_f32::generate_diff_bias_loop(int load_loop_blk) +{ + if (!jcp.with_bias || jcp.prop_kind != backward_weights) + return; + + Label diff_bias_loop, diff_bias_loop_out, diff_bias_init_out; + Label diff_bias_load; + + auto diff_bias_ptr = [=](int i, int n) { + return ptr[reg_diff_bias_data + i * jcp.oc_block * sizeof(float)+ 4*n*sizeof(float)]; + }; + + auto load_ptr = [=](int u, int i, int n) { + return ptr[aux_reg_load_data + + (i * jcp.os + u) * jcp.oc_block * sizeof(float) + 4*n*sizeof(float)]; + }; + + auto diff_bias_reg = [=](int i, int n) { return Xmm(2*i + n + 1); }; + + mov(reg_diff_bias_data, ptr[rsp + reg_diff_bias_data_stack_offt]); + cmp(reg_diff_bias_data, 0); + je(diff_bias_loop_out, T_NEAR); + + test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST); + jz(diff_bias_load, T_NEAR); + + for (int i = 0; i < load_loop_blk; ++i) { + auto r0 = diff_bias_reg(i, 0); + auto r1 = diff_bias_reg(i, 1); + xorps(r0, r0); + xorps(r1, r1); + } + jmp(diff_bias_init_out, T_NEAR); + + L(diff_bias_load); + for (int i = 0; i < load_loop_blk; ++i) { + movups(diff_bias_reg(i, 0), diff_bias_ptr(i, 0)); + movups(diff_bias_reg(i, 1), diff_bias_ptr(i, 1)); + } + + L(diff_bias_init_out); + mov(aux_reg_load_data, reg_load_data); + mov(reduce_loop_iter, reg_reduce_loop_work); + L(diff_bias_loop); { + for(int u = 0; u < jcp.reduce_loop_unroll; ++u) + for (int i = 0; i < load_loop_blk; ++i) { + addps(diff_bias_reg(i, 0), load_ptr(u, i, 0)); + addps(diff_bias_reg(i, 1), load_ptr(u, i, 1)); + } + assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0); + add(aux_reg_load_data, jcp.reduce_loop_load_step); + sub(reduce_loop_iter, jcp.reduce_loop_unroll); + jnz(diff_bias_loop, T_NEAR); + } + + for (int i = 0; i < load_loop_blk; i++) { + movups(diff_bias_ptr(i, 0), diff_bias_reg(i, 0)); + movups(diff_bias_ptr(i, 1), diff_bias_reg(i, 1)); + } + + add(reg_diff_bias_data, load_loop_blk * jcp.oc_block * sizeof(float)); + mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data); + + L(diff_bias_loop_out); +} + +void jit_sse42_1x1_conv_kernel_f32::generate() +{ + preamble(); + + mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]); + mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]); + mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]); + if (jcp.with_bias) { + if (jcp.prop_kind == backward_weights) { + sub(rsp, stack_space_needed); + mov(reg_diff_bias_data, ptr[param1 + GET_OFF(bias_data)]); + mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data); + } else + mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]); + } + + mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]); + mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]); + mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]); + mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]); + if (jcp.prop_kind == backward_weights) + mov(reg_output_stride, ptr[param1 + GET_OFF(output_stride)]); + + auto generate_load_loop_body = [=] (int load_loop_blk) { + generate_bcast_loop(load_loop_blk); + add(reg_load_data, load_loop_blk * jcp.load_loop_load_step); + switch (jcp.prop_kind) { + case forward_training: + case forward_inference: + add(reg_bias_data, load_loop_blk * jcp.oc_block * sizeof(float)); + add(reg_output_data, + load_loop_blk * jcp.os * jcp.oc_block * sizeof(float)); + break; + case backward_data: + add(reg_output_data, + load_loop_blk * jcp.is * jcp.ic_block * sizeof(float)); + break; + case backward_weights: + for (int i = 0; i < load_loop_blk; i++) + add(reg_output_data, reg_output_stride); + break; + default: + assert(!"invalid prop_kind"); + } + sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step); + }; + + Label load_loop_blk_8; + Label load_loop_blk_16; + Label load_loop_blk_24; + Label load_loop_blk_end; + + cmp(reg_load_loop_work, 8); + jle(load_loop_blk_8, T_NEAR); + + cmp(reg_load_loop_work, 32); + je(load_loop_blk_16, T_NEAR); + + cmp(reg_load_loop_work, 16); + jle(load_loop_blk_16, T_NEAR); + + L(load_loop_blk_24); { + generate_diff_bias_loop(3); + generate_load_loop_body(3); + cmp(reg_load_loop_work, 32); + je(load_loop_blk_16); + cmp(reg_load_loop_work, 24); + jge(load_loop_blk_24); + } + + cmp(reg_load_loop_work, 8); + jle(load_loop_blk_8, T_NEAR); + + L(load_loop_blk_16); { + generate_diff_bias_loop(2); + generate_load_loop_body(2); + cmp(reg_load_loop_work, 16); + jge(load_loop_blk_16); + } + + L(load_loop_blk_8); { + cmp(reg_load_loop_work, 0); + je(load_loop_blk_end, T_NEAR); + generate_diff_bias_loop(1); + generate_load_loop_body(1); + } + + L(load_loop_blk_end); + + if (jcp.with_bias && jcp.prop_kind == backward_weights) + add(rsp, stack_space_needed); + + postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +bool jit_sse42_1x1_conv_kernel_f32::post_ops_ok( + jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + + return false; +} + +status_t jit_sse42_1x1_conv_kernel_f32::init_conf(jit_1x1_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr) +{ + if (!mayiuse(sse42)) + return status::unimplemented; + + // TODO (Roma): this code is duplicated from the generic kernel; maybe the + // configuration struct could do some stuff below + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + const int ndims = src_d.ndims(); + + jcp.prop_kind = cd.prop_kind; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2]; + jcp.iw = src_d.dims()[ndims - 1]; + jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2]; + jcp.ow = dst_d.dims()[ndims - 1]; + + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0]; + jcp.l_pad = cd.padding[0][ndims - 3]; + + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0]; + jcp.stride_w = cd.strides[ndims - 3]; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + jcp.os = jcp.oh * jcp.ow; + jcp.is = jcp.ih * jcp.iw; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + jcp.with_sum = p.find(primitive_kind::sum) != -1; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + + const int is_bwd_d = jcp.prop_kind == backward_data; + + format_tag_t dat_tag = ndims == 3 ? nCw8c : nChw8c; + format_tag_t wei_tag = with_groups + ? utils::pick(2 * ndims - 6 + is_bwd_d, gOIw8i8o, gOIw8o8i, gOIhw8i8o, + gOIhw8o8i) + : utils::pick(2 * ndims - 6 + is_bwd_d, OIw8i8o, OIw8o8i, OIhw8i8o, + OIhw8o8i); + + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + + bool args_ok = true + && jcp.ngroups == 1 + && jcp.src_tag == dat_tag + && jcp.wei_tag == wei_tag + && jcp.dst_tag == dat_tag; + if (!args_ok) return status::unimplemented; + + const int simd_w = 4; + jcp.ic_block = jcp.oc_block = simd_w*2; + + args_ok = true + && jcp.oc % jcp.oc_block == 0 + && jcp.ic % jcp.ic_block == 0 + && jcp.t_pad == 0 && jcp.l_pad == 0 + && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides + && jcp.kh == 1 && jcp.kw == 1; + if (!args_ok) return status::unimplemented; + + jcp.ur = 1; + + int load_blocking{ 0 }; + int load_blocking_max{ 0 }; + int bcast_blocking{ 0 }; + int bcast_blocking_max{ 0 }; + int reduce_blocking{ 0 }; + + if (one_of(jcp.prop_kind, forward_training, forward_inference)) { + jcp.reduce_dim = jcp.ic; + jcp.reduce_block = jcp.ic_block; + + jcp.load_dim = jcp.oc; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.is; + jcp.bcast_block = jcp.ur; + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.is * sizeof(float); + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float); + + jcp.bcast_loop_output_step = jcp.ur * jcp.oc_block * sizeof(float); + jcp.bcast_loop_output_substep = -1; // unused + jcp.bcast_loop_bcast_step = jcp.ur * jcp.ic_block * sizeof(float); + jcp.bcast_loop_bcast_substep = -1; // unused + + jcp.load_loop_load_step = jcp.ic * jcp.oc_block * sizeof(float); + jcp.load_loop_iter_step = jcp.oc_block; + + load_blocking = 120; // assumes the kernel is jcp.ur x 3 + load_blocking_max = 144; + bcast_blocking = 128; // affects load balancing across threads + bcast_blocking_max = 192; + reduce_blocking = 128; // affects L1$ utilization + } else if (jcp.prop_kind == backward_data) { + jcp.reduce_dim = jcp.oc; + jcp.reduce_block = jcp.oc_block; + + jcp.load_dim = jcp.ic; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.os; + jcp.bcast_block = jcp.ur; + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.os * sizeof(float); + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.ic * sizeof(float); + + jcp.bcast_loop_output_step = jcp.ur * jcp.ic_block * sizeof(float); + jcp.bcast_loop_output_substep = -1; // unused + jcp.bcast_loop_bcast_step = jcp.ur * jcp.oc_block * sizeof(float); + jcp.bcast_loop_bcast_substep = -1; // unused + + jcp.load_loop_load_step = jcp.oc_block * jcp.ic_block * sizeof(float); + jcp.load_loop_iter_step = jcp.ic_block; + + load_blocking = 96; // assumes the kernel is jcp.ur x 3 + load_blocking_max = 144; + bcast_blocking = 128; // affects load balancing across threads + bcast_blocking_max = 196; + reduce_blocking = 64; // affects L1$ utilization + } else if (jcp.prop_kind == backward_weights) { + jcp.reduce_dim = jcp.os; + jcp.reduce_block = 1; + + jcp.load_dim = jcp.oc; + jcp.load_block = jcp.oc_block; + + jcp.bcast_dim = jcp.ic; + jcp.bcast_block = jcp.ic_block; + + jcp.reduce_loop_unroll = jcp.reduce_block; + jcp.reduce_loop_bcast_step + = jcp.reduce_loop_unroll * jcp.ic_block * sizeof(float); + jcp.reduce_loop_load_step + = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float); + + jcp.bcast_loop_output_step = jcp.oc_block * jcp.ic_block * sizeof(float); + jcp.bcast_loop_output_substep = jcp.oc_block * jcp.ur * sizeof(float); + jcp.bcast_loop_bcast_step = jcp.ic_block * jcp.is * sizeof(float); + jcp.bcast_loop_bcast_substep = jcp.ur * sizeof(float); + + jcp.load_loop_load_step = jcp.oc_block * jcp.os * sizeof(float); + jcp.load_loop_iter_step = jcp.oc_block; + + /* --- */ + + load_blocking = div_up(jcp.load_dim, jcp.load_block); + while (true) { + if (load_blocking <= 32) break; + else if (load_blocking % 2 == 0) load_blocking /= 2; + else if (load_blocking % 3 == 0) load_blocking /= 3; + else break; + } + load_blocking *= jcp.load_block; + load_blocking_max = load_blocking; + assert(jcp.load_dim % load_blocking == 0); + + bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block); + while (true) { + if (bcast_blocking <= 9) break; + else if (bcast_blocking % 2 == 0) bcast_blocking /= 2; + else if (bcast_blocking % 3 == 0) bcast_blocking /= 3; + else break; + } + bcast_blocking *= jcp.bcast_block; + bcast_blocking_max = bcast_blocking; + assert(jcp.bcast_dim % bcast_blocking == 0); + + reduce_blocking = 128; // affects L1$ utilization + } else + return status::unimplemented; + + assert(load_blocking); + assert(load_blocking_max); + assert(bcast_blocking); + assert(bcast_blocking_max); + assert(reduce_blocking); + + assert(jcp.bcast_block % jcp.ur == 0); + jcp.ur_tail = jcp.bcast_dim % jcp.ur; + + jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block; + jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block; + jcp.nb_load_blocking = load_blocking / jcp.load_block; + jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block; + jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block; + + jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block); + jcp.nb_load = div_up(jcp.load_dim, jcp.load_block); + jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block); + + return status::success; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp new file mode 100644 index 0000000000..b314a5098c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp @@ -0,0 +1,104 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_SSE42_1x1_CONV_KERNEL_F32_HPP +#define JIT_SSE42_1x1_CONV_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "cpu_memory.hpp" +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_sse42_1x1_conv_kernel_f32: public jit_generator { + jit_sse42_1x1_conv_kernel_f32(jit_1x1_conv_conf_t ajcp, + const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32(this, + jcp.eltwise); + + this->generate(); + jit_ker = (void (*)(jit_1x1_conv_call_s *))this->getCode(); + } + + ~jit_sse42_1x1_conv_kernel_f32() { + delete eltwise_injector_; + } + + static bool post_ops_ok(jit_1x1_conv_conf_t &jcp, + const primitive_attr_t &attr); + + static status_t init_conf(jit_1x1_conv_conf_t &jcp, + const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr); + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_sse42_1x1_conv_kernel_f32) + + jit_1x1_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker)(jit_1x1_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + using xmm_t = const Xbyak::Xmm; + + reg64_t reg_bcast_data = rax; + reg64_t reg_load_data = rsi; + reg64_t reg_output_data = rbx; + reg64_t aux_reg_bcast_data = rdx; + reg64_t aux1_reg_bcast_data = abi_not_param1; + reg64_t aux_reg_load_data = abi_param1; + reg64_t aux_reg_output_data = rbp; + reg64_t reg_load_loop_work = r9; + reg64_t reg_bcast_loop_work = r10; + reg64_t reg_reduce_loop_work = r11; + reg64_t load_loop_iter = r13; + reg64_t imm_addr64 = load_loop_iter; + reg64_t bcast_loop_iter = r14; + reg64_t reduce_loop_iter = r15; + reg64_t reg_reduce_pos_flag = r8; + reg64_t reg_output_stride = r12; + reg64_t reg_bias_data = r12; + reg64_t reg_diff_bias_data = bcast_loop_iter; + + int reg_diff_bias_data_stack_offt = 0; + int stack_space_needed = 8; + + xmm_t reg_bcast = xmm_t(15); + + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + void generate_bcast_loop(int load_loop_blk); + void generate_reduce_loop(int load_loop_blk, int ur); + void generate_diff_bias_loop(int load_loop_blk); + + void generate(); +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp new file mode 100644 index 0000000000..30c137641e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp @@ -0,0 +1,134 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "jit_sse42_1x1_convolution.hpp" +#include "utils.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +#define data_blk_off(f, n, c, h, w) \ + ((ndims == 3) \ + ? (f).blk_off(n, c, w) \ + : (f).blk_off(n, c, h, w)) + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::utils; + +void jit_sse42_1x1_convolution_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + const int ndims = src_d.ndims(); + + const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast; + + parallel(0, [&](const int ithr, const int nthr) { + // TODO (Roma): remove this restriction + assert(jcp.stride_w == 1 && jcp.stride_h == 1); + + auto par_conv = jit_1x1_conv_call_s(); + + const int nb_oc = jcp.nb_load; + const int nb_ic = jcp.nb_reduce; + const int nb_ic_blocking = jcp.nb_reduce_blocking; + const int os_block = jcp.bcast_block; + + int start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + + int iwork = start; + while (iwork < end) { + int n{0}, g{0}, osb{0}; + nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb, + jcp.nb_bcast); + + const int bcast_step_rem = jcp.nb_bcast - osb; + int bcast_step = bcast_step_rem <= jcp.nb_bcast_blocking_max + ? bcast_step_rem : jcp.nb_bcast_blocking; + bcast_step = nstl::min(bcast_step, end - iwork); + + const int os = osb * os_block; + const int ow = os % jcp.ow; + const int oh = os / jcp.ow; + const int iw = nstl::max(ow * jcp.stride_w - jcp.l_pad, 0); + const int ih = nstl::max(oh * jcp.stride_h - jcp.t_pad, 0); + + par_conv.bcast_dim = this_block_size(os, jcp.os, + bcast_step * os_block); + + int ocb = 0; + while (ocb < jcp.nb_load) { + const int load_step_rem = jcp.nb_load - ocb; + const int load_step = load_step_rem < jcp.nb_load_blocking_max + ? load_step_rem : jcp.nb_load_blocking; + + const size_t _ocb = g * nb_oc + ocb; + par_conv.load_dim = this_block_size(ocb * jcp.oc_block, jcp.oc, + load_step * jcp.oc_block); + + const size_t dst_off = data_blk_off(dst_d, n, _ocb, oh, ow); + par_conv.output_data = &dst[dst_off]; + + par_conv.bias_data = &bias[_ocb * jcp.oc_block]; + + for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) { + par_conv.first_last_flag = 0 + | (icb == 0) * FLAG_REDUCE_FIRST + | (icb + nb_ic_blocking >= nb_ic) * FLAG_REDUCE_LAST; + + par_conv.reduce_dim = this_block_size(icb * jcp.ic_block, + jcp.ic, nb_ic_blocking * jcp.ic_block); + + const size_t _icb = g * nb_ic + icb; + const size_t src_off = data_blk_off(src_d, n, _icb, ih, iw); + par_conv.bcast_data = &src[src_off]; + + par_conv.load_data = &weights[pd()->with_groups() + ? weights_d.blk_off(g, ocb, icb) + : weights_d.blk_off(ocb, icb)]; + + kernel_->jit_ker(&par_conv); + } + + ocb += load_step; + } + + iwork += bcast_step; + } + }); + + if (pd()->wants_zero_pad_dst()) + ctx.memory(MKLDNN_ARG_DST)->zero_pad(); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp new file mode 100644 index 0000000000..b32b1e4784 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp @@ -0,0 +1,96 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_SSE42_1x1_CONVOLUTION_HPP +#define CPU_JIT_SSE42_1x1_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" +#include "jit_sse42_1x1_conv_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_sse42_1x1_convolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_1x1:", sse42, ""), + jit_sse42_1x1_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + return jit_sse42_1x1_conv_kernel_f32::init_conf(jcp_, *desc(), + *src_md(), *weights_md(), *dst_md(), *attr()); + } + + jit_1x1_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, gOIw8i8o, gOIhw8i8o) + : utils::pick(ndims() - 3, OIw8i8o, OIhw8i8o); + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + jit_sse42_1x1_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) { + kernel_ = new jit_sse42_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr()); + } + ~jit_sse42_1x1_convolution_fwd_t() { delete kernel_; }; + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_sse42_1x1_conv_kernel_f32 *kernel_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp new file mode 100644 index 0000000000..17cabc1186 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp @@ -0,0 +1,497 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "cpu_memory.hpp" + +#include "jit_sse42_conv_kernel_f32.hpp" + +#define GET_OFF(field) offsetof(jit_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +void jit_sse42_conv_fwd_kernel_f32::oh_step_unroll_kw(int ur_w, + int pad_l, int pad_r, int oc_blocks) +{ + int iw = jcp.iw; + int ih = jcp.ih; + int kw = jcp.kw; + int kh = jcp.kh; + int nb_ic = jcp.nb_ic; + int stride_w = jcp.stride_w; + int dilate_w = jcp.dilate_w + 1; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + + for (int ki = 0; ki < kw; ki++) { + int jj_start = nstl::max(0, div_up(pad_l - ki * dilate_w, stride_w)); + int jj_end = ur_w + - nstl::max(0, div_up(ki*dilate_w + pad_r - (kw-1)*dilate_w, stride_w)); + for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) { + for (int jj = jj_start; jj < jj_end; jj++) { + int inp_off; + if (one_of(jcp.src_tag, ncw, nchw)) + inp_off = ifm2*ih*iw + (ki*dilate_w + jj*stride_w - pad_l); + else + inp_off = (ki*dilate_w + jj*stride_w - pad_l)*ic_blk + ifm2; + + movss(Xmm(oc_blocks * ur_w + jj + 1), + ptr[aux_reg_input + sizeof(float) * inp_off]); + shufps(Xmm(oc_blocks * ur_w + jj + 1), + Xmm(oc_blocks * ur_w + jj + 1), 0x0); + } + + for (int ii = 0; ii < oc_blocks; ii++) { + int ker_off = ii * nb_ic * kh * kw * ic_blk * oc_blk + + ki * ic_blk * oc_blk + ifm2 * oc_blk; + + for (int jj = jj_start; jj < jj_end; jj++) + { + movups(xmm0, + ptr[aux_reg_kernel + sizeof(float) * ker_off]); + mulps(xmm0, Xmm(oc_blocks * ur_w + jj + 1)); + addps(Xmm(ur_w * ii + jj + 1), xmm0); + } + } + } + } +} + +void jit_sse42_conv_fwd_kernel_f32::oh_step_nopad(int ur_w, + int pad_l, int pad_r, int oc_blocks) +{ + Label kw_loop; + + int iw = jcp.iw; + int ih = jcp.ih; + int kw = jcp.kw; + int kh = jcp.kh; + int nb_ic = jcp.nb_ic; + int stride_w = jcp.stride_w; + int dilate_w = jcp.dilate_w + 1; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + + xor_(ki_iter, ki_iter); + L(kw_loop); + { + int jj_start = 0; + int jj_end = ur_w; + for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) { + for (int jj = jj_start; jj < jj_end; jj++) { + int inp_off; + if (one_of(jcp.src_tag, ncw, nchw)) + inp_off = ifm2 * ih * iw + (jj * stride_w - pad_l); + else + inp_off = (jj * stride_w - pad_l) * ic_blk + ifm2; + + movss(Xmm(oc_blocks * ur_w + jj + 1), + ptr[aux_reg_input + sizeof(float) * inp_off]); + shufps(Xmm(oc_blocks * ur_w + jj + 1), + Xmm(oc_blocks * ur_w + jj + 1), 0x0); + } + for (int ii = 0; ii < oc_blocks; ii++) { + int aux_kernel_offset = ii * nb_ic * kh * kw * ic_blk * oc_blk + + ifm2 * oc_blk; + for (int jj = jj_start; jj < jj_end; jj++) { + movups(xmm0, + ptr[aux_reg_kernel + sizeof(float) * aux_kernel_offset]); + mulps(xmm0, Xmm(oc_blocks * ur_w + jj + 1)); + addps(Xmm(ur_w * ii + jj + 1), xmm0); + } + } + } + add(aux_reg_kernel, sizeof(float) * oc_blk * ic_blk); + add(aux_reg_input, sizeof(float) * (one_of(jcp.src_tag, ncw, nchw) ? + dilate_w : ic_blk * dilate_w)); + + inc(ki_iter); + cmp(ki_iter, kw); + jl(kw_loop, T_NEAR); + } +} + +void jit_sse42_conv_fwd_kernel_f32::width_blk_step(int ur_w, + int pad_l, int pad_r, int oc_blocks) +{ + int iw = jcp.iw; + int kw = jcp.kw; + int ow = jcp.ow; + int oh = jcp.oh; + int dilate_h = jcp.dilate_h + 1; + int dilate_w = jcp.dilate_w + 1; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + const int inp_mult = one_of(jcp.src_tag, ncw, nchw) + ? dilate_h : ic_blk * dilate_h; + const int inp_off = one_of(jcp.src_tag, ncw, nchw) + ? dilate_w : ic_blk * dilate_w; + + xor_(simd_iter, simd_iter); + + mov(aux_reg_input, reg_input); + mov(aux_reg_kernel, reg_kernel); + + Label init_simd_iter_loop; + Label init_done; + Label init_first; + + L(init_simd_iter_loop); + + if (!jcp.with_sum) { + test(reg_ci_flag, FLAG_IC_FIRST); + jne(init_first, T_NEAR); + } + + for (int ii = 0; ii < oc_blocks; ii++) + for (int jj = 0; jj < ur_w; jj++) + movups(Xmm(ur_w * ii + jj + 1), xword[reg_output + + sizeof(float) * (ii * oh * ow + jj) * oc_blk]); + + if (jcp.with_sum && jcp.with_bias) { + test(reg_ci_flag, FLAG_IC_FIRST); + je(init_done, T_NEAR); + + for (int ii = 0; ii < oc_blocks; ii++) + for (int jj = 0; jj < ur_w; jj++) + addps(Xmm(ur_w * ii + jj + 1), + xword[reg_bias + sizeof(float) * ii * oc_blk]); + } + + jmp(init_done); + + L(init_first); + if (this->jcp.with_bias) { + for (int ii = 0; ii < oc_blocks; ii++) + for (int jj = 0; jj < ur_w; jj++) + movups(Xmm(ur_w * ii + jj + 1), + xword[reg_bias + sizeof(float) * ii * oc_blk]); + } else { + for (int ii = 0; ii < oc_blocks; ii++) + for (int jj = 0; jj < ur_w; jj++) + pxor(Xmm(ur_w * ii + jj + 1), Xmm(ur_w * ii + jj + 1)); + } + + L(init_done); + + Label skip_kh_loop; + mov(kj, reg_kh); + if ((jcp.dilate_h >= jcp.ih) + || (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad)) { + cmp(kj, 0); + je(skip_kh_loop, T_NEAR); + } + Label kh_loop; + L(kh_loop); + { + if (jcp.kw >= 5 && pad_l == 0 && pad_r == 0) { + oh_step_nopad(ur_w, pad_l, pad_r, oc_blocks); + sub(aux_reg_input, sizeof(float) * kw * inp_off); + add(aux_reg_input, sizeof(float) * iw * inp_mult); + } else { + oh_step_unroll_kw(ur_w, pad_l, pad_r, oc_blocks); + add(aux_reg_kernel, sizeof(float) * kw * oc_blk * ic_blk); + add(aux_reg_input, sizeof(float) * iw * inp_mult); + } + + dec(kj); + cmp(kj, 0); + jg(kh_loop, T_NEAR); + } + + L(skip_kh_loop); + + if (jcp.with_eltwise) { + Label regular_store; + test(reg_ci_flag, FLAG_IC_LAST); + je(regular_store, T_NEAR); + + eltwise_injector_->compute_vector_range(1, oc_blocks * ur_w + 1); + + L(regular_store); + } + + for (int ii = 0; ii < oc_blocks; ii++) { + for (int jj = 0; jj < ur_w; jj++) { + const size_t o_off = (ii * oh * ow + jj) * oc_blk; + + Xmm reg_out = Xmm(ur_w * ii + jj + 1); + movups(xword[reg_output + sizeof(float) * o_off], reg_out); + } + } + + mov(aux_reg_kernel, reg_kernel); + mov(aux_reg_input, reg_input); + add(aux_reg_kernel, sizeof(float) * 4); + add(reg_output, sizeof(float) * 4); + add(reg_bias, sizeof(float) * 4); + + inc(simd_iter); + cmp(simd_iter, 2); + jl(init_simd_iter_loop, T_NEAR); + + sub(reg_output, sizeof(float) * 8); + sub(reg_bias, sizeof(float) * 8); +} + +inline void jit_sse42_conv_fwd_kernel_f32::solve_common(int oc_blocks) +{ + int ur_w = jcp.ur_w; + int ur_w_tail = jcp.ur_w_tail; + int n_oi = jcp.ow / ur_w; + int iw = jcp.iw; + int kw = jcp.kw; + int ic_blk = jcp.ic_block; + int oc_blk = jcp.oc_block; + int dilate_w = jcp.dilate_w + 1; + int str_w = jcp.stride_w; + const int inp_mult = one_of(jcp.src_tag, ncw, nchw) ? 1 : ic_blk; + + int l_pad = jcp.l_pad; + int r_pad = nstl::max(0, (int(jcp.ow) - 1) * str_w + (kw - 1) * dilate_w + - (iw + l_pad - 1)); + int r_pad1 = (ur_w * n_oi - 1) * str_w + (kw - 1) * dilate_w + - (iw + l_pad - 1); + if (r_pad1 > 0) n_oi--; + + if (l_pad > 0) { + n_oi--; + if (n_oi < 0 && r_pad1 > 0) + width_blk_step(ur_w, l_pad, r_pad1, oc_blocks); // "lrpad" + else + width_blk_step(ur_w, l_pad, 0, oc_blocks); // "lpad" + add(reg_input, sizeof(float) * (ur_w * str_w - l_pad) * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_blk); + } + + Label ow_loop; + xor_(oi_iter, oi_iter); + + if (n_oi > 0) { + L(ow_loop); + + width_blk_step(ur_w, 0, 0, oc_blocks); // "middle" + add(reg_input, sizeof(float) * ur_w * str_w * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_blk); + + inc(oi_iter); + cmp(oi_iter, n_oi); + jl(ow_loop, T_NEAR); + } + + if (r_pad1 > 0 && n_oi >=0) { + width_blk_step(ur_w, 0, r_pad1, oc_blocks); // "rpad" + add(reg_input, sizeof(float) * ur_w * str_w * inp_mult); + add(reg_output, sizeof(float) * ur_w * oc_blk); + } + + if (ur_w_tail != 0) + width_blk_step(ur_w_tail, 0, r_pad, oc_blocks); // "tail" +} + +void jit_sse42_conv_fwd_kernel_f32::generate() +{ + this->preamble(); + + mov(reg_input, ptr[this->param1 + GET_OFF(src)]); + mov(reg_output, ptr[this->param1 + GET_OFF(dst)]); + mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]); + if (jcp.with_bias) + mov(reg_bias, ptr[this->param1 + GET_OFF(bias)]); + mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]); + mov(reg_ci_flag, ptr[this->param1 + GET_OFF(flags)]); + mov(reg_oc_blocks, ptr[this->param1 + GET_OFF(oc_blocks)]); + + int nb_oc_tail = jcp.nb_oc % jcp.nb_oc_blocking; + Label tail, exit; + + cmp(reg_oc_blocks, jcp.nb_oc_blocking); + jne(nb_oc_tail ? tail : exit, T_NEAR); + + solve_common(jcp.nb_oc_blocking); + jmp(exit, T_NEAR); + + if (nb_oc_tail) { + L(tail); + cmp(reg_oc_blocks, nb_oc_tail); + jne(exit, T_NEAR); + solve_common(nb_oc_tail); + } + + L(exit); + + this->postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +bool jit_sse42_conv_fwd_kernel_f32::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + + return false; +} + +status_t jit_sse42_conv_fwd_kernel_f32::init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr) +{ + if (!mayiuse(sse42)) return status::unimplemented; + + jcp.prop_kind = cd.prop_kind; + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + const int ndims = src_d.ndims(); + jcp.ndims = ndims; + + jcp.ngroups = with_groups ? weights_d.dims()[0] : 1; + jcp.mb = src_d.dims()[0]; + + jcp.oc = dst_d.dims()[1] / jcp.ngroups; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2]; + jcp.iw = src_d.dims()[ndims - 1]; + jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2]; + jcp.ow = dst_d.dims()[ndims - 1]; + + jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2]; + jcp.kw = weights_d.dims()[with_groups + ndims - 1]; + + jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0]; + jcp.l_pad = cd.padding[0][ndims - 3]; + + jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0]; + jcp.stride_w = cd.strides[ndims - 3]; + + jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[0]; + jcp.dilate_w = cd.dilates[ndims - 3]; + jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1) + - (jcp.ih + jcp.t_pad - 1); + + if (ndims == 3) { + jcp.src_tag = src_d.matches_one_of_tag(ncw, nwc, nCw8c); + jcp.wei_tag = weights_d.matches_one_of_tag( + Owi8o, gOwi8o, OIw8i8o, gOIw8i8o); + jcp.dst_tag = dst_d.matches_one_of_tag(nCw8c); + } else if (ndims == 4) { + jcp.src_tag = src_d.matches_one_of_tag(nchw, nhwc, nChw8c); + jcp.wei_tag = weights_d.matches_one_of_tag( + Ohwi8o, gOhwi8o, OIhw8i8o, gOIhw8i8o); + jcp.dst_tag = dst_d.matches_one_of_tag(nChw8c); + } + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + jcp.with_sum = p.find(primitive_kind::sum) != -1; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + + const bool flat = jcp.ic == 3; + const bool mimo = !flat; + + bool args_ok = true + && IMPLICATION(flat, one_of(jcp.src_tag, ncw, nwc, nchw, nhwc) + && one_of(jcp.wei_tag, Owi8o, gOwi8o, Ohwi8o, gOhwi8o)) + && IMPLICATION(mimo, one_of(jcp.src_tag, nCw8c, nChw8c) + && one_of(jcp.wei_tag, OIw8i8o, gOIw8i8o, OIhw8i8o, gOIhw8i8o)) + && one_of(jcp.dst_tag, nCw8c, nChw8c); + if (!args_ok) return status::unimplemented; + + const int simd_w = 8; // 2 SSE vectors processing at once + + jcp.ur_h = 1; /* no code-unrolling by h so far */ + jcp.ur_w = 3; + if (jcp.ow < jcp.ur_w) jcp.ur_w = jcp.ow; + jcp.ur_w_tail = jcp.ow % jcp.ur_w; + + jcp.nb_oc_blocking = 4; /* the optimal value for the kernel */ + + args_ok = true + && jcp.oc % simd_w == 0 + && jcp.l_pad <= jcp.ur_w + && IMPLICATION(jcp.kw > 7, (jcp.t_pad == 0 && jcp.l_pad == 0) + || (jcp.stride_w == 1 && jcp.stride_h == 1)) + && IMPLICATION(mimo, jcp.ic % simd_w == 0); + if (!args_ok) return status::unimplemented; + + int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1)); + + // kernel needs 1 temporary YMM register + const int num_avail_regs = 15; + if (r_pad_no_tail > jcp.ur_w * jcp.stride_w && jcp.ow / jcp.ur_w > 1) { + /* recalculate ur_w, nb_oc_blocking and ur_w_tail */ + jcp.ur_w = nstl::min(r_pad_no_tail / jcp.stride_w + jcp.ur_w_tail, + nstl::min(jcp.ow, num_avail_regs / 2)); + jcp.nb_oc_blocking = (num_avail_regs - jcp.ur_w) / jcp.ur_w; + jcp.ur_w_tail = jcp.ow % jcp.ur_w; + /* check again ... */ + r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1)); + if (jcp.ur_w < nstl::max(jcp.l_pad, r_pad_no_tail)) + return status::unimplemented; + } + assert(jcp.nb_oc_blocking > 0); + assert(jcp.ur_w * (jcp.nb_oc_blocking + 1) <= num_avail_regs); + + jcp.ic_block = (jcp.ic % simd_w != 0) ? jcp.ic : simd_w; + jcp.nb_ic = jcp.ic / jcp.ic_block; + + jcp.oc_block = simd_w; + jcp.nb_oc = jcp.oc / jcp.oc_block; + + if (one_of(jcp.prop_kind, forward_training, forward_inference)) { + jcp.nb_ic_blocking = 12; + jcp.nb_ic_blocking_max = 16; + } else { + jcp.nb_ic_blocking = 1; + jcp.nb_ic_blocking_max = jcp.nb_ic_blocking; + } + + return status::success; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp new file mode 100644 index 0000000000..33c26ef081 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp @@ -0,0 +1,93 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_SSE42_CONV_KERNEL_F32_HPP +#define JIT_SSE42_CONV_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "cpu_memory.hpp" +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_sse42_conv_fwd_kernel_f32: public jit_generator { + jit_sse42_conv_fwd_kernel_f32(jit_conv_conf_t ajcp, + const primitive_attr_t &attr) + : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32(this, + jcp.eltwise); + + this->generate(); + jit_ker = (void (*)(jit_conv_call_s *))this->getCode(); + } + + ~jit_sse42_conv_fwd_kernel_f32() { + delete eltwise_injector_; + } + + static bool post_ops_ok(jit_conv_conf_t &jcp, + const primitive_attr_t &attr); + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, const primitive_attr_t &attr); + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_sse42_conv_fwd_kernel_f32) + jit_conv_conf_t jcp; + const primitive_attr_t &attr_; + void (*jit_ker)(jit_conv_call_s *); + +private: + using reg64_t = const Xbyak::Reg64; + reg64_t reg_input = rax; + reg64_t aux_reg_input = r8; + reg64_t reg_kernel = rdx; + reg64_t aux_reg_kernel = r9; + reg64_t reg_output = rsi; + reg64_t reg_bias = rbx; + + reg64_t kj = r10; + reg64_t oi_iter = r11; + reg64_t ki_iter = r12; + reg64_t reg_kh = abi_not_param1; + reg64_t simd_iter = r15; + reg64_t reg_oc_blocks = r14; + reg64_t imm_addr64 = reg_oc_blocks; + Xbyak::Reg32 reg_ci_flag = r13d; + + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + inline void oh_step_unroll_kw(int ur_w, int pad_l, int pad_r, + int oc_blocks); + inline void oh_step_nopad(int ur_w, int pad_l, int pad_r, int oc_blocks); + inline void width_blk_step(int ur_w, int pad_l, int pad_r, int oc_blocks); + inline void solve_common(int oc_blocks); + + void generate(); +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp new file mode 100644 index 0000000000..5f77d692f5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp @@ -0,0 +1,136 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "jit_sse42_convolution.hpp" +#include "mkldnn_thread.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::utils; + +#define src_blk_off(f, n, c, h, w) \ + (pd()->ndims() == 3) \ + ? (f).blk_off(n, c, w) \ + : (f).blk_off(n, c, h, w) + +#define wht_blk_off_(f, g, ...) \ + pd()->with_groups() \ + ? (f).blk_off(g, __VA_ARGS__) \ + : (f).blk_off(__VA_ARGS__) +#define wht_blk_off(f, g, oc, ic, kh, kw) \ + pd()->ndims() == 3 \ + ? wht_blk_off_(f, g, oc, ic, kw) \ + : wht_blk_off_(f, g, oc, ic, kh, kw) + +void jit_sse42_convolution_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const auto &jcp = kernel_->jcp; + + int ocb_work = div_up(jcp.nb_oc, jcp.nb_oc_blocking); + const size_t work_amount = jcp.mb * jcp.ngroups * ocb_work * jcp.oh; + + parallel(0, [&](const int ithr, const int nthr) { + size_t start{ 0 }, end{ 0 }; + balance211(work_amount, nthr, ithr, start, end); + + int icbb = 0; + while (icbb < jcp.nb_ic) { + int icb_step = jcp.nb_ic_blocking; + int icb_step_rem = jcp.nb_ic - icbb; + if (icb_step_rem < jcp.nb_ic_blocking_max) + icb_step = icb_step_rem; + + size_t n{0}, g{0}, ocbb{0}, oh{0}; + nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work, + oh, jcp.oh); + for (size_t iwork = start; iwork < end; ++iwork) { + int ocb = ocbb * jcp.nb_oc_blocking; + int ocb_num = jcp.nb_oc_blocking; + + for (int icb = icbb; icb < icbb + icb_step; ++icb) { + auto par_conv = jit_conv_call_s(); + + const int ij = oh * jcp.stride_h; + const int i_t_overflow = nstl::max(0, jcp.t_pad - ij); + const int i_b_overflow = nstl::max(jcp.ih, ij + + (jcp.kh-1) * (jcp.dilate_h+1) - jcp.t_pad+1) - jcp.ih; + + const size_t _oc = g * jcp.nb_oc + ocb; + const size_t _ic = g * jcp.nb_ic + icb; + + const int ih = nstl::max(ij - jcp.t_pad + + div_up(i_t_overflow, + (jcp.dilate_h+1)) * (jcp.dilate_h + 1), 0); + par_conv.src = &src[src_blk_off(src_d, n, + jcp.ic == 3 ? 0 : _ic, ih, 0)]; + + par_conv.dst = &dst[src_blk_off(dst_d, n, _oc, oh, 0)]; + + const int wh = div_up(i_t_overflow, (jcp.dilate_h + 1)); + par_conv.filt = &weights[wht_blk_off(weights_d, g, ocb, + jcp.ic == 3 ? 0 : icb, wh, 0)]; + + if (icb == 0) { + if (bias) + par_conv.bias = + &bias[bias_d.blk_off(_oc * jcp.oc_block)]; + par_conv.flags |= FLAG_IC_FIRST; + } + + if (jcp.with_eltwise && icb + 1 == jcp.nb_ic) { + par_conv.flags |= FLAG_IC_LAST; + } + + par_conv.oc_blocks = + nstl::min(ocb + ocb_num, jcp.nb_oc) - ocb; + + par_conv.kw_padding = 0; + const int kh_padding = jcp.kh + - div_up(i_t_overflow, (jcp.dilate_h + 1)) + - div_up(i_b_overflow, (jcp.dilate_h + 1)); + par_conv.kh_padding = nstl::max(0, kh_padding); + kernel_->jit_ker(&par_conv); + } + nd_iterator_step(n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work, + oh, jcp.oh); + } + icbb += icb_step; + } + }); + + if (pd()->wants_zero_pad_dst()) + ctx.memory(MKLDNN_ARG_DST)->zero_pad(); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp new file mode 100644 index 0000000000..d2f0a38c5c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp @@ -0,0 +1,103 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_SSE42_CONVOLUTION_HPP +#define CPU_JIT_SSE42_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_primitive_conf.hpp" +#include "jit_sse42_conv_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_sse42_convolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", sse42, ""), + jit_sse42_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + return jit_sse42_conv_fwd_kernel_f32::init_conf(jcp_, *desc(), + *src_md(), *weights_md(), *dst_md(), *attr()); + } + + jit_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + const bool flat = IC() == 3; + auto src_tag = flat + ? utils::pick(ndims() - 3, ncw, nchw, ncdhw) + : utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto dst_tag = + utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c); + auto wei_tag = with_groups() + ? utils::pick(2 * ndims() - 6 + flat, gOIw8i8o, gOwi8o, + gOIhw8i8o, gOhwi8o, gOIdhw8i8o, gOdhwi8o) + : utils::pick(2 * ndims() - 6 + flat, OIw8i8o, Owi8o, + OIhw8i8o, Ohwi8o, OIdhw8i8o, Odhwi8o); + + return set_default_formats_common(src_tag, wei_tag, dst_tag); + } + }; + + jit_sse42_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) + { kernel_ = new jit_sse42_conv_fwd_kernel_f32(pd()->jcp_, *pd()->attr()); } + ~jit_sse42_convolution_fwd_t() { delete kernel_; }; + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_sse42_conv_fwd_kernel_f32 *kernel_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp new file mode 100644 index 0000000000..0e734f7265 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp @@ -0,0 +1,1192 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "nstl.hpp" +#include "utils.hpp" +#include "jit_generator.hpp" +#include "cpu_barrier.hpp" + +#include "jit_transpose_src_utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; + +#define GET_OFF(x) offsetof(ctx_t, x) + +struct jit_trans_iw_ic_t: public jit_trans_src_t, public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_iw_ic_t) + + jit_trans_iw_ic_t(const jit_conv_conf_t *conf): jit_trans_src_t(conf) { + generate(); + ker_ = (decltype(ker_))this->getCode(); + } + +private: + using reg64_t = const Xbyak::Reg64; + using reg32_t = const Xbyak::Reg32; + using opmask_t = const Xbyak::Opmask; + + enum { typesize = sizeof(float), transpose_size = 16, small_spatial = 14 }; + int src_stride, tr_src_stride; + int tail; + bool enable_prefetch; + + opmask_t k3333 = k1; + opmask_t k5555 = k2; + opmask_t kAAAA = k3; + opmask_t kCCCC = k4; + opmask_t k0F0F = k5; + opmask_t kF0F0 = k6; + opmask_t kTail = k7; + + reg64_t reg_src = r8; + reg64_t reg_tr_src = r9; + reg64_t reg_src_prf = r10; + reg64_t reg_tr_src_prf = r11; + reg64_t reg_loop = r12; + reg64_t reg_tr_src_tmp = r13; + reg32_t regw_tmp = r14d; + + void transpose(int nrows, int l_pad, int r_pad, bool nontemporal_stores); + void generate(); +}; + +void jit_trans_iw_ic_t::transpose(int nrows, int l_pad, int r_pad, + bool nontemporal_stores) { + assert(nrows >= 0 && nrows <= transpose_size); + static_assert(transpose_size == 16, "Unsupported transpose size"); + if (!nrows) + return; + + auto pf_src_t0 = [=](int i) { + if(enable_prefetch) prefetcht0(EVEX_compress_addr(reg_src, + (transpose_size + i) * src_stride)); + }; + + auto pf_tr_src_t0 = [=](int i) { + int offset = (transpose_size) * typesize + i * tr_src_stride; + if(enable_prefetch) prefetcht0(EVEX_compress_addr(reg_tr_src, offset)); + if(enable_prefetch) prefetcht0(EVEX_compress_addr(reg_tr_src, + offset + 64)); + }; + + auto pf_src_t1 = [=](int i) { + if(enable_prefetch) prefetcht1(EVEX_compress_addr(reg_src_prf, + i * src_stride)); + }; + + auto pf_tr_src_t1 = [=](int i) { + if(enable_prefetch) prefetchwt1(EVEX_compress_addr(reg_tr_src_prf, + i * tr_src_stride)); + }; + + auto src_zmm = [=](int i) { + assert(i >= 0 && i < 16); + return Zmm(i); + }; + + auto tmp_zmm = [=](int i) { + assert(i >= 0 && i < 16); + return Zmm(16 + i); + }; + + auto load = [=](int i) { + vmovups(src_zmm(i), EVEX_compress_addr(reg_src, i * src_stride)); + }; + + auto store = [=](Zmm r, int i) { + auto kmovw = [=](Opmask k, unsigned w) { + mov(regw_tmp, w); + jit_generator::kmovw(k, regw_tmp); + }; + + auto padding = [=] (Reg64 reg, int pad) { + kmovw(kTail, (1 << pad) - 1); + auto k = kTail; + auto base = reg; + base.setOpmaskIdx(k.getIdx(), true); + + auto zmm_zero = r; + vpxord(zmm_zero, zmm_zero, zmm_zero); + auto addr = EVEX_compress_addr(base, i * tr_src_stride); + vmovups(addr, zmm_zero); + }; + + mov(reg_tr_src_tmp, reg_tr_src); + if (l_pad > 0) + add(reg_tr_src_tmp, l_pad * typesize); + + if (tail != transpose_size) + kmovw(kTail, (1 << tail) - 1); + + // Xbyak does not allow k0 to be specified explicitly via the '|' + // operator, so we have to do this via a method call (implicitly + // EVEX encoding uses k0 to mean 'no mask') + bool partial_store = nrows < 16; + auto k = partial_store ? kTail : k0; + auto base = reg_tr_src_tmp; + base.setOpmaskIdx(k.getIdx(), true); + + auto addr = EVEX_compress_addr(base, i * tr_src_stride); + if (nontemporal_stores && !partial_store) + vmovntps(addr, r); + else + vmovups(addr, r); + + if (r_pad > 0) { + add(reg_tr_src_tmp, tail * typesize); + padding(reg_tr_src_tmp, r_pad); + } + + if (l_pad > 0) { + padding(reg_tr_src, l_pad); + } + }; + + auto transpose16x8 = [=](int base_idx) { + assert(base_idx == 0 || base_idx == 8); + + // swap 1 + for (int i = 0; i < 4; i++) { + int src_idx0 = base_idx + i * 2; + int src_idx1 = src_idx0 + 1; + + int next_src_idx0 = src_idx0 + 2; + int next_src_idx1 = src_idx1 + 2; + bool load_next = base_idx == 0 || i < 3; + + if (base_idx == 0 && i == 0) { + load(src_idx0); + load(src_idx1); + } + + auto tmp0 = tmp_zmm(src_idx0); + auto tmp1 = tmp_zmm(src_idx1); + auto src0 = src_zmm(src_idx0); + auto src1 = src_zmm(src_idx1); + + if (next_src_idx0 < nrows && load_next) + load(next_src_idx0); + valignd(tmp0, src0, src0, 0x1); + pf_src_t1(base_idx + i); + + if (next_src_idx1 < nrows && load_next) + load(next_src_idx1); + valignd(tmp1, src1, src1, 0xf); + pf_src_t0(base_idx + i); + + vmovaps(src0 | kAAAA, tmp1); + vmovaps(src1 | k5555, tmp0); + } + // swap 2 + for (int i = 0; i < 4; i++) { + int select_half = (i < 2) ? 0 : 2; + int src_idx0 = base_idx + i + select_half + 0; + int src_idx2 = src_idx0 + 2; + + auto tmp0 = tmp_zmm(src_idx0); + auto tmp1 = tmp_zmm(src_idx2); + auto src0 = src_zmm(src_idx0); + auto src2 = src_zmm(src_idx2); + + valignd(tmp0, src0, src0, 0x2); + pf_src_t1(base_idx + 4 + i); + valignd(tmp1, src2, src2, 0xe); + pf_src_t0(base_idx + 4 + i); + vmovaps(src2 | k3333, tmp0); + vmovaps(src0 | kCCCC, tmp1); + } + + // swap 4 + for (int i = 0; i < 4; i++) { + int src_idx0 = base_idx + i; + int src_idx4 = src_idx0 + 4; + + auto tmp0 = tmp_zmm(src_idx0); + auto src0 = src_zmm(src_idx0); + auto src4 = src_zmm(src_idx4); + + vmovaps(tmp0, src0); + vshuff32x4(src0 | kF0F0, src4, src4, 0xb1); + pf_tr_src_t1(base_idx / 2 + i); + vshuff32x4(src4 | k0F0F, tmp0, tmp0, 0xb1); + pf_tr_src_t0(base_idx / 2 + i); + } + }; + + auto fixup16x16 = [=]() { + // swap 8 + for (int i = 0; i < 8; i++) { + auto tmp = tmp_zmm(i); + auto src0 = src_zmm(i); + auto src8 = src_zmm(8 + i); + vshuff64x2(tmp, src0, src8, 0x44); + store(tmp, i); + if (i % 2 == 0) { + pf_tr_src_t1(8 + i / 2); + pf_tr_src_t0(8 + i / 2); + } + } + + for (int i = 0; i < 8; i++) { + auto tmp = tmp_zmm(8 + i); + auto src0 = src_zmm(i); + auto src8 = src_zmm(8 + i); + vshuff64x2(tmp, src0, src8, 0xee); + store(tmp, 8 + i); + if (i % 2 == 0) { + pf_tr_src_t1(12 + i / 2); + pf_tr_src_t0(12 + i / 2); + } + } + }; + + transpose16x8(0); + transpose16x8(8); + fixup16x16(); +} + +void jit_trans_iw_ic_t::generate() { + preamble(); + + const int ic_block = conf_->ic_block; + const int iw = conf_->iw; + const int tr_iw = conf_->tr_iw; + const int transposes = utils::div_up(iw, transpose_size); + int loop_iters = nstl::max(0, transposes - 1); + tail = iw - loop_iters * transpose_size; + + src_stride = ic_block * typesize; + assert(src_stride == 64); + tr_src_stride = tr_iw * typesize; + + bool nontemporal_stores = false; + enable_prefetch = iw > small_spatial ? 1 : 0; + + assert(transpose_size == ic_block); + const int src_step = ic_block * transpose_size * typesize; + const int tr_src_step = ic_block * typesize; + + const int left_pad = conf_->l_pad; + const int right_pad = tr_iw - iw - left_pad; + + mov(reg_src, ptr [param1 + GET_OFF(src)]); + mov(reg_tr_src, ptr [param1 + GET_OFF(tr_src)]); + mov(reg_src_prf, ptr [param1 + GET_OFF(src_prf)]); + mov(reg_tr_src_prf, ptr [param1 + GET_OFF(tr_src_prf)]); + + auto kmovw = [=](Opmask k, unsigned w) { + mov(regw_tmp, w); + jit_generator::kmovw(k, regw_tmp); + }; + + kmovw(k3333, 0x3333); // 0011001100110011 + kmovw(k5555, 0x5555); // 0101010101010101 + kmovw(kAAAA, 0xaaaa); // 1010101010101010 + kmovw(kCCCC, 0xcccc); // 1100110011001100 + kmovw(k0F0F, 0x0f0f); // 0000111100001111 + kmovw(kF0F0, 0xf0f0); // 1111000011110000 + + if (left_pad > 0 && loop_iters > 0) { + loop_iters--; + transpose(transpose_size, left_pad, 0, nontemporal_stores); + add(reg_src, src_step); + add(reg_tr_src, tr_src_step + left_pad * typesize); + add(reg_src_prf, src_step); + add(reg_tr_src_prf, tr_src_step + left_pad * typesize); + } + + if (loop_iters) { + mov(reg_loop, loop_iters); + Label loop; + L(loop); { + transpose(transpose_size, 0, 0, nontemporal_stores); + add(reg_src, src_step); + add(reg_tr_src, tr_src_step); + add(reg_src_prf, src_step); + add(reg_tr_src_prf, tr_src_step); + sub(reg_loop, 1); + jnz(loop); + } + } + if (transposes > 1) + transpose(tail, 0, right_pad, nontemporal_stores); + else + transpose(tail, left_pad, right_pad, nontemporal_stores); + + postamble(); +} + +struct jit_trans_iw_ic_int16_t: public jit_trans_src_t, public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_iw_ic_int16_t) + jit_trans_iw_ic_int16_t(const jit_conv_conf_t *conf): + jit_trans_src_t(conf) { + generate(); + ker_ = (decltype(ker_))this->getCode(); + } + +private: + using reg64_t = const Xbyak::Reg64; + using reg32_t = const Xbyak::Reg32; + using opmask_t = const Xbyak::Opmask; + + enum { typesize = sizeof(int16_t), transpose_size = 16, small_spatial = 14 }; + int src_stride, tr_src_stride; + int tail; + bool enable_prefetch; + + opmask_t kFFFF = k1; + opmask_t k5555 = k2; + opmask_t kAAAA = k3; + opmask_t kAA = k4; + opmask_t k55 = k5; + opmask_t kCC = k6; + opmask_t k33 = k7; + opmask_t kTail = k1; + + reg64_t reg_src = r8; + reg64_t reg_tr_src = r9; + reg64_t reg_src_prf = r10; + reg64_t reg_tr_src_prf = r11; + reg64_t reg_loop = r12; + reg64_t reg_tr_src_tmp = r13; + reg32_t regw_tmp = r14d; + reg64_t imm_addr64 = rbx; + + Xbyak::Zmm vidx1 = zmm31; + Xbyak::Zmm vidx2 = zmm30; + Xbyak::Zmm vidx3 = zmm29; + Xbyak::Zmm vidx4 = zmm28; + Xbyak::Zmm vidx5 = zmm27; + Xbyak::Zmm zmm_tmp = zmm26; + + + void transpose(int nrows, int l_pad, int r_pad, bool nontemporal_stores); + void generate(); +}; + +void jit_trans_iw_ic_int16_t::transpose(int nrows, int l_pad, int r_pad, + bool nontemporal_stores) { + assert(nrows >= 0 && nrows <= transpose_size); + static_assert(transpose_size == 16, "Unsupported transpose size"); + if (!nrows) + return; + + auto src_zmm = [=](int i) { + return Zmm(i); + }; + + auto src_ymm = [=](int i) { + assert(i >= 0 && i < 16); + return Ymm(i); + }; + + auto load_ymm = [=](int i) { + vmovups(src_ymm(i), EVEX_compress_addr(reg_src, i * src_stride)); + }; + + auto kmovw = [=](Opmask k, unsigned w) { + mov(regw_tmp, w); + jit_generator::kmovw(k, regw_tmp); + }; + + auto store = [=](Zmm r, int i) { + + auto padding = [=] (Reg64 reg, int pad) { + kmovw(kTail, (1 << pad) - 1); + auto k = kTail; + auto base = reg; + base.setOpmaskIdx(k.getIdx(), true); + + auto zmm_zero = zmm_tmp; + vpxord(zmm_zero, zmm_zero, zmm_zero); + auto addr = EVEX_compress_addr(base, i * tr_src_stride); + vmovups(addr, zmm_zero); + }; + + int store_tail = (nrows%2) ? nrows+1 : nrows; + + int store_pad = (l_pad%2) ? l_pad/2 + 1 : l_pad/2; + mov(reg_tr_src_tmp, reg_tr_src); + if (l_pad > 0) { + padding(reg_tr_src, store_pad); + add(reg_tr_src_tmp, l_pad * typesize); + } + if (r_pad > 0) { + store_pad = (r_pad%2) ? r_pad/2 + 1 : r_pad/2; + int addr_shift = (r_pad%2) ? 1 : 0; + add(reg_tr_src_tmp, (nrows - addr_shift) * typesize); + padding(reg_tr_src_tmp, store_pad); + } + + mov(reg_tr_src_tmp, reg_tr_src); + add(reg_tr_src_tmp, l_pad * typesize); + + kmovw(kTail, (1 << store_tail/2) - 1); + auto k = kTail; + auto base = reg_tr_src_tmp; + base.setOpmaskIdx(k.getIdx(), true); + + auto addr = EVEX_compress_addr(base, i * tr_src_stride); + vmovups(addr, r); + + }; + + kmovw(kFFFF, 0xffff); + //all loads + for (int i=0; i<16; i++){ + vpxord(src_zmm(i), src_zmm(i), src_zmm(i)); + } + + for (int i = 0; i < nrows/2; i++) { + auto src0 = src_ymm(2*i); + auto src1 = src_ymm(2*i+1); + auto zmm_src0 = src_zmm(2*i); + load_ymm(2*i); + + vpunpcklwd(src1, src0, + EVEX_compress_addr(reg_src, (2*i+1) * src_stride)); + vpunpckhwd(src0, src0, + EVEX_compress_addr(reg_src, (2*i+1) * src_stride)); + vinserti64x4(zmm_src0, zmm_src0, src1, 1); + vpermps(zmm_src0 | kFFFF, vidx4, zmm_src0); + } + + // for odd numbers we need to mix row with zeroes + if (nrows%2) { + int i = nrows-1; + auto src0 = src_ymm(i); + auto src1 = src_ymm(i+1); //zero + + auto zmm_src0 = src_zmm(i); + vpxor(src1, src1, src1); + + load_ymm(i); + vpunpckhwd(src0, src0, src1); + vinserti64x4(zmm_tmp, zmm_tmp, src0, 0); + vpxor(src0, src0, src0); + load_ymm(i); + vpunpcklwd(src1, src0, src1); + vinserti64x4(zmm_tmp, zmm_tmp, src1, 1); + vpxord(zmm_src0, zmm_src0, zmm_src0); + vmovups(zmm_src0, zmm_tmp); + vpermps(zmm_src0 | kFFFF, vidx4, zmm_src0); + } + + // swap 1 + for (int i=0; i<4; i++) { + auto zmm0 = src_zmm(4*i); + auto zmm1 = src_zmm(4*i+2); + auto tmp0 = src_zmm(4*i+1); + auto tmp1 = src_zmm(4*i+3); + + vmovups(tmp0, zmm0); + vmovups(tmp1, zmm1); + + vpermps(tmp0 | kAAAA, vidx3, zmm1); + vpermps(tmp1 | k5555, vidx3, zmm0); + } + // swap 2 + int base_idx; + base_idx=0; + for (int i=0; i<2; i++) { + auto zmm0 = src_zmm(base_idx+2*i+1); + auto zmm1 = src_zmm(base_idx+2*i+5); + + auto tmp0 = src_zmm(base_idx+2*i); + auto tmp1 = src_zmm(base_idx+2*i+4); + + vmovupd(tmp0, zmm0); + vmovupd(tmp1, zmm1); + + vpermpd(tmp0 | kAA, vidx2, zmm1); + vpermpd(tmp1 | k55, vidx2, zmm0); + } + base_idx=8; + for (int i=0; i<2; i++) { + auto zmm0 = src_zmm(base_idx+2*i+1); + auto zmm1 = src_zmm(base_idx+2*i+5); + + auto tmp0 = src_zmm(base_idx+2*i); + auto tmp1 = src_zmm(base_idx+2*i+4); + + vmovupd(tmp0, zmm0); + vmovupd(tmp1, zmm1); + + vpermpd(tmp0 | kAA, vidx2, zmm1); + vpermpd(tmp1 | k55, vidx2, zmm0); + } + + // swap 3 + for (int i=0; i<4; i++) { + auto zmm0 = src_zmm(2*i); + auto zmm1 = src_zmm(2*i+8); + + auto tmp0 = src_zmm(2*i+1); + auto tmp1 = src_zmm(2*i+9); + + vmovupd(tmp0, zmm0); + vmovupd(tmp1, zmm1); + + vpermpd(tmp0 | kCC, vidx1, zmm1); + vpermpd(tmp1 | k33, vidx1, zmm0); + } + + // all stores + for (int i=0; i<8; i++) + vextracti64x4(src_ymm(2*i), src_zmm(2*i+1), 1); + + store(src_zmm(1), 0); + store(src_zmm(0), 1); + store(src_zmm(3), 2); + store(src_zmm(2), 3); + store(src_zmm(9), 4); + store(src_zmm(8), 5); + store(src_zmm(11), 6); + store(src_zmm(10), 7); + store(src_zmm(5), 8); + store(src_zmm(4), 9); + store(src_zmm(7), 10); + store(src_zmm(6), 11); + store(src_zmm(13), 12); + store(src_zmm(12), 13); + store(src_zmm(15), 14); + store(src_zmm(14), 15); + +} + +void jit_trans_iw_ic_int16_t::generate() { + preamble(); + + alignas(64) static constexpr const int64_t idx1[8] + = { 2, 3, 0, 1, 6, 7, 4, 5 }; + alignas(64) static constexpr const int64_t idx2[8] + = { 1, 0, 3, 2, 5, 4, 7, 6 }; + alignas(64) static constexpr const int32_t idx3[16] + = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }; + alignas(64) static constexpr const int32_t idx4[16] + = { 8, 10, 12, 14, 0, 2, 4, 6, 9, 11, 13, 15, 1, 3, 5, 7 }; + alignas(64) static constexpr const int32_t idx5[16] + = { 8, 10, 12, 14, 0, 2, 4, 6, 9, 11, 13, 15, 1, 3, 5, 7 }; + + const int ic_block = conf_->ic_block; + const int iw = conf_->iw; + const int tr_iw = conf_->tr_iw; + const int transposes = utils::div_up(iw, transpose_size); + int loop_iters = nstl::max(0, transposes - 1); + tail = iw - loop_iters * transpose_size; + + src_stride = ic_block * typesize; + tr_src_stride = tr_iw * typesize; + + bool nontemporal_stores = false; + enable_prefetch = iw > small_spatial ? 1 : 0; + + assert(transpose_size == ic_block); + const int src_step = ic_block * transpose_size * typesize; + const int tr_src_step = ic_block * typesize; + + const int left_pad = conf_->l_pad; + const int right_pad = tr_iw - iw - left_pad; + + mov(reg_src, ptr [param1 + GET_OFF(src)]); + mov(reg_tr_src, ptr [param1 + GET_OFF(tr_src)]); + mov(reg_src_prf, ptr [param1 + GET_OFF(src_prf)]); + mov(reg_tr_src_prf, ptr [param1 + GET_OFF(tr_src_prf)]); + + auto kmovw = [=](Opmask k, unsigned w) { + mov(regw_tmp, w); + jit_generator::kmovw(k, regw_tmp); + }; + + kmovw(kFFFF, 0xffff); + kmovw(k5555, 0x5555); + kmovw(kAAAA, 0xaaaa); + kmovw(kAA, 0xaa); + kmovw(k55, 0x55); + kmovw(kCC, 0xcc); + kmovw(k33, 0x33); + + auto vmovdqa64 = [=](Zmm z, const int64_t *addr) { + mov(imm_addr64, reinterpret_cast(addr)); + jit_generator::vmovdqa64(z, ptr[imm_addr64]); + }; + + auto vmovdqa32 = [=](Zmm z, const int32_t *addr) { + mov(imm_addr64, reinterpret_cast(addr)); + jit_generator::vmovdqa32(z, ptr[imm_addr64]); + }; + + vmovdqa64(vidx1, idx1); + vmovdqa64(vidx2, idx2); + vmovdqa32(vidx3, idx3); + vmovdqa32(vidx4, idx4); + vmovdqa32(vidx5, idx5); + + if (left_pad > 0 && loop_iters > 0) { + loop_iters--; + transpose(transpose_size, left_pad, 0, nontemporal_stores); + add(reg_src, src_step); + add(reg_tr_src, tr_src_step + left_pad * typesize); + add(reg_src_prf, src_step); + add(reg_tr_src_prf, tr_src_step + left_pad * typesize); + } + + if (loop_iters) { + mov(reg_loop, loop_iters); + Label loop; + L(loop); { + transpose(transpose_size, 0, 0, nontemporal_stores); + add(reg_src, src_step); + add(reg_tr_src, tr_src_step); + add(reg_src_prf, src_step); + add(reg_tr_src_prf, tr_src_step); + sub(reg_loop, 1); + jnz(loop); + } + } + if (transposes > 1) + transpose(tail, 0, right_pad, nontemporal_stores); + else + transpose(tail, left_pad, right_pad, nontemporal_stores); + + postamble(); + +} + +struct jit_trans_ow_oc_t: public jit_trans_dst_t, public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_ow_oc_t) + jit_trans_ow_oc_t(const jit_conv_conf_t *conf): jit_trans_dst_t(conf) { + generate(); + ker_ = (decltype(ker_))this->getCode(); + } + +private: + using reg64_t = const Xbyak::Reg64; + using reg32_t = const Xbyak::Reg32; + using opmask_t = const Xbyak::Opmask; + using zmm = const Xbyak::Zmm; + + enum { typesize = sizeof(int16_t), transpose_size = 16, small_spatial = 14 }; + int src_stride, tr_src_stride; + int tail; + bool enable_prefetch; + + opmask_t kFF = k1; + + zmm vidx1 = zmm31; + + reg64_t reg_src = r8; + reg64_t reg_tr_src = r9; + reg64_t reg_src_prf = r10; + reg64_t reg_tr_src_prf = r11; + reg64_t reg_loop = r12; + reg64_t reg_tr_src_tmp = r13; + reg32_t regw_tmp = r14d; + reg64_t imm_addr64 = rbx; + + void transpose(int nrows, int l_pad, int r_pad, bool nontemporal_stores); + void generate(); +}; + +void jit_trans_ow_oc_t::transpose(int nrows, int l_pad, int r_pad, + bool nontemporal_stores) { + assert(nrows >= 0 && nrows <= transpose_size); + static_assert(transpose_size == 16, "Unsupported transpose size"); + if (!nrows) + return; + + auto src_zmm = [=](int i) { + return Zmm(i); + }; + + auto src_ymm = [=](int i) { + assert(i >= 0 && i < 16); + return Ymm(i); + }; + + auto load_ymm = [=](int i) { + vmovups(src_ymm(i), EVEX_compress_addr(reg_src, i * src_stride)); + }; + + + auto store = [=](Zmm r, int i) { + auto addr = EVEX_compress_addr(reg_tr_src, i * tr_src_stride); + if (nontemporal_stores) + vmovntps(addr, r); + else + vmovups(addr, r); + }; + + for (int i = 0; i < nrows/2; i++) { + auto src0 = src_ymm(2*i); + auto src1 = src_ymm(2*i+1); + auto zmm_src0 = src_zmm(2*i); + load_ymm(2*i); + vpunpcklwd(src1, src0, + EVEX_compress_addr(reg_src, (2*i+1) * src_stride)); + vpunpckhwd(src0, src0, + EVEX_compress_addr(reg_src, (2*i+1) * src_stride)); + vinserti64x4(zmm_src0, zmm_src0, src1, 1); + vpermpd(zmm_src0 | kFF, vidx1, zmm_src0); + store(zmm_src0, 2*i); + } + if (r_pad > 0) { + auto src0 = src_ymm(nrows-1); + auto src1 = src_ymm(nrows); + auto zmm_src0 = src_zmm(30); + load_ymm(nrows-1); + + vpxor(src1, src1, src1); + vpunpckhwd(src1, src0, src1); + vinserti64x4(zmm_src0, zmm_src0, src1, 0); + vpxor(src1, src1, src1); + vpunpcklwd(src0, src0, src1); + vinserti64x4(zmm_src0, zmm_src0, src0, 1); + vpermpd(zmm_src0 | kFF, vidx1, zmm_src0); + store(zmm_src0, nrows-1); + } +} + +void jit_trans_ow_oc_t::generate() { + preamble(); + + alignas(64) static constexpr const int64_t idx1[8] + = { 4, 5, 0, 1, 6, 7, 2, 3 }; + + const int oc_block = conf_->oc_block; + const int ow = conf_->ow; + const int transposes = utils::div_up(ow, transpose_size); + int loop_iters = nstl::max(0, transposes - 1); + tail = ow - loop_iters * transpose_size; + + src_stride = oc_block * typesize; + tr_src_stride = oc_block * typesize; + + bool nontemporal_stores = false; + enable_prefetch = ow > small_spatial ? 1 : 0; + + const int src_step = oc_block * transpose_size * typesize; + const int tr_src_step = oc_block * transpose_size * typesize; + const int right_pad = ow % 2; + + mov(reg_src, ptr [param1 + GET_OFF(src)]); + mov(reg_tr_src, ptr [param1 + GET_OFF(tr_src)]); + mov(reg_src_prf, ptr [param1 + GET_OFF(src_prf)]); + mov(reg_tr_src_prf, ptr [param1 + GET_OFF(tr_src_prf)]); + + auto kmovw = [=](Opmask k, unsigned w) { + mov(regw_tmp, w); + jit_generator::kmovw(k, regw_tmp); + }; + + kmovw(kFF, 0xFF); + + auto vmovdqa64 = [=](Zmm z, const int64_t *addr) { + mov(imm_addr64, reinterpret_cast(addr)); + jit_generator::vmovdqa64(z, ptr[imm_addr64]); + }; + + vmovdqa64(vidx1, idx1); + if (loop_iters) { + mov(reg_loop, loop_iters); + Label loop; + L(loop); { + transpose(transpose_size, 0, 0, nontemporal_stores); + add(reg_src, src_step); + add(reg_tr_src, tr_src_step); + add(reg_src_prf, src_step); + add(reg_tr_src_prf, tr_src_step); + sub(reg_loop, 1); + jnz(loop); + } + } + transpose(tail, 0, right_pad, nontemporal_stores); + + postamble(); +} + +struct jit_trans_iw_x4_4x_t: public jit_trans_src_t, public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_iw_x4_4x_t) + + jit_trans_iw_x4_4x_t(const jit_conv_conf_t *conf): jit_trans_src_t(conf) { + generate(); + ker_ = (decltype(ker_))this->getCode(); + } + + void generate(); + enum { typesize = (int)sizeof(float) }; +}; + +/** @brief transposition of the form [:][iw/4][4] -> [:][4][iw/4] + * required for 1st 4fma backward by weights convolution */ +void jit_trans_iw_x4_4x_t::generate() { + using namespace utils; + + /* TODO: put into code */ + static int mask[16] = { + 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, }; + + const auto &c = *conf_; + const int simd_w = cpu_isa_traits::vlen / typesize; + const int niters = c.tr_ld / simd_w; + + assert(niters <= 4); /* [bwd_w:tr_src:r1] */ + + Reg64 reg_ptr_src = r8; + Reg64 reg_ptr_tr_src = r9; + + Reg64 reg_ih = rax; + Reg64 reg_ih_end = rbx; + + Reg64 reg_nthr_oc_b = rsi; + Reg64 reg_ptr_tr_src_bctx = abi_not_param1; + + Reg64 reg_tmp = rdx; + + Zmm vmsk = Zmm(31); + Opmask kmsk = k7; + + auto emit_tr_sync = [&]() { + simple_barrier::generate(*this, reg_ptr_tr_src_bctx, reg_nthr_oc_b); + }; + + auto emit_tr_iw = [&]() { + auto vreg = [](int iter, int i) { + assert(4 * iter + i < 24); + return Zmm(4 * iter + i); + }; + auto vtmp = [](int i) { return Zmm(24 + i); }; + + auto emit_load = [&](int iter) { + for (int i = 0; i < 4; ++i) { + auto v = vreg(iter, i); + const int off = (iter * 4 + i) * simd_w; + + if (off + simd_w <= c.iw) + vmovups(v, ptr[reg_ptr_src + off * typesize]); + else if (off < c.iw) + vmovups(v | kmsk | T_z, ptr[reg_ptr_src + off * typesize]); + else + vpxord(v, v, v); + } + }; + + auto emit_tr = [&](int iter) { + for (int i = 0; i < 4; ++i) + vpermps(vreg(iter, i), vmsk, vreg(iter, i)); + + vshuff32x4(vtmp(0), vreg(iter, 0), vreg(iter, 1), 0x88); + vshuff32x4(vtmp(1), vreg(iter, 0), vreg(iter, 1), 0xdd); + vshuff32x4(vtmp(2), vreg(iter, 2), vreg(iter, 3), 0x88); + vshuff32x4(vtmp(3), vreg(iter, 2), vreg(iter, 3), 0xdd); + + vshuff32x4(vreg(iter, 0), vtmp(0), vtmp(2), 0x88); + vshuff32x4(vreg(iter, 2), vtmp(0), vtmp(2), 0xdd); + vshuff32x4(vreg(iter, 1), vtmp(1), vtmp(3), 0x88); + vshuff32x4(vreg(iter, 3), vtmp(1), vtmp(3), 0xdd); + }; + + auto emit_store = [&]() { + for (int i = 0; i < 4; ++i) { + for (int iter = 0; iter < niters; ++iter) { + const size_t off = i * c.tr_ld + iter * simd_w; + vmovups(ptr[reg_ptr_tr_src + off * typesize], vreg(iter, i)); + } + } + }; + + for (int iter = 0; iter < niters; ++iter) + emit_load(iter); + + for (int iter = 0; iter < niters; ++iter) + emit_tr(iter); + + emit_store(); + }; + + preamble(); + + mov(reg_ptr_src, ptr[abi_param1 + GET_OFF(src)]); + mov(reg_ptr_tr_src, ptr[abi_param1 + GET_OFF(tr_src)]); + + mov(reg_nthr_oc_b.cvt32(), ptr[abi_param1 + GET_OFF(nthr_oc_b)]); + mov(reg_ih.cvt32(), ptr[abi_param1 + GET_OFF(tr_src_ih_start)]); + mov(reg_ih_end.cvt32(), ptr[abi_param1 + GET_OFF(tr_src_ih_end)]); + mov(reg_ptr_tr_src_bctx, ptr[abi_param1 + GET_OFF(tr_src_bctx)]); + + emit_tr_sync(); + + Label l_ih_loop, l_tr_done; + cmp(reg_ih, reg_ih_end); + je(l_tr_done, T_NEAR); + + mov(reg_tmp, (size_t)&mask[0]); + vmovups(vmsk, ptr[reg_tmp]); + + if (c.iw % simd_w) { + const char load_mask = (1 << (c.iw % simd_w)) - 1; + mov(reg_tmp, load_mask); + kmovw(kmsk, reg_tmp.cvt32()); + } + + /* src += ih_start * c.iw; */ + imul(reg_tmp, reg_ih, c.iw * typesize); + add(reg_ptr_src, reg_tmp); + /* tr_src += ih_start * c.stride_w * c.tr_ld; */ + imul(reg_tmp, reg_ih, c.stride_w * c.tr_ld * typesize); + add(reg_ptr_tr_src, reg_tmp); + + L(l_ih_loop); { + emit_tr_iw(); + + add(reg_ptr_src, c.iw * typesize); + add(reg_ptr_tr_src, c.stride_w * c.tr_ld * typesize); + + inc(reg_ih); + cmp(reg_ih, reg_ih_end); + jl(l_ih_loop, T_NEAR); + } + + L(l_tr_done); + + emit_tr_sync(); + + postamble(); +} + +/* +// ------------------------------------------------- +// jit_transpose4x16_src +// ------------------------------------------------- +*/ + +void jit_transpose4x16_src::transpose(int nrows) +{ + assert(nrows >= 0 && nrows <= transpose_size); + static_assert(transpose_size == 4, "Unsupported transpose size"); + if (!nrows) + return; + + auto pf_src_t0 = [=](int i) { + if (tparams->src_pf0_distance) + prefetcht0(EVEX_compress_addr( + reg_src, (tparams->src_pf0_distance + i) * src_stride)); + }; + + auto pf_tr_src_t0 = [=](int i) { + if (tparams->tr_src_pf0_distance) + prefetcht0(EVEX_compress_addr(reg_tr_src, + (tparams->tr_src_pf0_distance + i) * src_stride)); + }; + + auto pf_src_t1 = [=](int i) { + if (tparams->src_pf1) + prefetcht1(EVEX_compress_addr(reg_src_prf, i * src_stride)); + }; + + auto pf_tr_src_t1 = [=](int i) { + if (tparams->tr_src_pf1) + prefetchwt1(EVEX_compress_addr(reg_tr_src_prf, i * tr_src_stride)); + }; + + auto src_zmm = [=](int i) { + assert(i >= 0 && i < 4); + return Zmm(i); + }; + + auto tmp_zmm = [=](int i) { + assert(i >= 0 && i < 4); + return Zmm(4 + i); + }; + + auto load = [=](int i) { + vmovups(src_zmm(i), EVEX_compress_addr(reg_src, i * src_stride)); + }; + + auto store = [=](Zmm r, int i) { + vmovups(EVEX_compress_addr(reg_tr_src, i * tr_src_stride), r); + }; + + auto tmp0 = tmp_zmm(0); + auto tmp1 = tmp_zmm(1); + auto tmp2 = tmp_zmm(2); + auto tmp3 = tmp_zmm(3); + + auto src0 = src_zmm(0); + auto src1 = src_zmm(1); + auto src2 = src_zmm(2); + auto src3 = src_zmm(3); + for (int i = 0; i < nrows; i++) { + load(i); + } + + for (size_t i = nrows; i < 4; i++) { + vpxord(src_zmm(i), src_zmm(i), src_zmm(i)); + } + + vmovupd(tmp0, src0); + vmovupd(tmp1, src1); + pf_src_t0(0); + vpermpd(tmp0 | kF0, vidx01, src2); + vpermpd(tmp1 | kF0, vidx01, src3); + + valignd(src0, src0, src0, 8); + valignd(src1, src1, src1, 8); + pf_src_t0(1); + vmovupd(tmp2, src0); + vmovupd(tmp3, src1); + pf_src_t0(2); + vpermpd(tmp2 | kF0, vidx10, src2); + vpermpd(tmp3 | kF0, vidx10, src3); + pf_src_t0(3); + + vmovupd(src0, tmp0); + pf_src_t1(0); + vmovupd(src1, tmp2); + pf_src_t1(1); + vmovupd(src2, tmp1); + pf_src_t1(2); + vmovupd(src3, tmp3); + pf_src_t1(3); + vpermpd(src0 | kCC, vidx1, tmp1); + vpermpd(src1 | kCC, vidx1, tmp3); + pf_tr_src_t0(0); + vpermpd(src2 | k33, vidx1, tmp0); + vpermpd(src3 | k33, vidx1, tmp2); + pf_tr_src_t0(1); + + vmovupd(tmp0, src0); + vmovupd(tmp1, src2); + pf_tr_src_t0(2); + vmovupd(tmp2, src1); + vmovupd(tmp3, src3); + pf_tr_src_t0(3); + vpermps(tmp0 | kFFFF, vidxP, src0); + pf_tr_src_t1(0); + vpermps(tmp1 | kFFFF, vidxP, src2); + pf_tr_src_t1(1); + vpermps(tmp2 | kFFFF, vidxP, src1); + pf_tr_src_t1(3); + vpermps(tmp3 | kFFFF, vidxP, src3); + pf_tr_src_t1(4); + + store(tmp0, 0); + store(tmp1, 1); + store(tmp2, 2); + store(tmp3, 3); +} + +alignas(64) static constexpr const int64_t idx01[8] + = { 0, 0, 0, 0, 0, 1, 2, 3 }; +alignas(64) static constexpr const int64_t idx10[8] + = { 0, 0, 0, 0, 4, 5, 6, 7 }; +alignas(64) static constexpr const int64_t idx1[8] = { 2, 3, 0, 1, 6, 7, 4, 5 }; +alignas(64) static constexpr const int32_t idxP[16] + = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; + +void jit_transpose4x16_src::generate() +{ + preamble(); + + const int ic_block = params->ic_block; + const int is = params->is; + int tail = is % transpose_size; + + src_stride = ic_block * typesize; + assert(src_stride == 64); + tr_src_stride = ic_block * typesize; + + const int src_step = ic_block * transpose_size * typesize; + const int tr_src_step = ic_block * transpose_size * typesize; + +#define GET_TR_OFF(x) offsetof(jit_src_transpose_s, x) + mov(reg_loop, ptr[param1 + GET_TR_OFF(size)]); + mov(reg_src, ptr[param1 + GET_TR_OFF(src)]); + mov(reg_tr_src, ptr[param1 + GET_TR_OFF(tr_src)]); + mov(reg_src_prf, ptr[param1 + GET_TR_OFF(src_prf)]); + mov(reg_tr_src_prf, ptr[param1 + GET_TR_OFF(tr_src_prf)]); +#undef GET_TR_OFF + + auto kmovw = [=](Opmask k, unsigned w) { + mov(regw_tmp, w); + jit_generator::kmovw(k, regw_tmp); + }; + + auto vmovdqa64 = [=](Zmm z, const int64_t *addr) { + mov(imm_addr64, reinterpret_cast(addr)); + jit_generator::vmovdqa64(z, ptr[imm_addr64]); + }; + + auto vmovdqa32 = [=](Zmm z, const int32_t *addr) { + mov(imm_addr64, reinterpret_cast(addr)); + jit_generator::vmovdqa32(z, ptr[imm_addr64]); + }; + + kmovw(kF0, 0xf0); // 11110000 + kmovw(kCC, 0xcc); // 11001100 + kmovw(k33, 0x33); // 00110011 + kmovw(kFFFF, 0xffff); // 1111111111111111 + + vmovdqa64(vidx01, idx01); + vmovdqa64(vidx10, idx10); + vmovdqa64(vidx1, idx1); + vmovdqa32(vidxP, idxP); + + Label loop_label; + Label tail_label; + + cmp(reg_loop, transpose_size); + jl(tail_label, T_NEAR); + + L(loop_label); + { + transpose(transpose_size); + add(reg_src, src_step); + add(reg_tr_src, tr_src_step); + add(reg_src_prf, src_step); + add(reg_tr_src_prf, tr_src_step); + sub(reg_loop, transpose_size); + cmp(reg_loop, transpose_size); + jge(loop_label, T_NEAR); + } + L(tail_label); + transpose(tail); + + postamble(); +} + +jit_trans_src_t *create_trans_src(const jit_conv_conf_t *conf) { + if (conf->ver == ver_4fma && !conf->is_1stconv) + return new jit_trans_iw_ic_t(conf); + if (conf->ver == ver_4fma && conf->is_1stconv) + return new jit_trans_iw_x4_4x_t(conf); + assert(!"unsupported configuration"); + return nullptr; +} + +jit_trans_dst_t *create_trans_dst(const jit_conv_conf_t *conf) { + assert(!"unsupported configuration"); + return nullptr; +} +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp new file mode 100644 index 0000000000..565e97e4fc --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp @@ -0,0 +1,145 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_TRANSPOSE_SRC_HPP +#define CPU_JIT_TRANSPOSE_SRC_HPP + +#include "cpu_barrier.hpp" +#include "jit_primitive_conf.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_trans_src_t { + struct ctx_t { + const void *src; + const void *tr_src; + const void *src_prf; + const void *tr_src_prf; + + /* 1st conv 4fma: backward by weights */ + int nthr_oc_b; /* number of threads process given src image */ + int tr_src_ih_start, tr_src_ih_end; /* thread's transposition bounds */ + simple_barrier::ctx_t *tr_src_bctx; /* transposition synchronization */ + }; + + jit_trans_src_t(const jit_conv_conf_t *conf) + : conf_(conf), ker_(nullptr) {} + virtual ~jit_trans_src_t() {} + + void operator()(const ctx_t *ctx) + { assert(ker_); ker_(ctx); } + + const jit_conv_conf_t *conf_; + void (*ker_)(const ctx_t *); +}; + +struct jit_src_transpose_s { + size_t size; + const void *src; + const void *tr_src; + const void *src_prf; + const void *tr_src_prf; +}; + +struct jit_trans_dst_t { + struct ctx_t { + const void *src; + const void *tr_src; + const void *src_prf; + const void *tr_src_prf; + + /* 1st conv 4fma: backward by weights */ + int nthr_oc_b; /* number of threads process given src image */ + int tr_src_ih_start, tr_src_ih_end; /* thread's transposition bounds */ + simple_barrier::ctx_t *tr_src_bctx; /* transposition synchronization */ + }; + + jit_trans_dst_t(const jit_conv_conf_t *conf) + : conf_(conf), ker_(nullptr) {} + virtual ~jit_trans_dst_t() {} + + void operator()(const ctx_t *ctx) + { assert(ker_); ker_(ctx); } + + const jit_conv_conf_t *conf_; + void (*ker_)(const ctx_t *); +}; + +struct jit_transpose4x16_src_t { + int src_pf0_distance; + int tr_src_pf0_distance; + bool src_pf1; + bool tr_src_pf1; +}; + +struct jit_transpose4x16_src : public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_transpose4x16_src) + + jit_transpose4x16_src(const jit_1x1_conv_conf_t *aparams, + jit_transpose4x16_src_t *tparams_) + : params(aparams), tparams(tparams_) + { + this->generate(); + jit_ker = (decltype(jit_ker))this->getCode(); + } + + const jit_1x1_conv_conf_t *params; + const jit_transpose4x16_src_t *tparams; + void (*jit_ker)(jit_src_transpose_s *); + + void operator()(jit_src_transpose_s *arg) { jit_ker(arg); } + + static const int transpose_size = 4; +private: + static const int typesize = sizeof(float); + + int src_stride, tr_src_stride; + + Xbyak::Reg64 imm_addr64 = rbx; + + Xbyak::Opmask kF0 = k1; + Xbyak::Opmask kCC = k2; + Xbyak::Opmask k33 = k3; + Xbyak::Opmask kFFFF = k4; + + Xbyak::Zmm vidx01 = zmm31; + Xbyak::Zmm vidx10 = zmm30; + Xbyak::Zmm vidx1 = zmm29; + Xbyak::Zmm vidxP = zmm28; + + Xbyak::Reg64 reg_src = r8; + Xbyak::Reg64 reg_tr_src = r9; + Xbyak::Reg64 reg_src_prf = r10; + Xbyak::Reg64 reg_tr_src_prf = r11; + Xbyak::Reg64 reg_loop = r12; + Xbyak::Reg64 reg_tr_src_tmp = r13; + Xbyak::Reg32 regw_tmp = r14d; + + void transpose_block(int ur, int nrows); + void transpose(int nrows); + void generate(); +}; + +jit_trans_src_t *create_trans_src(const jit_conv_conf_t *conf); +jit_trans_dst_t *create_trans_dst(const jit_conv_conf_t *conf); + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp new file mode 100644 index 0000000000..53313f9f01 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp @@ -0,0 +1,327 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_UNI_1x1_CONV_UTILS_HPP +#define JIT_UNI_1x1_CONV_UTILS_HPP + +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; + +struct reduce_to_unit_stride_t { + convolution_desc_t conv_d_; + bool reduce_src_; + size_t space_per_thread_; +}; + +/* 1x1-kernel does not support non-unit strides so far, so the idea is: + * - for fwd or bwd_weights: to copy src to a scratch memory (with strides + * equal to 1) and then call the kernel + * - for bwd_data: reduce the problem to the one with unit stride by + * performing computations in a scratch memory (with strides equal to 1) + * and then copy the result to diff_src */ +template +inline void rtus_prepare(conv_pd_t *self, const convolution_desc_t *&conv_d, + const memory_desc_t *&src_d, const memory_desc_t *dst_d) { + const bool is_bwd_data = self->desc()->prop_kind + == prop_kind::backward_data; + + const int ndims = src_d->ndims; + const auto dat_tag = ndims == 3 + ? memory_desc_wrapper(dst_d).matches_one_of_tag( + format_tag::nCw8c, format_tag::nCw16c) + : memory_desc_wrapper(dst_d).matches_one_of_tag( + format_tag::nChw8c, format_tag::nChw16c); + + bool rtus_applicable = true + && utils::pick(ndims - 3, + (conv_d->strides[0] != 1 && !one_of(conv_d->src_desc.data_type, + data_type::s32)), + (conv_d->strides[0] != 1 || conv_d->strides[1] != 1)) + && dat_tag != format_tag::undef; + for (int d = 2; d < ndims; ++d) { + /* TODO: relax these conditions (by improving reducer) */ + rtus_applicable = rtus_applicable + && conv_d->padding[0][d - 2] == 0 + && dst_d->dims[d] * conv_d->strides[d - 2] == src_d->dims[d]; + } + + if (rtus_applicable) { + self->rtus_.reduce_src_ = true; + conv_d = &(self->rtus_.conv_d_ = *conv_d); + self->rtus_.conv_d_.strides[0] = 1; + if (ndims == 4) + self->rtus_.conv_d_.strides[1] = 1; + utils::array_set(self->rtus_.conv_d_.padding[0], 0, 2); + if (ndims == 4) + utils::array_set(self->rtus_.conv_d_.padding[1], 0, 2); + const int ic = src_d->dims[1]; + if (is_bwd_data) { + src_d = &(self->rtus_.conv_d_.diff_src_desc = *dst_d); + self->rtus_.conv_d_.diff_src_desc.dims[1] = ic; + memory_desc_wrapper::compute_blocking( + self->rtus_.conv_d_.diff_src_desc, dat_tag); + } else { + data_type_t data_type = self->rtus_.conv_d_.src_desc.data_type; + src_d = &(self->rtus_.conv_d_.src_desc = *dst_d); + self->rtus_.conv_d_.src_desc.dims[1] = ic; + self->rtus_.conv_d_.src_desc.data_type = data_type; + memory_desc_wrapper::compute_blocking( + self->rtus_.conv_d_.src_desc, dat_tag); + } + } +} + +template +inline void rtus_prepare_space_info(conv_pd_t *self, + memory_tracking::registrar_t &scratchpad) { + const auto &jcp = self->jcp_; + + const int max_threads = mkldnn_get_max_threads(); + const size_t factor = utils::pick_by_prop_kind(self->desc()->prop_kind, + jcp.nb_reduce, jcp.nb_load_blocking_max, jcp.nb_bcast_blocking); + size_t typesize = types::data_type_size( + conv_prop_invariant_src_d(self->desc())->data_type); + + self->rtus_.space_per_thread_ = factor * jcp.is * jcp.ic_block; + scratchpad.book(memory_tracking::names::key_conv_rtus_space, + typesize * max_threads * self->rtus_.space_per_thread_); +} + +template +struct rtus_driver_t: public jit_generator { + + struct call_params_t { + const void *ws; /* reduced image (w/ strides = 1) */ + const void *src; /* source image (w/ non-unit strides) */ + size_t icb; + size_t os; + size_t iw_start; + }; + + void (*ker_)(const call_params_t *p); + + DECLARE_CPU_JIT_AUX_FUNCTIONS(rtus_driver_t) + + /* cpu specific part */ + using Vmm = typename utils::conditional::type; + + Xbyak::Reg64 reg_ws = abi_param1; + Xbyak::Reg64 reg_src = abi_not_param1; + Xbyak::Reg64 reg_icb = rdx; + Xbyak::Reg64 reg_os = r11; + Xbyak::Reg64 reg_iw_start = r8; + + Xbyak::Reg64 reg_cur_os = rax; + Xbyak::Reg64 reg_cur_iw = r9; + Xbyak::Reg64 reg_cur_src = r10; + + int iw_, stride_w_; + int src_step_h_, src_step_icb_, ws_step_icb_, vlen_, vlen_shift_; + bool src_to_ws_; + size_t typesize_; + Vmm reg_zero; + Vmm reg_v; + + rtus_driver_t(int iw, int stride_w, int src_step_h, + int src_step_icb, int ws_step_icb, bool src_to_ws, size_t typesize) + : iw_(iw), stride_w_(stride_w), src_step_h_(src_step_h) + , src_step_icb_(src_step_icb), ws_step_icb_(ws_step_icb) + , src_to_ws_(src_to_ws), typesize_(typesize) + { + using namespace Xbyak; + vlen_ = cpu_isa_traits::vlen; + vlen_shift_ = cpu_isa_traits::vlen_shift; + if (typesize_ == 2) { + vlen_ /= 2; + vlen_shift_--; + } + + reg_zero = Vmm(0); + reg_v = Vmm(1); + + generate(); + } + + void loop_is() { + using namespace Xbyak; + + mov(reg_cur_src, reg_src); + mov(reg_cur_iw, reg_iw_start); + mov(reg_cur_os, reg_os); + + Label is_loop, skip_h_step; + L(is_loop); + + if (src_to_ws_) { + vmovups(reg_v, ptr[reg_cur_src]); + vmovups(ptr[reg_ws], reg_v); + } else { + vmovups(reg_v, ptr[reg_ws]); + vmovups(ptr[reg_cur_src], reg_v); + for (int w = 1; w < stride_w_; ++w) + vmovups(ptr[reg_cur_src + w * vlen_], reg_zero); + } + + add(reg_ws, vlen_); + + add(reg_cur_iw, stride_w_); + add(reg_cur_src, stride_w_ * vlen_); + + cmp(reg_cur_iw, iw_); + jl(skip_h_step); + /* for 1d convolution the loop over h should be skipped */ + if (src_step_icb_ == iw_) jmp(skip_h_step); + + if (src_to_ws_) { + add(reg_cur_src, (src_step_h_ - iw_) * vlen_); + } else { + Xbyak::Reg64 reg_cur_src_fin = reg_cur_iw; /* just reuse */ + mov(reg_cur_src_fin, reg_cur_src); + add(reg_cur_src_fin, (src_step_h_ - iw_) * vlen_); + Label ih_loop; + L(ih_loop); + + for (int w = 0; w < stride_w_; ++w) + vmovups(ptr[reg_cur_src + w * vlen_], reg_zero); + + add(reg_cur_src, stride_w_ * vlen_); + cmp(reg_cur_src, reg_cur_src_fin); + jl(ih_loop); + } + xor_(reg_cur_iw, reg_cur_iw); + + L(skip_h_step); + + sub(reg_cur_os, vlen_); + jnz(is_loop); + + /* restore dst */ + sub(reg_ws, reg_os); + } + + void generate() { + using namespace Xbyak; + assert(isa == avx2 || isa == avx512_common + || isa == avx512_core || isa == avx512_mic); + +#if defined(_WIN32) + assert(reg_src == abi_not_param1 && abi_not_param1 == rdi); + push(rdi); +#endif + +#define READ_PARAM(what) \ + mov(reg_ ## what, ptr[abi_param1 + offsetof(call_params_t, what)]) + READ_PARAM(src); + READ_PARAM(icb); + READ_PARAM(os); + READ_PARAM(iw_start); + + assert(reg_ws == abi_param1); + READ_PARAM(ws); /* reg_ws should always be read the last */ +#undef READ_PARAM + + shl(reg_os, vlen_shift_); + + if (!src_to_ws_) + uni_vpxor(reg_zero, reg_zero, reg_zero); + + Label icb_loop; + L(icb_loop); + + loop_is(); + + add(reg_ws, ws_step_icb_ * vlen_); + add(reg_src, src_step_icb_ * vlen_); + + dec(reg_icb); + jnz(icb_loop, T_NEAR); + +#if defined(_WIN32) + pop(rdi); +#endif + + uni_vzeroupper(); + ret(); + this->ker_ = reinterpret_cast(const_cast( + this->getCode())); + } +}; + +template +inline void init_rtus_driver(conv_t *self) { + const auto &conf = *self->pd(); + if (!conf.rtus_.reduce_src_) return; + + const auto &cd = *conf.desc(); + const int ndims = conf.ndims(); + const int stride_h = (conf.ndims() == 3) ? 1 : cd.strides[0]; + const int stride_w = cd.strides[ndims - 3]; + + const bool is_bwd_data = cd.prop_kind == prop_kind::backward_data; + const auto &src_d = is_bwd_data ? *conf.diff_src_md() : *conf.src_md(); + + const int ih = ndims == 3 ? 1 : src_d.dims[2]; + const int iw = src_d.dims[ndims - 1]; + + const int src_step_h = stride_h * iw; + const int src_step_icb = ih * iw; + const int ws_step_icb = conf.jcp_.is; + const bool src_to_ws = !is_bwd_data; + const size_t typesize = types::data_type_size( + conv_prop_invariant_src_d(self->pd()->desc())->data_type); + + self->rtus_driver_ = new rtus_driver_t(iw, stride_w, src_step_h, + src_step_icb, ws_step_icb, src_to_ws, typesize); +} + +inline int best_divider(int value, int min_divider, int max_divider, + bool find_max, int step = 1) +{ + max_divider = nstl::max(1, nstl::min(max_divider, value)); + min_divider = nstl::max(1, nstl::min(min_divider, max_divider)); + + auto loss_ratio = [](int total, int chunk) + { return float(rnd_up(total, chunk) - total) / rnd_up(total, chunk); }; + + float min_loss = FLT_MAX; + int x_divider = max_divider; + for (int divider = max_divider; divider >= min_divider; divider -= step) { + const float loss = loss_ratio(value, divider); + if ((find_max && loss < min_loss) || (!find_max && loss <= min_loss)) { + min_loss = loss; + x_divider = divider; + } + } + return x_divider; +} + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp new file mode 100644 index 0000000000..72fe3a8109 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp @@ -0,0 +1,1407 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "math_utils.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_barrier.hpp" +#include "cpu_batch_normalization_utils.hpp" +#include "jit_generator.hpp" + +#include "jit_uni_batch_normalization.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace { + +using namespace memory_tracking::names; + +using namespace Xbyak; +namespace barrier = simple_barrier; + +typedef float data_t; + +template +struct jit_bnorm_t: public jit_generator { + struct call_params_t { + // keep all sizes at 8 bytes -- jit code expects this + size_t N_ithr, N_nthr; + size_t coff_max, soff_max; + size_t mb_stride_Bc, spat_size, spat_size_loc; + size_t S_s, S_tail; + size_t is_cblk_tail; + data_t chan_size, eps, one; + const data_t *scale_shift; + const data_t *mean, *var; + const data_t *diff_scale_shift; + const data_t *src, *dst; + const data_t *diff_src, *diff_dst; + const data_t *rbuf1, *rbuf2; + const uint8_t *ws; + barrier::ctx_t *barrier; + }; + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_bnorm_t) + + /* cpu specific part */ + using Vmm = typename utils::conditional3::type; + const AddressFrame &vmmword = (isa == sse42) ? xword : + (isa == avx2) ? yword : zword; + + const int vlen = isa == sse42 ? 32 : cpu_isa_traits::vlen; + + const batch_normalization_pd_t *bdesc_; + bool is_spatial_thr_; + + void (*ker)(const call_params_t *); + void operator()(const call_params_t *p) { (*ker)(p); } + + Reg64 reg_param = abi_param1; + + Reg64 reg_scale_shift = rbx; + Reg64 reg_rbuf1 = abi_not_param1; + Reg64 reg_rbuf2 = rdx; + + Reg64 reg_mean = rbp; + Reg64 reg_var = reg_param; + Reg64 reg_diff_scale_shift = rax; + + Reg64 reg_coff = r8; + Reg64 reg_coff_max = r9; + Reg64 reg_soff = r10; + Reg64 reg_soff_max = r11; + Reg64 reg_ctr = r12; + Reg64 reg_roff = r13; + + Reg64 reg_mb_stride_Bc = r14; + + Reg64 reg_src = r15; + Reg64 reg_diff_src = reg_rbuf1; + Reg64 reg_dst = rsi; + Reg64 reg_diff_dst = reg_dst; + + Reg64 reg_tmp_off = reg_roff; + + // Reuse loop counters + Reg64 reg_bar = reg_coff; + Reg64 reg_nnthr = reg_soff; // must be usable w/ loops over coff + Reg64 reg_tmp = reg_ctr; + + // Relu section + bool with_relu, with_relu_inf_only; + Vmm vzero; // is_fwd() ? vdiff_beta : vbeta + Reg64 reg_ws = reg_roff; + Label l_relu_mask_avx2; + Opmask kstore_mask = Opmask(1); + + // channel tail processing + Opmask ktail_mask = Opmask(2); + + size_t unroll_blocks; + size_t unroll_regs; + Vmm vbuf = Vmm(isa == avx512_common ? 20 : 5); + Vmm vdiff_beta = Vmm(isa == avx512_common ? 21 : 6); + Vmm vdiff_gamma = Vmm(isa == avx512_common ? 22 : 7); + Vmm vsqrtvar = Vmm(isa == avx512_common ? 23 : 8); + Vmm vone = Vmm(isa == avx512_common ? 24 : 9); + Vmm vmean = Vmm(isa == avx512_common ? 25 : 10); + Vmm vgamma = Vmm(isa == avx512_common ? 26 : 11); + Vmm vbeta = Vmm(isa == avx512_common ? 27 : 12); + Vmm veps = Vmm(isa == avx512_common ? 28 : 13); + Vmm vchan_size = Vmm(isa == avx512_common ? 29 : 14); + Vmm vtail_mask = Vmm(isa == avx512_common ? 30 : 15); + + size_t t0_pf_offt; + size_t t1_pf_offt; + size_t spat_size; + size_t chan_data_offt; + + enum { + stack_off_N_nthr = 0, + stack_off_N_ithr = 8, + stack_off_src = 16, + stack_off_dst = 24, + stack_off_diff_src = 32, + stack_off_diff_dst = 40, + stack_off_diff_scale_shift = 48, + stack_off_ws = 56, + stack_off_barrier = 64, + stack_off_spat_size_loc = 72, + stack_off_s_s = 80, + stack_off_s_tail = 88, + stack_off_is_cblk_tail = 96, + stack_size_required = 104, + }; + + bool is_c_padded() const { + const memory_desc_wrapper data_d(bdesc_->src_md()); + return bdesc_->C() != data_d.padded_dims()[1]; + } + + void compute_static_strides() { + spat_size = bdesc_->D() * bdesc_->W() * bdesc_->H(); + chan_data_offt = bdesc_->C() * sizeof(data_t); + + if (isa == avx512_mic) { + t0_pf_offt = 4096; + t1_pf_offt = 0; + } else { + t0_pf_offt = 0; + t1_pf_offt = 0; + } + } + + void load_common_params() { +# define PARAM_OFF(x) offsetof(call_params_t, x) + mov(reg_rbuf1, ptr[reg_param + PARAM_OFF(rbuf1)]); + if (bdesc_->is_bwd()) + mov(reg_rbuf2, ptr[reg_param + PARAM_OFF(rbuf2)]); + mov(reg_coff_max, ptr[reg_param + PARAM_OFF(coff_max)]); + mov(reg_soff_max, ptr[reg_param + PARAM_OFF(soff_max)]); + mov(reg_mb_stride_Bc, ptr[reg_param + PARAM_OFF(mb_stride_Bc)]); + shl(reg_coff_max, 2); + shl(reg_soff_max, 2); + shl(reg_mb_stride_Bc, 2); + + mov(reg_mean, ptr[reg_param + PARAM_OFF(mean)]); + mov(reg_scale_shift, ptr[reg_param + PARAM_OFF(scale_shift)]); + + uni_vbroadcastss(vchan_size, vmmword[reg_param + PARAM_OFF(chan_size)]); + uni_vbroadcastss(vone, vmmword[reg_param + PARAM_OFF(one)]); + uni_vbroadcastss(veps, vmmword[reg_param + PARAM_OFF(eps)]); + + mov(reg_tmp, ptr[reg_param + PARAM_OFF(N_nthr)]); + mov(ptr[rsp + stack_off_N_nthr], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(N_ithr)]); + mov(ptr[rsp + stack_off_N_ithr], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(src)]); + mov(ptr[rsp + stack_off_src], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(dst)]); + mov(ptr[rsp + stack_off_dst], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(diff_src)]); + mov(ptr[rsp + stack_off_diff_src], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(diff_dst)]); + mov(ptr[rsp + stack_off_diff_dst], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(ws)]); + mov(ptr[rsp + stack_off_ws], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(barrier)]); + mov(ptr[rsp + stack_off_barrier], reg_tmp); + if (is_spatial_thr_) { + mov(reg_tmp, ptr[reg_param + PARAM_OFF(spat_size_loc)]); + mov(ptr[rsp + stack_off_spat_size_loc], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(S_s)]); + mov(ptr[rsp + stack_off_s_s], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(S_tail)]); + mov(ptr[rsp + stack_off_s_tail], reg_tmp); + } + if (is_c_padded()) { + mov(reg_tmp, ptr[reg_param + PARAM_OFF(is_cblk_tail)]); + mov(ptr[rsp + stack_off_is_cblk_tail], reg_tmp); + } + + if (bdesc_->is_fwd()) { + mov(reg_tmp, ptr[reg_param + PARAM_OFF(var)]); + mov(reg_var, reg_tmp); + } else { + mov(reg_tmp, ptr[reg_param + PARAM_OFF(diff_scale_shift)]); + mov(ptr[rsp + stack_off_diff_scale_shift], reg_tmp); + mov(reg_tmp, ptr[reg_param + PARAM_OFF(var)]); + mov(reg_var, reg_tmp); + } +# undef PARAM_OFF + } + + void prepare_tail_mask_avx512_common() { + if (!is_c_padded()) return; + + const int tail = bdesc_->C() % (int)(vlen / sizeof(float)); + const int mask = (1 << tail) - 1; + + Reg32 regw_tmp = reg_tmp.cvt32(); + mov(regw_tmp, mask); + kmovw(ktail_mask, regw_tmp); + } + + void prepare_tail_mask_avx2_common() { + if (!is_c_padded()) return; + + const int tail = bdesc_->C() % (int)(vlen / sizeof(float)); + static const uint32_t mask[16] = {0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0, 0, 0, 0, 0, 0, 0, 0}; + + mov(reg_tmp, reinterpret_cast(&mask[8 - tail])); + vmovups(vtail_mask, ptr[reg_tmp]); + } + + void prepare_relu() { + with_relu = bdesc_->is_fwd() + ? bdesc_->with_relu_post_op() || bdesc_->fuse_bn_relu() + : bdesc_->fuse_bn_relu(); + with_relu_inf_only = with_relu && bdesc_->is_fwd() + && !(bdesc_->fuse_bn_relu() && bdesc_->is_training()); + + vzero = bdesc_->is_fwd() ? vdiff_beta : vbeta; + if (with_relu) { + uni_vpxor(vzero, vzero, vzero); + if (!bdesc_->is_fwd() && isa == avx2) + prepare_l_relu_mask_avx2(); + } + } + + void prepare_l_relu_mask_avx2() { + Label l_mask_after; + jmp(l_mask_after); + align(32); + L(l_relu_mask_avx2); /* [0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01] */ + for (int i = 0; i < 8; ++i) dd(1< + void spat_loop(size_t len, size_t blocks, size_t regs, + init_t init, body_t body, fini_t fini) { + size_t factor = regs * blocks; + size_t loop_unroll = len / factor * factor; + size_t loop_tail = len - loop_unroll; + size_t num_active_regs = (len < regs) ? len : regs; + for (size_t i = 0; i < num_active_regs; i++) + init(i); + if (loop_unroll) { + if (is_spatial_thr_) { + mov(reg_ctr, ptr[rsp + stack_off_spat_size_loc]); + add(reg_soff, ptr[rsp + stack_off_s_s]); + } else { + mov(reg_ctr, loop_unroll); + } + Label label; + L(label); { + for (size_t i = 0; i < factor; i++) { + size_t base_reg = i % regs; + body(base_reg, i); + } + add(reg_soff, factor * vlen); + sub(reg_ctr, factor); + jnz(label); + } + if (is_spatial_thr_) { + add(reg_soff, ptr[rsp + stack_off_s_tail]); + } + } + + for (size_t i = 0; i < loop_tail; i++) { + size_t base_reg = i % regs; + body(base_reg, i); + } + if (loop_tail) + add(reg_soff, loop_tail * vlen); + + for (size_t i = 0; i < num_active_regs; i++) + fini(i); + } + + void mean_channels() { + Label ch_label; + L(ch_label); { + uni_vmovups(Vmm(0), vmmword[reg_rbuf1 + reg_coff]); + spat_loop(spat_size, unroll_blocks, + unroll_regs, + [=](size_t base_reg) { + Vmm v = Vmm(base_reg * 2); + if (base_reg) + uni_vpxor(v, v, v); + }, + [=](size_t base_reg, size_t i) { + Vmm v0 = Vmm(base_reg * 2 + 0); + Vmm v1 = Vmm(base_reg * 2 + 1); + size_t offt = i * vlen; + uni_vmovups(v1, + vmmword[reg_src + reg_soff + offt]); + uni_vaddps(v0, v0, v1); + mic_prefetcht0(ptr[reg_src + reg_soff + offt + + t0_pf_offt]); + mic_prefetcht1(ptr[reg_src + reg_soff + offt + + t1_pf_offt]); + }, + [=](size_t base_reg) { + Vmm b = Vmm(0); + Vmm v = Vmm(base_reg * 2); + if (base_reg) + uni_vaddps(b, b, v); + }); + uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0)); + + add(reg_coff, vlen); + cmp(reg_coff, reg_coff_max); + jl(ch_label); + } + } + + void var_channels() { + Label ch_label; + L(ch_label); { + uni_vmovups_maybe_tail(vmean, mean_ptr()); + uni_vmovups(Vmm(0), vmmword[reg_rbuf1 + reg_coff]); + spat_loop(spat_size, unroll_blocks, unroll_regs, + [=](size_t base_reg) { + Vmm v = Vmm(base_reg * 3); + if (base_reg > 0) + uni_vpxor(v, v, v); + }, + [=](size_t base_reg, size_t i) { + Vmm v = Vmm(3 * base_reg); + Vmm vtmp0 = Vmm(3 * base_reg + 1); + Vmm vtmp1 = Vmm(3 * base_reg + 2); + size_t offt = i * vlen; + uni_vmovups(vtmp0, + vmmword[reg_src + reg_soff + offt]); + if (isa == sse42) { + movups(vtmp1, vmean); + subps(vtmp1, vtmp0); + } else { + vsubps(vtmp1, vmean, vtmp0); + } + uni_vfmadd231ps(v, vtmp1, vtmp1); + + mic_prefetcht0(ptr[reg_src + reg_soff + offt + + t0_pf_offt]); + mic_prefetcht1(ptr[reg_src + reg_soff + offt + + t1_pf_offt]); + }, + [=](size_t base_reg) { + Vmm b = Vmm(0); + Vmm v = Vmm(base_reg * 3); + if (base_reg) + uni_vaddps(b, b, v); + }); + uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0)); + add(reg_coff, vlen); + cmp(reg_coff, reg_coff_max); + jl(ch_label); + } + } + + void compute_mean_variance() { + uni_vpxor(Vmm(0), Vmm(0), Vmm(0)); + xor_(reg_coff, reg_coff); + Label zero_rbuf; + L(zero_rbuf); { + uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0)); + add(reg_coff, isa == sse42 ? vlen / 2 : vlen); + cmp(reg_coff, reg_coff_max); + jne(zero_rbuf); + } + + mov(reg_src, ptr[rsp + stack_off_src]); + + xor_(reg_soff, reg_soff); + Label mean_spatial; + L(mean_spatial); { + xor_(reg_coff, reg_coff); + + if (isa == sse42) + mov(reg_tmp_off, reg_soff); + + mean_channels(); + + if (isa == sse42) { + mov(reg_soff, reg_tmp_off); + add(reg_src, vlen / 2); + mov(reg_coff, vlen / 2); + + mean_channels(); + + sub(reg_src, vlen / 2); + } + + add(reg_soff, reg_mb_stride_Bc); + cmp(reg_soff, reg_soff_max); + jne(mean_spatial); + } + + Label no_mean_reduction; + barrier(); { + mov(reg_tmp, ptr[rsp + stack_off_N_ithr]); + cmp(reg_tmp, 0); + jne(no_mean_reduction); + mov(reg_nnthr, ptr[rsp + stack_off_N_nthr]); + xor_(reg_coff, reg_coff); + Label mean_reduction_channels; + L(mean_reduction_channels); { + mov(reg_roff, reg_coff); + uni_vpxor(Vmm(0), Vmm(0), Vmm(0)); + uni_vpxor(Vmm(1), Vmm(1), Vmm(1)); + mov(reg_ctr, reg_nnthr); + Label mean_reduction_thrs; + L(mean_reduction_thrs); { + uni_vaddps(Vmm(1), Vmm(1), vmmword[reg_rbuf1 + reg_roff]); + uni_vmovups(vmmword[reg_rbuf1 + reg_roff], Vmm(0)); + add(reg_roff, reg_coff_max); + sub(reg_ctr, 1); + jnz(mean_reduction_thrs); + } + uni_vdivps(Vmm(1), Vmm(1), vchan_size); + uni_vmovups_maybe_tail(mean_ptr(), Vmm(1)); + + add(reg_coff, isa == sse42 ? vlen / 2 : vlen); + + cmp(reg_coff, reg_coff_max); + jne(mean_reduction_channels); + } + } + L(no_mean_reduction); + barrier(); + + xor_(reg_soff, reg_soff); + Label var_spatial; + L(var_spatial); { + xor_(reg_coff, reg_coff); + + if (isa == sse42) + mov(reg_tmp_off, reg_soff); + + var_channels(); + + if (isa == sse42) { + mov(reg_soff, reg_tmp_off); + add(reg_src, vlen / 2); + mov(reg_coff, vlen / 2); + + var_channels(); + + sub(reg_src, vlen / 2); + } + + add(reg_soff, reg_mb_stride_Bc); + cmp(reg_soff, reg_soff_max); + jne(var_spatial); + } + + Label no_var_reduction; + barrier(); { + mov(reg_tmp, ptr[rsp + stack_off_N_ithr]); + cmp(reg_tmp, 0); + jne(no_var_reduction); + + mov(reg_nnthr, ptr[rsp + stack_off_N_nthr]); + xor_(reg_coff, reg_coff); + Label var_reduction_channels; + L(var_reduction_channels); { + mov(reg_roff, reg_coff); + uni_vpxor(Vmm(1), Vmm(1), Vmm(1)); + mov(reg_ctr, reg_nnthr); + Label var_reduction_thrs; + L(var_reduction_thrs); { // TODO: unroll (?) + uni_vaddps(Vmm(1), Vmm(1), vmmword[reg_rbuf1 + reg_roff]); + add(reg_roff, reg_coff_max); + sub(reg_ctr, 1); + jnz(var_reduction_thrs); + } + uni_vdivps(Vmm(1), Vmm(1), vchan_size); + uni_vmovups_maybe_tail(var_ptr(), Vmm(1)); + add(reg_coff, isa == sse42 ? vlen / 2 : vlen); + + cmp(reg_coff, reg_coff_max); + jne(var_reduction_channels); + } + } + L(no_var_reduction); + barrier(); + } + + void forward_channels() { + Label ch_label; + L(ch_label); { + uni_vmovups_maybe_tail(vmean, mean_ptr()); + uni_vmovups_maybe_tail(vsqrtvar, var_ptr()); + uni_vaddps(vsqrtvar, vsqrtvar, veps); + uni_vsqrtps(vsqrtvar, vsqrtvar); + + if (bdesc_->use_scaleshift()) { + uni_vmovups_maybe_tail(vgamma, gamma_ptr()); + uni_vmovups_maybe_tail(vbeta, beta_ptr()); + } + + Vmm vscale = bdesc_->use_scaleshift() ? vgamma : vone; + Vmm vdiv = bdesc_->use_scaleshift() ? vgamma : vsqrtvar; + + if (isa == sse42) { + movups(vbuf, vscale); + divps(vbuf, vsqrtvar); + movups(vdiv, vbuf); + } else { + vdivps(vdiv, vscale, vsqrtvar); + } + + auto compute = [=](bool output_is_aligned) { + spat_loop(spat_size, unroll_blocks, unroll_regs, + [](size_t base_reg) {UNUSED(base_reg);}, + [=](size_t base_reg, size_t i) { + Vmm v = Vmm(base_reg); + size_t offt = i * vlen; + uni_vmovups(v, + vmmword[reg_src + reg_soff + offt]); + mic_prefetcht0(ptr[reg_src + reg_soff + offt + + t0_pf_offt]); + mic_prefetcht1(ptr[reg_src + reg_soff + offt + + t1_pf_offt]); + uni_vsubps(v, v, vmean); + if (bdesc_->use_scaleshift()) { + uni_vfmadd213ps(v, vgamma, vbeta); + } else { + uni_vmulps(v, v, vsqrtvar); + } + if (with_relu_inf_only) { + uni_vmaxps(v, v, vzero); + } else if (with_relu) { + if (isa == avx512_common) + fwd_process_relu_avx512_common(v, offt); + else + fwd_process_relu_avx2(v, offt, Vmm(3)); + } + if (output_is_aligned) { + uni_vmovntps( + vmmword[reg_dst + reg_soff + offt], v); + } else { + uni_vmovups( + vmmword[reg_dst + reg_soff + offt], v); + } + }, + [](size_t base_reg) {UNUSED(base_reg);}); + }; + + Label unaligned_store, end_store; + test(reg_dst, vlen - 1); + jnz(unaligned_store, T_NEAR); + compute(true); + jmp(end_store, T_NEAR); + L(unaligned_store); { + compute(false); + } + L(end_store); + + add(reg_coff, vlen); + cmp(reg_coff, reg_coff_max); + jl(ch_label); + } + } + + void forward() { + mov(reg_src, ptr[rsp + stack_off_src]); + mov(reg_dst, ptr[rsp + stack_off_dst]); + mov(reg_ws, ptr[rsp + stack_off_ws]); + + xor_(reg_soff, reg_soff); + Label dst_spatial; + L(dst_spatial); { + xor_(reg_coff, reg_coff); + if (isa == sse42) + mov(reg_tmp_off, reg_soff); + + forward_channels(); + + if (isa == sse42) { + mov(reg_soff, reg_tmp_off); + add(reg_src, vlen / 2); + add(reg_dst, vlen / 2); + mov(reg_coff, vlen / 2); + + forward_channels(); + + sub(reg_src, vlen / 2); + sub(reg_dst, vlen / 2); + } + + add(reg_soff, reg_mb_stride_Bc); + cmp(reg_soff, reg_soff_max); + jnz(dst_spatial); + } + } + + void backward_sh_channels() { + Label sh_channels; + L(sh_channels); { + uni_vmovups_maybe_tail(vmean, mean_ptr()); + uni_vmovups(Vmm(0), vmmword[reg_rbuf1 + reg_coff]); + uni_vmovups(Vmm(1), vmmword[reg_rbuf2 + reg_coff]); + spat_loop(spat_size, 1, 1, + [=](size_t base_reg) { + if (base_reg > 0) { + for (int i = 0; i < 2; i++) { + Vmm v(base_reg * 5 + i); + uni_vpxor(v, v, v); + } + } + }, + [=](size_t base_reg, size_t i) { + Vmm o0 = Vmm(base_reg * 5 + 0); + Vmm o1 = Vmm(base_reg * 5 + 1); + Vmm t1 = Vmm(base_reg * 5 + 2); + Vmm t2 = Vmm(base_reg * 5 + 3); + Vmm t3 = Vmm(base_reg * 5 + 4); + size_t offt = i * vlen; + uni_vmovups(t1, vmmword[reg_src + reg_soff + offt]); + uni_vmovups(t2, vmmword[reg_diff_dst + reg_soff + + offt]); + if (with_relu) { + if (isa == avx512_common) + bwd_process_relu_avx512_common(t2, offt); + else if (isa == avx2) + bwd_process_relu_avx2(t2, offt, t3); + else + assert(false); + } + uni_vsubps(t3, vmean, t1, t3); + if (isa == sse42) { + mulps(t3, t2); + subps(o0, t3); + } else { + vfnmadd231ps(o0, t3, t2); + } + uni_vaddps(o1, o1, t2); + mic_prefetcht0(ptr[reg_diff_dst + reg_soff + offt + + t0_pf_offt]); + mic_prefetcht0(ptr[reg_src + reg_soff + offt + + t0_pf_offt]); + mic_prefetcht1(ptr[reg_diff_dst + reg_soff + offt + + t1_pf_offt]); + mic_prefetcht1(ptr[reg_src + reg_soff + offt + + t1_pf_offt]); + }, + [=](size_t base_reg) { + Vmm b0 = Vmm(0); + Vmm b1 = Vmm(1); + if (base_reg) { + uni_vaddps(b0, b0, Vmm(base_reg * 5 + 0)); + uni_vaddps(b1, b1, Vmm(base_reg * 5 + 1)); + } + }); + uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0)); + uni_vmovups(vmmword[reg_rbuf2 + reg_coff], Vmm(1)); + add(reg_coff, vlen); + cmp(reg_coff, reg_coff_max); + jl(sh_channels); + } + } + + void backward_diff_channels() { + Label diff_channels; + L(diff_channels); { + uni_vmovups_maybe_tail(vmean, mean_ptr()); + uni_vmovups_maybe_tail(vsqrtvar, var_ptr()); + uni_vaddps(vsqrtvar, vsqrtvar, veps); + uni_vsqrtps(vsqrtvar, vsqrtvar); + uni_vdivps(vsqrtvar, vone, vsqrtvar, vbuf); + if (bdesc_->use_scaleshift()) + uni_vmovups_maybe_tail(vgamma, gamma_ptr()); + uni_vmovups_maybe_tail(vdiff_gamma, diff_gamma_ptr()); + uni_vmovups_maybe_tail(vdiff_beta, diff_beta_ptr()); + uni_vmulps(vdiff_gamma, vdiff_gamma, vsqrtvar); + uni_vdivps(vdiff_beta, vdiff_beta, vchan_size); + uni_vdivps(vdiff_gamma, vdiff_gamma, vchan_size); + + auto compute = [=](bool output_is_aligned) { + spat_loop(spat_size, unroll_blocks, unroll_regs, + [=](size_t base_reg) {UNUSED(base_reg);}, + [=](size_t base_reg, size_t i) { + Vmm v(base_reg * 2 + 0); + Vmm t(base_reg * 2 + 1); + Vmm t1(base_reg * 2 + 2); + size_t offt = i * vlen; + uni_vmovups(v, vmmword[reg_diff_dst + reg_soff + + offt]); + if (with_relu) { + if (isa == avx512_common) + bwd_process_relu_avx512_common(v, offt); + else if (isa == avx2) + bwd_process_relu_avx2(v, offt, t); + else + assert(false); + } + if (!bdesc_->use_global_stats()) { + uni_vsubps(v, v, vdiff_beta); + uni_vmovups(t, vmmword[reg_src + reg_soff + + offt]); + uni_vsubps(t, vmean, t, t1); + uni_vmulps(t, t, vdiff_gamma); + uni_vaddps(v, v, t); + } + uni_vmulps(v, v, vsqrtvar); + if (bdesc_->use_scaleshift()) { + uni_vmulps(v, v, vgamma); + } + if (output_is_aligned) { + uni_vmovntps( + vmmword[reg_diff_src + reg_soff + offt], + v); + } else { + uni_vmovups( + vmmword[reg_diff_src + reg_soff + offt], + v); + } + mic_prefetcht0(ptr[reg_diff_dst + reg_soff + offt + + t0_pf_offt]); + mic_prefetcht0(ptr[reg_src + reg_soff + offt + + t0_pf_offt]); + mic_prefetcht1(ptr[reg_diff_dst + reg_soff + + offt + t1_pf_offt]); + mic_prefetcht1(ptr[reg_src + reg_soff + offt + + t1_pf_offt]); + }, + [=](size_t base_reg) {UNUSED(base_reg);}); + }; + + Label unaligned_store, end_store; + test(reg_diff_src, vlen - 1); + jnz(unaligned_store, T_NEAR); + compute(true); + jmp(end_store, T_NEAR); + L(unaligned_store); { + compute(false); + } + L(end_store); + + add(reg_coff, vlen); + cmp(reg_coff, reg_coff_max); + jl(diff_channels); + } + } + + void backward() { + uni_vpxor(Vmm(0), Vmm(0), Vmm(0)); + xor_(reg_coff, reg_coff); + Label zero_rbuf, sh_spatial; + + L(zero_rbuf); { + uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0)); + uni_vmovups(vmmword[reg_rbuf2 + reg_coff], Vmm(0)); + add(reg_coff, isa == sse42 ? vlen / 2 : vlen); + cmp(reg_coff, reg_coff_max); + jne(zero_rbuf); + } + + mov(reg_src, ptr[rsp + stack_off_src]); + mov(reg_diff_dst, ptr[rsp + stack_off_diff_dst]); + if (with_relu) { + assert(isa == avx2 || isa == avx512_common); + mov(reg_ws, ptr[rsp + stack_off_ws]); + } + + xor_(reg_soff, reg_soff); + L(sh_spatial); { + xor_(reg_coff, reg_coff); + if (isa == sse42) { + mov(reg_tmp_off, reg_soff); + } + backward_sh_channels(); + if (isa == sse42) { + mov(reg_soff, reg_tmp_off); + add(reg_diff_dst, vlen / 2); + add(reg_src, vlen / 2); + mov(reg_coff, vlen / 2); + backward_sh_channels(); + sub(reg_diff_dst, vlen / 2); + sub(reg_src, vlen / 2); + } + add(reg_soff, reg_mb_stride_Bc); + cmp(reg_soff, reg_soff_max); + jne(sh_spatial); + } + + mov(reg_diff_scale_shift, ptr[rsp + stack_off_diff_scale_shift]); + + Label no_sh_reduction; + barrier(); { + mov(reg_tmp, ptr[rsp + stack_off_N_ithr]); + cmp(reg_tmp, 0); + Label sh_reduction_channels; + jne(no_sh_reduction, T_NEAR); + + mov(reg_nnthr, ptr[rsp + stack_off_N_nthr]); + xor_(reg_coff, reg_coff); + L(sh_reduction_channels); { + mov(reg_roff, reg_coff); + uni_vpxor(Vmm(0), Vmm(0), Vmm(0)); + uni_vpxor(Vmm(1), Vmm(1), Vmm(1)); + uni_vmovups_maybe_tail(vsqrtvar, var_ptr()); + uni_vaddps(vsqrtvar, vsqrtvar, veps); + uni_vsqrtps(vsqrtvar, vsqrtvar); + uni_vdivps(vsqrtvar, vone, vsqrtvar, vbuf); + mov(reg_ctr, reg_nnthr); + Label sh_reduction_thrs; + L(sh_reduction_thrs); { // TODO: unroll (?) + uni_vaddps(Vmm(0), Vmm(0), vmmword[reg_rbuf1 + reg_roff]); + uni_vaddps(Vmm(1), Vmm(1), vmmword[reg_rbuf2 + reg_roff]); + add(reg_roff, reg_coff_max); + sub(reg_ctr, 1); + jnz(sh_reduction_thrs); + } + uni_vmulps(Vmm(0), Vmm(0), vsqrtvar); + uni_vmovups_maybe_tail(diff_gamma_ptr(), Vmm(0)); + uni_vmovups_maybe_tail(diff_beta_ptr(), Vmm(1)); + add(reg_coff, isa == sse42 ? vlen / 2 : vlen); + cmp(reg_coff, reg_coff_max); + jne(sh_reduction_channels); + } + } + L(no_sh_reduction); + barrier(); + + mov(reg_diff_src, ptr[rsp + stack_off_diff_src]); + if (with_relu) { + assert(isa == avx2 || isa == avx512_common); + mov(reg_ws, ptr[rsp + stack_off_ws]); + } + + xor_(reg_soff, reg_soff); + Label diff_spatial; + L(diff_spatial); { + xor_(reg_coff, reg_coff); + if (isa == sse42) { + mov(reg_tmp_off, reg_soff); + } + backward_diff_channels(); + if (isa == sse42) { + mov(reg_soff, reg_tmp_off); + add(reg_diff_dst, vlen / 2); + add(reg_diff_src, vlen / 2); + add(reg_src, vlen / 2); + mov(reg_coff, vlen / 2); + backward_diff_channels(); + sub(reg_diff_dst, vlen / 2); + sub(reg_diff_src, vlen / 2); + sub(reg_src, vlen / 2); + } + add(reg_soff, reg_mb_stride_Bc); + cmp(reg_soff, reg_soff_max); + jne(diff_spatial); + } + } + + jit_bnorm_t(const batch_normalization_pd_t *bdesc): bdesc_(bdesc) { + static_assert(isa == sse42 || isa == avx2 || isa == avx512_common + || isa == avx512_mic, "unsupported isa"); + + const int simd_w = isa == sse42 ? 8 : + cpu_isa_traits::vlen / sizeof(data_t); + is_spatial_thr_ = + bnorm_utils::is_spatial_thr(bdesc_, simd_w, sizeof(data_t)); + + unroll_blocks = isa == avx512_common && !is_spatial_thr_ ? 4 : 1; + unroll_regs = isa == avx512_common && !is_spatial_thr_ ? 4 : 1; + + preamble(); + + if (isa == avx512_common) + prepare_tail_mask_avx512_common(); + else if (isa == avx2) + prepare_tail_mask_avx2_common(); + + compute_static_strides(); + sub(rsp, stack_size_required); + load_common_params(); + prepare_relu(); + + if (bdesc_->is_fwd()) { + if (!bdesc_->stats_is_src()) { + compute_mean_variance(); + } + forward(); + } else { + backward(); + } + add(rsp, stack_size_required); + postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); + } +}; + +template +struct uni_bnorm_driver_t: public c_compatible { + uni_bnorm_driver_t(const batch_normalization_pd_t *bdesc) + : bdesc_(bdesc), ker_(bdesc_) + { + const int nthrs = mkldnn_get_max_threads(); + const dim_t C_PADDED = get_c_padded(bdesc_); + + size_t data_size = sizeof(data_t) * bdesc_->MB() * C_PADDED + * bdesc_->D() * bdesc_->H() * bdesc_->W(); + l3_size_ = get_cache_size(3, true) * nthrs / 2; + do_blocking_ = (data_size >= l3_size_ / 2 && l3_size_ > 0); + } + + ~uni_bnorm_driver_t() {} + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const batch_normalization_pd_t *bdesc) { + int nthrs = mkldnn_get_max_threads(); + dim_t C_PADDED = get_c_padded(bdesc); + + int sbuf_sz = use_tmp_stats(bdesc) * 2 * C_PADDED; + int pbuf_sz = use_tmp_diff_scale_shift(bdesc) * 2 * C_PADDED; + int rbuf_sz = (bdesc->is_fwd() ? 1 : 2) * C_PADDED * nthrs; + + scratchpad.book(key_bnorm_tmp_stats, sizeof(data_t) * sbuf_sz); + scratchpad.book(key_bnorm_tmp_diff_ss, sizeof(data_t) * pbuf_sz); + scratchpad.book(key_bnorm_reduction, sizeof(data_t) * rbuf_sz); + + if (mkldnn_thr_syncable()) { + int n_barriers = C_PADDED / simd_w; + scratchpad.book(key_barrier, sizeof(barrier::ctx_t) * n_barriers); + } + } + + void exec(int ithr, int nthr, const data_t *src, data_t *diff_src, + data_t *dst, const data_t *diff_dst, const data_t *scale_shift, + data_t *diff_scale_shift, const data_t *mean, const data_t *var, + const uint8_t *ws, const memory_tracking::grantor_t &scratchpad) { + auto sbuf = scratchpad.get(key_bnorm_tmp_stats); + auto pbuf = scratchpad.get(key_bnorm_tmp_diff_ss); + auto rbuf = scratchpad.get(key_bnorm_reduction); + auto barriers = scratchpad.get(key_barrier); + + dim_t N = bdesc_->MB(); + dim_t C = bdesc_->C(); + dim_t C_PADDED = get_c_padded(bdesc_); + dim_t D = bdesc_->D(); + dim_t H = bdesc_->H(); + dim_t W = bdesc_->W(); + dim_t SP = D * H * W; + dim_t img_size = C_PADDED * D * H * W; + const int vlen = isa == sse42 ? 32 : cpu_isa_traits::vlen; + + typename jit_bnorm_t::call_params_t p; + + p.eps = bdesc_->desc()->batch_norm_epsilon; + p.one = 1.0f; + p.spat_size = D * H * W; + p.chan_size = 1.0f * N * p.spat_size; + + dim_t C_blks = C_PADDED / simd_w; + + int C_ithr{0}, C_nthr{0}, N_ithr{0}, N_nthr{0}, S_ithr{0}, S_nthr{0}; + dim_t C_blk_s{0}, C_blk_e{0}, N_s{0}, N_e{0}, S_s{0}, S_e{0}; + + dim_t C_blks_per_iter{ 1 }; + int64_t iters{ 1 }; + if (do_blocking_) { + int num_tensors = bdesc_->is_fwd() ? 1 : 2; + size_t working_set_size + = (N * D * H * W * simd_w * sizeof(data_t)) * num_tensors; + bnorm_utils::cache_balance(working_set_size, C_blks, + C_blks_per_iter, iters); + } + + bool spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking_, + true, ithr, nthr, N, do_blocking_ ? C_blks_per_iter : C_blks, + SP, C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s, N_e, + S_ithr, S_nthr, S_s, S_e); + + int SP_N_ithr = N_ithr * S_nthr + S_ithr; + int SP_N_nthr = N_nthr * S_nthr; + assert(IMPLICATION(!mkldnn_thr_syncable(), SP_N_nthr == 1)); + + p.N_ithr = SP_N_ithr; + p.N_nthr = SP_N_nthr; + + int last_iter_blks = C_blks - (iters - 1) * C_blks_per_iter; + int global_C_blk_s; + int global_barriers_per_iter = C_nthr; + + for (int64_t it = 0; it < iters; it++) { + if (it == iters - 1 && iters > 1) { + C_blk_s = C_blk_e = N_s = N_e = 0; + spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking_, + spatial_thr_allowed, ithr, nthr, N, last_iter_blks, SP, + C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s, + N_e, S_ithr, S_nthr, S_s, S_e); + + // Update call parameters for JIT, last iteration + p.N_ithr = N_ithr * S_nthr + S_ithr; + p.N_nthr = N_nthr * S_nthr; + } + + global_C_blk_s = do_blocking_ ? + (C_blk_s == -1) ? -1 : it * C_blks_per_iter + C_blk_s : + C_blk_s; + + int C_blks_thr = C_blk_e - C_blk_s; + int N_thr = N_e - N_s; + + size_t coff_base = global_C_blk_s * simd_w; + size_t soff_base + = global_C_blk_s * p.spat_size * simd_w + N_s * img_size; + + p.spat_size_loc = S_e - S_s; + p.S_s = S_s * vlen; + p.S_tail = (p.spat_size - S_e) * vlen; + p.coff_max = C_blks_thr * simd_w; + p.mean = (use_tmp_stats(bdesc_) ? sbuf : mean) + coff_base; + p.var = (use_tmp_stats(bdesc_) ? sbuf + C_PADDED : var) + coff_base; + p.scale_shift = scale_shift + coff_base; + p.diff_scale_shift = (use_tmp_diff_scale_shift(bdesc_) + ? pbuf : diff_scale_shift) + coff_base; + + p.soff_max = N_thr * img_size; + p.src = src + soff_base; + p.dst = dst + soff_base; + p.diff_src = diff_src + soff_base; + p.diff_dst = diff_dst + soff_base; + p.ws = ws + soff_base / 8; + + p.mb_stride_Bc = img_size - p.coff_max * p.spat_size; + + // use SP_N_nthr which is the same as p.N_nthr except maybe for + // the last iteration. + p.rbuf1 = rbuf + ((it * C_blks_per_iter) * SP_N_nthr + + C_blk_s * p.N_nthr + p.N_ithr * C_blks_thr) * simd_w; + // rbuf1 and rbuf2 have to be disjoint + p.rbuf2 = p.rbuf1 + C_PADDED * nthr; + p.is_cblk_tail = (it * C_blks_per_iter + C_blk_e) * simd_w > C; + + size_t iter_bariers + = do_blocking_ ? it * global_barriers_per_iter : 0; + p.barrier = barriers + C_ithr + iter_bariers; + if (p.soff_max != 0 && p.coff_max != 0) + ker_(&p); + } + } + + void init_barriers(const memory_tracking::grantor_t &scratchpad) { + auto barriers = scratchpad.get(key_barrier); + if (barriers) { + const int n_barriers = get_c_padded(bdesc_) / simd_w; + for (int i = 0; i < n_barriers; ++i) + barrier::ctx_init(&barriers[i]); + } + } + +private: + enum { + simd_w = isa == sse42 ? 8 : cpu_isa_traits::vlen / sizeof(data_t) + }; + + static bool use_tmp_stats(const batch_normalization_pd_t *bdesc) { + return true + && !bdesc->stats_is_src() + && bdesc->desc()->prop_kind == prop_kind::forward_inference; + } + + static bool use_tmp_diff_scale_shift(const batch_normalization_pd_t *bdesc) + { + return false + || (bdesc->is_bwd() && !bdesc->use_scaleshift()) + || bdesc->desc()->prop_kind == prop_kind::backward_data; + } + + static dim_t get_c_padded(const batch_normalization_pd_t *bdesc) + { return bdesc->src_md()->padded_dims[1]; } + + const batch_normalization_pd_t *bdesc_; + bool do_blocking_; + size_t l3_size_; + + jit_bnorm_t ker_; +}; + +} + +using namespace data_type; +using namespace format_tag; +using namespace utils; + +/* fwd */ + +template +status_t jit_uni_batch_normalization_fwd_t::pd_t::init() { + auto desired_fmt_tag = (ndims() == 4) + ? isa == avx512_common ? nChw16c : nChw8c + : isa == avx512_common ? nCdhw16c : nCdhw8c; + + bool ok = true + && mayiuse(isa) + && is_fwd() + && !has_zero_dim_memory() + && one_of(ndims(), 4, 5) + && src_md()->data_type == f32 + && IMPLICATION(use_scaleshift(), weights_md()->data_type == f32) + && memory_desc_matches_tag(*src_md(), desired_fmt_tag) + && (attr()->has_default_values() || this->with_relu_post_op()); + if (!ok) return status::unimplemented; + + if (is_training() && fuse_bn_relu()) { + if (isa < avx2) return status::unimplemented; + init_default_ws(1); + } + + if (memory_desc_wrapper(src_md()).padded_dims()[1] != C() + && isa < avx2) + return status::unimplemented; + + auto scratchpad = scratchpad_registry().registrar(); + uni_bnorm_driver_t::init_scratchpad(scratchpad, this); + + return status::success; +} + +template +jit_uni_batch_normalization_fwd_t::jit_uni_batch_normalization_fwd_t( + const pd_t *apd): cpu_primitive_t(apd) +{ bnorm_driver_ = new uni_bnorm_driver_t(pd()); } + +template +status_t jit_uni_batch_normalization_fwd_t::execute( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto scale_shift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT); + + auto mean = pd()->stats_is_src() + ? const_cast(CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN)) + : CTX_OUT_MEM(data_t *, MKLDNN_ARG_MEAN); + auto var = pd()->stats_is_src() + ? const_cast(CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE)) + : CTX_OUT_MEM(data_t *, MKLDNN_ARG_VARIANCE); + + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE); + + auto scratchpad = this->scratchpad(ctx); + + bnorm_driver_->init_barriers(scratchpad); + + parallel(0, [&](const int ithr, const int nthr) { + bnorm_driver_->exec(ithr, nthr, src, nullptr, dst, nullptr, + scale_shift, nullptr, mean, var, ws, scratchpad); + }); + + return status::success; +} + +template +jit_uni_batch_normalization_fwd_t::~jit_uni_batch_normalization_fwd_t() +{ delete bnorm_driver_; } + +/* bwd */ + +template +status_t jit_uni_batch_normalization_bwd_t::pd_t::init() { + auto desired_fmt_tag = (ndims() == 4) + ? one_of(isa, sse42, avx2) ? nChw8c : nChw16c + : one_of(isa, sse42, avx2) ? nCdhw8c : nCdhw16c; + + bool ok = true + && mayiuse(isa) + && is_bwd() + && !has_zero_dim_memory() + && one_of(ndims(), 4, 5) + && everyone_is(f32, src_md()->data_type, diff_src_md()->data_type) + && IMPLICATION(use_scaleshift(), + utils::everyone_is(f32, + weights_md()->data_type, + diff_weights_md()->data_type)) + && memory_desc_matches_tag(*src_md(), desired_fmt_tag) + && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + if (memory_desc_wrapper(src_md()).padded_dims()[1] != C() + && isa < avx2) + return status::unimplemented; + + if (fuse_bn_relu()) { + if (isa < avx2) return status::unimplemented; + init_default_ws(1); + if (!compare_ws(hint_fwd_pd_)) + return status::unimplemented; + } + + /* TODO: extra checks required */ + + auto scratchpad = scratchpad_registry().registrar(); + uni_bnorm_driver_t::init_scratchpad(scratchpad, this); + + return status::success; +} + +template +jit_uni_batch_normalization_bwd_t::jit_uni_batch_normalization_bwd_t( + const pd_t *apd): cpu_primitive_t(apd) +{ bnorm_driver_ = new uni_bnorm_driver_t(pd()); } + +template +status_t jit_uni_batch_normalization_bwd_t::execute( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN); + auto var = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto scale_shift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT); + auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE); + + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + auto diff_scale_shift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT); + + auto scratchpad = this->scratchpad(ctx); + + bnorm_driver_->init_barriers(scratchpad); + + parallel(0, [&](const int ithr, const int nthr) { + bnorm_driver_->exec(ithr, nthr, src, diff_src, nullptr, diff_dst, + scale_shift, diff_scale_shift, mean, var, ws, scratchpad); + }); + + return status::success; +} + +template +jit_uni_batch_normalization_bwd_t::~jit_uni_batch_normalization_bwd_t() +{ delete bnorm_driver_; } + +/* struct instantiation */ +template struct jit_uni_batch_normalization_fwd_t; +template struct jit_uni_batch_normalization_bwd_t; +template struct jit_uni_batch_normalization_fwd_t; +template struct jit_uni_batch_normalization_bwd_t; +template struct jit_uni_batch_normalization_fwd_t; +template struct jit_uni_batch_normalization_bwd_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp new file mode 100644 index 0000000000..96410ec84e --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp @@ -0,0 +1,100 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_UNI_BATCH_NORMALIZATION_HPP +#define JIT_UNI_BATCH_NORMALIZATION_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_batch_normalization_pd.hpp" +#include "cpu_isa_traits.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace { template struct uni_bnorm_driver_t; } + +template +struct jit_uni_batch_normalization_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_batch_normalization_fwd_pd_t { + pd_t(engine_t *engine, const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : cpu_batch_normalization_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_batch_normalization_fwd_t); + + status_t init(); + }; + + typedef typename prec_traits::type data_t; + + jit_uni_batch_normalization_fwd_t(const pd_t *apd); + ~jit_uni_batch_normalization_fwd_t(); + + virtual status_t execute(const exec_ctx_t &ctx) const override; + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + uni_bnorm_driver_t *bnorm_driver_; +}; + +template +struct jit_uni_batch_normalization_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_batch_normalization_bwd_pd_t { + pd_t(engine_t *engine, const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : cpu_batch_normalization_bwd_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_batch_normalization_bwd_t); + + status_t init(); + }; + + typedef typename prec_traits::type data_t; + + jit_uni_batch_normalization_bwd_t(const pd_t *apd); + ~jit_uni_batch_normalization_bwd_t(); + + virtual status_t execute(const exec_ctx_t &ctx) const override; + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + uni_bnorm_driver_t *bnorm_driver_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp new file mode 100644 index 0000000000..b7dc5f85c5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp @@ -0,0 +1,1302 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "cpu_memory.hpp" + +#include "jit_uni_dw_conv_kernel_f32.hpp" + +#define GET_OFF(field) offsetof(jit_conv_call_s, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::prop_kind; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +using namespace Xbyak; + +template +void jit_uni_dw_conv_fwd_kernel_f32::load_src(int ur_ch_blocks, int ur_w) { + int repeats = isa == sse42 ? 2 : 1; + for (int i = 0; i < repeats; i++) { + for (int ch = 0; ch < ur_ch_blocks; ch++) { + for (int ow = 0; ow < ur_w; ow++) { + Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_w + ch*ur_w + ow); + + int b_off = ch*jcp.ch_block + i*4; + if (this->jcp.with_bias) + uni_vmovups(vmm_acc, + vmmword[reg_bias + b_off*sizeof(float)]); + else + uni_vpxor(vmm_acc, vmm_acc, vmm_acc); + + int o_off = ch*jcp.oh*jcp.ow*jcp.ch_block + + ow*jcp.ch_block + i*4; + if (this->jcp.with_sum) + uni_vaddps(vmm_acc, vmm_acc, + vmmword[reg_output + o_off*sizeof(float)]); + } + } + } +} + +template +void jit_uni_dw_conv_fwd_kernel_f32::apply_filter( + int ur_ch_blocks, int ur_w) { + int ch_blk = jcp.ch_block; + int dilate_h = jcp.dilate_h + 1; + int dilate_w = jcp.dilate_w + 1; + int stride_w = jcp.stride_w; + + Label iter_exit_label; + + cmp(reg_kh, 0); + je(iter_exit_label, T_NEAR); + cmp(reg_kw, 0); + je(iter_exit_label, T_NEAR); + + mov(iter_kh, reg_kh); + Label kh_label; + L(kh_label); { + mov(iter_kw, reg_kw); + mov(aux1_reg_input, aux_reg_input); + mov(aux1_reg_kernel, aux_reg_kernel); + + Label kw_label; + L(kw_label); { + int repeats = isa == sse42 ? 2 : 1; + for (int i = 0; i < repeats; i++) { + for (int ch = 0; ch < ur_ch_blocks; ch++) { + int ker_off = ch*jcp.kh*jcp.kw*ch_blk + i*4; + Vmm vmm_ker = get_ker_reg(0); + uni_vmovups(vmm_ker, ptr[aux1_reg_kernel + + ker_off*sizeof(float)]); + + for (int ow = 0; ow < ur_w; ow++) { + int inp_off = ch*jcp.ih*jcp.iw*ch_blk + + ow*stride_w*ch_blk + i*4; + Vmm vmm_src = get_src_reg(0); + uni_vmovups(vmm_src, ptr[aux1_reg_input + + inp_off*sizeof(float)]); + + Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_w + + ch*ur_w + ow); + uni_vfmadd231ps(vmm_acc, vmm_src, vmm_ker); + } + } + } + add(aux1_reg_kernel, ch_blk*sizeof(float)); + add(aux1_reg_input, ch_blk*dilate_w*sizeof(float)); + + dec(iter_kw); + cmp(iter_kw, 0); + jg(kw_label, T_NEAR); + } + add(aux_reg_kernel, jcp.kw*ch_blk*sizeof(float)); + add(aux_reg_input, jcp.iw*ch_blk*dilate_h*sizeof(float)); + + dec(iter_kh); + cmp(iter_kh, 0); + jg(kh_label, T_NEAR); + } + + L(iter_exit_label); +} + +template +void jit_uni_dw_conv_fwd_kernel_f32::apply_filter_unrolled( + int ur_ch_blocks, int ur_w) { + int ch_blk = jcp.ch_block; + int dilate_h = jcp.dilate_h + 1; + int dilate_w = jcp.dilate_w + 1; + int stride_w = jcp.stride_w; + + Label iter_exit_label; + + cmp(reg_kh, 0); + je(iter_exit_label, T_NEAR); + + mov(iter_kh, reg_kh); + Label kh_label; + L(kh_label); { + int repeats = isa == sse42 ? 2 : 1; + for (int i = 0; i < repeats; i++) { + for (int ch = 0; ch < ur_ch_blocks; ch++) { + for (int kw = 0; kw < jcp.kw; kw++) { + int ker_off = ch*jcp.kh*jcp.kw*ch_blk + kw*ch_blk + i*4; + + Vmm vmm_ker = get_ker_reg(0); + uni_vmovups(vmm_ker, ptr[aux_reg_kernel + + ker_off*sizeof(float)]); + + for (int ow = 0; ow < ur_w; ow++) { + int inp_off = ch*jcp.ih*jcp.iw*ch_blk + + ow*stride_w*ch_blk + kw*ch_blk*dilate_w + i*4; + + Vmm vmm_src = get_src_reg(0); + uni_vmovups(vmm_src, ptr[aux_reg_input + + inp_off*sizeof(float)]); + + Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_w + + ch*ur_w + ow); + uni_vfmadd231ps(vmm_acc, vmm_src, vmm_ker); + } + } + } + } + + add(aux_reg_kernel, jcp.kw*ch_blk*sizeof(float)); + add(aux_reg_input, jcp.iw*ch_blk*dilate_h*sizeof(float)); + + dec(iter_kh); + cmp(iter_kh, 0); + jg(kh_label, T_NEAR); + } + + L(iter_exit_label); +} + +template +void jit_uni_dw_conv_fwd_kernel_f32::apply_activation( + int ur_ch_blocks, int ur_w) { + if (this->jcp.with_eltwise) { + int repeats = isa == sse42 ? 2 : 1; + eltwise_injector_->compute_vector_range(4, repeats * ur_w * ur_ch_blocks + 4); + } +} + +template +void jit_uni_dw_conv_fwd_kernel_f32::store_dst( + int ur_ch_blocks, int ur_w) { + int ch_blk = jcp.ch_block; + + int repeats = isa == sse42 ? 2 : 1; + for (int i = 0; i < repeats; i++) { + for (int ch = 0; ch < ur_ch_blocks; ch++) { + for (int ow = 0; ow < ur_w; ow++) { + int o_off = ch*jcp.oh*jcp.ow*ch_blk + ow*ch_blk + i*4; + Vmm vmm_dst = get_acc_reg(i*ur_ch_blocks*ur_w + ch*ur_w + ow); + + uni_vmovups(vmmword[reg_output + o_off*sizeof(float)], vmm_dst); + } + } + } +} + +template +void jit_uni_dw_conv_fwd_kernel_f32::loop_body(int ur_ch_blocks) { + Label unrolled_w_label; + Label tail_w_label; + Label exit_label; + + L(unrolled_w_label); { + int ur_w = jcp.ur_w; + + cmp(reg_ur_w, ur_w); + jl(tail_w_label, T_NEAR); + + mov(aux_reg_input, reg_input); + mov(aux_reg_kernel, reg_kernel); + + load_src(ur_ch_blocks, ur_w); + apply_filter_unrolled(ur_ch_blocks, ur_w); + apply_activation(ur_ch_blocks, ur_w); + store_dst(ur_ch_blocks, ur_w); + + add(reg_input, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w); + add(reg_output, sizeof(float) * ur_w * jcp.ch_block); + + sub(reg_ur_w, ur_w); + jmp(unrolled_w_label); + } + + L(tail_w_label); { + int ur_w = 1; + + cmp(reg_ur_w, ur_w); + jl(exit_label, T_NEAR); + + mov(aux_reg_input, reg_input); + mov(aux_reg_kernel, reg_kernel); + + load_src(ur_ch_blocks, ur_w); + apply_filter(ur_ch_blocks, ur_w); + apply_activation(ur_ch_blocks, ur_w); + store_dst(ur_ch_blocks, ur_w); + + add(reg_input, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w); + add(reg_output, sizeof(float) * ur_w * jcp.ch_block); + + sub(reg_ur_w, ur_w); + jmp(tail_w_label); + } + + L(exit_label); +} + +template +void jit_uni_dw_conv_fwd_kernel_f32::generate() { + this->preamble(); + + mov(reg_input, ptr[this->param1 + GET_OFF(src)]); + mov(reg_output, ptr[this->param1 + GET_OFF(dst)]); + mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]); + if (jcp.with_bias) + mov(reg_bias, ptr[this->param1 + GET_OFF(bias)]); + mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]); + mov(reg_kw, ptr[this->param1 + GET_OFF(kw_padding)]); + mov(reg_ch_blocks, ptr[this->param1 + GET_OFF(ch_blocks)]); + mov(reg_ur_w, ptr[this->param1 + GET_OFF(ur_w)]); + + Label ch_blocks_tail_label; + Label exit_label; + + int ch_blocks_tail = jcp.nb_ch % jcp.nb_ch_blocking; + + cmp(reg_ch_blocks, jcp.nb_ch_blocking); + jne(ch_blocks_tail ? ch_blocks_tail_label : exit_label, T_NEAR); + + loop_body(jcp.nb_ch_blocking); // channel main loop + + if (ch_blocks_tail) { + L(ch_blocks_tail_label); + + cmp(reg_ch_blocks, ch_blocks_tail); + jne(exit_label, T_NEAR); + + loop_body(ch_blocks_tail); // channel tail loop + } + + L(exit_label); + + this->postamble(); + + if (jcp.with_eltwise) + eltwise_injector_->prepare_table(); +} + +template +bool jit_uni_dw_conv_fwd_kernel_f32::post_ops_ok( + jit_conv_conf_t &jcp, const primitive_attr_t &attr) { + const auto &p = attr.post_ops_; + + auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); }; + auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); }; + + switch (p.len_) { + case 0: return true; // no post_ops + case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise + case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise + default: return false; + } + + return false; +} + +template +status_t jit_uni_dw_conv_fwd_kernel_f32::init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d, + const primitive_attr_t &attr) +{ + if (!mayiuse(isa)) return status::unimplemented; + + const int simd_w = isa == avx512_common ? 16 : 8; + + jcp.prop_kind = cd.prop_kind; + + const bool with_groups = weights_d.ndims() == src_d.ndims() + 1; + if (!with_groups) return status::unimplemented; + + jcp.ngroups = weights_d.dims()[0]; + jcp.mb = src_d.dims()[0]; + + jcp.oc = dst_d.dims()[1]; + jcp.oc_without_padding = jcp.oc; + jcp.ic = src_d.dims()[1]; + + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = dst_d.dims()[2]; + jcp.ow = dst_d.dims()[3]; + + jcp.kh = weights_d.dims()[3]; + jcp.kw = weights_d.dims()[4]; + + jcp.t_pad = cd.padding[0][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.b_pad = cd.padding[1][0]; + jcp.r_pad = cd.padding[1][1]; + + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + + jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef; + + if (!post_ops_ok(jcp, attr)) + return status::unimplemented; + + const auto &p = attr.post_ops_; + jcp.with_sum = p.find(primitive_kind::sum) != -1; + const int eltwise_ind = p.find(primitive_kind::eltwise); + jcp.with_eltwise = eltwise_ind != -1; + if (jcp.with_eltwise) + jcp.eltwise = p.entry_[eltwise_ind].eltwise; + + bool ok_to_pad_channels = true + && jcp.oc == jcp.ngroups + && jcp.ic == jcp.ngroups + && one_of(isa, avx512_common, avx2); + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.oc, simd_w); + jcp.ngroups = rnd_up(jcp.ngroups, simd_w); + } + + auto dat_tag = isa == avx512_common ? nChw16c : nChw8c; + auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g; + + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag); + + bool args_ok = true + && jcp.oc == jcp.ngroups + && jcp.ic == jcp.ngroups + && jcp.ngroups % simd_w == 0 + && jcp.src_tag == dat_tag + && jcp.wei_tag == wei_tag + && jcp.dst_tag == dat_tag + && jcp.ic <= src_d.padded_dims()[1] + && jcp.oc <= dst_d.padded_dims()[1] + && jcp.ngroups <= weights_d.padded_dims()[0]; + if (!args_ok) return status::unimplemented; + + jcp.ur_w = isa == avx512_common ? 6 : isa == avx2 ? 4 : 3; + + jcp.ch_block = simd_w; + jcp.nb_ch = jcp.oc / jcp.ch_block; + jcp.nb_ch_blocking = isa == avx512_common ? 4 : isa == avx2 ? 3 : 2; + if (jcp.nb_ch < jcp.nb_ch_blocking) + jcp.nb_ch_blocking = jcp.nb_ch; + + return status::success; +} + +template +void jit_uni_dw_conv_fwd_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + if (jcp.with_bias && jcp.oc_without_padding != jcp.oc) + scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc); +} + +template struct jit_uni_dw_conv_fwd_kernel_f32; +template struct jit_uni_dw_conv_fwd_kernel_f32; +template struct jit_uni_dw_conv_fwd_kernel_f32; + +template +inline void jit_uni_dw_conv_bwd_data_kernel_f32::load_ddst( + int ur_ch_blocks, int ur_str_w) { + int repeats = isa == sse42 ? 2 : 1; + for (int i = 0; i < repeats; i++) { + for (int ch = 0; ch < ur_ch_blocks; ch++) { + for (int w = 0; w < ur_str_w; w++) { + Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_str_w + + ch*ur_str_w + w); + uni_vpxor(vmm_acc, vmm_acc, vmm_acc); + } + } + } +} + +template +inline void jit_uni_dw_conv_bwd_data_kernel_f32::apply_filter( + int ur_ch_blocks, int ur_str_w) { + int kw = jcp.kw; + int kh = jcp.kh; + int ow = jcp.ow; + int oh = jcp.oh; + + int ch_blk = jcp.ch_block; + int stride_h = jcp.stride_h; + int stride_w = jcp.stride_w; + + Label iter_exit_label; + + cmp(reg_kh, 0); + je(iter_exit_label, T_NEAR); + + cmp(reg_kw, 0); + je(iter_exit_label, T_NEAR); + + mov(iter_kh, reg_kh); + Label kh_label; + L(kh_label); { + mov(aux1_reg_ddst, aux_reg_ddst); + mov(aux1_reg_kernel, aux_reg_kernel); + + mov(iter_kw, reg_kw); + Label kw_label; + L(kw_label); { + int repeats = isa == sse42 ? 2 : 1; + for (int i = 0; i < repeats; i++) { + for (int ch = 0; ch < ur_ch_blocks; ch++) { + int ker_off = ch*kh*kw*ch_blk + i*4; + Vmm vmm_ker = get_ker_reg(0); + uni_vmovups(vmm_ker, ptr[aux1_reg_kernel + + ker_off*sizeof(float)]); + + for (int w = 0; w < ur_str_w; w++) { + int ddst_off = (ch*oh*ow + w)*ch_blk + i*4; + + Vmm vmm_src = get_src_reg(0); + uni_vmovups(vmm_src, ptr[aux1_reg_ddst + + ddst_off*sizeof(float)]); + + Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_str_w + + ch*ur_str_w + w); + uni_vfmadd231ps(vmm_acc, vmm_src, vmm_ker); + } + } + } + + add(aux1_reg_kernel, ch_blk*stride_w*sizeof(float)); + sub(aux1_reg_ddst, ch_blk*sizeof(float)); + + sub(iter_kw, stride_w); + cmp(iter_kw, 0); + jg(kw_label, T_NEAR); + } + + add(aux_reg_kernel, kw*ch_blk*stride_h*sizeof(float)); + sub(aux_reg_ddst, ow*ch_blk*sizeof(float)); + + sub(iter_kh, stride_h); + cmp(iter_kh, 0); + jg(kh_label, T_NEAR); + } + + L(iter_exit_label); +} + +template +inline void jit_uni_dw_conv_bwd_data_kernel_f32::store_dsrc( + int ur_ch_blocks, int ur_str_w) { + int ch_blk = jcp.ch_block; + int iw = jcp.iw; + int ih = jcp.ih; + int stride_w = jcp.stride_w; + + int repeats = isa == sse42 ? 2 : 1; + for (int i = 0; i < repeats; i++) { + for (int ch = 0; ch < ur_ch_blocks; ch++) { + for (int w = 0; w < ur_str_w; w++) { + int dsrc_off = (ch*ih*iw + w*stride_w)*ch_blk + i*4; + Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_str_w + + ch*ur_str_w + w); + + uni_vmovups(ptr[reg_dsrc + dsrc_off*sizeof(float)], vmm_acc); + } + } + } +} + +template +inline void jit_uni_dw_conv_bwd_data_kernel_f32::loop_body( + int ur_ch_blocks) { + Label unrolled_w_label; + Label tail_w_label; + Label exit_label; + + L(unrolled_w_label); { + int ur_w = jcp.ur_w; + + cmp(reg_ur_str_w, ur_w); + jl(tail_w_label, T_NEAR); + + mov(aux_reg_ddst, reg_ddst); + mov(aux_reg_kernel, reg_kernel); + + load_ddst(ur_ch_blocks, ur_w); + apply_filter(ur_ch_blocks, ur_w); + store_dsrc(ur_ch_blocks, ur_w); + + add(reg_dsrc, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w); + add(reg_ddst, sizeof(float) * ur_w * jcp.ch_block); + + sub(reg_ur_str_w, ur_w); + jmp(unrolled_w_label); + } + + L(tail_w_label); { + int ur_w = 1; + + cmp(reg_ur_str_w, ur_w); + jl(exit_label, T_NEAR); + + mov(aux_reg_ddst, reg_ddst); + mov(aux_reg_kernel, reg_kernel); + + load_ddst(ur_ch_blocks, ur_w); + apply_filter(ur_ch_blocks, ur_w); + store_dsrc(ur_ch_blocks, ur_w); + + add(reg_dsrc, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w); + add(reg_ddst, sizeof(float) * ur_w * jcp.ch_block); + + sub(reg_ur_str_w, ur_w); + jmp(tail_w_label); + } + + L(exit_label); +} + +template +void jit_uni_dw_conv_bwd_data_kernel_f32::generate() { + preamble(); + + mov(reg_dsrc, ptr[this->param1 + GET_OFF(src)]); + mov(reg_ddst, ptr[this->param1 + GET_OFF(dst)]); + mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]); + mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]); + mov(reg_kw, ptr[this->param1 + GET_OFF(kw_padding)]); + mov(reg_ch_blocks, ptr[this->param1 + GET_OFF(ch_blocks)]); + mov(reg_ur_str_w, ptr[this->param1 + GET_OFF(ur_str_w)]); + + Label ch_blocks_tail_label; + Label exit_label; + + int ch_blocks_tail = jcp.nb_ch % jcp.nb_ch_blocking; + + cmp(reg_ch_blocks, jcp.nb_ch_blocking); + jne(ch_blocks_tail ? ch_blocks_tail_label : exit_label, T_NEAR); + + loop_body(jcp.nb_ch_blocking); // channel main loop + + if (ch_blocks_tail) { + L(ch_blocks_tail_label); + + cmp(reg_ch_blocks, ch_blocks_tail); + jne(exit_label, T_NEAR); + + loop_body(ch_blocks_tail); // channel tail loop + } + + L(exit_label); + + this->postamble(); +} + +template +status_t jit_uni_dw_conv_bwd_data_kernel_f32::init_conf( + jit_conv_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d) { + if (!mayiuse(isa)) return status::unimplemented; + + const int simd_w = isa == avx512_common ? 16 : 8; + + const bool with_groups = weights_d.ndims() == diff_src_d.ndims() + 1; + if (!with_groups) return status::unimplemented; + + jcp.ngroups = weights_d.dims()[0]; + jcp.mb = diff_src_d.dims()[0]; + + jcp.oc = diff_dst_d.dims()[1]; + jcp.oc_without_padding = jcp.oc; + jcp.ic = diff_src_d.dims()[1]; + + jcp.ih = diff_src_d.dims()[2]; + jcp.iw = diff_src_d.dims()[3]; + jcp.oh = diff_dst_d.dims()[2]; + jcp.ow = diff_dst_d.dims()[3]; + + jcp.kh = weights_d.dims()[3]; + jcp.kw = weights_d.dims()[4]; + + jcp.t_pad = cd.padding[0][0]; + jcp.l_pad = cd.padding[0][1]; + jcp.b_pad = cd.padding[1][0]; + jcp.r_pad = cd.padding[1][1]; + + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + + jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad; + jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad; + + bool ok_to_pad_channels = true + && jcp.oc == jcp.ngroups + && jcp.ic == jcp.ngroups + && one_of(isa, avx512_common, avx2); + if (ok_to_pad_channels) { + jcp.oc = rnd_up(jcp.oc, simd_w); + jcp.ic = rnd_up(jcp.oc, simd_w); + jcp.ngroups = rnd_up(jcp.ngroups, simd_w); + } + + auto dat_tag = isa == avx512_common ? nChw16c : nChw8c; + auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g; + + jcp.src_tag = diff_src_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag); + + bool args_ok = true + && jcp.oc == jcp.ngroups + && jcp.ic == jcp.ngroups + && jcp.ngroups % simd_w == 0 + && jcp.dilate_h == 0 + && jcp.dilate_w == 0 + && jcp.src_tag == dat_tag + && jcp.wei_tag == wei_tag + && jcp.dst_tag == dat_tag + && jcp.oh == (jcp.ihp - jcp.kh) / jcp.stride_h + 1 + && jcp.ow == (jcp.iwp - jcp.kw) / jcp.stride_w + 1 + && jcp.ic <= diff_src_d.padded_dims()[1] + && jcp.oc <= diff_dst_d.padded_dims()[1] + && jcp.ngroups <= weights_d.padded_dims()[0]; + if (!args_ok) return status::unimplemented; + + jcp.ur_w = isa == avx512_common ? 6 : isa == avx2 ? 4 : 3; + + jcp.ch_block = simd_w; + jcp.nb_ch = jcp.ic / jcp.ch_block; + jcp.nb_ch_blocking = isa == avx512_common ? 4 : isa == avx2 ? 3 : 2; + if (jcp.nb_ch < jcp.nb_ch_blocking) + jcp.nb_ch_blocking = jcp.nb_ch; + + return status::success; +} + +template +void jit_uni_dw_conv_bwd_data_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + UNUSED(scratchpad); + UNUSED(jcp); +} + +template struct jit_uni_dw_conv_bwd_data_kernel_f32; +template struct jit_uni_dw_conv_bwd_data_kernel_f32; +template struct jit_uni_dw_conv_bwd_data_kernel_f32; + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::zero_filter() { + for (int r = 0; r < reg_repeats; ++r) { + for (int i = 0; i < jcp.kw; ++i) { + Vmm vmm_acc = get_acc_reg(r * jcp.kw + i); + uni_vpxor(vmm_acc, vmm_acc, vmm_acc); + } + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::load_filter() { + for (int r = 0; r < reg_repeats; ++r) { + const int reg_set = r * jcp.kw; + for (int i = 0; i < jcp.kw; ++i) { + int off_filter = (reg_set + i) * simd_w; + Vmm vmm_acc = get_acc_reg(reg_set + i); + uni_vmovups(vmm_acc, + vmmword[reg_tmp_filter + off_filter * sizeof(float)]); + } + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::zero_bias() { + for (int r = 0; r < reg_repeats; ++r) { + Vmm vmm_bias = get_bias_reg(r); + uni_vpxor(vmm_bias, vmm_bias, vmm_bias); + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::load_bias() { + for (int r = 0; r < reg_repeats; ++r) { + Vmm vmm_bias = get_bias_reg(r); + uni_vmovups( + vmm_bias, vmmword[reg_bias_baddr + r * simd_w * sizeof(float)]); + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::compute_ow_step_unroll( + int unroll_w, int l_pad, int pad_offset, int ow_block) { + + const int iw_block = ow_block * jcp.stride_w; + const int right_border = jcp.iw - iw_block; + + const int cascade_input = nstl::min(jcp.stride_w, jcp.kw); + + /* preamble count for number of cascaded LOAD + FMA operation */ + const int input_overlap = nstl::max(jcp.kw - l_pad, 0); + + /* LOAD initial input registers, then cascade LOADs and FMAs*/ + for (int r = 0; r < reg_repeats; ++r) { + for (int i_ur = 0; i_ur < unroll_w; ++i_ur) { + int off_output = (i_ur * reg_repeats + r) * simd_w; + Vmm vmm_output = get_output_reg(r); + uni_vmovups(vmm_output, + ptr[reg_tmp_output + off_output * sizeof(float)]); + if (i_ur == 0) { + for (int c = 0; c < input_overlap; ++c) { + int off_input + = ((c - pad_offset) * reg_repeats + r) * simd_w; + Vmm vmm_input + = get_input_reg((c % jcp.kw) * reg_repeats + r); + uni_vmovups(vmm_input, + ptr[reg_tmp_input + off_input * sizeof(float)]); + } + } else { + for (int c = 0; c < cascade_input; ++c) { + int overlap = (i_ur - 1) * jcp.stride_w + input_overlap; + int off_input + = ((overlap + c - pad_offset) * reg_repeats + r) + * simd_w; + Vmm vmm_input = get_input_reg( + ((overlap + c) % jcp.kw) * reg_repeats + r); + uni_vmovups(vmm_input, + ptr[reg_tmp_input + off_input * sizeof(float)]); + } + } + + for (int i_kw = 0; i_kw < jcp.kw; ++i_kw) { + int io_overlap = i_kw + (i_ur * jcp.stride_w); + + /* Don't apply FMAs that fall into the padded region */ + if (io_overlap - l_pad < 0 + || io_overlap - jcp.l_pad >= right_border) + continue; + + Vmm vmm_input = get_input_reg( + ((io_overlap - l_pad) % jcp.kw) * reg_repeats + r); + Vmm vmm_acc = get_acc_reg(i_kw * reg_repeats + r); + Vmm vmm_aux = isa == sse42 ? get_aux_reg() : vmm_input; + if (isa == sse42) + uni_vmovups(vmm_aux, vmm_input); + uni_vfmadd231ps(vmm_acc, vmm_aux, vmm_output); + } + } + } +} + +template +inline void +jit_uni_dw_conv_bwd_weights_kernel_f32::compute_bias_step_unroll( + const int unroll_w) { + for (int r = 0; r < reg_repeats; ++r) { + for (int i = 0; i < unroll_w; ++i) { + Vmm vmm_bias = get_bias_reg(r); + int off_output = (i * reg_repeats + r) * simd_w; + if (isa == sse42) { + /* Need to support unaligned address loads for SSE42*/ + Vmm vmm_output = get_output_reg(1 + r); + uni_vmovups(vmm_output, + ptr[reg_tmp_output + off_output * sizeof(float)]); + uni_vaddps(vmm_bias, vmm_bias, vmm_output); + } else { + uni_vaddps(vmm_bias, vmm_bias, + vmmword[reg_tmp_output + off_output * sizeof(float)]); + } + } + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::store_filter() { + for (int r = 0; r < reg_repeats; ++r) { + const int reg_set = r * jcp.kw; + for (int i = 0; i < jcp.kw; ++i) { + int off_filter = (i + reg_set) * simd_w; + Vmm vmm_acc = get_acc_reg(i + reg_set); + uni_vmovups(vmmword[reg_tmp_filter + off_filter * sizeof(float)], + vmm_acc); + } + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::store_bias() { + for (int r = 0; r < reg_repeats; ++r) { + Vmm vmm_bias = get_bias_reg(r); + uni_vmovups( + vmmword[reg_bias_baddr + r * simd_w * sizeof(float)], vmm_bias); + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::compute_bias_loop( + const int block_size) { + Label oh_label; + Label ow_blk_label; + + const int unroll_w = nstl::min(block_size, jcp.ow); + const int unroll_w_trips = jcp.ow / unroll_w; + const int tail_w = jcp.ow > block_size ? jcp.ow % block_size : 0; + + const int ch_offset = jcp.ch_block; + + mov(reg_oh, ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_index)]); + mov(reg_oh_worksize, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_count)]); + + mov(reg_tmp_output, reg_output_baddr); + L(oh_label); + { + + mov(iter_ow_blk, unroll_w_trips); + L(ow_blk_label); + { + + compute_bias_step_unroll(unroll_w); + add(reg_tmp_output, unroll_w * ch_offset * sizeof(float)); + + dec(iter_ow_blk); + cmp(iter_ow_blk, 0); + jg(ow_blk_label, T_NEAR); + } + + if (tail_w > 0) { + compute_bias_step_unroll(tail_w); + add(reg_tmp_output, tail_w * ch_offset * sizeof(float)); + } + + inc(reg_oh); + cmp(reg_oh, reg_oh_worksize); + jl(oh_label, T_NEAR); + } +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::compute_zero_filter() { + + const int ch_offset = jcp.ch_block; + + Label kh_loop_label, skip_zeroing_label; + + mov(reg_exec_flags, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, exec_flags)]); + and_(reg_exec_flags, FLAG_ZERO_FILTER); + test(reg_exec_flags, reg_exec_flags); + je(skip_zeroing_label); + + zero_filter(); + + mov(reg_tmp_filter, reg_filter_baddr); + mov(reg_kh, jcp.kh); + L(kh_loop_label); + { + store_filter(); + + add(reg_tmp_filter, jcp.kw * ch_offset * sizeof(float)); + dec(reg_kh); + cmp(reg_kh, 0); + jg(kh_loop_label); + } + + /* Comeback pointers */ + sub(reg_tmp_filter, jcp.kh * jcp.kw * ch_offset * sizeof(float)); + + L(skip_zeroing_label); +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::compute_h_step( + int unroll_w, int l_pad, int pad_offset, int ow_block) { + + const int ch_offset = jcp.ch_block; + + Label kh_loop_label, skip_loop_label; + + cmp(reg_kh_count, 0); + je(skip_loop_label, T_NEAR); + + mov(reg_kh, reg_kh_count); + L(kh_loop_label); + { + load_filter(); + compute_ow_step_unroll(unroll_w, l_pad, pad_offset, ow_block); + store_filter(); + + add(reg_tmp_filter, jcp.kw * ch_offset * sizeof(float)); + add(reg_tmp_input, jcp.iw * ch_offset * sizeof(float)); + dec(reg_kh); + cmp(reg_kh, 0); + jg(kh_loop_label); + } + + /* Comeback pointers */ + Label kh_comeback_label; + mov(reg_kh, reg_kh_count); + L(kh_comeback_label); + { + sub(reg_tmp_input, jcp.iw * ch_offset * sizeof(float)); + sub(reg_tmp_filter, jcp.kw * ch_offset * sizeof(float)); + dec(reg_kh); + cmp(reg_kh, 0); + jg(kh_comeback_label, T_NEAR); + } + + L(skip_loop_label); +} + +template +inline void jit_uni_dw_conv_bwd_weights_kernel_f32::compute_h_loop( + int unroll_w, int l_pad, int pad_offset, int ow_block) { + + const size_t io_overlap = jcp.ih / jcp.stride_h < jcp.oh ? + jcp.ih / jcp.stride_h - 1 : + jcp.oh - jcp.b_pad - 1; + const int ch_offset = jcp.ch_block; + const int t_overlap_off = jcp.t_pad % jcp.stride_h == 0 ? jcp.stride_h : 1; + const int b_overlap_off = jcp.b_pad % jcp.stride_h == 0 ? jcp.stride_h : 1; + + Label tpad_loop_label, h_loop_label, skip_tpad_label, skip_bpad_label, + end_h_loop_label; + + mov(reg_oh, ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_index)]); + mov(reg_oh_worksize, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_count)]); + mov(reg_kh_count, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, kh_count)]); + + mov(reg_tmp_output, reg_output_baddr); + mov(reg_tmp_input, reg_input_baddr); + mov(reg_tmp_filter, reg_filter_baddr); + + L(h_loop_label); + { + + compute_h_step(unroll_w, l_pad, pad_offset, ow_block); + + add(reg_tmp_output, jcp.ow * ch_offset * sizeof(float)); + + /* If within the top_pad region */ + if (jcp.t_pad > 0) { + /* Skip t_pad area if no longer in initial h_block */ + cmp(reg_oh, jcp.t_pad); + jg(skip_tpad_label, T_NEAR); + + cmp(reg_kh_count, jcp.kh); + jge(skip_tpad_label, T_NEAR); + + add(reg_kh_count, t_overlap_off); + sub(reg_tmp_filter, + t_overlap_off * jcp.kw * ch_offset * sizeof(float)); + + /* kernel has moved beyond padding (adjust for stride effects) */ + if (jcp.t_pad % jcp.stride_h != 0) { + int inp_corr = jcp.stride_h - jcp.t_pad % jcp.stride_h; + add(reg_tmp_input, + inp_corr * jcp.iw * ch_offset * sizeof(float)); + } + jmp(tpad_loop_label, T_NEAR); + } + + L(skip_tpad_label); + + cmp(reg_oh, io_overlap); + jl(skip_bpad_label, T_NEAR); + sub(reg_kh_count, b_overlap_off); + + L(skip_bpad_label); + add(reg_tmp_input, jcp.stride_h * jcp.iw * ch_offset * sizeof(float)); + + L(tpad_loop_label); + + cmp(reg_oh, jcp.ih / jcp.stride_h); + jge(end_h_loop_label, T_NEAR); + + inc(reg_oh); + + cmp(reg_oh, reg_oh_worksize); + jl(h_loop_label, T_NEAR); + } + L(end_h_loop_label); +} + +template +inline void +jit_uni_dw_conv_bwd_weights_kernel_f32::compute_ow_block_unroll() { + + const int ch_offset = jcp.ch_block; + int ow = jcp.ow; + int pad_offset = 0; + int l_pad = jcp.l_pad; + + /* Calculate effective padding */ + int r_pad = nstl::max(0, (ow - 1) * jcp.stride_w + + (jcp.kw - 1) * (jcp.dilate_w + 1) + - (jcp.iw + jcp.l_pad - 1)); + + /* Is this strictly defined by: + * -code-size (?) + * -address size (?) */ + const int max_unroll_w = 30; + const int block_size = 15; + + int unroll_w_tail = 0; + int unroll_w = 0; + int unroll_w_trips = 0; + + if (jcp.ow > max_unroll_w) { + unroll_w = nstl::min(block_size, jcp.ow); + unroll_w_trips = ow / unroll_w; + /* calculate tail */ + unroll_w_tail = ow % unroll_w; + /* Perform some rebalancing if tail too small*/ + if ((unroll_w_tail == 0 && r_pad != 0) + || (r_pad > 0 && r_pad >= unroll_w_tail)) { + if (unroll_w_trips > 1) { + unroll_w_tail += unroll_w; + unroll_w_trips--; + } else { + /* Idealy, this case shouldn't happen */ + unroll_w_tail += (unroll_w - unroll_w / 2); + unroll_w = unroll_w / 2; + } + } + } else { + unroll_w = jcp.ow; + unroll_w_trips = nstl::max(1, ow / unroll_w); + } + if (jcp.with_bias) { + Label skip_load_bias; + mov(reg_bias_baddr, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, bias)]); + + zero_bias(); + + mov(reg_exec_flags, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, exec_flags)]); + and_(reg_exec_flags, FLAG_ZERO_BIAS); + test(reg_exec_flags, reg_exec_flags); + jne(skip_load_bias); + + load_bias(); + + L(skip_load_bias); + compute_bias_loop(block_size); + + store_bias(); + } + + /* Pass filter address, then offset for h_padding. */ + compute_zero_filter(); + mov(reg_kh_offset, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, filter_pad_off)]); + add(reg_filter_baddr, reg_kh_offset); + + /* compute left padded block */ + if (l_pad) { + compute_h_loop(unroll_w, l_pad, 0, 0); + add(reg_output_baddr, unroll_w * ch_offset * sizeof(float)); + add(reg_input_baddr, + unroll_w * jcp.stride_w * ch_offset * sizeof(float)); + unroll_w_trips--; + pad_offset = l_pad; + l_pad = 0; + } + + /* compute middle block */ + Label ow_blk_label; + + /* Insert loop for 'ow' block when middle block needs to execute more + * than once */ + bool do_ow_blk_loop = unroll_w_trips > 1; + if (do_ow_blk_loop) { + mov(iter_ow_blk, unroll_w_trips); + L(ow_blk_label); + } + if (unroll_w_trips > 0) { + compute_h_loop(unroll_w, l_pad, pad_offset, 0); + add(reg_output_baddr, unroll_w * ch_offset * sizeof(float)); + add(reg_input_baddr, + unroll_w * jcp.stride_w * ch_offset * sizeof(float)); + } + if (do_ow_blk_loop) { + dec(iter_ow_blk); + cmp(iter_ow_blk, 0); + jg(ow_blk_label, T_NEAR); + } + + /* compute right padded block */ + if (unroll_w_tail) { + compute_h_loop(unroll_w_tail, 0, pad_offset, jcp.ow - unroll_w_tail); + } +} + +template +void jit_uni_dw_conv_bwd_weights_kernel_f32::generate() { + preamble(); + + mov(reg_input_baddr, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, input)]); + mov(reg_output_baddr, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, output)]); + mov(reg_filter_baddr, + ptr[this->param1 + offsetof(jit_dw_conv_call_s, filter)]); + + compute_ow_block_unroll(); + + this->postamble(); +} + +template +status_t jit_uni_dw_conv_bwd_weights_kernel_f32::init_conf( + jit_conv_conf_t &jcp, const convolution_desc_t &cd, + const memory_desc_wrapper &src_d, + const memory_desc_wrapper &diff_weights_d, + const memory_desc_wrapper &diff_dst_d, int nthreads) { + if (!mayiuse(isa)) + return status::unimplemented; + + jcp.ngroups = diff_weights_d.dims()[0]; + jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups; + jcp.ic = src_d.dims()[1] / jcp.ngroups; + + const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1; + + jcp.is_depthwise = true && with_groups && everyone_is(1, jcp.oc, jcp.ic); + + if (!jcp.is_depthwise) + return status::unimplemented; + + jcp.ch_block = isa == avx512_common ? 16 : 8; + + jcp.mb = src_d.dims()[0]; + + jcp.ih = src_d.dims()[2]; + jcp.iw = src_d.dims()[3]; + jcp.oh = diff_dst_d.dims()[2]; + jcp.ow = diff_dst_d.dims()[3]; + + jcp.kh = diff_weights_d.dims()[3]; + jcp.kw = diff_weights_d.dims()[4]; + + jcp.stride_h = cd.strides[0]; + jcp.stride_w = cd.strides[1]; + + jcp.t_pad = cd.padding[0][0]; + jcp.b_pad = cd.padding[1][0]; + + jcp.l_pad = cd.padding[0][1]; + jcp.r_pad = cd.padding[1][1]; + + jcp.dilate_h = cd.dilates[0]; + jcp.dilate_w = cd.dilates[1]; + + jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad; + jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad; + + jcp.with_bias = cd.diff_bias_desc.format_kind != format_kind::undef; + + auto dat_tag = isa == avx512_common ? nChw16c : nChw8c; + auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g; + + jcp.src_tag = src_d.matches_one_of_tag(dat_tag); + jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag); + jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag); + + bool args_ok = true + && jcp.src_tag == dat_tag + && jcp.wei_tag == wei_tag + && jcp.dst_tag == dat_tag + && jcp.ngroups % jcp.ch_block == 0 && jcp.dilate_h == 0 + && jcp.dilate_w == 0 && jcp.kw <= 3 + && jcp.oh == (jcp.ihp - jcp.kh) / jcp.stride_h + 1 + && jcp.ow == (jcp.iwp - jcp.kw) / jcp.stride_w + 1; + if (!args_ok) + return status::unimplemented; + + jcp.nb_ch = jcp.ngroups / jcp.ch_block; + + /* kernel applicability check wrt boundaries + * the conditions are quite general across the kernels we have, + * but ideally the check should belong to a specific kernel... */ + const int max_hpad = (jcp.kh - 1 + 1) / 2; + const int max_wpad = (jcp.kw - 1 + 1) / 2; + const bool boundaries_ok = true && jcp.t_pad <= max_hpad + && jcp.b_pad <= max_hpad && jcp.l_pad <= max_wpad + && jcp.r_pad <= max_wpad; + if (!boundaries_ok) + return status::unimplemented; + + balance(jcp, nthreads); + + return status::success; +} + +template +void jit_uni_dw_conv_bwd_weights_kernel_f32::init_scratchpad( + memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) { + /* Notes: if splitting thread work on 'mb', then a reduction has to take + * place. Hence, book a per-thread, local weights-buffer for the + * reduction */ + if (jcp.nthr_mb > 1) { + const size_t wei_size = jcp.ngroups * jcp.kh * jcp.kw; + scratchpad.book(key_conv_wei_reduction, + sizeof(float) * wei_size * (jcp.nthr_mb - 1)); + + if (jcp.with_bias) + scratchpad.book(key_conv_bia_reduction, + sizeof(float) * jcp.ngroups * (jcp.nthr_mb - 1)); + } +} + +template +void jit_uni_dw_conv_bwd_weights_kernel_f32::balance(jit_conv_conf_t &jcp, + int nthreads) { + jcp.nthr = nthreads; + jcp.nthr_g = jcp.nthr_mb = 1; + + /* Basic-Heuristics for parallel strategy: + * 1) Tries to parallel on the number of Groups (g) where tasks are + * independent. Otherwise, + * 2) Tries to split the work across g and MiniBatch (mb). + * Parallelizing on mb requires computing a reduction for weights. + * + * NOTE: because of 'task partitioning' scheme, there will be unbalanced + * per-thread load when the number of threads is high (e.g. > 16). + */ + jcp.nthr_g = nstl::min(jcp.nb_ch, jcp.nthr); + jcp.nthr_mb = nstl::min(nstl::max(1, jcp.nthr / jcp.nthr_g), jcp.mb); + + jcp.nthr = jcp.nthr_g * jcp.nthr_mb; +} + +template struct jit_uni_dw_conv_bwd_weights_kernel_f32; +template struct jit_uni_dw_conv_bwd_weights_kernel_f32; +template struct jit_uni_dw_conv_bwd_weights_kernel_f32; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp new file mode 100644 index 0000000000..9c08fc4a09 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp @@ -0,0 +1,253 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_UNI_DW_CONV_KERNEL_F32_HPP +#define JIT_UNI_DW_CONV_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" +#include "jit_uni_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_uni_dw_conv_fwd_kernel_f32: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_dw_conv_fwd_kernel_f32) + + jit_uni_dw_conv_fwd_kernel_f32(jit_conv_conf_t ajcp) + : jcp(ajcp), eltwise_injector_(nullptr) + { + if (jcp.with_eltwise) + eltwise_injector_ = new jit_uni_eltwise_injector_f32(this, + jcp.eltwise); + + this->generate(); + jit_ker = (void (*)(jit_conv_call_s *))this->getCode(); + } + + ~jit_uni_dw_conv_fwd_kernel_f32() { + delete eltwise_injector_; + } + + static bool post_ops_ok(jit_conv_conf_t &jcp, + const primitive_attr_t &attr); + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &dst_d, const primitive_attr_t &attr); + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + jit_conv_conf_t jcp; + void (*jit_ker)(jit_conv_call_s *); + +private: + using Vmm = typename utils::conditional3::type; + using reg64_t = const Xbyak::Reg64; + const Xbyak::AddressFrame &vmmword = (isa == sse42) + ? xword : (isa == avx2) ? yword : zword; + const int vlen = cpu_isa_traits::vlen; + + // dw convolution + reg64_t reg_input = r8; + reg64_t aux_reg_input = r9; + reg64_t aux1_reg_input = r10; + reg64_t reg_kernel = r11; + reg64_t aux_reg_kernel = r12; + reg64_t aux1_reg_kernel = r13; + reg64_t reg_output = r14; + reg64_t reg_bias = r15; + reg64_t reg_kh = rax; + reg64_t reg_kw = rbx; + reg64_t iter_kh = rdx; + reg64_t iter_kw = rsi; + reg64_t reg_ur_w = rbp; + reg64_t reg_ch_blocks = aux1_reg_input; + reg64_t imm_addr64 = aux1_reg_input; + + inline Vmm get_ker_reg(int idx) { return Vmm(idx + 0); } + inline Vmm get_src_reg(int idx) { return Vmm(idx + 1); } + inline Vmm get_acc_reg(int idx) { return Vmm(idx + 4); } + + inline void load_src(int ur_ch_blocks, int ur_w); + inline void apply_filter(int ur_ch_blocks, int ur_w); + inline void apply_filter_unrolled(int ur_ch_blocks, int ur_w); + inline void apply_activation(int ur_ch_blocks, int ur_w); + inline void store_dst(int ur_ch_blocks, int ur_w); + inline void loop_body(int ur_ch_blocks); + + jit_uni_eltwise_injector_f32 *eltwise_injector_; + + void generate(); +}; + +template +struct jit_uni_dw_conv_bwd_data_kernel_f32: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_dw_conv_bwd_data_kernel_f32) + + jit_uni_dw_conv_bwd_data_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp) { + this->generate(); + jit_ker = (void (*)(jit_conv_call_s *))this->getCode(); + } + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, + const memory_desc_wrapper &diff_src_d, + const memory_desc_wrapper &weights_d, + const memory_desc_wrapper &diff_dst_d); + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + jit_conv_conf_t jcp; + void (*jit_ker)(jit_conv_call_s *); + +private: + using Vmm = typename utils::conditional3::type; + using reg64_t = const Xbyak::Reg64; + + inline Vmm get_ker_reg(int idx) { return Vmm(idx + 0); } + inline Vmm get_src_reg(int idx) { return Vmm(idx + 1); } + inline Vmm get_acc_reg(int idx) { return Vmm(idx + 4); } + + reg64_t reg_ddst = rax; + reg64_t aux_reg_ddst = r8; + reg64_t aux1_reg_ddst = abi_not_param1; + reg64_t reg_kernel = rdx; + reg64_t aux_reg_kernel = r10; + reg64_t aux1_reg_kernel = rbp; + reg64_t reg_dsrc = rsi; + + reg64_t reg_ur_str_w = r9; + reg64_t reg_ch_blocks = rbx; + + reg64_t iter_kh = r11; + reg64_t iter_kw = r12; + reg64_t reg_kh = r13; + reg64_t reg_kw = r14; + + inline void loop_body(int ur_ch_blocks); + inline void load_ddst(int ur_ch_blocks, int ur_str_w); + inline void apply_filter(int ur_ch_blocks, int ur_str_w); + inline void store_dsrc(int ur_ch_blocks, int ur_str_w); + + void generate(); +}; + +template +struct jit_uni_dw_conv_bwd_weights_kernel_f32 : public jit_generator { + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_dw_conv_bwd_weights_kernel_f32) + + jit_uni_dw_conv_bwd_weights_kernel_f32(jit_conv_conf_t ajcp) : jcp(ajcp) { + this->generate(); + jit_ker = (void (*)(jit_dw_conv_call_s *)) this->getCode(); + } + + static status_t init_conf(jit_conv_conf_t &jcp, + const convolution_desc_t &cd, const memory_desc_wrapper &src_d, + const memory_desc_wrapper &diff_weights_d, + const memory_desc_wrapper &diff_dst_d, int nthreads); + + static void init_scratchpad(memory_tracking::registrar_t &scratchpad, + const jit_conv_conf_t &jcp); + + static void balance(jit_conv_conf_t &jcp, int nthreads); + + jit_conv_conf_t jcp; + void (*jit_ker)(jit_dw_conv_call_s *); + +private: + using Vmm = typename utils::conditional3::type; + using reg64_t = const Xbyak::Reg64; + const int simd_w = cpu_isa_traits::vlen / sizeof(float); + const int reg_repeats = (isa == sse42) ? 2 : 1; + + const Xbyak::AddressFrame &vmmword + = (isa == sse42) ? xword : (isa == avx2) ? yword : zword; + + /* XXX: offset between input and accummulators is 3, therefore, assume 'kw' + * is no larger than 3*/ + inline Vmm get_bias_reg(int idx = 0) { return Vmm(idx); } + inline Vmm get_output_reg(int idx) { return Vmm(idx + 1); } + inline Vmm get_input_reg(int idx) { return Vmm(idx + 4 * reg_repeats + 1); } + inline Vmm get_acc_reg(int idx) { return Vmm(idx + 1 * reg_repeats + 1); } + inline Vmm get_aux_reg() { return Vmm(0); } + + reg64_t reg_tmp_input = r9; + reg64_t reg_tmp_output = r10; + reg64_t reg_tmp_filter = r13; + reg64_t reg_kh_offset = rax; + + /* parameter passed by driver into kernel */ + Xbyak::Reg8 reg_exec_flags = bl; + + reg64_t reg_oh_worksize = r14; + reg64_t reg_oh = rax; + + reg64_t iter_ow_blk = r11; + + reg64_t reg_kh = rsi; + reg64_t reg_kh_count = rdx; + + /* Base addresses for convolution parameters. */ + reg64_t reg_input_baddr = r15; + reg64_t reg_output_baddr = r12; + reg64_t reg_filter_baddr = abi_not_param1; + reg64_t reg_bias_baddr = r13; + + /* Micro-kernel JIT'ing, fusing 'kw' and 'ow_block' loops into unrolled FMAs + */ + inline void compute_ow_step_unroll( + int unroll_w, int l_pad, int pad_offset, int ow_block); + + /* JIT'ing the outer loops for the micro-kernel -> {kh, oh_block} */ + inline void compute_h_step( + int unroll_w, int l_pad, int pad_offset, int ow_block); + inline void compute_h_loop( + int unroll_w, int l_pad, int pad_offset, int ow_block); + + /* Write 'width' micro-kernel JITs; depending on the padding and convolution + * size, write a micro-kernel for the left ow-block, middle ow-block(s), and + * right ow-block.*/ + inline void compute_ow_block_unroll(); + + inline void compute_zero_filter(); + inline void load_filter(); + inline void zero_filter(); + inline void load_bias(); + inline void zero_bias(); + inline void compute_bias_step_unroll(const int unroll_w); + inline void compute_bias_loop(const int block_size); + inline void store_filter(); + inline void store_bias(); + + void generate(); +}; +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp new file mode 100644 index 0000000000..58449601a3 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp @@ -0,0 +1,427 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "mkldnn_thread.hpp" + +#include "jit_uni_dw_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::memory_tracking::names; +using namespace mkldnn::impl::utils; + +template +void _jit_uni_dw_convolution_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const auto &jcp = kernel_->jcp; + + if (pd()->wants_padded_bias()) { + auto padded_bias = this->scratchpad(ctx).template get( + key_conv_padded_bias); + utils::array_copy(padded_bias, bias, jcp.oc_without_padding); + utils::array_set(padded_bias + jcp.oc_without_padding, 0.f, + jcp.oc - jcp.oc_without_padding); + bias = padded_bias; + } + + int dil_h = jcp.dilate_h + 1; + int dil_w = jcp.dilate_w + 1; + int str_h = jcp.stride_h; + int str_w = jcp.stride_w; + + auto kernel_params = [&](int ur_w_step, int ow, int oh, int ih, int kh, + int kh_padding, int ch, int ch_num, int n) { + auto par_conv = jit_conv_call_s(); + + const int i_l_overflow = nstl::max(0, (jcp.l_pad - ow * str_w)); + const int i_r_overflow = nstl::max(jcp.iw, (ow * str_w + + (jcp.kw - 1)*dil_w - jcp.l_pad + 1)) - jcp.iw; + + const int iw = nstl::max((ow*str_w - jcp.l_pad + + div_up(i_l_overflow, dil_w)*dil_w), 0); + const int kw = div_up(i_l_overflow, dil_w); + + const int kw_padding = jcp.kw - div_up(i_l_overflow, dil_w) + - div_up(i_r_overflow, dil_w); + + par_conv.src = &src[src_d.blk_off(n, ch, ih, iw)]; + par_conv.dst = &dst[dst_d.blk_off(n, ch, oh, ow)]; + + par_conv.filt = &weights[weights_d.blk_off(ch, 0, 0, kh, kw)]; + if (bias) par_conv.bias = &bias[bias_d.blk_off(ch*jcp.ch_block)]; + + par_conv.kh_padding = (size_t)nstl::max(0, kh_padding); + par_conv.kw_padding = (size_t)nstl::max(0, kw_padding); + + par_conv.ur_w = (size_t)ur_w_step; + + par_conv.ch_blocks = nstl::min(ch + ch_num, jcp.nb_ch) - ch; + + return par_conv; + }; + + const int chb_work = utils::div_up(jcp.nb_ch, jcp.nb_ch_blocking); + parallel_nd(jcp.mb, chb_work, jcp.oh, + [&](int n, int chb, int oh) { + int ch = chb * jcp.nb_ch_blocking; + int ch_num = jcp.nb_ch_blocking; + + const int i_t_overflow = nstl::max(0, (int)(jcp.t_pad - oh*str_h)); + const int i_b_overflow = nstl::max(jcp.ih, + (int)(oh*str_h + (jcp.kh - 1)*dil_h - jcp.t_pad + 1)) - jcp.ih; + + const int ih = nstl::max((int)(oh*str_h - jcp.t_pad + + div_up(i_t_overflow, dil_h)*dil_h), 0); + const int kh = div_up(i_t_overflow, dil_h); + const int kh_padding = jcp.kh - div_up(i_t_overflow, dil_h) + - div_up(i_b_overflow, dil_h); + + // left border + int ow = 0; + int l_border = nstl::min(div_up(jcp.l_pad, str_w), jcp.ow); + int ur_w_step = 1; + for (; ow < l_border; ow++) { + jit_conv_call_s par_conv = kernel_params(ur_w_step, ow, oh, ih, + kh, kh_padding, ch, ch_num, n); + + kernel_->jit_ker(&par_conv); + } + + // main loop + ur_w_step = (jcp.iw - (jcp.kw - 1)*dil_w + jcp.l_pad - 1) + / jcp.stride_w - ow + 1; + if (ur_w_step > 0) { + jit_conv_call_s par_conv = kernel_params(ur_w_step, ow, oh, ih, + kh, kh_padding, ch, ch_num, n); + + kernel_->jit_ker(&par_conv); + + ow += ur_w_step; + } + + // right border + ur_w_step = 1; + for (; ow < jcp.ow; ow++) { + jit_conv_call_s par_conv = kernel_params(ur_w_step, ow, oh, ih, + kh, kh_padding, ch, ch_num, n); + + kernel_->jit_ker(&par_conv); + } + }); + + if (pd()->wants_zero_pad_dst()) + ctx.memory(MKLDNN_ARG_DST)->zero_pad(); +} + +template struct _jit_uni_dw_convolution_fwd_t; +template struct _jit_uni_dw_convolution_fwd_t; +template struct _jit_uni_dw_convolution_fwd_t; + +template +void _jit_uni_dw_convolution_bwd_data_t::execute_backward_data( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + + const auto &jcp = kernel_->jcp; + + auto kernel_params = [&](int ur_str_w, int iw, int oh, int ih, + int i_t_overflow, int i_b_overflow, int stride_off_h, + int ch, int ch_num, int n) { + auto par_conv = jit_conv_call_s(); + + const int i_l_overflow = nstl::max(0, (jcp.kw - 1 - iw - jcp.l_pad)); + const int i_r_overflow = nstl::max(0, (jcp.kw - 1 - (jcp.iw - 1 - iw) + - jcp.r_pad)); + + int ow = iw + jcp.l_pad - i_r_overflow; + int stride_off_w = ow % jcp.stride_w; + ow /= jcp.stride_w; + + par_conv.src = &diff_src[diff_src_d.blk_off(n, ch, ih, iw)]; + par_conv.dst = &diff_dst[diff_dst_d.blk_off(n, ch, oh, ow)]; + par_conv.filt = &weights[weights_d.blk_off(ch, 0, 0, i_b_overflow + + stride_off_h, i_r_overflow + stride_off_w)]; + + par_conv.kh_padding = nstl::max(0, jcp.kh - i_t_overflow - i_b_overflow + - stride_off_h); + par_conv.kw_padding = nstl::max(0, jcp.kw - i_l_overflow - i_r_overflow + - stride_off_w); + + par_conv.ur_str_w = ur_str_w; + + par_conv.ch_blocks = nstl::min(ch + ch_num, jcp.nb_ch) - ch; + + return par_conv; + }; + + const int chb_work = utils::div_up(jcp.nb_ch, jcp.nb_ch_blocking); + parallel_nd(jcp.mb, chb_work, jcp.ih, + [&](int n, int chb, int ih) { + int ch = chb * jcp.nb_ch_blocking; + int ch_num = jcp.nb_ch_blocking; + + const int i_t_overflow = nstl::max(0, (int)(jcp.kh - 1 - ih + - jcp.t_pad)); + const int i_b_overflow = nstl::max(0, (int)(jcp.kh - 1 + - (jcp.ih - 1 - ih) - jcp.b_pad)); + + int oh = ih + jcp.t_pad - i_b_overflow; + int stride_off_h = oh % jcp.stride_h; + oh /= jcp.stride_h; + + for (int i_str_w = 0; i_str_w < jcp.stride_w; i_str_w++) { + // left border + int iw = i_str_w; + int l_border = nstl::min(jcp.kw - 1 - jcp.l_pad, jcp.iw); + int ur_str_w = 1; + for (; iw < l_border; iw += jcp.stride_w) { + jit_conv_call_s par_conv = kernel_params(ur_str_w, iw, oh, + ih, i_t_overflow, i_b_overflow, + stride_off_h, ch, ch_num, n); + + kernel_->jit_ker(&par_conv); + } + + // main loop + ur_str_w = nstl::min((jcp.iw - jcp.kw + jcp.r_pad - iw) + / jcp.stride_w, jcp.iw); + if (ur_str_w > 0) { + jit_conv_call_s par_conv = kernel_params(ur_str_w, iw, oh, + ih, i_t_overflow, i_b_overflow, + stride_off_h, ch, ch_num, n); + + kernel_->jit_ker(&par_conv); + + iw += ur_str_w * jcp.stride_w; + } + + // right border + ur_str_w = 1; + for (; iw < jcp.iw; iw += jcp.stride_w) { + jit_conv_call_s par_conv = kernel_params(ur_str_w, iw, oh, + ih, i_t_overflow, i_b_overflow, + stride_off_h, ch, ch_num, n); + + kernel_->jit_ker(&par_conv); + } + } + }); +} + +template struct _jit_uni_dw_convolution_bwd_data_t; +template struct _jit_uni_dw_convolution_bwd_data_t; +template struct _jit_uni_dw_convolution_bwd_data_t; + +template +_jit_uni_dw_convolution_bwd_weights_t:: +_jit_uni_dw_convolution_bwd_weights_t(const pd_t *apd) + : cpu_primitive_t(apd) + , kernel_(nullptr), acc_ker_(nullptr) +{ + kernel_ = new jit_uni_dw_conv_bwd_weights_kernel_f32(pd()->jcp_); + if (pd()->jcp_.nthr_mb > 1 && do_parallel_reduction()) + acc_ker_ = new cpu_accumulator_1d_t(); +} + +template +void _jit_uni_dw_convolution_bwd_weights_t::execute_backward_weights( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + auto diff_wei_reduction_buf = + scratchpad(ctx).template get(key_conv_wei_reduction); + auto diff_bia_reduction_buf = + scratchpad(ctx).template get(key_conv_bia_reduction); + + const auto &jcp = kernel_->jcp; + + /* Used when executing a parallel reduction */ + simple_barrier::ctx_t reduction_bctx; + simple_barrier::ctx_init(&reduction_bctx); + + const size_t wei_size = jcp.ngroups * jcp.kh * jcp.kw; + const size_t bias_size = jcp.with_bias ? jcp.ngroups : 0; + + const int ch_block = jcp.ch_block; + + auto set_kernel_params = [&](jit_dw_conv_call_s *conv_params, + const int batch, const int group, const int oh_start, + const int work_size, const unsigned char exec_flag, + const size_t kh_padding, const size_t filter_off) { + const int tpad_underflow_off = jcp.t_pad - filter_off; + + conv_params->exec_flags = exec_flag; + conv_params->kh_count = jcp.kh - kh_padding; + + const int oh_s = oh_start; + const int oh_e = oh_start + work_size; + const int ih_s = oh_s * jcp.stride_h; + + conv_params->filter_pad_off + = filter_off * jcp.kw * ch_block * sizeof(float); + conv_params->oh_index = oh_s; + conv_params->oh_count = oh_e; + + size_t diff_dst_off + = ((batch * (jcp.ngroups / ch_block) + group) * jcp.oh + + oh_start) + * jcp.ow; + + size_t src_off = ((batch * (jcp.ngroups / ch_block) + group) * jcp.ih + + ih_s - tpad_underflow_off) * jcp.iw; + + conv_params->output = &diff_dst[diff_dst_off * ch_block]; + conv_params->input = &src[src_off * ch_block]; + }; + + parallel(jcp.nthr, [&](const int ithr, const int nthr) { + assert(nthr == jcp.nthr); + + auto conv_params = jit_dw_conv_call_s(); + const int h_block_size = 15; + + /* assign iteration space to thread */ + const int ithr_g = ithr % jcp.nthr_g; + const int ithr_mb = (ithr / jcp.nthr_g) % jcp.nthr_mb; + + /* split dimensions */ + int g_start{ 0 }, g_end{ 0 }; + balance211(jcp.nb_ch, jcp.nthr_g, ithr_g, g_start, g_end); + + int mb_start{ 0 }, mb_end{ 0 }; + balance211(jcp.mb, jcp.nthr_mb, ithr_mb, mb_start, mb_end); + + auto diff_wei = ithr_mb == 0 + ? diff_weights : diff_wei_reduction_buf + (ithr_mb - 1) * wei_size; + auto diff_bia = ithr_mb == 0 + ? diff_bias : diff_bia_reduction_buf + (ithr_mb - 1) * bias_size; + + for (int g = g_start; g < g_end; ++g) { + unsigned char zero_filter_flag = FLAG_ZERO_FILTER; + unsigned char zero_bias_flag = jcp.with_bias ? FLAG_ZERO_BIAS : 0; + + size_t diff_wei_off = g * jcp.kh * jcp.kw; + conv_params.filter = &diff_wei[diff_wei_off * ch_block]; + + if (jcp.with_bias) + conv_params.bias = &diff_bia[g * ch_block]; + + for (int mb = mb_start; mb < mb_end; ++mb) { + int oh = 0; + while (oh < jcp.oh) { + const int h_work = nstl::min(h_block_size, jcp.oh - oh); + auto kh_t_padding = nstl::max(0, jcp.t_pad - oh); + auto kh_b_padding + = (oh * jcp.stride_h + jcp.kh - 1 > jcp.ih) ? + jcp.b_pad - (h_work - 1) : + 0; + + set_kernel_params(&conv_params, mb, g, oh, h_work, + zero_filter_flag | zero_bias_flag, + kh_t_padding + kh_b_padding, kh_t_padding); + kernel_->jit_ker(&conv_params); + + zero_bias_flag &= ~FLAG_ZERO_BIAS; + zero_filter_flag &= ~FLAG_ZERO_FILTER; + oh += h_work; + } + } + } + + if (do_parallel_reduction() && jcp.nthr_mb > 1) { + size_t reduct_start{ 0 }, reduct_end{ 0 }; + balance211(wei_size, nthr, ithr, reduct_start, reduct_end); + + const int acc_size = reduct_end - reduct_start; + const size_t reduct_off = reduct_start; + auto *acc_data = diff_weights + reduct_off; + + simple_barrier::barrier(&reduction_bctx, nthr); + + for (int thr_mb = 1; thr_mb < jcp.nthr_mb; ++thr_mb) { + auto *src_data = diff_wei_reduction_buf + + (thr_mb - 1) * wei_size + reduct_off; + acc_ker_->accumulate(acc_data, src_data, acc_size); + } + } + }); + + if (jcp.nthr_mb <= 1) return; + + /* Apply single-threaded 'mb' reduction */ + for (int thr_mb = 1; thr_mb < jcp.nthr_mb; ++thr_mb) { + size_t mb_accum_offset = (thr_mb - 1) * wei_size; + size_t b_accum_offset = (thr_mb - 1) * bias_size; + + for (int g = 0; g < jcp.nb_ch; ++g) { + /* Reduction on Bias */ + if (jcp.with_bias) { + PRAGMA_OMP_SIMD() + for (int g_block = 0; g_block < ch_block; ++g_block) { + size_t bias_offset = g * ch_block + g_block; + diff_bias[bias_offset] += diff_bia_reduction_buf[ + b_accum_offset + bias_offset]; + } + } + + if (do_parallel_reduction()) continue; + + for (int kh = 0; kh < jcp.kh; ++kh) + for (int kw = 0; kw < jcp.kw; ++kw) + { + size_t wei_offset = (g * jcp.kh + kh) * jcp.kw + kw; + PRAGMA_OMP_SIMD() + for (int g_block = 0; g_block < ch_block; ++g_block) { + const size_t off = wei_offset * ch_block + g_block; + diff_weights[off] += + diff_wei_reduction_buf[mb_accum_offset + off]; + } + } + } + } +} + +template struct _jit_uni_dw_convolution_bwd_weights_t; +template struct _jit_uni_dw_convolution_bwd_weights_t; +template struct _jit_uni_dw_convolution_bwd_weights_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp new file mode 100644 index 0000000000..ca53749ec2 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp @@ -0,0 +1,266 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_UNI_DW_CONVOLUTION_HPP +#define CPU_JIT_UNI_DW_CONVOLUTION_HPP + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" + +#include "cpu_barrier.hpp" +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" +#include "cpu_reducer.hpp" + +#include "jit_uni_dw_conv_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct _jit_uni_dw_convolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + pd_t(engine_t *engine, const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const typename pd_t::base_class *hint_fwd_pd) + : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_dw:", isa, ""), + _jit_uni_dw_convolution_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + status_t status = jit_uni_dw_conv_fwd_kernel_f32::init_conf( + jcp_, *desc(), src_md(), *weights_md(), *dst_md(), *attr()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_uni_dw_conv_fwd_kernel_f32::init_scratchpad(scratchpad, + jcp_); + + return status::success; + } + + jit_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = isa == avx512_common ? nChw16c : nChw8c; + auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g; + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + _jit_uni_dw_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) + { kernel_ = new jit_uni_dw_conv_fwd_kernel_f32(pd()->jcp_); } + + ~_jit_uni_dw_convolution_fwd_t() { delete kernel_; } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_uni_dw_conv_fwd_kernel_f32 *kernel_; +}; + +using jit_avx512_common_dw_convolution_fwd_t = + _jit_uni_dw_convolution_fwd_t; +using jit_avx2_dw_convolution_fwd_t = _jit_uni_dw_convolution_fwd_t; +using jit_sse42_dw_convolution_fwd_t = _jit_uni_dw_convolution_fwd_t; + +template +struct _jit_uni_dw_convolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_data_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() + {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_dw:", isa, ""), + _jit_uni_dw_convolution_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::undef, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + + if (!ok) return status::unimplemented; + + status_t status = jit_uni_dw_conv_bwd_data_kernel_f32:: + init_conf(jcp_, *desc(), *diff_src_md(), *weights_md(), + *diff_dst_md()); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_uni_dw_conv_bwd_data_kernel_f32::init_scratchpad( + scratchpad, jcp_); + + return status::success; + } + + jit_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = isa == avx512_common ? nChw16c : nChw8c; + auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g; + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + _jit_uni_dw_convolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) + { kernel_ = new jit_uni_dw_conv_bwd_data_kernel_f32(pd()->jcp_); } + ~_jit_uni_dw_convolution_bwd_data_t() { delete kernel_; }; + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_uni_dw_conv_bwd_data_kernel_f32 *kernel_; +}; + +using jit_avx512_common_dw_convolution_bwd_data_t = + _jit_uni_dw_convolution_bwd_data_t; +using jit_avx2_dw_convolution_bwd_data_t = + _jit_uni_dw_convolution_bwd_data_t; +using jit_sse42_dw_convolution_bwd_data_t = + _jit_uni_dw_convolution_bwd_data_t; + +template +struct _jit_uni_dw_convolution_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_weights_pd_t { + pd_t(engine_t *engine, + const convolution_desc_t *adesc, + const primitive_attr_t *attr, + const convolution_fwd_pd_t *hint_fwd_pd) + : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , jcp_() {} + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit_dw:", isa, ""), + _jit_uni_dw_convolution_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(data_type::f32, data_type::f32, + data_type::f32, data_type::f32, data_type::f32) + && !has_zero_dim_memory() + && set_default_formats(); + if (!ok) return status::unimplemented; + + const int max_threads = mkldnn_in_parallel() + ? 1 : mkldnn_get_max_threads(); + + status_t status = jit_uni_dw_conv_bwd_weights_kernel_f32:: + init_conf(jcp_, *desc(), *src_md(), *diff_weights_md(), + *diff_dst_md(), max_threads); + if (status != status::success) return status; + + auto scratchpad = scratchpad_registry().registrar(); + jit_uni_dw_conv_bwd_weights_kernel_f32::init_scratchpad( + scratchpad, jcp_); + + return status::success; + } + + jit_conv_conf_t jcp_; + + protected: + bool set_default_formats() { + using namespace format_tag; + + auto dat_tag = isa == avx512_common ? nChw16c : nChw8c; + auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g; + + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + _jit_uni_dw_convolution_bwd_weights_t(const pd_t *apd); + ~_jit_uni_dw_convolution_bwd_weights_t() { + delete kernel_; + delete acc_ker_; + }; + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + bool do_parallel_reduction() const { return false; } + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_uni_dw_conv_bwd_weights_kernel_f32 *kernel_; + cpu_accumulator_1d_t *acc_ker_; +}; + +using jit_avx512_common_dw_convolution_bwd_weights_t = + _jit_uni_dw_convolution_bwd_weights_t; +using jit_avx2_dw_convolution_bwd_weights_t = + _jit_uni_dw_convolution_bwd_weights_t; +using jit_sse42_dw_convolution_bwd_weights_t = + _jit_uni_dw_convolution_bwd_weights_t; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp new file mode 100644 index 0000000000..2af6435871 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp @@ -0,0 +1,1142 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "utils.hpp" + +#include "jit_uni_eltwise.hpp" + +#define GET_OFF(field) offsetof(jit_args, field) + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; + +template +void jit_uni_eltwise_injector_f32::injector_preamble(size_t start_idx, + size_t end_idx) { + preserved_vecs_count = 0; + vecs_to_preserve = (size_t)aux_vecs_count(alg_); + start_idx_tail = start_idx; + + // For sse42 mask register has to be Xmm(0) + if (isa == sse42 && vecs_to_preserve > 0) { + size_t idx = 0; + assert(idx < start_idx); + preserved_vec_idxs[preserved_vecs_count++] = idx; + } + + for (size_t idx = preserved_vecs_count; idx < vecs_count; idx++) { + if (preserved_vecs_count >= vecs_to_preserve) break; + if (start_idx <= idx && idx < end_idx) continue; + + preserved_vec_idxs[preserved_vecs_count++] = idx; + } + + size_t preserved_vecs_count_tail = vecs_to_preserve - preserved_vecs_count; + for (size_t i = 0; i < preserved_vecs_count_tail; i++) { + preserved_vec_idxs[preserved_vecs_count++] = start_idx_tail++; + } + + assert(preserved_vecs_count == vecs_to_preserve); + + if (save_state_) { + h->push(p_table); + + if (preserved_vecs_count) + h->sub(h->rsp, preserved_vecs_count * vlen); + + for (size_t i = 0; i < preserved_vecs_count; ++i) + h->uni_vmovups(h->ptr[h->rsp + i * vlen], + Vmm(preserved_vec_idxs[i])); + + load_table_addr(); + } + + assign_regs(); +} + +template +void jit_uni_eltwise_injector_f32::injector_preamble_tail(size_t start_idx) +{ + size_t tail_vecs_to_preserve = start_idx_tail - start_idx; + if (tail_vecs_to_preserve == 0) return; + + const int idx_off = vecs_to_preserve - tail_vecs_to_preserve; + + if (save_state_) { + if (idx_off) + h->add(h->rsp, idx_off * vlen); + + for (size_t i = 0; i < tail_vecs_to_preserve; ++i) + h->uni_vmovups(Vmm(preserved_vec_idxs[idx_off + i]), + h->ptr[h->rsp + i * vlen]); + } + + for (size_t i = 0; i < tail_vecs_to_preserve; ++i) + preserved_vec_idxs[idx_off + i] += tail_vecs_to_preserve; + + if (save_state_) { + for (size_t i = 0; i < tail_vecs_to_preserve; ++i) + h->uni_vmovups(h->ptr[h->rsp + i * vlen], + Vmm(preserved_vec_idxs[idx_off + i])); + + if (idx_off) + h->sub(h->rsp, idx_off * vlen); + } + + assign_regs(); +} + +template +void jit_uni_eltwise_injector_f32::injector_postamble() { + if (!save_state_) return; + + for (size_t i = 0; i < preserved_vecs_count; ++i) + h->uni_vmovups(Vmm(preserved_vec_idxs[i]), + h->ptr[h->rsp + i * vlen]); + + if (preserved_vecs_count) + h->add(h->rsp, preserved_vecs_count * vlen); + + h->pop(p_table); +} + +template +void jit_uni_eltwise_injector_f32::assign_regs() { + vmm_mask = Vmm(preserved_vec_idxs[0]); + vmm_aux0 = Vmm(preserved_vec_idxs[0]); + vmm_aux1 = Vmm(preserved_vec_idxs[1]); + vmm_aux2 = Vmm(preserved_vec_idxs[2]); + vmm_aux3 = Vmm(preserved_vec_idxs[3]); + vmm_aux4 = Vmm(preserved_vec_idxs[4]); +} + +template +void jit_uni_eltwise_injector_f32::exp_compute_vector(const Vmm &vmm_src) { + h->uni_vminps(vmm_src, vmm_src, table_val(10)); + h->uni_vmaxps(vmm_src, vmm_src, table_val(11)); + h->uni_vmovups(vmm_aux0, vmm_src); + //calculate exp(x) + // fx = x * log2ef + 0.5 + h->uni_vmulps(vmm_src, vmm_src, table_val(2)); + h->uni_vaddps(vmm_src, vmm_src, table_val(1)); + + // tmp = floorf(fx) + if (isa == avx512_common) { + h->vcvtps2dq(vmm_aux1 | h->T_rd_sae, vmm_src); + h->vcvtdq2ps(vmm_aux1, vmm_aux1); + + h->vcmpps(k_mask, vmm_aux1, vmm_src, _cmp_nle_us); + h->vmovups(vmm_aux3 | k_mask | h->T_z, table_val(0)); + + h->uni_vsubps(vmm_aux1, vmm_aux1, vmm_aux3); + } else { + h->uni_vroundps(vmm_aux1, vmm_src, _op_floor); + } + + //keep fx for further computations + h->uni_vmovups(vmm_src, vmm_aux1); //vmm_src = fx + + //x = x - fx * ln2 + h->uni_vfnmadd231ps(vmm_aux0, vmm_aux1, table_val(3)); + + // compute 2^n + h->uni_vcvtps2dq(vmm_aux1, vmm_src); + h->uni_vpaddd(vmm_aux1, vmm_aux1, table_val(4)); + h->uni_vpslld(vmm_aux1, vmm_aux1, 23); //Vmm(6) = 2^-fx + + // y = p5 + h->uni_vmovups(vmm_src, table_val(9)); + // y = y * x + p4 + h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(8)); + // y = y * x + p3 + h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(7)); + // y = y * x + p2 + h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(6)); + // y = y * x + p1 + h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(0)); + // y = y * x + p0 + h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(5)); //exp(q) + // y = y * 2^n + h->uni_vmulps(vmm_src, vmm_src, vmm_aux1); +} + +template +void jit_uni_eltwise_injector_f32::relu_compute_vector(const Vmm &vmm_src) +{ + const int alpha_off = 0, zero_off = 1; + + h->uni_vmovups(vmm_aux1, vmm_src); + if (isa == sse42) { + h->movups(vmm_mask, vmm_src); + h->mulps(vmm_src, table_val(alpha_off)); + h->cmpps(vmm_mask, table_val(zero_off), _cmp_nle_us); + h->blendvps(vmm_src, vmm_aux1); + } else if (isa == avx2) { + h->vmulps(vmm_src, vmm_src, table_val(alpha_off)); + h->vcmpgtps(vmm_mask, vmm_aux1, table_val(zero_off)); + h->vblendvps(vmm_src, vmm_src, vmm_aux1, vmm_mask); + } else if (isa == avx512_common) { + h->vmulps(vmm_src, vmm_src, table_val(alpha_off)); + h->vcmpps(k_mask, vmm_aux1, table_val(zero_off), _cmp_nle_us); + h->vblendmps(vmm_src | k_mask, vmm_src, vmm_aux1); + } +} + +template +void jit_uni_eltwise_injector_f32::relu_zero_ns_compute_vector( + const Vmm &vmm_src) { + const int zero_off = 1; + h->uni_vmaxps(vmm_src, vmm_src, table_val(zero_off)); +} + +template +void jit_uni_eltwise_injector_f32::elu_compute_vector(const Vmm &vmm_src) { + const int alpha_off = 23, zero_off = 24; + + // compute exponent + h->uni_vmovups(vmm_aux2, vmm_src); + exp_compute_vector(vmm_src); + + // alpha * (exp(x) - 1) + h->uni_vsubps(vmm_src, vmm_src, table_val(0)); + h->uni_vmulps(vmm_src, vmm_src, table_val(alpha_off)); + + // combine with mask + if (isa == sse42) { + h->pxor(vmm_mask, vmm_mask); + h->cmpps(vmm_mask, vmm_aux2, _cmp_le_os); + h->blendvps(vmm_src, vmm_aux2); + } else if (isa == avx2) { + h->uni_vcmpgtps(vmm_mask, vmm_aux2, table_val(zero_off)); + h->uni_vblendvps(vmm_src, vmm_src, vmm_aux2, vmm_mask); + } else if (isa == avx512_common) { + h->vcmpps(k_mask, vmm_aux2, table_val(zero_off), _cmp_nle_us); + h->vblendmps(vmm_src | k_mask, vmm_src, vmm_aux2); + } +} + +template +void jit_uni_eltwise_injector_f32::tanh_compute_vector(const Vmm &vmm_src) +{ + // # comes from Taylor expansion error bound + // > linear_sat_point = single(sqrt(3) * 1b-12); + // # comes from the exp formula cancellation + // > exp_bound_point = (single(log(3)/2)); + // # comes from rounding accuracy in float + // > one_sat_point = round(atanh(1 - 1b-25), single, RU); + // > P = fpminimax(f, [|1, 3, 5, 7, 9|], [|24... |], + // [linear_sat_point, exp_bound_point], relative, floating); + // > err_bound = D(sup(supnorm(P, tanh(x), + // [linear_sat_point, exp_bound_point], relative, theta))); + // 0x1.fffd6f00b9539p-25 + // > P; + // x * (0x1.fffffep-1 + x^0x1p1 * (-0x1.55539ep-2 + x^0x1p1 * + // (0x1.10be3ep-3 + x^0x1p1 * (-0x1.ae57b4p-5 + // + x^0x1p1 * 0x1.09fa1p-6)))) + + // register mapping + // vmm_src contains input + // vmm_aux0 contains mask of currently valid results. + // 1 is need computation, 0 is already computed + // vmm_aux1 contains current output + // vmm_aux2, vmm_aux3 contains auxiliary values + // vmm_aux4 contains the original sign of inputs + + Label end_tanh_label; + + auto test_exit =[&](Xbyak::Address threshold){ + // is not necessary for >AVX, but should not matter on perf + h->uni_vmovups(vmm_aux0, vmm_src); + if (isa == avx512_common){ + h->vcmpps(k_mask, vmm_aux0, threshold, 0x5); + h->kortestw(k_mask, k_mask); + } else { + h->uni_vcmpgeps(vmm_aux0, vmm_aux0, threshold); + h->uni_vtestps(vmm_aux0, vmm_aux0); + } + h->jz(end_tanh_label, Xbyak::CodeGenerator::T_NEAR); + }; + + auto blend_results=[&](Vmm vmm_partial_res){ + if (isa == avx512_common) + h->vblendmps(vmm_aux1 | k_mask, vmm_aux1, vmm_partial_res); + else + h->uni_vblendvps(vmm_aux1, vmm_aux1, vmm_partial_res, vmm_aux0); + }; + + // because tanh(x) = -tanh(-x), we extract sign to make x postive + // and reapply sign at the end + // mov is not necessary for >AVX, but should not matter for performance + h->uni_vmovups(vmm_aux4, vmm_src); + h->uni_vandps(vmm_aux4, vmm_aux4, table_val(12)); + h->uni_vandps(vmm_src, vmm_src, table_val(17)); + + // if x < linear_sat_point for all inputs, we just return the input + h->uni_vmovups(vmm_aux1, vmm_src); + test_exit(table_val(13)); + + // if one of the mask is one, we have to compute an better approx + h->uni_vmovups(vmm_aux2, vmm_src); + h->uni_vmulps(vmm_aux2, vmm_aux2, vmm_aux2); + h->uni_vmovups(vmm_aux3, table_val(22)); + h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(21)); + h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(20)); + h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(19)); + h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(18)); + h->uni_vmulps(vmm_aux3, vmm_aux3, vmm_src); + + // we blend only the result that need update + blend_results(vmm_aux3); + + // if x < exp_bound_point, we go to return point + test_exit(table_val(14)); + + // if not we use a better approx 1 - 2 / (1 + exp(2x)) + // compute 2x + h->uni_vmovups(vmm_aux3, vmm_src); + h->uni_vaddps(vmm_aux3, vmm_aux3, vmm_aux3); + + // Compute exp(2x) + // We need to save kmask, vmm_aux0, vmm_aux1 and vmm_src as exp can use them + // vmm_src is not more read afterwards, so we do not have to save it + auto stack_size = 3 * vlen + (isa == avx512_common) * 4; + h->sub(h->rsp, stack_size); + h->uni_vmovups(h->ptr[h->rsp + 0 * vlen], vmm_aux0); + h->uni_vmovups(h->ptr[h->rsp + 1 * vlen], vmm_aux1); + h->uni_vmovups(h->ptr[h->rsp + 2 * vlen], vmm_src); + if (isa == avx512_common) + h->kmovw(h->ptr[h->rsp + 3 * vlen], k_mask); + + exp_compute_vector(vmm_aux3); + + h->uni_vmovups(vmm_aux0, h->ptr[h->rsp + 0 * vlen]); + h->uni_vmovups(vmm_aux1, h->ptr[h->rsp + 1 * vlen]); + h->uni_vmovups(vmm_src, h->ptr[h->rsp + 2 * vlen]); + if (isa == avx512_common) + h->kmovw(k_mask, h->ptr[h->rsp + 3 * vlen]); + h->add(h->rsp, stack_size); + + // 1 + exp(2x) + h->uni_vaddps(vmm_aux3, vmm_aux3, table_val(0)); + + // 1 - 2 / (1 + exp(2x)) + h->uni_vmovups(vmm_aux2, table_val(16)); + h->uni_vdivps(vmm_aux2, vmm_aux2, vmm_aux3); + h->uni_vaddps(vmm_aux2, vmm_aux2, table_val(0)); + + // we blend only the result that need update + blend_results(vmm_aux2); + + // finally, we saturate to 1 if needed + // TODO: maybe move that up if most inputs saturate in practice + if (isa == avx512_common) + h->vcmpps(k_mask, vmm_aux0, table_val(15), 0x5); + else { + h->uni_vmovups(vmm_aux0, vmm_src); + h->uni_vcmpgeps(vmm_aux0, vmm_aux0, table_val(15)); + } + h->uni_vmovups(vmm_aux2, table_val(0)); + blend_results(vmm_aux2); + + h->L(end_tanh_label); + { + // we apply the sign of x to the result and we are done + h->uni_vmovups(vmm_src, vmm_aux1); + h->uni_vpxor(vmm_src, vmm_src, vmm_aux4); + } +} + +template +void jit_uni_eltwise_injector_f32::square_compute_vector( + const Vmm &vmm_src) { + h->uni_vmulps(vmm_src, vmm_src, vmm_src); +} + +template +void jit_uni_eltwise_injector_f32::abs_compute_vector(const Vmm &vmm_src) { + // compute abs(x) = _mm_and_ps(x, 01111..111)); + h->uni_vandps(vmm_src, vmm_src, table_val(0)); +} + +template +void jit_uni_eltwise_injector_f32::sqrt_compute_vector(const Vmm &vmm_src) +{ + if (isa == avx512_common) { + h->vcmpps(k_mask, vmm_src, table_val(0), _cmp_nle_us); + h->uni_vsqrtps(vmm_aux1, vmm_src); + h->uni_vmovups(vmm_src, table_val(0)); + h->vblendmps(vmm_src | k_mask, vmm_src, vmm_aux1); + } else { + h->uni_vmovups(vmm_mask, vmm_src); + h->uni_vcmpgtps(vmm_mask, vmm_mask, table_val(0)); + h->uni_vsqrtps(vmm_aux1, vmm_src); + h->uni_vmovups(vmm_src, table_val(0)); + h->uni_vblendvps(vmm_src, vmm_src, vmm_aux1, vmm_mask); + } +} + +template +void jit_uni_eltwise_injector_f32::linear_compute_vector( + const Vmm &vmm_src) { + // compute x = alpha * x + beta; + h->uni_vmovups(vmm_aux0, table_val(0)); + h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(1)); +} + +template +void jit_uni_eltwise_injector_f32::bounded_relu_compute_vector( + const Vmm &vmm_src) { + // compute bounded relu */ + h->uni_vmaxps(vmm_src, vmm_src, table_val(1)); + h->uni_vminps(vmm_src, vmm_src, table_val(0)); +} + +template +void jit_uni_eltwise_injector_f32::soft_relu_compute_vector( + const Vmm &vmm_src) { + // duplicate src + h->uni_vmovups(vmm_aux2, vmm_src); + + h->uni_vminps(vmm_src, vmm_src, table_val(24)); + h->uni_vmaxps(vmm_src, vmm_src, table_val(25)); + h->uni_vmovups(vmm_aux1, vmm_src); + // calculate exp(x) + // fx = x * log2ef + 0.5 + h->uni_vmulps(vmm_src, vmm_src, table_val(2)); + h->uni_vaddps(vmm_src, vmm_src, table_val(1)); + + // tmp = floorf(fx) + if (isa == avx512_common) { + h->vcvtps2dq(vmm_aux0 | h->T_rd_sae, vmm_src); + h->vcvtdq2ps(vmm_aux0, vmm_aux0); + + h->vcmpps(k_mask, vmm_aux0, vmm_src, _cmp_nle_us); + h->vmovups(vmm_aux3 | k_mask | h->T_z, table_val(0)); + + h->vsubps(vmm_aux0, vmm_aux0, vmm_aux3); + } else { + h->uni_vroundps(vmm_aux0, vmm_src, _op_floor); + } + + // keep fx for further computations + h->uni_vmovups(vmm_src, vmm_aux0); //vmm_src = fx + // calculation fx * ln2 + h->uni_vmulps(vmm_aux0, vmm_aux0, table_val(3)); + // x = x - fx * ln2 + h->uni_vsubps(vmm_aux1, vmm_aux1, vmm_aux0); + // y = p5 + h->uni_vmovups(vmm_aux3, table_val(22)); + // y = y * x + p4 + h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(21)); + // y = y * x + p3 + h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(20)); + // y = y * x + p2 + h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(19)); + // y = y * x + p1 + h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(0)); + // y = y * x + p0 + h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(17)); + + // compute 2^(-n) + if (isa == avx512_common) { + h->vmulps(vmm_aux1, vmm_src, table_val(23)); + h->vcvtps2dq(vmm_aux1, vmm_aux1); + } else { + h->uni_vcvtps2dq(vmm_aux1, vmm_src); + h->uni_vpsignd(vmm_aux1, vmm_aux1, table_val(23)); + } + + h->uni_vpaddd(vmm_aux1, vmm_aux1, table_val(4)); + h->uni_vpslld(vmm_aux1, vmm_aux1, 23); //vmm_aux1 = 2^-fx + // calculate ln(1 + y) + h->uni_vaddps(vmm_aux3, vmm_aux3, vmm_aux1); + // x = y; y is free; keep x for further computations + h->uni_vmovups(vmm_src, vmm_aux3); + // frexp() + h->uni_vpsrld(vmm_src, vmm_src, 23); + h->uni_vcvtdq2ps(vmm_src, vmm_src); + // got n. where n is x = 2^n * y. y = 0.5 .. 1 + h->uni_vsubps(vmm_src, vmm_src, table_val(5)); + + h->uni_vandps(vmm_aux3, vmm_aux3, table_val(6)); + // got y. (mantisa) 0.5 < y < 1 + h->uni_vorps(vmm_aux3, vmm_aux3, table_val(7)); + // y = y - 1 + h->uni_vsubps(vmm_aux3, vmm_aux3, table_val(0)); + // y = p8 + h->uni_vmovups(vmm_aux1, table_val(16)); + // y = y * x + p7 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(15)); + // y = y * x + p6 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(14)); + // y = y * x + p5 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(13)); + // y = y * x + p4 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(12)); + // y = y * x + p3 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(11)); + // y = y * x + p2 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(10)); + // y = y * x + p1 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(9)); + // y = y * x + p0 ; p0 = 0 + h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(8)); + //calculate ln(2) * n + h->uni_vmulps(vmm_src, vmm_src, table_val(3)); + h->uni_vaddps(vmm_aux1, vmm_aux1, vmm_src); + h->uni_vaddps(vmm_aux1, vmm_aux1, vmm_aux0); + + // get vmm_mask = src > max logf + h->uni_vmovups(vmm_mask, vmm_aux2); + if (isa == avx512_common) { + // y = (x < max log f) ? soft_relu(x) : x + h->vcmpps(k_mask, vmm_mask, table_val(24), _cmp_nle_us); + h->vblendmps(vmm_aux1 | k_mask, vmm_aux1, vmm_aux2); + } else { + // y = (x < max log f) ? soft_relu(x) : x + h->uni_vcmpgtps(vmm_mask, vmm_mask, table_val(24)); + h->uni_vblendvps(vmm_aux1, vmm_aux1, vmm_aux2, vmm_mask); + } + + h->uni_vmovups(vmm_src, vmm_aux1); +} + +template +void jit_uni_eltwise_injector_f32::logistic_compute_vector( + const Vmm &vmm_src) { + // we store the original sign and make x negative + // IMPORTANT: we assume vmm_aux0 to be xmm0, as for sse4.2 path it is required + // IMPORTANT: we use vmm_aux2 for the mask as exp_compute does not use it. + h->uni_vmovups(vmm_aux2, vmm_src); + h->uni_vandps(vmm_aux2, vmm_aux2, table_val(12)); + h->uni_vorps(vmm_src, vmm_src, table_val(12)); + + exp_compute_vector(vmm_src); + // dup exp(x) + h->uni_vmovups(vmm_aux1, vmm_src); + // (exp(x) + 1) + h->uni_vaddps(vmm_aux1, vmm_aux1, table_val(0)); + // y = exp(x) / (exp(x) + 1) + h->uni_vdivps(vmm_src, vmm_src, vmm_aux1); + + // Now we have to apply the "symmetry" based on original sign + h->uni_vmovups(vmm_aux3, table_val(0)); + h->uni_vsubps(vmm_aux3, vmm_aux3, vmm_src); + if (isa == avx512_common) { + h->vptestmd(k_mask, vmm_aux2, vmm_aux2); + h->vblendmps(vmm_aux3 | k_mask, vmm_aux3, vmm_src); + } else { + h->uni_vmovups(vmm_aux0, vmm_aux2);// The mask should be xmm0 for sse4.2 + h->uni_vblendvps(vmm_aux3, vmm_aux3, vmm_src, vmm_aux0); + } + h->uni_vmovups(vmm_src, vmm_aux3); +} + +template +void jit_uni_eltwise_injector_f32::relu_prepare_table() { + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_)); + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0); +} + +template +void jit_uni_eltwise_injector_f32::elu_prepare_table() { + const unsigned int cvals[] = { + 0x3f800000, // [0] 1.0f + 0x3f000000, // [1] 0.5f + 0x3fb8aa3b, // [2] log2ef = 1.44269502f + 0x3f317218, // [3] ln2f = 0.69314718f + 0x0000007f, // [4] 0x7f + // exp(x) polynom + 0x3f800001, // [5] p0 = 1.0000001f + 0x3efffe85, // [6] p2 = 0.4999887f + 0x3e2aaa3e, // [7] p3 = 0.16666505f + 0x3d2bb1b1, // [8] p4 = 0.041917507f + 0x3c091ec1, // [9] p5 = 0.008369149f + 0x42b0c0a5, //[10] max logf = 88.3762589f + 0xc1766666, //[11] min logf = -14.5f + // tanh(x) constants, + 0x80000000, //[12] mask to extract sign + 0x39ddb3d7, //[13] arg below which tanh(x) = x + 0x3f0c9f54, //[14] arg below which pol approx is valid + 0x41102cb4, //[15] arg after which tanh(x) = 1 + 0xc0000000, //[16] -2.0f + 0x7fffffff, //[17] mask to make positive + // tanh pol approx + 0x3f7fffff, //[18] p0 + 0xbeaaa9cf, //[19] p1 + 0x3e085f1f, //[20] p2 + 0xbd572bda, //[21] p3 + 0x3c84fd08, //[22] p4 + }; + + for (size_t i = 0; i < sizeof(cvals) / sizeof(cvals[0]); ++i) { + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(cvals[i]); + } + + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_)); + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0); +} + +template +void jit_uni_eltwise_injector_f32::soft_relu_prepare_table() { + const unsigned int cvals[] = { + 0x3f800000, // [0] 1.0f + 0x3f000000, // [1] 0.5f + 0x3fb8aa3b, // [2] log2ef = 1.44269502f + 0x3f317218, // [3] ln2f = 0.69314718f + 0x0000007f, // [4] 0x7f + 0x42fc0000, // [5] 126 + 0x807fffff, // [6] and with (to get 0.5 * mantissa) + 0x3f000000, // [7] or with (to get 0.5 * mantissa) + // ln(1 + x) polynomial + 0xb2b4637d, // [8] p0 = 0.0000000244f + 0x3f7fff8e, // [9] p1 = 0.9999976971f + 0xbf001759, //[10] p2 = -0.5002478215f + 0x3ea70608, //[11] p3 = 0.3272714505f + 0xbea3d7bf, //[12] p4 = -0.3153830071f + 0xbe361d04, //[13] p5 = -0.1701777461f + 0xbfa8f1e6, //[14] p6 = -1.3254635147f + 0xbfe1e812, //[15] p7 = -1.7971917960f + 0xbfc4d30e, //[16] p8 = -1.5652673123f + // exp(x) polynomial + 0x3f800001, //[17] p0 = 1.0000001f + 0x3f800000, //[18] p1 = 1.0f + 0x3efffe85, //[19] p2 = 0.4999887f + 0x3e2aaa3e, //[20] p3 = 0.16666505f + 0x3d2bb1b1, //[21] p4 = 0.041917507f + 0x3c091ec1, //[22] p5 = 0.008369149f + 0xbf800000, //[23] is required for sign changing + 0x42b0c0a5, //[24] max logf = 88.3762589f + 0xc1766666 //[25] min logf = -14.5f + }; + + for (size_t i = 0; i < sizeof(cvals) / sizeof(cvals[0]); ++i) { + for (size_t d = 0; d < vlen / sizeof(float); ++d) { + h->dd(cvals[i]); + } + } +} + +template +void jit_uni_eltwise_injector_f32::abs_prepare_table() { + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0x7fffffff); +} + +template +void jit_uni_eltwise_injector_f32::sqrt_prepare_table() { + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0); +} + +template +void jit_uni_eltwise_injector_f32::linear_prepare_table() { + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_)); + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(beta_)); +} + +template +void jit_uni_eltwise_injector_f32::bounded_relu_prepare_table() { + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_)); + for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0); +} + +template +int jit_uni_eltwise_injector_f32::aux_vecs_count(alg_kind_t alg_) { + switch (alg_) { + case alg_kind::eltwise_relu: return (alpha_ == 0.f) ? 0 : 2; + case alg_kind::eltwise_elu: return 4; + case alg_kind::eltwise_tanh: return 5; + case alg_kind::eltwise_square: return 0; + case alg_kind::eltwise_abs: return 0; + case alg_kind::eltwise_sqrt: return 2; + case alg_kind::eltwise_linear: return 1; + case alg_kind::eltwise_bounded_relu: return 0; + case alg_kind::eltwise_soft_relu: return 4; + case alg_kind::eltwise_logistic: return 4; + default: assert(!"unsupported eltwise algorithm"); + } + + return 0; +} + +template +void jit_uni_eltwise_injector_f32::compute_body(size_t start_idx, + size_t end_idx) { + using namespace alg_kind; + for (size_t idx = start_idx; idx < end_idx; idx++) { + switch (alg_) { + case eltwise_relu: + if (alpha_ == 0.f) relu_zero_ns_compute_vector(Vmm(idx)); + else relu_compute_vector(Vmm(idx)); + break; + case eltwise_elu: elu_compute_vector(Vmm(idx)); break; + case eltwise_tanh: tanh_compute_vector(Vmm(idx)); break; + case eltwise_square: square_compute_vector(Vmm(idx)); break; + case eltwise_abs: abs_compute_vector(Vmm(idx)); break; + case eltwise_sqrt: sqrt_compute_vector(Vmm(idx)); break; + case eltwise_linear: linear_compute_vector(Vmm(idx)); break; + case eltwise_bounded_relu: bounded_relu_compute_vector(Vmm(idx)); break; + case eltwise_soft_relu: soft_relu_compute_vector(Vmm(idx)); break; + case eltwise_logistic: logistic_compute_vector(Vmm(idx)); break; + default: assert(!"unsupported eltwise algorithm"); + } + } +} + +template +void jit_uni_eltwise_injector_f32::compute_vector_range(size_t start_idx, + size_t end_idx) { + assert(start_idx < end_idx && end_idx <= vecs_count); + + injector_preamble(start_idx, end_idx); + compute_body(start_idx_tail, end_idx); + injector_preamble_tail(start_idx); + compute_body(start_idx, start_idx_tail); + injector_postamble(); +} + +template +void jit_uni_eltwise_injector_f32::prepare_table(bool gen_table) { + using namespace alg_kind; + + h->align(64); + h->L(l_table); + + if (gen_table) { + switch (alg_) { + case eltwise_relu: relu_prepare_table(); break; + case eltwise_elu: + case eltwise_tanh: + case eltwise_logistic: + elu_prepare_table(); break; + case eltwise_soft_relu: soft_relu_prepare_table(); break; + case eltwise_abs: abs_prepare_table(); break; + case eltwise_sqrt: sqrt_prepare_table(); break; + case eltwise_linear: linear_prepare_table(); break; + case eltwise_bounded_relu: bounded_relu_prepare_table(); break; + case eltwise_square: break; + default: assert(!"unsupported eltwise algorithm"); + } + } +} + +template struct jit_uni_eltwise_injector_f32; +template struct jit_uni_eltwise_injector_f32; +template struct jit_uni_eltwise_injector_f32; + + +struct jit_args { + const float *from; + const float *for_comparison; + const float *to; + size_t work_amount; +}; + +struct jit_uni_eltwise_kernel_f32 : public c_compatible { + const eltwise_desc_t &desc_; + + void (*ker_)(const jit_args *); + void operator()(const jit_args *args) { assert(ker_); ker_(args); } + + jit_uni_eltwise_kernel_f32(const eltwise_desc_t &desc) + : desc_(desc), ker_(nullptr) {} + virtual ~jit_uni_eltwise_kernel_f32() {} + +protected: + bool is_bwd() const { return desc_.prop_kind == prop_kind::backward_data; } +}; + +/* jit kernels */ +namespace { + +template +struct jit_uni_relu_kernel_f32 : public jit_uni_eltwise_kernel_f32, + public jit_generator +{ + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_relu_kernel_f32) + + void compute_step(bool vectorize, const int uf, const int shift) { + for (int i = 0; i < uf; i++) { + if (vectorize) { + uni_vmovups(Vmm(i + 1), ptr[reg_from + i * shift]); + if (is_bwd()) + uni_vmovups(Vmm(uf + i + 1), + ptr[reg_for_comparison + i * shift]); + } else { + movss(Xmm(i + 1), ptr[reg_from + i * shift]); + if (is_bwd()) + movss(Xmm(uf + i + 1), + ptr[reg_for_comparison + i * shift]); + } + } + + if (isa == sse42) { + for (int i = 0; i < uf; i++) { + movups(Vmm(2 * uf + i + 1), Vmm(i + 1)); + mulps(Vmm(2 * uf + i + 1), vmm_ns); + + Vmm mask = Vmm(0); + if (is_bwd()) { + movups(mask, Vmm(uf + i + 1)); + cmpps(mask, vmm_zero, _cmp_nle_us); + } else { + movups(mask, Vmm(i + 1)); + cmpps(mask, vmm_zero, _cmp_nle_us); + } + blendvps(Vmm(2 * uf + i + 1), Vmm(i + 1)); + } + } else { + for (int i = 0; i < uf; i++) { + vmulps(Vmm(2 * uf + i + 1), Vmm(i + 1), vmm_ns); + if (isa == avx2) { + if (is_bwd()) + vcmpgtps(vmm_mask, Vmm(uf + i + 1), vmm_zero); + else + vcmpgtps(vmm_mask, Vmm(i + 1), vmm_zero); + + vblendvps(Vmm(2 * uf + i + 1), Vmm(2 * uf + i + 1), + Vmm(i + 1), vmm_mask); + + } else { + if (is_bwd()) + vcmpps(k_mask, Vmm(uf + i + 1), vmm_zero, _cmp_nle_us); + else + vcmpps(k_mask, Vmm(i + 1), vmm_zero, _cmp_nle_us); + vblendmps(Vmm(2 * uf + i + 1) | k_mask, Vmm(2 * uf + i + 1), + Vmm(i + 1)); + } + } + } + + for (int i = 0; i < uf; i++) { + if (vectorize) { + uni_vmovups(ptr[reg_to + i * shift], Vmm(2 * uf + i + 1)); + } else { + movss(ptr[reg_to + i * shift], Xmm(2 * uf + i + 1)); + } + } + } + + jit_uni_relu_kernel_f32(const eltwise_desc_t &desc) + : jit_uni_eltwise_kernel_f32(desc), jit_generator() { + assert(desc.alg_kind == alg_kind::eltwise_relu); + assert(isa == sse42 || isa == avx2 || isa == avx512_common); + + Reg64 param = abi_param1; + + const int simd_w = cpu_isa_traits::vlen / sizeof(float); + const int loop_dec[] = {simd_w, 1}; + const int uf[] = {1, 1}; + const int shift[] = {cpu_isa_traits::vlen, sizeof(float)}; + const bool loop_vectorize[] = {true, false}; + + this->preamble(); + + mov(reg_from, ptr[param + GET_OFF(from)]); + if (is_bwd()) + mov(reg_for_comparison, ptr[param + GET_OFF(for_comparison)]); + mov(reg_to, ptr[param + GET_OFF(to)]); + mov(reg_work_amount, ptr[param + GET_OFF(work_amount)]); + + mov(imm_addr64, float2int(desc.alpha)); + movq(xmm_ns, imm_addr64); + uni_vbroadcastss(vmm_ns, xmm_ns); + + uni_vpxor(vmm_zero, vmm_zero, vmm_zero); + + Label loop_label[3]; + + for (int id = 0; id < 2; id++) { + L(loop_label[id]); + cmp(reg_work_amount, uf[id] * loop_dec[id] - 1); + jle(loop_label[id + 1], T_NEAR); + + compute_step(loop_vectorize[id], uf[id], shift[id]); + + add(reg_from, uf[id] * shift[id]); + add(reg_to, uf[id] * shift[id]); + if (is_bwd()) + add(reg_for_comparison, uf[id] * shift[id]); + + sub(reg_work_amount, uf[id] * loop_dec[id]); + jmp(loop_label[id]); + } + + L(loop_label[2]); + this->postamble(); + + ker_ = (decltype(ker_))this->getCode(); + } + +private: + using Vmm = typename utils::conditional3::type; + + Reg64 reg_from = rax; + Reg64 reg_for_comparison = is_bwd() ? rdx : reg_from; + Reg64 reg_to = r8; + Reg64 reg_work_amount = rsi; + Reg64 imm_addr64 = rbx; + + Xmm xmm_ns = Xmm(14); + + Vmm vmm_ns = Vmm(isa == avx512_common ? 30 : 14); + Vmm vmm_zero = Vmm(isa == avx512_common ? 31 : 15); + + Vmm vmm_mask = Vmm(isa == avx512_common ? 28 : 12); + Opmask k_mask = Opmask(1); +}; + +template +struct jit_uni_kernel_fwd_f32: public jit_uni_eltwise_kernel_f32, + public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_kernel_fwd_f32) + + jit_uni_kernel_fwd_f32(const eltwise_desc_t &desc) + : jit_uni_eltwise_kernel_f32(desc), jit_generator() { + + eltwise_injector_ = new jit_uni_eltwise_injector_f32(this, + desc.alg_kind, desc.alpha, desc.beta, false, r9, Opmask(1)); + + using namespace alg_kind; + + assert(is_bwd() == false); + assert(utils::one_of(desc.alg_kind, eltwise_tanh, eltwise_elu, + eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear, + eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic)); + + preamble(); + + Reg64 param = abi_param1; + mov(reg_from, ptr[param + GET_OFF(from)]); + mov(reg_to, ptr[param + GET_OFF(to)]); + mov(reg_work_amount, ptr[param + GET_OFF(work_amount)]); + eltwise_injector_->load_table_addr(); + + Label reminder_loop_start, reminder_loop_end; + Label vectorized_loop_start, vectorized_loop_end; + + cmp(reg_work_amount, simd_w); + jl(reminder_loop_start, T_NEAR); + + L(vectorized_loop_start); + + uni_vmovups(vmm_src, ptr[reg_from]); + eltwise_injector_->compute_vector(vmm_src.getIdx()); + uni_vmovups(ptr[reg_to], vmm_src); + + add(reg_from, vlen); + add(reg_to, vlen); + + sub(reg_work_amount, simd_w); + cmp(reg_work_amount, simd_w); + jge(vectorized_loop_start, T_NEAR); + + L(vectorized_loop_end); + + L(reminder_loop_start); + + cmp(reg_work_amount, 0); + jle(reminder_loop_end, T_NEAR); + + movss(xmm_src, ptr[reg_from]); + eltwise_injector_->compute_vector(xmm_src.getIdx()); + movss(ptr[reg_to], xmm_src); + + add(reg_from, sizeof(float)); + add(reg_to, sizeof(float)); + + dec(reg_work_amount); + jmp(reminder_loop_start, T_NEAR); + + L(reminder_loop_end); + + postamble(); + + eltwise_injector_->prepare_table(); + + ker_ = (decltype(ker_))this->getCode(); + } + + ~jit_uni_kernel_fwd_f32() { delete eltwise_injector_; } + +private: + using Vmm = typename utils::conditional3::type; + + const int simd_w = cpu_isa_traits::vlen / sizeof(float); + const int vlen = cpu_isa_traits::vlen; + + Reg64 reg_from = rax; + Reg64 reg_to = r8; + Reg64 reg_work_amount = rsi; + Reg64 imm_addr64 = rbx; + + Xmm xmm_src = Xmm(1); + Vmm vmm_src = Vmm(1); + + jit_uni_eltwise_injector_f32 *eltwise_injector_; +}; + +} /* namespace */ + +template +status_t jit_uni_eltwise_fwd_t::pd_t::init() { + using namespace alg_kind; + + bool ok = true + && mayiuse(isa) + && is_fwd() + && utils::everyone_is(data_type::f32, desc()->data_desc.data_type) + && !has_zero_dim_memory() + && utils::one_of(desc()->alg_kind, eltwise_relu, eltwise_tanh, + eltwise_elu, eltwise_square, eltwise_abs, eltwise_sqrt, + eltwise_linear, eltwise_bounded_relu, eltwise_soft_relu, + eltwise_logistic) + && memory_desc_wrapper(src_md()).is_dense(true) + && IMPLICATION(!memory_desc_wrapper(src_md()).is_dense(false), + math::eltwise_fwd_preserves_zero(desc()->alg_kind, true)) + && attr()->has_default_values(); + + return ok ? status::success : status::unimplemented; +} + +template +jit_uni_eltwise_fwd_t::jit_uni_eltwise_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd), kernel_(nullptr) { + const auto &desc = *pd()->desc(); + switch (desc.alg_kind) { + case alg_kind::eltwise_relu: + kernel_ = new jit_uni_relu_kernel_f32(desc); break; + default: + kernel_ = new jit_uni_kernel_fwd_f32(desc); + } +} + +template +jit_uni_eltwise_fwd_t::~jit_uni_eltwise_fwd_t() +{ delete kernel_; } + +template +void jit_uni_eltwise_fwd_t::execute_forward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper data_d(pd()->src_md()); + + const size_t nelems = data_d.nelems(true); + + src += data_d.offset0(); + dst += data_d.offset0(); + + parallel(0, [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + + const int cache_line = 16; + + balance211(utils::div_up(nelems, cache_line), nthr, ithr, start, end); + start = nstl::min(nelems, start * cache_line); + end = nstl::min(nelems, end * cache_line); + + auto arg = jit_args(); + arg.from = &src[start]; + arg.for_comparison = &src[start]; + arg.to = &dst[start]; + arg.work_amount = end - start; + if (arg.work_amount) + (*kernel_)(&arg); + }); +} + +template +status_t jit_uni_eltwise_bwd_t::pd_t::init() { + bool ok = true + && !is_fwd() + && utils::one_of(desc()->alg_kind, alg_kind::eltwise_relu) + && src_md()->data_type == data_type::f32 + && !has_zero_dim_memory() + && mayiuse(isa) + && memory_desc_wrapper(src_md()).is_dense() + && memory_desc_wrapper(diff_dst_md()) == memory_desc_wrapper(src_md()) + && attr()->has_default_values(); + + return ok ? status::success : status::unimplemented; +} + +template +jit_uni_eltwise_bwd_t::jit_uni_eltwise_bwd_t(const pd_t *apd) + : cpu_primitive_t(apd), kernel_(nullptr) { + const auto &desc = *pd()->desc(); + switch (desc.alg_kind) { + case alg_kind::eltwise_relu: + kernel_ = new jit_uni_relu_kernel_f32(desc); break; + default: assert(!"unknown eltwise alg_kind"); + } +} + +template +jit_uni_eltwise_bwd_t::~jit_uni_eltwise_bwd_t() +{ delete kernel_; } + +template +void jit_uni_eltwise_bwd_t::execute_backward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper data_d(pd()->src_md()); + const memory_desc_wrapper diff_data_d(pd()->diff_src_md()); + + const size_t nelems = data_d.nelems(); + + src += data_d.offset0(); + diff_dst += diff_data_d.offset0(); + diff_src += diff_data_d.offset0(); + + parallel(0, [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + + const int cache_line = 16; + + balance211(utils::div_up(nelems, cache_line), nthr, ithr, start, end); + start = nstl::min(nelems, start * cache_line); + end = nstl::min(nelems, end * cache_line); + + auto arg = jit_args(); + arg.from = &diff_dst[start]; + arg.to = &diff_src[start]; + arg.for_comparison = &src[start]; + arg.work_amount = end - start; + if (arg.work_amount) + (*kernel_)(&arg); + }); +} + +template struct jit_uni_eltwise_fwd_t; +template struct jit_uni_eltwise_bwd_t; +template struct jit_uni_eltwise_fwd_t; +template struct jit_uni_eltwise_bwd_t; +template struct jit_uni_eltwise_fwd_t; +template struct jit_uni_eltwise_bwd_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp new file mode 100644 index 0000000000..45436b9f46 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp @@ -0,0 +1,193 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_UNI_ELTWISE_HPP +#define CPU_JIT_UNI_ELTWISE_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_eltwise_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_uni_eltwise_injector_f32 { + using Vmm = typename utils::conditional3::type; + + jit_uni_eltwise_injector_f32(jit_generator *host, alg_kind_t alg, + float alpha, float beta, bool save_state = true, + Xbyak::Reg64 p_table = Xbyak::util::rax, + Xbyak::Opmask k_mask = Xbyak::Opmask(1)) + : alg_(alg), alpha_(alpha), beta_(beta), h(host) + , save_state_(save_state), p_table(p_table), k_mask(k_mask) + { + using namespace alg_kind; + assert(utils::one_of(isa, sse42, avx2, avx512_common)); + assert(utils::one_of(alg_, eltwise_relu, eltwise_tanh, eltwise_elu, + eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear, + eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic)); + } + + // note that eltwise.scale is ignored + jit_uni_eltwise_injector_f32(jit_generator *host, + const post_ops_t::entry_t::eltwise_t &eltwise, + bool save_state = true, Xbyak::Reg64 p_table = Xbyak::util::rax, + Xbyak::Opmask k_mask = Xbyak::Opmask(1)) + : jit_uni_eltwise_injector_f32(host, eltwise.alg, eltwise.alpha, + eltwise.beta, save_state, p_table, k_mask) {} + + void compute_vector_range(size_t start_idx, size_t end_idx); + void compute_vector(size_t idx) { compute_vector_range(idx, idx + 1); } + void prepare_table(bool gen_table=true); + void load_table_addr() { h->mov(p_table, l_table); } + + const alg_kind_t alg_; + const float alpha_; + const float beta_; + + jit_generator * const h; + + const bool save_state_; + const Xbyak::Reg64 p_table; + const Xbyak::Opmask k_mask; + Xbyak::Label l_table; + +private: + // if only the injector was inherited from jit_generator... + enum { + _cmp_le_os = jit_generator::_cmp_le_os, + _cmp_nle_us = jit_generator::_cmp_nle_us, + _op_floor = jit_generator::_op_floor, + }; + + size_t vlen = cpu_isa_traits::vlen; + + const static size_t preserved_vecs_max = 5; + + size_t vecs_to_preserve = 0; + size_t vecs_count = isa == avx512_common ? 32 : 16; + size_t preserved_vecs_count = 0; + size_t preserved_vec_idxs[preserved_vecs_max] = {0}; + size_t start_idx_tail = 0; + + Vmm vmm_mask, vmm_aux0, vmm_aux1, vmm_aux2, vmm_aux3, vmm_aux4; + + Xbyak::Address table_val(int index) + { return h->ptr[p_table + index * vlen]; } + + int aux_vecs_count(alg_kind_t alg); + + void compute_body(size_t start_idx, size_t end_idx); + void injector_preamble(size_t start_idx, size_t end_idx); + void injector_preamble_tail(size_t start_idx); + void injector_postamble(); + void assign_regs(); + + void exp_compute_vector(const Vmm &vmm_src); + void relu_compute_vector(const Vmm &vmm_src); + void relu_zero_ns_compute_vector(const Vmm &vmm_src); + void elu_compute_vector(const Vmm &vmm_src); + void tanh_compute_vector(const Vmm &vmm_src); + void square_compute_vector(const Vmm &vmm_src); + void abs_compute_vector(const Vmm &vmm_src); + void sqrt_compute_vector(const Vmm &vmm_src); + void linear_compute_vector(const Vmm &vmm_src); + void bounded_relu_compute_vector(const Vmm &vmm_src); + void soft_relu_compute_vector(const Vmm &vmm_src); + void logistic_compute_vector(const Vmm &vmm_src); + + void relu_prepare_table(); + void elu_prepare_table(); + void soft_relu_prepare_table(); + void abs_prepare_table(); + void sqrt_prepare_table(); + void linear_prepare_table(); + void bounded_relu_prepare_table(); +}; + +struct jit_uni_eltwise_kernel_f32; + +template +struct jit_uni_eltwise_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_eltwise_fwd_pd_t { + using cpu_eltwise_fwd_pd_t::cpu_eltwise_fwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_eltwise_fwd_t); + + status_t init(); + }; + + jit_uni_eltwise_fwd_t(const pd_t *apd); + ~jit_uni_eltwise_fwd_t(); + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_uni_eltwise_kernel_f32 *kernel_; +}; + +template +struct jit_uni_eltwise_bwd_t : public cpu_primitive_t { + struct pd_t : public cpu_eltwise_bwd_pd_t { + using cpu_eltwise_bwd_pd_t::cpu_eltwise_bwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_eltwise_bwd_t); + + status_t init(); + }; + + jit_uni_eltwise_bwd_t(const pd_t *apd); + ~jit_uni_eltwise_bwd_t(); + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_uni_eltwise_kernel_f32 *kernel_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp new file mode 100644 index 0000000000..a3ca6273a0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp @@ -0,0 +1,949 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "jit_uni_i8i8_pooling.hpp" + +#include + +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; + +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::types; +using namespace alg_kind; + +template +struct jit_uni_i8i8_pooling_fwd_ker_t: public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_i8i8_pooling_fwd_ker_t) + + struct call_params_t { + const char *src_i8; + const char *dst_i8; + size_t kw_range; + size_t kh_range; + float idivider; + }; + + using Vmm = typename cpu_isa_traits::Vmm; + Xmm xreg(int idx) const { return Xmm(idx); } + Ymm yreg(int idx) const { return Ymm(xreg(idx).getIdx()); } + Vmm vreg(int idx) const { return Vmm(xreg(idx).getIdx()); } + + // In case of avx2 with data type i8 we need to use + // maskmovdqu instruction which has its destination hardcoded in rdi. + // Windows ABI: abi_param1 is rcx - nothing to do else + // Unix ABI: abi_param1 is rdi - copy it to rcx and use it as abi_param1 + Reg64 reg_param = rcx; // Our "unified abi_param1" + Reg64 reg_ptr_src_i8 = r8; + Reg64 reg_ptr_dst_i8 = r9; + Reg64 reg_ptr_maskmovdqu_dst = rdi; // store destination - must be rdi + + Reg64 ki = r10; + Reg64 kj = r11; + Reg64 reg_kw = r12; + Reg64 reg_kh = r13; + Reg64 c_iter = r14; + + Reg64 aux_reg_src_h = rax; + Reg64 aux_reg_src_w = rbx; + + Reg64 reg_tmp = rdx; + + Reg64 reg_mask = r15; + + Opmask k_cmp_mask = Opmask(7); + + Opmask mask(int idx) { + return Opmask(6 - idx); + } + + // ref to any of XYZ-regs via xreg/yreg/vreg functions + Xmm xmm_tmp = xreg(0); // temp to init vreg_tmp + Vmm vreg_tmp = vreg(0); // max pooling : holds minimum values for data_type + Vmm vreg_zeros = vreg(1); + + // only in case of == avx2 + Vmm vreg_mask = vreg(2); // full byte-mask + Xmm xreg_mask_lo = xreg(2); // low 128-bits part of byte-mask (alias for xmm part of vreg_mask) + Xmm xreg_mask_hi = xreg(3); // "max" - high 128-bits part of byte-mask (stored separately) + Xmm xreg_mask_q = xreg(3); // "avg" - 1/4 part of the mask for s8/u8 operations + Vmm vreg_mask_q = vreg(3); // "avg" - 1/4 part for non-zero tails + + enum:int {vidx_base = isa == avx2 ? 4 : 2}; + Vmm base_vr(int idx) const { return vreg(vidx_base + idx); } + + size_t sizeof_src_dt() const { return data_type_size(jpp.src_dt); } + size_t sizeof_dst_dt() const { return data_type_size(jpp.dst_dt); } + + /* max pooling */ + Vmm vreg_src(int idx) const { return base_vr(idx); } // [0 .. ur_c-1] + Vmm vreg_dst(int idx) const { return base_vr(jpp.ur_c + idx); } // [ur_c .. 2*ur_c-1] + + /* avg pooling */ + // s32 used for processing of s8/u8 data + // thus we need to take into account ratio of sizes s32/i8 = 4 + static constexpr data_type_t avg_proc_dt = data_type::s32; + enum:int { + s32_to_i8_ratio = sizeof(typename prec_traits::type) + / sizeof(typename prec_traits::type), + max_num_ll = s32_to_i8_ratio + }; + Vmm vreg_src_s32(int jj, int ll) { return base_vr(3*max_num_ll*jj + ll + 0*max_num_ll); } // ll: 0..4 [0..3] + Vmm vreg_dst_s32(int jj, int ll) { return base_vr(3*max_num_ll*jj + ll + 1*max_num_ll); } // ll: 0..4 [4..7] + Vmm vreg_dst_f32(int jj, int ll) { return base_vr(3*max_num_ll*jj + ll + 2*max_num_ll); } // ll: 0..4 [8..11] + + void (*ker_)(const call_params_t *); + jit_pool_conf_t jpp; + + void init_tmp_reg(); + void init_mask(); + + void load_vreg_mask_q(int ll) {}; + + void load_src_max_op(int jj, int ll, size_t offset, bool masked, uint64_t msk); + void load_src_avg_op(int jj, int ll, size_t offset, bool masked, uint64_t msk); + void load_src(int jj, int ll, int c_tail); + + void store_dst_max_op(int jj, int ll, size_t offset, bool masked, uint64_t msk); + void store_dst_avg_op(int jj, int ll, size_t offset, bool masked, uint64_t msk); + void store_dst(int jj, int ll, int c_tail); + + void compute_avg_step(int ur_c, int c_tail); + void compute_max_op(const int jj); + void compute_max_step(int ur_c, int c_tail); + void compute_step(int ur_c, int c_tail); + + void compute_c_block(); + void generate(); + + static status_t init_conf(jit_pool_conf_t &jpp, const pooling_pd_t *ppd); + + jit_uni_i8i8_pooling_fwd_ker_t(const jit_pool_conf_t &jpp_) + : jpp(jpp_) { + generate(); + ker_ = reinterpret_cast(const_cast( + getCode())); + } +}; + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::load_vreg_mask_q(int ll) { + + // extract ll-th part of mask (ll-th QWORD) + vpblendd(vreg_mask_q, vreg_zeros, vreg_mask, 0x3 << ll); // 0x3 - mask for 2 x DWORD + + // Move mask from ll-th pos to 0-th pos + if (ll>0) + vpermq(vreg_mask_q, vreg_mask_q, ll); +}; + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::load_src_max_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk) { + using namespace data_type; + + if (masked) { + if (jpp.src_dt == s32) { + vpblendd(vreg_src(jj), vreg_tmp, ptr[aux_reg_src_w + offset], static_cast(msk)); + } else { + vpblendvb(vreg_src(jj), vreg_tmp, ptr[aux_reg_src_w + offset], vreg_mask); + } + } else + vmovups(vreg_src(jj), ptr[aux_reg_src_w + offset]); +}; + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::load_src_max_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk) { + using namespace data_type; + + if (masked) { + if (jpp.src_dt == s32) + vmovups(vreg_src(jj) | mask(0), ptr[aux_reg_src_w + offset]); + else + vmovdqu8(vreg_src(jj) | mask(0), ptr[aux_reg_src_w + offset]); + } else + vmovups(vreg_src(jj), ptr[aux_reg_src_w + offset]); +}; + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::load_src_avg_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk) { + using namespace data_type; + + // Don't generate useless code + if (masked && !msk) + return; + + auto load_i8 = [&](bool is_signed, const Vmm& vr_src) { + + // Need to use mask of tail? + if (masked) { + + // load ll-th part of mask into vreg_mask_q + load_vreg_mask_q(ll); + + // Load by mask from mem into register vr_src + vpblendvb(vr_src, vreg_zeros, ptr[aux_reg_src_w + offset], vreg_mask_q); + + // Conversion s8/u8 -> s32 + if (is_signed) + vpmovsxbd(vr_src, vr_src); + else + vpmovzxbd(vr_src, vr_src); + } else { + + // Load from mem into vr_src with conversion + if (is_signed) + vpmovsxbd(vr_src, ptr[aux_reg_src_w + offset]); + else + vpmovzxbd(vr_src, ptr[aux_reg_src_w + offset]); + } + }; + + switch (jpp.src_dt) { + case s32: + if (masked) + vpblendd(vreg_src_s32(jj, ll), vreg_zeros, ptr[aux_reg_src_w + offset], + static_cast(msk)); + else + vmovups(vreg_src_s32(jj, ll), ptr[aux_reg_src_w + offset]); + break; + case s8: + load_i8(true, vreg_src_s32(jj, ll)); + break; + case u8: + load_i8(false, vreg_src_s32(jj, ll)); + break; + default: assert(!"unsupported src data type"); + } +}; + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::load_src_avg_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk) { + using namespace data_type; + + // Don't generate useless code + if (masked && !msk) + return; + + const Vmm& vr_src = masked ? + vreg_src_s32(jj, ll) | mask(ll) : + vreg_src_s32(jj, ll); + + switch (jpp.src_dt) { + case s32: + vmovups(vr_src, ptr[aux_reg_src_w + offset]); + break; + case s8: + vpmovsxbd(vr_src, ptr[aux_reg_src_w + offset]); + break; + case u8: + vpmovzxbd(vr_src, ptr[aux_reg_src_w + offset]); + break; + default: assert(!"unsupported src data type"); + } +}; + +template +void jit_uni_i8i8_pooling_fwd_ker_t::load_src(int jj, int ll, int c_tail) { + using namespace data_type; + + int c_block = jpp.c_block; + int ur_c = jpp.ur_c; + + switch (jpp.alg) { + case pooling_max: { + auto offset = jj*c_block*sizeof_src_dt(); + bool masked = jj == ur_c - 1 && c_tail; + load_src_max_op(jj, ll, offset, masked, jpp.tail[0]); + break; + } + case pooling_avg_include_padding: + case pooling_avg_exclude_padding: { + auto offset = (ll*(c_block/max_num_ll) + jj*c_block)*sizeof_src_dt(); + bool masked = jj == ur_c - 1 && c_tail; + load_src_avg_op(jj, ll, offset, masked, jpp.tail[ll]); + break; + } + default: assert(!"unsupported algorithm"); + } +} + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::store_dst_max_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk) { + using namespace data_type; + + int c_block = jpp.c_block; + + if (masked) { + switch (jpp.src_dt) { + case s32: + vpmaskmovd(ptr[reg_ptr_dst_i8 + offset], vreg_mask, vreg_dst(jj)); + break; + case s8: + case u8: { + // Store low half by mask (bytes 0...15) + lea(reg_ptr_maskmovdqu_dst, ptr[reg_ptr_dst_i8 + offset]); + maskmovdqu(vreg_dst(jj), xreg_mask_lo); + + // Do we need to store high half (bytes 16...31) ? + const uint64_t low_mask = (1ULL << (c_block/2))-1; + if (msk & ~low_mask) { + vextracti128(Xmm(vreg_dst(jj).getIdx()), vreg_dst(jj), 1); + add(reg_ptr_maskmovdqu_dst, c_block / 2); + maskmovdqu(vreg_dst(jj), xreg_mask_hi); + } + } break; + default: assert(!"unsupported src data type"); + } + } else + vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj)); +} + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::store_dst_max_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk) { + using namespace data_type; + + if (masked) { + switch (jpp.src_dt) { + case s32: + vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj) | mask(0)); + break; + case s8: + case u8: + vmovdqu8(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj) | mask(0)); + break; + default: assert(!"unsupported src data type"); + } + } else + vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj)); +} + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::store_dst_avg_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk){ + using namespace data_type; + + // Don't generate useless code + if (masked && !msk) + return; + + auto s32_to_i8 = [&](bool is_signed, const Vmm& vr_dst) { + + // conversion: s32 -> s16/u16 : {8 x s32}{8 x 0} -> {16 x s16/u16} + // Result QWORDs (qw0, qw1) permuted: {qw0, 0, qw1, 0} + if (is_signed) + vpackssdw(vr_dst, vr_dst, vreg_zeros); + else + vpackusdw(vr_dst, vr_dst, vreg_zeros); + + // Permute qwords to restore original order + // {qw0, 0, qw1, 0} -> {qw0, qw1, 0, 0} + vpermq(vr_dst, vr_dst, 0x58); + + // conversion: s16/u16 -> s8/u8 : {16 x s16/u16}{16 x 0} -> {32 x s8/u8} + // Target QWORD qw = {8 x s8/u8} has proper position: {qw, xx, xx, xx} + if (is_signed) + vpacksswb(vr_dst, vr_dst, vreg_zeros); + else + vpackuswb(vr_dst, vr_dst, vreg_zeros); + + }; + + auto store_i8 = [&](bool is_signed, bool is_masked, const Vmm& vr_dst) { + + // Conversion s32 -> s8/u8 + s32_to_i8(is_signed, vr_dst); + + // Need to use mask of tail? + if (is_masked) { + // load ll-th part of mask into vreg_mask_q + load_vreg_mask_q(ll); + } + + // store 8 bytes + lea(reg_ptr_maskmovdqu_dst, ptr[reg_ptr_dst_i8 + offset]); + maskmovdqu(vr_dst, xreg_mask_q); + }; + + switch (jpp.dst_dt) { + case s32: + if (masked) { + vpmaskmovd(ptr[reg_ptr_dst_i8 + offset], vreg_mask, vreg_dst_s32(jj, ll)); + } else + vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst_s32(jj, ll)); + break; + case s8: + store_i8(true, masked, vreg_dst_s32(jj, ll)); + break; + case u8: + store_i8(false, masked, vreg_dst_s32(jj, ll)); + break; + default: assert(!"unsuppotred dst data_type"); + } +} + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::store_dst_avg_op(int jj, int ll, + size_t offset, bool masked, uint64_t msk) { + using namespace data_type; + + // Don't generate useless code + if (masked && !msk) + return; + + const Vmm& vr_dst = masked ? + vreg_dst_s32(jj, ll) | mask(ll) : + vreg_dst_s32(jj, ll); + + switch (jpp.dst_dt) { + case s32: + vmovups(ptr[reg_ptr_dst_i8 + offset], vr_dst); + break; + case s8: + vpmovdb(ptr[reg_ptr_dst_i8 + offset], vr_dst); + break; + case u8: + vpmovusdb(ptr[reg_ptr_dst_i8 + offset], vr_dst); + break; + default: assert(!"unsupported dst data_type"); + } +} + + +template +void jit_uni_i8i8_pooling_fwd_ker_t::store_dst(int jj, int ll, + int c_tail) { + using namespace data_type; + + int c_block = jpp.c_block; + int ur_c = jpp.ur_c; + + switch(jpp.alg) { + case pooling_max: { + auto offset = jj*c_block*sizeof_dst_dt(); + bool masked = jj == ur_c - 1 && c_tail; + store_dst_max_op(jj, ll, offset, masked, jpp.tail[ll]); + break; + } + case pooling_avg_include_padding: + case pooling_avg_exclude_padding: { + auto offset = (ll*(c_block/max_num_ll) + jj*c_block)*sizeof_dst_dt(); + bool masked = jj == ur_c - 1 && c_tail; + store_dst_avg_op(jj, ll, offset, masked, jpp.tail[ll]); + break; + } + default: assert(!"unsupported pooling algorithm"); + } +} + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::compute_max_op(const int jj) +{ + using namespace data_type; + switch (jpp.src_dt) { + case s32: + vpmaxsd(vreg_dst(jj), vreg_dst(jj), vreg_src(jj)); + break; + case s8: + vpmaxsb(vreg_dst(jj), vreg_dst(jj), vreg_src(jj)); + break; + case u8: + vpmaxub(vreg_dst(jj), vreg_dst(jj), vreg_src(jj)); + break; + default: assert(!"unsupported src data type"); + } +} + +template <> +void jit_uni_i8i8_pooling_fwd_ker_t::compute_max_op(const int jj) +{ + using namespace data_type; + + // Compare + switch (jpp.src_dt) { + case s32: + vpcmpd(k_cmp_mask, vreg_dst(jj), vreg_src(jj), _cmp_lt_os); + break; + case s8: + vpcmpb(k_cmp_mask, vreg_dst(jj), vreg_src(jj), _cmp_lt_os); + break; + case u8: + vpcmpub(k_cmp_mask, vreg_dst(jj), vreg_src(jj), _cmp_lt_os); + break; + default: assert(!"unsupported src data type"); + } + + // move max values into vreg_dst + if (jpp.src_dt == s32) + vpblendmd(vreg_dst(jj) | k_cmp_mask, vreg_dst(jj), vreg_src(jj)); + else + vpblendmb(vreg_dst(jj) | k_cmp_mask, vreg_dst(jj), vreg_src(jj)); +} + + +template +void jit_uni_i8i8_pooling_fwd_ker_t::compute_max_step(int ur_c, int c_tail) +{ + Label l_kw, l_kh; + + int iw = jpp.iw; + int c = jpp.c; + + for (int jj = 0; jj < ur_c; jj++) + vmovups(vreg_dst(jj), vreg_tmp); + + mov(aux_reg_src_h, reg_ptr_src_i8); + + xor_(kj, kj); + L(l_kh); + { + mov(aux_reg_src_w, aux_reg_src_h); + xor_(ki, ki); + L(l_kw); + { + for (int jj = 0; jj < ur_c; jj++) { + load_src(jj, 0, c_tail); + compute_max_op(jj); + } + add(aux_reg_src_w, c * sizeof_src_dt()); + inc(ki); + cmp(ki, reg_kw); + jl(l_kw, T_NEAR); + } + add(aux_reg_src_h, iw * c * sizeof_src_dt()); + inc(kj); + cmp(kj, reg_kh); + jl(l_kh, T_NEAR); + } + + for (int jj = 0; jj < ur_c; jj++) + store_dst(jj, 0, c_tail); +} + +template +void jit_uni_i8i8_pooling_fwd_ker_t::compute_avg_step(int ur_c, int c_tail) +{ + using namespace data_type; + + Label l_kw, l_kh; + + int iw = jpp.iw; + int c = jpp.c; + + const int num_ll = data_type_size(avg_proc_dt)/data_type_size(jpp.src_dt); + + for (int jj = 0; jj < ur_c; jj++) { + for (int ll = 0; ll < num_ll; ll++) { + bool masked = jj == ur_c - 1 && c_tail; + size_t msk = jpp.tail[ll]; + if (!(masked && !msk)) { + uni_vpxor(vreg_src_s32(jj, ll), vreg_src_s32(jj, ll), vreg_src_s32(jj, ll)); + uni_vpxor(vreg_dst_s32(jj, ll), vreg_dst_s32(jj, ll), vreg_dst_s32(jj, ll)); + } + } + } + + mov(aux_reg_src_h, reg_ptr_src_i8); + + xor_(kj, kj); + L(l_kh); + { + mov(aux_reg_src_w, aux_reg_src_h); + xor_(ki, ki); + L(l_kw); + { + for (int jj = 0; jj < ur_c; jj++) { + for (int ll = 0; ll < num_ll; ll++) { + bool masked = jj == ur_c - 1 && c_tail; + size_t msk = jpp.tail[ll]; + if (!(masked && !msk)) { + load_src(jj, ll, c_tail); + vpaddd(vreg_dst_s32(jj, ll), vreg_dst_s32(jj, ll), + vreg_src_s32(jj, ll)); + } + } + } + add(aux_reg_src_w, c * sizeof_src_dt()); + inc(ki); + cmp(ki, reg_kw); + jl(l_kw, T_NEAR); + } + add(aux_reg_src_h, iw * c * sizeof_src_dt()); + inc(kj); + cmp(kj, reg_kh); + jl(l_kh, T_NEAR); + } + + for (int jj = 0; jj < ur_c; jj++) { + for (int ll = 0; ll < num_ll; ll++) { + bool masked = jj == ur_c - 1 && c_tail; + size_t msk = jpp.tail[ll]; + if (!(masked && !msk)) { + vcvtdq2ps(vreg_dst_f32(jj, ll), vreg_dst_s32(jj, ll)); + vfmadd132ps(vreg_dst_f32(jj, ll), vreg_zeros, vreg_tmp); + vcvtps2dq(vreg_dst_s32(jj, ll), vreg_dst_f32(jj, ll)); + store_dst(jj, ll, c_tail); + } + } + } +} + +template +void jit_uni_i8i8_pooling_fwd_ker_t::compute_step(int ur_c, int c_tail) { + switch (jpp.alg) { + case pooling_max: + compute_max_step(ur_c, c_tail); break; + case pooling_avg_include_padding: + case pooling_avg_exclude_padding: + compute_avg_step(ur_c, c_tail); break; + default: assert(!"unsupported pooling algorithm"); + } +} + +template +void jit_uni_i8i8_pooling_fwd_ker_t::compute_c_block(){ + Label l_main_loop; + + int nb_c = jpp.nb_c; + int c_block = jpp.c_block; + int ur_c = jpp.ur_c; + int ur_c_tail = jpp.ur_c_tail; + int c_steps = nb_c / ur_c; + int c_tail = jpp.c_tail; + + xor_(c_iter, c_iter); + if (c_steps > 0) { + L(l_main_loop); { + compute_step(ur_c, 0); + add(reg_ptr_src_i8, ur_c*c_block*sizeof_src_dt()); + add(reg_ptr_dst_i8, ur_c*c_block*sizeof_dst_dt()); + inc(c_iter); + cmp(c_iter, c_steps); + jl(l_main_loop, T_NEAR); + } + } + + if (ur_c_tail != 0) { + compute_step(ur_c_tail, c_tail); + } +} + +template<> +void jit_uni_i8i8_pooling_fwd_ker_t::init_mask() { + using namespace data_type; + using cpu_isa = cpu_isa_traits; + + // AVX2 mask initialization: mask stored in Ymm-regs + auto init = [&](uint64_t bit_mask, bool init_mask_q) { + const size_t QW_PER_VREG = cpu_isa::vlen / sizeof(uint64_t); + + uint64_t vmask[QW_PER_VREG]; + for (size_t i = 0; i < QW_PER_VREG; i++){ + + uint64_t qw_vmask=0ULL; + const size_t DBITS = 8*sizeof_src_dt(); + const uint64_t VMSK = 1ULL << (DBITS-1); + const size_t D_PER_QW = (8*sizeof(qw_vmask))/DBITS; + for (size_t j = 0; j < D_PER_QW; j++) { + if (bit_mask & 1) + qw_vmask |= VMSK << DBITS * j; + bit_mask >>= 1; + } + vmask[i] = qw_vmask; + } + + // Put QWORDS with target mask into xmm regs + const int xdst_i[QW_PER_VREG] = { + xreg_mask_lo.getIdx(), + xreg_mask_lo.getIdx(), + xreg_mask_hi.getIdx(), + xreg_mask_hi.getIdx() + }; + const int xsrc_i[QW_PER_VREG] = { + vreg_zeros.getIdx(), // 0-th qword insert in zeros -> {qw0, 0} + xreg_mask_lo.getIdx(), // 1-st and 0-th merge -> {qw0,qw1} + vreg_zeros.getIdx(), + xreg_mask_hi.getIdx() + }; + const uint8 qw_dst_idx[QW_PER_VREG] = {0, 1, 0, 1}; // qword index in 128-bit xreg + + for (size_t i = 0; i < QW_PER_VREG; i++) { + mov(reg_mask, vmask[i]); + vpinsrq(Xmm(xdst_i[i]), Xmm(xsrc_i[i]), reg_mask, qw_dst_idx[i]); + } + + // Merge Low (xreg_mask_lo alias for vreg_mask.xreg) + // and High (xreg_mask_hi) into full vreg_mask + // vreg_mask -> {xreg_mask_hi, vreg_mask.xreg} + vinserti128(vreg_mask, vreg_mask, xreg_mask_hi, 1); + + // Keep only low qword of mask in xreg_mask_q + if (init_mask_q) { + mov(reg_mask, vmask[0]); + vpinsrq(xreg_mask_q, Xmm(vreg_zeros.getIdx()), reg_mask, 0); + } + }; + + uint64_t tail_mask = (1ULL << jpp.c_tail) - 1; + switch (jpp.alg) { + case pooling_max: + // For "max" we need mask only in case of non-zero tail + if (tail_mask) + init(tail_mask, false); + break; + case pooling_avg_include_padding: + case pooling_avg_exclude_padding: + // For "avg" we need mask: + // - s32 - in case of the non-zero tail + // - s8/u8 - irrespective of the tail + switch (jpp.src_dt) { + case s32: + if (tail_mask) + init(tail_mask, false); + break; + case s8: + case u8: + init(tail_mask ? tail_mask : ~0ULL, tail_mask == 0); + break; + default: assert(!"unsupported src data type"); + } + break; + default: assert(!"unsupported pooling algorithm"); + } +} + +template<> +void jit_uni_i8i8_pooling_fwd_ker_t::init_mask() { + + for (int ll = 0; ll < max_num_ll; ll++) { + mov(reg_mask, jpp.tail[ll]); + kmovq(mask(ll), reg_mask); + } +} + +template +void jit_uni_i8i8_pooling_fwd_ker_t::init_tmp_reg() { + using namespace data_type; + + switch (jpp.alg) { + case pooling_avg_include_padding: + case pooling_avg_exclude_padding: + mov(reg_tmp, ptr[reg_param + offsetof(call_params_t, idivider)]); + movq(xmm_tmp, reg_tmp); + vpbroadcastd(vreg_tmp, xmm_tmp); + break; + case pooling_max: + switch (jpp.src_dt) { + case s32: + mov(reg_tmp, nstl::numeric_limits::lowest()); + break; + case s8: + mov(reg_tmp, nstl::numeric_limits::lowest()); + break; + case u8: + mov(reg_tmp, nstl::numeric_limits::lowest()); + break; + default: assert(!"unsupported src data_type"); + } + + movq(xmm_tmp, reg_tmp); + if (jpp.src_dt == s32) + vpbroadcastd(vreg_tmp, xmm_tmp); + else + vpbroadcastb(vreg_tmp, xmm_tmp); + break; + default: assert(!"unsupported pooling algorithm"); + } + +} + +template +void jit_uni_i8i8_pooling_fwd_ker_t::generate() { + preamble(); + +#if !defined(_WIN32) + // Always use rcx as abi_param1 - + // see the note about maskmovdqu near reg_param. + mov(rcx, rdi); +#endif + +# define READ_PARAM(reg, field) \ + mov(reg, ptr[reg_param + offsetof(call_params_t, field)]) + READ_PARAM(reg_ptr_src_i8, src_i8); + READ_PARAM(reg_ptr_dst_i8, dst_i8); + READ_PARAM(reg_kw, kw_range); + READ_PARAM(reg_kh, kh_range); + +# undef READ_PARAM + + uni_vpxor(vreg_zeros, vreg_zeros, vreg_zeros); + + init_mask(); + + init_tmp_reg(); + + compute_c_block(); + + postamble(); +} + +template +status_t jit_uni_i8i8_pooling_fwd_ker_t::init_conf(jit_pool_conf_t &jpp, + const pooling_pd_t *ppd) { + if (!mayiuse(isa)) + return status::unimplemented; + + const auto &pd = *ppd->desc(); + const memory_desc_wrapper src_d(ppd->src_md()); + const memory_desc_wrapper dst_d(ppd->dst_md()); + + jpp.mb = src_d.dims()[0]; + jpp.c = src_d.dims()[1]; + jpp.ih = src_d.dims()[2]; + jpp.iw = src_d.dims()[3]; + jpp.oh = dst_d.dims()[2]; + jpp.ow = dst_d.dims()[3]; + + jpp.stride_h = pd.strides[0]; + jpp.stride_w = pd.strides[1]; + jpp.kh = pd.kernel[0]; + jpp.kw = pd.kernel[1]; + + jpp.t_pad = pd.padding[0][0]; + jpp.l_pad = pd.padding[0][1]; + + jpp.alg = pd.alg_kind; + + jpp.src_dt = pd.src_desc.data_type; + jpp.dst_dt = pd.dst_desc.data_type; + + // data_type items per one vreg on the + // isa == avx2 : 32 bytes -> 32 for s8/u8, 8 for s32 + // isa == avx512* : 64 bytes -> 64 for s8/u8, 16 for s32 + int simd_w = cpu_isa_traits::vlen / data_type_size(jpp.src_dt); + + jpp.c_block = simd_w; + jpp.c_tail = jpp.c % jpp.c_block; + jpp.nb_c = jpp.c / jpp.c_block; + jpp.ur_c = 1; + jpp.ur_c_tail = jpp.nb_c - (jpp.nb_c / jpp.ur_c)*jpp.ur_c + + (jpp.c_tail != 0); + + size_t tail_mask = (1ULL << jpp.c_tail) - 1; + + switch (jpp.alg) { + case pooling_max: + jpp.tail[0] = tail_mask; + jpp.tail[1] = 0; + jpp.tail[2] = 0; + jpp.tail[3] = 0; + break; + case pooling_avg_include_padding: + case pooling_avg_exclude_padding: { + // avg_proc_dt (s32) defines granularity (because u8/s8 processed as s32) + // avx2 : 8, avx512 : 16 + const size_t msk_gran = cpu_isa_traits::vlen / data_type_size(avg_proc_dt); + const size_t msk_msk = (1ULL << msk_gran) - 1; + size_t m = tail_mask; + for (size_t ll = 0; ll < max_num_ll; ll++) { + jpp.tail[ll] = m & msk_msk; + m = m >> msk_gran; + } + break; + } + default: return status::unimplemented; + } + + return status::success; +} + +template +status_t jit_uni_i8i8_pooling_fwd_t::pd_t::jit_conf() { + return jit_uni_i8i8_pooling_fwd_ker_t::init_conf(jpp_, this); +} + +template +jit_uni_i8i8_pooling_fwd_t:: +jit_uni_i8i8_pooling_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd), ker_(nullptr) +{ ker_ = new jit_uni_i8i8_pooling_fwd_ker_t(pd()->jpp_); } + +template +jit_uni_i8i8_pooling_fwd_t:: +~jit_uni_i8i8_pooling_fwd_t() { delete ker_; } + +template +void jit_uni_i8i8_pooling_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + auto src_i8 = CTX_IN_MEM(const char *, MKLDNN_ARG_SRC); + auto dst_i8 = CTX_OUT_MEM(char *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + + const auto &jpp = pd()->jpp_; + + parallel_nd(jpp.mb, jpp.oh, jpp.ow, + [&](int n, int oh, int ow) { + const int ih = nstl::max(oh*jpp.stride_h - jpp.t_pad, 0); + const int iw = nstl::max(ow*jpp.stride_w - jpp.l_pad, 0); + + const int kh_start = nstl::max(0, jpp.t_pad - oh * jpp.stride_h); + const int kh_end = nstl::min(jpp.kh, + jpp.ih + jpp.t_pad - oh * jpp.stride_h); + const int kw_start = nstl::max(0, jpp.l_pad - ow * jpp.stride_w); + const int kw_end = nstl::min(jpp.kw, + jpp.iw + jpp.l_pad - ow * jpp.stride_w); + + auto p = typename jit_uni_i8i8_pooling_fwd_ker_t::call_params_t(); + p.src_i8 = &src_i8[ + src_d.blk_off(n, 0, ih, iw) * src_d.data_type_size()]; + p.dst_i8 = &dst_i8[ + dst_d.blk_off(n, 0, oh, ow) * dst_d.data_type_size()]; + p.kw_range = (size_t)(kw_end - kw_start); + p.kh_range = (size_t)(kh_end - kh_start); + p.idivider = 1.0f / ((jpp.alg == pooling_avg_exclude_padding) ? + p.kh_range*p.kw_range : jpp.kw*jpp.kh); + + ker_->ker_(&p); + }); +} + +// Explicit instantiation only for supported values. +// +template struct jit_uni_i8i8_pooling_fwd_ker_t; +template struct jit_uni_i8i8_pooling_fwd_t; + +template struct jit_uni_i8i8_pooling_fwd_ker_t; +template struct jit_uni_i8i8_pooling_fwd_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp new file mode 100644 index 0000000000..d757679df5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp @@ -0,0 +1,89 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_UNI_I8I8_POOLING_HPP +#define CPU_JIT_UNI_I8I8_POOLING_HPP + +#include "c_types_map.hpp" + +#include "cpu_pooling_pd.hpp" +#include "cpu_primitive.hpp" + +#include "cpu_isa_traits.hpp" +#include "jit_primitive_conf.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_uni_i8i8_pooling_fwd_ker_t; + +template +struct jit_uni_i8i8_pooling_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_pooling_fwd_pd_t { + using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_i8i8_pooling_fwd_t); + + status_t init() { + bool ok = true + && mayiuse(isa) + && ndims() == 4 + && set_default_params() == status::success + && desc()->prop_kind == prop_kind::forward_inference + && utils::one_of(desc()->alg_kind, alg_kind::pooling_max, + alg_kind::pooling_avg_include_padding, + alg_kind::pooling_avg_exclude_padding) + && utils::one_of(src_md()->data_type, data_type::s32, + data_type::s8, data_type::u8) + && src_md()->data_type == dst_md()->data_type + && attr()->has_default_values() + && memory_desc_matches_tag(*src_md(), format_tag::nhwc) + && memory_desc_matches_tag(*dst_md(), format_tag::nhwc); + if (!ok) return status::unimplemented; + + return jit_conf(); + } + + jit_pool_conf_t jpp_; + + protected: + status_t jit_conf(); + }; + + jit_uni_i8i8_pooling_fwd_t(const pd_t *apd); + ~jit_uni_i8i8_pooling_fwd_t(); + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_uni_i8i8_pooling_fwd_ker_t *ker_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp new file mode 100644 index 0000000000..2c5a8e8973 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp @@ -0,0 +1,305 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_uni_lrn_kernel_f32.hpp" +#include "jit_uni_lrn.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::utils; + +template +jit_uni_lrn_fwd_t::jit_uni_lrn_fwd_t(const pd_t *apd) + : cpu_primitive_t(apd), ker_(nullptr) + , ker_first_(nullptr), ker_last_(nullptr) +{ + using namespace alg_kind; + + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + const int ls = pd()->desc()->local_size; + float A = pd()->desc()->lrn_alpha / ls; + float K = pd()->desc()->lrn_k; + + auto pk = pd()->desc()->prop_kind; + auto ak = pd()->desc()->alg_kind; + auto dat_tag = pd()->dat_tag_; + + if (dat_tag == nChw8c && ls == 5 && ak == lrn_across_channels) { + ker_ = new jit_uni_lrn_fwd_kernel_f32( + nchw8c_across(H, W, 0), A, K, pk); + ker_first_ = new jit_uni_lrn_fwd_kernel_f32( + nchw8c_across(H, W, -1), A, K, pk); + ker_last_ = new jit_uni_lrn_fwd_kernel_f32( + nchw8c_across(H, W, +1), A, K, pk); + } else if (dat_tag == nChw8c && ak == lrn_within_channel) { + /* within channel, local_size (x) local_size */ + A /= ls; /* XXX: why? */ + ker_ = new jit_uni_lrn_fwd_kernel_f32( + nchw8c_within(H, W, ls), A, K, pk); + } else if (dat_tag == nchw && ls == 5 && ak == lrn_across_channels) { + ker_ = new jit_uni_lrn_fwd_kernel_f32( + nchw_across(C, H*W, 0), A, K, pk); + int remind = (H*W) % VECTOR_LENGTH; + if (remind != 0) { + ker_last_ = new jit_uni_lrn_fwd_kernel_f32( + nchw_across(C, H*W, remind), A, K, pk); + } + } else if (true /* XXX: why */) { + ker_ = new jit_uni_lrn_fwd_kernel_f32(nhwc_across(C), A, K, pk); + } +} + +template +jit_uni_lrn_fwd_t::~jit_uni_lrn_fwd_t() +{ delete ker_; delete ker_first_; delete ker_last_; } + +template +void jit_uni_lrn_fwd_t::execute_forward(const exec_ctx_t &ctx) const { + using namespace alg_kind; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(data_t *, MKLDNN_ARG_WORKSPACE); + + const int N = pd()->MB(); + const int C = pd()->C(); + const int HW = pd()->H() * pd()->W(); + const int ls = pd()->desc()->local_size; + + auto ak = pd()->desc()->alg_kind; + auto dat_tag = pd()->dat_tag_; + + if (dat_tag == nChw8c && ls == 5 && ak == lrn_across_channels) { + parallel_nd(N, C / VECTOR_LENGTH, [&](int n, int c8) { + jit_args_fwd_t args; + args.src = &src[n*HW*C + c8 * HW * VECTOR_LENGTH]; + args.dst = &dst[n*HW*C + c8 * HW * VECTOR_LENGTH]; + args.scratch = &ws[n*HW*C + c8 * HW * VECTOR_LENGTH]; + if (c8 == 0) + (*ker_first_)(&args); + else if (c8 == C / VECTOR_LENGTH - 1) + (*ker_last_)(&args); + else + (*ker_)(&args); + }); + } + else if (dat_tag == nChw8c && ak == lrn_within_channel) { + parallel_nd(N, C / VECTOR_LENGTH, [&](int n, int c8) { + jit_args_fwd_t args; + args.src = &src[n*HW*C + c8 * HW * VECTOR_LENGTH]; + args.dst = &dst[n*HW*C + c8 * HW * VECTOR_LENGTH]; + args.scratch = &ws[n*HW*C + c8 * HW * VECTOR_LENGTH]; + (*ker_)(&args); + }); + } + else if (dat_tag == nchw && ls == 5 && ak == lrn_across_channels) { + parallel_nd(N, (HW + VECTOR_LENGTH - 1) / VECTOR_LENGTH, + [&](int n, int hw8) { + jit_args_fwd_t args; + args.src = &src[n*HW*C + hw8 * VECTOR_LENGTH]; + args.dst = &dst[n*HW*C + hw8 * VECTOR_LENGTH]; + args.scratch = &ws[n*HW*C + hw8 * VECTOR_LENGTH]; + if ((hw8 + 1)*VECTOR_LENGTH > HW) + (*ker_last_)(&args); + else + (*ker_)(&args); + }); + } + else { // nhwc + parallel_nd(N, HW, [&](int n, int hw) { + jit_args_fwd_t args; + args.src = &src[n*HW*C + hw * C]; + args.dst = &dst[n*HW*C + hw * C]; + args.scratch = &ws[n*HW*C + hw * C]; + (*ker_)(&args); + }); + } +} + +template +status_t jit_uni_lrn_fwd_t::pd_t::init() { + using namespace prop_kind; + using namespace alg_kind; + + const memory_desc_wrapper data_d(src_md()); + bool ok = true + && mayiuse(isa) + && is_fwd() + && everyone_is(data_type::f32, data_d.data_type()) + && !has_zero_dim_memory() + && data_d.ndims() == 4 + && data_d.dims()[1] % VECTOR_LENGTH == 0 + && data_d.dims()[1] >= 2 * VECTOR_LENGTH + && desc()->lrn_beta == 0.75 + && attr()->has_default_values(); + if (!ok) return unimplemented; + + if (desc_.prop_kind == forward_training) ws_md_ = *src_md(); + + dat_tag_ = memory_desc_matches_one_of_tag(*src_md(), nChw8c, nchw, nhwc); + + bool args_ok_across = true + && desc()->alg_kind == lrn_across_channels + && desc()->local_size == 5 + && one_of(dat_tag_, nChw8c, nchw, nhwc); + + const int jit_max_local_size = 5; // bigger size triggers too big code size + bool args_ok_within = true + && desc()->alg_kind == lrn_within_channel + && desc()->local_size <= ( jit_max_local_size <= MAX_LOCAL_SIZE + ? jit_max_local_size : MAX_LOCAL_SIZE) + && data_d.dims()[2] >= desc()->local_size + && data_d.dims()[3] >= desc()->local_size + && one_of(dat_tag_, nChw8c); + + return args_ok_across || args_ok_within ? success : unimplemented; +} + +template +jit_uni_lrn_bwd_t::jit_uni_lrn_bwd_t(const pd_t *apd) + : cpu_primitive_t(apd) + , ker_(nullptr), ker_first_(nullptr), ker_last_(nullptr) +{ + using namespace alg_kind; + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + const int ls = pd()->desc()->local_size; + float A = pd()->desc()->lrn_alpha / ls; + float B = pd()->desc()->lrn_beta; + + int use_h_parallelizm = 0;// XXX + if (C / VECTOR_LENGTH == 1) { + ker_ = new jit_uni_lrn_bwd_kernel_f32( + nchw8c_across(H, W, 3), A, B, use_h_parallelizm); + } + else { + ker_ = new jit_uni_lrn_bwd_kernel_f32( + nchw8c_across(H, W, 0), A, B, use_h_parallelizm); + ker_first_ = new jit_uni_lrn_bwd_kernel_f32( + nchw8c_across(H, W, -1), A, B, use_h_parallelizm); + ker_last_ = new jit_uni_lrn_bwd_kernel_f32( + nchw8c_across(H, W, +1), A, B, use_h_parallelizm); + } +} + +template +jit_uni_lrn_bwd_t::~jit_uni_lrn_bwd_t() +{ + delete ker_; delete ker_first_; delete ker_last_; +} + +template +void jit_uni_lrn_bwd_t::execute_backward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto ws = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WORKSPACE); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const int N = pd()->MB(); + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + + int use_h_parallelizm = 0; // XXX + if (use_h_parallelizm) { + parallel_nd(N, C / VECTOR_LENGTH, H, [&](int n, int c8, int h) { + auto offset = n*C*H*W + c8*H*W*VECTOR_LENGTH + + h*W*VECTOR_LENGTH; + jit_args_bwd_t args; + args.src = &src[offset]; + args.diff_dst = &diff_dst[offset]; + args.scratch = &ws[offset]; + args.diff_src = &diff_src[offset]; + if (C / VECTOR_LENGTH == 1) + (*ker_)(&args); + else if (c8 == 0) + (*ker_first_)(&args); + else if (c8 == C / VECTOR_LENGTH - 1) + (*ker_last_)(&args); + else + (*ker_)(&args); + }); + } + else { + parallel_nd(N, C / VECTOR_LENGTH, [&](int n, int c8) { + auto offset = n*C*H*W + c8*H*W*VECTOR_LENGTH; + jit_args_bwd_t args; + args.src = &src[offset]; + args.diff_dst = &diff_dst[offset]; + args.scratch = &ws[offset]; + args.diff_src = &diff_src[offset]; + if (C / VECTOR_LENGTH == 1) + (*ker_)(&args); + else if (c8 == 0) + (*ker_first_)(&args); + else if (c8 == C / VECTOR_LENGTH - 1) + (*ker_last_)(&args); + else + (*ker_)(&args); + }); + } +} + +template +status_t jit_uni_lrn_bwd_t::pd_t::init() { + using namespace prop_kind; + using namespace alg_kind; + + const memory_desc_wrapper data_d(src_md()); + bool ok = true + && mayiuse(isa) + && !is_fwd() + && utils::everyone_is(data_type::f32, data_d.data_type()) + && !has_zero_dim_memory() + && data_d.ndims() == 4 + && data_d.dims()[1] % VECTOR_LENGTH == 0 + && desc()->lrn_beta == 0.75 + && attr()->has_default_values(); + if (!ok) return unimplemented; + + ws_md_ = *src_md(); + if (!compare_ws(hint_fwd_pd_)) return unimplemented; + + dat_tag_ = memory_desc_matches_one_of_tag(*src_md(), nChw8c); + + bool args_ok_across = true + && desc()->alg_kind == lrn_across_channels + && desc()->local_size == 5 + && utils::one_of(dat_tag_, nChw8c); + + return args_ok_across ? success : unimplemented; +} + +template struct jit_uni_lrn_fwd_t; +template struct jit_uni_lrn_fwd_t; +template struct jit_uni_lrn_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp new file mode 100644 index 0000000000..333cd3396d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp @@ -0,0 +1,103 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_UNI_LRN_HPP +#define CPU_JIT_UNI_LRN_HPP + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_isa_traits.hpp" +#include "cpu_lrn_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template struct jit_uni_lrn_fwd_kernel_f32; +template struct jit_uni_lrn_bwd_kernel_f32; + +template +struct jit_uni_lrn_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_lrn_fwd_pd_t { + using cpu_lrn_fwd_pd_t::cpu_lrn_fwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_lrn_fwd_t); + + status_t init(); + + format_tag_t dat_tag_; + }; + + jit_uni_lrn_fwd_t(const pd_t *apd); + ~jit_uni_lrn_fwd_t(); + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_uni_lrn_fwd_kernel_f32 *ker_, *ker_first_, *ker_last_; +}; + +template +struct jit_uni_lrn_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_lrn_bwd_pd_t { + using cpu_lrn_bwd_pd_t::cpu_lrn_bwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_lrn_bwd_t); + + status_t init(); + + format_tag_t dat_tag_; + }; + + jit_uni_lrn_bwd_t(const pd_t *apd); + ~jit_uni_lrn_bwd_t(); + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + jit_uni_lrn_bwd_kernel_f32 *ker_, *ker_first_, *ker_last_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp new file mode 100644 index 0000000000..89af47272c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp @@ -0,0 +1,1487 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "utils.hpp" + +#include "jit_uni_lrn_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; + +////////////////////////////////////////////////////////////////////////////// +// forward kernel +template +void jit_uni_lrn_fwd_kernel_f32::within_body( + int hoff, int Hoff, int woff, int Woff, int stride, + Xbyak::Ymm ysum, Xbyak::Ymm ydst, Xbyak::Ymm ytmp, Xbyak::Ymm ysum2, + prop_kind_t pk) +{ + vxorps(ysum, ysum, ysum); + for (int i = hoff; i <= Hoff; ++i) + { + for (int j = woff; j <= Woff; ++j) + { + if (i == 0 && j == 0) + { + vmovups(ydst, ptr[src]); + vfmadd231ps(ysum, ydst, ydst); + } + else + { + vmovups(ytmp, ptr[src + (i*stride + j)*VECTOR_LENGTH*4]); + vfmadd231ps(ysum, ytmp, ytmp); + } + } + } + vfmadd132ps(ysum, yk, yalpha); // ysum <- ysum*yalpha+yk + vmovaps(ytmp, ysum); + if (pk != prop_kind::forward_inference) + vmovups(ptr[scratch], ytmp); + vmulps(ysum2, ysum, ysum); + vmulps(ysum, ysum, ysum2); // ysum = (ysum*yalpha+yk)^3; + vsqrtps(ysum, ysum); + vsqrtps(ysum, ysum); // ysum = (ysum*yalpha+yk)^0.75 + vdivps(ydst, ydst, ysum); // ydst <- ydst / ysum + vmovups(ptr[dst], ydst); + add(src, 32); + add(dst, 32); + if (pk != prop_kind::forward_inference) + add(scratch, 32); +} + +template +void jit_uni_lrn_fwd_kernel_f32::within_body_sse42( + int hoff, int Hoff, int woff, int Woff, int stride, prop_kind_t pk) +{ + Xbyak::Xmm xtmp_lo = xmm12; + Xbyak::Xmm xtmp_hi = xmm13; + Xbyak::Xmm xsum_lo = xmm8; + Xbyak::Xmm xsum_hi = xmm9; + Xbyak::Xmm xdst_lo = xmm10; + Xbyak::Xmm xdst_hi = xmm11; + Xbyak::Xmm xsum2_lo = xmm14; + Xbyak::Xmm xsum2_hi = xmm15; + + xorps(xsum_lo, xsum_lo); + xorps(xsum_hi, xsum_hi); + for (int i = hoff; i <= Hoff; ++i) + { + for (int j = woff; j <= Woff; ++j) + { + if (i == 0 && j == 0) + { + movups(xdst_lo, ptr[src]); + movups(xdst_hi, ptr[src + 4 * sizeof(float)]); + mulps(xdst_lo, xdst_lo); + mulps(xdst_hi, xdst_hi); + addps(xsum_lo, xdst_lo); + addps(xsum_hi, xdst_hi); + } + else + { + movups(xtmp_lo, ptr[src + (i*stride + j)*VECTOR_LENGTH * 4]); + movups(xtmp_hi, ptr[src + (i*stride + j)*VECTOR_LENGTH * 4 + 4 * sizeof(float)]); + mulps(xtmp_lo, xtmp_lo); + mulps(xtmp_hi, xtmp_hi); + addps(xsum_lo, xtmp_lo); + addps(xsum_hi, xtmp_hi); + } + } + } + mulps(xsum_lo, xalpha); + mulps(xsum_hi, xalpha); + addps(xsum_lo, xk); + addps(xsum_hi, xk); // xsum <- xsum*xalpha+xk + movaps(xtmp_lo, xsum_lo); + movaps(xtmp_hi, xsum_hi); + if (pk != prop_kind::forward_inference) { + movups(ptr[scratch], xtmp_lo); + movups(ptr[scratch + 4 * sizeof(float)], xtmp_hi); + } + movaps(xsum2_lo, xsum_lo); + movaps(xsum2_hi, xsum_hi); + mulps(xsum2_lo, xsum_lo); + mulps(xsum2_hi, xsum_hi); + mulps(xsum_lo, xsum2_lo); + mulps(xsum_hi, xsum2_hi); // xsum = (xsum*xalpha+xk)^3; + + sqrtps(xsum_lo, xsum_lo); + sqrtps(xsum_hi, xsum_hi); + sqrtps(xsum_lo, xsum_lo); + sqrtps(xsum_hi, xsum_hi); // xsum = (xsum*xalpha+xk)^0.75 + + movups(xdst_lo, ptr[src]); + movups(xdst_hi, ptr[src + 4 * sizeof(float)]); + divps(xdst_lo, xsum_lo); + divps(xdst_hi, xsum_hi); // xdst <- xdst / xsum + + movups(ptr[dst], xdst_lo); + movups(ptr[dst + 4 * sizeof(float)], xdst_hi); + add(src, 32); + add(dst, 32); + if (pk != prop_kind::forward_inference) + add(scratch, 32); +} + +template +jit_uni_lrn_fwd_kernel_f32::jit_uni_lrn_fwd_kernel_f32( + const struct nchw8c_within &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , alpha(A), k(K) +{ + Xbyak::Reg64 h = r9; + Xbyak::Reg64 w = r10; + Vmm ysum = Vmm(isa == avx2 ? 9 : 9); + Vmm ysum2 = Vmm(isa == avx2 ? 10 : 10); + Vmm ydst = Vmm(isa == avx2 ? 11 : 11); + Vmm ytmp = Vmm(isa == avx2 ? 12 : 12); + + this->preamble(); + + mov(src, ptr[this->param1 + 0]); + mov(dst, ptr[this->param1 + 8]); + if (pk != prop_kind::forward_inference) + mov(scratch, ptr[this->param1 + 16]); + + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + if (isa == avx2) { + vbroadcastss(yalpha, xalpha); + } else { + shufps(xalpha, xalpha, 0); + } + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + if (isa == avx2) { + vbroadcastss(yk, xk); + } else { + shufps(xk, xk, 0); + } + + int s2 = (J.size - 1) / 2, S2 = J.size - s2 - 1; + + for (int i = 0; i < s2; ++i) + { + Label label_t; + for (int j = 0; j < s2; ++j) { + if (isa == avx2) { + within_body(-i, S2, -j, S2, J.W, ysum, ydst, ytmp, ysum2, pk); + } + else { + within_body_sse42(-i, S2, -j, S2, J.W, pk); + } + } + mov(w, J.W - J.size + 1); + L(label_t); + if (isa == avx2) { + within_body(-i, S2, -s2, S2, J.W, ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-i, S2, -s2, S2, J.W, pk); + } + dec(w); + cmp(w, 0); + jne(label_t, T_NEAR); + for (int j = J.W - S2; j < J.W; ++j) { + if (isa == avx2) { + within_body(-i, S2, -s2, J.W - 1 - j, J.W, + ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-i, S2, -s2, J.W - 1 - j, J.W, pk); + } + } + } + + mov(h, J.H - J.size + 1); + Label lrn_loop_h; + L(lrn_loop_h); + for (int j = 0; j < s2; ++j) { + if (isa == avx2) { + within_body(-s2, S2, -j, S2, J.W, ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-s2, S2, -j, S2, J.W, pk); + } + } + mov(w, J.W - J.size + 1); + Label lrn_loop_w; + L(lrn_loop_w); + if (isa == avx2) { + within_body(-s2, S2, -s2, S2, J.W, ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-s2, S2, -s2, S2, J.W, pk); + } + dec(w); + cmp(w, 0); + jne(lrn_loop_w, T_NEAR); + for (int j = J.W - S2; j < J.W; ++j) { + if (isa == avx2) { + within_body(-s2, S2, -s2, J.W - 1 - j, J.W, + ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-s2, S2, -s2, J.W - 1 - j, J.W, pk); + } + } + dec(h); + cmp(h, 0); + jne(lrn_loop_h, T_NEAR); + + for (int i = J.H - S2; i < J.H; ++i) + { + for (int j = 0; j < s2; ++j) { + if (isa == avx2) { + within_body(-s2, J.H - 1 - i, -j, S2, J.W, + ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-s2, J.H - 1 - i, -j, S2, J.W, pk); + } + } + + mov(w, J.W - J.size + 1); + Label label_b; + L(label_b); + if (isa == avx2) { + within_body(-s2, J.H - 1 - i, -s2, S2, J.W, + ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-s2, J.H - 1 - i, -s2, S2, J.W, pk); + } + dec(w); + cmp(w, 0); + jne(label_b, T_NEAR); + + for (int j = J.W - S2; j < J.W; ++j) { + if (isa == avx2) { + within_body(-s2, J.H - 1 - i, -s2, J.W - 1 - j, J.W, + ysum, ydst, ytmp, ysum2, pk); + } else { + within_body_sse42(-s2, J.H - 1 - i, -s2, J.W - 1 - j, J.W, pk); + } + } + } + + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +template<> +jit_uni_lrn_fwd_kernel_f32::jit_uni_lrn_fwd_kernel_f32( + const struct nchw8c_across &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , alpha(A), k(K) +{ + Xbyak::Reg64 t = rsp; + Xbyak::Reg64 hw = r9; + Xbyak::Xmm xsrc_prev = xmm2; + Xbyak::Ymm ysrc = ymm3; + Xbyak::Ymm yc = ymm3; + Xbyak::Xmm xsrc_next = xmm4; + Xbyak::Ymm ya = ymm5; + Xbyak::Ymm yb = ymm6; + Xbyak::Ymm yd = ymm7; + Xbyak::Ymm ye = ymm8; + Xbyak::Ymm ysum = ymm9; + Xbyak::Ymm ysum2 = ymm10; + Xbyak::Ymm ydst = ymm11; + Xbyak::Ymm ybase = ymm12; + + this->preamble(); + + mov(src, ptr[this->param1 + 0]); + mov(dst, ptr[this->param1 + 8]); + if (pk != prop_kind::forward_inference) + mov(scratch, ptr[this->param1 + 16]); + sub(t, 64); + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + vbroadcastss(yalpha, xalpha); + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + vbroadcastss(yk, xk); + + if (J.version == -1) + { + vxorps(xsrc_prev, xsrc_prev, xsrc_prev); + vmovups(ptr[t + 0], xsrc_prev); + } + if (J.version == +1) + { + vxorps(xsrc_next, xsrc_next, xsrc_next); + vmovups(ptr[t + 48], xsrc_next); + } + + mov(hw, J.H*J.W); + + Label lrn_loop; + L(lrn_loop); + + if (J.version != -1) vmovups(xsrc_prev, ptr[src - J.H*J.W * 32 + 16]); + vmovups(ysrc, ptr[src]); + if (J.version != +1) vmovups(xsrc_next, ptr[src + J.H*J.W * 32]); + + if (J.version != -1) vmovups(ptr[t + 0], xsrc_prev); + vmovups(ptr[t + 16], ysrc); + if (J.version != +1) vmovups(ptr[t + 48], xsrc_next); + + vmovups(ya, ptr[t + 16 - 8]); + vmovups(yb, ptr[t + 16 - 4]); + vmovups(yd, ptr[t + 16 + 4]); + vmovups(ye, ptr[t + 16 + 8]); + vmulps(ysum, yc, yc); + vfmadd231ps(ysum, ya, ya); // ysum <- ysum + ya*ya + vfmadd231ps(ysum, yb, yb); + vfmadd231ps(ysum, yd, yd); + vfmadd231ps(ysum, ye, ye); + vfmadd132ps(ysum, yk, yalpha); // ysum <- ysum*yalpha+yk + + vmovaps(ybase, ysum); + if (pk != prop_kind::forward_inference) + vmovups(ptr[scratch], ybase); + vmulps(ysum2, ysum, ysum); + vmulps(ysum, ysum, ysum2); // ysum = ybase^3; + vsqrtps(ysum, ysum); + vsqrtps(ysum, ysum); // ysum = ybase^0.75 + vdivps(ydst, ysrc, ysum); // ydst = ysrc / ysum + vmovups(ptr[dst], ydst); + + add(src, 32); + add(dst, 32); + if (pk != prop_kind::forward_inference) + add(scratch, 32); + dec(hw); + cmp(hw, 0); + jne(lrn_loop, T_NEAR); + + add(t, 64); + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +template<> +jit_uni_lrn_fwd_kernel_f32::jit_uni_lrn_fwd_kernel_f32( + const struct nchw8c_across &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , alpha(A), k(K) +{ + Xbyak::Reg64 t = rsp; + Xbyak::Reg64 hw = r9; + + Xbyak::Xmm xsrc_lo = xmm2; + Xbyak::Xmm xsrc_hi = xmm3; + Xbyak::Xmm xc_lo = xmm4; + Xbyak::Xmm xc_hi = xmm5; + Xbyak::Xmm xsum_lo = xc_lo; + Xbyak::Xmm xsum_hi = xc_hi; + Xbyak::Xmm xsrc_prev = xmm6; + Xbyak::Xmm xsrc_next = xmm7; + Xbyak::Xmm xa_lo = xmm8; + Xbyak::Xmm xa_hi = xmm9; + Xbyak::Xmm xb_lo = xmm10; + Xbyak::Xmm xb_hi = xmm11; + Xbyak::Xmm xd_lo = xmm12; + Xbyak::Xmm xd_hi = xmm13; + Xbyak::Xmm xe_lo = xmm14; + Xbyak::Xmm xe_hi = xmm15; + Xbyak::Xmm xbase_lo = xmm14; + Xbyak::Xmm xbase_hi = xmm15; + + this->preamble(); + + mov(src, ptr[this->param1 + 0]); + mov(dst, ptr[this->param1 + 8]); + if (pk != prop_kind::forward_inference) + mov(scratch, ptr[this->param1 + 16]); + sub(t, 64); + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + shufps(xalpha, xalpha, 0); + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + shufps(xk, xk, 0); + + if (J.version == -1) + { + xorps(xsrc_prev, xsrc_prev); + movups(ptr[t + 0], xsrc_prev); + } + if (J.version == +1) + { + xorps(xsrc_next, xsrc_next); + movups(ptr[t + 48], xsrc_next); + } + + mov(hw, J.H*J.W); + Label lrn_loop; + L(lrn_loop); + + if (J.version != -1) movups(xsrc_prev, ptr[src - J.H*J.W * 32 + 16]); + movups(xsrc_lo, ptr[src]); + movups(xsrc_hi, ptr[src + 4 * sizeof(float)]); + if (J.version != +1) movups(xsrc_next, ptr[src + J.H*J.W * 32]); + + if (J.version != -1) movups(ptr[t + 0], xsrc_prev); + movups(ptr[t + 16], xsrc_lo); + movups(ptr[t + 16 + 4 * sizeof(float)], xsrc_hi); + if (J.version != +1) movups(ptr[t + 48], xsrc_next); + + movups(xa_lo, ptr[t + 16 - 8]); + movups(xa_hi, ptr[t + 16 - 8 + 4 * sizeof(float)]); + movups(xb_lo, ptr[t + 16 - 4]); + movups(xb_hi, ptr[t + 16 - 4 + 4 * sizeof(float)]); + movups(xd_lo, ptr[t + 16 + 4]); + movups(xd_hi, ptr[t + 16 + 4 + 4 * sizeof(float)]); + movups(xe_lo, ptr[t + 16 + 8]); + movups(xe_hi, ptr[t + 16 + 8 + 4 * sizeof(float)]); + movaps(xc_lo, xsrc_lo); + movaps(xc_hi, xsrc_hi); + mulps(xsum_lo, xc_lo); + mulps(xsum_hi, xc_hi); + mulps(xa_lo, xa_lo); + mulps(xa_hi, xa_hi); + addps(xsum_lo, xa_lo); + addps(xsum_hi, xa_hi); // xsum <- xsum + xa*xa + mulps(xb_lo, xb_lo); + mulps(xb_hi, xb_hi); + addps(xsum_lo, xb_lo); + addps(xsum_hi, xb_hi); + mulps(xd_lo, xd_lo); + mulps(xd_hi, xd_hi); + addps(xsum_lo, xd_lo); + addps(xsum_hi, xd_hi); + mulps(xe_lo, xe_lo); + mulps(xe_hi, xe_hi); + addps(xsum_lo, xe_lo); + addps(xsum_hi, xe_hi); + + mulps(xsum_lo, xalpha); + mulps(xsum_hi, xalpha); + addps(xsum_lo, xk); + addps(xsum_hi, xk); // xsum <- xsum*xalpha+xk + + movaps(xbase_lo, xsum_lo); + movaps(xbase_hi, xsum_hi); + if (pk != prop_kind::forward_inference) { + movups(ptr[scratch], xbase_lo); + movups(ptr[scratch + 4 * sizeof(float)], xbase_hi); + } + mulps(xsum_lo, xsum_lo); + mulps(xsum_hi, xsum_hi); + mulps(xsum_lo, xbase_lo); + mulps(xsum_hi, xbase_hi); // xsum = xbase^3; + sqrtps(xsum_lo, xsum_lo); + sqrtps(xsum_hi, xsum_hi); + sqrtps(xsum_lo, xsum_lo); + sqrtps(xsum_hi, xsum_hi); // xsum = xbase^0.75 + divps(xsrc_lo, xsum_lo); + divps(xsrc_hi, xsum_hi); // xdst = xsrc / xsum + movups(ptr[dst], xsrc_lo); + movups(ptr[dst + 4 * sizeof(float)], xsrc_hi); + + add(src, 32); + add(dst, 32); + if (pk != prop_kind::forward_inference) + add(scratch, 32); + dec(hw); + cmp(hw, 0); + jne(lrn_loop, T_NEAR); + + add(t, 64); + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +template<> +jit_uni_lrn_fwd_kernel_f32::jit_uni_lrn_fwd_kernel_f32( + const struct nhwc_across &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , alpha(A), k(K) +{ + static const uint32_t mask[] = { + 0, 0, 0x80000000, 0x80000000, 0x80000000, 0x80000000, + 0x80000000, 0x80000000, 0x80000000, 0, 0 + }; + + Xbyak::Reg64 c = r9; + Xbyak::Ymm ya = ymm2; + Xbyak::Ymm yb = ymm3; + Xbyak::Ymm yc = ymm4; + Xbyak::Ymm yd = ymm5; + Xbyak::Ymm ye = ymm6; + Xbyak::Ymm ysum = ymm7; + Xbyak::Ymm ydst = ymm8; + Xbyak::Ymm ybase = ymm9; + Xbyak::Ymm ymask = ymm10; + + this->preamble(); + + mov(src, ptr[this->param1 + 0]); + mov(dst, ptr[this->param1 + 8]); + if (pk != prop_kind::forward_inference) + mov(scratch, ptr[this->param1 + 16]); + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + vbroadcastss(yalpha, xalpha); + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + vbroadcastss(yk, xk); + + vxorps(ysum, ysum, ysum); + + mov(imm_addr64, reinterpret_cast(&mask[0])); + vmovups(ymask, ptr[imm_addr64]); + vmaskmovps(ya, ymask, ptr[src - 8]); + vfmadd231ps(ysum, ya, ya); // ysum <- ysum + ya^2+yb^2+yc^2+yd^2+ye^2 + + mov(imm_addr64, reinterpret_cast(&mask[1])); + vmovups(ymask, ptr[imm_addr64]); + vmaskmovps(yb, ymask, ptr[src - 4]); + vfmadd231ps(ysum, yb, yb); + + mov(c, J.C / 8 - 1); + Label lrn_loop; + L(lrn_loop); + + vmovups(yc, ptr[src]); + vmovups(yd, ptr[src + 4]); + vmovups(ye, ptr[src + 8]); + vfmadd231ps(ysum, yc, yc); + vfmadd231ps(ysum, yd, yd); + vfmadd231ps(ysum, ye, ye); + + vmovups(ydst, ysum); + vfmadd132ps(ydst, yk, yalpha); // ydst <- ysum*yalpha+yk + + vmovaps(ybase, ydst); + if (pk != prop_kind::forward_inference) + vmovups(ptr[scratch], ybase); + vmulps(ydst, ydst, ydst); + vmulps(ydst, ydst, ybase); // ydst = (ysum*yalpha+yk)^3; + vsqrtps(ydst, ydst); + vsqrtps(ydst, ydst); // ydst = (ysum*yalpha+yk)^0.75 + + vdivps(ydst, yc, ydst); // ydst = ysrc / (ysum*yalpha+yk)^0.75 + vmovups(ptr[dst], ydst); + + vxorps(ysum, ysum, ysum); + + add(src, 32); + add(dst, 32); + if (pk != prop_kind::forward_inference) + add(scratch, 32); + + vmovups(ya, ptr[src - 8]); + vfmadd231ps(ysum, ya, ya); + vmovups(yb, ptr[src - 4]); + vfmadd231ps(ysum, yb, yb); + + dec(c); + cmp(c, 0); + jne(lrn_loop, T_NEAR); + + vmovups(yc, ptr[src]); + vfmadd231ps(ysum, yc, yc); + + mov(imm_addr64, reinterpret_cast(&mask[2])); + vmovups(ymask, ptr[imm_addr64]); + vmaskmovps(yd, ymask, ptr[src + 4]); + vfmadd231ps(ysum, yd, yd); // ysum <- ysum + ya^2+yb^2+yc^2+yd^2+ye^2 + + mov(imm_addr64, reinterpret_cast(&mask[3])); + vmovups(ymask, ptr[imm_addr64]); + vmaskmovps(ye, ymask, ptr[src + 8]); + vfmadd231ps(ysum, ye, ye); + + vmovups(ydst, ysum); + vfmadd132ps(ydst, yk, yalpha); // ydst <- ysum*yalpha+yk + + vmovaps(ybase, ydst); + if (pk != prop_kind::forward_inference) + vmovups(ptr[scratch], ybase); + vmulps(ydst, ydst, ydst); + vmulps(ydst, ydst, ybase); // ydst = (ysum*yalpha+yk)^3; + vsqrtps(ydst, ydst); + vsqrtps(ydst, ydst); // ydst = (ysum*yalpha+yk)^0.75 + vdivps(ydst, yc, ydst); // ydst = ysrc / (ysum*yalpha+yk)^0.75 + + vmovups(ptr[dst], ydst); + + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +template<> +jit_uni_lrn_fwd_kernel_f32::jit_uni_lrn_fwd_kernel_f32( + const struct nhwc_across &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , alpha(A), k(K) +{ + static const uint32_t mask[] = { + 0, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0, 0 + }; + + static uint32_t store[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + Xbyak::Reg64 c = r9; + + Xbyak::Xmm xdst_lo = xmm0; + Xbyak::Xmm xdst_hi = xmm1; + Xbyak::Xmm xa_lo = xmm2; + Xbyak::Xmm xa_hi = xmm3; + Xbyak::Xmm xb_lo = xmm2; + Xbyak::Xmm xb_hi = xmm3; + Xbyak::Xmm xc_lo = xmm4; + Xbyak::Xmm xc_hi = xmm5; + Xbyak::Xmm xd_lo = xmm6; + Xbyak::Xmm xd_hi = xmm7; + Xbyak::Xmm xe_lo = xmm8; + Xbyak::Xmm xe_hi = xmm9; + Xbyak::Xmm xsum_lo = xmm10; + Xbyak::Xmm xsum_hi = xmm11; + Xbyak::Xmm xmask_lo = xmm12; + Xbyak::Xmm xmask_hi = xmm13; + Xbyak::Xmm xbase_lo = xmm14; + Xbyak::Xmm xbase_hi = xmm15; + + this->preamble(); + + mov(src, ptr[this->param1 + 0]); + mov(dst, ptr[this->param1 + 8]); + if (pk != prop_kind::forward_inference) + mov(scratch, ptr[this->param1 + 16]); + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + shufps(xalpha, xalpha, 0); + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + shufps(xk, xk, 0); + + mov(store_addr, reinterpret_cast(&store[0])); + and_(store_addr, -15); + movups(ptr[store_addr], xalpha); + movups(ptr[store_addr + 4 * sizeof(float)], xk); + + xorps(xsum_lo, xsum_lo); + xorps(xsum_hi, xsum_hi); + + mov(imm_addr64, reinterpret_cast(&mask[0])); + movups(xmask_lo, ptr[imm_addr64]); + movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]); + movups(xa_lo, ptr[src - 8]); + movups(xa_hi, ptr[src - 8 + 4 * sizeof(float)]); + andps(xa_lo, xmask_lo); + andps(xa_hi, xmask_hi); + mulps(xa_lo, xa_lo); + mulps(xa_hi, xa_hi); + addps(xsum_lo, xa_lo); + addps(xsum_hi, xa_hi); // xsum <- xsum + xa^2+xb^2+xc^2+xd^2+xe^2 + + mov(imm_addr64, reinterpret_cast(&mask[1])); + movups(xmask_lo, ptr[imm_addr64]); + movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]); + movups(xb_lo, ptr[src - 4]); + movups(xb_hi, ptr[src - 4 + 4 * sizeof(float)]); + andps(xb_lo, xmask_lo); + andps(xb_hi, xmask_hi); + mulps(xb_lo, xb_lo); + mulps(xb_hi, xb_hi); + addps(xsum_lo, xb_lo); + addps(xsum_hi, xb_hi); + + mov(c, J.C / 8 - 1); + Label lrn_loop; + L(lrn_loop); + + movups(xc_lo, ptr[src]); + movups(xc_hi, ptr[src + 4 * sizeof(float)]); + movups(xd_lo, ptr[src + 4]); + movups(xd_hi, ptr[src + 4 + 4 * sizeof(float)]); + movups(xe_lo, ptr[src + 8]); + movups(xe_hi, ptr[src + 8 + 4 * sizeof(float)]); + mulps(xc_lo, xc_lo); + mulps(xc_hi, xc_hi); + addps(xsum_lo, xc_lo); + addps(xsum_hi, xc_hi); + mulps(xd_lo, xd_lo); + mulps(xd_hi, xd_hi); + addps(xsum_lo, xd_lo); + addps(xsum_hi, xd_hi); + mulps(xe_lo, xe_lo); + mulps(xe_hi, xe_hi); + addps(xsum_lo, xe_lo); + addps(xsum_hi, xe_hi); + + movaps(xdst_lo, xsum_lo); + movaps(xdst_hi, xsum_hi); + // xdst <- xsum*xalpha+xk + mulps(xdst_lo, ptr[store_addr]); + mulps(xdst_hi, ptr[store_addr]); + addps(xdst_lo, ptr[store_addr + 4 * sizeof(float)]); + addps(xdst_hi, ptr[store_addr + 4 * sizeof(float)]); + + movaps(xbase_lo, xdst_lo); + movaps(xbase_hi, xdst_hi); + if (pk != prop_kind::forward_inference) { + movups(ptr[scratch], xbase_lo); + movups(ptr[scratch + 4 * sizeof(float)], xbase_hi); + } + mulps(xdst_lo, xdst_lo); + mulps(xdst_hi, xdst_hi); + mulps(xdst_lo, xbase_lo); + mulps(xdst_hi, xbase_hi); // xdst = (xsum*xalpha+xk)^3; + sqrtps(xdst_lo, xdst_lo); + sqrtps(xdst_hi, xdst_hi); + sqrtps(xdst_lo, xdst_lo); + sqrtps(xdst_hi, xdst_hi); // xdst = (xsum*xalpha+xk)^0.75 + + movups(xc_lo, ptr[src]); + movups(xc_hi, ptr[src + 4 * sizeof(float)]); + divps(xc_lo, xdst_lo); + divps(xc_hi, xdst_hi); // xdst = xsrc / (xsum*xalpha+xk)^0.75 + movups(ptr[dst], xc_lo); + movups(ptr[dst + 4 * sizeof(float)], xc_hi); + + xorps(xsum_lo, xsum_lo); + xorps(xsum_hi, xsum_hi); + + add(src, 32); + add(dst, 32); + if (pk != prop_kind::forward_inference) + add(scratch, 32); + + movups(xa_lo, ptr[src - 8]); + movups(xa_hi, ptr[src - 8 + 4 * sizeof(float)]); + mulps(xa_lo, xa_lo); + mulps(xa_hi, xa_hi); + addps(xsum_lo, xa_lo); + addps(xsum_hi, xa_hi); + movups(xb_lo, ptr[src - 4]); + movups(xb_hi, ptr[src - 4 + 4 * sizeof(float)]); + mulps(xb_lo, xb_lo); + mulps(xb_hi, xb_hi); + addps(xsum_lo, xb_lo); + addps(xsum_hi, xb_hi); + + dec(c); + cmp(c, 0); + jne(lrn_loop, T_NEAR); + + movups(xc_lo, ptr[src]); + movups(xc_hi, ptr[src + 4 * sizeof(float)]); + mulps(xc_lo, xc_lo); + mulps(xc_hi, xc_hi); + addps(xsum_lo, xc_lo); + addps(xsum_hi, xc_hi); + + mov(imm_addr64, reinterpret_cast(&mask[2])); + movups(xmask_lo, ptr[imm_addr64]); + movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]); + movups(xd_lo, ptr[src + 4]); + movups(xd_hi, ptr[src + 4 + 4 * sizeof(float)]); + andps(xd_lo, xmask_lo); + andps(xd_hi, xmask_hi); + mulps(xd_lo, xd_lo); + mulps(xd_hi, xd_hi); + addps(xsum_lo, xd_lo); + addps(xsum_hi, xd_hi); // xsum <- xsum + xa^2+xb^2+xc^2+xd^2+xe^2 + + mov(imm_addr64, reinterpret_cast(&mask[3])); + movups(xmask_lo, ptr[imm_addr64]); + movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]); + movups(xe_lo, ptr[src + 8]); + movups(xe_hi, ptr[src + 8 + 4 * sizeof(float)]); + andps(xe_lo, xmask_lo); + andps(xe_hi, xmask_hi); + mulps(xe_lo, xe_lo); + mulps(xe_hi, xe_hi); + addps(xsum_lo, xe_lo); + addps(xsum_hi, xe_hi); + + movups(xdst_lo, xsum_lo); + movups(xdst_hi, xsum_hi); + // xdst <- xsum*xalpha+xk + mulps(xdst_lo, ptr[store_addr]); + mulps(xdst_hi, ptr[store_addr]); + addps(xdst_lo, ptr[store_addr + 4 * sizeof(float)]); + addps(xdst_hi, ptr[store_addr + 4 * sizeof(float)]); + + movaps(xbase_lo, xdst_lo); + movaps(xbase_hi, xdst_hi); + if (pk != prop_kind::forward_inference) { + movups(ptr[scratch], xbase_lo); + movups(ptr[scratch + 4 * sizeof(float)], xbase_hi); + } + mulps(xdst_lo, xdst_lo); + mulps(xdst_hi, xdst_hi); + mulps(xdst_lo, xbase_lo); + mulps(xdst_hi, xbase_hi); // xdst = (xsum*xalpha+xk)^3; + sqrtps(xdst_lo, xdst_lo); + sqrtps(xdst_hi, xdst_hi); + sqrtps(xdst_lo, xdst_lo); + sqrtps(xdst_hi, xdst_hi); // xdst = (xsum*xalpha+xk)^0.75 + movups(xc_lo, ptr[src]); + movups(xc_hi, ptr[src + 4 * sizeof(float)]); + divps(xc_lo, xdst_lo); + divps(xc_hi, xdst_hi); // xdst = xsrc / (xsum*xalpha+xk)^0.75 + + movups(ptr[dst], xc_lo); + movups(ptr[dst + 4 * sizeof(float)], xc_hi); + + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +template<> +void jit_uni_lrn_fwd_kernel_f32::nchw_body( + int tail, int HW, prop_kind_t pk, + Xbyak::Ymm ymask, + Xbyak::Ymm ya, + Xbyak::Ymm yb, + Xbyak::Ymm yc, + Xbyak::Ymm yd, + Xbyak::Ymm ye, + Xbyak::Ymm ysum) {} + +template<> +void jit_uni_lrn_fwd_kernel_f32::nchw_body( + int tail, int HW, prop_kind_t pk, + Xbyak::Ymm ymask, + Xbyak::Ymm ya, + Xbyak::Ymm yb, + Xbyak::Ymm yc, + Xbyak::Ymm yd, + Xbyak::Ymm ye, + Xbyak::Ymm ysum) +{ + Xbyak::Ymm ydst = ymm14; + Xbyak::Ymm ybase = ymm15; + + vfmadd231ps(ysum, ye, ye); + + vmovups(ydst, ysum); + vfmadd132ps(ydst, yk, yalpha); // ydst <- ysum*yalpha+yk + + vmovaps(ybase, ydst); + if (pk != prop_kind::forward_inference) + { + if (tail != 0) + vmaskmovps(ptr[scratch], ymask, ybase); + else + vmovups(ptr[scratch], ybase); + } + vmulps(ydst, ydst, ydst); + vmulps(ydst, ydst, ybase); // ydst = (ysum*yalpha+yk)^3; + vsqrtps(ydst, ydst); + vsqrtps(ydst, ydst); // ydst = (ysum*yalpha+yk)^0.75 + vdivps(ydst, yc, ydst); // ydst = ysrc / (ysum*yalpha+yk)^0.75 + + if (tail != 0) + vmaskmovps(ptr[dst], ymask, ydst); + else + vmovups(ptr[dst], ydst); + + + vfnmadd231ps(ysum, ya, ya); + vmovups(ya, yb); + vmovups(yb, yc); + vmovups(yc, yd); + vmovups(yd, ye); +} + +template<> +void jit_uni_lrn_fwd_kernel_f32::nchw_tail_sse42( + int tail, Xbyak::Reg64 reg_dst, Xbyak::Xmm xtail_lo, Xbyak::Xmm xtail_hi) +{} + +template<> +void jit_uni_lrn_fwd_kernel_f32::nchw_tail_sse42( + int tail, Xbyak::Reg64 reg_dst, Xbyak::Xmm xtail_lo, Xbyak::Xmm xtail_hi) +{ + Xbyak::Xmm xmm_tmp = xmm10; + movaps(xmm_tmp, xtail_lo); + size_t offset = 0; + + if (tail > 4) { + movups(ptr[reg_dst], xtail_lo); + movaps(xmm_tmp, xtail_hi); + offset += 4 * sizeof(float); + tail -= 4; + } + movss(ptr[reg_dst + offset], xmm_tmp); + for (int i = 1; i < tail; i++) + { + psrldq(xmm_tmp, 4); + movss(ptr[reg_dst + offset + i * sizeof(float)], xmm_tmp); + } +} + +template<> +void jit_uni_lrn_fwd_kernel_f32::nchw_body_sse42( + int tail, int HW, prop_kind_t pk, + Xbyak::Xmm xmask_lo, Xbyak::Xmm xmask_hi, + Xbyak::Xmm xe_lo, Xbyak::Xmm xe_hi, + Xbyak::Xmm xsum_lo, Xbyak::Xmm xsum_hi) +{ + Xbyak::Xmm xdst_lo = xmm0; + Xbyak::Xmm xdst_hi = xmm1; + Xbyak::Xmm xbase_lo = xmm6; + Xbyak::Xmm xbase_hi = xmm7; + Xbyak::Xmm xtmp_lo = xmm8; + Xbyak::Xmm xtmp_hi = xmm9; + Xbyak::Xmm xa_lo = xmm6; + Xbyak::Xmm xa_hi = xmm7; + Xbyak::Xmm xb_lo = xmm8; + Xbyak::Xmm xb_hi = xmm9; + Xbyak::Xmm xc_lo = xmm10; + Xbyak::Xmm xc_hi = xmm11; + Xbyak::Xmm xd_lo = xmm12; + Xbyak::Xmm xd_hi = xmm13; + + // store xe + movaps(ptr[store_addr + 10 * 4 * sizeof(float)], xe_lo); + movaps(ptr[store_addr + 11 * 4 * sizeof(float)], xe_hi); + + mulps(xe_lo, xe_lo); + mulps(xe_hi, xe_hi); + addps(xsum_lo, xe_lo); + addps(xsum_hi, xe_hi); + + // xdst <- xsum*xalpha+xk + movaps(xdst_lo, xsum_lo); + movaps(xdst_hi, xsum_hi); + mulps(xdst_lo, ptr[store_addr + 0 * 4 * sizeof(float)]); + mulps(xdst_hi, ptr[store_addr + 0 * 4 * sizeof(float)]); + addps(xdst_lo, ptr[store_addr + 1 * 4 * sizeof(float)]); + addps(xdst_hi, ptr[store_addr + 1 * 4 * sizeof(float)]); + + movaps(xbase_lo, xdst_lo); + movaps(xbase_hi, xdst_hi); + if (pk != prop_kind::forward_inference) + { + if (tail != 0) { + nchw_tail_sse42(tail, scratch, xbase_lo, xbase_hi); + } + else { + movups(ptr[scratch], xbase_lo); + movups(ptr[scratch + 4 * sizeof(float)], xbase_hi); + } + } + mulps(xdst_lo, xdst_lo); + mulps(xdst_hi, xdst_hi); + mulps(xdst_lo, xbase_lo); + mulps(xdst_hi, xbase_hi); // xdst = (xsum*xalpha+xk)^3; + sqrtps(xdst_lo, xdst_lo); + sqrtps(xdst_hi, xdst_hi); + sqrtps(xdst_lo, xdst_lo); + sqrtps(xdst_hi, xdst_hi); // xdst = (xsum*xalpha+xk)^0.75 + movaps(xtmp_lo, ptr[store_addr + 6 * 4 * sizeof(float)]); + movaps(xtmp_hi, ptr[store_addr + 7 * 4 * sizeof(float)]); + divps(xtmp_lo, xdst_lo); + divps(xtmp_hi, xdst_hi); // xdst = xsrc / (xsum*xalpha+xk)^0.75 + movaps(xdst_lo, xtmp_lo); + movaps(xdst_hi, xtmp_hi); + + if (tail != 0) { + nchw_tail_sse42(tail, dst, xdst_lo, xdst_hi); + } + else { + movups(ptr[dst], xdst_lo); + movups(ptr[dst + 4 * sizeof(float)], xdst_hi); + } + + movaps(xa_lo, ptr[store_addr + 2 * 4 * sizeof(float)]); + movaps(xa_hi, ptr[store_addr + 3 * 4 * sizeof(float)]); + mulps(xa_lo, xa_lo); + mulps(xa_hi, xa_hi); + subps(xsum_lo, xa_lo); + subps(xsum_hi, xa_hi); + + // xa <- xb + movaps(xb_lo, ptr[store_addr + 4 * 4 * sizeof(float)]); + movaps(xb_hi, ptr[store_addr + 5 * 4 * sizeof(float)]); + movaps(ptr[store_addr + 2 * 4 * sizeof(float)], xb_lo); + movaps(ptr[store_addr + 3 * 4 * sizeof(float)], xb_hi); + + // xb <- xc + movaps(xc_lo, ptr[store_addr + 6 * 4 * sizeof(float)]); + movaps(xc_hi, ptr[store_addr + 7 * 4 * sizeof(float)]); + movaps(ptr[store_addr + 4 * 4 * sizeof(float)], xc_lo); + movaps(ptr[store_addr + 5 * 4 * sizeof(float)], xc_hi); + + // xc <- xd + movaps(xd_lo, ptr[store_addr + 8 * 4 * sizeof(float)]); + movaps(xd_hi, ptr[store_addr + 9 * 4 * sizeof(float)]); + movaps(ptr[store_addr + 6 * 4 * sizeof(float)], xd_lo); + movaps(ptr[store_addr + 7 * 4 * sizeof(float)], xd_hi); + + // xd <- xe + movaps(xe_lo, ptr[store_addr + 10 * 4 * sizeof(float)]); + movaps(xe_hi, ptr[store_addr + 11 * 4 * sizeof(float)]); + movaps(ptr[store_addr + 8 * 4 * sizeof(float)], xe_lo); + movaps(ptr[store_addr + 9 * 4 * sizeof(float)], xe_hi); +} + +template<> +void jit_uni_lrn_fwd_kernel_f32::nchw_body_sse42( + int tail, int HW, prop_kind_t pk, + Xbyak::Xmm xmask_lo, Xbyak::Xmm xmask_hi, + Xbyak::Xmm xe_lo, Xbyak::Xmm xe_hi, + Xbyak::Xmm xsum_lo, Xbyak::Xmm xsum_hi) {} + +template<> +jit_uni_lrn_fwd_kernel_f32::jit_uni_lrn_fwd_kernel_f32( + struct nchw_across J, + float A, + float K, + prop_kind_t pk, + void* code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , alpha(A), k(K) +{ + static const uint32_t mask[] = { + 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, + 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0 + }; + Xbyak::Reg64 c = r10; + Xbyak::Ymm ymask = ymm2; + Xbyak::Ymm ye = ymm3; + Xbyak::Ymm ya = ymm4; + Xbyak::Ymm yb = ymm5; + Xbyak::Ymm yc = ymm6; + Xbyak::Ymm yd = ymm7; + Xbyak::Ymm ysum = ymm8; + + this->preamble(); + + if (J.tail != 0) + { + mov(imm_addr64, reinterpret_cast(&mask[7 - J.tail])); + vmovups(ymask, ptr[imm_addr64]); + } + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + vbroadcastss(yalpha, xalpha); + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + vbroadcastss(yk, xk); + + mov(src, ptr[this->param1 + 0]); + mov(dst, ptr[this->param1 + 8]); + if (pk != prop_kind::forward_inference) + mov(scratch, ptr[this->param1 + 16]); + + vxorps(ya, ya, ya); + vxorps(yb, yb, yb); + if (J.tail != 0) + vmaskmovps(yc, ymask, ptr[src + J.HW * 0]); + else + vmovups(yc, ptr[src + J.HW * 0]); + if (J.tail != 0) + vmaskmovps(yd, ymask, ptr[src + J.HW * 4]); + else + vmovups(yd, ptr[src + J.HW * 4]); + + vxorps(ysum, ysum, ysum); + vfmadd231ps(ysum, yc, yc); // ysum <- ysum + ya^2+yb^2+yc^2+yd^2+ye^2 + vfmadd231ps(ysum, yd, yd); + + mov(c, J.C - 2); + Label lrn_loop; + L(lrn_loop); + + if (J.tail != 0) + vmaskmovps(ye, ymask, ptr[src + J.HW * 8]); + else + vmovups(ye, ptr[src + J.HW * 8]); + + nchw_body(J.tail, J.HW, pk, ymask, ya, yb, yc, yd, ye, ysum); + + add(src, J.HW * 4); + add(dst, J.HW * 4); + if (pk != prop_kind::forward_inference) + add(scratch, J.HW * 4); + dec(c); + cmp(c, 0); + jne(lrn_loop, T_NEAR); + + vxorps(ye, ye, ye); + + nchw_body(J.tail, J.HW, pk, ymask, ya, yb, yc, yd, ye, ysum); + add(src, J.HW * 4); + add(dst, J.HW * 4); + if (pk != prop_kind::forward_inference) + add(scratch, J.HW * 4); + + nchw_body(J.tail, J.HW, pk, ymask, ya, yb, yc, yd, ye, ysum); + + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +template<> +jit_uni_lrn_fwd_kernel_f32::jit_uni_lrn_fwd_kernel_f32( + struct nchw_across J, + float A, + float K, + prop_kind_t pk, + void* code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , alpha(A), k(K) +{ + static const uint32_t mask[] = { + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0, 0, 0, 0, 0, 0, 0 + }; + + Xbyak::Reg64 c = r10; + + Xbyak::Xmm xmask_lo = xmm2; + Xbyak::Xmm xmask_hi = xmm3; + Xbyak::Xmm xsum_lo = xmm4; + Xbyak::Xmm xsum_hi = xmm5; + Xbyak::Xmm xa_lo = xmm6; + Xbyak::Xmm xa_hi = xmm7; + Xbyak::Xmm xb_lo = xmm8; + Xbyak::Xmm xb_hi = xmm9; + Xbyak::Xmm xc_lo = xmm10; + Xbyak::Xmm xc_hi = xmm11; + Xbyak::Xmm xd_lo = xmm12; + Xbyak::Xmm xd_hi = xmm13; + Xbyak::Xmm xe_lo = xmm14; + Xbyak::Xmm xe_hi = xmm15; + + this->preamble(); + + mov(src, ptr[this->param1 + 0]); + mov(dst, ptr[this->param1 + 8]); + if (pk != prop_kind::forward_inference) + mov(scratch, ptr[this->param1 + 16]); + + sub(rsp, stack_space_needed); + mov(store_addr, rsp); + and_(store_addr, -15); + + mov(imm_addr64, float2int(this->alpha)); + movq(xalpha, imm_addr64); + shufps(xalpha, xalpha, 0); + + mov(imm_addr64, float2int(this->k)); + movq(xk, imm_addr64); + shufps(xk, xk, 0); + + // put alpha and k into store (free up regs) + movaps(ptr[store_addr + 0 * 4 * sizeof(float)], xalpha); + movaps(ptr[store_addr + 1 * 4 * sizeof(float)], xk); + + if (J.tail != 0) + { + mov(imm_addr64, reinterpret_cast(&mask[7 - J.tail])); + movups(xmask_lo, ptr[imm_addr64]); + movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]); + } + // init xa, xb + xorps(xa_lo, xa_lo); + xorps(xa_hi, xa_hi); + xorps(xb_lo, xb_lo); + xorps(xb_hi, xb_hi); + + // read xc, xd + if (J.tail != 0) { + movups(xc_lo, ptr[src + J.HW * 0]); + movups(xc_hi, ptr[src + J.HW * 0 + 4 * sizeof(float)]); + andps(xc_lo, xmask_lo); + andps(xc_hi, xmask_hi); + } + else { + movups(xc_lo, ptr[src + J.HW * 0]); + movups(xc_hi, ptr[src + J.HW * 0 + 4 * sizeof(float)]); + } + if (J.tail != 0) { + movups(xd_lo, ptr[src + J.HW * 4]); + movups(xd_hi, ptr[src + J.HW * 4 + 4 * sizeof(float)]); + andps(xd_lo, xmask_lo); + andps(xd_hi, xmask_hi); + } + else { + movups(xd_lo, ptr[src + J.HW * 4]); + movups(xd_hi, ptr[src + J.HW * 4 + 4 * sizeof(float)]); + } + + // put xa, xb, xc, xd into store to free-up regs + movaps(ptr[store_addr + 2 * 4 * sizeof(float)], xa_lo); + movaps(ptr[store_addr + 3 * 4 * sizeof(float)], xa_hi); + movaps(ptr[store_addr + 4 * 4 * sizeof(float)], xb_lo); + movaps(ptr[store_addr + 5 * 4 * sizeof(float)], xb_hi); + movaps(ptr[store_addr + 6 * 4 * sizeof(float)], xc_lo); + movaps(ptr[store_addr + 7 * 4 * sizeof(float)], xc_hi); + movaps(ptr[store_addr + 8 * 4 * sizeof(float)], xd_lo); + movaps(ptr[store_addr + 9 * 4 * sizeof(float)], xd_hi); + + xorps(xsum_lo, xsum_lo); + xorps(xsum_hi, xsum_hi); + mulps(xc_lo, xc_lo); + mulps(xc_hi, xc_hi); + addps(xsum_lo, xc_lo); + addps(xsum_hi, xc_hi); + mulps(xd_lo, xd_lo); + mulps(xd_hi, xd_hi); + addps(xsum_lo, xd_lo); + addps(xsum_hi, xd_hi); // xsum <- xsum + xa^2+xb^2+xc^2+xd^2+xe^2 + + mov(c, J.C - 2); + Label lrn_loop; + L(lrn_loop); + + if (J.tail != 0) { + movups(xe_lo, ptr[src + J.HW * 8]); + movups(xe_hi, ptr[src + J.HW * 8 + 4 * sizeof(float)]); + andps(xe_lo, xmask_lo); + andps(xe_hi, xmask_hi); + } + else { + movups(xe_lo, ptr[src + J.HW * 8]); + movups(xe_hi, ptr[src + J.HW * 8 + 4 * sizeof(float)]); + } + + nchw_body_sse42(J.tail, J.HW, pk, xmask_lo, xmask_hi, + xe_lo, xe_hi, + xsum_lo, xsum_hi); + + add(src, J.HW * 4); + add(dst, J.HW * 4); + if (pk != prop_kind::forward_inference) + add(scratch, J.HW * 4); + dec(c); + cmp(c, 0); + jne(lrn_loop, T_NEAR); + + xorps(xe_lo, xe_lo); + xorps(xe_hi, xe_hi); + + nchw_body_sse42(J.tail, J.HW, pk, xmask_lo, xmask_hi, + xe_lo, xe_hi, + xsum_lo, xsum_hi); + add(src, J.HW * 4); + add(dst, J.HW * 4); + if (pk != prop_kind::forward_inference) + add(scratch, J.HW * 4); + + nchw_body_sse42(J.tail, J.HW, pk, xmask_lo, xmask_hi, + xe_lo, xe_hi, + xsum_lo, xsum_hi); + + add(rsp, stack_space_needed); + + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +////////////////////////////////////////////////////////////////////////////// +// backward kernel +template +jit_uni_lrn_bwd_kernel_f32::jit_uni_lrn_bwd_kernel_f32( + const struct nchw8c_across &J, + float A, + float B, + int use_h_parallel, + void *code_ptr, + size_t code_size) + : jit_generator(code_ptr, code_size) + , nalphabeta(-2 * A*B) + , use_h_parallelizm(use_h_parallel) +{ + Xbyak::Reg64 t = rsp; + Xbyak::Reg64 hw = r10; + + Xbyak::Xmm xsrc_prev = xmm1; + Xbyak::Xmm xws_prev = xmm2; + Xbyak::Xmm xdiffdst_prev = xmm3; + Xbyak::Ymm ysrc = ymm4; + Xbyak::Ymm yws = ymm5; + Xbyak::Ymm ydiffdst = ymm6; + Xbyak::Xmm xsrc_next = xmm7; + Xbyak::Xmm xws_next = xmm8; + Xbyak::Xmm xdiffdst_next = xmm9; + Xbyak::Ymm ya = ymm10; + Xbyak::Xmm xa = xmm10; + Xbyak::Ymm yb = ymm11; + Xbyak::Ymm yd = ymm12; + Xbyak::Ymm ye = ymm13; + Xbyak::Ymm ysum = ymm14; + Xbyak::Ymm ydiffsrc = ymm15; + + this->preamble(); + + mov(src, ptr[this->param1 + 0]); + mov(diffdst, ptr[this->param1 + 8]); + mov(workspace, ptr[this->param1 + 16]); + mov(diffsrc, ptr[this->param1 + 24]); + + sub(t, 64); + mov(imm_addr64, float2int(this->nalphabeta)); + movq(xnalphabeta, imm_addr64); + vbroadcastss(ynalphabeta, xnalphabeta); + + bool is_single = J.version == 3; + bool is_first = J.version == -1 || J.version == -2; + bool is_last = J.version == +1 || J.version == -2; + + if (is_first || is_single) { + vxorps(xsrc_prev, xsrc_prev, xsrc_prev); + vmovups(ptr[t + 0], xsrc_prev); + } + if (is_last || is_single) { + vxorps(xsrc_next, xsrc_next, xsrc_next); + vmovups(ptr[t + 48], xsrc_next); + } + mov(hw, this->use_h_parallelizm ? J.W : J.H*J.W); + Label lrn_loop; + L(lrn_loop); + { + if (!is_first && !is_single) { + vmovups(xws_prev, ptr[workspace - J.H*J.W * 32 + 16]); + vmovups(xsrc_prev, ptr[src - J.H*J.W * 32 + 16]); + vmovups(xdiffdst_prev, ptr[diffdst - J.H*J.W * 32 + 16]); + vmulps(xa, xws_prev, xws_prev); + vmulps(xa, xa, xws_prev); + vsqrtps(xa, xa); + vsqrtps(xa, xa); + vmulps(xa, xa, xws_prev); + vdivps(xsrc_prev, xsrc_prev, xa); + vmulps(xdiffdst_prev, xdiffdst_prev, xsrc_prev); + } + + vmovups(ysrc, ptr[src]); + vmovups(yws, ptr[workspace]); + vmovups(ydiffdst, ptr[diffdst]); + vmulps(ya, yws, yws); + vmulps(ya, ya, yws); + vsqrtps(ya, ya); + vsqrtps(ya, ya); + vdivps(ydiffsrc, ydiffdst, ya); + vdivps(ysum, ydiffsrc, yws); + vmulps(ysum, ysum, ysrc); + + if (!is_last && !is_single) { + vmovups(xws_next, ptr[workspace + J.H*J.W * 32]); + vmovups(xsrc_next, ptr[src + J.H*J.W * 32]); + vmovups(xdiffdst_next, ptr[diffdst + J.H*J.W * 32]); + vmulps(xa, xws_next, xws_next); + vmulps(xa, xa, xws_next); + vsqrtps(xa, xa); + vsqrtps(xa, xa); + vmulps(xa, xa, xws_next); + vdivps(xsrc_next, xsrc_next, xa); + vdivps(xsrc_next, xsrc_next, xws_next); + vmulps(xdiffdst_next, xdiffdst_next, xsrc_next); + } + + if (!is_first && !is_single) vmovups(ptr[t + 0], xdiffdst_prev); + vmovups(ptr[t + 16], ysum); + if (!is_last && !is_single) vmovups(ptr[t + 48], xdiffdst_next); + + vmovups(ya, ptr[t + 16 - 8]); + vmovups(yb, ptr[t + 16 - 4]); + vaddps(ysum, ysum, ya); + vmulps(ysrc, ysrc, ynalphabeta); + vaddps(ysum, ysum, yb); + + vmovups(yd, ptr[t + 16 + 4]); + vmovups(ye, ptr[t + 16 + 8]); + vaddps(ysum, ysum, yd); + vaddps(ysum, ysum, ye); + + vfmadd231ps(ydiffsrc, ysum, ysrc); + + vmovups(ptr[diffsrc], ydiffsrc); + + add(src, 32); + add(diffsrc, 32); + add(diffdst, 32); + add(workspace, 32); + + dec(hw); + cmp(hw, 0); + jne(lrn_loop, T_NEAR); + } + + add(t, 64); + this->postamble(); + + ker = reinterpret_cast(const_cast( + this->getCode())); +} + +template struct jit_uni_lrn_fwd_kernel_f32; +template struct jit_uni_lrn_fwd_kernel_f32; +template struct jit_uni_lrn_bwd_kernel_f32; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp new file mode 100644 index 0000000000..2b3ed43cd4 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp @@ -0,0 +1,183 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_UNI_LRN_KERNEL_F32_HPP +#define CPU_JIT_UNI_LRN_KERNEL_F32_HPP + +#include "c_types_map.hpp" +#include "type_helpers.hpp" + +#include "jit_generator.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; + +enum params { VECTOR_LENGTH = 8, MAX_LOCAL_SIZE = 32 }; + +typedef struct { + const float *src; + float *dst, *scratch; +} jit_args_fwd_t; + +typedef struct { + const float *src, *diff_dst, *scratch; + float *diff_src; +} jit_args_bwd_t; + +struct nchw8c_across { + /* version: + * -1: channels 0..7, + * 1: channels C-8 .. C-1, + * 0: other channels + * 3: channels only for this kernel(without prev and next) + */ + int H, W, version; + nchw8c_across(int h, int w, int v) : H(h), W(w), version(v) {} +}; + +struct nchw8c_within { + int H, W, size; + nchw8c_within(int h, int w, int s) : H(h), W(w), size(s) {} +}; + +struct nchw_across { + int C, HW, tail; + nchw_across(int c, int hw, int t) : C(c), HW(hw), tail(t) {} +}; + +struct nhwc_across { + int C; + nhwc_across(int c) : C(c) {} +}; + +template +struct jit_uni_lrn_fwd_kernel_f32 : public jit_generator { + Xbyak::Reg64 src = rax; + Xbyak::Reg64 dst = r8; + Xbyak::Reg64 scratch = rdx; + Xbyak::Reg64 imm_addr64 = rbx; + Xbyak::Reg64 store_addr = rbp; + + Xbyak::Xmm xalpha = xmm0; + Xbyak::Ymm yalpha = ymm0; + Xbyak::Xmm xk = xmm1; + Xbyak::Ymm yk = ymm1; + + float alpha; + float k; + + int stack_space_needed = 11 * 4 * sizeof(float) + 16; + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_lrn_fwd_kernel_f32) + + /* cpu specific part */ + using Vmm = typename utils::conditional::type; + + jit_uni_lrn_fwd_kernel_f32( + const struct nchw8c_within &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr = nullptr, + size_t code_size = 4 * Xbyak::DEFAULT_MAX_CODE_SIZE); + jit_uni_lrn_fwd_kernel_f32( + const struct nchw8c_across &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr = nullptr, + size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE); + jit_uni_lrn_fwd_kernel_f32( + const struct nhwc_across &J, + float A, + float K, + prop_kind_t pk, + void *code_ptr = nullptr, + size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE); + jit_uni_lrn_fwd_kernel_f32( + struct nchw_across J, + float A, + float K, + prop_kind_t pk, + void* code_ptr = nullptr, + size_t code_size = 2 * Xbyak::DEFAULT_MAX_CODE_SIZE); + + void within_body( + int hoff, int Hoff, int woff, int Woff, int stride, + Xbyak::Ymm ysum, Xbyak::Ymm ydst, Xbyak::Ymm ytmp, Xbyak::Ymm ysum2, + prop_kind_t pk); + void within_body_sse42( + int hoff, int Hoff, int woff, int Woff, int stride, prop_kind_t pk); + + + void nchw_body(int tail, int HW, prop_kind_t pk, + Xbyak::Ymm ymask, + Xbyak::Ymm ya, + Xbyak::Ymm yb, + Xbyak::Ymm yc, + Xbyak::Ymm yd, + Xbyak::Ymm ye, + Xbyak::Ymm ysum); + void nchw_body_sse42(int tail, int HW, prop_kind_t pk, + Xbyak::Xmm xmask_lo, Xbyak::Xmm xmask_hi, + Xbyak::Xmm xe_lo, Xbyak::Xmm xe_hi, + Xbyak::Xmm xsum_lo, Xbyak::Xmm xsum_hi); + void nchw_tail_sse42(int tail, Xbyak::Reg64 reg_dst, + Xbyak::Xmm xtail_lo, Xbyak::Xmm xtail_hi); + + void operator()(jit_args_fwd_t *arg) { ker(arg); } + void(*ker)(jit_args_fwd_t *); +}; + +template +struct jit_uni_lrn_bwd_kernel_f32 : public jit_generator { + Xbyak::Reg64 src = rax; + Xbyak::Reg64 diffsrc = r8; + Xbyak::Reg64 diffdst = r9; + Xbyak::Reg64 workspace = rdx; + Xbyak::Reg64 imm_addr64 = rsi; + + Xbyak::Xmm xnalphabeta = xmm0; + Xbyak::Ymm ynalphabeta = ymm0; + + float nalphabeta; + + int use_h_parallelizm; + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_lrn_bwd_kernel_f32) + + jit_uni_lrn_bwd_kernel_f32( + const struct nchw8c_across &J, + float A, + float B, + int use_h_parallel, + void *code_ptr = nullptr, + size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE); + + void operator()(jit_args_bwd_t *arg) { ker(arg); } + void(*ker)(jit_args_bwd_t *); +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp new file mode 100644 index 0000000000..bf8e609d23 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp @@ -0,0 +1,699 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* Copyright 2018 YANDEX LLC +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "utils.hpp" +#include "cpu_pooling_pd.hpp" + +#include "jit_uni_pool_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; +using namespace alg_kind; + +#define GET_OFF(field) offsetof(jit_pool_call_s, field) + +template +status_t jit_uni_pool_kernel_f32::init_conf(jit_pool_conf_t &jpp, + const pooling_pd_t *ppd) { + const auto &pd = *ppd->desc(); + const memory_desc_wrapper src_d( + ppd->is_fwd() ? ppd->src_md() : ppd->diff_src_md()); + const memory_desc_wrapper dst_d( + ppd->is_fwd() ? ppd->dst_md() : ppd->diff_dst_md()); + + bool args_ok = true + && mayiuse(isa) + && utils::one_of(pd.alg_kind, pooling_max, + pooling_avg_include_padding, + pooling_avg_exclude_padding); + if (!args_ok) return status::unimplemented; + + const int simd_w = isa == avx512_common ? 16 : 8; + const int ndims = src_d.ndims(); + + jpp.ndims = ndims; + jpp.mb = src_d.dims()[0]; + + jpp.c = utils::rnd_up(src_d.dims()[1], simd_w); + if (jpp.c > src_d.padded_dims()[1]) + return status::unimplemented; + + jpp.id = (ndims == 5) ? src_d.dims()[2] : 1; + jpp.ih = src_d.dims()[ndims-2]; + jpp.iw = src_d.dims()[ndims-1]; + jpp.od = (ndims == 5) ? dst_d.dims()[2] : 1; + jpp.oh = dst_d.dims()[ndims-2]; + jpp.ow = dst_d.dims()[ndims-1]; + + jpp.stride_d = (ndims == 5 ) ? pd.strides[0] : 1; + jpp.stride_h = pd.strides[ndims-4]; + jpp.stride_w = pd.strides[ndims-3]; + jpp.kd = (ndims == 5) ? pd.kernel[0] : 1; + jpp.kh = pd.kernel[ndims-4]; + jpp.kw = pd.kernel[ndims-3]; + + jpp.f_pad = (ndims == 5 ) ? pd.padding[0][0] : 0; + jpp.t_pad = pd.padding[0][ndims-4]; + jpp.l_pad = pd.padding[0][ndims-3]; + + jpp.alg = pd.alg_kind; + + jpp.is_training = pd.prop_kind == prop_kind::forward_training; + jpp.is_backward = pd.prop_kind == prop_kind::backward_data; + jpp.ind_dt = ppd->workspace_md() + ? ppd->workspace_md()->data_type : data_type::undef; + + jpp.simple_alg = jpp.is_training + || IMPLICATION(jpp.is_backward, jpp.kd <= jpp.stride_d); + + jpp.c_block = simd_w; + + jpp.nb_c = jpp.c / jpp.c_block; + if (jpp.alg == pooling_max) { + jpp.ur_w = isa == avx512_common ? 16 : 4; + if (jpp.is_training) + jpp.ur_w = isa == avx512_common ? 9 : 3; + else if (jpp.is_backward) + jpp.ur_w = isa == avx512_common ? 6 : 3; + } else { + if (jpp.is_backward) + jpp.ur_w = isa == avx512_common ? 12 : 6; + else + jpp.ur_w = isa == avx512_common ? 24 : 12; + } + if (jpp.ow < jpp.ur_w) jpp.ur_w = jpp.ow; + if (jpp.l_pad > jpp.ur_w) return status::unimplemented; + + jpp.ur_w_tail = jpp.ow % jpp.ur_w; + + return status::success; +} + +template +inline void jit_uni_pool_kernel_f32::maybe_recalculate_divisor(int jj, + int ur_w, int pad_l, int pad_r) { + if (jpp.alg == pooling_avg_exclude_padding) { + int kw = jpp.kw; + int stride_w = jpp.stride_w; + + int non_zero_kw = kw; + non_zero_kw -= nstl::max(0, pad_l - jj*stride_w); + non_zero_kw -= nstl::max(0, pad_r - (ur_w - 1 - jj)*stride_w); + + if (non_zero_kw != prev_kw) { + mov(tmp_gpr, float2int((float)non_zero_kw)); + movq(xmm_tmp, tmp_gpr); + uni_vbroadcastss(vmm_tmp, xmm_tmp); + uni_vmulps(vmm_tmp, vmm_tmp, vmm_ker_area_h); + prev_kw = non_zero_kw; + } + } +} + +template +inline void jit_uni_pool_kernel_f32::avg_step(int ur_w, int pad_l, + int pad_r) { + + int iw = jpp.iw; + int kw = jpp.kw; + int stride_w = jpp.stride_w; + int c_block = jpp.c_block; + Label kd_label, kh_label; + + for (int jj = 0; jj < ur_w; jj++) { + if (jpp.is_backward) { + uni_vmovups(vreg(jj), ptr[reg_output + sizeof(float)*jj*c_block]); + maybe_recalculate_divisor(jj, ur_w, pad_l, pad_r); + uni_vdivps(vreg(jj), vreg(jj), vmm_tmp); + } else { + uni_vpxor(vreg(jj), vreg(jj), vreg(jj)); + } + } + + if (jpp.simple_alg && jpp.ndims == 5) { + push(reg_input); + push(reg_output); + mov(aux_reg_input_d, reg_input); + mov(ki, ptr[reg_param + GET_OFF(kd_padding)]); + L(kd_label); + mov(aux_reg_input, aux_reg_input_d); + } else { + mov(aux_reg_input, reg_input); + } + + xor_(kj, kj); + L(kh_label); + { + for (int ki = 0; ki < kw; ki++) { + int jj_start = nstl::max(0, pad_l - ki); + int jj_end = ur_w + - utils::div_up(nstl::max(0, ki + pad_r - (kw-1)), stride_w); + for (int jj = jj_start; jj < jj_end; jj++) { + int aux_input_offset = (ki+jj*stride_w-pad_l)* c_block; + if (aux_input_offset > iw * c_block) + continue; + int input_offset = sizeof(float)*aux_input_offset; + if (jpp.is_backward) { + uni_vmovups(vreg(ur_w+jj), + ptr[aux_reg_input + input_offset]); + uni_vaddps(vreg(ur_w+jj), vreg(ur_w+jj), vreg(jj)); + uni_vmovups(vmmword[aux_reg_input + input_offset], + vreg(ur_w+jj)); + } else { + uni_vaddps(vreg(jj), vreg(jj), + ptr[aux_reg_input + input_offset]); + } + } + } + add(aux_reg_input, sizeof(float) * iw * c_block); + inc(kj); + cmp(kj, reg_kh); + jl(kh_label, T_NEAR); + } + + if (jpp.simple_alg && jpp.ndims == 5) + { + add(aux_reg_input_d, sizeof(float) * jpp.ih * iw * c_block); + dec(ki); + cmp(ki, 0); + jg(kd_label, T_NEAR); + pop(reg_output); + pop(reg_input); + } + + if (!jpp.is_backward) { + for (int jj = 0; jj < ur_w; jj++) { + maybe_recalculate_divisor(jj, ur_w, pad_l, pad_r); + uni_vdivps(vreg(jj), vreg(jj), vmm_tmp); + uni_vmovups(vmmword[reg_output + sizeof(float)*jj*c_block], + vreg(jj)); + } + } +} + +template +inline void jit_uni_pool_kernel_f32::max_step_fwd(int ur_w, int pad_l, + int pad_r) { + int iw = jpp.iw; + int kw = jpp.kw; + int stride_w = jpp.stride_w; + int c_block = jpp.c_block; + Label kd_label, kh_label; + + mov(tmp_gpr, float2int(nstl::numeric_limits::lowest())); + movq(xmm_tmp, tmp_gpr); + uni_vbroadcastss(vmm_tmp, xmm_tmp); + + for (int jj = 0; jj < ur_w; jj++) { + uni_vmovups(vreg(jj), vmm_tmp); + if (jpp.is_training) + uni_vpxor(vreg(2*ur_w+jj), vreg(2*ur_w+jj), vreg(2*ur_w+jj)); + } + if (jpp.is_training) + { + movq(xmm_tmp, reg_k_shift); + uni_vpbroadcastd(vmm_k_offset, xmm_tmp); + } + + if (jpp.ndims == 5) { + push(reg_input); + push(reg_output); + mov(aux_reg_input_d, reg_input); + mov(ki, ptr[reg_param + GET_OFF(kd_padding)]); + L(kd_label); + mov(aux_reg_input, aux_reg_input_d); + } else { + mov(aux_reg_input, reg_input); + } + xor_(kj, kj); + L(kh_label); + { + for (int ki = 0; ki < kw; ki++) { + int jj_start = nstl::max(0, pad_l - ki); + int jj_end = ur_w + - utils::div_up(nstl::max(0, ki + pad_r - (kw-1)), stride_w); + for (int jj = jj_start; jj < jj_end; jj++) { + int aux_input_offset = (ki+jj*stride_w-pad_l)* c_block; + if (aux_input_offset > iw * c_block) + continue; + int input_offset = sizeof(float)*aux_input_offset; + uni_vmovups(vreg(ur_w+jj), ptr[aux_reg_input + input_offset]); + if (isa == sse42) { + movups(vmm_mask, vreg(jj)); + cmpps(vmm_mask, vreg(ur_w+jj), _cmp_lt_os); + blendvps(vreg(jj), vreg(ur_w+jj)); + if (jpp.is_training) + blendvps(vreg(2*ur_w+jj), vmm_k_offset); + } else if (isa == avx) { + vcmpps(vreg(3*ur_w+jj), vreg(jj), vreg(ur_w+jj), + _cmp_lt_os); + vblendvps(vreg(jj), vreg(jj), vreg(ur_w+jj), + vreg(3*ur_w+jj)); + if (jpp.is_training) + vblendvps(vreg(2*ur_w+jj), vreg(2*ur_w+jj), + vmm_k_offset, vreg(3*ur_w+jj)); + } else { + vcmpps(k_store_mask, vreg(jj), vreg(ur_w+jj), _cmp_lt_os); + vblendmps(vreg(jj) | k_store_mask, vreg(jj), vreg(ur_w+jj)); + if (jpp.is_training) + vblendmps(vreg(2*ur_w+jj) | k_store_mask, + vreg(2*ur_w+jj), vmm_k_offset); + } + } + if (jpp.is_training) { + if (isa == avx && !mayiuse(avx2)) { + avx_vpadd1(vmm_k_offset, vmm_one, xmm_tmp); + } else { + uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_one); + } + } + } + add(aux_reg_input, sizeof(float) * iw * c_block); + inc(kj); + cmp(kj, reg_kh); + jl(kh_label, T_NEAR); + } + + if (jpp.ndims == 5) + { + add(aux_reg_input_d, sizeof(float) * jpp.ih * iw * c_block); + if (jpp.is_training) { + mov(tmp_gpr, ptr[reg_param + GET_OFF(kd_padding_shift)]); + movq(xmm_tmp, tmp_gpr); + uni_vpbroadcastd(vmm_tmp, xmm_tmp); + if (isa == avx && !mayiuse(avx2)) { + Xmm t(vmm_mask.getIdx()); + avx_vpadd1(vmm_k_offset, xmm_tmp, t); + } else { + uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_tmp); + } + } + + dec(ki); + cmp(ki, 0); + jg(kd_label, T_NEAR); + pop(reg_output); + pop(reg_input); + } + + for (int jj = 0; jj < ur_w; jj++) { + uni_vmovups(vmmword[reg_output + sizeof(float)*jj*c_block], vreg(jj)); + if (jpp.is_training) { + const size_t step_index + = jj * c_block * types::data_type_size(jpp.ind_dt); + + auto x = xreg(2 * ur_w + jj); + if (jpp.ind_dt == data_type::u8) { + if (isa == sse42) { + for (int i = 0; i < 4; ++i) + pextrb(ptr[reg_index + step_index + i], x, 4*i); + } else if (isa == avx) { + auto y = yreg(2 * ur_w + jj); + if (jj == 0) { + movd(xmm_tmp, reg_shuf_mask); + uni_vpbroadcastd(vmm_tmp, xmm_tmp); + } + if (mayiuse(avx2)) { + vpshufb(y, y, vmm_tmp); + movd(ptr[reg_index + step_index], x); + vperm2i128(y, y, y, 0x1u); + movd(ptr[reg_index + step_index + 4], x); + } else { + Xmm t(vmm_mask.getIdx()); + vextractf128(t, y, 0); + vpshufb(t, t, xmm_tmp); + movd(ptr[reg_index + step_index], t); + vextractf128(t, y, 1); + vpshufb(t, t, xmm_tmp); // ymm_tmp[:128]==ymm_tmp[127:0] + movd(ptr[reg_index + step_index + 4], t); + } + } else { + auto v = vreg(2 * ur_w + jj); + vpmovusdb(x, v); + vmovups(ptr[reg_index + step_index], v | k_index_mask); + } + } else { + uni_vmovups(ptr[reg_index + step_index], vreg(2*ur_w+jj)); + } + } + } +} + +template +inline void jit_uni_pool_kernel_f32::max_step_bwd(int ur_w, int pad_l, + int pad_r) { + + int iw = jpp.iw; + int kw = jpp.kw; + int stride_w = jpp.stride_w; + int c_block = jpp.c_block; + Label kd_label, kh_label; + + for (int jj = 0; jj < ur_w; jj++) { + uni_vmovups(vreg(jj), ptr[reg_output + sizeof(float)*jj*c_block]); + + const size_t step_index + = jj * c_block * types::data_type_size(jpp.ind_dt); + if (jpp.ind_dt == data_type::u8) { + if (isa == sse42) { + movd(xreg(ur_w+jj), ptr[reg_index + step_index]); + pmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj)); + } else if (isa == avx) { + movq(xreg(ur_w+jj), ptr[reg_index + step_index]); + if (!mayiuse(avx2)) { + avx_pmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj), xmm_tmp); + } else { + vpmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj)); + } + } else { + vmovups(vreg(ur_w+jj) | k_index_mask, + ptr[reg_index + step_index]); + vpmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj)); + } + } else { + uni_vmovups(vreg(ur_w+jj), ptr[reg_index + step_index]); + } + } + movq(xmm_tmp, reg_k_shift); + uni_vpbroadcastd(vmm_k_offset, xmm_tmp); + + if (jpp.simple_alg && jpp.ndims == 5) { + push(reg_input); + push(reg_output); + if (isa == sse42) { + // Save rdi since it is used in maskmovdqu + assert(dst_ptr == rdi); + push(dst_ptr); + } + mov(aux_reg_input_d, reg_input); + mov(ki, ptr[reg_param + GET_OFF(kd_padding)]); + mov(reg_kd_pad_shift, ptr[reg_param + GET_OFF(kd_padding_shift)]); + L(kd_label); + mov(aux_reg_input, aux_reg_input_d); + } else { + mov(aux_reg_input, reg_input); + } + + xor_(kj, kj); + L(kh_label); + { + for (int ki = 0; ki < kw; ki++) { + int jj_start = nstl::max(0, pad_l - ki); + int jj_end = ur_w + - utils::div_up(nstl::max(0, ki + pad_r - (kw-1)), stride_w); + for (int jj = jj_start; jj < jj_end; jj++) { + int aux_input_offset = (ki+jj*stride_w-pad_l)* c_block; + if (aux_input_offset > iw * c_block) + continue; + int input_offset = sizeof(float)*aux_input_offset; + uni_vmovups(vreg(2*ur_w+jj), ptr[aux_reg_input + input_offset]); + if (isa == sse42) { + mov(dst_ptr, aux_reg_input); + add(dst_ptr, input_offset); + + movups(vreg(3*ur_w+jj), vreg(ur_w+jj)); + pcmpeqd(vreg(3*ur_w+jj), vmm_k_offset); + addps(vreg(2*ur_w+jj), vreg(jj)); + maskmovdqu(vreg(2*ur_w+jj), vreg(3*ur_w+jj)); + } else if (isa == avx) { + if (mayiuse(avx2)) { + vpcmpeqd(vreg(3*ur_w+jj), vreg(ur_w+jj), vmm_k_offset); + } else { + avx_pcmpeqd(vreg(3*ur_w+jj), vreg(ur_w+jj), vmm_k_offset, xmm_tmp); + } + vaddps(vreg(2*ur_w+jj), vreg(2*ur_w+jj), vreg(jj)); + vmaskmovps(vmmword[aux_reg_input + input_offset], + vreg(3*ur_w+jj), vreg(2*ur_w+jj)); + } else { + vpcmpeqd(k_store_mask, vreg(ur_w+jj), vmm_k_offset); + vblendmps(vmm_tmp | k_store_mask | T_z, vreg(jj), vreg(jj)); + vaddps(vreg(2*ur_w+jj), vreg(2*ur_w+jj), vmm_tmp); + vmovups(vmmword[aux_reg_input + + sizeof(float)*aux_input_offset], vreg(2*ur_w+jj)); + } + } + if (isa == avx && !mayiuse(avx2)) { + avx_vpadd1(vmm_k_offset, vmm_one, xmm_tmp); + } else { + uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_one); + } + } + add(aux_reg_input, sizeof(float) * iw * c_block); + inc(kj); + cmp(kj, reg_kh); + jl(kh_label, T_NEAR); + } + if (jpp.simple_alg && jpp.ndims == 5) + { + add(aux_reg_input_d, sizeof(float) * jpp.ih * iw * c_block); + + mov(tmp_gpr, reg_kd_pad_shift); + movq(xmm_tmp, tmp_gpr); + uni_vpbroadcastd(vmm_tmp, xmm_tmp); + if (isa == avx && !mayiuse(avx2)) { + Xmm t(vmm_mask.getIdx()); + avx_vpadd1(vmm_k_offset, vmm_tmp, t); + } else { + uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_tmp); + } + + dec(ki); + cmp(ki, 0); + jg(kd_label, T_NEAR); + if (isa == sse42) { + // Save rdi since it is used in maskmovdqu + assert(dst_ptr == rdi); + pop(dst_ptr); + } + pop(reg_output); + pop(reg_input); + } +} + +template +void jit_uni_pool_kernel_f32::maybe_zero_diff_src() { + assert(jpp.c_block * sizeof(float) % cpu_isa_traits::vlen == 0); + Label l_skip, l_zero; + + auto reg_oh = tmp_gpr; + mov(reg_oh, ptr[reg_param + GET_OFF(oh)]); + cmp(reg_oh, 0); + jz(l_skip, T_NEAR); + + if (jpp.ndims == 5) { + mov(zero_size, ptr[reg_param + GET_OFF(oh)]); + mov(tmp_gpr, jpp.ih * jpp.iw * jpp.c_block * sizeof(float)); + imul(zero_size, tmp_gpr); + } + + auto vzero = vmm_tmp; + uni_vpxor(vzero, vzero, vzero); + + auto reg_off = tmp_gpr; + xor_(reg_off, reg_off); + + L(l_zero); + { + const int dim = jpp.iw * jpp.c_block * sizeof(float); + for (int i = 0; i < dim; i += cpu_isa_traits::vlen) + uni_vmovups(ptr[reg_input + reg_off + i], vzero); + add(reg_off, dim); + if (jpp.ndims == 5) cmp(reg_off, zero_size); + else cmp(reg_off, jpp.ih * dim); + jl(l_zero, T_NEAR); + } + + L(l_skip); +} + +template +void jit_uni_pool_kernel_f32::generate() { + + this->preamble(); + + int ow = jpp.ow; + int iw = jpp.iw; + int kw = jpp.kw; + int kh = jpp.kh; + int ur_w = jpp.ur_w; + int c_block = jpp.c_block; + int stride_w = jpp.stride_w; + int l_pad = jpp.l_pad; + int ur_w_tail = jpp.ur_w_tail; + + int n_oi = ow / ur_w; + + prev_kw = 0; + + int vlen = cpu_isa_traits::vlen; + +#if defined(_WIN32) + // Always mimic the Unix ABI (see the note about maskmovdqu in the header + // file). + xor_(rdi, rcx); + xor_(rcx, rdi); + xor_(rdi, rcx); +#endif + + mov(reg_input, ptr[reg_param + GET_OFF(src)]); + mov(reg_output, ptr[reg_param + GET_OFF(dst)]); + if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward)) + mov(reg_index, ptr[reg_param + GET_OFF(indices)]); + mov(reg_kh, ptr[reg_param + GET_OFF(kh_padding)]); + mov(reg_k_shift, ptr[reg_param + GET_OFF(kh_padding_shift)]); + mov(reg_ker_area_h, ptr[reg_param + GET_OFF(ker_area_h)]); + + if (jpp.is_backward) + maybe_zero_diff_src(); + + if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward)) { + mov(tmp_gpr, 1); + movq(xmm_one, tmp_gpr); + uni_vpbroadcastd(vmm_one, xmm_one); + + if (isa == avx) { + mov(reg_shuf_mask, 0x0c080400); + } else if (isa >= avx512_common) { + mov(tmp_gpr.cvt32(), 0x000f); + kmovw(k_index_mask, tmp_gpr.cvt32()); + } + } + + int r_pad = nstl::max(0, ((ow-1)*stride_w) + kw - 1 - (iw + l_pad - 1)); + int r_pad1 = (ur_w*n_oi - 1)*stride_w + kw - 1 - (iw + l_pad - 1); + if (r_pad1 > 0) n_oi--; + + if (jpp.alg == pooling_avg_exclude_padding) { + movq(xmm_ker_area_h, reg_ker_area_h); + uni_vpbroadcastd(vmm_ker_area_h, xmm_ker_area_h); + } + + if (jpp.alg == pooling_avg_include_padding) { + mov(tmp_gpr, float2int((float)(kw * kh * jpp.kd))); + movq(xmm_tmp, tmp_gpr); + uni_vpbroadcastd(vmm_tmp, xmm_tmp); + } + if (l_pad > 0) { + n_oi--; + if (n_oi < 0 && r_pad1 > 0) { + step(ur_w, l_pad, r_pad1); + } else { + step(ur_w, l_pad, 0); + } + + if (isa == sse42) { + if (n_oi < 0 && r_pad1 > 0) { + step_high_half(ur_w, l_pad, r_pad1); + } else { + step_high_half(ur_w, l_pad, 0); + } + } + + if (isa == sse42) { + add(reg_input, sizeof(float)*(ur_w*stride_w-l_pad)*c_block - vlen); + add(reg_output, sizeof(float)*ur_w*c_block - vlen); + if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward)) + add(reg_index, (2 * ur_w - 1) * c_block / 2 + * types::data_type_size(jpp.ind_dt)); + } else { + add(reg_input, sizeof(float)*(ur_w*stride_w - l_pad)*c_block); + add(reg_output, sizeof(float)*ur_w*c_block); + if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward)) + add(reg_index, ur_w * c_block + * types::data_type_size(jpp.ind_dt)); + } + } + + xor_(oi_iter, oi_iter); + if (n_oi > 0) { + Label ow_loop; + L(ow_loop); { + step(ur_w, 0, 0); + + if (isa == sse42) { + step_high_half(ur_w, 0, 0); + } + + if (isa == sse42) { + add(reg_input, sizeof(float)*ur_w*stride_w*c_block - vlen); + add(reg_output, sizeof(float)*ur_w*c_block - vlen); + if (jpp.alg == pooling_max && + (jpp.is_training || jpp.is_backward)) + add(reg_index, (2 * ur_w - 1) * c_block / 2 + * types::data_type_size(jpp.ind_dt)); + } else { + add(reg_input, sizeof(float)*ur_w*stride_w*c_block); + add(reg_output, sizeof(float)*ur_w*c_block); + if (jpp.alg == pooling_max && + (jpp.is_training || jpp.is_backward)) + add(reg_index, ur_w * c_block + * types::data_type_size(jpp.ind_dt)); + } + + inc(oi_iter); + cmp(oi_iter, n_oi); + jl(ow_loop, T_NEAR); + } + } + + if (r_pad1 > 0 && n_oi >= 0) { + step(ur_w, 0, r_pad1); + + if (isa == sse42) { + step_high_half(ur_w, 0, r_pad1); + } + + if (isa == sse42) { + add(reg_input, sizeof(float)*ur_w*stride_w*c_block - vlen); + add(reg_output, sizeof(float)*ur_w*c_block - vlen); + if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward)) + add(reg_index, (2 * ur_w - 1) * c_block / 2 + * types::data_type_size(jpp.ind_dt)); + } else { + add(reg_input, sizeof(float)*ur_w*stride_w*c_block); + add(reg_output, sizeof(float)*ur_w*c_block); + if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward)) + add(reg_index, ur_w * c_block + * types::data_type_size(jpp.ind_dt)); + } + } + + if (ur_w_tail != 0) { + step(ur_w_tail, 0, r_pad); + + if (isa == sse42) { + step_high_half(ur_w_tail, 0, r_pad); + } + } + + this->postamble(); +} + +template struct jit_uni_pool_kernel_f32; +template struct jit_uni_pool_kernel_f32; // implements both and +template struct jit_uni_pool_kernel_f32; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp new file mode 100644 index 0000000000..992b526587 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp @@ -0,0 +1,192 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* Copyright 2018 YANDEX LLC +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_UNI_POOL_KERNEL_F32_HPP +#define JIT_UNI_POOL_KERNEL_F32_HPP + +#include + +#include "c_types_map.hpp" +#include "pooling_pd.hpp" +#include "type_helpers.hpp" + +#include "jit_generator.hpp" +#include "jit_primitive_conf.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace Xbyak; + +template +struct jit_uni_pool_kernel_f32: public jit_generator { + jit_uni_pool_kernel_f32(jit_pool_conf_t ajpp): jpp(ajpp) + { + this->generate(); + jit_ker = (decltype(jit_ker))this->getCode(); + } + + jit_pool_conf_t jpp; + + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_pool_kernel_f32) + + void operator()(jit_pool_call_s *arg) { jit_ker(arg); } + static status_t init_conf(jit_pool_conf_t &jbp, const pooling_pd_t *ppd); + +private: + using Vmm = typename utils::conditional3::type; + Xmm xreg(int idx) { return Xmm((isa == avx512_common ? 31 : 15) - idx); } + Ymm yreg(int idx) { return Ymm(xreg(idx).getIdx()); } + Vmm vreg(int idx) { return Vmm(xreg(idx).getIdx()); } + + const AddressFrame &vmmword = (isa == sse42) ? xword : + (isa == avx) ? yword : zword; + + Xmm vmm_mask = Xmm(0); + Xmm xmm_ker_area_h = Xmm(2); + Xmm xmm_one = Xmm(2); + Xmm xmm_tmp = Xmm(3); + + Vmm vmm_ker_area_h = Vmm(2); + Vmm vmm_one = Vmm(2); + Vmm vmm_tmp = Vmm(3); + + Vmm vmm_k_offset = Vmm(1); + + Opmask k_index_mask = Opmask(6); + Opmask k_store_mask = Opmask(7); + + // Here be some (tame) dragons. This kernel does not follow the regular + // OS-agnostic ABI pattern because when isa is sse42 it uses maskmovdqu + // instruction which has its destination hardcoded in rdi. Therefore: + // - all registers are hardcoded + // - on Windows rdi and rcx are swapped to mimic the Unix x86_64 ABI + // + // While this is only required by the backward pass, the quirk above + // is applied to the forward pass as well to keep things simpler. + + using reg64_t = const Xbyak::Reg64; + reg64_t reg_param = rdi; // Always mimic the Unix ABI + reg64_t reg_input = r8; + reg64_t aux_reg_input = r9; + reg64_t reg_index = r10; + reg64_t reg_output = r12; + reg64_t reg_kd_pad_shift = r13; + reg64_t dst_ptr = rdi; // Must be rdi due to maskmovdqu + + reg64_t kj = r14; + reg64_t oi_iter = r15; + reg64_t reg_kh = rax; + reg64_t reg_k_shift = rbx; + reg64_t tmp_gpr = rcx; // Must be rcx because rdi is used above + reg64_t reg_ker_area_h = rdx; + + reg64_t zero_size = r15; + reg64_t ki = r12; + reg64_t aux_reg_input_d = r8; + + Xbyak::Reg32 reg_shuf_mask = esi; + + int prev_kw; + void (*jit_ker)(jit_pool_call_s *); + + void maybe_recalculate_divisor(int jj, int ur_w, int pad_l, int pad_r); + void avg_step(int ur_w, int pad_l, int pad_r); + void max_step_fwd(int ur_w, int pad_l, int pad_r); + void max_step_bwd(int ur_w, int pad_l, int pad_r); + + void maybe_zero_diff_src(); + + void step(int ur_w, int pad_l, int pad_r) { + if (jpp.alg == alg_kind::pooling_max) { + if(jpp.is_backward) + max_step_bwd(ur_w, pad_l, pad_r); + else + max_step_fwd(ur_w, pad_l, pad_r); + } + else + avg_step(ur_w, pad_l, pad_r); + } + + void step_high_half(int ur_w, int pad_l, int pad_r) { + add(reg_input, sizeof(float) * 4); + add(reg_output, sizeof(float) * 4); + if (jpp.alg == alg_kind::pooling_max && + (jpp.is_training || jpp.is_backward)) + add(reg_index, types::data_type_size(jpp.ind_dt) * 4); + + step(ur_w, pad_l, pad_r); + } + + void generate(); + + void avx_vpadd1(const Ymm& y0, const Xmm& x1, const Xmm& xtmp) { + assert(y0.getIdx() != x1.getIdx()); + vextractf128(xtmp, y0, 0); + vpaddd(xtmp, xtmp, x1); + vinsertf128(y0, y0, xtmp, 0); + vextractf128(xtmp, y0, 1); + vpaddd(xtmp, xtmp, x1); + vinsertf128(y0, y0, xtmp, 1); + } + + void avx_vpadd1(const Xmm& x0, const Xmm& x1, const Xmm&) { + assert(false /*function should not be used*/); + paddd(x0, x1); + } + + void avx_pmovzxbd(const Ymm& y0, const Xmm& x1, const Xmm& xtmp) { + Xmm x0(y0.getIdx()); + pshufd(xmm_tmp, x1, 1); + pmovzxbd(x0, x1); + pmovzxbd(xmm_tmp, xmm_tmp); + vinsertf128(y0, y0, xmm_tmp, 1); + } + + void avx_pmovzxbd(const Xmm& x0, const Xmm& x1, const Xmm&) { + assert(false /*function should not be used*/); + pmovzxbd(x0, x1); + } + + void avx_pcmpeqd(const Ymm& y0, const Ymm& y1, const Ymm& y2, const Xmm& xtmp) { + assert(y0.getIdx() != y1.getIdx()); + assert(y0.getIdx() != y2.getIdx()); + Xmm x0(y0.getIdx()); + Xmm x2(y2.getIdx()); + vextractf128(x0, y1, 1); + vextractf128(xtmp, y2, 1); + pcmpeqd(xtmp, x0); + vextractf128(x0, y1, 0); + pcmpeqd(x0, x2); + vinsertf128(y0, y0, xtmp, 1); + } + + void avx_pcmpeqd(const Xmm& x0, const Xmm& x1, const Xmm&, const Xmm&) { + assert(false /*function should not be used*/); + pcmpeqd(x0, x1); + } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp new file mode 100644 index 0000000000..afbcf996d8 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp @@ -0,0 +1,264 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_types.h" + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "nstl.hpp" + +#include "jit_uni_pooling.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +void jit_uni_pooling_fwd_t::execute_forward(const data_t *src, + data_t *dst, char *indices) const { + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper indices_d(pd()->workspace_md()); + const size_t ind_dt_size = indices + ? types::data_type_size(indices_d.data_type()) : 0; + + const auto &jpp = pd()->jpp_; + + auto ker = [&](int n, int b_c, int oh) { + auto arg = jit_pool_call_s(); + + const int ij = oh * jpp.stride_h; + const int i_t_overflow = nstl::max(0, jpp.t_pad-ij); + const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih; + const int ih = nstl::max(ij - jpp.t_pad, 0); + + arg.src = &src[src_d.blk_off(n, b_c, ih)]; + arg.dst = &dst[dst_d.blk_off(n, b_c, oh)]; + if (indices) { + const size_t ind_off = indices_d.blk_off(n, b_c, oh); + arg.indices = &indices[ind_off * ind_dt_size]; + } + arg.oh = oh == 0; + arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow; + arg.kh_padding_shift = i_t_overflow*jpp.kw; + arg.kw_padding = 0; + arg.ker_area_h = (float)(jpp.kh - + nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) - + nstl::max(0, jpp.t_pad - oh*jpp.stride_h)); + (*kernel_)(&arg); + }; + + parallel_nd(jpp.mb, jpp.nb_c, jpp.oh, + [&](int n, int b_c, int oh) { + ker(n, b_c, oh); + }); +} + +template +void jit_uni_pooling_fwd_t::execute_forward_3d(const data_t *src, + data_t *dst, char *indices) const { + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper indices_d(pd()->workspace_md()); + const size_t ind_dt_size = indices + ? types::data_type_size(indices_d.data_type()) : 0; + + const auto &jpp = pd()->jpp_; + + auto ker = [&](int n, int b_c, int od, int oh, int id, int d_t_overflow, + int d_b_overflow) { + auto arg = jit_pool_call_s(); + + const int ij = oh * jpp.stride_h; + const int i_t_overflow = nstl::max(0, jpp.t_pad-ij); + const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih; + const int ih = nstl::max(ij - jpp.t_pad, 0); + + arg.src = &src[src_d.blk_off(n, b_c, id, ih)]; + arg.dst = &dst[dst_d.blk_off(n, b_c, od, oh)]; + if (indices) { + const size_t ind_off = indices_d.blk_off(n, b_c, od, oh); + arg.indices = &indices[ind_off * ind_dt_size]; + } + arg.oh = (oh + od == 0); + arg.kd_padding = jpp.kd - d_t_overflow - d_b_overflow; + arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow; + arg.kh_padding_shift = i_t_overflow*jpp.kw + d_t_overflow*jpp.kw*jpp.kh; + arg.kd_padding_shift = (i_t_overflow + i_b_overflow)*jpp.kw; + arg.kw_padding = 0; + arg.ker_area_h = (float)(jpp.kh - + nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) - + nstl::max(0, jpp.t_pad - oh*jpp.stride_h)) * (jpp.kd - + nstl::max(0, od*jpp.stride_d - jpp.f_pad + jpp.kd - jpp.id) - + nstl::max(0, jpp.f_pad - od*jpp.stride_d)); + + + (*kernel_)(&arg); + }; + + parallel_nd(jpp.mb, jpp.nb_c, jpp.od, + [&](int n, int b_c, int od) { + const int ik = od * jpp.stride_d; + const int d_t_overflow = nstl::max(0, jpp.f_pad-ik); + const int d_b_overflow = nstl::max(jpp.id, ik+jpp.kd-jpp.f_pad) + -jpp.id; + const int id = nstl::max(ik - jpp.f_pad, 0); + for (int oh = 0; oh < jpp.oh; ++oh) { + ker(n, b_c, od, oh, id, d_t_overflow, d_b_overflow); + } + }); +} + +template +void jit_uni_pooling_bwd_t::execute_backward(const data_t *diff_dst, + const char *indices, data_t *diff_src) const { + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper indices_d(pd()->workspace_md()); + const size_t ind_dt_size = indices + ? types::data_type_size(indices_d.data_type()) : 0; + + const auto &jpp = pd()->jpp_; + + auto ker = [&](int n, int b_c, int oh) { + auto arg = jit_pool_call_s(); + + const int ij = oh * jpp.stride_h; + const int i_t_overflow = nstl::max(0, jpp.t_pad-ij); + const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih; + const int ih = nstl::max(ij - jpp.t_pad, 0); + + arg.src = &diff_src[diff_src_d.blk_off(n, b_c, ih)]; + arg.dst = &diff_dst[diff_dst_d.blk_off(n, b_c, oh)]; + if (indices) { + const size_t ind_off = indices_d.blk_off(n, b_c, oh); + arg.indices = &indices[ind_off * ind_dt_size]; + } + arg.oh = (oh == 0); + arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow; + arg.kh_padding_shift = i_t_overflow*jpp.kw; + arg.kw_padding = 0; + arg.ker_area_h = (float)(jpp.kh - + nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) - + nstl::max(0, jpp.t_pad - oh*jpp.stride_h)); + + (*kernel_)(&arg); + }; + + parallel_nd(jpp.mb, jpp.nb_c, [&](int n, int b_c) { + for (int oh = 0; oh < jpp.oh; ++oh) { + ker(n, b_c, oh); + } + }); +} + +template +void jit_uni_pooling_bwd_t::execute_backward_3d(const data_t *diff_dst, + const char *indices, data_t *diff_src) const { + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper indices_d(pd()->workspace_md()); + const size_t ind_dt_size = indices + ? types::data_type_size(indices_d.data_type()) : 0; + + const auto &jpp = pd()->jpp_; + + auto ker = [&](int n, int b_c, int od, int oh, int id, int d_t_overflow, + int d_b_overflow, int zero_size, int kd) { + auto arg = jit_pool_call_s(); + + const int ij = oh * jpp.stride_h; + const int i_t_overflow = nstl::max(0, jpp.t_pad-ij); + const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih; + const int ih = nstl::max(ij - jpp.t_pad, 0); + + arg.src = &diff_src[diff_src_d.blk_off(n, b_c, id + kd, ih)]; + arg.dst = &diff_dst[diff_dst_d.blk_off(n, b_c, od, oh)]; + if (indices) { + const size_t ind_off = indices_d.blk_off(n, b_c, od, oh); + arg.indices = &indices[ind_off * ind_dt_size]; + } + arg.oh = zero_size; + arg.kd_padding = jpp.kd - d_t_overflow - d_b_overflow; + arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow; + arg.kh_padding_shift = i_t_overflow*jpp.kw + d_t_overflow*jpp.kw*jpp.kh + + kd * jpp.kw * jpp.kh; + arg.kd_padding_shift = (i_t_overflow + i_b_overflow)*jpp.kw; + arg.kw_padding = 0; + arg.ker_area_h = (float)(jpp.kh - + nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) - + nstl::max(0, jpp.t_pad - oh*jpp.stride_h)) * (jpp.kd - + nstl::max(0, od*jpp.stride_d - jpp.f_pad + jpp.kd - jpp.id) - + nstl::max(0, jpp.f_pad - od*jpp.stride_d)); + + (*kernel_)(&arg); + }; + + if (jpp.simple_alg) { + + parallel_nd(jpp.mb, jpp.nb_c, jpp.od, + [&](int n, int b_c, int od) { + const int ik = od * jpp.stride_d; + const int d_t_overflow = nstl::max(0, jpp.f_pad - ik); + const int d_b_overflow = nstl::max(jpp.id, ik + jpp.kd + - jpp.f_pad) - jpp.id; + const int id = nstl::max(ik - jpp.f_pad, 0); + int zero_s = jpp.stride_d - d_t_overflow - (nstl::max( + jpp.id, ik + jpp.stride_d - jpp.f_pad) - jpp.id); + for (int oh = 0; oh < jpp.oh; ++oh) { + ker(n, b_c, od, oh, id, d_t_overflow, d_b_overflow, + (oh == 0) ? zero_s : 0, 0); + } + }); + } else { + ptrdiff_t nelems = (ptrdiff_t)jpp.mb * (ptrdiff_t)jpp.c + * (ptrdiff_t)jpp.id * (ptrdiff_t)jpp.ih * (ptrdiff_t)jpp.iw; + + parallel_nd(nelems, [&](ptrdiff_t i) { diff_src[i] = 0.f; }); + + for (int kd = 0; kd < jpp.kd; ++kd) { + parallel_nd(jpp.mb, jpp.nb_c, [&](int n, int b_c) { + for (int od = 0; od < jpp.od; ++od) { + const int ik = od * jpp.stride_d; + const int d_t_overflow = nstl::max(0, jpp.f_pad-ik); + const int d_b_overflow = nstl::max(jpp.id, ik + jpp.kd + - jpp.f_pad) - jpp.id; + if (kd >= jpp.kd - d_t_overflow - d_b_overflow) + continue; + const int id = nstl::max(ik - jpp.f_pad, 0); + for (int oh = 0; oh < jpp.oh; ++oh) { + ker(n, b_c, od, oh, id, d_t_overflow, d_b_overflow, + 0, kd); + } + } + }); + } + } +} + + +template struct jit_uni_pooling_fwd_t; +template struct jit_uni_pooling_bwd_t; +template struct jit_uni_pooling_fwd_t; +template struct jit_uni_pooling_bwd_t; +template struct jit_uni_pooling_fwd_t; +template struct jit_uni_pooling_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp new file mode 100644 index 0000000000..57bebacdee --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp @@ -0,0 +1,182 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_JIT_UNI_POOLING_HPP +#define CPU_JIT_UNI_POOLING_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_pooling_pd.hpp" +#include "cpu_primitive.hpp" + +#include "jit_uni_pool_kernel_f32.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct jit_uni_pooling_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_fwd_pd_t { + using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_pooling_fwd_t); + + status_t init() { + using namespace utils; + + bool ok = true + && set_default_params() == status::success + && is_fwd() + && !has_zero_dim_memory() + && everyone_is(data_type::f32, + src_md()->data_type, + dst_md()->data_type) + && attr()->has_default_values() + && memory_desc_matches_tag(*src_md(), desired_fmt_tag()) + && memory_desc_matches_tag(*dst_md(), desired_fmt_tag()); + if (!ok) return status::unimplemented; + + bool is_training = desc_.prop_kind == prop_kind::forward_training; + if (desc()->alg_kind == alg_kind::pooling_max && is_training) + init_default_ws(); + + return jit_uni_pool_kernel_f32::init_conf(jpp_, this); + } + + format_tag_t desired_fmt_tag() { + using namespace format_tag; + return ndims() == 4 + ? isa == avx512_common ? nChw16c : nChw8c + : isa == avx512_common ? nCdhw16c : nCdhw8c; + } + + jit_pool_conf_t jpp_; + }; + + jit_uni_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd) + { kernel_ = new jit_uni_pool_kernel_f32(pd()->jpp_); } + + ~jit_uni_pooling_fwd_t() { delete kernel_; } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(char *, MKLDNN_ARG_WORKSPACE); + + if (pd()->ndims() == 5) + execute_forward_3d(src, dst, ws); + else + execute_forward(src, dst, ws); + + return status::success; + } + +private: + void execute_forward(const data_t *src, data_t *dst, char *indices) const; + void execute_forward_3d(const data_t *src, data_t *dst, + char *indices) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_uni_pool_kernel_f32 *kernel_; +}; + +template +struct jit_uni_pooling_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_bwd_pd_t { + using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t; + + DECLARE_COMMON_PD_T( + JIT_IMPL_NAME_HELPER("jit:", isa, ""), + jit_uni_pooling_bwd_t); + + status_t init() { + using namespace utils; + + bool ok = true + && set_default_params() == status::success + && !is_fwd() + && !has_zero_dim_memory() + && everyone_is(data_type::f32, + diff_src_md()->data_type, + diff_dst_md()->data_type) + && attr()->has_default_values() + && memory_desc_matches_tag(*diff_dst_md(), desired_fmt_tag()) + && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag()); + if (!ok) return status::unimplemented; + + if (desc()->alg_kind == alg_kind::pooling_max) { + init_default_ws(); + if (!compare_ws(hint_fwd_pd_)) + return status::unimplemented; + } + + return jit_uni_pool_kernel_f32::init_conf(jpp_, this); + } + + format_tag_t desired_fmt_tag() { + using namespace format_tag; + return ndims() + ? isa == avx512_common ? nChw16c : nChw8c + : isa == avx512_common ? nCdhw16c : nCdhw8c; + } + + jit_pool_conf_t jpp_; + }; + + jit_uni_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd) + { kernel_ = new jit_uni_pool_kernel_f32(pd()->jpp_); } + + ~jit_uni_pooling_bwd_t() { delete kernel_; } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto ws = CTX_IN_MEM(const char *, MKLDNN_ARG_WORKSPACE); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + if (pd()->ndims() == 5) + execute_backward_3d(diff_dst, ws, diff_src); + else + execute_backward(diff_dst, ws, diff_src); + + return status::success; + } + +private: + void execute_backward(const data_t *diff_dst, const char *indices, + data_t *diff_src) const; + void execute_backward_3d(const data_t *diff_dst, const char *indices, + data_t *diff_src) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + jit_uni_pool_kernel_f32 *kernel_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp new file mode 100644 index 0000000000..98796503b7 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp @@ -0,0 +1,1006 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "memory_desc_wrapper.hpp" +#include "mkldnn_debug.h" +#include "nstl.hpp" +#include "type_helpers.hpp" + +#include "cpu_primitive.hpp" +#include "cpu_reorder_pd.hpp" +#include "jit_uni_reorder.hpp" + +#include "jit_generator.hpp" + +// #define TR_DEBUG +#if defined(TR_DEBUG) +#define DEBUg(...) do { __VA_ARGS__ } while (0) +#else +#define DEBUg(...) +#endif +#define DEBUG(...) DEBUg(__VA_ARGS__) + +#ifdef _WIN32 +/* seems like s_addr is a reserved macro on Windows */ +#undef s_addr +#endif + +using namespace Xbyak; +using namespace mkldnn::impl::types; + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace tr { + +/** Minimal reasonable/desirable kernel size. + * The constant might be used to determine how a problem should be split + * between kernel and threading driver. */ +const size_t ker_prb_size_min = 64; + +/* kernel */ +struct jit_uni_reorder_kernel_f32: public kernel_t, public jit_generator { + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_reorder_kernel_f32) + + enum { + len_unroll_max = 256, + ndims_jit_loop_max = 3, + }; + + struct simple_impl_desc_t { + int ndims_full_unroll; + int len_last_dim_unroll; + int len_unroll; + }; + + static bool simple_impl_desc_init(const prb_t &prb, + simple_impl_desc_t *desc) { + const int ndims = prb.ndims; + + int ndims_full_unroll = 0; + int len_last_dim_unroll = 1; + int len_unroll = 1; + + for (int d = 0; d < ndims; ++d) { + auto &node = prb.nodes[d]; + if (len_unroll * node.n <= len_unroll_max) { + ndims_full_unroll++; + len_unroll *= node.n; + } else { + len_last_dim_unroll = len_unroll_max / len_unroll; + while (node.n % len_last_dim_unroll) + --len_last_dim_unroll; + len_unroll *= len_last_dim_unroll; + break; + } + } + + if (prb.ndims - ndims_full_unroll > ndims_jit_loop_max) + return false; + + if (desc) { + desc->ndims_full_unroll = ndims_full_unroll; + desc->len_last_dim_unroll = len_last_dim_unroll; + desc->len_unroll = len_unroll; + } + + return true; + } + + static bool applicable(const prb_t &p) { + using namespace data_type; + + bool ok = true + && p.ndims > 0 + && utils::one_of(p.itype, f32, s32, s8, u8) + && utils::one_of(p.otype, f32, s32, s8, u8) + && utils::everyone_is(0, p.ioff, p.ooff) /* do we need this? */ + && utils::one_of(p.beta, 0.f, 1.f) /* anything else? */ + && simple_impl_desc_init(p, nullptr) + && mayiuse(sse42) + && IMPLICATION(!utils::everyone_is(f32, p.itype, p.otype), + mayiuse(avx)); + if (!ok) return false; + + const ptrdiff_t max_stride = (1LL<<31) - 1; + for (int d = 0; d < p.ndims; ++d) { + const ptrdiff_t cms = max_stride / p.nodes[d].n; + bool strides_ok = true + && p.nodes[d].is < cms / (int)data_type_size(p.itype) + && p.nodes[d].os < cms / (int)data_type_size(p.otype); + if (!strides_ok) return false; + } + + return true; + } + + int n(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].n; } + int is(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].is; } + int os(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].os; } + int ss(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].ss; } + + Address i_addr(int i_off) + { return ptr[reg_ptr_in + reg_off_in + i_off * itype_sz]; } + + Address o_addr(int o_off) + { return ptr[reg_ptr_out + reg_off_out + o_off * otype_sz]; } + + Address s_addr(int s_off) + { return ptr[reg_ptr_scale + reg_off_scale + s_off * stype_sz]; } + + void step(int off, int prev_i_off, int prev_o_off, int prev_s_off, + int &i_off, int &o_off, int &s_off, int step_size = 1) { + i_off = prev_i_off; + o_off = prev_o_off; + s_off = prev_s_off; + + if (off == 0) return; + + int start_dim = 0, dims_prod = 1; + for (; start_dim < prb_.ndims && dims_prod != step_size; ++start_dim) + dims_prod *= n(start_dim); + assert(start_dim < prb_.ndims); + off /= step_size; + + for (int d = start_dim; d < prb_.ndims; ++d) { + i_off += is(d); + o_off += os(d); + s_off += ss(d); + + if (off % n(d)) break; + + i_off += - n(d) * is(d); + o_off += - n(d) * os(d); + s_off += - n(d) * ss(d); + off /= n(d); + + if (off == 0) break; /* FIXME: is it really required? */ + } + } + + void step(int off, int prev_i_off, int prev_o_off, int &i_off, int &o_off, + int step_size = 1) { + int dummy = 0; + step(off, prev_i_off, prev_o_off, dummy, i_off, o_off, dummy, + step_size); + } + + void tr8x8_avx2(int i_off, int o_off) { + for (int i = 0; i < 8; i++) + vmovups(Ymm(i), i_addr(i_off + i * 8)); + + for (int i = 0; i < 8 / 2; i++) { + vunpcklps(Ymm(8 + i), Ymm(2 * i), Ymm(2 * i + 1)); + vunpckhps(Ymm(i), Ymm(2 * i), Ymm(2 * i + 1)); + } + + const unsigned int lfloat = 0x44; + const unsigned int ufloat = 0xee; + for (int i = 0; i < 8 / 2; i++) { + int j = i % 2 == 0 ? 8 + i : i - 1; + vshufps(Ymm(8 / 2 + 2 * i), Ymm(j), Ymm(j + 1), lfloat); + vshufps(Ymm(8 / 2 + 2 * i + 1), Ymm(j), Ymm(j + 1), ufloat); + } + + const unsigned int lquad = 0x20; + for (int i = 0; i < 8 / 2; i++) + vperm2f128(Ymm(i), Ymm(8 / 2 + i), Ymm(8 + i), lquad); + + const unsigned int uquad = 0x31; + for (int i = 8 / 2; i < 8; i++) + vperm2f128(Ymm(i), Ymm(i), Ymm(8 / 2 + i), uquad); + + for (int i = 0; i < 8; i++) + vmovups(o_addr(o_off + i * 8), Ymm(i)); + } + + bool process_unroll_tr8x8(int len) { + bool can_do = true + && mayiuse(avx2) + && prb_.ndims >= 2 + && utils::everyone_is(4, itype_sz, otype_sz) + && utils::everyone_is(8, n(0), n(1)) + && utils::everyone_is(1, os(0), is(1)) + && utils::everyone_is(8, os(1), is(0)) + && prb_.scale_type == scale_type_t::NONE + && prb_.beta == 0.f; + if (!can_do) return false; + + const int step_size = n(0) * n(1); + int i_off = 0, o_off = 0; + for (int off = 0; off < len; off += step_size) { + step(off, i_off, o_off, i_off, o_off, step_size); + tr8x8_avx2(i_off, o_off); + } + + return true; + } + + template + bool process_direct_copy(int len) { + using namespace data_type; + + using Vmm = typename cpu_isa_traits::Vmm; + const int simd_w = cpu_isa_traits::vlen / itype_sz; + + bool can_do = true + && mayiuse(isa) + && utils::everyone_is(1, os(0), is(0)) + && (false + || prb_.itype == prb_.otype + || (prb_.itype == s32 && prb_.otype == f32) + || (prb_.itype == f32 && prb_.otype == s32) + ) + && len % simd_w == 0 + && n(0) % len == 0 + && prb_.scale_type == scale_type_t::NONE + && prb_.beta == 0.f; + if (!can_do) return false; + + for (int off = 0; off < len;) { + const int unroll = nstl::min(16, (len - off) / simd_w); + + for (int ur = 0; ur < unroll; ++ur) + uni_vmovups(Vmm(ur), i_addr(off + ur * simd_w)); + + if (prb_.itype != prb_.otype) { + for (int ur = 0; ur < unroll; ++ur) { + if (prb_.itype == s32 && prb_.otype == f32) + uni_vcvtdq2ps(Vmm(ur), Vmm(ur)); + else if (prb_.itype == f32 && prb_.otype == s32) + uni_vcvtps2dq(Vmm(ur), Vmm(ur)); + else assert(!"unreachable"); + } + } + + for (int ur = 0; ur < unroll; ++ur) + uni_vmovups(o_addr(off + ur * simd_w), Vmm(ur)); + + off += unroll * simd_w; + } + + return true; + } + + void process_unroll_generic_step(int reg_unroll, const int *i_off, + const int *o_off, const int *s_off) { + using namespace data_type; + + auto cvt2ps = [=](const Xmm &dst, const Operand &src, data_type_t idt) { + Xmm dst_pure = Xmm(dst.getIdx()); + switch (idt) { + case f32: + if (src.isMEM() || src.getIdx() != dst.getIdx()) + vmovups(dst, src); + break; + case s32: vcvtdq2ps(dst, src); break; + case s8: vpmovsxbd(dst, src); vcvtdq2ps(dst_pure, dst); break; + case u8: vpmovzxbd(dst, src); vcvtdq2ps(dst_pure, dst); break; + default: assert(!"unreachable"); + } + }; + + auto cvt2int = [=](const Xmm &xmm, data_type_t odt, data_type_t idt) { + switch (odt) { + case s32: + if (idt == f32) vcvtps2dq(xmm, xmm); + else if (idt == s8) vpmovsxbd(xmm, xmm); + else if (idt == u8) vpmovzxbd(xmm, xmm); + break; + case s8: + if (idt == f32) vcvtps2dq(xmm, xmm); + if (idt == f32 || idt == s32) { + if (mayiuse(avx512_core)) { + vpmovsdb(xmm, xmm); + } else { + vpackssdw(xmm, xmm, xmm_zero); + vpacksswb(xmm, xmm, xmm_zero); + } + } + if (idt == u8) vpminub(xmm, xmm, xmm_4x127b); + break; + case u8: + if (idt == f32) vcvtps2dq(xmm, xmm); + if (idt == f32 || idt == s32) { + if (mayiuse(avx512_core)) { + vpmaxsd(xmm, xmm, xmm_zero); + vpmovusdb(xmm, xmm); + } else { + vpackssdw(xmm, xmm, xmm_zero); + vpackuswb(xmm, xmm, xmm_zero); + } + } + if (idt == s8) vpmaxsb(xmm, xmm, xmm_zero); + break; + default: assert(!"unreachable"); + } + }; + + auto load = [=](const Xmm &xmm, const Address &addr, int size) { + switch (size) { + case 16: movups(xmm, addr); break; + case 4: movss(xmm, addr); break; + case 1: pinsrb(xmm, addr, 0x0); break; + default: assert(!"unreachable"); + } + }; + + auto store = [=](const Address &addr, const Xmm &xmm, int size) { + switch (size) { + case 16: movups(addr, xmm); break; + case 4: movss(addr, xmm); break; + case 1: pextrb(addr, xmm, 0x0); break; + default: assert(!"unreachable"); + } + }; + + /* check whether loading 4 values at once is possible */ + bool can_load_xmm = mayiuse(avx) && reg_unroll % 4 == 0; + for (int ur = 1; ur < reg_unroll; ++ur) + if (i_off[ur] != i_off[ur - 1] + 1) + can_load_xmm = false; + const int load_step = can_load_xmm ? 4 : 1; + + /* check whether storing 4 values at once is possible */ + bool can_store_xmm = reg_unroll % 4 == 0; + for (int ur = 1; ur < reg_unroll; ++ur) + if (o_off[ur] != o_off[ur - 1] + 1) + can_store_xmm = false; + const int ur_step = can_store_xmm ? 4 : 1; + + const bool interim_f32 = false + || utils::one_of(f32, prb_.itype, prb_.otype) + || prb_.scale_type != scale_type_t::NONE + || prb_.beta != 0.f; + + if (!can_load_xmm && can_store_xmm) { + assert(ur_step == 4); + /* load with stride */ + for (int ur = 0; ur < reg_unroll; ur += ur_step) { + for (int r = 0; r < ur_step; ++r) { + if (itype_sz == 4) + pinsrd(Xmm(ur), i_addr(i_off[ur + r]), r); + else + pinsrb(Xmm(ur), i_addr(i_off[ur + r]), r); + } + } + } else { + for (int ur = 0; ur < reg_unroll; ur += load_step) + load(Xmm(ur), i_addr(i_off[ur]), load_step * itype_sz); + } + + /* xmm[:] <-- (f32)xmm[:] */ + if (interim_f32) { + const int cvt_step = nstl::max(load_step, ur_step); + for (int ur = 0; ur < reg_unroll; ur += cvt_step) + cvt2ps(Xmm(ur), Xmm(ur), prb_.itype); + } + + if (can_load_xmm && !can_store_xmm) { + const bool fast_return = true // transposition on the fly + && prb_.scale_type != scale_type_t::MANY + && prb_.beta == 0.f; + if (fast_return) { + for (int ur = 0; ur < reg_unroll; ur += load_step) { + if (prb_.scale_type == scale_type_t::COMMON) + mulps(Xmm(ur), xmm_scale); + if (prb_.otype != f32) + cvt2int(Xmm(ur), prb_.otype, + interim_f32 ? f32 : prb_.itype); + for (int r = 0; r < load_step; ++r) { + if (otype_sz == 4) + pextrd(o_addr(o_off[ur + r]), Xmm(ur), r); + else + pextrb(o_addr(o_off[ur + r]), Xmm(ur), r); + } + } + return; + } + + /* scatter elements of xmm into 4 xmms */ + if (itype_sz == 4 || interim_f32) { + for (int ur = 0; ur < reg_unroll; ur += load_step) + for (int r = 1; r < load_step; ++r) + vshufps(Xmm(ur + r), Xmm(ur), Xmm(ur), r); + } else { + for (int ur = 0; ur < reg_unroll; ur += load_step) + for (int r = 1; r < load_step; ++r) + vpalignr(Xmm(ur + r), Xmm(ur), Xmm(ur), r); + } + } + + /* scale and beta processing */ + if (can_store_xmm) { + /* xmm <-- scale * xmm[:] */ + if (prb_.scale_type == scale_type_t::COMMON) { + for (int ur = 0; ur < reg_unroll; ur += ur_step) + mulps(Xmm(ur), xmm_scale); + } else if (prb_.scale_type == scale_type_t::MANY) { + enum class scale_load_type_t { bcast, load, gather }; + + for (int ur = 0; ur < reg_unroll; ur += ur_step) { + scale_load_type_t scale_load_type = + scale_load_type_t::bcast; // the best case + + for (int r = ur + 1; r < ur + ur_step; ++r) + if (s_off[r] != s_off[r - 1] + 0) + scale_load_type = scale_load_type_t::load; + + if (scale_load_type == scale_load_type_t::bcast) { + movss(xmm_scale, s_addr(s_off[ur])); + shufps(xmm_scale, xmm_scale, 0x0); + mulps(Xmm(ur), xmm_scale); + continue; + } + + // bcast doesn't work, the next try -- load + for (int r = ur + 1; r < ur + ur_step; ++r) + if (s_off[r] != s_off[r - 1] + 1) + scale_load_type = scale_load_type_t::gather; + + if (scale_load_type == scale_load_type_t::load) { + movups(xmm_scale, s_addr(s_off[ur])); + mulps(Xmm(ur), xmm_scale); + continue; + } + + // load doesn't work as well + // so gather the scale factors one by one + for (int r = ur; r < ur + ur_step; ++r) + pinsrd(xmm_scale, s_addr(s_off[r]), r - ur); + mulps(Xmm(ur), xmm_scale); + } + } + + /* dst <-- beta * dst + xmm[:] */ + assert(prb_.beta == 0.f || prb_.beta == 1.f); + if (prb_.beta == 1.f) { + for (int ur = 0; ur < reg_unroll; ur += ur_step) { + if (prb_.otype == f32) { + /* non VEX instructions do not support unaligned + * memory for instructions other than movups. */ + if (mayiuse(avx)) { + vaddps(Xmm(ur), o_addr(o_off[ur])); + } else { + /* register xmm(1) is unused */ + movups(Xmm(1), o_addr(o_off[ur])); + addps(Xmm(ur), Xmm(1)); + } + } else { + cvt2ps(Xmm(1), o_addr(o_off[ur]), prb_.otype); + vaddps(Xmm(ur), Xmm(1)); + } + } + } + } else { + /* xmm[0] <-- scale * xmm[0] */ + if (prb_.scale_type == scale_type_t::COMMON) { + for (int ur = 0; ur < reg_unroll; ur += ur_step) + mulss(Xmm(ur), xmm_scale); + } else if (prb_.scale_type == scale_type_t::MANY) { + for (int ur = 0; ur < reg_unroll; ur += ur_step) { + mulss(Xmm(ur), s_addr(s_off[ur])); + } + } + + /* dst <-- beta * dst + xmm[0] */ + assert(prb_.beta == 0.f || prb_.beta == 1.f); + if (prb_.beta == 1.f) { + for (int ur = 0; ur < reg_unroll; ur += ur_step) { + if (prb_.otype == f32) { + addss(Xmm(ur), o_addr(o_off[ur])); + } else { + if (prb_.otype == s32) { + vmovss(xmm_tmp, o_addr(o_off[ur])); + } else if (utils::one_of(prb_.otype, s8, u8)) { + pinsrb(xmm_tmp, o_addr(o_off[ur]), 0x0); + } else { + assert(!"unsupported o_type"); + } + cvt2ps(xmm_tmp, xmm_tmp, prb_.otype); + addps(Xmm(ur), xmm_tmp); + } + } + } + } + + for (int ur = 0; ur < reg_unroll; ur += ur_step) { + if (prb_.otype != f32) + cvt2int(Xmm(ur), prb_.otype, interim_f32 ? f32 : prb_.itype); + store(o_addr(o_off[ur]), Xmm(ur), ur_step * otype_sz); + } + } + + void process_unroll_generic(int len) { + const int blk = 8; + + int i_off[2 * blk] = {0}; + int o_off[2 * blk] = {0}; + int s_off[2 * blk] = {0}; + + int curr = 0; // will switch between 0 and 1 + + for (int off = 0; off < len; off += blk) { + const int reg_unroll = nstl::min(off + blk, len) - off; + + /* compute offsets */ + for (int ur = off != 0 ? 0 : 1; ur < reg_unroll; ++ur) { + const int ur_c = curr * blk + ur; + const int ur_p = (ur_c - 1 + 2 * blk) % (2 * blk); // prev ur + step(off + ur, + i_off[ur_p], o_off[ur_p], s_off[ur_p], + i_off[ur_c], o_off[ur_c], s_off[ur_c]); + } + + process_unroll_generic_step(reg_unroll, i_off + curr * blk, + o_off + curr * blk, s_off + curr * blk); + + curr = 1 - curr; + } + } + + void loop_begin(Label &l, Reg64 reg_cnt, int len) { + mov(reg_cnt, len); + L(l); + } + + void loop_end(Label &l, Reg64 reg_cnt, int len, + int i_step, int o_step, int s_step) { + add(reg_off_in, i_step * itype_sz); + add(reg_off_out, o_step * otype_sz); + if (prb_.scale_type == scale_type_t::MANY) + add(reg_off_scale, s_step * stype_sz); + dec(reg_cnt); + jnz(l); + + sub(reg_off_in, len * i_step * itype_sz); + sub(reg_off_out, len * o_step * otype_sz); + if (prb_.scale_type == scale_type_t::MANY) + sub(reg_off_scale, len * s_step * stype_sz); + } + + bool simple_impl() { + simple_impl_desc_t d; + if (!simple_impl_desc_init(prb_, &d)) return false; + + const int nfu = d.ndims_full_unroll; + const int ldu = d.len_last_dim_unroll; + const int n_jit_loops = prb_.ndims - d.ndims_full_unroll; + assert(n_jit_loops <= ndims_jit_loop_max); + + xor_(reg_off_in, reg_off_in); + xor_(reg_off_out, reg_off_out); + if (prb_.scale_type == scale_type_t::MANY) + xor_(reg_off_scale, reg_off_scale); + + Label l_loop[3]; + Reg64 reg_cnt[3] = {r15, r14, r13}; + + if (n_jit_loops > 2) + loop_begin(l_loop[2], reg_cnt[2], n(nfu + 2)); + + if (n_jit_loops > 1) + loop_begin(l_loop[1], reg_cnt[1], n(nfu + 1)); + + if (n_jit_loops > 0) + loop_begin(l_loop[0], reg_cnt[0], n(nfu + 0) / ldu); + + const bool optimized = false + || process_direct_copy(d.len_unroll) + || process_direct_copy(d.len_unroll) + || process_unroll_tr8x8(d.len_unroll); + if (!optimized) + process_unroll_generic(d.len_unroll); + + if (n_jit_loops > 0) + loop_end(l_loop[0], reg_cnt[0], + n(nfu + 0) / ldu, is(nfu + 0) * ldu, os(nfu + 0) * ldu, + ss(nfu + 0) * ldu); + + if (n_jit_loops > 1) + loop_end(l_loop[1], reg_cnt[1], + n(nfu + 1), is(nfu + 1), os(nfu + 1), ss(nfu + 1)); + + if (n_jit_loops > 2) + loop_end(l_loop[2], reg_cnt[2], + n(nfu + 2), is(nfu + 2), os(nfu + 2), ss(nfu + 2)); + + return true; + } + + void impl() { + if (simple_impl()) return; + assert(!"no implementation available"); + } + + jit_uni_reorder_kernel_f32(const desc_t &desc) + : kernel_t(desc), jit_generator() { + itype_sz = data_type_size(prb_.itype); + otype_sz = data_type_size(prb_.otype); + stype_sz = sizeof(float); + + preamble(); +# define PARAM(x) ptr[abi_param1 + offsetof(call_param_t, x)] + if (prb_.scale_type == scale_type_t::COMMON) { + auto reg_ptr_scale_tmp = reg_ptr_in; + mov(reg_ptr_scale_tmp, PARAM(scale)); + movups(xmm_scale, ptr[reg_ptr_scale_tmp]); + } else if (prb_.scale_type == scale_type_t::MANY) { + mov(reg_ptr_scale, PARAM(scale)); + } + mov(reg_ptr_in, PARAM(in)); + mov(reg_ptr_out, PARAM(out)); +# undef PARAM + + if (mayiuse(avx)) { + vxorps(xmm_zero, xmm_zero, xmm_zero); + + if (prb_.itype == data_type::u8 && prb_.otype == data_type::s8) { + mov(reg_tmp.cvt32(), 0x7f7f7f7f); + movd(xmm_4x127b, reg_tmp.cvt32()); + } + } + + impl(); + postamble(); + ker_ = (void (*)(const call_param_t *))getCode(); + } + +private: + int itype_sz; + int otype_sz; + int stype_sz; + + Reg64 reg_ptr_in = rsi; + Reg64 reg_ptr_out = rdx; + Reg64 reg_ptr_scale = abi_not_param1; + + Reg64 reg_off_in = r8; + Reg64 reg_off_out = r9; + Reg64 reg_off_scale = r10; + + Reg64 reg_tmp = rax; + + Xmm xmm_scale = xmm15; + Xmm xmm_zero = xmm14; + Xmm xmm_4x127b = xmm13; // TODO: unite with xmm_zero + Xmm xmm_tmp = xmm12; +}; + +status_t kernel_t::desc_init(kernel_t::desc_t &desc, const prb_t &prb, + int ndims_ker_max) { + desc.prb = prb; + desc.prb.ioff = desc.prb.ooff = 0; + + if (ndims_ker_max > prb.ndims) + return status::invalid_arguments; + + auto ndims_ker_max_f = [&]() { + size_t cur_size = 1; + for (int d = 0; d < prb.ndims; cur_size *= prb.nodes[d++].n) + if (cur_size >= ker_prb_size_min) return d; + return prb.ndims; + }; + + if (ndims_ker_max <= 0) + ndims_ker_max = ndims_ker_max_f(); + + /* traverse through kernel implementations */ + /* TODO: find a better way to do that... */ + desc.id = 0; + for (int ndims_ker = ndims_ker_max; ndims_ker > 0; --ndims_ker) { + desc.prb.ndims = ndims_ker; + if (jit_uni_reorder_kernel_f32::applicable(desc.prb)) + return status::success; + } + + return status::unimplemented; +} + +kernel_t *kernel_t::create(const kernel_t::desc_t &desc) { + switch (desc.id) { + case 0: return new jit_uni_reorder_kernel_f32(desc); + default: assert(!"unknown kernel id"); return nullptr; + } + + return nullptr; +} + +} + +static void prb_block_for_cache(tr::prb_t &prb) { + if (prb.nodes[0].is % 64 == 0 && prb.nodes[0].n > 16) { + /** an attempt to use caches more efficient and + * address the 4K-aliasing issue */ + /* TODO: improve the logic around here */ + int j = 1; + for (; j < prb.ndims && prb.nodes[j].is != 1; ++j); + if (j == prb.ndims) return; + + /* it makes sense to re-prioritize sequential read over + * sequential write if the former would not trash the + * cache, i.e. is == 1 and os % 2^smth != 0. Smth is + * set to 2 at the moment */ + const int move_to = prb.nodes[j].os % 4 != 0 ? 0 : 1; + if (j == move_to) return; + + if (prb.nodes[j].n > 16 && prb.nodes[j].n % 16 == 0) + prb_node_split(prb, j, 16); + + prb_node_move(prb, j, move_to); + DEBUG({ printf("cache: "); prb_dump(prb); }); + } +} + +/** finds the maximum number of dimension the kernel should process and + * optionally splits one of the dimension to achieve better balance between + * parallel driver and the kernel. */ +static void prb_thread_kernel_balance(tr::prb_t &prb, int &ndims_ker_max) { + size_t sz_total = 1; + for (int d = 0; d < prb.ndims; ++d) + sz_total *= prb.nodes[d].n; + + /* sz_drv_min is the minimal size for the parallel + * driver required for good parallelization */ + const size_t sz_drv_min = nstl::min( + 16 * mkldnn_get_max_threads(), + utils::div_up(sz_total, 1024)); + + /* kdims -- # of dimensions processed by a kernel + * sz_ker_cur -- product of the dimension processed by a kernel + * sz_drv_cur -- product of the dimension processed by a driver */ + + int kdims = prb.ndims; + size_t sz_drv_cur = 1; + for (; kdims > 1 && sz_drv_cur < sz_drv_min; --kdims) + sz_drv_cur *= prb.nodes[kdims - 1].n; + + size_t sz_ker_cur = 1; + for (int d = 0; d < kdims; ++d) + sz_ker_cur *= prb.nodes[d].n; + + /* Initially kdims is chosen so that sz_drv_cur >= sz_drv_min. + * + * It might happen that for chosen kdims the sz_ker_cur is too small + * (less than tr::ker_prb_size_min). In that case try to split the + * innermost driver dimension into two, to increase sz_ker_cur. */ + bool want_borrow_ker_from_drv = true + && kdims < prb.ndims + && sz_ker_cur < tr::ker_prb_size_min + && sz_drv_cur > sz_drv_min; + if (want_borrow_ker_from_drv) { + /* sz_want_borrow is the minimal sz, so that: + * o) sz_ker_cur * sz_want_borrow >= tr::ker_prb_size_min + * o) current innermost driver dimension is divisible by + * sz_want_borrow (so that we can evenly split that + * dimension into two) + * + * In the worst case the minimal sz_want_borrow is equal + * to the innermost driver dimension itself. In that case + * we will sacrifice it in favor of kernel (is it fine?). */ + size_t sz_want_borrow + = utils::div_up(tr::ker_prb_size_min, sz_ker_cur); + for (; prb.nodes[kdims].n % sz_want_borrow; ++sz_want_borrow); + if (sz_want_borrow != prb.nodes[kdims].n) + prb_node_split(prb, kdims, sz_want_borrow); + kdims += 1; + } + + /* On the other hand it might happen that for chosen kdims + * the sz_drv_cur is too small (less than sz_drv_min). In that case + * try to split the outermost kernel dimension into two, to increase + * sz_drv_cur. */ + bool want_borrow_drv_from_ker = true + && sz_ker_cur > tr::ker_prb_size_min + && sz_drv_cur < sz_drv_min; + if (want_borrow_drv_from_ker) { + size_t sz_want_borrow = utils::div_up(sz_drv_min, sz_drv_cur); + for (; prb.nodes[kdims - 1].n % sz_want_borrow; ++sz_want_borrow); + if (sz_want_borrow != prb.nodes[kdims - 1].n) + prb_node_split(prb, kdims - 1, + prb.nodes[kdims - 1].n / sz_want_borrow); + } + + ndims_ker_max = kdims; + + if (want_borrow_ker_from_drv || want_borrow_drv_from_ker) { + DEBUG({ printf("split: "); prb_dump(prb); + printf("ndims_ker_max = %d\n", ndims_ker_max); }); + } +} + +struct jit_uni_reorder_t : public cpu_primitive_t { + struct pd_t : public cpu_reorder_pd_t { + using cpu_reorder_pd_t::cpu_reorder_pd_t; + + DECLARE_COMMON_PD_T("jit:uni", jit_uni_reorder_t); + + static status_t create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) { + auto prb = tr::prb_t(); + + status_t prb_init_status = prb_init(prb, *src_md, *dst_md, attr); + if (prb_init_status != status::success) return prb_init_status; + + DEBUG({ printf("init : "); prb_dump(prb); }); + prb_normalize(prb); + DEBUG({ printf("norm : "); prb_dump(prb); }); + prb_simplify(prb); + DEBUG({ printf("smpl : "); prb_dump(prb); }); + + prb_block_for_cache(prb); + + int ndims_ker_max; + prb_thread_kernel_balance(prb, ndims_ker_max); + + tr::kernel_t::desc_t ker_desc; + status_t ker_init_status + = tr::kernel_t::desc_init(ker_desc, prb, ndims_ker_max); + if (ker_init_status != status::success) return ker_init_status; + + const int ndims_driver = prb.ndims - ker_desc.prb.ndims; + if (ndims_driver > jit_uni_reorder_t::ndims_driver_max) + return status::unimplemented; + + DEBUG({ printf("ker : "); prb_dump(ker_desc.prb); }); + + auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine, + dst_md); + if (_pd == nullptr) return status::out_of_memory; + if (_pd->init() != status::success) { + delete _pd; + return status::unimplemented; + } + _pd->prb_ = prb; + _pd->ker_desc_ = ker_desc; + return safe_ptr_assign(*reorder_pd, _pd); + } + + tr::prb_t prb_; + tr::kernel_t::desc_t ker_desc_; + }; + + jit_uni_reorder_t(const pd_t *apd): cpu_primitive_t(apd) { + kernel_ = tr::kernel_t::create(pd()->ker_desc_); + assert(kernel_); + } + ~jit_uni_reorder_t() { delete kernel_; } + + void omp_driver_0d(int off, const char *in, char *out, + const float *scale) const { + tr::call_param_t c{in, out, scale}; + (*kernel_)(&c); + } + + void omp_driver_1d(int ithr, int nthr, int off, const char *in, char *out, + const float *scale) const { + const tr::node_t *ns = pd()->prb_.nodes + off; + for_nd(ithr, nthr, (ptrdiff_t)ns[0].n, [&](ptrdiff_t d0) { + auto c = tr::call_param_t(); + c.in = in + d0 * ns[0].is * data_type_size(pd()->prb_.itype); + c.out = out + d0 * ns[0].os * data_type_size(pd()->prb_.otype); + c.scale = scale + d0 * ns[0].ss; + (*kernel_)(&c); + }); + } + + void omp_driver_2d(int ithr, int nthr, int off, const char *in, char *out, + const float *scale) const { + const tr::node_t *ns = pd()->prb_.nodes + off; + for_nd(ithr, nthr, (ptrdiff_t)ns[1].n, (ptrdiff_t)ns[0].n, + [&](ptrdiff_t d1, ptrdiff_t d0) { + auto c = tr::call_param_t(); + c.in = in + (d0 * ns[0].is + d1 * ns[1].is) + * data_type_size(pd()->prb_.itype); + c.out = out + (d0 * ns[0].os + d1 * ns[1].os) + * data_type_size(pd()->prb_.otype); + c.scale = scale + d0 * ns[0].ss + d1 * ns[1].ss; + (*kernel_)(&c); + }); + } + + void omp_driver_3d(int ithr, int nthr, int off, const char *in, char *out, + const float *scale) const { + const tr::node_t *ns = pd()->prb_.nodes + off; + for_nd(ithr, nthr, (ptrdiff_t)ns[2].n, (ptrdiff_t)ns[1].n, + (ptrdiff_t)ns[0].n, + [&](ptrdiff_t d2, ptrdiff_t d1, ptrdiff_t d0) { + auto c = tr::call_param_t(); + c.in = in + (d0 * ns[0].is + d1 * ns[1].is + d2 * ns[2].is) + * data_type_size(pd()->prb_.itype); + c.out = out + (d0 * ns[0].os + d1 * ns[1].os + d2 * ns[2].os) + * data_type_size(pd()->prb_.otype); + c.scale = scale + d0 * ns[0].ss + d1 * ns[1].ss + d2 * ns[2].ss; + (*kernel_)(&c); + }); + } + + void omp_driver_4d(int ithr, int nthr, int off, const char *in, char *out, + const float *scale) const { + const tr::node_t *ns = pd()->prb_.nodes + off; + for_nd(ithr, nthr, (ptrdiff_t)ns[3].n, (ptrdiff_t)ns[2].n, + (ptrdiff_t)ns[1].n, (ptrdiff_t)ns[0].n, + [&](ptrdiff_t d3, ptrdiff_t d2, ptrdiff_t d1, ptrdiff_t d0) { + auto c = tr::call_param_t(); + c.in = in + (d0 * ns[0].is + d1 * ns[1].is + d2 * ns[2].is + + d3 * ns[3].is) * data_type_size(pd()->prb_.itype); + c.out = out + (d0 * ns[0].os + d1 * ns[1].os + d2 * ns[2].os + + d3 * ns[3].os) * data_type_size(pd()->prb_.otype); + c.scale = scale + d0 * ns[0].ss + d1 * ns[1].ss + d2 * ns[2].ss + + d3 * ns[3].ss; + (*kernel_)(&c); + }); + } + + void omp_driver(const char *in, char *out, const float *scale) const { + in += pd()->prb_.ioff * data_type_size(pd()->prb_.itype); + out += pd()->prb_.ooff * data_type_size(pd()->prb_.otype); + + DEBUG({ printf("prb : "); tr::prb_dump(pd()->prb_); }); + DEBUG({ printf("ker : "); tr::prb_dump(pd()->ker_desc_.prb); }); + + int ndims = pd()->prb_.ndims; + int ndims_ker = pd()->ker_desc_.prb.ndims; + assert(ndims - ndims_ker <= ndims_driver_max); + + if (ndims - ndims_ker == 0) { + omp_driver_0d(ndims_ker, in, out, scale); + } else { + parallel(0, [&](const int ithr, const int nthr) { + switch (ndims - ndims_ker) { + case 1: omp_driver_1d(ithr, nthr, ndims_ker, in, out, scale); break; + case 2: omp_driver_2d(ithr, nthr, ndims_ker, in, out, scale); break; + case 3: omp_driver_3d(ithr, nthr, ndims_ker, in, out, scale); break; + case 4: omp_driver_4d(ithr, nthr, ndims_ker, in, out, scale); break; + default: assert(!"unimplemented"); + } + }); + } + } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto in = CTX_IN_MEM(const char *, MKLDNN_ARG_FROM); + auto out = CTX_OUT_MEM(char *, MKLDNN_ARG_TO); + + omp_driver(in, out, pd()->attr()->output_scales_.scales_); + + return status::success; + } + + enum { ndims_driver_max = 4 }; + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + tr::kernel_t *kernel_; +}; + +status_t jit_uni_reorder_create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) { + return jit_uni_reorder_t::pd_t::create(reorder_pd, engine, attr, + src_engine, src_md, dst_engine, dst_md); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp new file mode 100644 index 0000000000..0746ea61d3 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp @@ -0,0 +1,127 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef _JIT_UNI_REORDER_HPP +#define _JIT_UNI_REORDER_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" + +#include "cpu_primitive.hpp" +#include "cpu_reorder_pd.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace tr { + +constexpr int max_ndims = MKLDNN_MAX_NDIMS; + +struct node_t { + size_t n; + ptrdiff_t is; // input stride + ptrdiff_t os; // output stride + ptrdiff_t ss; // scale stride +}; + +enum class scale_type_t { NONE, COMMON, MANY }; + +struct prb_t { + data_type_t itype; + data_type_t otype; + int ndims; + node_t nodes[max_ndims]; + ptrdiff_t ioff; + ptrdiff_t ooff; + scale_type_t scale_type; + float beta; +}; + +status_t prb_init(prb_t &prb, const memory_desc_t &imd, + const memory_desc_t &omd, const primitive_attr_t *attr); + +/** sorts the problem nodes so that output strides come in ascending order */ +void prb_normalize(prb_t &p); + +/** folds nodes together if possible */ +void prb_simplify(prb_t &p); + +/** splits the node dim into two of sizes n1 and n / n1 + * @warning n must be multiple of n1 */ +void prb_node_split(prb_t &p, int dim, size_t n1); + +/** swaps d0 and d1 nodes */ +void prb_node_swap(prb_t &p, int d0, int d1); + +/** moves node d0 to the d1 position. + * nodes (d0, d1] are shifted to the left if d0 < d1 or + * to the right if d0 > d1 */ +void prb_node_move(prb_t &p, int d0, int d1); + +/** dumps the problem to stdout */ +void prb_dump(const prb_t &p); + +struct call_param_t { + const void *in; + void *out; + const float *scale; +}; + +struct kernel_t { + struct desc_t { + int id; + prb_t prb; + }; + + kernel_t(const desc_t &desc): desc_(desc), ker_(nullptr) {} + void operator()(const call_param_t *c) const { assert(ker_); ker_(c); } + virtual ~kernel_t() {} + + /** inits kernel descriptor: + * desc -- kernel descriptor (output) + * prb -- transposition problem (input) + * ndims_ker_max -- limit the maximum number of dimensions kernel + * will process (optional, 0 -- no limitation) */ + static status_t desc_init(desc_t &desc, const prb_t &prb, + int ndims_ker_max = 0); + + /** creates kernel for the problem described in desc */ + static kernel_t *create(const desc_t &desc); + +protected: + const desc_t desc_; + const prb_t &prb_ = desc_.prb; + void (*ker_)(const call_param_t *); +}; + +/* TODO: add trans_t class */ + +} + +/* for cpu reorder list */ +status_t jit_uni_reorder_create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md); + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp new file mode 100644 index 0000000000..69b7a33604 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp @@ -0,0 +1,313 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "memory_desc_wrapper.hpp" +#include "mkldnn_debug.h" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "jit_uni_reorder.hpp" + +using namespace mkldnn::impl::types; +using namespace mkldnn::impl::status; + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace tr { + +/** ad-hoc structure to describe blocked memory layout */ +struct layout_desc_t { + data_type_t dt; + int ndims; + dims_t id; + dims_t dims; + strides_t strides; +}; + +status_t cvt_mem_desc_to_layout_desc(const memory_desc_t &md_, + layout_desc_t &ld) { + const auto md = memory_desc_wrapper(md_); + + bool ok = true + && md.is_blocking_desc() + && md.extra().flags == 0; + if (!ok) return invalid_arguments; + + const auto &bd = md.blocking_desc(); + + ld.ndims = 0; + ld.dt = md.data_type(); + + auto P = [&ld](int id, int dim, ptrdiff_t stride) { + assert((size_t)ld.ndims < sizeof(ld.dims) / sizeof(ld.dims[0])); + ld.id[ld.ndims] = id; + ld.dims[ld.ndims] = dim; + ld.strides[ld.ndims] = stride; + ++ld.ndims; + }; + + dims_t blocks; + md.compute_blocks(blocks); + + for (int d = 0; d < md.ndims(); ++d) { + const int ld_ndims_start = ld.ndims; + if (blocks[d] != 1) { + stride_t stride = 1; + for (int iblk = bd.inner_nblks - 1; iblk >= 0; --iblk) { + if (bd.inner_idxs[iblk] == d) + P(d, bd.inner_blks[iblk], stride); + stride *= bd.inner_blks[iblk]; + } + } + P(d, md.padded_dims()[d] / blocks[d], bd.strides[d]); + + // TODO: NOW: revisit, do we need a reverse? + // TODO: NOW: consider using strides instead of block sizes in md + // reverse the order of dims + for (int ld_d = 0; ld_d < (ld.ndims - ld_ndims_start) / 2; ++ld_d) { + const int idx0 = ld_ndims_start + ld_d; + const int idx1 = ld.ndims - 1 - ld_d; + nstl::swap(ld.dims[idx0], ld.dims[idx1]); + nstl::swap(ld.strides[idx0], ld.strides[idx1]); + } + } + + return success; +} + +status_t prb_init(prb_t &p, const memory_desc_t &imd, const memory_desc_t &omd, + const primitive_attr_t *attr) { + auto im_d = memory_desc_wrapper(imd); + auto om_d = memory_desc_wrapper(omd); + + bool ok = true + && im_d.is_blocking_desc() + && om_d.is_blocking_desc() + && !im_d.has_zero_dim() + && !om_d.has_zero_dim(); + if (!ok) + return unimplemented; + + dims_t iblocks, oblocks; + im_d.compute_blocks(iblocks); + om_d.compute_blocks(oblocks); + + /* padding_dim consistency check */ + for (int d = 0; d < im_d.ndims(); ++d) { + const auto pdim = im_d.padded_dims()[d]; + bool ok = true + && pdim == om_d.padded_dims()[d] + && pdim % iblocks[d] == 0 + && pdim % oblocks[d] == 0; + if (!ok) return unimplemented; + } + + layout_desc_t ild, old; + status_t status = cvt_mem_desc_to_layout_desc(imd, ild); + if (status != success) return status; + status = cvt_mem_desc_to_layout_desc(omd, old); + if (status != success) return status; + + p.itype = ild.dt; + p.otype = old.dt; + + p.scale_type = attr->output_scales_.has_default_values() + ? scale_type_t::NONE + : (attr->output_scales_.mask_ == 0 + ? scale_type_t::COMMON + : scale_type_t::MANY); + + ptrdiff_t ss[max_ndims] = {0}; + if (p.scale_type == scale_type_t::MANY) { + ptrdiff_t last_ss = 1; + for (int d = old.ndims - 1; d >=0; --d) { + assert((d == 0 || old.id[d - 1] <= old.id[d]) + && "logical dimensions should be in ascending order"); + if (attr->output_scales_.mask_ & (1 << old.id[d])) { + ss[d] = last_ss; + last_ss *= old.dims[d]; + } + } + } + + int ndims = 0; + + int i_pos = 0; /* state for input -- current dimension */ + int o_pos = 0; /* state for output -- current dimension */ + + while (i_pos < ild.ndims && o_pos < old.ndims) { + assert(ild.id[i_pos] == old.id[o_pos]); + if (ild.id[i_pos] != old.id[o_pos]) + return runtime_error; + + assert(ndims < max_ndims); + if (ndims == max_ndims) + return runtime_error; + + if (ild.dims[i_pos] == old.dims[o_pos]) { + p.nodes[ndims].n = ild.dims[i_pos]; + p.nodes[ndims].is = ild.strides[i_pos]; + p.nodes[ndims].os = old.strides[o_pos]; + p.nodes[ndims].ss = ss[o_pos]; + ++ndims; + ++i_pos; + ++o_pos; + } else if (ild.dims[i_pos] < old.dims[o_pos]) { + assert(old.dims[o_pos] % ild.dims[i_pos] == 0); + int factor = old.dims[o_pos] / ild.dims[i_pos]; + p.nodes[ndims].n = ild.dims[i_pos]; + p.nodes[ndims].is = ild.strides[i_pos]; + p.nodes[ndims].os = old.strides[o_pos] * factor; + p.nodes[ndims].ss = ss[o_pos] * factor; + ++ndims; + ++i_pos; + old.dims[o_pos] = factor; + } else if (ild.dims[i_pos] > old.dims[o_pos]) { + assert(ild.dims[i_pos] % old.dims[o_pos] == 0); + int factor = ild.dims[i_pos] / old.dims[o_pos]; + p.nodes[ndims].n = old.dims[o_pos]; + p.nodes[ndims].is = ild.strides[i_pos] * factor; + p.nodes[ndims].os = old.strides[o_pos]; + p.nodes[ndims].ss = ss[o_pos]; + ++ndims; + ++o_pos; + ild.dims[i_pos] = factor; + } + } + p.ndims = ndims; + + dims_t zero_pos = {0}; + p.ioff = memory_desc_wrapper(imd).off_v(zero_pos); + p.ooff = memory_desc_wrapper(omd).off_v(zero_pos); + + const int sum_idx = attr->post_ops_.find(primitive_kind::sum); + p.beta = sum_idx == -1 ? 0.f : attr->post_ops_.entry_[sum_idx].sum.scale; + + return success; +} + +void prb_normalize(prb_t &p) { + for (int d = 0; d < p.ndims; ++d) { + int min_pos = d; + for (int j = d + 1; j < p.ndims; ++j) { + bool new_min = false + || p.nodes[j].os < p.nodes[min_pos].os + || (true + && p.nodes[j].os == p.nodes[min_pos].os + && p.nodes[j].n < p.nodes[min_pos].n); + if (new_min) min_pos = j; + } + if (min_pos != d) + nstl::swap(p.nodes[d], p.nodes[min_pos]); + } +} + +void prb_simplify(prb_t &p) { +#if defined(__GNUC__) && __GNUC__ >= 4 +/* GCC produces bogus array subscript is above array bounds warning for + * the `p.nodes[j - 1] = p.nodes[j]` line below, so disable it for now. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif + for (int d = 0; d < p.ndims - 1; ++d) { + auto &this_node = p.nodes[d + 0]; + auto &next_node = p.nodes[d + 1]; + const bool fold = false + || next_node.n == (size_t)1 // trivial case, just drop next node + || (true // or real folding if possible + && next_node.is == (ptrdiff_t)this_node.n * this_node.is + && next_node.os == (ptrdiff_t)this_node.n * this_node.os + && next_node.ss == (ptrdiff_t)this_node.n * this_node.ss); + if (fold) { + this_node.n *= next_node.n; + for (int j = d + 2; j < p.ndims; ++j) + p.nodes[j - 1] = p.nodes[j]; + --p.ndims; + --d; // make another try + } + } +#if defined(__GNUC__) && __GNUC__ >= 4 +#pragma GCC diagnostic pop +#endif +} + +void prb_node_split(prb_t &p, int dim, size_t n1) { + assert(dim < p.ndims); + assert(p.ndims < max_ndims); + assert(p.nodes[dim].n % n1 == 0); + + p.ndims += 1; + + for (int d = p.ndims; d > dim + 1; --d) + p.nodes[d] = p.nodes[d - 1]; + + p.nodes[dim + 1].n = p.nodes[dim].n / n1; + p.nodes[dim + 1].is = p.nodes[dim].is * n1; + p.nodes[dim + 1].os = p.nodes[dim].os * n1; + p.nodes[dim + 1].ss = p.nodes[dim].ss * n1; + + p.nodes[dim].n = n1; +} + +void prb_node_swap(prb_t &p, int d0, int d1) { + assert(d0 < p.ndims); + assert(d1 < p.ndims); + assert(p.ndims < max_ndims); + + if (d0 == d1) return; + + nstl::swap(p.nodes[d0], p.nodes[d1]); +} + +void prb_node_move(prb_t &p, int d0, int d1) { + assert(d0 < p.ndims); + assert(d1 < p.ndims); + assert(p.ndims < max_ndims); + + if (d0 == d1) return; + + node_t node = p.nodes[d0]; + + if (d0 < d1) + for (int d = d0; d < d1; ++d) + p.nodes[d] = p.nodes[d + 1]; + else + for (int d = d0; d > d1; --d) + p.nodes[d] = p.nodes[d - 1]; + + p.nodes[d1] = node; +} + +void prb_dump(const prb_t &p) { + printf("@@@ type:%s:%s ndims:%d ", mkldnn_dt2str(p.itype), + mkldnn_dt2str(p.otype), p.ndims); + for (int d = 0; d < p.ndims; ++d) + printf("[%zu:%td:%td:%td]", + p.nodes[d].n, p.nodes[d].is, p.nodes[d].os, p.nodes[d].ss); + printf(" off:%zu:%zu\n", p.ioff, p.ooff); +} + +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp new file mode 100644 index 0000000000..08747aa89c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp @@ -0,0 +1,115 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "utils.hpp" + +#ifndef MKLDNN_ENABLE_JIT_PROFILING +#define MKLDNN_ENABLE_JIT_PROFILING 1 +#endif + +#ifndef MKLDNN_ENABLE_JIT_DUMP +#define MKLDNN_ENABLE_JIT_DUMP 1 +#endif + +#if MKLDNN_ENABLE_JIT_PROFILING +#include "jitprofiling/jitprofiling.h" +#endif + +namespace mkldnn { +namespace impl { +namespace cpu { +namespace jit_utils { + +// WARNING: These functions are not thread safe and must be protected by a +// mutex + +void dump_jit_code(const void *code, size_t code_size, const char *code_name) +{ +#if MKLDNN_ENABLE_JIT_DUMP + if (code && jit_dump_enabled()) { + static int counter = 0; +#define MAX_FNAME_LEN 256 + char fname[MAX_FNAME_LEN + 1]; + // TODO (Roma): support prefix for code / linux perf dumps + snprintf(fname, MAX_FNAME_LEN, "mkldnn_dump_%s.%d.bin", code_name, + counter); + counter++; + + FILE *fp = fopen(fname, "w+"); + // Failure to dump code is not fatal + if (fp) { + size_t unused = fwrite(code, code_size, 1, fp); + UNUSED(unused); + fclose(fp); + } + } +#undef MAX_FNAME_LEN +#else + UNUSED(code); + UNUSED(code_size); + UNUSED(code_name); +#endif +} + +void register_jit_code_vtune(const void *code, size_t code_size, + const char *code_name, const char *source_file_name) +{ +#if MKLDNN_ENABLE_JIT_PROFILING + if (iJIT_IsProfilingActive() == iJIT_SAMPLING_ON) { + auto jmethod = iJIT_Method_Load(); + jmethod.method_id = iJIT_GetNewMethodID(); // XXX: not thread-safe + jmethod.method_name = (char *)code_name; // XXX: dropping const + jmethod.class_file_name = NULL; + jmethod.source_file_name = (char *)source_file_name; // XXX: dropping const + jmethod.method_load_address = (void *)code; + jmethod.method_size = (unsigned int)code_size; + + iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, + (void*)&jmethod); + } +#else + UNUSED(code); + UNUSED(code_size); + UNUSED(code_name); + UNUSED(source_file_name); +#endif +} + +void register_jit_code(const void *code, size_t code_size, + const char *code_name, const char *source_file_name) +{ + // The #ifdef guards are required to avoid generating a function that only + // consists of lock and unlock code +#if MKLDNN_ENABLE_JIT_PROFILING || MKLDNN_ENABLE_JIT_DUMP + static std::mutex m; + std::lock_guard guard(m); + + dump_jit_code(code, code_size, code_name); + register_jit_code_vtune(code, code_size, code_name, source_file_name); +#else + UNUSED(code); + UNUSED(code_size); + UNUSED(code_name); + UNUSED(source_file_name); +#endif +} + +} +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp new file mode 100644 index 0000000000..2f52dba4ac --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp @@ -0,0 +1,32 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef JIT_SUPPORT_HPP +#define JIT_SUPPORT_HPP + +namespace mkldnn { +namespace impl { +namespace cpu { +namespace jit_utils { + +void register_jit_code(const void *code, size_t code_size, + const char *code_name, const char *source_file_name); + +} +} +} +} +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD new file mode 100644 index 0000000000..4fd21cea57 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD @@ -0,0 +1,27 @@ +Copyright (c) 2011, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md new file mode 100644 index 0000000000..fc67c4f134 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md @@ -0,0 +1 @@ +This code is from [Intel SEAPI library](https://github.com/intel/IntelSEAPI) diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h new file mode 100644 index 0000000000..edbf4a15f0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h @@ -0,0 +1,595 @@ +/* + + Contact Information: + http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/ + + BSD LICENSE + + Copyright (c) 2005-2014 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _ITTNOTIFY_CONFIG_H_ +#define _ITTNOTIFY_CONFIG_H_ + +/** @cond exclude_from_documentation */ +#ifndef ITT_OS_WIN +# define ITT_OS_WIN 1 +#endif /* ITT_OS_WIN */ + +#ifndef ITT_OS_LINUX +# define ITT_OS_LINUX 2 +#endif /* ITT_OS_LINUX */ + +#ifndef ITT_OS_MAC +# define ITT_OS_MAC 3 +#endif /* ITT_OS_MAC */ + +#ifndef ITT_OS_FREEBSD +# define ITT_OS_FREEBSD 4 +#endif /* ITT_OS_FREEBSD */ + +#ifndef ITT_OS +# if defined WIN32 || defined _WIN32 +# define ITT_OS ITT_OS_WIN +# elif defined( __APPLE__ ) && defined( __MACH__ ) +# define ITT_OS ITT_OS_MAC +# elif defined( __FreeBSD__ ) +# define ITT_OS ITT_OS_FREEBSD +# else +# define ITT_OS ITT_OS_LINUX +# endif +#endif /* ITT_OS */ + +#ifndef ITT_PLATFORM_WIN +# define ITT_PLATFORM_WIN 1 +#endif /* ITT_PLATFORM_WIN */ + +#ifndef ITT_PLATFORM_POSIX +# define ITT_PLATFORM_POSIX 2 +#endif /* ITT_PLATFORM_POSIX */ + +#ifndef ITT_PLATFORM_MAC +# define ITT_PLATFORM_MAC 3 +#endif /* ITT_PLATFORM_MAC */ + +#ifndef ITT_PLATFORM_FREEBSD +# define ITT_PLATFORM_FREEBSD 4 +#endif /* ITT_PLATFORM_FREEBSD */ + +#ifndef ITT_PLATFORM +# if ITT_OS==ITT_OS_WIN +# define ITT_PLATFORM ITT_PLATFORM_WIN +# elif ITT_OS==ITT_OS_MAC +# define ITT_PLATFORM ITT_PLATFORM_MAC +# elif ITT_OS==ITT_OS_FREEBSD +# define ITT_PLATFORM ITT_PLATFORM_FREEBSD +# else +# define ITT_PLATFORM ITT_PLATFORM_POSIX +# endif +#endif /* ITT_PLATFORM */ + +#if defined(_UNICODE) && !defined(UNICODE) +#define UNICODE +#endif + +#include +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include +#if defined(UNICODE) || defined(_UNICODE) +#include +#endif /* UNICODE || _UNICODE */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#ifndef ITTAPI_CDECL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define ITTAPI_CDECL __cdecl +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_IX86 || defined __i386__ +# define ITTAPI_CDECL __attribute__ ((cdecl)) +# else /* _M_IX86 || __i386__ */ +# define ITTAPI_CDECL /* actual only on x86 platform */ +# endif /* _M_IX86 || __i386__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* ITTAPI_CDECL */ + +#ifndef STDCALL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define STDCALL __stdcall +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_IX86 || defined __i386__ +# define STDCALL __attribute__ ((stdcall)) +# else /* _M_IX86 || __i386__ */ +# define STDCALL /* supported only on x86 platform */ +# endif /* _M_IX86 || __i386__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* STDCALL */ + +#define ITTAPI ITTAPI_CDECL +#define LIBITTAPI ITTAPI_CDECL + +/* TODO: Temporary for compatibility! */ +#define ITTAPI_CALL ITTAPI_CDECL +#define LIBITTAPI_CALL ITTAPI_CDECL + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +/* use __forceinline (VC++ specific) */ +#define ITT_INLINE __forceinline +#define ITT_INLINE_ATTRIBUTE /* nothing */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/* + * Generally, functions are not inlined unless optimization is specified. + * For functions declared inline, this attribute inlines the function even + * if no optimization level was specified. + */ +#ifdef __STRICT_ANSI__ +#define ITT_INLINE static +#define ITT_INLINE_ATTRIBUTE __attribute__((unused)) +#else /* __STRICT_ANSI__ */ +#define ITT_INLINE static inline +#define ITT_INLINE_ATTRIBUTE __attribute__((always_inline, unused)) +#endif /* __STRICT_ANSI__ */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/** @endcond */ + +#ifndef ITT_ARCH_IA32 +# define ITT_ARCH_IA32 1 +#endif /* ITT_ARCH_IA32 */ + +#ifndef ITT_ARCH_IA32E +# define ITT_ARCH_IA32E 2 +#endif /* ITT_ARCH_IA32E */ + +#ifndef ITT_ARCH_ARM +# define ITT_ARCH_ARM 4 +#endif /* ITT_ARCH_ARM */ + +#ifndef ITT_ARCH_PPC64 +# define ITT_ARCH_PPC64 5 +#endif /* ITT_ARCH_PPC64 */ + +#ifndef ITT_ARCH +# if defined _M_IX86 || defined __i386__ +# define ITT_ARCH ITT_ARCH_IA32 +# elif defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define ITT_ARCH ITT_ARCH_IA32E +# elif defined _M_IA64 || defined __ia64__ +# define ITT_ARCH ITT_ARCH_IA64 +# elif defined _M_ARM || defined __arm__ +# define ITT_ARCH ITT_ARCH_ARM +# elif defined __powerpc64__ +# define ITT_ARCH ITT_ARCH_PPC64 +# endif +#endif + +#ifdef __cplusplus +# define ITT_EXTERN_C extern "C" +# define ITT_EXTERN_C_BEGIN extern "C" { +# define ITT_EXTERN_C_END } +#else +# define ITT_EXTERN_C /* nothing */ +# define ITT_EXTERN_C_BEGIN /* nothing */ +# define ITT_EXTERN_C_END /* nothing */ +#endif /* __cplusplus */ + +#define ITT_TO_STR_AUX(x) #x +#define ITT_TO_STR(x) ITT_TO_STR_AUX(x) + +#define __ITT_BUILD_ASSERT(expr, suffix) do { \ + static char __itt_build_check_##suffix[(expr) ? 1 : -1]; \ + __itt_build_check_##suffix[0] = 0; \ +} while(0) +#define _ITT_BUILD_ASSERT(expr, suffix) __ITT_BUILD_ASSERT((expr), suffix) +#define ITT_BUILD_ASSERT(expr) _ITT_BUILD_ASSERT((expr), __LINE__) + +#define ITT_MAGIC { 0xED, 0xAB, 0xAB, 0xEC, 0x0D, 0xEE, 0xDA, 0x30 } + +/* Replace with snapshot date YYYYMMDD for promotion build. */ +#define API_VERSION_BUILD 20151119 + +#ifndef API_VERSION_NUM +#define API_VERSION_NUM 0.0.0 +#endif /* API_VERSION_NUM */ + +#define API_VERSION "ITT-API-Version " ITT_TO_STR(API_VERSION_NUM) \ + " (" ITT_TO_STR(API_VERSION_BUILD) ")" + +/* OS communication functions */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include +typedef HMODULE lib_t; +typedef DWORD TIDT; +typedef CRITICAL_SECTION mutex_t; +#define MUTEX_INITIALIZER { 0 } +#define strong_alias(name, aliasname) /* empty for Windows */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include +#if defined(UNICODE) || defined(_UNICODE) +#include +#endif /* UNICODE */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 /* need for PTHREAD_MUTEX_RECURSIVE */ +#endif /* _GNU_SOURCE */ +#ifndef __USE_UNIX98 +#define __USE_UNIX98 1 /* need for PTHREAD_MUTEX_RECURSIVE, on SLES11.1 with gcc 4.3.4 wherein pthread.h missing dependency on __USE_XOPEN2K8 */ +#endif /*__USE_UNIX98*/ +#include +typedef void* lib_t; +typedef pthread_t TIDT; +typedef pthread_mutex_t mutex_t; +#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +#define strong_alias(name, aliasname) _strong_alias(name, aliasname) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_get_proc(lib, name) GetProcAddress(lib, name) +#define __itt_mutex_init(mutex) InitializeCriticalSection(mutex) +#define __itt_mutex_lock(mutex) EnterCriticalSection(mutex) +#define __itt_mutex_unlock(mutex) LeaveCriticalSection(mutex) +#define __itt_load_lib(name) LoadLibraryA(name) +#define __itt_unload_lib(handle) FreeLibrary(handle) +#define __itt_system_error() (int)GetLastError() +#define __itt_fstrcmp(s1, s2) lstrcmpA(s1, s2) +#define __itt_fstrnlen(s, l) strnlen_s(s, l) +#define __itt_fstrcpyn(s1, b, s2, l) strncpy_s(s1, b, s2, l) +#define __itt_fstrdup(s) _strdup(s) +#define __itt_thread_id() GetCurrentThreadId() +#define __itt_thread_yield() SwitchToThread() +#ifndef ITT_SIMPLE_INIT +ITT_INLINE long +__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE; +ITT_INLINE long __itt_interlocked_increment(volatile long* ptr) +{ + return InterlockedIncrement(ptr); +} +#endif /* ITT_SIMPLE_INIT */ + +#define DL_SYMBOLS (1) +#define PTHREAD_SYMBOLS (1) + +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +#define __itt_get_proc(lib, name) dlsym(lib, name) +#define __itt_mutex_init(mutex) {\ + pthread_mutexattr_t mutex_attr; \ + int error_code = pthread_mutexattr_init(&mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_init", \ + error_code); \ + error_code = pthread_mutexattr_settype(&mutex_attr, \ + PTHREAD_MUTEX_RECURSIVE); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_settype", \ + error_code); \ + error_code = pthread_mutex_init(mutex, &mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutex_init", \ + error_code); \ + error_code = pthread_mutexattr_destroy(&mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_destroy", \ + error_code); \ +} +#define __itt_mutex_lock(mutex) pthread_mutex_lock(mutex) +#define __itt_mutex_unlock(mutex) pthread_mutex_unlock(mutex) +#define __itt_load_lib(name) dlopen(name, RTLD_LAZY) +#define __itt_unload_lib(handle) dlclose(handle) +#define __itt_system_error() errno +#define __itt_fstrcmp(s1, s2) strcmp(s1, s2) + +/* makes customer code define safe APIs for SDL_STRNLEN_S and SDL_STRNCPY_S */ +#ifdef SDL_STRNLEN_S +#define __itt_fstrnlen(s, l) SDL_STRNLEN_S(s, l) +#else +#define __itt_fstrnlen(s, l) strlen(s) +#endif /* SDL_STRNLEN_S */ +#ifdef SDL_STRNCPY_S +#define __itt_fstrcpyn(s1, b, s2, l) SDL_STRNCPY_S(s1, b, s2, l) +#else +#define __itt_fstrcpyn(s1, b, s2, l) strncpy(s1, s2, l) +#endif /* SDL_STRNCPY_S */ + +#define __itt_fstrdup(s) strdup(s) +#define __itt_thread_id() pthread_self() +#define __itt_thread_yield() sched_yield() +#if ITT_ARCH==ITT_ARCH_IA64 +#ifdef __INTEL_COMPILER +#define __TBB_machine_fetchadd4(addr, val) __fetchadd4_acq((void *)addr, val) +#else /* __INTEL_COMPILER */ +/* TODO: Add Support for not Intel compilers for IA-64 architecture */ +#endif /* __INTEL_COMPILER */ +#elif ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_IA32E /* ITT_ARCH!=ITT_ARCH_IA64 */ +ITT_INLINE long +__TBB_machine_fetchadd4(volatile void* ptr, long addend) ITT_INLINE_ATTRIBUTE; +ITT_INLINE long __TBB_machine_fetchadd4(volatile void* ptr, long addend) +{ + long result; + __asm__ __volatile__("lock\nxadd %0,%1" + : "=r"(result),"=m"(*(int*)ptr) + : "0"(addend), "m"(*(int*)ptr) + : "memory"); + return result; +} +#elif ITT_ARCH==ITT_ARCH_ARM || ITT_ARCH==ITT_ARCH_PPC64 +#define __TBB_machine_fetchadd4(addr, val) __sync_fetch_and_add(addr, val) +#endif /* ITT_ARCH==ITT_ARCH_IA64 */ +#ifndef ITT_SIMPLE_INIT +ITT_INLINE long +__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE; +ITT_INLINE long __itt_interlocked_increment(volatile long* ptr) +{ + return __TBB_machine_fetchadd4(ptr, 1) + 1L; +} +#endif /* ITT_SIMPLE_INIT */ + +void* dlopen(const char*, int) __attribute__((weak)); +void* dlsym(void*, const char*) __attribute__((weak)); +int dlclose(void*) __attribute__((weak)); +#define DL_SYMBOLS (dlopen && dlsym && dlclose) + +int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*) __attribute__((weak)); +int pthread_mutex_lock(pthread_mutex_t*) __attribute__((weak)); +int pthread_mutex_unlock(pthread_mutex_t*) __attribute__((weak)); +int pthread_mutex_destroy(pthread_mutex_t*) __attribute__((weak)); +int pthread_mutexattr_init(pthread_mutexattr_t*) __attribute__((weak)); +int pthread_mutexattr_settype(pthread_mutexattr_t*, int) __attribute__((weak)); +int pthread_mutexattr_destroy(pthread_mutexattr_t*) __attribute__((weak)); +pthread_t pthread_self(void) __attribute__((weak)); +#define PTHREAD_SYMBOLS (pthread_mutex_init && pthread_mutex_lock && pthread_mutex_unlock && pthread_mutex_destroy && pthread_mutexattr_init && pthread_mutexattr_settype && pthread_mutexattr_destroy && pthread_self) + +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +typedef enum { + __itt_collection_normal = 0, + __itt_collection_paused = 1 +} __itt_collection_state; + +typedef enum { + __itt_thread_normal = 0, + __itt_thread_ignored = 1 +} __itt_thread_state; + +#pragma pack(push, 8) + +typedef struct ___itt_thread_info +{ + const char* nameA; /*!< Copy of original name in ASCII. */ +#if defined(UNICODE) || defined(_UNICODE) + const wchar_t* nameW; /*!< Copy of original name in UNICODE. */ +#else /* UNICODE || _UNICODE */ + void* nameW; +#endif /* UNICODE || _UNICODE */ + TIDT tid; + __itt_thread_state state; /*!< Thread state (paused or normal) */ + int extra1; /*!< Reserved to the runtime */ + void* extra2; /*!< Reserved to the runtime */ + struct ___itt_thread_info* next; +} __itt_thread_info; + +#include "ittnotify_types.h" /* For __itt_group_id definition */ + +typedef struct ___itt_api_info_20101001 +{ + const char* name; + void** func_ptr; + void* init_func; + __itt_group_id group; +} __itt_api_info_20101001; + +typedef struct ___itt_api_info +{ + const char* name; + void** func_ptr; + void* init_func; + void* null_func; + __itt_group_id group; +} __itt_api_info; + +typedef struct __itt_counter_info +{ + const char* nameA; /*!< Copy of original name in ASCII. */ +#if defined(UNICODE) || defined(_UNICODE) + const wchar_t* nameW; /*!< Copy of original name in UNICODE. */ +#else /* UNICODE || _UNICODE */ + void* nameW; +#endif /* UNICODE || _UNICODE */ + const char* domainA; /*!< Copy of original name in ASCII. */ +#if defined(UNICODE) || defined(_UNICODE) + const wchar_t* domainW; /*!< Copy of original name in UNICODE. */ +#else /* UNICODE || _UNICODE */ + void* domainW; +#endif /* UNICODE || _UNICODE */ + int type; + long index; + int extra1; /*!< Reserved to the runtime */ + void* extra2; /*!< Reserved to the runtime */ + struct __itt_counter_info* next; +} __itt_counter_info_t; + +struct ___itt_domain; +struct ___itt_string_handle; + +typedef struct ___itt_global +{ + unsigned char magic[8]; + unsigned long version_major; + unsigned long version_minor; + unsigned long version_build; + volatile long api_initialized; + volatile long mutex_initialized; + volatile long atomic_counter; + mutex_t mutex; + lib_t lib; + void* error_handler; + const char** dll_path_ptr; + __itt_api_info* api_list_ptr; + struct ___itt_global* next; + /* Joinable structures below */ + __itt_thread_info* thread_list; + struct ___itt_domain* domain_list; + struct ___itt_string_handle* string_list; + __itt_collection_state state; + __itt_counter_info_t* counter_list; +} __itt_global; + +#pragma pack(pop) + +#define NEW_THREAD_INFO_W(gptr,h,h_tail,t,s,n) { \ + h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \ + if (h != NULL) { \ + h->tid = t; \ + h->nameA = NULL; \ + h->nameW = n ? _wcsdup(n) : NULL; \ + h->state = s; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->thread_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_THREAD_INFO_A(gptr,h,h_tail,t,s,n) { \ + h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \ + if (h != NULL) { \ + h->tid = t; \ + h->nameA = n ? __itt_fstrdup(n) : NULL; \ + h->nameW = NULL; \ + h->state = s; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->thread_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_DOMAIN_W(gptr,h,h_tail,name) { \ + h = (__itt_domain*)malloc(sizeof(__itt_domain)); \ + if (h != NULL) { \ + h->flags = 1; /* domain is enabled by default */ \ + h->nameA = NULL; \ + h->nameW = name ? _wcsdup(name) : NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->domain_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_DOMAIN_A(gptr,h,h_tail,name) { \ + h = (__itt_domain*)malloc(sizeof(__itt_domain)); \ + if (h != NULL) { \ + h->flags = 1; /* domain is enabled by default */ \ + h->nameA = name ? __itt_fstrdup(name) : NULL; \ + h->nameW = NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->domain_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_STRING_HANDLE_W(gptr,h,h_tail,name) { \ + h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \ + if (h != NULL) { \ + h->strA = NULL; \ + h->strW = name ? _wcsdup(name) : NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->string_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_STRING_HANDLE_A(gptr,h,h_tail,name) { \ + h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \ + if (h != NULL) { \ + h->strA = name ? __itt_fstrdup(name) : NULL; \ + h->strW = NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->string_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_COUNTER_W(gptr,h,h_tail,name,domain,type) { \ + h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \ + if (h != NULL) { \ + h->nameA = NULL; \ + h->nameW = name ? _wcsdup(name) : NULL; \ + h->domainA = NULL; \ + h->domainW = name ? _wcsdup(domain) : NULL; \ + h->type = type; \ + h->index = 0; \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->counter_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_COUNTER_A(gptr,h,h_tail,name,domain,type) { \ + h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \ + if (h != NULL) { \ + h->nameA = name ? __itt_fstrdup(name) : NULL; \ + h->nameW = NULL; \ + h->domainA = domain ? __itt_fstrdup(domain) : NULL; \ + h->domainW = NULL; \ + h->type = type; \ + h->index = 0; \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->counter_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#endif /* _ITTNOTIFY_CONFIG_H_ */ diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h new file mode 100644 index 0000000000..99fbc24054 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h @@ -0,0 +1,94 @@ +/* + + Contact Information: + http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/ + + BSD LICENSE + + Copyright (c) 2005-2014 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ITTNOTIFY_TYPES_H_ +#define _ITTNOTIFY_TYPES_H_ + +typedef enum ___itt_group_id +{ + __itt_group_none = 0, + __itt_group_legacy = 1<<0, + __itt_group_control = 1<<1, + __itt_group_thread = 1<<2, + __itt_group_mark = 1<<3, + __itt_group_sync = 1<<4, + __itt_group_fsync = 1<<5, + __itt_group_jit = 1<<6, + __itt_group_model = 1<<7, + __itt_group_splitter_min = 1<<7, + __itt_group_counter = 1<<8, + __itt_group_frame = 1<<9, + __itt_group_stitch = 1<<10, + __itt_group_heap = 1<<11, + __itt_group_splitter_max = 1<<12, + __itt_group_structure = 1<<12, + __itt_group_suppress = 1<<13, + __itt_group_arrays = 1<<14, + __itt_group_all = -1 +} __itt_group_id; + +#pragma pack(push, 8) + +typedef struct ___itt_group_list +{ + __itt_group_id id; + const char* name; +} __itt_group_list; + +#pragma pack(pop) + +#define ITT_GROUP_LIST(varname) \ + static __itt_group_list varname[] = { \ + { __itt_group_all, "all" }, \ + { __itt_group_control, "control" }, \ + { __itt_group_thread, "thread" }, \ + { __itt_group_mark, "mark" }, \ + { __itt_group_sync, "sync" }, \ + { __itt_group_fsync, "fsync" }, \ + { __itt_group_jit, "jit" }, \ + { __itt_group_model, "model" }, \ + { __itt_group_counter, "counter" }, \ + { __itt_group_frame, "frame" }, \ + { __itt_group_stitch, "stitch" }, \ + { __itt_group_heap, "heap" }, \ + { __itt_group_structure, "structure" }, \ + { __itt_group_suppress, "suppress" }, \ + { __itt_group_arrays, "arrays" }, \ + { __itt_group_none, NULL } \ + } + +#endif /* _ITTNOTIFY_TYPES_H_ */ diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c new file mode 100644 index 0000000000..15f4b9929b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c @@ -0,0 +1,293 @@ +/* + + Contact Information: + http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/ + + BSD LICENSE + + Copyright (c) 2005-2014 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ittnotify_config.h" + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM != ITT_PLATFORM_MAC && ITT_PLATFORM != ITT_PLATFORM_FREEBSD +#include +#endif +#include + +#include "jitprofiling.h" + +static const char rcsid[] = "\n@(#) $Revision: 471937 $\n"; + +#define DLL_ENVIRONMENT_VAR "VS_PROFILER" + +#ifndef NEW_DLL_ENVIRONMENT_VAR +#if ITT_ARCH==ITT_ARCH_IA32 +#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER32" +#else +#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER64" +#endif +#endif /* NEW_DLL_ENVIRONMENT_VAR */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define DEFAULT_DLLNAME "JitPI.dll" +HINSTANCE m_libHandle = NULL; +#elif ITT_PLATFORM==ITT_PLATFORM_MAC +#define DEFAULT_DLLNAME "libJitPI.dylib" +void* m_libHandle = NULL; +#else +#define DEFAULT_DLLNAME "libJitPI.so" +void* m_libHandle = NULL; +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/* default location of JIT profiling agent on Android */ +#define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so" + +/* the function pointers */ +typedef unsigned int(JITAPI *TPInitialize)(void); +static TPInitialize FUNC_Initialize=NULL; + +typedef unsigned int(JITAPI *TPNotify)(unsigned int, void*); +static TPNotify FUNC_NotifyEvent=NULL; + +static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING; + +/* end collector dll part. */ + +/* loadiJIT_Funcs() : this function is called just in the beginning + * and is responsible to load the functions from BistroJavaCollector.dll + * result: + * on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1 + * on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0 + */ +static int loadiJIT_Funcs(void); + +/* global representing whether the collector can't be loaded */ +static int iJIT_DLL_is_missing = 0; + +ITT_EXTERN_C int JITAPI +iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData) +{ + int ReturnValue = 0; + + /* initialization part - the collector has not been loaded yet. */ + if (!FUNC_NotifyEvent) + { + if (iJIT_DLL_is_missing) + return 0; + + if (!loadiJIT_Funcs()) + return 0; + } + + if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED || + event_type == iJVM_EVENT_TYPE_METHOD_UPDATE) + { + if (((piJIT_Method_Load)EventSpecificData)->method_id == 0) + return 0; + } + else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2) + { + if (((piJIT_Method_Load_V2)EventSpecificData)->method_id == 0) + return 0; + } + else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3) + { + if (((piJIT_Method_Load_V3)EventSpecificData)->method_id == 0) + return 0; + } + else if (event_type == iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED) + { + if (((piJIT_Method_Inline_Load)EventSpecificData)->method_id == 0 || + ((piJIT_Method_Inline_Load)EventSpecificData)->parent_method_id == 0) + return 0; + } + + ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData); + + return ReturnValue; +} + +ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive() +{ + if (!iJIT_DLL_is_missing) + { + loadiJIT_Funcs(); + } + + return executionMode; +} + +/* This function loads the collector dll and the relevant functions. + * on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1 + * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0 + */ +static int loadiJIT_Funcs() +{ + static int bDllWasLoaded = 0; + char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN + DWORD dNameLength = 0; +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + + if(bDllWasLoaded) + { + /* dll was already loaded, no need to do it for the second time */ + return 1; + } + + /* Assumes that the DLL will not be found */ + iJIT_DLL_is_missing = 1; + FUNC_NotifyEvent = NULL; + + if (m_libHandle) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + FreeLibrary(m_libHandle); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + dlclose(m_libHandle); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + m_libHandle = NULL; + } + + /* Try to get the dll name from the environment */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN + dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0); + if (dNameLength) + { + DWORD envret = 0; + dllName = (char*)malloc(sizeof(char) * (dNameLength + 1)); + if(dllName != NULL) + { + envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, + dllName, dNameLength); + if (envret) + { + /* Try to load the dll from the PATH... */ + m_libHandle = LoadLibraryExA(dllName, + NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + free(dllName); + } + } else { + /* Try to use old VS_PROFILER variable */ + dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0); + if (dNameLength) + { + DWORD envret = 0; + dllName = (char*)malloc(sizeof(char) * (dNameLength + 1)); + if(dllName != NULL) + { + envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, + dllName, dNameLength); + if (envret) + { + /* Try to load the dll from the PATH... */ + m_libHandle = LoadLibraryA(dllName); + } + free(dllName); + } + } + } +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + dllName = getenv(NEW_DLL_ENVIRONMENT_VAR); + if (!dllName) + dllName = getenv(DLL_ENVIRONMENT_VAR); +#if defined(__ANDROID__) || defined(ANDROID) + if (!dllName) + dllName = ANDROID_JIT_AGENT_PATH; +#endif + if (dllName) + { + /* Try to load the dll from the PATH... */ + m_libHandle = dlopen(dllName, RTLD_LAZY); + } +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + + if (!m_libHandle) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + m_libHandle = LoadLibraryA(DEFAULT_DLLNAME); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + } + + /* if the dll wasn't loaded - exit. */ + if (!m_libHandle) + { + iJIT_DLL_is_missing = 1; /* don't try to initialize + * JIT agent the second time + */ + return 0; + } + +#if ITT_PLATFORM==ITT_PLATFORM_WIN + FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent"); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + FUNC_NotifyEvent = (TPNotify)dlsym(m_libHandle, "NotifyEvent"); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + if (!FUNC_NotifyEvent) + { + FUNC_Initialize = NULL; + return 0; + } + +#if ITT_PLATFORM==ITT_PLATFORM_WIN + FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize"); +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + FUNC_Initialize = (TPInitialize)dlsym(m_libHandle, "Initialize"); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + if (!FUNC_Initialize) + { + FUNC_NotifyEvent = NULL; + return 0; + } + + executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize(); + + bDllWasLoaded = 1; + iJIT_DLL_is_missing = 0; /* DLL is ok. */ + + return 1; +} + +ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID() +{ + static unsigned int methodID = 1; + + if (methodID == 0) + return 0; /* ERROR : this is not a valid value */ + + return methodID++; +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h new file mode 100644 index 0000000000..bf0489b1a1 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h @@ -0,0 +1,673 @@ +/* + + Contact Information: + http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/ + + BSD LICENSE + + Copyright (c) 2005-2014 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __JITPROFILING_H__ +#define __JITPROFILING_H__ + +/** + * @brief JIT Profiling APIs + * + * The JIT Profiling API is used to report information about just-in-time + * generated code that can be used by performance tools. The user inserts + * calls in the code generator to report information before JIT-compiled + * code goes to execution. This information is collected at runtime and used + * by tools like Intel(R) VTune(TM) Amplifier to display performance metrics + * associated with JIT-compiled code. + * + * These APIs can be used to\n + * - **Profile trace-based and method-based JIT-compiled + * code**. Some examples of environments that you can profile with these APIs: + * dynamic JIT compilation of JavaScript code traces, JIT execution in OpenCL(TM) + * software technology, Java/.NET managed execution environments, and custom + * ISV JIT engines. + * @code + * #include + * + * if (iJIT_IsProfilingActive != iJIT_SAMPLING_ON) { + * return; + * } + * + * iJIT_Method_Load jmethod = {0}; + * jmethod.method_id = iJIT_GetNewMethodID(); + * jmethod.method_name = "method_name"; + * jmethod.class_file_name = "class_name"; + * jmethod.source_file_name = "source_file_name"; + * jmethod.method_load_address = code_addr; + * jmethod.method_size = code_size; + * + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod); + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, NULL); + * @endcode + * + * * Expected behavior: + * * If any iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event overwrites an + * already reported method, then such a method becomes invalid and its + * memory region is treated as unloaded. VTune Amplifier displays the metrics + * collected by the method until it is overwritten. + * * If supplied line number information contains multiple source lines for + * the same assembly instruction (code location), then VTune Amplifier picks up + * the first line number. + * * Dynamically generated code can be associated with a module name. + * Use the iJIT_Method_Load_V2 structure.\n + * Clarification of some cases: + * * If you register a function with the same method ID multiple times, + * specifying different module names, then the VTune Amplifier picks up + * the module name registered first. If you want to distinguish the same + * function between different JIT engines, supply different method IDs for + * each function. Other symbolic information (for example, source file) + * can be identical. + * + * - **Analyze split functions** (multiple joint or disjoint code regions + * belonging to the same function) **including re-JIT** + * with potential overlapping of code regions in time, which is common in + * resource-limited environments. + * @code + * #include + * + * unsigned int method_id = iJIT_GetNewMethodID(); + * + * iJIT_Method_Load a = {0}; + * a.method_id = method_id; + * a.method_load_address = 0x100; + * a.method_size = 0x20; + * + * iJIT_Method_Load b = {0}; + * b.method_id = method_id; + * b.method_load_address = 0x200; + * b.method_size = 0x30; + * + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&a); + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&b); + * @endcode + * + * * Expected behaviour: + * * If a iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event overwrites an + * already reported method, then such a method becomes invalid and + * its memory region is treated as unloaded. + * * All code regions reported with the same method ID are considered as + * belonging to the same method. Symbolic information (method name, + * source file name) will be taken from the first notification, and all + * subsequent notifications with the same method ID will be processed + * only for line number table information. So, the VTune Amplifier will map + * samples to a source line using the line number table from the current + * notification while taking the source file name from the very first one.\n + * Clarification of some cases:\n + * * If you register a second code region with a different source file + * name and the same method ID, then this information will be saved and + * will not be considered as an extension of the first code region, but + * VTune Amplifier will use the source file of the first code region and map + * performance metrics incorrectly. + * * If you register a second code region with the same source file as + * for the first region and the same method ID, then the source file will be + * discarded but VTune Amplifier will map metrics to the source file correctly. + * * If you register a second code region with a null source file and + * the same method ID, then provided line number info will be associated + * with the source file of the first code region. + * + * - **Explore inline functions** including multi-level hierarchy of + * nested inline methods which shows how performance metrics are distributed through them. + * @code + * #include + * + * // method_id parent_id + * // [-- c --] 3000 2000 + * // [---- d -----] 2001 1000 + * // [---- b ----] 2000 1000 + * // [------------ a ----------------] 1000 n/a + * + * iJIT_Method_Load a = {0}; + * a.method_id = 1000; + * + * iJIT_Method_Inline_Load b = {0}; + * b.method_id = 2000; + * b.parent_method_id = 1000; + * + * iJIT_Method_Inline_Load c = {0}; + * c.method_id = 3000; + * c.parent_method_id = 2000; + * + * iJIT_Method_Inline_Load d = {0}; + * d.method_id = 2001; + * d.parent_method_id = 1000; + * + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&a); + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&b); + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&c); + * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&d); + * @endcode + * + * * Requirements: + * * Each inline (iJIT_Method_Inline_Load) method should be associated + * with two method IDs: one for itself; one for its immediate parent. + * * Address regions of inline methods of the same parent method cannot + * overlap each other. + * * Execution of the parent method must not be started until it and all + * its inline methods are reported. + * * Expected behaviour: + * * In case of nested inline methods an order of + * iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED events is not important. + * * If any event overwrites either inline method or top parent method, + * then the parent, including inline methods, becomes invalid and its memory + * region is treated as unloaded. + * + * **Life time of allocated data**\n + * The client sends an event notification to the agent with event-specific + * data, which is a structure. The pointers in the structure refer to memory + * allocated by the client, which responsible for releasing it. The pointers are + * used by the iJIT_NotifyEvent method to copy client's data in a trace file, + * and they are not used after the iJIT_NotifyEvent method returns. + */ + +/** + * @defgroup jitapi JIT Profiling + * @ingroup internal + * @{ + */ + +/** + * @brief Enumerator for the types of notifications + */ +typedef enum iJIT_jvm_event +{ + iJVM_EVENT_TYPE_SHUTDOWN = 2, /**<\brief Send this to shutdown the agent. + * Use NULL for event data. */ + + iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED = 13, /**<\brief Send when dynamic code is + * JIT compiled and loaded into + * memory by the JIT engine, but + * before the code is executed. + * Use iJIT_Method_Load as event + * data. */ +/** @cond exclude_from_documentation */ + iJVM_EVENT_TYPE_METHOD_UNLOAD_START, /**<\brief Send when compiled dynamic + * code is being unloaded from memory. + * Use iJIT_Method_Load as event data.*/ +/** @endcond */ + + iJVM_EVENT_TYPE_METHOD_UPDATE, /**<\brief Send to provide new content for + * a previously reported dynamic code. + * The previous content will be invalidated + * starting from the time of the notification. + * Use iJIT_Method_Load as event data but + * required fields are following: + * - method_id identify the code to update. + * - method_load_address specify start address + * within identified code range + * where update should be started. + * - method_size specify length of updated code + * range. */ + + + iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, /**<\brief Send when an inline dynamic + * code is JIT compiled and loaded + * into memory by the JIT engine, + * but before the parent code region + * starts executing. + * Use iJIT_Method_Inline_Load as event data.*/ + +/** @cond exclude_from_documentation */ + iJVM_EVENT_TYPE_METHOD_UPDATE_V2, +/** @endcond */ + + iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2 = 21, /**<\brief Send when a dynamic code is + * JIT compiled and loaded into + * memory by the JIT engine, but + * before the code is executed. + * Use iJIT_Method_Load_V2 as event data. */ + + iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3 /**<\brief Send when a dynamic code is + * JIT compiled and loaded into + * memory by the JIT engine, but + * before the code is executed. + * Use iJIT_Method_Load_V3 as event data. */ +} iJIT_JVM_EVENT; + +/** + * @brief Enumerator for the agent's mode + */ +typedef enum _iJIT_IsProfilingActiveFlags +{ + iJIT_NOTHING_RUNNING = 0x0000, /**<\brief The agent is not running; + * iJIT_NotifyEvent calls will + * not be processed. */ + iJIT_SAMPLING_ON = 0x0001, /**<\brief The agent is running and + * ready to process notifications. */ +} iJIT_IsProfilingActiveFlags; + +/** + * @brief Description of a single entry in the line number information of a code region. + * @details A table of line number entries gives information about how the reported code region + * is mapped to source file. + * Intel(R) VTune(TM) Amplifier uses line number information to attribute + * the samples (virtual address) to a line number. \n + * It is acceptable to report different code addresses for the same source line: + * @code + * Offset LineNumber + * 1 2 + * 12 4 + * 15 2 + * 18 1 + * 21 30 + * + * VTune Amplifier constructs the following table using the client data + * + * Code subrange Line number + * 0-1 2 + * 1-12 4 + * 12-15 2 + * 15-18 1 + * 18-21 30 + * @endcode + */ +typedef struct _LineNumberInfo +{ + unsigned int Offset; /**<\brief Offset from the begining of the code region. */ + unsigned int LineNumber; /**<\brief Matching source line number offset (from beginning of source file). */ + +} *pLineNumberInfo, LineNumberInfo; + +/** + * @brief Enumerator for the code architecture. + */ +typedef enum _iJIT_CodeArchitecture +{ + iJIT_CA_NATIVE = 0, /**<\brief Native to the process architecture that is calling it. */ + + iJIT_CA_32, /**<\brief 32-bit machine code. */ + + iJIT_CA_64 /**<\brief 64-bit machine code. */ + +} iJIT_CodeArchitecture; + +#pragma pack(push, 8) + +/** + * @brief Description of a JIT-compiled method + * @details When you use the iJIT_Method_Load structure to describe + * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED + * as an event type to report it. + */ +typedef struct _iJIT_Method_Load +{ + unsigned int method_id; /**<\brief Unique method ID. Cannot be 0. + * You must either use the API function + * iJIT_GetNewMethodID to get a valid and unique + * method ID, or else manage ID uniqueness + * and correct range by yourself.\n + * You must use the same method ID for all code + * regions of the same method, otherwise different + * method IDs specify different methods. */ + + char* method_name; /**<\brief The name of the method. It can be optionally + * prefixed with its class name and appended with + * its complete signature. Can't be NULL. */ + + void* method_load_address; /**<\brief The start virtual address of the method code + * region. If NULL, data provided with + * event are not accepted. */ + + unsigned int method_size; /**<\brief The code size of the method in memory. + * If 0, then data provided with the event are not + * accepted. */ + + unsigned int line_number_size; /**<\brief The number of entries in the line number + * table.0 if none. */ + + pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info + * array. Can be NULL if + * line_number_size is 0. See + * LineNumberInfo Structure for a + * description of a single entry in + * the line number info array */ + + unsigned int class_id; /**<\brief This field is obsolete. */ + + char* class_file_name; /**<\brief Class name. Can be NULL.*/ + + char* source_file_name; /**<\brief Source file name. Can be NULL.*/ + +} *piJIT_Method_Load, iJIT_Method_Load; + +/** + * @brief Description of a JIT-compiled method + * @details When you use the iJIT_Method_Load_V2 structure to describe + * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2 + * as an event type to report it. + */ +typedef struct _iJIT_Method_Load_V2 +{ + unsigned int method_id; /**<\brief Unique method ID. Cannot be 0. + * You must either use the API function + * iJIT_GetNewMethodID to get a valid and unique + * method ID, or else manage ID uniqueness + * and correct range by yourself.\n + * You must use the same method ID for all code + * regions of the same method, otherwise different + * method IDs specify different methods. */ + + char* method_name; /**<\brief The name of the method. It can be optionally + * prefixed with its class name and appended with + * its complete signature. Can't be NULL. */ + + void* method_load_address; /**<\brief The start virtual address of the method code + * region. If NULL, then data provided with the + * event are not accepted. */ + + unsigned int method_size; /**<\brief The code size of the method in memory. + * If 0, then data provided with the event are not + * accepted. */ + + unsigned int line_number_size; /**<\brief The number of entries in the line number + * table. 0 if none. */ + + pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info + * array. Can be NULL if + * line_number_size is 0. See + * LineNumberInfo Structure for a + * description of a single entry in + * the line number info array. */ + + char* class_file_name; /**<\brief Class name. Can be NULL. */ + + char* source_file_name; /**<\brief Source file name. Can be NULL. */ + + char* module_name; /**<\brief Module name. Can be NULL. + The module name can be useful for distinguishing among + different JIT engines. VTune Amplifier will display + reported methods grouped by specific module. */ + +} *piJIT_Method_Load_V2, iJIT_Method_Load_V2; + +/** + * @brief Description of a JIT-compiled method + * @details The iJIT_Method_Load_V3 structure is the same as iJIT_Method_Load_V2 + * with a newly introduced 'arch' field that specifies architecture of the code region. + * When you use the iJIT_Method_Load_V3 structure to describe + * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3 + * as an event type to report it. + */ +typedef struct _iJIT_Method_Load_V3 +{ + unsigned int method_id; /**<\brief Unique method ID. Cannot be 0. + * You must either use the API function + * iJIT_GetNewMethodID to get a valid and unique + * method ID, or manage ID uniqueness + * and correct range by yourself.\n + * You must use the same method ID for all code + * regions of the same method, otherwise they are + * treated as regions of different methods. */ + + char* method_name; /**<\brief The name of the method. It can be optionally + * prefixed with its class name and appended with + * its complete signature. Cannot be NULL. */ + + void* method_load_address; /**<\brief The start virtual address of the method code + * region. If NULL, then data provided with the + * event are not accepted. */ + + unsigned int method_size; /**<\brief The code size of the method in memory. + * If 0, then data provided with the event are not + * accepted. */ + + unsigned int line_number_size; /**<\brief The number of entries in the line number + * table. 0 if none. */ + + pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info + * array. Can be NULL if + * line_number_size is 0. See + * LineNumberInfo Structure for a + * description of a single entry in + * the line number info array. */ + + char* class_file_name; /**<\brief Class name. Can be NULL. */ + + char* source_file_name; /**<\brief Source file name. Can be NULL. */ + + char* module_name; /**<\brief Module name. Can be NULL. + * The module name can be useful for distinguishing among + * different JIT engines. VTune Amplifier will display + * reported methods grouped by specific module. */ + + iJIT_CodeArchitecture module_arch; /**<\brief Architecture of the method's code region. + * By default, it is the same as the process + * architecture that is calling it. + * For example, you can use it if your 32-bit JIT + * engine generates 64-bit code. + * + * If JIT engine reports both 32-bit and 64-bit types + * of methods then VTune Amplifier splits the methods + * with the same module name but with different + * architectures in two different modules. VTune Amplifier + * modifies the original name provided with a 64-bit method + * version by ending it with '(64)' */ + +} *piJIT_Method_Load_V3, iJIT_Method_Load_V3; + +/** + * @brief Description of an inline JIT-compiled method + * @details When you use the_iJIT_Method_Inline_Load structure to describe + * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED + * as an event type to report it. + */ +typedef struct _iJIT_Method_Inline_Load +{ + unsigned int method_id; /**<\brief Unique method ID. Cannot be 0. + * You must either use the API function + * iJIT_GetNewMethodID to get a valid and unique + * method ID, or else manage ID uniqueness + * and correct range by yourself. */ + + unsigned int parent_method_id; /**<\brief Unique immediate parent's method ID. + * Cannot be 0. + * You must either use the API function + * iJIT_GetNewMethodID to get a valid and unique + * method ID, or else manage ID uniqueness + * and correct range by yourself. */ + + char* method_name; /**<\brief The name of the method. It can be optionally + * prefixed with its class name and appended with + * its complete signature. Can't be NULL. */ + + void* method_load_address; /** <\brief The virtual address on which the method + * is inlined. If NULL, then data provided with + * the event are not accepted. */ + + unsigned int method_size; /**<\brief The code size of the method in memory. + * If 0, then data provided with the event are not + * accepted. */ + + unsigned int line_number_size; /**<\brief The number of entries in the line number + * table. 0 if none. */ + + pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info + * array. Can be NULL if + * line_number_size is 0. See + * LineNumberInfo Structure for a + * description of a single entry in + * the line number info array */ + + char* class_file_name; /**<\brief Class name. Can be NULL.*/ + + char* source_file_name; /**<\brief Source file name. Can be NULL.*/ + +} *piJIT_Method_Inline_Load, iJIT_Method_Inline_Load; + +/** @cond exclude_from_documentation */ +/** + * @brief Description of a segment type + * @details Use the segment type to specify a type of data supplied + * with the iJVM_EVENT_TYPE_METHOD_UPDATE_V2 event to be applied to + * a certain code trace. + */ +typedef enum _iJIT_SegmentType +{ + iJIT_CT_UNKNOWN = 0, + + iJIT_CT_CODE, /**<\brief Executable code. */ + + iJIT_CT_DATA, /**<\brief Data (not executable code). + * VTune Amplifier uses the format string + * (see iJIT_Method_Update) to represent + * this data in the VTune Amplifier GUI */ + + iJIT_CT_KEEP, /**<\brief Use the previous markup for the trace. + * Can be used for the following + * iJVM_EVENT_TYPE_METHOD_UPDATE_V2 events, + * if the type of the previously reported segment + * type is the same. */ + iJIT_CT_EOF +} iJIT_SegmentType; + +/** + * @brief Description of a dynamic update of the content within JIT-compiled method + * @details The JIT engine may generate the methods that are updated at runtime + * partially by mixed (data + executable code) content. When you use the iJIT_Method_Update + * structure to describe the update of the content within a JIT-compiled method, + * use iJVM_EVENT_TYPE_METHOD_UPDATE_V2 as an event type to report it. + * + * On the first Update event, VTune Amplifier copies the original code range reported by + * the iJVM_EVENT_TYPE_METHOD_LOAD event, then modifies it with the supplied bytes and + * adds the modified range to the original method. For next update events, VTune Amplifier + * does the same but it uses the latest modified version of a code region for update. + * Eventually, VTune Amplifier GUI displays multiple code ranges for the method reported by + * the iJVM_EVENT_TYPE_METHOD_LOAD event. + * Notes: + * - Multiple update events with different types for the same trace are allowed + * but they must be reported for the same code ranges. + * Example, + * @code + * [-- data---] Allowed + * [-- code --] Allowed + * [code] Ignored + * [-- data---] Allowed + * [-- code --] Allowed + * [------------ trace ---------] + * @endcode + * - The types of previously reported events can be changed but they must be reported + * for the same code ranges. + * Example, + * @code + * [-- data---] Allowed + * [-- code --] Allowed + * [-- data---] Allowed + * [-- code --] Allowed + * [------------ trace ---------] + * @endcode + */ + +typedef struct _iJIT_Method_Update +{ + void* load_address; /**<\brief Start address of the update within a method */ + + unsigned int size; /**<\brief The update size */ + + iJIT_SegmentType type; /**<\brief Type of the update */ + + const char* data_format; /**<\brief C string that contains a format string + * that follows the same specifications as format in printf. + * The format string is used for iJIT_CT_CODE only + * and cannot be NULL. + * Format can be changed on the fly. */ +} *piJIT_Method_Update, iJIT_Method_Update; + +/** @endcond */ + +#pragma pack(pop) + +/** @cond exclude_from_documentation */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef JITAPI_CDECL +# if defined WIN32 || defined _WIN32 +# define JITAPI_CDECL __cdecl +# else /* defined WIN32 || defined _WIN32 */ +# if defined _M_IX86 || defined __i386__ +# define JITAPI_CDECL __attribute__ ((cdecl)) +# else /* _M_IX86 || __i386__ */ +# define JITAPI_CDECL /* actual only on x86_64 platform */ +# endif /* _M_IX86 || __i386__ */ +# endif /* defined WIN32 || defined _WIN32 */ +#endif /* JITAPI_CDECL */ + +#define JITAPI JITAPI_CDECL +/** @endcond */ + +/** + * @brief Generates a new unique method ID. + * + * You must use this API to obtain unique and valid method IDs for methods or + * traces reported to the agent if you don't have your own mechanism to generate + * unique method IDs. + * + * @return a new unique method ID. When out of unique method IDs, this API + * returns 0, which is not an accepted value. + */ +unsigned int JITAPI iJIT_GetNewMethodID(void); + +/** + * @brief Returns the current mode of the agent. + * + * @return iJIT_SAMPLING_ON, indicating that agent is running, or + * iJIT_NOTHING_RUNNING if no agent is running. + */ +iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive(void); + +/** + * @brief Reports infomation about JIT-compiled code to the agent. + * + * The reported information is used to attribute samples obtained from any + * Intel(R) VTune(TM) Amplifier collector. This API needs to be called + * after JIT compilation and before the first entry into the JIT-compiled + * code. + * + * @param[in] event_type - type of the data sent to the agent + * @param[in] EventSpecificData - pointer to event-specific data + * + * @returns 1 on success, otherwise 0. + */ +int JITAPI iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +/** @endcond */ + +/** @} jitapi group */ + +#endif /* __JITPROFILING_H__ */ diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp new file mode 100644 index 0000000000..ef4c42bacf --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp @@ -0,0 +1,317 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" + +#include "nchw_pooling.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +void nchw_pooling_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + using namespace alg_kind; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(unsigned char *, MKLDNN_ARG_WORKSPACE); + + const memory_desc_wrapper ws_d(pd()->workspace_md()); + const data_type_t ws_dt = ws ? ws_d.data_type() : data_type::undef; + + const int MB = pd()->MB(); + const int C = pd()->C(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + const int SD = pd()->KSD(); + const int SH = pd()->KSH(); + const int SW = pd()->KSW(); + const int padF = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + + auto alg = pd()->desc()->alg_kind; + + auto apply_offset = [=](int index, int offset) { + return (index > offset) ? index - offset : 0; + }; + + auto set_ws = [=](int mb, int c, int od, int oh, int ow, int value) { + if (ws) { + assert(ws_dt == data_type::u8 || ws_dt == data_type::s32); + size_t ws_offset + = (size_t)OW * OH * OD * C * mb + + (size_t)OW * OH * OD * c + + (size_t)OW * OH * od + + (size_t)OW * oh + + (size_t)ow; + if (ws_dt == data_type::u8) { + assert(0 <= value && value <= 255); + ws[ws_offset] = value; + } else + reinterpret_cast(ws)[ws_offset] = value; + } + }; + + auto ker_max = [=](data_t *d, int mb, int c, int od, int oh, int ow) { + for (int kd = 0; kd < KD; ++kd) { + for (int kh = 0; kh < KH; ++kh) { + for (int kw = 0; kw < KW; ++kw) { + const int id = od * SD - padF + kd; + const int ih = oh * SH - padT + kh; + const int iw = ow * SW - padL + kw; + + if (id < 0 || id >= ID) continue; + if (ih < 0 || ih >= IH) continue; + if (iw < 0 || iw >= IW) continue; + + auto src_offset + = (size_t)IW * IH * ID * C * mb + + (size_t)IW * IH * ID * c + + (size_t)IW * IH * id + + (size_t)IW * ih + + (size_t)iw; + auto s = src[src_offset]; + if (s > d[0]) { + d[0] = s; + set_ws(mb, c, od, oh, ow, kd*KH*KW + kh*KW + kw); + } + } + } + } + }; + + auto ker_avg = [=](data_t *d, int mb, int c, int od, int oh, int ow) { + auto id_start = apply_offset(od*SD, padF); + auto ih_start = apply_offset(oh*SH, padT); + auto iw_start = apply_offset(ow*SW, padL); + auto id_end = nstl::min(od*SD - padF + KD, ID); + auto ih_end = nstl::min(oh*SH - padT + KH, IH); + auto iw_end = nstl::min(ow*SW - padL + KW, IW); + + auto num_summands = (alg == pooling_avg_include_padding) ? KD*KW*KH + : (id_end - id_start)*(ih_end - ih_start)*(iw_end - iw_start); + + for (int id = id_start; id < id_end; ++id) { + for (int ih = ih_start; ih < ih_end; ++ih) { + for (int iw = iw_start; iw < iw_end; ++iw) { + auto src_offset + = (size_t)IW * IH * ID * C * mb + + (size_t)IW * IH * ID * c + + (size_t)IW * IH * id + + (size_t)IW * ih + + (size_t)iw; + d[0] += src[src_offset]; + } + } + } + + d[0] = math::out_round((float)d[0] / num_summands); + }; + + + if (pd()->desc()->alg_kind == pooling_max) { + parallel_nd(MB, C, OD, OH, OW, + [&](int mb, int c, int od, int oh, int ow) { + size_t dst_offset + = (size_t)OW * OH * OD * C * mb + + (size_t)OW * OH * OD * c + + (size_t)OW * OH * od + + (size_t)OW * oh + + (size_t)ow; + data_t *d = &dst[dst_offset]; + d[0] = nstl::numeric_limits::lowest(); + set_ws(mb, c, od, oh, ow, 0); + ker_max(d, mb, c, od, oh, ow); + }); + } else { + parallel_nd(MB, C, OD, OH, OW, + [&](int mb, int c, int od, int oh, int ow) { + size_t dst_offset + = (size_t)OW * OH * OD * C * mb + + (size_t)OW * OH * OD * c + + (size_t)OW * OH * od + + (size_t)OW * oh + + (size_t)ow; + data_t *d = &dst[dst_offset]; + d[0] = 0; + ker_avg(d, mb, c, od, oh, ow); + }); + } +} + +template +void nchw_pooling_bwd_t::execute_backward( + const exec_ctx_t &ctx) const { + using namespace alg_kind; + + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto ws = CTX_IN_MEM(const unsigned char *, MKLDNN_ARG_WORKSPACE); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper ws_d(pd()->workspace_md()); + + const int MB = pd()->MB(); + const int C = pd()->C(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + const int SD = pd()->KSD(); + const int SH = pd()->KSH(); + const int SW = pd()->KSW(); + const int padF = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + + const bool is_3d = pd()->desc()->diff_src_desc.ndims == 5; + + auto alg = pd()->desc()->alg_kind; + + auto apply_offset = [=](int index, int offset) { + return (index > offset) ? index - offset : 0; + }; + + auto ker_zero = [=](int mb, int c) { + size_t diff_src_offset = (size_t)mb*C*ID*IH*IW + (size_t)c*ID*IH*IW; + for (int id = 0; id < ID; ++id) { + for (int ih = 0; ih < IH; ++ih) { + for (int iw = 0; iw < IW; ++iw) { + diff_src[diff_src_offset++] = 0; + } + } + } + }; + + auto ker_max = [=](const data_t *d, int mb, int c, int od, int oh, int ow) { + auto b_c = ws_d.blocking_desc().inner_nblks == 0 + ? 1 : ws_d.blocking_desc().inner_blks[0]; + auto ws_offset = is_3d + ? ws_d.blk_off(mb, c / b_c, od, oh, ow) + c % b_c + : ws_d.blk_off(mb, c / b_c, oh, ow) + c % b_c; + + const int index = ws_d.data_type() == data_type::u8 + ? (int)ws[ws_offset] : ((const int *)ws)[ws_offset]; + const int kw = index % KW; + const int kh = (index / KW) % KH; + const int kd = (index / KW) / KH; + + const int id = od * SD - padF + kd; + const int ih = oh * SH - padT + kh; + const int iw = ow * SW - padL + kw; + + // If padding area could fit the kernel, + // then input displacement would be out of bounds. + // No need to back propagate there as padding is + // virtual in pooling_max case. + if (id < 0 || id >= ID) + return; + if (ih < 0 || ih >= IH) + return; + if (iw < 0 || iw >= IW) + return; + + size_t diff_src_offset = + (size_t)mb*C*ID*IH*IW + (size_t)c*ID*IH*IW + (size_t)id*IH*IW + + (size_t)ih*IW + (size_t)iw; + diff_src[diff_src_offset] += d[0]; + }; + + auto ker_avg = [=](const data_t *d, int mb, int c, int od, int oh, int ow) { + auto id_start = apply_offset(od*SD, padF); + auto ih_start = apply_offset(oh*SH, padT); + auto iw_start = apply_offset(ow*SW, padL); + auto id_end = nstl::min(od*SD - padF + KD, ID); + auto ih_end = nstl::min(oh*SH - padT + KH, IH); + auto iw_end = nstl::min(ow*SW - padL + KW, IW); + + size_t num_summands = (alg == pooling_avg_include_padding) + ? (size_t)KW*KH*KD + : (size_t)(id_end - id_start)*(ih_end - ih_start) + *(iw_end - iw_start); + + for (int id = id_start; id < id_end; ++id) { + for (int ih = ih_start; ih < ih_end; ++ih) { + for (int iw = iw_start; iw < iw_end; ++iw) { + size_t diff_src_offset = (size_t)mb*C*ID*IH*IW + + (size_t)c*ID*IH*IW + (size_t)id*IH*IW + + (size_t)ih*IW + (size_t)iw; + diff_src[diff_src_offset] += d[0] / num_summands; + } + } + } + }; + + if (pd()->desc()->alg_kind == pooling_max) { + parallel_nd(MB, C, [&](int mb, int c) { + size_t diff_dst_offset = (size_t)mb*C*OD*OH*OW + + (size_t)c*OD*OH*OW; + ker_zero(mb, c); + for (int od = 0; od < OD; ++od) { + for (int oh = 0; oh < OH; ++oh) { + for (int ow = 0; ow < OW; ++ow) { + const data_t *d = &diff_dst[diff_dst_offset++]; + ker_max(d, mb, c, od, oh, ow); + } + } + } + }); + } else { + parallel_nd(MB, C, [&](int mb, int c) { + size_t diff_dst_offset = (size_t)mb*C*OD*OH*OW + + (size_t)c*OD*OH*OW; + ker_zero(mb, c); + for (int od = 0; od < OD; ++od) { + for (int oh = 0; oh < OH; ++oh) { + for (int ow = 0; ow < OW; ++ow) { + const data_t *d = &diff_dst[diff_dst_offset++]; + ker_avg(d, mb, c, od, oh, ow); + } + } + } + }); + } +} + +template struct nchw_pooling_fwd_t; +template struct nchw_pooling_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp new file mode 100644 index 0000000000..bbdd04f6b9 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp @@ -0,0 +1,147 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_NCHW_POOLING_HPP +#define CPU_NCHW_POOLING_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_pooling_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct nchw_pooling_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_fwd_pd_t { + using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t; + + DECLARE_COMMON_PD_T("nchw_pooling:any", nchw_pooling_fwd_t); + + status_t init() { + const format_tag_t desired_fmt_tag = + ndims() == 4 ? format_tag::nchw : format_tag::ncdhw; + + bool ok = true + && set_default_params() == status::success + && is_fwd() + && utils::one_of(desc()->alg_kind, alg_kind::pooling_max, + alg_kind::pooling_avg_include_padding, + alg_kind::pooling_avg_exclude_padding) + && !has_zero_dim_memory() + && utils::everyone_is(data_type, src_md()->data_type, + dst_md()->data_type) + && attr()->has_default_values() + && memory_desc_matches_tag(*src_md(), desired_fmt_tag) + && memory_desc_matches_tag(*dst_md(), desired_fmt_tag); + if (!ok) return status::unimplemented; + + bool is_training = desc_.prop_kind == prop_kind::forward_training; + if (desc()->alg_kind == alg_kind::pooling_max && is_training) + init_default_ws(); + + return status::success; + } + }; + + nchw_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct nchw_pooling_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_bwd_pd_t { + using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t; + + DECLARE_COMMON_PD_T("nchw:any", nchw_pooling_bwd_t); + + status_t init() { + const format_tag_t desired_fmt_tag = + ndims() == 4 ? format_tag::nchw : format_tag::ncdhw; + + bool ok = true + && set_default_params() == status::success + && !is_fwd() + && utils::one_of(desc()->alg_kind, alg_kind::pooling_max, + alg_kind::pooling_avg_include_padding, + alg_kind::pooling_avg_exclude_padding) + && !has_zero_dim_memory() + && utils::everyone_is(data_type, + diff_dst_md()->data_type, + diff_src_md()->data_type) + && attr()->has_default_values() + && memory_desc_matches_tag(*diff_dst_md(), desired_fmt_tag) + && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag); + if (!ok) return status::unimplemented; + + if (desc()->alg_kind == alg_kind::pooling_max) { + bool ws_ok = true + && hint_fwd_pd_ + && hint_fwd_pd_->workspace_md(); + if (!ws_ok) + return status::unimplemented; + + const auto &ws_blk = + hint_fwd_pd_->workspace_md()->format_desc.blocking; + ws_ok = ws_ok + && ws_blk.inner_nblks < 1 + && IMPLICATION(ws_blk.inner_nblks == 1, + ws_blk.inner_idxs[0] == 1); + if (!ws_ok) + return status::unimplemented; + + ws_md_ = *hint_fwd_pd_->workspace_md(); + } + + return status::success; + } + }; + + nchw_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp new file mode 100644 index 0000000000..c0e93fefe4 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp @@ -0,0 +1,382 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" + +#include "cpu_batch_normalization_utils.hpp" +#include "jit_generator.hpp" + +#include "ncsp_batch_normalization.hpp" + +// clang 6 and 7 generate incorrect code with OMP_SIMD in some particular cases +#if (defined __clang_major__) && (__clang_major__ >= 6) +#define SAFE_TO_USE_OMP_SIMD 0 +#else +#define SAFE_TO_USE_OMP_SIMD 1 +#endif + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace memory_tracking::names; + +void ncsp_batch_normalization_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + const bool calculate_stats = !pd()->stats_is_src(); + const bool save_stats = pd()->is_training(); + const bool is_training = pd()->is_training(); + const bool fuse_bn_relu = pd()->fuse_bn_relu(); + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT); + + auto scratchpad = this->scratchpad(ctx); + auto *ws_reduce = scratchpad.get(key_bnorm_reduction); + + data_t *mean, *variance; + if (!calculate_stats) { + mean = const_cast( + CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN)); + variance = const_cast( + CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE)); + } else { + if (save_stats) { + mean = CTX_OUT_MEM(data_t *, MKLDNN_ARG_MEAN); + variance = CTX_OUT_MEM(data_t *, MKLDNN_ARG_VARIANCE); + } else { + mean = scratchpad.get(key_bnorm_tmp_mean); + variance = scratchpad.get(key_bnorm_tmp_var); + } + } + + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE); + + const float eps = pd()->desc()->batch_norm_epsilon; + const bool use_scaleshift = pd()->use_scaleshift(); + const bool with_relu = pd()->with_relu_post_op(); + auto maybe_post_op + = [&](data_t res) { return (with_relu && res < 0) ? 0 : res; }; + const bool has_spatial = utils::one_of(pd()->ndims(), 4, 5); + dim_t SP = (has_spatial) ? pd()->H() * pd()->W() * pd()->D() : 1; + dim_t N = pd()->MB(); + dim_t C = pd()->C(); + + int nthr = mkldnn_get_max_threads(); + size_t l3_size_ = get_cache_size(3, true) * nthr / 2; + size_t data_size = N * C * SP * sizeof(data_t); + bool do_blocking = (data_size >= l3_size_ / 2 && l3_size_ > 0); + + parallel(0, [&](const int ithr, const int nthr) { + int C_ithr = 0, C_nthr = 0; + int N_ithr = 0, N_nthr = 0; + int S_ithr = 0, S_nthr = 0; + + dim_t C_blk_gl_s = 0, C_blk_gl_e = 0, C_blk_s = 0, C_blk_e = 0; + dim_t N_s = 0, N_e = 0; + dim_t S_s = 0, S_e = 0; + + dim_t C_blks_per_iter = 1; + int64_t iters = 1; + + if (do_blocking) { + size_t working_set_size = N * SP * sizeof(data_t); + bnorm_utils::cache_balance( + working_set_size, C, C_blks_per_iter, iters); + } else + C_blks_per_iter = C; + int64_t last_iter_blks = C - (iters - 1) * C_blks_per_iter; + bool spatial_thr_allowed + = bnorm_utils::thread_balance(do_blocking, true, ithr, nthr, N, + C_blks_per_iter, SP, C_ithr, C_nthr, C_blk_s, C_blk_e, + N_ithr, N_nthr, N_s, N_e, S_ithr, S_nthr, S_s, S_e); + balance211(C_blks_per_iter, nthr, ithr, C_blk_gl_s, C_blk_gl_e); + int SP_N_ithr = N_ithr * S_nthr + S_ithr; + int SP_N_nthr = N_nthr * S_nthr; + for (int64_t it = 0; it < iters; ++it) { + if (it == iters - 1 && iters > 1) { + // On the last iteration the access pattern to ws_reduce + // might change (due to re-balance on C). So sync the + // threads if they are not synced by the algorithm. + if (SP_N_nthr == 1 && mkldnn_thr_syncable()) + mkldnn_thr_barrier(); + + S_s = S_e = C_blk_s = C_blk_e = N_s = N_e = 0; + spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking, + spatial_thr_allowed, ithr, nthr, N, last_iter_blks, SP, + C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s, + N_e, S_ithr, S_nthr, S_s, S_e); + balance211(last_iter_blks, nthr, ithr, C_blk_gl_s, C_blk_gl_e); + SP_N_ithr = N_ithr * S_nthr + S_ithr; + SP_N_nthr = N_nthr * S_nthr; + } + size_t C_off = it * C_blks_per_iter; + // On the last iteration the access pattern to ws_reduce + // might change (due to re-balance on C). Since sync is not always + // possible (in case of TBB) use different parts of ws for each + // iteration if threads are not synced by the algorithm. + size_t ws_iter_off = (mkldnn_thr_syncable() ? 0 : 1) * C_off; + + if (calculate_stats) { + data_t *mean_blk = mean + C_off; + data_t *variance_blk = variance + C_off; + for (dim_t c = C_blk_s; c < C_blk_e; c++) { + size_t off = (c + C_off) * SP; + data_t sum = 0; + for (dim_t n = N_s; n < N_e; ++n) + PRAGMA_OMP_SIMD(reduction(+ : sum)) + for (dim_t sp = S_s; sp < S_e; ++sp) { + sum += src[off + n * C * SP + sp]; + } + ws_reduce[ws_iter_off + SP_N_ithr * C_blks_per_iter + c] + = sum; + } + + if (SP_N_nthr > 1) mkldnn_thr_barrier(); + + for (dim_t c = C_blk_gl_s; c < C_blk_gl_e; c++) { + mean_blk[c] = 0.; + for (dim_t n = 0; n < SP_N_nthr; n++) + mean_blk[c] += ws_reduce[ws_iter_off + + n * C_blks_per_iter + c]; + mean_blk[c] /= (N * SP); + } + + if (SP_N_nthr > 1) mkldnn_thr_barrier(); + + for (dim_t c = C_blk_s; c < C_blk_e; c++) { + size_t off = c + C_off; + data_t sum = 0.; + for (dim_t n = N_s; n < N_e; ++n) + PRAGMA_OMP_SIMD(reduction(+ : sum)) + for (dim_t sp = S_s; sp < S_e; ++sp) { + data_t m = src[off * SP + n * C * SP + sp] + - mean[off]; + sum += m * m; + } + ws_reduce[ws_iter_off + SP_N_ithr * C_blks_per_iter + c] + = sum; + } + + if (SP_N_nthr > 1) mkldnn_thr_barrier(); + + for (dim_t c = C_blk_gl_s; c < C_blk_gl_e; c++) { + variance_blk[c] = 0.; + for (dim_t n = 0; n < SP_N_nthr; n++) + variance_blk[c] += ws_reduce[ws_iter_off + + n * C_blks_per_iter + c]; + variance_blk[c] /= (N * SP); + } + + if (SP_N_nthr > 1) mkldnn_thr_barrier(); + } + + for (dim_t c = C_blk_s; c < C_blk_e; c++) { + size_t off = c + C_off; + data_t sqrt_variance + = static_cast(sqrtf(variance[off] + eps)); + data_t sm = (use_scaleshift ? scaleshift[off] : 1.0f) / sqrt_variance; + data_t sv = use_scaleshift ? scaleshift[C + off] : 0; + for (dim_t n = N_s; n < N_e; ++n) +#if SAFE_TO_USE_OMP_SIMD + PRAGMA_OMP_SIMD() +#endif + for (dim_t sp = S_s; sp < S_e; ++sp) { + size_t d_off = off * SP + n * C * SP + sp; + data_t bn_res + = sm * (src[d_off] - mean[off]) + sv; + if (fuse_bn_relu) { + if (bn_res <= 0) { + bn_res = 0; + if (is_training) + ws[d_off] = 0; + } else { + if (is_training) + ws[d_off] = 1; + } + } + dst[d_off] = maybe_post_op(bn_res); + } + } + } + }); +} + +void ncsp_batch_normalization_bwd_t::execute_backward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN); + auto variance = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT); + auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE); + + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + auto diff_scaleshift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT); + + auto scratchpad = this->scratchpad(ctx); + auto *ws_reduce = scratchpad.get(key_bnorm_reduction); + + if (diff_scaleshift == nullptr) + diff_scaleshift = scratchpad.get(key_bnorm_tmp_diff_ss); + + const bool has_spatial = utils::one_of(pd()->ndims(), 4, 5); + dim_t SP = (has_spatial) ? pd()->H() * pd()->W() * pd()->D() : 1; + dim_t C = pd()->C(), N = pd()->MB(); + const bool use_scaleshift = pd()->use_scaleshift(); + const float eps = pd()->desc()->batch_norm_epsilon; + const bool calculate_diff_stats = !pd()->use_global_stats(); + const bool fuse_bn_relu = pd()->fuse_bn_relu(); + + int nthr = mkldnn_get_max_threads(); + size_t l3_size_ = get_cache_size(3, true) * nthr / 2; + size_t data_size = N * C * SP * sizeof(data_t); + bool do_blocking = (data_size >= l3_size_ / 2 && l3_size_ > 0); + + parallel(0, [&](const int ithr, const int nthr) { + int C_ithr = 0, C_nthr = 0; + int N_ithr = 0, N_nthr = 0; + int S_ithr = 0, S_nthr = 0; + + dim_t C_blk_gl_s = 0, C_blk_gl_e = 0, C_blk_s = 0, C_blk_e = 0; + dim_t N_s = 0, N_e = 0; + dim_t S_s = 0, S_e = 0; + + dim_t C_blks_per_iter = 1; + int64_t iters = 1; + + if (do_blocking) { + size_t working_set_size = 2 * N * SP * sizeof(data_t); + bnorm_utils::cache_balance( + working_set_size, C, C_blks_per_iter, iters); + } else + C_blks_per_iter = C; + int64_t last_iter_blks = C - (iters - 1) * C_blks_per_iter; + bool spatial_thr_allowed + = bnorm_utils::thread_balance(do_blocking, true, ithr, nthr, N, + C_blks_per_iter, SP, C_ithr, C_nthr, C_blk_s, C_blk_e, + N_ithr, N_nthr, N_s, N_e, S_ithr, S_nthr, S_s, S_e); + balance211(C_blks_per_iter, nthr, ithr, C_blk_gl_s, C_blk_gl_e); + int SP_N_ithr = N_ithr * S_nthr + S_ithr; + int SP_N_nthr = N_nthr * S_nthr; + + for (int64_t it = 0; it < iters; ++it) { + if (it == iters - 1 && iters > 1) { + // On the last iteration the access pattern to ws_reduce + // might change (due to re-balance on C). So sync the + // threads if they are not synced by the algorithm. + if (SP_N_nthr == 1 && mkldnn_thr_syncable()) + mkldnn_thr_barrier(); + + C_blk_s = C_blk_e = N_s = N_e = 0; + spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking, + spatial_thr_allowed, ithr, nthr, N, last_iter_blks, SP, + C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s, + N_e, S_ithr, S_nthr, S_s, S_e); + balance211(last_iter_blks, nthr, ithr, C_blk_gl_s, C_blk_gl_e); + SP_N_ithr = N_ithr * S_nthr + S_ithr; + SP_N_nthr = N_nthr * S_nthr; + } + size_t C_off = it * C_blks_per_iter; + // On the last iteration the access pattern to ws_reduce + // might change (due to re-balance on C). Since sync is not always + // possible (in case of TBB) use different parts of ws for each + // iteration if threads are not synced by the algorithm. + size_t ws_iter_off = (mkldnn_thr_syncable() ? 0 : 1) * 2 * C_off; + + data_t *diff_gamma_blk = diff_scaleshift + C_off; + data_t *diff_beta_blk = diff_scaleshift + C + C_off; + for (dim_t c = C_blk_s; c < C_blk_e; c++) { + size_t off = c + C_off; + data_t diff_gamma = 0.0, diff_beta = 0.0; + data_t v_mean = mean[off]; + for (dim_t n = N_s; n < N_e; ++n) + PRAGMA_OMP_SIMD(reduction(+ : diff_gamma, diff_beta)) + for (dim_t sp = S_s; sp < S_e; ++sp) { + const size_t d_off = off * SP + n * C * SP + sp; + data_t dd; + if (fuse_bn_relu) + dd = (!ws[d_off]) ? 0 : diff_dst[d_off]; + else + dd = diff_dst[d_off]; + diff_gamma += (src[d_off] - v_mean) * dd; + diff_beta += dd; + } + ws_reduce[ws_iter_off + SP_N_ithr * C_blks_per_iter + c] + = diff_gamma; + ws_reduce[ws_iter_off + SP_N_nthr * C_blks_per_iter + + SP_N_ithr * C_blks_per_iter + c] = diff_beta; + } + + if (SP_N_nthr > 1) mkldnn_thr_barrier(); + + for (dim_t c = C_blk_gl_s; c < C_blk_gl_e; c++) { + data_t sqrt_variance = static_cast( + 1.0f / sqrtf(variance[c + C_off] + eps)); + diff_gamma_blk[c] = 0.; + diff_beta_blk[c] = 0.; + for (dim_t n = 0; n < SP_N_nthr; n++) { + diff_gamma_blk[c] += ws_reduce[ws_iter_off + + n * C_blks_per_iter + c]; + diff_beta_blk[c] += ws_reduce[ws_iter_off + + SP_N_nthr * C_blks_per_iter + n * C_blks_per_iter + + c]; + } + diff_gamma_blk[c] *= sqrt_variance; + } + + if (SP_N_nthr > 1) mkldnn_thr_barrier(); + + for (dim_t c = C_blk_s; c < C_blk_e; c++) { + size_t off = c + C_off; + data_t gamma = use_scaleshift ? scaleshift[off] : 1; + data_t sqrt_variance + = static_cast(1.0f / sqrtf(variance[off] + eps)); + data_t v_mean = mean[off]; + for (dim_t n = N_s; n < N_e; ++n) +#if SAFE_TO_USE_OMP_SIMD + PRAGMA_OMP_SIMD() +#endif + for (dim_t sp = S_s; sp < S_e; ++sp) { + const size_t d_off = off * SP + n * C * SP + sp; + + data_t v_diff_src; + if (fuse_bn_relu) + v_diff_src = (!ws[d_off]) ? 0 : diff_dst[d_off]; + else + v_diff_src = diff_dst[d_off]; + if (calculate_diff_stats) { + v_diff_src -= diff_beta_blk[c] / (SP * N) + + (src[d_off] - v_mean) * diff_gamma_blk[c] + * sqrt_variance / (SP * N); + } + v_diff_src *= gamma * sqrt_variance; + diff_src[d_off] = v_diff_src; + } + } + } + }); +} +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp new file mode 100644 index 0000000000..97ca3b003f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp @@ -0,0 +1,160 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_NCSP_BATCH_NORMALIZATION_HPP +#define CPU_NCSP_BATCH_NORMALIZATION_HPP + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_batch_normalization_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct ncsp_batch_normalization_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_batch_normalization_fwd_pd_t { + using cpu_batch_normalization_fwd_pd_t::cpu_batch_normalization_fwd_pd_t; + + DECLARE_COMMON_PD_T("ncsp_bnorm:any", ncsp_batch_normalization_fwd_t); + + status_t init() { + using namespace data_type; + using namespace prop_kind; + using namespace format_tag; + + bool ok = true + && is_fwd() + && !has_zero_dim_memory() + && src_md()->data_type == f32 + && IMPLICATION(use_scaleshift(), weights_md()->data_type == f32) + && memory_desc_matches_one_of_tag(*src_md(), ncdhw, nchw, nc) + && (attr()->has_default_values() || this->with_relu_post_op()); + if (!ok) return status::unimplemented; + + if (is_training() && fuse_bn_relu()) init_default_ws(8); + + init_scratchpad(); + + return status::success; + } + + private: + void init_scratchpad() { + using namespace memory_tracking::names; + auto scratchpad = scratchpad_registry().registrar(); + if (!stats_is_src()) { + scratchpad.book(key_bnorm_reduction, + sizeof(data_t) * C() * mkldnn_get_max_threads()); + + if (!is_training()) { + scratchpad.book(key_bnorm_tmp_mean, sizeof(data_t) * C()); + scratchpad.book(key_bnorm_tmp_var, sizeof(data_t) * C()); + } + } + } + }; + + typedef typename prec_traits::type data_t; + + ncsp_batch_normalization_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + ~ncsp_batch_normalization_fwd_t() {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +struct ncsp_batch_normalization_bwd_t : public cpu_primitive_t { + struct pd_t : public cpu_batch_normalization_bwd_pd_t { + using cpu_batch_normalization_bwd_pd_t::cpu_batch_normalization_bwd_pd_t; + + DECLARE_COMMON_PD_T("ncsp_bnorm:any", ncsp_batch_normalization_bwd_t); + + status_t init() { + using namespace data_type; + using namespace format_tag; + + bool ok = true + && is_bwd() + && !has_zero_dim_memory() + && utils::everyone_is(f32, src_md()->data_type, + diff_src_md()->data_type) + && IMPLICATION(use_scaleshift(), + utils::everyone_is(f32, + weights_md()->data_type, + diff_weights_md()->data_type)) + && memory_desc_matches_one_of_tag(*src_md(), ncdhw, nchw, nc) + && memory_desc_matches_one_of_tag(*diff_src_md(), ncdhw, nchw, nc) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + if (fuse_bn_relu()) { + init_default_ws(8); + if (!compare_ws(hint_fwd_pd_)) + return status::unimplemented; + } + + init_scratchpad(); + + return status::success; + } + + private: + void init_scratchpad() { + using namespace memory_tracking::names; + auto scratchpad = scratchpad_registry().registrar(); + scratchpad.book(key_bnorm_reduction, + sizeof(data_t) * 2 * C() * mkldnn_get_max_threads()); + if (!(use_scaleshift() && desc()->prop_kind == prop_kind::backward)) + scratchpad.book(key_bnorm_tmp_diff_ss, + sizeof(data_t) * 2 * C()); + } + }; + + typedef typename prec_traits::type data_t; + + ncsp_batch_normalization_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + ~ncsp_batch_normalization_bwd_t() {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp new file mode 100644 index 0000000000..38cfb28dce --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp @@ -0,0 +1,392 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" + +#include "nhwc_pooling.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +#define MEM_D(name) name##_d + +#define DECLARE_READ_STRIDES(name) \ + const size_t name##_n_stride = MEM_D(name).blocking_desc().strides[0]; \ + const size_t name##_d_stride = (!is_3d) \ + ? 0 \ + : MEM_D(name).blocking_desc().strides[2]; \ + const size_t name##_h_stride = (!is_3d) \ + ? MEM_D(name).blocking_desc().strides[2] \ + : MEM_D(name).blocking_desc().strides[3]; \ + const size_t name##_w_stride = (!is_3d) \ + ? MEM_D(name).blocking_desc().strides[3] \ + : MEM_D(name).blocking_desc().strides[4]; + +namespace nhwc_pooling { + size_t strided_offset(const int _n, const size_t _sn, + const int _d, const size_t _sd, + const int _h, const size_t _sh, + const int _w, const size_t _sw) + { + return _n * _sn + + _d * _sd + + _h * _sh + + _w * _sw; + } +} + +template +void nhwc_pooling_fwd_t::array_div_by_const(const int n, + const data_t *src, const size_t num, data_t *dst) const +{ + for (int i = 0; i < n; ++i) + { + float ftmp = (float)src[i]; + ftmp = ftmp / num; + dst[i] = math::out_round(ftmp); + } +} + +template +void nhwc_pooling_fwd_t::array_add(const int n, const data_t *src, + data_t *dst) const +{ + for (int i = 0; i < n; ++i) + { + dst[i] += src[i]; + } +} + +template +void nhwc_pooling_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + using namespace alg_kind; + using namespace prop_kind; + using namespace nhwc_pooling; + + auto alg = pd()->desc()->alg_kind; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(unsigned char *, MKLDNN_ARG_WORKSPACE); + + const memory_desc_wrapper MEM_D(src)(pd()->src_md()); + const memory_desc_wrapper MEM_D(dst)(pd()->dst_md()); + const memory_desc_wrapper MEM_D(ws)(pd()->workspace_md()); + + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + const int SD = pd()->KSD(); + const int SH = pd()->KSH(); + const int SW = pd()->KSW(); + const int padF = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + const int MB = pd()->MB(); + const int OC = pd()->C(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + + const bool is_3d = pd()->desc()->src_desc.ndims == 5; + const data_type_t ws_dt = ws ? ws_d.data_type() : data_type::undef; + + DECLARE_READ_STRIDES(src); + DECLARE_READ_STRIDES(dst); + + auto apply_offset = [=](int index, int offset) { + return (index > offset) ? index - offset : 0; + }; + + parallel_nd(MB, OD, OH, OW, + [&](int mb, int od, int oh, int ow) { + size_t dst_offset_init = strided_offset(mb, dst_n_stride, + od, dst_d_stride, + oh, dst_h_stride, + ow, dst_w_stride); + if (alg == pooling_max) { + size_t ws_offset_init = 0; + if (ws) + { + DECLARE_READ_STRIDES(ws); + ws_offset_init = strided_offset(mb, ws_n_stride, + od, ws_d_stride, + oh, ws_h_stride, + ow, ws_w_stride); + } + // Note: GCC 4.8.5 won't vectorize below + // simple loops unless they are singled out + // into separate helper routines: + // array_nhwc_initialize, array_nhwc_max + if (!ws) + array_nhwc_initialize(OC, dst + dst_offset_init, + ws, ws_offset_init, ws_dt); + else + array_nhwc_initialize(OC, dst + dst_offset_init, + ws, ws_offset_init, ws_dt); + + + for (int kd = 0; kd < KD; ++kd) + for (int kh = 0; kh < KH; ++kh) + for (int kw = 0; kw < KW; ++kw) { + const int id = od * SD - padF + kd; + const int ih = oh * SH - padT + kh; + const int iw = ow * SW - padL + kw; + + if (id < 0 || id >= ID) + continue; + if (ih < 0 || ih >= IH) + continue; + if (iw < 0 || iw >= IW) + continue; + + size_t src_offset_init = strided_offset(mb, src_n_stride, + id, src_d_stride, + ih, src_h_stride, + iw, src_w_stride); + + if (!ws) + array_nhwc_max(OC, + dst + dst_offset_init, + src + src_offset_init, + ws, ws_offset_init, + ws_dt, + kd * KH * KW + kh * KW + kw + ); + else + array_nhwc_max(OC, + dst + dst_offset_init, + src + src_offset_init, + ws, ws_offset_init, + ws_dt, + kd * KH * KW + kh * KW + kw + ); + } + } else { + // pooling_avg + auto d = dst + dst_offset_init; + + utils::array_set(d, 0, OC); + + auto id_start = apply_offset(od * SD, padF); + auto ih_start = apply_offset(oh * SH, padT); + auto iw_start = apply_offset(ow * SW, padL); + auto id_end = nstl::min(od * SD - padF + KD, ID); + auto ih_end = nstl::min(oh * SH - padT + KH, IH); + auto iw_end = nstl::min(ow * SW - padL + KW, IW); + + // it is cheaper to actually count this in a loop + // as the typical kernel is small + size_t num_summands = 0; + + for (int id = id_start; id < id_end; ++id) + for (int ih = ih_start; ih < ih_end; ++ih) + for (int iw = iw_start; iw < iw_end; ++iw) { + size_t src_offset_init = strided_offset(mb, src_n_stride, + id, src_d_stride, + ih, src_h_stride, + iw, src_w_stride); + auto s = src + src_offset_init; + + // need to move the loop to separate function + // for GCC 4.8.5 to vectorize + array_add(OC, s, d); + + num_summands++; + } + + num_summands = (alg == pooling_avg_include_padding) ? + KW * KH * KD : num_summands; + + // need to move the loop to separate function + // for GCC 4.8.5 to vectorize + array_div_by_const(OC, d, num_summands, d); + } + }); +} + +template +void nhwc_pooling_bwd_t::execute_backward( + const exec_ctx_t &ctx) const { + using namespace alg_kind; + using namespace nhwc_pooling; + + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto ws = CTX_IN_MEM(const unsigned char *, MKLDNN_ARG_WORKSPACE); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper MEM_D(diff_src)(pd()->diff_src_md()); + const memory_desc_wrapper MEM_D(diff_dst)(pd()->diff_dst_md()); + const memory_desc_wrapper MEM_D(ws)(pd()->workspace_md()); + + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + const int SD = pd()->KSD(); + const int SH = pd()->KSH(); + const int SW = pd()->KSW(); + const int OC = pd()->C(); + const int padF = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + + const bool is_3d = pd()->desc()->diff_src_desc.ndims == 5; + auto alg = pd()->desc()->alg_kind; + + DECLARE_READ_STRIDES(diff_src); + DECLARE_READ_STRIDES(diff_dst); + + auto apply_offset = [=](int index, int offset) { + return (index > offset) ? index - offset : 0; + }; + + const int MB = pd()->MB(); + + parallel_nd(MB, ID, IH, IW, + [&](int mb, int id, int ih, int iw) { + size_t src_offset_init = strided_offset(mb, diff_src_n_stride, + id, diff_src_d_stride, + ih, diff_src_h_stride, + iw, diff_src_w_stride); + + // check if kernel windows are disjoint, in this case there's no + // update needed and we just write there once, no initialization + // required. + if (!(KD == SD && KH == SH && KW == SW)) + for (int oc = 0; oc < OC; ++oc) + diff_src[src_offset_init + oc] = data_type_t(0); + + // Find out which output cells may correspond to current + // input position. Current input postition divided by + // stride, with integer divide rounding down, is the + // right-most output. + // Left-most output may be computed if we decrement input + // by (kernel_size - 1) and then do the same division by + // stride. + int od_left = nstl::max((id + padF - KD + 1) / SD, 0); + int oh_left = nstl::max((ih + padT - KH + 1) / SH, 0); + int ow_left = nstl::max((iw + padL - KW + 1) / SW, 0); + // Notice +1 here to preserve the C loop "less than" + // condition for continuing the for loop. + int od_right = nstl::min((id + padF) / SD + 1 , OD); + int oh_right = nstl::min((ih + padT) / SH + 1 , OH); + int ow_right = nstl::min((iw + padL) / SW + 1 , OW); + + for (int od = od_left; od < od_right; ++od) + for (int oh = oh_left; oh < oh_right; ++oh) + for (int ow = ow_left; ow < ow_right; ++ow) { + const int kd = id - od*SD + padF; + const int kh = ih - oh*SH + padT; + const int kw = iw - ow*SW + padL; + + if (kd < 0 || kd >= KD) + continue; + if (kh < 0 || kh >= KH) + continue; + if (kw < 0 || kw >= KW) + continue; + + size_t dst_offset_init = strided_offset(mb, diff_dst_n_stride, + od, diff_dst_d_stride, + oh, diff_dst_h_stride, + ow, diff_dst_w_stride); + + if (alg == pooling_max) { + DECLARE_READ_STRIDES(ws); + size_t ws_offset_init = strided_offset(mb, ws_n_stride, + od, ws_d_stride, + oh, ws_h_stride, + ow, ws_w_stride); + const int index = kd * KH * KW + kh * KW + kw; + + PRAGMA_OMP_SIMD() + for (int oc = 0; oc < OC; ++oc) { + const int index_from_ws = + (MEM_D(ws).data_type() == data_type::u8) + ? (int)ws[ws_offset_init + oc] + : ((int *)ws)[ws_offset_init + oc]; + + const data_t d = diff_dst[dst_offset_init + oc]; + + // Check if kernel windows are disjoint, in this case + // there's no update needed and we just write there once + // otherwise we add value to the contents. + if (!(KD == SD && KH == SH && KW == SW)) + diff_src[src_offset_init + oc] += + (index_from_ws == index) + ? d + : data_type_t(0); + else + diff_src[src_offset_init + oc] = + (index_from_ws == index) + ? d + : data_type_t(0); + } + } else { + // pooling_avg + auto id_start = apply_offset(od*SD, padF); + auto ih_start = apply_offset(oh*SH, padT); + auto iw_start = apply_offset(ow*SW, padL); + auto id_end = nstl::min(od*SD - padF + KD, ID); + auto ih_end = nstl::min(oh*SH - padT + KH, IH); + auto iw_end = nstl::min(ow*SW - padL + KW, IW); + + auto num_summands = (alg == pooling_avg_include_padding) + ? KW*KH*KD + : (ih_end - ih_start)*(iw_end - iw_start)*(id_end - id_start); + + PRAGMA_OMP_SIMD() + for (int oc = 0; oc < OC; ++oc) { + const data_t d = diff_dst[dst_offset_init + oc]; + // Check if kernel windows are disjoint, in this case + // there's no update needed and we just write there once + // otherwise we add value to the contents. + if (!(KD == SD && KH == SH && KW == SW)) + diff_src[src_offset_init + oc] += d / num_summands; + else + diff_src[src_offset_init + oc] = d / num_summands; + } + } + } + }); +} + +template struct nhwc_pooling_fwd_t; +template struct nhwc_pooling_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp new file mode 100644 index 0000000000..7e33b6869f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp @@ -0,0 +1,210 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_NHWC_POOLING_HPP +#define CPU_NHWC_POOLING_HPP + +#include + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_pooling_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace nhwc_pooling { +size_t strided_offset(const int _n, const size_t _sn, const int _d, + const size_t _sd, const int _h, const size_t _sh, const int _w, + const size_t _sw); +} + +template +struct nhwc_pooling_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_fwd_pd_t { + using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t; + + DECLARE_COMMON_PD_T("nhwc_pooling:any", nhwc_pooling_fwd_t); + + status_t init() { + const format_tag_t desired_fmt_tag = + ndims() == 4 ? format_tag::nhwc : format_tag::ndhwc; + + bool ok = true + && set_default_params() == status::success + && is_fwd() + && utils::one_of(desc()->alg_kind, alg_kind::pooling_max, + alg_kind::pooling_avg_include_padding, + alg_kind::pooling_avg_exclude_padding) + && utils::everyone_is(data_type, + src_md()->data_type, + dst_md()->data_type) + && attr()->has_default_values() + && memory_desc_matches_tag(*src_md(), desired_fmt_tag) + && memory_desc_matches_tag(*dst_md(), desired_fmt_tag); + if (!ok) return status::unimplemented; + + bool is_training = desc_.prop_kind == prop_kind::forward_training; + if (desc()->alg_kind == alg_kind::pooling_max && is_training) + init_default_ws(); + + return status::success; + } + }; + + nhwc_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + void array_div_by_const(const int n, const data_t *src, const size_t num, + data_t *dst) const; + void array_add(const int n, const data_t *src, data_t *dst) const; + + template + void array_nhwc_max(const int n, data_t *dst, const data_t *src, + unsigned char *ws, const size_t ws_offset, const data_type_t ws_dt, + const int index) const { + assert(!((use_workspace == false) ^ (!ws))); // ensure ws pointer exists + PRAGMA_OMP_SIMD() + for (int oc = 0; oc < n; ++oc) { + auto s = src[oc]; + data_t mv = dst[oc]; + + // update index of maximum +#if defined __INTEL_COMPILER + if ((use_workspace) && (s > mv)) { + assert(ws_dt == data_type::u8 || ws_dt == data_type::s32); + if (ws_dt == data_type::u8) { + assert(0 <= index && index <= 255); + ws[ws_offset + oc] = index; + } else + reinterpret_cast(ws)[ws_offset + oc] = index; + } +#else + // Need to add explicit predicates for GCC to vectorize this. + // And although the resulting code is ugly, it is still 4 times + // faster than scalar + if (use_workspace) { + assert(ws_dt == data_type::u8 || ws_dt == data_type::s32); + + if (ws_dt == data_type::u8) { + assert(0 <= index && index <= 255); + unsigned char predicate = (s > mv) ? 0xff : 0; + unsigned char current_value = ws[ws_offset + oc]; + current_value = (predicate & (unsigned char)index) + | ((~predicate) & current_value); + ws[ws_offset + oc] = current_value; + } else { + auto wint = reinterpret_cast(ws); + unsigned int predicate = (s > mv) ? 0xffffffff : 0; + unsigned int current_value = wint[ws_offset + oc]; + current_value = (predicate & (unsigned int)index) + | ((~predicate) & current_value); + wint[ws_offset + oc] = current_value; + } + } +#endif + // update maximum + dst[oc] = nstl::max(s, mv); + } + } + + template + void array_nhwc_initialize(const int n, data_t *dst, unsigned char *ws, + const size_t ws_offset, const data_type_t ws_dt) const { + assert(!((use_workspace == false) ^ (!ws))); // ensure ws pointer exists + for (int oc = 0; oc < n; ++oc) { + if (use_workspace) { + assert(ws_dt == data_type::u8 || ws_dt == data_type::s32); + if (ws_dt == data_type::u8) { + ws[ws_offset + oc] = 0; + } else + reinterpret_cast(ws)[ws_offset + oc] = 0; + } + dst[oc] = nstl::numeric_limits::lowest(); + } + } + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct nhwc_pooling_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_bwd_pd_t { + using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t; + + DECLARE_COMMON_PD_T("nhwc:any", nhwc_pooling_bwd_t); + + status_t init() { + const format_tag_t desired_fmt_tag = + ndims() == 4 ? format_tag::nchw : format_tag::ncdhw; + + bool ok = true + && set_default_params() == status::success + && !is_fwd() + && utils::one_of(desc()->alg_kind, alg_kind::pooling_max, + alg_kind::pooling_avg_include_padding, + alg_kind::pooling_avg_exclude_padding) + && utils::everyone_is(data_type, + diff_dst_md()->data_type, + diff_src_md()->data_type) + && attr()->has_default_values() + && memory_desc_matches_tag(*diff_dst_md(), desired_fmt_tag) + && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag); + if (!ok) return status::unimplemented; + + if (desc()->alg_kind == alg_kind::pooling_max) { + init_default_ws(); + if (!compare_ws(hint_fwd_pd_)) + return status::unimplemented; + } + + return status::success; + } + }; + + nhwc_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +}// namespace cpu +}// namespace impl +}// namespace mkldnn + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp new file mode 100644 index 0000000000..e20333e66f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp @@ -0,0 +1,288 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" + +#include "cpu_batch_normalization_utils.hpp" +#include "jit_generator.hpp" + +#include "nspc_batch_normalization.hpp" + +// clang 6 and 7 generate incorrect code with OMP_SIMD in some particular cases +#if (defined __clang_major__) && (__clang_major__ >= 6) +#define SAFE_TO_USE_OMP_SIMD 0 +#else +#define SAFE_TO_USE_OMP_SIMD 1 +#endif + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace memory_tracking::names; + +void nspc_batch_normalization_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + const bool save_stats = pd()->is_training(); + const bool is_training = pd()->is_training(); + const bool fuse_bn_relu = pd()->fuse_bn_relu(); + const bool calculate_stats = !pd()->stats_is_src(); + const bool with_relu = pd()->with_relu_post_op(); + + auto scratchpad = this->scratchpad(ctx); + auto tmp_mean = scratchpad.get(key_bnorm_tmp_mean); + auto tmp_var = scratchpad.get(key_bnorm_tmp_var); + auto *ws_reduce = scratchpad.get(key_bnorm_reduction); + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT); + + data_t *mean, *variance; + if (!calculate_stats) { + mean = const_cast( + CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN)); + variance = const_cast( + CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE)); + } else { + if (save_stats) { + mean = CTX_OUT_MEM(data_t *, MKLDNN_ARG_MEAN); + variance = CTX_OUT_MEM(data_t *, MKLDNN_ARG_VARIANCE); + } else { + mean = tmp_mean; + variance = tmp_var; + } + } + + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE); + + const dim_t N = pd()->MB(); + const dim_t C = pd()->C(); + const dim_t SP = pd()->H() * pd()->W() * pd()->D(); + + const float eps = pd()->desc()->batch_norm_epsilon; + const bool use_scaleshift = pd()->use_scaleshift(); + auto maybe_post_op + = [&](data_t res) { return (with_relu && res < 0) ? 0 : res; }; + + assert(mkldnn_thr_syncable()); + parallel(0, [&](const int ithr, const int nthr) { + dim_t N_s = 0, N_e = 0, C_s = 0, C_e = 0; + balance211(N, nthr, ithr, N_s, N_e); + balance211(C, nthr, ithr, C_s, C_e); + data_t *mean_loc = tmp_mean + nstl::max(C, (dim_t)16) * ithr; + data_t *variance_loc = tmp_var + nstl::max(C, (dim_t)16) * ithr; + + if (calculate_stats) { + for (dim_t c = 0; c < C; c++) + ws_reduce[C * ithr + c] = 0.; + + for (dim_t n = N_s; n < N_e; n++) + for (dim_t sp = 0; sp < SP; sp++) + PRAGMA_OMP_SIMD() + for (dim_t c = 0; c < C; c++) + ws_reduce[C * ithr + c] += src[(size_t)n * SP * C + + sp * C + c]; + + mkldnn_thr_barrier(); + + for (dim_t c = C_s; c < C_e; c++) { + mean[c] = 0; + for (dim_t n = 0; n < nthr; n++) + mean[c] += ws_reduce[C * n + c]; + mean[c] /= SP * N; + } + + mkldnn_thr_barrier(); + + for (dim_t c = 0; c < C; c++) { + mean_loc[c] = mean[c]; + ws_reduce[C * ithr + c] = 0.; + } + + for (dim_t n = N_s; n < N_e; n++) + for (dim_t sp = 0; sp < SP; sp++) + PRAGMA_OMP_SIMD() + for (dim_t c = 0; c < C; c++) { + data_t m = src[(size_t)n * SP * C + sp * C + c] + - mean_loc[c]; + ws_reduce[C * ithr + c] += m * m; + } + + mkldnn_thr_barrier(); + + for (dim_t c = C_s; c < C_e; c++) { + variance[c] = 0; + for (dim_t n = 0; n < nthr; n++) + variance[c] += ws_reduce[C * n + c]; + variance[c] /= SP * N; + } + + mkldnn_thr_barrier(); + + for (dim_t c = 0; c < C; c++) + variance_loc[c] = variance[c]; + } else { + variance_loc = variance; + mean_loc = mean; + } + + for (dim_t n = N_s; n < N_e; n++) { + for (dim_t sp = 0; sp < SP; sp++) { +#if SAFE_TO_USE_OMP_SIMD + PRAGMA_OMP_SIMD() +#endif + for (dim_t c = 0; c < C; c++) { + data_t sqrt_variance = static_cast( + sqrtf(variance_loc[c] + eps)); + data_t sm = (use_scaleshift ? scaleshift[c] : 1.0f) / sqrt_variance; + data_t sv = use_scaleshift ? scaleshift[C + c] : 0; + size_t d_off = (size_t)n * SP * C + sp * C + c; + data_t bn_res = sm * (src[d_off] - mean_loc[c]) + sv; + if (fuse_bn_relu) { + if (bn_res <= 0) { + bn_res = 0; + if (is_training) + ws[d_off] = 0; + } else { + if (is_training) + ws[d_off] = 1; + } + } + dst[d_off] = maybe_post_op(bn_res); + } + } + } + }); +} + +void nspc_batch_normalization_bwd_t::execute_backward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN); + auto variance = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT); + auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE); + + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + auto diff_scaleshift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT); + + auto scratchpad = this->scratchpad(ctx); + auto tmp_diff_ss = scratchpad.get(key_bnorm_tmp_diff_ss); + + if (diff_scaleshift == nullptr) + diff_scaleshift = tmp_diff_ss; + + const dim_t N = pd()->MB(); + const dim_t C = pd()->C(); + const dim_t SP = pd()->D() * pd()->H() * pd()->W(); + data_t *diff_gamma = diff_scaleshift, *diff_beta = diff_scaleshift + C; + auto *ws_reduce = scratchpad.get(key_bnorm_reduction); + + const float eps = pd()->desc()->batch_norm_epsilon; + const bool use_scaleshift = pd()->use_scaleshift(); + const bool calculate_diff_stats = !pd()->use_global_stats(); + const bool fuse_bn_relu = pd()->fuse_bn_relu(); + + assert(mkldnn_thr_syncable()); + parallel(0, [&](const int ithr, const int nthr) { + dim_t N_s = 0, N_e = 0, C_s = 0, C_e = 0; + balance211(N, nthr, ithr, N_s, N_e); + balance211(C, nthr, ithr, C_s, C_e); + + data_t *diff_gamma_loc = tmp_diff_ss + 2 * C + C * ithr; + data_t *diff_beta_loc = tmp_diff_ss + 2 * C + C * (nthr + ithr); + + for (dim_t c = 0; c < C; c++) { + ws_reduce[C * ithr + c] = 0.; + ws_reduce[C * nthr + C * ithr + c] = 0.; + } + + for (dim_t n = N_s; n < N_e; n++) + for (dim_t sp = 0; sp < SP; sp++) +#if SAFE_TO_USE_OMP_SIMD + PRAGMA_OMP_SIMD() +#endif + for (dim_t c = 0; c < C; c++) { + const size_t d_off = (size_t)n * SP * C + sp * C + c; + data_t dd; + if (fuse_bn_relu) + dd = (!ws[d_off]) ? 0 : diff_dst[d_off]; + else + dd = diff_dst[d_off]; + ws_reduce[C * ithr + c] += (src[d_off] - mean[c]) * dd; + ws_reduce[C * nthr + C * ithr + c] += dd; + } + + mkldnn_thr_barrier(); + + for (dim_t c = C_s; c < C_e; c++) { + data_t sqrt_variance + = static_cast(1.0f / sqrtf(variance[c] + eps)); + diff_gamma[c] = 0; + diff_beta[c] = 0; + for (dim_t n = 0; n < nthr; n++) { + diff_gamma[c] += ws_reduce[C * n + c]; + diff_beta[c] += ws_reduce[C * nthr + C * n + c]; + } + diff_gamma[c] *= sqrt_variance; + } + + mkldnn_thr_barrier(); + + for (dim_t c = 0; c < C; c++) { + diff_gamma_loc[c] = diff_gamma[c]; + diff_beta_loc[c] = diff_beta[c]; + } + + for (dim_t n = N_s; n < N_e; n++) { + for (dim_t sp = 0; sp < SP; sp++) { +#if SAFE_TO_USE_OMP_SIMD + PRAGMA_OMP_SIMD() +#endif + for (dim_t c = 0; c < C; c++) { + const size_t d_off = (size_t)n * SP * C + sp * C + c; + data_t gamma = use_scaleshift ? scaleshift[c] : 1; + data_t sqrt_variance + = static_cast(1.0f / sqrtf(variance[c] + eps)); + data_t v_diff_src; + if (fuse_bn_relu) + v_diff_src = (!ws[d_off]) ? 0 : diff_dst[d_off]; + else + v_diff_src = diff_dst[d_off]; + if (calculate_diff_stats) { + v_diff_src -= diff_beta_loc[c] / (SP * N) + + (src[d_off] - mean[c]) * diff_gamma_loc[c] + * sqrt_variance / (SP * N); + } + v_diff_src *= gamma * sqrt_variance; + diff_src[d_off] = v_diff_src; + } + } + } + }); +} + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp new file mode 100644 index 0000000000..aad86b05a7 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp @@ -0,0 +1,169 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_NSPC_BATCH_NORMALIZATION_HPP +#define CPU_NSPC_BATCH_NORMALIZATION_HPP + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_batch_normalization_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct nspc_batch_normalization_fwd_t : public cpu_primitive_t { + struct pd_t : public cpu_batch_normalization_fwd_pd_t { + pd_t(engine_t *engine, const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : cpu_batch_normalization_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + DECLARE_COMMON_PD_T("nspc_bnorm:any", nspc_batch_normalization_fwd_t); + + status_t init() { + using namespace data_type; + using namespace prop_kind; + + bool ok = true + /* the algorithm requires barriers while switching + * between parallelization over N and C dimensions */ + && mkldnn_thr_syncable() + && is_fwd() + && !has_zero_dim_memory() + && src_md()->data_type == f32 + && IMPLICATION(use_scaleshift(), weights_md()->data_type == f32) + && memory_desc_matches_tag(*src_md(), format_tag::nhwc) + && (attr()->has_default_values() || this->with_relu_post_op()); + if (!ok) return status::unimplemented; + + if (is_training() && fuse_bn_relu()) init_default_ws(8); + + init_scratchpad(); + + return status::success; + } + + private: + void init_scratchpad() { + using namespace memory_tracking::names; + auto scratchpad = scratchpad_registry().registrar(); + if (!stats_is_src()) { + dim_t sz = nstl::max(C(), 16) * mkldnn_get_max_threads(); + scratchpad.book(key_bnorm_reduction, sizeof(data_t) * sz); + scratchpad.book(key_bnorm_tmp_mean, sizeof(data_t) * sz); + scratchpad.book(key_bnorm_tmp_var, sizeof(data_t) * sz); + } + } + }; + + typedef typename prec_traits::type data_t; + + nspc_batch_normalization_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + ~nspc_batch_normalization_fwd_t() {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +struct nspc_batch_normalization_bwd_t : public cpu_primitive_t { + struct pd_t : public cpu_batch_normalization_bwd_pd_t { + pd_t(engine_t *engine, const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : cpu_batch_normalization_bwd_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + DECLARE_COMMON_PD_T("nspc_bnorm:any", nspc_batch_normalization_bwd_t); + + status_t init() { + using namespace data_type; + using namespace prop_kind; + + bool ok = true + /* the algorithm requires barriers while switching + * between parallelization over N and C dimensions */ + && mkldnn_thr_syncable() + && is_bwd() + && !has_zero_dim_memory() + && utils::everyone_is(f32, src_md()->data_type, + diff_src_md()->data_type) + && IMPLICATION(use_scaleshift(), + utils::everyone_is(f32, + weights_md()->data_type, + diff_weights_md()->data_type)) + && memory_desc_matches_tag(*src_md(), format_tag::nhwc) + && memory_desc_matches_tag(*diff_src_md(), format_tag::nhwc) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + if (fuse_bn_relu()) { + init_default_ws(8); + if (!compare_ws(hint_fwd_pd_)) + return status::unimplemented; + } + + init_scratchpad(); + + return status::success; + } + + private: + void init_scratchpad() { + using namespace memory_tracking::names; + auto scratchpad = scratchpad_registry().registrar(); + scratchpad.book(key_bnorm_reduction, + sizeof(data_t) * 2 * C() * mkldnn_get_max_threads()); + scratchpad.book(key_bnorm_tmp_diff_ss, sizeof(data_t) * 2 * C() + * (mkldnn_get_max_threads() + 1)); + } + }; + + typedef typename prec_traits::type data_t; + + nspc_batch_normalization_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + ~nspc_batch_normalization_bwd_t() {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp new file mode 100644 index 0000000000..d79b1a034b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp @@ -0,0 +1,265 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" +#include "simple_q10n.hpp" + +#include "ref_batch_normalization.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +void ref_batch_normalization_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + /* fast return */ + if (this->pd()->has_zero_dim_memory()) return; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto scaleshift = CTX_IN_MEM(const float *, MKLDNN_ARG_SCALE_SHIFT); + + auto mean = pd()->stats_is_src() + ? const_cast(CTX_IN_MEM(const float *, MKLDNN_ARG_MEAN)) + : CTX_OUT_MEM(float *, MKLDNN_ARG_MEAN); + auto variance = pd()->stats_is_src() + ? const_cast(CTX_IN_MEM(const float *, MKLDNN_ARG_VARIANCE)) + : CTX_OUT_MEM(float *, MKLDNN_ARG_VARIANCE); + + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE); + + const memory_desc_wrapper data_d(pd()->src_md()); + const memory_desc_wrapper scaleshift_d(pd()->weights_md()); + + const dim_t N = pd()->MB(); + const dim_t C = pd()->C(); + dim_t H = 1, W = 1, D = 1; + const bool has_spatial = utils::one_of(data_d.ndims(), 4, 5); + if (has_spatial) { + D = pd()->D(); + H = pd()->H(); + W = pd()->W(); + } + + const float eps = pd()->desc()->batch_norm_epsilon; + const bool use_scaleshift = pd()->use_scaleshift();; + const bool save_stats = pd()->is_training(); + const bool is_training = pd()->is_training(); + const bool fuse_bn_relu = pd()->fuse_bn_relu(); + const bool calculate_stats = !pd()->stats_is_src(); + + const bool with_relu = pd()->with_relu_post_op(); + auto maybe_post_op = [&](float res) { + return (with_relu && res < 0.0f) ? 0.0f : res; + }; + const bool is_3d = data_d.ndims() == 5; + + auto data_offset = [&](const memory_desc_wrapper &data_d, dim_t n, dim_t c, + dim_t d, dim_t h, dim_t w) { + if (has_spatial) { + if (is_3d) + return data_d.off(n, c, d, h, w); + else + return data_d.off(n, c, h, w); + } else + return data_d.off(n, c); + }; + + parallel_nd(C, [&](dim_t c) { + float v_mean = calculate_stats ? 0 : mean[c]; + float v_variance = calculate_stats ? 0 : variance[c]; + + if (calculate_stats) { + for (dim_t n = 0; n < N; ++n) + for (dim_t d = 0; d < D; ++d) + for (dim_t h = 0; h < H; ++h) + for (dim_t w = 0; w < W; ++w) + v_mean += src[data_offset(data_d, n, c, d, h, w)]; + v_mean /= W*N*H*D; + + for (dim_t n = 0; n < N; ++n) + for (dim_t d = 0; d < D; ++d) + for (dim_t h = 0; h < H; ++h) + for (dim_t w = 0; w < W; ++w) { + float m = src[data_offset(data_d, n, c, d, h, w)] - v_mean; + v_variance += m*m; + } + v_variance /= W*H*N*D; + } + + float sqrt_variance = sqrtf(v_variance + eps); + float sm = (use_scaleshift + ? scaleshift[scaleshift_d.off(0, c)] + : 1.0f) / sqrt_variance; + float sv = use_scaleshift ? scaleshift[scaleshift_d.off(1, c)] : 0; + + for (dim_t n = 0; n < N; ++n) + for (dim_t d = 0; d < D; ++d) + for (dim_t h = 0; h < H; ++h) + for (dim_t w = 0; w < W; ++w) { + auto d_off = data_offset(data_d,n,c,d,h,w); + float bn_res = sm * ((float)src[d_off] - v_mean) + sv; + if (fuse_bn_relu) { + if (bn_res <= 0) { + bn_res = 0; + if (is_training) + ws[d_off] = 0; + } else { + if (is_training) + ws[d_off] = 1; + } + } + if (data_type == data_type::s8) { + dst[d_off] = qz_a1b0()(maybe_post_op(bn_res)); + } else { + dst[d_off] = static_cast(maybe_post_op(bn_res)); + } + } + + if (calculate_stats) { + if (save_stats) { + mean[c] = v_mean; + variance[c] = v_variance; + } + } + }); +} + +template struct ref_batch_normalization_fwd_t; +template struct ref_batch_normalization_fwd_t; + +template +void ref_batch_normalization_bwd_t::execute_backward( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN); + auto variance = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT); + auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE); + + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + auto diff_scaleshift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT); + + const memory_desc_wrapper data_d(pd()->src_md()); + const memory_desc_wrapper diff_data_d(pd()->diff_src_md()); + const memory_desc_wrapper scaleshift_d(pd()->weights_md()); + const memory_desc_wrapper diff_scaleshift_d(pd()->diff_weights_md()); + + const dim_t C = pd()->C(); + + /* fast return */ + if (this->pd()->has_zero_dim_memory()) { + if (diff_scaleshift) { + for (dim_t c = 0; c < C; ++c) { + diff_scaleshift[diff_scaleshift_d.off(0, c)] = 0; + diff_scaleshift[diff_scaleshift_d.off(1, c)] = 0; + } + } + return; + } + + const dim_t N = pd()->MB(); + dim_t H = 1, W = 1, D = 1; + const bool has_spatial = utils::one_of(data_d.ndims(), 4, 5); + if (has_spatial) { + D = pd()->D(); + H = pd()->H(); + W = pd()->W(); + } + + const float eps = pd()->desc()->batch_norm_epsilon; + const bool use_scaleshift = pd()->use_scaleshift(); + const bool calculate_diff_stats = !pd()->use_global_stats(); + const bool fuse_bn_relu = pd()->fuse_bn_relu(); + + const bool is_3d = data_d.ndims() == 5; + + auto data_offset = [&](const memory_desc_wrapper &data_d, dim_t n, dim_t c, + dim_t d, dim_t h, dim_t w) { + if (has_spatial) { + if (is_3d) + return data_d.off(n, c, d, h, w); + else + return data_d.off(n, c, h, w); + } else + return data_d.off(n, c); + }; + + parallel_nd(C, [&](dim_t c) { + data_t v_mean = mean[c]; + data_t v_variance = variance[c]; + data_t sqrt_variance = static_cast(1.0f / sqrtf(v_variance + eps)); + data_t gamma = use_scaleshift ? scaleshift[scaleshift_d.off(0, c)] : 1; + data_t diff_gamma = data_t(0); + data_t diff_beta = data_t(0); + diff_gamma = 0.0; + diff_beta = 0.0; + + for (dim_t n = 0; n < N; ++n) + for (dim_t d = 0; d < D; ++d) + for (dim_t h = 0; h < H; ++h) + for (dim_t w = 0; w < W; ++w) { + const size_t s_off = data_offset(data_d, n, c, d, h, w); + data_t dd = diff_dst[data_offset(diff_data_d, n, c, d, h, w)]; + if (fuse_bn_relu && !ws[s_off]) + dd = 0; + + diff_gamma += (src[s_off] - v_mean) * dd; + diff_beta += dd; + } + diff_gamma *= sqrt_variance; + + if (diff_scaleshift) { + diff_scaleshift[diff_scaleshift_d.off(0, c)] = diff_gamma; + diff_scaleshift[diff_scaleshift_d.off(1, c)] = diff_beta; + } + + for (dim_t n = 0; n < N; ++n) + for (dim_t d = 0; d < D; ++d) + for (dim_t h = 0; h < H; ++h) + for (dim_t w = 0; w < W; ++w) { + const size_t s_off = data_offset(data_d, n, c, d, h, w); + const size_t dd_off = data_offset(diff_data_d, n, c, d, h, w); + data_t dd = diff_dst[dd_off]; + if (fuse_bn_relu && !ws[s_off]) + dd = 0; + + data_t v_diff_src = dd; + if (calculate_diff_stats) { + v_diff_src -= diff_beta/(D*W*H*N) + + (src[s_off] - v_mean) * + diff_gamma*sqrt_variance/(D*W*H*N); + } + v_diff_src *= gamma*sqrt_variance; + diff_src[dd_off] = v_diff_src; + } + }); +} + +template struct ref_batch_normalization_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp new file mode 100644 index 0000000000..aa9f74125a --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp @@ -0,0 +1,127 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_BATCH_NORMALIZATION_HPP +#define CPU_REF_BATCH_NORMALIZATION_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_batch_normalization_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct ref_batch_normalization_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_batch_normalization_fwd_pd_t { + pd_t(engine_t *engine, const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : cpu_batch_normalization_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + DECLARE_COMMON_PD_T("ref:any", ref_batch_normalization_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && src_md()->data_type == data_type + && IMPLICATION(use_scaleshift(), + weights_md()->data_type == data_type::f32) + && (attr()->has_default_values() || with_relu_post_op()); + if (!ok) return status::unimplemented; + + if (src_md()->data_type == data_type::s8 && !stats_is_src()) + return status::unimplemented; + + if (is_training() && fuse_bn_relu()) init_default_ws(8); + + return status::success; + } + }; + + ref_batch_normalization_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_batch_normalization_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_batch_normalization_bwd_pd_t { + pd_t(engine_t *engine, const batch_normalization_desc_t *adesc, + const primitive_attr_t *attr, + const batch_normalization_fwd_pd_t *hint_fwd_pd) + : cpu_batch_normalization_bwd_pd_t(engine, adesc, attr, hint_fwd_pd) + {} + + DECLARE_COMMON_PD_T("ref:any", ref_batch_normalization_bwd_t); + + status_t init() { + bool ok = true + && is_bwd() + && utils::everyone_is(data_type, src_md()->data_type, + diff_src_md()->data_type) + && IMPLICATION(use_scaleshift(), utils::everyone_is(data_type, + weights_md()->data_type, + diff_weights_md()->data_type)) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + if (fuse_bn_relu()) { + init_default_ws(8); + if (!compare_ws(hint_fwd_pd_)) + return status::unimplemented; + } + + return status::success; + } + }; + + ref_batch_normalization_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp new file mode 100644 index 0000000000..4c534b5508 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp @@ -0,0 +1,97 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef REF_CONCAT_HPP +#define REF_CONCAT_HPP + +#include "reorder_pd.hpp" + +#include "cpu_concat_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct ref_concat_t: public cpu_primitive_t { + struct pd_t: public cpu_concat_pd_t { + using cpu_concat_pd_t::cpu_concat_pd_t; + + pd_t(const pd_t &rhs): cpu_concat_pd_t(rhs) { + for (size_t i = 0; i < rhs.reorder_pds_.size(); ++i) + reorder_pds_.push_back( + (const reorder_pd_t *)rhs.reorder_pds_[i]->clone()); + } + ~pd_t() { for (auto &rpd: reorder_pds_) delete rpd; } + + DECLARE_CONCAT_PD_T("ref:any", ref_concat_t); + + status_t init() { + bool ok = cpu_concat_pd_t::init() == status::success; + if (!ok) return status::unimplemented; + + for (int i = 0; i < n_; ++i) { + auto r_impls = engine_->get_reorder_implementation_list(); + for (auto r = r_impls; *r; ++r) { + const primitive_attr_t attr; /* alpha == 1. */ + reorder_pd_t *r_pd = nullptr; + if ((*r)(&r_pd, engine_, &attr, engine_, src_md(i), + engine_, src_image_md(i)) == status::success) { + r_pd->init_info(); + reorder_pds_.push_back(r_pd); + break; + } + } + } + + ok = reorder_pds_.size() == (size_t)n_; + return ok ? status::success : status::unimplemented; + } + + nstl::vector reorder_pds_; + }; + + ref_concat_t(const pd_t *apd): cpu_primitive_t(apd) { + const int n = pd()->n_inputs(); + reorders_.resize(n); + for (int i = 0; i < n; ++i) + pd()->reorder_pds_[i]->create_primitive(&reorders_[i]); + } + + ~ref_concat_t() { for (auto &r: reorders_) delete r; } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + const auto n = pd()->n_inputs(); + for (int i = 0; i < n; ++i) { + exec_args_t r_args; + r_args[MKLDNN_ARG_SRC] = ctx.args().at(MKLDNN_ARG_MULTIPLE_SRC + i); + r_args[MKLDNN_ARG_DST] = ctx.args().at(MKLDNN_ARG_DST); + exec_ctx_t r_ctx(ctx.stream(), std::move(r_args)); + reorders_[i]->execute(r_ctx); + } + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + nstl::vector reorders_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp new file mode 100644 index 0000000000..c0a979c4cf --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp @@ -0,0 +1,395 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" +#include "mkldnn_traits.hpp" +#include "type_helpers.hpp" + +#include "ref_convolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using math::saturate; +using math::get_bias; + +template +void ref_convolution_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const bool with_groups = pd()->with_groups(); + + const int G = pd()->G(); + const int MB = pd()->MB(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + + const int OC = pd()->OC() / G; + const int IC = pd()->IC() / G; + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + + const int KSD = pd()->KSD(); + const int KSH = pd()->KSH(); + const int KSW = pd()->KSW(); + + const int KDD = pd()->KDD(); + const int KDH = pd()->KDH(); + const int KDW = pd()->KDW(); + + const int padFront = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + + const bool with_relu = 0; // TODO: change if support post_ops + const float nslope = 0.f; + + const int ndims = pd()->desc()->src_desc.ndims; + + auto ker = [=](int g, int mb, int oc, int od, int oh, + int ow) { + acc_data_t d = 0; + for (int ic = 0; ic < IC; ++ic) + for (int kd = 0; kd < KD; ++kd) + for (int kh = 0; kh < KH; ++kh) + for (int kw = 0; kw < KW; ++kw) { + const int id = od * KSD - padFront + kd * (1 + KDD); + const int ih = oh * KSH - padT + kh * (1 + KDH); + const int iw = ow * KSW - padL + kw * (1 + KDW); + + if (id < 0 || id >= ID) continue; + if (ih < 0 || ih >= IH) continue; + if (iw < 0 || iw >= IW) continue; + + if (ndims == 5) + d += (acc_data_t)src[src_d.off(mb, g*IC + ic, id, ih, iw)] + * (with_groups + ? weights[weights_d.off(g, oc, ic, kd, kh, kw)] + : weights[weights_d.off(oc, ic, kd, kh, kw)]); + else if (ndims == 4) + d += (acc_data_t)src[src_d.off(mb, g*IC + ic, ih, iw)] + * (with_groups + ? weights[weights_d.off(g, oc, ic, kh, kw)] + : weights[weights_d.off(oc, ic, kh, kw)]); + else if (ndims == 3) + d += (acc_data_t)src[src_d.off(mb, g*IC + ic, iw)] + * (with_groups + ? weights[weights_d.off(g, oc, ic, kw)] + : weights[weights_d.off(oc, ic, kw)]); + else + assert(false); + + } + return d; + }; + + parallel_nd(G, MB, OC, OD, OH, OW, + [&](int g, int mb, int oc, int od, int oh, int ow) { + float a = bias + ? get_bias(bias, bias_d.off(g * OC + oc), + pd()->desc()->bias_desc.data_type) + : 0; + a += ker(g, mb, oc, od, oh, ow); + if (with_relu && a < 0) + a = a * nslope; + if (ndims == 5) + dst[dst_d.off(mb, g*OC + oc, od, oh, ow)] = saturate(a); + else if (ndims == 4) + dst[dst_d.off(mb, g*OC + oc, oh, ow)] = saturate(a); + else if (ndims == 3) + dst[dst_d.off(mb, g*OC + oc, ow)] = saturate(a); + else + assert(false); + }); +} + +template +void ref_convolution_bwd_data_t::execute_backward_data(const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const bool with_groups = pd()->with_groups(); + + const int G = pd()->G(); + const int MB = pd()->MB(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + + const int OC = pd()->OC() / G; + const int IC = pd()->IC() / G; + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + + const int KSD = pd()->KSD(); + const int KSH = pd()->KSH(); + const int KSW = pd()->KSW(); + + const int KDD = pd()->KDD(); + const int KDH = pd()->KDH(); + const int KDW = pd()->KDW(); + + const int padFront = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + + const int ndims = pd()->desc()->diff_src_desc.ndims; + + auto ker = [=](int g, int mb, int ic, int id, int ih, + int iw) { + acc_data_t d = 0; + for (int oc = 0; oc < OC; ++oc) + for (int kd = 0; kd < KD; ++kd) + for (int kh = 0; kh < KH; ++kh) + for (int kw = 0; kw < KW; ++kw) { + if (iw + padL < kw * (1 + KDW) + || ih + padT < kh * (1 + KDH) + || id + padFront < kd * (1 + KDD)) + continue; + int ow = iw - kw * (1 + KDW) + padL; + int oh = ih - kh * (1 + KDH) + padT; + int od = id - kd * (1 + KDD) + padFront; + if (ow % KSW != 0 || oh % KSH != 0 || od % KSD != 0) + continue; + + ow /= KSW; + oh /= KSH; + od /= KSD; + + if (od < OD && oh < OH && ow < OW) { + if (ndims == 5) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + + oc, od, oh, ow)] * (with_groups + ? weights[weights_d.off(g, oc, ic, kd, kh, kw)] + : weights[weights_d.off(oc, ic, kd, kh, kw)]); + else if (ndims == 4) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + + oc, oh, ow)] * (with_groups + ? weights[weights_d.off(g, oc, ic, kh, kw)] + : weights[weights_d.off(oc, ic, kh, kw)]); + else if (ndims == 3) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + + oc, ow)] * (with_groups + ? weights[weights_d.off(g, oc, ic, kw)] + : weights[weights_d.off(oc, ic, kw)]); + else + assert(false); + } + } + return d; + }; + + parallel_nd(G, MB, IC, ID, IH, IW, + [&](int g, int mb, int ic, int id, int ih, int iw) { + auto ds_idx = (ndims == 5) + ? diff_src_d.off(mb, g*IC + ic, id, ih, iw) + : (ndims == 4) + ? diff_src_d.off(mb, g*IC + ic, ih, iw) + : diff_src_d.off(mb, g*IC + ic, iw); + float a = bias + ? get_bias(bias, bias_d.off(g * IC + ic), + pd()->desc()->bias_desc.data_type) + : 0; + a += ker(g, mb, ic, id, ih, iw); + diff_src[ds_idx] = saturate(a); + }); +} + +template +void ref_convolution_bwd_weights_t::execute_backward_weights(const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(diff_wei_data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias = CTX_OUT_MEM(diff_wei_data_t *, MKLDNN_ARG_DIFF_BIAS); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1)); + + const bool with_groups = pd()->with_groups(); + + const int G = pd()->G(); + const int MB = pd()->MB(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + + const int OC = pd()->OC() / G; + const int IC = pd()->IC() / G; + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + + const int KSD = pd()->KSD(); + const int KSH = pd()->KSH(); + const int KSW = pd()->KSW(); + + const int KDD = pd()->KDD(); + const int KDH = pd()->KDH(); + const int KDW = pd()->KDW(); + + const int padFront = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + + const int ndims = pd()->desc()->src_desc.ndims; + +auto ker = [=](acc_data_t &d, int g, int oc, int ic, int kd, int kh, int kw) { + for (int mb = 0; mb < MB; ++mb) + for (int od = 0; od < OD; ++od) + for (int oh = 0; oh < OH; ++oh) + for (int ow = 0; ow < OW; ++ow) { + if (ow*KSW + kw * (1 + KDW) < padL + || oh*KSH + kh * (1 + KDH) < padT + || od*KSD + kd * (1 + KDD) < padFront + || ow*KSW + kw * (1 + KDW) >= IW + padL + || oh*KSH + kh * (1 + KDH) >= IH + padT + || od*KSD + kd * (1 + KDD) >= ID + padFront) + continue; + + int id = od*KSD - padFront + kd * (1 + KDD); + int ih = oh*KSH - padT + kh * (1 + KDH); + int iw = ow*KSW - padL + kw * (1 + KDW); + if (ndims == 5) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, od, + oh, ow)] * src[src_d.off(mb, g*IC + ic, id, ih, iw)]; + else if (ndims == 4) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, oh, ow)] + * src[src_d.off(mb, g*IC + ic, ih, iw)]; + else if (ndims == 3) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, ow)] + * src[src_d.off(mb, g*IC + ic, iw)]; + else + assert(false); + } + }; + + auto ker_bias = [=](acc_data_t &d, int g, int oc) { + for (int mb = 0; mb < MB; ++mb) + for (int od = 0; od < OD; ++od) + for (int oh = 0; oh < OH; ++oh) + for (int ow = 0; ow < OW; ++ow) { + if (ndims == 5) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, od, oh, + ow)]; + else if (ndims == 4) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, oh, + ow)]; + else if (ndims == 3) + d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, ow)]; + else + assert(false); + } + }; + + parallel_nd(G, OC, [&](int g, int oc) { + if (diff_bias) { + // XXX: loss of precision when bias is a float... + acc_data_t db = 0; + ker_bias(db, g, oc); + diff_bias[diff_bias_d.off(g*OC+oc)] + = saturate(db); + } + + for (int ic = 0; ic < IC; ++ic) + for (int kd = 0; kd < KD; ++kd) + for (int kh = 0; kh < KH; ++kh) + for (int kw = 0; kw < KW; ++kw) { + acc_data_t dw = 0; + ker(dw, g, oc, ic, kd, kh, kw); + + if (ndims == 5) { + auto idx = with_groups + ? diff_weights_d.off(g, oc, ic, kd, kh, kw) + : diff_weights_d.off(oc, ic, kd, kh, kw); + diff_weights[idx] = saturate(dw); + } else if (ndims == 4) { + auto idx = with_groups + ? diff_weights_d.off(g, oc, ic, kh, kw) + : diff_weights_d.off(oc, ic, kh, kw); + diff_weights[idx] = saturate(dw); + } else if (ndims == 3) { + auto idx = with_groups + ? diff_weights_d.off(g, oc, ic, kw) + : diff_weights_d.off(oc, ic, kw); + diff_weights[idx] = saturate(dw); + } else { + assert(false); + } + } + }); +} + +using namespace data_type; + +template struct ref_convolution_fwd_t; + +template struct ref_convolution_fwd_t; +template struct ref_convolution_fwd_t; +template struct ref_convolution_fwd_t; +template struct ref_convolution_fwd_t; + +template struct ref_convolution_bwd_data_t; + +template struct ref_convolution_bwd_data_t; +template struct ref_convolution_bwd_data_t; +template struct ref_convolution_bwd_data_t; +template struct ref_convolution_bwd_data_t; + +template struct ref_convolution_bwd_weights_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp new file mode 100644 index 0000000000..7c83d0c6d4 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp @@ -0,0 +1,194 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_CONVOLUTION_HPP +#define CPU_REF_CONVOLUTION_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct ref_convolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_fwd_pd_t { + using cpu_convolution_fwd_pd_t::cpu_convolution_fwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_convolution_fwd_t); + + status_t init() { + using namespace data_type; + + bool ok = true + && is_fwd() + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, wei_type, data_type::undef, + dst_type, acc_type) + && IMPLICATION(with_bias(), true + && IMPLICATION(src_type == u8, + utils::one_of(bias_md_.data_type, f32, s32, s8, u8)) + && IMPLICATION(src_type == f32, + bias_md_.data_type == f32)) + && set_default_formats() + && attr()->has_default_values(); + return ok ? status::success : status::unimplemented; + } + + protected: + bool set_default_formats() { + using namespace format_tag; + auto dat_tag = utils::pick(ndims() - 3, ncw, nchw, ncdhw); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, goiw, goihw, goidhw) + : utils::pick(ndims() - 3, oiw, oihw, oidhw); + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + ref_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_convolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_data_pd_t { + using cpu_convolution_bwd_data_pd_t::cpu_convolution_bwd_data_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_convolution_bwd_data_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(diff_src_type, wei_type, data_type::undef, + diff_dst_type, acc_type) + && set_default_formats() + && attr()->has_default_values(); + + return ok ? status::success : status::unimplemented; + } + + virtual bool support_bias() const override { return true; } + + protected: + bool set_default_formats() { + using namespace format_tag; + auto dat_tag = utils::pick(ndims() - 3, ncw, nchw, ncdhw); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, goiw, goihw, goidhw) + : utils::pick(ndims() - 3, oiw, oihw, oidhw); + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + ref_convolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type diff_src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type diff_dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_convolution_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_convolution_bwd_weights_pd_t { + using cpu_convolution_bwd_weights_pd_t::cpu_convolution_bwd_weights_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_convolution_bwd_weights_t); + + status_t init() { + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && set_default_alg_kind(alg_kind::convolution_direct) + && expect_data_types(src_type, diff_wei_type, diff_wei_type, + diff_dst_type, acc_type) + && set_default_formats() + && attr()->has_default_values(); + return ok ? status::success : status::unimplemented; + } + + protected: + bool set_default_formats() { + using namespace format_tag; + auto dat_tag = utils::pick(ndims() - 3, ncw, nchw, ncdhw); + auto wei_tag = with_groups() + ? utils::pick(ndims() - 3, goiw, goihw, goidhw) + : utils::pick(ndims() - 3, oiw, oihw, oidhw); + return set_default_formats_common(dat_tag, wei_tag, dat_tag); + } + }; + + ref_convolution_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type diff_wei_data_t; + typedef typename prec_traits::type diff_dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp new file mode 100644 index 0000000000..541a303aab --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp @@ -0,0 +1,199 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" +#include "mkldnn_traits.hpp" +#include "math_utils.hpp" + +#include "ref_deconvolution.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +void ref_deconvolution_fwd_t::compute_fwd_bias(const data_t *bias, + data_t *dst) const { + const memory_desc_wrapper dst_d(pd()->dst_md()); + + const int G = pd()->G(); + const int MB = pd()->MB(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + const int OD = pd()->OD(); + const int OC = pd()->OC() / G; + const int ndims = pd()->desc()->src_desc.ndims; + + parallel_nd(MB, G, OC, OD, OH, OW, + [&](int mb, int g, int oc, int od, int oh, int ow) { + auto b = bias[g * OC + oc]; + switch (ndims) { + case 5: dst[dst_d.off(mb, g * OC + oc, od, oh, ow)] += b; break; + case 4: dst[dst_d.off(mb, g * OC + oc, oh, ow)] += b; break; + case 3: dst[dst_d.off(mb, g * OC + oc, ow)] += b; break; + default: assert(!"invalid dimension size"); + } + }); +} + +void ref_deconvolution_fwd_t::compute_fwd_bias_ncdhw(const data_t *bias, + data_t *dst) const { + const memory_desc_wrapper dst_d(pd()->dst_md()); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int SP = pd()->OW()*pd()->OH()*pd()->OD(); + + parallel_nd(MB, OC, [&](int mb, int oc) { + PRAGMA_OMP_SIMD() + for (int sp = 0; sp < SP; ++sp) { + auto offset = (size_t)(mb * OC + oc) * SP + sp; + dst[offset] += bias[oc]; + } + }); +} + +template +void ref_deconvolution_fwd_t::compute_fwd_bias_nCdhwXc(const data_t *bias, + data_t *dst) const { + const memory_desc_wrapper dst_d(pd()->dst_md()); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int SP = pd()->OW() * pd()->OH() * pd()->OD(); + + const ptrdiff_t stride_mb = dst_d.blocking_desc().strides[0]; + + parallel_nd(MB, utils::div_up(OC, blksize), SP, + [&](int mb, int oc_blk, int sp) { + int oc = oc_blk * blksize; + auto offset = mb * stride_mb + oc * SP + sp * blksize; + const int blk = nstl::min(blksize, OC - oc); + + PRAGMA_OMP_SIMD() + for (int i = 0; i < blk; ++i) + dst[offset + i] += bias[oc + i]; + }); +} + +void ref_deconvolution_bwd_weights_t::compute_bwd_bias(const data_t *diff_dst, + data_t *diff_bias) const { + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + + const int G = pd()->G(); + const int MB = pd()->MB(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + const int OC = pd()->OC() / G; + const int OD = pd()->OD(); + const int ndims = pd()->desc()->src_desc.ndims; + + parallel_nd(G, OC, [&](int g, int oc) { + data_t db = 0; + for (int mb = 0; mb < MB; ++mb) { + for (int od = 0; od < OD; ++od) { + for (int oh = 0; oh < OH; ++oh) { + for (int ow = 0; ow < OW; ++ow) { + switch (ndims) { + case 5: + db += diff_dst[diff_dst_d.off( + mb, g * OC + oc, od, oh, ow)]; + break; + case 4: + db += diff_dst[diff_dst_d.off( + mb, g * OC + oc, oh, ow)]; + break; + case 3: + db += diff_dst[diff_dst_d.off(mb, g * OC + oc, ow)]; + break; + default: assert(!"invalid dimension size"); + } + } + } + } + } + diff_bias[g * OC + oc] = db; + }); +} + +void ref_deconvolution_bwd_weights_t::compute_bwd_bias_ncdhw( + const data_t *diff_dst, data_t *diff_bias) const { + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + + const int OC = pd()->OC(); + const int MB = pd()->MB(); + const int SP = pd()->OH()*pd()->OW()*pd()->OD(); + + parallel_nd(OC, [&](int oc) { + data_t db = 0; + for (int mb = 0; mb < MB; ++mb) { + PRAGMA_OMP_SIMD() + for (int sp = 0; sp < SP; ++sp) { + auto offset = (size_t)(mb * OC + oc) * SP + sp; + db += diff_dst[offset]; + } + } + diff_bias[oc] = db; + }); +} + +template +void ref_deconvolution_bwd_weights_t::compute_bwd_bias_nCdhwXc( + const data_t *diff_dst, data_t *diff_bias) const { + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + + const int OC = pd()->OC(); + const int MB = pd()->MB(); + const int SP = pd()->OH() * pd()->OW() * pd()->OD(); + + const ptrdiff_t stride_mb = diff_dst_d.blocking_desc().strides[0]; + + parallel_nd(utils::div_up(OC, blksize), [&](int ocb) { + data_t db[blksize] = {0}; + + for (int mb = 0; mb < MB; ++mb) { + for (int sp = 0; sp < SP; ++sp) { + auto offset = mb * stride_mb + (ocb * SP + sp) * blksize; + + PRAGMA_OMP_SIMD() + for (int i = 0; i < blksize; ++i) + db[i] += diff_dst[offset+i]; + } + } + + const int blk = nstl::min(blksize, OC - ocb * blksize); + + PRAGMA_OMP_SIMD() + for (int i = 0; i < blk; ++i) + diff_bias[ocb * blksize + i] = db[i]; + }); +} + +template void ref_deconvolution_fwd_t::compute_fwd_bias_nCdhwXc<8>( + const data_t *diff_dst, data_t *diff_bias) const; +template void ref_deconvolution_fwd_t::compute_fwd_bias_nCdhwXc<16>( + const data_t *diff_dst, data_t *diff_bias) const; +template void ref_deconvolution_bwd_weights_t::compute_bwd_bias_nCdhwXc<8>( + const data_t *diff_dst, data_t *diff_bias) const; +template void ref_deconvolution_bwd_weights_t::compute_bwd_bias_nCdhwXc<16>( + const data_t *diff_dst, data_t *diff_bias) const; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp new file mode 100644 index 0000000000..d61903c32d --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp @@ -0,0 +1,502 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_DECONVOLUTION_HPP +#define CPU_REF_DECONVOLUTION_HPP + +#include +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "primitive_iterator.hpp" + +#include "cpu_convolution_pd.hpp" +#include "cpu_deconvolution_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +static status_t compute_blocked_format(bool with_groups, + const memory_desc_t *oi_md, memory_desc_t *io_md) +{ + /* Computes blocking for *i*o* format from *o*i* format */ + + bool sanity_check_ok = true + && oi_md->ndims == io_md->ndims + && oi_md->format_kind == format_kind::blocked; + if (!sanity_check_ok) return status::invalid_arguments; + + const blocking_desc_t &oi_blk = oi_md->format_desc.blocking; + blocking_desc_t io_blk = io_md->format_desc.blocking; + + io_md->format_kind = format_kind::blocked; + io_blk = oi_blk; + + const int ID_OC = 0 + with_groups; + const int ID_IC = 1 + with_groups; + + nstl::swap(io_blk.strides[ID_OC], io_blk.strides[ID_IC]); + for (int i_blk = 0; i_blk < io_blk.inner_nblks; ++i_blk) { + if (utils::one_of(io_blk.inner_idxs[i_blk], ID_OC, ID_IC)) { + io_blk.inner_idxs[i_blk] = + (io_blk.inner_idxs[i_blk] == ID_OC ? ID_IC : ID_OC); + } + } + + return memory_desc_init_by_blocking_desc(*io_md, io_blk); +} + +static status_t conv_descr_create(const deconvolution_desc_t *dd, + convolution_desc_t *cd) +{ + using namespace prop_kind; + alg_kind_t alg_kind = dd->alg_kind == alg_kind::deconvolution_direct + ? alg_kind::convolution_direct : alg_kind::convolution_winograd; + + const memory_desc_t *src_md, *dst_md, *d_weights_d; + prop_kind_t prop_kind; + memory_desc_t c_weights_d; + if (utils::one_of(dd->prop_kind, forward_training, forward_inference)) { + prop_kind = backward_data; + src_md = &dd->dst_desc; + dst_md = &dd->src_desc; + d_weights_d = &dd->weights_desc; + } else if (dd->prop_kind == backward_data) { + prop_kind = forward_training; + src_md = &dd->diff_dst_desc; + dst_md = &dd->diff_src_desc; + d_weights_d = &dd->weights_desc; + } else { + prop_kind = dd->prop_kind; + src_md = &dd->diff_dst_desc; + dst_md = &dd->src_desc; + d_weights_d = &dd->diff_weights_desc; + } + + const bool with_groups = d_weights_d->ndims == src_md->ndims + 1; + + /* create weights desc for convolution */ + c_weights_d = *d_weights_d; + + const int ID_OC = 0 + with_groups; + const int ID_IC = 1 + with_groups; + + nstl::swap(c_weights_d.dims[ID_OC], c_weights_d.dims[ID_IC]); + nstl::swap(c_weights_d.padded_dims[ID_OC], c_weights_d.padded_dims[ID_IC]); + nstl::swap(c_weights_d.padded_offsets[ID_OC], c_weights_d.padded_offsets[ID_IC]); + + if (c_weights_d.format_kind != format_kind::any) + CHECK(compute_blocked_format(with_groups, d_weights_d, &c_weights_d)); + + return conv_desc_init(cd, prop_kind, alg_kind, src_md, &c_weights_d, + prop_kind != backward_weights ? &dd->bias_desc : nullptr, + dst_md, dd->strides, dd->dilates, + dd->padding[0], dd->padding[1], dd->padding_kind); +} + +struct ref_deconvolution_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_deconvolution_fwd_pd_t { + pd_t(engine_t *engine, + const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : cpu_deconvolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd) + , conv_pd_(nullptr) + {} + + pd_t(const pd_t &other) + : cpu_deconvolution_fwd_pd_t(other) + , conv_pd_(other.conv_pd_->clone()) + , conv_supports_bias_(other.conv_supports_bias_) + , dst_tag_(other.dst_tag_) + {} + + ~pd_t() { delete conv_pd_; } + + DECLARE_COMMON_PD_T(conv_pd_->name(), ref_deconvolution_fwd_t); + + status_t init_convolution() { + using namespace types; + + convolution_desc_t cd; + CHECK(conv_descr_create(desc(), &cd)); + + mkldnn_primitive_desc_iterator it(engine_, (op_desc_t *)&cd, + &attr_, nullptr); + while (++it != it.end()) { + conv_pd_ = *it; + conv_supports_bias_ = + static_cast(conv_pd_) + ->support_bias(); + bool output_f32 = utils::everyone_is(data_type::f32, + desc()->accum_data_type, desc()->dst_desc.data_type); + + bool ok = true + && conv_pd_->weights_md()->extra.flags == 0 + /* deconv reference code can process only f32 bias */ + && IMPLICATION(with_bias(), + conv_supports_bias_ || output_f32); + if (ok) return status::success; + + delete conv_pd_; + } + conv_pd_ = nullptr; + return status::unimplemented; + } + + status_t init() { + using namespace format_tag; + bool ok = true + && is_fwd() + && utils::one_of(desc()->alg_kind, + alg_kind::deconvolution_direct, + alg_kind::deconvolution_winograd) + && attr()->post_ops_.has_default_values(); + + if (ok) { + CHECK(init_convolution()); + if (weights_md_.format_kind == format_kind::any) { + CHECK(compute_blocked_format(with_groups(), + conv_pd_->weights_md(), &desc_.weights_desc)); + weights_md_ = desc_.weights_desc; + } + if (src_md_.format_kind == format_kind::any) + src_md_ = *conv_pd_->diff_dst_md(); + if (dst_md_.format_kind == format_kind::any) + dst_md_ = *conv_pd_->diff_src_md(); + if (bias_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(bias_md_, x)); + + dst_tag_ = memory_desc_matches_one_of_tag(dst_md_, + utils::pick(ndims() - 3, ncw, nchw, ncdhw), + utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c), + utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c)); + + return status::success; + } + + return status::unimplemented; + } + + virtual void init_scratchpad_md() override { + scratchpad_md_ = *conv_pd_->scratchpad_md(); + } + + primitive_desc_t *conv_pd_; + bool conv_supports_bias_; + format_tag_t dst_tag_; + }; + + typedef typename prec_traits::type data_t; + + ref_deconvolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) + { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); } + ~ref_deconvolution_fwd_t() { delete conv_p_; } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + const auto &args = ctx.args(); + exec_args_t conv_args; + conv_args[MKLDNN_ARG_DIFF_DST] = args.at(MKLDNN_ARG_SRC); + conv_args[MKLDNN_ARG_WEIGHTS] = args.at(MKLDNN_ARG_WEIGHTS); + if (pd()->with_bias() && pd()->conv_supports_bias_) + conv_args[MKLDNN_ARG_BIAS] = args.at(MKLDNN_ARG_BIAS); + conv_args[MKLDNN_ARG_DIFF_SRC] = args.at(MKLDNN_ARG_DST); + if (!types::is_zero_md(pd()->scratchpad_md())) + conv_args[MKLDNN_ARG_SCRATCHPAD] = args.at(MKLDNN_ARG_SCRATCHPAD); + const exec_ctx_t conv_ctx(ctx.stream(), std::move(conv_args)); + + conv_p_->execute(conv_ctx); + + if (pd()->with_bias() && !pd()->conv_supports_bias_) { + using namespace format_tag; + + auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + switch (pd()->dst_tag_) { + case ncdhw: case nchw: case ncw: + compute_fwd_bias_ncdhw(bias, dst); + break; + case nCdhw8c: case nChw8c: case nCw8c: + compute_fwd_bias_nCdhwXc<8>(bias, dst); + break; + case nCdhw16c: case nChw16c: case nCw16c: + compute_fwd_bias_nCdhwXc<16>(bias, dst); + break; + default: + compute_fwd_bias(bias, dst); + break; + } + } + return status::success; + } + +private: + void compute_fwd_bias(const data_t *bias, data_t *dst) const; + void compute_fwd_bias_ncdhw(const data_t *bias, data_t *dst) const; + template void compute_fwd_bias_nCdhwXc(const data_t *bias, + data_t *dst) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + primitive_t *conv_p_; +}; + +struct ref_deconvolution_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_deconvolution_bwd_data_pd_t { + pd_t(engine_t *engine, const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : cpu_deconvolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd) + , conv_pd_(nullptr) + {} + + pd_t(const pd_t &other) + : cpu_deconvolution_bwd_data_pd_t(other) + , conv_pd_(other.conv_pd_->clone()) {} + + ~pd_t() { delete conv_pd_; } + + DECLARE_COMMON_PD_T(conv_pd_->name(), ref_deconvolution_bwd_data_t); + + status_t init_convolution() { + using namespace types; + + convolution_desc_t cd; + status_t status = conv_descr_create(desc(), &cd); + if (status != status::success) return status; + + mkldnn_primitive_desc_iterator it(engine_, (op_desc_t *)&cd, + &attr_, nullptr); + while (++it != it.end()) { + conv_pd_ = *it; + if (conv_pd_->weights_md()->extra.flags == 0) + return status::success; + delete conv_pd_; + } + + return status::unimplemented; + } + + status_t init() { + using namespace data_type; + bool ok = true + && desc()->prop_kind == prop_kind::backward_data + && utils::everyone_is(data_type::f32, + desc()->diff_src_desc.data_type, + desc()->weights_desc.data_type, + desc()->diff_dst_desc.data_type) + && utils::one_of(desc()->alg_kind, + alg_kind::deconvolution_direct, + alg_kind::deconvolution_winograd); + + if (ok) { + CHECK(init_convolution()); + if (weights_md_.format_kind == format_kind::any) { + CHECK(compute_blocked_format(with_groups(), + conv_pd_->weights_md(), &desc_.weights_desc)); + weights_md_ = desc_.weights_desc; + } + if (diff_src_md_.format_kind == format_kind::any) + diff_src_md_ = *conv_pd_->dst_md(); + if (diff_dst_md_.format_kind == format_kind::any) + diff_dst_md_ = *conv_pd_->src_md(); + + return status::success; + } + + return status::unimplemented; + } + + virtual void init_scratchpad_md() override { + scratchpad_md_ = *conv_pd_->scratchpad_md(); + } + + primitive_desc_t *conv_pd_; + }; + + typedef typename prec_traits::type data_t; + + ref_deconvolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) + { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); } + ~ref_deconvolution_bwd_data_t() { delete conv_p_; } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + const auto &args = ctx.args(); + exec_args_t conv_args; + conv_args[MKLDNN_ARG_SRC] = args.at(MKLDNN_ARG_DIFF_DST); + conv_args[MKLDNN_ARG_WEIGHTS] = args.at(MKLDNN_ARG_WEIGHTS); + conv_args[MKLDNN_ARG_DST] = args.at(MKLDNN_ARG_DIFF_SRC); + if (!types::is_zero_md(pd()->scratchpad_md())) + conv_args[MKLDNN_ARG_SCRATCHPAD] = args.at(MKLDNN_ARG_SCRATCHPAD); + const exec_ctx_t conv_ctx(ctx.stream(), std::move(conv_args)); + + conv_p_->execute(conv_ctx); + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + primitive_t *conv_p_; +}; + +struct ref_deconvolution_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_deconvolution_bwd_weights_pd_t { + pd_t(engine_t *engine, + const deconvolution_desc_t *adesc, + const primitive_attr_t *attr, + const deconvolution_fwd_pd_t *hint_fwd_pd) + : cpu_deconvolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd) + , conv_pd_(nullptr) + {} + + pd_t(const pd_t &other) + : cpu_deconvolution_bwd_weights_pd_t(other) + , conv_pd_(other.conv_pd_->clone()) + , dst_tag_(other.dst_tag_) + {} + + ~pd_t() { delete conv_pd_; } + + DECLARE_COMMON_PD_T(conv_pd_->name(), ref_deconvolution_bwd_weights_t); + + status_t init_convolution() { + using namespace types; + + convolution_desc_t cd; + status_t status = conv_descr_create(desc(), &cd); + if (status != status::success) return status; + + mkldnn_primitive_desc_iterator it(engine_, (op_desc_t *)&cd, + &attr_, nullptr); + while (++it != it.end()) { + conv_pd_ = *it; + if (conv_pd_->diff_weights_md()->extra.flags == 0) + return status::success; + delete conv_pd_; + } + return status::unimplemented; + } + + status_t init() { + using namespace format_tag; + bool ok = true + && desc()->prop_kind == prop_kind::backward_weights + && utils::everyone_is(data_type::f32, + desc()->src_desc.data_type, + desc()->diff_weights_desc.data_type, + desc()->diff_dst_desc.data_type) + && utils::one_of(desc()->alg_kind, + alg_kind::deconvolution_direct, + alg_kind::deconvolution_winograd) + && attr()->has_default_values(); + if (ok) { + CHECK(init_convolution()); + if (diff_weights_md_.format_kind == format_kind::any) { + CHECK(compute_blocked_format(with_groups(), + conv_pd_->diff_weights_md(), + &desc_.diff_weights_desc)); + diff_weights_md_ = desc_.diff_weights_desc; + } + if (src_md_.format_kind == format_kind::any) + src_md_ = *conv_pd_->diff_dst_md(); + if (diff_dst_md_.format_kind == format_kind::any) + diff_dst_md_ = *conv_pd_->src_md(); + if (diff_bias_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_bias_md_, x)); + + dst_tag_ = memory_desc_matches_one_of_tag(diff_dst_md_, + utils::pick(ndims() - 3, ncw, nchw, ncdhw), + utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c), + utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c)); + + return status::success; + } + + return status::unimplemented; + } + + virtual void init_scratchpad_md() override { + scratchpad_md_ = *conv_pd_->scratchpad_md(); + } + + primitive_desc_t *conv_pd_; + format_tag_t dst_tag_; + }; + + typedef typename prec_traits::type data_t; + + ref_deconvolution_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd) + { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); } + ~ref_deconvolution_bwd_weights_t() { delete conv_p_; } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + const auto &args = ctx.args(); + exec_args_t conv_args; + conv_args[MKLDNN_ARG_DIFF_DST] = args.at(MKLDNN_ARG_SRC); + conv_args[MKLDNN_ARG_SRC] = args.at(MKLDNN_ARG_DIFF_DST); + conv_args[MKLDNN_ARG_DIFF_WEIGHTS] = args.at(MKLDNN_ARG_DIFF_WEIGHTS); + if (!types::is_zero_md(pd()->scratchpad_md())) + conv_args[MKLDNN_ARG_SCRATCHPAD] = args.at(MKLDNN_ARG_SCRATCHPAD); + const exec_ctx_t conv_ctx(ctx.stream(), std::move(conv_args)); + + status_t status = conv_p_->execute(conv_ctx); + if (status != status::success) return status; + + if (pd()->with_bias()) { + using namespace format_tag; + + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + switch (pd()->dst_tag_) { + case ncdhw: case nchw: case ncw: + compute_bwd_bias_ncdhw(diff_dst, diff_bias); + break; + case nCdhw8c: case nChw8c: case nCw8c: + compute_bwd_bias_nCdhwXc<8>(diff_dst, diff_bias); + break; + case nCdhw16c: case nChw16c: case nCw16c: + compute_bwd_bias_nCdhwXc<16>(diff_dst, diff_bias); + break; + default: + compute_bwd_bias(diff_dst, diff_bias); + break; + } + } + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + void compute_bwd_bias(const data_t *diff_dst, data_t *diff_bias) const; + void compute_bwd_bias_ncdhw(const data_t *diff_dst, + data_t *diff_bias) const; + template void compute_bwd_bias_nCdhwXc( + const data_t *diff_dst, data_t *diff_bias) const; + + primitive_t *conv_p_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp new file mode 100644 index 0000000000..7beee8d323 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp @@ -0,0 +1,297 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" + +#include "ref_eltwise.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace alg_kind; +using namespace math; + +ref_eltwise_scalar_fwd_t::ref_eltwise_scalar_fwd_t(alg_kind_t alg, float alpha, + float beta): alg_(alg), alpha_(alpha), beta_(beta) { + assert(utils::one_of(alg_, eltwise_relu, eltwise_tanh, eltwise_elu, + eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear, + eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic)); +} + +ref_eltwise_scalar_fwd_t::ref_eltwise_scalar_fwd_t( + const post_ops_t::entry_t::eltwise_t &eltwise) + : ref_eltwise_scalar_fwd_t(eltwise.alg, eltwise.alpha, eltwise.beta) {} + +float ref_eltwise_scalar_fwd_t::compute_scalar(float s) { + switch (alg_) { + case eltwise_relu: return relu_fwd(s, alpha_); + case eltwise_tanh: return tanh_fwd(s); + case eltwise_elu: return elu_fwd(s, alpha_); + case eltwise_square: return square_fwd(s); + case eltwise_abs: return abs_fwd(s); + case eltwise_sqrt: return sqrt_fwd(s); + case eltwise_linear: return linear_fwd(s, alpha_, beta_); + case eltwise_bounded_relu: return bounded_relu_fwd(s, alpha_); + case eltwise_soft_relu: return soft_relu_fwd(s); + case eltwise_logistic: return logistic_fwd(s); + default: assert(!"unknown eltwise alg_kind"); + } + + return 0.f; +} + +template +void ref_eltwise_fwd_t::execute_forward_nCspBc_padded( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper data_d(pd()->src_md()); + const blocking_desc_t &blk = data_d.blocking_desc(); + const int block = blk.inner_blks[0]; + + const int MB = pd()->MB(); + const int C = pd()->C() / block; + const int C_PADDED = data_d.padded_dims()[1] / block; + const int tail = pd()->C() % block; + const int SP = pd()->D() * pd()->H() * pd()->W(); + const auto alg_kind = pd()->desc()->alg_kind; + const float alpha = pd()->desc()->alpha; + const float beta = pd()->desc()->beta; + + auto ker = [=] (data_t &d, data_t s) { + switch (alg_kind) { + case eltwise_linear: d = linear_fwd(s, alpha, beta); break; + case eltwise_bounded_relu: + d = bounded_relu_fwd(s, alpha); break; + case eltwise_soft_relu: d = soft_relu_fwd(s); break; + case eltwise_logistic: d = logistic_fwd(s); break; + default: assert(!"unknown eltwise alg_kind"); + } + }; + + // FIXME: integer overflow? + + parallel_nd(MB, C_PADDED, SP, + [&](int n, int c, int sp) { + auto d_off = (n*C_PADDED*SP + c*SP + sp) * block; + if (c < C) { + for (int v = 0; v < block; v++) + ker(dst[d_off + v], src[d_off + v]); + } else { + for (int v = 0; v < tail; v++) + ker(dst[d_off + v], src[d_off + v]); + } + }); +} + +template +void ref_eltwise_fwd_t::execute_forward_generic( + const exec_ctx_t &ctx) const { + /* fast return */ + if (pd()->has_zero_dim_memory()) return; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper data_d(pd()->src_md()); + + const int MB = pd()->MB(); + const int C = pd()->C(); + const int D = pd()->D(); + const int H = pd()->H(); + const int W = pd()->W(); + const auto alg_kind = pd()->desc()->alg_kind; + const float alpha = pd()->desc()->alpha; + const float beta = pd()->desc()->beta; + const bool is_3d = pd()->desc()->data_desc.ndims == 5; + + parallel_nd(MB, C, D, H, W, + [&](int n, int c, int id, int h, int w) { + auto d_off = is_3d + ? data_d.off(n, c, id, h, w) : data_d.off(n, c, h, w); + data_t s = src[d_off]; + data_t &d = dst[d_off]; + switch (alg_kind) { + case eltwise_relu: d = relu_fwd(s, alpha); break; + case eltwise_tanh: d = tanh_fwd(s); break; + case eltwise_elu: d = elu_fwd(s, alpha); break; + case eltwise_square: d = square_fwd(s); break; + case eltwise_abs: d = abs_fwd(s); break; + case eltwise_sqrt: d = sqrt_fwd(s); break; + case eltwise_linear: d = linear_fwd(s, alpha, beta); break; + case eltwise_bounded_relu: + d = bounded_relu_fwd(s, alpha); break; + case eltwise_soft_relu: d = soft_relu_fwd(s); break; + case eltwise_logistic: d = logistic_fwd(s); break; + default: assert(!"unknown eltwise alg_kind"); + } + }); +} + +template +void ref_eltwise_fwd_t::execute_forward_dense( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper data_d(pd()->src_md()); + + const ptrdiff_t nelems = static_cast(data_d.nelems(true)); + const auto alg_kind = pd()->desc()->alg_kind; + const float alpha = pd()->desc()->alpha; + const float beta = pd()->desc()->beta; + + src += data_d.offset0(); + dst += data_d.offset0(); + + if (alg_kind == eltwise_relu) { + // a fast path for relu as the most popular activation + parallel_nd(nelems, [&](ptrdiff_t e) { + dst[e] = relu_fwd(src[e], alpha); + }); + return; + } + + parallel_nd(nelems, [&](ptrdiff_t e) { + const data_t s = src[e]; + data_t &d = dst[e]; + + switch (alg_kind) { + case eltwise_tanh: d = tanh_fwd(s); break; + case eltwise_elu: d = elu_fwd(s, alpha); break; + case eltwise_square: d = square_fwd(s); break; + case eltwise_abs: d = abs_fwd(s); break; + case eltwise_sqrt: d = sqrt_fwd(s); break; + case eltwise_linear: d = linear_fwd(s, alpha, beta); break; + case eltwise_bounded_relu: d = bounded_relu_fwd(s, alpha); break; + case eltwise_soft_relu: d = soft_relu_fwd(s); break; + case eltwise_logistic: d = logistic_fwd(s); break; + default: assert(!"unknown eltwise alg_kind"); + } + }); +} + +template +void ref_eltwise_bwd_t::execute_backward_generic( + const exec_ctx_t &ctx) const { + /* fast return */ + if (pd()->has_zero_dim_memory()) return; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper data_d(pd()->src_md()); + const memory_desc_wrapper diff_data_d(pd()->diff_src_md()); + + const int MB = pd()->MB(); + const int C = pd()->C(); + const int D = pd()->D(); + const int H = pd()->H(); + const int W = pd()->W(); + const auto alg_kind = pd()->desc()->alg_kind; + const float alpha = pd()->desc()->alpha; + const float beta = pd()->desc()->beta; + const bool is_3d = pd()->desc()->data_desc.ndims == 5; + + parallel_nd(MB, C, D, H, W, + [&](int n, int c, int d, int h, int w) { + auto data_off = is_3d + ? data_d.off(n, c, d, h, w) : data_d.off(n, c, h, w); + auto diff_data_off = is_3d + ? diff_data_d.off(n, c, d, h, w) + : diff_data_d.off(n, c, h, w); + data_t s = src[data_off]; + data_t dd = diff_dst[diff_data_off]; + data_t &ds = diff_src[diff_data_off]; + switch (alg_kind) { + case eltwise_relu: ds = relu_bwd(dd, s, alpha); break; + case eltwise_tanh: ds = tanh_bwd(dd, s); break; + case eltwise_elu: ds = elu_bwd(dd, s, alpha); break; + case eltwise_square: ds = square_bwd(dd, s); break; + case eltwise_abs: ds = abs_bwd(dd, s); break; + case eltwise_sqrt: ds = sqrt_bwd(dd, s); break; + case eltwise_linear: + ds = linear_bwd(dd, s, alpha, beta); break; + case eltwise_bounded_relu: + ds = bounded_relu_bwd(dd, s, alpha); break; + case eltwise_soft_relu: ds = soft_relu_bwd(dd, s); break; + case eltwise_logistic: ds = logistic_bwd(dd, s); break; + default: assert(!"unknown eltwise alg_kind"); + } + }); +} + +template +void ref_eltwise_bwd_t::execute_backward_dense( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper data_d(pd()->src_md()); + const memory_desc_wrapper diff_data_d(pd()->diff_src_md()); + + const ptrdiff_t nelems = static_cast(data_d.nelems(true)); + const auto alg_kind = pd()->desc()->alg_kind; + const float alpha = pd()->desc()->alpha; + const float beta = pd()->desc()->beta; + + src += data_d.offset0(); + diff_dst += diff_data_d.offset0(); + diff_src += diff_data_d.offset0(); + + parallel_nd(nelems, [&](ptrdiff_t e) { + const data_t dd = diff_dst[e]; + const data_t s = src[e]; + data_t &ds = diff_src[e]; + + switch (alg_kind) { + case eltwise_relu: ds = relu_bwd(dd, s, alpha); break; + case eltwise_tanh: ds = tanh_bwd(dd, s); break; + case eltwise_elu: ds = elu_bwd(dd, s, alpha); break; + case eltwise_square: ds = square_bwd(dd, s); break; + case eltwise_abs: ds = abs_bwd(dd, s); break; + case eltwise_sqrt: ds = sqrt_bwd(dd, s); break; + case eltwise_linear: ds = linear_bwd(dd, s, alpha, beta); break; + case eltwise_bounded_relu: ds = bounded_relu_bwd(dd, s, alpha); break; + case eltwise_soft_relu: ds = soft_relu_bwd(dd, s); break; + case eltwise_logistic: ds = logistic_bwd(dd, s); break; + default: assert(!"unknown eltwise alg_kind"); + } + }); +} + +template struct ref_eltwise_fwd_t; +template struct ref_eltwise_fwd_t; +template struct ref_eltwise_fwd_t; +template struct ref_eltwise_fwd_t; + +template struct ref_eltwise_bwd_t; +template struct ref_eltwise_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp new file mode 100644 index 0000000000..8f4ab35413 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp @@ -0,0 +1,168 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_ELTWISE_HPP +#define CPU_REF_ELTWISE_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_eltwise_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct ref_eltwise_scalar_fwd_t { +public: + ref_eltwise_scalar_fwd_t(alg_kind_t alg, float alpha, float beta); + + // note that eltwise.scale is ignored + ref_eltwise_scalar_fwd_t(const post_ops_t::entry_t::eltwise_t &eltwise); + + float compute_scalar(float s); + + const alg_kind_t alg_; + const float alpha_; + const float beta_; +}; + +template +struct ref_eltwise_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_eltwise_fwd_pd_t { + using cpu_eltwise_fwd_pd_t::cpu_eltwise_fwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_eltwise_fwd_t); + + status_t init() { + using namespace utils; + + auto src_d = memory_desc_wrapper(src_md()); + + use_dense_ = false + || src_d.is_dense() + || (src_d.is_dense(true) && is_zero_preserved()); + + use_nCspBc_padded_ = !use_dense_ + && src_d.blocking_desc().inner_nblks == 1 + && one_of(src_d.blocking_desc().inner_blks[0], 8, 16) + && src_d.blocking_desc().inner_idxs[0] == 1 + && src_d.only_padded_dim(1) + && src_d.is_dense(true); + + if (has_zero_dim_memory()) + use_dense_ = use_nCspBc_padded_ = false; + + const bool use_generic = !use_dense_ && !use_nCspBc_padded_; + + bool ok = true + && is_fwd() + && everyone_is(data_type, desc()->data_desc.data_type) + && IMPLICATION(use_generic, one_of(src_d.ndims(), 4, 5)) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + return status::success; + } + + bool use_dense_, use_nCspBc_padded_; + }; + + ref_eltwise_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + if (pd()->use_dense_) + execute_forward_dense(ctx); + else if (pd()->use_nCspBc_padded_) + execute_forward_nCspBc_padded(ctx); + else + execute_forward_generic(ctx); + return status::success; + } + +private: + void execute_forward_nCspBc_padded(const exec_ctx_t &ctx) const; + void execute_forward_dense(const exec_ctx_t &ctx) const; + void execute_forward_generic(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_eltwise_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_eltwise_bwd_pd_t { + using cpu_eltwise_bwd_pd_t::cpu_eltwise_bwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_eltwise_bwd_t); + + status_t init() { + using namespace utils; + + bool ok = true + && !is_fwd() + && everyone_is(data_type, + desc()->data_desc.data_type, + desc()->diff_data_desc.data_type) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + auto diff_dst_d = memory_desc_wrapper(diff_dst_md()); + const bool same_fmt_ = diff_dst_d == memory_desc_wrapper(src_md()); + + use_dense_ = true + && same_fmt_ + && diff_dst_d.is_dense(true) + && is_zero_preserved() + && !has_zero_dim_memory(); + const bool use_generic = !use_dense_; + + if (use_generic && !one_of(diff_dst_d.ndims(), 4, 5)) + return status::unimplemented; + + return status::success; + } + + bool use_dense_; + }; + + ref_eltwise_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + if (pd()->use_dense_) + execute_backward_dense(ctx); + else + execute_backward_generic(ctx); + return status::success; + } + +private: + void execute_backward_dense(const exec_ctx_t &ctx) const; + void execute_backward_generic(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp new file mode 100644 index 0000000000..c807a9ffd0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp @@ -0,0 +1,285 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" +#include "mkldnn_traits.hpp" +#include "math_utils.hpp" + +#include "ref_inner_product.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using math::saturate; +using math::get_bias; + +template +void ref_inner_product_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS); + auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper bias_d(pd()->weights_md(1)); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int IC = pd()->IC(); + + const bool src_has_spatial = utils::one_of(src_d.ndims(), 3, 4, 5); + const int ndims = src_d.ndims() - 2; + + const auto &post_ops = pd()->attr()->post_ops_; + const bool do_relu = post_ops.len_ == 1; + const float nslope = do_relu ? post_ops.entry_[0].eltwise.alpha : 0.f; + + auto ker_has_spatial = [=](int mb, int oc) { + acc_data_t d = 0; + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + for (int ic = 0; ic < IC; ++ic) { + for (int kd = 0; kd < KD; ++kd) { + for (int kh = 0; kh < KH; ++kh) { + for (int kw = 0; kw < KW; ++kw) { + switch (ndims) { + case 3: + d += (acc_data_t)src[src_d.off(mb, ic, kd, kh, kw)] + * weights[weights_d.off( + oc, ic, kd, kh, kw)]; + break; + case 2: + d += (acc_data_t)src[src_d.off(mb, ic, kh, kw)] + * weights[weights_d.off(oc, ic, kh, kw)]; + break; + case 1: + d += (acc_data_t)src[src_d.off(mb, ic, kw)] + * weights[weights_d.off(oc, ic, kw)]; + break; + default: assert(!"unsupported ndims size"); + } + } + } + } + } + return d; + }; + + auto ker_no_spatial = [=](int mb, int oc) { + acc_data_t d = 0; + for (int ic = 0; ic < IC; ++ic) { + d += (acc_data_t)src[src_d.off(mb, ic)] + * weights[weights_d.off(oc, ic)]; + } + return d; + }; + + parallel_nd(MB, OC, [&](int mb, int oc) { + float a = bias + ? get_bias(bias, bias_d.off(oc), pd()->desc()->bias_desc.data_type) + : 0; + if (src_has_spatial) + a += ker_has_spatial(mb, oc); + else + a += ker_no_spatial(mb, oc); + if (do_relu && a < (acc_data_t)0) + a *= nslope; + dst[dst_d.off(mb, oc)] = saturate(a); + }); +} + +using namespace data_type; +template struct ref_inner_product_fwd_t; +template struct ref_inner_product_fwd_t; +template struct ref_inner_product_fwd_t; +template struct ref_inner_product_fwd_t; +template struct ref_inner_product_fwd_t; + +template +void ref_inner_product_bwd_data_t::execute_backward_data(const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST); + auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS); + auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper weights_d(pd()->weights_md(0)); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int IC = pd()->IC(); + + const bool diff_src_has_spatial + = utils::one_of(diff_src_d.ndims(), 3, 4, 5); + const int ndims = diff_src_d.ndims() - 2; + + parallel_nd(MB, IC, [&](int mb, int ic) { + if (diff_src_has_spatial) { + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + for (int kd = 0; kd < KD; ++kd) + for (int kh = 0; kh < KH; ++kh) + for (int kw = 0; kw < KW; ++kw) { + acc_data_t ds = acc_data_t(0); + for (int oc = 0; oc < OC; ++oc) { + switch (ndims) { + case 3: + ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)] + * weights[weights_d.off(oc, ic, kd, kh, kw)]); + break; + case 2: + ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)] + * weights[weights_d.off(oc, ic, kh, kw)]); + break; + case 1: + ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)] + * weights[weights_d.off(oc, ic, kw)]); + break; + default: assert(!"unsupported ndims size"); + } + } + switch (ndims) { + case 3: + diff_src[diff_src_d.off(mb, ic, kd, kh, kw)] + = (diff_src_data_t)ds; + break; + case 2: + diff_src[diff_src_d.off(mb, ic, kh, kw)] + = (diff_src_data_t)ds; + break; + case 1: + diff_src[diff_src_d.off(mb, ic, kw)] = (diff_src_data_t)ds; + break; + default: assert(!"unsupported ndims size"); + } + } + } else { + acc_data_t ds = acc_data_t(0); + for (int oc = 0; oc < OC; ++oc) { + ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)] * + weights[weights_d.off(oc, ic)]); + } + diff_src[diff_src_d.off(mb, ic)] = (diff_src_data_t)ds; + } + }); +} + +template struct ref_inner_product_bwd_data_t; + +template +void ref_inner_product_bwd_weights_t::execute_backward_weights( + const exec_ctx_t &ctx) const { + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS); + auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0)); + const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1)); + + const int MB = pd()->MB(); + const int OC = pd()->OC(); + const int IC = pd()->IC(); + + const bool src_has_spatial = utils::one_of(src_d.ndims(), 3, 4 ,5); + const int ndims = src_d.ndims() - 2; + + parallel_nd(OC, IC, [&](int oc, int ic) { + if (src_has_spatial) { + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + for (int kd = 0; kd < KD; ++kd) { + for (int kh = 0; kh < KH; ++kh) { + for (int kw = 0; kw < KW; ++kw) { + data_t *dw(nullptr); + switch (ndims) { + case 3: + dw = &diff_weights[diff_weights_d.off( + oc, ic, kd, kh, kw)]; + break; + case 2: + dw = &diff_weights[diff_weights_d.off( + oc, ic, kh, kw)]; + break; + case 1: + dw = &diff_weights[diff_weights_d.off(oc, ic, kw)]; + break; + default: assert(!"unsupported ndims size"); + } + *dw = data_t(0); + for (int mb = 0; mb < MB; ++mb) { + switch (ndims) { + case 3: + *dw += diff_dst[diff_dst_d.off(mb, oc)] + * src[src_d.off(mb, ic, kd, kh, kw)]; + break; + case 2: + *dw += diff_dst[diff_dst_d.off(mb, oc)] + * src[src_d.off(mb, ic, kh, kw)]; + break; + case 1: + *dw += diff_dst[diff_dst_d.off(mb, oc)] + * src[src_d.off(mb, ic, kw)]; + break; + default: assert(!"unsupported ndims size"); + } + } + } + } + } + } else { + data_t *dw = &diff_weights[diff_weights_d.off(oc, ic)]; + *dw = data_t(0); + for (int mb = 0; mb < MB; ++mb) { + *dw += diff_dst[diff_dst_d.off(mb, oc)] * + src[src_d.off(mb, ic)]; + } + } + }); + + if (diff_bias) { + diff_bias += diff_bias_d.offset0(); + + parallel_nd(OC, [&](int oc) { + data_t *db = &diff_bias[oc]; + *db = data_t(0); + for (int mb = 0; mb < MB; ++mb) + *db += diff_dst[diff_dst_d.off(mb, oc)]; + }); + } +} + +template struct ref_inner_product_bwd_weights_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp new file mode 100644 index 0000000000..bf87dbd514 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp @@ -0,0 +1,159 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_INNER_PRODUCT_HPP +#define CPU_REF_INNER_PRODUCT_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_inner_product_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct ref_inner_product_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_inner_product_fwd_pd_t { + using cpu_inner_product_fwd_pd_t::cpu_inner_product_fwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_inner_product_fwd_t); + + status_t init() { + using namespace data_type; + + bool ok = true + && set_default_params() == status::success + && is_fwd() + && src_md()->data_type == src_type + && weights_md()->data_type == wei_type + && desc()->accum_data_type == acc_type + && dst_md()->data_type == dst_type + && IMPLICATION(with_bias(), utils::one_of( + weights_md(1)->data_type, f32, s32, s8, u8)) + && attr()->output_scales_.has_default_values() + && attr()->post_ops_.len_ <= 1 + && IMPLICATION(attr()->post_ops_.len_ == 1, + attr()->post_ops_.entry_[0].is_relu(true, false)); + return ok ? status::success : status::unimplemented; + } + }; + + ref_inner_product_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_inner_product_bwd_data_t: public cpu_primitive_t { + struct pd_t: public cpu_inner_product_bwd_data_pd_t { + using cpu_inner_product_bwd_data_pd_t::cpu_inner_product_bwd_data_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_inner_product_bwd_data_t); + + status_t init() { + bool ok = true + && set_default_params() == status::success + && desc()->prop_kind == prop_kind::backward_data + && diff_src_md()->data_type == diff_src_type + && weights_md()->data_type == wei_type + && desc()->accum_data_type == acc_type + && diff_dst_md()->data_type == diff_dst_type + && attr()->has_default_values(); + return ok ? status::success : status::unimplemented; + } + }; + + ref_inner_product_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type diff_src_data_t; + typedef typename prec_traits::type wei_data_t; + typedef typename prec_traits::type diff_dst_data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_data(ctx); + return status::success; + } + +private: + void execute_backward_data(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_inner_product_bwd_weights_t: public cpu_primitive_t { + struct pd_t: public cpu_inner_product_bwd_weights_pd_t { + using cpu_inner_product_bwd_weights_pd_t::cpu_inner_product_bwd_weights_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_inner_product_bwd_weights_t); + + status_t init() { + bool ok = true + && set_default_params() == status::success + && desc()->prop_kind == prop_kind::backward_weights + && utils::everyone_is(data_type, + src_md()->data_type, + diff_dst_md()->data_type, + diff_weights_md()->data_type) + && IMPLICATION(with_bias(), + data_type == diff_weights_md(1)->data_type) + && attr()->has_default_values(); + return ok ? status::success : status::unimplemented; + } + }; + + ref_inner_product_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward_weights(ctx); + return status::success; + } + +private: + void execute_backward_weights(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp new file mode 100644 index 0000000000..325e97963b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp @@ -0,0 +1,252 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" + +#include "ref_lrn.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +static inline float fast_negative_powf(float omega, float beta) { + float Y; +/* + * Y = omega^(-3/4) = + * = 1.0f / sqrtf(omega) * sqrtf(1.0f / sqrtf(omega)) + * = sqrtf(1.0f / sqrtf(omega)) * 1.0f / sqrtf(omega) + * = sqrtf(1.0f / sqrtf(omega)) / sqrtf(omega) + * = sqrtf(1.0f / sqrtf(omega) / omega) + * = sqrtf(1.0f / (sqrtf(omega) * omega)) + */ + if (beta == 0.75f) { + Y = sqrtf(1.0f / (sqrtf(omega) * omega)); + } else { + Y = 1.0f / powf(omega, beta); + } + return Y; +}; + +template +template +void ref_lrn_fwd_t::execute_forward(const exec_ctx_t &ctx) const { + using namespace alg_kind; + using namespace format_tag; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper data_d(pd()->src_md()); + + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + const size_t stride_mb = data_d.blocking_desc().strides[0]; + const bool across_channels = pd()->desc()->alg_kind == lrn_across_channels; + constexpr int blksize = tag == nChw16c ? 16 : 8; + + auto data_off = [&](int mb, int c, int h, int w) -> size_t { + switch (tag) { + case nChw16c: + case nChw8c: return mb * stride_mb + c / blksize * H * W * blksize + + h * W * blksize + w * blksize + c % blksize; + case nchw: return mb * stride_mb + c * H * W + h * W + w; + case nhwc: return mb * stride_mb + h * W * C + w * C + c; + default: return data_d.off(mb, c, h, w); + } + }; + + auto ker = [=](data_t *d, int mb, int oc, int oh, int ow) { + const float alpha = static_cast(pd()->desc()->lrn_alpha); + const float beta = static_cast(pd()->desc()->lrn_beta); + const float k = static_cast(pd()->desc()->lrn_k); + + const int size = pd()->desc()->local_size; + const int half_size = (size - 1) / 2; + + float sum = 0; + if (across_channels) { + const int c_st = nstl::max(oc - half_size + 0, 0); + const int c_en = nstl::min(oc + half_size + 1, C); + + for (int c = c_st; c < c_en; ++c) { + const float s = src[data_off(mb, c, oh, ow)]; + sum += s * s; + } + } else { + int h_st = nstl::max(oh - half_size + 0, 0); + int h_en = nstl::min(oh + half_size + 1, H); + int w_st = nstl::max(ow - half_size + 0, 0); + int w_en = nstl::min(ow + half_size + 1, W); + for (int h = h_st; h < h_en; ++h) { + for (int w = w_st; w < w_en; ++w) { + const float s = src[data_off(mb, oc, h, w)]; + sum += s * s; + } + } + } + const int summands = across_channels ? size : size * size; + sum = k + alpha * sum / summands; + size_t off = data_off(mb, oc, oh, ow); + d[0] = static_cast(src[off] * fast_negative_powf(sum, beta)); + }; + + const int MB = pd()->MB(); + if (tag == nChw16c || tag == nChw8c) { + parallel_nd(MB, utils::div_up(C, blksize), H, W, + [&](int mb, int c_blk, int h, int w) { + int c = c_blk * blksize; + const size_t off = mb * stride_mb + c * H * W + + (h * W + w) * blksize; + PRAGMA_OMP_SIMD() + for (int cc = 0; cc < nstl::min(blksize, C - c); ++cc) + ker(&dst[off + cc], mb, c + cc, h, w); + }); + } else if (tag == nhwc) { + parallel_nd(MB, H, W, C, + [&](int mb, int h, int w, int c) { + const size_t off = mb * stride_mb + h * W * C + w * C + c; + ker(&dst[off], mb, c, h, w); + }); + } else { + parallel_nd(MB, C, H, W, + [&](int mb, int c, int h, int w) { + const size_t off = data_off(mb, c, h, w); + ker(&dst[off], mb, c, h, w); + }); + } +} + +template +template +void ref_lrn_bwd_t::execute_backward(const exec_ctx_t &ctx) const { + using namespace alg_kind; + using namespace format_tag; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper data_d(pd()->src_md()); + + const int MB = pd()->MB(); + const int C = pd()->C(); + const int H = pd()->H(); + const int W = pd()->W(); + const size_t stride_mb = data_d.blocking_desc().strides[0]; + constexpr int blksize = tag == nChw16c ? 16 : 8; + + const float alpha = static_cast(pd()->desc()->lrn_alpha); + const float beta = static_cast(pd()->desc()->lrn_beta); + const float k = static_cast(pd()->desc()->lrn_k); + const int kernel_size = pd()->desc()->local_size; + const int half_ksize = (kernel_size - 1) / 2; + + auto data_off = [&](int mb, int c, int h, int w) -> size_t { + switch (tag) { + case nChw16c: + case nChw8c: return mb * stride_mb + c/blksize * H * W * blksize + + h * W * blksize + w * blksize + c%blksize; + case nchw: return mb * stride_mb + c * H * W + h * W + w; + case nhwc: return mb * stride_mb + h * W * C + w * C + c; + default: return data_d.off(mb, c, h, w); + } + }; + + auto ker = [=](data_t *d, int mb, int oc, int oh, int ow) { + const int c_st = nstl::max(oc - half_ksize + 0, 0); + const int c_en = nstl::min(oc + half_ksize + 1, C); + + float A = 0, B = 0, omega_mid = 0; + for (int c = c_st; c < c_en; c++) { + float sum = 0.0; + const int i_st = nstl::max(c - half_ksize, 0); + const int i_en = nstl::min(c + kernel_size - half_ksize, C); + + for (int i = i_st; i < i_en; ++i) { + const float value = src[data_off(mb, i, oh, ow)]; + sum += value * value; + } + const float omega = static_cast(k + sum * alpha / kernel_size); + if (c == oc) omega_mid = omega; + float t = src[data_off(mb, c, oh, ow)] + * fast_negative_powf(omega, beta); + B += 1.0f / omega * t * diff_dst[data_off(mb, c, oh, ow)]; + } + + const size_t off = data_off(mb, oc, oh, ow); + A = fast_negative_powf(omega_mid, beta) * diff_dst[off]; + B *= src[off]; + B *= (2.0f * alpha * beta) / kernel_size; + *d = static_cast(A - B); // final cast down to data_t + }; + + if (tag == nChw16c || tag == nChw8c) { + parallel_nd(MB, utils::div_up(C, blksize), H, W, + [&](int mb, int c_blk, int h, int w) { + int c = c_blk * blksize; + const size_t off = mb * stride_mb + c * H * W + + (h * W + w) * blksize; + PRAGMA_OMP_SIMD() + for (int cc = 0; cc < nstl::min(blksize, C - c); ++cc) + ker(&diff_src[off + cc], mb, c + cc, h, w); + }); + } else if (tag == nhwc) { + parallel_nd(MB, H, W, C, + [&](int mb, int h, int w, int c) { + const size_t off = mb * stride_mb + h * W * C + w * C + c; + ker(&diff_src[off], mb, c, h, w); + }); + } else { + parallel_nd(MB, C, H, W, + [&](int mb, int c, int h, int w) { + const size_t off = data_off(mb, c, h, w); + ker(&diff_src[off], mb, c, h, w); + }); + } +} + +template void ref_lrn_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const; +template void ref_lrn_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const; +template void ref_lrn_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const; +template void ref_lrn_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const; +template void ref_lrn_fwd_t:: +execute_forward(const exec_ctx_t &ctx) const; +template void ref_lrn_bwd_t:: +execute_backward(const exec_ctx_t &ctx) const; +template void ref_lrn_bwd_t:: +execute_backward(const exec_ctx_t &ctx) const; +template void ref_lrn_bwd_t:: +execute_backward(const exec_ctx_t &ctx) const; +template void ref_lrn_bwd_t:: +execute_backward(const exec_ctx_t &ctx) const; +template void ref_lrn_bwd_t:: +execute_backward(const exec_ctx_t &ctx) const; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp new file mode 100644 index 0000000000..f25cfb7fae --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp @@ -0,0 +1,136 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_LRN_HPP +#define CPU_REF_LRN_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_lrn_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct ref_lrn_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_lrn_fwd_pd_t { + using cpu_lrn_fwd_pd_t::cpu_lrn_fwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_lrn_fwd_t); + + status_t init() { + using namespace format_tag; + + bool ok = true + && is_fwd() + && src_md()->data_type == data_type + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + dat_tag_ = memory_desc_matches_one_of_tag( + *src_md(), nChw16c, nChw8c, nchw, nhwc); + + return status::success; + } + + format_tag_t dat_tag_; + }; + + ref_lrn_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + using namespace format_tag; + switch (pd()->dat_tag_) { + case nChw16c: execute_forward(ctx); break; + case nChw8c: execute_forward(ctx); break; + case nchw: execute_forward(ctx); break; + case nhwc: execute_forward(ctx); break; + default: execute_forward(ctx); + } + return status::success; + } + +private: + template + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_lrn_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_lrn_bwd_pd_t { + using cpu_lrn_bwd_pd_t::cpu_lrn_bwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_lrn_bwd_t); + + status_t init() { + using namespace format_tag; + using namespace alg_kind; + + bool ok = true + && !is_fwd() + && utils::one_of(desc()->alg_kind, lrn_across_channels + /*, lrn_within_channel */) // not supported yet + && utils::everyone_is(data_type, + src_md()->data_type, + diff_src_md()->data_type) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + dat_tag_ = memory_desc_matches_one_of_tag( + *src_md(), nChw16c, nChw8c, nchw, nhwc); + + return status::success; + } + + format_tag_t dat_tag_; + }; + + ref_lrn_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + using namespace format_tag; + switch (pd()->dat_tag_) { + case nChw16c: execute_backward(ctx); break; + case nChw8c: execute_backward(ctx); break; + case nchw: execute_backward(ctx); break; + case nhwc: execute_backward(ctx); break; + default: execute_backward(ctx); + } + return status::success; + } + +private: + template + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp new file mode 100644 index 0000000000..65b934e123 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp @@ -0,0 +1,381 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" + +#include "ref_pooling.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +void ref_pooling_fwd_t::execute_forward( + const exec_ctx_t &ctx) const { + using namespace alg_kind; + using namespace prop_kind; + + auto alg = pd()->desc()->alg_kind; + + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + auto ws = CTX_OUT_MEM(unsigned char *, MKLDNN_ARG_WORKSPACE); + + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + const memory_desc_wrapper ws_d(pd()->workspace_md()); + const data_type_t ws_dt = ws ? ws_d.data_type() : data_type::undef; + + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + const int SD = pd()->KSD(); + const int SH = pd()->KSH(); + const int SW = pd()->KSW(); + const int padF = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + + const bool is_3d = pd()->desc()->src_desc.ndims == 5; + + auto apply_offset = [=](int index, int offset) { + return (index > offset) ? index - offset : 0; + }; + + auto set_ws = [=](int mb, int oc, int od, int oh, int ow, int value) { + if (ws) { + assert(ws_dt == data_type::u8 || ws_dt == data_type::s32); + size_t offset = is_3d + ? ws_d.off(mb, oc, od, oh, ow) : ws_d.off(mb, oc, oh, ow);; + if (ws_dt == data_type::u8) { + assert(0 <= value && value <= 255); + ws[offset] = value; + } else + reinterpret_cast(ws)[offset] = value; + } + }; + + auto ker_max = [=](data_t *d, int mb, int oc, int oh, int ow) { + for (int kh = 0; kh < KH; ++kh) { + for (int kw = 0; kw < KW; ++kw) { + const int ih = oh * SH - padT + kh; + const int iw = ow * SW - padL + kw; + + if (ih < 0 || ih >= IH) continue; + if (iw < 0 || iw >= IW) continue; + + auto s = src[src_d.off(mb, oc, ih, iw)]; + if (s > d[0]) { + d[0] = s; + set_ws(mb, oc, 1, oh, ow, kh*KW + kw); + } + } + } + }; + + auto ker_avg = [=](data_t *d, int mb, int oc, int oh, int ow) { + auto ih_start = apply_offset(oh*SH, padT); + auto iw_start = apply_offset(ow*SW, padL); + auto ih_end = nstl::min(oh*SH - padT + KH, IH); + auto iw_end = nstl::min(ow*SW - padL + KW, IW); + + auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH + : (ih_end - ih_start)*(iw_end - iw_start); + + acc_data_t dst = 0; + for (int ih = ih_start; ih < ih_end; ++ih) { + for (int iw = iw_start; iw < iw_end; ++iw) { + dst += src[src_d.off(mb, oc, ih, iw)]; + } + } + + d[0] = math::out_round((float)dst / num_summands); + }; + + auto ker_max_3d = [=](data_t *d, int mb, int oc, int od, int oh, int ow) { + for (int kd = 0; kd < KD; ++kd) { + for (int kh = 0; kh < KH; ++kh) { + for (int kw = 0; kw < KW; ++kw) { + const int id = od * SD - padF + kd; + const int ih = oh * SH - padT + kh; + const int iw = ow * SW - padL + kw; + + if (id < 0 || id >= ID) continue; + if (ih < 0 || ih >= IH) continue; + if (iw < 0 || iw >= IW) continue; + + auto s = src[src_d.off(mb, oc, id, ih, iw)]; + if (s > d[0]) { + d[0] = s; + set_ws(mb, oc, od, oh, ow, kd * KH * KW + kh*KW + kw); + } + } + } + } + }; + + auto ker_avg_3d = [=](data_t *d, int mb, int oc, int od, int oh, int ow) { + auto id_start = apply_offset(od*SD, padF); + auto ih_start = apply_offset(oh*SH, padT); + auto iw_start = apply_offset(ow*SW, padL); + auto id_end = nstl::min(od*SD - padF + KD, ID); + auto ih_end = nstl::min(oh*SH - padT + KH, IH); + auto iw_end = nstl::min(ow*SW - padL + KW, IW); + + auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH*KD + : (ih_end - ih_start)*(iw_end - iw_start)*(id_end - id_start); + + acc_data_t dst = 0; + for (int id = id_start; id < id_end; ++id) { + for (int ih = ih_start; ih < ih_end; ++ih) { + for (int iw = iw_start; iw < iw_end; ++iw) { + dst += src[src_d.off(mb, oc, id, ih, iw)]; + } + } + } + + d[0] = math::out_round((float)dst / num_summands); + }; + + const int MB = pd()->MB(); + const int OC = pd()->C(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + + if (alg == pooling_max) { + parallel_nd(MB, OC, OD, OH, OW, + [&](int mb, int oc, int od, int oh, int ow) { + data_t *d = is_3d + ? &dst[dst_d.off(mb, oc, od, oh, ow)] + : &dst[dst_d.off(mb, oc, oh, ow)]; + d[0] = nstl::numeric_limits::lowest(); + set_ws(mb, oc, od, oh, ow, 0); + if (is_3d) ker_max_3d(d, mb, oc, od, oh, ow); + else ker_max(d, mb, oc, oh, ow); + }); + } else { + parallel_nd(MB, OC, OD, OH, OW, + [&](int mb, int oc, int od, int oh, int ow) { + data_t *d = is_3d + ? &dst[dst_d.off(mb, oc, od, oh, ow)] + : &dst[dst_d.off(mb, oc, oh, ow)]; + d[0] = 0; + if (is_3d) ker_avg_3d(d, mb, oc, od, oh, ow); + else ker_avg(d, mb, oc, oh, ow); + }); + } +} + +template +void ref_pooling_bwd_t::execute_backward( + const exec_ctx_t &ctx) const { + using namespace alg_kind; + + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto ws = CTX_IN_MEM(const unsigned char *, MKLDNN_ARG_WORKSPACE); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md()); + const memory_desc_wrapper diff_src_d(pd()->diff_src_md()); + const memory_desc_wrapper ws_d(pd()->workspace_md()); + + const int ID = pd()->ID(); + const int IH = pd()->IH(); + const int IW = pd()->IW(); + const int KD = pd()->KD(); + const int KH = pd()->KH(); + const int KW = pd()->KW(); + const int SD = pd()->KSD(); + const int SH = pd()->KSH(); + const int SW = pd()->KSW(); + const int padF = pd()->padFront(); + const int padT = pd()->padT(); + const int padL = pd()->padL(); + + const bool is_3d = pd()->desc()->diff_src_desc.ndims == 5; + + auto alg = pd()->desc()->alg_kind; + + auto apply_offset = [=](int index, int offset) { + return (index > offset) ? index - offset : 0; + }; + + auto ker_zero = [=](int _mb, int _oc) { + for (int ih = 0; ih < IH; ++ih) { + for (int iw = 0; iw < IW; ++iw) { + diff_src[diff_src_d.off(_mb, _oc, ih, iw)] = data_type_t(0); + } + } + }; + + auto ker_max = [=](const data_t *d, int mb, int oc, int oh, int ow) { + const size_t ws_off = ws_d.off(mb, oc, oh, ow); + const int index = ws_d.data_type() == data_type::u8 + ? (int)ws[ws_off] : ((int *)ws)[ws_off]; + const int kw = index % KW; + const int kh = index / KW; + const int ih = oh * SH - padT + kh; + const int iw = ow * SW - padL + kw; + + // If padding area could fit the kernel, + // then input displacement would be out of bounds. + // No need to back propagate there as padding is + // virtual in pooling_max case. + if (ih < 0 || ih >= IH) + return; + if (iw < 0 || iw >= IW) + return; + + diff_src[diff_src_d.off(mb, oc, ih, iw)] += d[0]; + }; + + auto ker_avg = [=](const data_t *d, int mb, int oc, int oh, int ow) { + auto ih_start = apply_offset(oh*SH, padT); + auto iw_start = apply_offset(ow*SW, padL); + auto ih_end = nstl::min(oh*SH - padT + KH, IH); + auto iw_end = nstl::min(ow*SW - padL + KW, IW); + + auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH + : (ih_end - ih_start)*(iw_end - iw_start); + + for (int ih = ih_start; ih < ih_end; ++ih) { + for (int iw = iw_start; iw < iw_end; ++iw) { + diff_src[diff_src_d.off(mb, oc, ih, iw)] += d[0] / num_summands; + } + } + }; + + auto ker_zero_3d = [=](int _mb, int _oc) { + for (int id = 0; id < ID; ++id) { + for (int ih = 0; ih < IH; ++ih) { + for (int iw = 0; iw < IW; ++iw) { + diff_src[diff_src_d.off(_mb, _oc, id, ih, iw)] = + data_type_t(0); + } + } + } + }; + + auto ker_max_3d = [=](const data_t *d, int mb, int oc, int od, int oh, + int ow) { + const size_t ws_off = ws_d.off(mb, oc, od, oh, ow); + const int index = ws_d.data_type() == data_type::u8 + ? (int)ws[ws_off] : ((int *)ws)[ws_off]; + const int kw = index % KW; + const int kh = (index / KW) % KH; + const int kd = (index / KW) / KH; + const int id = od * SD - padF + kd; + const int ih = oh * SH - padT + kh; + const int iw = ow * SW - padL + kw; + + // If padding area could fit the kernel, + // then input displacement would be out of bounds. + // No need to back propagate there as padding is + // virtual in pooling_max case. + if (id < 0 || id >= ID) + return; + if (ih < 0 || ih >= IH) + return; + if (iw < 0 || iw >= IW) + return; + + diff_src[diff_src_d.off(mb, oc, id, ih, iw)] += d[0]; + }; + + auto ker_avg_3d = [=](const data_t *d, int mb, int oc, int od, int oh, + int ow) { + auto id_start = apply_offset(od*SD, padF); + auto ih_start = apply_offset(oh*SH, padT); + auto iw_start = apply_offset(ow*SW, padL); + auto id_end = nstl::min(od*SD - padF + KD, ID); + auto ih_end = nstl::min(oh*SH - padT + KH, IH); + auto iw_end = nstl::min(ow*SW - padL + KW, IW); + + auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH*KD + : (ih_end - ih_start)*(iw_end - iw_start)*(id_end - id_start); + + for (int id = id_start; id < id_end; ++id) + for (int ih = ih_start; ih < ih_end; ++ih) + for (int iw = iw_start; iw < iw_end; ++iw) { + diff_src[diff_src_d.off(mb, oc, id, ih, iw)] += d[0] / num_summands; + } + }; + + const int MB = pd()->MB(); + const int OC = pd()->C(); + const int OD = pd()->OD(); + const int OH = pd()->OH(); + const int OW = pd()->OW(); + + if (pd()->desc()->alg_kind == alg_kind::pooling_max) { + parallel_nd(MB, OC, [&](int mb, int oc) { + if (is_3d) ker_zero_3d(mb, oc); + else ker_zero(mb, oc); + for (int od = 0; od < OD; ++od) { + for (int oh = 0; oh < OH; ++oh) { + for (int ow = 0; ow < OW; ++ow) { + const data_t *d = is_3d + ? &diff_dst[diff_dst_d.off(mb, oc, od, oh, ow)] + : &diff_dst[diff_dst_d.off(mb, oc, oh, ow)]; + if (is_3d) ker_max_3d(d, mb, oc, od, oh, ow); + else ker_max(d, mb, oc, oh, ow); + } + } + } + }); + } else { + parallel_nd(MB, OC, [&](int mb, int oc) { + if (is_3d) ker_zero_3d(mb, oc); + else ker_zero(mb, oc); + for (int od = 0; od < OD; ++od) { + for (int oh = 0; oh < OH; ++oh) { + for (int ow = 0; ow < OW; ++ow) { + const data_t *d = is_3d + ? &diff_dst[diff_dst_d.off(mb, oc, od, oh, ow)] + : &diff_dst[diff_dst_d.off(mb, oc, oh, ow)]; + if (is_3d) ker_avg_3d(d, mb, oc, od, oh, ow); + else ker_avg(d, mb, oc, oh, ow); + } + } + } + }); + } +} + +template struct ref_pooling_fwd_t; +template struct ref_pooling_fwd_t; +template struct ref_pooling_fwd_t; +template struct ref_pooling_fwd_t; + +template struct ref_pooling_bwd_t; +template struct ref_pooling_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp new file mode 100644 index 0000000000..e43ceaa82b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp @@ -0,0 +1,119 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_POOLING_HPP +#define CPU_REF_POOLING_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_pooling_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct ref_pooling_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_fwd_pd_t { + using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_pooling_fwd_t); + + status_t init() { + bool ok = true + && set_default_params() == status::success + && is_fwd() + && utils::everyone_is(data_type, src_md()->data_type, + dst_md()->data_type) + && desc()->accum_data_type == acc_type + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + bool is_training = desc_.prop_kind == prop_kind::forward_training; + if (desc()->alg_kind == alg_kind::pooling_max && is_training) + init_default_ws(); + + return status::success; + } + }; + + ref_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + + typedef typename prec_traits::type data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_forward(ctx); + return status::success; + } + +private: + void execute_forward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct ref_pooling_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_pooling_bwd_pd_t { + using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_pooling_bwd_t); + + status_t init() { + bool ok = true + && set_default_params() == status::success + && !is_fwd() + && utils::everyone_is(data_type, diff_dst_md()->data_type, + diff_src_md()->data_type) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + if (desc()->alg_kind == alg_kind::pooling_max) { + init_default_ws(); + if (!compare_ws(hint_fwd_pd_)) + return status::unimplemented; + } + + return status::success; + } + }; + + ref_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {} + typedef typename prec_traits::type data_t; + typedef typename prec_traits::type acc_data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_backward(ctx); + return status::success; + } + +private: + void execute_backward(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp new file mode 100644 index 0000000000..af27743110 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp @@ -0,0 +1,153 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" + +#include "ref_shuffle.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace format_tag; + +template +template +void ref_shuffle_t::execute_(const exec_ctx_t &ctx) const { + using namespace prop_kind; + using namespace utils; + + const memory_desc_wrapper data_d(pd()->data_md()); + + auto i_arg = pd()->is_fwd() ? MKLDNN_ARG_SRC : MKLDNN_ARG_DIFF_DST; + auto o_arg = pd()->is_fwd() ? MKLDNN_ARG_DST : MKLDNN_ARG_DIFF_SRC; + auto input = CTX_IN_MEM(const data_t *, i_arg); + auto output = CTX_OUT_MEM(data_t *, o_arg); + + const int axis = pd()->axis(); + const int axis_size = pd()->axis_size(); + + const int MB = pd()->MB(); + const int C = pd()->C(); + int H = 1, W = 1, D = 1, HW = 1, SP = 1; + const bool has_spatial = utils::one_of(data_d.ndims(), 3, 4 ,5); + if (has_spatial) + { + D = pd()->D(); + H = pd()->H(); + W = pd()->W(); + HW = H * W; + SP = D * HW; + } + const size_t stride_mb = data_d.blocking_desc().strides[0]; + constexpr int blksize = one_of(tag, nChw16c, nCdhw16c) ? 16 : 8; + + if (axis == 1 && one_of(tag, nChw16c, nChw8c, nCdhw16c, nCdhw16c)) { +#if MKLDNN_THR == MKLDNN_THR_OMP +# pragma omp parallel for collapse(3) schedule(static) + for (int mb = 0; mb < MB; ++mb) + for (int cb = 0; cb < C; cb += blksize) + for (int sp = 0; sp < SP; ++sp) { + const size_t off = mb * stride_mb + sp * blksize; + const size_t output_off = off + cb * SP; + PRAGMA_OMP_SIMD() + for (int cc = 0; cc < nstl::min(blksize, C - cb); ++cc) + { + int input_c = rev_transposed_[cb + cc]; + const size_t input_off = off + input_c / blksize * SP * blksize + + input_c % blksize; + output[output_off + cc] = input[input_off]; + } + } +#else + parallel_nd(MB, utils::div_up(C, blksize), SP, [&](int mb, int c, + int sp) { + const size_t off = mb * stride_mb + sp * blksize; + const int cb = c * blksize; + const size_t output_off = off + cb * SP; + for (int cc = 0; cc < nstl::min(blksize, C - cb); ++cc) + { + int input_c = rev_transposed_[cb + cc]; + const size_t input_off = off + input_c / blksize * SP * blksize + + input_c % blksize; + output[output_off + cc] = input[input_off]; + } + }); +#endif + } else if (axis == 1 && one_of(tag, nhwc, ndhwc)) { + parallel_nd(MB, SP, [&](int mb, int sp) { + const size_t off = mb * stride_mb + sp * C; + PRAGMA_OMP_SIMD() + for (int c = 0; c < C; ++c) + output[off + c] = input[off + rev_transposed_[c]]; + }); + } else if (axis == 1 && one_of(tag, nchw, ncdhw)) { + parallel_nd(MB, C, [&](int mb, int c) { + const size_t output_off = mb * stride_mb + c * SP; + const size_t input_off = mb * stride_mb + rev_transposed_[c] * SP; + PRAGMA_OMP_SIMD() + for (int sp = 0; sp < SP; ++sp) { + output[output_off + sp] = input[input_off + sp]; + } + }); + } else { + auto dims = pd()->desc()->data_desc.dims; + auto ndims = pd()->desc()->data_desc.ndims; + const size_t outer_size = utils::array_product(dims, axis); + const size_t inner_size = utils::array_product(dims + axis + 1, + ndims - axis - 1); + const size_t dim = axis_size * inner_size; + + parallel_nd(outer_size, axis_size, inner_size, [&](size_t ou, int a, + size_t in) + { + const size_t off = ou * dim + in; + auto &o = output[data_d.off_l(off + a * inner_size)]; + o = input[data_d.off_l(off + rev_transposed_[a] * inner_size)]; + }); + } +} + +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<4>::execute_(const exec_ctx_t &ctx) const; + +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; +template void ref_shuffle_t<1>::execute_(const exec_ctx_t &ctx) const; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp new file mode 100644 index 0000000000..5e09a1a69b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp @@ -0,0 +1,111 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_SHUFFLE_HPP +#define CPU_REF_SHUFFLE_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_shuffle_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct ref_shuffle_t : public cpu_primitive_t { + using shuffle_class = ref_shuffle_t; + + struct pd_t: public cpu_shuffle_pd_t { + using cpu_shuffle_pd_t::cpu_shuffle_pd_t; + + DECLARE_COMMON_PD_T("ref:any", shuffle_class); + + status_t init() { + using namespace format_tag; + + bool ok = true + && data_type_size + == types::data_type_size(data_md()->data_type); + if (!ok) return status::unimplemented; + + if (ndims() == 5) { + dat_tag_ = memory_desc_matches_one_of_tag( + *data_md(), nCdhw16c, nCdhw8c, ncdhw, ndhwc); + } else if (ndims() == 4) { + dat_tag_ = memory_desc_matches_one_of_tag( + *data_md(), nChw16c, nChw8c, nchw, nhwc); + } else + dat_tag_ = any; + + return status::success; + } + + format_tag_t dat_tag_; + }; + + ref_shuffle_t(const pd_t *apd): cpu_primitive_t(apd) { + const int axis_size = pd()->axis_size(); + const int group_size = pd()->group_size(); + const int transpose_row = pd()->is_fwd() ? group_size + : axis_size / group_size; + const int transpose_col = pd()->is_fwd() ? axis_size / group_size + : group_size; + rev_transposed_ = (int *)malloc(axis_size * sizeof(int), 64); + parallel_nd(transpose_col, transpose_row, [&](int i, int j) { + rev_transposed_[j * transpose_col + i] = i * transpose_row + j; + }); + } + + ~ref_shuffle_t() { free(rev_transposed_); } + + typedef typename typesize_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + using namespace format_tag; + switch (pd()->dat_tag_) { + case nCdhw16c: execute_(ctx); break; + case nChw16c: execute_(ctx); break; + case nCdhw8c: execute_(ctx); break; + case nChw8c: execute_(ctx); break; + case ncdhw: execute_(ctx); break; + case nchw: execute_(ctx); break; + case ndhwc: execute_(ctx); break; + case nhwc: execute_(ctx); break; + default: execute_(ctx); break; + } + return status::success; + } + +private: + template + void execute_(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + int *rev_transposed_; +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp new file mode 100644 index 0000000000..36d5237f56 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp @@ -0,0 +1,264 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include +#include +#include + +#include "c_types_map.hpp" +#include "mkldnn_thread.hpp" +#include "type_helpers.hpp" + +#include "ref_softmax.hpp" +#include "gemm/os_blas.hpp" + +#ifdef USE_MKL +#include "mkl_vml_functions.h" +#endif + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +void ref_softmax_fwd_t::execute_forward_dense( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + parallel_nd(outer_size_, [&](int ou) { + const data_t *src_data = src + ou * channels_; + data_t *dst_data = dst + ou * channels_; + data_t scalar = 0; + + _max(channels_, src_data, &scalar); + _sub(channels_, scalar, src_data, dst_data); + _exp(channels_, dst_data, dst_data); + _sum(channels_, dst_data, &scalar); + _scal(channels_, data_t(1)/scalar, dst_data); + }); +} + +template +void ref_softmax_fwd_t::execute_forward_generic( + const exec_ctx_t &ctx) const { + auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC); + auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + data_t space_max_val = 0, space_denom_val = 0; + data_t *space_max = &space_max_val, *space_denom = &space_denom_val; + if (inner_size_ > 1) { + using namespace memory_tracking::names; + space_max = scratchpad(ctx).template get(key_softmax_reduction); + space_denom = space_max + inner_size_; + } + + const memory_desc_wrapper data_d(pd()->src_md()); + const size_t dim = channels_ * inner_size_; + + for (int ou = 0; ou < outer_size_; ou++) { + utils::array_set(space_max, -FLT_MAX, inner_size_); + utils::array_set(space_denom, 0, inner_size_); + + for (int c = 0; c < channels_; c++) { + for(int in = 0; in < inner_size_; in++) { + size_t off = data_d.off_l(ou * dim + c * inner_size_ + in); + space_max[in] = nstl::max(space_max[in], src[off]); + } + } + + for (int c = 0; c < channels_; c++) { + for(int in = 0; in < inner_size_; in++) { + size_t off = data_d.off_l(ou * dim + c * inner_size_ + in); + space_denom[in] += dst[off] = exp(src[off] - space_max[in]); + } + } + + for (int c = 0; c < channels_; c++) { + for (int in = 0; in < inner_size_; in++) { + size_t off = data_d.off_l(ou * dim + c * inner_size_ + in); + dst[off] /= space_denom[in]; + } + } + } +} + +template +void ref_softmax_fwd_t::_max(int n, const data_t *x, + data_t *max_data) const { +// Intel(R) C++ Compiler generates the maxps + shuffle pattern +// for the max search which works faster +#if !defined(__INTEL_COMPILER) + // The code below makes a compiler to generate maxps instruction + // rather than maxss, which is generated for the 'else' code path + auto max_wrapper = [](data_t a, data_t b) { return nstl::max(a, b); }; + auto min_wrapper = [](int a, int b) { return nstl::min(a, b); }; + + constexpr int unroll_factor = 32; + data_t max_values[unroll_factor]; + + if (n < unroll_factor) { + data_t max_val = x[0]; + for (int i = 1; i < n; i++) { + max_val = max_wrapper(max_val, x[i]); + } + max_data[0] = max_val; + return; + } + for (int i = 0; i < unroll_factor; i++) { + max_values[i] = x[i]; + } + for (int i = unroll_factor; i < n; i += unroll_factor) { + int offset = min_wrapper(i, n - unroll_factor); + for (int j = 0; j < unroll_factor; j++) { + max_values[j] = max_wrapper(max_values[j], x[offset + j]); + } + } + data_t max_val = max_values[0]; + for (int i = 1; i < unroll_factor; i++) { + max_val = max_wrapper(max_val, max_values[i]); + } + max_data[0] = max_val; +#else + max_data[0] = x[0]; + for (int c = 1; c < n; ++c) + max_data[0] = nstl::max(max_data[0], x[c]); +#endif +} + +template +void ref_softmax_fwd_t::_sub(int n, data_t alpha, const data_t *x, + data_t *y) const { + constexpr int unroll_factor = 32; + int tail = n % unroll_factor; + for (int i = 0; i < n - tail; i += unroll_factor) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < unroll_factor; j++) { + y[i + j] = x[i + j] - alpha; + } + } + PRAGMA_OMP_SIMD() + for (int i = n - tail; i < n; i++) { + y[i] = x[i] - alpha; + } +} + +template +void ref_softmax_fwd_t::_exp(int n, const data_t *a, + data_t *r) const { +#ifdef USE_MKL + if (data_type == data_type::f32) { + vsExp(n, a, r); + return; + } +#endif + parallel_nd(n, [&](int c) { r[c] = expf(a[c]); }); +} + +template +void ref_softmax_fwd_t::_sum(int n, const data_t *x, + data_t *sum_data) const { +#ifdef USE_CBLAS + // Here we are summing x's eg. e^z , which are positives + // so we can use BLAS ASUM + if (data_type == data_type::f32) { + sum_data[0] = cblas_sasum(n, x, 1); + return; + } +#endif + data_t tsum = static_cast(0); + PRAGMA_OMP_SIMD(reduction(+ : tsum)) + for (int c = 0; c < n; ++c) + tsum += x[c]; + sum_data[0] = tsum; +} + +template +void ref_softmax_fwd_t::_scal(int n, data_t alpha, data_t *x) const { +#ifdef USE_CBLAS + if (data_type == data_type::f32) { + cblas_sscal(n, alpha, x, 1); + return; + } +#endif + parallel_nd(n, [&](int c) { x[c] *= alpha; }); +} + +template struct ref_softmax_fwd_t; + + +// NC/NCHW softmax for along final axe (1 for NC, 3 for NCHW) +template +void ref_softmax_bwd_t::execute_backward_dense( + const exec_ctx_t &ctx) const { + auto dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DST); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + parallel_nd(outer_size_, [&](int ou) { + data_t sbr = 0; + size_t off = channels_*ou; + for (int c = 0; c < channels_; c++) { + size_t loff = off + c; + data_t ldata = dst[loff]; + sbr += diff_dst[loff]*ldata; + diff_src[loff] = ldata; + } + + for(int c=0; c < channels_ ; ++c) { + size_t loff = off + c; + diff_src[loff] *= (diff_dst[loff] - sbr); + } + }); +} + +template +void ref_softmax_bwd_t::execute_backward_generic( + const exec_ctx_t &ctx) const { + auto dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DST); + auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST); + auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC); + + const memory_desc_wrapper diff_d(pd()->diff_src_md()); + const memory_desc_wrapper data_d(pd()->dst_md()); + + const size_t dim = channels_ * inner_size_; + + parallel_nd(outer_size_, [&](int ou) { + for (int in = 0; in < inner_size_; in++) { + data_t sbr = 0; + for (int c = 0; c < channels_; c++) { + size_t off_diff = diff_d.off_l(ou * dim + c * inner_size_ + in); + size_t off_data = diff_d.off_l(ou * dim + c * inner_size_ + in); + sbr += diff_dst[off_diff] * dst[off_data]; + } + + for(int c=0; c < channels_ ; ++c) { + size_t off_diff = diff_d.off_l(ou * dim + c * inner_size_ + in); + size_t off_data = data_d.off_l(ou * dim + c * inner_size_ + in); + diff_src[off_diff] = dst[off_data] * (diff_dst[off_diff] - sbr); + } + } + }); +} + +template struct ref_softmax_bwd_t; + +} +} +} + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp new file mode 100644 index 0000000000..5cb74d8007 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp @@ -0,0 +1,186 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_SOFTMAX_HPP +#define CPU_REF_SOFTMAX_HPP + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "cpu_softmax_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct ref_softmax_fwd_t: public cpu_primitive_t { + struct pd_t: public cpu_softmax_fwd_pd_t { + using cpu_softmax_fwd_pd_t::cpu_softmax_fwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_softmax_fwd_t); + + status_t init() { + bool ok = true + && is_fwd() + && src_md()->data_type == data_type + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + init_scratchpad(); + + return status::success; + } + + private: + void init_scratchpad() { + const int inner_size = utils::array_product( + desc()->data_desc.dims + desc()->softmax_axis + 1, + desc()->data_desc.ndims - desc()->softmax_axis - 1); + + if (inner_size > 1) { + auto scratchpad = scratchpad_registry().registrar(); + scratchpad.book(memory_tracking::names::key_softmax_reduction, + sizeof(data_t) * 2 * inner_size); + } + } + }; + + ref_softmax_fwd_t(const pd_t *apd): cpu_primitive_t(apd) + { + auto ndims = pd()->desc()->data_desc.ndims; + auto dims = pd()->desc()->data_desc.dims; + auto axis = pd()->desc()->softmax_axis; + + outer_size_ = utils::array_product(dims, axis); + channels_ = dims[axis]; + inner_size_ = utils::array_product(dims + axis + 1, ndims - axis - 1); + + const memory_desc_wrapper data_d(pd()->src_md()); + + bool no_axis_blocking = true; + for (int iblk = 0; iblk < data_d.blocking_desc().inner_nblks; ++iblk) + if (data_d.blocking_desc().inner_idxs[iblk] == axis) + no_axis_blocking = false; + + use_dense_ = inner_size_ == 1 && data_d.is_dense() + && no_axis_blocking + && data_d.blocking_desc().strides[axis] == 1; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + if (use_dense_) + execute_forward_dense(ctx); + else + execute_forward_generic(ctx); + return status::success; + } + +private: + void execute_forward_dense(const exec_ctx_t &ctx) const; + void execute_forward_generic(const exec_ctx_t &ctx) const; + + void _max(int n, const data_t *x, data_t *max_data) const; + void _sub(int n, data_t alpha, const data_t *x, data_t *y) const; + void _exp(int n, const data_t *a, data_t *r) const; + void _sum(int n, const data_t *x, data_t *sum_data) const; + void _scal(int n, data_t alpha, data_t *x) const; + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + bool use_dense_; + int outer_size_, channels_, inner_size_; +}; + +template +struct ref_softmax_bwd_t: public cpu_primitive_t { + struct pd_t: public cpu_softmax_bwd_pd_t { + using cpu_softmax_bwd_pd_t::cpu_softmax_bwd_pd_t; + + DECLARE_COMMON_PD_T("ref:any", ref_softmax_bwd_t); + + status_t init() { + bool ok = true + && !is_fwd() + && utils::everyone_is(data_type, + dst_md()->data_type, + diff_src_md()->data_type) + && attr()->has_default_values(); + if (!ok) return status::unimplemented; + + return status::success; + } + }; + + ref_softmax_bwd_t(const pd_t *apd): cpu_primitive_t(apd) { + auto dims = pd()->desc()->diff_desc.dims; + auto axis = pd()->desc()->softmax_axis; + auto ndims = pd()->desc()->diff_desc.ndims; + + outer_size_ = utils::array_product(dims, axis); + channels_ = dims[axis]; + inner_size_ = utils::array_product(dims + axis + 1, ndims - axis - 1); + + const memory_desc_wrapper data_d(pd()->dst_md()); + const memory_desc_wrapper diff_d(pd()->diff_dst_md()); + + bool no_axis_blocking = true; + for (int iblk = 0; iblk < diff_d.blocking_desc().inner_nblks; ++iblk) + if (diff_d.blocking_desc().inner_idxs[iblk] == axis) + no_axis_blocking = false; + + use_dense_ = true + && inner_size_ == 1 + && diff_d == data_d + && diff_d.is_dense() + && no_axis_blocking + && diff_d.blocking_desc().strides[axis] == 1; + } + + typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + if (use_dense_) + execute_backward_dense(ctx); + else + execute_backward_generic(ctx); + return status::success; + } + +private: + void execute_backward_dense(const exec_ctx_t &ctx) const; + void execute_backward_generic(const exec_ctx_t &ctx) const; + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + bool use_dense_; + int outer_size_, channels_, inner_size_; +}; + + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp new file mode 100644 index 0000000000..3b2a75d99b --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp @@ -0,0 +1,101 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef REF_SUM_HPP +#define REF_SUM_HPP + +#include "reorder_pd.hpp" + +#include "cpu_sum_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct ref_sum_t: public cpu_primitive_t { + struct pd_t: public cpu_sum_pd_t { + using cpu_sum_pd_t::cpu_sum_pd_t; + + pd_t(const pd_t &rhs): cpu_sum_pd_t(rhs) { + for (size_t i = 0; i < rhs.reorder_pds_.size(); ++i) + reorder_pds_.push_back( + (const reorder_pd_t *)rhs.reorder_pds_[i]->clone()); + } + + ~pd_t() { for (auto &rpd: reorder_pds_) delete rpd; } + + DECLARE_SUM_PD_T("ref:any", ref_sum_t); + + status_t init() { + bool ok = cpu_sum_pd_t::init() == status::success; + if (!ok) return status::unimplemented; + + for (int i = 0; i < n_; ++i) { + auto r_impls = engine_->get_reorder_implementation_list(); + for (auto r = r_impls; *r; ++r) { + primitive_attr_t attr; + attr.output_scales_.set(scales_[i]); + if (i != 0) attr.post_ops_.append_sum(1.0); + + reorder_pd_t *r_pd; + if ((*r)(&r_pd, engine_, &attr, engine_, src_md(i), + engine_, dst_md()) == status::success) { + r_pd->init_info(); + reorder_pds_.push_back(r_pd); + break; + } + } + } + + ok = reorder_pds_.size() == (size_t)n_; + return ok ? status::success : status::unimplemented; + } + + nstl::vector reorder_pds_; + }; + + ref_sum_t(const pd_t *apd): cpu_primitive_t(apd) { + const int n = pd()->n_inputs(); + reorders_.resize(n); + for (int i = 0; i < n; ++i) + pd()->reorder_pds_[i]->create_primitive(&reorders_[i]); + } + + ~ref_sum_t() { for (auto &r: reorders_) delete r; } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + const auto n = pd()->n_inputs(); + for (int i = 0; i < n; ++i) { + exec_args_t r_args; + r_args[MKLDNN_ARG_SRC] = ctx.args().at(MKLDNN_ARG_MULTIPLE_SRC + i); + r_args[MKLDNN_ARG_DST] = ctx.args().at(MKLDNN_ARG_DST); + exec_ctx_t r_ctx(ctx.stream(), std::move(r_args)); + reorders_[i]->execute(r_ctx); + } + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + nstl::vector reorders_; +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp new file mode 100644 index 0000000000..537084db91 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp @@ -0,0 +1,90 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* + * Common for RNN and LSTM cell execution + */ +#include "ref_rnn.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { +using namespace rnn_utils; + +template +rnn_cell_execution_sig( + (_ref_rnn_common_t::cell_execution)) { + if (!rnn.merge_gemm_layer) { + (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb, + rnn.slc, 1.0, w_layer_[0], rnn.weights_layer_ld, + states_t_lm1_, rnn.states_ws_ld, 0.0, ws_gates_, + rnn.gates_ws_ld); + } + (this->*gemm_iter_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb, rnn.sic, + 1.0, w_iter_[0], rnn.weights_iter_ld, states_tm1_l_, + rnn.states_ws_ld, 1.0, ws_gates_, rnn.gates_ws_ld); + + if (rnn_postgemm_ != nullptr) + rnn_postgemm_->execute(rnn, ws_gates_, states_t_l_, c_states_t_l_, + states_tm1_l_, c_states_tm1_l_, diff_states_t_l_, + diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_, + ws_cell_); + else + (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_, + states_tm1_l_, c_states_tm1_l_, diff_states_t_l_, + diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_, + ws_cell_); +} +template rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution); +template rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution); + +template <> +rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution) { + ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_); + (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_, + states_tm1_l_, c_states_tm1_l_, diff_states_t_l_, + diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_, + ws_cell_); + + /// bwd by data on the cell + (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb, rnn.n_gates * rnn.dic, + 1.0, w_iter_[0], rnn.weights_iter_ld, ws_gates_, rnn.gates_ws_ld, + 0.0, diff_states_t_l_, rnn.states_ws_ld); + + if (!rnn.merge_gemm_layer) { + (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb, + rnn.n_gates * rnn.dic, 1.0, w_layer_[0], + rnn.weights_layer_ld, ws_gates_, rnn.gates_ws_ld, 0.0, + &diff_states_t_l(rnn.n_states, 0, 0), rnn.states_ws_ld); + + /// bwd by weights on the cell + gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc, rnn.mb, 1.0, ws_gates_, + rnn.gates_ws_ld, states_t_lm1_, rnn.states_ws_ld, 1.0, + diff_w_layer_, rnn.diff_weights_layer_ld); + } + + if (!rnn.merge_gemm_iter) + gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.sic, rnn.mb, 1.0, ws_gates_, + rnn.gates_ws_ld, states_tm1_l_, rnn.states_ws_ld, 1.0, + diff_w_iter_, rnn.diff_weights_iter_ld); + + /// bwd by bias we just accumulate diffs from the gates + gates_reduction(rnn, ws_gates_, diff_bias_); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp new file mode 100644 index 0000000000..e1a61d4c62 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp @@ -0,0 +1,180 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* + * Cell execution GRU + */ + +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" + +#include "ref_rnn.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::math; +using namespace rnn_utils; + +#define AOC array_offset_calculator +template <> +rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + bias_aoc_t bias(rnn, bias_[0]); + ws_states_aoc_t states_t_l(rnn, states_t_l_); + ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_); + + // 1. gemm Wx[0-2],x + if (!rnn.merge_gemm_layer) { + (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb, + rnn.slc, 1.0, w_layer_[0], rnn.weights_layer_ld, + states_t_lm1_, rnn.states_ws_ld, 0.0, ws_gates_, + rnn.gates_ws_ld); + } + + // 2. gemm Wh[0-1],h + (this->*gemm_iter_func)('N', 'N', (rnn.n_gates - 1) * rnn.dic, rnn.mb, + rnn.sic, 1.0, w_iter_[0], rnn.weights_iter_ld, states_tm1_l_, + rnn.states_ws_ld, 1.0, ws_gates_, rnn.gates_ws_ld); + + // 3. activation zt and rt + elemwise multiplication rt,ht-1 + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + ws_gates(i, 0, j) = logistic_fwd(ws_gates(i, 0, j) + bias(0, j)); + ws_gates(i, 1, j) = logistic_fwd(ws_gates(i, 1, j) + bias(1, j)); + states_t_l(i, j) = states_tm1_l(i, j) * ws_gates(i, 1, j); + } + }); + + // 4. gemm Wh[2],h~t + (this->*gemm_iter_func)('N', 'N', rnn.dic, rnn.mb, rnn.sic, 1.0, w_iter_[1], + rnn.weights_iter_ld, states_t_l_, rnn.states_ws_ld, 1.0, + &(ws_gates(0, 2, 0)), rnn.gates_ws_ld); + + // 5. activation h~t + calculate ht + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + ws_gates(i, 2, j) = tanh_fwd(ws_gates(i, 2, j) + bias(2, j)); + states_t_l(i, j) = states_tm1_l(i, j) * ws_gates(i, 0, j) + + (1.0f - ws_gates(i, 0, j)) * ws_gates(i, 2, j); + } + }); +} + +template <> +rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru) { + assert(!"GRU int8 is not supported"); +} + +template <> +rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + ws_states_aoc_t states_t_l(rnn, states_t_l_); + ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_); + ws_diff_w_iter_aoc_t diff_w_iter(rnn, diff_w_iter_); + ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_); + ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_); + ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_); + + // use state memory for intermediate computations + // TODO: use cell ws for that + float *dhG1_ = &(diff_states_t_l(rnn.n_states, 0, 0)); + float *hG1_ = dhG1_; + AOC dhG1(dhG1_, rnn.states_nld, rnn.states_ws_ld); + AOC hG1(hG1_, rnn.states_nld, rnn.states_ws_ld); + + // 1. calculate dG2, dG1, and part of dht-1 + // dG2^ = dh * (1 - G0) * (1 - G2^2) + // dG0^ = dh * (ht-1 - G2) * u * (1 - G0) + // dht-1 (part) = dh * G0 + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + float h = states_tm1_l(i, j); + float dHt = diff_states_tp1_l(0, i, j) + + diff_states_t_lp1(rnn.n_states, i, j); + float dG2 = (1.0f - ws_gates(i, 0, j)) * dHt + * one_m_square(ws_gates(i, 2, j)); + float dG0 = (h - ws_gates(i, 2, j)) * dHt + * x_m_square(ws_gates(i, 0, j)); + + diff_states_t_l(0, i, j) = dHt * ws_gates(i, 0, j); + ws_gates(i, 0, j) = dG0; + ws_gates(i, 2, j) = dG2; + } + }); + + // 2. calculate intermediate d(hG1) + // d(hG1) = dG2 * W2h^t + (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb, rnn.dic, 1.0, w_iter_[1], + rnn.weights_iter_ld, &(ws_gates(0, 2, 0)), rnn.gates_ws_ld, 0.0, + dhG1_, rnn.states_ws_ld); + + // 3. calculate dG1^ and part of dht-1 + // dG1^ = d(hG1) * h * G1 * (1 - G1) + // dht-1 (part) += d(hG1) * G1 + // h * G1 (required for dWh) + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + float h = states_tm1_l(i, j); + float G1 = ws_gates(i, 1, j); + diff_states_t_l(0, i, j) += dhG1(i, j) * G1; + ws_gates(i, 1, j) = dhG1(i, j) * h * x_m_square(G1); + hG1(i, j) = G1 * h; + } + }); + + // 4. calculate diff weights + // dWh1 += dG1 * h, dWh2 += dG2 * h, dWh3 += dG3 * (G1(*)h) + gemm('N', 'T', (rnn.n_gates - 1) * rnn.dic, rnn.sic, rnn.mb, 1.0, ws_gates_, + rnn.gates_ws_ld, states_tm1_l_, rnn.states_ws_ld, 1.0, diff_w_iter_, + rnn.diff_weights_iter_ld); + gemm('N', 'T', rnn.dic, rnn.sic, rnn.mb, 1.0, &(ws_gates(0, 2, 0)), + rnn.gates_ws_ld, hG1_, rnn.states_ws_ld, 1.0, + &(diff_w_iter(0, 2, 0)), rnn.diff_weights_iter_ld); + + // 5. calculate diff states + // dht-1 += dG1 * W1h + dG0 * W0h + (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb, + (rnn.n_gates - 1) * rnn.dic, 1.0, w_iter_[0], + rnn.weights_iter_ld, ws_gates_, rnn.gates_ws_ld, 1.0, + diff_states_t_l_, rnn.states_ws_ld); + + if (!rnn.merge_gemm_layer) { + // dWx += [dG0 dG1 dG2] * [x] + gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc, rnn.mb, 1.0, ws_gates_, + rnn.gates_ws_ld, states_t_lm1_, rnn.states_ws_ld, 1.0, + diff_w_layer_, rnn.diff_weights_layer_ld); + // dx = dG2 * W2x + dG1 * W1x + dG0 * W0x + (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb, + rnn.n_gates * rnn.dic, 1.0, w_layer_[0], + rnn.weights_layer_ld, ws_gates_, rnn.gates_ws_ld, 0.0, + &(diff_states_t_l(rnn.n_states, 0, 0)), rnn.states_ws_ld); + } + + // 6. calculate diff bias + gates_reduction(rnn, ws_gates_, diff_bias_); +} +#undef AOC + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp new file mode 100644 index 0000000000..8dea8c90a4 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp @@ -0,0 +1,170 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* + * Cell execution GRU with linear before reset + */ + +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" + +#include "ref_rnn.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::math; +using namespace rnn_utils; +#define AOC array_offset_calculator + +template <> +rnn_elemwise_sig(ref_rnn_fwd_f32_t::gru_lbr_elemwise) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + bias_aoc_t bias(rnn, bias_); + ws_states_aoc_t states_t_l(rnn, states_t_l_); + ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_); + ws_gates_aoc_t ws_gemm_state(rnn, ws_cell_); + AOC ws_Wh_b(ws_grid_, rnn.mb, rnn.dic); + + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + float Wh_b = ws_gemm_state(i, 2, j) + bias(3, j); + ws_gates(i, 0, j) = logistic_fwd( + ws_gates(i, 0, j) + ws_gemm_state(i, 0, j) + bias(0, j)); + ws_gates(i, 1, j) = logistic_fwd( + ws_gates(i, 1, j) + ws_gemm_state(i, 1, j) + bias(1, j)); + ws_gates(i, 2, j) = tanh_fwd( + ws_gates(i, 2, j) + ws_gates(i, 1, j) * Wh_b + bias(2, j)); + states_t_l(i, j) = states_tm1_l(i, j) * ws_gates(i, 0, j) + + (1.0f - ws_gates(i, 0, j)) * ws_gates(i, 2, j); + if (rnn.is_training) + ws_Wh_b(i, j) = Wh_b; + } + }); +} + +template <> +rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::gru_lbr_elemwise) { + assert(!"GRU LBR int8 is not supported"); +} + +template <> +rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru_lbr) { + if (!rnn.merge_gemm_layer) { + (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb, + rnn.slc, 1.0, w_layer_[0], rnn.weights_layer_ld, + states_t_lm1_, rnn.states_ws_ld, 0.0, ws_gates_, + rnn.gates_ws_ld); + } + (this->*gemm_iter_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb, rnn.sic, + 1.0, w_iter_[0], rnn.weights_iter_ld, states_tm1_l_, + rnn.states_ws_ld, 0.0, ws_cell_, rnn.gates_ws_ld); + (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_, + states_tm1_l_, c_states_tm1_l_, diff_states_t_l_, + diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_, + ws_cell_); +} + +template <> +rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru_lbr) { + assert(!"GRU LBR int8 is not supported"); +} + +template <> +rnn_elemwise_sig(ref_rnn_bwd_f32_t::gru_lbr_elemwise) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_); + ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_); + ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_); + ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_); + ws_gates_aoc_t ws_gates_r(rnn, ws_cell_); + AOC ws_Wh_b(ws_grid_, rnn.mb, rnn.dic); + + // 1. calculate dG1 dG2 dG3 + // dG0 = (dht - G2) * dht * (1 - G0) * G0 + // dG1 = (W*h + b) * dG2 * (1 - G1) * G1 + // dG2 = (1 - G0) * dht * (1 - G2*G2) + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + float h = states_tm1_l(i, j); + float dHt = diff_states_tp1_l(0, i, j) + + diff_states_t_lp1(rnn.n_states, i, j); + float dG0 = (h - ws_gates(i, 2, j)) * dHt + * x_m_square(ws_gates(i, 0, j)); + float dG2 = (1.0f - ws_gates(i, 0, j)) + * one_m_square(ws_gates(i, 2, j)) * dHt; + float dG1 = ws_Wh_b(i, j) * dG2 * x_m_square(ws_gates(i, 1, j)); + + diff_states_t_l(0, i, j) = dHt * ws_gates(i, 0, j); + ws_gates(i, 2, j) = dG2; + ws_gates_r(i, 2, j) = dG2 * ws_gates(i, 1, j); + ws_gates(i, 0, j) = ws_gates_r(i, 0, j) = dG0; + ws_gates(i, 1, j) = ws_gates_r(i, 1, j) = dG1; + } + }); +} + +template <> +rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru_lbr) { + ws_gates_aoc_t ws_gates_r(rnn, ws_cell_); + ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_); + + (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_, + states_tm1_l_, c_states_tm1_l_, diff_states_t_l_, + diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_, + ws_cell_); + + if (!rnn.merge_gemm_layer) { + // dx = dG * Wx^t + (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb, + rnn.n_gates * rnn.dic, 1.0, w_layer_[0], + rnn.weights_layer_ld, ws_gates_, rnn.gates_ws_ld, 0.0, + &diff_states_t_l(rnn.n_states, 0, 0), rnn.states_ws_ld); + // dWx += dG^t * x + gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc, rnn.mb, 1.0, ws_gates_, + rnn.gates_ws_ld, states_t_lm1_, rnn.states_ws_ld, 1.0, + diff_w_layer_, rnn.diff_weights_layer_ld); + } + // dh += dGr * Wh^t + (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb, rnn.n_gates * rnn.dic, + 1.0, w_iter_[0], rnn.weights_iter_ld, ws_cell_, rnn.gates_ws_ld, + 1.0, diff_states_t_l_, rnn.states_ws_ld); + + // dWh += dGr^t * h + gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.sic, rnn.mb, 1.0, ws_cell_, + rnn.gates_ws_ld, states_tm1_l_, rnn.states_ws_ld, 1.0, diff_w_iter_, + rnn.diff_weights_layer_ld); + + // db1-3 += e * dG + // db4 += e * (r * dG2) + gates_reduction(rnn, ws_gates_, diff_bias_); + + parallel_nd(rnn.dic, [&](int j) { + for (int i = 0; i < rnn.mb; i++) { + diff_bias_[3 * rnn.dic + j] += ws_gates_r(i, 2, j); + } + }); +} + +#undef AOC + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp new file mode 100644 index 0000000000..a15ba00d4c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp @@ -0,0 +1,143 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* + * Cell execution LSTM + */ + +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" + +#include "../simple_q10n.hpp" +#include "ref_rnn.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::math; +using namespace rnn_utils; + +template <> +rnn_elemwise_sig(ref_rnn_fwd_f32_t::lstm_elemwise) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + bias_aoc_t bias(rnn, bias_); + ws_states_aoc_t states_t_l(rnn, states_t_l_); + ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_); + ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_); + + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + ws_gates(i, 0, j) = logistic_fwd(ws_gates(i, 0, j) + bias(0, j)); + ws_gates(i, 1, j) = logistic_fwd(ws_gates(i, 1, j) + bias(1, j)); + ws_gates(i, 2, j) = tanh_fwd(ws_gates(i, 2, j) + bias(2, j)); + ws_gates(i, 3, j) = logistic_fwd(ws_gates(i, 3, j) + bias(3, j)); + + float tmp = ws_gates(i, 1, j) * c_states_tm1_l(i, j) + + ws_gates(i, 0, j) * ws_gates(i, 2, j); + states_t_l(i, j) = ws_gates(i, 3, j) * tanh_fwd(tmp); + c_states_t_l(i, j) = tmp; + } + }); +} + +template <> +rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::lstm_elemwise) { + ws_gates_aoc_s32_t ws_gates_s32(rnn, ws_gates_); + bias_aoc_t bias(rnn, bias_); + ws_states_aoc_u8_t states_t_l(rnn, states_t_l_); + ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_); + ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_); + + float *weights_scales = pd()->attr()->rnn_weights_qparams_.scales_; + float data_shift = pd()->attr()->rnn_data_qparams_.shift_; + float data_scale = pd()->attr()->rnn_data_qparams_.scale_; + + auto q_d = [&](float f) { + float qf = f * data_scale + data_shift; + return qz_a1b0()(qf); + }; + + auto deq_w = [&](acc_data_t s, int gate, int j) { + return pd()->attr()->rnn_weights_qparams_.mask_ == 0 ? + saturate(s) * (1.f / (weights_scales[0] * data_scale)) : + saturate(s) * (1.f / (weights_scales[gate * rnn.dic + j] + * data_scale)); + }; + + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + float G0 = logistic_fwd( + deq_w(ws_gates_s32(i, 0, j), 0, j) + bias(0, j)); + float G1 = logistic_fwd( + deq_w(ws_gates_s32(i, 1, j), 1, j) + bias(1, j)); + float G2 = tanh_fwd( + deq_w(ws_gates_s32(i, 2, j), 2, j) + bias(2, j)); + float G3 = logistic_fwd( + deq_w(ws_gates_s32(i, 3, j), 3, j) + bias(3, j)); + float tmp = G1 * c_states_tm1_l(i, j) + G0 * G2; + states_t_l(i, j) = q_d(G3 * tanh_fwd(tmp)); + c_states_t_l(i, j) = tmp; + } + }); +} + +template <> +rnn_elemwise_sig(ref_rnn_bwd_f32_t::lstm_elemwise) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + bias_aoc_t bias(rnn, bias_); + ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_); + ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_); + ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_); + ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_); + ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_); + + parallel_nd(rnn.mb, [&](int i) { + PRAGMA_OMP_SIMD() + for (int j = 0; j < rnn.dic; j++) { + float Ct = c_states_t_l(i, j); + /// @todo save it in the workspace in fwd pass or recompute it to + /// save bw + float tanhCt = tanh_fwd(Ct); + // we have 2 incoming diffs on Ht + float dHt = diff_states_tp1_l(0, i, j) + + diff_states_t_lp1(rnn.n_states, i, j); + float dCt = diff_states_tp1_l(1, i, j) + + one_m_square(tanhCt) * ws_gates(i, 3, j) * dHt; + + float dG1 = c_states_tm1_l(i, j) * dCt + * x_m_square(ws_gates(i, 1, j)); + float dG0 = ws_gates(i, 2, j) * dCt * x_m_square(ws_gates(i, 0, j)); + float dG3 = tanhCt * dHt * x_m_square(ws_gates(i, 3, j)); + float dG2 + = ws_gates(i, 0, j) * dCt * one_m_square(ws_gates(i, 2, j)); + + diff_states_t_l(1, i, j) = dCt * ws_gates(i, 1, j); + + ws_gates(i, 0, j) = dG0; + ws_gates(i, 1, j) = dG1; + ws_gates(i, 2, j) = dG2; + ws_gates(i, 3, j) = dG3; + } + }); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp new file mode 100644 index 0000000000..4536e8dfad --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp @@ -0,0 +1,113 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* + * Cell execution of Vanilla RNN + */ + +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" + +#include "ref_rnn.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::math; +using namespace rnn_utils; + +template <> +float activation( + float dd, float s, float alpha, float cliping) { + return relu_fwd(s, alpha); +} + +template <> +float activation( + float dd, float s, float alpha, float cliping) { + return relu_bwd(dd, s, alpha); +} + +template <> +float activation( + float dd, float s, float alpha, float cliping) { + return tanh_fwd(s); +} + +template <> +float activation( + float dd, float s, float alpha, float cliping) { + return dd * one_m_square(s); +} + +template <> +float activation( + float dd, float s, float alpha, float cliping) { + return logistic_fwd(s); +} + +template <> +float activation( + float dd, float s, float alpha, float cliping) { + return dd * x_m_square(s); +} + +template <> +rnn_elemwise_sig(ref_rnn_fwd_f32_t::rnn_elemwise) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + bias_aoc_t bias(rnn, bias_); + ws_states_aoc_t states_t_l(rnn, states_t_l_); + ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_); + + parallel_nd(rnn.mb, [&](int i) { + for (int j = 0; j < rnn.dic; j++) { + const float h + = activation_func(0, ws_gates(i, 0, j) + bias(0, j), 0, 0); + ws_gates(i, 0, j) = states_t_l(i, j) = h; + } + }); +} + +template <> +rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::rnn_elemwise) { + assert(!"VANILLA RNN int8 is not supported"); +} + +template <> +rnn_elemwise_sig(ref_rnn_bwd_f32_t::rnn_elemwise) { + ws_gates_aoc_t ws_gates(rnn, ws_gates_); + bias_aoc_t bias(rnn, bias_); + ws_states_aoc_t states_t_l(rnn, states_t_l_); + ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_); + ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_); + ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_); + ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_); + + parallel_nd(rnn.mb, [&](int i) { + for (int j = 0; j < rnn.dic; ++j) { + const float dH = diff_states_t_lp1(rnn.n_states, i, j) + + diff_states_tp1_l(0, i, j); + auto g = ws_gates(i, 0, j); + ws_gates(i, 0, j) = activation_func(dH, g, 0, 0); + } + }); +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp new file mode 100644 index 0000000000..b39427caf9 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp @@ -0,0 +1,191 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_RNN_PD_HPP +#define CPU_RNN_PD_HPP + +#include "c_types_map.hpp" +#include "nstl.hpp" +#include "rnn_pd.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" +#include "rnn_utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct cpu_rnn_fwd_pd_t : public rnn_fwd_pd_t { + using rnn_fwd_pd_t::rnn_fwd_pd_t; + +protected: + status_t set_default_params() { + using namespace format_tag; + if (src_layer_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(src_layer_md_, tnc)); + if (dst_layer_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(dst_layer_md_, tnc)); + + // Optional parameters + if (with_src_iter() && src_iter_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(src_iter_md_, ldsnc)); + if (with_bias() && bias_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(bias_md_, ldgo)); + if (with_dst_iter() && dst_iter_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(dst_iter_md_, ldsnc)); + + return status::success; + } + + status_t check_layout_consistency() { + using namespace format_tag; + using namespace data_type; + using namespace types; + + auto is_blocked = [&](memory_desc_t md, int ndims) { + return md.format_kind == format_kind::blocked && md.ndims == ndims; + }; + + bool ok = true; + ok = ok && is_blocked(src_layer_md_, 3) + && is_blocked(dst_layer_md_, 3); + ok = ok && IMPLICATION(!is_zero_md(&src_iter_md_), + is_blocked(src_iter_md_, 5)) + && IMPLICATION(!is_zero_md(&dst_iter_md_), + is_blocked(dst_iter_md_, 5)); + + if (weights_layer_md_.format_kind == format_kind::rnn_packed) + ok = ok && (weights_layer_md_.format_desc.rnn_packed_desc.format + == mkldnn_ldigo_p); + else + ok = ok && rnn_utils::is_ldigo(&weights_layer_md_); + + if (weights_iter_md_.format_kind == format_kind::rnn_packed) + ok = ok && (weights_iter_md_.format_desc.rnn_packed_desc.format + == mkldnn_ldigo_p); + else + ok = ok && rnn_utils::is_ldigo(&weights_iter_md_); + + ok = ok && IMPLICATION(!is_zero_md(&bias_md_), + memory_desc_matches_tag(bias_md_, ldgo)); + + /* Int8 is supported only for packed weights */ + data_type_t weights_iter_dt = weights_iter_md_.data_type; + data_type_t weights_layer_dt = weights_layer_md_.data_type; + ok = ok && IMPLICATION( + weights_iter_dt == s8, weights_iter_md_.format_kind + == format_kind::rnn_packed); + ok = ok && IMPLICATION( + weights_layer_dt == s8, weights_layer_md_.format_kind + == format_kind::rnn_packed); + + return ok ? status::success : status::unimplemented; + } +}; + +struct cpu_rnn_bwd_pd_t : public rnn_bwd_pd_t { + using rnn_bwd_pd_t::rnn_bwd_pd_t; + +protected: + status_t set_default_params() { + using namespace format_tag; + if (src_layer_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(src_layer_md_, tnc)); + if (dst_layer_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(dst_layer_md_, tnc)); + + if (diff_src_layer_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_src_layer_md_, tnc)); + if (diff_weights_layer_md_.format_kind == format_kind::any) { + CHECK(memory_desc_init_by_tag(diff_weights_layer_md_, ldigo)); + CHECK(rnn_utils::set_good_strides(diff_weights_layer_md_, ldigo)); + } + if (diff_weights_iter_md_.format_kind == format_kind::any) { + CHECK(memory_desc_init_by_tag(diff_weights_iter_md_, ldigo)); + CHECK(rnn_utils::set_good_strides(diff_weights_iter_md_, ldigo)); + } + if (diff_dst_layer_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_dst_layer_md_, tnc)); + + // Optional parameters + if (with_src_iter() && src_iter_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(src_iter_md_, ldsnc)); + if (with_bias() && bias_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(bias_md_, ldgo)); + if (with_dst_iter() && dst_iter_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(dst_iter_md_, ldsnc)); + + if (with_src_iter() && diff_src_iter_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_src_iter_md_, ldsnc)); + if (with_bias() && diff_bias_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_bias_md_, ldgo)); + if (with_dst_iter() && diff_dst_iter_md_.format_kind == format_kind::any) + CHECK(memory_desc_init_by_tag(diff_dst_iter_md_, ldsnc)); + + return status::success; + } + + status_t check_layout_consistency() { + using namespace format_tag; + using namespace types; + + auto is_blocked = [&](memory_desc_t md, int ndims) { + return md.format_kind == format_kind::blocked && md.ndims == ndims; + }; + + bool ok = true; + ok = ok && is_blocked(src_layer_md_, 3) + && is_blocked(dst_layer_md_, 3); + ok = ok && IMPLICATION(!is_zero_md(&src_iter_md_), + is_blocked(src_iter_md_, 5)) + && IMPLICATION(!is_zero_md(&dst_iter_md_), + is_blocked(dst_iter_md_, 5)); + + if (weights_layer_md_.format_kind == format_kind::rnn_packed) + ok = ok && (weights_layer_md_.format_desc.rnn_packed_desc.format + == mkldnn_ldgoi_p); + else + ok = ok && rnn_utils::is_ldgoi(&weights_layer_md_); + + if (weights_iter_md_.format_kind == format_kind::rnn_packed) + ok = ok && (weights_iter_md_.format_desc.rnn_packed_desc.format + == mkldnn_ldgoi_p); + else + ok = ok && rnn_utils::is_ldgoi(&weights_iter_md_); + + ok = ok && IMPLICATION(!is_zero_md(&bias_md_), + memory_desc_matches_tag(bias_md_, ldgo)); + + ok = ok && is_blocked(diff_src_layer_md_, 3) + && is_blocked(diff_dst_layer_md_, 3); + ok = ok && IMPLICATION(!is_zero_md(&diff_src_iter_md_), + is_blocked(diff_src_iter_md_, 5)) + && IMPLICATION(!is_zero_md(&diff_dst_iter_md_), + is_blocked(diff_dst_iter_md_, 5)); + + ok = ok && rnn_utils::is_ldigo(&diff_weights_layer_md_) + && rnn_utils::is_ldigo(&diff_weights_iter_md_); + ok = ok && IMPLICATION(!is_zero_md(&diff_bias_md_), + memory_desc_matches_tag(diff_bias_md_, ldgo)); + + return ok ? status::success : status::unimplemented; + } +}; +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp new file mode 100644 index 0000000000..09445648aa --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp @@ -0,0 +1,401 @@ +/******************************************************************************* +* Copyright 2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* + * Cell execution LSTM + */ + +#include "rnn_utils.hpp" +#include "../jit_generator.hpp" +#include "../jit_uni_eltwise.hpp" +#include "c_types_map.hpp" +#include "utils.hpp" + +#include "mkldnn_thread.hpp" + + +namespace mkldnn { +namespace impl { +namespace cpu { + +struct jit_uni_rnn_postgemm_kernel : public jit_generator { + + typedef void (*kernel_t)(void *gates_, const void *bias, void *states_t_l_, + void *c_states_t_l_, void *c_states_tm1_l_); + + jit_uni_rnn_postgemm_kernel(const rnn_utils::rnn_conf_t &rnn, const primitive_attr_t *attr): rnn_(rnn), attr_(attr){} + + virtual void init() = 0; + +template + rnn_elemwise_sig(execute) { + rnn_utils::ws_gates_aoc ws_gates(rnn, ws_gates_); + rnn_utils::bias_aoc_t bias(rnn, bias_); + rnn_utils::ws_states_aoc states_t_l(rnn, states_t_l_); + rnn_utils::ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_); + rnn_utils::ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_); + + // Todo: add parallelization on dic for the batch 1 case + // Assumption: the kernel runs a loop on dic elements + parallel_nd(rnn.mb, [&](int i) { + auto b_ = &bias(0, 0); + auto g_ = &ws_gates(i, 0, 0); + auto s_tl_ = &states_t_l(i, 0); + auto c_tl_ = &c_states_t_l(i, 0); + auto c_tm1l_ = &c_states_tm1_l(i, 0); + kernel_(g_, b_, s_tl_, c_tm1l_, c_tl_); + }); + } + +protected: + kernel_t kernel_; + const rnn_utils::rnn_conf_t &rnn_; + const primitive_attr_t *attr_; +}; + +template +struct jit_uni_lstm_postgemm_kernel_fwd: public jit_uni_rnn_postgemm_kernel +{ + DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_lstm_postgemm_kernel_fwd) + + typedef typename utils::conditional::type acc_data_t; + typedef typename utils::conditional, + jit_uni_eltwise_injector_f32>::type injector_t; + + jit_uni_lstm_postgemm_kernel_fwd(const rnn_utils::rnn_conf_t &rnn, const primitive_attr_t *attr) + : jit_uni_rnn_postgemm_kernel(rnn, attr){} + + void init() override { + // we use rax for both constant tables as they use the same table + sigmoid_injector_ = new injector_t(this, + alg_kind::eltwise_logistic, 0.0f, 0.0f, true, rax); + tanh_injector_ = new injector_t(this, + alg_kind::eltwise_tanh, 0.0f, 0.0f, true, rax); + generate(); + kernel_ = (kernel_t) this->getCode(); + } + +protected: + injector_t *sigmoid_injector_; + injector_t *tanh_injector_; + + // register size in bytes + using Vmm = typename jit_uni_eltwise_injector_f32::Vmm; + size_t vlen = cpu_isa_traits::vlen; + size_t vlen_dst = (src_data_t == data_type::u8) ? vlen/4 : vlen; + size_t cstate_dt_size = sizeof(float); + size_t hstate_dt_size = (src_data_t == data_type::u8) ? sizeof(uint8_t) : sizeof(float); + size_t gate_dt_size = (src_data_t == data_type::u8) ? sizeof(uint32_t) : sizeof(float); + size_t qscale_dt_size = sizeof(float); + size_t bias_dt_size = sizeof(float); + + void generate() { + using namespace Xbyak; + + int mask = attr_->rnn_weights_qparams_.mask_; + float *weights_scales = attr_->rnn_weights_qparams_.scales_; + float data_scale = attr_->rnn_data_qparams_.scale_; + float data_shift = attr_->rnn_data_qparams_.shift_; + + // Labels declaration + Label vector_loop_start_label, vector_loop_end_label; + Label rem_loop_start_label, rem_loop_end_label; + Label table_label; + + // Register map + Reg64 loop_cnt(r11); // loop counter + Reg64 table_reg(rbx); // table is used for data scale and shifts + Reg64 weights_scales_reg(r13); + // We skip vmm0 as it can be used by the injector for masks on sse4.2 + Vmm G0(1), G1(2), G2(3), G3(4), tmp1_vmm(5), tmp2_vmm(6), zero_vmm(7); + + // constant table map + Address dscale_off_addr = ptr[table_reg]; + Address dshift_off_addr = ptr[table_reg + vlen]; + Address ymm_perm_mask_addr = ptr[table_reg + 2*vlen]; + Address zmm_perm_mask_addr = ptr[table_reg + 2*vlen + cpu_isa_traits::vlen]; + + // quantize from float to u8 + auto q_d = [&](Vmm f, Vmm tmp_vmm) { + uni_vpxor(tmp_vmm, tmp_vmm, tmp_vmm); + uni_vmulps(f, f, dscale_off_addr); // apply scale + uni_vaddps(f, f, dshift_off_addr); // apply shift + uni_vcvtps2dq(f, f); // convert to int32 + uni_vpackssdw(f, f, tmp_vmm); // convert from s32 to s16 + uni_vpackuswb(f, f, tmp_vmm); // convert from s16 to u8 with saturation + // Note that the results are interleaved by 128 bit chunks, so we need to merge them together + switch (vlen) { + case 64: { //avx512 + Zmm fz(f.getIdx()), tmpz(tmp_vmm.getIdx()); + uni_vmovups(tmpz, zmm_perm_mask_addr); + vpermd(fz, tmpz, fz); + break; } + case 32: { //avx + Ymm fy(f.getIdx()), tmpy(tmp_vmm.getIdx()); + uni_vmovups(tmpy, ymm_perm_mask_addr); + vpermd(fy, tmpy, fy); + break; } + case 16: // sse: nothing to do + break; + default: assert(!"Unsupported case"); + }; + }; + + auto fast_recip =[&](Vmm s, Vmm tmp, bool packed) { + if (packed) + uni_vrcpps(tmp, s); + else + uni_vrcpss(tmp, s); // prevent divide by zero + // we add one Newton iteration + uni_vmulps(s, s, tmp); + uni_vmulps(s, s, tmp); // s <- s * tmp^2 + uni_vaddps(tmp, tmp, tmp); + uni_vsubps(tmp, tmp, s); + uni_vmovups(s, tmp); // s <- 2 * tmp - s * tmp^2 + }; + + // dequantize from s32 to float + auto deq_w = [&](Vmm s, Vmm tmp1, Vmm tmp2, int gate, bool packed) { + // TODO: if mask is 0 precompute mul and inverse + if (mask == 0) + uni_vbroadcastss(tmp1, ptr[weights_scales_reg]); + else + uni_vmovups(tmp1, ptr[weights_scales_reg + gate * rnn_.dic * qscale_dt_size]); + uni_vcvtdq2ps(s, s); + uni_vmulps(tmp1, tmp1, dscale_off_addr); + fast_recip(tmp1, tmp2, packed); + uni_vmulps(s, s, tmp1); + }; + + // We start code generations here + preamble(); + + // extract addresses passed as parameter +#ifdef _WIN32 + auto addr_ws_gates_reg = abi_param1; + auto addr_bias_reg = abi_param2; + auto addr_states_t_l_reg = abi_param3; + auto addr_c_states_tm1_l_reg = abi_param4; + auto addr_c_states_t_l_reg = r10; + // Here we cannot use rbp to have initial stack pointer so we + // use rsp and offset it with the size of pushed registers in + // preamble + mov(addr_c_states_t_l_reg, ptr[rsp + get_size_of_abi_save_regs() + 40]); +#else + auto addr_ws_gates_reg = abi_param1; + auto addr_bias_reg = abi_param2; + auto addr_states_t_l_reg = abi_param3; + auto addr_c_states_tm1_l_reg = abi_param4; + auto addr_c_states_t_l_reg = abi_param5; +#endif + + // initialize registers with addresses and constants + mov(table_reg, table_label); + mov(weights_scales_reg, size_t(weights_scales)); + // both sigmoid and tanh use the same table so load address just once in rax + sigmoid_injector_->load_table_addr(); + + mov(loop_cnt, rnn_.dic * gate_dt_size); + cmp(loop_cnt, vlen); + jl(vector_loop_end_label, Xbyak::CodeGenerator::T_NEAR); + + L(vector_loop_start_label); + { + // load G0 G1 G2 G3 + uni_vmovups(G0, ptr[addr_ws_gates_reg + 0 * rnn_.dic * gate_dt_size]); + uni_vmovups(G1, ptr[addr_ws_gates_reg + 1 * rnn_.dic * gate_dt_size]); + uni_vmovups(G2, ptr[addr_ws_gates_reg + 2 * rnn_.dic * gate_dt_size]); + uni_vmovups(G3, ptr[addr_ws_gates_reg + 3 * rnn_.dic * gate_dt_size]); + + // dequantize the gates from s32 to f32 if needed + if (src_data_t == data_type::u8){ + deq_w(G0, tmp1_vmm, tmp2_vmm, 0, true); + deq_w(G1, tmp1_vmm, tmp2_vmm, 1, true); + deq_w(G2, tmp1_vmm, tmp2_vmm, 2, true); + deq_w(G3, tmp1_vmm, tmp2_vmm, 3, true); + } + + // add biases + uni_vaddps(G0, G0, ptr[addr_bias_reg + 0 * rnn_.dic * bias_dt_size]); + uni_vaddps(G1, G1, ptr[addr_bias_reg + 1 * rnn_.dic * bias_dt_size]); + uni_vaddps(G2, G2, ptr[addr_bias_reg + 2 * rnn_.dic * bias_dt_size]); + uni_vaddps(G3, G3, ptr[addr_bias_reg + 3 * rnn_.dic * bias_dt_size]); + + // inject eltwise code + sigmoid_injector_->compute_vector(G0.getIdx()); + sigmoid_injector_->compute_vector(G1.getIdx()); + tanh_injector_->compute_vector(G2.getIdx()); + sigmoid_injector_->compute_vector(G3.getIdx()); + + // compute c_states_t_l = G1 * c_tm1_l + G0 * G2 + uni_vmovups(tmp1_vmm, ptr[addr_c_states_tm1_l_reg]); + uni_vmulps(tmp1_vmm, tmp1_vmm, G1); + uni_vfmadd231ps(tmp1_vmm, G0, G2); + uni_vmovups(ptr[addr_c_states_t_l_reg], tmp1_vmm); + + // states_t_l = G3 * tanh(c_states_t_l) + tanh_injector_->compute_vector(tmp1_vmm.getIdx()); + uni_vmulps(tmp1_vmm, tmp1_vmm, G3); + + // if int8, we quantize the resulting state + if (src_data_t == data_type::u8) + q_d(tmp1_vmm, tmp2_vmm); + + // write back the result + if(vlen_dst == vlen) + uni_vmovups(ptr[addr_states_t_l_reg], tmp1_vmm); + else + // we write only 1/4 of the register + switch(vlen_dst){ + case 16: uni_vmovups(ptr[addr_states_t_l_reg], Xmm(tmp1_vmm.getIdx())); break; + case 8: uni_vmovsd(ptr[addr_states_t_l_reg], Xmm(tmp1_vmm.getIdx())); break; + case 4: uni_vmovss(ptr[addr_states_t_l_reg], Xmm(tmp1_vmm.getIdx())); break; + default: + assert(!"Unsuported vector length for quantization"); + } + + // increment address pointers + add(addr_ws_gates_reg, vlen); + add(addr_bias_reg, vlen); + add(addr_states_t_l_reg, vlen_dst); + add(addr_c_states_tm1_l_reg, vlen); + add(addr_c_states_t_l_reg, vlen); + if (mask != 0) + add(weights_scales_reg, vlen); + + // increment loop counter + sub(loop_cnt, vlen); + cmp(loop_cnt, vlen); + jge(vector_loop_start_label); + } + L(vector_loop_end_label); + + cmp(loop_cnt, 0); + je(rem_loop_end_label, Xbyak::CodeGenerator::T_NEAR); + // Same code as above, we just use movuss for accessing inputs + // TODO: smarter handling of tails with Zmm -> Ymm -> Xmm -> scalar + L(rem_loop_start_label); + { + // remaping registers to Xmms + Xmm G0s(G0.getIdx()), G1s(G1.getIdx()), G2s(G2.getIdx()), G3s(G3.getIdx()); + Xmm tmp1s_vmm(tmp1_vmm.getIdx()); + + // load G0 G1 G2 G3 + uni_vmovss(G0s, ptr[addr_ws_gates_reg + 0 * rnn_.dic * gate_dt_size]); + uni_vmovss(G1s, ptr[addr_ws_gates_reg + 1 * rnn_.dic * gate_dt_size]); + uni_vmovss(G2s, ptr[addr_ws_gates_reg + 2 * rnn_.dic * gate_dt_size]); + uni_vmovss(G3s, ptr[addr_ws_gates_reg + 3 * rnn_.dic * gate_dt_size]); + + // dequantize the gates from s32 to f32 if needed + if (src_data_t == data_type::u8){ + deq_w(G0, tmp1_vmm, tmp2_vmm, 0, false); + deq_w(G1, tmp1_vmm, tmp2_vmm, 1, false); + deq_w(G2, tmp1_vmm, tmp2_vmm, 2, false); + deq_w(G3, tmp1_vmm, tmp2_vmm, 3, false); + } + + // add biases + uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 0 * rnn_.dic * bias_dt_size]); + uni_vaddps(G0s, G0s, tmp1s_vmm); + uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 1 * rnn_.dic * bias_dt_size]); + uni_vaddps(G1s, G1s, tmp1s_vmm); + uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 2 * rnn_.dic * bias_dt_size]); + uni_vaddps(G2s, G2s, tmp1s_vmm); + uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 3 * rnn_.dic * bias_dt_size]); + uni_vaddps(G3s, G3s, tmp1s_vmm); + + // inject eltwise code + sigmoid_injector_->compute_vector(G0s.getIdx()); + sigmoid_injector_->compute_vector(G1s.getIdx()); + tanh_injector_->compute_vector(G2s.getIdx()); + sigmoid_injector_->compute_vector(G3s.getIdx()); + + // compute c_states_t_l = G1 * c_tm1_l + G0s * G2 + uni_vmovups(tmp1s_vmm, ptr[addr_c_states_tm1_l_reg]); + uni_vmulps(tmp1s_vmm, tmp1s_vmm, G1s); + uni_vfmadd231ps(tmp1s_vmm, G0s, G2s); + uni_vmovss(ptr[addr_c_states_t_l_reg], tmp1s_vmm); + + // states_t_l = G3 * tanh(c_states_t_l) + tanh_injector_->compute_vector(tmp1s_vmm.getIdx()); + uni_vmulps(tmp1s_vmm, tmp1s_vmm, G3s); + + // if int8, we quantize the resulting state + if (src_data_t == data_type::u8) + q_d(tmp1_vmm, tmp2_vmm); + + // write back the result + if(vlen_dst == vlen) + uni_vmovups(ptr[addr_states_t_l_reg], tmp1s_vmm); + else + // we write only 1/4 of the register + switch(vlen_dst){ + case 16: uni_vmovups(ptr[addr_states_t_l_reg], Xmm(tmp1s_vmm.getIdx())); break; + case 8: uni_vmovsd(ptr[addr_states_t_l_reg], Xmm(tmp1s_vmm.getIdx())); break; + case 4: uni_vmovss(ptr[addr_states_t_l_reg], Xmm(tmp1s_vmm.getIdx())); break; + default: + assert(!"Unsuported vector length for quantization"); + } + + // increment address pointers + add(addr_ws_gates_reg, gate_dt_size); + add(addr_bias_reg, bias_dt_size); + add(addr_states_t_l_reg, hstate_dt_size); + add(addr_c_states_tm1_l_reg, cstate_dt_size); + add(addr_c_states_t_l_reg, cstate_dt_size); + if (mask != 0) + add(weights_scales_reg, qscale_dt_size); + + // increment loop counter + sub(loop_cnt, gate_dt_size); + cmp(loop_cnt, 0); + jg(rem_loop_start_label); + + } + L(rem_loop_end_label); + + postamble(); + + // Again, only one table is needed and shared between sigmoid and tanh + sigmoid_injector_->prepare_table(false); + tanh_injector_->prepare_table(true); + + L(table_label); + { + for (size_t i = 0; i < vlen / sizeof(float); i++) dd(float2int(data_scale)); + for (size_t i = 0; i < vlen / sizeof(float); i++) dd(float2int(data_shift)); + // perm mask for ymm + dd(0); dd(4); dd(2); dd(3); dd(1); dd(5); dd(6); dd(7); + // perm mask for zmm + dd(0); dd(4); dd(8); dd(12); dd(1); dd(5); dd(6); dd(7); + dd(2); dd(9); dd(10); dd(11); dd(3); dd(12); dd(13); dd(14); + } + } + +}; + +template struct jit_uni_lstm_postgemm_kernel_fwd; +template struct jit_uni_lstm_postgemm_kernel_fwd; +template struct jit_uni_lstm_postgemm_kernel_fwd; + +template struct jit_uni_lstm_postgemm_kernel_fwd; +template struct jit_uni_lstm_postgemm_kernel_fwd; +template struct jit_uni_lstm_postgemm_kernel_fwd; +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp new file mode 100644 index 0000000000..ead536816c --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp @@ -0,0 +1,788 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/* + General architecture + + for diff states, we have n_states + 1 as we have n_states diff + to propagate to the previous iteration and 1 states to propagate + to the previous layer + index 0 is dh for cell(t-1, l) to consume + index 1 is dc for cell(t-1, l) to consume + index 2 is dh for cell(t, l-1) to consume + this indexing enables to have the same indexing for states in elemwise + function + only the cell execution function should be impacted + + */ + +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" + +#include "ref_rnn.hpp" +#include "../gemm/gemm.hpp" +#include "../simple_q10n.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace mkldnn::impl::memory_tracking::names; +using namespace rnn_utils; +#define AOC array_offset_calculator + +template +void _ref_rnn_common_t::gates_reduction( + const rnn_conf_t &rnn, const acc_data_t *ws_gates_, + float *diff_bias_) const { + auto body = [&](int i, int k) { + for (int j = 0; j < rnn.mb; j++) + diff_bias_[i * rnn.dic + k] + += ws_gates_[j * rnn.gates_ws_ld + i * rnn.dic + k]; + }; + + // @todo block k on simd-width +#if MKLDNN_THR == MKLDNN_THR_OMP && _OPENMP >= 201307 \ + /* icc 17.0 has a problem with simd collapse */ \ + && !((defined __INTEL_COMPILER) && (__INTEL_COMPILER == 1700)) +#pragma omp parallel for simd collapse(2) + for (int i = 0; i < rnn.n_gates; i++) + for (int k = 0; k < rnn.dic; k++) + body(i, k); +#else + parallel_nd(rnn.n_gates, rnn.dic, body); +#endif +} + +template +rnn_gemm_sig((_ref_rnn_common_t::gemm)) { + assert(ldA * ldB * ldC != 0); + extended_sgemm(&transA, &transB, &m, &n, &k, &alpha, a_, &ldA, b_, &ldB, + &beta, c_, &ldC, nullptr, pd()->rnn_.use_jit_gemm); +} + +template <> +rnn_gemm_sig((ref_rnn_fwd_u8s8_t::gemm)) { + assert(!"non packed gemm is disabled for int8"); +} + +template +rnn_gemm_sig((_ref_rnn_common_t::packed_gemm)) { +#if (USE_MKL_PACKED_GEMM) + assert(transA == 'N'); + cblas_sgemm_compute(CblasColMajor, CblasPacked, + (transB == 'T') ? CblasTrans : CblasNoTrans, m, n, k, a_, ldA, b_, + ldB, beta, c_, ldC); +#else + UNUSED(transA); + UNUSED(transB); + UNUSED(m); + UNUSED(n); + UNUSED(k); + UNUSED(alpha); + UNUSED(ldA); + UNUSED(b_); + UNUSED(ldB); + UNUSED(beta); + UNUSED(c_); + UNUSED(ldC); + assert(!"packed gemm is disabled"); +#endif +} + +template <> +rnn_gemm_sig((ref_rnn_fwd_u8s8_t::packed_gemm)) { +#if (USE_MKL_PACKED_GEMM) + int8_t offseta = 0, offsetb = 0; + int32_t offsetc = 0; + cblas_gemm_s8u8s32_compute(CblasColMajor, (CBLAS_TRANSPOSE)CblasPacked, + CblasNoTrans, CblasFixOffset, m, n, k, alpha, a_, ldA, offseta, b_, + ldB, offsetb, beta, c_, ldC, &offsetc); +#else + UNUSED(transA); + UNUSED(transB); + UNUSED(m); + UNUSED(n); + UNUSED(k); + UNUSED(alpha); + UNUSED(ldA); + UNUSED(b_); + UNUSED(ldB); + UNUSED(beta); + UNUSED(c_); + UNUSED(ldC); + assert(!"packed gemm is disabled"); +#endif +} + +//*************** Grid computations strategy: linear ***************// +template +rnn_grid_execution_sig( + (_ref_rnn_common_t::linear_execution)) { + AOC ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_iter + 1, rnn.states_nld * rnn.states_ws_ld); + AOC ws_c_states(ws_c_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_iter + 1, rnn.states_nld * rnn.states_ws_ld); + AOC ws_diff_states(ws_diff_states_, rnn.n_layer + 1, rnn.n_dir, + (rnn.n_states + 1), rnn.n_iter + 1, + rnn.states_nld * rnn.states_ws_ld); + AOC ws_gates(ws_gates_, rnn.n_layer, rnn.n_dir, rnn.n_iter, + rnn.gates_nld * rnn.gates_ws_ld); + AOC weights_input( + weights_layer_, rnn.n_layer, rnn.n_dir, rnn.n_parts_weights_layer); + AOC weights_states( + weights_states_, rnn.n_layer, rnn.n_dir, rnn.n_parts_weights_iter); + AOC bias( + bias_, rnn.n_layer, rnn.n_dir, rnn.n_parts_bias); + AOC diff_weights_layer(diff_weights_layer_, rnn.n_layer, + rnn.n_dir, + rnn.diff_weights_layer_nld * rnn.diff_weights_layer_ld); + AOC diff_weights_iter(diff_weights_iter_, rnn.n_layer, rnn.n_dir, + rnn.diff_weights_iter_nld * rnn.diff_weights_iter_ld); + AOC diff_bias( + diff_bias_, rnn.n_layer, rnn.n_dir, rnn.n_bias * rnn.dic); + AOC ws_grid( + ws_grid_, rnn.n_layer, rnn.n_dir, rnn.n_iter, (int)rnn.ws_per_cell); + + // We run the grid of computation + for (int dir = 0; dir < rnn.n_dir; dir++) { + for (int j = 0; j < rnn.n_layer; j++) { + int lay = (aprop == prop_kind::forward) ? j : rnn.n_layer - j - 1; + + if ((aprop == prop_kind::forward) && rnn.merge_gemm_layer) { + (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic, + rnn.mb * rnn.n_iter, rnn.slc, 1.0, + weights_input(lay, dir, 0), rnn.weights_iter_ld, + &(ws_states(lay, dir, 1, 0)), rnn.states_ws_ld, 0.0, + &(ws_gates(lay, dir, 0, 0)), rnn.gates_ws_ld); + } + + for (int i = 0; i < rnn.n_iter; i++) { + int iter = (aprop == prop_kind::forward) ? i : rnn.n_iter - i - 1; + (this->*cell_func)(rnn, + &(ws_states(lay + 1, dir, iter + 1, 0)), + &(ws_c_states(lay + 1, dir, iter + 1, 0)), + &(ws_diff_states(lay, dir, 0, iter, 0)), + &(weights_input(lay, dir, 0)), + &(weights_states(lay, dir, 0)), + &(bias(lay, dir, 0)), + &(ws_states(lay, dir, iter + 1, 0)), + &(ws_states(lay + 1, dir, iter, 0)), + &(ws_c_states(lay + 1, dir, iter, 0)), + &(ws_diff_states(lay + 1, dir, 0, iter, 0)), + &(ws_diff_states(lay, dir, 0, iter + 1, 0)), + &(diff_weights_layer(lay, dir, 0)), + &(diff_weights_iter(lay, dir, 0)), + &(diff_bias(lay, dir, 0)), + &(ws_gates(lay, dir, iter, 0)), + &(ws_grid(lay, dir, iter, 0)), + ws_cell_); + } + + if ((aprop == prop_kind::backward) && rnn.merge_gemm_layer) { + (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb * rnn.n_iter, + rnn.n_gates * rnn.dic, 1.0, weights_input(lay, dir, 0), + rnn.weights_layer_ld, + (src_data_t *)(&(ws_gates(lay, dir, 0, 0))), + rnn.gates_ws_ld, 0.0, + (acc_data_t *)(&(ws_diff_states( + lay, dir, rnn.n_states, 0, 0))), + rnn.states_ws_ld); + gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc, + rnn.mb * rnn.n_iter, 1.0, + (weights_data_t *)(&(ws_gates(lay, dir, 0, 0))), + rnn.gates_ws_ld, + (src_data_t *)(&(ws_states(lay, dir, 1, 0))), + rnn.states_ws_ld, 1.0, + (acc_data_t *)(&(diff_weights_layer(lay, dir, 0))), + rnn.diff_weights_layer_ld); + } + if ((aprop == prop_kind::backward) && rnn.merge_gemm_iter) { + gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.sic, + rnn.mb * rnn.n_iter, 1.0, + (weights_data_t *)(&(ws_gates(lay, dir, 0, 0))), + rnn.gates_ws_ld, + (src_data_t *)(&(ws_states(lay + 1, dir, 0, 0))), + rnn.states_ws_ld, 1.0, + (acc_data_t *)(&(diff_weights_iter(lay, dir, 0))), + rnn.diff_weights_iter_ld); + } + } + } +} + +//********* GRID computations strategy: utility functions **********// + +template +void _ref_rnn_common_t::copy_init_layer( + const rnn_conf_t &rnn, src_data_t *__restrict ws_states_, + float *__restrict ws_diff_states_, const src_data_t *__restrict xt_, + const float *__restrict diff_dst_layer_) const { + + AOC ws_states( + ws_states_, rnn.n_dir, rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + auto xt_d = memory_desc_wrapper(pd()->src_md(0)); + + parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) { + auto xxt = xt_ + xt_d.blk_off(it, b); + src_data_t *ws_l2r_ptr = &(ws_states(0, it + 1, b, 0)); + src_data_t *ws_r2l_ptr = &(ws_states(rnn.n_dir - 1, rnn.n_iter - it, b, 0)); + if (rnn.exec_dir != r2l) + for (int c = 0; c < rnn.slc; c++) + ws_l2r_ptr[c] = xxt[c]; + if (rnn.exec_dir != l2r) + for (int c = 0; c < rnn.slc; c++) + ws_r2l_ptr[c] = xxt[c]; + }); +} + +template <> +void ref_rnn_bwd_f32_t::copy_init_layer(const rnn_conf_t &rnn, + src_data_t *ws_states_, float *ws_diff_states_, const src_data_t *xt_, + const float *diff_dst_layer_) const { + AOC ws_diff_states(ws_diff_states_, rnn.n_layer + 1, rnn.n_dir, + (rnn.n_states + 1), rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + auto diff_dst_layer_d = memory_desc_wrapper(pd()->diff_dst_md(0)); + + switch (rnn.exec_dir) { + case bi_concat: + parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) { + auto diff_dst_layer_x + = diff_dst_layer_ + diff_dst_layer_d.blk_off(it, b); + for (int s = 0; s < rnn.dic; s++) { + ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s) + = diff_dst_layer_x[s]; + ws_diff_states( + rnn.n_layer, 1, rnn.n_states, rnn.n_iter - it - 1, b, s) + = diff_dst_layer_x[rnn.dic + s]; + } + }); + break; + case bi_sum: + parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) { + auto diff_dst_layer_x + = diff_dst_layer_ + diff_dst_layer_d.blk_off(it, b); + for (int s = 0; s < rnn.dic; s++) { + ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s) + = diff_dst_layer_x[s]; + ws_diff_states( + rnn.n_layer, 1, rnn.n_states, rnn.n_iter - it - 1, b, s) + = diff_dst_layer_x[s]; + } + }); + break; + case l2r: + parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) { + auto diff_dst_layer_x + = diff_dst_layer_ + diff_dst_layer_d.blk_off(it, b); + for (int s = 0; s < rnn.dic; s++) { + ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s) + = diff_dst_layer_x[s]; + } + }); + break; + case r2l: + parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) { + auto diff_dst_layer_x = diff_dst_layer_ + + diff_dst_layer_d.blk_off(rnn.n_iter - it - 1, b); + for (int s = 0; s < rnn.dic; s++) { + ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s) + = diff_dst_layer_x[s]; + } + }); + break; + default: assert(!"Unsupported direction"); break; + } +} + +/* For int8 configuration, input iteration states may be of types f32 or u8 + * Internally h_state is always stored in u8 and c_state is always stored in f32 + * If input states are of type u8 then h state is copied and c state is dequantized + * If input states are of type f32 then h state is quantized and c_state is copied + * */ +template +template +void _ref_rnn_common_t::copy_init_iter( + const rnn_conf_t &rnn, src_data_t *__restrict ws_states_, + float *__restrict ws_c_states_, float *__restrict ws_diff_states_, + const input_data_t *__restrict firstit_states_, + const float *__restrict diff_dst_iter_) const { + AOC ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + AOC ws_c_states(ws_c_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + float data_shift = pd()->attr()->rnn_data_qparams_.shift_; + float data_scale = pd()->attr()->rnn_data_qparams_.scale_; + + const bool quantize = pd()->with_src_iter() + && pd()->src_md(1)->data_type == data_type::f32 + && rnn.dt_conf != all_f32; + auto maybe_q = [&](input_data_t f) { + if (quantize) { + float qf = f * data_scale + data_shift; + return qz_a1b0()(qf); + } else + return (src_data_t)f; + }; + + const bool dequantize = pd()->with_src_iter() + && pd()->src_md(1)->data_type == data_type::u8; + auto maybe_deq = [&](input_data_t s) { + if (dequantize) + return (((float)s - data_shift) / data_scale); + else + return (float)s; + }; + auto firstit_states_d = memory_desc_wrapper(pd()->src_md(1)); + if (firstit_states_) { + parallel_nd( + rnn.n_layer, rnn.n_dir, rnn.mb, [&](int lay, int dir, int b) { + for (int s = 0; s < rnn.sic; s++) + ws_states(lay + 1, dir, 0, b, s) = maybe_q( + firstit_states_[firstit_states_d.blk_off( + lay, dir, 0, b, s)]); + if (pd()->cell_kind() == alg_kind::vanilla_lstm) + for (int s = 0; s < rnn.sic; s++) + ws_c_states(lay + 1, dir, 0, b, s) = maybe_deq( + firstit_states_[firstit_states_d.blk_off( + lay, dir, 1, b, s)]); + }); + } else { + parallel_nd( + rnn.n_layer, rnn.n_dir, rnn.mb, [&](int lay, int dir, int b) { + for (int j = 0; j < rnn.sic; j++) { + ws_states(lay + 1, dir, 0, b, j) = (src_data_t)0; + ws_c_states(lay + 1, dir, 0, b, j) = 0.0f; + } + }); + } +} + +template <> +template +void ref_rnn_bwd_f32_t::copy_init_iter(const rnn_conf_t &rnn, + src_data_t *ws_states_, float *ws_c_states_, float *ws_diff_states_, + const input_data_t *firstit_states_, + const float *diff_dst_iter_) const { + AOC ws_diff_states(ws_diff_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_states + 1, rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + auto diff_dst_iter_d = memory_desc_wrapper(pd()->diff_dst_md(1)); + if (diff_dst_iter_) { + parallel_nd(rnn.n_layer, rnn.n_dir, rnn.n_states, rnn.mb, + [&](int lay, int dir, int state, int b) { + array_copy(&(ws_diff_states( + lay, dir, state, rnn.n_iter, b, 0)), + diff_dst_iter_ + + diff_dst_iter_d.blk_off( + lay, dir, state, b), + rnn.dic); + }); + } else { + parallel_nd(rnn.n_layer, rnn.n_dir, rnn.n_states, rnn.mb, + [&](int lay, int dir, int state, int i) { + for (int j = 0; j < rnn.dic; j++) + ws_diff_states(lay, dir, state, rnn.n_iter, i, j) + = 0.0f; + }); + } +} + +template +template +void _ref_rnn_common_t::copy_res_layer( + const rnn_conf_t &rnn, dst_data_t *dst_layer_, float *diff_src_layer, + const src_data_t *ws_states_, const float *ws_diff_states_) const { + + auto dst_layer_d = memory_desc_wrapper(pd()->dst_md(0)); + AOC ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + float shift = (pd()->attr()->rnn_data_qparams_.shift_); + float scale = (pd()->attr()->rnn_data_qparams_.scale_); + + const bool dequantize = pd()->dst_md(0)->data_type == data_type::f32 + && rnn.dt_conf != all_f32; + auto maybe_deq = [&](src_data_t s) { + if (dequantize) + return (dst_data_t)(((float)s - shift) / scale); + else + return (dst_data_t)s; + }; + parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) { + int dir = 0; + if (rnn.exec_dir != r2l) { + for (int s = 0; s < rnn.dic; s++) { + dst_layer_[dst_layer_d.blk_off(it, b, dir * rnn.dic + s)] + = maybe_deq(ws_states(rnn.n_layer, dir, it + 1, b, s)); + } + dir = 1; + } + if (rnn.exec_dir != l2r) { + for (int s = 0; s < rnn.dic; s++) + switch (rnn.exec_dir) { + case bi_sum: + dst_layer_[dst_layer_d.blk_off(it, b, s)] + += maybe_deq(ws_states( + rnn.n_layer, dir, rnn.n_iter - it, b, s)); + break; + default: + dst_layer_[dst_layer_d.blk_off(it, b, dir * rnn.dic + s)] + = maybe_deq(ws_states( + rnn.n_layer, dir, rnn.n_iter - it, b, s)); + } + } + }); +} + +template <> +template +void ref_rnn_bwd_f32_t::copy_res_layer( + const rnn_conf_t &rnn, dst_data_t *dst_layer_, float *diff_src_layer_, + const src_data_t *ws_states_, const float *ws_diff_states_) const { + auto diff_src_layer_d = memory_desc_wrapper(pd()->diff_src_md(0)); + AOC ws_diff_states(ws_diff_states_, rnn.n_layer + 1, + rnn.n_dir, rnn.n_states + 1, rnn.n_iter + 1, rnn.mb, + rnn.states_ws_ld); + + parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) { + int dir = 0; + for (int s = 0; s < rnn.slc; s++) { + float *dst_addr = diff_src_layer_ + + diff_src_layer_d.blk_off( + (rnn.exec_dir == r2l) ? rnn.n_iter - 1 - it : it, + b, dir * rnn.slc + s); + float res = ws_diff_states(0, 0, rnn.n_states, it, b, s); + if (rnn.n_dir - 1) + res += ws_diff_states( + 0, 1, rnn.n_states, rnn.n_iter - 1 - it, b, s); + dst_addr[0] = res; + } + }); +} + +template +template +void _ref_rnn_common_t::copy_res_iter( + const rnn_conf_t &rnn, output_data_t *dst_iter_, float *diff_src_iter_, + const src_data_t *ws_states_, float *ws_c_states_, + const float *ws_diff_states_) const { + auto dst_iter_d = memory_desc_wrapper(pd()->dst_md(1)); + AOC ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + AOC ws_c_states(ws_c_states_, rnn.n_layer + 1, rnn.n_dir, + rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld); + float data_shift = pd()->attr()->rnn_data_qparams_.shift_; + float data_scale = pd()->attr()->rnn_data_qparams_.scale_; + + const bool quantize = pd()->with_dst_iter() + && pd()->dst_md(1)->data_type == data_type::u8 + && rnn.dt_conf != all_f32; + auto maybe_q = [&](float f) { + if (quantize) { + float qf = f * data_scale + data_shift; + return qz_a1b0()(qf); + } else + return (output_data_t)f; + }; + + const bool dequantize = pd()->with_dst_iter() + && pd()->dst_md(1)->data_type == data_type::f32 + && rnn.dt_conf != all_f32; + auto maybe_deq = [&](src_data_t s) { + if (dequantize) + return (output_data_t)(((float)s - data_shift) / data_scale); + else + return (output_data_t)s; + }; + if (dst_iter_) { + parallel_nd(rnn.n_layer, rnn.n_dir, rnn.mb, + [&](int lay, int dir, int b) { + for (int s = 0; s < rnn.dic; s++) { + dst_iter_[dst_iter_d.blk_off(lay, dir, 0, b, s)] + = maybe_deq(ws_states(lay + 1, dir, rnn.n_iter, b, s)); + } + if (pd()->cell_kind() == alg_kind::vanilla_lstm) + for (int s = 0; s < rnn.dic; s++) { + dst_iter_[dst_iter_d.blk_off(lay, dir, 1, b, s)] + = maybe_q(ws_c_states( + lay + 1, dir, rnn.n_iter, b, s)); + } + }); + } +} + +template <> +template +void ref_rnn_bwd_f32_t::copy_res_iter( + const rnn_conf_t &rnn, output_data_t *dst_iter_, float *diff_src_iter_, + const src_data_t *ws_states_, float *ws_c_states_, + const float *ws_diff_states_) const { + auto diff_src_iter_d = memory_desc_wrapper(pd()->diff_src_md(1)); + AOC ws_diff_states(ws_diff_states_, rnn.n_layer + 1, + rnn.n_dir, rnn.n_states + 1, rnn.n_iter + 1, rnn.mb, + rnn.states_ws_ld); + if (diff_src_iter_) { + parallel_nd(rnn.n_layer, rnn.n_dir, rnn.n_states, rnn.mb, + [&](int lay, int dir, int state, int b) { + for (int s = 0; s < rnn.sic; s++) { + diff_src_iter_[diff_src_iter_d.blk_off( + lay, dir, state, b, s)] + = ws_diff_states(lay, dir, state, 0, b, s); + } + }); + } +} + +template +rnn_bias_prepare_sig((_ref_rnn_common_t::bias_prepare)) { + /* Original set of bias provided by the user */ + AOC b( + b_, rnn.n_layer, rnn.n_dir, rnn.n_bias * rnn.dic); + /* Array of pointers initialized in packing */ + AOC bias(bias_, rnn.n_layer, rnn.n_dir, rnn.n_parts_bias); + AOC scratch_bias( + scratch_bias_, rnn.n_layer, rnn.n_dir, rnn.n_bias * rnn.dic); + + if (rnn.copy_bias) { + parallel_nd(rnn.n_layer * rnn.n_dir * rnn.n_bias * rnn.dic, + [&](size_t i) { scratch_bias_[i] = b_[i]; }); + } + + for (int i = 0; i < rnn.n_layer; i++) { + for (int d = 0; d < rnn.n_dir; d++) { + int offset_bias = 0; + for (int p = 0; p < rnn.n_parts_bias; p++) { + bias(i, d, p) = rnn.copy_bias + ? (float *) &scratch_bias(i, d, offset_bias) + : (float *) &b(i, d, offset_bias); + offset_bias += rnn.parts_bias[p] * rnn.dic; + } + } + } + +} + +template +rnn_bias_finalize_sig( + (_ref_rnn_common_t::bias_finalize)) { + if (rnn.dt_conf != all_f32) { + float data_shift = pd()->attr()->rnn_data_qparams_.shift_; + float data_scale = pd()->attr()->rnn_data_qparams_.scale_; + float *weights_scales = pd()->attr()->rnn_weights_qparams_.scales_; + bool scale_per_oc = pd()->attr()->rnn_weights_qparams_.mask_ != 0; + for (int i = 0; i < rnn.n_layer * rnn.n_dir; i++) + for (int j = 0; j < rnn.n_bias * rnn.dic; j++) { + size_t off = i * rnn.n_bias * rnn.dic + j; + float weights_scale + = scale_per_oc ? weights_scales[j] : weights_scales[0]; + scratch_bias_[off] -= (w_iter_comp[off] + w_layer_comp[off]) + * data_shift / (weights_scale * data_scale); + } + } +} + +template +rnn_weights_assign_sig((_ref_rnn_common_t::assign_packed_weights)) { + assert(md->format_kind == format_kind::rnn_packed); + const auto packed_desc = md->format_desc.rnn_packed_desc; + AOC weights(weights_, + rnn.n_layer, rnn.n_dir, packed_desc.n_parts); + + size_t offset_packed = 0; + for (int l = 0; l < rnn.n_layer; l++) + for (int d = 0; d < rnn.n_dir; d++) { + for (int p = 0; p < packed_desc.n_parts; p++) { + weights(l, d, p) = (weights_data_t *)&w_[offset_packed]; + offset_packed + += packed_desc.part_pack_size[p] / sizeof(weights_data_t); + } + } +} + +template +rnn_weights_assign_sig( + (_ref_rnn_common_t::assign_weights)) { + assert(md->format_kind == format_kind::blocked); + const auto &blk = md->format_desc.blocking; + /* Original set of weights provided by the user */ + AOC w(w_, + rnn.n_layer, rnn.n_dir, (int)blk.strides[1]); + /* Array of pointers for each part of weights */ + AOC weights(weights_, rnn.n_layer, rnn.n_dir, n_parts); + + for (int i = 0; i < rnn.n_layer; i++) + for (int d = 0; d < rnn.n_dir; d++) { + size_t offset_weights = 0; + for (int p = 0; p < n_parts; p++) { + weights(i, d, p) = (weights_data_t *)&w(i, d, offset_weights); + offset_weights += gates_per_part[p] * blk.strides[3]; + } + } +} + +//********************* Execution function *********************// +template +void _ref_rnn_common_t::execute_( + const exec_ctx_t &ctx) const { + const rnn_conf_t &rnn = this->pd()->rnn_; + auto input = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC_LAYER); + auto states = CTX_IN_MEM(const char *, MKLDNN_ARG_SRC_ITER); + auto layer_weights_n_comp = CTX_IN_MEM(const char *, MKLDNN_ARG_WEIGHTS_LAYER); + auto iter_weights_n_comp = CTX_IN_MEM(const char *, MKLDNN_ARG_WEIGHTS_ITER); + auto bias = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS); + + auto dst_last_layer = rnn.is_fwd + ? CTX_OUT_MEM(char *, MKLDNN_ARG_DST_LAYER) + : const_cast(CTX_IN_MEM(const char *, MKLDNN_ARG_DST_LAYER)); + auto dst_last_iter = rnn.is_fwd + ? CTX_OUT_MEM(char *, MKLDNN_ARG_DST_ITER) + : const_cast(CTX_IN_MEM(const char *, MKLDNN_ARG_DST_ITER)); + + auto diff_dst_layer = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST_LAYER); + auto diff_dst_iter = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST_ITER); + + auto w_layer = reinterpret_cast(layer_weights_n_comp); + auto w_iter = reinterpret_cast(iter_weights_n_comp); + auto w_iter_comp = reinterpret_cast( + iter_weights_n_comp + rnn.weights_iter_comp_offset); + auto w_layer_comp = reinterpret_cast( + layer_weights_n_comp + rnn.weights_layer_comp_offset); + + auto scratchpad = this->scratchpad(ctx); + + auto ptr_wei_layer + = scratchpad.template get(key_rnn_ptrs_wei_layer); + auto ptr_wei_iter + = scratchpad.template get(key_rnn_ptrs_wei_iter); + auto ptr_bias = + scratchpad.template get(key_rnn_ptrs_bia); + + // fetchihg buffers from the workspace + // if no workspace was provided we use the scratchpad + char *scratch_ptr = scratchpad.template get(key_rnn_space); + char *ws_ptr = nullptr; + if (rnn.use_workspace) + ws_ptr = rnn.is_fwd + ? CTX_OUT_MEM(char *, MKLDNN_ARG_WORKSPACE) + : const_cast(CTX_IN_MEM(const char *, MKLDNN_ARG_WORKSPACE)); + + char *base_ptr = rnn.use_workspace ? ws_ptr : scratch_ptr; + acc_data_t *ws_gates = (acc_data_t *)(base_ptr + ws_gates_offset_); + src_data_t *ws_states = (src_data_t *)(base_ptr + ws_states_offset_); + float *ws_c_states = (float *)(base_ptr + ws_c_states_offset_); + float *ws_diff_states = (float *)(base_ptr + ws_diff_states_offset_); + float *ws_grid = (float *)(base_ptr + ws_grid_comp_offset_); + float *ws_cell = (float *)(base_ptr + ws_cell_comp_offset_); + + auto diff_src_layer = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC_LAYER); + auto diff_src_iter = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC_ITER); + + auto diff_weights_layer = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS_LAYER); + auto diff_weights_iter = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS_ITER); + auto diff_bias = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_BIAS); + + // Fetching extra buffers from scratchpad + float *ws_bias = (float *)(scratch_ptr + ws_bias_offset_); + + // initialize diff_states to 0 + if (aprop == prop_kind::backward) + array_set(ws_diff_states, 0.0f, rnn.ws_diff_states_size / sizeof(float)); + + /* Pack(if using packed gemm API) or copy(if input arrays have bad leading + * dimension */ + (this->*bias_preparation_func)(rnn, ptr_bias, bias, ws_bias); + + (this->*weights_iter_assign_func)(rnn, pd()->weights_md(1), + rnn.weights_iter_nld, rnn.weights_iter_ld, rnn.dic, + rnn.sic, rnn.n_parts_weights_iter, rnn.parts_weights_iter, + rnn.part_weights_iter_pack_size, ptr_wei_iter, w_iter, + ptr_bias, bias, ws_bias); + (this->*weights_layer_assign_func)(rnn, pd()->weights_md(0), + rnn.weights_layer_nld, rnn.weights_layer_ld, rnn.dic, rnn.slc, + rnn.n_parts_weights_layer, rnn.parts_weights_layer, + rnn.part_weights_layer_pack_size, ptr_wei_layer, w_layer, ptr_bias, + bias, ws_bias); + + (this->*bias_finalization_func)(rnn, ws_bias, w_iter_comp, w_layer_comp); + + // we first need to copy the initial states and input into ws + copy_init_layer(rnn, ws_states, ws_diff_states, input, diff_dst_layer); + if (rnn.dt_conf == f32u8f32u8 || rnn.dt_conf == f32u8f32f32 + || rnn.dt_conf == all_f32) + copy_init_iter(rnn, ws_states, ws_c_states, ws_diff_states, + (const float *)states, diff_dst_iter); + else if (rnn.dt_conf == u8u8u8u8 || rnn.dt_conf == u8u8u8f32) + copy_init_iter(rnn, ws_states, ws_c_states, ws_diff_states, + (const uint8_t *)states, diff_dst_iter); + else + assert(!"unimplemented"); + + // run the execution on the grid + (this->*grid_computation)(rnn, ptr_wei_layer, ptr_wei_iter, ptr_bias, + ws_states, ws_c_states, ws_diff_states, ws_gates, ws_cell, ws_grid, + diff_weights_layer, diff_weights_iter, diff_bias); + + // Finally we copy the results to the result buffers + if (rnn.dt_conf == u8u8u8f32 || rnn.dt_conf == f32u8f32f32 + || rnn.dt_conf == all_f32) + copy_res_layer(rnn, (float *)dst_last_layer, diff_src_layer, ws_states, + ws_diff_states); + else if (rnn.dt_conf == u8u8u8u8 || rnn.dt_conf == f32u8f32u8) + copy_res_layer(rnn, (uint8_t *)dst_last_layer, diff_src_layer, + ws_states, ws_diff_states); + else + assert(!"unimplemented"); + + if (rnn.dt_conf == f32u8f32u8 || rnn.dt_conf == f32u8f32f32 + || rnn.dt_conf == all_f32) + copy_res_iter(rnn, (float *)dst_last_iter, diff_src_iter, ws_states, + ws_c_states, ws_diff_states); + else if (rnn.dt_conf == u8u8u8u8 || rnn.dt_conf == u8u8u8f32) + copy_res_iter(rnn, (uint8_t *)dst_last_iter, diff_src_iter, ws_states, + ws_c_states, ws_diff_states); + else + assert(!"unimplemented"); +}; + +/* Fix for MSVS warning C4661 */ +template<> rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution); +template<> rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution); +template<> rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution); +template<> rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru); +template<> rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru); +template<> rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru); +template<> rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru_lbr); +template<> rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru_lbr); +template<> rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru_lbr); +template<> rnn_elemwise_sig(ref_rnn_fwd_f32_t::rnn_elemwise); +template<> rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::rnn_elemwise); +template<> rnn_elemwise_sig(ref_rnn_bwd_f32_t::rnn_elemwise); +template<> rnn_elemwise_sig(ref_rnn_fwd_f32_t::lstm_elemwise); +template<> rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::lstm_elemwise); +template<> rnn_elemwise_sig(ref_rnn_bwd_f32_t::lstm_elemwise); +template<> rnn_elemwise_sig(ref_rnn_fwd_f32_t::gru_lbr_elemwise); +template<> rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::gru_lbr_elemwise); +template<> rnn_elemwise_sig(ref_rnn_bwd_f32_t::gru_lbr_elemwise); + +template struct _ref_rnn_common_t; +template struct _ref_rnn_common_t; +template struct _ref_rnn_common_t; + +#undef AOC +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp new file mode 100644 index 0000000000..6f449a9016 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp @@ -0,0 +1,328 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_REF_RNN_HPP +#define CPU_REF_RNN_HPP + +#include + +#include "c_types_map.hpp" +#include "memory_tracking.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +#include "../cpu_isa_traits.hpp" +#include "../gemm/os_blas.hpp" + +#include "cpu_rnn_pd.hpp" +#include "../cpu_primitive.hpp" +#include "rnn_utils.hpp" +#include "jit_uni_rnn_postgemm.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +float activation(float s, float alpha, float cliping, float dd); + +template +struct _ref_rnn_common_t : public cpu_primitive_t { + typedef typename prec_traits::type src_data_t; + typedef typename prec_traits::type weights_data_t; + typedef typename utils::conditional::type acc_data_t; + + using class_name = _ref_rnn_common_t; + + typedef rnn_elemwise_sig((class_name::*elemwise_f)); + typedef rnn_cell_execution_sig((class_name::*cell_execution_f)); + typedef rnn_grid_execution_sig((class_name::*grid_execution_f)); + + typedef rnn_gemm_sig((class_name::*gemm_t)); + typedef rnn_bias_prepare_sig((class_name::*bias_prepare_t)); + typedef rnn_bias_finalize_sig((class_name::*bias_finalize_t)); + typedef rnn_weights_assign_sig((class_name::*weights_assign_t)); + + using base_pd_t = + typename utils::conditional::type; + + struct pd_t : public base_pd_t { + using base_pd_t::base_pd_t; + + DECLARE_COMMON_PD_T("ref:any", class_name); + + status_t init() { + using namespace prop_kind; + using namespace utils; + using namespace format_tag; + using namespace rnn_utils; + const alg_kind_t cell_kind = this->desc()->cell_desc.cell_kind; + + data_type_t src_layer_dt = this->desc()->src_layer_desc.data_type; + data_type_t weights_iter_dt + = this->desc()->weights_iter_desc.data_type; + data_type_t weights_layer_dt + = this->desc()->weights_layer_desc.data_type; + + bool ok = true + && one_of(cell_kind, alg_kind::vanilla_rnn, + alg_kind::vanilla_lstm, alg_kind::vanilla_gru, + alg_kind::gru_linear_before_reset) + && IMPLICATION(aprop == prop_kind::forward, + one_of(this->desc()->prop_kind, forward_training, + forward_inference)) + && IMPLICATION(aprop == backward, + one_of(this->desc()->prop_kind, backward)) + && src_layer_dt == src_type + && everyone_is( + weights_type, weights_iter_dt, weights_layer_dt) + && this->set_default_params() == status::success + && this->with_bias(); + if (!ok) + return status::unimplemented; + + init_conf(rnn_, *this->desc(), this->src_md(0), this->src_md(1), + this->weights_md(0), this->weights_md(1), this->dst_md(0)); + + if (rnn_.dt_conf == all_f32) + ok = ok && this->attr()->has_default_values(); + + // Set weights descriptors to desired format + memory_desc_t new_weights_layer_md = *this->weights_md(0); + CHECK(set_expected_desc(rnn_, new_weights_layer_md, false)); + if (this->weights_layer_md_.format_kind == format_kind::any) { + this->weights_layer_md_ = new_weights_layer_md; + } else if (this->weights_layer_md_.format_kind + == format_kind::rnn_packed) { + if (this->weights_layer_md_ != new_weights_layer_md) + return status::unimplemented; + } + + memory_desc_t new_weights_iter_md = *this->weights_md(1); + CHECK(set_expected_desc(rnn_, new_weights_iter_md, true)); + if (this->weights_iter_md_.format_kind == format_kind::any) { + this->weights_iter_md_ = new_weights_iter_md; + } else if (this->weights_iter_md_.format_kind + == format_kind::rnn_packed) { + if (this->weights_iter_md_ != new_weights_iter_md) + return status::unimplemented; + } + + CHECK(this->check_layout_consistency()); + + set_conf(rnn_, *this->desc(), this->weights_md(0), + this->weights_md(1), this->diff_weights_md(0), + this->diff_weights_md(1)); + + size_t scratchpad_sz{0}, ws_sz{0}; + get_scratchpad_and_workspace_sizes(rnn_, scratchpad_sz, ws_sz); + + // initialize the workspace if needed + if (rnn_.is_training) { + dims_t ws_dims = { (int)ws_sz }; + mkldnn_memory_desc_init_by_tag(&this->ws_md_, 1, ws_dims, + data_type::u8, format_tag::x); + } + + init_scratchpad(scratchpad_sz); + + return status::success; + } + + rnn_utils::rnn_conf_t rnn_; + + private: + void init_scratchpad(size_t scratchpad_sz) { + using namespace memory_tracking::names; + auto scratchpad = this->scratchpad_registry().registrar(); + scratchpad.book(key_rnn_space, sizeof(float) * scratchpad_sz, 4096); + + int max_nparts = this->cell_kind() == alg_kind::vanilla_gru ? 2 : 1; + int ptr_wei_sz = rnn_.n_layer * rnn_.n_dir * max_nparts; + scratchpad.book(key_rnn_ptrs_wei_layer, + sizeof(float *) * ptr_wei_sz); + scratchpad.book(key_rnn_ptrs_wei_iter, + sizeof(float *) * ptr_wei_sz); + scratchpad.book(key_rnn_ptrs_bia, + sizeof(float *) * ptr_wei_sz); + } + }; + + _ref_rnn_common_t(const pd_t *apd) + : cpu_primitive_t(apd, true), rnn_postgemm_(nullptr) { + /// @todo set max_feature_size assuming that we limit the number of + /// iterations and layer to one if slc != dic and sic != dic + /// respectively + + bias_preparation_func = &class_name::bias_prepare; + bias_finalization_func = &class_name::bias_finalize; + + auto set_gemm_funcs + = [](bool packed_gemm, gemm_t &g, weights_assign_t &a) { + if (packed_gemm) { + g = &class_name::packed_gemm; + a = &class_name::assign_packed_weights; + } else { + g = &class_name::gemm; + a = &class_name::assign_weights; + } + }; + set_gemm_funcs(pd()->rnn_.use_iter_packed_gemm, gemm_iter_func, + weights_iter_assign_func); + + set_gemm_funcs(pd()->rnn_.use_layer_packed_gemm, gemm_layer_func, + weights_layer_assign_func); + + switch (pd()->cell_kind()) { + case alg_kind::vanilla_lstm: + cell_func = &class_name::cell_execution; + if (aprop == prop_kind::forward) { + if (mayiuse(avx512_core)) + rnn_postgemm_ = new jit_uni_lstm_postgemm_kernel_fwd( + pd()->rnn_, pd()->attr()); + else if (mayiuse(avx2)) + rnn_postgemm_ = new jit_uni_lstm_postgemm_kernel_fwd( + pd()->rnn_, pd()->attr()); + else if (mayiuse(sse42)) + rnn_postgemm_ = new jit_uni_lstm_postgemm_kernel_fwd( + pd()->rnn_, pd()->attr()); + assert(rnn_postgemm_ != nullptr); + rnn_postgemm_->init(); + } + elemwise_func = &class_name::lstm_elemwise; + break; + case alg_kind::vanilla_rnn: // @todo switch on cell kind + cell_func = &class_name::cell_execution; + elemwise_func = &class_name::rnn_elemwise; + switch (pd()->activation_kind()) { + case alg_kind::eltwise_relu: + activation_func = &activation; + break; + case alg_kind::eltwise_tanh: + activation_func = &activation; + break; + case alg_kind::eltwise_logistic: + activation_func = &activation; + break; + default: break; + } + break; + case alg_kind::vanilla_gru: + cell_func = &class_name::cell_execution_gru; + break; + case alg_kind::gru_linear_before_reset: + cell_func = &class_name::cell_execution_gru_lbr; + elemwise_func = &class_name::gru_lbr_elemwise; + break; + default: break; + } + + grid_computation = &class_name::linear_execution; + + size_t scratchpad_size, workspace_size; + rnn_utils::set_offsets(pd()->rnn_, ws_gates_offset_, ws_states_offset_, + ws_c_states_offset_, ws_diff_states_offset_, + ws_grid_comp_offset_, ws_cell_comp_offset_, + ws_bias_offset_, scratchpad_size, workspace_size); + } + + ~_ref_rnn_common_t() {} + + // typedef typename prec_traits::type data_t; + + virtual status_t execute(const exec_ctx_t &ctx) const override { + execute_(ctx); + return status::success; + } + +private: + void execute_(const exec_ctx_t &ctx) const; + rnn_grid_execution_sig(linear_execution); + rnn_cell_execution_sig(cell_execution); + rnn_cell_execution_sig(cell_execution_gru); + rnn_cell_execution_sig(cell_execution_gru_lbr); + rnn_elemwise_sig(rnn_elemwise); + rnn_elemwise_sig(lstm_elemwise); + rnn_elemwise_sig(gru_lbr_elemwise); + rnn_gemm_sig(gemm); + rnn_gemm_sig(packed_gemm); + rnn_bias_prepare_sig(bias_prepare); + rnn_bias_finalize_sig(bias_finalize); + rnn_weights_assign_sig(assign_weights); + rnn_weights_assign_sig(assign_packed_weights); + + float (*activation_func)(float dd, float s, float alpha, float cliping); + + void copy_init_layer(const rnn_utils::rnn_conf_t &rnn, + src_data_t *ws_states_, float *ws_diff_states_, + const src_data_t *xt_, const float *diff_dst_layer) const; + + template + void copy_init_iter(const rnn_utils::rnn_conf_t &rnn, + src_data_t *ws_states_, float *ws_c_states, float *ws_diff_states_, + const input_data_t *firstit_states_, + const float *diff_dst_iter) const; + + template + void copy_res_layer(const rnn_utils::rnn_conf_t &rnn, + dst_data_t *dst_layer_, float *diff_src_layer, + const src_data_t *ws_states_, const float *ws_diff_states_) const; + + template + void copy_res_iter(const rnn_utils::rnn_conf_t &rnn, + output_data_t *dst_iter_, float *diff_src_iter, + const src_data_t *ws_states_, float *ws_c_states, + const float *ws_diff_states_) const; + + void gates_reduction(const rnn_utils::rnn_conf_t &rnn, + const acc_data_t *ws_gates_, float *diff_bias_) const; + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + + size_t ws_gates_offset_; + size_t ws_states_offset_; + size_t ws_c_states_offset_; + size_t ws_bias_offset_; + size_t ws_diff_states_offset_; + size_t ws_grid_comp_offset_; + size_t ws_cell_comp_offset_; + jit_uni_rnn_postgemm_kernel *rnn_postgemm_; + + grid_execution_f grid_computation; + cell_execution_f cell_func; + + bias_prepare_t bias_preparation_func; + bias_finalize_t bias_finalization_func; + weights_assign_t weights_layer_assign_func; + weights_assign_t weights_iter_assign_func; + + gemm_t gemm_layer_func; + gemm_t gemm_iter_func; + elemwise_f elemwise_func; +}; + +using ref_rnn_fwd_f32_t = _ref_rnn_common_t; +using ref_rnn_bwd_f32_t = _ref_rnn_common_t; +using ref_rnn_fwd_u8s8_t = _ref_rnn_common_t; +} +} +} +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp new file mode 100644 index 0000000000..597c63e3f8 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp @@ -0,0 +1,380 @@ +/******************************************************************************* + * Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#ifndef CPU_RNN_REORDERS_HPP +#define CPU_RNN_REORDERS_HPP + +#include + +#include "type_helpers.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" +#include "simple_q10n.hpp" +#include "cpu_reorder_pd.hpp" +#include "../gemm/os_blas.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct rnn_data_reorder_t : public cpu_primitive_t { + struct pd_t : public cpu_reorder_pd_t { + using cpu_reorder_pd_t::cpu_reorder_pd_t; + + DECLARE_COMMON_PD_T("rnn_data_reorder", rnn_data_reorder_t); + + static status_t create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) { + const memory_desc_wrapper id(src_md), od(dst_md); + bool args_ok = true + && id.data_type() == type_i + && od.data_type() == type_o + && id.matches_one_of_tag(format_tag::tnc, format_tag::ldsnc) + && od == id; + if (!args_ok) return status::invalid_arguments; + + auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine, + dst_md); + if (_pd == nullptr) return out_of_memory; + if (_pd->init() != success) { delete _pd; return unimplemented; } + return safe_ptr_assign(*reorder_pd, _pd); + } + }; + +private: + typedef typename prec_traits::type in_data_t; + typedef typename prec_traits::type out_data_t; + + rnn_data_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto input = CTX_IN_MEM(const in_data_t *, MKLDNN_ARG_FROM); + auto output = CTX_OUT_MEM(out_data_t *, MKLDNN_ARG_TO); + const memory_desc_wrapper &input_d = pd()->src_md(); + const memory_desc_wrapper &output_d = pd()->dst_md(); + const size_t nelems = input_d.nelems(); + const float scale = pd()->attr()->rnn_data_qparams_.scale_; + const float shift = pd()->attr()->rnn_data_qparams_.shift_; + + parallel_nd(nelems, [&](size_t i) { + float in = (float)input[input_d.off_l(i)] * scale + shift; + output[output_d.off_l(i)] = qz_a1b0()(in); + }); + + return status::success; + } + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template +struct rnn_weights_reorder_t : public cpu_primitive_t { + struct pd_t : public cpu_reorder_pd_t { + using cpu_reorder_pd_t::cpu_reorder_pd_t; + + DECLARE_COMMON_PD_T("rnn_weights_reorder", rnn_weights_reorder_t); + + static status_t create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) { +#if !USE_MKL_PACKED_GEMM + return status::unimplemented; +#endif + const memory_desc_wrapper id(src_md), od(dst_md); + bool args_ok = true + && id.data_type() == type_i + && od.data_type() == type_o + && od.format_kind() == format_kind::rnn_packed + && od.rnn_packed_desc().format == mkldnn_ldigo_p + && od.rnn_packed_desc().n_parts == 1 + && attr != nullptr; + if (!args_ok) return status::invalid_arguments; + + format_tag_t itag = id.matches_one_of_tag( + format_tag::ldigo, format_tag::ldgoi); + if (itag == format_tag::undef) return status::invalid_arguments; + + const int mask = attr->rnn_weights_qparams_.mask_; + if (!utils::one_of(mask, 0, 3)) return status::unimplemented; + + auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine, + dst_md); + if (_pd == nullptr) return out_of_memory; + _pd->itag_ = itag; + if (_pd->init() != success) { delete _pd; return unimplemented; } + return safe_ptr_assign(*reorder_pd, _pd); + } + + status_t init() { + status_t status = cpu_reorder_pd_t::init(); + if (status != status::success) return status; + + init_scratchpad(); + + return status::success; + } + + format_tag_t itag_; + + private: + void init_scratchpad() { + const memory_desc_wrapper id(src_md()); + const size_t nelems = id.nelems(); + const auto &dims = id.dims(); + + using namespace memory_tracking::names; + auto scratchpad = scratchpad_registry().registrar(); + size_t quantization_size = sizeof(int8_t) * nelems; + size_t reduction_size = itag_ == ldigo + ? sizeof(int32_t) * mkldnn_get_max_threads() * dims[0] + * dims[1] * dims[3] * dims[4] + : 0; + scratchpad.book( + key_reorder_rnn_weights_quantization, quantization_size); + scratchpad.book(key_reorder_rnn_weights_reduction, reduction_size); + } + }; + +private: + typedef typename prec_traits::type in_data_t; + typedef typename prec_traits::type out_data_t; + + rnn_weights_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { +#if USE_MKL_PACKED_GEMM + auto input = CTX_IN_MEM(const in_data_t *, MKLDNN_ARG_FROM); + auto output = CTX_OUT_MEM(char *, MKLDNN_ARG_TO); + const memory_desc_wrapper &input_d = pd()->src_md(); + const memory_desc_wrapper &output_d = pd()->dst_md(); + const auto &dims = input_d.dims(); + + const int L = dims[0]; + const int D = dims[1]; + const int I = dims[2]; + const int G = dims[3]; + const int O = dims[4]; + + const bool is_igo = pd()->itag_ == format_tag::ldigo; + + /* Quantize input & compute compensation */ + auto quantized = (int8_t * __restrict)scratchpad(ctx).template get( + memory_tracking::names::key_reorder_rnn_weights_quantization); + auto reduction = (int32_t * __restrict)scratchpad(ctx).template get( + memory_tracking::names::key_reorder_rnn_weights_reduction); + float *comp = reinterpret_cast( + output + output_d.rnn_packed_desc().offset_compensation); + const float *scales = pd()->attr()->rnn_weights_qparams_.scales_; + const int mask = pd()->attr()->rnn_weights_qparams_.mask_; + + if (is_igo) { + int nthr = mkldnn_get_max_threads(); + int LD_nthr = nstl::min(L * D, nthr); + int I_nthr = nstl::min(I, nthr / LD_nthr); + parallel(nthr, [&](const int ithr, const int nthr) { + int LD_ithr = -1, LD_s = -1, LD_e = -1; + int I_ithr = -1, I_s = -1, I_e = -1; + if (ithr < LD_nthr * I_nthr) { + LD_ithr = ithr % LD_nthr; + I_ithr = ithr / LD_nthr; + balance211(L * D, LD_nthr, LD_ithr, LD_s, LD_e); + balance211(I, I_nthr, I_ithr, I_s, I_e); + } + int32_t *comp_ithr = reduction + I_ithr * L * D * G * O; + for (int ld = LD_s; ld < LD_e; ld++) { + for (int go = 0; go < G * O; go++) + comp_ithr[ld * G * O + go] = 0; + for (int i = I_s; i < I_e; i++) { + PRAGMA_OMP_SIMD() + for (int go = 0; go < G * O; go++) { + const float s = scales[(mask == 0) ? 0 : go]; + int8_t q = qz_b0()( + input[ld * I * G * O + i * G * O + go], s); + quantized[ld * I * G * O + i * G * O + go] + = (int32_t)q; + comp_ithr[ld * G * O + go] += (int32_t)q; + } + } + } + }); + parallel_nd(L * D * G * O, + [&](int s) { comp[s] = saturate(reduction[s]); }); + for (int i = 1; i < I_nthr; i++) { + parallel_nd(L * D * G * O, [&](int s) { + comp[s] += saturate( + reduction[i * L * D * G * O + s]); + }); + } + } else { + parallel_nd(L * D, G * O, [&](int ld, int go) { + int32_t compensation = 0; + const float s = scales[(mask == 0) ? 0 : go]; + PRAGMA_OMP_SIMD() + for (int i = 0; i < I; i++) { + int8_t q = qz_b0()( + input[ld * G * O * I + go * I + i], s); + compensation += (int32_t)q; + quantized[ld * G * O * I + go * I + i] = q; + } + comp[ld * G * O + go] = saturate(compensation); + }); + } + + /* Pack */ + auto off_igo = [&](int l, int d, int i, int g, int o) { + return l * D * I * G * O + d * I * G * O + i * G * O + g * O + o; + }; + auto off_goi = [&](int l, int d, int i, int g, int o) { + return l * D * G * O * I + d * G * O * I + g * O * I + o * I + i; + }; + int n_parts = output_d.rnn_packed_desc().n_parts; + const size_t *size_packed_cell + = output_d.rnn_packed_desc().part_pack_size; + const int *parts = output_d.rnn_packed_desc().parts; + const int n = output_d.rnn_packed_desc().n; + char *to_pack = output; + for (int l = 0; l < L; l++) { + for (int d = 0; d < D; d++) { + for (int p = 0; p < n_parts; p++) { + int g = (p > 0) ? parts[p - 1] : 0; + int m_p = parts[p] * O; + int k_p = I; + cblas_gemm_s8u8s32_pack(CblasColMajor, CblasAMatrix, + is_igo ? CblasNoTrans : CblasTrans, m_p, n, k_p, + &quantized[is_igo ? off_igo(l, d, 0, g, 0) : + off_goi(l, d, g, 0, 0)], + is_igo ? G * O : I, to_pack); + to_pack += size_packed_cell[p]; + } + } + } +#endif + return status::success; + } + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +template <> +struct rnn_weights_reorder_t + : public cpu_primitive_t { + struct pd_t : public cpu_reorder_pd_t { + using cpu_reorder_pd_t::cpu_reorder_pd_t; + + DECLARE_COMMON_PD_T("rnn_weights_reorder", rnn_weights_reorder_t); + + static status_t create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) { +#if !USE_MKL_PACKED_GEMM + return status::unimplemented; +#endif + const memory_desc_wrapper id(src_md), od(dst_md); + bool args_ok = true + && id.data_type() == data_type::f32 + && od.data_type() == data_type::f32 + && od.format_kind() == format_kind::rnn_packed + && utils::one_of(od.rnn_packed_desc().format, + mkldnn_ldigo_p, mkldnn_ldgoi_p) + && attr->has_default_values(); + if (!args_ok) return status::invalid_arguments; + + format_tag_t itag = id.matches_one_of_tag( + format_tag::ldigo, format_tag::ldgoi); + if (itag == format_tag::undef) return status::invalid_arguments; + + const int mask = attr->rnn_weights_qparams_.mask_; + if (!utils::one_of(mask, 0, 3)) return status::unimplemented; + + auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine, + dst_md); + if (_pd == nullptr) return out_of_memory; + if (_pd->init() != success) { delete _pd; return unimplemented; } + _pd->itag_ = itag; + return safe_ptr_assign(*reorder_pd, _pd); + } + + format_tag_t itag_; + }; + +private: + rnn_weights_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { +#if USE_MKL_PACKED_GEMM + auto input = CTX_IN_MEM(const float *, MKLDNN_ARG_FROM); + auto output = CTX_OUT_MEM(float *, MKLDNN_ARG_TO); + const memory_desc_wrapper &input_d = pd()->src_md(); + const memory_desc_wrapper &output_d = pd()->dst_md(); + const auto &dims = input_d.dims(); + const rnn_packed_desc_t &rnn_pdata = output_d.rnn_packed_desc(); + const int L = dims[0]; + const int D = dims[1]; + const int I = dims[2]; + const int G = dims[3]; + const int O = dims[4]; + + /* Pack */ + bool cross_case = false + || (pd()->itag_ == format_tag::ldigo + && rnn_pdata.format == mkldnn_ldgoi_p) + || (pd()->itag_ == format_tag::ldgoi + && rnn_pdata.format == mkldnn_ldigo_p); + auto trans = cross_case ? CblasTrans : CblasNoTrans; + int n_parts = rnn_pdata.n_parts; + const size_t *size_packed_cell = rnn_pdata.part_pack_size; + const int *parts = rnn_pdata.parts; + const int n = rnn_pdata.n; + + const bool is_igo = pd()->itag_ == format_tag::ldigo; + auto off_igo = [&](int l, int d, int i, int g, int o) { + return l * D * I * G * O + d * I * G * O + i * G * O + g * O + o; + }; + auto off_goi = [&](int l, int d, int i, int g, int o) { + return l * D * G * O * I + d * G * O * I + g * O * I + o * I + i; + }; + for (int l = 0; l < L; l++) { + for (int d = 0; d < D; d++) { + for (int p = 0; p < n_parts; p++) { + int g = (p > 0) ? parts[p - 1] : 0; + int m_p = is_igo ? parts[p] * O : I; + int k_p = is_igo ? I : parts[p] * O; + int ld = is_igo ? G * O : I; + cblas_sgemm_pack(CblasColMajor, CblasAMatrix, trans, m_p, n, + k_p, 1.0f, &input[is_igo ? off_igo(l, d, 0, g, 0) : + off_goi(l, d, 0, g, 0)], + ld, output); + output += size_packed_cell[p] / sizeof(float); + } + } + } +#endif + return status::success; + } + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} // namespace cpu +} // namespace impl +} // namespace mkldnn + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp new file mode 100644 index 0000000000..1d60415cbc --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp @@ -0,0 +1,426 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "c_types_map.hpp" +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" + +#include "ref_rnn.hpp" +#include "rnn_utils.hpp" +#include "type_helpers.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::utils; +using namespace rnn_utils; +using namespace format_tag; +using namespace rnn_packed_format; +using namespace data_type; + +bool rnn_utils::is_ldigo(const memory_desc_wrapper &md) { + if (md.format_kind() != format_kind::blocked) + return false; + + auto blk = md.blocking_desc(); + auto str = blk.strides; + auto dims = md.dims(); + return md.ndims() == 5 && blk.inner_nblks == 0 && str[4] == 1 + && str[3] == dims[4] && str[1] == str[2] * dims[2] + && str[0] == str[1] * dims[1]; +}; + +bool rnn_utils::is_ldgoi(const memory_desc_wrapper &md) { + if (md.format_kind() != format_kind::blocked) + return false; + + auto blk = md.blocking_desc(); + auto str = blk.strides; + auto dims = md.dims(); + return md.ndims() == 5 && blk.inner_nblks == 0 && str[2] == 1 + && str[3] == dims[4] * str[4] && str[1] == str[3] * dims[3] + && str[0] == str[1] * dims[1]; +}; + +void rnn_utils::init_conf(rnn_conf_t &rnn, const rnn_desc_t &rd, + const memory_desc_wrapper &src_layer_d, + const memory_desc_wrapper &src_iter_d, + const memory_desc_wrapper &weights_layer_d, + const memory_desc_wrapper &weights_iter_d, + const memory_desc_wrapper &dst_layer_d) { + rnn.is_fwd = utils::one_of(rd.prop_kind, prop_kind::forward_training, + prop_kind::forward_inference); + rnn.is_training = utils::one_of( + rd.prop_kind, prop_kind::forward_training, prop_kind::backward); + rnn.is_lbr = rd.cell_desc.cell_kind == mkldnn_gru_linear_before_reset; + + switch (rd.direction) { + case mkldnn_unidirectional_left2right: rnn.exec_dir = l2r; break; + case mkldnn_unidirectional_right2left: rnn.exec_dir = r2l; break; + case mkldnn_bidirectional_concat: rnn.exec_dir = bi_concat; break; + case mkldnn_bidirectional_sum: rnn.exec_dir = bi_sum; break; + default: break; + } + + if (everyone_is(f32, src_layer_d.data_type(), dst_layer_d.data_type(), + weights_layer_d.data_type())) + rnn.dt_conf = all_f32; + else if (dst_layer_d.data_type() == u8) { + if (IMPLICATION(src_iter_d.md_, src_iter_d.data_type() == u8)) + rnn.dt_conf = u8u8u8u8; + else + rnn.dt_conf = f32u8f32u8; + } else { + if (IMPLICATION(src_iter_d.md_, src_iter_d.data_type() == u8)) + rnn.dt_conf = u8u8u8f32; + else + rnn.dt_conf = f32u8f32f32; + } + + rnn.n_layer = weights_layer_d.dims()[0]; + rnn.n_iter = src_layer_d.dims()[0]; + rnn.n_dir = weights_layer_d.dims()[1]; + rnn.n_gates = weights_layer_d.dims()[3]; + rnn.n_states = mkldnn_rnn_cell_get_states_count(&rd.cell_desc); + rnn.n_bias = rnn.n_gates + rnn.is_lbr; + rnn.mb = src_layer_d.dims()[1]; + rnn.sic = weights_iter_d.dims()[2]; + rnn.slc = weights_layer_d.dims()[2]; + rnn.dic = weights_layer_d.dims()[4]; + rnn.dlc = dst_layer_d.dims()[2]; + + rnn.gates_ld = rnn.dic * rnn.n_gates; + rnn.gates_nld = rnn.mb; + rnn.states_nld = rnn.mb; + + /* Set the correct number of weights parts */ + bool is_orig_gru = rd.cell_desc.cell_kind == alg_kind::vanilla_gru; + rnn.n_parts_weights_layer = 1; + rnn.parts_weights_layer[0] = rnn.n_gates; + rnn.parts_weights_layer[1] = 0; + + rnn.n_parts_weights_iter = is_orig_gru ? 2 : 1; + rnn.parts_weights_iter[0] = is_orig_gru ? 2 : rnn.n_gates; + rnn.parts_weights_iter[1] = is_orig_gru ? 1 : 0; + + rnn.n_parts_bias = 1; + rnn.parts_bias[0] = rnn.n_bias; + rnn.parts_bias[1] = 0; + + /* Decide wich gemm implementation to use: packed/nonpacked jit/cblas + * and if to mergre gemm across iterations */ + bool is_int8 = rnn.dt_conf != all_f32; + rnn.merge_gemm_layer = ((rnn.is_fwd && rnn.mb < 128) || !rnn.is_fwd) + || is_int8; + bool is_gru = utils::one_of(rd.cell_desc.cell_kind, alg_kind::vanilla_gru, + alg_kind::gru_linear_before_reset); + rnn.merge_gemm_iter = !(rnn.is_fwd || is_gru) || is_int8; + bool is_inference = !rnn.is_training; + + rnn.use_jit_gemm = !mayiuse(avx512_mic) + && ((is_inference && (rnn.n_layer > 1 || rnn.mb < 100)) + || (rnn.is_training && rnn.dic < 500)); + + /* Decide to copy bias */ + rnn.copy_bias = rnn.dt_conf != all_f32; + +#if USE_MKL_PACKED_GEMM + rnn.use_layer_packed_gemm + = (weights_layer_d.format_kind() == format_kind::any + && rnn.slc > 760 && rnn.dic > 760 && is_inference) + || is_int8; // packed gemm is the only supported option for int8 + rnn.use_iter_packed_gemm + = (weights_iter_d.format_kind() == format_kind::any && rnn.sic > 760 + && rnn.dic > 760 && is_inference) + || is_int8; +#else + rnn.use_layer_packed_gemm = false; + rnn.use_iter_packed_gemm = false; +#endif + + /* Set packed gemm sizes */ + if (rnn.use_layer_packed_gemm) { + rnn.weights_layer_pack_size = 0; + for (int p = 0; p < rnn.n_parts_weights_layer; p++) { + int m_p = rnn.is_fwd + ? (rnn.parts_weights_layer[p] * rnn.dic) + : rnn.slc; + int k_p = rnn.is_fwd + ? rnn.slc + : (rnn.parts_weights_layer[p] * rnn.dic); + int n_p = rnn.merge_gemm_layer ? rnn.mb * rnn.n_iter : rnn.mb; + +#if USE_MKL_PACKED_GEMM + if (rnn.dt_conf == all_f32) + rnn.part_weights_layer_pack_size[p] = cblas_sgemm_pack_get_size( + CblasAMatrix, m_p, n_p, k_p); + else + rnn.part_weights_layer_pack_size[p] + = cblas_gemm_s8u8s32_pack_get_size( + CblasAMatrix, m_p, n_p, k_p); +#else + UNUSED(m_p); + UNUSED(k_p); + UNUSED(n_p); + rnn.part_weights_layer_pack_size[p] = 0; +#endif + rnn.weights_layer_pack_size += rnn.n_layer * rnn.n_dir + * rnn.part_weights_layer_pack_size[p]; + } + rnn.weights_layer_comp_offset = rnn.weights_layer_pack_size; + rnn.weights_layer_pack_size += rnn.dt_conf == all_f32 ? 0 : rnn.n_layer + * rnn.n_dir * rnn.n_gates * rnn.dlc * sizeof(float); + } + + if (rnn.use_iter_packed_gemm) { + rnn.weights_iter_pack_size = 0; + for (int p = 0; p < rnn.n_parts_weights_iter; p++) { + int m_p = rnn.is_fwd ? (rnn.parts_weights_iter[p] * rnn.dic) : + rnn.sic; + int k_p = rnn.is_fwd ? rnn.sic : + (rnn.parts_weights_iter[p] * rnn.dic); + int n_p = rnn.merge_gemm_iter ? rnn.mb * rnn.n_iter : rnn.mb; + +#if USE_MKL_PACKED_GEMM + if (rnn.dt_conf == all_f32) + rnn.part_weights_iter_pack_size[p] = cblas_sgemm_pack_get_size( + CblasAMatrix, m_p, n_p, k_p); + else + rnn.part_weights_iter_pack_size[p] + = cblas_gemm_s8u8s32_pack_get_size( + CblasAMatrix, m_p, n_p, k_p); +#else + UNUSED(m_p); + UNUSED(k_p); + UNUSED(n_p); + rnn.part_weights_iter_pack_size[p] = 0; +#endif + rnn.weights_iter_pack_size += rnn.n_layer * rnn.n_dir + * rnn.part_weights_iter_pack_size[p]; + } + rnn.weights_iter_comp_offset = rnn.weights_iter_pack_size; + rnn.weights_iter_pack_size += rnn.dt_conf == all_f32 ? 0 : rnn.n_layer + * rnn.n_dir * rnn.n_gates * rnn.dic * sizeof(float); + } + +} + +void rnn_utils::set_conf(rnn_conf_t &rnn, const rnn_desc_t &rd, + const memory_desc_wrapper &weights_layer_d, + const memory_desc_wrapper &weights_iter_d, + const memory_desc_wrapper &diff_weights_layer_d, + const memory_desc_wrapper &diff_weights_iter_d) { + + /* Set leading dimensions for input weights arrays depending on input format + */ + rnn.weights_layer_is_packed + = weights_layer_d.format_kind() == format_kind::rnn_packed; + rnn.weights_iter_is_packed + = weights_iter_d.format_kind() == format_kind::rnn_packed; + + auto set_dims = [&](const memory_desc_wrapper &md, int &ld, int &nld) { + ld = 0; nld = 0; + if (md.is_blocking_desc()) { + if (is_ldigo(md)) { + ld = (int)md.blocking_desc().strides[2]; + nld = md.dims()[2]; + } else if (is_ldgoi(md)) { + ld = (int)md.blocking_desc().strides[4]; + nld = md.dims()[3] * md.dims()[4]; + } else + assert(!"unsupported weights format"); + } + }; + set_dims(weights_layer_d, rnn.weights_layer_ld, rnn.weights_layer_nld); + set_dims(weights_iter_d, rnn.weights_iter_ld, rnn.weights_iter_nld); + if (!rnn.is_fwd) { + set_dims(diff_weights_layer_d, rnn.diff_weights_layer_ld, + rnn.diff_weights_layer_nld); + set_dims(diff_weights_iter_d, rnn.diff_weights_iter_ld, + rnn.diff_weights_iter_nld); + } + + int sizeof_states_dt + = rnn.dt_conf == all_f32 ? sizeof(float) : sizeof(uint8_t); + rnn.states_ws_ld + = get_good_ld(nstl::max(rnn.slc, nstl::max(rnn.sic, rnn.dic)), + sizeof_states_dt); + rnn.gates_ws_ld = get_good_ld(rnn.gates_ld, sizeof(float)); + + /* Set workspace sizes to store: + * states to copmute a pass + * diff states to copmute bwd pass (training only) + * intermediate results from the gates + */ + rnn.use_workspace = rnn.is_training; + rnn.ws_states_size = (size_t)(rnn.n_layer + 1) * rnn.n_dir + * (rnn.n_iter + 1) * rnn.mb * rnn.states_ws_ld * sizeof_states_dt; + bool is_lstm = rd.cell_desc.cell_kind == mkldnn_vanilla_lstm; + rnn.ws_c_states_size = is_lstm + ? (size_t)(rnn.n_layer + 1) * rnn.n_dir * (rnn.n_iter + 1) * rnn.mb + * rnn.states_ws_ld * sizeof(float) + : 0; + rnn.ws_diff_states_size = rnn.is_training + ? (size_t)(rnn.n_layer + 1) * rnn.n_dir * (rnn.n_iter + 1) + * (rnn.n_states + 1) * rnn.mb * rnn.states_ws_ld + * sizeof(float) + : (size_t)0; + rnn.ws_gates_size = (size_t)rnn.n_layer * rnn.n_dir * rnn.n_iter * rnn.mb + * rnn.gates_ws_ld * sizeof(float); + + /* set other sizes */ + rnn.ws_per_cell = (size_t)rnn.is_lbr * rnn.mb * rnn.dic * sizeof(float); + rnn.ws_cell_comp_size + = rnn.is_lbr || rnn.dt_conf != all_f32 + ? (size_t) rnn.gates_nld * rnn.gates_ws_ld * sizeof(float) + : 0; + rnn.ws_grid_comp_size = (size_t)rnn.is_lbr * rnn.is_training * rnn.n_layer + * rnn.n_dir * rnn.n_iter * rnn.ws_per_cell * sizeof(float); + rnn.ws_bias_size = (size_t)rnn.n_layer * rnn.n_dir * rnn.n_bias * rnn.dic + * sizeof(float); +} + +int rnn_utils::get_good_ld(int dim, int sizeof_dt) { + // we want matrices leading dimentions to be 64-byte aligned, + // and not divisible by 256 to avoid 4K aliasing effects + int ld = rnd_up(dim, 64 / sizeof_dt); + return (ld % 256 == 0) ? ld + 64 / sizeof_dt : ld; +} + +void rnn_utils::set_offsets(const rnn_conf_t &rnn, size_t &ws_gates_offset, + size_t &ws_states_offset, size_t &ws_c_states_offset, + size_t &ws_diff_states_offset, size_t &ws_grid_comp_offset, + size_t &ws_cell_comp_offset, size_t &ws_bias_offset, + size_t &scratchpad_size, size_t &workspace_size) { + + const size_t page_size = 4096; // 2097152; + size_t current_offset; + /* Mandatory workspaces: go to workspace if use_workspace, scratchpad + * otherwise */ + current_offset = 0; // assumes the workspace base pointer is page aligned + ws_gates_offset = current_offset; + current_offset += rnn.ws_gates_size; + + current_offset = utils::rnd_up(current_offset, page_size); + ws_states_offset = current_offset; + current_offset += rnn.ws_states_size; + + current_offset = utils::rnd_up(current_offset, page_size); + ws_c_states_offset = current_offset; + current_offset += rnn.ws_c_states_size; + + current_offset = utils::rnd_up(current_offset, page_size); + ws_diff_states_offset = current_offset; + current_offset += rnn.ws_diff_states_size; + + current_offset = utils::rnd_up(current_offset, page_size); + ws_grid_comp_offset = current_offset; + current_offset += rnn.ws_grid_comp_size; + + current_offset = utils::rnd_up(current_offset, page_size); + ws_cell_comp_offset = current_offset; + current_offset += rnn.ws_cell_comp_size; + + workspace_size = rnn.use_workspace ? current_offset : 0; + + /* Optional scratchpads */ + // Assumes the scratchpad base pointer is page aligned. + // If use_workspace, the following goes to scratchpad alone, + // otherwise, all goes to scratchpad and continue incrementing offset + current_offset = rnn.use_workspace ? 0 : current_offset; + + if (rnn.copy_bias) { + current_offset = utils::rnd_up(current_offset, page_size); + ws_bias_offset = current_offset; + current_offset += rnn.ws_bias_size; + } + + scratchpad_size = current_offset; +} + +void rnn_utils::get_scratchpad_and_workspace_sizes(const rnn_conf_t &rnn, + size_t &scratchpad_size, size_t &workspace_size) { + size_t ws_gates_offset, ws_states_offset, ws_c_states_offset, + ws_diff_states_offset, ws_grid_comp_offset, ws_cell_comp_offset, + ws_bias_offset; + set_offsets(rnn, ws_gates_offset, ws_states_offset, ws_diff_states_offset, + ws_c_states_offset, ws_grid_comp_offset, ws_cell_comp_offset, + ws_bias_offset, scratchpad_size, workspace_size); +} + +status_t rnn_utils::set_good_strides( + memory_desc_t &weights_md, format_tag_t tag) { + auto &strides = weights_md.format_desc.blocking.strides; + auto dims = weights_md.dims; + + if (tag == ldigo) { + strides[2] = rnn_utils::get_good_ld((int)strides[2], + (int)types::data_type_size(weights_md.data_type)); + strides[1] = dims[2] * strides[2]; + strides[0] = dims[1] * strides[1]; + } else if (tag == ldgoi) { + strides[4] = rnn_utils::get_good_ld((int)strides[4], + (int)types::data_type_size(weights_md.data_type)); + strides[3] = dims[4] * strides[4]; + strides[1] = dims[3] * strides[3]; + strides[0] = dims[1] * strides[1]; + } else + return status::unimplemented; + + return status::success; +} + +status_t rnn_utils::set_expected_desc(rnn_conf_t &rnn, + memory_desc_t &weights_md, bool is_iter) { + using namespace format_tag; + bool use_packed_gemm = is_iter + ? rnn.use_iter_packed_gemm + : rnn.use_layer_packed_gemm; + if (use_packed_gemm) { + weights_md.format_kind = format_kind::rnn_packed; + rnn_packed_desc_t &rnn_pdata = weights_md.format_desc.rnn_packed_desc; + rnn_pdata.format = rnn.is_fwd ? mkldnn_ldigo_p : mkldnn_ldgoi_p; + if (is_iter) { + rnn_pdata.n = rnn.mb; + rnn_pdata.n_parts = rnn.n_parts_weights_iter; + array_copy(rnn_pdata.parts, rnn.parts_weights_iter, + MKLDNN_RNN_MAX_N_PARTS); + array_copy(rnn_pdata.part_pack_size, + rnn.part_weights_iter_pack_size, MKLDNN_RNN_MAX_N_PARTS); + rnn_pdata.offset_compensation = rnn.weights_iter_comp_offset; + rnn_pdata.size = rnn.weights_iter_pack_size; + } else { + rnn_pdata.n = rnn.merge_gemm_layer ? rnn.n_iter * rnn.mb : rnn.mb; + rnn_pdata.n_parts = rnn.n_parts_weights_layer; + array_copy(rnn_pdata.parts, rnn.parts_weights_layer, + MKLDNN_RNN_MAX_N_PARTS); + array_copy(rnn_pdata.part_pack_size, + rnn.part_weights_layer_pack_size, MKLDNN_RNN_MAX_N_PARTS); + rnn_pdata.offset_compensation = rnn.weights_layer_comp_offset; + rnn_pdata.size = rnn.weights_layer_pack_size; + } + } else { + CHECK(memory_desc_init_by_tag(weights_md, rnn.is_fwd ? ldigo : ldgoi)); + // Adjust strides for good leading dimension in GEMM + CHECK(set_good_strides(weights_md, rnn.is_fwd ? ldigo : ldgoi)); + } + return status::success; +} + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp new file mode 100644 index 0000000000..99eb787a64 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp @@ -0,0 +1,225 @@ +/******************************************************************************* +* Copyright 2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef RNN_UTILS_HPP +#define RNN_UTILS_HPP + +#include "mkldnn.h" + +#include "cpu_rnn_pd.hpp" + + +#define rnn_elemwise_sig(f) \ + void f(const rnn_utils::rnn_conf_t &rnn, acc_data_t *ws_gates_, \ + src_data_t *states_t_l_, float *c_states_t_l_, \ + src_data_t *states_tm1_l_, float *c_states_tm1_l_, \ + float *diff_states_t_l_, float *diff_states_t_lp1_, \ + float *diff_states_tp1_l_, float *bias_, float *ws_grid_, \ + float *ws_cell_) const + +#define rnn_cell_execution_sig(f) \ + void f(const rnn_utils::rnn_conf_t &rnn, src_data_t *states_t_l_, \ + float *c_states_t_l_, float *diff_states_t_l_, \ + weights_data_t **w_layer_, weights_data_t **w_iter_, \ + float **bias_, src_data_t *states_t_lm1_, \ + src_data_t *states_tm1_l_, float *c_states_tm1_l_, \ + float *diff_states_t_lp1_, float *diff_states_tp1_l_, \ + float *diff_w_layer_, float *diff_w_iter_, float *diff_bias_, \ + acc_data_t *ws_gates_, float *ws_grid_, float *ws_cell_) const + +#define rnn_grid_execution_sig(f) \ + void f(const rnn_utils::rnn_conf_t &rnn, weights_data_t **weights_layer_, \ + weights_data_t **weights_states_, float **bias_, \ + src_data_t *ws_states_, float *ws_c_states_, \ + float *ws_diff_states_, acc_data_t *ws_gates_, float *ws_cell_, \ + float *ws_grid_, float *diff_weights_layer_, \ + float *diff_weights_iter_, float *diff_bias_) const + +#define rnn_gemm_sig(f) \ + void f(const char transA, const char transB, int m, int n, int k, \ + const float alpha, const weights_data_t *a_, const int ldA, \ + const src_data_t *b_, const int ldB, const float beta, \ + acc_data_t *c_, const int ldC) const + +#define rnn_bias_prepare_sig(f) \ + void f(const rnn_utils::rnn_conf_t &rnn, float **bias_, const float *b_, \ + float *scratch_bias_) const + +#define rnn_bias_finalize_sig(f) \ + void f(const rnn_utils::rnn_conf_t &rnn, float *scratch_bias_, \ + const float *w_iter_comp, const float *w_layer_comp) const + +#define rnn_weights_assign_sig(f) \ + void f(const rnn_utils::rnn_conf_t &rnn, const memory_desc_t *md, int nld, \ + int ld, int OC_size, int IC_size, const int n_parts, \ + const int *gates_per_part, const size_t *part_weights_pack_size, \ + weights_data_t **weights_, const weights_data_t *w_, \ + float **bias_, const float *b_, float *scratch_bias_) const + + +namespace mkldnn { +namespace impl { +namespace cpu { + +namespace rnn_utils { + +using namespace mkldnn::impl::utils; + +enum execution_direction_t { + l2r, + r2l, + bi_concat, + bi_sum, +}; + +enum data_type_conf_t { + all_f32, + u8u8u8f32, + f32u8f32f32, + u8u8u8u8, + f32u8f32u8 +}; + +struct rnn_conf_t { + execution_direction_t exec_dir; + data_type_conf_t dt_conf; + int n_layer, n_iter, n_dir, n_gates, n_states; + int mb; + int slc, sic, dic, dlc; + int gates_ld, gates_nld, gates_ws_ld; + int n_parts_weights_layer, parts_weights_layer[MKLDNN_RNN_MAX_N_PARTS]; + int n_parts_weights_iter, parts_weights_iter[MKLDNN_RNN_MAX_N_PARTS]; + int n_bias, n_parts_bias, parts_bias[MKLDNN_RNN_MAX_N_PARTS]; + size_t part_weights_iter_pack_size[MKLDNN_RNN_MAX_N_PARTS], + part_weights_layer_pack_size[MKLDNN_RNN_MAX_N_PARTS]; + bool weights_layer_is_packed, weights_iter_is_packed; + /* Size of packed data in bytes */ + size_t weights_layer_comp_offset, weights_layer_pack_size, + weights_iter_comp_offset, weights_iter_pack_size; + + bool copy_bias; + int weights_layer_ld, weights_layer_nld; + int diff_weights_layer_ld, diff_weights_layer_nld; + int weights_iter_ld, weights_iter_nld; + int diff_weights_iter_ld, diff_weights_iter_nld; + int states_nld, states_ws_ld; + int weights_iter_compensation_size, weights_layer_compensation_size; + bool is_fwd, is_training, is_lbr; + bool use_workspace; + + /* Size of workspace for each tensor in bytes */ + size_t ws_gates_size, ws_states_size, ws_c_states_size, ws_diff_states_size, + ws_cell_comp_size, ws_grid_comp_size, ws_per_cell, ws_bias_size; + bool merge_gemm_iter, merge_gemm_layer, use_jit_gemm, use_layer_packed_gemm, + use_iter_packed_gemm; +}; + +bool is_ldigo(const memory_desc_wrapper &md); +bool is_ldgoi(const memory_desc_wrapper &md); + +int get_good_ld(int dim, int sizeof_dt); + +void init_conf(rnn_conf_t &rnn, const rnn_desc_t &rd, + const memory_desc_wrapper &src_layer_d, + const memory_desc_wrapper &src_iter_d, + const memory_desc_wrapper &weights_layer_d, + const memory_desc_wrapper &weights_iter_d, + const memory_desc_wrapper &dst_layer_d); + +void set_conf(rnn_conf_t &rnn, const rnn_desc_t &rd, + const memory_desc_wrapper &weights_layer_d, + const memory_desc_wrapper &weights_iter_d, + const memory_desc_wrapper &diff_weights_layer_d, + const memory_desc_wrapper &diff_weights_iter_d); + +void set_offsets(const rnn_conf_t &rnn, size_t &ws_gates_offset, + size_t &ws_h_state_offset, size_t &ws_c_state_offset, + size_t &ws_diff_states_offset, size_t &ws_grid_comp_offset, + size_t &ws_cell_comp_offset, size_t &ws_bias_offset, + size_t &scratchpad_size, size_t &workspace_size); + +void get_scratchpad_and_workspace_sizes(const rnn_conf_t &rnn, + size_t &scratchpad_size, size_t &workspace_size); +status_t set_expected_desc( + rnn_conf_t &rnn, memory_desc_t &weights_md, bool is_iter); +status_t set_good_strides(memory_desc_t &weights_md, format_tag_t tag); + +template +struct ws_gates_aoc { + ws_gates_aoc(const rnn_conf_t &rnn, T *data) + : gates_(data, rnn.gates_nld, rnn.gates_ws_ld), DIC_(rnn.dic) {} + T &operator()(int batch, int gate, int dic) { + return gates_(batch, gate * DIC_ + dic); + } + +private: + mkldnn::impl::utils::array_offset_calculator gates_; + int DIC_; +}; +using ws_gates_aoc_t = ws_gates_aoc; +using ws_gates_aoc_s32_t = ws_gates_aoc; + +struct bias_aoc_t { + bias_aoc_t(const rnn_conf_t &rnn, const float *data) + : bias_(data, rnn.n_bias, rnn.dic) {} + const float &operator()(int bias_n, int dic) { return bias_(bias_n, dic); } + +private: + mkldnn::impl::utils::array_offset_calculator bias_; +}; + +template +struct ws_states_aoc { + ws_states_aoc(const rnn_conf_t &rnn, T *data) + : state_(data, rnn.states_nld, rnn.states_ws_ld) {} + T &operator()(int batch, int dic) { return state_(batch, dic); } + +private: + mkldnn::impl::utils::array_offset_calculator state_; +}; +using ws_states_aoc_t = ws_states_aoc; +using ws_states_aoc_u8_t = ws_states_aoc; + +struct ws_diff_states_aoc_t { + ws_diff_states_aoc_t(const rnn_conf_t &rnn, float *data) + : diff_states_(data, rnn.n_states + 1, rnn.n_iter + 1, rnn.states_nld, + rnn.states_ws_ld) {} + float &operator()(int state_n, int batch, int dic) { + return diff_states_(state_n, 0, batch, dic); + } + +private: + mkldnn::impl::utils::array_offset_calculator diff_states_; +}; + +struct ws_diff_w_iter_aoc_t { + ws_diff_w_iter_aoc_t(const rnn_conf_t &rnn, float *data) + : diff_weights_iter_( + data, rnn.diff_weights_iter_nld, rnn.diff_weights_iter_ld) + , DIC_(rnn.dic) {} + float &operator()(int sic, int gate, int dic) { + return diff_weights_iter_(sic, gate * DIC_ + dic); + } + +private: + mkldnn::impl::utils::array_offset_calculator diff_weights_iter_; + int DIC_; +}; +} +} +} +} +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp new file mode 100644 index 0000000000..0420f87aa5 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp @@ -0,0 +1,126 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_thread.hpp" + +#include "simple_concat.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace memory_tracking::names; + +template +status_t simple_concat_t::execute(const exec_ctx_t &ctx) const { + auto scratchpad = this->scratchpad(ctx); + auto iptrs = scratchpad.template get(key_concat_iptrs); + auto optrs = scratchpad.template get(key_concat_optrs); + auto nelems_to_copy = scratchpad.template get(key_concat_nelems); + auto is = scratchpad.template get(key_concat_istrides); + + const int num_arrs = pd()->n_inputs(); + const int *perm = pd()->perm_, *iperm = pd()->iperm_; + const int concat_dim = pd()->concat_dim(); + auto o_base_ptr = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + for (int a = 0; a < num_arrs; ++a) { + const memory_desc_wrapper i_d(pd()->src_md(a)); + const memory_desc_wrapper o_d(pd()->src_image_md(a)); + + iptrs[a] = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MULTIPLE_SRC + a) + + i_d.blk_off(0); + optrs[a] = o_base_ptr + o_d.blk_off(0); + nelems_to_copy[a] = pd()->nelems_to_concat(i_d); + for (int i = 0; i < MKLDNN_MAX_NDIMS; i++) { + if (i < perm[concat_dim]) + is[a][i] = size_t(i_d.blocking_desc().strides[iperm[i]]); + else + is[a][i] = 0; + } + } + + const memory_desc_wrapper o_d(pd()->src_image_md(0)); + + strides_t os = { 0 }; + for (int i = 0; i < perm[concat_dim]; i++) + os[i] = o_d.blocking_desc().strides[iperm[i]]; + + dims_t phys_dims; + for (size_t i = 0; i < sizeof(phys_dims)/sizeof(phys_dims[0]); i++) + phys_dims[i] = (i < (size_t)perm[concat_dim]) + ? o_d.dims()[iperm[i]] / pd()->blocks_[iperm[i]] : 1; + + if (perm[concat_dim] == 0) { + for (int a = 0; a < num_arrs; ++a) { + const data_t *i = &iptrs[a][0]; + data_t *o = &optrs[a][0]; + parallel_nd((ptrdiff_t)nelems_to_copy[a], + [&](ptrdiff_t e) { o[e] = i[e]; }); + } + } else { + parallel_nd(phys_dims[0], phys_dims[1], phys_dims[2], phys_dims[3], + phys_dims[4], num_arrs, + [&](dim_t n0, dim_t n1, dim_t n2, dim_t n3, dim_t n4, int a) { + // XXX: this code may access uninitialized values in is[*][0-4] -- + // that's why we have to set them to zero although this is + // probably benign + size_t in_off = is[a][0] * n0 + is[a][1] * n1 + is[a][2] * n2 + + is[a][3] * n3 + is[a][4] * n4; + size_t out_off = os[0] * n0 + os[1] * n1 + os[2] * n2 + + os[3] * n3 + os[4] * n4; + const data_t *i = &iptrs[a][in_off]; + data_t *o = &optrs[a][out_off]; +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) + // The code below performs data copying: o[e] = i[e] + // and uses a workaround to make GNU compilers optimize it + uint8_t *ptro = reinterpret_cast(o); + const uint8_t *ptri = reinterpret_cast(i); + const dim_t main_part = + nelems_to_copy[a] * sizeof(data_t) / sizeof(uint32_t); + const dim_t tail_part = + nelems_to_copy[a] % sizeof(data_t) / sizeof(uint32_t); + + PRAGMA_OMP_SIMD() + for (dim_t e = 0; e < main_part; ++e) { + *(reinterpret_cast(ptro)) + = *(reinterpret_cast(ptri)); + ptro += sizeof(uint32_t); + ptri += sizeof(uint32_t); + } + for (dim_t e = 0; e < tail_part; ++e) { + *ptro = *ptri; + ++ptro; + ++ptri; + } +#else + PRAGMA_OMP_SIMD() + for (dim_t e = 0; e < nelems_to_copy[a]; ++e) o[e] = i[e]; +#endif + }); + } + + return status::success; +} + +template struct simple_concat_t; +template struct simple_concat_t; +template struct simple_concat_t; +template struct simple_concat_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp new file mode 100644 index 0000000000..5177275452 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp @@ -0,0 +1,155 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef SIMPLE_CONCAT_HPP +#define SIMPLE_CONCAT_HPP + +#include "memory_tracking.hpp" + +#include "cpu_concat_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct simple_concat_t: public cpu_primitive_t { + struct pd_t: public cpu_concat_pd_t { + using cpu_concat_pd_t::cpu_concat_pd_t; + + pd_t(const pd_t &rhs): cpu_concat_pd_t(rhs) { + int ndims = rhs.dst_md_.ndims; + utils::array_copy(perm_, rhs.perm_, ndims); + utils::array_copy(iperm_, rhs.iperm_, ndims); + utils::array_copy(blocks_, rhs.blocks_, ndims); + } + + DECLARE_CONCAT_PD_T("simple:any", simple_concat_t); + + status_t init() { + const memory_desc_wrapper dst_d(dst_md()); + bool ok = true + && cpu_concat_pd_t::init() == status::success + && dst_d.ndims() <= 6; + if (!ok) return status::unimplemented; + + for (size_t i = 0; i < src_mds_.size(); ++i) { + const memory_desc_wrapper i_d(&src_mds_[i]); + const memory_desc_wrapper o_d(&src_image_mds_[i]); + + const int ignore_strides = 0; + + ok = ok + && utils::everyone_is(data_type, i_d.data_type(), + o_d.data_type()) + && utils::everyone_is(format_kind::blocked, + i_d.format_kind(), o_d.format_kind()) + && types::blocking_desc_is_equal(i_d.blocking_desc(), + o_d.blocking_desc(), ignore_strides) + && types::blocking_desc_is_equal(i_d.blocking_desc(), + dst_d.blocking_desc(), ignore_strides) + && !i_d.is_additional_buffer(); + if (!ok) return status::unimplemented; + } + + dst_d.compute_blocks(blocks_); + format_perm(); + + // start dim is the first dimension after which the concatenation + // would happen contiguously + const int start_dim = perm_[concat_dim()]; + + // check that contiguous part is indeed contiguous (i.e. dense) + if (nelems_to_concat(dst_d) != + dst_d.padded_dims()[concat_dim()] / blocks_[concat_dim()] + * dst_d.blocking_desc().strides[concat_dim()]) + return status::unimplemented; + + // check that all inputs have the same strides for the + // contiguous part [concat_dim .. ndims] for the *major* dims. + // the block part is already checked above + for (size_t i = 0; i < src_mds_.size(); ++i) { + const memory_desc_wrapper i_d(&src_mds_[i]); + for (int d = start_dim; d < dst_d.ndims(); ++d) { + if (dst_d.blocking_desc().strides[iperm_[d]] + != i_d.blocking_desc().strides[iperm_[d]]) + return status::unimplemented; + } + } + + init_scratchpad(); + + return status::success; + } + + int perm_[MKLDNN_MAX_NDIMS]; + int iperm_[MKLDNN_MAX_NDIMS]; + dims_t blocks_; + + dim_t nelems_to_concat(const memory_desc_wrapper &data_d) const { + const int ndims = data_d.ndims(); + + dim_t nelems = 1; + for (int i = perm_[concat_dim()]; i < ndims; i++) + nelems *= data_d.dims()[iperm_[i]] / blocks_[iperm_[i]]; + for (int i = 0; i < ndims; i++) + nelems *= blocks_[i]; + + return nelems; + } + + private: + void format_perm() { + const memory_desc_wrapper dst_d(dst_md()); + const int ndims = dst_d.ndims(); + + strides_t strides; + utils::array_copy(strides, dst_d.blocking_desc().strides, ndims); + for (int i = 0; i < ndims; i++) iperm_[i] = i; + + utils::simultaneous_sort(strides, iperm_, ndims, + [](stride_t a, stride_t b) { return b - a; }); + + for (int i = 0; i < ndims; i++) perm_[iperm_[i]] = i; + } + + void init_scratchpad() { + using namespace memory_tracking::names; + auto scratchpad = scratchpad_registry().registrar(); + scratchpad.book(key_concat_iptrs, sizeof(data_t *) * n_inputs()); + scratchpad.book(key_concat_optrs, sizeof(data_t *) * n_inputs()); + scratchpad.book(key_concat_nelems, sizeof(dim_t) * n_inputs()); + scratchpad.book(key_concat_istrides, + sizeof(strides_t) * n_inputs()); + } + }; + + simple_concat_t(const pd_t *apd): cpu_primitive_t(apd) {} + + virtual status_t execute(const exec_ctx_t &ctx) const override; + + typedef typename prec_traits::type data_t; + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp new file mode 100644 index 0000000000..e6c3b8d7af --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp @@ -0,0 +1,98 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_SIMPLE_Q10N_HPP +#define CPU_SIMPLE_Q10N_HPP + +#include + +#include "c_types_map.hpp" +#include "math_utils.hpp" +#include "nstl.hpp" +#include "type_helpers.hpp" +#include "utils.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::math; + +template +inline out_t round_and_saturate(float f) +{ return math::saturate(out_round(f)); } + +/* Quantization with alpha == 1 and beta == 0 */ +template +struct qz_a1b0 { + out_t operator()(in_t in) + { return round_and_saturate((float)in); } +}; + +template +struct qz_a1b0::value + && !is_subset::value + >::type> { + out_t operator()(in_t in) { return math::saturate(in); } +}; + +template +struct qz_a1b0::value>::type> { + out_t operator()(in_t in) { return (out_t)in; } +}; + +/* Quantization with alpha == 1 */ +template struct qz_a1 { + out_t operator()(in_t in, out_t out, float beta) + { return round_and_saturate((float)in + beta * out); } +}; + +template struct qz_a1 { + float operator()(in_t in, float out, float beta) + { return (float)in + beta * out; } +}; + +/* Quantization with beta == 0 */ +template struct qz_b0 { + out_t operator()(in_t in, float alpha) + { return round_and_saturate(alpha * in); } +}; + +template struct qz_b0 { + float operator()(in_t in, float alpha) { return alpha * in; } +}; + +/* Quantization */ +template struct qz { + out_t operator()(in_t in, out_t out, float alpha, float beta) { + return round_and_saturate( + alpha * in + (beta ? beta * out : 0)); + } +}; + +template struct qz { + float operator()(in_t in, float out, float alpha, float beta) + { return alpha * in + (beta ? beta * out : 0); } +}; + +} +} +} + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp new file mode 100644 index 0000000000..ff845f5bd3 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp @@ -0,0 +1,1022 @@ +/******************************************************************************* +* Copyright 2016-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CPU_SIMPLE_REORDER_HPP +#define CPU_SIMPLE_REORDER_HPP + +#include + +#include "c_types_map.hpp" +#include "type_helpers.hpp" +#include "math_utils.hpp" +#include "mkldnn_thread.hpp" +#include "utils.hpp" + +#include "tag_traits.hpp" +#include "cpu_reorder_pd.hpp" +#include "cpu_primitive.hpp" + +#include "simple_q10n.hpp" +#include "cpu_isa_traits.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +using namespace mkldnn::impl::status; +using namespace mkldnn::impl::format_tag; +using namespace mkldnn::impl::data_type; + +using bd = block_dim_t; +using ib = inner_blk_t; + +using namespace mkldnn::impl::utils; +using math::saturate; + +template +using data_t = typename prec_traits::type; + +template +using _qz_a1b0 = qz_a1b0, data_t>; + +template +using _qz = qz, data_t>; + +namespace fmt_order { + const bool keep = true; + const bool reverse = false; + const bool any = keep; +} + +namespace spec { +struct direct_copy {}; +struct direct_copy_except_dim_0 {}; +struct reference {}; +struct conv_s8s8 {}; +} + +#define SIMPLE_REORDER_TEMPL_DECL \ + impl::data_type_t type_i, impl::format_tag_t tag_i, \ + impl::data_type_t type_o, impl::format_tag_t tag_o, bool order_keep +#define SIMPLE_REORDER_TEMPL_CALL \ + type_i, tag_i, type_o, tag_o, order_keep + +#define DECLARE_COMMON_PARAMS() \ + const memory_desc_wrapper &input_d = pd->src_md(); \ + const memory_desc_wrapper &output_d = pd->dst_md(); \ + const float alpha = pd->alpha(); MAYBE_UNUSED(alpha); \ + const float beta = pd->beta(); MAYBE_UNUSED(beta); + +/* specific reorders: common template */ +template +struct simple_reorder_impl {}; + +namespace { +inline bool simple_fmt_check(bool order_keep, impl::format_tag_t tag_i, + impl::format_tag_t tag_o, const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d) { + return input_d.matches_tag(order_keep ? tag_i : tag_o) + && output_d.matches_tag(order_keep ? tag_o : tag_i); +} +inline bool simple_attr_check(const primitive_attr_t *attr, bool many_scales_support) { + if (many_scales_support) + return true; + return IMPLICATION(attr, attr->output_scales_.mask_ == 0); +} +} + +/* specific reorders: implementation */ +template +struct simple_reorder_impl::type> +{ + static bool is_applicable(const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) + { + const size_t D_mask = utils::array_product(input_d.dims(), + math::ilog2q(attr->output_scales_.mask_ + 1)); + const int oc = (input_d.dims()[tag_o == hwigo + 0]); + const int g = (tag_o == hwigo) ? (input_d.dims()[0]) : 1; + + return output_d.matches_tag(tag_o) + && (output_d.extra().flags & memory_extra_flags::compensation_conv_s8s8) + && (input_d.data_type() == f32 || input_d.data_type() == s8) + && output_d.data_type() == s8 + && (D_mask == 1 || D_mask == (size_t)g * oc); + } + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + static constexpr bool w_groups = tag_o == hwigo; + + const auto &dims = input_d.dims(); + const auto &pdims = output_d.padded_dims(); + + const int G = w_groups ? dims[0] : 1; + const int OC = dims[w_groups + 0]; + const int IC = dims[w_groups + 1]; + const int H = dims[w_groups + 2]; + const int W = dims[w_groups + 3]; + + const float *scales = pd->attr()->output_scales_.scales_; + const size_t D_mask = utils::array_product(input_d.dims(), + math::ilog2q(pd->attr()->output_scales_.mask_ + 1)); + + assert(output_d.extra().flags + & memory_extra_flags::compensation_conv_s8s8); + float adj_scale = + (output_d.extra().flags & memory_extra_flags::scale_adjust) + ? output_d.extra().scale_adjust : 1.f; + + size_t offset = G * pdims[w_groups + 0] * pdims[w_groups + 1] * H * W; + int32_t *cp = reinterpret_cast(output + offset); + + parallel_nd(G, OC, [&](int g, int oc) { + cp[g * OC + oc] = 0; + for (int ic = 0; ic < IC; ic++) + for (int h = 0; h < H; h++) + for (int w = 0; w < W; w++) { + auto i = input[input_d.blk_off(g, oc, ic, h, w)]; + auto &o = output[output_d.blk_off(g, oc, ic, h, w)]; + const float s = scales[(D_mask == 1) ? 0 : g * OC + oc]; + + o = qz_b0, data_t>()( + i, s * adj_scale); + cp[g * OC + oc] -= (int32_t)o; + } + cp [g * OC + oc] *= 128; + }); + return success; + } +}; + +template +struct simple_reorder_impl::type> +{ + static bool is_applicable(const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) + { + const size_t D_mask = utils::array_product(input_d.dims(), + math::ilog2q(attr->output_scales_.mask_ + 1)); + const bool w_groups = !utils::one_of(tag_o, OIw4i16o4i, OIhw4i16o4i); + const int oc = (input_d.dims()[w_groups ? 1 : 0]); + const int g = w_groups ? input_d.dims()[0] : 1; + + return input_d.matches_tag(tag_i) + && output_d.matches_tag(tag_o) + && (output_d.extra().flags & memory_extra_flags::compensation_conv_s8s8) + && (input_d.data_type() == f32 || input_d.data_type() == s8) + && output_d.data_type() == s8 + && (D_mask == 1 || D_mask == (size_t)g * oc); + } + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + static constexpr bool w_groups = + !utils::one_of(tag_o, OIw4i16o4i, OIhw4i16o4i); + constexpr int is_1d = + utils::one_of(tag_o, gOIw4i16o4i, OIw4i16o4i); + constexpr int blksize = tag_traits::inner_blks == ib::_4b4c + ? 4 + : tag_traits::inner_blks == ib::_2c8b4c + ? 8 + : 16; + + const auto &_g_oihw_d = order_keep ? input_d : output_d; + const auto &dims = input_d.dims(); + const auto &pdims = order_keep + ? output_d.padded_dims() + : input_d.padded_dims(); + + const int G = w_groups ? dims[0] : 1; + const int OC = dims[w_groups + 0]; + const int NB_OC = pdims[w_groups + 0] / blksize; + const int IC = dims[w_groups + 1]; + const int NB_IC = pdims[w_groups + 1] / blksize; + const int H = is_1d ? 1 : dims[w_groups + 2]; + const int W = dims[w_groups + 3 - is_1d]; + + const float *scales = pd->attr()->output_scales_.scales_; + const size_t D_mask = utils::array_product(input_d.dims(), + math::ilog2q(pd->attr()->output_scales_.mask_ + 1)); + + assert(output_d.extra().flags + & memory_extra_flags::compensation_conv_s8s8); + float adj_scale = + (output_d.extra().flags & memory_extra_flags::scale_adjust) + ? output_d.extra().scale_adjust : 1.f; + + auto ker = [&](const data_t *inp, data_t *out, + int32_t *c, const float *s, const int oc_block, const int ic_block) { +# define index AB_or_BC_blk_off::inner_blks> + + for (int ic = 0; ic < ic_block; ++ic) { + for (int oc = 0; oc < oc_block; ++oc) { + const auto _g_oihw_off = + oc * _g_oihw_d.blocking_desc().strides[w_groups + 0] + + ic * _g_oihw_d.blocking_desc().strides[w_groups + 1]; + out[index(oc, ic)] + = qz_b0, data_t>()( + inp[_g_oihw_off], s[oc] * adj_scale); + c[oc] -= (128 * (int32_t)(out[index(oc, ic)])); + } + } +# undef index + }; + + constexpr int i_mult = blksize; + constexpr int o_mult = 1; + + size_t offset = G * pdims[w_groups+0] * pdims[w_groups+1] * H * W; + int32_t *cp = reinterpret_cast(output + offset); + parallel_nd(G * NB_OC * blksize, [&](int i) { + cp[i] = 0; + }); + +# define wei_blk_off(md, g, o, i, h, w) \ + (is_1d ? (md).blk_off(g, o, i, w) \ + : (md).blk_off(g, o, i, h, w)) + + parallel_nd(G, NB_OC, [&](int g, int O) { + for (int I = 0; I < NB_IC; I++) + for (int h = 0; h < H; h++) + for (int w = 0; w < W; w++) { + auto i = &input[wei_blk_off( + input_d, g, i_mult * O, i_mult * I, h, w)]; + auto o = &output[wei_blk_off( + output_d, g, o_mult * O, o_mult * I, h, w)]; + const int oc_block = nstl::min(blksize, OC - O * blksize); + const int ic_block = nstl::min(blksize, IC - I * blksize); + + int _offset = (g * NB_OC + O) * blksize; + ker(i, o, (order_keep) ? &cp[_offset] : nullptr, + &scales[(D_mask == 1) ? 0 : _offset], + oc_block, ic_block); + } + }); + +# undef wei_blk_off + + return success; + } +}; + +template +struct simple_reorder_impl::type> +{ + static bool is_applicable(const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) { + const size_t D_mask = utils::array_product(input_d.dims(), + math::ilog2q(attr->output_scales_.mask_ + 1)); + const int oc = input_d.dims()[1]; + const int g = input_d.dims()[0]; + + return true + && order_keep + && input_d.matches_tag(tag_i) + && output_d.matches_tag(tag_o) + && (output_d.extra().flags & memory_extra_flags::compensation_conv_s8s8) + && (input_d.data_type() == f32 || input_d.data_type() == s8) + && output_d.data_type() == s8 + && (D_mask == 1 || D_mask == (size_t)g * oc); + } + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + constexpr bool is_1d = tag_i == goiw; + constexpr int blksize = 16; + + const auto &dims = input_d.dims(); + const auto &pdims = output_d.padded_dims(); + const int G = dims[0]; + const int Gp = pdims[0]; + const int OC = dims[1]; + const int IC = dims[2]; + const int H = is_1d ? 1 : dims[3]; + const int W = dims[4 - is_1d]; + + const size_t D_mask = utils::array_product(input_d.dims(), + math::ilog2q(pd->attr()->output_scales_.mask_ + 1)); + const float *scales = pd->attr()->output_scales_.scales_; + + assert(output_d.extra().flags + & memory_extra_flags::compensation_conv_s8s8); + float adj_scale = + (output_d.extra().flags & memory_extra_flags::scale_adjust) + ? output_d.extra().scale_adjust : 1.f; + + auto ker = [&](const data_t *inp, data_t *out, + int32_t *cp, const float *s, const int g_block) { + PRAGMA_OMP_SIMD() + for (int g = 0; g < g_block; g++) { + const auto i_off = g * input_d.blocking_desc().strides[0]; + out[g] = qz_b0, data_t>()( + inp[i_off], s[g * OC] * adj_scale); + cp[g * OC] -= 128 * (int32_t)(out[g]); + } + }; + + size_t cp_offset = output_d.size() - output_d.additional_buffer_size(); + int32_t *cp = reinterpret_cast(output + cp_offset); + parallel_nd((Gp/blksize) * OC, [&](int ib) { + PRAGMA_OMP_SIMD() + for (int i = 0; i < blksize; i++) + cp[ib * blksize + i] = 0; + }); + +# define wei_blk_off(md, g, o, i, h, w) \ + (is_1d ? (md).blk_off(g, o, i, w) : (md).blk_off(g, o, i, h, w)) + + parallel_nd(Gp/blksize, OC, [&](int gb, int O) { + for (int I = 0; I < IC; I++) { + for (int h = 0; h < H; h++) + for (int w = 0; w < W; w++) + { + const int g_block = nstl::min(G - gb * blksize, blksize); + const auto inp = &input[wei_blk_off( + input_d, gb * blksize, O, I, h, w)]; + const auto out = &output[wei_blk_off( + output_d, gb, O, I, h, w)]; + int offset = gb * blksize + O; + ker(inp, out, &cp[offset], + &scales[(D_mask == 1) ? 0 : offset], g_block); + } + } + }); + +# undef wei_blk_off + + return success; + } +}; + +/* reorders with tail support */ + +template +struct simple_reorder_impl::type> +{ + static bool is_applicable(const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) + { + return simple_fmt_check(order_keep, tag_i, tag_o, input_d, output_d) + && simple_attr_check(attr, false); + } + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + constexpr int is_1d = tag_i == nCw8c; + constexpr int is_3d = tag_i == nCdhw8c; + constexpr int blksize_16 = 16; + constexpr int blksize_8 = 8; + constexpr int ic_mult = order_keep ? 2 : 1; + constexpr int oc_mult = order_keep ? 1 : 2; + + const auto &dims = input_d.dims(); + const auto &pdims = order_keep ? output_d.padded_dims() + : input_d.padded_dims(); + + const int C = dims[1]; + const int D = is_3d ? dims[2] : 1; + const int H = is_1d ? 1 : dims[2 + is_3d]; + const int W = dims[3 + is_3d - is_1d]; + + auto ker = [&](const data_t *i, data_t *o, + const int block_16) { + const int nb = (block_16 - 1) / blksize_8 + 1; + if (alpha == 1.0 && beta == 0.0) { + for (int b = 0; b < nb; ++b) { + const ptrdiff_t i_off = order_keep ? b : b * blksize_8; + const ptrdiff_t o_off = order_keep ? b * blksize_8 : b; + const int block_8 = nstl::min(blksize_8, + block_16 - b * blksize_8); + for (int c = 0; c < block_8; ++c) { + o[o_off + c] = _qz_a1b0()( + i[i_off + c]); + } + } + } else { + for (int b = 0; b < nb; ++b) { + const ptrdiff_t i_off = order_keep ? b : b * blksize_8; + const ptrdiff_t o_off = order_keep ? b * blksize_8 : b; + const int block_8 = nstl::min(blksize_8, + block_16 - b * blksize_8); + for (int c = 0; c < block_8; ++c) { + o[o_off + c] = _qz()(i[i_off + c], + o[o_off + c], alpha, beta); + } + } + } + }; + +# define data_blk_off(md, n, c, d, h, w) \ + ( is_1d ? (md).blk_off(n, c, w) \ + : is_3d ? (md).blk_off(n, c, d, h, w) : (md).blk_off(n, c, h, w)) + + parallel_nd(dims[0], pdims[1] / blksize_16, D, H, W, + [&](int n, int nb_c, int d, int h, int w) { + auto i = &input[data_blk_off(input_d, n, ic_mult * nb_c, d, h, w)]; + auto o = &output[data_blk_off(output_d, n, oc_mult * nb_c, d, h, w)]; + const int block_16 = nstl::min(blksize_16, C - nb_c * blksize_16); + ker(i, o, block_16); + }); + +# undef data_blk_off + + return success; + } +}; + +#define PLAIN_TO_BLOCKED_IS_APPLICABLE() \ + static bool is_applicable(const memory_desc_wrapper &input_d, \ + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) { \ + return simple_attr_check(attr, false) && (order_keep \ + ? output_d.matches_tag(tag_o) && input_d.is_plain() \ + : input_d.matches_tag(tag_o) && output_d.is_plain()); \ + } + +template +struct simple_reorder_impl::block_dims == bd::_A + || tag_traits::block_dims == bd::_B) + && tag_traits::ndims >= 3 + && tag_traits::ndims <= 6 + >::type> +{ + PLAIN_TO_BLOCKED_IS_APPLICABLE(); + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + const auto &flat_d = order_keep ? input_d : output_d; + const auto &block_d = order_keep ? output_d : input_d; + const auto &dims = input_d.dims(); + const auto &pdims = block_d.padded_dims(); + + constexpr int ndims = tag_traits::ndims; + constexpr int blk_idx = tag_traits::block_dims == bd::_A ? 0 : 1; + + const dim_t H0 = dims[0]; + const dim_t H1 = dims[1]; + const dim_t M0 = ndims >= 6 ? dims[ndims - 4] : 1; + const dim_t M1 = ndims >= 5 ? dims[ndims - 3] : 1; + const dim_t M2 = ndims >= 4 ? dims[ndims - 2] : 1; + const dim_t L = dims[ndims - 1]; + const dim_t l_blk_stride = block_d.blocking_desc().strides[ndims - 1]; + + constexpr int blksize = false ? 0 + : utils::one_of(tag_traits::inner_blks, ib::_4a, ib::_4b) ? 4 + : utils::one_of(tag_traits::inner_blks, ib::_8a, ib::_8b) ? 8 + : 16; + + auto ker = [&](const data_t *i, data_t *o, int block) { + if (alpha == 1.0 && beta == 0.0) { + for (int l = 0; l < L; ++l) + for (int blk = 0; blk < block; ++blk) { + const dim_t flat_off = 0 + + blk * flat_d.blocking_desc().strides[blk_idx] + + l * flat_d.blocking_desc().strides[ndims - 1]; + if (order_keep) { + o[l * l_blk_stride + blk] = _qz_a1b0()( + i[flat_off]); + } else { + o[flat_off] = _qz_a1b0()( + i[l * l_blk_stride + blk]); + } + } + } else { + for (int l = 0; l < L; ++l) + for (int blk = 0; blk < block; ++blk) { + const dim_t flat_off = 0 + + blk * flat_d.blocking_desc().strides[blk_idx] + + l * flat_d.blocking_desc().strides[ndims - 1]; + if (order_keep) { + o[l * l_blk_stride + blk] = _qz()( + i[flat_off], o[l * blksize + blk], + alpha, beta); + } else { + o[flat_off] = _qz()( + i[l * l_blk_stride + blk], o[flat_off], + alpha, beta); + } + } + } + }; + +# define off(md, h0, h1, m0, m1, m2) \ + (ndims >= 6 ? (md).blk_off(h0, h1, m0, m1, m2) \ + : ndims >= 5 ? (md).blk_off(h0, h1, m1, m2) \ + : ndims >= 4 ? (md).blk_off(h0, h1, m2) \ + : /* ndims >= 3 ? */ (md).blk_off(h0, h1)) + + constexpr int i_mult = order_keep ? blksize : 1; + constexpr int o_mult = order_keep ? 1 : blksize; + + if (blk_idx == 0) { + const dim_t BH0 = pdims[0] / blksize; + parallel_nd(BH0, H1, M0, M1, M2, + [&](dim_t bh0, dim_t h1, dim_t m0, dim_t m1, dim_t m2) { + auto i = &input[off(input_d, bh0 * i_mult, h1, m0, m1, m2)]; + auto o = &output[off(output_d, bh0 * o_mult, h1, m0, m1, m2)]; + const int block = nstl::min(blksize, H0 - bh0 * blksize); + ker(i, o, block); + }); + } else if (blk_idx == 1) { + const dim_t BH1 = pdims[1] / blksize; + parallel_nd(H0, BH1, M0, M1, M2, + [&](dim_t h0, dim_t bh1, dim_t m0, dim_t m1, dim_t m2) { + auto i = &input[off(input_d, h0, bh1 * i_mult, m0, m1, m2)]; + auto o = &output[off(output_d, h0, bh1 * o_mult, m0, m1, m2)]; + const int block = nstl::min(blksize, H1 - bh1 * blksize); + ker(i, o, block); + }); + } else { + assert(!"unimplemented"); + } + +# undef off + + return success; + } +}; + +template +struct simple_reorder_impl::block_dims == bd::_AB + || tag_traits::block_dims == bd::_BC) + && IMPLICATION(tag_traits::block_dims == bd::_AB, + tag_traits::ndims >= 3 && tag_traits::ndims <= 5) + && IMPLICATION(tag_traits::block_dims == bd::_BC, + tag_traits::ndims >= 4 && tag_traits::ndims <= 6) + >::type> +{ + PLAIN_TO_BLOCKED_IS_APPLICABLE(); + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + const auto &flat_d = order_keep ? input_d : output_d; + const auto &dims = input_d.dims(); + const auto &pdims = order_keep + ? output_d.padded_dims() + : input_d.padded_dims(); + + constexpr int ndims = tag_traits::ndims; + + static constexpr bool with_g = tag_traits::block_dims == bd::_BC; + const dim_t G = with_g ? dims[0] : 1; + + const dim_t H0 = dims[0 + with_g]; + const dim_t H1 = dims[1 + with_g]; + + const dim_t M0 = ndims >= 5 + with_g ? dims[ndims - 3] : 1; + const dim_t M1 = ndims >= 4 + with_g ? dims[ndims - 2] : 1; + const dim_t M2 = ndims >= 3 + with_g ? dims[ndims - 1] : 1; + + constexpr int blksize_0 = false ? 0 + : utils::one_of(tag_traits::inner_blks, + ib::_4b4a, ib::_4b4c, ib::_4c4b) + ? 4 + : utils::one_of(tag_traits::inner_blks, + ib::_8a8b, ib::_8b8a, ib::_8b8c, ib::_8c8b, ib::_2c8b4c) + ? 8 + : utils::one_of(tag_traits::inner_blks, + ib::_16a16b, ib::_16a4b, ib::_16b16a, ib::_16b4c, + ib::_16b16c, ib::_16c16b, ib::_8a16b2a, ib::_4b16a4b, + ib::_8b16a2b, ib::_8b16c2b, ib::_4c16b4c, ib::_8c16b2c) + ? 16 : INT_MIN; + + constexpr int blksize_1 = utils::one_of(tag_traits::inner_blks, + ib::_8a8b, ib::_8b8a, ib::_8b8c, ib::_8c8b, ib::_2c8b4c) + ? 8 + : utils::one_of(tag_traits::inner_blks, + ib::_16a16b, ib::_16b16a, ib::_16b16c, ib::_16c16b, + ib::_8a16b2a, ib::_4b16a4b, ib::_8b16a2b, ib::_8b16c2b, + ib::_4c16b4c, ib::_8c16b2c) + ? 16 + : utils::one_of(tag_traits::inner_blks, + ib::_4b4a, ib::_4b4c, ib::_4c4b, + ib::_16a4b, ib::_16b4c) + ? 4 + : INT_MIN; + + const dim_t NB_H0 = pdims[0 + with_g] / blksize_0; + const dim_t NB_H1 = pdims[1 + with_g] / blksize_1; + + auto ker = [&](const data_t *i, data_t *o, + const int block_h0, const int block_h1) { +# define blk_off AB_or_BC_blk_off::inner_blks> + + if (alpha == 1.0 && beta == 0.0) { + for (int h0 = 0; h0 < block_h0; ++h0) + for (int h1 = 0; h1 < block_h1; ++h1) { + const dim_t flat_off = 0 + + h0 * flat_d.blocking_desc().strides[with_g + 0] + + h1 * flat_d.blocking_desc().strides[with_g + 1]; + if (order_keep) { + o[blk_off(h0, h1)] = _qz_a1b0()( + i[flat_off]); + } else { + o[flat_off] = _qz_a1b0()( + i[blk_off(h0, h1)]); + } + } + } else { + for (int h0 = 0; h0 < block_h0; ++h0) + for (int h1 = 0; h1 < block_h1; ++h1) { + const dim_t flat_off = 0 + + h0 * flat_d.blocking_desc().strides[with_g + 0] + + h1 * flat_d.blocking_desc().strides[with_g + 1]; + if (order_keep) { + o[blk_off(h0, h1)] = _qz()(i[flat_off], + o[blk_off(h0, h1)], alpha, beta); + } else { + o[flat_off] = _qz()(i[blk_off(h0, h1)], + o[flat_off], alpha, beta); + } + } + } + +# undef blk_off + }; + + constexpr int i_mult_0 = order_keep ? blksize_0 : 1; + constexpr int o_mult_0 = order_keep ? 1 : blksize_0; + + constexpr int i_mult_1 = order_keep ? blksize_1 : 1; + constexpr int o_mult_1 = order_keep ? 1 : blksize_1; + +# define off(md, g, h0, h1, m0, m1, m2) \ + (ndims >= 5 + with_g ? (md).blk_off(g, h0, h1, m0, m1, m2) \ + : ndims >= 4 + with_g ? (md).blk_off(g, h0, h1, m1, m2) \ + : /* ndims >= 3 + with_g ? */ (md).blk_off(g, h0, h1, m2)) + + parallel_nd(G, NB_H0, NB_H1, M0, M1, M2, + [&](dim_t g, dim_t nb_h0, dim_t nb_h1, dim_t m0, dim_t m1, dim_t m2) { + auto i = &input[off(input_d, + g, i_mult_0 * nb_h0, i_mult_1 * nb_h1, m0, m1, m2)]; + auto o = &output[off(output_d, + g, o_mult_0 * nb_h0, o_mult_1 * nb_h1, m0, m1, m2)]; + const int block_h0 = nstl::min(blksize_0, H0 - nb_h0 * blksize_0); + const int block_h1 = nstl::min(blksize_1, H1 - nb_h1 * blksize_1); + ker(i, o, block_h0, block_h1); + }); + +# undef off + + return success; + } +}; + +/* generic and direct-copy reorders */ + +template +struct simple_reorder_impl::type> +{ + static bool is_applicable(const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) { + /* FIXME: is the formula correct? */ + return input_d.similar_to(output_d, true, false, 0) + && input_d.is_dense() && output_d.is_dense() + && simple_attr_check(attr, false); + } + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + assert(input_d.is_dense()); + + input += input_d.blk_off(0); + output += output_d.blk_off(0); + + const size_t nelems = input_d.nelems(); + + constexpr int block_size = 16; + const auto num_blocks = nelems / block_size; + const auto rem_elems = nelems % block_size; + + parallel(0, [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + balance211(num_blocks, nthr, ithr, start, end); + start = start * block_size; + end = end * block_size; + + if (alpha == 1.0 && beta == 0.0) { + PRAGMA_OMP_SIMD() + for (size_t e = start; e < end; ++e) { + output[e] = qz_a1b0, data_t>() + (input[e]); + } + } else if (alpha == 1.0) { + PRAGMA_OMP_SIMD() + for (size_t e = start; e < end; ++e) { + output[e] = qz_a1, data_t>() + (input[e], output[e], beta); + } + } else if (beta == 0.0) { + PRAGMA_OMP_SIMD() + for (size_t e = start; e < end; ++e) { + output[e] = qz_b0, data_t>() + (input[e], alpha); + } + } else { + PRAGMA_OMP_SIMD() + for (size_t e = start; e < end; ++e) { + output[e] = qz, data_t>() + (input[e], output[e], alpha, beta); + } + } + + if (rem_elems != 0 && ithr == nthr - 1){ + if (alpha == 1.0 && beta == 0.0) { + PRAGMA_OMP_SIMD() + for (size_t e = nelems - rem_elems; e < nelems; ++e) { + output[e] = qz_a1b0, + data_t>()(input[e]); + } + } else if (alpha == 1.0) { + PRAGMA_OMP_SIMD() + for (size_t e = nelems - rem_elems; e < nelems; ++e) { + output[e] = qz_a1, + data_t>()(input[e], output[e], beta); + } + } else if (beta == 0.0) { + PRAGMA_OMP_SIMD() + for (size_t e = nelems - rem_elems; e < nelems; ++e) { + output[e] = qz_b0, + data_t>()(input[e], alpha); + } + } else { + PRAGMA_OMP_SIMD() + for (size_t e = nelems - rem_elems; e < nelems; ++e) { + output[e] = qz, data_t>() + (input[e], output[e], alpha, beta); + } + } + } + }); + return success; + } +}; + +template +struct simple_reorder_impl::type> +{ + static bool is_applicable(const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) { + auto is_dense_no_0 = [](const memory_desc_wrapper &data_d) { + return nelems_no_dim_0(data_d) == _size_no_dim_0(data_d); + }; + /* FIXME: is the formula correct? */ + return input_d.similar_to(output_d, true, false, 1) + && is_dense_no_0(input_d) && is_dense_no_0(output_d) + && simple_attr_check(attr, false); + } + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + input += input_d.blk_off(0); + output += output_d.blk_off(0); + + const int N = input_d.dims()[0]; + const dim_t is = input_d.blocking_desc().strides[0]; + const dim_t os = output_d.blocking_desc().strides[0]; + const dim_t nelems_no_d0 = nelems_no_dim_0(input_d); + const dim_t work_amount = N * nelems_no_d0; + + if (alpha == 1.0 && beta == 0.0) { + parallel(0, [&](const int ithr, const int nthr) { + dim_t n{0}, dim1_s{0}; + dim_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + nd_iterator_init(start, n, N, dim1_s, nelems_no_d0); + while(start < end) { + dim_t work_rem = end - start; + dim_t dim1_e = dim1_s + work_rem > nelems_no_d0 + ? nelems_no_d0 : dim1_s + work_rem; + PRAGMA_OMP_SIMD() + for (dim_t e = dim1_s; e < dim1_e; ++e) { + output[os * n + e] = _qz_a1b0()( + input[is * n + e]); + } + nd_iterator_jump(start, end, n, N, dim1_s, nelems_no_d0); + } + }); + } else { + parallel(0, [&](const int ithr, const int nthr) { + dim_t n{0}, dim1_s{0}; + dim_t start{0}, end{0}; + balance211(work_amount, nthr, ithr, start, end); + nd_iterator_init(start, n, N, dim1_s, nelems_no_d0); + while(start < end) { + dim_t work_rem = end - start; + dim_t dim1_e = + dim1_s + work_rem > nelems_no_d0 ? nelems_no_d0 + : dim1_s + work_rem; + PRAGMA_OMP_SIMD() + for (dim_t e = dim1_s; e < dim1_e; ++e){ + output[os * n + e] = _qz()( + input[is * n + e], output[os * n + e], alpha, + beta); + } + nd_iterator_jump(start, end, n, N, dim1_s, nelems_no_d0); + } + }); + } + + return success; + } + +private: + static dim_t nelems_no_dim_0(const memory_desc_wrapper &data_d) { + const int ndims = data_d.ndims(); + if (ndims <= 1) return 1; + return utils::array_product(data_d.dims() + 1, data_d.ndims() - 1); + } + + static dim_t _size_no_dim_0(const memory_desc_wrapper &data_d) { + dims_t blocks; + data_d.compute_blocks(blocks); + + const auto &blk = data_d.blocking_desc(); + + dim_t blk_size = 1; + for (int iblk = 0; iblk < blk.inner_nblks; ++iblk) + blk_size *= blk.inner_blks[iblk]; + + dim_t max_size = blk_size; + for (int d = 1; d < data_d.ndims(); ++d) { + max_size = nstl::max(max_size, + data_d.padded_dims()[d] / blocks[d] * blk.strides[d]); + } + + return max_size; + } +}; + +template +struct simple_reorder_impl::type> +{ + static bool is_applicable(const memory_desc_wrapper &input_d, + const memory_desc_wrapper &output_d, const primitive_attr_t *attr) { + /* supported smask: 0x0...011..10...0, + * i.e. 1 should be contiguous */ + int smask = attr ? attr->output_scales_.mask_ : 0; + for (; smask > 0 && !(smask & 0x1); smask >>= 1); + for (; smask > 0 && smask & 0x1; smask >>= 1); + return true + && input_d.is_blocking_desc() + && output_d.is_blocking_desc() + && !output_d.is_additional_buffer() + && !input_d.is_additional_buffer() + && smask == 0; + } + + static status_t execute(const cpu_reorder_pd_t *pd, + const data_t *input, data_t *output) { + DECLARE_COMMON_PARAMS(); + + const size_t nelems = input_d.nelems(); + + int ndims_start = 0, ndims_mask = 0; + int smask = pd->attr()->output_scales_.mask_; + for (; smask > 0 && !(smask & 0x1); smask >>= 1) ++ndims_start; + for (; smask > 0 && smask & 0x1; smask >>= 1) ++ndims_mask; + assert(smask == 0); + + const ptrdiff_t D_start + = utils::array_product(input_d.dims(), ndims_start); + const ptrdiff_t D_mask + = utils::array_product(input_d.dims() + ndims_start, ndims_mask); + const ptrdiff_t D_rest = nelems / D_start / D_mask; + + const float *scales = pd->attr()->output_scales_.scales_; + + parallel_nd(D_start, D_mask, D_rest, + [&](ptrdiff_t ds, ptrdiff_t dm, ptrdiff_t dr) { + const float scale = scales[dm]; + + const size_t e = (ds * D_mask + dm) * D_rest + dr; + const auto &i = input[input_d.off_l(e)]; + auto &o = output[output_d.off_l(e)]; + + o = _qz()(i, o, scale, beta); + }); + + return success; + } +}; + + +/* high level class declaration */ + +template +struct simple_reorder_t: public cpu_primitive_t { + struct pd_t: public cpu_reorder_pd_t { + using cpu_reorder_pd_t::cpu_reorder_pd_t; + + DECLARE_COMMON_PD_T("simple:any", simple_reorder_t); + + static status_t create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) { + bool args_ok = true + && src_md->data_type == type_i + && dst_md->data_type == type_o + && simple_reorder_impl:: + is_applicable(src_md, dst_md, attr); + if (!args_ok) + return status::invalid_arguments; + + auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine, + dst_md); + if (_pd == nullptr) return status::out_of_memory; + if (_pd->init() != status::success) { + delete _pd; + return status::unimplemented; + } + return safe_ptr_assign(*reorder_pd, _pd); + } + }; + + simple_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {} + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto input = CTX_IN_MEM(const data_t *, MKLDNN_ARG_FROM); + auto output = CTX_OUT_MEM(data_t *, MKLDNN_ARG_TO); + simple_reorder_impl::execute( + pd(), input, output); + return status::success; + } + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +#undef SIMPLE_REORDER_TEMPL_DECL +#undef SIMPLE_REORDER_TEMPL_CALL + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp new file mode 100644 index 0000000000..f0947573a9 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp @@ -0,0 +1,91 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "mkldnn_thread.hpp" + +#include "simple_sum.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +status_t simple_sum_t::execute(const exec_ctx_t &ctx) const { + auto output = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST); + + const memory_desc_wrapper o_d(pd()->dst_md()); + output += o_d.blk_off(0); + + const int num_arrs = pd()->n_inputs(); + const data_t *input_ptrs[max_num_arrs]; + const size_t nelems = o_d.nelems(); + + for (int a = 0; a < num_arrs; ++a) { + const memory_desc_wrapper i_d(pd()->src_md(a)); + input_ptrs[a] = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MULTIPLE_SRC + a) + + i_d.blk_off(0); + } + + const size_t block_size = 16 * 1024 / sizeof(data_type); + const size_t blocks_number = nelems / block_size; + const size_t tail = nelems % block_size; + + const auto scales = pd()->scales(); + parallel(0, [&](const int ithr, const int nthr) { + size_t start{0}, end{0}; + balance211(blocks_number, nthr, ithr, start, end); + + for (size_t nb = start; nb < end; ++nb) { + size_t start_e = nb * block_size; + size_t end_e = start_e + block_size; + + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] = data_t(scales[0] * input_ptrs[0][e]); + } + for (int a = 1; a < num_arrs; a++) { + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] += data_t(scales[a] * input_ptrs[a][e]); + } + } + } + + if (tail != 0 && ithr == nthr - 1) { + size_t start_e = nelems - tail; + size_t end_e = nelems; + + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] = data_t(scales[0] * input_ptrs[0][e]); + } + for (int a = 1; a < num_arrs; a++) { + PRAGMA_OMP_SIMD() + for (size_t e = start_e; e < end_e; e++) { + output[e] += data_t(scales[a] * input_ptrs[a][e]); + } + } + } + }); + + return status::success; +} + +template struct simple_sum_t; + +} +} +} diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp new file mode 100644 index 0000000000..2a0187a184 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp @@ -0,0 +1,74 @@ +/******************************************************************************* +* Copyright 2017-2018 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef SIMPLE_SUM_HPP +#define SIMPLE_SUM_HPP + +#include "cpu_sum_pd.hpp" +#include "cpu_primitive.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct simple_sum_t: public cpu_primitive_t { + struct pd_t: public cpu_sum_pd_t { + using cpu_sum_pd_t::cpu_sum_pd_t; + + DECLARE_SUM_PD_T("simple:any", simple_sum_t); + + status_t init() { + const int n = n_inputs(); + + bool ok = true + && cpu_sum_pd_t::init() == status::success + && n <= max_num_arrs; + if (!ok) return status::unimplemented; + + const memory_desc_wrapper o_d(dst_md()); + ok = ok + && o_d.data_type() == data_type + && o_d.is_dense(); + if (!ok) return status::unimplemented; + + for (int i = 0; i < n; ++i) { + const memory_desc_wrapper i_d(src_md(i)); + if (i_d != o_d) return status::unimplemented; + } + + return status::success; + } + }; + + simple_sum_t(const pd_t *apd): cpu_primitive_t(apd) {} + + virtual status_t execute(const exec_ctx_t &ctx) const override; + + enum {max_num_arrs = 16 }; + typedef typename prec_traits::type data_t; + +private: + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } +}; + +} +} +} + +#endif + +// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp new file mode 100644 index 0000000000..c2082d7d62 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp @@ -0,0 +1,376 @@ +/******************************************************************************* + * Copyright 2017-2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#ifndef CPU_WINO_REORDER_HPP +#define CPU_WINO_REORDER_HPP + +#include "mkldnn_thread.hpp" + +#include "simple_q10n.hpp" + +namespace mkldnn { +namespace impl { +namespace cpu { + +template +struct wino_reorder_t : public cpu_primitive_t { + struct pd_t : public cpu_reorder_pd_t { + using cpu_reorder_pd_t::cpu_reorder_pd_t; + + DECLARE_COMMON_PD_T("wino_reorder", wino_reorder_t); + + static status_t create(reorder_pd_t **reorder_pd, + engine_t *engine, const primitive_attr_t *attr, + engine_t *src_engine, const memory_desc_t *src_md, + engine_t *dst_engine, const memory_desc_t *dst_md) { + const memory_desc_wrapper id(src_md), od(dst_md); + bool args_ok = true + && id.data_type() == type_i + && od.data_type() == type_o + && id.matches_tag(utils::pick(id.ndims() - 4, + format_tag::oihw, format_tag::goihw)) + && od.format_kind() == format_kind::wino + && utils::one_of(od.wino_desc().wino_format, + mkldnn_wino_wei_aaOIoi, mkldnn_wino_wei_aaOio, + mkldnn_wino_wei_aaOBiOo, mkldnn_wino_wei_OBaaIBOIio); + if (!args_ok) return status::invalid_arguments; + + auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine, + dst_md); + if (_pd == nullptr) return status::out_of_memory; + if (_pd->init() != status::success) { + delete _pd; + return status::unimplemented; + } + return safe_ptr_assign(*reorder_pd, _pd); + } + + status_t init() { + status_t status = cpu_reorder_pd_t::init(); + if (status != status::success) return status; + + init_scratchpad(); + + return status::success; + } + + private: + void init_scratchpad() { + auto &o = memory_desc_wrapper(dst_md()).wino_desc(); + size_t transform_space_size = (size_t)o.r * o.alpha * o.oc_block; + size_t plain_size = (size_t)o.alpha * o.alpha * o.oc * o.ic; + + using namespace memory_tracking::names; + auto scratchpad = scratchpad_registry().registrar(); + scratchpad.book(key_reorder_wino_transform_space, + sizeof(in_data_t) * transform_space_size); + scratchpad.book(key_reorder_wino_plain, + sizeof(out_data_t) * plain_size); + } + }; + +private: + typedef typename prec_traits::type in_data_t; + typedef typename prec_traits::type out_data_t; + const int unsign_val_in_wino_domain_ = 5; + + wino_reorder_t(const pd_t *apd): cpu_primitive_t(apd) { + const memory_desc_wrapper src_d(pd()->src_md()); + const memory_desc_wrapper dst_d(pd()->dst_md()); + + r_ = dst_d.wino_desc().r; + w_alpha_ = dst_d.wino_desc().alpha; + wino_format_ = dst_d.wino_desc().wino_format; + + const auto &in_dims = src_d.dims(); + int groups; + int groups_offset; + if (src_d.ndims() == 5) { + groups = in_dims[0]; + groups_offset = 1; + } else { + groups = 1; + groups_offset = 0; + } + assert(groups == 1); // groups are not supported now + MAYBE_UNUSED(groups); + + or_oc_ = in_dims[0 + groups_offset]; + or_ic_ = in_dims[1 + groups_offset]; + kh_ = in_dims[2 + groups_offset]; + kw_ = in_dims[3 + groups_offset]; + + oc_ = dst_d.wino_desc().oc; + ic_ = dst_d.wino_desc().ic; + oc_block_ = dst_d.wino_desc().oc_block; + ic_block_ = dst_d.wino_desc().ic_block; + assert(oc_ % oc_block_ == 0 && ic_ % ic_block_ == 0); + nb_oc_ = oc_ / oc_block_; + nb_ic_ = ic_ / ic_block_; + ic2_block_ = 1; + if (wino_format_ == mkldnn_wino_wei_OBaaIBOIio) + ic2_block_ = dst_d.wino_desc().ic2_block; + oc2_block_ = dst_d.wino_desc().oc2_block; + assert(nb_ic_ % ic2_block_ == 0 && nb_oc_ % oc2_block_ == 0); + + adj_scale_ = dst_d.wino_desc().adj_scale; + + size_wino_wei_ = w_alpha_ * w_alpha_ * oc_ * ic_; + size_wspace_ = r_ * w_alpha_ * oc_block_; + } + + void transform(out_data_t *__restrict tmp_wei, + const in_data_t *__restrict input, + in_data_t *__restrict wspace) const { + const memory_desc_wrapper src_d(pd()->src_md()); + + const int smask = pd()->attr()->output_scales_.mask_; + const int ndims_mask = math::ilog2q(smask + 1); + const size_t D_mask = utils::array_product(src_d.dims(), ndims_mask); + const float *__restrict scales = pd()->attr()->output_scales_.scales_; + assert(D_mask == 1 || D_mask == (size_t)oc_); + + /* transform weights to winograd domain */ + const float G_2x2_3x3[4][3] = { { 1.0, 0.0, 0.0 }, { 0.5, 0.5, 0.5 }, + { 0.5, -0.5, 0.5 }, { 0.0, 0.0, 1.0 } }; + + const float G_4x4_3x3[6][3] = { { 1.13777777777778f, 0.f, 0.f }, + { -0.688403361344538f, -0.430252100840336f, -0.26890756302521f }, + { -0.688403361344538f, 0.430252100840336f, -0.26890756302521f }, + { 0.119514472455649f, 0.179271708683473f, 0.26890756302521f }, + { 0.119514472455649f, -0.179271708683473f, 0.26890756302521f }, + { 0.f, 0.f, 1.f } }; + + float *__restrict g; + if (utils::one_of(wino_format_, mkldnn_wino_wei_aaOIoi, + mkldnn_wino_wei_aaOio, mkldnn_wino_wei_aaOBiOo)) + g = (float *)G_2x2_3x3; + else if (wino_format_ == mkldnn_wino_wei_OBaaIBOIio) + g = (float *)G_4x4_3x3; + else { + assert("Unknown winograd weights target layout"); + return; + } + + int Z = oc_ * ic_; + assert(r_ == kh_ && r_ == kw_); + + for (int iic = 0; iic < ic_; iic++) { + for (int ob = 0; ob < nb_oc_; ob++) { + const in_data_t *__restrict _inp + = input + (ob * oc_block_ * or_ic_ + iic) * kh_ * kw_; + out_data_t *__restrict _out + = tmp_wei + (iic * nb_oc_ + ob) * oc_block_; + + for_nd(0, 1, size_wspace_, [&](int i) { wspace[i] = 0.f; }); + + for_nd(0, 1, r_, w_alpha_, oc_block_, + [&](int ih, int j, int ioc) { + for (int iw = 0; iw < r_; ++iw) { + int inp_oc = ob * oc_block_ + ioc; + int inp_ic = iic; + in_data_t inp_v = (inp_ic < or_ic_ && inp_oc < or_oc_) + ? _inp[ioc * or_ic_ * kh_ * kw_ + ih * kw_ + iw] + : 0.f; + wspace[(ih * w_alpha_ + j) * oc_block_ + ioc] + += inp_v * g[j * r_ + iw]; + } + }); + + for_nd(0, 1, w_alpha_, w_alpha_, oc_block_, + [&](int i, int j, int ioc) { + float t = 0; + for (int k = 0; k < r_; ++k) + t += g[i * r_ + k] + * wspace[(k * w_alpha_ + j) * oc_block_ + ioc]; + if (type_o == data_type::s8) { + const float scale = (D_mask == 1) + ? scales[0] + : scales[ob * oc_block_ + ioc]; + _out[(i * w_alpha_ + j) * Z + ioc] + = qz_b0()( + (in_data_t)t, scale * adj_scale_); + } else { + _out[(i * w_alpha_ + j) * Z + ioc] = (out_data_t)t; + } + }); + }} + } + + void reorder_to_aaOIoi(out_data_t *__restrict output, + const out_data_t *__restrict tmp_wei) const { + int32_t *__restrict dst_bias = nullptr; + if (type_o == data_type::s8) { + const auto bias_shift = sizeof(out_data_t) * size_wino_wei_; + const size_t bias_size = w_alpha_ * w_alpha_ * oc_; + + dst_bias = (int32_t *)(output + bias_shift); + utils::array_set((int32_t *)dst_bias, 0, bias_size); + } + int index = 0; + for (int u_h = 0; u_h < w_alpha_; u_h++) { + for (int u_w = 0; u_w < w_alpha_; u_w++) { + for_nd(0, 1, nb_oc_, oc_block_, [&](int ob, int o) { + int u_h_shift = u_h * w_alpha_ * ic_ * oc_; + int u_w_shift = u_w * ic_ * oc_; + int u_h_shift_b = u_h * w_alpha_ * oc_; + int u_w_shift_b = u_w * oc_; + int oc_block_shift = ob * oc_block_ * ic_ + o * ic_block_; + for (int ib = 0; ib < nb_ic_; ib++) { + for (int i = 0; i < ic_block_; i++) { + int _i = ib * ic_block_; + int _o = ob * oc_block_; + int ic_shift = (_i + i) * oc_; + int oc_shift = (_o + o); + int ic_block_shift = ib * oc_block_ * ic_block_ + i; + int src_offset = + u_h_shift + u_w_shift + ic_shift + oc_shift; + int dst_offset = u_h_shift + u_w_shift + oc_block_shift + + ic_block_shift; + + output[dst_offset] = tmp_wei[src_offset]; + if (type_o == data_type::s8) { + int bias_offset = u_h_shift_b + u_w_shift_b + oc_shift; + if (index != unsign_val_in_wino_domain_) + dst_bias[bias_offset] + -= (128 * (int32_t)output[dst_offset]); + else + dst_bias[bias_offset] = 0; + } + }} + }); + index++; + }} + } + + void reorder_to_aaOio(out_data_t *__restrict output, + const out_data_t *__restrict tmp_wei) const { + for_nd(0, 1, w_alpha_, w_alpha_, nb_oc_, + [&](int u_h, int u_w, int ob) { + for (int ib = 0; ib < nb_ic_; ib++) { + for (int i = 0; i < ic_block_; i++) { + for (int o = 0; o < oc_block_; o++) { + int src_offset = u_h * w_alpha_ * ic_ * oc_ + u_w * ic_ * oc_ + + (ib * ic_block_ + i) * oc_ + (ob * oc_block_ + o); + + int dst_offset + = u_h * w_alpha_ * nb_oc_ * nb_ic_ * ic_block_ * oc_block_ + + u_w * nb_oc_ * nb_ic_ * ic_block_ * oc_block_ + + ob * nb_ic_ * ic_block_ * oc_block_ + + ib * ic_block_ * oc_block_ + i * oc_block_ + o; + output[dst_offset] = tmp_wei[src_offset]; + }}} + }); + } + + void reorder_to_aaOBiOo(out_data_t *__restrict output, + const out_data_t *__restrict tmp_wei) const { + int oc_chunks = nb_oc_ / oc2_block_; + + for_nd(0, 1, w_alpha_, w_alpha_, oc_chunks, + [&](int u_h, int u_w, int occ) { + for (int ib = 0; ib < nb_ic_; ib++) { + out_data_t *__restrict wei_ptr = output + + (((u_h * w_alpha_ + u_w) * oc_chunks + occ) * nb_ic_ + ib) + * oc2_block_ * ic_block_ * oc_block_; + int wei_offset = 0; + for (int i = 0; i < ic_block_; i++) { + for (int ob2 = 0; ob2 < oc2_block_; ob2++) { + for (int o = 0; o < oc_block_; o++) { + int icp = ib * ic_block_ + i; + int ocp = + occ * oc2_block_ * oc_block_ + ob2 * oc_block_ + o; + + int src_offset = u_h * w_alpha_ * ic_ * oc_ + + u_w * ic_ * oc_ + icp * oc_ + ocp; + wei_ptr[wei_offset + o] = tmp_wei[src_offset]; + } + wei_offset += oc_block_; + }} + } + }); + } + + void reorder_to_OBaaIBOIio(out_data_t *__restrict output, + const out_data_t *__restrict tmp_wei) const { + int ic_chunks = nb_ic_ / ic2_block_; + int oc_chunks = nb_oc_ / oc2_block_; + + for_nd(0, 1, oc_chunks, w_alpha_, w_alpha_, + [&](int occ, int u_h, int u_w) { + for (int icc = 0; icc < ic_chunks; icc++) { + for (int ob = 0; ob < oc2_block_; ob++) { + int ocp = (occ * oc2_block_ + ob) * oc_block_; + for (int ib = 0; ib < ic2_block_; ib++) { + for (int i = 0; i < ic_block_; i++) { + int icp = (icc * ic2_block_ + ib) * ic_block_ + i; + + int src_offset = u_h * w_alpha_ * ic_ * oc_ + + u_w * ic_ * oc_ + icp * oc_ + ocp; + int wei_offset + = ((((((occ * w_alpha_ + u_h) * w_alpha_ + u_w) + * ic_chunks + icc) * oc2_block_ + ob) * ic2_block_ + + ib) * ic_block_ + i) * oc_block_; + for (int o = 0; o < oc_block_; o++) + output[wei_offset + o] = tmp_wei[src_offset + o]; + }} + }} + }); + } + + virtual status_t execute(const exec_ctx_t &ctx) const override { + auto input = CTX_IN_MEM(const in_data_t *, MKLDNN_ARG_FROM); + auto output = CTX_OUT_MEM(out_data_t *, MKLDNN_ARG_TO); + + auto wspace = (in_data_t *__restrict)scratchpad(ctx).template get( + memory_tracking::names::key_reorder_wino_transform_space); + auto tmp_wei = (out_data_t *__restrict)scratchpad(ctx).template get( + memory_tracking::names::key_reorder_wino_plain); + + transform(tmp_wei, input, wspace); + + /* reorder to winograd domain */ + switch (wino_format_) { + case mkldnn_wino_wei_aaOIoi: + reorder_to_aaOIoi(output, tmp_wei); break; + case mkldnn_wino_wei_aaOio: + reorder_to_aaOio(output, tmp_wei); break; + case mkldnn_wino_wei_aaOBiOo: + reorder_to_aaOBiOo(output, tmp_wei); break; + case mkldnn_wino_wei_OBaaIBOIio: + reorder_to_OBaaIBOIio(output, tmp_wei); break; + default: assert("Unknown wino format"); break; + } + + return status::success; + } + + const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); } + int r_, w_alpha_; + int ic_, oc_, or_ic_, or_oc_, kh_, kw_; + int oc_block_, ic_block_, oc2_block_, ic2_block_; + float adj_scale_; + int nb_oc_, nb_ic_; + mkldnn_wino_memory_format_t wino_format_; + int size_wino_wei_; + int size_wspace_; +}; + +} // namespace cpu +} // namespace impl +} // namespace mkldnn + +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT new file mode 100644 index 0000000000..66b6ea55d0 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT @@ -0,0 +1,47 @@ + +Copyright (c) 2007 MITSUNARI Shigeo +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +Neither the name of the copyright owner nor the names of its contributors may +be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満た +す場合に限り、再頒布および使用が許可されます。 + +ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項 +を含めること。 +バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作 +権表示、本条件一覧、および下記免責条項を含めること。 +書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進 +に、著作権者の名前またはコントリビューターの名前を使用してはならない。 +本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供さ +れており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性 +に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありません。 +著作権者もコントリビューターも、事由のいかんを問わず、 損害発生の原因いかんを +問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法行為で +あるかを問わず、仮にそのような損害が発生する可能性を知らされていたとしても、 +本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、使用の +喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されない)直接 +損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害について、 +一切責任を負わないものとします。 diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h new file mode 100644 index 0000000000..cf5771332f --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h @@ -0,0 +1,2658 @@ +/******************************************************************************* +* Copyright 2016-2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/******************************************************************************* +* Copyright (c) 2007 MITSUNARI Shigeo +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* Neither the name of the copyright owner nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#pragma once +#ifndef XBYAK_XBYAK_H_ +#define XBYAK_XBYAK_H_ +/*! + @file xbyak.h + @brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++ + @author herumi + @url https://github.com/herumi/xbyak + @note modified new BSD license + http://opensource.org/licenses/BSD-3-Clause +*/ +#ifndef XBYAK_NO_OP_NAMES + #if not +0 // trick to detect whether 'not' is operator or not + #error "use -fno-operator-names option if you want to use and(), or(), xor(), not() as function names, Or define XBYAK_NO_OP_NAMES and use and_(), or_(), xor_(), not_()." + #endif +#endif + +#include // for debug print +#include +#include +#include +#include +#ifndef NDEBUG +#include +#endif + +// #define XBYAK_DISABLE_AVX512 + +//#define XBYAK_USE_MMAP_ALLOCATOR +#if !defined(__GNUC__) || defined(__MINGW32__) + #undef XBYAK_USE_MMAP_ALLOCATOR +#endif + +#ifdef __GNUC__ + #define XBYAK_GNUC_PREREQ(major, minor) ((__GNUC__) * 100 + (__GNUC_MINOR__) >= (major) * 100 + (minor)) +#else + #define XBYAK_GNUC_PREREQ(major, minor) 0 +#endif + +// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft. +#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\ + ((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__))) + #include + #define XBYAK_STD_UNORDERED_SET std::unordered_set + #include + #define XBYAK_STD_UNORDERED_MAP std::unordered_map + #define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap + +/* + Clang/llvm-gcc and ICC-EDG in 'GCC-mode' always claim to be GCC 4.2, using + libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version). +*/ +#elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__) + #include + #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set + #include + #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map + #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap + +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600) + #include + #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set + #include + #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map + #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap + +#else + #include + #define XBYAK_STD_UNORDERED_SET std::set + #include + #define XBYAK_STD_UNORDERED_MAP std::map + #define XBYAK_STD_UNORDERED_MULTIMAP std::multimap +#endif +#ifdef _WIN32 + #include + #include + #include +#elif defined(__GNUC__) + #include + #include + #include +#endif +#if !defined(_MSC_VER) || (_MSC_VER >= 1600) + #include +#endif + +#if defined(_WIN64) || defined(__MINGW64__) || (defined(__CYGWIN__) && defined(__x86_64__)) + #define XBYAK64_WIN +#elif defined(__x86_64__) + #define XBYAK64_GCC +#endif +#if !defined(XBYAK64) && !defined(XBYAK32) + #if defined(XBYAK64_GCC) || defined(XBYAK64_WIN) + #define XBYAK64 + #else + #define XBYAK32 + #endif +#endif + +#if (__cplusplus >= 201103) || (_MSC_VER >= 1800) + #define XBYAK_VARIADIC_TEMPLATE +#endif + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4514) /* remove inline function */ + #pragma warning(disable : 4786) /* identifier is too long */ + #pragma warning(disable : 4503) /* name is too long */ + #pragma warning(disable : 4127) /* constant expresison */ +#endif + +namespace Xbyak { + +enum { + DEFAULT_MAX_CODE_SIZE = 4096, + VERSION = 0x5760 /* 0xABCD = A.BC(D) */ +}; + +#ifndef MIE_INTEGER_TYPE_DEFINED +#define MIE_INTEGER_TYPE_DEFINED +#ifdef _MSC_VER + typedef unsigned __int64 uint64; + typedef __int64 sint64; +#else + typedef uint64_t uint64; + typedef int64_t sint64; +#endif +typedef unsigned int uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; +#endif + +#ifndef MIE_ALIGN + #ifdef _MSC_VER + #define MIE_ALIGN(x) __declspec(align(x)) + #else + #define MIE_ALIGN(x) __attribute__((aligned(x))) + #endif +#endif +#ifndef MIE_PACK // for shufps + #define MIE_PACK(x, y, z, w) ((x) * 64 + (y) * 16 + (z) * 4 + (w)) +#endif + +enum { + ERR_NONE = 0, + ERR_BAD_ADDRESSING, + ERR_CODE_IS_TOO_BIG, + ERR_BAD_SCALE, + ERR_ESP_CANT_BE_INDEX, + ERR_BAD_COMBINATION, + ERR_BAD_SIZE_OF_REGISTER, + ERR_IMM_IS_TOO_BIG, + ERR_BAD_ALIGN, + ERR_LABEL_IS_REDEFINED, + ERR_LABEL_IS_TOO_FAR, + ERR_LABEL_IS_NOT_FOUND, + ERR_CODE_ISNOT_COPYABLE, + ERR_BAD_PARAMETER, + ERR_CANT_PROTECT, + ERR_CANT_USE_64BIT_DISP, + ERR_OFFSET_IS_TOO_BIG, + ERR_MEM_SIZE_IS_NOT_SPECIFIED, + ERR_BAD_MEM_SIZE, + ERR_BAD_ST_COMBINATION, + ERR_OVER_LOCAL_LABEL, // not used + ERR_UNDER_LOCAL_LABEL, + ERR_CANT_ALLOC, + ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW, + ERR_BAD_PROTECT_MODE, + ERR_BAD_PNUM, + ERR_BAD_TNUM, + ERR_BAD_VSIB_ADDRESSING, + ERR_CANT_CONVERT, + ERR_LABEL_ISNOT_SET_BY_L, + ERR_LABEL_IS_ALREADY_SET_BY_L, + ERR_BAD_LABEL_STR, + ERR_MUNMAP, + ERR_OPMASK_IS_ALREADY_SET, + ERR_ROUNDING_IS_ALREADY_SET, + ERR_K0_IS_INVALID, + ERR_EVEX_IS_INVALID, + ERR_SAE_IS_INVALID, + ERR_ER_IS_INVALID, + ERR_INVALID_BROADCAST, + ERR_INVALID_OPMASK_WITH_MEMORY, + ERR_INVALID_ZERO, + ERR_INVALID_RIP_IN_AUTO_GROW, + ERR_INVALID_MIB_ADDRESS, + ERR_INTERNAL, + ERR_X2APIC_IS_NOT_SUPPORTED +}; + +class Error : public std::exception { + int err_; +public: + explicit Error(int err) : err_(err) + { + if (err_ < 0 || err_ > ERR_INTERNAL) { + fprintf(stderr, "bad err=%d in Xbyak::Error\n", err_); + //exit(1); + } + } + operator int() const { return err_; } + const char *what() const throw() + { + static const char *errTbl[] = { + "none", + "bad addressing", + "code is too big", + "bad scale", + "esp can't be index", + "bad combination", + "bad size of register", + "imm is too big", + "bad align", + "label is redefined", + "label is too far", + "label is not found", + "code is not copyable", + "bad parameter", + "can't protect", + "can't use 64bit disp(use (void*))", + "offset is too big", + "MEM size is not specified", + "bad mem size", + "bad st combination", + "over local label", + "under local label", + "can't alloc", + "T_SHORT is not supported in AutoGrow", + "bad protect mode", + "bad pNum", + "bad tNum", + "bad vsib addressing", + "can't convert", + "label is not set by L()", + "label is already set by L()", + "bad label string", + "err munmap", + "opmask is already set", + "rounding is already set", + "k0 is invalid", + "evex is invalid", + "sae(suppress all exceptions) is invalid", + "er(embedded rounding) is invalid", + "invalid broadcast", + "invalid opmask with memory", + "invalid zero", + "invalid rip in AutoGrow", + "invalid mib address", + "internal error", + "x2APIC is not supported" + }; + assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl)); + return errTbl[err_]; + } +}; + +inline const char *ConvertErrorToString(const Error& err) +{ + return err.what(); +} + +inline void *AlignedMalloc(size_t size, size_t alignment) +{ +#ifdef __MINGW32__ + return __mingw_aligned_malloc(size, alignment); +#elif defined(_WIN32) + return _aligned_malloc(size, alignment); +#else + void *p; + int ret = posix_memalign(&p, alignment, size); + return (ret == 0) ? p : 0; +#endif +} + +inline void AlignedFree(void *p) +{ +#ifdef __MINGW32__ + __mingw_aligned_free(p); +#elif defined(_MSC_VER) + _aligned_free(p); +#else + free(p); +#endif +} + +template +inline const To CastTo(From p) throw() +{ + return (const To)(size_t)(p); +} +namespace inner { + +static const size_t ALIGN_PAGE_SIZE = 4096; + +inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; } +inline bool IsInInt32(uint64 x) { return ~uint64(0x7fffffffu) <= x || x <= 0x7FFFFFFFU; } + +inline uint32 VerifyInInt32(uint64 x) +{ +#ifdef XBYAK64 + if (!IsInInt32(x)) throw Error(ERR_OFFSET_IS_TOO_BIG); +#endif + return static_cast(x); +} + +enum LabelMode { + LasIs, // as is + Labs, // absolute + LaddTop // (addr + top) for mov(reg, label) with AutoGrow +}; + +} // inner + +/* + custom allocator +*/ +struct Allocator { + virtual uint8 *alloc(size_t size) { return reinterpret_cast(AlignedMalloc(size, inner::ALIGN_PAGE_SIZE)); } + virtual void free(uint8 *p) { AlignedFree(p); } + virtual ~Allocator() {} + /* override to return false if you call protect() manually */ + virtual bool useProtect() const { return true; } +}; + +#ifdef XBYAK_USE_MMAP_ALLOCATOR +class MmapAllocator : Allocator { + typedef XBYAK_STD_UNORDERED_MAP SizeList; + SizeList sizeList_; +public: + uint8 *alloc(size_t size) + { + const size_t alignedSizeM1 = inner::ALIGN_PAGE_SIZE - 1; + size = (size + alignedSizeM1) & ~alignedSizeM1; +#ifdef MAP_ANONYMOUS + const int mode = MAP_PRIVATE | MAP_ANONYMOUS; +#elif defined(MAP_ANON) + const int mode = MAP_PRIVATE | MAP_ANON; +#else + #error "not supported" +#endif + void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, mode, -1, 0); + if (p == MAP_FAILED) throw Error(ERR_CANT_ALLOC); + assert(p); + sizeList_[(uintptr_t)p] = size; + return (uint8*)p; + } + void free(uint8 *p) + { + if (p == 0) return; + SizeList::iterator i = sizeList_.find((uintptr_t)p); + if (i == sizeList_.end()) throw Error(ERR_BAD_PARAMETER); + if (munmap((void*)i->first, i->second) < 0) throw Error(ERR_MUNMAP); + sizeList_.erase(i); + } +}; +#endif + +class Address; +class Reg; + +class Operand { + static const uint8 EXT8BIT = 0x20; + unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil + unsigned int kind_:9; + unsigned int bit_:10; +protected: + unsigned int zero_:1; + unsigned int mask_:3; + unsigned int rounding_:3; + void setIdx(int idx) { idx_ = idx; } +public: + enum Kind { + NONE = 0, + MEM = 1 << 0, + REG = 1 << 1, + MMX = 1 << 2, + FPU = 1 << 3, + XMM = 1 << 4, + YMM = 1 << 5, + ZMM = 1 << 6, + OPMASK = 1 << 7, + BNDREG = 1 << 8 + }; + enum Code { +#ifdef XBYAK64 + RAX = 0, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15, + R8D = 8, R9D, R10D, R11D, R12D, R13D, R14D, R15D, + R8W = 8, R9W, R10W, R11W, R12W, R13W, R14W, R15W, + R8B = 8, R9B, R10B, R11B, R12B, R13B, R14B, R15B, + SPL = 4, BPL, SIL, DIL, +#endif + EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + AX = 0, CX, DX, BX, SP, BP, SI, DI, + AL = 0, CL, DL, BL, AH, CH, DH, BH + }; + Operand() : idx_(0), kind_(0), bit_(0), zero_(0), mask_(0), rounding_(0) { } + Operand(int idx, Kind kind, int bit, bool ext8bit = 0) + : idx_(static_cast(idx | (ext8bit ? EXT8BIT : 0))) + , kind_(kind) + , bit_(bit) + , zero_(0), mask_(0), rounding_(0) + { + assert((bit_ & (bit_ - 1)) == 0); // bit must be power of two + } + Kind getKind() const { return static_cast(kind_); } + int getIdx() const { return idx_ & (EXT8BIT - 1); } + bool isNone() const { return kind_ == 0; } + bool isMMX() const { return is(MMX); } + bool isXMM() const { return is(XMM); } + bool isYMM() const { return is(YMM); } + bool isZMM() const { return is(ZMM); } + bool isXMEM() const { return is(XMM | MEM); } + bool isYMEM() const { return is(YMM | MEM); } + bool isZMEM() const { return is(ZMM | MEM); } + bool isOPMASK() const { return is(OPMASK); } + bool isBNDREG() const { return is(BNDREG); } + bool isREG(int bit = 0) const { return is(REG, bit); } + bool isMEM(int bit = 0) const { return is(MEM, bit); } + bool isFPU() const { return is(FPU); } + bool isExt8bit() const { return (idx_ & EXT8BIT) != 0; } + bool isExtIdx() const { return (getIdx() & 8) != 0; } + bool isExtIdx2() const { return (getIdx() & 16) != 0; } + bool hasEvex() const { return isZMM() || isExtIdx2() || getOpmaskIdx() || getRounding(); } + bool hasRex() const { return isExt8bit() || isREG(64) || isExtIdx(); } + bool hasZero() const { return zero_; } + int getOpmaskIdx() const { return mask_; } + int getRounding() const { return rounding_; } + void setKind(Kind kind) + { + if ((kind & (XMM|YMM|ZMM)) == 0) return; + kind_ = kind; + bit_ = kind == XMM ? 128 : kind == YMM ? 256 : 512; + } + void setBit(int bit) { bit_ = bit; } + void setOpmaskIdx(int idx, bool ignore_idx0 = false) + { + if (!ignore_idx0 && idx == 0) throw Error(ERR_K0_IS_INVALID); + if (mask_) throw Error(ERR_OPMASK_IS_ALREADY_SET); + mask_ = idx; + } + void setRounding(int idx) + { + if (rounding_) throw Error(ERR_ROUNDING_IS_ALREADY_SET); + rounding_ = idx; + } + void setZero() { zero_ = true; } + // ah, ch, dh, bh? + bool isHigh8bit() const + { + if (!isBit(8)) return false; + if (isExt8bit()) return false; + const int idx = getIdx(); + return AH <= idx && idx <= BH; + } + // any bit is accetable if bit == 0 + bool is(int kind, uint32 bit = 0) const + { + return (kind == 0 || (kind_ & kind)) && (bit == 0 || (bit_ & bit)); // cf. you can set (8|16) + } + bool isBit(uint32 bit) const { return (bit_ & bit) != 0; } + uint32 getBit() const { return bit_; } + const char *toString() const + { + const int idx = getIdx(); + if (kind_ == REG) { + if (isExt8bit()) { + static const char *tbl[4] = { "spl", "bpl", "sil", "dil" }; + return tbl[idx - 4]; + } + static const char *tbl[4][16] = { + { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, + { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, + { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, + }; + return tbl[bit_ == 8 ? 0 : bit_ == 16 ? 1 : bit_ == 32 ? 2 : 3][idx]; + } else if (isOPMASK()) { + static const char *tbl[8] = { "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" }; + return tbl[idx]; + } else if (isZMM()) { + static const char *tbl[32] = { + "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", + "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31" + }; + return tbl[idx]; + } else if (isYMM()) { + static const char *tbl[32] = { + "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", + "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31" + }; + return tbl[idx]; + } else if (isXMM()) { + static const char *tbl[32] = { + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", + "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31" + }; + return tbl[idx]; + } else if (isMMX()) { + static const char *tbl[8] = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }; + return tbl[idx]; + } else if (isFPU()) { + static const char *tbl[8] = { "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7" }; + return tbl[idx]; + } else if (isBNDREG()) { + static const char *tbl[4] = { "bnd0", "bnd1", "bnd2", "bnd3" }; + return tbl[idx]; + } + throw Error(ERR_INTERNAL); + } + bool isEqualIfNotInherited(const Operand& rhs) const { return idx_ == rhs.idx_ && kind_ == rhs.kind_ && bit_ == rhs.bit_ && zero_ == rhs.zero_ && mask_ == rhs.mask_ && rounding_ == rhs.rounding_; } + bool operator==(const Operand& rhs) const; + bool operator!=(const Operand& rhs) const { return !operator==(rhs); } + const Address& getAddress() const; + const Reg& getReg() const; +}; + +class Label; + +struct Reg8; +struct Reg16; +struct Reg32; +#ifdef XBYAK64 +struct Reg64; +#endif +class Reg : public Operand { +public: + Reg() { } + Reg(int idx, Kind kind, int bit = 0, bool ext8bit = false) : Operand(idx, kind, bit, ext8bit) { } + Reg changeBit(int bit) const { return Reg(getIdx(), getKind(), bit, isExt8bit()); } + uint8 getRexW() const { return isREG(64) ? 8 : 0; } + uint8 getRexR() const { return isExtIdx() ? 4 : 0; } + uint8 getRexX() const { return isExtIdx() ? 2 : 0; } + uint8 getRexB() const { return isExtIdx() ? 1 : 0; } + uint8 getRex(const Reg& base = Reg()) const + { + uint8 rex = getRexW() | getRexR() | base.getRexW() | base.getRexB(); + if (rex || isExt8bit() || base.isExt8bit()) rex |= 0x40; + return rex; + } + Reg8 cvt8() const; + Reg16 cvt16() const; + Reg32 cvt32() const; +#ifdef XBYAK64 + Reg64 cvt64() const; +#endif +}; + +inline const Reg& Operand::getReg() const +{ + assert(!isMEM()); + return static_cast(*this); +} + +struct Reg8 : public Reg { + explicit Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { } +}; + +struct Reg16 : public Reg { + explicit Reg16(int idx = 0) : Reg(idx, Operand::REG, 16) { } +}; + +struct Mmx : public Reg { + explicit Mmx(int idx = 0, Kind kind = Operand::MMX, int bit = 64) : Reg(idx, kind, bit) { } +}; + +struct EvexModifierRounding { + enum { + T_RN_SAE = 1, + T_RD_SAE = 2, + T_RU_SAE = 3, + T_RZ_SAE = 4, + T_SAE = 5 + }; + explicit EvexModifierRounding(int rounding) : rounding(rounding) {} + int rounding; +}; +struct EvexModifierZero{EvexModifierZero() {}}; + +struct Xmm : public Mmx { + explicit Xmm(int idx = 0, Kind kind = Operand::XMM, int bit = 128) : Mmx(idx, kind, bit) { } + Xmm(Kind kind, int idx) : Mmx(idx, kind, kind == XMM ? 128 : kind == YMM ? 256 : 512) { } + Xmm operator|(const EvexModifierRounding& emr) const { Xmm r(*this); r.setRounding(emr.rounding); return r; } + Xmm copyAndSetIdx(int idx) const { Xmm ret(*this); ret.setIdx(idx); return ret; } + Xmm copyAndSetKind(Operand::Kind kind) const { Xmm ret(*this); ret.setKind(kind); return ret; } +}; + +struct Ymm : public Xmm { + explicit Ymm(int idx = 0, Kind kind = Operand::YMM, int bit = 256) : Xmm(idx, kind, bit) { } + Ymm operator|(const EvexModifierRounding& emr) const { Ymm r(*this); r.setRounding(emr.rounding); return r; } +}; + +struct Zmm : public Ymm { + explicit Zmm(int idx = 0) : Ymm(idx, Operand::ZMM, 512) { } + Zmm operator|(const EvexModifierRounding& emr) const { Zmm r(*this); r.setRounding(emr.rounding); return r; } +}; + +struct Opmask : public Reg { + explicit Opmask(int idx = 0) : Reg(idx, Operand::OPMASK, 64) {} +}; + +struct BoundsReg : public Reg { + explicit BoundsReg(int idx = 0) : Reg(idx, Operand::BNDREG, 128) {} +}; + +templateT operator|(const T& x, const Opmask& k) { T r(x); r.setOpmaskIdx(k.getIdx()); return r; } +templateT operator|(const T& x, const EvexModifierZero&) { T r(x); r.setZero(); return r; } +templateT operator|(const T& x, const EvexModifierRounding& emr) { T r(x); r.setRounding(emr.rounding); return r; } + +struct Fpu : public Reg { + explicit Fpu(int idx = 0) : Reg(idx, Operand::FPU, 32) { } +}; + +struct Reg32e : public Reg { + explicit Reg32e(int idx, int bit) : Reg(idx, Operand::REG, bit) {} +}; +struct Reg32 : public Reg32e { + explicit Reg32(int idx = 0) : Reg32e(idx, 32) {} +}; +#ifdef XBYAK64 +struct Reg64 : public Reg32e { + explicit Reg64(int idx = 0) : Reg32e(idx, 64) {} +}; +struct RegRip { + sint64 disp_; + const Label* label_; + bool isAddr_; + explicit RegRip(sint64 disp = 0, const Label* label = 0, bool isAddr = false) : disp_(disp), label_(label), isAddr_(isAddr) {} + friend const RegRip operator+(const RegRip& r, int disp) { + return RegRip(r.disp_ + disp, r.label_, r.isAddr_); + } + friend const RegRip operator-(const RegRip& r, int disp) { + return RegRip(r.disp_ - disp, r.label_, r.isAddr_); + } + friend const RegRip operator+(const RegRip& r, sint64 disp) { + return RegRip(r.disp_ + disp, r.label_, r.isAddr_); + } + friend const RegRip operator-(const RegRip& r, sint64 disp) { + return RegRip(r.disp_ - disp, r.label_, r.isAddr_); + } + friend const RegRip operator+(const RegRip& r, const Label& label) { + if (r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING); + return RegRip(r.disp_, &label); + } + friend const RegRip operator+(const RegRip& r, const void *addr) { + if (r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING); + return RegRip(r.disp_ + (sint64)addr, 0, true); + } +}; +#endif + +inline Reg8 Reg::cvt8() const +{ + const int idx = getIdx(); + if (isBit(8)) return Reg8(idx, isExt8bit()); +#ifdef XBYAK32 + if (idx >= 4) throw Error(ERR_CANT_CONVERT); +#endif + return Reg8(idx, 4 <= idx && idx < 8); +} + +inline Reg16 Reg::cvt16() const +{ + const int idx = getIdx(); + if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT); + return Reg16(idx); +} + +inline Reg32 Reg::cvt32() const +{ + const int idx = getIdx(); + if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT); + return Reg32(idx); +} + +#ifdef XBYAK64 +inline Reg64 Reg::cvt64() const +{ + const int idx = getIdx(); + if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT); + return Reg64(idx); +} +#endif + +#ifndef XBYAK_DISABLE_SEGMENT +// not derived from Reg +class Segment { + int idx_; +public: + enum { + es, cs, ss, ds, fs, gs + }; + explicit Segment(int idx) : idx_(idx) { assert(0 <= idx_ && idx_ < 6); } + int getIdx() const { return idx_; } + const char *toString() const + { + static const char tbl[][3] = { + "es", "cs", "ss", "ds", "fs", "gs" + }; + return tbl[idx_]; + } +}; +#endif + +class RegExp { +public: +#ifdef XBYAK64 + enum { i32e = 32 | 64 }; +#else + enum { i32e = 32 }; +#endif + RegExp(size_t disp = 0) : scale_(0), disp_(disp) { } + RegExp(const Reg& r, int scale = 1) + : scale_(scale) + , disp_(0) + { + if (!r.isREG(i32e) && !r.is(Reg::XMM|Reg::YMM|Reg::ZMM)) throw Error(ERR_BAD_SIZE_OF_REGISTER); + if (scale == 0) return; + if (scale != 1 && scale != 2 && scale != 4 && scale != 8) throw Error(ERR_BAD_SCALE); + if (r.getBit() >= 128 || scale != 1) { // xmm/ymm is always index + index_ = r; + } else { + base_ = r; + } + } + bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); } + RegExp optimize() const + { + RegExp exp = *this; + // [reg * 2] => [reg + reg] + if (index_.isBit(i32e) && !base_.getBit() && scale_ == 2) { + exp.base_ = index_; + exp.scale_ = 1; + } + return exp; + } + bool operator==(const RegExp& rhs) const + { + return base_ == rhs.base_ && index_ == rhs.index_ && disp_ == rhs.disp_ && scale_ == rhs.scale_; + } + const Reg& getBase() const { return base_; } + const Reg& getIndex() const { return index_; } + int getScale() const { return scale_; } + size_t getDisp() const { return disp_; } + void verify() const + { + if (base_.getBit() >= 128) throw Error(ERR_BAD_SIZE_OF_REGISTER); + if (index_.getBit() && index_.getBit() <= 64) { + if (index_.getIdx() == Operand::ESP) throw Error(ERR_ESP_CANT_BE_INDEX); + if (base_.getBit() && base_.getBit() != index_.getBit()) throw Error(ERR_BAD_SIZE_OF_REGISTER); + } + } + friend RegExp operator+(const RegExp& a, const RegExp& b); + friend RegExp operator-(const RegExp& e, size_t disp); + uint8 getRex() const + { + uint8 rex = index_.getRexX() | base_.getRexB(); + return rex ? uint8(rex | 0x40) : 0; + } +private: + /* + [base_ + index_ * scale_ + disp_] + base : Reg32e, index : Reg32e(w/o esp), Xmm, Ymm + */ + Reg base_; + Reg index_; + int scale_; + size_t disp_; +}; + +inline RegExp operator+(const RegExp& a, const RegExp& b) +{ + if (a.index_.getBit() && b.index_.getBit()) throw Error(ERR_BAD_ADDRESSING); + RegExp ret = a; + if (!ret.index_.getBit()) { ret.index_ = b.index_; ret.scale_ = b.scale_; } + if (b.base_.getBit()) { + if (ret.base_.getBit()) { + if (ret.index_.getBit()) throw Error(ERR_BAD_ADDRESSING); + // base + base => base + index * 1 + ret.index_ = b.base_; + // [reg + esp] => [esp + reg] + if (ret.index_.getIdx() == Operand::ESP) std::swap(ret.base_, ret.index_); + ret.scale_ = 1; + } else { + ret.base_ = b.base_; + } + } + ret.disp_ += b.disp_; + return ret; +} +inline RegExp operator*(const Reg& r, int scale) +{ + return RegExp(r, scale); +} +inline RegExp operator-(const RegExp& e, size_t disp) +{ + RegExp ret = e; + ret.disp_ -= disp; + return ret; +} + +// 2nd parameter for constructor of CodeArray(maxSize, userPtr, alloc) +void *const AutoGrow = (void*)1; //-V566 +void *const DontSetProtectRWE = (void*)2; //-V566 + +class CodeArray { + enum Type { + USER_BUF = 1, // use userPtr(non alignment, non protect) + ALLOC_BUF, // use new(alignment, protect) + AUTO_GROW // automatically move and grow memory if necessary + }; + CodeArray(const CodeArray& rhs); + void operator=(const CodeArray&); + bool isAllocType() const { return type_ == ALLOC_BUF || type_ == AUTO_GROW; } + struct AddrInfo { + size_t codeOffset; // position to write + size_t jmpAddr; // value to write + int jmpSize; // size of jmpAddr + inner::LabelMode mode; + AddrInfo(size_t _codeOffset, size_t _jmpAddr, int _jmpSize, inner::LabelMode _mode) + : codeOffset(_codeOffset), jmpAddr(_jmpAddr), jmpSize(_jmpSize), mode(_mode) {} + uint64 getVal(const uint8 *top) const + { + uint64 disp = (mode == inner::LaddTop) ? jmpAddr + size_t(top) : (mode == inner::LasIs) ? jmpAddr : jmpAddr - size_t(top); + if (jmpSize == 4) disp = inner::VerifyInInt32(disp); + return disp; + } + }; + typedef std::list AddrInfoList; + AddrInfoList addrInfoList_; + const Type type_; +#ifdef XBYAK_USE_MMAP_ALLOCATOR + MmapAllocator defaultAllocator_; +#else + Allocator defaultAllocator_; +#endif + Allocator *alloc_; +protected: + size_t maxSize_; + uint8 *top_; + size_t size_; + bool isCalledCalcJmpAddress_; + + bool useProtect() const { return alloc_->useProtect(); } + /* + allocate new memory and copy old data to the new area + */ + void growMemory() + { + const size_t newSize = (std::max)(DEFAULT_MAX_CODE_SIZE, maxSize_ * 2); + uint8 *newTop = alloc_->alloc(newSize); + if (newTop == 0) throw Error(ERR_CANT_ALLOC); + for (size_t i = 0; i < size_; i++) newTop[i] = top_[i]; + alloc_->free(top_); + top_ = newTop; + maxSize_ = newSize; + } + /* + calc jmp address for AutoGrow mode + */ + void calcJmpAddress() + { + if (isCalledCalcJmpAddress_) return; + for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) { + uint64 disp = i->getVal(top_); + rewrite(i->codeOffset, disp, i->jmpSize); + } + isCalledCalcJmpAddress_ = true; + } +public: + enum ProtectMode { + PROTECT_RW = 0, // read/write + PROTECT_RWE = 1, // read/write/exec + PROTECT_RE = 2 // read/exec + }; + explicit CodeArray(size_t maxSize, void *userPtr = 0, Allocator *allocator = 0) + : type_(userPtr == AutoGrow ? AUTO_GROW : (userPtr == 0 || userPtr == DontSetProtectRWE) ? ALLOC_BUF : USER_BUF) + , alloc_(allocator ? allocator : (Allocator*)&defaultAllocator_) + , maxSize_(maxSize) + , top_(type_ == USER_BUF ? reinterpret_cast(userPtr) : alloc_->alloc((std::max)(maxSize, 1))) + , size_(0) + , isCalledCalcJmpAddress_(false) + { + if (maxSize_ > 0 && top_ == 0) throw Error(ERR_CANT_ALLOC); + if ((type_ == ALLOC_BUF && userPtr != DontSetProtectRWE && useProtect()) && !setProtectMode(PROTECT_RWE, false)) { + alloc_->free(top_); + throw Error(ERR_CANT_PROTECT); + } + } + virtual ~CodeArray() + { + if (isAllocType()) { + if (useProtect()) setProtectModeRW(false); + alloc_->free(top_); + } + } + bool setProtectMode(ProtectMode mode, bool throwException = true) + { + bool isOK = protect(top_, maxSize_, mode); + if (isOK) return true; + if (throwException) throw Error(ERR_CANT_PROTECT); + return false; + } + bool setProtectModeRE(bool throwException = true) { return setProtectMode(PROTECT_RE, throwException); } + bool setProtectModeRW(bool throwException = true) { return setProtectMode(PROTECT_RW, throwException); } + void resetSize() + { + size_ = 0; + addrInfoList_.clear(); + isCalledCalcJmpAddress_ = false; + } + void db(int code) + { + if (size_ >= maxSize_) { + if (type_ == AUTO_GROW) { + growMemory(); + } else { + throw Error(ERR_CODE_IS_TOO_BIG); + } + } + top_[size_++] = static_cast(code); + } + void db(const uint8 *code, size_t codeSize) + { + for (size_t i = 0; i < codeSize; i++) db(code[i]); + } + void db(uint64 code, size_t codeSize) + { + if (codeSize > 8) throw Error(ERR_BAD_PARAMETER); + for (size_t i = 0; i < codeSize; i++) db(static_cast(code >> (i * 8))); + } + void dw(uint32 code) { db(code, 2); } + void dd(uint32 code) { db(code, 4); } + void dq(uint64 code) { db(code, 8); } + const uint8 *getCode() const { return top_; } + template + const F getCode() const { return reinterpret_cast(top_); } + const uint8 *getCurr() const { return &top_[size_]; } + template + const F getCurr() const { return reinterpret_cast(&top_[size_]); } + size_t getSize() const { return size_; } + void setSize(size_t size) + { + if (size > maxSize_) throw Error(ERR_OFFSET_IS_TOO_BIG); + size_ = size; + } + void dump() const + { + const uint8 *p = getCode(); + size_t bufSize = getSize(); + size_t remain = bufSize; + for (int i = 0; i < 4; i++) { + size_t disp = 16; + if (remain < 16) { + disp = remain; + } + for (size_t j = 0; j < 16; j++) { + if (j < disp) { + printf("%02X", p[i * 16 + j]); + } + } + putchar('\n'); + remain -= disp; + if (remain == 0) { + break; + } + } + } + /* + @param offset [in] offset from top + @param disp [in] offset from the next of jmp + @param size [in] write size(1, 2, 4, 8) + */ + void rewrite(size_t offset, uint64 disp, size_t size) + { + assert(offset < maxSize_); + if (size != 1 && size != 2 && size != 4 && size != 8) throw Error(ERR_BAD_PARAMETER); + uint8 *const data = top_ + offset; + for (size_t i = 0; i < size; i++) { + data[i] = static_cast(disp >> (i * 8)); + } + } + void save(size_t offset, size_t val, int size, inner::LabelMode mode) + { + addrInfoList_.push_back(AddrInfo(offset, val, size, mode)); + } + bool isAutoGrow() const { return type_ == AUTO_GROW; } + bool isCalledCalcJmpAddress() const { return isCalledCalcJmpAddress_; } + /** + change exec permission of memory + @param addr [in] buffer address + @param size [in] buffer size + @param protectMode [in] mode(RW/RWE/RE) + @return true(success), false(failure) + */ + static inline bool protect(const void *addr, size_t size, int protectMode) + { +#if defined(_WIN32) + const DWORD c_rw = PAGE_READWRITE; + const DWORD c_rwe = PAGE_EXECUTE_READWRITE; + const DWORD c_re = PAGE_EXECUTE_READ; + DWORD mode; +#else + const int c_rw = PROT_READ | PROT_WRITE; + const int c_rwe = PROT_READ | PROT_WRITE | PROT_EXEC; + const int c_re = PROT_READ | PROT_EXEC; + int mode; +#endif + switch (protectMode) { + case PROTECT_RW: mode = c_rw; break; + case PROTECT_RWE: mode = c_rwe; break; + case PROTECT_RE: mode = c_re; break; + default: + return false; + } +#if defined(_WIN32) + DWORD oldProtect; + return VirtualProtect(const_cast(addr), size, mode, &oldProtect) != 0; +#elif defined(__GNUC__) + size_t pageSize = sysconf(_SC_PAGESIZE); + size_t iaddr = reinterpret_cast(addr); + size_t roundAddr = iaddr & ~(pageSize - static_cast(1)); +#ifndef NDEBUG + if (pageSize != 4096) fprintf(stderr, "large page(%zd) is used. not tested enough.\n", pageSize); +#endif + return mprotect(reinterpret_cast(roundAddr), size + (iaddr - roundAddr), mode) == 0; +#else + return true; +#endif + } + /** + get aligned memory pointer + @param addr [in] address + @param alignedSize [in] power of two + @return aligned addr by alingedSize + */ + static inline uint8 *getAlignedAddress(uint8 *addr, size_t alignedSize = 16) + { + return reinterpret_cast((reinterpret_cast(addr) + alignedSize - 1) & ~(alignedSize - static_cast(1))); + } +}; + +class Address : public Operand { +public: + enum Mode { + M_ModRM, + M_64bitDisp, + M_rip, + M_ripAddr + }; + Address(uint32 sizeBit, bool broadcast, const RegExp& e) + : Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), broadcast_(broadcast) + { + e_.verify(); + } +#ifdef XBYAK64 + explicit Address(size_t disp) + : Operand(0, MEM, 64), e_(disp), label_(0), mode_(M_64bitDisp), broadcast_(false){ } + Address(uint32 sizeBit, bool broadcast, const RegRip& addr) + : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), broadcast_(broadcast) { } +#endif + RegExp getRegExp(bool optimize = true) const + { + return optimize ? e_.optimize() : e_; + } + Mode getMode() const { return mode_; } + bool is32bit() const { return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; } + bool isOnlyDisp() const { return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax + size_t getDisp() const { return e_.getDisp(); } + uint8 getRex() const + { + if (mode_ != M_ModRM) return 0; + return getRegExp().getRex(); + } + bool is64bitDisp() const { return mode_ == M_64bitDisp; } // for moffset + bool isBroadcast() const { return broadcast_; } + const Label* getLabel() const { return label_; } + bool operator==(const Address& rhs) const + { + return getBit() == rhs.getBit() && e_ == rhs.e_ && label_ == rhs.label_ && mode_ == rhs.mode_ && broadcast_ == rhs.broadcast_; + } + bool operator!=(const Address& rhs) const { return !operator==(rhs); } + bool isVsib() const { return e_.isVsib(); } +private: + RegExp e_; + const Label* label_; + Mode mode_; + bool broadcast_; +}; + +inline const Address& Operand::getAddress() const +{ + assert(isMEM()); + return static_cast(*this); +} + +inline bool Operand::operator==(const Operand& rhs) const +{ + if (isMEM() && rhs.isMEM()) return this->getAddress() == rhs.getAddress(); + return isEqualIfNotInherited(rhs); +} + +class AddressFrame { + void operator=(const AddressFrame&); + AddressFrame(const AddressFrame&); +public: + const uint32 bit_; + const bool broadcast_; + explicit AddressFrame(uint32 bit, bool broadcast = false) : bit_(bit), broadcast_(broadcast) { } + Address operator[](const RegExp& e) const + { + return Address(bit_, broadcast_, e); + } + Address operator[](const void *disp) const + { + return Address(bit_, broadcast_, RegExp(reinterpret_cast(disp))); + } +#ifdef XBYAK64 + Address operator[](uint64 disp) const { return Address(disp); } + Address operator[](const RegRip& addr) const { return Address(bit_, broadcast_, addr); } +#endif +}; + +struct JmpLabel { + size_t endOfJmp; /* offset from top to the end address of jmp */ + int jmpSize; + inner::LabelMode mode; + size_t disp; // disp for [rip + disp] + explicit JmpLabel(size_t endOfJmp = 0, int jmpSize = 0, inner::LabelMode mode = inner::LasIs, size_t disp = 0) + : endOfJmp(endOfJmp), jmpSize(jmpSize), mode(mode), disp(disp) + { + } +}; + +class LabelManager; + +class Label { + mutable LabelManager *mgr; + mutable int id; + friend class LabelManager; +public: + Label() : mgr(0), id(0) {} + Label(const Label& rhs); + Label& operator=(const Label& rhs); + ~Label(); + void clear() { mgr = 0; id = 0; } + int getId() const { return id; } + const uint8 *getAddress() const; + + // backward compatibility + static inline std::string toStr(int num) + { + char buf[16]; +#if defined(_MSC_VER) && (_MSC_VER < 1900) + _snprintf_s +#else + snprintf +#endif + (buf, sizeof(buf), ".%08x", num); + return buf; + } +}; + +class LabelManager { + // for string label + struct SlabelVal { + size_t offset; + SlabelVal(size_t offset) : offset(offset) {} + }; + typedef XBYAK_STD_UNORDERED_MAP SlabelDefList; + typedef XBYAK_STD_UNORDERED_MULTIMAP SlabelUndefList; + struct SlabelState { + SlabelDefList defList; + SlabelUndefList undefList; + }; + typedef std::list StateList; + // for Label class + struct ClabelVal { + ClabelVal(size_t offset = 0) : offset(offset), refCount(1) {} + size_t offset; + int refCount; + }; + typedef XBYAK_STD_UNORDERED_MAP ClabelDefList; + typedef XBYAK_STD_UNORDERED_MULTIMAP ClabelUndefList; + typedef XBYAK_STD_UNORDERED_SET LabelPtrList; + + CodeArray *base_; + // global : stateList_.front(), local : stateList_.back() + StateList stateList_; + mutable int labelId_; + ClabelDefList clabelDefList_; + ClabelUndefList clabelUndefList_; + LabelPtrList labelPtrList_; + + int getId(const Label& label) const + { + if (label.id == 0) label.id = labelId_++; + return label.id; + } + template + void define_inner(DefList& defList, UndefList& undefList, const T& labelId, size_t addrOffset) + { + // add label + typename DefList::value_type item(labelId, addrOffset); + std::pair ret = defList.insert(item); + if (!ret.second) throw Error(ERR_LABEL_IS_REDEFINED); + // search undefined label + for (;;) { + typename UndefList::iterator itr = undefList.find(labelId); + if (itr == undefList.end()) break; + const JmpLabel *jmp = &itr->second; + const size_t offset = jmp->endOfJmp - jmp->jmpSize; + size_t disp; + if (jmp->mode == inner::LaddTop) { + disp = addrOffset; + } else if (jmp->mode == inner::Labs) { + disp = size_t(base_->getCurr()); + } else { + disp = addrOffset - jmp->endOfJmp + jmp->disp; +#ifdef XBYAK64 + if (jmp->jmpSize <= 4 && !inner::IsInInt32(disp)) throw Error(ERR_OFFSET_IS_TOO_BIG); +#endif + if (jmp->jmpSize == 1 && !inner::IsInDisp8((uint32)disp)) throw Error(ERR_LABEL_IS_TOO_FAR); + } + if (base_->isAutoGrow()) { + base_->save(offset, disp, jmp->jmpSize, jmp->mode); + } else { + base_->rewrite(offset, disp, jmp->jmpSize); + } + undefList.erase(itr); + } + } + template + bool getOffset_inner(const DefList& defList, size_t *offset, const T& label) const + { + typename DefList::const_iterator i = defList.find(label); + if (i == defList.end()) return false; + *offset = i->second.offset; + return true; + } + friend class Label; + void incRefCount(int id, Label *label) + { + clabelDefList_[id].refCount++; + labelPtrList_.insert(label); + } + void decRefCount(int id, Label *label) + { + labelPtrList_.erase(label); + ClabelDefList::iterator i = clabelDefList_.find(id); + if (i == clabelDefList_.end()) return; + if (i->second.refCount == 1) { + clabelDefList_.erase(id); + } else { + --i->second.refCount; + } + } + template + bool hasUndefinedLabel_inner(const T& list) const + { +#ifndef NDEBUG + for (typename T::const_iterator i = list.begin(); i != list.end(); ++i) { + std::cerr << "undefined label:" << i->first << std::endl; + } +#endif + return !list.empty(); + } + // detach all labels linked to LabelManager + void resetLabelPtrList() + { + for (LabelPtrList::iterator i = labelPtrList_.begin(), ie = labelPtrList_.end(); i != ie; ++i) { + (*i)->clear(); + } + labelPtrList_.clear(); + } +public: + LabelManager() + { + reset(); + } + ~LabelManager() + { + resetLabelPtrList(); + } + void reset() + { + base_ = 0; + labelId_ = 1; + stateList_.clear(); + stateList_.push_back(SlabelState()); + stateList_.push_back(SlabelState()); + clabelDefList_.clear(); + clabelUndefList_.clear(); + resetLabelPtrList(); + } + void enterLocal() + { + stateList_.push_back(SlabelState()); + } + void leaveLocal() + { + if (stateList_.size() <= 2) throw Error(ERR_UNDER_LOCAL_LABEL); + if (hasUndefinedLabel_inner(stateList_.back().undefList)) throw Error(ERR_LABEL_IS_NOT_FOUND); + stateList_.pop_back(); + } + void set(CodeArray *base) { base_ = base; } + void defineSlabel(std::string label) + { + if (label == "@b" || label == "@f") throw Error(ERR_BAD_LABEL_STR); + if (label == "@@") { + SlabelDefList& defList = stateList_.front().defList; + SlabelDefList::iterator i = defList.find("@f"); + if (i != defList.end()) { + defList.erase(i); + label = "@b"; + } else { + i = defList.find("@b"); + if (i != defList.end()) { + defList.erase(i); + } + label = "@f"; + } + } + SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front(); + define_inner(st.defList, st.undefList, label, base_->getSize()); + } + void defineClabel(Label& label) + { + define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize()); + label.mgr = this; + labelPtrList_.insert(&label); + } + void assign(Label& dst, const Label& src) + { + ClabelDefList::const_iterator i = clabelDefList_.find(src.id); + if (i == clabelDefList_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L); + define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset); + dst.mgr = this; + labelPtrList_.insert(&dst); + } + bool getOffset(size_t *offset, std::string& label) const + { + const SlabelDefList& defList = stateList_.front().defList; + if (label == "@b") { + if (defList.find("@f") != defList.end()) { + label = "@f"; + } else if (defList.find("@b") == defList.end()) { + throw Error(ERR_LABEL_IS_NOT_FOUND); + } + } else if (label == "@f") { + if (defList.find("@f") != defList.end()) { + label = "@b"; + } + } + const SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front(); + return getOffset_inner(st.defList, offset, label); + } + bool getOffset(size_t *offset, const Label& label) const + { + return getOffset_inner(clabelDefList_, offset, getId(label)); + } + void addUndefinedLabel(const std::string& label, const JmpLabel& jmp) + { + SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front(); + st.undefList.insert(SlabelUndefList::value_type(label, jmp)); + } + void addUndefinedLabel(const Label& label, const JmpLabel& jmp) + { + clabelUndefList_.insert(ClabelUndefList::value_type(label.id, jmp)); + } + bool hasUndefSlabel() const + { + for (StateList::const_iterator i = stateList_.begin(), ie = stateList_.end(); i != ie; ++i) { + if (hasUndefinedLabel_inner(i->undefList)) return true; + } + return false; + } + bool hasUndefClabel() const { return hasUndefinedLabel_inner(clabelUndefList_); } + const uint8 *getCode() const { return base_->getCode(); } + bool isReady() const { return !base_->isAutoGrow() || base_->isCalledCalcJmpAddress(); } +}; + +inline Label::Label(const Label& rhs) +{ + id = rhs.id; + mgr = rhs.mgr; + if (mgr) mgr->incRefCount(id, this); +} +inline Label& Label::operator=(const Label& rhs) +{ + if (id) throw Error(ERR_LABEL_IS_ALREADY_SET_BY_L); + id = rhs.id; + mgr = rhs.mgr; + if (mgr) mgr->incRefCount(id, this); + return *this; +} +inline Label::~Label() +{ + if (id && mgr) mgr->decRefCount(id, this); +} +inline const uint8* Label::getAddress() const +{ + if (mgr == 0 || !mgr->isReady()) return 0; + size_t offset; + if (!mgr->getOffset(&offset, *this)) return 0; + return mgr->getCode() + offset; +} + +class CodeGenerator : public CodeArray { +public: + enum LabelType { + T_SHORT, + T_NEAR, + T_AUTO // T_SHORT if possible + }; +private: + CodeGenerator operator=(const CodeGenerator&); // don't call +#ifdef XBYAK64 + enum { i32e = 32 | 64, BIT = 64 }; + static const size_t dummyAddr = (size_t(0x11223344) << 32) | 55667788; + typedef Reg64 NativeReg; +#else + enum { i32e = 32, BIT = 32 }; + static const size_t dummyAddr = 0x12345678; + typedef Reg32 NativeReg; +#endif + // (XMM, XMM|MEM) + static inline bool isXMM_XMMorMEM(const Operand& op1, const Operand& op2) + { + return op1.isXMM() && (op2.isXMM() || op2.isMEM()); + } + // (MMX, MMX|MEM) or (XMM, XMM|MEM) + static inline bool isXMMorMMX_MEM(const Operand& op1, const Operand& op2) + { + return (op1.isMMX() && (op2.isMMX() || op2.isMEM())) || isXMM_XMMorMEM(op1, op2); + } + // (XMM, MMX|MEM) + static inline bool isXMM_MMXorMEM(const Operand& op1, const Operand& op2) + { + return op1.isXMM() && (op2.isMMX() || op2.isMEM()); + } + // (MMX, XMM|MEM) + static inline bool isMMX_XMMorMEM(const Operand& op1, const Operand& op2) + { + return op1.isMMX() && (op2.isXMM() || op2.isMEM()); + } + // (XMM, REG32|MEM) + static inline bool isXMM_REG32orMEM(const Operand& op1, const Operand& op2) + { + return op1.isXMM() && (op2.isREG(i32e) || op2.isMEM()); + } + // (REG32, XMM|MEM) + static inline bool isREG32_XMMorMEM(const Operand& op1, const Operand& op2) + { + return op1.isREG(i32e) && (op2.isXMM() || op2.isMEM()); + } + // (REG32, REG32|MEM) + static inline bool isREG32_REG32orMEM(const Operand& op1, const Operand& op2) + { + return op1.isREG(i32e) && ((op2.isREG(i32e) && op1.getBit() == op2.getBit()) || op2.isMEM()); + } + void rex(const Operand& op1, const Operand& op2 = Operand()) + { + uint8 rex = 0; + const Operand *p1 = &op1, *p2 = &op2; + if (p1->isMEM()) std::swap(p1, p2); + if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION); + if (p2->isMEM()) { + const Address& addr = p2->getAddress(); + if (BIT == 64 && addr.is32bit()) db(0x67); + rex = addr.getRex() | p1->getReg().getRex(); + } else { + // ModRM(reg, base); + rex = op2.getReg().getRex(op1.getReg()); + } + // except movsx(16bit, 32/64bit) + if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66); + if (rex) db(rex); + } + enum AVXtype { + // low 3 bit + T_N1 = 1, + T_N2 = 2, + T_N4 = 3, + T_N8 = 4, + T_N16 = 5, + T_N32 = 6, + T_NX_MASK = 7, + // + T_N_VL = 1 << 3, // N * (1, 2, 4) for VL + T_DUP = 1 << 4, // N = (8, 32, 64) + T_66 = 1 << 5, + T_F3 = 1 << 6, + T_F2 = 1 << 7, + T_0F = 1 << 8, + T_0F38 = 1 << 9, + T_0F3A = 1 << 10, + T_L0 = 1 << 11, + T_L1 = 1 << 12, + T_W0 = 1 << 13, + T_W1 = 1 << 14, + T_EW0 = 1 << 15, + T_EW1 = 1 << 16, + T_YMM = 1 << 17, // support YMM, ZMM + T_EVEX = 1 << 18, + T_ER_X = 1 << 19, // xmm{er} + T_ER_Y = 1 << 20, // ymm{er} + T_ER_Z = 1 << 21, // zmm{er} + T_SAE_X = 1 << 22, // xmm{sae} + T_SAE_Y = 1 << 23, // ymm{sae} + T_SAE_Z = 1 << 24, // zmm{sae} + T_MUST_EVEX = 1 << 25, // contains T_EVEX + T_B32 = 1 << 26, // m32bcst + T_B64 = 1 << 27, // m64bcst + T_M_K = 1 << 28, // mem{k} + T_VSIB = 1 << 29, + T_MEM_EVEX = 1 << 30, // use evex if mem + T_XXX + }; + void vex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false) + { + int w = (type & T_W1) ? 1 : 0; + bool is256 = (type & T_L1) ? true : (type & T_L0) ? false : reg.isYMM(); + bool r = reg.isExtIdx(); + bool b = base.isExtIdx(); + int idx = v ? v->getIdx() : 0; + if ((idx | reg.getIdx() | base.getIdx()) >= 16) throw Error(ERR_BAD_COMBINATION); + uint32 pp = (type & T_66) ? 1 : (type & T_F3) ? 2 : (type & T_F2) ? 3 : 0; + uint32 vvvv = (((~idx) & 15) << 3) | (is256 ? 4 : 0) | pp; + if (!b && !x && !w && (type & T_0F)) { + db(0xC5); db((r ? 0 : 0x80) | vvvv); + } else { + uint32 mmmm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0; + db(0xC4); db((r ? 0 : 0x80) | (x ? 0 : 0x40) | (b ? 0 : 0x20) | mmmm); db((w << 7) | vvvv); + } + db(code); + } + void verifySAE(const Reg& r, int type) const + { + if (((type & T_SAE_X) && r.isXMM()) || ((type & T_SAE_Y) && r.isYMM()) || ((type & T_SAE_Z) && r.isZMM())) return; + throw Error(ERR_SAE_IS_INVALID); + } + void verifyER(const Reg& r, int type) const + { + if (((type & T_ER_X) && r.isXMM()) || ((type & T_ER_Y) && r.isYMM()) || ((type & T_ER_Z) && r.isZMM())) return; + throw Error(ERR_ER_IS_INVALID); + } + // (a, b, c) contains non zero two or three values then err + int verifyDuplicate(int a, int b, int c, int err) + { + int v = a | b | c; + if ((a > 0 && a != v) + (b > 0 && b != v) + (c > 0 && c != v) > 0) return Error(err); + return v; + } + int evex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false, bool b = false, int aaa = 0, uint32 VL = 0, bool Hi16Vidx = false) + { + if (!(type & (T_EVEX | T_MUST_EVEX))) throw Error(ERR_EVEX_IS_INVALID); + int w = (type & T_EW1) ? 1 : 0; + uint32 mm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0; + uint32 pp = (type & T_66) ? 1 : (type & T_F3) ? 2 : (type & T_F2) ? 3 : 0; + + int idx = v ? v->getIdx() : 0; + uint32 vvvv = ~idx; + + bool R = !reg.isExtIdx(); + bool X = x ? false : !base.isExtIdx2(); + bool B = !base.isExtIdx(); + bool Rp = !reg.isExtIdx2(); + int LL; + int rounding = verifyDuplicate(reg.getRounding(), base.getRounding(), v ? v->getRounding() : 0, ERR_ROUNDING_IS_ALREADY_SET); + int disp8N = 1; + if (rounding) { + if (rounding == EvexModifierRounding::T_SAE) { + verifySAE(base, type); LL = 0; + } else { + verifyER(base, type); LL = rounding - 1; + } + b = true; + } else { + if (v) VL = (std::max)(VL, v->getBit()); + VL = (std::max)((std::max)(reg.getBit(), base.getBit()), VL); + LL = (VL == 512) ? 2 : (VL == 256) ? 1 : 0; + if (b) { + disp8N = (type & T_B32) ? 4 : 8; + } else if (type & T_DUP) { + disp8N = VL == 128 ? 8 : VL == 256 ? 32 : 64; + } else { + if ((type & (T_NX_MASK | T_N_VL)) == 0) { + type |= T_N16 | T_N_VL; // default + } + int low = type & T_NX_MASK; + if (low > 0) { + disp8N = 1 << (low - 1); + if (type & T_N_VL) disp8N *= (VL == 512 ? 4 : VL == 256 ? 2 : 1); + } + } + } + bool Vp = !((v ? v->isExtIdx2() : 0) | Hi16Vidx); + bool z = reg.hasZero() || base.hasZero() || (v ? v->hasZero() : false); + if (aaa == 0) aaa = verifyDuplicate(base.getOpmaskIdx(), reg.getOpmaskIdx(), (v ? v->getOpmaskIdx() : 0), ERR_OPMASK_IS_ALREADY_SET); + db(0x62); + db((R ? 0x80 : 0) | (X ? 0x40 : 0) | (B ? 0x20 : 0) | (Rp ? 0x10 : 0) | (mm & 3)); + db((w == 1 ? 0x80 : 0) | ((vvvv & 15) << 3) | 4 | (pp & 3)); + db((z ? 0x80 : 0) | ((LL & 3) << 5) | (b ? 0x10 : 0) | (Vp ? 8 : 0) | (aaa & 7)); + db(code); + return disp8N; + } + void setModRM(int mod, int r1, int r2) + { + db(static_cast((mod << 6) | ((r1 & 7) << 3) | (r2 & 7))); + } + void setSIB(const RegExp& e, int reg, int disp8N = 0) + { + size_t disp64 = e.getDisp(); +#ifdef XBYAK64 + size_t high = disp64 >> 32; + if (high != 0 && high != 0xFFFFFFFF) throw Error(ERR_OFFSET_IS_TOO_BIG); +#endif + uint32 disp = static_cast(disp64); + const Reg& base = e.getBase(); + const Reg& index = e.getIndex(); + const int baseIdx = base.getIdx(); + const int baseBit = base.getBit(); + const int indexBit = index.getBit(); + enum { + mod00 = 0, mod01 = 1, mod10 = 2 + }; + int mod = mod10; // disp32 + if (!baseBit || ((baseIdx & 7) != Operand::EBP && disp == 0)) { + mod = mod00; + } else { + if (disp8N == 0) { + if (inner::IsInDisp8(disp)) { + mod = mod01; + } + } else { + // disp must be casted to signed + uint32 t = static_cast(static_cast(disp) / disp8N); + if ((disp % disp8N) == 0 && inner::IsInDisp8(t)) { + disp = t; + mod = mod01; + } + } + } + const int newBaseIdx = baseBit ? (baseIdx & 7) : Operand::EBP; + /* ModR/M = [2:3:3] = [Mod:reg/code:R/M] */ + bool hasSIB = indexBit || (baseIdx & 7) == Operand::ESP; +#ifdef XBYAK64 + if (!baseBit && !indexBit) hasSIB = true; +#endif + if (hasSIB) { + setModRM(mod, reg, Operand::ESP); + /* SIB = [2:3:3] = [SS:index:base(=rm)] */ + const int idx = indexBit ? (index.getIdx() & 7) : Operand::ESP; + const int scale = e.getScale(); + const int SS = (scale == 8) ? 3 : (scale == 4) ? 2 : (scale == 2) ? 1 : 0; + setModRM(SS, idx, newBaseIdx); + } else { + setModRM(mod, reg, newBaseIdx); + } + if (mod == mod01) { + db(disp); + } else if (mod == mod10 || (mod == mod00 && !baseBit)) { + dd(disp); + } + } + LabelManager labelMgr_; + bool isInDisp16(uint32 x) const { return 0xFFFF8000 <= x || x <= 0x7FFF; } + void opModR(const Reg& reg1, const Reg& reg2, int code0, int code1 = NONE, int code2 = NONE) + { + rex(reg2, reg1); + db(code0 | (reg1.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2); + setModRM(3, reg1.getIdx(), reg2.getIdx()); + } + void opModM(const Address& addr, const Reg& reg, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0) + { + if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP); + rex(addr, reg); + db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2); + opAddr(addr, reg.getIdx(), immSize); + } + void opMIB(const Address& addr, const Reg& reg, int code0, int code1) + { + if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP); + if (addr.getMode() != Address::M_ModRM) throw Error(ERR_INVALID_MIB_ADDRESS); + if (BIT == 64 && addr.is32bit()) db(0x67); + const RegExp& regExp = addr.getRegExp(false); + uint8 rex = regExp.getRex(); + if (rex) db(rex); + db(code0); db(code1); + setSIB(regExp, reg.getIdx()); + } + void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref) + { + const int shortJmpSize = 2; + const int longHeaderSize = longPref ? 2 : 1; + const int longJmpSize = longHeaderSize + 4; + if (type != T_NEAR && inner::IsInDisp8(disp - shortJmpSize)) { + db(shortCode); db(disp - shortJmpSize); + } else { + if (type == T_SHORT) throw Error(ERR_LABEL_IS_TOO_FAR); + if (longPref) db(longPref); + db(longCode); dd(disp - longJmpSize); + } + } + template + void opJmp(T& label, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref) + { + if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */ + size_t offset = 0; + if (labelMgr_.getOffset(&offset, label)) { /* label exists */ + makeJmp(inner::VerifyInInt32(offset - size_), type, shortCode, longCode, longPref); + } else { + int jmpSize = 0; + if (type == T_NEAR) { + jmpSize = 4; + if (longPref) db(longPref); + db(longCode); dd(0); + } else { + jmpSize = 1; + db(shortCode); db(0); + } + JmpLabel jmp(size_, jmpSize, inner::LasIs); + labelMgr_.addUndefinedLabel(label, jmp); + } + } + void opJmpAbs(const void *addr, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref = 0) + { + if (isAutoGrow()) { + if (type != T_NEAR) throw Error(ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW); + if (size_ + 16 >= maxSize_) growMemory(); + if (longPref) db(longPref); + db(longCode); + dd(0); + save(size_ - 4, size_t(addr) - size_, 4, inner::Labs); + } else { + makeJmp(inner::VerifyInInt32(reinterpret_cast(addr) - getCurr()), type, shortCode, longCode, longPref); + } + + } + // reg is reg field of ModRM + // immSize is the size for immediate value + // disp8N = 0(normal), disp8N = 1(force disp32), disp8N = {2, 4, 8} ; compressed displacement + void opAddr(const Address &addr, int reg, int immSize = 0, int disp8N = 0, bool permitVisb = false) + { + if (!permitVisb && addr.isVsib()) throw Error(ERR_BAD_VSIB_ADDRESSING); + if (addr.getMode() == Address::M_ModRM) { + setSIB(addr.getRegExp(), reg, disp8N); + } else if (addr.getMode() == Address::M_rip || addr.getMode() == Address::M_ripAddr) { + setModRM(0, reg, 5); + if (addr.getLabel()) { // [rip + Label] + putL_inner(*addr.getLabel(), true, addr.getDisp() - immSize); + } else { + size_t disp = addr.getDisp(); + if (addr.getMode() == Address::M_ripAddr) { + if (isAutoGrow()) throw Error(ERR_INVALID_RIP_IN_AUTO_GROW); + disp -= (size_t)getCurr() + 4 + immSize; + } + dd(inner::VerifyInInt32(disp)); + } + } + } + /* preCode is for SSSE3/SSE4 */ + void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE) + { + if (isValid && !isValid(reg, op)) throw Error(ERR_BAD_COMBINATION); + if (pref != NONE) db(pref); + if (op.isMEM()) { + opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0); + } else { + opModR(reg.getReg(), op.getReg(), 0x0F, preCode, code); + } + if (imm8 != NONE) db(imm8); + } + void opMMX_IMM(const Mmx& mmx, int imm8, int code, int ext) + { + if (mmx.isXMM()) db(0x66); + opModR(Reg32(ext), mmx, 0x0F, code); + db(imm8); + } + void opMMX(const Mmx& mmx, const Operand& op, int code, int pref = 0x66, int imm8 = NONE, int preCode = NONE) + { + opGen(mmx, op, code, mmx.isXMM() ? pref : NONE, isXMMorMMX_MEM, imm8, preCode); + } + void opMovXMM(const Operand& op1, const Operand& op2, int code, int pref) + { + if (pref != NONE) db(pref); + if (op1.isXMM() && op2.isMEM()) { + opModM(op2.getAddress(), op1.getReg(), 0x0F, code); + } else if (op1.isMEM() && op2.isXMM()) { + opModM(op1.getAddress(), op2.getReg(), 0x0F, code | 1); + } else { + throw Error(ERR_BAD_COMBINATION); + } + } + void opExt(const Operand& op, const Mmx& mmx, int code, int imm, bool hasMMX2 = false) + { + if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */ + if (mmx.isXMM()) db(0x66); + opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm); + } else { + opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A); + } + } + void opR_ModM(const Operand& op, int bit, int ext, int code0, int code1 = NONE, int code2 = NONE, bool disableRex = false, int immSize = 0) + { + int opBit = op.getBit(); + if (disableRex && opBit == 64) opBit = 32; + if (op.isREG(bit)) { + opModR(Reg(ext, Operand::REG, opBit), op.getReg().changeBit(opBit), code0, code1, code2); + } else if (op.isMEM()) { + opModM(op.getAddress(), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize); + } else { + throw Error(ERR_BAD_COMBINATION); + } + } + void opShift(const Operand& op, int imm, int ext) + { + verifyMemHasSize(op); + opR_ModM(op, 0, ext, (0xC0 | ((imm == 1 ? 1 : 0) << 4)), NONE, NONE, false, (imm != 1) ? 1 : 0); + if (imm != 1) db(imm); + } + void opShift(const Operand& op, const Reg8& _cl, int ext) + { + if (_cl.getIdx() != Operand::CL) throw Error(ERR_BAD_COMBINATION); + opR_ModM(op, 0, ext, 0xD2); + } + void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0) + { + if (condR) { + opModR(op1.getReg(), op2.getReg(), code0, code1, code2); + } else if (condM) { + opModM(op2.getAddress(), op1.getReg(), code0, code1, code2, immSize); + } else { + throw Error(ERR_BAD_COMBINATION); + } + } + void opShxd(const Operand& op, const Reg& reg, uint8 imm, int code, const Reg8 *_cl = 0) + { + if (_cl && _cl->getIdx() != Operand::CL) throw Error(ERR_BAD_COMBINATION); + opModRM(reg, op, (op.isREG(16 | i32e) && op.getBit() == reg.getBit()), op.isMEM() && (reg.isREG(16 | i32e)), 0x0F, code | (_cl ? 1 : 0), NONE, _cl ? 0 : 1); + if (!_cl) db(imm); + } + // (REG, REG|MEM), (MEM, REG) + void opRM_RM(const Operand& op1, const Operand& op2, int code) + { + if (op1.isREG() && op2.isMEM()) { + opModM(op2.getAddress(), op1.getReg(), code | 2); + } else { + opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code); + } + } + // (REG|MEM, IMM) + void opRM_I(const Operand& op, uint32 imm, int code, int ext) + { + verifyMemHasSize(op); + uint32 immBit = inner::IsInDisp8(imm) ? 8 : isInDisp16(imm) ? 16 : 32; + if (op.isBit(8)) immBit = 8; + if (op.getBit() < immBit) throw Error(ERR_IMM_IS_TOO_BIG); + if (op.isBit(32|64) && immBit == 16) immBit = 32; /* don't use MEM16 if 32/64bit mode */ + if (op.isREG() && op.getIdx() == 0 && (op.getBit() == immBit || (op.isBit(64) && immBit == 32))) { // rax, eax, ax, al + rex(op); + db(code | 4 | (immBit == 8 ? 0 : 1)); + } else { + int tmp = immBit < (std::min)(op.getBit(), 32U) ? 2 : 0; + opR_ModM(op, 0, ext, 0x80 | tmp, NONE, NONE, false, immBit / 8); + } + db(imm, immBit / 8); + } + void opIncDec(const Operand& op, int code, int ext) + { + verifyMemHasSize(op); +#ifndef XBYAK64 + if (op.isREG() && !op.isBit(8)) { + rex(op); db(code | op.getIdx()); + return; + } +#endif + code = 0xFE; + if (op.isREG()) { + opModR(Reg(ext, Operand::REG, op.getBit()), op.getReg(), code); + } else { + opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code); + } + } + void opPushPop(const Operand& op, int code, int ext, int alt) + { + int bit = op.getBit(); + if (bit == 16 || bit == BIT) { + if (bit == 16) db(0x66); + if (op.isREG()) { + if (op.getReg().getIdx() >= 8) db(0x41); + db(alt | (op.getIdx() & 7)); + return; + } + if (op.isMEM()) { + opModM(op.getAddress(), Reg(ext, Operand::REG, 32), code); + return; + } + } + throw Error(ERR_BAD_COMBINATION); + } + void verifyMemHasSize(const Operand& op) const + { + if (op.isMEM() && op.getBit() == 0) throw Error(ERR_MEM_SIZE_IS_NOT_SPECIFIED); + } + /* + mov(r, imm) = db(imm, mov_imm(r, imm)) + */ + int mov_imm(const Reg& reg, size_t imm) + { + int bit = reg.getBit(); + const int idx = reg.getIdx(); + int code = 0xB0 | ((bit == 8 ? 0 : 1) << 3); + if (bit == 64 && (imm & ~size_t(0xffffffffu)) == 0) { + rex(Reg32(idx)); + bit = 32; + } else { + rex(reg); + if (bit == 64 && inner::IsInInt32(imm)) { + db(0xC7); + code = 0xC0; + bit = 32; + } + } + db(code | (idx & 7)); + return bit / 8; + } + template + void putL_inner(T& label, bool relative = false, size_t disp = 0) + { + const int jmpSize = relative ? 4 : (int)sizeof(size_t); + if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); + size_t offset = 0; + if (labelMgr_.getOffset(&offset, label)) { + if (relative) { + db(inner::VerifyInInt32(offset + disp - size_ - jmpSize), jmpSize); + } else if (isAutoGrow()) { + db(uint64(0), jmpSize); + save(size_ - jmpSize, offset, jmpSize, inner::LaddTop); + } else { + db(size_t(top_) + offset, jmpSize); + } + return; + } + db(uint64(0), jmpSize); + JmpLabel jmp(size_, jmpSize, (relative ? inner::LasIs : isAutoGrow() ? inner::LaddTop : inner::Labs), disp); + labelMgr_.addUndefinedLabel(label, jmp); + } + void opMovxx(const Reg& reg, const Operand& op, uint8 code) + { + if (op.isBit(32)) throw Error(ERR_BAD_COMBINATION); + int w = op.isBit(16); +#ifdef XBYAK64 + if (op.isHigh8bit()) throw Error(ERR_BAD_COMBINATION); +#endif + bool cond = reg.isREG() && (reg.getBit() > op.getBit()); + opModRM(reg, op, cond && op.isREG(), cond && op.isMEM(), 0x0F, code | w); + } + void opFpuMem(const Address& addr, uint8 m16, uint8 m32, uint8 m64, uint8 ext, uint8 m64ext) + { + if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP); + uint8 code = addr.isBit(16) ? m16 : addr.isBit(32) ? m32 : addr.isBit(64) ? m64 : 0; + if (!code) throw Error(ERR_BAD_MEM_SIZE); + if (m64ext && addr.isBit(64)) ext = m64ext; + + rex(addr, st0); + db(code); + opAddr(addr, ext); + } + // use code1 if reg1 == st0 + // use code2 if reg1 != st0 && reg2 == st0 + void opFpuFpu(const Fpu& reg1, const Fpu& reg2, uint32 code1, uint32 code2) + { + uint32 code = reg1.getIdx() == 0 ? code1 : reg2.getIdx() == 0 ? code2 : 0; + if (!code) throw Error(ERR_BAD_ST_COMBINATION); + db(uint8(code >> 8)); + db(uint8(code | (reg1.getIdx() | reg2.getIdx()))); + } + void opFpu(const Fpu& reg, uint8 code1, uint8 code2) + { + db(code1); db(code2 | reg.getIdx()); + } + void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE) + { + if (op2.isMEM()) { + const Address& addr = op2.getAddress(); + const RegExp& regExp = addr.getRegExp(); + const Reg& base = regExp.getBase(); + const Reg& index = regExp.getIndex(); + if (BIT == 64 && addr.is32bit()) db(0x67); + int disp8N = 0; + bool x = index.isExtIdx(); + if ((type & (T_MUST_EVEX|T_MEM_EVEX)) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) { + int aaa = addr.getOpmaskIdx(); + if (aaa && !(type & T_M_K)) throw Error(ERR_INVALID_OPMASK_WITH_MEMORY); + bool b = false; + if (addr.isBroadcast()) { + if (!(type & (T_B32 | T_B64))) throw Error(ERR_INVALID_BROADCAST); + b = true; + } + int VL = regExp.isVsib() ? index.getBit() : 0; + disp8N = evex(r, base, p1, type, code, x, b, aaa, VL, index.isExtIdx2()); + } else { + vex(r, base, p1, type, code, x); + } + opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N, (type & T_VSIB) != 0); + } else { + const Reg& base = op2.getReg(); + if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) { + evex(r, base, p1, type, code); + } else { + vex(r, base, p1, type, code); + } + setModRM(3, r.getIdx(), base.getIdx()); + } + if (imm8 != NONE) db(imm8); + } + // (r, r, r/m) if isR_R_RM + // (r, r/m, r) + void opGpr(const Reg32e& r, const Operand& op1, const Operand& op2, int type, uint8 code, bool isR_R_RM, int imm8 = NONE) + { + const Operand *p1 = &op1; + const Operand *p2 = &op2; + if (!isR_R_RM) std::swap(p1, p2); + const unsigned int bit = r.getBit(); + if (p1->getBit() != bit || (p2->isREG() && p2->getBit() != bit)) throw Error(ERR_BAD_COMBINATION); + type |= (bit == 64) ? T_W1 : T_W0; + opVex(r, p1, *p2, type, code, imm8); + } + void opAVX_X_X_XM(const Xmm& x1, const Operand& op1, const Operand& op2, int type, int code0, int imm8 = NONE) + { + const Xmm *x2 = static_cast(&op1); + const Operand *op = &op2; + if (op2.isNone()) { // (x1, op1) -> (x1, x1, op1) + x2 = &x1; + op = &op1; + } + // (x1, x2, op) + if (!((x1.isXMM() && x2->isXMM()) || ((type & T_YMM) && ((x1.isYMM() && x2->isYMM()) || (x1.isZMM() && x2->isZMM()))))) throw Error(ERR_BAD_COMBINATION); + opVex(x1, x2, *op, type, code0, imm8); + } + void opAVX_K_X_XM(const Opmask& k, const Xmm& x2, const Operand& op3, int type, int code0, int imm8 = NONE) + { + if (!op3.isMEM() && (x2.getKind() != op3.getKind())) throw Error(ERR_BAD_COMBINATION); + opVex(k, &x2, op3, type, code0, imm8); + } + // (x, x/m), (y, x/m256), (z, y/m) + void checkCvt1(const Operand& x, const Operand& op) const + { + if (!op.isMEM() && !(x.is(Operand::XMM | Operand::YMM) && op.isXMM()) && !(x.isZMM() && op.isYMM())) throw Error(ERR_BAD_COMBINATION); + } + // (x, x/m), (x, y/m256), (y, z/m) + void checkCvt2(const Xmm& x, const Operand& op) const + { + if (!(x.isXMM() && op.is(Operand::XMM | Operand::YMM | Operand::MEM)) && !(x.isYMM() && op.is(Operand::ZMM | Operand::MEM))) throw Error(ERR_BAD_COMBINATION); + } + void opCvt2(const Xmm& x, const Operand& op, int type, int code) + { + checkCvt2(x, op); + Operand::Kind kind = x.isXMM() ? (op.isBit(256) ? Operand::YMM : Operand::XMM) : Operand::ZMM; + opVex(x.copyAndSetKind(kind), &xm0, op, type, code); + } + void opCvt3(const Xmm& x1, const Xmm& x2, const Operand& op, int type, int type64, int type32, uint8 code) + { + if (!(x1.isXMM() && x2.isXMM() && (op.isREG(i32e) || op.isMEM()))) throw Error(ERR_BAD_SIZE_OF_REGISTER); + Xmm x(op.getIdx()); + const Operand *p = op.isREG() ? &x : &op; + opVex(x1, &x2, *p, type | (op.isBit(64) ? type64 : type32), code); + } + const Xmm& cvtIdx0(const Operand& x) const + { + return x.isZMM() ? zm0 : x.isYMM() ? ym0 : xm0; + } + // support (x, x/m, imm), (y, y/m, imm) + void opAVX_X_XM_IMM(const Xmm& x, const Operand& op, int type, int code, int imm8 = NONE) + { + opAVX_X_X_XM(x, cvtIdx0(x), op, type, code, imm8); + } + // QQQ:need to refactor + void opSp1(const Reg& reg, const Operand& op, uint8 pref, uint8 code0, uint8 code1) + { + if (reg.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); + bool is16bit = reg.isREG(16) && (op.isREG(16) || op.isMEM()); + if (!is16bit && !(reg.isREG(i32e) && (op.isREG(reg.getBit()) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); + if (is16bit) db(0x66); + db(pref); opModRM(reg.changeBit(i32e == 32 ? 32 : reg.getBit()), op, op.isREG(), true, code0, code1); + } + void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8 code, int mode) + { + const RegExp& regExp = addr.getRegExp(); + if (!regExp.isVsib(128 | 256)) throw Error(ERR_BAD_VSIB_ADDRESSING); + const int y_vx_y = 0; + const int y_vy_y = 1; +// const int x_vy_x = 2; + const bool isAddrYMM = regExp.getIndex().getBit() == 256; + if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) { + bool isOK = false; + if (mode == y_vx_y) { + isOK = x1.isYMM() && !isAddrYMM && x2.isYMM(); + } else if (mode == y_vy_y) { + isOK = x1.isYMM() && isAddrYMM && x2.isYMM(); + } else { // x_vy_x + isOK = !x1.isYMM() && isAddrYMM && !x2.isYMM(); + } + if (!isOK) throw Error(ERR_BAD_VSIB_ADDRESSING); + } + opAVX_X_X_XM(isAddrYMM ? Ymm(x1.getIdx()) : x1, isAddrYMM ? Ymm(x2.getIdx()) : x2, addr, type, code); + } + enum { + xx_yy_zz = 0, + xx_yx_zy = 1, + xx_xy_yz = 2 + }; + void checkGather2(const Xmm& x1, const Reg& x2, int mode) const + { + if (x1.isXMM() && x2.isXMM()) return; + switch (mode) { + case xx_yy_zz: if ((x1.isYMM() && x2.isYMM()) || (x1.isZMM() && x2.isZMM())) return; + break; + case xx_yx_zy: if ((x1.isYMM() && x2.isXMM()) || (x1.isZMM() && x2.isYMM())) return; + break; + case xx_xy_yz: if ((x1.isXMM() && x2.isYMM()) || (x1.isYMM() && x2.isZMM())) return; + break; + } + throw Error(ERR_BAD_VSIB_ADDRESSING); + } + void opGather2(const Xmm& x, const Address& addr, int type, uint8 code, int mode) + { + if (x.hasZero()) throw Error(ERR_INVALID_ZERO); + checkGather2(x, addr.getRegExp().getIndex(), mode); + opVex(x, 0, addr, type, code); + } + /* + xx_xy_yz ; mode = true + xx_xy_xz ; mode = false + */ + void opVmov(const Operand& op, const Xmm& x, int type, uint8 code, bool mode) + { + if (mode) { + if (!op.isMEM() && !((op.isXMM() && x.isXMM()) || (op.isXMM() && x.isYMM()) || (op.isYMM() && x.isZMM()))) throw Error(ERR_BAD_COMBINATION); + } else { + if (!op.isMEM() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); + } + opVex(x, 0, op, type, code); + } + void opGatherFetch(const Address& addr, const Xmm& x, int type, uint8 code, Operand::Kind kind) + { + if (addr.hasZero()) throw Error(ERR_INVALID_ZERO); + if (addr.getRegExp().getIndex().getKind() != kind) throw Error(ERR_BAD_VSIB_ADDRESSING); + opVex(x, 0, addr, type, code); + } +public: + unsigned int getVersion() const { return VERSION; } + using CodeArray::db; + const Mmx mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7; + const Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; + const Ymm ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7; + const Zmm zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7; + const Xmm &xm0, &xm1, &xm2, &xm3, &xm4, &xm5, &xm6, &xm7; + const Ymm &ym0, &ym1, &ym2, &ym3, &ym4, &ym5, &ym6, &ym7; + const Ymm &zm0, &zm1, &zm2, &zm3, &zm4, &zm5, &zm6, &zm7; + const Reg32 eax, ecx, edx, ebx, esp, ebp, esi, edi; + const Reg16 ax, cx, dx, bx, sp, bp, si, di; + const Reg8 al, cl, dl, bl, ah, ch, dh, bh; + const AddressFrame ptr, byte, word, dword, qword, xword, yword, zword; // xword is same as oword of NASM + const AddressFrame ptr_b, xword_b, yword_b, zword_b; // broadcast such as {1to2}, {1to4}, {1to8}, {1to16}, {b} + const Fpu st0, st1, st2, st3, st4, st5, st6, st7; + const Opmask k0, k1, k2, k3, k4, k5, k6, k7; + const BoundsReg bnd0, bnd1, bnd2, bnd3; + const EvexModifierRounding T_sae, T_rn_sae, T_rd_sae, T_ru_sae, T_rz_sae; // {sae}, {rn-sae}, {rd-sae}, {ru-sae}, {rz-sae} + const EvexModifierZero T_z; // {z} +#ifdef XBYAK64 + const Reg64 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; + const Reg32 r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d; + const Reg16 r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w; + const Reg8 r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b; + const Reg8 spl, bpl, sil, dil; + const Xmm xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15; + const Xmm xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23; + const Xmm xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31; + const Ymm ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15; + const Ymm ymm16, ymm17, ymm18, ymm19, ymm20, ymm21, ymm22, ymm23; + const Ymm ymm24, ymm25, ymm26, ymm27, ymm28, ymm29, ymm30, ymm31; + const Zmm zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15; + const Zmm zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23; + const Zmm zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31; + const Xmm &xm8, &xm9, &xm10, &xm11, &xm12, &xm13, &xm14, &xm15; // for my convenience + const Xmm &xm16, &xm17, &xm18, &xm19, &xm20, &xm21, &xm22, &xm23; + const Xmm &xm24, &xm25, &xm26, &xm27, &xm28, &xm29, &xm30, &xm31; + const Ymm &ym8, &ym9, &ym10, &ym11, &ym12, &ym13, &ym14, &ym15; + const Ymm &ym16, &ym17, &ym18, &ym19, &ym20, &ym21, &ym22, &ym23; + const Ymm &ym24, &ym25, &ym26, &ym27, &ym28, &ym29, &ym30, &ym31; + const Zmm &zm8, &zm9, &zm10, &zm11, &zm12, &zm13, &zm14, &zm15; + const Zmm &zm16, &zm17, &zm18, &zm19, &zm20, &zm21, &zm22, &zm23; + const Zmm &zm24, &zm25, &zm26, &zm27, &zm28, &zm29, &zm30, &zm31; + const RegRip rip; +#endif +#ifndef XBYAK_DISABLE_SEGMENT + const Segment es, cs, ss, ds, fs, gs; +#endif + void L(const std::string& label) { labelMgr_.defineSlabel(label); } + void L(Label& label) { labelMgr_.defineClabel(label); } + Label L() { Label label; L(label); return label; } + void inLocalLabel() { labelMgr_.enterLocal(); } + void outLocalLabel() { labelMgr_.leaveLocal(); } + /* + assign src to dst + require + dst : does not used by L() + src : used by L() + */ + void assignL(Label& dst, const Label& src) { labelMgr_.assign(dst, src); } + /* + put address of label to buffer + @note the put size is 4(32-bit), 8(64-bit) + */ + void putL(std::string label) { putL_inner(label); } + void putL(const Label& label) { putL_inner(label); } + + void jmp(const Operand& op) { opR_ModM(op, BIT, 4, 0xFF, NONE, NONE, true); } + void jmp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); } + void jmp(const char *label, LabelType type = T_AUTO) { jmp(std::string(label), type); } + void jmp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); } + void jmp(const void *addr, LabelType type = T_AUTO) { opJmpAbs(addr, type, 0xEB, 0xE9); } + + void call(const Operand& op) { opR_ModM(op, 16 | i32e, 2, 0xFF, NONE, NONE, true); } + // call(string label), not const std::string& + void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); } + void call(const char *label) { call(std::string(label)); } + void call(const Label& label) { opJmp(label, T_NEAR, 0, 0xE8, 0); } + // call(function pointer) +#ifdef XBYAK_VARIADIC_TEMPLATE + template + void call(Ret(*func)(Params...)) { call(reinterpret_cast(func)); } +#endif + void call(const void *addr) { opJmpAbs(addr, T_NEAR, 0, 0xE8); } + + void test(const Operand& op, const Reg& reg) + { + opModRM(reg, op, op.isREG() && (op.getKind() == reg.getKind()), op.isMEM(), 0x84); + } + void test(const Operand& op, uint32 imm) + { + verifyMemHasSize(op); + int immSize = (std::min)(op.getBit() / 8, 4U); + if (op.isREG() && op.getIdx() == 0) { // al, ax, eax + rex(op); + db(0xA8 | (op.isBit(8) ? 0 : 1)); + } else { + opR_ModM(op, 0, 0, 0xF6, NONE, NONE, false, immSize); + } + db(imm, immSize); + } + void imul(const Reg& reg, const Operand& op) + { + opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x0F, 0xAF); + } + void imul(const Reg& reg, const Operand& op, int imm) + { + int s = inner::IsInDisp8(imm) ? 1 : 0; + int immSize = s ? 1 : reg.isREG(16) ? 2 : 4; + opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x69 | (s << 1), NONE, NONE, immSize); + db(imm, immSize); + } + void push(const Operand& op) { opPushPop(op, 0xFF, 6, 0x50); } + void pop(const Operand& op) { opPushPop(op, 0x8F, 0, 0x58); } + void push(const AddressFrame& af, uint32 imm) + { + if (af.bit_ == 8 && inner::IsInDisp8(imm)) { + db(0x6A); db(imm); + } else if (af.bit_ == 16 && isInDisp16(imm)) { + db(0x66); db(0x68); dw(imm); + } else { + db(0x68); dd(imm); + } + } + /* use "push(word, 4)" if you want "push word 4" */ + void push(uint32 imm) + { + if (inner::IsInDisp8(imm)) { + push(byte, imm); + } else { + push(dword, imm); + } + } + void mov(const Operand& reg1, const Operand& reg2) + { + const Reg *reg = 0; + const Address *addr = 0; + uint8 code = 0; + if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp] + reg = ®1.getReg(); + addr= ®2.getAddress(); + code = 0xA0; + } else + if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al + reg = ®2.getReg(); + addr= ®1.getAddress(); + code = 0xA2; + } +#ifdef XBYAK64 + if (addr && addr->is64bitDisp()) { + if (code) { + rex(*reg); + db(reg1.isREG(8) ? 0xA0 : reg1.isREG() ? 0xA1 : reg2.isREG(8) ? 0xA2 : 0xA3); + db(addr->getDisp(), 8); + } else { + throw Error(ERR_BAD_COMBINATION); + } + } else +#else + if (code && addr->isOnlyDisp()) { + rex(*reg, *addr); + db(code | (reg->isBit(8) ? 0 : 1)); + dd(static_cast(addr->getDisp())); + } else +#endif + { + opRM_RM(reg1, reg2, 0x88); + } + } + void mov(const Operand& op, size_t imm) + { + if (op.isREG()) { + const int size = mov_imm(op.getReg(), imm); + db(imm, size); + } else if (op.isMEM()) { + verifyMemHasSize(op); + int immSize = op.getBit() / 8; + if (immSize <= 4) { + sint64 s = sint64(imm) >> (immSize * 8); + if (s != 0 && s != -1) throw Error(ERR_IMM_IS_TOO_BIG); + } else { + if (!inner::IsInInt32(imm)) throw Error(ERR_IMM_IS_TOO_BIG); + immSize = 4; + } + opModM(op.getAddress(), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize); + db(static_cast(imm), immSize); + } else { + throw Error(ERR_BAD_COMBINATION); + } + } + void mov(const NativeReg& reg, const char *label) // can't use std::string + { + if (label == 0) { + mov(static_cast(reg), 0); // call imm + return; + } + mov_imm(reg, dummyAddr); + putL(label); + } + void mov(const NativeReg& reg, const Label& label) + { + mov_imm(reg, dummyAddr); + putL(label); + } + void xchg(const Operand& op1, const Operand& op2) + { + const Operand *p1 = &op1, *p2 = &op2; + if (p1->isMEM() || (p2->isREG(16 | i32e) && p2->getIdx() == 0)) { + p1 = &op2; p2 = &op1; + } + if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION); + if (p2->isREG() && (p1->isREG(16 | i32e) && p1->getIdx() == 0) +#ifdef XBYAK64 + && (p2->getIdx() != 0 || !p1->isREG(32)) +#endif + ) { + rex(*p2, *p1); db(0x90 | (p2->getIdx() & 7)); + return; + } + opModRM(*p1, *p2, (p1->isREG() && p2->isREG() && (p1->getBit() == p2->getBit())), p2->isMEM(), 0x86 | (p1->isBit(8) ? 0 : 1)); + } + +#ifndef XBYAK_DISABLE_SEGMENT + void push(const Segment& seg) + { + switch (seg.getIdx()) { + case Segment::es: db(0x06); break; + case Segment::cs: db(0x0E); break; + case Segment::ss: db(0x16); break; + case Segment::ds: db(0x1E); break; + case Segment::fs: db(0x0F); db(0xA0); break; + case Segment::gs: db(0x0F); db(0xA8); break; + default: + assert(0); + } + } + void pop(const Segment& seg) + { + switch (seg.getIdx()) { + case Segment::es: db(0x07); break; + case Segment::cs: throw Error(ERR_BAD_COMBINATION); + case Segment::ss: db(0x17); break; + case Segment::ds: db(0x1F); break; + case Segment::fs: db(0x0F); db(0xA1); break; + case Segment::gs: db(0x0F); db(0xA9); break; + default: + assert(0); + } + } + void putSeg(const Segment& seg) + { + switch (seg.getIdx()) { + case Segment::es: db(0x2E); break; + case Segment::cs: db(0x36); break; + case Segment::ss: db(0x3E); break; + case Segment::ds: db(0x26); break; + case Segment::fs: db(0x64); break; + case Segment::gs: db(0x65); break; + default: + assert(0); + } + } + void mov(const Operand& op, const Segment& seg) + { + opModRM(Reg8(seg.getIdx()), op, op.isREG(16|i32e), op.isMEM(), 0x8C); + } + void mov(const Segment& seg, const Operand& op) + { + opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast(op.getReg().cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E); + } +#endif + + enum { NONE = 256 }; + // constructor + CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0, Allocator *allocator = 0) + : CodeArray(maxSize, userPtr, allocator) + , mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7) + , xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7) + , ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7) + , zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7) + // for my convenience + , xm0(xmm0), xm1(xmm1), xm2(xmm2), xm3(xmm3), xm4(xmm4), xm5(xmm5), xm6(xmm6), xm7(xmm7) + , ym0(ymm0), ym1(ymm1), ym2(ymm2), ym3(ymm3), ym4(ymm4), ym5(ymm5), ym6(ymm6), ym7(ymm7) + , zm0(zmm0), zm1(zmm1), zm2(zmm2), zm3(zmm3), zm4(zmm4), zm5(zmm5), zm6(zmm6), zm7(zmm7) + + , eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI) + , ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI) + , al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH) + , ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512) + , ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true) + , st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7) + , k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7) + , bnd0(0), bnd1(1), bnd2(2), bnd3(3) + , T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE) + , T_z() +#ifdef XBYAK64 + , rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15) + , r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15) + , r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15) + , r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15) + , spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true) + , xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15) + , xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23) + , xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31) + , ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15) + , ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23) + , ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31) + , zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15) + , zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23) + , zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31) + // for my convenience + , xm8(xmm8), xm9(xmm9), xm10(xmm10), xm11(xmm11), xm12(xmm12), xm13(xmm13), xm14(xmm14), xm15(xmm15) + , xm16(xmm16), xm17(xmm17), xm18(xmm18), xm19(xmm19), xm20(xmm20), xm21(xmm21), xm22(xmm22), xm23(xmm23) + , xm24(xmm24), xm25(xmm25), xm26(xmm26), xm27(xmm27), xm28(xmm28), xm29(xmm29), xm30(xmm30), xm31(xmm31) + , ym8(ymm8), ym9(ymm9), ym10(ymm10), ym11(ymm11), ym12(ymm12), ym13(ymm13), ym14(ymm14), ym15(ymm15) + , ym16(ymm16), ym17(ymm17), ym18(ymm18), ym19(ymm19), ym20(ymm20), ym21(ymm21), ym22(ymm22), ym23(ymm23) + , ym24(ymm24), ym25(ymm25), ym26(ymm26), ym27(ymm27), ym28(ymm28), ym29(ymm29), ym30(ymm30), ym31(ymm31) + , zm8(zmm8), zm9(zmm9), zm10(zmm10), zm11(zmm11), zm12(zmm12), zm13(zmm13), zm14(zmm14), zm15(zmm15) + , zm16(zmm16), zm17(zmm17), zm18(zmm18), zm19(zmm19), zm20(zmm20), zm21(zmm21), zm22(zmm22), zm23(zmm23) + , zm24(zmm24), zm25(zmm25), zm26(zmm26), zm27(zmm27), zm28(zmm28), zm29(zmm29), zm30(zmm30), zm31(zmm31) + , rip() +#endif +#ifndef XBYAK_DISABLE_SEGMENT + , es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs) +#endif + { + labelMgr_.set(this); + } + void reset() + { + resetSize(); + labelMgr_.reset(); + labelMgr_.set(this); + } + bool hasUndefinedLabel() const { return labelMgr_.hasUndefSlabel() || labelMgr_.hasUndefClabel(); } + /* + MUST call ready() to complete generating code if you use AutoGrow mode. + It is not necessary for the other mode if hasUndefinedLabel() is true. + */ + void ready(ProtectMode mode = PROTECT_RWE) + { + if (hasUndefinedLabel()) throw Error(ERR_LABEL_IS_NOT_FOUND); + if (isAutoGrow()) { + calcJmpAddress(); + if (useProtect()) setProtectMode(mode); + } + } + // set read/exec + void readyRE() { return ready(PROTECT_RE); } +#ifdef XBYAK_TEST + void dump(bool doClear = true) + { + CodeArray::dump(); + if (doClear) size_ = 0; + } +#endif + +#ifdef XBYAK_UNDEF_JNL + #undef jnl +#endif + + /* + use single byte nop if useMultiByteNop = false + */ + void nop(size_t size = 1, bool useMultiByteNop = true) + { + if (!useMultiByteNop) { + for (size_t i = 0; i < size; i++) { + db(0x90); + } + return; + } + /* + Intel Architectures Software Developer's Manual Volume 2 + recommended multi-byte sequence of NOP instruction + AMD and Intel seem to agree on the same sequences for up to 9 bytes: + https://support.amd.com/TechDocs/55723_SOG_Fam_17h_Processors_3.00.pdf + */ + static const uint8 nopTbl[9][9] = { + {0x90}, + {0x66, 0x90}, + {0x0F, 0x1F, 0x00}, + {0x0F, 0x1F, 0x40, 0x00}, + {0x0F, 0x1F, 0x44, 0x00, 0x00}, + {0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00}, + {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00}, + {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + }; + const size_t n = sizeof(nopTbl) / sizeof(nopTbl[0]); + while (size > 0) { + size_t len = (std::min)(n, size); + const uint8 *seq = nopTbl[len - 1]; + db(seq, len); + size -= len; + } + } + +#ifndef XBYAK_DONT_READ_LIST +#include "xbyak_mnemonic.h" + /* + use single byte nop if useMultiByteNop = false + */ + void align(size_t x = 16, bool useMultiByteNop = true) + { + if (x == 1) return; + if (x < 1 || (x & (x - 1))) throw Error(ERR_BAD_ALIGN); + if (isAutoGrow() && x > inner::ALIGN_PAGE_SIZE) fprintf(stderr, "warning:autoGrow mode does not support %d align\n", (int)x); + size_t remain = size_t(getCurr()) % x; + if (remain) { + nop(x - remain, useMultiByteNop); + } + } +#endif +}; + +namespace util { +static const Mmx mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7); +static const Xmm xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7); +static const Ymm ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7); +static const Zmm zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7); +static const Reg32 eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI); +static const Reg16 ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI); +static const Reg8 al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH); +static const AddressFrame ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512); +static const AddressFrame ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true); +static const Fpu st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7); +static const Opmask k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7); +static const BoundsReg bnd0(0), bnd1(1), bnd2(2), bnd3(3); +static const EvexModifierRounding T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE); +static const EvexModifierZero T_z; +#ifdef XBYAK64 +static const Reg64 rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15); +static const Reg32 r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15); +static const Reg16 r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15); +static const Reg8 r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15), spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true); +static const Xmm xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15); +static const Xmm xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23); +static const Xmm xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31); +static const Ymm ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15); +static const Ymm ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23); +static const Ymm ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31); +static const Zmm zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15); +static const Zmm zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23); +static const Zmm zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31); +static const RegRip rip; +#endif +#ifndef XBYAK_DISABLE_SEGMENT +static const Segment es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs); +#endif +} // util + +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +} // end of namespace + +#endif // XBYAK_XBYAK_H_ diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h new file mode 100644 index 0000000000..a22e5224c3 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h @@ -0,0 +1,303 @@ +/******************************************************************************* +* Copyright 2016-2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/******************************************************************************* +* Copyright (c) 2007 MITSUNARI Shigeo +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* Neither the name of the copyright owner nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +enum { + B00000000= 0, + B00000001= 1, + B00000010= 2, + B00000011= 3, + B00000100= 4, + B00000101= 5, + B00000110= 6, + B00000111= 7, + B00001000= 8, + B00001001= 9, + B00001010= 10, + B00001011= 11, + B00001100= 12, + B00001101= 13, + B00001110= 14, + B00001111= 15, + B00010000= 16, + B00010001= 17, + B00010010= 18, + B00010011= 19, + B00010100= 20, + B00010101= 21, + B00010110= 22, + B00010111= 23, + B00011000= 24, + B00011001= 25, + B00011010= 26, + B00011011= 27, + B00011100= 28, + B00011101= 29, + B00011110= 30, + B00011111= 31, + B00100000= 32, + B00100001= 33, + B00100010= 34, + B00100011= 35, + B00100100= 36, + B00100101= 37, + B00100110= 38, + B00100111= 39, + B00101000= 40, + B00101001= 41, + B00101010= 42, + B00101011= 43, + B00101100= 44, + B00101101= 45, + B00101110= 46, + B00101111= 47, + B00110000= 48, + B00110001= 49, + B00110010= 50, + B00110011= 51, + B00110100= 52, + B00110101= 53, + B00110110= 54, + B00110111= 55, + B00111000= 56, + B00111001= 57, + B00111010= 58, + B00111011= 59, + B00111100= 60, + B00111101= 61, + B00111110= 62, + B00111111= 63, + B01000000= 64, + B01000001= 65, + B01000010= 66, + B01000011= 67, + B01000100= 68, + B01000101= 69, + B01000110= 70, + B01000111= 71, + B01001000= 72, + B01001001= 73, + B01001010= 74, + B01001011= 75, + B01001100= 76, + B01001101= 77, + B01001110= 78, + B01001111= 79, + B01010000= 80, + B01010001= 81, + B01010010= 82, + B01010011= 83, + B01010100= 84, + B01010101= 85, + B01010110= 86, + B01010111= 87, + B01011000= 88, + B01011001= 89, + B01011010= 90, + B01011011= 91, + B01011100= 92, + B01011101= 93, + B01011110= 94, + B01011111= 95, + B01100000= 96, + B01100001= 97, + B01100010= 98, + B01100011= 99, + B01100100= 100, + B01100101= 101, + B01100110= 102, + B01100111= 103, + B01101000= 104, + B01101001= 105, + B01101010= 106, + B01101011= 107, + B01101100= 108, + B01101101= 109, + B01101110= 110, + B01101111= 111, + B01110000= 112, + B01110001= 113, + B01110010= 114, + B01110011= 115, + B01110100= 116, + B01110101= 117, + B01110110= 118, + B01110111= 119, + B01111000= 120, + B01111001= 121, + B01111010= 122, + B01111011= 123, + B01111100= 124, + B01111101= 125, + B01111110= 126, + B01111111= 127, + B10000000= 128, + B10000001= 129, + B10000010= 130, + B10000011= 131, + B10000100= 132, + B10000101= 133, + B10000110= 134, + B10000111= 135, + B10001000= 136, + B10001001= 137, + B10001010= 138, + B10001011= 139, + B10001100= 140, + B10001101= 141, + B10001110= 142, + B10001111= 143, + B10010000= 144, + B10010001= 145, + B10010010= 146, + B10010011= 147, + B10010100= 148, + B10010101= 149, + B10010110= 150, + B10010111= 151, + B10011000= 152, + B10011001= 153, + B10011010= 154, + B10011011= 155, + B10011100= 156, + B10011101= 157, + B10011110= 158, + B10011111= 159, + B10100000= 160, + B10100001= 161, + B10100010= 162, + B10100011= 163, + B10100100= 164, + B10100101= 165, + B10100110= 166, + B10100111= 167, + B10101000= 168, + B10101001= 169, + B10101010= 170, + B10101011= 171, + B10101100= 172, + B10101101= 173, + B10101110= 174, + B10101111= 175, + B10110000= 176, + B10110001= 177, + B10110010= 178, + B10110011= 179, + B10110100= 180, + B10110101= 181, + B10110110= 182, + B10110111= 183, + B10111000= 184, + B10111001= 185, + B10111010= 186, + B10111011= 187, + B10111100= 188, + B10111101= 189, + B10111110= 190, + B10111111= 191, + B11000000= 192, + B11000001= 193, + B11000010= 194, + B11000011= 195, + B11000100= 196, + B11000101= 197, + B11000110= 198, + B11000111= 199, + B11001000= 200, + B11001001= 201, + B11001010= 202, + B11001011= 203, + B11001100= 204, + B11001101= 205, + B11001110= 206, + B11001111= 207, + B11010000= 208, + B11010001= 209, + B11010010= 210, + B11010011= 211, + B11010100= 212, + B11010101= 213, + B11010110= 214, + B11010111= 215, + B11011000= 216, + B11011001= 217, + B11011010= 218, + B11011011= 219, + B11011100= 220, + B11011101= 221, + B11011110= 222, + B11011111= 223, + B11100000= 224, + B11100001= 225, + B11100010= 226, + B11100011= 227, + B11100100= 228, + B11100101= 229, + B11100110= 230, + B11100111= 231, + B11101000= 232, + B11101001= 233, + B11101010= 234, + B11101011= 235, + B11101100= 236, + B11101101= 237, + B11101110= 238, + B11101111= 239, + B11110000= 240, + B11110001= 241, + B11110010= 242, + B11110011= 243, + B11110100= 244, + B11110101= 245, + B11110110= 246, + B11110111= 247, + B11111000= 248, + B11111001= 249, + B11111010= 250, + B11111011= 251, + B11111100= 252, + B11111101= 253, + B11111110= 254, + B11111111= 255 +}; diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h new file mode 100644 index 0000000000..28d2d222f9 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h @@ -0,0 +1,2017 @@ +/******************************************************************************* +* Copyright 2016-2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/******************************************************************************* +* Copyright (c) 2007 MITSUNARI Shigeo +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* Neither the name of the copyright owner nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +const char *getVersionString() const { return "5.76"; } +void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); } +void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); } +void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); } +void add(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x00, 0); } +void add(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x00); } +void addpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x66, isXMM_XMMorMEM); } +void addps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x100, isXMM_XMMorMEM); } +void addsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF2, isXMM_XMMorMEM); } +void addss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF3, isXMM_XMMorMEM); } +void addsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0x66, isXMM_XMMorMEM); } +void addsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0xF2, isXMM_XMMorMEM); } +void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); } +void aesdec(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDE, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesdeclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesenc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDC, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesenclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDD, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesimc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDB, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aeskeygenassist(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void and_(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x20, 4); } +void and_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x20); } +void andn(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_0F38, 0xf2, true); } +void andnpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x66, isXMM_XMMorMEM); } +void andnps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x100, isXMM_XMMorMEM); } +void andpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x66, isXMM_XMMorMEM); } +void andps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x100, isXMM_XMMorMEM); } +void bextr(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf7, false); } +void blendpd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0D, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void blendps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0C, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void blendvpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void blendvps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void blsi(const Reg32e& r, const Operand& op) { opGpr(Reg32e(3, r.getBit()), op, r, T_0F38, 0xf3, false); } +void blsmsk(const Reg32e& r, const Operand& op) { opGpr(Reg32e(2, r.getBit()), op, r, T_0F38, 0xf3, false); } +void blsr(const Reg32e& r, const Operand& op) { opGpr(Reg32e(1, r.getBit()), op, r, T_0F38, 0xf3, false); } +void bnd() { db(0xF2); } +void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); } +void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); } +void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); } +void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); } +void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); } +void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); } +void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); } +void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); } +void bsf(const Reg®, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBC); } +void bsr(const Reg®, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBD); } +void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); } +void bt(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xA3); } +void bt(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 4, 0x0f, 0xba, NONE, false, 1); db(imm); } +void btc(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xBB); } +void btc(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 7, 0x0f, 0xba, NONE, false, 1); db(imm); } +void btr(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xB3); } +void btr(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 6, 0x0f, 0xba, NONE, false, 1); db(imm); } +void bts(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xAB); } +void bts(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 5, 0x0f, 0xba, NONE, false, 1); db(imm); } +void bzhi(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf5, false); } +void cbw() { db(0x66); db(0x98); } +void cdq() { db(0x99); } +void clc() { db(0xF8); } +void cld() { db(0xFC); } +void clflush(const Address& addr) { opModM(addr, Reg32(7), 0x0F, 0xAE); } +void cli() { db(0xFA); } +void cmc() { db(0xF5); } +void cmova(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524 +void cmovae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524 +void cmovb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524 +void cmovbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524 +void cmovc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524 +void cmove(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524 +void cmovg(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524 +void cmovge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524 +void cmovl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524 +void cmovle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524 +void cmovna(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524 +void cmovnae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524 +void cmovnb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524 +void cmovnbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524 +void cmovnc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524 +void cmovne(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524 +void cmovng(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524 +void cmovnge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524 +void cmovnl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524 +void cmovnle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524 +void cmovno(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 1); }//-V524 +void cmovnp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524 +void cmovns(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 9); }//-V524 +void cmovnz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524 +void cmovo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 0); }//-V524 +void cmovp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524 +void cmovpe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524 +void cmovpo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524 +void cmovs(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 8); }//-V524 +void cmovz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524 +void cmp(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x38, 7); } +void cmp(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x38); } +void cmpeqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 0); } +void cmpeqps(const Xmm& x, const Operand& op) { cmpps(x, op, 0); } +void cmpeqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 0); } +void cmpeqss(const Xmm& x, const Operand& op) { cmpss(x, op, 0); } +void cmplepd(const Xmm& x, const Operand& op) { cmppd(x, op, 2); } +void cmpleps(const Xmm& x, const Operand& op) { cmpps(x, op, 2); } +void cmplesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 2); } +void cmpless(const Xmm& x, const Operand& op) { cmpss(x, op, 2); } +void cmpltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 1); } +void cmpltps(const Xmm& x, const Operand& op) { cmpps(x, op, 1); } +void cmpltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 1); } +void cmpltss(const Xmm& x, const Operand& op) { cmpss(x, op, 1); } +void cmpneqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 4); } +void cmpneqps(const Xmm& x, const Operand& op) { cmpps(x, op, 4); } +void cmpneqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 4); } +void cmpneqss(const Xmm& x, const Operand& op) { cmpss(x, op, 4); } +void cmpnlepd(const Xmm& x, const Operand& op) { cmppd(x, op, 6); } +void cmpnleps(const Xmm& x, const Operand& op) { cmpps(x, op, 6); } +void cmpnlesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 6); } +void cmpnless(const Xmm& x, const Operand& op) { cmpss(x, op, 6); } +void cmpnltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 5); } +void cmpnltps(const Xmm& x, const Operand& op) { cmpps(x, op, 5); } +void cmpnltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 5); } +void cmpnltss(const Xmm& x, const Operand& op) { cmpss(x, op, 5); } +void cmpordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 7); } +void cmpordps(const Xmm& x, const Operand& op) { cmpps(x, op, 7); } +void cmpordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 7); } +void cmpordss(const Xmm& x, const Operand& op) { cmpss(x, op, 7); } +void cmppd(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0x66, isXMM_XMMorMEM, imm8); } +void cmpps(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0x100, isXMM_XMMorMEM, imm8); } +void cmpsb() { db(0xA6); } +void cmpsd() { db(0xA7); } +void cmpsd(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0xF2, isXMM_XMMorMEM, imm8); } +void cmpss(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0xF3, isXMM_XMMorMEM, imm8); } +void cmpsw() { db(0x66); db(0xA7); } +void cmpunordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 3); } +void cmpunordps(const Xmm& x, const Operand& op) { cmpps(x, op, 3); } +void cmpunordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 3); } +void cmpunordss(const Xmm& x, const Operand& op) { cmpss(x, op, 3); } +void cmpxchg(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xB0 | (reg.isBit(8) ? 0 : 1)); } +void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); } +void comisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x66, isXMM_XMMorMEM); } +void comiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x100, isXMM_XMMorMEM); } +void cpuid() { db(0x0F); db(0xA2); } +void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); } +void cvtdq2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF3, isXMM_XMMorMEM); } +void cvtdq2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x100, isXMM_XMMorMEM); } +void cvtpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF2, isXMM_XMMorMEM); } +void cvtpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x66, isMMX_XMMorMEM); } +void cvtpd2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x66, isXMM_XMMorMEM); } +void cvtpi2pd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x66, isXMM_MMXorMEM); } +void cvtpi2ps(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x100, isXMM_MMXorMEM); } +void cvtps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x66, isXMM_XMMorMEM); } +void cvtps2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x100, isXMM_XMMorMEM); } +void cvtps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x100, isMMX_XMMorMEM); } +void cvtsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF2, isREG32_XMMorMEM); } +void cvtsd2ss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF2, isXMM_XMMorMEM); } +void cvtsi2sd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF2, isXMM_REG32orMEM); } +void cvtsi2ss(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF3, isXMM_REG32orMEM); } +void cvtss2sd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF3, isXMM_XMMorMEM); } +void cvtss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF3, isREG32_XMMorMEM); } +void cvttpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0x66, isXMM_XMMorMEM); } +void cvttpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x66, isMMX_XMMorMEM); } +void cvttps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0xF3, isXMM_XMMorMEM); } +void cvttps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x100, isMMX_XMMorMEM); } +void cvttsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF2, isREG32_XMMorMEM); } +void cvttss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF3, isREG32_XMMorMEM); } +void cwd() { db(0x66); db(0x99); } +void cwde() { db(0x98); } +void dec(const Operand& op) { opIncDec(op, 0x48, 1); } +void div(const Operand& op) { opR_ModM(op, 0, 6, 0xF6); } +void divpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x66, isXMM_XMMorMEM); } +void divps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x100, isXMM_XMMorMEM); } +void divsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF2, isXMM_XMMorMEM); } +void divss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF3, isXMM_XMMorMEM); } +void dppd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void dpps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void emms() { db(0x0F); db(0x77); } +void extractps(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x17, imm); } +void f2xm1() { db(0xD9); db(0xF0); } +void fabs() { db(0xD9); db(0xE1); } +void fadd(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 0, 0); } +void fadd(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C0, 0xDCC0); } +void fadd(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C0, 0xDCC0); } +void faddp() { db(0xDE); db(0xC1); } +void faddp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC0); } +void faddp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC0); } +void fchs() { db(0xD9); db(0xE0); } +void fcmovb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC0, 0x00C0); } +void fcmovb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC0, 0x00C0); } +void fcmovbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD0, 0x00D0); } +void fcmovbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD0, 0x00D0); } +void fcmove(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC8, 0x00C8); } +void fcmove(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC8, 0x00C8); } +void fcmovnb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC0, 0x00C0); } +void fcmovnb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC0, 0x00C0); } +void fcmovnbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD0, 0x00D0); } +void fcmovnbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD0, 0x00D0); } +void fcmovne(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC8, 0x00C8); } +void fcmovne(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC8, 0x00C8); } +void fcmovnu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD8, 0x00D8); } +void fcmovnu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD8, 0x00D8); } +void fcmovu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD8, 0x00D8); } +void fcmovu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD8, 0x00D8); } +void fcom() { db(0xD8); db(0xD1); } +void fcom(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 2, 0); } +void fcom(const Fpu& reg) { opFpu(reg, 0xD8, 0xD0); } +void fcomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBF0, 0x00F0); } +void fcomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBF0, 0x00F0); } +void fcomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFF0, 0x00F0); } +void fcomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFF0, 0x00F0); } +void fcomp() { db(0xD8); db(0xD9); } +void fcomp(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 3, 0); } +void fcomp(const Fpu& reg) { opFpu(reg, 0xD8, 0xD8); } +void fcompp() { db(0xDE); db(0xD9); } +void fcos() { db(0xD9); db(0xFF); } +void fdecstp() { db(0xD9); db(0xF6); } +void fdiv(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 6, 0); } +void fdiv(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F0, 0xDCF8); } +void fdiv(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F0, 0xDCF8); } +void fdivp() { db(0xDE); db(0xF9); } +void fdivp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF8); } +void fdivp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF8); } +void fdivr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 7, 0); } +void fdivr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F8, 0xDCF0); } +void fdivr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F8, 0xDCF0); } +void fdivrp() { db(0xDE); db(0xF1); } +void fdivrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF0); } +void fdivrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF0); } +void ffree(const Fpu& reg) { opFpu(reg, 0xDD, 0xC0); } +void fiadd(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 0, 0); } +void ficom(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 2, 0); } +void ficomp(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 3, 0); } +void fidiv(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 6, 0); } +void fidivr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 7, 0); } +void fild(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 0, 5); } +void fimul(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 1, 0); } +void fincstp() { db(0xD9); db(0xF7); } +void finit() { db(0x9B); db(0xDB); db(0xE3); } +void fist(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0x00, 2, 0); } +void fistp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 3, 7); } +void fisttp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDD, 1, 0); } +void fisub(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 4, 0); } +void fisubr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 5, 0); } +void fld(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 0, 0); } +void fld(const Fpu& reg) { opFpu(reg, 0xD9, 0xC0); } +void fld1() { db(0xD9); db(0xE8); } +void fldcw(const Address& addr) { opModM(addr, Reg32(5), 0xD9, 0x100); } +void fldl2e() { db(0xD9); db(0xEA); } +void fldl2t() { db(0xD9); db(0xE9); } +void fldlg2() { db(0xD9); db(0xEC); } +void fldln2() { db(0xD9); db(0xED); } +void fldpi() { db(0xD9); db(0xEB); } +void fldz() { db(0xD9); db(0xEE); } +void fmul(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 1, 0); } +void fmul(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C8, 0xDCC8); } +void fmul(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C8, 0xDCC8); } +void fmulp() { db(0xDE); db(0xC9); } +void fmulp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC8); } +void fmulp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC8); } +void fninit() { db(0xDB); db(0xE3); } +void fnop() { db(0xD9); db(0xD0); } +void fpatan() { db(0xD9); db(0xF3); } +void fprem() { db(0xD9); db(0xF8); } +void fprem1() { db(0xD9); db(0xF5); } +void fptan() { db(0xD9); db(0xF2); } +void frndint() { db(0xD9); db(0xFC); } +void fscale() { db(0xD9); db(0xFD); } +void fsin() { db(0xD9); db(0xFE); } +void fsincos() { db(0xD9); db(0xFB); } +void fsqrt() { db(0xD9); db(0xFA); } +void fst(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 2, 0); } +void fst(const Fpu& reg) { opFpu(reg, 0xDD, 0xD0); } +void fstcw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xD9, NONE); } +void fstp(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 3, 0); } +void fstp(const Fpu& reg) { opFpu(reg, 0xDD, 0xD8); } +void fsub(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 4, 0); } +void fsub(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E0, 0xDCE8); } +void fsub(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E0, 0xDCE8); } +void fsubp() { db(0xDE); db(0xE9); } +void fsubp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE8); } +void fsubp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE8); } +void fsubr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 5, 0); } +void fsubr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E8, 0xDCE0); } +void fsubr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E8, 0xDCE0); } +void fsubrp() { db(0xDE); db(0xE1); } +void fsubrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE0); } +void fsubrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE0); } +void ftst() { db(0xD9); db(0xE4); } +void fucom() { db(0xDD); db(0xE1); } +void fucom(const Fpu& reg) { opFpu(reg, 0xDD, 0xE0); } +void fucomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBE8, 0x00E8); } +void fucomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBE8, 0x00E8); } +void fucomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFE8, 0x00E8); } +void fucomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFE8, 0x00E8); } +void fucomp() { db(0xDD); db(0xE9); } +void fucomp(const Fpu& reg) { opFpu(reg, 0xDD, 0xE8); } +void fucompp() { db(0xDA); db(0xE9); } +void fwait() { db(0x9B); } +void fxam() { db(0xD9); db(0xE5); } +void fxch() { db(0xD9); db(0xC9); } +void fxch(const Fpu& reg) { opFpu(reg, 0xD9, 0xC8); } +void fxtract() { db(0xD9); db(0xF4); } +void fyl2x() { db(0xD9); db(0xF1); } +void fyl2xp1() { db(0xD9); db(0xF9); } +void gf2p8affineinvqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void gf2p8affineqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCE, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void gf2p8mulb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void haddpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0x66, isXMM_XMMorMEM); } +void haddps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0xF2, isXMM_XMMorMEM); } +void hsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0x66, isXMM_XMMorMEM); } +void hsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0xF2, isXMM_XMMorMEM); } +void idiv(const Operand& op) { opR_ModM(op, 0, 7, 0xF6); } +void imul(const Operand& op) { opR_ModM(op, 0, 5, 0xF6); } +void inc(const Operand& op) { opIncDec(op, 0x40, 0); } +void insertps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void ja(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void ja(const char *label, LabelType type = T_AUTO) { ja(std::string(label), type); }//-V524 +void ja(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524 +void ja(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void jae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jae(const char *label, LabelType type = T_AUTO) { jae(std::string(label), type); }//-V524 +void jae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524 +void jae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jb(const char *label, LabelType type = T_AUTO) { jb(std::string(label), type); }//-V524 +void jb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524 +void jb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jbe(const char *label, LabelType type = T_AUTO) { jbe(std::string(label), type); }//-V524 +void jbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524 +void jbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jc(const char *label, LabelType type = T_AUTO) { jc(std::string(label), type); }//-V524 +void jc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524 +void jc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void je(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void je(const char *label, LabelType type = T_AUTO) { je(std::string(label), type); }//-V524 +void je(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524 +void je(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void jg(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jg(const char *label, LabelType type = T_AUTO) { jg(std::string(label), type); }//-V524 +void jg(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524 +void jg(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jge(const char *label, LabelType type = T_AUTO) { jge(std::string(label), type); }//-V524 +void jge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524 +void jge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jl(const char *label, LabelType type = T_AUTO) { jl(std::string(label), type); }//-V524 +void jl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524 +void jl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jle(const char *label, LabelType type = T_AUTO) { jle(std::string(label), type); }//-V524 +void jle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524 +void jle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jna(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jna(const char *label, LabelType type = T_AUTO) { jna(std::string(label), type); }//-V524 +void jna(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524 +void jna(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jnae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jnae(const char *label, LabelType type = T_AUTO) { jnae(std::string(label), type); }//-V524 +void jnae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524 +void jnae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jnb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jnb(const char *label, LabelType type = T_AUTO) { jnb(std::string(label), type); }//-V524 +void jnb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524 +void jnb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jnbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void jnbe(const char *label, LabelType type = T_AUTO) { jnbe(std::string(label), type); }//-V524 +void jnbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524 +void jnbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void jnc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jnc(const char *label, LabelType type = T_AUTO) { jnc(std::string(label), type); }//-V524 +void jnc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524 +void jnc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jne(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jne(const char *label, LabelType type = T_AUTO) { jne(std::string(label), type); }//-V524 +void jne(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524 +void jne(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jng(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jng(const char *label, LabelType type = T_AUTO) { jng(std::string(label), type); }//-V524 +void jng(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524 +void jng(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jnge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jnge(const char *label, LabelType type = T_AUTO) { jnge(std::string(label), type); }//-V524 +void jnge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524 +void jnge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jnl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jnl(const char *label, LabelType type = T_AUTO) { jnl(std::string(label), type); }//-V524 +void jnl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524 +void jnl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jnle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jnle(const char *label, LabelType type = T_AUTO) { jnle(std::string(label), type); }//-V524 +void jnle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524 +void jnle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jno(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524 +void jno(const char *label, LabelType type = T_AUTO) { jno(std::string(label), type); }//-V524 +void jno(const void *addr) { opJmpAbs(addr, T_NEAR, 0x71, 0x81, 0x0F); }//-V524 +void jno(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524 +void jnp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void jnp(const char *label, LabelType type = T_AUTO) { jnp(std::string(label), type); }//-V524 +void jnp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524 +void jnp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void jns(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524 +void jns(const char *label, LabelType type = T_AUTO) { jns(std::string(label), type); }//-V524 +void jns(const void *addr) { opJmpAbs(addr, T_NEAR, 0x79, 0x89, 0x0F); }//-V524 +void jns(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524 +void jnz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jnz(const char *label, LabelType type = T_AUTO) { jnz(std::string(label), type); }//-V524 +void jnz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524 +void jnz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524 +void jo(const char *label, LabelType type = T_AUTO) { jo(std::string(label), type); }//-V524 +void jo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x70, 0x80, 0x0F); }//-V524 +void jo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524 +void jp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jp(const char *label, LabelType type = T_AUTO) { jp(std::string(label), type); }//-V524 +void jp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524 +void jp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jpe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jpe(const char *label, LabelType type = T_AUTO) { jpe(std::string(label), type); }//-V524 +void jpe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524 +void jpe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jpo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void jpo(const char *label, LabelType type = T_AUTO) { jpo(std::string(label), type); }//-V524 +void jpo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524 +void jpo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void js(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524 +void js(const char *label, LabelType type = T_AUTO) { js(std::string(label), type); }//-V524 +void js(const void *addr) { opJmpAbs(addr, T_NEAR, 0x78, 0x88, 0x0F); }//-V524 +void js(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524 +void jz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void jz(const char *label, LabelType type = T_AUTO) { jz(std::string(label), type); }//-V524 +void jz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524 +void jz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void lahf() { db(0x9F); } +void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); } +void ldmxcsr(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0xAE); } +void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModM(addr, reg, 0x8D); } +void lfence() { db(0x0F); db(0xAE); db(0xE8); } +void lock() { db(0xF0); } +void lzcnt(const Reg®, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBD); } +void maskmovdqu(const Xmm& reg1, const Xmm& reg2) { db(0x66); opModR(reg1, reg2, 0x0F, 0xF7); } +void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) throw Error(ERR_BAD_COMBINATION); opModR(reg1, reg2, 0x0F, 0xF7); } +void maxpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x66, isXMM_XMMorMEM); } +void maxps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x100, isXMM_XMMorMEM); } +void maxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF2, isXMM_XMMorMEM); } +void maxss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF3, isXMM_XMMorMEM); } +void mfence() { db(0x0F); db(0xAE); db(0xF0); } +void minpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x66, isXMM_XMMorMEM); } +void minps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x100, isXMM_XMMorMEM); } +void minsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF2, isXMM_XMMorMEM); } +void minss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF3, isXMM_XMMorMEM); } +void monitor() { db(0x0F); db(0x01); db(0xC8); } +void movapd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x29); } +void movapd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x66); } +void movaps(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x29); } +void movaps(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x100); } +void movbe(const Address& addr, const Reg& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF1); } +void movbe(const Reg& reg, const Address& addr) { opModM(addr, reg, 0x0F, 0x38, 0xF0); } +void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); } +void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x6E); } +void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); } +void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); } +void movddup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF2, isXMM_XMMorMEM, NONE, NONE); } +void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); } +void movdqa(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x7F); } +void movdqa(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0x66); } +void movdqu(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x7F); } +void movdqu(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0xF3); } +void movhlps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x12); } +void movhpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x66); } +void movhps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x100); } +void movlhps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x16); } +void movlpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x66); } +void movlps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x100); } +void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); } +void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); } +void movntdq(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0xE7); } +void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); } +void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); } +void movntpd(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0x2B); } +void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); } +void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) throw Error(ERR_BAD_COMBINATION); opModM(addr, mmx, 0x0F, 0xE7); } +void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); } +void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); } +void movq2dq(const Xmm& xmm, const Mmx& mmx) { db(0xF3); opModR(xmm, mmx, 0x0F, 0xD6); } +void movsb() { db(0xA4); } +void movsd() { db(0xA5); } +void movsd(const Address& addr, const Xmm& xmm) { db(0xF2); opModM(addr, xmm, 0x0F, 0x11); } +void movsd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF2); } +void movshdup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x16, 0xF3, isXMM_XMMorMEM, NONE, NONE); } +void movsldup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF3, isXMM_XMMorMEM, NONE, NONE); } +void movss(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x11); } +void movss(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF3); } +void movsw() { db(0x66); db(0xA5); } +void movsx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xBE); } +void movupd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x11); } +void movupd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x66); } +void movups(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x11); } +void movups(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x100); } +void movzx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xB6); } +void mpsadbw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x42, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void mul(const Operand& op) { opR_ModM(op, 0, 4, 0xF6); } +void mulpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x66, isXMM_XMMorMEM); } +void mulps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x100, isXMM_XMMorMEM); } +void mulsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF2, isXMM_XMMorMEM); } +void mulss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF3, isXMM_XMMorMEM); } +void mulx(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf6, true); } +void mwait() { db(0x0F); db(0x01); db(0xC9); } +void neg(const Operand& op) { opR_ModM(op, 0, 3, 0xF6); } +void not_(const Operand& op) { opR_ModM(op, 0, 2, 0xF6); } +void or_(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x08, 1); } +void or_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x08); } +void orpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x66, isXMM_XMMorMEM); } +void orps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x100, isXMM_XMMorMEM); } +void pabsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1C, 0x66, NONE, 0x38); } +void pabsd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1E, 0x66, NONE, 0x38); } +void pabsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1D, 0x66, NONE, 0x38); } +void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); } +void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); } +void packusdw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2B, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); } +void paddb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFC); } +void paddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFE); } +void paddq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD4); } +void paddsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEC); } +void paddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xED); } +void paddusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDC); } +void paddusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDD); } +void paddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFD); } +void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast(imm), 0x3a); } +void pand(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDB); } +void pandn(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDF); } +void pause() { db(0xF3); db(0x90); } +void pavgb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE0); } +void pavgw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE3); } +void pblendvb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x10, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pblendw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0E, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void pclmulhqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x11); } +void pclmulhqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x01); } +void pclmullqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x10); } +void pclmullqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x00); } +void pclmulqdq(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x44, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void pcmpeqb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x74); } +void pcmpeqd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x76); } +void pcmpeqq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x29, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pcmpeqw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x75); } +void pcmpestri(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x61, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pcmpestrm(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x60, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pcmpgtb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x64); } +void pcmpgtd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x66); } +void pcmpgtq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x37, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pcmpgtw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x65); } +void pcmpistri(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x63, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pcmpistrm(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x62, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pdep(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf5, true); } +void pext(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F3 | T_0F38, 0xf5, true); } +void pextrb(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x14, imm); } +void pextrd(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x16, imm); } +void pextrw(const Operand& op, const Mmx& xmm, uint8 imm) { opExt(op, xmm, 0x15, imm, true); } +void phaddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x02, 0x66, NONE, 0x38); } +void phaddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x03, 0x66, NONE, 0x38); } +void phaddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x01, 0x66, NONE, 0x38); } +void phminposuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void phsubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x06, 0x66, NONE, 0x38); } +void phsubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x07, 0x66, NONE, 0x38); } +void phsubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x05, 0x66, NONE, 0x38); } +void pinsrb(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); } +void pinsrd(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); } +void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); } +void pmaddubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x04, 0x66, NONE, 0x38); } +void pmaddwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF5); } +void pmaxsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3C, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmaxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3D, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmaxsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEE); } +void pmaxub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDE); } +void pmaxud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3F, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmaxuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3E, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x38, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x39, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEA); } +void pminub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDA); } +void pminud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3B, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3A, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); } +void pmovsxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x22, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x20, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x25, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x23, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x24, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x31, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x32, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x30, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x35, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x33, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x34, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmuldq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x28, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmulhrsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0B, 0x66, NONE, 0x38); } +void pmulhuw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE4); } +void pmulhw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE5); } +void pmulld(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmullw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD5); } +void pmuludq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF4); } +void popcnt(const Reg®, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xB8); } +void popf() { db(0x9D); } +void por(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEB); } +void prefetchnta(const Address& addr) { opModM(addr, Reg32(0), 0x0F, 0x18); } +void prefetcht0(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x18); } +void prefetcht1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x18); } +void prefetcht2(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0x18); } +void prefetchw(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x0D); } +void prefetchwt1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x0D); } +void psadbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF6); } +void pshufb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x00, 0x66, NONE, 0x38); } +void pshufd(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0x66, imm8); } +void pshufhw(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0xF3, imm8); } +void pshuflw(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0xF2, imm8); } +void pshufw(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0x00, imm8); } +void psignb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x08, 0x66, NONE, 0x38); } +void psignd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0A, 0x66, NONE, 0x38); } +void psignw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x09, 0x66, NONE, 0x38); } +void pslld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF2); } +void pslld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 6); } +void pslldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 7); } +void psllq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF3); } +void psllq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 6); } +void psllw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF1); } +void psllw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 6); } +void psrad(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE2); } +void psrad(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 4); } +void psraw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE1); } +void psraw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 4); } +void psrld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD2); } +void psrld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 2); } +void psrldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 3); } +void psrlq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD3); } +void psrlq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 2); } +void psrlw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD1); } +void psrlw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 2); } +void psubb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF8); } +void psubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFA); } +void psubq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFB); } +void psubsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE8); } +void psubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE9); } +void psubusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD8); } +void psubusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD9); } +void psubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF9); } +void ptest(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x17, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void punpckhbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x68); } +void punpckhdq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6A); } +void punpckhqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6D, 0x66, isXMM_XMMorMEM); } +void punpckhwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x69); } +void punpcklbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x60); } +void punpckldq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x62); } +void punpcklqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6C, 0x66, isXMM_XMMorMEM); } +void punpcklwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x61); } +void pushf() { db(0x9C); } +void pxor(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEF); } +void rcl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 2); } +void rcl(const Operand& op, int imm) { opShift(op, imm, 2); } +void rcpps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0x100, isXMM_XMMorMEM); } +void rcpss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0xF3, isXMM_XMMorMEM); } +void rcr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 3); } +void rcr(const Operand& op, int imm) { opShift(op, imm, 3); } +void rdmsr() { db(0x0F); db(0x32); } +void rdpmc() { db(0x0F); db(0x33); } +void rdrand(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); } +void rdseed(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); } +void rdtsc() { db(0x0F); db(0x31); } +void rdtscp() { db(0x0F); db(0x01); db(0xF9); } +void rep() { db(0xF3); } +void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } } +void rol(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 0); } +void rol(const Operand& op, int imm) { opShift(op, imm, 0); } +void ror(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 1); } +void ror(const Operand& op, int imm) { opShift(op, imm, 1); } +void rorx(const Reg32e& r, const Operand& op, uint8 imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); } +void roundpd(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x09, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void roundps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x08, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void roundsd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0B, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void roundss(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0A, 0x66, isXMM_XMMorMEM, static_cast(imm), 0x3A); } +void rsqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0x100, isXMM_XMMorMEM); } +void rsqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0xF3, isXMM_XMMorMEM); } +void sahf() { db(0x9E); } +void sal(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); } +void sal(const Operand& op, int imm) { opShift(op, imm, 4); } +void sar(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 7); } +void sar(const Operand& op, int imm) { opShift(op, imm, 7); } +void sarx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F3 | T_0F38, 0xf7, false); } +void sbb(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x18, 3); } +void sbb(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x18); } +void scasb() { db(0xAE); } +void scasd() { db(0xAF); } +void scasw() { db(0x66); db(0xAF); } +void seta(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524 +void setae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524 +void setb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524 +void setbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524 +void setc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524 +void sete(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524 +void setg(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524 +void setge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524 +void setl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524 +void setle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524 +void setna(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524 +void setnae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524 +void setnb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524 +void setnbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524 +void setnc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524 +void setne(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524 +void setng(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524 +void setnge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524 +void setnl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524 +void setnle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524 +void setno(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 1); }//-V524 +void setnp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524 +void setns(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 9); }//-V524 +void setnz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524 +void seto(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 0); }//-V524 +void setp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524 +void setpe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524 +void setpo(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524 +void sets(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 8); }//-V524 +void setz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524 +void sfence() { db(0x0F); db(0xAE); db(0xF8); } +void sha1msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC9, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha1msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCA, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha1nexte(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC8, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha1rnds4(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, imm, 0x3A); } +void sha256msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha256msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCD, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha256rnds2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCB, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void shl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); } +void shl(const Operand& op, int imm) { opShift(op, imm, 4); } +void shld(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xA4, &_cl); } +void shld(const Operand& op, const Reg& reg, uint8 imm) { opShxd(op, reg, imm, 0xA4); } +void shlx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_66 | T_0F38, 0xf7, false); } +void shr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 5); } +void shr(const Operand& op, int imm) { opShift(op, imm, 5); } +void shrd(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xAC, &_cl); } +void shrd(const Operand& op, const Reg& reg, uint8 imm) { opShxd(op, reg, imm, 0xAC); } +void shrx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F2 | T_0F38, 0xf7, false); } +void shufpd(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC6, 0x66, isXMM_XMMorMEM, imm8); } +void shufps(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC6, 0x100, isXMM_XMMorMEM, imm8); } +void sqrtpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x66, isXMM_XMMorMEM); } +void sqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x100, isXMM_XMMorMEM); } +void sqrtsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF2, isXMM_XMMorMEM); } +void sqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF3, isXMM_XMMorMEM); } +void stac() { db(0x0F); db(0x01); db(0xCB); } +void stc() { db(0xF9); } +void std() { db(0xFD); } +void sti() { db(0xFB); } +void stmxcsr(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0xAE); } +void stosb() { db(0xAA); } +void stosd() { db(0xAB); } +void stosw() { db(0x66); db(0xAB); } +void sub(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x28, 5); } +void sub(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x28); } +void subpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x66, isXMM_XMMorMEM); } +void subps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x100, isXMM_XMMorMEM); } +void subsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF2, isXMM_XMMorMEM); } +void subss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF3, isXMM_XMMorMEM); } +void tzcnt(const Reg®, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBC); } +void ucomisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x66, isXMM_XMMorMEM); } +void ucomiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x100, isXMM_XMMorMEM); } +void ud2() { db(0x0F); db(0x0B); } +void unpckhpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM); } +void unpckhps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x100, isXMM_XMMorMEM); } +void unpcklpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM); } +void unpcklps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x100, isXMM_XMMorMEM); } +void vaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x58); } +void vaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x58); } +void vaddsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x58); } +void vaddss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x58); } +void vaddsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0xD0); } +void vaddsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0xD0); } +void vaesdec(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDE); } +void vaesdeclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDF); } +void vaesenc(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDC); } +void vaesenclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDD); } +void vaesimc(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_W0, 0xDB); } +void vaeskeygenassist(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0xDF, imm); } +void vandnpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x55); } +void vandnps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x55); } +void vandpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x54); } +void vandps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x54); } +void vblendpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0D, imm); } +void vblendps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0C, imm); } +void vblendvpd(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4B, x4.getIdx() << 4); } +void vblendvps(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4A, x4.getIdx() << 4); } +void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); } +void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); } +void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); } +void vbroadcastss(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x18); } +void vcmpeq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 16); } +void vcmpeq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 16); } +void vcmpeq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 16); } +void vcmpeq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 16); } +void vcmpeq_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 8); } +void vcmpeq_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 8); } +void vcmpeq_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 8); } +void vcmpeq_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 8); } +void vcmpeq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 24); } +void vcmpeq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 24); } +void vcmpeq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 24); } +void vcmpeq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 24); } +void vcmpeqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 0); } +void vcmpeqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 0); } +void vcmpeqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 0); } +void vcmpeqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 0); } +void vcmpfalse_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 27); } +void vcmpfalse_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 27); } +void vcmpfalse_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 27); } +void vcmpfalse_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 27); } +void vcmpfalsepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 11); } +void vcmpfalseps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 11); } +void vcmpfalsesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 11); } +void vcmpfalsess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 11); } +void vcmpge_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 29); } +void vcmpge_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 29); } +void vcmpge_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 29); } +void vcmpge_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 29); } +void vcmpgepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 13); } +void vcmpgeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 13); } +void vcmpgesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 13); } +void vcmpgess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 13); } +void vcmpgt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 30); } +void vcmpgt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 30); } +void vcmpgt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 30); } +void vcmpgt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 30); } +void vcmpgtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 14); } +void vcmpgtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 14); } +void vcmpgtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 14); } +void vcmpgtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 14); } +void vcmple_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 18); } +void vcmple_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 18); } +void vcmple_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 18); } +void vcmple_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 18); } +void vcmplepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 2); } +void vcmpleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 2); } +void vcmplesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 2); } +void vcmpless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 2); } +void vcmplt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 17); } +void vcmplt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 17); } +void vcmplt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 17); } +void vcmplt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 17); } +void vcmpltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 1); } +void vcmpltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 1); } +void vcmpltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 1); } +void vcmpltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 1); } +void vcmpneq_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 12); } +void vcmpneq_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 12); } +void vcmpneq_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 12); } +void vcmpneq_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 12); } +void vcmpneq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 28); } +void vcmpneq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 28); } +void vcmpneq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 28); } +void vcmpneq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 28); } +void vcmpneq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 20); } +void vcmpneq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 20); } +void vcmpneq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 20); } +void vcmpneq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 20); } +void vcmpneqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 4); } +void vcmpneqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 4); } +void vcmpneqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 4); } +void vcmpneqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 4); } +void vcmpnge_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 25); } +void vcmpnge_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 25); } +void vcmpnge_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 25); } +void vcmpnge_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 25); } +void vcmpngepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 9); } +void vcmpngeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 9); } +void vcmpngesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 9); } +void vcmpngess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 9); } +void vcmpngt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 26); } +void vcmpngt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 26); } +void vcmpngt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 26); } +void vcmpngt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 26); } +void vcmpngtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 10); } +void vcmpngtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 10); } +void vcmpngtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 10); } +void vcmpngtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 10); } +void vcmpnle_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 22); } +void vcmpnle_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 22); } +void vcmpnle_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 22); } +void vcmpnle_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 22); } +void vcmpnlepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 6); } +void vcmpnleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 6); } +void vcmpnlesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 6); } +void vcmpnless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 6); } +void vcmpnlt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 21); } +void vcmpnlt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 21); } +void vcmpnlt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 21); } +void vcmpnlt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 21); } +void vcmpnltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 5); } +void vcmpnltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 5); } +void vcmpnltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 5); } +void vcmpnltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 5); } +void vcmpord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 23); } +void vcmpord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 23); } +void vcmpord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 23); } +void vcmpord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 23); } +void vcmpordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 7); } +void vcmpordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 7); } +void vcmpordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 7); } +void vcmpordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 7); } +void vcmppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xC2, imm); } +void vcmpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_YMM, 0xC2, imm); } +void vcmpsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F, 0xC2, imm); } +void vcmpss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0xC2, imm); } +void vcmptrue_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 31); } +void vcmptrue_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 31); } +void vcmptrue_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 31); } +void vcmptrue_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 31); } +void vcmptruepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 15); } +void vcmptrueps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 15); } +void vcmptruesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 15); } +void vcmptruess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 15); } +void vcmpunord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 19); } +void vcmpunord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 19); } +void vcmpunord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 19); } +void vcmpunord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 19); } +void vcmpunordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 3); } +void vcmpunordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 3); } +void vcmpunordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 3); } +void vcmpunordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 3); } +void vcomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2F); } +void vcomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2F); } +void vcvtdq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0xE6); } +void vcvtdq2ps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); } +void vcvtpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0xE6); } +void vcvtpd2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5A); } +void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); } +void vcvtps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); } +void vcvtps2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x5A); } +void vcvtps2ph(const Operand& op, const Xmm& x, uint8 imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x1D, imm); } +void vcvtsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_ER_X, 0x2D); } +void vcvtsd2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x5A); } +void vcvtsi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F2 | T_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); } +void vcvtsi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F3 | T_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); } +void vcvtss2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x5A); } +void vcvtss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_ER_X | T_N8, 0x2D); } +void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); } +void vcvttps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX | T_SAE_Z | T_B32, 0x5B); } +void vcvttsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, 0x2C); } +void vcvttss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_SAE_X | T_N8, 0x2C); } +void vdivpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5E); } +void vdivps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5E); } +void vdivsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5E); } +void vdivss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5E); } +void vdppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x41, imm); } +void vdpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x40, imm); } +void vextractf128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); } +void vextracti128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); } +void vextractps(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); } +void vfmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x98); } +void vfmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x98); } +void vfmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x99); } +void vfmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x99); } +void vfmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA8); } +void vfmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA8); } +void vfmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xA9); } +void vfmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xA9); } +void vfmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB8); } +void vfmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB8); } +void vfmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xB9); } +void vfmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xB9); } +void vfmaddsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x96); } +void vfmaddsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x96); } +void vfmaddsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA6); } +void vfmaddsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA6); } +void vfmaddsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB6); } +void vfmaddsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB6); } +void vfmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9A); } +void vfmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9A); } +void vfmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9B); } +void vfmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9B); } +void vfmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAA); } +void vfmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAA); } +void vfmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAB); } +void vfmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAB); } +void vfmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBA); } +void vfmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBA); } +void vfmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBB); } +void vfmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBB); } +void vfmsubadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x97); } +void vfmsubadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x97); } +void vfmsubadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA7); } +void vfmsubadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA7); } +void vfmsubadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB7); } +void vfmsubadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB7); } +void vfnmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9C); } +void vfnmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9C); } +void vfnmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9D); } +void vfnmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9D); } +void vfnmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAC); } +void vfnmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAC); } +void vfnmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAD); } +void vfnmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAD); } +void vfnmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBC); } +void vfnmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBC); } +void vfnmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBD); } +void vfnmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBD); } +void vfnmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9E); } +void vfnmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9E); } +void vfnmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9F); } +void vfnmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9F); } +void vfnmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAE); } +void vfnmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAE); } +void vfnmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAF); } +void vfnmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAF); } +void vfnmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBE); } +void vfnmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBE); } +void vfnmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBF); } +void vfnmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBF); } +void vgatherdpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x92, 0); } +void vgatherdps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x92, 1); } +void vgatherqpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x93, 1); } +void vgatherqps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x93, 2); } +void vgf2p8affineinvqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCF, imm); } +void vgf2p8affineqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCE, imm); } +void vgf2p8mulb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_SAE_Z, 0xCF); } +void vhaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7C); } +void vhaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7C); } +void vhsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7D); } +void vhsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7D); } +void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); } +void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); } +void vinsertps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_W0 | T_EW0 | T_EVEX, 0x21, imm); } +void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); } +void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); } +void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); } +void vmaskmovpd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2F); } +void vmaskmovpd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2D); } +void vmaskmovps(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2E); } +void vmaskmovps(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2C); } +void vmaxpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5F); } +void vmaxps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5F); } +void vmaxsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5F); } +void vmaxss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5F); } +void vminpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5D); } +void vminps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5D); } +void vminsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5D); } +void vminss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5D); } +void vmovapd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x29); } +void vmovapd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x28); } +void vmovaps(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x29); } +void vmovaps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x28); } +void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); } +void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); } +void vmovddup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_DUP | T_F2 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_X | T_ER_Y | T_ER_Z, 0x12); } +void vmovdqa(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_YMM, 0x7F); } +void vmovdqa(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_YMM, 0x6F); } +void vmovdqu(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_F3 | T_0F | T_YMM, 0x7F); } +void vmovdqu(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM, 0x6F); } +void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); } +void vmovhpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x17); } +void vmovhpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x16); } +void vmovhps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x17); } +void vmovhps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x16); } +void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); } +void vmovlpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x13); } +void vmovlpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x12); } +void vmovlps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x13); } +void vmovlps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x12); } +void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); } +void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); } +void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); } +void vmovntdqa(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0, 0x2A); } +void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); } +void vmovntps(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_YMM | T_EVEX | T_EW0, 0x2B); } +void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); } +void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); } +void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); } +void vmovsd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_M_K, 0x11); } +void vmovsd(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); } +void vmovsd(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); } +void vmovshdup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x16); } +void vmovsldup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x12); } +void vmovss(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_M_K, 0x11); } +void vmovss(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); } +void vmovss(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); } +void vmovupd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x11); } +void vmovupd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x10); } +void vmovups(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x11); } +void vmovups(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x10); } +void vmpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x42, imm); } +void vmulpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x59); } +void vmulps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x59); } +void vmulsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x59); } +void vmulss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x59); } +void vorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x56); } +void vorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x56); } +void vpabsb(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1C); } +void vpabsd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x1E); } +void vpabsw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1D); } +void vpackssdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6B); } +void vpacksswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x63); } +void vpackusdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x2B); } +void vpackuswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x67); } +void vpaddb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFC); } +void vpaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFE); } +void vpaddq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xD4); } +void vpaddsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEC); } +void vpaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xED); } +void vpaddusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDC); } +void vpaddusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDD); } +void vpaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFD); } +void vpalignr(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_YMM | T_EVEX, 0x0F, imm); } +void vpand(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDB); } +void vpandn(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDF); } +void vpavgb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE0); } +void vpavgw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE3); } +void vpblendd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x02, imm); } +void vpblendvb(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4C, x4.getIdx() << 4); } +void vpblendw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0E, imm); } +void vpbroadcastb(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x78); } +void vpbroadcastd(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x58); } +void vpbroadcastq(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX, 0x59); } +void vpbroadcastw(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x79); } +void vpclmulqdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM | T_EVEX, 0x44, imm); } +void vpcmpeqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x74); } +void vpcmpeqd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x76); } +void vpcmpeqq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x29); } +void vpcmpeqw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x75); } +void vpcmpestri(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x61, imm); } +void vpcmpestrm(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x60, imm); } +void vpcmpgtb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x64); } +void vpcmpgtd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x66); } +void vpcmpgtq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x37); } +void vpcmpgtw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x65); } +void vpcmpistri(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x63, imm); } +void vpcmpistrm(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x62, imm); } +void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); } +void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); } +void vpermd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x36); } +void vpermilpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x0D); } +void vpermilpd(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_EVEX | T_B64, 0x05, imm); } +void vpermilps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x0C); } +void vpermilps(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_EVEX | T_B32, 0x04, imm); } +void vpermpd(const Ymm& y, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x01, imm); } +void vpermpd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x16); } +void vpermps(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x16); } +void vpermq(const Ymm& y, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x00, imm); } +void vpermq(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x36); } +void vpextrb(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); } +void vpextrd(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); } +void vpextrq(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); } +void vpextrw(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } } +void vpgatherdd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x90, 1); } +void vpgatherdq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x90, 0); } +void vpgatherqd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x91, 2); } +void vpgatherqq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x91, 1); } +void vphaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x02); } +void vphaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x03); } +void vphaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x01); } +void vphminposuw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38, 0x41); } +void vphsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x06); } +void vphsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x07); } +void vphsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x05); } +void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); } +void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); } +void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); } +void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); } +void vpmaddubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x04); } +void vpmaddwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF5); } +void vpmaskmovd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8E); } +void vpmaskmovd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8C); } +void vpmaskmovq(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8E); } +void vpmaskmovq(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8C); } +void vpmaxsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3C); } +void vpmaxsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3D); } +void vpmaxsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEE); } +void vpmaxub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDE); } +void vpmaxud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3F); } +void vpmaxuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3E); } +void vpminsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x38); } +void vpminsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x39); } +void vpminsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEA); } +void vpminub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDA); } +void vpminud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3B); } +void vpminuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3A); } +void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); } +void vpmovsxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x21); } +void vpmovsxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x22); } +void vpmovsxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x20); } +void vpmovsxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x25); } +void vpmovsxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x23); } +void vpmovsxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x24); } +void vpmovzxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x31); } +void vpmovzxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x32); } +void vpmovzxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x30); } +void vpmovzxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x35); } +void vpmovzxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x33); } +void vpmovzxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x34); } +void vpmuldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x28); } +void vpmulhrsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x0B); } +void vpmulhuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE4); } +void vpmulhw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE5); } +void vpmulld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x40); } +void vpmullw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD5); } +void vpmuludq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xF4); } +void vpor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEB); } +void vpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF6); } +void vpshufb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x00); } +void vpshufd(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x70, imm); } +void vpshufhw(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM | T_EVEX, 0x70, imm); } +void vpshuflw(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_F2 | T_0F | T_YMM | T_EVEX, 0x70, imm); } +void vpsignb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x08); } +void vpsignd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x0A); } +void vpsignw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x09); } +void vpslld(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); } +void vpslld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xF2); } +void vpslldq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 7), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); } +void vpsllq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); } +void vpsllq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xF3); } +void vpsllvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x47); } +void vpsllvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x47); } +void vpsllw(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); } +void vpsllw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xF1); } +void vpsrad(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); } +void vpsrad(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xE2); } +void vpsravd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x46); } +void vpsraw(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); } +void vpsraw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xE1); } +void vpsrld(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); } +void vpsrld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xD2); } +void vpsrldq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 3), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); } +void vpsrlq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); } +void vpsrlq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xD3); } +void vpsrlvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x45); } +void vpsrlvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x45); } +void vpsrlw(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); } +void vpsrlw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xD1); } +void vpsubb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF8); } +void vpsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFA); } +void vpsubq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xFB); } +void vpsubsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE8); } +void vpsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE9); } +void vpsubusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD8); } +void vpsubusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD9); } +void vpsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF9); } +void vptest(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x17); } +void vpunpckhbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x68); } +void vpunpckhdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6A); } +void vpunpckhqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6D); } +void vpunpckhwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x69); } +void vpunpcklbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x60); } +void vpunpckldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x62); } +void vpunpcklqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6C); } +void vpunpcklwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x61); } +void vpxor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEF); } +void vrcpps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x53); } +void vrcpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x53); } +void vroundpd(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x09, imm); } +void vroundps(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x08, imm); } +void vroundsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0B, imm); } +void vroundss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0A, imm); } +void vrsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x52); } +void vrsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x52); } +void vshufpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xC6, imm); } +void vshufps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xC6, imm); } +void vsqrtpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x51); } +void vsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x51); } +void vsqrtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x51); } +void vsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_ER_X, 0x51); } +void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); } +void vsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5C); } +void vsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5C); } +void vsubsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5C); } +void vsubss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5C); } +void vtestpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0F); } +void vtestps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0E); } +void vucomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2E); } +void vucomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2E); } +void vunpckhpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x15); } +void vunpckhps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x15); } +void vunpcklpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x14); } +void vunpcklps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x14); } +void vxorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x57); } +void vxorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x57); } +void vzeroall() { db(0xC5); db(0xFC); db(0x77); } +void vzeroupper() { db(0xC5); db(0xF8); db(0x77); } +void wait() { db(0x9B); } +void wbinvd() { db(0x0F); db(0x09); } +void wrmsr() { db(0x0F); db(0x30); } +void xadd(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xC0 | (reg.isBit(8) ? 0 : 1)); } +void xgetbv() { db(0x0F); db(0x01); db(0xD0); } +void xlatb() { db(0xD7); } +void xor_(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x30, 6); } +void xor_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x30); } +void xorpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x66, isXMM_XMMorMEM); } +void xorps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x100, isXMM_XMMorMEM); } +#ifdef XBYAK_ENABLE_OMITTED_OPERAND +void vblendpd(const Xmm& x, const Operand& op, uint8 imm) { vblendpd(x, x, op, imm); } +void vblendps(const Xmm& x, const Operand& op, uint8 imm) { vblendps(x, x, op, imm); } +void vblendvpd(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvpd(x1, x1, op, x4); } +void vblendvps(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvps(x1, x1, op, x4); } +void vcmpeq_ospd(const Xmm& x, const Operand& op) { vcmpeq_ospd(x, x, op); } +void vcmpeq_osps(const Xmm& x, const Operand& op) { vcmpeq_osps(x, x, op); } +void vcmpeq_ossd(const Xmm& x, const Operand& op) { vcmpeq_ossd(x, x, op); } +void vcmpeq_osss(const Xmm& x, const Operand& op) { vcmpeq_osss(x, x, op); } +void vcmpeq_uqpd(const Xmm& x, const Operand& op) { vcmpeq_uqpd(x, x, op); } +void vcmpeq_uqps(const Xmm& x, const Operand& op) { vcmpeq_uqps(x, x, op); } +void vcmpeq_uqsd(const Xmm& x, const Operand& op) { vcmpeq_uqsd(x, x, op); } +void vcmpeq_uqss(const Xmm& x, const Operand& op) { vcmpeq_uqss(x, x, op); } +void vcmpeq_uspd(const Xmm& x, const Operand& op) { vcmpeq_uspd(x, x, op); } +void vcmpeq_usps(const Xmm& x, const Operand& op) { vcmpeq_usps(x, x, op); } +void vcmpeq_ussd(const Xmm& x, const Operand& op) { vcmpeq_ussd(x, x, op); } +void vcmpeq_usss(const Xmm& x, const Operand& op) { vcmpeq_usss(x, x, op); } +void vcmpeqpd(const Xmm& x, const Operand& op) { vcmpeqpd(x, x, op); } +void vcmpeqps(const Xmm& x, const Operand& op) { vcmpeqps(x, x, op); } +void vcmpeqsd(const Xmm& x, const Operand& op) { vcmpeqsd(x, x, op); } +void vcmpeqss(const Xmm& x, const Operand& op) { vcmpeqss(x, x, op); } +void vcmpfalse_ospd(const Xmm& x, const Operand& op) { vcmpfalse_ospd(x, x, op); } +void vcmpfalse_osps(const Xmm& x, const Operand& op) { vcmpfalse_osps(x, x, op); } +void vcmpfalse_ossd(const Xmm& x, const Operand& op) { vcmpfalse_ossd(x, x, op); } +void vcmpfalse_osss(const Xmm& x, const Operand& op) { vcmpfalse_osss(x, x, op); } +void vcmpfalsepd(const Xmm& x, const Operand& op) { vcmpfalsepd(x, x, op); } +void vcmpfalseps(const Xmm& x, const Operand& op) { vcmpfalseps(x, x, op); } +void vcmpfalsesd(const Xmm& x, const Operand& op) { vcmpfalsesd(x, x, op); } +void vcmpfalsess(const Xmm& x, const Operand& op) { vcmpfalsess(x, x, op); } +void vcmpge_oqpd(const Xmm& x, const Operand& op) { vcmpge_oqpd(x, x, op); } +void vcmpge_oqps(const Xmm& x, const Operand& op) { vcmpge_oqps(x, x, op); } +void vcmpge_oqsd(const Xmm& x, const Operand& op) { vcmpge_oqsd(x, x, op); } +void vcmpge_oqss(const Xmm& x, const Operand& op) { vcmpge_oqss(x, x, op); } +void vcmpgepd(const Xmm& x, const Operand& op) { vcmpgepd(x, x, op); } +void vcmpgeps(const Xmm& x, const Operand& op) { vcmpgeps(x, x, op); } +void vcmpgesd(const Xmm& x, const Operand& op) { vcmpgesd(x, x, op); } +void vcmpgess(const Xmm& x, const Operand& op) { vcmpgess(x, x, op); } +void vcmpgt_oqpd(const Xmm& x, const Operand& op) { vcmpgt_oqpd(x, x, op); } +void vcmpgt_oqps(const Xmm& x, const Operand& op) { vcmpgt_oqps(x, x, op); } +void vcmpgt_oqsd(const Xmm& x, const Operand& op) { vcmpgt_oqsd(x, x, op); } +void vcmpgt_oqss(const Xmm& x, const Operand& op) { vcmpgt_oqss(x, x, op); } +void vcmpgtpd(const Xmm& x, const Operand& op) { vcmpgtpd(x, x, op); } +void vcmpgtps(const Xmm& x, const Operand& op) { vcmpgtps(x, x, op); } +void vcmpgtsd(const Xmm& x, const Operand& op) { vcmpgtsd(x, x, op); } +void vcmpgtss(const Xmm& x, const Operand& op) { vcmpgtss(x, x, op); } +void vcmple_oqpd(const Xmm& x, const Operand& op) { vcmple_oqpd(x, x, op); } +void vcmple_oqps(const Xmm& x, const Operand& op) { vcmple_oqps(x, x, op); } +void vcmple_oqsd(const Xmm& x, const Operand& op) { vcmple_oqsd(x, x, op); } +void vcmple_oqss(const Xmm& x, const Operand& op) { vcmple_oqss(x, x, op); } +void vcmplepd(const Xmm& x, const Operand& op) { vcmplepd(x, x, op); } +void vcmpleps(const Xmm& x, const Operand& op) { vcmpleps(x, x, op); } +void vcmplesd(const Xmm& x, const Operand& op) { vcmplesd(x, x, op); } +void vcmpless(const Xmm& x, const Operand& op) { vcmpless(x, x, op); } +void vcmplt_oqpd(const Xmm& x, const Operand& op) { vcmplt_oqpd(x, x, op); } +void vcmplt_oqps(const Xmm& x, const Operand& op) { vcmplt_oqps(x, x, op); } +void vcmplt_oqsd(const Xmm& x, const Operand& op) { vcmplt_oqsd(x, x, op); } +void vcmplt_oqss(const Xmm& x, const Operand& op) { vcmplt_oqss(x, x, op); } +void vcmpltpd(const Xmm& x, const Operand& op) { vcmpltpd(x, x, op); } +void vcmpltps(const Xmm& x, const Operand& op) { vcmpltps(x, x, op); } +void vcmpltsd(const Xmm& x, const Operand& op) { vcmpltsd(x, x, op); } +void vcmpltss(const Xmm& x, const Operand& op) { vcmpltss(x, x, op); } +void vcmpneq_oqpd(const Xmm& x, const Operand& op) { vcmpneq_oqpd(x, x, op); } +void vcmpneq_oqps(const Xmm& x, const Operand& op) { vcmpneq_oqps(x, x, op); } +void vcmpneq_oqsd(const Xmm& x, const Operand& op) { vcmpneq_oqsd(x, x, op); } +void vcmpneq_oqss(const Xmm& x, const Operand& op) { vcmpneq_oqss(x, x, op); } +void vcmpneq_ospd(const Xmm& x, const Operand& op) { vcmpneq_ospd(x, x, op); } +void vcmpneq_osps(const Xmm& x, const Operand& op) { vcmpneq_osps(x, x, op); } +void vcmpneq_ossd(const Xmm& x, const Operand& op) { vcmpneq_ossd(x, x, op); } +void vcmpneq_osss(const Xmm& x, const Operand& op) { vcmpneq_osss(x, x, op); } +void vcmpneq_uspd(const Xmm& x, const Operand& op) { vcmpneq_uspd(x, x, op); } +void vcmpneq_usps(const Xmm& x, const Operand& op) { vcmpneq_usps(x, x, op); } +void vcmpneq_ussd(const Xmm& x, const Operand& op) { vcmpneq_ussd(x, x, op); } +void vcmpneq_usss(const Xmm& x, const Operand& op) { vcmpneq_usss(x, x, op); } +void vcmpneqpd(const Xmm& x, const Operand& op) { vcmpneqpd(x, x, op); } +void vcmpneqps(const Xmm& x, const Operand& op) { vcmpneqps(x, x, op); } +void vcmpneqsd(const Xmm& x, const Operand& op) { vcmpneqsd(x, x, op); } +void vcmpneqss(const Xmm& x, const Operand& op) { vcmpneqss(x, x, op); } +void vcmpnge_uqpd(const Xmm& x, const Operand& op) { vcmpnge_uqpd(x, x, op); } +void vcmpnge_uqps(const Xmm& x, const Operand& op) { vcmpnge_uqps(x, x, op); } +void vcmpnge_uqsd(const Xmm& x, const Operand& op) { vcmpnge_uqsd(x, x, op); } +void vcmpnge_uqss(const Xmm& x, const Operand& op) { vcmpnge_uqss(x, x, op); } +void vcmpngepd(const Xmm& x, const Operand& op) { vcmpngepd(x, x, op); } +void vcmpngeps(const Xmm& x, const Operand& op) { vcmpngeps(x, x, op); } +void vcmpngesd(const Xmm& x, const Operand& op) { vcmpngesd(x, x, op); } +void vcmpngess(const Xmm& x, const Operand& op) { vcmpngess(x, x, op); } +void vcmpngt_uqpd(const Xmm& x, const Operand& op) { vcmpngt_uqpd(x, x, op); } +void vcmpngt_uqps(const Xmm& x, const Operand& op) { vcmpngt_uqps(x, x, op); } +void vcmpngt_uqsd(const Xmm& x, const Operand& op) { vcmpngt_uqsd(x, x, op); } +void vcmpngt_uqss(const Xmm& x, const Operand& op) { vcmpngt_uqss(x, x, op); } +void vcmpngtpd(const Xmm& x, const Operand& op) { vcmpngtpd(x, x, op); } +void vcmpngtps(const Xmm& x, const Operand& op) { vcmpngtps(x, x, op); } +void vcmpngtsd(const Xmm& x, const Operand& op) { vcmpngtsd(x, x, op); } +void vcmpngtss(const Xmm& x, const Operand& op) { vcmpngtss(x, x, op); } +void vcmpnle_uqpd(const Xmm& x, const Operand& op) { vcmpnle_uqpd(x, x, op); } +void vcmpnle_uqps(const Xmm& x, const Operand& op) { vcmpnle_uqps(x, x, op); } +void vcmpnle_uqsd(const Xmm& x, const Operand& op) { vcmpnle_uqsd(x, x, op); } +void vcmpnle_uqss(const Xmm& x, const Operand& op) { vcmpnle_uqss(x, x, op); } +void vcmpnlepd(const Xmm& x, const Operand& op) { vcmpnlepd(x, x, op); } +void vcmpnleps(const Xmm& x, const Operand& op) { vcmpnleps(x, x, op); } +void vcmpnlesd(const Xmm& x, const Operand& op) { vcmpnlesd(x, x, op); } +void vcmpnless(const Xmm& x, const Operand& op) { vcmpnless(x, x, op); } +void vcmpnlt_uqpd(const Xmm& x, const Operand& op) { vcmpnlt_uqpd(x, x, op); } +void vcmpnlt_uqps(const Xmm& x, const Operand& op) { vcmpnlt_uqps(x, x, op); } +void vcmpnlt_uqsd(const Xmm& x, const Operand& op) { vcmpnlt_uqsd(x, x, op); } +void vcmpnlt_uqss(const Xmm& x, const Operand& op) { vcmpnlt_uqss(x, x, op); } +void vcmpnltpd(const Xmm& x, const Operand& op) { vcmpnltpd(x, x, op); } +void vcmpnltps(const Xmm& x, const Operand& op) { vcmpnltps(x, x, op); } +void vcmpnltsd(const Xmm& x, const Operand& op) { vcmpnltsd(x, x, op); } +void vcmpnltss(const Xmm& x, const Operand& op) { vcmpnltss(x, x, op); } +void vcmpord_spd(const Xmm& x, const Operand& op) { vcmpord_spd(x, x, op); } +void vcmpord_sps(const Xmm& x, const Operand& op) { vcmpord_sps(x, x, op); } +void vcmpord_ssd(const Xmm& x, const Operand& op) { vcmpord_ssd(x, x, op); } +void vcmpord_sss(const Xmm& x, const Operand& op) { vcmpord_sss(x, x, op); } +void vcmpordpd(const Xmm& x, const Operand& op) { vcmpordpd(x, x, op); } +void vcmpordps(const Xmm& x, const Operand& op) { vcmpordps(x, x, op); } +void vcmpordsd(const Xmm& x, const Operand& op) { vcmpordsd(x, x, op); } +void vcmpordss(const Xmm& x, const Operand& op) { vcmpordss(x, x, op); } +void vcmppd(const Xmm& x, const Operand& op, uint8 imm) { vcmppd(x, x, op, imm); } +void vcmpps(const Xmm& x, const Operand& op, uint8 imm) { vcmpps(x, x, op, imm); } +void vcmpsd(const Xmm& x, const Operand& op, uint8 imm) { vcmpsd(x, x, op, imm); } +void vcmpss(const Xmm& x, const Operand& op, uint8 imm) { vcmpss(x, x, op, imm); } +void vcmptrue_uspd(const Xmm& x, const Operand& op) { vcmptrue_uspd(x, x, op); } +void vcmptrue_usps(const Xmm& x, const Operand& op) { vcmptrue_usps(x, x, op); } +void vcmptrue_ussd(const Xmm& x, const Operand& op) { vcmptrue_ussd(x, x, op); } +void vcmptrue_usss(const Xmm& x, const Operand& op) { vcmptrue_usss(x, x, op); } +void vcmptruepd(const Xmm& x, const Operand& op) { vcmptruepd(x, x, op); } +void vcmptrueps(const Xmm& x, const Operand& op) { vcmptrueps(x, x, op); } +void vcmptruesd(const Xmm& x, const Operand& op) { vcmptruesd(x, x, op); } +void vcmptruess(const Xmm& x, const Operand& op) { vcmptruess(x, x, op); } +void vcmpunord_spd(const Xmm& x, const Operand& op) { vcmpunord_spd(x, x, op); } +void vcmpunord_sps(const Xmm& x, const Operand& op) { vcmpunord_sps(x, x, op); } +void vcmpunord_ssd(const Xmm& x, const Operand& op) { vcmpunord_ssd(x, x, op); } +void vcmpunord_sss(const Xmm& x, const Operand& op) { vcmpunord_sss(x, x, op); } +void vcmpunordpd(const Xmm& x, const Operand& op) { vcmpunordpd(x, x, op); } +void vcmpunordps(const Xmm& x, const Operand& op) { vcmpunordps(x, x, op); } +void vcmpunordsd(const Xmm& x, const Operand& op) { vcmpunordsd(x, x, op); } +void vcmpunordss(const Xmm& x, const Operand& op) { vcmpunordss(x, x, op); } +void vcvtsd2ss(const Xmm& x, const Operand& op) { vcvtsd2ss(x, x, op); } +void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); } +void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); } +void vcvtss2sd(const Xmm& x, const Operand& op) { vcvtss2sd(x, x, op); } +void vdppd(const Xmm& x, const Operand& op, uint8 imm) { vdppd(x, x, op, imm); } +void vdpps(const Xmm& x, const Operand& op, uint8 imm) { vdpps(x, x, op, imm); } +void vinsertps(const Xmm& x, const Operand& op, uint8 imm) { vinsertps(x, x, op, imm); } +void vmpsadbw(const Xmm& x, const Operand& op, uint8 imm) { vmpsadbw(x, x, op, imm); } +void vpackssdw(const Xmm& x, const Operand& op) { vpackssdw(x, x, op); } +void vpacksswb(const Xmm& x, const Operand& op) { vpacksswb(x, x, op); } +void vpackusdw(const Xmm& x, const Operand& op) { vpackusdw(x, x, op); } +void vpackuswb(const Xmm& x, const Operand& op) { vpackuswb(x, x, op); } +void vpaddb(const Xmm& x, const Operand& op) { vpaddb(x, x, op); } +void vpaddd(const Xmm& x, const Operand& op) { vpaddd(x, x, op); } +void vpaddq(const Xmm& x, const Operand& op) { vpaddq(x, x, op); } +void vpaddsb(const Xmm& x, const Operand& op) { vpaddsb(x, x, op); } +void vpaddsw(const Xmm& x, const Operand& op) { vpaddsw(x, x, op); } +void vpaddusb(const Xmm& x, const Operand& op) { vpaddusb(x, x, op); } +void vpaddusw(const Xmm& x, const Operand& op) { vpaddusw(x, x, op); } +void vpaddw(const Xmm& x, const Operand& op) { vpaddw(x, x, op); } +void vpalignr(const Xmm& x, const Operand& op, uint8 imm) { vpalignr(x, x, op, imm); } +void vpand(const Xmm& x, const Operand& op) { vpand(x, x, op); } +void vpandn(const Xmm& x, const Operand& op) { vpandn(x, x, op); } +void vpavgb(const Xmm& x, const Operand& op) { vpavgb(x, x, op); } +void vpavgw(const Xmm& x, const Operand& op) { vpavgw(x, x, op); } +void vpblendd(const Xmm& x, const Operand& op, uint8 imm) { vpblendd(x, x, op, imm); } +void vpblendvb(const Xmm& x1, const Operand& op, const Xmm& x4) { vpblendvb(x1, x1, op, x4); } +void vpblendw(const Xmm& x, const Operand& op, uint8 imm) { vpblendw(x, x, op, imm); } +void vpclmulqdq(const Xmm& x, const Operand& op, uint8 imm) { vpclmulqdq(x, x, op, imm); } +void vpcmpeqb(const Xmm& x, const Operand& op) { vpcmpeqb(x, x, op); } +void vpcmpeqd(const Xmm& x, const Operand& op) { vpcmpeqd(x, x, op); } +void vpcmpeqq(const Xmm& x, const Operand& op) { vpcmpeqq(x, x, op); } +void vpcmpeqw(const Xmm& x, const Operand& op) { vpcmpeqw(x, x, op); } +void vpcmpgtb(const Xmm& x, const Operand& op) { vpcmpgtb(x, x, op); } +void vpcmpgtd(const Xmm& x, const Operand& op) { vpcmpgtd(x, x, op); } +void vpcmpgtq(const Xmm& x, const Operand& op) { vpcmpgtq(x, x, op); } +void vpcmpgtw(const Xmm& x, const Operand& op) { vpcmpgtw(x, x, op); } +void vphaddd(const Xmm& x, const Operand& op) { vphaddd(x, x, op); } +void vphaddsw(const Xmm& x, const Operand& op) { vphaddsw(x, x, op); } +void vphaddw(const Xmm& x, const Operand& op) { vphaddw(x, x, op); } +void vphsubd(const Xmm& x, const Operand& op) { vphsubd(x, x, op); } +void vphsubsw(const Xmm& x, const Operand& op) { vphsubsw(x, x, op); } +void vphsubw(const Xmm& x, const Operand& op) { vphsubw(x, x, op); } +void vpinsrb(const Xmm& x, const Operand& op, uint8 imm) { vpinsrb(x, x, op, imm); } +void vpinsrd(const Xmm& x, const Operand& op, uint8 imm) { vpinsrd(x, x, op, imm); } +void vpinsrq(const Xmm& x, const Operand& op, uint8 imm) { vpinsrq(x, x, op, imm); } +void vpinsrw(const Xmm& x, const Operand& op, uint8 imm) { vpinsrw(x, x, op, imm); } +void vpmaddubsw(const Xmm& x, const Operand& op) { vpmaddubsw(x, x, op); } +void vpmaddwd(const Xmm& x, const Operand& op) { vpmaddwd(x, x, op); } +void vpmaxsb(const Xmm& x, const Operand& op) { vpmaxsb(x, x, op); } +void vpmaxsd(const Xmm& x, const Operand& op) { vpmaxsd(x, x, op); } +void vpmaxsw(const Xmm& x, const Operand& op) { vpmaxsw(x, x, op); } +void vpmaxub(const Xmm& x, const Operand& op) { vpmaxub(x, x, op); } +void vpmaxud(const Xmm& x, const Operand& op) { vpmaxud(x, x, op); } +void vpmaxuw(const Xmm& x, const Operand& op) { vpmaxuw(x, x, op); } +void vpminsb(const Xmm& x, const Operand& op) { vpminsb(x, x, op); } +void vpminsd(const Xmm& x, const Operand& op) { vpminsd(x, x, op); } +void vpminsw(const Xmm& x, const Operand& op) { vpminsw(x, x, op); } +void vpminub(const Xmm& x, const Operand& op) { vpminub(x, x, op); } +void vpminud(const Xmm& x, const Operand& op) { vpminud(x, x, op); } +void vpminuw(const Xmm& x, const Operand& op) { vpminuw(x, x, op); } +void vpmuldq(const Xmm& x, const Operand& op) { vpmuldq(x, x, op); } +void vpmulhrsw(const Xmm& x, const Operand& op) { vpmulhrsw(x, x, op); } +void vpmulhuw(const Xmm& x, const Operand& op) { vpmulhuw(x, x, op); } +void vpmulhw(const Xmm& x, const Operand& op) { vpmulhw(x, x, op); } +void vpmulld(const Xmm& x, const Operand& op) { vpmulld(x, x, op); } +void vpmullw(const Xmm& x, const Operand& op) { vpmullw(x, x, op); } +void vpmuludq(const Xmm& x, const Operand& op) { vpmuludq(x, x, op); } +void vpor(const Xmm& x, const Operand& op) { vpor(x, x, op); } +void vpsadbw(const Xmm& x, const Operand& op) { vpsadbw(x, x, op); } +void vpsignb(const Xmm& x, const Operand& op) { vpsignb(x, x, op); } +void vpsignd(const Xmm& x, const Operand& op) { vpsignd(x, x, op); } +void vpsignw(const Xmm& x, const Operand& op) { vpsignw(x, x, op); } +void vpslld(const Xmm& x, const Operand& op) { vpslld(x, x, op); } +void vpslld(const Xmm& x, uint8 imm) { vpslld(x, x, imm); } +void vpslldq(const Xmm& x, uint8 imm) { vpslldq(x, x, imm); } +void vpsllq(const Xmm& x, const Operand& op) { vpsllq(x, x, op); } +void vpsllq(const Xmm& x, uint8 imm) { vpsllq(x, x, imm); } +void vpsllw(const Xmm& x, const Operand& op) { vpsllw(x, x, op); } +void vpsllw(const Xmm& x, uint8 imm) { vpsllw(x, x, imm); } +void vpsrad(const Xmm& x, const Operand& op) { vpsrad(x, x, op); } +void vpsrad(const Xmm& x, uint8 imm) { vpsrad(x, x, imm); } +void vpsraw(const Xmm& x, const Operand& op) { vpsraw(x, x, op); } +void vpsraw(const Xmm& x, uint8 imm) { vpsraw(x, x, imm); } +void vpsrld(const Xmm& x, const Operand& op) { vpsrld(x, x, op); } +void vpsrld(const Xmm& x, uint8 imm) { vpsrld(x, x, imm); } +void vpsrldq(const Xmm& x, uint8 imm) { vpsrldq(x, x, imm); } +void vpsrlq(const Xmm& x, const Operand& op) { vpsrlq(x, x, op); } +void vpsrlq(const Xmm& x, uint8 imm) { vpsrlq(x, x, imm); } +void vpsrlw(const Xmm& x, const Operand& op) { vpsrlw(x, x, op); } +void vpsrlw(const Xmm& x, uint8 imm) { vpsrlw(x, x, imm); } +void vpsubb(const Xmm& x, const Operand& op) { vpsubb(x, x, op); } +void vpsubd(const Xmm& x, const Operand& op) { vpsubd(x, x, op); } +void vpsubq(const Xmm& x, const Operand& op) { vpsubq(x, x, op); } +void vpsubsb(const Xmm& x, const Operand& op) { vpsubsb(x, x, op); } +void vpsubsw(const Xmm& x, const Operand& op) { vpsubsw(x, x, op); } +void vpsubusb(const Xmm& x, const Operand& op) { vpsubusb(x, x, op); } +void vpsubusw(const Xmm& x, const Operand& op) { vpsubusw(x, x, op); } +void vpsubw(const Xmm& x, const Operand& op) { vpsubw(x, x, op); } +void vpunpckhbw(const Xmm& x, const Operand& op) { vpunpckhbw(x, x, op); } +void vpunpckhdq(const Xmm& x, const Operand& op) { vpunpckhdq(x, x, op); } +void vpunpckhqdq(const Xmm& x, const Operand& op) { vpunpckhqdq(x, x, op); } +void vpunpckhwd(const Xmm& x, const Operand& op) { vpunpckhwd(x, x, op); } +void vpunpcklbw(const Xmm& x, const Operand& op) { vpunpcklbw(x, x, op); } +void vpunpckldq(const Xmm& x, const Operand& op) { vpunpckldq(x, x, op); } +void vpunpcklqdq(const Xmm& x, const Operand& op) { vpunpcklqdq(x, x, op); } +void vpunpcklwd(const Xmm& x, const Operand& op) { vpunpcklwd(x, x, op); } +void vpxor(const Xmm& x, const Operand& op) { vpxor(x, x, op); } +void vrcpss(const Xmm& x, const Operand& op) { vrcpss(x, x, op); } +void vroundsd(const Xmm& x, const Operand& op, uint8 imm) { vroundsd(x, x, op, imm); } +void vroundss(const Xmm& x, const Operand& op, uint8 imm) { vroundss(x, x, op, imm); } +void vrsqrtss(const Xmm& x, const Operand& op) { vrsqrtss(x, x, op); } +void vshufpd(const Xmm& x, const Operand& op, uint8 imm) { vshufpd(x, x, op, imm); } +void vshufps(const Xmm& x, const Operand& op, uint8 imm) { vshufps(x, x, op, imm); } +void vsqrtsd(const Xmm& x, const Operand& op) { vsqrtsd(x, x, op); } +void vsqrtss(const Xmm& x, const Operand& op) { vsqrtss(x, x, op); } +void vunpckhpd(const Xmm& x, const Operand& op) { vunpckhpd(x, x, op); } +void vunpckhps(const Xmm& x, const Operand& op) { vunpckhps(x, x, op); } +void vunpcklpd(const Xmm& x, const Operand& op) { vunpcklpd(x, x, op); } +void vunpcklps(const Xmm& x, const Operand& op) { vunpcklps(x, x, op); } +#endif +#ifdef XBYAK64 +void jecxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jrcxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jrcxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void cdqe() { db(0x48); db(0x98); } +void cqo() { db(0x48); db(0x99); } +void cmpsq() { db(0x48); db(0xA7); } +void movsq() { db(0x48); db(0xA5); } +void scasq() { db(0x48); db(0xAF); } +void stosq() { db(0x48); db(0xAB); } +void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xC7); } +void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); } +void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); } +void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) throw Error(ERR_BAD_COMBINATION); opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); } +void pextrq(const Operand& op, const Xmm& xmm, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); } +void pinsrq(const Xmm& xmm, const Operand& op, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); } +void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); } +void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); } +void vcvtsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_ER_X, 0x2D); } +void vcvttsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_SAE_X, 0x2C); } +void vmovq(const Xmm& x, const Reg64& r) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x6E); } +void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); } +#else +void jcxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jcxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void aaa() { db(0x37); } +void aad() { db(0xD5); db(0x0A); } +void aam() { db(0xD4); db(0x0A); } +void aas() { db(0x3F); } +void daa() { db(0x27); } +void das() { db(0x2F); } +void popad() { db(0x61); } +void popfd() { db(0x9D); } +void pusha() { db(0x60); } +void pushad() { db(0x60); } +void pushfd() { db(0x9C); } +void popa() { db(0x61); } +#endif +#ifndef XBYAK_NO_OP_NAMES +void and(const Operand& op1, const Operand& op2) { and_(op1, op2); } +void and(const Operand& op, uint32 imm) { and_(op, imm); } +void or(const Operand& op1, const Operand& op2) { or_(op1, op2); } +void or(const Operand& op, uint32 imm) { or_(op, imm); } +void xor(const Operand& op1, const Operand& op2) { xor_(op1, op2); } +void xor(const Operand& op, uint32 imm) { xor_(op, imm); } +void not(const Operand& op) { not_(op); } +#endif +#ifndef XBYAK_DISABLE_AVX512 +void kaddb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4A); } +void kaddd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x4A); } +void kaddq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4A); } +void kaddw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4A); } +void kandb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x41); } +void kandd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x41); } +void kandnb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x42); } +void kandnd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x42); } +void kandnq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x42); } +void kandnw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x42); } +void kandq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x41); } +void kandw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x41); } +void kmovb(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W0, 0x91); } +void kmovb(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W0, 0x90); } +void kmovb(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_66 | T_W0, 0x92); } +void kmovb(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_66 | T_W0, 0x93); } +void kmovd(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W1, 0x91); } +void kmovd(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W1, 0x90); } +void kmovd(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W0, 0x92); } +void kmovd(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W0, 0x93); } +void kmovq(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W1, 0x91); } +void kmovq(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_W1, 0x90); } +void kmovw(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W0, 0x91); } +void kmovw(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_W0, 0x90); } +void kmovw(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_W0, 0x92); } +void kmovw(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_W0, 0x93); } +void knotb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x44); } +void knotd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x44); } +void knotq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x44); } +void knotw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x44); } +void korb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x45); } +void kord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x45); } +void korq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x45); } +void kortestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x98); } +void kortestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x98); } +void kortestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x98); } +void kortestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x98); } +void korw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x45); } +void kshiftlb(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x32, imm); } +void kshiftld(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x33, imm); } +void kshiftlq(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x33, imm); } +void kshiftlw(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x32, imm); } +void kshiftrb(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x30, imm); } +void kshiftrd(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x31, imm); } +void kshiftrq(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x31, imm); } +void kshiftrw(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x30, imm); } +void ktestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x99); } +void ktestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x99); } +void ktestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x99); } +void ktestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x99); } +void kunpckbw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4B); } +void kunpckdq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4B); } +void kunpckwd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4B); } +void kxnorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x46); } +void kxnord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x46); } +void kxnorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x46); } +void kxnorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x46); } +void kxorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x47); } +void kxord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x47); } +void kxorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x47); } +void kxorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x47); } +void v4fmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x9A); } +void v4fmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0x9B); } +void v4fnmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0xAA); } +void v4fnmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0xAB); } +void valignd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x03, imm); } +void valignq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x03, imm); } +void vblendmpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x65); } +void vblendmps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x65); } +void vbroadcastf32x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x19); } +void vbroadcastf32x4(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x1A); } +void vbroadcastf32x8(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x1B); } +void vbroadcastf64x2(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x1A); } +void vbroadcastf64x4(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x1B); } +void vbroadcasti32x2(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x59); } +void vbroadcasti32x4(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x5A); } +void vbroadcasti32x8(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x5B); } +void vbroadcasti64x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x5A); } +void vbroadcasti64x4(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x5B); } +void vcmppd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } +void vcmpps(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } +void vcmpsd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N8 | T_F2 | T_0F | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } +void vcmpss(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N4 | T_F3 | T_0F | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } +void vcompressb(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x63); } +void vcompresspd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8A); } +void vcompressps(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8A); } +void vcompressw(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x63); } +void vcvtpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7B); } +void vcvtpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x79); } +void vcvtpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); } +void vcvtps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_ER_Y, 0x7B); } +void vcvtps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x79); } +void vcvtps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_ER_Y, 0x79); } +void vcvtqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0xE6); } +void vcvtqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5B); } +void vcvtsd2usi(const Reg32e& r, const Operand& op) { int type = (T_F2 | T_0F | T_MUST_EVEX | T_N8 | T_ER_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x79); } +void vcvtss2usi(const Reg32e& r, const Operand& op) { int type = (T_F3 | T_0F | T_MUST_EVEX | T_N4 | T_ER_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x79); } +void vcvttpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x7A); } +void vcvttpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_SAE_Z, 0x78); } +void vcvttpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x78); } +void vcvttps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x7A); } +void vcvttps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x78); } +void vcvttps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x78); } +void vcvttsd2usi(const Reg32e& r, const Operand& op) { int type = (T_F2 | T_0F | T_MUST_EVEX | T_N8 | T_SAE_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x78); } +void vcvttss2usi(const Reg32e& r, const Operand& op) { int type = (T_F3 | T_0F | T_MUST_EVEX | T_N4 | T_SAE_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x78); } +void vcvtudq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_F3 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0x7A); } +void vcvtudq2ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x7A); } +void vcvtuqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); } +void vcvtuqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_F2 | T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x7A); } +void vcvtusi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F2 | T_0F | T_MUST_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); } +void vcvtusi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F3 | T_0F | T_MUST_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); } +void vdbpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x42, imm); } +void vexp2pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xC8); } +void vexp2ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xC8); } +void vexpandpd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x88); } +void vexpandps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x88); } +void vextractf32x4(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x19, imm); } +void vextractf32x8(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1B, imm); } +void vextractf64x2(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x19, imm); } +void vextractf64x4(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1B, imm); } +void vextracti32x4(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x39, imm); } +void vextracti32x8(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3B, imm); } +void vextracti64x2(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x39, imm); } +void vextracti64x4(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3B, imm); } +void vfixupimmpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x54, imm); } +void vfixupimmps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x54, imm); } +void vfixupimmsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); } +void vfixupimmss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); } +void vfpclasspd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); Reg x = k; x.setBit(op.getBit()); opVex(x, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW1 | T_B64, 0x66, imm); } +void vfpclassps(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); Reg x = k; x.setBit(op.getBit()); opVex(x, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); } +void vfpclasssd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); } +void vfpclassss(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); } +void vgatherdpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 1); } +void vgatherdps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 0); } +void vgatherpf0dpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vgatherpf0dps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vgatherpf0qpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherpf0qps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherpf1dpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vgatherpf1dps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vgatherpf1qpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherpf1qps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherqpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 0); } +void vgatherqps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 2); } +void vgetexppd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x42); } +void vgetexpps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x42); } +void vgetexpsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x43); } +void vgetexpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x43); } +void vgetmantpd(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x26, imm); } +void vgetmantps(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x26, imm); } +void vgetmantsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x27, imm); } +void vgetmantss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x27, imm); } +void vinsertf32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x18, imm); } +void vinsertf32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1A, imm); } +void vinsertf64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x18, imm); } +void vinsertf64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1A, imm); } +void vinserti32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x38, imm); } +void vinserti32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3A, imm); } +void vinserti64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x38, imm); } +void vinserti64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3A, imm); } +void vmovdqa32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqa32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqa64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqa64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu16(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu16(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu8(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu8(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vp4dpwssd(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x52); } +void vp4dpwssds(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x53); } +void vpabsq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_MUST_EVEX | T_EW1 | T_B64 | T_YMM, 0x1F); } +void vpandd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDB); } +void vpandnd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDF); } +void vpandnq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDF); } +void vpandq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDB); } +void vpblendmb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x66); } +void vpblendmd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x64); } +void vpblendmq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x64); } +void vpblendmw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x66); } +void vpbroadcastb(const Xmm& x, const Reg8& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7A); } +void vpbroadcastd(const Xmm& x, const Reg32& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7C); } +void vpbroadcastmb2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1, 0x2A); } +void vpbroadcastmw2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0, 0x3A); } +void vpbroadcastw(const Xmm& x, const Reg16& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7B); } +void vpcmpb(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3F, imm); } +void vpcmpd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1F, imm); } +void vpcmpeqb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x74); } +void vpcmpeqd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_B32, 0x76); } +void vpcmpeqq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x29); } +void vpcmpeqw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x75); } +void vpcmpgtb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x64); } +void vpcmpgtd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x66); } +void vpcmpgtq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x37); } +void vpcmpgtw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x65); } +void vpcmpq(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1F, imm); } +void vpcmpub(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3E, imm); } +void vpcmpud(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1E, imm); } +void vpcmpuq(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1E, imm); } +void vpcmpuw(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3E, imm); } +void vpcmpw(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3F, imm); } +void vpcompressd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8B); } +void vpcompressq(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8B); } +void vpconflictd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xC4); } +void vpconflictq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xC4); } +void vpdpbusd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x50); } +void vpdpbusds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x51); } +void vpdpwssd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x52); } +void vpdpwssds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x53); } +void vpermb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8D); } +void vpermi2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x75); } +void vpermi2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x76); } +void vpermi2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x77); } +void vpermi2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x77); } +void vpermi2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x76); } +void vpermi2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x75); } +void vpermt2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7D); } +void vpermt2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7E); } +void vpermt2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7F); } +void vpermt2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7F); } +void vpermt2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7E); } +void vpermt2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7D); } +void vpermw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8D); } +void vpexpandb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); } +void vpexpandd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x89); } +void vpexpandq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x89); } +void vpexpandw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); } +void vpgatherdd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 0); } +void vpgatherdq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 1); } +void vpgatherqd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 2); } +void vpgatherqq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 0); } +void vplzcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x44); } +void vplzcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x44); } +void vpmadd52huq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xB5); } +void vpmadd52luq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xB4); } +void vpmaxsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3D); } +void vpmaxuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3F); } +void vpminsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x39); } +void vpminuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3B); } +void vpmovb2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x29); } +void vpmovd2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x39); } +void vpmovdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x31, false); } +void vpmovdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x33, true); } +void vpmovm2b(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x28); } +void vpmovm2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x38); } +void vpmovm2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x38); } +void vpmovm2w(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x28); } +void vpmovq2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x39); } +void vpmovqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x32, false); } +void vpmovqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x35, true); } +void vpmovqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x34, false); } +void vpmovsdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x21, false); } +void vpmovsdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x23, true); } +void vpmovsqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x22, false); } +void vpmovsqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x25, true); } +void vpmovsqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x24, false); } +void vpmovswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x20, true); } +void vpmovusdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x11, false); } +void vpmovusdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x13, true); } +void vpmovusqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x12, false); } +void vpmovusqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x15, true); } +void vpmovusqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x14, false); } +void vpmovuswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x10, true); } +void vpmovw2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x29); } +void vpmovwb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x30, true); } +void vpmullq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x40); } +void vpmultishiftqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x83); } +void vpopcntb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); } +void vpopcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x55); } +void vpopcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x55); } +void vpopcntw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); } +void vpord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEB); } +void vporq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEB); } +void vprold(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); } +void vprolq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); } +void vprolvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x15); } +void vprolvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x15); } +void vprord(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); } +void vprorq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); } +void vprorvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x14); } +void vprorvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x14); } +void vpscatterdd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 0); } +void vpscatterdq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 1); } +void vpscatterqd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 2); } +void vpscatterqq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 0); } +void vpshldd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71, imm); } +void vpshldq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71, imm); } +void vpshldvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71); } +void vpshldvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71); } +void vpshldvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70); } +void vpshldw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70, imm); } +void vpshrdd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73, imm); } +void vpshrdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73, imm); } +void vpshrdvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73); } +void vpshrdvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73); } +void vpshrdvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72); } +void vpshrdw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72, imm); } +void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); } +void vpsllvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x12); } +void vpsraq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); } +void vpsraq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX, 0xE2); } +void vpsravq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x46); } +void vpsravw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x11); } +void vpsrlvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x10); } +void vpternlogd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x25, imm); } +void vpternlogq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x25, imm); } +void vptestmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); } +void vptestmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); } +void vptestmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); } +void vptestmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); } +void vptestnmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); } +void vptestnmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); } +void vptestnmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); } +void vptestnmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); } +void vpxord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEF); } +void vpxorq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEF); } +void vrangepd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x50, imm); } +void vrangeps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x50, imm); } +void vrangesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x51, imm); } +void vrangess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x51, imm); } +void vrcp14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4C); } +void vrcp14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4C); } +void vrcp14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX, 0x4D); } +void vrcp14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX, 0x4D); } +void vrcp28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCA); } +void vrcp28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCA); } +void vrcp28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCB); } +void vrcp28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCB); } +void vreducepd(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x56, imm); } +void vreduceps(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x56, imm); } +void vreducesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x57, imm); } +void vreducess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x57, imm); } +void vrndscalepd(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x09, imm); } +void vrndscaleps(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x08, imm); } +void vrndscalesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_MUST_EVEX, 0x0B, imm); } +void vrndscaless(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_MUST_EVEX, 0x0A, imm); } +void vrsqrt14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4E); } +void vrsqrt14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4E); } +void vrsqrt14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x4F); } +void vrsqrt14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x4F); } +void vrsqrt28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCC); } +void vrsqrt28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCC); } +void vrsqrt28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCD); } +void vrsqrt28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCD); } +void vscalefpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x2C); } +void vscalefps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x2C); } +void vscalefsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_ER_X | T_MUST_EVEX, 0x2D); } +void vscalefss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x2D); } +void vscatterdpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 1); } +void vscatterdps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 0); } +void vscatterpf0dpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vscatterpf0dps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vscatterpf0qpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterpf0qps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterpf1dpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vscatterpf1dps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vscatterpf1qpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterpf1qps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterqpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 0); } +void vscatterqps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 2); } +void vshuff32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x23, imm); } +void vshuff64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x23, imm); } +void vshufi32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x43, imm); } +void vshufi64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x43, imm); } +#ifdef XBYAK64 +void kmovq(const Opmask& k, const Reg64& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W1, 0x92); } +void kmovq(const Reg64& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W1, 0x93); } +void vpbroadcastq(const Xmm& x, const Reg64& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7C); } +#endif +#endif diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h new file mode 100644 index 0000000000..8ef076e680 --- /dev/null +++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h @@ -0,0 +1,772 @@ +/******************************************************************************* +* Copyright 2016-2019 Intel Corporation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +/******************************************************************************* +* Copyright (c) 2007 MITSUNARI Shigeo +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* Neither the name of the copyright owner nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XBYAK_XBYAK_UTIL_H_ +#define XBYAK_XBYAK_UTIL_H_ + +/** + utility class and functions for Xbyak + Xbyak::util::Clock ; rdtsc timer + Xbyak::util::Cpu ; detect CPU + @note this header is UNDER CONSTRUCTION! +*/ +#include "xbyak.h" + +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) + #define XBYAK_INTEL_CPU_SPECIFIC +#endif + +#ifdef XBYAK_INTEL_CPU_SPECIFIC +#ifdef _MSC_VER + #if (_MSC_VER < 1400) && defined(XBYAK32) + static inline __declspec(naked) void __cpuid(int[4], int) + { + __asm { + push ebx + push esi + mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn + cpuid + mov esi, dword ptr [esp + 4 * 2 + 4] // data + mov dword ptr [esi], eax + mov dword ptr [esi + 4], ebx + mov dword ptr [esi + 8], ecx + mov dword ptr [esi + 12], edx + pop esi + pop ebx + ret + } + } + #else + #include // for __cpuid + #endif +#else + #ifndef __GNUC_PREREQ + #define __GNUC_PREREQ(major, minor) ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor))) + #endif + #if __GNUC_PREREQ(4, 3) && !defined(__APPLE__) + #include + #else + #if defined(__APPLE__) && defined(XBYAK32) // avoid err : can't find a register in class `BREG' while reloading `asm' + #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn)) + #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn)) + #else + #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn)) + #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn)) + #endif + #endif +#endif +#endif + +namespace Xbyak { namespace util { + +typedef enum { + SmtLevel = 1, + CoreLevel = 2 +} IntelCpuTopologyLevel; + +/** + CPU detection class +*/ +class Cpu { + uint64 type_; + //system topology + bool x2APIC_supported_; + static const size_t maxTopologyLevels = 2; + unsigned int numCores_[maxTopologyLevels]; + + static const unsigned int maxNumberCacheLevels = 10; + unsigned int dataCacheSize_[maxNumberCacheLevels]; + unsigned int coresSharignDataCache_[maxNumberCacheLevels]; + unsigned int dataCacheLevels_; + + unsigned int get32bitAsBE(const char *x) const + { + return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); + } + unsigned int mask(int n) const + { + return (1U << n) - 1; + } + void setFamily() + { + unsigned int data[4] = {}; + getCpuid(1, data); + stepping = data[0] & mask(4); + model = (data[0] >> 4) & mask(4); + family = (data[0] >> 8) & mask(4); + // type = (data[0] >> 12) & mask(2); + extModel = (data[0] >> 16) & mask(4); + extFamily = (data[0] >> 20) & mask(8); + if (family == 0x0f) { + displayFamily = family + extFamily; + } else { + displayFamily = family; + } + if (family == 6 || family == 0x0f) { + displayModel = (extModel << 4) + model; + } else { + displayModel = model; + } + } + unsigned int extractBit(unsigned int val, unsigned int base, unsigned int end) + { + return (val >> base) & ((1u << (end - base)) - 1); + } + void setNumCores() + { + if ((type_ & tINTEL) == 0) return; + + unsigned int data[4] = {}; + + /* CAUTION: These numbers are configuration as shipped by Intel. */ + getCpuidEx(0x0, 0, data); + if (data[0] >= 0xB) { + /* + if leaf 11 exists(x2APIC is supported), + we use it to get the number of smt cores and cores on socket + + leaf 0xB can be zeroed-out by a hypervisor + */ + x2APIC_supported_ = true; + for (unsigned int i = 0; i < maxTopologyLevels; i++) { + getCpuidEx(0xB, i, data); + IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extractBit(data[2], 8, 15); + if (level == SmtLevel || level == CoreLevel) { + numCores_[level - 1] = extractBit(data[1], 0, 15); + } + } + } else { + /* + Failed to deremine num of cores without x2APIC support. + TODO: USE initial APIC ID to determine ncores. + */ + numCores_[SmtLevel - 1] = 0; + numCores_[CoreLevel - 1] = 0; + } + + } + void setCacheHierarchy() + { + if ((type_ & tINTEL) == 0) return; + const unsigned int NO_CACHE = 0; + const unsigned int DATA_CACHE = 1; +// const unsigned int INSTRUCTION_CACHE = 2; + const unsigned int UNIFIED_CACHE = 3; + unsigned int smt_width = 0; + unsigned int logical_cores = 0; + unsigned int data[4] = {}; + + if (x2APIC_supported_) { + smt_width = numCores_[0]; + logical_cores = numCores_[1]; + } + + /* + Assumptions: + the first level of data cache is not shared (which is the + case for every existing architecture) and use this to + determine the SMT width for arch not supporting leaf 11. + when leaf 4 reports a number of core less than numCores_ + on socket reported by leaf 11, then it is a correct number + of cores not an upperbound. + */ + for (int i = 0; dataCacheLevels_ < maxNumberCacheLevels; i++) { + getCpuidEx(0x4, i, data); + unsigned int cacheType = extractBit(data[0], 0, 4); + if (cacheType == NO_CACHE) break; + if (cacheType == DATA_CACHE || cacheType == UNIFIED_CACHE) { + unsigned int actual_logical_cores = extractBit(data[0], 14, 25) + 1; + if (logical_cores != 0) { // true only if leaf 0xB is supported and valid + actual_logical_cores = (std::min)(actual_logical_cores, logical_cores); + } + assert(actual_logical_cores != 0); + dataCacheSize_[dataCacheLevels_] = + (extractBit(data[1], 22, 31) + 1) + * (extractBit(data[1], 12, 21) + 1) + * (extractBit(data[1], 0, 11) + 1) + * (data[2] + 1); + if (cacheType == DATA_CACHE && smt_width == 0) smt_width = actual_logical_cores; + assert(smt_width != 0); + // FIXME: check and fix number of cores sharing L3 cache for different configurations + // (HT-, 2 sockets), (HT-, 1 socket), (HT+, 2 sockets), (HT+, 1 socket) + coresSharignDataCache_[dataCacheLevels_] = (std::max)(actual_logical_cores / smt_width, 1u); + dataCacheLevels_++; + } + } + } + +public: + int model; + int family; + int stepping; + int extModel; + int extFamily; + int displayFamily; // family + extFamily + int displayModel; // model + extModel + + unsigned int getNumCores(IntelCpuTopologyLevel level) { + if (level != SmtLevel && level != CoreLevel) throw Error(ERR_BAD_PARAMETER); + if (!x2APIC_supported_) throw Error(ERR_X2APIC_IS_NOT_SUPPORTED); + return (level == CoreLevel) + ? numCores_[level - 1] / numCores_[SmtLevel - 1] + : numCores_[level - 1]; + } + + unsigned int getDataCacheLevels() const { return dataCacheLevels_; } + unsigned int getCoresSharingDataCache(unsigned int i) const + { + if (i >= dataCacheLevels_) throw Error(ERR_BAD_PARAMETER); + return coresSharignDataCache_[i]; + } + unsigned int getDataCacheSize(unsigned int i) const + { + if (i >= dataCacheLevels_) throw Error(ERR_BAD_PARAMETER); + return dataCacheSize_[i]; + } + + /* + data[] = { eax, ebx, ecx, edx } + */ + static inline void getCpuid(unsigned int eaxIn, unsigned int data[4]) + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _MSC_VER + __cpuid(reinterpret_cast(data), eaxIn); + #else + __cpuid(eaxIn, data[0], data[1], data[2], data[3]); + #endif +#else + (void)eaxIn; + (void)data; +#endif + } + static inline void getCpuidEx(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _MSC_VER + __cpuidex(reinterpret_cast(data), eaxIn, ecxIn); + #else + __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]); + #endif +#else + (void)eaxIn; + (void)ecxIn; + (void)data; +#endif + } + static inline uint64 getXfeature() + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _MSC_VER + return _xgetbv(0); + #else + unsigned int eax, edx; + // xgetvb is not support on gcc 4.2 +// __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0)); + __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0)); + return ((uint64)edx << 32) | eax; + #endif +#else + return 0; +#endif + } + typedef uint64 Type; + + static const Type NONE = 0; + static const Type tMMX = 1 << 0; + static const Type tMMX2 = 1 << 1; + static const Type tCMOV = 1 << 2; + static const Type tSSE = 1 << 3; + static const Type tSSE2 = 1 << 4; + static const Type tSSE3 = 1 << 5; + static const Type tSSSE3 = 1 << 6; + static const Type tSSE41 = 1 << 7; + static const Type tSSE42 = 1 << 8; + static const Type tPOPCNT = 1 << 9; + static const Type tAESNI = 1 << 10; + static const Type tSSE5 = 1 << 11; + static const Type tOSXSAVE = 1 << 12; + static const Type tPCLMULQDQ = 1 << 13; + static const Type tAVX = 1 << 14; + static const Type tFMA = 1 << 15; + + static const Type t3DN = 1 << 16; + static const Type tE3DN = 1 << 17; + static const Type tSSE4a = 1 << 18; + static const Type tRDTSCP = 1 << 19; + static const Type tAVX2 = 1 << 20; + static const Type tBMI1 = 1 << 21; // andn, bextr, blsi, blsmsk, blsr, tzcnt + static const Type tBMI2 = 1 << 22; // bzhi, mulx, pdep, pext, rorx, sarx, shlx, shrx + static const Type tLZCNT = 1 << 23; + + static const Type tINTEL = 1 << 24; + static const Type tAMD = 1 << 25; + + static const Type tENHANCED_REP = 1 << 26; // enhanced rep movsb/stosb + static const Type tRDRAND = 1 << 27; + static const Type tADX = 1 << 28; // adcx, adox + static const Type tRDSEED = 1 << 29; // rdseed + static const Type tSMAP = 1 << 30; // stac + static const Type tHLE = uint64(1) << 31; // xacquire, xrelease, xtest + static const Type tRTM = uint64(1) << 32; // xbegin, xend, xabort + static const Type tF16C = uint64(1) << 33; // vcvtph2ps, vcvtps2ph + static const Type tMOVBE = uint64(1) << 34; // mobve + static const Type tAVX512F = uint64(1) << 35; + static const Type tAVX512DQ = uint64(1) << 36; + static const Type tAVX512_IFMA = uint64(1) << 37; + static const Type tAVX512IFMA = tAVX512_IFMA; + static const Type tAVX512PF = uint64(1) << 38; + static const Type tAVX512ER = uint64(1) << 39; + static const Type tAVX512CD = uint64(1) << 40; + static const Type tAVX512BW = uint64(1) << 41; + static const Type tAVX512VL = uint64(1) << 42; + static const Type tAVX512_VBMI = uint64(1) << 43; + static const Type tAVX512VBMI = tAVX512_VBMI; // changed by Intel's manual + static const Type tAVX512_4VNNIW = uint64(1) << 44; + static const Type tAVX512_4FMAPS = uint64(1) << 45; + static const Type tPREFETCHWT1 = uint64(1) << 46; + static const Type tPREFETCHW = uint64(1) << 47; + static const Type tSHA = uint64(1) << 48; + static const Type tMPX = uint64(1) << 49; + static const Type tAVX512_VBMI2 = uint64(1) << 50; + static const Type tGFNI = uint64(1) << 51; + static const Type tVAES = uint64(1) << 52; + static const Type tVPCLMULQDQ = uint64(1) << 53; + static const Type tAVX512_VNNI = uint64(1) << 54; + static const Type tAVX512_BITALG = uint64(1) << 55; + static const Type tAVX512_VPOPCNTDQ = uint64(1) << 56; + + Cpu() + : type_(NONE) + , x2APIC_supported_(false) + , numCores_() + , dataCacheSize_() + , coresSharignDataCache_() + , dataCacheLevels_(0) + { + unsigned int data[4] = {}; + const unsigned int& EAX = data[0]; + const unsigned int& EBX = data[1]; + const unsigned int& ECX = data[2]; + const unsigned int& EDX = data[3]; + getCpuid(0, data); + const unsigned int maxNum = EAX; + static const char intel[] = "ntel"; + static const char amd[] = "cAMD"; + if (ECX == get32bitAsBE(amd)) { + type_ |= tAMD; + getCpuid(0x80000001, data); + if (EDX & (1U << 31)) type_ |= t3DN; + if (EDX & (1U << 15)) type_ |= tCMOV; + if (EDX & (1U << 30)) type_ |= tE3DN; + if (EDX & (1U << 22)) type_ |= tMMX2; + if (EDX & (1U << 27)) type_ |= tRDTSCP; + } + if (ECX == get32bitAsBE(intel)) { + type_ |= tINTEL; + getCpuid(0x80000001, data); + if (EDX & (1U << 27)) type_ |= tRDTSCP; + if (ECX & (1U << 5)) type_ |= tLZCNT; + if (ECX & (1U << 8)) type_ |= tPREFETCHW; + } + getCpuid(1, data); + if (ECX & (1U << 0)) type_ |= tSSE3; + if (ECX & (1U << 9)) type_ |= tSSSE3; + if (ECX & (1U << 19)) type_ |= tSSE41; + if (ECX & (1U << 20)) type_ |= tSSE42; + if (ECX & (1U << 22)) type_ |= tMOVBE; + if (ECX & (1U << 23)) type_ |= tPOPCNT; + if (ECX & (1U << 25)) type_ |= tAESNI; + if (ECX & (1U << 1)) type_ |= tPCLMULQDQ; + if (ECX & (1U << 27)) type_ |= tOSXSAVE; + if (ECX & (1U << 30)) type_ |= tRDRAND; + if (ECX & (1U << 29)) type_ |= tF16C; + + if (EDX & (1U << 15)) type_ |= tCMOV; + if (EDX & (1U << 23)) type_ |= tMMX; + if (EDX & (1U << 25)) type_ |= tMMX2 | tSSE; + if (EDX & (1U << 26)) type_ |= tSSE2; + + if (type_ & tOSXSAVE) { + // check XFEATURE_ENABLED_MASK[2:1] = '11b' + uint64 bv = getXfeature(); + if ((bv & 6) == 6) { + if (ECX & (1U << 28)) type_ |= tAVX; + if (ECX & (1U << 12)) type_ |= tFMA; + if (((bv >> 5) & 7) == 7) { + getCpuidEx(7, 0, data); + if (EBX & (1U << 16)) type_ |= tAVX512F; + if (type_ & tAVX512F) { + if (EBX & (1U << 17)) type_ |= tAVX512DQ; + if (EBX & (1U << 21)) type_ |= tAVX512_IFMA; + if (EBX & (1U << 26)) type_ |= tAVX512PF; + if (EBX & (1U << 27)) type_ |= tAVX512ER; + if (EBX & (1U << 28)) type_ |= tAVX512CD; + if (EBX & (1U << 30)) type_ |= tAVX512BW; + if (EBX & (1U << 31)) type_ |= tAVX512VL; + if (ECX & (1U << 1)) type_ |= tAVX512_VBMI; + if (ECX & (1U << 6)) type_ |= tAVX512_VBMI2; + if (ECX & (1U << 8)) type_ |= tGFNI; + if (ECX & (1U << 9)) type_ |= tVAES; + if (ECX & (1U << 10)) type_ |= tVPCLMULQDQ; + if (ECX & (1U << 11)) type_ |= tAVX512_VNNI; + if (ECX & (1U << 12)) type_ |= tAVX512_BITALG; + if (ECX & (1U << 14)) type_ |= tAVX512_VPOPCNTDQ; + if (EDX & (1U << 2)) type_ |= tAVX512_4VNNIW; + if (EDX & (1U << 3)) type_ |= tAVX512_4FMAPS; + } + } + } + } + if (maxNum >= 7) { + getCpuidEx(7, 0, data); + if (type_ & tAVX && (EBX & (1U << 5))) type_ |= tAVX2; + if (EBX & (1U << 3)) type_ |= tBMI1; + if (EBX & (1U << 8)) type_ |= tBMI2; + if (EBX & (1U << 9)) type_ |= tENHANCED_REP; + if (EBX & (1U << 18)) type_ |= tRDSEED; + if (EBX & (1U << 19)) type_ |= tADX; + if (EBX & (1U << 20)) type_ |= tSMAP; + if (EBX & (1U << 4)) type_ |= tHLE; + if (EBX & (1U << 11)) type_ |= tRTM; + if (EBX & (1U << 14)) type_ |= tMPX; + if (EBX & (1U << 29)) type_ |= tSHA; + if (ECX & (1U << 0)) type_ |= tPREFETCHWT1; + } + setFamily(); + setNumCores(); + setCacheHierarchy(); + } + void putFamily() const + { + printf("family=%d, model=%X, stepping=%d, extFamily=%d, extModel=%X\n", + family, model, stepping, extFamily, extModel); + printf("display:family=%X, model=%X\n", displayFamily, displayModel); + } + bool has(Type type) const + { + return (type & type_) != 0; + } +}; + +class Clock { +public: + static inline uint64 getRdtsc() + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _MSC_VER + return __rdtsc(); + #else + unsigned int eax, edx; + __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx)); + return ((uint64)edx << 32) | eax; + #endif +#else + // TODO: Need another impl of Clock or rdtsc-equivalent for non-x86 cpu + return 0; +#endif + } + Clock() + : clock_(0) + , count_(0) + { + } + void begin() + { + clock_ -= getRdtsc(); + } + void end() + { + clock_ += getRdtsc(); + count_++; + } + int getCount() const { return count_; } + uint64 getClock() const { return clock_; } + void clear() { count_ = 0; clock_ = 0; } +private: + uint64 clock_; + int count_; +}; + +#ifdef XBYAK64 +const int UseRCX = 1 << 6; +const int UseRDX = 1 << 7; + +class Pack { + static const size_t maxTblNum = 15; + const Xbyak::Reg64 *tbl_[maxTblNum]; + size_t n_; +public: + Pack() : tbl_(), n_(0) {} + Pack(const Xbyak::Reg64 *tbl, size_t n) { init(tbl, n); } + Pack(const Pack& rhs) + : n_(rhs.n_) + { + for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i]; + } + Pack& operator=(const Pack& rhs) + { + n_ = rhs.n_; + for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i]; + return *this; + } + Pack(const Xbyak::Reg64& t0) + { n_ = 1; tbl_[0] = &t0; } + Pack(const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 2; tbl_[0] = &t0; tbl_[1] = &t1; } + Pack(const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 3; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; } + Pack(const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 4; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; } + Pack(const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 5; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; } + Pack(const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 6; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; } + Pack(const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 7; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; } + Pack(const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 8; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; tbl_[7] = &t7; } + Pack(const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 9; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; tbl_[7] = &t7; tbl_[8] = &t8; } + Pack(const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 10; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; tbl_[7] = &t7; tbl_[8] = &t8; tbl_[9] = &t9; } + Pack& append(const Xbyak::Reg64& t) + { + if (n_ == maxTblNum) { + fprintf(stderr, "ERR Pack::can't append\n"); + throw Error(ERR_BAD_PARAMETER); + } + tbl_[n_++] = &t; + return *this; + } + void init(const Xbyak::Reg64 *tbl, size_t n) + { + if (n > maxTblNum) { + fprintf(stderr, "ERR Pack::init bad n=%d\n", (int)n); + throw Error(ERR_BAD_PARAMETER); + } + n_ = n; + for (size_t i = 0; i < n; i++) { + tbl_[i] = &tbl[i]; + } + } + const Xbyak::Reg64& operator[](size_t n) const + { + if (n >= n_) { + fprintf(stderr, "ERR Pack bad n=%d(%d)\n", (int)n, (int)n_); + throw Error(ERR_BAD_PARAMETER); + } + return *tbl_[n]; + } + size_t size() const { return n_; } + /* + get tbl[pos, pos + num) + */ + Pack sub(size_t pos, size_t num = size_t(-1)) const + { + if (num == size_t(-1)) num = n_ - pos; + if (pos + num > n_) { + fprintf(stderr, "ERR Pack::sub bad pos=%d, num=%d\n", (int)pos, (int)num); + throw Error(ERR_BAD_PARAMETER); + } + Pack pack; + pack.n_ = num; + for (size_t i = 0; i < num; i++) { + pack.tbl_[i] = tbl_[pos + i]; + } + return pack; + } + void put() const + { + for (size_t i = 0; i < n_; i++) { + printf("%s ", tbl_[i]->toString()); + } + printf("\n"); + } +}; + +class StackFrame { +#ifdef XBYAK64_WIN + static const int noSaveNum = 6; + static const int rcxPos = 0; + static const int rdxPos = 1; +#else + static const int noSaveNum = 8; + static const int rcxPos = 3; + static const int rdxPos = 2; +#endif + static const int maxRegNum = 14; // maxRegNum = 16 - rsp - rax + Xbyak::CodeGenerator *code_; + int pNum_; + int tNum_; + bool useRcx_; + bool useRdx_; + int saveNum_; + int P_; + bool makeEpilog_; + Xbyak::Reg64 pTbl_[4]; + Xbyak::Reg64 tTbl_[maxRegNum]; + Pack p_; + Pack t_; + StackFrame(const StackFrame&); + void operator=(const StackFrame&); +public: + const Pack& p; + const Pack& t; + /* + make stack frame + @param sf [in] this + @param pNum [in] num of function parameter(0 <= pNum <= 4) + @param tNum [in] num of temporary register(0 <= tNum, with UseRCX, UseRDX) #{pNum + tNum [+rcx] + [rdx]} <= 14 + @param stackSizeByte [in] local stack size + @param makeEpilog [in] automatically call close() if true + + you can use + rax + gp0, ..., gp(pNum - 1) + gt0, ..., gt(tNum-1) + rcx if tNum & UseRCX + rdx if tNum & UseRDX + rsp[0..stackSizeByte - 1] + */ + StackFrame(Xbyak::CodeGenerator *code, int pNum, int tNum = 0, int stackSizeByte = 0, bool makeEpilog = true) + : code_(code) + , pNum_(pNum) + , tNum_(tNum & ~(UseRCX | UseRDX)) + , useRcx_((tNum & UseRCX) != 0) + , useRdx_((tNum & UseRDX) != 0) + , saveNum_(0) + , P_(0) + , makeEpilog_(makeEpilog) + , p(p_) + , t(t_) + { + using namespace Xbyak; + if (pNum < 0 || pNum > 4) throw Error(ERR_BAD_PNUM); + const int allRegNum = pNum + tNum_ + (useRcx_ ? 1 : 0) + (useRdx_ ? 1 : 0); + if (tNum_ < 0 || allRegNum > maxRegNum) throw Error(ERR_BAD_TNUM); + const Reg64& _rsp = code->rsp; + saveNum_ = (std::max)(0, allRegNum - noSaveNum); + const int *tbl = getOrderTbl() + noSaveNum; + for (int i = 0; i < saveNum_; i++) { + code->push(Reg64(tbl[i])); + } + P_ = (stackSizeByte + 7) / 8; + if (P_ > 0 && (P_ & 1) == (saveNum_ & 1)) P_++; // (rsp % 16) == 8, then increment P_ for 16 byte alignment + P_ *= 8; + if (P_ > 0) code->sub(_rsp, P_); + int pos = 0; + for (int i = 0; i < pNum; i++) { + pTbl_[i] = Xbyak::Reg64(getRegIdx(pos)); + } + for (int i = 0; i < tNum_; i++) { + tTbl_[i] = Xbyak::Reg64(getRegIdx(pos)); + } + if (useRcx_ && rcxPos < pNum) code_->mov(code_->r10, code_->rcx); + if (useRdx_ && rdxPos < pNum) code_->mov(code_->r11, code_->rdx); + p_.init(pTbl_, pNum); + t_.init(tTbl_, tNum_); + } + /* + make epilog manually + @param callRet [in] call ret() if true + */ + void close(bool callRet = true) + { + using namespace Xbyak; + const Reg64& _rsp = code_->rsp; + const int *tbl = getOrderTbl() + noSaveNum; + if (P_ > 0) code_->add(_rsp, P_); + for (int i = 0; i < saveNum_; i++) { + code_->pop(Reg64(tbl[saveNum_ - 1 - i])); + } + + if (callRet) code_->ret(); + } + ~StackFrame() + { + if (!makeEpilog_) return; + try { + close(); + } catch (std::exception& e) { + printf("ERR:StackFrame %s\n", e.what()); + //exit(1); + } + } +private: + const int *getOrderTbl() const + { + using namespace Xbyak; + static const int tbl[] = { +#ifdef XBYAK64_WIN + Operand::RCX, Operand::RDX, Operand::R8, Operand::R9, Operand::R10, Operand::R11, Operand::RDI, Operand::RSI, +#else + Operand::RDI, Operand::RSI, Operand::RDX, Operand::RCX, Operand::R8, Operand::R9, Operand::R10, Operand::R11, +#endif + Operand::RBX, Operand::RBP, Operand::R12, Operand::R13, Operand::R14, Operand::R15 + }; + return &tbl[0]; + } + int getRegIdx(int& pos) const + { + assert(pos < maxRegNum); + using namespace Xbyak; + const int *tbl = getOrderTbl(); + int r = tbl[pos++]; + if (useRcx_) { + if (r == Operand::RCX) { return Operand::R10; } + if (r == Operand::R10) { r = tbl[pos++]; } + } + if (useRdx_) { + if (r == Operand::RDX) { return Operand::R11; } + if (r == Operand::R11) { return tbl[pos++]; } + } + return r; + } +}; +#endif + +} } // end of util +#endif diff --git a/thirdparty/oidn/weights/rtlightmap_hdr.tza b/thirdparty/oidn/weights/rtlightmap_hdr.tza new file mode 100644 index 0000000000000000000000000000000000000000..12459a33bc889cea2c1bcd628d48981eac8d7de4 GIT binary patch literal 5660131 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

8uGoi4m|#Y7QdY~3x6#P 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%0AYXp0*8$_+docRtZVJ_v9aHO&o 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 z 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⅊%t?Ipt)@nM;y}gYp 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 N`nV9qNZEy|^Ln&P47J|Ok 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 z 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

    7md}GVmc9_h^R-huck1 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

    8a>M2-6 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

    gTgr5WJojZn$ntcSVPQMXYCOxF3 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

      Sq7v4ugnvExnSm=hisV$t5f)DOc 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�%&_9?Oscjkn4WF%r%878 z*kF4Hu1?&AFSFT<%`2`8+f*DsinQnc&SqFXt()9@70Y=imy>T7GMKuQNhH#d$Mj|P zki40m(DdUAYzaDx#^mE5YWR~?rNe$Ad1W4nYH)=)nH^Z+b^*LUa293@%|z684RfY< z6}s_05r_BtLwUvsndO*+H_g@N*qXL99ks%OT^q6EuW@`Lc>%7`6sG3_cVScMYiOfw z1?X&>MW>aYhs`(3agV}m-U2ayoTq;kIW3jO%WEzmvnm_vQM{LalRie*Y|KOjGv6=) z##;&h=MStfPY|yUjQFh}hs(W<}b(*8X+jhK-J>H;) zS4-4$J3I{>xGo+~sLi4RcXH^T>+!TXdV;<5Srze#N8~DbGm00tPE`DH!pf52G zB$Ud@kLB~RsUtu3Y!>6Cdh7G%x<awzL9FV@26{iuA>T*!qhflHt&#EChRtE zXYIn4ard?ZEah{jxBuP(eKpzUmNSMZR@@g$5i>k&okJ8-*MQx^uSC%0IFUKS@vGgB z;h8_wu&|gH@PAv67Mk>=hzZ4XR%0@bw#)$XH`>dkPmaX`yo>g7MP^s-rxS@ z>@7YxwQLdIttEojXo`W4OD?(}G6}2hY0#feK2!k-!-)^BO#gKq*d%k2SvGhYq6`;8 z#MjM`=6IC2Z4#%-p|?pde={2QyhT_~0WjipKkbJ{p-8R(CJnk_zh^jPse!f8{Xudl zY%54BoWXi8AET*>O8CD!i>SE8DH>I^l8!Bu0`^ciPCp0mqjM78=9=IQid8ULZv%YA z&S;~kEYw|2A~{f>sy#V6&Kh7|@(SKUQs|x7JSM^|uXK8wfRF|E3dY9e+Dq-mo8)1+AnJd$!S= zmY6oI_q5jBt_w+1M6sq!F3cuJiL_@nks3WlJUYFR@kU8@P?K^##}imXUmEZ0IFFZw zrC3#RK3!M+Zth+D2tE8&f}Ju9*#4y~HuVU@6S)c?%|5`AZcg}jR3X9~gFJ%&6w$wK zOnqkAg6)TUIKZVH0^Iik_U1TXm9waHaXVa-c*p)&vX#c{a;7^M{>JTDLRd}JgXX$R z!Hsj9t)2)~!ZrR0y!m7Z0p#!2*yj?@!r%HM!$R&H9vL+oVoq# z%9t{|VR{ERDyG5x-n+POZ5VuWQ>F{MT^MFP})R55iHef7JN1Z@h2 zWK&^Wi^TAUHN_BAVFi8mf=zYzu(Qhu>~%_j>)RCYrLY@F)j$&ao>xIx zFQ1XNpH*jgWdH%G?@kLN=>L$??h=_}jkaFmrJTQFbb4gWXlYkJDHVV?ks; zIEq$rS?|u+7#tySnod*vk8X*H#4Vz)NzVp#O8INSBc96*T%HQYL?7b6R~_j2wR_;x zFEuRKR{*hsnsj}AEt2p)jc;93;@S;DK+2LqlY{(V@Gl)i!dR>M!Dcuyf}872cfj() zF7y|EN3^+)lPk@m&h3m7rKp{e!M$O#@qtXRzl;}NH+AI}$)coaoDq6ur*c>nW{S8$Z z11c|iLkczqVWVCNz$Z>amv}Dg?k^p|O?c;Lw(g-p}zChW19?WQ3OGB4tbNwVy%%X3_ z2up^#RI#1WZ`29mj6qfQlOD{u;`hMQ5lkZ_Us-{0DMsaa^Hn-0&2c=SZSh;OF zZ}>(nQPGWuKi<#4z|n>pipZmX4|jrZ&LNP~X#;QX1F$UCmeQ_+kmTcqgE?)D-aP;> zR{PPpZnLP^w*j~knn9xcu8TdRk_ZJaSD!J_Ac>>zrDo6So<^^~i#YdaCf~a|MQ1o!F7n zk-`HW;R;SWt6EWn9JG>%e++yjz-Y%^S3z=JQpN}+$Ul)WM{ z4Xr=01tf$m=q3I_sA2^1o6iz3St3S_-Yvna-PS{2{9&4RV2CuzY{PHwwBvZyY@R@b z9B-j&DZUsf${Sd@ftOVw0u7C2ShI-B(syUU>k)UHbUOzEB;4o>%bOf)x|Y32=RwzP zPjb;=A+4HooyMFtrE?Ev(gDu~*xmaAmh`Qn_5P3XeUm_X0RLjc7SH2di4g?<%3jcI zEP{)dD;f3aKk=TCHVAlah^OkcVZBdj_*>a^)W1lUw0H|rzmX?+UCS@z)0GE(CDX{T zpdjwCGsWH!C3xtq3&iBdlbm)*9I{&v4syMQ|C!V;d-JC2g z4#jWultAUZFKrNl#!lwe zfwOF+%>oEG9R_2jTbS6Xk6`oF8f&i`X=Gtq58>nc4PR!zCt9DR7*j?V)Xff~wV=t= zH+G=eVl#PvA1UClA01?YaWlEO5kVoGhAE38VcO#fWYet$VoqmC=xZ*Qv3xbX(en~+ zz3+rQtB$~`Pg+!cYcW;ga=^!IuVItaMVxH5Ez)p^Bb)zt)fOM0&3 z!`jj$ZhHo1&3Yi9e;HjCXN2#skA`_3Vbph7BKJJ~1ck^w(Dm&#j^Fr=IPkTQ#+qWH zzTpsAI{Fa#o&SL{jyg1#EHXrc&*oC)?|bMOOFJ+e>Ln}fW}~f@-q=_+kd`IXLV-}8 zwaT#~T-dt1E>s>ncIjG6qk1>VUtUpF&p`MLt%ixqMPopb#G`VK4XROzhH1niV4gUNNX=Ji#|&~Z{3XT5$8PtOEX!xdgM%7_48rXeJD za!j4-WH>*e3BI?*c=9W>c|D9I85t>JSG(5W0h=$-f360M8(erY*FWO(vdb_Q8A5%p zj^opLHz0K-$E#Ra1s{$Jfm@9OM*A{x5>x;;*jA3X$Jp-N7 zy^ZW9pF^Z5=SLaIg1NiCFqWJz&rvv=>*P6x!`xhWK{0JO)ZZHHKHkUVwmU*vzSMRh z!qv@uV62itlz#c*PTm0QzIFn%epaF>ZcpJ+=3V%3^%_}E1gVY!j~cm(&@X>N@vk4B zAu`s6s?^T`{@caeH!6tgq`$Ci#%mZ^IFA?ojKKa6hMJ8`%VA{X0v5IM#W$M5agcR6 z(fL(Oez-Pr{aQLWTYDYzcKit5b^}4m*(!WT7I1dJZb&MX(Tx~0B+w^gfh;<@u^6Wdg@p)>C+2XrGT4c z|N22De60qNjz5p)`>tR}`%<*MO$BGv@sWw&gLtv|4m3&+0W5 zf}jhK`7ejsNF0O1`D@`_^iHa2rA$M%Js={F{XzGn8JsIIAvd$QK9#y%uv5Z>x5%pw zH>CRGfv*XuSX-Zb_sB!5?Z)xG>^9hN;WW~5If8X^qiI>M1ntq74JQhndG0e}G0*!Z zp7ZoHzTTdP219Bg^jj!d_g^+PZ>ymNpEgmo0e6}n97U^!G^ysOCKYkHL~V+vP}$8p zX?4{qs6M8_b8Q&Ke@uFq;=&|sT)O}|e~a+)DyQ@2mTm)lypWsMe5f3MHLUKJ0=`8H z=uomDTsc$?_4kcwr|%8&?~WhR+xD70G`^6;?rB3Ks`@baoV&la)sT<-i=kG(232|< z2ifl&kGt+8$;kKt&Dx=0JKT;Ey?(*iLtUu4#KY{o!^mz?0*y2fqHVioApb61y8mzv zH)CyqX|9D(oI;SE!Yz2KGY^~we=%QWMwph4bl81glkB(`2ZBOMFnvcX7&mb{b%(8J zwu3J1`jdn|##{0nS~t?np#!+&b2RU&-WbHU$WrUb{oIW82RLDdSQga^4=t=T^Z--z=i&n+)mgLG<~yU$E`$J*+bC2wV_8hA++*=UL2N z4|Ck?@iPx=d~@&}+7dYo#quLK@2es{lI?_*@;mUx@3)cR{&Ldud;@m35u}bYOt7RX zH@6;bgfaFP6r&Di?ok=*>W5>bPuYwr-#iXKXQvU>AQQS`_BwD+Md;gwQ8GL_3op1` zL-?||9)oLqAgiT|>mQ5K!f;6K>fphiQpE(7_o4)Wi8Cf4~6fZ6N}vqi0-?z24g z8a@eSgD*jIVHTtLM-SJRq(Fn`ImjQoiPn{5VDUp|NpFD~6bD^EgT;kVIoxX>hOza_0q=2=tZiS2q3%HP>1H1Ab;Wrm3ew;W8 zPb`iRb9q_1Og9rK=k3*4@t61>cEwe#sxW+2kLRybiU$g(gU!HFRGZO?zc^mD{?&be z)T;c(o;~4EDyt9Q|HgqpVgYEMtp}lK0eWbhA+vtuk`4J%;P1dsg_<|Q(ahL zORszLk>b;knm+~+3%)?|OBpP)v}p~FEs?v ztEVJs#`QN~!KX%FQbj7G-wn>=b@qrq#FiwJ{MM@460_T=WF--te<#K^zBWGw1u9Gf9?a zR^m^5C6GOJFHU>zkIy%7?AuqnVa2!?&vo-uP`nzCJ1Z9=(^cW+D2yxT3ZLgOfx(6 z>`hi}Vwll7bg%jFzKt-!&+S3EE^|KvN`&6NCWDtQpq#y|b+yz#lB8h-;&bhB(S1d@ zKlC3mbh4)FN6XsWZ37x={=j2v3u({x>nlpzpE&NY zh6&~vy5yOQc0QOy4@++{>$ko}GJPkAHn%6$3cUmyj3?l@;tBcmH48cl z?5WywA0!ZS0xGVm(7xz%c=bL3&QBJJHw5%)*EIb3O&j+ylcZDq4JqY&m zk23b~4th3SgYyECwBKU}gl{vVvrY!U$d`rGE7<`$9NrUg=PZaU&xd!G7CaIRC@b_Z zuF+qQWnTWa`qg&>0+fr<+>l7j@A?QHC}!hZZC}y*dphu5f)77fbr%xXePOk>`|$$f ze_MaK=f`z%@4(##{jlioKd9aG71+upME{ovWhQf>^T+~PI`0V#1_t4Zh0z?-$sWEt zujE-IH-hoZ3OL-Y$Vq|kBO-N5xC^RM?amOf&1|lCzV3o;zHuTt?|50?_;aI+J z7>|guRYX=9(Lzdi?&~cyR4Su1wWN@iQHn}gWfMhYr;M^Hyw80-vQklzl$JE{HQJF% zzvuU-e;khE_1^b=o!5DOPT`s3jYQolkJWfp$~ZnwCvETLQJ?P#?z%zvo>60%razH6 zt}P;XCw$6xgI&Ot!Sz@)ErPcDFCb;yXo07DyKr;o3DA$bPE33$7|8C2$2+>n;DaAz z`#Rn?*cFWSOKtFAQ3PD9z5uG~j#PQpD&luD6YZ?zpt8akRyx`OyigH*_EP1d2G_v9 zq$*fbZAA`$dP|3>1cos_%rTEQxOvwk9GtHV_J1m2T22jde_ca8!xnP-6BH~`b+5A} ztO)m6aUXY}DUYxpS73A{pN*d8N=x31BONo1VB?WCxTP9Lrg>MAigVl0CS(mapSy&O ziq}#6+%_)U_!=(Ath1Q^f7X*&EBpz~A@}(1!PoP8$P<;DdgtY`$y zmJ}F1+=00R(Zpb}J6LCx!x*b2B-!gEJRjoNK318lZqJ7tyCs6dRpa@ds9|tynnn%$ zWr=eAc}UIp09!&wfvT&rK(jU(^%hx@`t?%W?~EhZ+%XyJ7h2FM4+xjNYbke3&WYRf zPz^oLHq+91FUW1lE@)|&5LDz@!M+km1hlHO>qE8+(AUX3koE*>hlYKFTCfg?3Zy|?)w>9Br zJSCP*#^83jwsQKjTv&U&j}?1_U|#r=Ig)rA-}{Smx!z~+#l0M|SBcknw^)FA=UkA| z)*_)d@>u1ClWEgUX^3hvK!qU7tKr+8RqUqzwdlsbiRbQGEm-?&vS6X(I6=g-Y3!i*H=;T!0(O~ev#kZ=@kH(! z!WFi_!|2Vd_NowQ-aiVbRE%K*Kg}aa?QcMI{W`3-4TCIp6=YSNrI$9%ryk8$p;F>M zn5?3Y>jOqH)&={(cX}N(mfPU3@+tJnI}N&Lfi@TxSF%qY9e^JaZ(ywUKl(Ju1J=3E zgrSUFTI<`4u6C2D>41_TFa0r@_+%>n-DU>Ce;n!LSK;_eitqkYUQ3I%Um-%P3MzVX zCL9}-K&yTM%yzy(S)R9bFxVZ^^*SML`)lT!SulLgyZ~%a7{soY5Oh2?797;|CF}f` zgL;GwZrrsA0s`Y<)4D}?)b=;Kcat9&UEsSu2cJHOq>yLt& z-HLE%Rwf(pbD<6{nx&9ITPZlSESmSq zK0&v;N;o4Sl_pI63XclJQFft-z)t2Sh%+y6V@(HY&P=3-R(4YLo3W&M?<_1GN`w5S zrEsmcmuB1zW&@Q+(S9Q-%=;FB6(0AIuCAcP2HH@t-X14~@LfasMQHQlA~_q|guAn) zxVN%dkk_%E?z|OBOOv}`RI;kzJMR&^1x=u@FUgfFc9VjgwZz^l0E)Av1u7g_J=Sd5H{)b-krVZx6=cTl;dFN)BEj!G9+h#${s;YsR9|;cIc((1O-=srN0)8c3 zBaPpA2G;dsw0!qhbblg-AE!oOUEdULX3b?RseJ@`LS1TRaumWnX2b8=N#sG#PqIO6 zH7+x;hWobNuy1TDF>OqQ%2i9)IlBIA{RLCrr@oVQ_A|w6D~trYyius~Nz0B**x@5?&qX-Th2XPJFf;weQ$Xy+W zJH{U&e}4U7)ka^W?bAHbtX7rU-a137_c)MSEvvZ5Idx1%1YpzfII>i`oUYd1LZ(h^ zpywnEL3ctW{+LmUSDx%4fj3WL*VgYi*Z4Lp+^zy%g-tY#&lXMN`C(NKgAhKVAb5R> z<2zt}kta!4P-ojF8u9ly+4e0SL>KPDu<7b}kKBhro&&ZyMHS9o2xVtq>&0D8whX)V z8`RjIW>tF?AoAcu_*(sjEsJ$Q+m{JA^70xDRn~;o_VVL)RGV_8Rn;>Zh7wV#+WUUzfTG7K8nVlqCmQO*) z>{fX8Ga3xdN8{14CvjuPSv+uM4$ZrI4qZ$Rq4_30zcS!TW?ZUccYS<_iD|svRVg5_ zP7HI@7U9r8fK*SO16Q+|nH|C=F4#J&1pD%eg&L4@rPWSbcjw51G5+Lg;N`w^}@cvq}F#W?WSfOi0KBk^y z>J=XI``pFw?^Qkn&KiPpYn~N-^}I!dmOR>j-blj2YT?_;C@eb=LzHnQIM4abW3I9& z_qz!r-zI>KmI$tN5#=)aJ2@VPwoP+`fDb4OCc;&n*T>hOQ)PI9X#} z@*;da_c)z*>N-m6O#|h)H7FvZ1VM+6(V7G$G#k*yC$7=3eDOEBDE$!FxR=7le>3S` z&J>Cs-DRtTDfDE_gM8N*YA-B@m-8n<&rTWaTQ^tuWr_@Ryzgh%6crS9|9ad>%CQi`}Ce0`IgTx#|ym~O5$c%eJJotV4@(DKh7(4Ld(V4XAs0wWj zeaCtXwUQYsH)!heSnU;9 z)`tlfoY+R3Pq&cPDgj*mVvStIJ0Z({qCYhRmBt4;%&*uqGplb)bN~DvqxkVZ^psNs zjo;8nT#Rbz=nyHCjXnjZbo;5!Cm$TUvxGPG#}oGc1}y)36 zLw{n(ic=W$oWFN0M{$$iZ{fZ#59bo?udp2?i;8=Uqk?xCD7H+R_M0gY>)$r!`5tAk ztnfW?`51u?3h6x8Opdgy_h5I)?!)7+__uxKpfI3I4EO4er|Sj)$AybC2ira|GCR(I z?e*W(d)8e1D67u=ncq%gFTUnQa2wn=`!Q9}TZEGB%CO_%Y*=Ja2M;!=2rB;!F*a;3 z2-B{@s;9#w(r-3scL*><`vIdSxf|s4HOU|4IoLKFN%f8|M&Z1hcug@KKl+`9M-O=R zqK!6I3$tjhqbU-HLB>*YwBSp+Cd|-RhL2@gq~n2|K-zm7XEN<1nHg9GKl?;DjjRHq zxcw7gMm1d+AuAZ@tfDVR=E4s1vAFT$Xz&`j21lz0$tS<5;Ixe;#fKNdubj&QY4=SK zx;2rtF5irc&+xe*_9-^G(N=xra;-f5 zDf=16KXQesf<454?KUvuF5}NZd5%fofA81}7&|nLeYiIdS6_Nb<)R(ne!ih#bZ{Sd zMJ3YdZ?@pKvWw8vn@l~#Ey22Y0_-!G2$7!~;M}4fnkO`c^F^X?l7vE}Tri2QcSTj+ zd%AA&9XhCL1dlcC@S#aL46e+?G;=9xm+%?)zR1MKH)nDpE2`*$9b-6ck2E}TO@-MY zJ_Du#OGNFakd-GllBG+d@I-bbvu4l$Rku|O6-OtN{r_2UWlgWiNHoA-W)Bc`FTOu( zKiN~>3)4J1usDc=Grgk(f7xLYXy6WWtw*Dv@&)r9SJ7<;rU~w3ULn&ZjzC48F_`!y zu^%T5!JyC@q8+lqe)2@}>(U)EJ`cR#&NRw=|dLeSt102%~k=CD>(ce2l`s&ME%+- zcsah2?#Mn*r!}(dkH}@%dVU^0n2}Ds(&WHn>rTd5E{=v&7!$dCMSzc|VS6o0n#MjP z;#KO9!$u36UnG5t4&?vDUX1OdO zFT^8Ag<04{?Ov|DNNC0AH=*!cvdrB zkQ2}XfBTB)Ke6TD+r5cK-d#sm9XU>#Kaa<*>!CRHmOUF7^Mb}Ij^X0XolxP_UHq`I z73~y?AmdjGj;krcq?w_#SGEULSI2e)!dPBez+8N!gFk}1 zpgt`FZ|r>tiB;yefjLW(@#(uyIILAqMr;buVc%9z zRp^Jn_F^nEyhjZz7vSn_eiv%>g@kGakq{MsW}1f_?K0wZSEZ}4c!w3c)XtE2<2?~dDHt3 zE)Wx~~Ne@xOFf(5nT$>hpe@a!Vb z#lC7!XKNm#ufM3nNGR`fIkDPe-P{?+Fd?Cx9QENdF8A)^vQIfA_K_^ANE*VMNl9#^RxUP{c~Iw$@sRrMB01Xg zkoY9ZVv|b|-8yFu*xYoY-`fw9I=*Y{`&J8*ru&1$+n!_l1BcK?=?v5Ti6 zaGa2Oo5?h_7LMzh%WYozl9elyWTl1=`B5i3R%(E5G^{SQpwoWtJH_5UWrm6C%narY~-f9MRG!M_W=Vn@?|_7YtE{vuL+E1l#` zQYZDQ9x(ZeJxj(f!E2q#!W?TwnCTxyA$1~s(>euLXl%hb*EOlUN(k(H!f+0?_c3qc z4^l15dpMs6xV1kF1m|=F&^3A)?E99CeF-1QyVO|JwY^9(Q!J?OKt9R;z+%Y3b>zvp zT|{j-iE?WuVgAp{RC0MWn{jm=F1~Yx$Q8{4Q(li-F8fKSXXk`!%S^E#aU7-}m4K2AROI$i#%o0=-VeISRCbRfAAQe~8MTjLX`dEVJ#NKSFL#F2n0P!?JdJze{+(!Rj3v_!J*V}5&f)gD z0Bk>R25}=2fH{$<}?wHXeC| zs$C|u_eC>}Sk;Kvn*QL+LyD~FgJ^cKyeyJK34)LNfo_WcYdZJeK*1 z!|!KTiA2~~Y+)ypw5$s}Q(_a|XwHLvkJ&^yrWI#rM6boo3pXsd-=_dcUEg*9|n&iYGMthacAxBAY}mXo{iZ@(j+ZK2e8 z{Xf#J|DC2NjRnIwi57vT!EoYRC2nXr2W9zjB&$IOgfkv+-LI=?tFnMgX=>vZH&U$qH0NqM46f?{E1q@Zp_2yJ zsgL}?Of-ONwuol_BY4wBl3ROR2iHG~#7f(AysqMj^QX$%_KUW#g6@{nAIl2sg+3y|uP znS!{_4gwYt_U&yJnk1)JnS&5UK?~$=Y zi}uo^)X@pStzJPO({z9~>*un!Vsoha9dB5doDBuZ7jesv3EUxlH^HdD8d83-9v@}L zfTy<^mwNpGccOC>#KffVIb(Uj`@GZikPb^XtKI?WggWwU>{$McIZReA_kq|~uCSMX zhkAHqfI^!M#B6fHpKknjbh9nUZ|7i6(iwhkE~LJaC*jt7QTP#d8|$-w;jbm*P%ZWq z`rqpzi3G_N^jCrqi&Mt zk*f4~Y)z%b@Ls-$ULTU`kVv1)!=FPT=y&HR_E$@D#%F_Z$6y?NQ>+fRcP+%?-fCW{c`vzVaBtBPT*9t z4~$z|A-NZG6+87t)Au%kBw&&$E-u!_X*Fl@p`{%NBzB{IO)+-8m*#HoROF(5zQbAG zF*M00pG1BU!~M&aU`Fo~P(3sTUszhgGvD>(T4EGuc-aDt)z0H_*-hNxp)Tf<_g>uF zl!Or-+rWWw#+sOKT7YFI$H{t4vWRw}t#XGYNlQEkkGh zNnq|ycXACTmIN9UP$X>Tefm5rIs2_83$? zahZ{In}GUD)qwT=j3*?l@wyYGO8e!p@@EhGu22K*6`Dxp2;cGc@h7kGwW6iGJiYX> z87AGUg!JSDNOy98O*8i6vG-CS$i9TBKlGudM44R6G=*ZKOb!cHawD$Q7J-Rbf|sL* zK~vX*NZ(dQO}ne~*{Hi@{q8}kY$r)KHL|#EixJ<+5rwbBY#En?$85gc9?Th|&mHw% zj`vQPV*sBiS=0RlS5J724eqAgfT0jSNBe_J%nCB3WrIf2ZbZ-KDReEHEa(_I23M;m zQB}8jc;uM?JMxp!Bc_{-&+&y6Cwct-_$e+~l0^b!XOP39iS%ZP2#Y~{GDT*kxFvoay5u6-5 zoo0yD(not9kiNeg*|3X=FsY#q4)&iSb$dLa^Hw;{Sr~{-7T!Fw{4R!!ZJ?&dj-Zrr zAAaC9a_|WEi`QQ$Im;;3yjX z&I%n}I&sIb#bBbC!nQ9R#?C}**e@!NzgwSUNb5stX%WSIkT)d{%Ji^x_!oQU=@Y6j zv6@wnu)ub8H@5nz7PLgL5)!W=$M-q>Wp4@Z4GZrMh|*3E_S;_+0+B$yVv`e0u6 z8~9kA3KIrpU}ZoGXmpOl@$dgZ-Ho@9A@v`?vAd{nRT7#~FN2JjDc6(}1VbB@aD3`s zZq+Rr!K@c*a8${Z)_goc8l#J8%JD-ut=$A7oeRLMH;q_4x`XD?I$ZCTeC$wbL$eMA zR(zZv(|PwVy(N7ZKWigC^{}M_rzu9QGlJ|b;(|J}JJ8Xf0?}SeD$**XxuL}|D2TsC zzjMo=dgVtF^;s1cS_c6&)CIk`L2@a3H0j|)85X=Sw!49ZA2e4(bRyB) zr6C_rz1$DJnd>q2Hum?{C%|~^gH%-zeJO#9l$r$!8EbiDAMbIY(*+fJ$D5x zI)i!7y$f9Z5D2rgw~}(JA~GoBL|Pui(|iRJ*gLuc*RR|M6YVS64?9M%V%$=uQ$>$< zPA#UyWhp-W9!0yk)fVUXN`o)Q>y{=VXw-j-rX?*V%;<$+=Wz~y-(5vwb;Ib6>d#D9 z(sQPN?IuQ1u!6c-xnpSAQwv|O0D7oH6^7=@3EIs3ENX_&;jjJqq;oH_SH$O9(iUBsJ}@iT5zZ$E5YMhrWQ~k2eLn_XF_CF8(3Ig0fjzaKNknE(S`u&>7k^m8AfmNy^~kK(SxePxg7FT|o6 z!1p>$#IJb`eBGWxmmVo)Glyq`Y|UQw`0@+P6+bDmenu&4CgMqYrsvZ&PlKRrj4AQ` zeu_?Uy^U3Gf}yp(gDkAj=3+NBF~$p1-~;9TjN28-vTj8bO_{>gpZ-V0Z@A#As)^{{ zI2D3)yfEn1Xs#$&A8y}Uhr#xrS;uijwFI^5vQn^(jk zvw>R7TMkny<+#$+xq{DjnV@dG4dOniaL4$iyy2CgphZ_LvxrN2qQu?LzJ{lF8FO|b z_lW3)EOz-4Dbg>y1Sj0khRi%oSl;{}xqobcOn>%*IjfmZ+YhhByv$jw!@wuTzUVHU z_v#+}cOn+AdA2dy-&A3T`bmsj=7;uvQwi@<$EepW7XAho7;*L}=&VH9qZU8IF}Zvvobg%MSG*e+N!Q@4*hrAbEV1~PFqK>5R>h7?j%6y&r-P}_T|BGy zk$ftAiO1u4rhY{s1brNW{7dl=l6{0!iAIyoo|&viaU+%LQiO4fT%g>o6DMY86MNC) zD0W_*oARjv5*Jmom2eouA61jb_loi0Hbrjaj3OSt>52i7254=0lO!4~#cw{z7}k-B z1;t-Tt6Um9&FF`;uPxMh$w4&v#BcnYSp?u8iM%e;-hXZ(2H?CyC(s5$!vo|f!H$s8MQu8f@E zI&+5<$V+kMMcX*Bd1E+-w~M*GZ#v1qX?|yUzL2;vTj1Y@B9JgR2{L;NVXD_#cr~mm zxDY4Bb$_+RdD=lFdfsAO^>q@fmR39p&Mqjtl zuGuPFiLyDE+*k;wl!L*DC0a;{%aoQf@TM?=pjI`ZcSc9q{JvG5VE#8(qCtHlK(vr>@(4bt-nrZ)pddp<^ z5?yXlJu{JL%z8wcH;&_X+*?4)!~kl?-}Saa zH@<()QtBlclOV*H{YG$Xwiu`0rVJMUeDTbQ4Or4FNAopo;H675xw33Kyf2c6)@Rl1 zt9fc%^RHEqcWMy+bGZQ5SwCuA{g|2EJ)V0|lS8_f#iMDI7?<`#9+ZeCZHWAeX_NF| zNH-P|OGIHMzk|DH@)oC!|AwcyncO`zqawl5F#oVP5OYJ=^5_r*UrvV8JM3|d@hDC? z)eF;?ZioMNq!1g!I6Qm1jZGOeF=_%UJZD3#Hj6F#->gQklRAxYvG6OL) zRvq;=uBS(@okY1MPsx=xYQp4gJRd01l8bDV!VPQIpu*~6BDE<8HV#U`-@F7ODC?vL zTn6cn=^tp%idUdqp3W{jwUg^PdkBkF1IsV0rI6h@xQ4Kob&eE$eWzdt9~b0 zxYHBkM>81sp#UxAa)_bRD+^D4PpVix0UTBazztDt(&rOR=Bl43i>3#Y^L;$4u4^(n zNle6N0h24|Df3MFDYbONm~4E^|D8LkcG35%PLY(}IcV5^omONhp)Y#^lmAq(MP+Mo zN0JA|*KSMG;XmE(n4hv`94ReiuG94*9U16 zCct++N<;#*v2Lw3&nq#&OR6X6u~+S^o3t&Aa=ixjhZQVdba@fu7y${mwizeYl~6&3 zB|dmq#YprT;kqUvIk?;cy$&Uk(xnIC>7U);z;jzmd&Xj+*f29=|2ce~K7yf}GiXqK zFhm4V>LXvlia9kw(^MznSmgki(vd+}hYW^P%7F5lEAWOGpkKxw($>N9y}8q%iZmON-phQatmICZS)3+tbrQLJs{yir6_HjN{ zI;x6#A(b}N`pC@^OnRmVwXa9R_a$qfxiySB zxf!#cBpYeoS_6jN@{K%}zsdCMNhNFTtW8i;&fGXzN^2JFX$<>wJH2%c^>6AQ&a9#oorF6;VLssO( z@dn`{qeW<(^N#Lp%)^(wsAb*p7z-|J!<2cK(Dm9s+TYwwKWYeRSYt7&haSg5E*#6g zFxY&~o49T8z`7sK81m7M85p+9$xvq6ARWiGriq1Hk{U zL8;^zaGSdVzN$DuWxulE^ms?;znliP*;km+CQ`W8G=*AhS%tlqOyThUA8cFQ6|y_m z0xQ-}!pw)-WX1YjBt7geF;`MS_j^H%ox=qB?3XI8$fPtvkM}yoFJ#`B$D+6Gce*=p z9CxFC1Ik_0MaQ}4aEsz(TzjPswX)uk-(e+i-9HlNZYaU;RW)>v>07!vV?Aa!{-Aea zzu?)MZFofe3Z59sLhACtqFG>s{cEq%dt+XbW9?sX!TEfYG7+H}iE-3ryFBzioozm* z-;gMboe2+fzOXIXvtX{440Ty^#O!mR98r6v&&|nsM%VM5ni<3M>6G)k;nBJbnrvwW z+df9ov2%35wfZ*ue3Cb|emD;XHzM)wfoS-8Qi^%lmyXsZ^D%IuBK^jD?0qgag42vx zc$6PbUnThwqa~%J-kfKlgeuU}DKT)-Y6u%%J2AtP3qbs-Bdb~To!?v3QMcSXL{UXr z;33vPySuHxPWCmtX;FngnQ=_iVcuKxdk3g(lIM3%9$+=g1}5lJ{I*Mo%6{|sOsgF? zVa98IkMV@Yghb$>efi{mr5z~g{h_brJCR#D6Au@45}}qBMrobI+gk&0j8Zgzmqfw# zADU#5YcgfhdEIq`5KqgDfyevRp#SSvlJ-3mA<7jkpZL?gpVs2Lu6DBB%agGZJf{w& zKcMvB2BNvpms%!@lPu{4SQ8RtzNJ15n6BgauTTO$Pfmc;g*v$N_b@wGMGbDpjEC-> z6_wI?u591qLNGWW#lOFS>J7I*_NH>?dyNBREs=n_YTi>){MO<`2Jg8TJOf>eyP)#% za$ah1rw-TNfVR~%(spedQ=-#_2OQm?pxqs}VGsQwY$LOO^Ze0MduaQk9;`c~i@%?1 z;3X$xh}x0}UU!_~Nvs+spBKXqcl055mMqM4o(P$lU8HpFGSqABqxVD9sdZr-esSr; zv3&nkUgci2@!uDNz_Qz_z*cq@y~2Rx!h_Y&c|K@QtIsR7n)R;8^4Gr_oFJK0e>AO6}sfa^SQrsYc< zh|KhZ1~ML$R!qg8yV}XYO@}NtsF}g@z$D_izZY#jCl{p$e3BLA=-`JKy?b33rkZ3FH}8lg@*p0RI?irBM(7f@RJ4BoGv z0RcmauzoQszbB77YvrUQq(kr z6c1_e^5%J}e^PNk#*ZAXTLbOFZ4mF3PS=bS<8pp>lz6_J{h)u{;=nyOEDQI-Gb$=L zU|WJWe`V8aV?~)omgYFLECIC?f@o545Z{+2MMSl|@uP1oyXQ|Pi>DGCh_CBewtCoo~gAsTb@42^mHiipXL$Gp&Lp?8A;=C0$J^7^}>;Dao9&o+Q? zhYa|3R1_w!I!kwcQKa(xxqkH4Rm?>Pym>o<_7=aU&zi?#_TUS4o&~Q1l{?_R24|do zv=+I0n((3J4vFhGMbl;Bu;4)uz2BGx3Wm{;=4%eit`@LDLnqw5_XV?k@=LPk@jeu_ z(q>}qP4J|-Id;dMq<>^2@ksAYrg?!qj!P?}Vzo0-+q;p!{!R^reScZc?vr#*Kmm%6 zPb8)rPN4sy=k#208vJc)XKNo&np^*jW{$d#MI9<2s}%&pCpY7@ABymBt_$NOvJE;W zUVyV^z9c-#2@Z!>RrU=Lk~O)ENGe2S&&$;Zs30(|TW=yX8{E*01B}3_cIDe!?IwT)PEzjsK%FM;D=` zFbr!WWZ=Q~&6s*=8O|}84*vE0M6~$~wOU?5XB-_Q;8aVF#RlU0w2y$hD(DBh=ggxe zuZZ!dTnt%hOhX^W;<|5BaHH*aQhK47)hSFOH%I2UpDYDwLgBY6Y zx6^KSKaP))pn*yWAY!u=dOuZ?>(7J8D4$mH{dGA?R$8%rit~7_)17$k6)>{mvPjJ= zV8v&DCZR}@=hVf~eqk);Oc*AHqb|@nI=RsLE(O{eMX2GIFNC#e1C#kL`FpK{{g-)! zDqDSJW_)^0I{o>q|DIs>#HT{WYHT|lF$g9LmmMZ@HKQRlbAWlvYuR@94dGMM2a+Y3 zO$?-saJu|EW>`iFYp5cGv@w{KD26js6sUk_ALyLnS!{LY;7^aUuT;WeV@wdZJdI^7 zX4bGzdP*TBYa!s0bSg}3g^%$X;5ZVA8zb9Uzh`?H6X{0kdOM2EymbZQ-K4-z7y&m^ z0GsDtr6ViHq5iJ{I{(Tw;lDtnt1JK`$q`EVd*=@oU>LWP=j#>KuHPBm#|${{J%ER*Y{>6) zbCmQn$Nb%=!R8ddLrnG|ir&YdUtmhX{1`+G-5~Pb%49)cCRN#K27do?AyI83tMehB z2)EYapWtaYE4P-7T5yx`=}Dm*f4*g>cNUUw>+e#L`+tb%2;UdDwuceEx=+|nQP`N& zOq-?v{kvElOud(4P=X244SCeo_B35IDHFU7USKi=$!3Y+ooHt6jk;SrXtUEPJmhhc z6z=gPQM+;oR}l^$7M~@SPpXK&6rzaHdkgw$BlcPpqW`nASg4~-2Y;Q1egE-2S4xzO z+M*4?8S|OrYk6IH(hHKn>yuBvUZQ(I3sM{(p{eQo#ZaOzGyt6|zq3gax{{K+U@N4NxAo;E^$##xy5 z$sX(8FT&3eQ*p@@4`$N((?q^uGAkS1Ml+b{D5<^zm(A5>S3JB;=I_g)6VugEQvW_m z3bvvv?@L%RM;0e-&L*2bc0+Q$42Zl{L6`8gP&~61eiL{2?q2}PzaJCl;Gg94-qqxK zKnm&<7LiBKjk$gEl>~vwa&UImUFzhx2<9I>NNZJGu)L~*`8r(-cAVqyip4cV{K!hC zOXWS?xknYdyX|1)mn4ebS`TGq7a(#>JkgnQ2(ynKMEf_Hc%RR|u6Mpd)qlLBevdTJ zrEI3fnDqAqdw7QSwZqskZUa@6`9erc6kgUh!%u%kL!q|DA}30D$$ zM#t|&lIigZ&V`1MrQU6p~69}ACt^vH&j?<&JL++g(LWk}L_b8_TECowH|Lx*S? zM)p}a-`V;ZpV#iC`n4Yt7dzd7{4)fO_svp~i$3*i1eK2KY92`-xz z!lTe^bZ@97PYTlLLmf+ey*UW4%Y38Q@QA7Mjv}^w@91vctM)HvJ_&eQK#ODRNXU(C z;OrkyKds%)GfLL54^A4uTc#B6>2JUt1wQ2K=NRGMvw9HGZEe1%`vId7X#}5p6F~XB z3U^@DcoOMD#owI6i$w- zpo2<(aQe@S7D?%*Fj-Wg1IJg#K@*~);rbRIM%UO7*tp!HfQ&FT_ zR`~L^Dt-u$Wc*KFp&kd~(f__B{x#AfTWquNhQ>AC+i3{DeC{(fl0hUt>JtsCU%;&v z|A(XN>v%0$8F%XIL$P%j@6)^ts||0%)l@CIV(%ZK(5#FL*5$G5g(28z_Yi+ZXAqBP z=V3Wn3Z^eV&;=a{uvOj|D(Zv<>cB6ZzI9E8GXR1D5jVW4t zv0ww=-zPQ)SL^S?Uw(BkxOW=f81_J!%VDgk`F{G&SQ$?~-NH2U-Pe->x@hGZ6I2|X zjc?|r;?{l%daFr{^q-8v(d$cK8fka zK6({!^|B-G-k?hQgX6*WzfPEEABnY7l%XR?41M?ihbhk+K&NFNaoeH}I;K|a53K=m zRPPEXYOG~;AKU`Ns~6(ZQ7smFS9zB2{rU94{nPOGEr7*SM?Sl?nH)(M(&AIMiP(No zMrPS9e8%j?NmDMO9>;UlcgQfl)0DaEHwrM1&&Ni;?59?wcFzbPlNV=QZlQ2Qz_SQw1@#l!g4K$>$nqKvjX4xq5zlkcBGY;Q=%ZG}I`><9c@ zy!SPA9o4Io|x=Up{`Y`o)-}&wTC^`>+uD(Bx z+a#1dvWjdal5x-bMnh8~Qbt2VOKIFVaL@aSHkI_Pw2=0ur6K(8?;rSh zJnp^jJ?Fe%ujdmB#bkKRzVpO1K$%^zn1`XpP29>*cgHDBEAXqp6)1jN>sah&u97!LZn+~sY zpL4&;qF~?S25$eX&G1vS-|>u@2N*u-W;}=GF*aEjL_IG;=+<~tUs(b__gsLdLOvZX zMsmTc<4Lpk8G70?i^K1iip_>#!LI_tVi`yRv zz1G92_^u_HT*@EhUOnj}rBe#v(^27jSpJJUa9R_3)KlPNMhr>PQNeYo5p+zR0#0fx zrFS-u2dRip)U!nmBVLC>^UepjFW3*yxgN#bfh$;Yq=00)pRVISJZ<8Yh-vS;mmho1x0(;&p3VhWFj9O2-)}S zA-J^{p8qbOAK6-=v%!Ij!as7XqL6!#V28iA2a?1?LS|fR6};OhM-4<4(G44J(o2n} zx&OPS=a=(1{P`sP@~4?h*`bB98@H3`SLE5A>7}@*q!j$eJ)@GwZD^_20h?OlvH1Qx z{`qeO_T{!{NM) zZ|5;gFX#1=6C>17Mgd#3C4g;=JmpynFSePfjw=nFMfC?#_p_hgRM7iqM=kc zv<8U79bHv+<4X^L!+(ZUtutW9`OW9|3LS}99|e|;n+tta1CZpL0__ILG+*opdGfV@ z`X0T<6jw{LvcjA-=ak@M*(r3JdZv=+IU&r)j6CLEp)i9|;nBs@jEeAYNM>Lb>f5Vg zK;mqaXw55S{~wl<9Tlz`ciHA2Wjo;QViaCgji*yqJk&w2ge znP|f**lDo!tAio+%V_rWhWRjJgaJMNI~=b4H=5O0;s++|I958R1Kd7tgKcJ`kbCkB zI+rbh&5PEfZTBG`7TlZMy`9rrR_5^Y)s;^Aie z&aFvsqo^FDEq8%cN;~9wMBtO5dg^Xp38v@XK(~t~7>E|Z?8_4D<9C0__%YXDt(Z8d z8d6-;u#!<(cmSHjehFD(S&$LapyPTsW6G}@^l_Djl39I3YflP1GIe89y~CO0LNVCo zSwzAcP5@J>$TA{%a6y=FeU#3H1v^_w2G@qtai^X( zRWtoWgPv}qKi)o|2g1g&fwn5t!&;8jKO@IZcd?|?zy&a~8$>(f;PnPA_N-zZI1y6} zNIpW0WZghy@nRgY%o?!&1e0GcS3CvdSUc9?&0-Q6D#rR-FDAjyGckCv3EOF9Ow5lv6K%!^zb1NN z!qYR*;HQuGq$(*Zla7mCuVqfx{-WB_QvC1eQ9?#%n2~qwAd3>#(a^P;cu4#q+|2Z6 zVrNV6KE@%$@K6|BR@Xx1WNY+EkYLx$ETX64HQ<=F8Ea~33>7Dipz@L)@>uwOc2+E+ zMP3E)V0I0iXP*soMqdGQrwtJNPYFD|6RE6bEdAOk%Z>^e%hl|Bfv?2%nD!S1*c%p3 zyoSc&qs}Vw#>D_nl%`?t-!I&Ok}8~4eijol{rOoaCJ(y)x^mZ&wixZP#QQD;TuU{*31RQD8hvl*@_>fkVovblL6kXs{%OKF!gj zBAV;q`$Ts-u-p%BkBLLooQZsY-$=f5V-l_iuZ0Z`xlp}761KmZ&gu+J=e0t3^sfoz z;$uyDsd;&D1u|grq4lWxQ(D;j8G&+VFJ72c#XNp3$8I?hiw3(@&~yI{=t(+_2h~n< z6GTKHV$ysxtd`)T_4je_EUtm}hpEupVMs--XwnOW16h% z0AtL>*}cVuK}O2U7 zRe4n`#s#J0-^==Zyi+(}RuHDykHYoc$~gX|4Q@PBM1Iu7faV8T5NvAo>>5oMvd~*K^Wd?0wlEh=hMiUUXrlX#6luJMzGg+-`)VA# zl)5D_sZT?6nkw<%q!0I!UcykgGf>nSJE!;(E+M zFPay5k*rXg$z5430pm9n!01Q%{Plo~p#E|chKt41v3D%gM*s^Y}Vj4YOqWtAIK_rHmfHBvfQ|)F^nDN2^jYjt2h7kea z6`;YZp}JdmQ-`7b)2GwW*&X;=q5Z)XUWRbnPhg}J$x|Z zE0JrgMcwPQ_%`Yp#Q&1#%{N$~hpWJ-84-oQT|U8`M+NYY(_?DZQh2H^?9C!_(N%I5 z94uY}qi&smYy55MrFF7$k;XFz$0YmE9E# z53}s?UC)2mZCwC5=azzNhj3k8I+@zx0!NpJQw9E15e*R?K$ZNPu>Op6f%bN5ij zbMYg%Ve}u&(YgbszMnz%SpmG;?*gf}?$%Fl-vqC}upsxbEuwT77mv>g)jcwWSrj z7axbL&y&C>H5NXcct#!VOPG^;N}=o89yoo9W$mKv*-xxGdfYnRaKGLHug*@v4WV{m zaiD-4T5ZKv-AIO&Ya_tNO%rCm&BT!2EcBFOn6B;^{4H{TkC>ZE2TD{RIaL8`f)2sh zvQ``~tIIYmu3|dc+Tq@%PBNGv!zo#3(FsaDWawEK9C`GScq+S-f1@Qx>)0vG!u5AS z^jkj>y)qdq)9Z+1*R-awpvBH6DLCcFLwz2k%_8pDfq%Y z5v?B!-s?e9FP(cPD<+FM8bKm2vn6*37# z;U+moCZM=mRl~JMVo)^uGSRV-LOC&^>zKNimG3&lwT)RI_$10e)H#MpS+fRK?>Gl# zQs2m1n;F#Yc?7wveF7KtjK@>S|G}9rPnn2xId;Kd2An;j3PGWw>{^}8VD~VWk!!Ca zM*S;jvhz0LUUr>?iF|iCjhS%{z&uw_cKuO=6%t#Q~?R5nPL2gw}cr9uc=Vvi*88Eh?)-i7;ol7j+W1 zR~(>ehUHvdf-`me90k57wCIk*&fIJ;j6~ZjVZ;GJTkqmRmhoAh;N^!%6fzdJhk zIZ%d=yfDmF$*IH0s8aart|+*Lg}L?fSt#Qc2q$MbVuf=T{iGL!{c^?VIDH6!D%k{Ul8zkxbK?1kGPHxW{`sN!6}l=#+DV{qtUcb?&CE0;AQY8-DZ=eDuVNghiRb+ZU%$PdDAs`dl`1s`@jy znMS}BA%l6yBcA-q-hkmNbn*LoSMJvaF~LXum~K>6V7*VsW5&{9aCxwbJ*h0^xMePY zx&A}&i<-|oulxZQ#(Kc{h#gRn5k}@-RR{A!$=tpts&M+*NY1-$5t-!E$L+UgP`cn7 zUDBOT=bmdLcYiYULSZE4jxc}=^{>c^KnGaWwpdu#-J*uenm~Q0G+S%YOhsS)CLdRP zplfv&f^yq;tkc$l$DJma6YGUD3u8%O$x^uRPB@m<68_hN#X;>)8y7V%8t2`0X4r#A z>5M0%;kbwl+i_6`hYsDvhu2MT@JuLLPfmn)10K-3RD%t2m`hc@xT0df8KSLg$t<-= zAugs$xXVqAt&*5VWM&?OS%sBQs~yPNFZN*PKTF`wYtM!FZlQbLDa8&R%z-N*bvT&9 zL!FKohQA%l%QY`z4^DbV6<_|wk@t$|B7@?G=t24IaKt|0X$_%TqGSKy*J#}3Z+Zl_Mv!HnWdepSO;^3aJnfm7)CEM#RQ@6t7jCsKwdNrj5 zPX^7wN!JxXH+3t_xT3)-U%HOz&6JFr)Btkj|2TzrDny^_6S3e8EN(n`>JTMKa%;oX3 zu^W+jl1hKo7}MI4y(Fcp44(K4;Wu^yqq${OHJrXpq9)LVv5=>JEhd zCjw^GH( zr+o2MSp}?UKZ|LnvuRvzBUlVr!_xED&`748c8;rt$(OquDvcJA>-hv+eNGCVod@XC zD$n~ZO$T?q-(<6U3Z8XtM~#ocLjI=+s$3jFEYu#ySJ*q=YDuAr*H_@9pB&6Me5hYF-w`?=!QddV9R!nw_YlW!g3LI`k3;&%dG;!E0$`gB%9V z{thnt2EeFjChS@!&04$V5YefYf@A$O{(L)(9cT8#KkZR${)z9TSgxFQwps8Ahu_iu z8EIH+5dED@O6s|fa!3E`n&|tQo-kLocSD%&y7ySv0YLY!JJaLsQXch8= z-X}S(y^x%-l4MW&s6f~Z7jT{}!aB_h!5@cK;HKLfF>!VPsz(k28)L#uKP&Lf*hJF3 z;W1==Xdw?frosI|afls#o0v?QPMe$FF)Njhla@6q?9DApP+e@mF^Jv7%~PtNO?6SY z=6o6Xy+;%eejG)&dCkJN%}3#kmOSezuTN!ih~P`|fU*@W_@ZGJSryzw=&dL!zv}~| zVZ%FGd=x>~wFY=TR}6n`)WfgE_sQZ%f0&bZL&zPM>A-u*@%|Ur!}y@ttS;G&uhS$O z3Jkx~E+>8j{6e-of<6AWsL^*IQkusM};p_*!`Pp z;EUk3FxdGMvc{Cr4uuuywIGk&-7Sr^HO6Gz6&>QAv=yr}ZDG1^Fv|6>qQ4yWl6PY> z=>F7EsNLlE2loLPL)}T6GMMx=3(;uH`tKG)ZIre6@u5 z>>J=6I*P3rF&C$dNT#k^lRZ;b|d*o!%TtW_sGf zkJziwSS!w|{8neJlWg#PBGR6T9{9NF4jSZ1pu#($L-)v^xHMaG&uV1oq@~*IaL_2Y zacVJp?t~(Y*I0~_>6xJaFdEX1DU+XD6QMg#U>?0bOlt&N+SS(!XxB#{VIQu9H7@tbD@+jSQUT`!PHa<`aoha#v}TnXo(b;0p?-v_$n;V~?+ zbQAnnqI_9&I+f?$nP**^`~ubp7he2{2|HfmU9rt1b-e_1k@HNGh8?6mafBcjTac_* zV(xEj1}F7JFkyvoKTev`TQLssLnRO+22X))!ET%|GJ{CZ5@Qz%XEj+3zF4%NjBLF7 zK=465fu=L>gbsfp$zRt&{s_#_YgYs5EO7@MC=z(mQN=L!dml8(wb5YQ3!H2}ja+9! zY_u3^XyoK*yC)7mOi9F&-|0AH7C|Q(=TdRyDe&B(31w>q#?JB^Le}1ZC{?wPZ*K$+ zmdInWDC-b@(0)bl^%+BV;!OH;QV&@@?KtyCOJME1H)9{@b`bq%Aymz6AH4f#LD|98 zSU9ynVE?({TqP0u<@9bG5WHC8>=w+Z7w5b4!jaWIfttKIJh$z^hNWXMT|OGB|7h?Z z;#O0sNowrQuu;6#gK)TMH;Qd%C0NDCSn&UrO~&|qfGMR@>3^ydK_fnsF3Y&g_y^y| zACZc<$;3jK(*$9o!7|)v`4T(2_h6I#C!Dcdk}qMWV!Bg0{njs>t%>;a7YruytD<+{ zvytNb2C)D<2NO`kdkgAWHj&v1f>(I{D_W9xgG&CeBTAAZnTUBt(9zOJyN%?T4(mjm zyt^2y2ekN|MeZOGnaQ23HRMNFS7BYKJGFjUgY&dwQC2^lq;J`cZ!`s_$c~$!*3b^A z1=qn(@)ty8k7pf=wuA4}V!HW`zy;g)lni=w6YXo+ptkTT)A-~GW(Vd$PULHnVE&WY z)Nq~1JPOB~j3}pc@;u%0`Y!|oRg$&#j&x{N0*r$Bu*X&&T6exB+KuhR(t0(N*G0fJ zx}4m}je(y^+Whuk%6#9@WNh+1h`$u$p-KHEnPXD|FRySgxvU%}>z6aY;j%l zC-nD1G!$26XBuk3@#-;xZ(=f=Ug<@p^8O=sflpzas~BteC~3SCbPkBhSF>@mX|}=Nk}<{tUYL3251C2CGNiz=-hESP~urR)0f4 zGEf%u((CYD>S%WA9XXg-;Y+oa6ybor7J5%RgdY1=Q2(6|Y17ghT+9@C+%cR&4QBkn z3!BXNH&=@BRrUjFI_IR|s#D>wU1adD-$G2TtikGgQtW5F&18o|EP?vf%=_aH$jw{j zWTkIw{TB;+{5#a)xND;#D$1rYZ9j8ioc4)mqsnNFV3LP1`YPlVr7Vm=lk|IK>UZ(qK z4$^mm-{}4hxMV(uOV=2O@-8<>tB`{|Qy+#mOyt;`V!PnYwn9cGJA`a@RD$}LOl(=+ z3=OU?P*TMVPUY(I{HIzvV&Wi_EGxpqb4A$Pm_*`k_0s1#g>>uEyJXRatz2^WYr4UC zm{8&VtB+`8RQ9G&OYuGU+bSBnU#HQ>E61SR5`p26u^M*yWsnJj)9{wtQ*L6ACa!In z2?qjzh`%+!?j_N5oI@x!CcU9QCH~TFNf4Z(BGs^6pgPb9gj+w?UO1b)17k3U+LF5}=2r zHMLnC2Bnin(}J@vh^=G_&YYx$syEc&-_}i_^gxDpb{JyDgsem5hv%_N^EAC%afA~+ z>5WPPYcxslB)eqJV>_mg21gw$2#S0LV--G9r^sL0 znt(kYlrU5D1>9FX$?c6F#eN9732Sdi*@ndw$koi8bp<}u(hDxr+0Sy;e!Q8>OVRvv83akqofpK_Q6K?!m zh6~pEh>Ur+XM)|F{eT^ZlS}YcwurJL$?JcW6LY6g7E25k3{q zhn4O1Fu7*}?NZFbSpkdDp-4vw7;n*| z$^X0Ifl5!ui=NDEy@ z;Km~ncv?;jG+cC1;*tm26>h;@_pSJvMsGA(Vo1)-iifF6N#w!WXOs~fDKguq5sSYJ zIc~oXz7=k2nD22MwjFlH%Qt1Qt??>OwG0t{BVEWiO~dLq!v>p62^e}Ujkayj!7Hnd zG`LN;$Lu*9!F%;sU}35q|Jt*Jf1$aTxC}VMCgJZ(TPo0_63?j0jUpW1oev`voI%%a z7v0U3Lw&dsof*3onGK6@mvRPoaYQaHeE*XwEAx1&<1Yr!s={~aF}Sn$6CKtr#Jw@S zSf(-!6%XE{5#>wxzDRj~=3F0C2|7T}&g>%PzbBwm+A+!oI->2dF?5DO4*9n&gRF{L z2f3xa;I@4$^lT5KUF&aQRK;mJ+V~drW&dJQjxw+F){@PdsZ5HD{?N$^bKqg9I?S7( z1erb8V2jL5P^({0z7Foi+ff_f$320uSvrwy9M}ZIwP#_?4}r<15KnFGBAIfz81%Kw zYbf=Sz_l-4GWM6nq4B;muKXN=yJN!O?#MXcZ31yz`cLMyZwZR8mTSn!mcVDGVZ#1m zIbF483a0LLp^Q z9CF@;3{+ji7oTo(&mU$&f9y4~rcQ-DJVP0u{cCYFQ=16R^+V*M^F(&`e}T+&+iZCD zdK2u4>k-Zf`_bHU7e8f%DqbF)O7)w5;$w4TzB0#yyb&*_Z;qDX^ln}L=SNZ6C-e~O z!$a}XQ5(Ub)Jigz2N5&velo#P$opy3V!iQW+&7<+Q4Mz-L*%pZ%JS0<^CXTts<({= zi%};qOhXELLSJBK`CMdMJjo;5_1JS(ft)6pB^_ZWB!?4W0ND#0yj5}fGT%}ra|LPT>LaA(dG zx(AQo=ADTsQn#AM5;MBxohc#Fy0o)98q5`Qm?24NSaWbcUccMQG!{>!A%8EDI+fRS z?00F#d)^gdTIPy-_Y~qp3q$PQa-QDPc}WtZ>oDYd7JYE8(eY?XJhWmcd1Epa_pXRR zg=1R$n;A~n(>0q~M|q(0ia4%%ng-0-FqVJ)pa~5pCK0dpXsCbWE6fpF!K?ZQ3Hgx) z=AM^;G8csP*FJDQ^NpPM*XP#0b)l&eW@u!n$afr>!{7Z@%>`$KfVi$QZ>%~V{u{Fw zo|xZ(rD{>|W}FjB3%vj*-!2HBIg(SVnFd#D6`4zOztFeilyI6v4MZ+EmzMB2A zv_#$xomV;&>1kEurj#lKErlcuQN@9^_)Jn@8P426o}3(ucTKBsnL#2x zI$H*vXERBd@?PAn?hhYNouGAYs(4`M97xh=!~-7-h@s;mczAXr_!pJJ#GVRrla#={ zl<&|l@LkWhzkp9$Z^J-VGTI$4#VVKW%r4d0)Zoboe#W!ERB8HC`o?e)PMhuhvS$v9aIv;{bdza%4AxGxkn2t%EX?Q>?33m(ENI5?kevMRdR1-R|D!NKgRgUsJoM3T-rp{&I<@C?a=pTj_U*0KDg z@+hkFF_6Swc!Yb8J*8jYO~U!&$#mq1co;2kD%UvQfbt|!_%vC9e6o{-7k9&Gwp%N? z+#Cl9&%VQ^ySKqjX)NzDHU)F@Gf+n+gx4?@;Z1%#7qV(CsQYat?kps>HcPato1g2S4=tdHwtcfp_-Ems6I~G1QfRg8znFW%&&^@>oCtr}`2M>l(&A~^+ zr$iigwOLa!gUMvPeK#j3uxAaY$J1MMKZ@x6qn>jY!bvYlCNEnDn_iE==~d16seezy zOGQx#9{Nltl}tq=kyN5&c#&p&IY(pP*^mhdpWx_Zp=URIpXq6>huWueVThdqs>$Bq zpVJSg_YXq_jo}idiXD}fZ35l)I9#qDie&B$2!5fX`-6=!;p76z04u?CE^*i<}t z$qU-PZUk!M3BegQ-~n00(NmxF+A1+#10~!m;q3BU#TcL^5*TPxk99%jkYUB*oLSR( zBY9gWs*!hTvE$w{)?NX_P zY09R@FMXrm%+H~+IM1E@tdEMN37q-5*6jB{BjQD|gay&VPyezU9=sWokhMZ$k-vSgK4C)~8dE z+e@)^O0nSS;$5oAwIr0mVYwc>XjFk4 z#qH@?`2en_OxXV_H{wj6TlmUCoLAfu%T534$lpuNqAGPBtoV#MuvGBib@*Dbdc_(j zy3B#^ogBziY}e(#*v{j(Sxd+LPzWCWF|e6i2iFo+>Cm)APp?pgBk&@D`6!mw-hFc^upz^UD0?6%*Dc#;m$=CuN& ze)KOYzDwW_PVvJn84O(V*Wpd~9mS7Zu9B3=`q;Ma7hRNilX|ZWLy^cz2-^9abf;;6 zfBXU18Zr%{zKO%}(yMqf#|4eMSV;LIa3H@OgO~Lo=;*f*Rg~R`kxd=h=g|s@mBZK> zvyyns93qFxO3CKqq4<1%GCqFij~cIvxoMl8P;u!DEWXo#P4|^4{H%t)HTGonmFHYk zpcU?(u!MfVYouVTD*NYi6tmnxnjbv&3F;dbGO}?8U`1;kw2!($=4VxqC4n|zNjKB} z_8D|$S~m0_N2vRCoC*R#2>fp^9J@7}Eh&;@#lMV!*@MNH$jn<#hXb_OqGzJqgUnRWwk^UGA+M-qEyc&kAHrsj)9AinBxD>nVwX;y0^Li* z@ZOBQ#DS#^$A``63Y`*e)Y9!}^P-I;cCNwgHASTKvNPLYTZ8v*3QWs&4`5hffNr&X zMbzeILy@y2?hMVNrg#+7{z%c$x25?xvyAwLm$K0Hy$k}}X0oOHKkAFeK&@^7jtJ|s zPQi9KO+w*M9x$F*SXOv=jk_<}TX-1{*71+1z1ilOy z!8eW+dL0IpLay2YXIQks$^07f-$)zy`OB65`;|qzXfYfrKG;wrdV{b6cWZC;M`ru< zZnUG`5Zg75Uw2cUZ`qOy7W0c}MM5-rk$xQlM++<;^%8pQ`$~AaSQ3x^a^a+&%ELl& z74FL1e&W5m3|wC5gLvXpGHCvZF|EErJxb!}H{%m%G)kPL^xr3p*=KHHQZ3VW{xTd| zJP}?t>Op<$C|02>9CrFg<8VR|v=`}v^WwMUM6)*Dh#HGi($3LW-oI$kL=jl|@D^QF zI}-BeD8kLw;|)i1q%mB^9^=M+q?SfWxKAUIi3)PVT~?}a{p4jTE$NNM_pfll0nRvA z&kfz;BGB(_Jl$qp!CBEn{GD|GdW-fzdyft|uZ7dL@I z-Ql^M+H4DaGBJjdgO+r#cnkgTO<0!(>aeCRyWpVoWvKA6#-SPUFlxL$4wj9fOIAkG z>7ntQl}a!3e!M-%%&((+JIe6kRDJkiR?M_6aRaXz^+ZgpiWHxn4O@f`a-F;moZS41 zWS3@>&Wk0qA!rA<_}s>TbDF&Cn@1?K=MG9tYQZPEwzya#7R_`%b6q=wVE>dhd@zrr z%l^~AVd-8Hz1$lr&bL#8`XgLpR55iB%VTz>-JnP2B!IKTNYobpMz2giK>zm1F*sKO z{G88l;V-rjks)RLDK-ah`o6-0=1b9R&CUjIk0g3Gl&2HjMqqbe0`YsL2usfz;xiu| zp6Ez12P=1z);05NE%lPspo!!>!exeTrKQq{=CCYclOip3tg!A=@cH>m4?j{*U)z8 z0?ygG61pcG1(m8c?x>`2Z~ZRAc)_`KPEsGeYb&uZIt>fW`ggbDt3nY>jCNxtVaPcG)dcEy56>AHkox;9>ewBoSrpe@m zQ7HcY&jg$`2Faz~G;*Ux5=|we$d@=@I1?(5o0injxx#x!K5Ze4d!0vS{^x=lzYTDA z;0H+Lg-E6-0Xn&_5_2z(E%te3uH__s*;jFw;6k_ zAhKXYCdlfEK<7jgxUhXO=hYHMHo+313$%}3o6w5Ow6<^qzYS=_j3IJGbP-J6e*w&n zO0zr6)u^bzxZB;no-Ta(k{t0F4R?N@p*dqNpwqz&+_YvRqzF0pqf#MQ&& zFVc9w&m?55Djl<;f;*=88IEeIV56fpxQ1jxb#wvL9lb;5T0MZuqo+Bwg_d~k-T@pl z@Pc;iYoxdG)M?xrVIDV?r&rqR1a^Na))~vve~DwTHB1EV_z7oQ9m}arzc0v5c*`_u z`ckL;Dp+yHio7q9z{eX6@L8=g`4Q@Xo6Q7&ShqPA&KO6JTEC!MvW}2(aeA~;)r3~R zZNh}DI=D6a0~Ke?$m@6!Xv-Og=aR(8g91skGTMNJ!%yjY_Z%GFC5bj;N^zRW2<li}p4O0|&f3}vz~8FeeexY(#{oS{j8S4^WT z@-{X;&ug63-4XPgl`Ra6vxCSL|B?A=JzTB`GQTv3sDj>3(x{>d3%d+)uir(u ztvm_t9r;2!jJnA^?I@5qFb79&ea&?^8*w`%wQ*gRKIPm4q1bgBHH(X;MHeo>@5)DX zvrGaxqgN)ld}8Rpz$b|5zfJu%x1j&mcuvxz5`E8@;eu(g7|~XRQkTXO|LDEwX)=wX z(98a_&UAi?4iF0fCWD5Ro{KQxI93gYN@3l5ob!1@5 z`U=Pn3_(*d@V$&=_4JjvDQEV!FC++U6F68F)^Y1#O9sx!WuV1kCC zC#d|LS&%#R57}UK9di=$N$LqbC{K6B67fSMKB$m(ueT9cH-M{SzSGnHGRejfjt!A- z-;;A;;{g{86XM1BZ(b*g?W9}mA-oOhhc1` zvE*tFr<-Gix_VLge2Fr(H7J8bkuPu{&73^{v>*TaW|5gUO~KnokNT7>!6$0Tpmg~V zxY~Jf(T`%d)h)%Gp;HR!c2=g&exk%-ektkK9>}2EipPtE=iuGdBaU`&#*o0^pJep69$FKp z%}f(32XC1a=qx(|E+&q+VgGep<)22z_pYS*`T^u%R|i=zC7Rf#YS4eywN!qA9DWhz zjZfFu)A?^Zs7dBndS=vDGP61hecZR;w)8sMYJZnPN z3a2g+&eOEp>9`|d)V?|s%~xsQDeW7${l+Pj_lUvew`Sw{4?I^Jc^MCmmnPFEdr<4L z8gfij3_qKOV1#He>2w%C{b}*IfBy!u&}1IuS>}P)mxa*E@n9(Sow%ngf-^m;_@J>E z#~MUnkdQ?-^fbg%WE)jVn@>`_7E>LA7~&R}j_oft;o3%mbFM^_!~1=3c0dEBZmNf- z)$UMG5Y5eW_QtoO)wI)W5$c6V;huRBuPFgPA(8$-IruDAB?#PPX(^=NUBA zy~BBDXz~^R&%{*~k+fhHbPb!%IAyh9g=iO3xbru8(H(&g^(f9Ocu%eb-gc}CsDi_d z=CCx^2|6N!PHAdd4-(h{)* zt|E0cjX83Y`?K2{P6r%@V6`mfS%oabTi8&qUx#t&#KYvj5+g#x^YP#XUsS6sMRukV zbxk;cU2aR^2j>H=iQSm-#GL;+Hv<>%k|2}E*P@?S5mp)SbWz(X97xrJBYj~ce|b9f znp{HuFxOFKV%u?-_Vt(r?-(d5&v;dp3o-X@0QRld$4g3fjL!OF7~T{N zS%FU6kxz#(QDEh)mNev@Yy=+DIZG6EPQWDVBKqLs6#T9jL+^L%;KzV4=&Y|I14`kT z-Z2VP`bBVyiy{s=S(3FSGte)=i(An>0v6UZlN<1h*xG-@Pe0V?&s|=qT`a+Guek+v z)By&sJ0ngih5yuMp>20KjMUFV=Q&4k+vaN2Gz+D>w9OrxO60Jg8=$vDhG@Oi?%sVkInsh!bibu5r$6EPJ(_6#_ENlE6@zho zhv@t;2F{NZV4vH6kv^fv`AAqpE?oJV{PFi^u09?QFAf+`n@t%wrEDWD-mwF%&LrWF zhCSFZc89?8$YZ3>tN_VL^Ek18MpV<20i%qrdYQ~NX5Y^PP~qr|Dk0@`%t0qcYwK~Y zcv=R@KUj-L&}(Q8Zc#JAQ(ohUzot6)HWw4AQ;~FD z3M+h@H*y>NPvMi>=2&IFl_*zl!n_B^G3>D$9^G*j_is6Z`9F*C^W-z=9^`}p+M9{G zaicvuB50hfTEkhnV!CgyHt3`R7+B6G61hVpWYI&%(v6;|COJUQ{C5e)eA*6& zW6J1>5(PZ{+6{xZd?$lP_3`Y=U%pAO zz2tWLW9roAj$88YV2?>OT{cGs#lwZpra~{b>lVjJoHqfjSV|Y32*Y(jBkALjMsTO> zKDoVMBYC=Y1d$$UBD*XHxyK8usM^k@-0&Vp81LnT=UsI%|Ea+1t}b(&&pjr;po#be zJ|qdQYw^^fcFgRXgO;zBVXAO`^lsBAT%ov-hPo~SmrQ`@E>T>W_lmoyPN<5e7n;Us z2=DNk2ARQBGX2_m2>Bw5`x7$h%0D~F)?X5I&xQLm>EbL5oe%*xCNlW7QXeJ$ieR|i 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

    1. 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

      UGipDft7>FWN!fXbh@cD?+W&aPVJu0dFih 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

      Z*WS@iOp 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 z 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 ?pWId5bxQ1j%~c(%Bn>VBRNp<@iPs$z`#B0b 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
      mg?6TRp-|#`nCg2K=YCv|&$GlJPWRWf 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
      7^A1rWab1`gbk0v&xLMkBi$H+=NKKh{ejzwH(2 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 fk0#=W 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

      e@;{oB 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%0Aim6gS_DH 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¨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 {WO^f$W_6!woo5CA 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%0DcP&M;chNL2Bmy^{O+dq5Yq+}l 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 Z*^kLS>~;sk8W8$wh{ccRAt1>XE~IJZM5q1;)J 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%0Ar0=^6 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

      d(#$R3|4t8XzN|(suU4|N;2nG6r4%N2y(b+{ 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⋙A?baA)@pIvcJc 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%0A96xEs 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 _D)gW|8_^xhNs&%4xME({0xN_%P3h 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 z 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≺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

      JNvX_o)EsHTW!&2WgMEvs#k+R;Hp5@Yb{|E9 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

      LgJ$hHrw$+xzdROXc=H-F3l+PUAE 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⁣g<^Y)r~t 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вG~xbWjOJXcL& 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

      $-a)eRyvX%PP3BkEz}3#N;D20s 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 z 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 QpxYUj)A+we)O7cGZdsu@^TGWf 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

      vf~(>+m3VVp&nm~We+L+1Isj%k1>A1ntQh4US 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≧2-o_g+pGcg3927TvSv# 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. +This can be avoided by defining an R128_ASSERT macro in your implementation +file. Since this library uses 64-bit arithmetic, this may implicitly add a +runtime library dependency on 32-bit platforms. + +C++ SUPPORT +----------- +Operator overloads are supplied for C++ files that include this file. Since all +C++ functions are declared inline (or static inline), the R128_IMPLEMENTATION +file can be either C++ or C. + +LICENSE +------- +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef H_R128_H +#define H_R128_H + +#include + +// 64-bit integer support +// If your compiler does not have stdint.h, add appropriate defines for these macros. +#if defined(_MSC_VER) && (_MSC_VER < 1600) +# define R128_S32 __int32 +# define R128_U32 unsigned __int32 +# define R128_S64 __int64 +# define R128_U64 unsigned __int64 +# define R128_LIT_S64(x) x##i64 +# define R128_LIT_U64(x) x##ui64 +#else +# include +# define R128_S32 int32_t +# define R128_U32 uint32_t +# define R128_S64 int64_t +# define R128_U64 long long unsigned int +# define R128_LIT_S64(x) x##ll +# define R128_LIT_U64(x) x##ull +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct R128 { + R128_U64 lo; + R128_U64 hi; + +#ifdef __cplusplus + R128(); + R128(double); + R128(int); + R128(R128_S64); + R128(R128_U64 low, R128_U64 high); + + operator double() const; + operator R128_S64() const; + operator int() const; + operator bool() const; + + bool operator!() const; + R128 operator~() const; + R128 operator-() const; + R128 &operator|=(const R128 &rhs); + R128 &operator&=(const R128 &rhs); + R128 &operator^=(const R128 &rhs); + R128 &operator+=(const R128 &rhs); + R128 &operator-=(const R128 &rhs); + R128 &operator*=(const R128 &rhs); + R128 &operator/=(const R128 &rhs); + R128 &operator%=(const R128 &rhs); + R128 &operator<<=(int amount); + R128 &operator>>=(int amount); +#endif //__cplusplus +} R128; + +// Type conversion +extern void r128FromInt(R128 *dst, R128_S64 v); +extern void r128FromFloat(R128 *dst, double v); +extern R128_S64 r128ToInt(const R128 *v); +extern double r128ToFloat(const R128 *v); + +// Copy +extern void r128Copy(R128 *dst, const R128 *src); + +// Negate +extern void r128Neg(R128 *dst, const R128 *src); + +// Bitwise operations +extern void r128Not(R128 *dst, const R128 *src); // ~a +extern void r128Or(R128 *dst, const R128 *a, const R128 *b); // a | b +extern void r128And(R128 *dst, const R128 *a, const R128 *b); // a & b +extern void r128Xor(R128 *dst, const R128 *a, const R128 *b); // a ^ b +extern void r128Shl(R128 *dst, const R128 *src, int amount); // shift left by amount mod 128 +extern void r128Shr(R128 *dst, const R128 *src, int amount); // shift right logical by amount mod 128 +extern void r128Sar(R128 *dst, const R128 *src, int amount); // shift right arithmetic by amount mod 128 + +// Arithmetic +extern void r128Add(R128 *dst, const R128 *a, const R128 *b); // a + b +extern void r128Sub(R128 *dst, const R128 *a, const R128 *b); // a - b +extern void r128Mul(R128 *dst, const R128 *a, const R128 *b); // a * b +extern void r128Div(R128 *dst, const R128 *a, const R128 *b); // a / b +extern void r128Mod(R128 *dst, const R128 *a, const R128 *b); // a - toInt(a / b) * b + +extern void r128Sqrt(R128 *dst, const R128 *v); // sqrt(v) +extern void r128Rsqrt(R128 *dst, const R128 *v); // 1 / sqrt(v) + +// Comparison +extern int r128Cmp(const R128 *a, const R128 *b); // sign of a-b +extern void r128Min(R128 *dst, const R128 *a, const R128 *b); +extern void r128Max(R128 *dst, const R128 *a, const R128 *b); +extern void r128Floor(R128 *dst, const R128 *v); +extern void r128Ceil(R128 *dst, const R128 *v); +extern int r128IsNeg(const R128 *v); // quick check for < 0 + +// String conversion +// +typedef enum R128ToStringSign { + R128ToStringSign_Default, // no sign character for positive values + R128ToStringSign_Space, // leading space for positive values + R128ToStringSign_Plus, // leading '+' for positive values +} R128ToStringSign; + +// Formatting options for use with r128ToStringOpt. The "defaults" correspond +// to a format string of "%f". +// +typedef struct R128ToStringFormat { + // sign character for positive values. Default is R128ToStringSign_Default. + R128ToStringSign sign; + + // minimum number of characters to write. Default is 0. + int width; + + // place to the right of the decimal at which rounding is performed. If negative, + // a maximum of 20 decimal places will be written, with no trailing zeroes. + // (20 places is sufficient to ensure that r128FromString will convert back to the + // original value.) Default is -1. NOTE: This is not the same default that the C + // standard library uses for %f. + int precision; + + // If non-zero, pads the output string with leading zeroes if the final result is + // fewer than width characters. Otherwise, leading spaces are used. Default is 0. + int zeroPad; + + // Always print a decimal point, even if the value is an integer. Default is 0. + int decimal; + + // Left-align output if width specifier requires padding. + // Default is 0 (right align). + int leftAlign; +} R128ToStringFormat; + +// r128ToStringOpt: convert R128 to a decimal string, with formatting. +// +// dst and dstSize: specify the buffer to write into. At most dstSize bytes will be written +// (including null terminator). No additional rounding is performed if dstSize is not large +// enough to hold the entire string. +// +// opt: an R128ToStringFormat struct (q.v.) with formatting options. +// +// Uses the R128_decimal global as the decimal point character. +// Always writes a null terminator, even if the destination buffer is not large enough. +// +// Number of bytes that will be written (i.e. how big does dst need to be?): +// If width is specified: width + 1 bytes. +// If precision is specified: at most precision + 22 bytes. +// If neither is specified: at most 42 bytes. +// +// Returns the number of bytes that would have been written if dst was sufficiently large, +// not including the final null terminator. +// +extern int r128ToStringOpt(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *opt); + +// r128ToStringf: convert R128 to a decimal string, with formatting. +// +// dst and dstSize: specify the buffer to write into. At most dstSize bytes will be written +// (including null terminator). +// +// format: a printf-style format specifier, as one would use with floating point types. +// e.g. "%+5.2f". (The leading % and trailing f are optional.) +// NOTE: This is NOT a full replacement for sprintf. Any characters in the format string +// that do not correspond to a format placeholder are ignored. +// +// Uses the R128_decimal global as the decimal point character. +// Always writes a null terminator, even if the destination buffer is not large enough. +// +// Number of bytes that will be written (i.e. how big does dst need to be?): +// If the precision field is specified: at most max(width, precision + 21) + 1 bytes +// Otherwise: at most max(width, 41) + 1 bytes. +// +// Returns the number of bytes that would have been written if dst was sufficiently large, +// not including the final null terminator. +// +extern int r128ToStringf(char *dst, size_t dstSize, const char *format, const R128 *v); + +// r128ToString: convert R128 to a decimal string, with default formatting. +// Equivalent to r128ToStringf(dst, dstSize, "%f", v). +// +// Uses the R128_decimal global as the decimal point character. +// Always writes a null terminator, even if the destination buffer is not large enough. +// +// Will write at most 42 bytes (including NUL) to dst. +// +// Returns the number of bytes that would have been written if dst was sufficiently large, +// not including the final null terminator. +// +extern int r128ToString(char *dst, size_t dstSize, const R128 *v); + +// r128FromString: Convert string to R128. +// +// The string can be formatted either as a decimal number with optional sign +// or as hexadecimal with a prefix of 0x or 0X. +// +// endptr, if not NULL, is set to the character following the last character +// used in the conversion. +// +extern void r128FromString(R128 *dst, const char *s, char **endptr); + +// Constants +extern const R128 R128_min; // minimum (most negative) value +extern const R128 R128_max; // maximum (most positive) value +extern const R128 R128_smallest; // smallest positive value +extern const R128 R128_zero; // zero +extern const R128 R128_one; // 1.0 + +extern char R128_decimal; // decimal point character used by r128From/ToString. defaults to '.' + +#ifdef __cplusplus +} + +#include +namespace std { +template<> +struct numeric_limits +{ + static const bool is_specialized = true; + + static R128 min() throw() { return R128_min; } + static R128 max() throw() { return R128_max; } + + static const int digits = 127; + static const int digits10 = 38; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const int radix = 2; + static R128 epsilon() throw() { return R128_smallest; } + static R128 round_error() throw() { return R128_one; } + + static const int min_exponent = 0; + static const int min_exponent10 = 0; + static const int max_exponent = 0; + static const int max_exponent10 = 0; + + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const float_denorm_style has_denorm = denorm_absent; + static const bool has_denorm_loss = false; + + static R128 infinity() throw() { return R128_zero; } + static R128 quiet_NaN() throw() { return R128_zero; } + static R128 signaling_NaN() throw() { return R128_zero; } + static R128 denorm_min() throw() { return R128_zero; } + + static const bool is_iec559 = false; + static const bool is_bounded = true; + static const bool is_modulo = true; + + static const bool traps = numeric_limits::traps; + static const bool tinyness_before = false; + static const float_round_style round_style = round_toward_zero; +}; +} //namespace std + +inline R128::R128() {} + +inline R128::R128(double v) +{ + r128FromFloat(this, v); +} + +inline R128::R128(int v) +{ + r128FromInt(this, v); +} + +inline R128::R128(R128_S64 v) +{ + r128FromInt(this, v); +} + +inline R128::R128(R128_U64 low, R128_U64 high) +{ + lo = low; + hi = high; +} + +inline R128::operator double() const +{ + return r128ToFloat(this); +} + +inline R128::operator R128_S64() const +{ + return r128ToInt(this); +} + +inline R128::operator int() const +{ + return (int) r128ToInt(this); +} + +inline R128::operator bool() const +{ + return lo || hi; +} + +inline bool R128::operator!() const +{ + return !lo && !hi; +} + +inline R128 R128::operator~() const +{ + R128 r; + r128Not(&r, this); + return r; +} + +inline R128 R128::operator-() const +{ + R128 r; + r128Neg(&r, this); + return r; +} + +inline R128 &R128::operator|=(const R128 &rhs) +{ + r128Or(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator&=(const R128 &rhs) +{ + r128And(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator^=(const R128 &rhs) +{ + r128Xor(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator+=(const R128 &rhs) +{ + r128Add(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator-=(const R128 &rhs) +{ + r128Sub(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator*=(const R128 &rhs) +{ + r128Mul(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator/=(const R128 &rhs) +{ + r128Div(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator%=(const R128 &rhs) +{ + r128Mod(this, this, &rhs); + return *this; +} + +inline R128 &R128::operator<<=(int amount) +{ + r128Shl(this, this, amount); + return *this; +} + +inline R128 &R128::operator>>=(int amount) +{ + r128Sar(this, this, amount); + return *this; +} + +static inline R128 operator|(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r |= rhs; +} + +static inline R128 operator&(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r &= rhs; +} + +static inline R128 operator^(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r ^= rhs; +} + +static inline R128 operator+(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r += rhs; +} + +static inline R128 operator-(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r -= rhs; +} + +static inline R128 operator*(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r *= rhs; +} + +static inline R128 operator/(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r /= rhs; +} + +static inline R128 operator%(const R128 &lhs, const R128 &rhs) +{ + R128 r(lhs); + return r %= rhs; +} + +static inline R128 operator<<(const R128 &lhs, int amount) +{ + R128 r(lhs); + return r <<= amount; +} + +static inline R128 operator>>(const R128 &lhs, int amount) +{ + R128 r(lhs); + return r >>= amount; +} + +static inline bool operator<(const R128 &lhs, const R128 &rhs) +{ + return r128Cmp(&lhs, &rhs) < 0; +} + +static inline bool operator>(const R128 &lhs, const R128 &rhs) +{ + return r128Cmp(&lhs, &rhs) > 0; +} + +static inline bool operator<=(const R128 &lhs, const R128 &rhs) +{ + return r128Cmp(&lhs, &rhs) <= 0; +} + +static inline bool operator>=(const R128 &lhs, const R128 &rhs) +{ + return r128Cmp(&lhs, &rhs) >= 0; +} + +static inline bool operator==(const R128 &lhs, const R128 &rhs) +{ + return lhs.lo == rhs.lo && lhs.hi == rhs.hi; +} + +static inline bool operator!=(const R128 &lhs, const R128 &rhs) +{ + return lhs.lo != rhs.lo || lhs.hi != rhs.hi; +} + +#endif //__cplusplus +#endif //H_R128_H + +#ifdef R128_IMPLEMENTATION + +#ifdef R128_DEBUG_VIS +# define R128_DEBUG_SET(x) r128ToString(R128_last, sizeof(R128_last), x) +#else +# define R128_DEBUG_SET(x) +#endif + +#define R128_SET2(x, l, h) do { (x)->lo = (R128_U64)(l); (x)->hi = (R128_U64)(h); } while(0) +#define R128_R0(x) ((R128_U32)(x)->lo) +#define R128_R2(x) ((R128_U32)(x)->hi) +#if defined(_M_IX86) +// workaround: MSVC x86's handling of 64-bit values is not great +# define R128_SET4(x, r0, r1, r2, r3) do { \ + ((R128_U32*)&(x)->lo)[0] = (R128_U32)(r0); \ + ((R128_U32*)&(x)->lo)[1] = (R128_U32)(r1); \ + ((R128_U32*)&(x)->hi)[0] = (R128_U32)(r2); \ + ((R128_U32*)&(x)->hi)[1] = (R128_U32)(r3); \ + } while(0) +# define R128_R1(x) (((R128_U32*)&(x)->lo)[1]) +# define R128_R3(x) (((R128_U32*)&(x)->hi)[1]) +#else +# define R128_SET4(x, r0, r1, r2, r3) do { (x)->lo = (R128_U64)(r0) | ((R128_U64)(r1) << 32); \ + (x)->hi = (R128_U64)(r2) | ((R128_U64)(r3) << 32); } while(0) +# define R128_R1(x) ((R128_U32)((x)->lo >> 32)) +# define R128_R3(x) ((R128_U32)((x)->hi >> 32)) +#endif + +#if defined(_M_X64) +# define R128_INTEL 1 +# define R128_64BIT 1 +# ifndef R128_STDC_ONLY +# include +# endif +#elif defined(__x86_64__) +# define R128_INTEL 1 +# define R128_64BIT 1 +# ifndef R128_STDC_ONLY +# include +# endif +#elif defined(_M_IX86) +# define R128_INTEL 1 +# ifndef R128_STDC_ONLY +# include +# endif +#elif defined(__i386__) +# define R128_INTEL 1 +# ifndef R128_STDC_ONLY +# include +# endif +#elif defined(_M_ARM) +# ifndef R128_STDC_ONLY +# include +# endif +#elif defined(_M_ARM64) +# define R128_64BIT 1 +# ifndef R128_STDC_ONLY +# include +# endif +#elif defined(__aarch64__) +# define R128_64BIT 1 +#endif + +#ifndef R128_INTEL +# define R128_INTEL 0 +#endif + +#ifndef R128_64BIT +# define R128_64BIT 0 +#endif + +#ifndef R128_ASSERT +# include +# define R128_ASSERT(x) assert(x) +#endif + +#include // for NULL + +static const R128ToStringFormat R128__defaultFormat = { + R128ToStringSign_Default, + 0, + -1, + 0, + 0, + 0 +}; + +const R128 R128_min = { 0, R128_LIT_U64(0x8000000000000000) }; +const R128 R128_max = { R128_LIT_U64(0xffffffffffffffff), R128_LIT_U64(0x7fffffffffffffff) }; +const R128 R128_smallest = { 1, 0 }; +const R128 R128_zero = { 0, 0 }; +const R128 R128_one = { 0, 1 }; +char R128_decimal = '.'; +#ifdef R128_DEBUG_VIS +char R128_last[42]; +#endif + +static int r128__clz64(R128_U64 x) +{ +#if defined(R128_STDC_ONLY) + R128_U64 n = 64, y; + y = x >> 32; if (y) { n -= 32; x = y; } + y = x >> 16; if (y) { n -= 16; x = y; } + y = x >> 8; if (y) { n -= 8; x = y; } + y = x >> 4; if (y) { n -= 4; x = y; } + y = x >> 2; if (y) { n -= 2; x = y; } + y = x >> 1; if (y) { n -= 1; x = y; } + return (int)(n - x); +#elif defined(_M_X64) || defined(_M_ARM64) + unsigned long idx; + if (_BitScanReverse64(&idx, x)) { + return 63 - (int)idx; + } else { + return 64; + } +#elif defined(_MSC_VER) + unsigned long idx; + if (_BitScanReverse(&idx, (R128_U32)(x >> 32))) { + return 31 - (int)idx; + } else if (_BitScanReverse(&idx, (R128_U32)x)) { + return 63 - (int)idx; + } else { + return 64; + } +#else + return x ? __builtin_clzll(x) : 64; +#endif +} + +#if !R128_64BIT +// 32*32->64 +static R128_U64 r128__umul64(R128_U32 a, R128_U32 b) +{ +# if defined(_M_IX86) && !defined(R128_STDC_ONLY) + return __emulu(a, b); +# elif defined(_M_ARM) && !defined(R128_STDC_ONLY) + return _arm_umull(a, b); +# else + return a * (R128_U64)b; +# endif +} + +// 64/32->32 +static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *rem) +{ +# if defined(_M_IX86) && (_MSC_VER >= 1920) && !defined(R128_STDC_ONLY) + unsigned __int64 n = ((unsigned __int64)nhi << 32) | nlo; + return _udiv64(n, d, rem); +# elif defined(_M_IX86) && !defined(R128_STDC_ONLY) + __asm { + mov eax, nlo + mov edx, nhi + div d + mov ecx, rem + mov dword ptr [ecx], edx + } +# elif defined(__i386__) && !defined(R128_STDC_ONLY) + R128_U32 q, r; + __asm("divl %4" + : "=a"(q), "=d"(r) + : "a"(nlo), "d"(nhi), "X"(d)); + *rem = r; + return q; +# else + R128_U64 n64 = ((R128_U64)nhi << 32) | nlo; + *rem = (R128_U32)(n64 % d); + return (R128_U32)(n64 / d); +# endif +} +#elif !defined(_M_X64) || defined(R128_STDC_ONLY) +#define r128__umul64(a, b) ((a) * (R128_U64)(b)) +/*static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *rem) +{ + R128_U64 n64 = ((R128_U64)nhi << 32) | nlo; + *rem = (R128_U32)(n64 % d); + return (R128_U32)(n64 / d); +}*/ +#endif //!R128_64BIT + +static void r128__neg(R128 *dst, const R128 *src) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(src != NULL); + +#if R128_INTEL && !defined(R128_STDC_ONLY) + { + unsigned char carry = 0; +# if R128_64BIT + carry = _addcarry_u64(carry, ~src->lo, 1, &dst->lo); + carry = _addcarry_u64(carry, ~src->hi, 0, &dst->hi); +# else + R128_U32 r0, r1, r2, r3; + carry = _addcarry_u32(carry, ~R128_R0(src), 1, &r0); + carry = _addcarry_u32(carry, ~R128_R1(src), 0, &r1); + carry = _addcarry_u32(carry, ~R128_R2(src), 0, &r2); + carry = _addcarry_u32(carry, ~R128_R3(src), 0, &r3); + R128_SET4(dst, r0, r1, r2, r3); +# endif //R128_64BIT + } +#else + if (src->lo) { + dst->lo = ~src->lo + 1; + dst->hi = ~src->hi; + } else { + dst->lo = 0; + dst->hi = ~src->hi + 1; + } +#endif //R128_INTEL +} + +// 64*64->128 +static void r128__umul128(R128 *dst, R128_U64 a, R128_U64 b) +{ +#if defined(_M_X64) && !defined(R128_STDC_ONLY) + dst->lo = _umul128(a, b, &dst->hi); +#elif R128_64BIT && !defined(_MSC_VER) && !defined(R128_STDC_ONLY) + unsigned __int128 p0 = a * (unsigned __int128)b; + dst->hi = (R128_U64)(p0 >> 64); + dst->lo = (R128_U64)p0; +#else + R128_U32 alo = (R128_U32)a; + R128_U32 ahi = (R128_U32)(a >> 32); + R128_U32 blo = (R128_U32)b; + R128_U32 bhi = (R128_U32)(b >> 32); + R128_U64 p0, p1, p2, p3; + + p0 = r128__umul64(alo, blo); + p1 = r128__umul64(alo, bhi); + p2 = r128__umul64(ahi, blo); + p3 = r128__umul64(ahi, bhi); + + { +#if R128_INTEL && !defined(R128_STDC_ONLY) + R128_U32 r0, r1, r2, r3; + unsigned char carry; + + r0 = (R128_U32)(p0); + r1 = (R128_U32)(p0 >> 32); + r2 = (R128_U32)(p1 >> 32); + r3 = (R128_U32)(p3 >> 32); + + carry = _addcarry_u32(0, r1, (R128_U32)p1, &r1); + carry = _addcarry_u32(carry, r2, (R128_U32)(p2 >> 32), &r2); + _addcarry_u32(carry, r3, 0, &r3); + carry = _addcarry_u32(0, r1, (R128_U32)p2, &r1); + carry = _addcarry_u32(carry, r2, (R128_U32)p3, &r2); + _addcarry_u32(carry, r3, 0, &r3); + + R128_SET4(dst, r0, r1, r2, r3); +#else + R128_U64 carry, lo, hi; + carry = ((R128_U64)(R128_U32)p1 + (R128_U64)(R128_U32)p2 + (p0 >> 32)) >> 32; + + lo = p0 + ((p1 + p2) << 32); + hi = p3 + ((R128_U32)(p1 >> 32) + (R128_U32)(p2 >> 32)) + carry; + + R128_SET2(dst, lo, hi); +#endif + } +#endif +} + +// 128/64->64 +#if defined(_M_X64) && (_MSC_VER < 1920) && !defined(R128_STDC_ONLY) +// MSVC x64 provides neither inline assembly nor (pre-2019) a div intrinsic, so we do fake +// "inline assembly" to avoid long division or outline assembly. +#pragma code_seg(".text") +__declspec(allocate(".text")) static const unsigned char r128__udiv128Code[] = { + 0x48, 0x8B, 0xC1, //mov rax, rcx + 0x49, 0xF7, 0xF0, //div rax, r8 + 0x49, 0x89, 0x11, //mov qword ptr [r9], rdx + 0xC3 //ret +}; +typedef R128_U64 (*r128__udiv128Proc)(R128_U64 nlo, R128_U64 nhi, R128_U64 d, R128_U64 *rem); +static const r128__udiv128Proc r128__udiv128 = (r128__udiv128Proc)(void*)r128__udiv128Code; +#else +static R128_U64 r128__udiv128(R128_U64 nlo, R128_U64 nhi, R128_U64 d, R128_U64 *rem) +{ +#if defined(_M_X64) && !defined(R128_STDC_ONLY) + return _udiv128(nhi, nlo, d, rem); +#elif defined(__x86_64__) && !defined(R128_STDC_ONLY) + R128_U64 q, r; + __asm("divq %4" + : "=a"(q), "=d"(r) + : "a"(nlo), "d"(nhi), "X"(d)); + *rem = r; + return q; +#else + R128_U64 tmp; + R128_U32 d0, d1; + R128_U32 n3, n2, n1, n0; + R128_U32 q0, q1; + R128_U32 r; + int shift; + + R128_ASSERT(d != 0); //division by zero + R128_ASSERT(nhi < d); //overflow + + // normalize + shift = r128__clz64(d); + + if (shift) { + R128 tmp128; + R128_SET2(&tmp128, nlo, nhi); + r128Shl(&tmp128, &tmp128, shift); + n3 = R128_R3(&tmp128); + n2 = R128_R2(&tmp128); + n1 = R128_R1(&tmp128); + n0 = R128_R0(&tmp128); + d <<= shift; + } else { + n3 = (R128_U32)(nhi >> 32); + n2 = (R128_U32)nhi; + n1 = (R128_U32)(nlo >> 32); + n0 = (R128_U32)nlo; + } + + d1 = (R128_U32)(d >> 32); + d0 = (R128_U32)d; + + // first digit + R128_ASSERT(n3 <= d1); + if (n3 < d1) { + q1 = r128__udiv64(n2, n3, d1, &r); + } else { + q1 = 0xffffffffu; + r = n2 + d1; + } +refine1: + if (r128__umul64(q1, d0) > ((R128_U64)r << 32) + n1) { + --q1; + if (r < ~d1 + 1) { + r += d1; + goto refine1; + } + } + + tmp = ((R128_U64)n2 << 32) + n1 - (r128__umul64(q1, d0) + (r128__umul64(q1, d1) << 32)); + n2 = (R128_U32)(tmp >> 32); + n1 = (R128_U32)tmp; + + // second digit + R128_ASSERT(n2 <= d1); + if (n2 < d1) { + q0 = r128__udiv64(n1, n2, d1, &r); + } else { + q0 = 0xffffffffu; + r = n1 + d1; + } +refine0: + if (r128__umul64(q0, d0) > ((R128_U64)r << 32) + n0) { + --q0; + if (r < ~d1 + 1) { + r += d1; + goto refine0; + } + } + + tmp = ((R128_U64)n1 << 32) + n0 - (r128__umul64(q0, d0) + (r128__umul64(q0, d1) << 32)); + n1 = (R128_U32)(tmp >> 32); + n0 = (R128_U32)tmp; + + *rem = (((R128_U64)n1 << 32) + n0) >> shift; + return ((R128_U64)q1 << 32) + q0; +#endif +} +#endif + +static int r128__ucmp(const R128 *a, const R128 *b) +{ + if (a->hi != b->hi) { + if (a->hi > b->hi) { + return 1; + } else { + return -1; + } + } else { + if (a->lo == b->lo) { + return 0; + } else if (a->lo > b->lo) { + return 1; + } else { + return -1; + } + } +} + +static void r128__umul(R128 *dst, const R128 *a, const R128 *b) +{ +#if defined(_M_X64) && !defined(R128_STDC_ONLY) + R128_U64 t0, t1; + R128_U64 lo, hi = 0; + unsigned char carry; + + t0 = _umul128(a->lo, b->lo, &t1); + carry = _addcarry_u64(0, t1, t0 >> 63, &lo); + _addcarry_u64(carry, hi, hi, &hi); + + t0 = _umul128(a->lo, b->hi, &t1); + carry = _addcarry_u64(0, lo, t0, &lo); + _addcarry_u64(carry, hi, t1, &hi); + + t0 = _umul128(a->hi, b->lo, &t1); + carry = _addcarry_u64(0, lo, t0, &lo); + _addcarry_u64(carry, hi, t1, &hi); + + t0 = _umul128(a->hi, b->hi, &t1); + hi += t0; + + R128_SET2(dst, lo, hi); +#elif defined(__x86_64__) && !defined(R128_STDC_ONLY) + unsigned __int128 p0, p1, p2, p3; + p0 = a->lo * (unsigned __int128)b->lo; + p1 = a->lo * (unsigned __int128)b->hi; + p2 = a->hi * (unsigned __int128)b->lo; + p3 = a->hi * (unsigned __int128)b->hi; + + p0 = (p3 << 64) + p2 + p1 + (p0 >> 64) + ((R128_U64)p0 >> 63); + dst->lo = (R128_U64)p0; + dst->hi = (R128_U64)(p0 >> 64); +#else + R128 p0, p1, p2, p3, round; + + r128__umul128(&p0, a->lo, b->lo); + round.hi = 0; round.lo = p0.lo >> 63; + p0.lo = p0.hi; p0.hi = 0; //r128Shr(&p0, &p0, 64); + r128Add(&p0, &p0, &round); + + r128__umul128(&p1, a->hi, b->lo); + r128Add(&p0, &p0, &p1); + + r128__umul128(&p2, a->lo, b->hi); + r128Add(&p0, &p0, &p2); + + r128__umul128(&p3, a->hi, b->hi); + p3.hi = p3.lo; p3.lo = 0; //r128Shl(&p3, &p3, 64); + r128Add(&p0, &p0, &p3); + + R128_SET2(dst, p0.lo, p0.hi); +#endif +} + +// Shift d left until the high bit is set, and shift n left by the same amount. +// returns non-zero on overflow. +static int r128__norm(R128 *n, R128 *d, R128_U64 *n2) +{ + R128_U64 d0, d1; + R128_U64 n0, n1; + int shift; + + d1 = d->hi; + d0 = d->lo; + n1 = n->hi; + n0 = n->lo; + + if (d1) { + shift = r128__clz64(d1); + if (shift) { + d1 = (d1 << shift) | (d0 >> (64 - shift)); + d0 = d0 << shift; + *n2 = n1 >> (64 - shift); + n1 = (n1 << shift) | (n0 >> (64 - shift)); + n0 = n0 << shift; + } else { + *n2 = 0; + } + } else { + shift = r128__clz64(d0); + if (r128__clz64(n1) <= shift) { + return 1; // overflow + } + + if (shift) { + d1 = d0 << shift; + d0 = 0; + *n2 = (n1 << shift) | (n0 >> (64 - shift)); + n1 = n0 << shift; + n0 = 0; + } else { + d1 = d0; + d0 = 0; + *n2 = n1; + n1 = n0; + n0 = 0; + } + } + + R128_SET2(n, n0, n1); + R128_SET2(d, d0, d1); + return 0; +} + +static void r128__udiv(R128 *quotient, const R128 *dividend, const R128 *divisor) +{ + R128 tmp; + R128_U64 d0, d1; + R128_U64 n1, n2, n3; + R128 q; + + R128_ASSERT(dividend != NULL); + R128_ASSERT(divisor != NULL); + R128_ASSERT(quotient != NULL); + R128_ASSERT(divisor->hi != 0 || divisor->lo != 0); // divide by zero + + // scale dividend and normalize + { + R128 n, d; + R128_SET2(&n, dividend->lo, dividend->hi); + R128_SET2(&d, divisor->lo, divisor->hi); + if (r128__norm(&n, &d, &n3)) { + R128_SET2(quotient, R128_max.lo, R128_max.hi); + return; + } + + d1 = d.hi; + d0 = d.lo; + n2 = n.hi; + n1 = n.lo; + } + + // first digit + R128_ASSERT(n3 <= d1); + { + R128 t0, t1; + t0.lo = n1; + if (n3 < d1) { + q.hi = r128__udiv128(n2, n3, d1, &t0.hi); + } else { + q.hi = R128_LIT_U64(0xffffffffffffffff); + t0.hi = n2 + d1; + } + +refine1: + r128__umul128(&t1, q.hi, d0); + if (r128__ucmp(&t1, &t0) > 0) { + --q.hi; + if (t0.hi < ~d1 + 1) { + t0.hi += d1; + goto refine1; + } + } + } + + { + R128 t0, t1, t2; + t0.hi = n2; + t0.lo = n1; + + r128__umul128(&t1, q.hi, d0); + r128__umul128(&t2, q.hi, d1); + + t2.hi = t2.lo; t2.lo = 0; //r128Shl(&t2, &t2, 64); + r128Add(&tmp, &t1, &t2); + r128Sub(&tmp, &t0, &tmp); + } + n2 = tmp.hi; + n1 = tmp.lo; + + // second digit + R128_ASSERT(n2 <= d1); + { + R128 t0, t1; + t0.lo = 0; + if (n2 < d1) { + q.lo = r128__udiv128(n1, n2, d1, &t0.hi); + } else { + q.lo = R128_LIT_U64(0xffffffffffffffff); + t0.hi = n1 + d1; + } + + refine0: + r128__umul128(&t1, q.lo, d0); + if (r128__ucmp(&t1, &t0) > 0) { + --q.lo; + if (t0.hi < ~d1 + 1) { + t0.hi += d1; + goto refine0; + } + } + } + + R128_SET2(quotient, q.lo, q.hi); +} + +static R128_U64 r128__umod(R128 *n, R128 *d) +{ + R128_U64 d0, d1; + R128_U64 n3, n2, n1; + R128_U64 q; + + R128_ASSERT(d != NULL); + R128_ASSERT(n != NULL); + R128_ASSERT(d->hi != 0 || d->lo != 0); // divide by zero + + if (r128__norm(n, d, &n3)) { + return R128_LIT_U64(0xffffffffffffffff); + } + + d1 = d->hi; + d0 = d->lo; + n2 = n->hi; + n1 = n->lo; + + R128_ASSERT(n3 < d1); + { + R128 t0, t1; + t0.lo = n1; + q = r128__udiv128(n2, n3, d1, &t0.hi); + + refine1: + r128__umul128(&t1, q, d0); + if (r128__ucmp(&t1, &t0) > 0) { + --q; + if (t0.hi < ~d1 + 1) { + t0.hi += d1; + goto refine1; + } + } + } + + return q; +} + +static int r128__format(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *format) +{ + char buf[128]; + R128 tmp; + R128_U64 whole; + char *cursor, *decimal, *dstp = dst; + int sign = 0; + int fullPrecision = 1; + int width, precision; + int padCnt, trail = 0; + + R128_ASSERT(dst != NULL && dstSize > 0); + R128_ASSERT(v != NULL); + R128_ASSERT(format != NULL); + + --dstSize; + + R128_SET2(&tmp, v->lo, v->hi); + if (r128IsNeg(&tmp)) { + r128__neg(&tmp, &tmp); + sign = 1; + } + + width = format->width; + if (width < 0) { + width = 0; + } + + precision = format->precision; + if (precision < 0) { + // print a maximum of 20 digits + fullPrecision = 0; + precision = 20; + } else if (precision > (int)sizeof(buf) - 21) { + trail = precision - (sizeof(buf) - 21); + precision -= trail; + } + + whole = tmp.hi; + decimal = cursor = buf; + + // fractional part first in case a carry into the whole part is required + if (tmp.lo || format->decimal) { + while (tmp.lo || (fullPrecision && precision)) { + if ((int)(cursor - buf) == precision) { + if ((R128_S64)tmp.lo < 0) { + // round up, propagate carry backwards + char *c; + for (c = cursor - 1; c >= buf; --c) { + char d = ++*c; + if (d <= '9') { + goto endfrac; + } else { + *c = '0'; + } + } + + // carry out into the whole part + whole++; + } + + break; + } + + r128__umul128(&tmp, tmp.lo, 10); + *cursor++ = (char)tmp.hi + '0'; + } + + endfrac: + if (format->decimal || precision) { + decimal = cursor; + *cursor++ = R128_decimal; + } + } + + // whole part + do { + char digit = (char)(whole % 10); + whole /= 10; + *cursor++ = digit + '0'; + } while (whole); + +#define R128__WRITE(c) do { if (dstp < dst + dstSize) *dstp = c; ++dstp; } while(0) + + padCnt = width - (int)(cursor - buf) - 1; + + // left padding + if (!format->leftAlign) { + char padChar = format->zeroPad ? '0' : ' '; + if (format->zeroPad) { + if (sign) { + R128__WRITE('-'); + } else if (format->sign == R128ToStringSign_Plus) { + R128__WRITE('+'); + } else if (format->sign == R128ToStringSign_Space) { + R128__WRITE(' '); + } else { + ++padCnt; + } + } + + for (; padCnt > 0; --padCnt) { + R128__WRITE(padChar); + } + } + + if (format->leftAlign || !format->zeroPad) { + if (sign) { + R128__WRITE('-'); + } else if (format->sign == R128ToStringSign_Plus) { + R128__WRITE('+'); + } else if (format->sign == R128ToStringSign_Space) { + R128__WRITE(' '); + } else { + ++padCnt; + } + } + + { + char *i; + + // reverse the whole part + for (i = cursor - 1; i >= decimal; --i) { + R128__WRITE(*i); + } + + // copy the fractional part + for (i = buf; i < decimal; ++i) { + R128__WRITE(*i); + } + } + + // right padding + if (format->leftAlign) { + char padChar = format->zeroPad ? '0' : ' '; + for (; padCnt > 0; --padCnt) { + R128__WRITE(padChar); + } + } + + // trailing zeroes for very large precision + while (trail--) { + R128__WRITE('0'); + } + +#undef R128__WRITE + + if (dstp <= dst + dstSize) { + *dstp = '\0'; + } else { + dst[dstSize] = '\0'; + } + return (int)(dstp - dst); +} + +void r128FromInt(R128 *dst, R128_S64 v) +{ + R128_ASSERT(dst != NULL); + dst->lo = 0; + dst->hi = (R128_U64)v; + R128_DEBUG_SET(dst); +} + +void r128FromFloat(R128 *dst, double v) +{ + R128_ASSERT(dst != NULL); + + if (v < -9223372036854775808.0) { + r128Copy(dst, &R128_min); + } else if (v >= 9223372036854775808.0) { + r128Copy(dst, &R128_max); + } else { + R128 r; + int sign = 0; + + if (v < 0) { + v = -v; + sign = 1; + } + + r.hi = (R128_U64)(R128_S64)v; + v -= (R128_S64)v; + r.lo = (R128_U64)(v * 18446744073709551616.0); + + if (sign) { + r128__neg(&r, &r); + } + + r128Copy(dst, &r); + } +} + +void r128FromString(R128 *dst, const char *s, char **endptr) +{ + R128_U64 lo = 0, hi = 0; + R128_U64 base = 10; + + int sign = 0; + + R128_ASSERT(dst != NULL); + R128_ASSERT(s != NULL); + + R128_SET2(dst, 0, 0); + + // consume whitespace + for (;;) { + if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' || *s == '\v') { + ++s; + } else { + break; + } + } + + // sign + if (*s == '-') { + sign = 1; + ++s; + } else if (*s == '+') { + ++s; + } + + // parse base prefix + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { + base = 16; + s += 2; + } + + // whole part + for (;; ++s) { + R128_U64 digit; + + if ('0' <= *s && *s <= '9') { + digit = *s - '0'; + } else if (base == 16 && 'a' <= *s && *s <= 'f') { + digit = *s - 'a' + 10; + } else if (base == 16 && 'A' <= *s && *s <= 'F') { + digit = *s - 'A' + 10; + } else { + break; + } + + hi = hi * base + digit; + } + + // fractional part + if (*s == R128_decimal) { + const char *exp = ++s; + + // find the last digit and work backwards + for (;; ++s) { + if ('0' <= *s && *s <= '9') { + } else if (base == 16 && ('a' <= *s && *s <= 'f')) { + } else if (base == 16 && ('A' <= *s && *s <= 'F')) { + } else { + break; + } + } + + for (--s; s >= exp; --s) { + R128_U64 digit, unused; + + if ('0' <= *s && *s <= '9') { + digit = *s - '0'; + } else if ('a' <= *s && *s <= 'f') { + digit = *s - 'a' + 10; + } else { + digit = *s - 'A' + 10; + } + + lo = r128__udiv128(lo, digit, base, &unused); + } + } + + R128_SET2(dst, lo, hi); + if (sign) { + r128__neg(dst, dst); + } + + if (endptr) { + *endptr = (char *) s; + } +} + +R128_S64 r128ToInt(const R128 *v) +{ + R128_ASSERT(v != NULL); + return (R128_S64)v->hi; +} + +double r128ToFloat(const R128 *v) +{ + R128 tmp; + int sign = 0; + double d; + + R128_ASSERT(v != NULL); + + R128_SET2(&tmp, v->lo, v->hi); + if (r128IsNeg(&tmp)) { + r128__neg(&tmp, &tmp); + sign = 1; + } + + d = tmp.hi + tmp.lo * (1 / 18446744073709551616.0); + if (sign) { + d = -d; + } + + return d; +} + +int r128ToStringOpt(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *opt) +{ + return r128__format(dst, dstSize, v, opt); +} + +int r128ToStringf(char *dst, size_t dstSize, const char *format, const R128 *v) +{ + R128ToStringFormat opts; + + R128_ASSERT(dst != NULL && dstSize); + R128_ASSERT(format != NULL); + R128_ASSERT(v != NULL); + + opts.sign = R128__defaultFormat.sign; + opts.precision = R128__defaultFormat.precision; + opts.zeroPad = R128__defaultFormat.zeroPad; + opts.decimal = R128__defaultFormat.decimal; + opts.leftAlign = R128__defaultFormat.leftAlign; + + if (*format == '%') { + ++format; + } + + // flags field + for (;; ++format) { + if (*format == ' ' && opts.sign != R128ToStringSign_Plus) { + opts.sign = R128ToStringSign_Space; + } else if (*format == '+') { + opts.sign = R128ToStringSign_Plus; + } else if (*format == '0') { + opts.zeroPad = 1; + } else if (*format == '-') { + opts.leftAlign = 1; + } else if (*format == '#') { + opts.decimal = 1; + } else { + break; + } + } + + // width field + opts.width = 0; + for (;;) { + if ('0' <= *format && *format <= '9') { + opts.width = opts.width * 10 + *format++ - '0'; + } else { + break; + } + } + + // precision field + if (*format == '.') { + opts.precision = 0; + ++format; + for (;;) { + if ('0' <= *format && *format <= '9') { + opts.precision = opts.precision * 10 + *format++ - '0'; + } else { + break; + } + } + } + + return r128__format(dst, dstSize, v, &opts); +} + +int r128ToString(char *dst, size_t dstSize, const R128 *v) +{ + return r128__format(dst, dstSize, v, &R128__defaultFormat); +} + +void r128Copy(R128 *dst, const R128 *src) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(src != NULL); + dst->lo = src->lo; + dst->hi = src->hi; + R128_DEBUG_SET(dst); +} + +void r128Neg(R128 *dst, const R128 *src) +{ + r128__neg(dst, src); + R128_DEBUG_SET(dst); +} + +void r128Not(R128 *dst, const R128 *src) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(src != NULL); + + dst->lo = ~src->lo; + dst->hi = ~src->hi; + R128_DEBUG_SET(dst); +} + +void r128Or(R128 *dst, const R128 *a, const R128 *b) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + dst->lo = a->lo | b->lo; + dst->hi = a->hi | b->hi; + R128_DEBUG_SET(dst); +} + +void r128And(R128 *dst, const R128 *a, const R128 *b) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + dst->lo = a->lo & b->lo; + dst->hi = a->hi & b->hi; + R128_DEBUG_SET(dst); +} + +void r128Xor(R128 *dst, const R128 *a, const R128 *b) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + dst->lo = a->lo ^ b->lo; + dst->hi = a->hi ^ b->hi; + R128_DEBUG_SET(dst); +} + +void r128Shl(R128 *dst, const R128 *src, int amount) +{ + R128_U64 r[4]; + + R128_ASSERT(dst != NULL); + R128_ASSERT(src != NULL); + +#if defined(_M_IX86) && !defined(R128_STDC_ONLY) + __asm { + // load src + mov edx, dword ptr[src] + mov ecx, amount + + mov edi, dword ptr[edx] + mov esi, dword ptr[edx + 4] + mov ebx, dword ptr[edx + 8] + mov eax, dword ptr[edx + 12] + + // shift mod 32 + shld eax, ebx, cl + shld ebx, esi, cl + shld esi, edi, cl + shl edi, cl + + // clear out low 12 bytes of stack + xor edx, edx + mov dword ptr[r], edx + mov dword ptr[r + 4], edx + mov dword ptr[r + 8], edx + + // store shifted amount offset by count/32 bits + shr ecx, 5 + and ecx, 3 + mov dword ptr[r + ecx * 4 + 0], edi + mov dword ptr[r + ecx * 4 + 4], esi + mov dword ptr[r + ecx * 4 + 8], ebx + mov dword ptr[r + ecx * 4 + 12], eax + } +#else + + r[0] = src->lo; + r[1] = src->hi; + + amount &= 127; + if (amount >= 64) { + r[1] = r[0] << (amount - 64); + r[0] = 0; + } else if (amount) { +# ifdef _M_X64 + r[1] = __shiftleft128(r[0], r[1], (char) amount); +# else + r[1] = (r[1] << amount) | (r[0] >> (64 - amount)); +# endif + r[0] = r[0] << amount; + } +#endif //_M_IX86 + + dst->lo = r[0]; + dst->hi = r[1]; + R128_DEBUG_SET(dst); +} + +void r128Shr(R128 *dst, const R128 *src, int amount) +{ + R128_U64 r[4]; + + R128_ASSERT(dst != NULL); + R128_ASSERT(src != NULL); + +#if defined(_M_IX86) && !defined(R128_STDC_ONLY) + __asm { + // load src + mov edx, dword ptr[src] + mov ecx, amount + + mov edi, dword ptr[edx] + mov esi, dword ptr[edx + 4] + mov ebx, dword ptr[edx + 8] + mov eax, dword ptr[edx + 12] + + // shift mod 32 + shrd edi, esi, cl + shrd esi, ebx, cl + shrd ebx, eax, cl + shr eax, cl + + // clear out high 12 bytes of stack + xor edx, edx + mov dword ptr[r + 20], edx + mov dword ptr[r + 24], edx + mov dword ptr[r + 28], edx + + // store shifted amount offset by -count/32 bits + shr ecx, 5 + and ecx, 3 + neg ecx + mov dword ptr[r + ecx * 4 + 16], edi + mov dword ptr[r + ecx * 4 + 20], esi + mov dword ptr[r + ecx * 4 + 24], ebx + mov dword ptr[r + ecx * 4 + 28], eax + } +#else + r[2] = src->lo; + r[3] = src->hi; + + amount &= 127; + if (amount >= 64) { + r[2] = r[3] >> (amount - 64); + r[3] = 0; + } else if (amount) { +#ifdef _M_X64 + r[2] = __shiftright128(r[2], r[3], (char) amount); +#else + r[2] = (r[2] >> amount) | (r[3] << (64 - amount)); +#endif + r[3] = r[3] >> amount; + } +#endif + + dst->lo = r[2]; + dst->hi = r[3]; + R128_DEBUG_SET(dst); +} + +void r128Sar(R128 *dst, const R128 *src, int amount) +{ + R128_U64 r[4]; + + R128_ASSERT(dst != NULL); + R128_ASSERT(src != NULL); + +#if defined(_M_IX86) && !defined(R128_STDC_ONLY) + __asm { + // load src + mov edx, dword ptr[src] + mov ecx, amount + + mov edi, dword ptr[edx] + mov esi, dword ptr[edx + 4] + mov ebx, dword ptr[edx + 8] + mov eax, dword ptr[edx + 12] + + // shift mod 32 + shrd edi, esi, cl + shrd esi, ebx, cl + shrd ebx, eax, cl + sar eax, cl + + // copy sign to high 12 bytes of stack + cdq + mov dword ptr[r + 20], edx + mov dword ptr[r + 24], edx + mov dword ptr[r + 28], edx + + // store shifted amount offset by -count/32 bits + shr ecx, 5 + and ecx, 3 + neg ecx + mov dword ptr[r + ecx * 4 + 16], edi + mov dword ptr[r + ecx * 4 + 20], esi + mov dword ptr[r + ecx * 4 + 24], ebx + mov dword ptr[r + ecx * 4 + 28], eax + } +#else + r[2] = src->lo; + r[3] = src->hi; + + amount &= 127; + if (amount >= 64) { + r[2] = (R128_U64)((R128_S64)r[3] >> (amount - 64)); + r[3] = (R128_U64)((R128_S64)r[3] >> 63); + } else if (amount) { + r[2] = (r[2] >> amount) | (R128_U64)((R128_S64)r[3] << (64 - amount)); + r[3] = (R128_U64)((R128_S64)r[3] >> amount); + } +#endif + + dst->lo = r[2]; + dst->hi = r[3]; + R128_DEBUG_SET(dst); +} + +void r128Add(R128 *dst, const R128 *a, const R128 *b) +{ + unsigned char carry = 0; + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + +#if R128_INTEL && !defined(R128_STDC_ONLY) +# if R128_64BIT + carry = _addcarry_u64(carry, a->lo, b->lo, &dst->lo); + carry = _addcarry_u64(carry, a->hi, b->hi, &dst->hi); +# else + R128_U32 r0, r1, r2, r3; + carry = _addcarry_u32(carry, R128_R0(a), R128_R0(b), &r0); + carry = _addcarry_u32(carry, R128_R1(a), R128_R1(b), &r1); + carry = _addcarry_u32(carry, R128_R2(a), R128_R2(b), &r2); + carry = _addcarry_u32(carry, R128_R3(a), R128_R3(b), &r3); + R128_SET4(dst, r0, r1, r2, r3); +# endif //R128_64BIT +#else + { + R128_U64 r = a->lo + b->lo; + carry = r < a->lo; + dst->lo = r; + dst->hi = a->hi + b->hi + carry; + } +#endif //R128_INTEL + + R128_DEBUG_SET(dst); +} + +void r128Sub(R128 *dst, const R128 *a, const R128 *b) +{ + unsigned char borrow = 0; + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + +#if R128_INTEL && !defined(R128_STDC_ONLY) +# if R128_64BIT + borrow = _subborrow_u64(borrow, a->lo, b->lo, &dst->lo); + borrow = _subborrow_u64(borrow, a->hi, b->hi, &dst->hi); +# else + R128_U32 r0, r1, r2, r3; + borrow = _subborrow_u32(borrow, R128_R0(a), R128_R0(b), &r0); + borrow = _subborrow_u32(borrow, R128_R1(a), R128_R1(b), &r1); + borrow = _subborrow_u32(borrow, R128_R2(a), R128_R2(b), &r2); + borrow = _subborrow_u32(borrow, R128_R3(a), R128_R3(b), &r3); + R128_SET4(dst, r0, r1, r2, r3); +# endif //R128_64BIT +#else + { + R128_U64 r = a->lo - b->lo; + borrow = r > a->lo; + dst->lo = r; + dst->hi = a->hi - b->hi - borrow; + } +#endif //R128_INTEL + + R128_DEBUG_SET(dst); +} + +void r128Mul(R128 *dst, const R128 *a, const R128 *b) +{ + int sign = 0; + R128 ta, tb, tc; + + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + R128_SET2(&ta, a->lo, a->hi); + R128_SET2(&tb, b->lo, b->hi); + + if (r128IsNeg(&ta)) { + r128__neg(&ta, &ta); + sign = !sign; + } + if (r128IsNeg(&tb)) { + r128__neg(&tb, &tb); + sign = !sign; + } + + r128__umul(&tc, &ta, &tb); + if (sign) { + r128__neg(&tc, &tc); + } + + r128Copy(dst, &tc); +} + +void r128Div(R128 *dst, const R128 *a, const R128 *b) +{ + int sign = 0; + R128 tn, td, tq; + + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + R128_SET2(&tn, a->lo, a->hi); + R128_SET2(&td, b->lo, b->hi); + + if (r128IsNeg(&tn)) { + r128__neg(&tn, &tn); + sign = !sign; + } + + if (td.lo == 0 && td.hi == 0) { + // divide by zero + if (sign) { + r128Copy(dst, &R128_min); + } else { + r128Copy(dst, &R128_max); + } + return; + } else if (r128IsNeg(&td)) { + r128__neg(&td, &td); + sign = !sign; + } + + r128__udiv(&tq, &tn, &td); + + if (sign) { + r128__neg(&tq, &tq); + } + + r128Copy(dst, &tq); +} + +void r128Mod(R128 *dst, const R128 *a, const R128 *b) +{ + int sign = 0; + R128 tn, td, tq; + + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + R128_SET2(&tn, a->lo, a->hi); + R128_SET2(&td, b->lo, b->hi); + + if (r128IsNeg(&tn)) { + r128__neg(&tn, &tn); + sign = !sign; + } + + if (td.lo == 0 && td.hi == 0) { + // divide by zero + if (sign) { + r128Copy(dst, &R128_min); + } else { + r128Copy(dst, &R128_max); + } + return; + } else if (r128IsNeg(&td)) { + r128__neg(&td, &td); + sign = !sign; + } + + tq.hi = r128__umod(&tn, &td); + tq.lo = 0; + + if (sign) { + tq.hi = ~tq.hi + 1; + } + + r128Mul(&tq, &tq, b); + r128Sub(dst, a, &tq); +} + +void r128Rsqrt(R128 *dst, const R128 *v) +{ + static const R128 threeHalves = { R128_LIT_U64(0x8000000000000000), 1 }; + R128 x, est; + int i; + + if ((R128_S64)v->hi < 0) { + r128Copy(dst, &R128_min); + return; + } + + R128_SET2(&x, v->lo, v->hi); + + // get initial estimate + if (x.hi) { + int shift = (64 + r128__clz64(x.hi)) >> 1; + est.lo = R128_LIT_U64(1) << shift; + est.hi = 0; + } else if (x.lo) { + int shift = r128__clz64(x.lo) >> 1; + est.hi = R128_LIT_U64(1) << shift; + est.lo = 0; + } else { + R128_SET2(dst, 0, 0); + return; + } + + // x /= 2 + r128Shr(&x, &x, 1); + + // Newton-Raphson iterate + for (i = 0; i < 7; ++i) { + R128 newEst; + + // newEst = est * (threeHalves - (x / 2) * est * est); + r128__umul(&newEst, &est, &est); + r128__umul(&newEst, &newEst, &x); + r128Sub(&newEst, &threeHalves, &newEst); + r128__umul(&newEst, &est, &newEst); + + if (newEst.lo == est.lo && newEst.hi == est.hi) { + break; + } + R128_SET2(&est, newEst.lo, newEst.hi); + } + + r128Copy(dst, &est); +} + +void r128Sqrt(R128 *dst, const R128 *v) +{ + R128 x, est; + int i; + + if ((R128_S64)v->hi < 0) { + r128Copy(dst, &R128_min); + return; + } + + R128_SET2(&x, v->lo, v->hi); + + // get initial estimate + if (x.hi) { + int shift = (63 - r128__clz64(x.hi)) >> 1; + r128Shr(&est, &x, shift); + } else if (x.lo) { + int shift = (1 + r128__clz64(x.lo)) >> 1; + r128Shl(&est, &x, shift); + } else { + R128_SET2(dst, 0, 0); + return; + } + + // Newton-Raphson iterate + for (i = 0; i < 7; ++i) { + R128 newEst; + + // newEst = (est + x / est) / 2 + r128__udiv(&newEst, &x, &est); + r128Add(&newEst, &newEst, &est); + r128Shr(&newEst, &newEst, 1); + + if (newEst.lo == est.lo && newEst.hi == est.hi) { + break; + } + R128_SET2(&est, newEst.lo, newEst.hi); + } + + r128Copy(dst, &est); +} + +int r128Cmp(const R128 *a, const R128 *b) +{ + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + if (a->hi == b->hi) { + if (a->lo == b->lo) { + return 0; + } else if (a->lo > b->lo) { + return 1; + } else { + return -1; + } + } else if ((R128_S64)a->hi > (R128_S64)b->hi) { + return 1; + } else { + return -1; + } +} + +int r128IsNeg(const R128 *v) +{ + R128_ASSERT(v != NULL); + + return (R128_S64)v->hi < 0; +} + +void r128Min(R128 *dst, const R128 *a, const R128 *b) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + if (r128Cmp(a, b) < 0) { + r128Copy(dst, a); + } else { + r128Copy(dst, b); + } +} + +void r128Max(R128 *dst, const R128 *a, const R128 *b) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(a != NULL); + R128_ASSERT(b != NULL); + + if (r128Cmp(a, b) > 0) { + r128Copy(dst, a); + } else { + r128Copy(dst, b); + } +} + +void r128Floor(R128 *dst, const R128 *v) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(v != NULL); + + if ((R128_S64)v->hi < 0) { + dst->hi = v->hi - (v->lo != 0); + } else { + dst->hi = v->hi; + } + dst->lo = 0; + R128_DEBUG_SET(dst); +} + +void r128Ceil(R128 *dst, const R128 *v) +{ + R128_ASSERT(dst != NULL); + R128_ASSERT(v != NULL); + + if ((R128_S64)v->hi > 0) { + dst->hi = v->hi + (v->lo != 0); + } else { + dst->hi = v->hi; + } + dst->lo = 0; + R128_DEBUG_SET(dst); +} + +#endif //R128_IMPLEMENTATION + diff --git a/thirdparty/stb_rect_pack/stb_rect_pack.h b/thirdparty/stb_rect_pack/stb_rect_pack.h new file mode 100644 index 0000000000..3336fe7395 --- /dev/null +++ b/thirdparty/stb_rect_pack/stb_rect_pack.h @@ -0,0 +1,629 @@ +// stb_rect_pack.h - v1.00 - public domain - rectangle packing +// Sean Barrett 2014 +// +// Useful for e.g. packing rectangular textures into an atlas. +// Does not do rotation. +// +// Not necessarily the awesomest packing method, but better than +// the totally naive one in stb_truetype (which is primarily what +// this is meant to replace). +// +// Has only had a few tests run, may have issues. +// +// More docs to come. +// +// No memory allocations; uses qsort() and assert() from stdlib. +// Can override those by defining STBRP_SORT and STBRP_ASSERT. +// +// This library currently uses the Skyline Bottom-Left algorithm. +// +// Please note: better rectangle packers are welcome! Please +// implement them to the same API, but with a different init +// function. +// +// Credits +// +// Library +// Sean Barrett +// Minor features +// Martins Mozeiko +// github:IntellectualKitty +// +// Bugfixes / warning fixes +// Jeremy Jaussaud +// Fabian Giesen +// +// Version history: +// +// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles +// 0.99 (2019-02-07) warning fixes +// 0.11 (2017-03-03) return packing success/fail result +// 0.10 (2016-10-25) remove cast-away-const to avoid warnings +// 0.09 (2016-08-27) fix compiler warnings +// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) +// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) +// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort +// 0.05: added STBRP_ASSERT to allow replacing assert +// 0.04: fixed minor bug in STBRP_LARGE_RECTS support +// 0.01: initial release +// +// LICENSE +// +// See end of file for license information. + +////////////////////////////////////////////////////////////////////////////// +// +// INCLUDE SECTION +// + +#ifndef STB_INCLUDE_STB_RECT_PACK_H +#define STB_INCLUDE_STB_RECT_PACK_H + +#define STB_RECT_PACK_VERSION 1 + +#ifdef STBRP_STATIC +#define STBRP_DEF static +#else +#define STBRP_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stbrp_context stbrp_context; +typedef struct stbrp_node stbrp_node; +typedef struct stbrp_rect stbrp_rect; + +#ifdef STBRP_LARGE_RECTS +typedef int stbrp_coord; +#else +typedef unsigned short stbrp_coord; +#endif + +STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); +// Assign packed locations to rectangles. The rectangles are of type +// 'stbrp_rect' defined below, stored in the array 'rects', and there +// are 'num_rects' many of them. +// +// Rectangles which are successfully packed have the 'was_packed' flag +// set to a non-zero value and 'x' and 'y' store the minimum location +// on each axis (i.e. bottom-left in cartesian coordinates, top-left +// if you imagine y increasing downwards). Rectangles which do not fit +// have the 'was_packed' flag set to 0. +// +// You should not try to access the 'rects' array from another thread +// while this function is running, as the function temporarily reorders +// the array while it executes. +// +// To pack into another rectangle, you need to call stbrp_init_target +// again. To continue packing into the same rectangle, you can call +// this function again. Calling this multiple times with multiple rect +// arrays will probably produce worse packing results than calling it +// a single time with the full rectangle array, but the option is +// available. +// +// The function returns 1 if all of the rectangles were successfully +// packed and 0 otherwise. + +struct stbrp_rect +{ + // reserved for your use: + int id; + + // input: + stbrp_coord w, h; + + // output: + stbrp_coord x, y; + int was_packed; // non-zero if valid packing + +}; // 16 bytes, nominally + + +STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); +// Initialize a rectangle packer to: +// pack a rectangle that is 'width' by 'height' in dimensions +// using temporary storage provided by the array 'nodes', which is 'num_nodes' long +// +// You must call this function every time you start packing into a new target. +// +// There is no "shutdown" function. The 'nodes' memory must stay valid for +// the following stbrp_pack_rects() call (or calls), but can be freed after +// the call (or calls) finish. +// +// Note: to guarantee best results, either: +// 1. make sure 'num_nodes' >= 'width' +// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' +// +// If you don't do either of the above things, widths will be quantized to multiples +// of small integers to guarantee the algorithm doesn't run out of temporary storage. +// +// If you do #2, then the non-quantized algorithm will be used, but the algorithm +// may run out of temporary storage and be unable to pack some rectangles. + +STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); +// Optionally call this function after init but before doing any packing to +// change the handling of the out-of-temp-memory scenario, described above. +// If you call init again, this will be reset to the default (false). + + +STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); +// Optionally select which packing heuristic the library should use. Different +// heuristics will produce better/worse results for different data sets. +// If you call init again, this will be reset to the default. + +enum +{ + STBRP_HEURISTIC_Skyline_default=0, + STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, + STBRP_HEURISTIC_Skyline_BF_sortHeight +}; + + +////////////////////////////////////////////////////////////////////////////// +// +// the details of the following structures don't matter to you, but they must +// be visible so you can handle the memory allocations for them + +struct stbrp_node +{ + stbrp_coord x,y; + stbrp_node *next; +}; + +struct stbrp_context +{ + int width; + int height; + int align; + int init_mode; + int heuristic; + int num_nodes; + stbrp_node *active_head; + stbrp_node *free_head; + stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' +}; + +#ifdef __cplusplus +} +#endif + +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// IMPLEMENTATION SECTION +// + +#ifdef STB_RECT_PACK_IMPLEMENTATION +#ifndef STBRP_SORT +#include +#define STBRP_SORT qsort +#endif + +#ifndef STBRP_ASSERT +#include +#define STBRP_ASSERT assert +#endif + +#ifdef _MSC_VER +#define STBRP__NOTUSED(v) (void)(v) +#else +#define STBRP__NOTUSED(v) (void)sizeof(v) +#endif + +enum +{ + STBRP__INIT_skyline = 1 +}; + +STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) +{ + switch (context->init_mode) { + case STBRP__INIT_skyline: + STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); + context->heuristic = heuristic; + break; + default: + STBRP_ASSERT(0); + } +} + +STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) +{ + if (allow_out_of_mem) + // if it's ok to run out of memory, then don't bother aligning them; + // this gives better packing, but may fail due to OOM (even though + // the rectangles easily fit). @TODO a smarter approach would be to only + // quantize once we've hit OOM, then we could get rid of this parameter. + context->align = 1; + else { + // if it's not ok to run out of memory, then quantize the widths + // so that num_nodes is always enough nodes. + // + // I.e. num_nodes * align >= width + // align >= width / num_nodes + // align = ceil(width/num_nodes) + + context->align = (context->width + context->num_nodes-1) / context->num_nodes; + } +} + +STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) +{ + int i; +#ifndef STBRP_LARGE_RECTS + STBRP_ASSERT(width <= 0xffff && height <= 0xffff); +#endif + + for (i=0; i < num_nodes-1; ++i) + nodes[i].next = &nodes[i+1]; + nodes[i].next = NULL; + context->init_mode = STBRP__INIT_skyline; + context->heuristic = STBRP_HEURISTIC_Skyline_default; + context->free_head = &nodes[0]; + context->active_head = &context->extra[0]; + context->width = width; + context->height = height; + context->num_nodes = num_nodes; + stbrp_setup_allow_out_of_mem(context, 0); + + // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) + context->extra[0].x = 0; + context->extra[0].y = 0; + context->extra[0].next = &context->extra[1]; + context->extra[1].x = (stbrp_coord) width; +#ifdef STBRP_LARGE_RECTS + context->extra[1].y = (1<<30); +#else + context->extra[1].y = 65535; +#endif + context->extra[1].next = NULL; +} + +// find minimum y position if it starts at x1 +static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) +{ + stbrp_node *node = first; + int x1 = x0 + width; + int min_y, visited_width, waste_area; + + STBRP__NOTUSED(c); + + STBRP_ASSERT(first->x <= x0); + + #if 0 + // skip in case we're past the node + while (node->next->x <= x0) + ++node; + #else + STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency + #endif + + STBRP_ASSERT(node->x <= x0); + + min_y = 0; + waste_area = 0; + visited_width = 0; + while (node->x < x1) { + if (node->y > min_y) { + // raise min_y higher. + // we've accounted for all waste up to min_y, + // but we'll now add more waste for everything we've visted + waste_area += visited_width * (node->y - min_y); + min_y = node->y; + // the first time through, visited_width might be reduced + if (node->x < x0) + visited_width += node->next->x - x0; + else + visited_width += node->next->x - node->x; + } else { + // add waste area + int under_width = node->next->x - node->x; + if (under_width + visited_width > width) + under_width = width - visited_width; + waste_area += under_width * (min_y - node->y); + visited_width += under_width; + } + node = node->next; + } + + *pwaste = waste_area; + return min_y; +} + +typedef struct +{ + int x,y; + stbrp_node **prev_link; +} stbrp__findresult; + +static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) +{ + int best_waste = (1<<30), best_x, best_y = (1 << 30); + stbrp__findresult fr; + stbrp_node **prev, *node, *tail, **best = NULL; + + // align to multiple of c->align + width = (width + c->align - 1); + width -= width % c->align; + STBRP_ASSERT(width % c->align == 0); + + // if it can't possibly fit, bail immediately + if (width > c->width || height > c->height) { + fr.prev_link = NULL; + fr.x = fr.y = 0; + return fr; + } + + node = c->active_head; + prev = &c->active_head; + while (node->x + width <= c->width) { + int y,waste; + y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); + if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL + // bottom left + if (y < best_y) { + best_y = y; + best = prev; + } + } else { + // best-fit + if (y + height <= c->height) { + // can only use it if it first vertically + if (y < best_y || (y == best_y && waste < best_waste)) { + best_y = y; + best_waste = waste; + best = prev; + } + } + } + prev = &node->next; + node = node->next; + } + + best_x = (best == NULL) ? 0 : (*best)->x; + + // if doing best-fit (BF), we also have to try aligning right edge to each node position + // + // e.g, if fitting + // + // ____________________ + // |____________________| + // + // into + // + // | | + // | ____________| + // |____________| + // + // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned + // + // This makes BF take about 2x the time + + if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { + tail = c->active_head; + node = c->active_head; + prev = &c->active_head; + // find first node that's admissible + while (tail->x < width) + tail = tail->next; + while (tail) { + int xpos = tail->x - width; + int y,waste; + STBRP_ASSERT(xpos >= 0); + // find the left position that matches this + while (node->next->x <= xpos) { + prev = &node->next; + node = node->next; + } + STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); + y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); + if (y + height <= c->height) { + if (y <= best_y) { + if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { + best_x = xpos; + STBRP_ASSERT(y <= best_y); + best_y = y; + best_waste = waste; + best = prev; + } + } + } + tail = tail->next; + } + } + + fr.prev_link = best; + fr.x = best_x; + fr.y = best_y; + return fr; +} + +static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) +{ + // find best position according to heuristic + stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); + stbrp_node *node, *cur; + + // bail if: + // 1. it failed + // 2. the best node doesn't fit (we don't always check this) + // 3. we're out of memory + if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { + res.prev_link = NULL; + return res; + } + + // on success, create new node + node = context->free_head; + node->x = (stbrp_coord) res.x; + node->y = (stbrp_coord) (res.y + height); + + context->free_head = node->next; + + // insert the new node into the right starting point, and + // let 'cur' point to the remaining nodes needing to be + // stiched back in + + cur = *res.prev_link; + if (cur->x < res.x) { + // preserve the existing one, so start testing with the next one + stbrp_node *next = cur->next; + cur->next = node; + cur = next; + } else { + *res.prev_link = node; + } + + // from here, traverse cur and free the nodes, until we get to one + // that shouldn't be freed + while (cur->next && cur->next->x <= res.x + width) { + stbrp_node *next = cur->next; + // move the current node to the free list + cur->next = context->free_head; + context->free_head = cur; + cur = next; + } + + // stitch the list back in + node->next = cur; + + if (cur->x < res.x + width) + cur->x = (stbrp_coord) (res.x + width); + +#ifdef _DEBUG + cur = context->active_head; + while (cur->x < context->width) { + STBRP_ASSERT(cur->x < cur->next->x); + cur = cur->next; + } + STBRP_ASSERT(cur->next == NULL); + + { + int count=0; + cur = context->active_head; + while (cur) { + cur = cur->next; + ++count; + } + cur = context->free_head; + while (cur) { + cur = cur->next; + ++count; + } + STBRP_ASSERT(count == context->num_nodes+2); + } +#endif + + return res; +} + +static int rect_height_compare(const void *a, const void *b) +{ + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; + if (p->h > q->h) + return -1; + if (p->h < q->h) + return 1; + return (p->w > q->w) ? -1 : (p->w < q->w); +} + +static int rect_original_order(const void *a, const void *b) +{ + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; + return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); +} + +#ifdef STBRP_LARGE_RECTS +#define STBRP__MAXVAL 0xffffffff +#else +#define STBRP__MAXVAL 0xffff +#endif + +STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) +{ + int i, all_rects_packed = 1; + + // we use the 'was_packed' field internally to allow sorting/unsorting + for (i=0; i < num_rects; ++i) { + rects[i].was_packed = i; + } + + // sort according to heuristic + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); + + for (i=0; i < num_rects; ++i) { + if (rects[i].w == 0 || rects[i].h == 0) { + rects[i].x = rects[i].y = 0; // empty rect needs no space + } else { + stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); + if (fr.prev_link) { + rects[i].x = (stbrp_coord) fr.x; + rects[i].y = (stbrp_coord) fr.y; + } else { + rects[i].x = rects[i].y = STBRP__MAXVAL; + } + } + } + + // unsort + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); + + // set was_packed flags and all_rects_packed status + for (i=0; i < num_rects; ++i) { + rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + if (!rects[i].was_packed) + all_rects_packed = 0; + } + + // return the all_rects_packed status + return all_rects_packed; +} +#endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ + diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp index 80cacf9746..b1cbeb980f 100644 --- a/thirdparty/xatlas/xatlas.cpp +++ b/thirdparty/xatlas/xatlas.cpp @@ -33,19 +33,19 @@ https://github.com/brandonpelfrey/Fast-BVH MIT License Copyright (c) 2012 Brandon Pelfrey */ -#include -#include -#include -#include #include #include // FLT_MAX #include #include +#include +#include +#include +#include #define __STDC_LIMIT_MACROS +#include "xatlas.h" #include #include #include -#include "xatlas.h" #ifndef XA_DEBUG #ifdef NDEBUG @@ -70,7 +70,10 @@ Copyright (c) 2012 Brandon Pelfrey #define XA_XSTR(x) XA_STR(x) #ifndef XA_ASSERT -#define XA_ASSERT(exp) if (!(exp)) { XA_PRINT_WARNING("\rASSERT: %s %s %d\n", XA_XSTR(exp), __FILE__, __LINE__); } +#define XA_ASSERT(exp) \ + if (!(exp)) { \ + XA_PRINT_WARNING("\rASSERT: %s %s %d\n", XA_XSTR(exp), __FILE__, __LINE__); \ + } #endif #ifndef XA_DEBUG_ASSERT @@ -78,13 +81,13 @@ Copyright (c) 2012 Brandon Pelfrey #endif #ifndef XA_PRINT -#define XA_PRINT(...) \ +#define XA_PRINT(...) \ if (xatlas::internal::s_print && xatlas::internal::s_printVerbose) \ xatlas::internal::s_print(__VA_ARGS__); #endif #ifndef XA_PRINT_WARNING -#define XA_PRINT_WARNING(...) \ +#define XA_PRINT_WARNING(...) \ if (xatlas::internal::s_print) \ xatlas::internal::s_print(__VA_ARGS__); #endif @@ -136,19 +139,13 @@ Copyright (c) 2012 Brandon Pelfrey #define XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION 0 #define XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS 0 -#define XA_DEBUG_EXPORT_OBJ (0 \ - || XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES \ - || XA_DEBUG_EXPORT_OBJ_CHART_GROUPS \ - || XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS \ - || XA_DEBUG_EXPORT_OBJ_CHARTS \ - || XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION \ - || XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR \ - || XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION \ - || XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION \ - || XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS) +#define XA_DEBUG_EXPORT_OBJ (0 || XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES || XA_DEBUG_EXPORT_OBJ_CHART_GROUPS || XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS || XA_DEBUG_EXPORT_OBJ_CHARTS || XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION || XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR || XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION || XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION || XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS) #ifdef _MSC_VER -#define XA_FOPEN(_file, _filename, _mode) { if (fopen_s(&_file, _filename, _mode) != 0) _file = NULL; } +#define XA_FOPEN(_file, _filename, _mode) \ + { \ + if (fopen_s(&_file, _filename, _mode) != 0) _file = NULL; \ + } #define XA_SPRINTF(_buffer, _size, _format, ...) sprintf_s(_buffer, _size, _format, __VA_ARGS__) #else #define XA_FOPEN(_file, _filename, _mode) _file = fopen(_filename, _mode) @@ -163,10 +160,8 @@ static FreeFunc s_free = free; static PrintFunc s_print = printf; static bool s_printVerbose = false; -struct MemTag -{ - enum - { +struct MemTag { + enum { Default, BitImage, BVH, @@ -189,8 +184,7 @@ struct MemTag }; #if XA_DEBUG_HEAP -struct AllocHeader -{ +struct AllocHeader { size_t size; const char *file; int line; @@ -203,11 +197,10 @@ struct AllocHeader static std::mutex s_allocMutex; static AllocHeader *s_allocRoot = nullptr; static size_t s_allocTotalCount = 0, s_allocTotalSize = 0, s_allocPeakSize = 0, s_allocCount[MemTag::Count] = { 0 }, s_allocTotalTagSize[MemTag::Count] = { 0 }, s_allocPeakTagSize[MemTag::Count] = { 0 }; -static uint32_t s_allocId =0 ; +static uint32_t s_allocId = 0; static constexpr uint32_t kAllocRedzone = 0x12345678; -static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line) -{ +static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line) { std::unique_lock lock(s_allocMutex); if (!size && !ptr) return nullptr; @@ -268,8 +261,7 @@ static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line return newPtr + sizeof(AllocHeader); } -static void ReportLeaks() -{ +static void ReportLeaks() { printf("Checking for memory leaks...\n"); bool anyLeaks = false; AllocHeader *header = s_allocRoot; @@ -297,8 +289,7 @@ static void ReportLeaks() s_allocTotalTagSize[i] = s_allocPeakTagSize[i] = 0; } -static void PrintMemoryUsage() -{ +static void PrintMemoryUsage() { XA_PRINT("Total allocations: %zu\n", s_allocTotalCount); XA_PRINT("Memory usage: %0.2fMB current, %0.2fMB peak\n", internal::s_allocTotalSize / 1024.0f / 1024.0f, internal::s_allocPeakSize / 1024.0f / 1024.0f); static const char *labels[] = { // Sync with MemTag @@ -327,8 +318,7 @@ static void PrintMemoryUsage() #define XA_PRINT_MEM_USAGE internal::PrintMemoryUsage(); #else -static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, int /*line*/) -{ +static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, int /*line*/) { if (size == 0 && !ptr) return nullptr; if (size == 0 && s_free) { @@ -347,10 +337,11 @@ static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, #if XA_PROFILE #define XA_PROFILE_START(var) const clock_t var##Start = clock(); #define XA_PROFILE_END(var) internal::s_profile.var += clock() - var##Start; -#define XA_PROFILE_PRINT_AND_RESET(label, var) XA_PRINT("%s%.2f seconds (%g ms)\n", label, internal::clockToSeconds(internal::s_profile.var), internal::clockToMs(internal::s_profile.var)); internal::s_profile.var = 0; +#define XA_PROFILE_PRINT_AND_RESET(label, var) \ + XA_PRINT("%s%.2f seconds (%g ms)\n", label, internal::clockToSeconds(internal::s_profile.var), internal::clockToMs(internal::s_profile.var)); \ + internal::s_profile.var = 0; -struct ProfileData -{ +struct ProfileData { clock_t addMeshReal; clock_t addMeshCopyData; std::atomic addMeshThread; @@ -390,13 +381,11 @@ struct ProfileData static ProfileData s_profile; -static double clockToMs(clock_t c) -{ +static double clockToMs(clock_t c) { return c * 1000.0 / CLOCKS_PER_SEC; } -static double clockToSeconds(clock_t c) -{ +static double clockToSeconds(clock_t c) { return c / (double)CLOCKS_PER_SEC; } #else @@ -412,89 +401,75 @@ static constexpr float kEpsilon = 0.0001f; static constexpr float kAreaEpsilon = FLT_EPSILON; static constexpr float kNormalEpsilon = 0.001f; -static int align(int x, int a) -{ +static int align(int x, int a) { return (x + a - 1) & ~(a - 1); } template -static T max(const T &a, const T &b) -{ +static T max(const T &a, const T &b) { return a > b ? a : b; } template -static T min(const T &a, const T &b) -{ +static T min(const T &a, const T &b) { return a < b ? a : b; } template -static T max3(const T &a, const T &b, const T &c) -{ +static T max3(const T &a, const T &b, const T &c) { return max(a, max(b, c)); } /// Return the maximum of the three arguments. template -static T min3(const T &a, const T &b, const T &c) -{ +static T min3(const T &a, const T &b, const T &c) { return min(a, min(b, c)); } /// Clamp between two values. template -static T clamp(const T &x, const T &a, const T &b) -{ +static T clamp(const T &x, const T &a, const T &b) { return min(max(x, a), b); } template -static void swap(T &a, T &b) -{ +static void swap(T &a, T &b) { T temp = a; a = b; b = temp; } -union FloatUint32 -{ +union FloatUint32 { float f; uint32_t u; }; -static bool isFinite(float f) -{ +static bool isFinite(float f) { FloatUint32 fu; fu.f = f; return fu.u != 0x7F800000u && fu.u != 0x7F800001u; } -static bool isNan(float f) -{ +static bool isNan(float f) { return f != f; } // Robust floating point comparisons: // http://realtimecollisiondetection.net/blog/?p=89 -static bool equal(const float f0, const float f1, const float epsilon) -{ +static bool equal(const float f0, const float f1, const float epsilon) { //return fabs(f0-f1) <= epsilon; return fabs(f0 - f1) <= epsilon * max3(1.0f, fabsf(f0), fabsf(f1)); } -static int ftoi_ceil(float val) -{ +static int ftoi_ceil(float val) { return (int)ceilf(val); } -static bool isZero(const float f, const float epsilon) -{ +static bool isZero(const float f, const float epsilon) { return fabs(f) <= epsilon; } -static float square(float f) -{ +static float square(float f) { return f * f; } @@ -504,9 +479,8 @@ static float square(float f) * @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x * @note nextPowerOfTwo(x) = 2 << log2(x-1) */ -static uint32_t nextPowerOfTwo(uint32_t x) -{ - XA_DEBUG_ASSERT( x != 0 ); +static uint32_t nextPowerOfTwo(uint32_t x) { + XA_DEBUG_ASSERT(x != 0); // On modern CPUs this is supposed to be as fast as using the bsr instruction. x--; x |= x >> 1; @@ -517,65 +491,59 @@ static uint32_t nextPowerOfTwo(uint32_t x) return x + 1; } -static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381) -{ - const uint8_t *data = (const uint8_t *) data_in; +static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381) { + const uint8_t *data = (const uint8_t *)data_in; uint32_t i = 0; while (i < size) { - h = (h << 16) + (h << 6) - h + (uint32_t ) data[i++]; + h = (h << 16) + (h << 6) - h + (uint32_t)data[i++]; } return h; } template -static uint32_t hash(const T &t, uint32_t h = 5381) -{ +static uint32_t hash(const T &t, uint32_t h = 5381) { return sdbmHash(&t, sizeof(T), h); } // Functors for hash table: -template struct Hash -{ +template +struct Hash { uint32_t operator()(const Key &k) const { return hash(k); } }; -template struct Equal -{ +template +struct Equal { bool operator()(const Key &k0, const Key &k1) const { return k0 == k1; } }; -class Vector2 -{ +class Vector2 { public: Vector2() {} - explicit Vector2(float f) : x(f), y(f) {} - Vector2(float x, float y): x(x), y(y) {} + explicit Vector2(float f) : + x(f), y(f) {} + Vector2(float x, float y) : + x(x), y(y) {} - Vector2 operator-() const - { + Vector2 operator-() const { return Vector2(-x, -y); } - void operator+=(const Vector2 &v) - { + void operator+=(const Vector2 &v) { x += v.x; y += v.y; } - void operator-=(const Vector2 &v) - { + void operator-=(const Vector2 &v) { x -= v.x; y -= v.y; } - void operator*=(float s) - { + void operator*=(float s) { x *= s; y *= s; } - void operator*=(const Vector2 &v) - { + void operator*=(const Vector2 &v) { x *= v.x; y *= v.y; } @@ -583,13 +551,11 @@ public: float x, y; }; -static bool operator==(const Vector2 &a, const Vector2 &b) -{ +static bool operator==(const Vector2 &a, const Vector2 &b) { return a.x == b.x && a.y == b.y; } -static bool operator!=(const Vector2 &a, const Vector2 &b) -{ +static bool operator!=(const Vector2 &a, const Vector2 &b) { return a.x != b.x || a.y != b.y; } @@ -598,40 +564,33 @@ static bool operator!=(const Vector2 &a, const Vector2 &b) return Vector2(a.x + b.x, a.y + b.y); }*/ -static Vector2 operator-(const Vector2 &a, const Vector2 &b) -{ +static Vector2 operator-(const Vector2 &a, const Vector2 &b) { return Vector2(a.x - b.x, a.y - b.y); } -static Vector2 operator*(const Vector2 &v, float s) -{ +static Vector2 operator*(const Vector2 &v, float s) { return Vector2(v.x * s, v.y * s); } -static float dot(const Vector2 &a, const Vector2 &b) -{ +static float dot(const Vector2 &a, const Vector2 &b) { return a.x * b.x + a.y * b.y; } -static float lengthSquared(const Vector2 &v) -{ +static float lengthSquared(const Vector2 &v) { return v.x * v.x + v.y * v.y; } -static float length(const Vector2 &v) -{ +static float length(const Vector2 &v) { return sqrtf(lengthSquared(v)); } #if XA_DEBUG -static bool isNormalized(const Vector2 &v, float epsilon = kNormalEpsilon) -{ +static bool isNormalized(const Vector2 &v, float epsilon = kNormalEpsilon) { return equal(length(v), 1, epsilon); } #endif -static Vector2 normalize(const Vector2 &v, float epsilon) -{ +static Vector2 normalize(const Vector2 &v, float epsilon) { float l = length(v); XA_DEBUG_ASSERT(!isZero(l, epsilon)); XA_UNUSED(epsilon); @@ -640,36 +599,30 @@ static Vector2 normalize(const Vector2 &v, float epsilon) return n; } -static Vector2 normalizeSafe(const Vector2 &v, const Vector2 &fallback, float epsilon) -{ +static Vector2 normalizeSafe(const Vector2 &v, const Vector2 &fallback, float epsilon) { float l = length(v); if (isZero(l, epsilon)) return fallback; return v * (1.0f / l); } -static bool equal(const Vector2 &v1, const Vector2 &v2, float epsilon) -{ +static bool equal(const Vector2 &v1, const Vector2 &v2, float epsilon) { return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon); } -static Vector2 min(const Vector2 &a, const Vector2 &b) -{ +static Vector2 min(const Vector2 &a, const Vector2 &b) { return Vector2(min(a.x, b.x), min(a.y, b.y)); } -static Vector2 max(const Vector2 &a, const Vector2 &b) -{ +static Vector2 max(const Vector2 &a, const Vector2 &b) { return Vector2(max(a.x, b.x), max(a.y, b.y)); } -static bool isFinite(const Vector2 &v) -{ +static bool isFinite(const Vector2 &v) { return isFinite(v.x) && isFinite(v.y); } -static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c) -{ +static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c) { // IC: While it may be appealing to use the following expression: //return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y) * 0.5f; // That's actually a terrible idea. Small triangles far from the origin can end up producing fairly large floating point @@ -683,8 +636,7 @@ static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c) return (v0.x * v1.y - v0.y * v1.x) * 0.5f; } -static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &b1, const Vector2 &b2, float epsilon) -{ +static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &b1, const Vector2 &b2, float epsilon) { const Vector2 v0 = a2 - a1; const Vector2 v1 = b2 - b1; const float denom = -v1.x * v0.y + v0.x * v1.y; @@ -692,76 +644,70 @@ static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 & return false; const float s = (-v0.y * (a1.x - b1.x) + v0.x * (a1.y - b1.y)) / denom; if (s > epsilon && s < 1.0f - epsilon) { - const float t = ( v1.x * (a1.y - b1.y) - v1.y * (a1.x - b1.x)) / denom; + const float t = (v1.x * (a1.y - b1.y) - v1.y * (a1.x - b1.x)) / denom; return t > epsilon && t < 1.0f - epsilon; } return false; } -struct Vector2i -{ +struct Vector2i { Vector2i() {} - Vector2i(int32_t x, int32_t y) : x(x), y(y) {} + Vector2i(int32_t x, int32_t y) : + x(x), y(y) {} int32_t x, y; }; -class Vector3 -{ +class Vector3 { public: Vector3() {} - explicit Vector3(float f) : x(f), y(f), z(f) {} - Vector3(float x, float y, float z) : x(x), y(y), z(z) {} - Vector3(const Vector2 &v, float z) : x(v.x), y(v.y), z(z) {} + explicit Vector3(float f) : + x(f), y(f), z(f) {} + Vector3(float x, float y, float z) : + x(x), y(y), z(z) {} + Vector3(const Vector2 &v, float z) : + x(v.x), y(v.y), z(z) {} - Vector2 xy() const - { + Vector2 xy() const { return Vector2(x, y); } - Vector3 operator-() const - { + Vector3 operator-() const { return Vector3(-x, -y, -z); } - void operator+=(const Vector3 &v) - { + void operator+=(const Vector3 &v) { x += v.x; y += v.y; z += v.z; } - void operator-=(const Vector3 &v) - { + void operator-=(const Vector3 &v) { x -= v.x; y -= v.y; z -= v.z; } - void operator*=(float s) - { + void operator*=(float s) { x *= s; y *= s; z *= s; } - void operator/=(float s) - { + void operator/=(float s) { float is = 1.0f / s; x *= is; y *= is; z *= is; } - void operator*=(const Vector3 &v) - { + void operator*=(const Vector3 &v) { x *= v.x; y *= v.y; z *= v.z; } - void operator/=(const Vector3 &v) - { + void operator/=(const Vector3 &v) { x /= v.x; y /= v.y; z /= v.z; @@ -770,53 +716,43 @@ public: float x, y, z; }; -static Vector3 operator+(const Vector3 &a, const Vector3 &b) -{ +static Vector3 operator+(const Vector3 &a, const Vector3 &b) { return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); } -static Vector3 operator-(const Vector3 &a, const Vector3 &b) -{ +static Vector3 operator-(const Vector3 &a, const Vector3 &b) { return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); } -static Vector3 cross(const Vector3 &a, const Vector3 &b) -{ +static Vector3 cross(const Vector3 &a, const Vector3 &b) { return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); } -static Vector3 operator*(const Vector3 &v, float s) -{ +static Vector3 operator*(const Vector3 &v, float s) { return Vector3(v.x * s, v.y * s, v.z * s); } -static Vector3 operator/(const Vector3 &v, float s) -{ +static Vector3 operator/(const Vector3 &v, float s) { return v * (1.0f / s); } -static float dot(const Vector3 &a, const Vector3 &b) -{ +static float dot(const Vector3 &a, const Vector3 &b) { return a.x * b.x + a.y * b.y + a.z * b.z; } -static float lengthSquared(const Vector3 &v) -{ +static float lengthSquared(const Vector3 &v) { return v.x * v.x + v.y * v.y + v.z * v.z; } -static float length(const Vector3 &v) -{ +static float length(const Vector3 &v) { return sqrtf(lengthSquared(v)); } -static bool isNormalized(const Vector3 &v, float epsilon = kNormalEpsilon) -{ +static bool isNormalized(const Vector3 &v, float epsilon = kNormalEpsilon) { return equal(length(v), 1, epsilon); } -static Vector3 normalize(const Vector3 &v, float epsilon) -{ +static Vector3 normalize(const Vector3 &v, float epsilon) { float l = length(v); XA_DEBUG_ASSERT(!isZero(l, epsilon)); XA_UNUSED(epsilon); @@ -825,8 +761,7 @@ static Vector3 normalize(const Vector3 &v, float epsilon) return n; } -static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float epsilon) -{ +static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float epsilon) { float l = length(v); if (isZero(l, epsilon)) { return fallback; @@ -834,72 +769,59 @@ static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float ep return v * (1.0f / l); } -static bool equal(const Vector3 &v0, const Vector3 &v1, float epsilon) -{ +static bool equal(const Vector3 &v0, const Vector3 &v1, float epsilon) { return fabs(v0.x - v1.x) <= epsilon && fabs(v0.y - v1.y) <= epsilon && fabs(v0.z - v1.z) <= epsilon; } -static Vector3 min(const Vector3 &a, const Vector3 &b) -{ +static Vector3 min(const Vector3 &a, const Vector3 &b) { return Vector3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); } -static Vector3 max(const Vector3 &a, const Vector3 &b) -{ +static Vector3 max(const Vector3 &a, const Vector3 &b) { return Vector3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); } #if XA_DEBUG -bool isFinite(const Vector3 &v) -{ +bool isFinite(const Vector3 &v) { return isFinite(v.x) && isFinite(v.y) && isFinite(v.z); } #endif -struct Extents2 -{ +struct Extents2 { Vector2 min, max; - void reset() - { + void reset() { min.x = min.y = FLT_MAX; max.x = max.y = -FLT_MAX; } - void add(Vector2 p) - { + void add(Vector2 p) { min = xatlas::internal::min(min, p); max = xatlas::internal::max(max, p); } - Vector2 midpoint() const - { + Vector2 midpoint() const { return Vector2(min.x + (max.x - min.x) * 0.5f, min.y + (max.y - min.y) * 0.5f); } - static bool intersect(Extents2 e1, Extents2 e2) - { + static bool intersect(Extents2 e1, Extents2 e2) { return e1.min.x <= e2.max.x && e1.max.x >= e2.min.x && e1.min.y <= e2.max.y && e1.max.y >= e2.min.y; } }; -struct Plane -{ +struct Plane { Plane() = default; - - Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) - { + + Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) { normal = cross(p2 - p1, p3 - p1); dist = dot(normal, p1); } - float distance(const Vector3 &p) const - { + float distance(const Vector3 &p) const { return dot(normal, p) - dist; } - void normalize() - { + void normalize() { const float len = length(normal); if (len > 0.0f) { const float il = 1.0f / len; @@ -912,8 +834,7 @@ struct Plane float dist; }; -static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart, const Vector3 &lineEnd, float *t, float epsilon) -{ +static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart, const Vector3 &lineEnd, float *t, float epsilon) { float tt; if (!t) t = &tt; @@ -930,22 +851,19 @@ static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart, return *t > kEpsilon && *t < 1.0f - kEpsilon; } -static bool sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b) -{ +static bool sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b) { const Vector3 &ab = b - a; return dot(cross(ab, p1 - a), cross(ab, p2 - a)) >= 0.0f; } // http://blackpawn.com/texts/pointinpoly/default.html -static bool pointInTriangle(const Vector3 &p, const Vector3 &a, const Vector3 &b, const Vector3 &c) -{ +static bool pointInTriangle(const Vector3 &p, const Vector3 &a, const Vector3 &b, const Vector3 &c) { return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b); } #if XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm -static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDir, const Vector3 *tri, float *t) -{ +static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDir, const Vector3 *tri, float *t) { *t = 0.0f; const Vector3 &edge1 = tri[1] - tri[0]; const Vector3 &edge2 = tri[2] - tri[0]; @@ -972,50 +890,47 @@ static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDi #endif // From Fast-BVH -struct AABB -{ - AABB() : min(FLT_MAX, FLT_MAX, FLT_MAX), max(-FLT_MAX, -FLT_MAX, -FLT_MAX) {} - AABB(const Vector3 &min, const Vector3 &max) : min(min), max(max) { } - AABB(const Vector3 &p, float radius = 0.0f) : min(p), max(p) { if (radius > 0.0f) expand(radius); } +struct AABB { + AABB() : + min(FLT_MAX, FLT_MAX, FLT_MAX), max(-FLT_MAX, -FLT_MAX, -FLT_MAX) {} + AABB(const Vector3 &min, const Vector3 &max) : + min(min), max(max) {} + AABB(const Vector3 &p, float radius = 0.0f) : + min(p), max(p) { + if (radius > 0.0f) expand(radius); + } - bool intersect(const AABB &other) const - { + bool intersect(const AABB &other) const { return min.x <= other.max.x && max.x >= other.min.x && min.y <= other.max.y && max.y >= other.min.y && min.z <= other.max.z && max.z >= other.min.z; } - void expandToInclude(const Vector3 &p) - { + void expandToInclude(const Vector3 &p) { min = internal::min(min, p); max = internal::max(max, p); } - void expandToInclude(const AABB &aabb) - { + void expandToInclude(const AABB &aabb) { min = internal::min(min, aabb.min); max = internal::max(max, aabb.max); } - void expand(float amount) - { + void expand(float amount) { min -= Vector3(amount); max += Vector3(amount); } - Vector3 centroid() const - { + Vector3 centroid() const { return min + (max - min) * 0.5f; } - uint32_t maxDimension() const - { + uint32_t maxDimension() const { const Vector3 extent = max - min; uint32_t result = 0; if (extent.y > extent.x) { result = 1; if (extent.z > extent.y) result = 2; - } - else if(extent.z > extent.x) + } else if (extent.z > extent.x) result = 2; return result; } @@ -1023,10 +938,9 @@ struct AABB Vector3 min, max; }; -struct ArrayBase -{ - ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) : buffer(nullptr), elementSize(elementSize), size(0), capacity(0) - { +struct ArrayBase { + ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) : + buffer(nullptr), elementSize(elementSize), size(0), capacity(0) { #if XA_DEBUG_HEAP this->memTag = memTag; #else @@ -1034,31 +948,26 @@ struct ArrayBase #endif } - ~ArrayBase() - { + ~ArrayBase() { XA_FREE(buffer); } - XA_INLINE void clear() - { + XA_INLINE void clear() { size = 0; } - void copyFrom(const uint8_t *data, uint32_t length) - { + void copyFrom(const uint8_t *data, uint32_t length) { resize(length, true); memcpy(buffer, data, length * elementSize); } - void copyTo(ArrayBase &other) const - { + void copyTo(ArrayBase &other) const { XA_DEBUG_ASSERT(elementSize == other.elementSize); other.resize(size, true); memcpy(other.buffer, buffer, size * elementSize); } - void destroy() - { + void destroy() { size = 0; XA_FREE(buffer); buffer = nullptr; @@ -1067,8 +976,7 @@ struct ArrayBase } // Insert the given element at the given index shifting all the elements up. - void insertAt(uint32_t index, const uint8_t *value) - { + void insertAt(uint32_t index, const uint8_t *value) { XA_DEBUG_ASSERT(index >= 0 && index <= size); resize(size + 1, false); if (index < size - 1) @@ -1076,8 +984,7 @@ struct ArrayBase memcpy(&buffer[index * elementSize], value, elementSize); } - void moveTo(ArrayBase &other) - { + void moveTo(ArrayBase &other) { XA_DEBUG_ASSERT(elementSize == other.elementSize); other.destroy(); other.buffer = buffer; @@ -1091,21 +998,18 @@ struct ArrayBase elementSize = size = capacity = 0; } - void pop_back() - { + void pop_back() { XA_DEBUG_ASSERT(size > 0); resize(size - 1, false); } - void push_back(const uint8_t *value) - { + void push_back(const uint8_t *value) { XA_DEBUG_ASSERT(value < buffer || value >= buffer + size); resize(size + 1, false); memcpy(&buffer[(size - 1) * elementSize], value, elementSize); } - void push_back(const ArrayBase &other) - { + void push_back(const ArrayBase &other) { XA_DEBUG_ASSERT(elementSize == other.elementSize); if (other.size == 0) return; @@ -1115,22 +1019,19 @@ struct ArrayBase } // Remove the element at the given index. This is an expensive operation! - void removeAt(uint32_t index) - { + void removeAt(uint32_t index) { XA_DEBUG_ASSERT(index >= 0 && index < size); if (size != 1) memmove(buffer + elementSize * index, buffer + elementSize * (index + 1), elementSize * (size - 1 - index)); size--; } - void reserve(uint32_t desiredSize) - { + void reserve(uint32_t desiredSize) { if (desiredSize > capacity) setArrayCapacity(desiredSize); } - void resize(uint32_t newSize, bool exact) - { + void resize(uint32_t newSize, bool exact) { size = newSize; if (size > capacity) { // First allocation is always exact. Otherwise, following allocations grow array to 150% of desired size. @@ -1143,8 +1044,7 @@ struct ArrayBase } } - void setArrayCapacity(uint32_t newCapacity) - { + void setArrayCapacity(uint32_t newCapacity) { XA_DEBUG_ASSERT(newCapacity >= size); if (newCapacity == 0) { // free the buffer. @@ -1164,8 +1064,7 @@ struct ArrayBase } #if XA_DEBUG_HEAP - void setMemTag(int memTag) - { + void setMemTag(int memTag) { this->memTag = memTag; } #endif @@ -1179,28 +1078,25 @@ struct ArrayBase #endif }; -template -class Array -{ +template +class Array { public: - Array(int memTag = MemTag::Default) : m_base(sizeof(T), memTag) {} - Array(const Array&) = delete; + Array(int memTag = MemTag::Default) : + m_base(sizeof(T), memTag) {} + Array(const Array &) = delete; Array &operator=(const Array &) = delete; - XA_INLINE const T &operator[](uint32_t index) const - { + XA_INLINE const T &operator[](uint32_t index) const { XA_DEBUG_ASSERT(index < m_base.size); return ((const T *)m_base.buffer)[index]; } - XA_INLINE T &operator[](uint32_t index) - { + XA_INLINE T &operator[](uint32_t index) { XA_DEBUG_ASSERT(index < m_base.size); return ((T *)m_base.buffer)[index]; } - XA_INLINE const T &back() const - { + XA_INLINE const T &back() const { XA_DEBUG_ASSERT(!isEmpty()); return ((const T *)m_base.buffer)[m_base.size - 1]; } @@ -1208,8 +1104,7 @@ public: XA_INLINE T *begin() { return (T *)m_base.buffer; } XA_INLINE void clear() { m_base.clear(); } - bool contains(const T &value) const - { + bool contains(const T &value) const { for (uint32_t i = 0; i < m_base.size; i++) { if (((const T *)m_base.buffer)[i] == value) return true; @@ -1232,20 +1127,17 @@ public: void reserve(uint32_t desiredSize) { m_base.reserve(desiredSize); } void resize(uint32_t newSize) { m_base.resize(newSize, true); } - void runCtors() - { + void runCtors() { for (uint32_t i = 0; i < m_base.size; i++) new (&((T *)m_base.buffer)[i]) T; } - void runDtors() - { + void runDtors() { for (uint32_t i = 0; i < m_base.size; i++) ((T *)m_base.buffer)[i].~T(); } - void setAll(const T &value) - { + void setAll(const T &value) { auto buffer = (T *)m_base.buffer; for (uint32_t i = 0; i < m_base.size; i++) buffer[i] = value; @@ -1262,33 +1154,47 @@ private: ArrayBase m_base; }; -template -struct ArrayView -{ - ArrayView(Array &a) : data(a.data()), length(a.size()) {} - ArrayView(T *data, uint32_t length) : data(data), length(length) {} - ArrayView &operator=(Array &a) { data = a.data(); length = a.size(); return *this; } - XA_INLINE const T &operator[](uint32_t index) const { XA_DEBUG_ASSERT(index < length); return data[index]; } +template +struct ArrayView { + ArrayView(Array &a) : + data(a.data()), length(a.size()) {} + ArrayView(T *data, uint32_t length) : + data(data), length(length) {} + ArrayView &operator=(Array &a) { + data = a.data(); + length = a.size(); + return *this; + } + XA_INLINE const T &operator[](uint32_t index) const { + XA_DEBUG_ASSERT(index < length); + return data[index]; + } T *data; uint32_t length; }; -template -struct ConstArrayView -{ - ConstArrayView(const Array &a) : data(a.data()), length(a.size()) {} - ConstArrayView(const T *data, uint32_t length) : data(data), length(length) {} - ConstArrayView &operator=(const Array &a) { data = a.data(); length = a.size(); return *this; } - XA_INLINE const T &operator[](uint32_t index) const { XA_DEBUG_ASSERT(index < length); return data[index]; } +template +struct ConstArrayView { + ConstArrayView(const Array &a) : + data(a.data()), length(a.size()) {} + ConstArrayView(const T *data, uint32_t length) : + data(data), length(length) {} + ConstArrayView &operator=(const Array &a) { + data = a.data(); + length = a.size(); + return *this; + } + XA_INLINE const T &operator[](uint32_t index) const { + XA_DEBUG_ASSERT(index < length); + return data[index]; + } const T *data; uint32_t length; }; /// Basis class to compute tangent space basis, ortogonalizations and to transform vectors from one space to another. -struct Basis -{ - XA_NODISCARD static Vector3 computeTangent(const Vector3 &normal) - { +struct Basis { + XA_NODISCARD static Vector3 computeTangent(const Vector3 &normal) { XA_ASSERT(isNormalized(normal)); // Choose minimum axis. Vector3 tangent; @@ -1304,8 +1210,7 @@ struct Basis return tangent; } - XA_NODISCARD static Vector3 computeBitangent(const Vector3 &normal, const Vector3 &tangent) - { + XA_NODISCARD static Vector3 computeBitangent(const Vector3 &normal, const Vector3 &tangent) { return cross(normal, tangent); } @@ -1315,36 +1220,31 @@ struct Basis }; // Simple bit array. -class BitArray -{ +class BitArray { public: - BitArray() : m_size(0) {} + BitArray() : + m_size(0) {} - BitArray(uint32_t sz) - { + BitArray(uint32_t sz) { resize(sz); } - void resize(uint32_t new_size) - { + void resize(uint32_t new_size) { m_size = new_size; m_wordArray.resize((m_size + 31) >> 5); } - bool get(uint32_t index) const - { + bool get(uint32_t index) const { XA_DEBUG_ASSERT(index < m_size); return (m_wordArray[index >> 5] & (1 << (index & 31))) != 0; } - void set(uint32_t index) - { + void set(uint32_t index) { XA_DEBUG_ASSERT(index < m_size); - m_wordArray[index >> 5] |= (1 << (index & 31)); + m_wordArray[index >> 5] |= (1 << (index & 31)); } - void zeroOutMemory() - { + void zeroOutMemory() { m_wordArray.zeroOutMemory(); } @@ -1353,13 +1253,13 @@ private: Array m_wordArray; }; -class BitImage -{ +class BitImage { public: - BitImage() : m_width(0), m_height(0), m_rowStride(0), m_data(MemTag::BitImage) {} + BitImage() : + m_width(0), m_height(0), m_rowStride(0), m_data(MemTag::BitImage) {} - BitImage(uint32_t w, uint32_t h) : m_width(w), m_height(h), m_data(MemTag::BitImage) - { + BitImage(uint32_t w, uint32_t h) : + m_width(w), m_height(h), m_data(MemTag::BitImage) { m_rowStride = (m_width + 63) >> 6; m_data.resize(m_rowStride * m_height); m_data.zeroOutMemory(); @@ -1370,16 +1270,14 @@ public: uint32_t width() const { return m_width; } uint32_t height() const { return m_height; } - void copyTo(BitImage &other) - { + void copyTo(BitImage &other) { other.m_width = m_width; other.m_height = m_height; other.m_rowStride = m_rowStride; m_data.copyTo(other.m_data); } - void resize(uint32_t w, uint32_t h, bool discard) - { + void resize(uint32_t w, uint32_t h, bool discard) { const uint32_t rowStride = (w + 63) >> 6; if (discard) { m_data.resize(rowStride * h); @@ -1403,28 +1301,24 @@ public: m_rowStride = rowStride; } - bool get(uint32_t x, uint32_t y) const - { + bool get(uint32_t x, uint32_t y) const { XA_DEBUG_ASSERT(x < m_width && y < m_height); const uint32_t index = (x >> 6) + y * m_rowStride; return (m_data[index] & (UINT64_C(1) << (uint64_t(x) & UINT64_C(63)))) != 0; } - void set(uint32_t x, uint32_t y) - { + void set(uint32_t x, uint32_t y) { XA_DEBUG_ASSERT(x < m_width && y < m_height); const uint32_t index = (x >> 6) + y * m_rowStride; m_data[index] |= UINT64_C(1) << (uint64_t(x) & UINT64_C(63)); XA_DEBUG_ASSERT(get(x, y)); } - void zeroOutMemory() - { + void zeroOutMemory() { m_data.zeroOutMemory(); } - bool canBlit(const BitImage &image, uint32_t offsetX, uint32_t offsetY) const - { + bool canBlit(const BitImage &image, uint32_t offsetX, uint32_t offsetY) const { for (uint32_t y = 0; y < image.m_height; y++) { const uint32_t thisY = y + offsetY; if (thisY >= m_height) @@ -1448,8 +1342,7 @@ public: return true; } - void dilate(uint32_t padding) - { + void dilate(uint32_t padding) { BitImage tmp(m_width, m_height); for (uint32_t p = 0; p < padding; p++) { tmp.zeroOutMemory(); @@ -1486,11 +1379,10 @@ private: }; // From Fast-BVH -class BVH -{ +class BVH { public: - BVH(const Array &objectAabbs, uint32_t leafSize = 4) : m_objectIds(MemTag::BVH), m_nodes(MemTag::BVH) - { + BVH(const Array &objectAabbs, uint32_t leafSize = 4) : + m_objectIds(MemTag::BVH), m_nodes(MemTag::BVH) { m_objectAabbs = &objectAabbs; if (m_objectAabbs->isEmpty()) return; @@ -1510,7 +1402,7 @@ public: Node node; m_nodes.reserve(objectAabbs.size() * 2); uint32_t nNodes = 0; - while(stackptr > 0) { + while (stackptr > 0) { // Pop the next item off of the stack const BuildEntry &bnode = todo[--stackptr]; const uint32_t start = bnode.start; @@ -1523,7 +1415,7 @@ public: // Calculate the bounding box for this node AABB bb(objectAabbs[m_objectIds[start]]); AABB bc(objectAabbs[m_objectIds[start]].centroid()); - for(uint32_t p = start + 1; p < end; ++p) { + for (uint32_t p = start + 1; p < end; ++p) { bb.expandToInclude(objectAabbs[m_objectIds[p]]); bc.expandToInclude(objectAabbs[m_objectIds[p]].centroid()); } @@ -1539,7 +1431,7 @@ public: m_nodes[bnode.parent].rightOffset--; // When this is the second touch, this is the right child. // The right child sets up the offset for the flat tree. - if (m_nodes[bnode.parent].rightOffset == kTouchedTwice ) + if (m_nodes[bnode.parent].rightOffset == kTouchedTwice) m_nodes[bnode.parent].rightOffset = nNodes - 1 - bnode.parent; } // If this is a leaf, no need to subdivide. @@ -1574,21 +1466,20 @@ public: } } - void query(const AABB &queryAabb, Array &result) const - { + void query(const AABB &queryAabb, Array &result) const { result.clear(); // Working set uint32_t todo[64]; int32_t stackptr = 0; // "Push" on the root node to the working set todo[stackptr] = 0; - while(stackptr >= 0) { + while (stackptr >= 0) { // Pop off the next node to work on. const int ni = todo[stackptr--]; const Node &node = m_nodes[ni]; // Is leaf -> Intersect if (node.rightOffset == 0) { - for(uint32_t o = 0; o < node.nPrims; ++o) { + for (uint32_t o = 0; o < node.nPrims; ++o) { const uint32_t obj = node.start + o; if (queryAabb.intersect((*m_objectAabbs)[m_objectIds[obj]])) result.push_back(m_objectIds[obj]); @@ -1605,14 +1496,12 @@ public: } private: - struct BuildEntry - { + struct BuildEntry { uint32_t parent; // If non-zero then this is the index of the parent. (used in offsets) uint32_t start, end; // The range of objects in the object list covered by this node. }; - struct Node - { + struct Node { AABB aabb; uint32_t start, nPrims, rightOffset; }; @@ -1622,10 +1511,8 @@ private: Array m_nodes; }; -struct Fit -{ - static bool computeBasis(const Vector3 *points, uint32_t pointsCount, Basis *basis) - { +struct Fit { + static bool computeBasis(const Vector3 *points, uint32_t pointsCount, Basis *basis) { if (computeLeastSquaresNormal(points, pointsCount, &basis->normal)) { basis->tangent = Basis::computeTangent(basis->normal); basis->bitangent = Basis::computeBitangent(basis->normal, basis->tangent); @@ -1639,8 +1526,7 @@ private: // Fast, and accurate to within a few degrees. // Returns None if the points do not span a plane. // https://www.ilikebigbits.com/2015_03_04_plane_from_points.html - static bool computeLeastSquaresNormal(const Vector3 *points, uint32_t pointsCount, Vector3 *normal) - { + static bool computeLeastSquaresNormal(const Vector3 *points, uint32_t pointsCount, Vector3 *normal) { XA_DEBUG_ASSERT(pointsCount >= 3); if (pointsCount == 3) { *normal = normalize(cross(points[2] - points[0], points[1] - points[0]), kEpsilon); @@ -1705,7 +1591,7 @@ private: // Pick path with best conditioning: Vector3 dir(0.0f); if (det_max == det_x) - dir = Vector3(det_x,xz * yz - xy * zz,xy * yz - xz * yy); + dir = Vector3(det_x, xz * yz - xy * zz, xy * yz - xz * yy); else if (det_max == det_y) dir = Vector3(xz * yz - xy * zz, det_y, xy * xz - yz * xx); else if (det_max == det_z) @@ -1718,8 +1604,7 @@ private: return isNormalized(*normal); } - static bool computeEigen(const Vector3 *points, uint32_t pointsCount, Basis *basis) - { + static bool computeEigen(const Vector3 *points, uint32_t pointsCount, Basis *basis) { float matrix[6]; computeCovariance(pointsCount, points, matrix); if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0) @@ -1734,8 +1619,7 @@ private: return true; } - static Vector3 computeCentroid(int n, const Vector3 * points) - { + static Vector3 computeCentroid(int n, const Vector3 *points) { Vector3 centroid(0.0f); for (int i = 0; i < n; i++) { centroid += points[i]; @@ -1744,8 +1628,7 @@ private: return centroid; } - static Vector3 computeCovariance(int n, const Vector3 * points, float * covariance) - { + static Vector3 computeCovariance(int n, const Vector3 *points, float *covariance) { // compute the centroid Vector3 centroid = computeCentroid(n, points); // compute covariance matrix @@ -1767,8 +1650,7 @@ private: // Tridiagonal solver from Charles Bloom. // Householder transforms followed by QL decomposition. // Seems to be based on the code from Numerical Recipes in C. - static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3]) - { + static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3]) { XA_DEBUG_ASSERT(matrix != nullptr && eigenValues != nullptr && eigenVectors != nullptr); float subd[3]; float diag[3]; @@ -1793,7 +1675,7 @@ private: // eigenvectors are the columns; make them the rows : for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - (&eigenVectors[j].x)[i] = (float) work[i][j]; + (&eigenVectors[j].x)[i] = (float)work[i][j]; } } // shuffle to sort by singular value : @@ -1815,8 +1697,7 @@ private: } private: - static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd) - { + static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd) { // Householder reduction T = Q^t M Q // Input: // mat, symmetric 3x3 matrix M @@ -1868,8 +1749,7 @@ private: } } - static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd) - { + static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd) { // QL iteration with implicit shifting to reduce matrix from tridiagonal // to diagonal const int maxiter = 32; @@ -1879,21 +1759,21 @@ private: int m; for (m = ell; m <= 1; m++) { float dd = fabsf(diag[m]) + fabsf(diag[m + 1]); - if ( fabsf(subd[m]) + dd == dd ) + if (fabsf(subd[m]) + dd == dd) break; } - if ( m == ell ) + if (m == ell) break; float g = (diag[ell + 1] - diag[ell]) / (2 * subd[ell]); float r = sqrtf(g * g + 1); - if ( g < 0 ) + if (g < 0) g = diag[m] - diag[ell] + subd[ell] / (g - r); else g = diag[m] - diag[ell] + subd[ell] / (g + r); float s = 1, c = 1, p = 0; for (int i = m - 1; i >= ell; i--) { float f = s * subd[i], b = c * subd[i]; - if ( fabsf(f) >= fabsf(g) ) { + if (fabsf(f) >= fabsf(g)) { c = g / f; r = sqrtf(c * c + 1); subd[i + 1] = f * r; @@ -1919,7 +1799,7 @@ private: subd[ell] = g; subd[m] = 0; } - if ( iter == maxiter ) + if (iter == maxiter) // should not get here under normal circumstances return false; } @@ -1928,18 +1808,18 @@ private: }; /// Fixed size vector class. -class FullVector -{ +class FullVector { public: - FullVector(uint32_t dim) : m_array(MemTag::FullVector) { m_array.resize(dim); } - FullVector(const FullVector &v) : m_array(MemTag::FullVector) { v.m_array.copyTo(m_array); } + FullVector(uint32_t dim) : + m_array(MemTag::FullVector) { m_array.resize(dim); } + FullVector(const FullVector &v) : + m_array(MemTag::FullVector) { v.m_array.copyTo(m_array); } FullVector &operator=(const FullVector &v) = delete; XA_INLINE uint32_t dimension() const { return m_array.size(); } XA_INLINE const float &operator[](uint32_t index) const { return m_array[index]; } XA_INLINE float &operator[](uint32_t index) { return m_array[index]; } - void fill(float f) - { + void fill(float f) { const uint32_t dim = dimension(); for (uint32_t i = 0; i < dim; i++) m_array[i] = f; @@ -1949,22 +1829,19 @@ private: Array m_array; }; -template, typename E = Equal > -class HashMap -{ +template , typename E = Equal> +class HashMap { public: - HashMap(int memTag, uint32_t size) : m_memTag(memTag), m_size(size), m_numSlots(0), m_slots(nullptr), m_keys(memTag), m_next(memTag) - { + HashMap(int memTag, uint32_t size) : + m_memTag(memTag), m_size(size), m_numSlots(0), m_slots(nullptr), m_keys(memTag), m_next(memTag) { } - ~HashMap() - { + ~HashMap() { if (m_slots) XA_FREE(m_slots); } - void add(const Key &key) - { + void add(const Key &key) { if (!m_slots) alloc(); const uint32_t hash = computeHash(key); @@ -1973,8 +1850,7 @@ public: m_slots[hash] = m_next.size() - 1; } - uint32_t get(const Key &key) const - { + uint32_t get(const Key &key) const { if (!m_slots) return UINT32_MAX; const uint32_t hash = computeHash(key); @@ -1988,8 +1864,7 @@ public: return UINT32_MAX; } - uint32_t getNext(uint32_t current) const - { + uint32_t getNext(uint32_t current) const { uint32_t i = m_next[current]; E equal; while (i != UINT32_MAX) { @@ -2001,8 +1876,7 @@ public: } private: - void alloc() - { + void alloc() { XA_DEBUG_ASSERT(m_size > 0); m_numSlots = nextPowerOfTwo(m_size); auto minNumSlots = uint32_t(m_size * 1.3); @@ -2015,8 +1889,7 @@ private: m_next.reserve(m_size); } - uint32_t computeHash(const Key &key) const - { + uint32_t computeHash(const Key &key) const { H hash; return hash(key) & (m_numSlots - 1); } @@ -2029,9 +1902,8 @@ private: Array m_next; }; -template -static void insertionSort(T *data, uint32_t length) -{ +template +static void insertionSort(T *data, uint32_t length) { for (int32_t i = 1; i < (int32_t)length; i++) { T x = data[i]; int32_t j = i - 1; @@ -2043,21 +1915,18 @@ static void insertionSort(T *data, uint32_t length) } } -class KISSRng -{ +class KISSRng { public: KISSRng() { reset(); } - void reset() - { + void reset() { x = 123456789; y = 362436000; z = 521288629; c = 7654321; } - uint32_t getRange(uint32_t range) - { + uint32_t getRange(uint32_t range) { if (range == 0) return 0; x = 69069 * x + 12345; @@ -2076,20 +1945,18 @@ private: // Based on Pierre Terdiman's and Michael Herf's source code. // http://www.codercorner.com/RadixSortRevisited.htm // http://www.stereopsis.com/radix.html -class RadixSort -{ +class RadixSort { public: - RadixSort() : m_size(0), m_ranks(nullptr), m_ranks2(nullptr), m_validRanks(false) {} + RadixSort() : + m_size(0), m_ranks(nullptr), m_ranks2(nullptr), m_validRanks(false) {} - ~RadixSort() - { + ~RadixSort() { // Release everything XA_FREE(m_ranks2); XA_FREE(m_ranks); } - RadixSort &sort(const float *input, uint32_t count) - { + RadixSort &sort(const float *input, uint32_t count) { if (input == nullptr || count == 0) return *this; // Resize lists if needed if (count != m_size) { @@ -2115,20 +1982,17 @@ public: return *this; } - RadixSort &sort(const Array &input) - { + RadixSort &sort(const Array &input) { return sort(input.data(), input.size()); } // Access to results. m_ranks is a list of indices in sorted order, i.e. in the order you may further process your data - const uint32_t *ranks() const - { + const uint32_t *ranks() const { XA_DEBUG_ASSERT(m_validRanks); return m_ranks; } - uint32_t *ranks() - { + uint32_t *ranks() { XA_DEBUG_ASSERT(m_validRanks); return m_ranks; } @@ -2139,21 +2003,18 @@ private: uint32_t *m_ranks2; bool m_validRanks; - void FloatFlip(uint32_t &f) - { + void FloatFlip(uint32_t &f) { int32_t mask = (int32_t(f) >> 31) | 0x80000000; // Warren Hunt, Manchor Ko. f ^= mask; } - void IFloatFlip(uint32_t &f) - { + void IFloatFlip(uint32_t &f) { uint32_t mask = ((f >> 31) - 1) | 0x80000000; // Michael Herf. f ^= mask; } - template - void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram) - { + template + void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram) { const uint32_t bucketCount = sizeof(T); // (8 * sizeof(T)) / log2(radix) // Init bucket pointers. uint32_t *h[bucketCount]; @@ -2161,10 +2022,10 @@ private: h[i] = histogram + 256 * i; } // Clear histograms. - memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t )); + memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t)); // @@ Add support for signed integers. // Build histograms. - const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules? + const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules? const uint8_t *pe = p + count * sizeof(T); while (p != pe) { h[0][*p++]++, h[1][*p++]++, h[2][*p++]++, h[3][*p++]++; @@ -2179,8 +2040,8 @@ private: } } - template void insertionSort(const T *input, uint32_t count) - { + template + void insertionSort(const T *input, uint32_t count) { if (!m_validRanks) { m_ranks[0] = 0; for (uint32_t i = 1; i != count; ++i) { @@ -2210,8 +2071,8 @@ private: } } - template void radixSort(const T *input, uint32_t count) - { + template + void radixSort(const T *input, uint32_t count) { const uint32_t P = sizeof(T); // pass count // Allocate histograms & offsets on the stack uint32_t histogram[256 * P]; @@ -2229,7 +2090,8 @@ private: } // Create offsets link[0] = m_ranks2; - for (uint32_t i = 1; i < 256; i++) link[i] = link[i - 1] + h[i - 1]; + for (uint32_t i = 1; i < 256; i++) + link[i] = link[i - 1] + h[i - 1]; // Perform Radix Sort if (!m_validRanks) { for (uint32_t i = 0; i < count; i++) { @@ -2256,25 +2118,21 @@ private: }; // Wrapping this in a class allows temporary arrays to be re-used. -class BoundingBox2D -{ +class BoundingBox2D { public: Vector2 majorAxis, minorAxis, minCorner, maxCorner; - void clear() - { + void clear() { m_boundaryVertices.clear(); } - void appendBoundaryVertex(Vector2 v) - { + void appendBoundaryVertex(Vector2 v) { m_boundaryVertices.push_back(v); } // This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method. // If vertices is null or vertexCount is 0, the boundary vertices are used. - void compute(const Vector2 *vertices = nullptr, uint32_t vertexCount = 0) - { + void compute(const Vector2 *vertices = nullptr, uint32_t vertexCount = 0) { if (!vertices || vertexCount == 0) { vertices = m_boundaryVertices.data(); vertexCount = m_boundaryVertices.size(); @@ -2322,8 +2180,7 @@ public: private: // Compute the convex hull using Graham Scan. - void convexHull(const Vector2 *input, uint32_t inputCount, Array &output, float epsilon) - { + void convexHull(const Vector2 *input, uint32_t inputCount, Array &output, float epsilon) { m_coords.resize(inputCount); for (uint32_t i = 0; i < inputCount; i++) m_coords[i] = input[i].x; @@ -2353,7 +2210,7 @@ private: XA_DEBUG_ASSERT(m_top.size() >= 2); output.push_back(m_top[0]); output.push_back(m_top[1]); - for (uint32_t i = 2; i < m_top.size(); ) { + for (uint32_t i = 2; i < m_top.size();) { Vector2 a = output[output.size() - 2]; Vector2 b = output[output.size() - 1]; Vector2 c = m_top[i]; @@ -2369,7 +2226,7 @@ private: XA_DEBUG_ASSERT(m_bottom.size() >= 2); output.push_back(m_bottom[1]); // Filter bottom list. - for (uint32_t i = 2; i < m_bottom.size(); ) { + for (uint32_t i = 2; i < m_bottom.size();) { Vector2 a = output[output.size() - 2]; Vector2 b = output[output.size() - 1]; Vector2 c = m_bottom[i]; @@ -2391,33 +2248,33 @@ private: Array m_top, m_bottom, m_hull; }; -static uint32_t meshEdgeFace(uint32_t edge) { return edge / 3; } -static uint32_t meshEdgeIndex0(uint32_t edge) { return edge; } +static uint32_t meshEdgeFace(uint32_t edge) { + return edge / 3; +} +static uint32_t meshEdgeIndex0(uint32_t edge) { + return edge; +} -static uint32_t meshEdgeIndex1(uint32_t edge) -{ +static uint32_t meshEdgeIndex1(uint32_t edge) { const uint32_t faceFirstEdge = edge / 3 * 3; return faceFirstEdge + (edge - faceFirstEdge + 1) % 3; } -struct MeshFlags -{ - enum - { - HasFaceGroups = 1<<0, - HasIgnoredFaces = 1<<1, - HasNormals = 1<<2 +struct MeshFlags { + enum { + HasFaceGroups = 1 << 0, + HasIgnoredFaces = 1 << 1, + HasNormals = 1 << 2 }; }; class Mesh; static void meshGetBoundaryLoops(const Mesh &mesh, Array &boundaryLoops); -class Mesh -{ +class Mesh { public: - Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) : m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_ignoredFaceCount(0), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_faceGroups(MemTag::Mesh), m_faceGroupFirstFace(MemTag::Mesh), m_faceGroupNextFace(MemTag::Mesh), m_faceGroupFaceCounts(MemTag::Mesh), m_colocalVertexCount(0), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryEdges(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3) - { + Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) : + m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_ignoredFaceCount(0), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_faceGroups(MemTag::Mesh), m_faceGroupFirstFace(MemTag::Mesh), m_faceGroupNextFace(MemTag::Mesh), m_faceGroupFaceCounts(MemTag::Mesh), m_colocalVertexCount(0), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryEdges(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3) { m_indices.reserve(approxFaceCount * 3); m_positions.reserve(approxVertexCount); m_texcoords.reserve(approxVertexCount); @@ -2433,8 +2290,7 @@ public: uint32_t flags() const { return m_flags; } uint32_t id() const { return m_id; } - void addVertex(const Vector3 &pos, const Vector3 &normal = Vector3(0.0f), const Vector2 &texcoord = Vector2(0.0f)) - { + void addVertex(const Vector3 &pos, const Vector3 &normal = Vector3(0.0f), const Vector2 &texcoord = Vector2(0.0f)) { XA_DEBUG_ASSERT(isFinite(pos)); m_positions.push_back(pos); if (m_flags & MeshFlags::HasNormals) @@ -2442,17 +2298,14 @@ public: m_texcoords.push_back(texcoord); } - struct AddFaceResult - { - enum Enum - { + struct AddFaceResult { + enum Enum { OK, DuplicateEdge = 1 }; }; - AddFaceResult::Enum addFace(uint32_t v0, uint32_t v1, uint32_t v2, bool ignore = false, bool hashEdge = true) - { + AddFaceResult::Enum addFace(uint32_t v0, uint32_t v1, uint32_t v2, bool ignore = false, bool hashEdge = true) { uint32_t indexArray[3]; indexArray[0] = v0; indexArray[1] = v1; @@ -2460,8 +2313,7 @@ public: return addFace(indexArray, ignore, hashEdge); } - AddFaceResult::Enum addFace(const uint32_t *indices, bool ignore = false, bool hashEdge = true) - { + AddFaceResult::Enum addFace(const uint32_t *indices, bool ignore = false, bool hashEdge = true) { AddFaceResult::Enum result = AddFaceResult::OK; if (m_flags & MeshFlags::HasFaceGroups) m_faceGroups.push_back(kInvalidFaceGroup); @@ -2486,8 +2338,7 @@ public: return result; } - void createColocals() - { + void createColocals() { const uint32_t vertexCount = m_positions.size(); Array aabbs(MemTag::BVH); aabbs.resize(vertexCount); @@ -2515,7 +2366,7 @@ public: if (colocals.size() == 1) { // No colocals for this vertex. m_nextColocalVertex[i] = i; - continue; + continue; } m_colocalVertexCount += colocals.size(); // Link in ascending order. @@ -2527,8 +2378,7 @@ public: } // Check if the face duplicates any edges of any face already in the group. - bool faceDuplicatesGroupEdge(uint16_t group, uint32_t face) const - { + bool faceDuplicatesGroupEdge(uint16_t group, uint32_t face) const { for (FaceEdgeIterator edgeIt(this, face); !edgeIt.isDone(); edgeIt.advance()) { for (ColocalEdgeIterator colocalEdgeIt(this, edgeIt.vertex0(), edgeIt.vertex1()); !colocalEdgeIt.isDone(); colocalEdgeIt.advance()) { if (m_faceGroups[meshEdgeFace(colocalEdgeIt.edge())] == group) @@ -2538,8 +2388,7 @@ public: return false; } - void createFaceGroups() - { + void createFaceGroups() { uint32_t firstUnassignedFace = 0; uint16_t group = 0; Array growFaces; @@ -2619,8 +2468,7 @@ public: } } - void createBoundaries() - { + void createBoundaries() { const uint32_t edgeCount = m_indices.size(); const uint32_t vertexCount = m_positions.size(); m_oppositeEdges.resize(edgeCount); @@ -2650,8 +2498,7 @@ public: } } - void linkBoundaries() - { + void linkBoundaries() { const uint32_t edgeCount = m_indices.size(); HashMap vertexToEdgeMap(MemTag::Mesh, edgeCount); // Edge is index / 2 for (uint32_t i = 0; i < edgeCount; i++) { @@ -2744,8 +2591,7 @@ public: } /// Find edge, test all colocals. - uint32_t findEdge(uint32_t vertex0, uint32_t vertex1) const - { + uint32_t findEdge(uint32_t vertex0, uint32_t vertex1) const { uint32_t result = UINT32_MAX; if (m_nextColocalVertex.isEmpty()) { EdgeKey key(vertex0, vertex1); @@ -2784,8 +2630,7 @@ public: } #if XA_DEBUG_EXPORT_OBJ - void writeObjVertices(FILE *file) const - { + void writeObjVertices(FILE *file) const { for (uint32_t i = 0; i < m_positions.size(); i++) fprintf(file, "v %g %g %g\n", m_positions[i].x, m_positions[i].y, m_positions[i].z); if (m_flags & MeshFlags::HasNormals) { @@ -2796,8 +2641,7 @@ public: fprintf(file, "vt %g %g\n", m_texcoords[i].x, m_texcoords[i].y); } - void writeObjFace(FILE *file, uint32_t face) const - { + void writeObjFace(FILE *file, uint32_t face) const { fprintf(file, "f "); for (uint32_t j = 0; j < 3; j++) { const uint32_t index = m_indices[face * 3 + j] + 1; // 1-indexed @@ -2805,8 +2649,7 @@ public: } } - void writeObjBoundaryEges(FILE *file) const - { + void writeObjBoundaryEges(FILE *file) const { if (m_oppositeEdges.isEmpty()) return; // Boundaries haven't been created. fprintf(file, "o boundary_edges\n"); @@ -2817,8 +2660,7 @@ public: } } - void writeObjLinkedBoundaries(FILE *file) const - { + void writeObjLinkedBoundaries(FILE *file) const { if (m_oppositeEdges.isEmpty() || m_nextBoundaryEdges.isEmpty()) return; // Boundaries haven't been created and/or linked. Array boundaryLoops; @@ -2840,8 +2682,7 @@ public: } } - void writeObjFile(const char *filename) const - { + void writeObjFile(const char *filename) const { FILE *file; XA_FOPEN(file, filename, "w"); if (!file) @@ -2857,8 +2698,7 @@ public: } #endif - float computeSurfaceArea() const - { + float computeSurfaceArea() const { float area = 0; for (uint32_t f = 0; f < faceCount(); f++) area += computeFaceArea(f); @@ -2866,24 +2706,21 @@ public: return area; } - float computeParametricArea() const - { + float computeParametricArea() const { float area = 0; for (uint32_t f = 0; f < faceCount(); f++) area += computeFaceParametricArea(f); return fabsf(area); // May be negative, depends on texcoord winding. } - float computeFaceArea(uint32_t face) const - { + float computeFaceArea(uint32_t face) const { const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]]; const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]]; const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]]; return length(cross(p1 - p0, p2 - p0)) * 0.5f; } - Vector3 computeFaceCentroid(uint32_t face) const - { + Vector3 computeFaceCentroid(uint32_t face) const { Vector3 sum(0.0f); for (uint32_t i = 0; i < 3; i++) sum += m_positions[m_indices[face * 3 + i]]; @@ -2892,8 +2729,7 @@ public: // Average of the edge midpoints weighted by the edge length. // I want a point inside the triangle, but closer to the cirumcenter. - Vector3 computeFaceCenter(uint32_t face) const - { + Vector3 computeFaceCenter(uint32_t face) const { const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]]; const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]]; const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]]; @@ -2906,8 +2742,7 @@ public: return m0 + m1 + m2; } - Vector3 computeFaceNormal(uint32_t face) const - { + Vector3 computeFaceNormal(uint32_t face) const { const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]]; const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]]; const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]]; @@ -2917,17 +2752,15 @@ public: return normalizeSafe(normalAreaScaled, Vector3(0, 0, 1), 0.0f); } - float computeFaceParametricArea(uint32_t face) const - { + float computeFaceParametricArea(uint32_t face) const { const Vector2 &t0 = m_texcoords[m_indices[face * 3 + 0]]; const Vector2 &t1 = m_texcoords[m_indices[face * 3 + 1]]; const Vector2 &t2 = m_texcoords[m_indices[face * 3 + 2]]; return triangleArea(t0, t1, t2); } - + // @@ This is not exactly accurate, we should compare the texture coordinates... - bool isSeam(uint32_t edge) const - { + bool isSeam(uint32_t edge) const { const uint32_t oppositeEdge = m_oppositeEdges[edge]; if (oppositeEdge == UINT32_MAX) return false; // boundary edge @@ -2938,8 +2771,7 @@ public: return m_indices[e0] != m_indices[oe1] || m_indices[e1] != m_indices[oe0]; } - bool isTextureSeam(uint32_t edge) const - { + bool isTextureSeam(uint32_t edge) const { const uint32_t oppositeEdge = m_oppositeEdges[edge]; if (oppositeEdge == UINT32_MAX) return false; // boundary edge @@ -2950,8 +2782,7 @@ public: return m_texcoords[m_indices[e0]] != m_texcoords[m_indices[oe1]] || m_texcoords[m_indices[e1]] != m_texcoords[m_indices[oe0]]; } - uint32_t firstColocal(uint32_t vertex) const - { + uint32_t firstColocal(uint32_t vertex) const { for (ColocalVertexIterator it(this, vertex); !it.isDone(); it.advance()) { if (it.vertex() < vertex) vertex = it.vertex(); @@ -2959,8 +2790,7 @@ public: return vertex; } - bool areColocal(uint32_t vertex0, uint32_t vertex1) const - { + bool areColocal(uint32_t vertex0, uint32_t vertex1) const { if (vertex0 == vertex1) return true; if (m_nextColocalVertex.isEmpty()) @@ -2982,17 +2812,32 @@ public: XA_INLINE uint32_t vertexCount() const { return m_positions.size(); } XA_INLINE uint32_t vertexAt(uint32_t i) const { return m_indices[i]; } XA_INLINE const Vector3 &position(uint32_t vertex) const { return m_positions[vertex]; } - XA_INLINE const Vector3 &normal(uint32_t vertex) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasNormals); return m_normals[vertex]; } + XA_INLINE const Vector3 &normal(uint32_t vertex) const { + XA_DEBUG_ASSERT(m_flags & MeshFlags::HasNormals); + return m_normals[vertex]; + } XA_INLINE const Vector2 &texcoord(uint32_t vertex) const { return m_texcoords[vertex]; } XA_INLINE Vector2 &texcoord(uint32_t vertex) { return m_texcoords[vertex]; } XA_INLINE const Vector2 *texcoords() const { return m_texcoords.data(); } XA_INLINE Vector2 *texcoords() { return m_texcoords.data(); } XA_INLINE uint32_t ignoredFaceCount() const { return m_ignoredFaceCount; } XA_INLINE uint32_t faceCount() const { return m_indices.size() / 3; } - XA_INLINE uint16_t faceGroupAt(uint32_t face) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroups[face]; } - XA_INLINE uint32_t faceGroupCount() const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroupFaceCounts.size(); } - XA_INLINE uint32_t faceGroupNextFace(uint32_t face) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroupNextFace[face]; } - XA_INLINE uint32_t faceGroupFaceCount(uint32_t group) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroupFaceCounts[group]; } + XA_INLINE uint16_t faceGroupAt(uint32_t face) const { + XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); + return m_faceGroups[face]; + } + XA_INLINE uint32_t faceGroupCount() const { + XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); + return m_faceGroupFaceCounts.size(); + } + XA_INLINE uint32_t faceGroupNextFace(uint32_t face) const { + XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); + return m_faceGroupNextFace[face]; + } + XA_INLINE uint32_t faceGroupFaceCount(uint32_t group) const { + XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); + return m_faceGroupFaceCounts[group]; + } XA_INLINE const uint32_t *indices() const { return m_indices.data(); } XA_INLINE uint32_t indexCount() const { return m_indices.size(); } @@ -3027,49 +2872,45 @@ private: // Populated by linkBoundaries Array m_nextBoundaryEdges; // The index of the next boundary edge. UINT32_MAX if the edge is not a boundary edge. - struct EdgeKey - { + struct EdgeKey { EdgeKey() {} - EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {} - EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {} + EdgeKey(const EdgeKey &k) : + v0(k.v0), v1(k.v1) {} + EdgeKey(uint32_t v0, uint32_t v1) : + v0(v0), v1(v1) {} bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; } uint32_t v0; uint32_t v1; }; - struct EdgeHash - { + struct EdgeHash { uint32_t operator()(const EdgeKey &k) const { return k.v0 * 32768u + k.v1; } }; HashMap m_edgeMap; public: - class BoundaryLoopEdgeIterator - { + class BoundaryLoopEdgeIterator { public: - BoundaryLoopEdgeIterator(const Mesh *mesh, uint32_t edge) : m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {} + BoundaryLoopEdgeIterator(const Mesh *mesh, uint32_t edge) : + m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {} - void advance() - { + void advance() { if (m_first == UINT32_MAX) m_first = m_current; m_current = m_mesh->m_nextBoundaryEdges[m_current]; } - bool isDone() const - { + bool isDone() const { return m_first == m_current || m_current == UINT32_MAX; } - uint32_t edge() const - { + uint32_t edge() const { return m_current; } - uint32_t nextEdge() const - { + uint32_t nextEdge() const { return m_mesh->m_nextBoundaryEdges[m_current]; } @@ -3079,31 +2920,27 @@ public: uint32_t m_current; }; - class ColocalVertexIterator - { + class ColocalVertexIterator { public: - ColocalVertexIterator(const Mesh *mesh, uint32_t v) : m_mesh(mesh), m_first(UINT32_MAX), m_current(v) {} + ColocalVertexIterator(const Mesh *mesh, uint32_t v) : + m_mesh(mesh), m_first(UINT32_MAX), m_current(v) {} - void advance() - { + void advance() { if (m_first == UINT32_MAX) m_first = m_current; if (!m_mesh->m_nextColocalVertex.isEmpty()) m_current = m_mesh->m_nextColocalVertex[m_current]; } - bool isDone() const - { + bool isDone() const { return m_first == m_current; } - uint32_t vertex() const - { + uint32_t vertex() const { return m_current; } - const Vector3 *pos() const - { + const Vector3 *pos() const { return &m_mesh->m_positions[m_current]; } @@ -3113,39 +2950,33 @@ public: uint32_t m_current; }; - class ColocalEdgeIterator - { + class ColocalEdgeIterator { public: - ColocalEdgeIterator(const Mesh *mesh, uint32_t vertex0, uint32_t vertex1) : m_mesh(mesh), m_vertex0It(mesh, vertex0), m_vertex1It(mesh, vertex1), m_vertex1(vertex1) - { + ColocalEdgeIterator(const Mesh *mesh, uint32_t vertex0, uint32_t vertex1) : + m_mesh(mesh), m_vertex0It(mesh, vertex0), m_vertex1It(mesh, vertex1), m_vertex1(vertex1) { do { if (!resetElement()) { advanceVertex1(); - } - else { + } else { break; } } while (!isDone()); } - void advance() - { + void advance() { advanceElement(); } - bool isDone() const - { + bool isDone() const { return m_vertex0It.isDone() && m_vertex1It.isDone() && m_edge == UINT32_MAX; } - uint32_t edge() const - { + uint32_t edge() const { return m_edge; } private: - bool resetElement() - { + bool resetElement() { m_edge = m_mesh->m_edgeMap.get(Mesh::EdgeKey(m_vertex0It.vertex(), m_vertex1It.vertex())); while (m_edge != UINT32_MAX) { if (!isIgnoredFace()) @@ -3158,8 +2989,7 @@ public: return true; } - void advanceElement() - { + void advanceElement() { for (;;) { m_edge = m_mesh->m_edgeMap.getNext(m_edge); if (m_edge == UINT32_MAX) @@ -3171,17 +3001,15 @@ public: advanceVertex1(); } - void advanceVertex1() - { + void advanceVertex1() { auto successful = false; - while (!successful) { + while (!successful) { m_vertex1It.advance(); if (m_vertex1It.isDone()) { if (!m_vertex0It.isDone()) { m_vertex0It.advance(); m_vertex1It = ColocalVertexIterator(m_mesh, m_vertex1); - } - else { + } else { return; } } @@ -3189,8 +3017,7 @@ public: } } - bool isIgnoredFace() const - { + bool isIgnoredFace() const { return m_mesh->m_faceIgnore[meshEdgeFace(m_edge)]; } @@ -3200,24 +3027,21 @@ public: uint32_t m_edge; }; - class FaceEdgeIterator - { + class FaceEdgeIterator { public: - FaceEdgeIterator (const Mesh *mesh, uint32_t face) : m_mesh(mesh), m_face(face), m_relativeEdge(0) - { + FaceEdgeIterator(const Mesh *mesh, uint32_t face) : + m_mesh(mesh), m_face(face), m_relativeEdge(0) { m_edge = m_face * 3; } - void advance() - { + void advance() { if (m_relativeEdge < 3) { m_edge++; m_relativeEdge++; } } - bool isDone() const - { + bool isDone() const { return m_relativeEdge == 3; } @@ -3228,9 +3052,8 @@ public: uint32_t relativeEdge() const { return m_relativeEdge; } uint32_t face() const { return m_face; } uint32_t oppositeEdge() const { return m_mesh->m_oppositeEdges[m_edge]; } - - uint32_t oppositeFace() const - { + + uint32_t oppositeFace() const { const uint32_t oedge = m_mesh->m_oppositeEdges[m_edge]; if (oedge == UINT32_MAX) return UINT32_MAX; @@ -3253,27 +3076,23 @@ public: uint32_t m_relativeEdge; }; - class GroupFaceIterator - { + class GroupFaceIterator { public: - GroupFaceIterator(const Mesh *mesh, uint32_t group) : m_mesh(mesh) - { + GroupFaceIterator(const Mesh *mesh, uint32_t group) : + m_mesh(mesh) { XA_DEBUG_ASSERT(group != UINT32_MAX); m_current = mesh->m_faceGroupFirstFace[group]; } - void advance() - { + void advance() { m_current = m_mesh->m_faceGroupNextFace[m_current]; } - bool isDone() const - { + bool isDone() const { return m_current == UINT32_MAX; } - uint32_t face() const - { + uint32_t face() const { return m_current; } @@ -3285,8 +3104,7 @@ public: constexpr uint16_t Mesh::kInvalidFaceGroup; -static bool meshCloseHole(Mesh *mesh, const Array &holeVertices, const Vector3 &normal) -{ +static bool meshCloseHole(Mesh *mesh, const Array &holeVertices, const Vector3 &normal) { #if XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION const uint32_t faceCount = mesh->faceCount(); #endif @@ -3412,8 +3230,7 @@ static bool meshCloseHole(Mesh *mesh, const Array &holeVertices, const return true; } -static bool meshCloseHoles(Mesh *mesh, const Array &boundaryLoops, const Vector3 &normal, uint32_t *holeCount, Array *holeFaceCounts) -{ +static bool meshCloseHoles(Mesh *mesh, const Array &boundaryLoops, const Vector3 &normal, uint32_t *holeCount, Array *holeFaceCounts) { if (holeFaceCounts) holeFaceCounts->clear(); // Compute lengths. @@ -3469,8 +3286,7 @@ static bool meshCloseHoles(Mesh *mesh, const Array &boundaryLoops, con return result; } -static bool meshIsPlanar(const Mesh &mesh) -{ +static bool meshIsPlanar(const Mesh &mesh) { const Vector3 p1 = mesh.position(mesh.vertexAt(0)); const Vector3 p2 = mesh.position(mesh.vertexAt(1)); const Vector3 p3 = mesh.position(mesh.vertexAt(2)); @@ -3496,14 +3312,12 @@ Fixing T-junctions. - Split edge. */ -struct SplitEdge -{ +struct SplitEdge { uint32_t edge; float t; uint32_t vertex; - bool operator<(const SplitEdge &other) const - { + bool operator<(const SplitEdge &other) const { if (edge < other.edge) return true; else if (edge == other.edge) { @@ -3515,8 +3329,7 @@ struct SplitEdge }; // Returns nullptr if there were no t-junctions to fix. -static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool *failed, uint32_t *fixedTJunctionsCount) -{ +static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool *failed, uint32_t *fixedTJunctionsCount) { if (duplicatedEdge) *duplicatedEdge = false; if (failed) @@ -3591,8 +3404,7 @@ static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool } // boundaryLoops are the first edges for each boundary loop. -static void meshGetBoundaryLoops(const Mesh &mesh, Array &boundaryLoops) -{ +static void meshGetBoundaryLoops(const Mesh &mesh, Array &boundaryLoops) { const uint32_t edgeCount = mesh.edgeCount(); BitArray bitFlags(edgeCount); bitFlags.zeroOutMemory(); @@ -3607,26 +3419,23 @@ static void meshGetBoundaryLoops(const Mesh &mesh, Array &boundaryLoop } } -struct Progress -{ - Progress(ProgressCategory::Enum category, ProgressFunc func, void *userData, uint32_t maxValue) : value(0), cancel(false), m_category(category), m_func(func), m_userData(userData), m_maxValue(maxValue), m_progress(0) - { +struct Progress { + Progress(ProgressCategory::Enum category, ProgressFunc func, void *userData, uint32_t maxValue) : + value(0), cancel(false), m_category(category), m_func(func), m_userData(userData), m_maxValue(maxValue), m_progress(0) { if (m_func) { if (!m_func(category, 0, userData)) cancel = true; } } - ~Progress() - { + ~Progress() { if (m_func) { if (!m_func(m_category, 100, m_userData)) cancel = true; } } - void update() - { + void update() { if (!m_func) return; m_mutex.lock(); @@ -3639,8 +3448,7 @@ struct Progress m_mutex.unlock(); } - void setMaxValue(uint32_t maxValue) - { + void setMaxValue(uint32_t maxValue) { m_mutex.lock(); m_maxValue = maxValue; m_mutex.unlock(); @@ -3658,32 +3466,31 @@ private: std::mutex m_mutex; }; -struct Spinlock -{ - void lock() { while(m_lock.test_and_set(std::memory_order_acquire)) {} } +struct Spinlock { + void lock() { + while (m_lock.test_and_set(std::memory_order_acquire)) { + } + } void unlock() { m_lock.clear(std::memory_order_release); } private: std::atomic_flag m_lock = ATOMIC_FLAG_INIT; }; -struct TaskGroupHandle -{ +struct TaskGroupHandle { uint32_t value = UINT32_MAX; }; -struct Task -{ +struct Task { void (*func)(void *userData); void *userData; }; #if XA_MULTITHREADED -class TaskScheduler -{ +class TaskScheduler { public: - TaskScheduler() : m_shutdown(false) - { + TaskScheduler() : + m_shutdown(false) { m_threadIndex = 0; // Max with current task scheduler usage is 1 per thread + 1 deep nesting, but allow for some slop. m_maxGroups = std::thread::hardware_concurrency() * 4; @@ -3701,8 +3508,7 @@ public: } } - ~TaskScheduler() - { + ~TaskScheduler() { m_shutdown = true; for (uint32_t i = 0; i < m_workers.size(); i++) { Worker &worker = m_workers[i]; @@ -3720,13 +3526,11 @@ public: XA_FREE(m_groups); } - uint32_t threadCount() const - { + uint32_t threadCount() const { return max(1u, std::thread::hardware_concurrency()); // Including the main thread. } - TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) - { + TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) { // Claim the first free group. for (uint32_t i = 0; i < m_maxGroups; i++) { TaskGroup &group = m_groups[i]; @@ -3748,8 +3552,7 @@ public: return handle; } - void run(TaskGroupHandle handle, Task task) - { + void run(TaskGroupHandle handle, Task task) { XA_DEBUG_ASSERT(handle.value != UINT32_MAX); TaskGroup &group = m_groups[handle.value]; group.queueLock.lock(); @@ -3763,8 +3566,7 @@ public: } } - void wait(TaskGroupHandle *handle) - { + void wait(TaskGroupHandle *handle) { if (handle->value == UINT32_MAX) { XA_DEBUG_ASSERT(false); return; @@ -3792,8 +3594,7 @@ public: static uint32_t currentThreadIndex() { return m_threadIndex; } private: - struct TaskGroup - { + struct TaskGroup { std::atomic free; Array queue; // Items are never removed. queueHead is incremented to pop items. uint32_t queueHead = 0; @@ -3801,8 +3602,7 @@ private: std::atomic ref; // Increment when a task is enqueued, decrement when a task finishes. }; - struct Worker - { + struct Worker { std::thread *thread = nullptr; std::mutex mutex; std::condition_variable cv; @@ -3815,12 +3615,11 @@ private: std::atomic m_shutdown; static thread_local uint32_t m_threadIndex; - static void workerThread(TaskScheduler *scheduler, Worker *worker, uint32_t threadIndex) - { + static void workerThread(TaskScheduler *scheduler, Worker *worker, uint32_t threadIndex) { m_threadIndex = threadIndex; std::unique_lock lock(worker->mutex); for (;;) { - worker->cv.wait(lock, [=]{ return worker->wakeup.load(); }); + worker->cv.wait(lock, [=] { return worker->wakeup.load(); }); worker->wakeup = false; for (;;) { if (scheduler->m_shutdown) @@ -3851,22 +3650,18 @@ private: thread_local uint32_t TaskScheduler::m_threadIndex; #else -class TaskScheduler -{ +class TaskScheduler { public: - ~TaskScheduler() - { + ~TaskScheduler() { for (uint32_t i = 0; i < m_groups.size(); i++) destroyGroup({ i }); } - uint32_t threadCount() const - { + uint32_t threadCount() const { return 1; } - TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) - { + TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) { TaskGroup *group = XA_NEW(MemTag::Default, TaskGroup); group->queue.reserve(reserveSize); m_groups.push_back(group); @@ -3875,13 +3670,11 @@ public: return handle; } - void run(TaskGroupHandle handle, Task task) - { + void run(TaskGroupHandle handle, Task task) { m_groups[handle.value]->queue.push_back(task); } - void wait(TaskGroupHandle *handle) - { + void wait(TaskGroupHandle *handle) { if (handle->value == UINT32_MAX) { XA_DEBUG_ASSERT(false); return; @@ -3897,8 +3690,7 @@ public: static uint32_t currentThreadIndex() { return 0; } private: - void destroyGroup(TaskGroupHandle handle) - { + void destroyGroup(TaskGroupHandle handle) { TaskGroup *group = m_groups[handle.value]; if (group) { group->~TaskGroup(); @@ -3907,8 +3699,7 @@ private: } } - struct TaskGroup - { + struct TaskGroup { Array queue; }; @@ -3921,8 +3712,7 @@ const uint8_t TGA_TYPE_RGB = 2; const uint8_t TGA_ORIGIN_UPPER = 0x20; #pragma pack(push, 1) -struct TgaHeader -{ +struct TgaHeader { uint8_t id_length; uint8_t colormap_type; uint8_t image_type; @@ -3939,8 +3729,7 @@ struct TgaHeader }; #pragma pack(pop) -static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height) -{ +static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height) { XA_DEBUG_ASSERT(sizeof(TgaHeader) == TgaHeader::Size); FILE *f; XA_FOPEN(f, filename, "wb"); @@ -3965,12 +3754,10 @@ static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, } #endif -template -class ThreadLocal -{ +template +class ThreadLocal { public: - ThreadLocal() - { + ThreadLocal() { #if XA_MULTITHREADED const uint32_t n = std::thread::hardware_concurrency(); #else @@ -3981,8 +3768,7 @@ public: new (&m_array[i]) T; } - ~ThreadLocal() - { + ~ThreadLocal() { #if XA_MULTITHREADED const uint32_t n = std::thread::hardware_concurrency(); #else @@ -3993,8 +3779,7 @@ public: XA_FREE(m_array); } - T &get() const - { + T &get() const { return m_array[TaskScheduler::currentThreadIndex()]; } @@ -4002,11 +3787,9 @@ private: T *m_array; }; -class UniformGrid2 -{ +class UniformGrid2 { public: - void reset(const Vector2 *positions, const uint32_t *indices = nullptr, uint32_t reserveEdgeCount = 0) - { + void reset(const Vector2 *positions, const uint32_t *indices = nullptr, uint32_t reserveEdgeCount = 0) { m_edges.clear(); if (reserveEdgeCount > 0) m_edges.reserve(reserveEdgeCount); @@ -4015,14 +3798,12 @@ public: m_cellDataOffsets.clear(); } - void append(uint32_t edge) - { + void append(uint32_t edge) { XA_DEBUG_ASSERT(m_cellDataOffsets.isEmpty()); m_edges.push_back(edge); } - bool intersect(Vector2 v1, Vector2 v2, float epsilon) - { + bool intersect(Vector2 v1, Vector2 v2, float epsilon) { const uint32_t edgeCount = m_edges.size(); bool bruteForce = edgeCount <= 64; if (!bruteForce && m_cellDataOffsets.isEmpty()) @@ -4048,8 +3829,7 @@ public: return false; } - bool intersectSelf(float epsilon) - { + bool intersectSelf(float epsilon) { const uint32_t edgeCount = m_edges.size(); bool bruteForce = edgeCount <= 64; if (!bruteForce && m_cellDataOffsets.isEmpty()) @@ -4079,8 +3859,7 @@ public: } #if XA_DEBUG_EXPORT_BOUNDARY_GRID - void debugExport(const char *filename) - { + void debugExport(const char *filename) { Array image; image.resize(m_gridWidth * m_gridHeight * 3); for (uint32_t y = 0; y < m_gridHeight; y++) { @@ -4102,8 +3881,7 @@ public: #endif private: - bool createGrid() - { + bool createGrid() { // Compute edge extents. Min will be the grid origin. const uint32_t edgeCount = m_edges.size(); Extents2 edgeExtents; @@ -4155,8 +3933,7 @@ private: return true; } - void computePotentialEdges(Vector2 p1, Vector2 p2) - { + void computePotentialEdges(Vector2 p1, Vector2 p2) { m_potentialEdges.clear(); traverse(p1, p2); for (uint32_t j = 0; j < m_traversedCellOffsets.size(); j++) { @@ -4174,8 +3951,7 @@ private: } // "A Fast Voxel Traversal Algorithm for Ray Tracing" - void traverse(Vector2 p1, Vector2 p2) - { + void traverse(Vector2 p1, Vector2 p2) { const Vector2 dir = p2 - p1; const Vector2 normal = normalizeSafe(dir, Vector2(0.0f), kEpsilon); const int stepX = dir.x >= 0 ? 1 : -1; @@ -4196,14 +3972,12 @@ private: if (normal.x > kEpsilon || normal.x < -kEpsilon) { tMaxX = (distToNextCellX * stepX) / normal.x; tDeltaX = (m_cellSize * stepX) / normal.x; - } - else + } else tMaxX = tDeltaX = FLT_MAX; if (normal.y > kEpsilon || normal.y < -kEpsilon) { tMaxY = (distToNextCellY * stepY) / normal.y; tDeltaY = (m_cellSize * stepY) / normal.y; - } - else + } else tMaxY = tDeltaY = FLT_MAX; m_traversedCellOffsets.clear(); m_traversedCellOffsets.push_back(firstCell[0] + firstCell[1] * m_gridWidth); @@ -4230,8 +4004,7 @@ private: } } - bool edgesIntersect(uint32_t edge1, uint32_t edge2, float epsilon) const - { + bool edgesIntersect(uint32_t edge1, uint32_t edge2, float epsilon) const { if (edge1 == edge2) return false; const uint32_t ai[2] = { vertexAt(meshEdgeIndex0(edge1)), vertexAt(meshEdgeIndex1(edge1)) }; @@ -4242,28 +4015,23 @@ private: return linesIntersect(m_positions[ai[0]], m_positions[ai[1]], m_positions[bi[0]], m_positions[bi[1]], epsilon); } - uint32_t cellX(float x) const - { + uint32_t cellX(float x) const { return min((uint32_t)max(0.0f, (x - m_gridOrigin.x) / m_cellSize), m_gridWidth - 1u); } - uint32_t cellY(float y) const - { + uint32_t cellY(float y) const { return min((uint32_t)max(0.0f, (y - m_gridOrigin.y) / m_cellSize), m_gridHeight - 1u); } - Vector2 edgePosition0(uint32_t edge) const - { + Vector2 edgePosition0(uint32_t edge) const { return m_positions[vertexAt(meshEdgeIndex0(edge))]; } - Vector2 edgePosition1(uint32_t edge) const - { + Vector2 edgePosition1(uint32_t edge) const { return m_positions[vertexAt(meshEdgeIndex1(edge))]; } - uint32_t vertexAt(uint32_t index) const - { + uint32_t vertexAt(uint32_t index) const { return m_indices ? m_indices[index] : index; } @@ -4279,34 +4047,29 @@ private: Array m_traversedCellOffsets; }; -struct UvMeshChart -{ +struct UvMeshChart { Array faces; Array indices; uint32_t material; }; -struct UvMesh -{ +struct UvMesh { UvMeshDecl decl; Array indices; Array charts; Array vertexToChartMap; }; -struct UvMeshInstance -{ +struct UvMeshInstance { UvMesh *mesh; Array texcoords; bool rotateCharts; }; namespace raster { -class ClippedTriangle -{ +class ClippedTriangle { public: - ClippedTriangle(const Vector2 &a, const Vector2 &b, const Vector2 &c) - { + ClippedTriangle(const Vector2 &a, const Vector2 &b, const Vector2 &c) { m_numVertices = 3; m_activeVertexBuffer = 0; m_verticesA[0] = a; @@ -4316,20 +4079,19 @@ public: m_vertexBuffers[1] = m_verticesB; } - void clipHorizontalPlane(float offset, float clipdirection) - { - Vector2 *v = m_vertexBuffers[m_activeVertexBuffer]; + void clipHorizontalPlane(float offset, float clipdirection) { + Vector2 *v = m_vertexBuffers[m_activeVertexBuffer]; m_activeVertexBuffer ^= 1; Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer]; v[m_numVertices] = v[0]; - float dy2, dy1 = offset - v[0].y; - int dy2in, dy1in = clipdirection * dy1 >= 0; - uint32_t p = 0; + float dy2, dy1 = offset - v[0].y; + int dy2in, dy1in = clipdirection * dy1 >= 0; + uint32_t p = 0; for (uint32_t k = 0; k < m_numVertices; k++) { - dy2 = offset - v[k + 1].y; + dy2 = offset - v[k + 1].y; dy2in = clipdirection * dy2 >= 0; if (dy1in) v2[p++] = v[k]; - if ( dy1in + dy2in == 1 ) { // not both in/out + if (dy1in + dy2in == 1) { // not both in/out float dx = v[k + 1].x - v[k].x; float dy = v[k + 1].y - v[k].y; v2[p++] = Vector2(v[k].x + dy1 * (dx / dy), offset); @@ -4340,20 +4102,19 @@ public: m_numVertices = p; } - void clipVerticalPlane(float offset, float clipdirection) - { - Vector2 *v = m_vertexBuffers[m_activeVertexBuffer]; + void clipVerticalPlane(float offset, float clipdirection) { + Vector2 *v = m_vertexBuffers[m_activeVertexBuffer]; m_activeVertexBuffer ^= 1; Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer]; v[m_numVertices] = v[0]; - float dx2, dx1 = offset - v[0].x; - int dx2in, dx1in = clipdirection * dx1 >= 0; - uint32_t p = 0; + float dx2, dx1 = offset - v[0].x; + int dx2in, dx1in = clipdirection * dx1 >= 0; + uint32_t p = 0; for (uint32_t k = 0; k < m_numVertices; k++) { dx2 = offset - v[k + 1].x; dx2in = clipdirection * dx2 >= 0; if (dx1in) v2[p++] = v[k]; - if ( dx1in + dx2in == 1 ) { // not both in/out + if (dx1in + dx2in == 1) { // not both in/out float dx = v[k + 1].x - v[k].x; float dy = v[k + 1].y - v[k].y; v2[p++] = Vector2(offset, v[k].y + dx1 * (dy / dx)); @@ -4364,9 +4125,8 @@ public: m_numVertices = p; } - void computeArea() - { - Vector2 *v = m_vertexBuffers[m_activeVertexBuffer]; + void computeArea() { + Vector2 *v = m_vertexBuffers[m_activeVertexBuffer]; v[m_numVertices] = v[0]; m_area = 0; float centroidx = 0, centroidy = 0; @@ -4380,8 +4140,7 @@ public: m_area = 0.5f * fabsf(m_area); } - void clipAABox(float x0, float y0, float x1, float y1) - { + void clipAABox(float x0, float y0, float x1, float y1) { clipVerticalPlane(x0, -1); clipHorizontalPlane(y0, -1); clipVerticalPlane(x1, 1); @@ -4389,8 +4148,7 @@ public: computeArea(); } - float area() const - { + float area() const { return m_area; } @@ -4407,10 +4165,8 @@ private: typedef bool (*SamplingCallback)(void *param, int x, int y); /// A triangle for rasterization. -struct Triangle -{ - Triangle(const Vector2 &v0, const Vector2 &v1, const Vector2 &v2) - { +struct Triangle { + Triangle(const Vector2 &v0, const Vector2 &v1, const Vector2 &v2) { // Init vertices. this->v1 = v0; this->v2 = v2; @@ -4422,8 +4178,7 @@ struct Triangle computeUnitInwardNormals(); } - bool isValid() - { + bool isValid() { const Vector2 e0 = v3 - v1; const Vector2 e1 = v2 - v1; const float area = e0.y * e1.x - e1.y * e0.x; @@ -4431,18 +4186,17 @@ struct Triangle } // extents has to be multiple of BK_SIZE!! - bool drawAA(const Vector2 &extents, SamplingCallback cb, void *param) - { - const float PX_INSIDE = 1.0f/sqrtf(2.0f); - const float PX_OUTSIDE = -1.0f/sqrtf(2.0f); + bool drawAA(const Vector2 &extents, SamplingCallback cb, void *param) { + const float PX_INSIDE = 1.0f / sqrtf(2.0f); + const float PX_OUTSIDE = -1.0f / sqrtf(2.0f); const float BK_SIZE = 8; - const float BK_INSIDE = sqrtf(BK_SIZE*BK_SIZE/2.0f); - const float BK_OUTSIDE = -sqrtf(BK_SIZE*BK_SIZE/2.0f); + const float BK_INSIDE = sqrtf(BK_SIZE * BK_SIZE / 2.0f); + const float BK_OUTSIDE = -sqrtf(BK_SIZE * BK_SIZE / 2.0f); // Bounding rectangle float minx = floorf(max(min3(v1.x, v2.x, v3.x), 0.0f)); float miny = floorf(max(min3(v1.y, v2.y, v3.y), 0.0f)); - float maxx = ceilf( min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f)); - float maxy = ceilf( min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f)); + float maxx = ceilf(min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f)); + float maxy = ceilf(min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f)); // There's no reason to align the blocks to the viewport, instead we align them to the origin of the triangle bounds. minx = floorf(minx); miny = floorf(miny); @@ -4467,9 +4221,9 @@ struct Triangle float bC = C2 + n2.x * xc + n2.y * yc; float cC = C3 + n3.x * xc + n3.y * yc; // Skip block when outside an edge - if ( (aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE) ) continue; + if ((aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE)) continue; // Accept whole block when totally covered - if ( (aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE) ) { + if ((aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE)) { for (float y = y0; y < y0 + BK_SIZE; y++) { for (float x = x0; x < x0 + BK_SIZE; x++) { if (!cb(param, (int)x, (int)y)) @@ -4512,10 +4266,9 @@ struct Triangle } private: - void flipBackface() - { + void flipBackface() { // check if triangle is backfacing, if so, swap two vertices - if ( ((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0 ) { + if (((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0) { Vector2 hv = v1; v1 = v2; v2 = hv; // swap pos @@ -4523,8 +4276,7 @@ private: } // compute unit inward normals for each edge. - void computeUnitInwardNormals() - { + void computeUnitInwardNormals() { n1 = v1 - v2; n1 = Vector2(-n1.y, n1.x); n1 = n1 * (1.0f / sqrtf(dot(n1, n1))); @@ -4542,8 +4294,7 @@ private: }; // Process the given triangle. Returns false if rasterization was interrupted by the callback. -static bool drawTriangle(const Vector2 &extents, const Vector2 v[3], SamplingCallback cb, void *param) -{ +static bool drawTriangle(const Vector2 &extents, const Vector2 v[3], SamplingCallback cb, void *param) { Triangle tri(v[0], v[1], v[2]); // @@ It would be nice to have a conservative drawing mode that enlarges the triangle extents by one texel and is able to handle degenerate triangles. // @@ Maybe the simplest thing to do would be raster triangle edges. @@ -4566,18 +4317,16 @@ namespace sparse { * elements for each row of the matrix. As with the FullVector the * dimension of the matrix is constant. **/ -class Matrix -{ +class Matrix { public: // An element of the sparse array. - struct Coefficient - { - uint32_t x; // column + struct Coefficient { + uint32_t x; // column float v; // value }; - Matrix(uint32_t d) : m_width(d), m_array(MemTag::Matrix) - { + Matrix(uint32_t d) : + m_width(d), m_array(MemTag::Matrix) { m_array.resize(d); m_array.runCtors(); #if XA_DEBUG_HEAP @@ -4585,9 +4334,9 @@ public: m_array[i].setMemTag(MemTag::Matrix); #endif } - - Matrix(uint32_t w, uint32_t h) : m_width(w), m_array(MemTag::Matrix) - { + + Matrix(uint32_t w, uint32_t h) : + m_width(w), m_array(MemTag::Matrix) { m_array.resize(h); m_array.runCtors(); #if XA_DEBUG_HEAP @@ -4595,9 +4344,8 @@ public: m_array[i].setMemTag(MemTag::Matrix); #endif } - - ~Matrix() - { + + ~Matrix() { m_array.runDtors(); } @@ -4608,10 +4356,9 @@ public: bool isSquare() const { return width() == height(); } // x is column, y is row - float getCoefficient(uint32_t x, uint32_t y) const - { - XA_DEBUG_ASSERT( x < width() ); - XA_DEBUG_ASSERT( y < height() ); + float getCoefficient(uint32_t x, uint32_t y) const { + XA_DEBUG_ASSERT(x < width()); + XA_DEBUG_ASSERT(y < height()); const uint32_t count = m_array[y].size(); for (uint32_t i = 0; i < count; i++) { if (m_array[y][i].x == x) return m_array[y][i].v; @@ -4619,10 +4366,9 @@ public: return 0.0f; } - void setCoefficient(uint32_t x, uint32_t y, float f) - { - XA_DEBUG_ASSERT( x < width() ); - XA_DEBUG_ASSERT( y < height() ); + void setCoefficient(uint32_t x, uint32_t y, float f) { + XA_DEBUG_ASSERT(x < width()); + XA_DEBUG_ASSERT(y < height()); const uint32_t count = m_array[y].size(); for (uint32_t i = 0; i < count; i++) { if (m_array[y][i].x == x) { @@ -4632,13 +4378,12 @@ public: } if (f != 0.0f) { Coefficient c = { x, f }; - m_array[y].push_back( c ); + m_array[y].push_back(c); } } - float dotRow(uint32_t y, const FullVector &v) const - { - XA_DEBUG_ASSERT( y < height() ); + float dotRow(uint32_t y, const FullVector &v) const { + XA_DEBUG_ASSERT(y < height()); const uint32_t count = m_array[y].size(); float sum = 0; for (uint32_t i = 0; i < count; i++) { @@ -4647,8 +4392,7 @@ public: return sum; } - void madRow(uint32_t y, float alpha, FullVector &v) const - { + void madRow(uint32_t y, float alpha, FullVector &v) const { XA_DEBUG_ASSERT(y < height()); const uint32_t count = m_array[y].size(); for (uint32_t i = 0; i < count; i++) { @@ -4656,9 +4400,8 @@ public: } } - void clearRow(uint32_t y) - { - XA_DEBUG_ASSERT( y < height() ); + void clearRow(uint32_t y) { + XA_DEBUG_ASSERT(y < height()); m_array[y].clear(); } @@ -4669,12 +4412,11 @@ private: const uint32_t m_width; /// Array of matrix elements. - Array< Array > m_array; + Array> m_array; }; // y = a * x + y -static void saxpy(float a, const FullVector &x, FullVector &y) -{ +static void saxpy(float a, const FullVector &x, FullVector &y) { XA_DEBUG_ASSERT(x.dimension() == y.dimension()); const uint32_t dim = x.dimension(); for (uint32_t i = 0; i < dim; i++) { @@ -4682,8 +4424,7 @@ static void saxpy(float a, const FullVector &x, FullVector &y) } } -static void copy(const FullVector &x, FullVector &y) -{ +static void copy(const FullVector &x, FullVector &y) { XA_DEBUG_ASSERT(x.dimension() == y.dimension()); const uint32_t dim = x.dimension(); for (uint32_t i = 0; i < dim; i++) { @@ -4691,16 +4432,14 @@ static void copy(const FullVector &x, FullVector &y) } } -static void scal(float a, FullVector &x) -{ +static void scal(float a, FullVector &x) { const uint32_t dim = x.dimension(); for (uint32_t i = 0; i < dim; i++) { x[i] *= a; } } -static float dot(const FullVector &x, const FullVector &y) -{ +static float dot(const FullVector &x, const FullVector &y) { XA_DEBUG_ASSERT(x.dimension() == y.dimension()); const uint32_t dim = x.dimension(); float sum = 0; @@ -4711,24 +4450,22 @@ static float dot(const FullVector &x, const FullVector &y) } // y = M * x -static void mult(const Matrix &M, const FullVector &x, FullVector &y) -{ +static void mult(const Matrix &M, const FullVector &x, FullVector &y) { uint32_t w = M.width(); uint32_t h = M.height(); - XA_DEBUG_ASSERT( w == x.dimension() ); + XA_DEBUG_ASSERT(w == x.dimension()); XA_UNUSED(w); - XA_DEBUG_ASSERT( h == y.dimension() ); + XA_DEBUG_ASSERT(h == y.dimension()); for (uint32_t i = 0; i < h; i++) y[i] = M.dotRow(i, x); } // y = alpha*A*x + beta*y -static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y) -{ +static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y) { const uint32_t w = A.width(); const uint32_t h = A.height(); - XA_DEBUG_ASSERT( w == x.dimension() ); - XA_DEBUG_ASSERT( h == y.dimension() ); + XA_DEBUG_ASSERT(w == x.dimension()); + XA_DEBUG_ASSERT(h == y.dimension()); XA_UNUSED(w); XA_UNUSED(h); for (uint32_t i = 0; i < h; i++) @@ -4736,8 +4473,7 @@ static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, } // dot y-row of A by x-column of B -static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) -{ +static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) { const Array &row = A.getRow(y); const uint32_t count = row.size(); float sum = 0.0f; @@ -4748,8 +4484,7 @@ static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) return sum; } -static void transpose(const Matrix &A, Matrix &B) -{ +static void transpose(const Matrix &A, Matrix &B) { XA_DEBUG_ASSERT(A.width() == B.height()); XA_DEBUG_ASSERT(B.width() == A.height()); const uint32_t w = A.width(); @@ -4768,8 +4503,7 @@ static void transpose(const Matrix &A, Matrix &B) } } -static void sgemm(float alpha, const Matrix &A, const Matrix &B, float beta, Matrix &C) -{ +static void sgemm(float alpha, const Matrix &A, const Matrix &B, float beta, Matrix &C) { const uint32_t w = C.width(); const uint32_t h = C.height(); #if XA_DEBUG @@ -4793,8 +4527,7 @@ static void sgemm(float alpha, const Matrix &A, const Matrix &B, float beta, Mat } // C = A * B -static void mult(const Matrix &A, const Matrix &B, Matrix &C) -{ +static void mult(const Matrix &A, const Matrix &B, Matrix &C) { sgemm(1.0f, A, B, 0.0f, C); } @@ -4804,22 +4537,19 @@ namespace segment { // - Insertion is o(n) // - Smallest element goes at the end, so that popping it is o(1). -struct CostQueue -{ - CostQueue(uint32_t size = UINT32_MAX) : m_maxSize(size), m_pairs(MemTag::SegmentAtlasChartCandidates) {} +struct CostQueue { + CostQueue(uint32_t size = UINT32_MAX) : + m_maxSize(size), m_pairs(MemTag::SegmentAtlasChartCandidates) {} - float peekCost() const - { + float peekCost() const { return m_pairs.back().cost; } - uint32_t peekFace() const - { + uint32_t peekFace() const { return m_pairs.back().face; } - void push(float cost, uint32_t face) - { + void push(float cost, uint32_t face) { const Pair p = { cost, face }; if (m_pairs.isEmpty() || cost < peekCost()) m_pairs.push_back(p); @@ -4836,29 +4566,25 @@ struct CostQueue } } - uint32_t pop() - { + uint32_t pop() { XA_DEBUG_ASSERT(!m_pairs.isEmpty()); uint32_t f = m_pairs.back().face; m_pairs.pop_back(); return f; } - XA_INLINE void clear() - { + XA_INLINE void clear() { m_pairs.clear(); } - XA_INLINE uint32_t count() const - { + XA_INLINE uint32_t count() const { return m_pairs.size(); } private: const uint32_t m_maxSize; - struct Pair - { + struct Pair { float cost; uint32_t face; }; @@ -4866,9 +4592,9 @@ private: Array m_pairs; }; -struct Chart -{ - Chart() : faces(MemTag::SegmentAtlasChartFaces) {} +struct Chart { + Chart() : + faces(MemTag::SegmentAtlasChartFaces) {} int id = -1; Basis basis; // Best fit normal. @@ -4882,12 +4608,11 @@ struct Chart CostQueue candidates; }; -struct Atlas -{ - Atlas() : m_edgeLengths(MemTag::SegmentAtlasMeshData), m_faceAreas(MemTag::SegmentAtlasMeshData), m_faceNormals(MemTag::SegmentAtlasMeshData), m_texcoords(MemTag::SegmentAtlasMeshData), m_bestTriangles(10), m_nextPlanarRegionFace(MemTag::SegmentAtlasPlanarRegions), m_facePlanarRegionId(MemTag::SegmentAtlasPlanarRegions) {} +struct Atlas { + Atlas() : + m_edgeLengths(MemTag::SegmentAtlasMeshData), m_faceAreas(MemTag::SegmentAtlasMeshData), m_faceNormals(MemTag::SegmentAtlasMeshData), m_texcoords(MemTag::SegmentAtlasMeshData), m_bestTriangles(10), m_nextPlanarRegionFace(MemTag::SegmentAtlasPlanarRegions), m_facePlanarRegionId(MemTag::SegmentAtlasPlanarRegions) {} - ~Atlas() - { + ~Atlas() { const uint32_t chartCount = m_charts.size(); for (uint32_t i = 0; i < chartCount; i++) { m_charts[i]->~Chart(); @@ -4900,8 +4625,7 @@ struct Atlas const Array &chartFaces(uint32_t i) const { return m_charts[i]->faces; } const Basis &chartBasis(uint32_t chartIndex) const { return m_charts[chartIndex]->basis; } - void reset(uint32_t meshId, uint32_t chartGroupId, const Mesh *mesh, const ChartOptions &options) - { + void reset(uint32_t meshId, uint32_t chartGroupId, const Mesh *mesh, const ChartOptions &options) { XA_UNUSED(meshId); XA_UNUSED(chartGroupId); XA_PROFILE_START(buildAtlasInit) @@ -4995,8 +4719,7 @@ struct Atlas XA_PROFILE_END(buildAtlasInit) } - void placeSeeds(float threshold) - { + void placeSeeds(float threshold) { XA_PROFILE_START(buildAtlasPlaceSeeds) // Instead of using a predefiened number of seeds: // - Add seeds one by one, growing chart until a certain treshold. @@ -5010,8 +4733,7 @@ struct Atlas } // Returns true if any of the charts can grow more. - void growCharts(float threshold) - { + void growCharts(float threshold) { XA_PROFILE_START(buildAtlasGrowCharts) for (;;) { if (m_facesLeft == 0) @@ -5057,8 +4779,7 @@ struct Atlas XA_PROFILE_END(buildAtlasGrowCharts) } - void resetCharts() - { + void resetCharts() { XA_PROFILE_START(buildAtlasResetCharts) const uint32_t faceCount = m_mesh->faceCount(); for (uint32_t i = 0; i < faceCount; i++) @@ -5083,8 +4804,7 @@ struct Atlas XA_PROFILE_END(buildAtlasResetCharts) } - bool relocateSeeds() - { + bool relocateSeeds() { XA_PROFILE_START(buildAtlasRelocateSeeds) bool anySeedChanged = false; const uint32_t chartCount = m_charts.size(); @@ -5097,8 +4817,7 @@ struct Atlas return anySeedChanged; } - void fillHoles(float threshold) - { + void fillHoles(float threshold) { XA_PROFILE_START(buildAtlasFillHoles) while (m_facesLeft > 0) createRandomChart(threshold); @@ -5106,8 +4825,7 @@ struct Atlas } #if XA_MERGE_CHARTS - void mergeCharts() - { + void mergeCharts() { XA_PROFILE_START(buildAtlasMergeCharts) const uint32_t chartCount = m_charts.size(); // Merge charts progressively until there's none left to merge. @@ -5165,7 +4883,7 @@ struct Atlas // Merge if chart2 has a single face. // chart1 must have more than 1 face. // chart2 area must be <= 10% of chart1 area. - if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f) + if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f) goto merge; // Merge if chart2 has two faces (probably a quad), and chart1 bounds at least 2 of its edges. if (chart2->faces.size() == 2 && m_sharedBoundaryEdgeCountNoSeams[cc] >= 2) @@ -5173,8 +4891,8 @@ struct Atlas // Merge if chart2 is wholely inside chart1, ignoring seams. if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && equal(m_sharedBoundaryLengthsNoSeams[cc], chart2->boundaryLength, kEpsilon)) goto merge; - if (m_sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) || - m_sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength) + if (m_sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) || + m_sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength) goto merge; continue; merge: @@ -5212,8 +4930,7 @@ struct Atlas #endif private: - void createRandomChart(float threshold) - { + void createRandomChart(float threshold) { Chart *chart = XA_NEW(MemTag::Default, Chart); chart->id = (int)m_charts.size(); m_charts.push_back(chart); @@ -5239,15 +4956,13 @@ private: } } - bool isChartBoundaryEdge(const Chart *chart, uint32_t edge) const - { + bool isChartBoundaryEdge(const Chart *chart, uint32_t edge) const { const uint32_t oppositeEdge = m_mesh->oppositeEdge(edge); const uint32_t oppositeFace = meshEdgeFace(oppositeEdge); return oppositeEdge == UINT32_MAX || m_faceCharts[oppositeFace] != chart->id; } - bool computeChartBasis(Chart *chart, Basis *basis) - { + bool computeChartBasis(Chart *chart, Basis *basis) { const uint32_t faceCount = chart->faces.size(); m_tempPoints.resize(chart->faces.size() * 3); for (uint32_t i = 0; i < faceCount; i++) { @@ -5258,8 +4973,7 @@ private: return Fit::computeBasis(m_tempPoints.data(), m_tempPoints.size(), basis); } - bool isFaceFlipped(uint32_t face) const - { + bool isFaceFlipped(uint32_t face) const { const Vector2 &v1 = m_texcoords[face * 3 + 0]; const Vector2 &v2 = m_texcoords[face * 3 + 1]; const Vector2 &v3 = m_texcoords[face * 3 + 2]; @@ -5267,8 +4981,7 @@ private: return parametricArea < 0.0f; } - void parameterizeChart(const Chart *chart) - { + void parameterizeChart(const Chart *chart) { const uint32_t faceCount = chart->faces.size(); for (uint32_t i = 0; i < faceCount; i++) { const uint32_t face = chart->faces[i]; @@ -5281,8 +4994,7 @@ private: } // m_faceCharts for the chart faces must be set to the chart ID. Needed to compute boundary edges. - bool isChartParameterizationValid(const Chart *chart) - { + bool isChartParameterizationValid(const Chart *chart) { const uint32_t faceCount = chart->faces.size(); // Check for flipped faces in the parameterization. OK if all are flipped. uint32_t flippedFaceCount = 0; @@ -5307,15 +5019,14 @@ private: return true; } - bool addFaceToChart(Chart *chart, uint32_t face) - { + bool addFaceToChart(Chart *chart, uint32_t face) { XA_DEBUG_ASSERT(m_faceCharts[face] == -1); const uint32_t oldFaceCount = chart->faces.size(); const bool firstFace = oldFaceCount == 0; // Append the face and any coplanar connected faces to the chart faces array. chart->faces.push_back(face); uint32_t coplanarFace = m_nextPlanarRegionFace[face]; - while (coplanarFace != face) { + while (coplanarFace != face) { XA_DEBUG_ASSERT(m_faceCharts[coplanarFace] == -1); chart->faces.push_back(coplanarFace); coplanarFace = m_nextPlanarRegionFace[coplanarFace]; @@ -5327,7 +5038,7 @@ private: // Use the first face normal. // Use any edge as the tangent vector. basis.normal = m_faceNormals[face]; - basis.tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 0)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 1)), kEpsilon); + basis.tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 0)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 1)), 0); basis.bitangent = cross(basis.normal, basis.tangent); } else { // Use best fit normal. @@ -5385,8 +5096,7 @@ private: } // Returns true if the seed has changed. - bool relocateSeed(Chart *chart) - { + bool relocateSeed(Chart *chart) { // Find the first N triangles that fit the proxy best. const uint32_t faceCount = chart->faces.size(); m_bestTriangles.clear(); @@ -5425,8 +5135,7 @@ private: } // Evaluate combined metric. - float evaluateCost(Chart *chart, uint32_t face) const - { + float evaluateCost(Chart *chart, uint32_t face) const { if (dot(m_faceNormals[face], chart->basis.normal) <= 0.26f) // ~75 degrees return FLT_MAX; // Estimate boundary length and area: @@ -5467,16 +5176,14 @@ private: } // Returns a value in [0-1]. - float evaluateProxyFitMetric(Chart *chart, uint32_t face) const - { + float evaluateProxyFitMetric(Chart *chart, uint32_t face) const { // All faces in coplanar regions have the same normal, can use any face. const Vector3 faceNormal = m_faceNormals[face]; // Use plane fitting metric for now: return 1 - dot(faceNormal, chart->basis.normal); // @@ normal deviations should be weighted by face area } - float evaluateRoundnessMetric(Chart *chart, float newBoundaryLength, float newChartArea) const - { + float evaluateRoundnessMetric(Chart *chart, float newBoundaryLength, float newChartArea) const { const float roundness = square(chart->boundaryLength) / chart->area; const float newBoundaryLengthSq = square(newBoundaryLength); const float newRoundness = newBoundaryLengthSq / newChartArea; @@ -5486,12 +5193,11 @@ private: return 0; } - float evaluateStraightnessMetric(Chart *chart, uint32_t firstFace) const - { + float evaluateStraightnessMetric(Chart *chart, uint32_t firstFace) const { float l_out = 0.0f, l_in = 0.0f; const uint32_t planarRegionId = m_facePlanarRegionId[firstFace]; uint32_t face = firstFace; - for (;;) { + for (;;) { for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) { const float l = m_edgeLengths[it.edge()]; if (it.isBoundary()) { @@ -5512,8 +5218,7 @@ private: return min(ratio, 0.0f); // Only use the straightness metric to close gaps. } - bool isNormalSeam(uint32_t edge) const - { + bool isNormalSeam(uint32_t edge) const { const uint32_t oppositeEdge = m_mesh->oppositeEdge(edge); if (oppositeEdge == UINT32_MAX) return false; // boundary edge @@ -5533,11 +5238,10 @@ private: return !equal(m_faceNormals[f0], m_faceNormals[f1], kNormalEpsilon); } - float evaluateNormalSeamMetric(Chart *chart, uint32_t firstFace) const - { + float evaluateNormalSeamMetric(Chart *chart, uint32_t firstFace) const { float seamFactor = 0.0f, totalLength = 0.0f; uint32_t face = firstFace; - for (;;) { + for (;;) { for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) { if (it.isBoundary()) continue; @@ -5574,11 +5278,10 @@ private: return seamFactor / totalLength; } - float evaluateTextureSeamMetric(Chart *chart, uint32_t firstFace) const - { + float evaluateTextureSeamMetric(Chart *chart, uint32_t firstFace) const { float seamLength = 0.0f, totalLength = 0.0f; uint32_t face = firstFace; - for (;;) { + for (;;) { for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) { if (it.isBoundary()) continue; @@ -5601,11 +5304,10 @@ private: return seamLength / totalLength; } - float computeArea(Chart *chart, uint32_t firstFace) const - { + float computeArea(Chart *chart, uint32_t firstFace) const { float area = chart->area; uint32_t face = firstFace; - for (;;) { + for (;;) { area += m_faceAreas[face]; face = m_nextPlanarRegionFace[face]; if (face == firstFace) @@ -5614,13 +5316,12 @@ private: return area; } - float computeBoundaryLength(Chart *chart, uint32_t firstFace) const - { + float computeBoundaryLength(Chart *chart, uint32_t firstFace) const { float boundaryLength = chart->boundaryLength; // Add new edges, subtract edges shared with the chart. const uint32_t planarRegionId = m_facePlanarRegionId[firstFace]; uint32_t face = firstFace; - for (;;) { + for (;;) { for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) { const float edgeLength = m_edgeLengths[it.edge()]; if (it.isBoundary()) { @@ -5636,11 +5337,10 @@ private: if (face == firstFace) break; } - return max(0.0f, boundaryLength); // @@ Hack! + return max(0.0f, boundaryLength); // @@ Hack! } - bool mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength) - { + bool mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength) { const uint32_t oldOwnerFaceCount = owner->faces.size(); const uint32_t chartFaceCount = chart->faces.size(); owner->faces.push_back(chart->faces); @@ -5706,11 +5406,10 @@ private: namespace param { -class JacobiPreconditioner -{ +class JacobiPreconditioner { public: - JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) : m_inverseDiagonal(M.width()) - { + JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) : + m_inverseDiagonal(M.width()) { XA_ASSERT(M.isSquare()); for (uint32_t x = 0; x < M.width(); x++) { float elem = M.getCoefficient(x, x); @@ -5723,8 +5422,7 @@ public: } } - void apply(const FullVector &x, FullVector &y) const - { + void apply(const FullVector &x, FullVector &y) const { XA_DEBUG_ASSERT(x.dimension() == m_inverseDiagonal.dimension()); XA_DEBUG_ASSERT(y.dimension() == m_inverseDiagonal.dimension()); // @@ Wrap vector component-wise product into a separate function. @@ -5739,12 +5437,10 @@ private: }; // Linear solvers. -class Solver -{ +class Solver { public: // Solve the symmetric system: At·A·x = At·b - static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) - { + static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) { XA_DEBUG_ASSERT(A.width() == x.dimension()); XA_DEBUG_ASSERT(A.height() == b.dimension()); XA_DEBUG_ASSERT(A.height() >= A.width()); // @@ If height == width we could solve it directly... @@ -5759,8 +5455,7 @@ public: } // See section 10.4.3 in: Mesh Parameterization: Theory and Practice, Siggraph Course Notes, August 2007 - static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f) - { + static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f) { XA_DEBUG_ASSERT(A.width() == x.dimension()); XA_DEBUG_ASSERT(A.height() == b.dimension()); XA_DEBUG_ASSERT(A.height() >= A.width() - lockedCount); @@ -5859,18 +5554,17 @@ private: * **/ // Conjugate gradient with preconditioner. - static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) - { - XA_DEBUG_ASSERT( A.isSquare() ); - XA_DEBUG_ASSERT( A.width() == b.dimension() ); - XA_DEBUG_ASSERT( A.width() == x.dimension() ); + static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) { + XA_DEBUG_ASSERT(A.isSquare()); + XA_DEBUG_ASSERT(A.width() == b.dimension()); + XA_DEBUG_ASSERT(A.width() == x.dimension()); int i = 0; const int D = A.width(); - const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not. - FullVector r(D); // residual - FullVector p(D); // search direction - FullVector q(D); // - FullVector s(D); // preconditioned + const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not. + FullVector r(D); // residual + FullVector p(D); // search direction + FullVector q(D); // + FullVector s(D); // preconditioned float delta_0; float delta_old; float delta_new; @@ -5896,7 +5590,7 @@ private: // x = alfa·p + x sparse::saxpy(alpha, p, x); if ((i & 31) == 0) { // recompute r after 32 steps - // r = b - A·x + // r = b - A·x sparse::copy(b, r); sparse::sgemv(-1, A, x, 1, r); } else { @@ -5906,7 +5600,7 @@ private: // s = M^-1 · r preconditioner.apply(r, s); delta_old = delta_new; - delta_new = sparse::dot( r, s ); + delta_new = sparse::dot(r, s); beta = delta_new / delta_old; // p = s + beta·p sparse::scal(beta, p); @@ -5915,8 +5609,7 @@ private: return delta_new <= epsilon * epsilon * delta_0; } - static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) - { + static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) { XA_DEBUG_ASSERT(A.height() == A.width()); XA_DEBUG_ASSERT(A.height() == b.dimension()); XA_DEBUG_ASSERT(b.dimension() == x.dimension()); @@ -5926,8 +5619,7 @@ private: }; // Fast sweep in 3 directions -static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b) -{ +static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b) { XA_DEBUG_ASSERT(a != nullptr); XA_DEBUG_ASSERT(b != nullptr); const uint32_t vertexCount = mesh->vertexCount(); @@ -5984,28 +5676,24 @@ static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b // Conformal relations from Brecht Van Lommel (based on ABF): -static float vec_angle_cos(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) -{ +static float vec_angle_cos(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) { Vector3 d1 = v1 - v2; Vector3 d2 = v3 - v2; return clamp(dot(d1, d2) / (length(d1) * length(d2)), -1.0f, 1.0f); } -static float vec_angle(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) -{ +static float vec_angle(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) { float dot = vec_angle_cos(v1, v2, v3); return acosf(dot); } -static void triangle_angles(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, float *a1, float *a2, float *a3) -{ +static void triangle_angles(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, float *a1, float *a2, float *a3) { *a1 = vec_angle(v3, v1, v2); *a2 = vec_angle(v1, v2, v3); *a3 = kPi - *a2 - *a1; } -static void setup_abf_relations(sparse::Matrix &A, int row, int id0, int id1, int id2, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2) -{ +static void setup_abf_relations(sparse::Matrix &A, int row, int id0, int id1, int id2, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2) { // @@ IC: Wouldn't it be more accurate to return cos and compute 1-cos^2? // It does indeed seem to be a little bit more robust. // @@ Need to revisit this more carefully! @@ -6055,8 +5743,7 @@ static void setup_abf_relations(sparse::Matrix &A, int row, int id0, int id1, in A.setCoefficient(v2_id, 2 * row + 1, 1); } -static bool computeLeastSquaresConformalMap(Mesh *mesh) -{ +static bool computeLeastSquaresConformalMap(Mesh *mesh) { // For this to work properly, mesh should not have colocals that have the same // attributes, unless you want the vertices to actually have different texcoords. const uint32_t vertexCount = mesh->vertexCount(); @@ -6114,10 +5801,8 @@ static bool computeLeastSquaresConformalMap(Mesh *mesh) } #if XA_RECOMPUTE_CHARTS -struct PiecewiseParam -{ - void reset(const Mesh *mesh, uint32_t faceCount) - { +struct PiecewiseParam { + void reset(const Mesh *mesh, uint32_t faceCount) { m_mesh = mesh; m_faceCount = faceCount; const uint32_t vertexCount = m_mesh->vertexCount(); @@ -6134,8 +5819,7 @@ struct PiecewiseParam ConstArrayView chartFaces() const { return m_patch; } const Vector2 *texcoords() const { return m_texcoords.data(); } - bool computeChart() - { + bool computeChart() { m_patch.clear(); m_faceInvalid.zeroOutMemory(); m_faceInPatch.zeroOutMemory(); @@ -6242,8 +5926,7 @@ struct PiecewiseParam } private: - struct Candidate - { + struct Candidate { uint32_t face, vertex; uint32_t next; // The next candidate with the same vertex. Vector2 position; @@ -6253,10 +5936,12 @@ private: float patchVertexOrient; }; - struct CandidateIterator - { - CandidateIterator(Array &candidates, uint32_t first) : m_candidates(candidates), m_current(first) {} - void advance() { if (m_current != UINT32_MAX) m_current = m_candidates[m_current].next; } + struct CandidateIterator { + CandidateIterator(Array &candidates, uint32_t first) : + m_candidates(candidates), m_current(first) {} + void advance() { + if (m_current != UINT32_MAX) m_current = m_candidates[m_current].next; + } bool isDone() const { return m_current == UINT32_MAX; } Candidate ¤t() { return m_candidates[m_current]; } @@ -6277,8 +5962,7 @@ private: UniformGrid2 m_boundaryGrid; // Find candidate faces on the patch front. - void findCandidates() - { + void findCandidates() { m_candidates.clear(); m_faceInCandidates.zeroOutMemory(); for (uint32_t i = 0; i < m_patch.size(); i++) { @@ -6335,8 +6019,7 @@ private: } } - void addCandidateFace(uint32_t patchEdge, float patchVertexOrient, uint32_t face, uint32_t edge, uint32_t freeVertex) - { + void addCandidateFace(uint32_t patchEdge, float patchVertexOrient, uint32_t face, uint32_t edge, uint32_t freeVertex) { Vector2 texcoords[3]; orthoProjectFace(face, texcoords); // Find corresponding vertices between the patch edge and candidate edge. @@ -6412,8 +6095,7 @@ private: m_faceInCandidates.set(face); } - void orthoProjectFace(uint32_t face, Vector2 *texcoords) const - { + void orthoProjectFace(uint32_t face, Vector2 *texcoords) const { const Vector3 normal = m_mesh->computeFaceNormal(face); const Vector3 tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 1)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 0)), kEpsilon); const Vector3 bitangent = cross(normal, tangent); @@ -6423,16 +6105,14 @@ private: } } - float parametricArea(const Vector2 *texcoords) const - { + float parametricArea(const Vector2 *texcoords) const { const Vector2 &v1 = texcoords[0]; const Vector2 &v2 = texcoords[1]; const Vector2 &v3 = texcoords[2]; return ((v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y)) * 0.5f; } - float computeStretch(Vector3 p1, Vector3 p2, Vector3 p3, Vector2 t1, Vector2 t2, Vector2 t3) const - { + float computeStretch(Vector3 p1, Vector3 p2, Vector3 p3, Vector2 t1, Vector2 t2, Vector2 t3) const { float parametricArea = ((t2.y - t1.y) * (t3.x - t1.x) - (t3.y - t1.y) * (t2.x - t1.x)) * 0.5f; if (isZero(parametricArea, kAreaEpsilon)) return FLT_MAX; @@ -6446,16 +6126,14 @@ private: } // Return value is positive if the point is one side of the edge, negative if on the other side. - float orientToEdge(Vector2 edgeVertex0, Vector2 edgeVertex1, Vector2 point) const - { + float orientToEdge(Vector2 edgeVertex0, Vector2 edgeVertex1, Vector2 point) const { return (edgeVertex0.x - point.x) * (edgeVertex1.y - point.y) - (edgeVertex0.y - point.y) * (edgeVertex1.x - point.x); } }; #endif // Estimate quality of existing parameterization. -struct Quality -{ +struct Quality { // computeBoundaryIntersection bool boundaryIntersection = false; @@ -6472,8 +6150,7 @@ struct Quality float conformalMetric = 0.0f; float authalicMetric = 0.0f; - void computeBoundaryIntersection(const Mesh *mesh, UniformGrid2 &boundaryGrid) - { + void computeBoundaryIntersection(const Mesh *mesh, UniformGrid2 &boundaryGrid) { const Array &boundaryEdges = mesh->boundaryEdges(); const uint32_t boundaryEdgeCount = boundaryEdges.size(); boundaryGrid.reset(mesh->texcoords(), mesh->indices(), boundaryEdgeCount); @@ -6489,8 +6166,7 @@ struct Quality #endif } - void computeFlippedFaces(const Mesh *mesh, uint32_t faceCount, Array *flippedFaces) - { + void computeFlippedFaces(const Mesh *mesh, uint32_t faceCount, Array *flippedFaces) { totalTriangleCount = flippedTriangleCount = zeroAreaTriangleCount = 0; if (flippedFaces) flippedFaces->clear(); @@ -6525,8 +6201,7 @@ struct Quality flippedFaces->clear(); flippedTriangleCount = 0; } - if (flippedTriangleCount > totalTriangleCount / 2) - { + if (flippedTriangleCount > totalTriangleCount / 2) { // If more than half the triangles are flipped, reverse the flipped / not flipped classification. flippedTriangleCount = totalTriangleCount - flippedTriangleCount; if (flippedFaces) { @@ -6548,8 +6223,7 @@ struct Quality } } - void computeMetrics(const Mesh *mesh, uint32_t faceCount) - { + void computeMetrics(const Mesh *mesh, uint32_t faceCount) { totalGeometricArea = totalParametricArea = 0.0f; stretchMetric = maxStretchMetric = conformalMetric = authalicMetric = 0.0f; for (uint32_t f = 0; f < faceCount; f++) { @@ -6580,7 +6254,7 @@ struct Quality const float a = dot(Ss, Ss); // E const float b = dot(Ss, St); // F const float c = dot(St, St); // G - // Compute eigen-values of the first fundamental form: + // Compute eigen-values of the first fundamental form: const float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue. const float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue. XA_ASSERT(sigma2 > sigma1 || equal(sigma1, sigma2, kEpsilon)); @@ -6611,37 +6285,33 @@ struct Quality if (totalGeometricArea > 0.0f) { const float normFactor = sqrtf(totalParametricArea / totalGeometricArea); stretchMetric = sqrtf(stretchMetric / totalGeometricArea) * normFactor; - maxStretchMetric *= normFactor; + maxStretchMetric *= normFactor; conformalMetric = sqrtf(conformalMetric / totalGeometricArea); authalicMetric = sqrtf(authalicMetric / totalGeometricArea); } } }; -struct ChartWarningFlags -{ - enum Enum - { - CloseHolesFailed = 1<<1, - FixTJunctionsDuplicatedEdge = 1<<2, - FixTJunctionsFailed = 1<<3, - TriangulateDuplicatedEdge = 1<<4, +struct ChartWarningFlags { + enum Enum { + CloseHolesFailed = 1 << 1, + FixTJunctionsDuplicatedEdge = 1 << 2, + FixTJunctionsFailed = 1 << 3, + TriangulateDuplicatedEdge = 1 << 4, }; }; -struct ChartCtorBuffers -{ +struct ChartCtorBuffers { Array chartMeshIndices; Array unifiedMeshIndices; Array boundaryLoops; }; /// A chart is a connected set of faces with a certain topology (usually a disk). -class Chart -{ +class Chart { public: - Chart(ChartCtorBuffers &buffers, const Basis &basis, ConstArrayView faces, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : m_basis(basis), m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::LSCM), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) - { + Chart(ChartCtorBuffers &buffers, const Basis &basis, ConstArrayView faces, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : + m_basis(basis), m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::LSCM), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) { XA_UNUSED(meshId); XA_UNUSED(chartGroupId); XA_UNUSED(chartId); @@ -6780,8 +6450,8 @@ public: } #if XA_RECOMPUTE_CHARTS - Chart(ChartCtorBuffers &buffers, const Chart *parent, const Mesh *parentMesh, ConstArrayView faces, const Vector2 *texcoords, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::Piecewise), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) - { + Chart(ChartCtorBuffers &buffers, const Chart *parent, const Mesh *parentMesh, ConstArrayView faces, const Vector2 *texcoords, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : + m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::Piecewise), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) { XA_UNUSED(meshId); XA_UNUSED(chartGroupId); XA_UNUSED(chartId); @@ -6846,8 +6516,7 @@ public: } #endif - ~Chart() - { + ~Chart() { if (m_mesh) { m_mesh->~Mesh(); XA_FREE(m_mesh); @@ -6880,8 +6549,7 @@ public: const Mesh *unmodifiedUnifiedMesh() const { return m_unmodifiedUnifiedMesh; } uint32_t mapChartVertexToOriginalVertex(uint32_t i) const { return m_chartToOriginalMap[i]; } - void evaluateOrthoQuality(UniformGrid2 &boundaryGrid) - { + void evaluateOrthoQuality(UniformGrid2 &boundaryGrid) { XA_PROFILE_START(parameterizeChartsEvaluateQuality) m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid); m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr); @@ -6892,8 +6560,7 @@ public: m_type = ChartType::Ortho; } - void evaluateQuality(UniformGrid2 &boundaryGrid) - { + void evaluateQuality(UniformGrid2 &boundaryGrid) { XA_PROFILE_START(parameterizeChartsEvaluateQuality) m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid); #if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION @@ -6906,15 +6573,13 @@ public: } // Transfer parameterization from unified mesh to chart mesh. - void transferParameterization() - { + void transferParameterization() { const uint32_t vertexCount = m_mesh->vertexCount(); for (uint32_t v = 0; v < vertexCount; v++) m_mesh->texcoord(v) = m_unifiedMesh->texcoord(m_chartToUnifiedMap[v]); } - Vector2 computeParametricBounds() const - { + Vector2 computeParametricBounds() const { Vector2 minCorner(FLT_MAX, FLT_MAX); Vector2 maxCorner(-FLT_MAX, -FLT_MAX); const uint32_t vertexCount = m_mesh->vertexCount(); @@ -6949,8 +6614,7 @@ private: #endif }; -struct CreateChartTaskArgs -{ +struct CreateChartTaskArgs { const Mesh *mesh; const Basis *basis; ConstArrayView faces; @@ -6961,27 +6625,23 @@ struct CreateChartTaskArgs Chart **chart; }; -static void runCreateChartTask(void *userData) -{ +static void runCreateChartTask(void *userData) { XA_PROFILE_START(createChartMeshesThread) auto args = (CreateChartTaskArgs *)userData; *(args->chart) = XA_NEW_ARGS(MemTag::Default, Chart, args->chartBuffers->get(), *(args->basis), args->faces, args->mesh, args->meshId, args->chartGroupId, args->chartId); XA_PROFILE_END(createChartMeshesThread) } -struct ParameterizeChartTaskArgs -{ +struct ParameterizeChartTaskArgs { Chart *chart; ParameterizeFunc func; ThreadLocal *boundaryGrid; }; -static void runParameterizeChartTask(void *userData) -{ +static void runParameterizeChartTask(void *userData) { auto args = (ParameterizeChartTaskArgs *)userData; Mesh *mesh = args->chart->unifiedMesh(); - XA_PROFILE_START(parameterizeChartsOrthogonal) - { + XA_PROFILE_START(parameterizeChartsOrthogonal) { // Project vertices to plane. const uint32_t vertexCount = mesh->vertexCount(); const Basis &basis = args->chart->basis(); @@ -7006,11 +6666,10 @@ static void runParameterizeChartTask(void *userData) } // Set of charts corresponding to mesh faces in the same face group. -class ChartGroup -{ +class ChartGroup { public: - ChartGroup(uint32_t id, const Mesh *sourceMesh, uint16_t faceGroup) : m_sourceId(sourceMesh->id()), m_id(id), m_isVertexMap(faceGroup == Mesh::kInvalidFaceGroup), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0) - { + ChartGroup(uint32_t id, const Mesh *sourceMesh, uint16_t faceGroup) : + m_sourceId(sourceMesh->id()), m_id(id), m_isVertexMap(faceGroup == Mesh::kInvalidFaceGroup), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0) { // Create new mesh from the source mesh, using faces that belong to this group. const uint32_t sourceFaceCount = sourceMesh->faceCount(); if (!m_isVertexMap) { @@ -7072,8 +6731,7 @@ public: #endif } - ~ChartGroup() - { + ~ChartGroup() { m_mesh->~Mesh(); XA_FREE(m_mesh); for (uint32_t i = 0; i < m_charts.size(); i++) { @@ -7151,8 +6809,7 @@ public: - emphasize roundness metrics to prevent those cases. - If interior self-overlaps: preserve boundary parameterization and use mean-value map. */ - void computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, segment::Atlas &atlas, ThreadLocal *chartBuffers) - { + void computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, segment::Atlas &atlas, ThreadLocal *chartBuffers) { m_chartOptions = options; // This function may be called multiple times, so destroy existing charts. for (uint32_t i = 0; i < m_charts.size(); i++) { @@ -7222,7 +6879,7 @@ public: #if XA_RECOMPUTE_CHARTS void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ThreadLocal *boundaryGrid, ThreadLocal *chartBuffers, ThreadLocal *piecewiseParam) #else - void parameterizeCharts(TaskScheduler* taskScheduler, ParameterizeFunc func, ThreadLocal* boundaryGrid, ThreadLocal* /*chartBuffers*/) + void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ThreadLocal *boundaryGrid, ThreadLocal * /*chartBuffers*/) #endif { m_paramAddedChartsCount = 0; @@ -7316,8 +6973,7 @@ public: } private: - void buildAtlas(segment::Atlas &atlas, const ChartOptions &options) - { + void buildAtlas(segment::Atlas &atlas, const ChartOptions &options) { if (atlas.facesLeft() == 0) return; // Create initial charts greedely. @@ -7347,8 +7003,7 @@ private: XA_DEBUG_ASSERT(atlas.facesLeft() == 0); } - void removeChart(const Chart *chart) - { + void removeChart(const Chart *chart) { for (uint32_t i = 0; i < m_charts.size(); i++) { if (m_charts[i] == chart) { m_charts.removeAt(i); @@ -7368,24 +7023,21 @@ private: uint32_t m_paramDeletedChartsCount; // Number of charts with invalid parameterizations that were deleted, after charts were recomputed. }; -struct CreateChartGroupTaskArgs -{ +struct CreateChartGroupTaskArgs { uint16_t faceGroup; uint32_t groupId; const Mesh *mesh; ChartGroup **chartGroup; }; -static void runCreateChartGroupTask(void *userData) -{ +static void runCreateChartGroupTask(void *userData) { XA_PROFILE_START(addMeshCreateChartGroupsThread) auto args = (CreateChartGroupTaskArgs *)userData; *(args->chartGroup) = XA_NEW_ARGS(MemTag::Default, ChartGroup, args->groupId, args->mesh, args->faceGroup); XA_PROFILE_END(addMeshCreateChartGroupsThread) } -struct ComputeChartsTaskArgs -{ +struct ComputeChartsTaskArgs { TaskScheduler *taskScheduler; ChartGroup *chartGroup; ThreadLocal *atlas; @@ -7394,8 +7046,7 @@ struct ComputeChartsTaskArgs Progress *progress; }; -static void runComputeChartsJob(void *userData) -{ +static void runComputeChartsJob(void *userData) { auto args = (ComputeChartsTaskArgs *)userData; if (args->progress->cancel) return; @@ -7406,8 +7057,7 @@ static void runComputeChartsJob(void *userData) args->progress->update(); } -struct ParameterizeChartsTaskArgs -{ +struct ParameterizeChartsTaskArgs { TaskScheduler *taskScheduler; ChartGroup *chartGroup; ParameterizeFunc func; @@ -7419,8 +7069,7 @@ struct ParameterizeChartsTaskArgs Progress *progress; }; -static void runParameterizeChartsJob(void *userData) -{ +static void runParameterizeChartsJob(void *userData) { auto args = (ParameterizeChartsTaskArgs *)userData; if (args->progress->cancel) return; @@ -7436,13 +7085,12 @@ static void runParameterizeChartsJob(void *userData) } /// An atlas is a set of chart groups. -class Atlas -{ +class Atlas { public: - Atlas() : m_meshCount(0), m_chartsComputed(false), m_chartsParameterized(false) {} + Atlas() : + m_meshCount(0), m_chartsComputed(false), m_chartsParameterized(false) {} - ~Atlas() - { + ~Atlas() { for (uint32_t i = 0; i < m_chartGroups.size(); i++) { m_chartGroups[i]->~ChartGroup(); XA_FREE(m_chartGroups[i]); @@ -7454,8 +7102,7 @@ public: uint32_t chartGroupCount() const { return m_chartGroups.size(); } const ChartGroup *chartGroupAt(uint32_t index) const { return m_chartGroups[index]; } - uint32_t chartGroupCount(uint32_t mesh) const - { + uint32_t chartGroupCount(uint32_t mesh) const { uint32_t count = 0; for (uint32_t i = 0; i < m_chartGroups.size(); i++) { if (m_chartGroupSourceMeshes[i] == mesh) @@ -7464,8 +7111,7 @@ public: return count; } - const ChartGroup *chartGroupAt(uint32_t mesh, uint32_t group) const - { + const ChartGroup *chartGroupAt(uint32_t mesh, uint32_t group) const { for (uint32_t c = 0; c < m_chartGroups.size(); c++) { if (m_chartGroupSourceMeshes[c] != mesh) continue; @@ -7477,8 +7123,7 @@ public: } // This function is thread safe. - void addMesh(TaskScheduler *taskScheduler, const Mesh *mesh) - { + void addMesh(TaskScheduler *taskScheduler, const Mesh *mesh) { // Create one chart group per face group. // If there's any ignored faces in the mesh, create an extra face group for that (vertex map). // Chart group creation is slow since it copies a chunk of the source mesh, so use tasks. @@ -7513,8 +7158,7 @@ public: // Chart id/index is determined by depth-first hierarchy of mesh -> chart group -> chart. // For chart index to be consistent here, chart groups needs to sorted by mesh index. Since addMesh is called by multithreaded tasks, order is indeterminate, so chart groups need to be explicitly sorted after all meshes are added. - void sortChartGroups() - { + void sortChartGroups() { Array oldChartGroups; oldChartGroups.resize(m_chartGroups.size()); memcpy(oldChartGroups.data(), m_chartGroups.data(), sizeof(ChartGroup *) * m_chartGroups.size()); @@ -7533,8 +7177,7 @@ public: } } - bool computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, ProgressFunc progressFunc, void *progressUserData) - { + bool computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, ProgressFunc progressFunc, void *progressUserData) { m_chartsComputed = false; m_chartsParameterized = false; // Ignore vertex maps. @@ -7582,8 +7225,7 @@ public: return true; } - bool parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ProgressFunc progressFunc, void *progressUserData) - { + bool parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ProgressFunc progressFunc, void *progressUserData) { m_chartsParameterized = false; // Ignore vertex maps. uint32_t chartGroupCount = 0; @@ -7643,17 +7285,15 @@ private: namespace pack { -class AtlasImage -{ +class AtlasImage { public: - AtlasImage(uint32_t width, uint32_t height) : m_width(width), m_height(height) - { + AtlasImage(uint32_t width, uint32_t height) : + m_width(width), m_height(height) { m_data.resize(m_width * m_height); memset(m_data.data(), 0, sizeof(uint32_t) * m_data.size()); } - void resize(uint32_t width, uint32_t height) - { + void resize(uint32_t width, uint32_t height) { Array data; data.resize(width * height); memset(data.data(), 0, sizeof(uint32_t) * data.size()); @@ -7664,8 +7304,7 @@ public: data.moveTo(m_data); } - void addChart(uint32_t chartIndex, const BitImage *image, const BitImage *imageBilinear, const BitImage *imagePadding, int atlas_w, int atlas_h, int offset_x, int offset_y) - { + void addChart(uint32_t chartIndex, const BitImage *image, const BitImage *imageBilinear, const BitImage *imagePadding, int atlas_w, int atlas_h, int offset_x, int offset_y) { const int w = image->width(); const int h = image->height(); for (int y = 0; y < h; y++) { @@ -7691,15 +7330,13 @@ public: } } - void copyTo(uint32_t *dest, uint32_t destWidth, uint32_t destHeight, int padding) const - { + void copyTo(uint32_t *dest, uint32_t destWidth, uint32_t destHeight, int padding) const { for (uint32_t y = 0; y < destHeight; y++) memcpy(&dest[y * destWidth], &m_data[padding + (y + padding) * m_width], destWidth * sizeof(uint32_t)); } #if XA_DEBUG_EXPORT_ATLAS_IMAGES - void writeTga(const char *filename, uint32_t width, uint32_t height) const - { + void writeTga(const char *filename, uint32_t width, uint32_t height) const { Array image; image.resize(width * height * 3); for (uint32_t y = 0; y < height; y++) { @@ -7741,8 +7378,7 @@ private: Array m_data; }; -struct Chart -{ +struct Chart { int32_t atlasIndex; uint32_t material; uint32_t indexCount; @@ -7764,15 +7400,13 @@ struct Chart uint32_t uniqueVertexCount() const { return uniqueVertices.isEmpty() ? vertexCount : uniqueVertices.size(); } }; -struct AddChartTaskArgs -{ +struct AddChartTaskArgs { ThreadLocal *boundingBox; param::Chart *paramChart; Chart *chart; // out }; -static void runAddChartTask(void *userData) -{ +static void runAddChartTask(void *userData) { XA_PROFILE_START(packChartsAddChartsThread) auto args = (AddChartTaskArgs *)userData; param::Chart *paramChart = args->paramChart; @@ -7811,10 +7445,8 @@ static void runAddChartTask(void *userData) XA_PROFILE_END(packChartsAddChartsThread) } -struct Atlas -{ - ~Atlas() - { +struct Atlas { + ~Atlas() { for (uint32_t i = 0; i < m_atlasImages.size(); i++) { m_atlasImages[i]->~AtlasImage(); XA_FREE(m_atlasImages[i]); @@ -7838,8 +7470,7 @@ struct Atlas const Array &getImages() const { return m_atlasImages; } float getUtilization(uint32_t atlas) const { return m_utilization[atlas]; } - void addCharts(TaskScheduler *taskScheduler, param::Atlas *paramAtlas) - { + void addCharts(TaskScheduler *taskScheduler, param::Atlas *paramAtlas) { // Count charts. uint32_t chartCount = 0; const uint32_t chartGroupsCount = paramAtlas->chartGroupCount(); @@ -7880,8 +7511,7 @@ struct Atlas m_charts[i] = taskArgs[i].chart; } - void addUvMeshCharts(UvMeshInstance *mesh) - { + void addUvMeshCharts(UvMeshInstance *mesh) { BitArray vertexUsed(mesh->texcoords.size()); BoundingBox2D boundingBox; for (uint32_t c = 0; c < mesh->mesh->charts.size(); c++) { @@ -7942,8 +7572,7 @@ struct Atlas } // Pack charts in the smallest possible rectangle. - bool packCharts(const PackOptions &options, ProgressFunc progressFunc, void *progressUserData) - { + bool packCharts(const PackOptions &options, ProgressFunc progressFunc, void *progressUserData) { if (progressFunc) { if (!progressFunc(ProgressCategory::PackCharts, 0, progressUserData)) return false; @@ -8178,8 +7807,7 @@ struct Atlas int best_x = 0, best_y = 0; int best_cw = 0, best_ch = 0; int best_r = 0; - for (;;) - { + for (;;) { bool firstChartInBitImage = false; XA_UNUSED(firstChartInBitImage); if (currentAtlas + 1 > m_bitImages.size()) { @@ -8212,8 +7840,7 @@ struct Atlas if (best_x + best_cw > atlasSizes[currentAtlas].x || best_y + best_ch > atlasSizes[currentAtlas].y) { for (uint32_t j = 0; j < chartStartPositions.size(); j++) chartStartPositions[j] = Vector2i(0, 0); - } - else { + } else { chartStartPositions[currentAtlas] = Vector2i(best_x, best_y); } } @@ -8312,8 +7939,7 @@ struct Atlas } if (m_utilization.size() > 1) { XA_PRINT(" %u: %f%% utilization\n", i, m_utilization[i] * 100.0f); - } - else { + } else { XA_PRINT(" %f%% utilization\n", m_utilization[i] * 100.0f); } } @@ -8336,16 +7962,14 @@ private: // is occupied at this point. At the end we have many small charts and a large atlas with sparse holes. Finding those holes randomly is slow. A better approach would be to // start stacking large charts as if they were tetris pieces. Once charts get small try to place them randomly. It may be interesting to try a intermediate strategy, first try // along one axis and then try exhaustively along that axis. - bool findChartLocation(const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) - { + bool findChartLocation(const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) { const int attempts = 4096; if (bruteForce || attempts >= w * h) return findChartLocation_bruteForce(startPosition, atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, blockAligned, maxResolution, allowRotate); return findChartLocation_random(atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, attempts, blockAligned, maxResolution, allowRotate); } - bool findChartLocation_bruteForce(const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) - { + bool findChartLocation_bruteForce(const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) { const int stepSize = blockAligned ? 4 : 1; int best_metric = INT_MAX; // Try two different orientations. @@ -8390,8 +8014,7 @@ private: return best_metric != INT_MAX; } - bool findChartLocation_random(const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned, uint32_t maxResolution, bool allowRotate) - { + bool findChartLocation_random(const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned, uint32_t maxResolution, bool allowRotate) { bool result = false; const int BLOCK_SIZE = 4; int best_metric = INT_MAX; @@ -8446,8 +8069,7 @@ private: return result; } - void addChart(BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) - { + void addChart(BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) { XA_DEBUG_ASSERT(r == 0 || r == 1); const BitImage *image = r == 0 ? chartBitImage : chartBitImageRotated; const int w = image->width(); @@ -8470,8 +8092,7 @@ private: } } - void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated, UniformGrid2 &boundaryEdgeGrid) const - { + void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated, UniformGrid2 &boundaryEdgeGrid) const { boundaryEdgeGrid.reset(chart->vertices, chart->indices); if (chart->boundaryEdges) { const uint32_t edgeCount = chart->boundaryEdges->size(); @@ -8526,13 +8147,11 @@ private: } } - struct DrawTriangleCallbackArgs - { + struct DrawTriangleCallbackArgs { BitImage *chartBitImage, *chartBitImageRotated; }; - static bool drawTriangleCallback(void *param, int x, int y) - { + static bool drawTriangleCallback(void *param, int x, int y) { auto args = (DrawTriangleCallbackArgs *)param; args->chartBitImage->set(x, y); if (args->chartBitImageRotated) @@ -8554,8 +8173,7 @@ private: } // namespace pack } // namespace internal -struct Context -{ +struct Context { Atlas atlas; uint32_t meshCount = 0; internal::Progress *addMeshProgress = nullptr; @@ -8568,16 +8186,14 @@ struct Context internal::Array uvMeshInstances; }; -Atlas *Create() -{ +Atlas *Create() { Context *ctx = XA_NEW(internal::MemTag::Default, Context); memset(&ctx->atlas, 0, sizeof(Atlas)); ctx->taskScheduler = XA_NEW(internal::MemTag::Default, internal::TaskScheduler); return &ctx->atlas; } -static void DestroyOutputMeshes(Context *ctx) -{ +static void DestroyOutputMeshes(Context *ctx) { if (!ctx->atlas.meshes) return; for (int i = 0; i < (int)ctx->atlas.meshCount; i++) { @@ -8598,8 +8214,7 @@ static void DestroyOutputMeshes(Context *ctx) ctx->atlas.meshes = nullptr; } -void Destroy(Atlas *atlas) -{ +void Destroy(Atlas *atlas) { XA_DEBUG_ASSERT(atlas); Context *ctx = (Context *)atlas; if (atlas->utilization) @@ -8634,14 +8249,12 @@ void Destroy(Atlas *atlas) #endif } -struct AddMeshTaskArgs -{ +struct AddMeshTaskArgs { Context *ctx; internal::Mesh *mesh; }; -static void runAddMeshTask(void *userData) -{ +static void runAddMeshTask(void *userData) { XA_PROFILE_START(addMeshThread) auto args = (AddMeshTaskArgs *)userData; // Responsible for freeing this. internal::Mesh *mesh = args->mesh; @@ -8710,37 +8323,32 @@ cleanup: XA_PROFILE_END(addMeshThread) } -static internal::Vector3 DecodePosition(const MeshDecl &meshDecl, uint32_t index) -{ +static internal::Vector3 DecodePosition(const MeshDecl &meshDecl, uint32_t index) { XA_DEBUG_ASSERT(meshDecl.vertexPositionData); XA_DEBUG_ASSERT(meshDecl.vertexPositionStride > 0); return *((const internal::Vector3 *)&((const uint8_t *)meshDecl.vertexPositionData)[meshDecl.vertexPositionStride * index]); } -static internal::Vector3 DecodeNormal(const MeshDecl &meshDecl, uint32_t index) -{ +static internal::Vector3 DecodeNormal(const MeshDecl &meshDecl, uint32_t index) { XA_DEBUG_ASSERT(meshDecl.vertexNormalData); XA_DEBUG_ASSERT(meshDecl.vertexNormalStride > 0); return *((const internal::Vector3 *)&((const uint8_t *)meshDecl.vertexNormalData)[meshDecl.vertexNormalStride * index]); } -static internal::Vector2 DecodeUv(const MeshDecl &meshDecl, uint32_t index) -{ +static internal::Vector2 DecodeUv(const MeshDecl &meshDecl, uint32_t index) { XA_DEBUG_ASSERT(meshDecl.vertexUvData); XA_DEBUG_ASSERT(meshDecl.vertexUvStride > 0); return *((const internal::Vector2 *)&((const uint8_t *)meshDecl.vertexUvData)[meshDecl.vertexUvStride * index]); } -static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, int32_t offset, uint32_t i) -{ +static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, int32_t offset, uint32_t i) { XA_DEBUG_ASSERT(indexData); if (format == IndexFormat::UInt16) return uint16_t((int32_t)((const uint16_t *)indexData)[i] + offset); return uint32_t((int32_t)((const uint32_t *)indexData)[i] + offset); } -AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint) -{ +AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint) { XA_DEBUG_ASSERT(atlas); if (!atlas) { XA_PRINT_WARNING("AddMesh: atlas is null.\n"); @@ -8758,8 +8366,7 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh // Don't know how many times AddMesh will be called, so progress needs to adjusted each time. if (!ctx->addMeshProgress) { ctx->addMeshProgress = XA_NEW_ARGS(internal::MemTag::Default, internal::Progress, ProgressCategory::AddMesh, ctx->progressFunc, ctx->progressUserData, 1); - } - else { + } else { ctx->addMeshProgress->setMaxValue(internal::max(ctx->meshCount + 1, meshCountHint)); } XA_PROFILE_START(addMeshCopyData) @@ -8875,8 +8482,7 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh return AddMeshError::Success; } -void AddMeshJoin(Atlas *atlas) -{ +void AddMeshJoin(Atlas *atlas) { XA_DEBUG_ASSERT(atlas); if (!atlas) { XA_PRINT_WARNING("AddMeshJoin: atlas is null.\n"); @@ -8904,19 +8510,19 @@ void AddMeshJoin(Atlas *atlas) XA_PRINT_MEM_USAGE } -struct EdgeKey -{ +struct EdgeKey { EdgeKey() {} - EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {} - EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {} + EdgeKey(const EdgeKey &k) : + v0(k.v0), v1(k.v1) {} + EdgeKey(uint32_t v0, uint32_t v1) : + v0(v0), v1(v1) {} bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; } uint32_t v0; uint32_t v1; }; -AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl) -{ +AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl) { XA_DEBUG_ASSERT(atlas); if (!atlas) { XA_PRINT_WARNING("AddUvMesh: atlas is null.\n"); @@ -9026,8 +8632,7 @@ AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl) return AddMeshError::Success; } -void ComputeCharts(Atlas *atlas, ChartOptions chartOptions) -{ +void ComputeCharts(Atlas *atlas, ChartOptions chartOptions) { if (!atlas) { XA_PRINT_WARNING("ComputeCharts: atlas is null.\n"); return; @@ -9100,8 +8705,7 @@ void ComputeCharts(Atlas *atlas, ChartOptions chartOptions) XA_PRINT_MEM_USAGE } -void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) -{ +void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) { if (!atlas) { XA_PRINT_WARNING("ParameterizeCharts: atlas is null.\n"); return; @@ -9132,7 +8736,7 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) XA_PROFILE_START(parameterizeChartsReal) if (!ctx->paramAtlas.parameterizeCharts(ctx->taskScheduler, func, ctx->progressFunc, ctx->progressUserData)) { XA_PRINT(" Cancelled by user\n"); - return; + return; } XA_PROFILE_END(parameterizeChartsReal) uint32_t chartCount = 0, orthoChartsCount = 0, planarChartsCount = 0, lscmChartsCount = 0, piecewiseChartsCount = 0, chartsAddedCount = 0, chartsDeletedCount = 0; @@ -9234,8 +8838,7 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) XA_PRINT_MEM_USAGE } -void PackCharts(Atlas *atlas, PackOptions packOptions) -{ +void PackCharts(Atlas *atlas, PackOptions packOptions) { // Validate arguments and context state. if (!atlas) { XA_PRINT_WARNING("PackCharts: atlas is null.\n"); @@ -9277,8 +8880,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions) if (!ctx->uvMeshInstances.isEmpty()) { for (uint32_t i = 0; i < ctx->uvMeshInstances.size(); i++) packAtlas.addUvMeshCharts(ctx->uvMeshInstances[i]); - } - else + } else packAtlas.addCharts(ctx->taskScheduler, &ctx->paramAtlas); XA_PROFILE_END(packChartsAddCharts) XA_PROFILE_START(packCharts) @@ -9479,8 +9081,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions) XA_PRINT_MEM_USAGE } -void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFunc, PackOptions packOptions) -{ +void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFunc, PackOptions packOptions) { if (!atlas) { XA_PRINT_WARNING("Generate: atlas is null.\n"); return; @@ -9499,8 +9100,7 @@ void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFun PackCharts(atlas, packOptions); } -void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progressUserData) -{ +void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progressUserData) { if (!atlas) { XA_PRINT_WARNING("SetProgressCallback: atlas is null.\n"); return; @@ -9510,20 +9110,17 @@ void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progress ctx->progressUserData = progressUserData; } -void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc) -{ +void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc) { internal::s_realloc = reallocFunc; internal::s_free = freeFunc; } -void SetPrint(PrintFunc print, bool verbose) -{ +void SetPrint(PrintFunc print, bool verbose) { internal::s_print = print; internal::s_printVerbose = verbose; } -const char *StringForEnum(AddMeshError::Enum error) -{ +const char *StringForEnum(AddMeshError::Enum error) { if (error == AddMeshError::Error) return "Unspecified error"; if (error == AddMeshError::IndexOutOfRange) @@ -9533,8 +9130,7 @@ const char *StringForEnum(AddMeshError::Enum error) return "Success"; } -const char *StringForEnum(ProgressCategory::Enum category) -{ +const char *StringForEnum(ProgressCategory::Enum category) { if (category == ProgressCategory::AddMesh) return "Adding mesh(es)"; if (category == ProgressCategory::ComputeCharts)

      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

    pXCh$$Ffz(N3_|=_4H2sADBwsVo>= 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

    DltK%oCPF3?ZacO6qT;c1hwBz+|&1J-12s7 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

    MzekM1rttbF^yaS{0-m2Wb}Qe z`g}id=9GSFINS~1cA8A?8y1#M?Zde6ay&Zm6e{RpR=;1P z$kQs+leA*q42?yV3ml49?&RNg7DLv5_c6=bh}}DR6$+WwVzAa?jybBxeGcAEtyN<1 z__Y^&7hY0Ox9kqhkhy^&H=FVJpK7#lOyPM8GWcP*3&qD;an|;mxxEeJsFhL;*}Ojt zJJh>L?ac42a(xiE4j-p>JwdcWRGn?zstclH=AlH^B|)m}TnL#uiCa2foU>axn{3*3 z16|+d;>}g}Xetwe_I@Ym8;@o5{K*v7sJ|aw7P9n-4#ibP)2OK0b3)JaeALrtC$^imOm%}HllhQ2`y1@@>mp{tuLS+t>acyTFy<>9LB+0% zg5@<5Tz#hmXTDVjM>8hSciWbc5?=@EZ261a+NXp;Nj9*^L@Y4)-gDE*s7sXFPhFiqQHDWD6ov;fX;LV#Ou=<(ee0;oo15?U&@dqIq_!tS(phwh$|{C&Rx9g=FCdJ92vI zYdYAj4EvUq;IE+Z$Qrvrp&sG0l8XcZNrv>Bq9zV*a)5)Q1r1LQ=3xHyUcs?Vk!arf z1D#~Dp?*&<5qbL)<6Q30Evc65N&^cnN5PIW?0PI%*n66Mp0R>v7oMhl`nRE4IGX2p zexxg=cw?DXJ!$Y;LS``{+{$bDc>VbTfl`M9$Z2k+Zml=)iA*bfo3w~5yj)6#^+LhJ zd@@%toyNi~d-U$<9^RYL0AqZY>N1dNKaJTcYV8;YGE@{;USZQ;V&bWR7{g)^OX;ltPyU$D`AZF<9#TjilLydXzLSV=9VH}j7K?3(2r*fJXK;=&)gbKf*ugQW2(U5Mzj+tYys?Wy4TP1@; z+9TO+6pb5a>A~w1ejSvm6Wo|!B-my-1(!ULCnH6(ar?*9m@K6LT(}wU=Cwhw08{Rg zjR*JfQ9Mq2=77TnhFCT1O$wKM#$ksXoOQk#Jp=)8tSOw??yktJ=~)EBQ+1fJuVtb6 zO)O08u7#$hLd=}6NNvn-5y=;0QTC29jn|H*_D_`Y*KiN3YRm})Z~F;J=NZ1vMtI}C zKv12NLlbz<_1TF?-`@0L?bj}%K78J3Z>2Mb>uop*o_F+S!C%@NuZ!+apYlwSLr{|Q zl)gANhIgS*?A_3dhCx5*)GkSAZ<&t9vRhcma|R98&H30|x&?PVO~LDyvr#lt0v6K>c1!M!BCih|KA$C|cwU4rBCTlG;9M^0kY0_m*S4*)}vjs>gW^yKs(AHNZ#p z1pCQ)BB|c5fu8fe<5h*R*raI-Jr&pK{%r(=eWak|of&=>T}Gc=o57^24U$_w&qC4^ zUqK4HgyM@r8WA=FUEAf^-zK)O_EAUuEQb&75om|=Dxi;iSyF@;Ly_fIHdcGY^qVAiv#kJ zyDrT&OqS-3(>W+Ksg{WEK8)u!tz}oeV^B8N9^S_^Q0l?ajju<^y4rGZNfUygN9nBY z!%RUE2=Mmd6Lek3U1+~5$xLQ=e{!)RovStzRDDJ9Ie&NVkoS`)m;D0&gOi!IXJQNu zk7qtasgUdY&Vk;l8Mw`^giSSa=l9Se{B31QPLF*?ysJY&@%A<9Zt;O08n{Cb#2azgVlvf&PWJ-=Eocgsln~=w3|QE8NikP;xI&0hBF~DQhqL6&;1%D0xypoty}T99xU7d2 ziYxitrWHx=i^e+Rx(3%d{tf9xMRdpAFkCAgi&o0cC>nha<7(8<^GqhqyX#2YvxRYO zi#*9d6|DKOhqQef6@)b{1iM9#iSZFbHg3N@K3L?2hmHz;#ToQ{qA8O&&YgJ~8$XGC2sD@oJ zS@6c*lIPUdvRCH_m?^{?LX7@EPrzG?JP^_N>ZTLWaHbv5iTaFFBJ~iyeE?=Dg zc^uCZo{2vk3~-I`4@_Ek33G3M#5dazrAoHa)x013yLAZt*m;@0T=ELe4eFCo|Cg}2 z&jy~1CZf`J-c_P50pHgILPXOpB#kUIw-yp5Ro-K8I2v$qVuPK^HL5Km#%Ygr;8wn! zMO(j|MqA^Pc;az3$$54kMLv0P`H{ylUS5X36KVr2W-1)( z^(8|~Q^0DBHWM*k1I)Qza?LOWX0+x&w8TBCB~lE50WaC*>yE)cwPN_e?+^AhC-Hh) zGbqj6jar@4Ij`GAAg&UCY2Np6)6hbQ-E@V{+!9UNC(7ZR6*8EuU}vEqA43&&8j04F zx3t}PF+?P6hqgVdVc`M_M=o{1ipnnf#a)wmwOo|Bt}>6?zj-oK(yh)ch`57)x9)@f zaY@jXCIJ^pdrAHJWl#?-yptk?UVgQlcl7wf{&k1&`(!-~d|8S?@sDsp7tf?|EW~8q z4Swb|3;(sbP~E|$=v}Id>-}znLw-2TygQCjS~{N3Z(X26`TEcpZN(`|Pi6E>4d}fS zO{lljA1389P#scFO)QOJhkAx!J9CGgtJTHs4$AW@J6Yp$Z@j>@Qt4;8w0++)6NZoNgUXS` z5WMRWoI0=q*7EGD=4K~)TC37x&0kaIMWH4$FnblFlzg4Pcl|*gxxV4guH|s;xe>^= z7vZE=Rdn|L@zisiCps87K>O_}D5SXq!tBnI@^fXFRa6ZV?{CKG^RbaVZmDVti@mH0n&Ah|Gbg_MwiZHBs#Z2{Rp{} za~vz4i_-h$FR{&j3Ko=^v$wPxaMOEnXgSFD`hMu(t*rO-e%CBE%2tQC1kFXAuk*R# zc@wz4{7dN3>XqJI#t8_s=Uy_KQ zx(^j!l;CEYH%4c5LUtdYS(w3dr2abxg^3?Q+VKPVZ=j1kyGsm`9;)Exo$}cFWek1u zDVBBC4+GJvaCD+ESnF3sF1i0{u((nIb(=4Ny-y)H=9iH~2VZu1?0B$go=w^(h(Lp^ zCK#^FfKw}G;DT$ibb5&=S+i3J&jzo6EHQcRZK4qKuz0_IKfX)G_=)^9pEt!K$Zc`u^8pav?I+rnHeIntUq8!In*&<*Zy@L{L` zcaD2R;x2tceU*01Ka`AL*jOC<_#uYQWvE-A1Kta>2RoT`@K3hK{4yCLW-~<7mZnpm zu~wLMHXhHb8e$8o(-@}14`#>r*?r37Q0z+|d`hQf>fp;BV%fPK8@fg=` z4l3?T+3|CS%+5C0!{zMf7`FAR#WB@$u%}`&J+dSmf`3K9vh#;<^~`T{8Iuar(qEH` zo)fs?S1Z5o##=19EJS=l6;7H5m9c z#S_=={YT@UhiK$$~(fkZfQ|M{h(e03nWkF(%L{_q&j&%#i;`#rkYErfdt z_8_qIH)6cdB zM0iy+(lyC&SW7^T$Q{EN;RHza$>+0M{5iVa5%hW9h%fm_l+stwd`o4VX%j@Mc9}v# z<34tM*CP0FLKIapuh0{=YMfkPJWlPpPri346MS}smY92k$mlI>Unk7;X%rAapClgh zJ4LWh6=nYsqX$GVw95ugi?*zP7TL9*&F~qH?4~|}T$2B(&LBf|{7xAi!R&h>vsR?Q2+gmp>qbp1GH zj8!S!;eQ45eijK%oP239eaR!NvlyU@=7kBc%@htT;Q8s_JgG`r8s>)Ulgud;v*)$o z-m4b)TJa+9K^4WO&_=58(2-8qb;P3ZRS#A!oK5xavBXSkCTjF3Q01V-upsmdCZBHP zdn<+5u(pBRJ*f^I%m2`4Dd9l1_XzB_-N3ZDr|{tw4Y0H5C9%zJU}zBtpUbLFhknkdtB*6Em2smUea!VDTF#FBoVLFUT8wJ1$cMd_A% z^n$QDE!sPc>+UdyD^cs=g{wL@Y5665yVL|zN7iD<@piO|c|p2;G-;0gSkBw(4CL#) zB$FIFQT?_r&S>)_vO`}XMz$G6rlr&Ur+?CMgOV8k@+c_$y@+>S<oa&ZCONU21CqEK&?5?By?q7l>wuc2T?)}9t2Yo^HsWA)% zPXwbwW1#7wB2J$@0Plnz(bq9%FnjS+5SjD~r!5qthQHP_BYH=v($~W@?&C)8oVz(^ zxuuzkS4VIm{7fCR?KpPx#5FnRHTct7h-)}g2-hC`M{m7KLB*{1;QILuS=n7i?@XS~ z{MOXM6t%x}_^KHuJh;!wHysh6X)1KQc}+f7|Dgu_Im_d%HHfJHLtkfk&LRF5Xb7yh z-%iuGei=oE@!0}TEZi}1|8cn28x2`Y47gExgv&zs#NaJ0` z&#ccAJ!hV8b#rD)fv4Dj37Hb36i{B1>#;FK>b2MZDjndO@_s~6G3hXxZu(}XF0=!;u;&D;-zQ>!gb?@i$a#8XIiD?^y&qfB-jSz1326V^ ziaX|)g01gZviNN*&z@}}3d=q4gsrAP)=3O6INV|Pr>c>LXI|*IU=Q5av&DmN?cm6= z7)P<0v*6rKXSyKAAv;<~fMe_tdXig_nc4NJy)W{AFgRSH{f&Oz?z zSiUc01{PMn@L;$dBToIGvy(f?-8kM6_k1GXWsSjAXRcuVmVb2UMg~kvn8{VWPUkbu zDi|Vifcv8(&2!Om2})kaNxBnZ`HKVWlvkTkxkn8GJDs4Nf78*>OQOF@(s0#!VO%FL z#{`cvxc*@k`DfQoHWgK4(UWKJRWue|r}I6ZIu^RM{7`jO94_0ckM4p};-J)s8>3or zm%kDG3>XEmRRZkpyNNRbmtp^S6VB9j8xCr(f!ky2k^b<;pxs*BQE459`48~qo-jNS z`h{4JDsZ`4dR+X6t@uYtj}!efA4P@_VP{PcOna}wym%jhOvp=Bd;c6zPA_BR8z zD-p^se8MfeWtiNxIdty8X}Y|s00NTBuwN|?B6}p5oNZ(!PH_9>*%x4<5 zED~f&hA`km9dSIsnfFOP$_^U`r@x+uP9(}_($ zE_q>=h^7`9*r6SZMQ$7C%l#CNRv*9kn+AQk&O&j9zb zm=1AHI8|dax$xgbNQ~>E=MtCGtqO+(F(Yc!Y3iV0Bb!X}>)^ zpXu@MRSoCeQs|>~eq?{#csw#EgRXcN2VZLJ&62Ab=G#<9_G-jo=%X$~*s~s92+2_U zQh9W+Nu!l^)wEHe71R16>Gi3m^m0l7TqwDWsb_KoEqm%L+Fr(kp2{gyTKW-NRrg^+ z^90h`yBLXbEnPE3hSlvmfMV@;sH9j7+%x+R*Pbn+-i9Xy@4Ga)?a^^$t_IKKOd7{6 zZ5zX=Tv~vGV$+#z;-a8+hH%MFn;@y67CJT3srj;r+;fi`7*paWDO<@=g&EjJqu zeE)!Ve(7*W6P%#5)t@LEk0lLKGtusSF|EG4l7^q9g6SO($o+auHgHn^4J&P3oax1sA6~vOWdvtvJY6(kNTYg?^j=O z*}qhJmUq&y_m6|z7hTR>p_d)Ge+7n5HY2RthVEx8h~?Cy_{eA@Y`ZFkYF~rcm!qG_ zx&jCGWm_)#NnK{6TVu(g2w$8xbvjpGe+TQN$l@&Tx6y> z?*IJ^Hyh8yIvGXU)A$~w8-S19 zRlNBr3O+4wrLJ1Vu+gg(ChSXs$K|WA%-sVD>eR7UM~QiQPK4b16DBw)Ed+iuwJ^Q- zI=Py#l=MG}gpzbAa@Dv-knA>wEdHv8zhdS<)^0s8`7F#06`aMUs2_Z*ACbA? za$MO_A5Jo`nS2ai%f%P0=h}p9KtEB7yZuKQyRPRE?V}ZVH|!8RxS;{mWey&TXvQr= zZ>ay|xllLS##VQ%fu0}#;NHGbaPO7E_c|#!?wuHV7DQr#NEGTzPT>;okAv@B)3A;x zayOGZ@Y}fqpx5R}r5`o5g@E#9pKAH~PnN*(pRY;GWGik{EwVjo#ng>@`^R3LEhG-RFg=32Q=_hk(u6(8& zoNnx+Yj)kD6K}1?p{sLH@oxpb5w`;7=Xdn9l;P&8P6I9D<0vNH?LhGNSw5d)bnnHMGfmg)IyZBXH>Cb!FiCN_ysELu0qhkKqzY+WM!q4 zq0K*@zN`~xjvI8*p!K6{s;xM*uZcr0D;ziTXG=LPf9PC14KHW>rA5_?xjbP-F5}`o z;-E1OH*QWr?dD!SugdQSif(9F-Ak4%AEfHL70{+#8xS4uV8=VLQLp-2PrWI`0bG^X0+D8$M$qvjv!i>ql+I9VIkGz-yC zsqv_I%MhOZS%c-eo^bx>eSr_ZzP(l;T+6!6;JE&QfcvSz`y*ZpDj$dntY$W0>R(@r zJ0}ydZgvTrKATHRcK=72jz+jVE`r!y6bFw}{RHqh``^clV32=L5H@PbP2qfSmRbkh zk+z1rc(;=zlr5!Koq_wi*cWd8^<+C~3K})PB*vP}u>8+Kype8%F%l^-XnzxnPKuF& zdRa!=C6pCC&_wTRm=p8)lS!#@3``RK0xp?a0+z0Uj=dLA*IAA{4(Wp#YVWZ+caT-f zR%Xsi7GlxXLKF%64D};Dr2D`Uobi4dOg(MIv)BsJkqpC<76mfLnMLh-eRN#)2S49r z@b|JVGU`Gx(@}{^EjTCWUOu0DrtLx8U#oLjiD6vv-ksd{Cu1>mHE`BEXCPklB0jA@ z&B><(agP&Aagv-1O7%_RJolx;p~zxz$Wwu14zI9TOPf10D-OT8?Lx7I^$n$cf9d^o zQuy-uAo@>mBvbM-K-o~3yEU{8eV*4)CEa>@GCzr^`zE7(7mE%?rR0`ED6)NFINZMr z_x2lce|APgaPkY<@ADXoEqSki z%o#7v=^XYWSIgv>)25MR-%t%q`VxjRu2Nj>k06v;_mS2q3!zhMC{8&LjfGAkbVC}? zwh{VHJKm_G(=1J5wq+f|?AwK(j`MfN(n8D#&tgAKhUsa;53pNhD#@KY6P5%&Lgif| zbfr%xt*D5@f{P`vrg|D?g= z0}iHe)b0j3VEYBU^(tv+k|N~DrhsktI{H*k2qU{buv7E2*d*ucSYb33mpZnP%J?fF zlN5|T((M!iqb-V3fR--R=eEf#qqadesA_N*ZnQc{)yw~*Z^l<*#xX_6I`@!v$@NlI zP^E1HGH5tm1PmG`lkcHB*%#?qke4xz@e#fRwyu01$9*ivH*V2;_Xpf{L4w=W8vvaa zG32t~1U}+thU}bJyj7~imGLuqj+QPnJ5on*%jOgNEl(0m4%f1mtX-(_r&wA#8cUhg z`6Os~J{3FSf&0}D!`Qv6L1EAZ`ZY#y;_f|&>63`L(*RlWvygR|x{EHIybgCfz6}dL zNi!M-dmuSX9%gE0!tS+q$d{T2ROfXfzKrMBsE77EPx2m}J3bFoswTlQOKX_KvjRkG zx8iukvus7*Ib!hNL#SNSNc_#Nl@Ju zdIVfuI+maS9;!x@J=&r;eDE#1SY!$O`(+Gkv=ZPm-GD>qq~S|fq=j3}To#L@nC{#6 z;gV}6&#bJbi}E#aU)5QZ4QAOl7zcrBS25g%K{%g_*(<_1OEFhcVyD10v?QXYO9~2V z`1$sU4)_+Ea+WbgSj`=SX64!V{N-|<9~OmrDk0FQ4s`752{g|06}csU0&-T0;0)10 zf!EJmsxR`FZ8#BuY!2^=GTDJnKWE|XzG;|sM;A?YWC=7^Z)SJ?{6PW&6tLB9J6u@T zPyWZydH7TLhGCov5wc~|P*P}6&Ux-PBN?TVQYn%sNs9_CWoOSavk4I;%6aZLvl1#L zDw;}*_WG6hy??>^ILG_E_jBFX^}VdV9w1w+f0FNk({N)$58an@44*z-NuU26#Ntd{ z8vR5RMQ1$55Bd}E&}ns2GvhQQ`Sw7-uBBxC$`ml;Tq`bBGjOG9Bt3t}iEbKvf{`w# z=`BlFo}|%AtZkl&(({*+Z{ve;^}=)*U7E&aC-;NE$PI6XP&~Y54ZC@z7DnqXL^8*e zUB9>q#|u*MmWC@G8;GIZT<|gzL%P=l^_H9SPsV)4 z3$D>PQu-BRj^xs(*Dr#_$1HksRD{hQ{s|8G69opdd!b{ZDkEbliG!yv!TiiYXb~Hx zLmDQG3(;b{3?ylQ!)2m4Bb3hR=AH)yNeDE4Pr}aJq%EKB(>=)xp@|k^uTLSai4LZC z$C|A0$)k_TbK%<|V>YdE4LkX07Dl~H$4NK8P&(-zmHnp7x^S74n=j>1J!lpyTRe}g zy)HqA_BB(u%FxmuN^rF<4^RADjaSOWVc6Ul?@bb*tl6YArhql?pQHK^O_Q2fh#7Jf$^%C*KsW&{pvpI@hvyA6=Wru)~ zc`jORQzqN=o598C2B|(g0sipQLEL!^<4k7a$Fqu9V^KthYqL@Nk~t+mpHuPtP8|FK zyrkAJWc7RTUEmS?%rSYNFaAL_=6T@nW3R}}0!895D#5xN)=|BmH!=16Rb1laCzv5J zMlCo`LM(Teu$DaprOP;8oAX^#QuCg6ijBkRH8HqRuNO}*_(75ub)%@*dVH2}fa+OG zuv<8vs7l)`YH`GfVLc>q(u_92jb&#A$3{02rLWgNM@!*z7`(awiz55++KZC1jIYe%x7~zqlRW9t2!; zNSuCNxSq^ZDg?F0Q)J-%FTQ~DLQUiH$>;7&gm>b;IL=Qn*oeBWYFTQI;^Z3&p!DT4~HTnsPY<)=hOHGuEd7X^d++Fd>@1f zcSeYaYsV`BBHacy>4V$ls$u z;@Ko$MxN_#+{Et6(qf;!IK}l7M}d|3aS%%V2p4_!Lf;=p>`3jT$?I<5@wo}qeE2he z>fYHn>im<$x?QKvKi6=%#NIDSII*9xgP$6^=T00IZT`Oxi5ASiK1f@c5!N03pM_mQU6qLJY9eD9=}a#Cj?YS zQ%}BZ{S1; z6>J-^p;I%if|05U{@I;{7bHU&h4+o5`;P*v4Kvv;t1#?2{vS2x@ z8ZXKiB9GSuz0YN_{LLk@{=g)dR`>_6m6+kefdml!qDn418Dm4N1+liWW0y#|kstLH zWL;Sy{w?*OKTU57ngZsqvC@k`YFq}id4-b$K6{|$+8t=#T1;lodP^N5-t*Ky*+b0q zEV^U+JF-+el>EE8LNH5DjLM%Afw$A81Pg+>vvTJ`_<7k5{kLqSB_;jjgt9NJe8h)q z*XNKv{VmYn(*=fgJUF^fjegs#1tkvmL1k|{(NQab>Pk_Z@;Z@J>&t<`frD`8S|j=A ztBV0P`S{Rg7rk3j!!bNQ(6x*N-2Bsx8fod+`&kZE#6RPb<`n*hC`YjQ+0GyBzDGAz zae2hXIgsojFBqy(rYky&+m8sdgPrN9t=EcSr(cnpvmJuARbK`E z1+w_d;iPqZa_Ti@IA3mSQXoBeu$@Z% zS51?0KNAUUJNjm)8cyr2!DS`{eE)JCHy533!T5tpuC`yC|(^BBpi#xuv`@^YcHSy zdoEDbsh#|BT(5T5Cj|_XnSv4_2Wk9*5S$(9Nj|(U!uh{@vA|A|pX)FaienxNevQs# zH%42tiZ_DU?+G1ncJp}n`CbAx%4!jx{!ip)nG>D){((!!$+hQ);la_n)D-wPMBrc2W955?4*63^j6GYE}JaGT3-4nupLc@xXr8Bu6?Uv zO7aY*AZ`-8*V7PaI=%tH8a=Xk!AmmBQWwrl8pBbC4`g{qA6&IRL5q)#(6u^?;P@vM zEOBcgY3{llr++d@ex-?Pg6@-ZLy6>}sW8*(IEAij$RuOw7a-m~mCiU@hP57MFz=`c zxR;J+?>L>KSN65ThrKV+P38x#v-!<=XNB%WWA;f-V&|oGkcy-*kc|Go?|;pCuS>U+rymKVFA zZqpdbro`a#Izu+{*DXBuZae12XYi%|coH|;TjT}PCm44ljk*W!gT7FXrPs^7PbB0~ zZKzRjAp9l%SalAz98-g)3y-k;?jGK7z7_r;C*FQj8Pf;dny9?84nM-n(_%e0*<+Ov-`&A=eV*B_P=#X`p9^E<*^^ZniMUxTE zE&G863jXl-U=EDT&}KHOl+fG;NjNvT1U}zbPIkUC#(BrD!gB%FO+N1qJ#t?YUngCr z>S7bom1Abm7VdA|UqS{uWY9@l0%UCV@)tdRN&>dllEiFhocD4POcbi5FaH$dhPZf~ zzHKo%YcE7I&ig~|x}WqyT?qf@BQ?Q1&XeZyb{y;7Ur9~pkI@OLQut=~Y^*L*fff&E zd=wXj6K(A17e^5^>gW>;n~Dphho_UoB`eTt{F%iQ+OMK{pB%m1n~hqX*J)61DRvdU zg~Pte;2x^RZ_YjoGly-++f*@7J3mayn}&E_-mHN(*ERTodq8AA)cT zPe^w-LHu&ckvHCo1YAzRRjups;HFZ%P^>|_7P~XiPPTY6(2WGMnUGX%_W!to-Gb^Mv zv#6Mey}#E(m##DGKPL^1jFTAY^-^rfBQA;9tHU@4^kevFir~u0Z=k+Fgw=Ow$4*sm zIK6xoYE<5WF@I_3b3cQTK7Yt@?I3y}N1pxq{0=Ew6Ai;(@6x8@S*EJc@2wz=hN^ z_*tTl;OHi6c6($Y*o%uY)xOfKk4Gc*DcS_(gJpD`bp!b^JC3l^bLiK`Eb10Lj`C|& z33EXfHdWuHi=5j-g_fX@+IX1I&_c?EPhzz1b;1u(V=f)< z5hO1z$GpsE^hMAfGD}sKHoiG3h`3kBSB>}QJX}HK>c}zv-av8KSi2do3O|AIb8@&o zxJmpM>wZI1SOHCoj-;LMuR}Xe4?TV_;&zX3aYl)>JVb)APg_;odNIK&%hr zw^zcZzhO9QT?k+D)D*ONyA(9bRbY3$4q=SNm`CYH1+y_9WfhjPPqoFEO@{wqa;z1* zI<|sV)z~pJJVtTd(aGp`eBu=?Qj5>kQepOoM%Xw!n;limf-jn(pspH<|MJ}!#j{Vr zvVS~|+qxDje@Ehxx6wFhERQGrm``44Ucv2m{}3tXBJ}BExs1s+Hf$ru3(MGn?~*#P z?Ux7GcSzvdad&aGiVRyl?gPy|S3>PK@tEQR(e$%kIv!OBfR?o%(dCFAeH$*$`2101 z59jq`$*Z&2y)p#%JsiM~hl}Z-iOQ_&n^o-n)DbLr-iY#t+fcCKG}eEQ0&O8X>@u$6 zSfkePqdOEY7Ony9jyNpm_kg<00e=4OV7hbVWN=*Nh>vBrvceS|xYJ|a6l&pZ6cYZC)IwR$}i zSH`n5*1|Q*Q=o2piT~Co0yb1ipV-^LEc?xBt+_=eGsC#RGp)ckmv%JS#^M zb&{x@T0*&oVpNn<#kKkklmtY=JWP)u_PI(HYE~IvvJn-fnn) z^9M<7o=>}OJp;eT&-r!N*U}9kAK==$637}OU773c9TAhe4NY@K-Qko7aB_o#gMh z`EW2hKGJ}>x9%Q2;FwDOm3$_Hy?an=S0>@PhmxV@*?3?!{Qs@?O`Q2$==8QZ7FCLJBj!lyoEJ=gNXm_;642PoZR{N9Puaw3x#=bSI!wbb0k>X?cIIfiSP|Mb-P(F;|XE29edrR^Mw=iCGhl{xfqRTx~l z9|u`(_H>_9T76XfTr8*zB^O?N;OjL?!0g)8MSJ8cv3+bYVCz>hWqucqxX*&z_2z=X z&Nv8r5D86n3=O|&#maXV!HnOWcX9qhWD7;uDe@+m|7QSGH&0-DB|p=~7aHv8V}tmh zozSdV%kW)!Dx|Kqqq4J=*o@a(Ay)r3q;q}lZ^oCRVGBaL-bB8i+fmdjxd6L|mDuVd zE3niu2l^5&pux^8v@*X*zJGlMyDz?h%62ofzqpKS*dR~5r^JprBX$M3r^O>E?Tlkgf|IyD6 zigA7hr46MG^!DN)RFoFRx@iKE*j0c!k8aW_Gk38&Z@j0m?ss9~l2F#ZEE4pK8x~ud zuVHl$6%nZ`Ct?4qh1BwKC(X(gMy-EWAYPKi+xzNC)ithPb>Vjmb2=tygar^Z30SW- zB_eox1uk*V$#bI+QfyHI^;S0Qx5+UmxuAih-8N(jRer!n$@jc~jw&kiUX4!O{0}o( zL!6S5f;$;wlJU)eoQ#Ra8h!{&-gUYDf%RK*si%)x|N29&{a8Tre&nG${VlL@y-!B3 zrJ%)_G5ok}2(gdmVN=&-z6&Q#uhQ3`pU*3jCjBr77VzMUstH)M#6f>>A#N~aX+UNi zQNMla4Vr21_UWA`^_8sC=U; zPI9fGW8*&4M>!X1-Kw`7UpWe{c!k59xk4>3zR0vnGDU_(L% zNf~bqPt8X7|1|1QUCUbVeHPN?Id|~F9*%M2xsBTkdK3BVGAy)ghlV}Z$(&_e2YKio zdcO6IplPQByJ-C@xLdjl7Wr*Q|7AOf?&}OZU-p&eW;zp@bLr6kND6K|-cG(5DWLy` z5aOO-56SMm0*RHMz`Z|)?tKwJKfVI+I(8rJ;ziNbD~gW8O-#(4R*3rXj$AaYg15^8 zLFGai?Csr!30kgjRk;y-&-8<<&O7?e?lA!m1O5%|mx96cC`>T!flsgesqnZobY^;} z;N2!zxO_9*H+I11+ty)O$V-wIcZt5%kD=k$Yv6RxO>j|_!`an`(6rD99`HTMB^!!r zgHnu{{vWbQ+?ZVFCE(388Dd+08kV>2z|a5Yk_0Dhuve3YH6?SP;Hm=L2#KUMe%pC& zNy_-UaXg&sFXlVOZ6PMjp@NtR56IrNl5lYEAsp$C#k-cR|#vsfif^QJ$c!4u!XqG!eMs2~MWYXp#Ip#&q9Rb+-`I=Zw}ql4y5 zHdkyTe98+Jq>bk^rOT7)){SBKvjCWV-aj6u5rM<8()1 zCSk5L`0QK<%fp|-@{IfR`08h5e2hKsr%?~yni+(*jX&d9K{R^lIk9kbJ{x@G6+Rpl z!bz`UsoRBe5Z~O14ooYxDYHYFO`P6!D+p6ppTM0~tElc9V^aC@53RqylgqH*gFZK% zdWY3NaoolpTC`RKX64x7je%v|U2oEPbp|(QVU?F~-{yJVsUPwzr;Tb))@Q@8vSu@Q_~)dH$h(!tVd zIjgKCk7t584&XITXML&yr$P*f%XS$&=b1s)_^zZ*qTcYP@gn}49}N>8iNG<%sVF=9 z1o`t*47c4>hm!OIIHWoq<(hXB8<*p#dxYS2rzkX=VUIStb$B%35ITQO$HNy1{u&mc zuLDo<_p?*k>h`DgT1J~;MaBTVMgB9EU$~BTPd4F=hz^Q_;y91ab)O?V9(_qPx0!&X z^Cg=3ZWZdzcnQk7GBjIF6c@E>b7!eL%1Ljb}!x9S->3P)j)=1)}8Hiq$b=TX-z z3ny;x1jWXDXq=mgYoyyCqb?i*Oy3C%JrBYopIqMgvz8DmdjiHCiw2Ft&EPe!n#}sQ z5kJ4_#!uY)X~|1TcI*;&&#KQPLYW+2&ifCyTj{~7xAm|*IUYuz^iie!S%$k0ebq=vDZot<_&L0yUT}QV}c~^ zTh@Rl&YvR%Q`68c{M`py54VCkkE<;=}Pk4U~3kVhe#As}fAU9-smGrWRT

    o2pm*Shpm|IKLYv$8vj;u!-=N0t~+pb5cuxHF1!`ptMPHZM0r zP-N%r2(8fB$o@jtKI@I%7{wt3tlr9=K; zBhx`Ya{VpqC$9m!4tHqgpN1bNjo`DI6gj-9n_ic^Pv1Uig#gZr^32Bj zrr9FX_zH{lsAkW3eE%{BcMsO%k1d)cbYltpN6%l8xR8V^Uwc78{bs?BMN8qp+CuW@ zQUG71zKDCKDG1dBpn3W!;^^)Lf42F8Sc)QU5Ao)FG{X4t^K!C!Ne@kocLdA1HY8|W z1d&{JNl?=<6Avifq#BiR8ZrlEF2j{^ReYWs z*D0Va${H6KGG?0P^|co`*6A`6CU(RX#501}SbKj^iPt3IC)@ZB9MwROs)Vl7k5Sii zv*6P}5s|!XDyWJ52Gxf?fW=~OIJ5gboQ+t+d>EO^WXo`zgoH_qw66@arSvpu*O$TE zJrDRpsX6@RPx4@vlQ-c4NhN%yBZS-Z+|EX^~6EW z#AXsOC7Q2vGXb=9EJ60k30j(%Kzu&khSEs~V9AgX%IArJfsY3!GiA`Wss!RcdlO;t z74T5=2>i&nO~=J4vs-K@VvONkj!RxkN@8wv{%-|HnHCAz8CCSQQX@U6FAMr7o#5}0 zH?$|>96!9ildfAk%D*7$OxjoWqv8Z}Ufc?`%u-T0vlw z%RTS8b^Kcy3hZ3FE%-|2CLG#SjhbdZ1cAb*Vc^daaQoxTS9NJZSLJR&z~~UY-S?HM zT#bg#ibT}kA)t+?jBpzFe}HzkV6&Mb{7ZUImMh*N7tj9?)Hbe%Nr^K7mj)20^;dAH zQ53|xykP~mf4hCGOki_S5%!e|v9AWI&^eHs*H7J|ff;o~Tpfo03m{P0ss5Rr6uHEl(8jm13t-7tiMy zXR(6QdBj;?b63b&J{KpsGzb#JUQ^k`on-&=S?vD3Lg4V_F@Nv69K12SnH+jkfhDIy zFZp~3*y*t9drRfao&gneKj~?Uu8->Jq-)*w( zW(BOg+(gRuw$h5ZJXqEc4&EOUq38T=JXvNBahD9}>6j3*cBd-7KG7p#xbzl{yx)Ym_8J_|p@jU3-is#@*01%Ib^ z;>X}-T)ZQge`;wOS$*jywjHa$_d^jFA@LvGq1uF_-5S)|K_C1toJ6Cx65v-pz_IDW zcv0D&ouQzGr2|2zd=BZ9*LSE=(h&4~OBN`%KM+J8YU1*>j@b3Pg>--;y!{l8`8f~y zGHTwm)}D(H~3yN4U{<6#PQ|yuI z@zAk;DzoFF9=jmd46}(QoN~WUPRYNduQ_hZwE2zDW*CKG%r^efDdt#`Jc-dgcoDXz zXW*>&HW1e%#hb_Kf=%}r-z2aCChYXXiU*;v(oY>kYQ@>pSGKag;cCqTpDBB-y~4GMd#nUf9rO#IC4uxgVee$aBo2(E+R#^7YO zottT$Eu|T~NUHw9VXU$B{Q*)aA^cnBIk zK1+i$E1*75n~`n~qn*CSpgYf#KDc2>*F|NLR`=_?mE|*G;q@+}(Q%l@jLz5;u9M**+21>k&6mg}i^qpURYxjD|5L*|{ylEctTeR!WX;sx$*e)x48SsKDI222ogN=L~3RgrX({RJrQUJO~S zE9laX3y74P5VZey9XIZHMNa38GCMb4Tk>l?+;M{yU*cmmBR4K@yVAdlt zqij4zPmZ9{k3#C#nf)ZPy^;9ho+~Xsr7JtoFpYWM&<>Rs=dzAoO;Fr2lVkCSqHp|K;F-p;&%e)NHBJ$B zX1FLGxObRX{x_b)M~7pbL^`N$I!;GU?nV-mj*pobFyHVGc=l82AF6>?trNi5@*0aV ze)#Qtz427F2O8d3jZKSwksS*Od9t6ohr8$F ze;HiAYC|Tv)yCo?&adU*Ylc(5?11F?uKe}C&+_FBf1;nn4RUX%D7#Z+HM}47=XrOg z(cjrui12CFvP?x8g}NLtTCp0kbs9n6#(+sO8b-a`kEHx23)78G!n((o=)i=vbo)wy zpfKb--CsM&(?5gcSgRHs)z<)aY9229Is?Qqny@a+mBc^V z0Et$1M04{=`1V+g_87b+Q|)I%l6E{%ncqUZ_9?*9S|OkvA5qH?*u9%Iq43~1wmA9` zojD4)GToD4QH}#lx#_i-(*dttQ&fUwpYiLT6E(~}ZVLy0)m7N$d z_dQBm3Vg7h%g*i$PC+Fa!8iFVjhg>{5y8~=^(uFAX{?*oZd87616|8YJfJyIqq&gyY&o$cR3F=E9S z(mg4lc|DNkFTRRTg8_g6xt=Vn6ztgr{tyw%5EE zsqQ=69GFAYmj(l?RSM3b(Re;B9dyUpk_sO_efP-*=9MRsFM>ou98N-?Z9Uw)^_kuq zd<3CHoG1>B3HI6Nkj7unal@xfl+PRwmozyqp5#i*>dt`8uHW!sWd;i0F#xafL-6)X zF<Ykf z&(0H=*m?qly~N>RpE71wrGR(qSzPZsfdq98!6ESs&hNBD-gcdh8FS7M z=`lX<6Kh3m|2?HePrK;f(j{>Dz9H65xKi(bU;@Utd4NaSG#dTSk37@j*p%u=P^U5+ zHL8UeF^(1dD6|mnEYkq1p)n${;5>hU&M=9sI0Qe&lzAF#Ip3>$A~bLr>!2nV$X`UH>m<9h;=^47J;&*x>WMgh}RDFTE{z zcX9^UJ(d#a=$DhQS_$%i^G3JG&0|JI{}Wtaw*bZVu7I}+n^4R`7o&WqWAn@TWJhuh zJv&noIv2bUbVPJR(6b7Df~PqoDg;v%=^;8adkN%99R`QyE2yUVl4=|G*57a1hTALd z65gNz{kFY=UJ9s#qzlLJRKY$x+`onXL*mig0FQf&aip)FyxjVj8A$-@f42Ps9(u%11;a|M7*GTdd=a|+xK*!P6(cEF@alV3vh{9 zJ}rB&4^ur}k-k5dz^~YWR_-{?3;C-B`+QfDC3bg6yzp&|a@1ojFD76I*UKGjdy?*) zmqMK1l$ctV>cYsLGBV&Y8y}vyNmQElBY9H^b~g$jsJn~!Klwz9OQPXtv=H8%v4?fq z{{x+s?jl{Y9e7pp?DHFXVCs08oP<_BI_8n^OV{b(oyGXt^dP2Hhw(*Pj?zOXxjD{3 z84iVQgO!GRY0B=WxPkuxljKBM`YxHI-PcC-8~Iq197_`KYSkw$H^$PzPMlpJ&K^8p zNNdhNqc`@ig=q)JgHvv9y-c$?T0N=cH~CG(!-Fk+v2orsaPb@neA{oj?#+B0koPAp zqW9_4huM&E%nV*mJVJk0eSr6s1XoLnFy8eq$ow2W&QT79X^!=D=hZx--JC#o1xT_% z_#L_%_;gl~J5kCrfbL!2>ExG`_;jVhmuZ{IZ)puwb3 zMFUoV(KabK(s+vMR;0k1C*ANYVufIBz$k1vE6+g1L>SY{f#7Aj)K;UGwhvu|VnH+6 z_1}Gv8JWd=)HPz_ef61J+6@>%IG_HMWOCZ>7v^1^iLDz<1$)N*#=JuXSYW_o^UQa{ zo{Qq}^>rWV3`^ucoZ|u0mK_2M@(9^3H!M24h>qshfvn|Zc(L>_h*iucOcIQJ%+;PBguibcp9<7hkXC(MFp@;Q18p}|7WJxR;%{c|4lz35bRqC@Y{$N9IuWd zlXCH~{Z{N5;ygkHXJCtzElH@~kBxE0RO;I&dN$7k#yVaLUi#G4mQ%J>81^ zdUN2Q{Qde$Sr&&EW{^<9K{}irhP>J`7?8>(vQS61I*5XAG1ue$VmBs#e*%zn7)IGs zXyWmRW-{{yVdpFA&AQasW{n59*qyL7OX5K3l?8w5 zar?91^p*H&o>Z+i=+(Hw%WDnvkVH3)jn)RIZydWjm=&l*SHdrsNuW9!1;RVjnU|dv z7&(0*TCP5bA1dRa^4xqB`&&vk-CczB(?=*z>=iv=_#XQQWAVKDL3;F{E&E&34Y%yK zp<67}*$EHlVAbAR_#xsVEz5Y#4^S;cseMy$_5n%qZsaC~DMJFW;NQfmisK5s9O27- zIf=>!y11jQ6cX2@Qxa1IP2Xcta3_XN-hB(7pO3*%zcwhH&oPb{>97NBfRSx3wCKVp z$zR?{JC2$`{-`yI*@U83b}q@~dUd85Y~`|V!i==8B*xg@r6c>JN&NnY0`pbt;kq)w ziUkkocFybkVEZ`Ukxlx{)i!lzVDTY1`(qTYj>QoP&sgGFuz+#cG6hn2#_;Ut7HZ^7 zG0kThYCI0b^Yc$&_Z~4c@Ona>*87raLr!qEa*=7 z@PVl~8!%Ogp1t@Vy!SR^L)#PaQM)I~B==x(u_&h@xRX1jMR-b20qjOZ>GLNdD9D@% zk_pDxd(@2UK}PU;X@?KH57oca^@APrHskQm6J*chcnoYI^o(Q>Y&bXzUd88;WXf8^V~dPqK1N*3*PB;F>b@TRPo)T~$p2R-!Z8=L!J z`niJ3%Pxes=O!_R8yo2pfjvptW{V**9T57rkbmOn0Il5{3#XzNfRNNg`10)W`)?r%Y5mEts(5p@gJ~DsGimp zD{+ivX=?h#l9~(r!FO>m9ob$^Wjb!qNy(D9^?VJfaZV@32^-0cfML?~F_*(~C89ZZ zw~1CL;mbaghvjxr^}iNYVYiDR?t5(sy&r3^<xDp1pc`qPSHVT@0p8>j_2lK#I zIGij6#!Uk_jVF%p7iU6wrxW-${DJo%!p6lEp`FJh-1||8E&o1)xJJ4{k;E)E=09yV ztA*Q_Kje7&QWBIToPbv=WwGg87%|{78GF4=P)GPTd99qxe?DJ@?aff2VSoK_<^~~F zyYU-e_niT$8!$)1jy&?1%P#KzGt@QV$NfOoUhM*RM_wctQD5;Usf%4BWCY z0_*SAaBEE?#1EO#{*D_Y-*Ql36n-2Fy$9)q-GwwYToZGw67k1-jsfeajrV#5q~)A5 z=*U#jfx-olAJ`0y$)-?~y#NMMDsfZ%F5x;ut2%Y0<)L@GwvnA*s-T0{ruP)OeCC_v5Z{TwD?&X2jZf#h*V;R2S z?(OMn?&O@K2I!9L12xl|5R+6du&6NyvnxB{xQrJxcvzs-W+5hg@-^b4m5hrH?x1^2 zZxO>y^0XoKD=qX1#_s`lamRvJ{Et`6z%61u>XHsz#_@Q9qpi^+P?c$2V$FBgoR7ci zJy5IGh^@>KX4M~z!jMTIQI-8p9)!(cloI=4caJ#OUeje{L$YCV&3htzJA|p0lV`LX zAHq`M%T!Ws6)vuI=VlaJR(?h@CJrB_Jk^)DKA;_^|5V22XAw|5dj$+_Z~331GY!P* z>!P@skV1w+6bg|j#B=s78bmZ9Nh&m_;jfg6G7lLdC3A@=r6elu*;knwr9x66i83@$ zDn-5b{pO1guIIVu?6ueWEr?ndf*)>I5P|M_aIAhn!_2n{$~7v9y!Q+KuC)-{wFn*+ znZi|K7Ox{Jai_MuWzU)$!^PQvxXKUtx&Ig_|**R>rbMPebRuiUC zKa`k*xjdusx;L6?q@l0zO0wucCpqIc1l+^R_>T8k-_(C2_ye^V6y*s1hb(xViNl=< zYB+gi5<7JQ-zlVa90Nb-GVClD@a|a#yH^J>c7b1ES{>kgXTutv4*hw-m>GgS*| zrK;o4;Vs@v8)$Zn&_#{7HsKbW=nBObo%`9*?qMF$x(gQ!tY%cdC{p#uv3OM^nD?~t zy_9l2c#g}$=zWnmc~>a57VpE=JYz#iaU$xxYGXg@$3tLk9C;P<0S5i^p>b;8^h|SbkBG8<;v1;zaAnmK7ZOg>h73 z#U;Td(aUgl;X*WfqYP8xmq5edbvWiefq87sl3vLw^7gwZuCF!XVro`!qNi`*qM}Yn zw-Cc-K_=;SxIhz&zgfPWR>Us(uafwO<=~uFdum{Q5`Ii4AX!}k7atgqT_5bR?_?fi z@3dvCWlxfCDzCsp)eWlCEAjG*UQ!$NiKvZ{qlcO=qU_BkQncwH>`4?N`;Vw&&r&V0 z(|L}>#L?x< zH0Jco)Hrp!Hu{X7Cp%Y8 zCtjf~w0oWiW_zevwfsH<>yx)(Q%VYs)}ANhI;A)d*?!{M{udw2iUg;$V0OBh9s1U7 zhN)98f^C)uZPx!pcdaXe&Nsm5c?Z$Y$1L!ElpCr46AFur^YPP(FDQ{35C2SWmgl{0 z5%jm0VrW?#uD;MC=s6HcHh-%?+i~vD7%s_edg+Islcl+H=XAijGhgs=$r?=i8iCOr z?})~vDjF?b&nk5Kz+3fcxZme9nbh}JkT?96y<239-d~H@Wc^guIr2X2w$h+`gmQ>z z`Y&|~-eeW;aivC(2q%O^zE^voEp-POVyCPUwixHC^ zH$hd-d%8VQ49*1CqqVvoE$GgJr<>x)K@&4Dw=#iE+SLO8`36w2RGxD_D+1L|BTz4v z=M2?W($~}XqOO!JDDAH&>3chQ=5iXk%`Jg1WB23y^Iow2as^rQ%7%_Dn8nrP&qhPp zaGawq&;8N#C0|x(aH{VIsH$!^-RE-{wSAtmThsi|K(UZ^S&ikk*Ivg4Z5x~^@rce7 zZ$@2(659KDzd-rVkiZdN2{c1eSVv0^p87rlqdP+MI`7q*b2Nn5N9B?Eg)AA|`mt>5 ztowN1$BDCVq{Q;BKT)acB`*@HNU?P}#Ge=gdy@EW+JP%DeQFooH|-EMCCNkP^rKKB z;*C#3CBW1*2qm873J%-FLh9?YgR_Wpz%MD5sAAm=MOS+T3u_Lb1J7ejn(zcfHDkcxX)E|ez5~6V+aYf5Dqde& z4_yVOD6r&LNRisy_^r#is)Hdo({+e_)i;h2+jI`q=86;5Nu{)>2xxqEEjE_bL(Y^v z5N`1cRfs8Sugb^tx%#*>NQ`SRox&}Pa==}?l(+?{vpMNalR2lDGE{4mfV+;ukaj_W zaU29lUbzfbJ}U)-O`quDa5X4hA&hGtr9qkKJmy{OWg_V!!OplR${ate1?smute$p_ zLe+C;*t0VeU)9#JhMBivclbVT=2{1i?pCo1YOmn#yw>4l=GV~EvHLk~!BecU>MLJ= zx&j?GxWKq}VH*9|lFM#VrG7C(0vRn|^m(snnK|JOd&VS$xuWI5%sy(%Y`Ojh7r$7* zo}DxYl7^f}|6E=x64Rvj9!|#>Q}prXc{h~(#g$(uc>(pk0dQuA7#BN-XG={I;nZ8+ zBggKf$4aJiA^iSFFI<%7zKtQ7gElm5Pz<|e#^T)P1)RU+Qcl$HG~aWYie+d2vQMlt zh>7PSQm?Uy=iJ=F$G>cF#I+V(jwFKins!WFuo3;tB``E&9UZx91@B%Fx-FiPA>~^{ z&!YHf(@T-ct0wMF`j_?1p7MhvAw@FphmWOdHKjA%(x2IUgGblz7oy>}p;= z>?7uzg<-0TCB8G6$*Pycln3viyl-a~+)IdnxbZ(&e@7O7zF&(*IhT2^bqChOc!O7U z0a0*XgD&@yF?BnO8`5-mbtjjc&y2(9xf98knd)%9Y&EJ+XkiCi^zcu;HLlF$JFHq+ zo;9%-+&g`kF6S9cz|zT}tm%in%O2oW&v0UBI1c0v%z*-ZWwc1QLhJj*Kz3_@p=~6* zn0AUS^d7>iwITEw?{n9hbqPPub|Mcv&(a-iJsp_n&;7mhxNO;fQh4f<28o+>jc)qK z!0{m7W72XOOI+gkK2p9jP&^e|l2$`K?{(_i`4s5T1T_AUkLw&|;Zu)4ikXG5Ba$QZ zjYA>YBp7jn#0_=ldtj}*5^fg$h`;3L@_vptbY1q0@{qWz@WC~TZm;B}u!TZcex?!^ z#fPBp>Sx$q_8-pdoksfWL*ZP60!(P#PrpaCVEXcO+&{h$;)~+Q^{=5IKJF~~O{<6J z1^SqnzLxhEOlFq+`wJyjm+(ko2}wwKM>cO62e-W!fm(wtl*{sLzexw7XVj9Bds_+@ zC+&xwcY8pfzX}`=6~I2>arj^cf8V_RhU~LDiT&=!VRr92sLXZ*orQc46p4VvviD#k z?}0he{u55i*TIW37R&<$p5rhSMru@4K*=JDtP2Wea|{L4bRdRItPKUvDs{*!iNQOG zXHnkS5cfAn!Rn)%1TtAC=}f8HG_wa%&HZP)_F+>1jFvI_r1QE1%@K`280!;hcwq(}o5XGDSj4CK1(>31z(w=^Ls1!Pv~^gAqH1|~@^=ItGn0-v=AhmhoOJCYd(BLV%+l6?FO50$z{I)a zwUU$7{)UrS5=Jr3=pY*U$>65v`lvlco?SCule-la$i16hjnAG&=U~1WqdGOy`TlpoT(rNiE5nLJO|G1)f3k7(j|U(R7EScuOT(D>qv5`7|wYx z0T*Q$WA1Y!?(>`hROESZTMhpLYfu7TZ!3V)jU2dl`6mGB5J+y7qj$HA0o9#%(JOX3 z&d@s#m;RKHfmz#N-*hFWcat#leNGklRyJB)Q-28=LmqJV(pS>D+J!V0z6E>64*pfy z7^pj3et(i4Y)hU@CNG+gugkX3z%dF~vfrMDqz$oDWsnA*jm60e zR^yF5l3YP+4DC@E%bf7=Gp;8mU_>{qx9UbiXpy<01= zuk0b~lRr%Is%^n{!#MKhfevPk=3|RuCo8m|_jX;{d{!D%tXsop>(}tAvIX|lWslo zkv6L9;?gRb^)Z#Jpv(n|KQ`I@pyE~ zW>};9uH0R33-!DlgqyCPp#9>9;g9=8`X*rqd>-a?{@H%mZ})|SFTP55tKJtJU9?c^>+d$034gD*i_q$Uh!H~ zXxn@mx;vX%dCBqfxdpgi^+9<%b&QlN!Un!GZo-epR9|-&-?OEONmaf$DWjEiZ@xkFp3I5@c{33isPEp04OE{)4nttd##~#d|NRrlO)8_u<(&kPe|6}oS!poo(iYTtR;RHTc}j-S`u!K%4OF?|^P#k5odg`*n@AeJScBJE zPq>okNc9ax8DkfH{HW{ztrxG5z1=tayPv!AfXcwUZSsNkZSPM+mnf5|kt)K_=guK2)5B#Sz-LR#KQWy7Xa$ zN=xvGr%P5(iDS3IotuySPlrg3AefAgjG^TjC!r>x6;|HMf~`?YwgId-nk-cqi$yUqFRJ}2Z zyyc$I^^1*g?u66`Z3sr)xf9yq41^NfV@kZO4Oa~F?z`mIq|ZCM8}>a zGVMWRhw}!=Dq4X1(oSHmhCh~@s&bnT&jg*-VZ>&888)7G2W6=n0O-3DmqLy%;dvorgfhTnQPwC2?2|V-v(i%;Ro>O#xYz*O%hE#;Y{az9wgoY34+tx_QEE<`&xC| zYp4?Ewf<>0$>8zgdK@i)Dpz5K`iy0Y@3)ba%}HpqH64Y6 z6JX27B$7H$4E$4!n4Asr%;&OEQ2QlHWpCG@c-1XBvAYUG*0uYR`SCYwSiUB%zy>kP=o>pXL$i1%|H4#xD$Q<*$7 z3c1^bF>$F5vw!;_xChH{?Z@YmuWeL(T`G-oUIf0vk|6JW2AivX zklKBRAjv!drr0a-VtzPiDlIR!z`v~IlASotzLtL8VS!0G&j=NZAvfi&l8LLY&^Zw@ zsC&1O_1@n@Q}`Z;u3QnclN6$@hRN)Jy94QVPQ@$P1Rd)V=_0`ak}r3KZtGKK($ub# z(25(Nd{lz$-uQ^_{9QpVh9NA_3gf#@g3)9+0pFZzA{A=VopU3?BQ4vH#ITjnB}rVIdaDCy?X!l4xDVX)-=wKRBETrlPx@sPj-1RvIsZnpH{E z;=khp-3524#R6B@*kglTvY)YSb2`rIJ6_(MIB0eCeHgx=_rPetjfs8woi4VQ0cX`| zoRVfgdi|4yTV^_(%RmfzLkqrpH63=g1c7;>fZUEzfJu}6NZ(;ayxTVo9CVw|LE97c z*Lflyv_j#pDOR>U*Qw>_F1AeM4WH|cpu5O^k{iE5*jOUL#hQw9w?^C4#jUH>pSc1dLjApFZli4D)!O9tL<~gJm1;43tAJgI4gg&&2Ba zhA`)^6?1O-Tr@FW3(v$)k@o0Hl6$t2bm#a|=J$K>Ivm7v&xM&xrw;bK%>=mb%+h7H zd1SNRb-JX<4Oe^)#H3%7Vb0)5daRfQt|Cs*kr7N5r!K`O9&T`SrZmK^Y6JG&B$%{g zJsi~!r!tmxyhnGOl`1;3FI6_SH$+(7u4y9 zIy`wX6F(-eB2Q)KU@_nSu=a2!aXn3m%-;{N@%C+EvNoFDe$@bdTZ|xMu_*bN9zj1Z zxy&*ncF?iT6CMQEfn5?GZ!v6v`#MOR$6BIH`!3YGl}an%GU?Z=z}t%>XidW)yRZ8e z{i$upL|o{AM{A})cvZKcV!8`7UoIwh4`$--BSKt5>If;*Y!=+KsHUd3@oUPSh_4`>mYjmm~b#9KFN%&}A&W*Vu}+$AY0Ta}U4g zKF&3xKjz;Z!;Oi3j8c+G?1!BUE-!vba_gt?UZs12BB^MY_Cbn1D11lN&*sAuyFDO2 z(q8^={|*e@eU_F+<+~?VPkXn?2>lGEb?A})DY&n-a?Y1J! z8&R52kcQ4xdi*T15f-=pM?&;I;_BXOc;4QS-`9NwJZQ_U{oy)#$vLQ^m{UhBgUjX!ki>0>Bk7>XjV z(%?&*7M0;_aq^UG`XgW#_l(Bz9#2i!GDQNvUw8)%IcDT&v@~%tXaYS~4P*loa9FpE zMX_sw0hK9uBRGP)TUvwTD;(F|eq9LNEG+VPpRp5*pD! zIuGgN&u|-jFu@yoX5C`NPXw?cR-#s_eX>k-^hL5z-Wt}=^=IEZfJ56Jwy1o@(Q-`@8^leX9ed)BhdMbtKgD~D&LLkMs|I_goP^S zFj%S&&#oB{E$+?aqsw?^B>o`t_-iJp2TC#fYAoSl>U0o&ISG%bXG6%eG2F7}hq*}` zc}6q;eS5|xVv<=nHuq%Ww=SO7-8c<9x1FQQ42&=sc-DU03~u*O8eZHxl`GOc30(6p zI<-QR$aje_tvc~gacv&fXU!DMyCwlgqJZ%qe*#|mMUZpi`LKjr%f!k>a1$CXaV9Yw zxASAKV6mw%Q@r~UG(0il-^l?ecYhK4)_yf?ANft?O(OCBZwuVGWJvc*G#ig*@G%jOCUny$MY@mf6Ea`k5DkwO4ooe!a zjO0g6xbO6SjIWrEwXd@=!c`Ug*9&8~_epZsvAtYVZUJY1IuzxeKfsY@S4OEUo_TD$ zju~CSlIY*ZQK?lK+I}y>AJT(Zmleese2@V1CDBARCRz$Uk zx<7e`>jvdeoQ=1N{%<9_Cyn>^RNqGZw%c^+FA?mk*i3M847BEY;irGjWW!EF^vU0d z>644f&x~p!YHj29J4U4C`es;u)ErG?=Hjd+TA-UKz`)1nFn`x0lrDC`_3zJ;OZ#WS zm=)$s-F`J-a!LhC%bx;8SBxILNamIf2-Gf2r=RZ&3q%|EzJlKt?9(5oQSkHxHvK3?=aBK3 zD$md`YYt=*OkwJ!+1#1dFT`;ce_s)_W3PWQj&<{ZRoeMb8KVy4&!~ZaS1nFCFV20F zybo!S?&P$10hUd-r`fhq7`)z`Snj!2=6O;BH?%e*SB+@J^Keh`cY{j>-vzfn9R{i9 z&-n6=J|~i7$R$rxMLRK;jnCjPf2k(-adQ&xjvUJ!pB+#7y#wF~lLcNOicF545HmyO zHzW;z0GR?m!L_aPVYcN6q#pFb!l$v+DCQ1kNWLXewv$P5ZzLAwoWeir0_eRjRrGDZ zc=(m+OuCaza0fRBBV})p>DQE4_t^2=wAE4ga%2h5Y@Cm_wR^~toflC>VN?0m@5v~% z{th0Sb`s0OGXzckPJ&&1o$=>6+F7u}1S4{nO6S7r=ql4Gkvu&_ec8Y%EQ4 z+e;Q)am0ZW9OiXebHg$ZU~g(EoK?9Yh#TLJrB3HjCuk0L!eS-3>*v58eg}B&pfNnV zEyb<+;>9Jt9fMojJ>hF!9qv*rLD|&>e6DmV3@4r2gT4<$d~{lR@r}7&CRU69-^R zzWkNK>DxA-+WJd^y9P>N^ZN>t{i)O|=mG{hPQtc-YeCK^AG~Vb(}aDK2_uvSi}4~B zicI2MdyO#itu7;p80vCS3e# zKTf*%FS#KT_rYgylVKb;sIi$bz9~%F(GK}Tf_$-g z2Qs6+UN^vyinWUiLkP4)H48?;12ig7UR|r?%LAx^2*)^W>%!6TX z*!ySz{qDrj`mVi#gJ(Rjw>g8(kDH9|zJ%f8M+vx`_oN66lG)w2_0Y2apWsbxo#4vE zZ7e-$!$~%_lL?2nf^do%6Q~vd-G30EEsxbMw*VB5Bdu+B;k3g{ux$z_=`IuD_uKdQ zE4xu}H{%p2{%9jM%MW4yz;;X$GKH@Vl{BN8L-C9*y3(fsUwoTO#>y?iLFYPlYRGA{ zsLjR8Cl_LM0*fR3JI{NODoPzqgV|k2G3Z=1c4gIL*T5}oi=4}yI2MU^ajuN{b`@?( zOb(%5s_1?C2i>>xI*}HU=iF*O&+^IsQaTu3IfTb95H z`6NIwJ#brL#VlDEgv-a-ELi5xnDrYbqK3qJBh0dV@p<~xU^|&v$q^AKdEK}wJ z|D2(fJj=ka=py=Stit^8h1{4weMp%K8q`utS30-B@%#7CNSeW@uqkNgZOHw6!~31Q zQ}DpEndtU31J$lQ$NcLFu;XwJebep+1`j@B->@jBtY*f!Xq`agaCN8*l;gyYOooejoaL$$hl9M!NnGrq44_!u+_Dd?)($Po%yr`>+QPnkf#adL(+tNe-tKI?8}gOt`78Xmn4`c940GN zP6~+Cd7P*)2iARX#MO;ucsMp5TG->bemUEv3U&() zZ3%b{ou&{6NRQHbbGDDNs@J z0HP<=!sLTxH~dKe+>Uof|I7rzQkx>x| z3^Yj~V>TTvzyIef`_Qri3-6ggdC>yclHLlX`(|Uc-F5uO`!@rnKO;T&AJm-C$9&6Z zRQSZ_Zw8P$NgSuHb%cmDET#bwF9h#?RM8cAA!PNLPI~0bODoNR3Yy|2gZCz#!D(aW zkUe6Wq_^V@%u@=1?Di(Ob9p=539Vuc-%KFeSG2HXBn-Bif1%67nOTAt#DLvmS`QPDO(sPIysjCGoTtXZ)YF(`M5ju;5u94ZM?t zh7W&3+#xaUbKNWqEtO@yzPUu~Rp%o!YzGA%v3N}ECZ_w?f!?%Q;;tbMt=k)jxOF{E~cBs5r7MH!}FmhoYZIyikQ(`V+nOQu<-MRo* zS6#(L&GW$LKOyF3ND!oY&jPMT3vO@rhW@pg^`=acAwA#Sf<20()tV$S3i<7SB-d#5a=6CLanBTA9X8U`hlx9a5zXAT7&VlZCm6nmqvWQdI z7orr$(YYS{&udOo^RqoPkhQ^qUO!B&c_HvtNWlG$3+YS$#bt*ETIfUbC=gialBo~Z z@wz_mk>Ak3KC`c+V<+edZr#+O7n>BQ`a^RZdg1|oxB+0yUMO|jiEbOM1^WALfkZ#g zD_*NwuHJZpO6|>u9p{gO`w0PDeleAq#rIhA%QTFSeu--pH{*o16x1`QrawDRV%oS- zc4VRsmz^?~bDqPW*H-7jOGK25Npj^plKRPn^S<=D3hznwOT@vKrua?0hkA_0!}qU0 z1c9s$h#H*$lVcKs(Z;DX`-%f=lmC^*Osyy7qa1RY~g>it8p1Z;Yx+s#rqZDK51}X^HPyxM3>v#^PJT9=@Pb<qUNdg?Uy!cePu;($X zJNy&r>?gSOtOwrYb=<<qfNFv7m}L*fw7v{X!;*A zO+nCe#FZNCy@*A>>*%>J%gWk?K0qr!Gj(YmrHLhniT=I|*kSh&Mc#^GOjr=Uk9$ok zgr5-L?{-sm1cL9BVN&i*A^MXlSsOeF3;IjZbx4vM*OZHWZBZcgG?-S#lw!o@P#hoV z1^&U8u;J=7%qx+hJAKTsNu~j5=L^BiwPv{bdm3RDJK+1u^LY1kIaN^2rD4bTGe18M zKg~SP&I=8qv4MZf;@ln3p;HQb>aFn4Sf2G)>jxv-Bsu5Pi6}mY@9(PF%PoEF#`&bq z;a-MbqtE$gnk*3ql>?L|9LcVr>X_J0KCQ6I|XUtgeR?Zfod(P`{O$4+{-EE~zS>$GO#dsuy2 ziRRb~Xv|P6Jsb2AQ>*4s$SIQ`)l^g%T5ecJE_|5TacuD9AG+9eyq0^8W^Yo2f{KnD)g zKM|Y_9gmaj#z1>}jX-br3o_P_XR5W0lDqPnbVf`DHoZw9!>c+_MRO{auicIl%s%mR z)LHT@=^aL{j^JlISL)ns04C>zQ0Ig+9jkqcxTGu6#*ar}{+@b4Tw56CdW&IJ)z}V7cybwB zSt$y&XIzL(^IDv$y_dWfvx7ZFKVWX=JQVA{N^A~YU4k*FP_t=BjNPw z)vIXKCkBxv=gPw`mgDh@LxN+5;q3ht$4RuU5&C@$608n>LA2~Ga7x2l*1TpS)`xV1 zY?mziATJ6x+~1GiuQsFd#1FJdfgzkto|`ry!H0h|16z;yC2EJ!$pfo{LaX`RRLXuT@;KzI)> zs}!bB?ElaOvEJm&_he9Vmt)A&RnYk;T%h|;1MMc(!LMW4Fd_1$V5ikP!Mw^DnCL|X zi+F0M=YAn>uh|QyO(Tp8q3X-+DV@rJ`X0*MR+q_om1az zi4CD*Ano~(O^fg)Zg={~jUs8-Wq$;(8LlKT0s4ZpLNlD%RZH$TR$<1q80s*)24^j z8`bD1(Jc}%F-MlW{9-4JGvQ}oy&f!4(}8^o$rupqh>jhG@Sm<3zOH&J_~cszcQW=+ zm!-THoC$h zFJ>uwu#QnaHQmQN)Phzs<>3Q}P8cnvuCwwNpjc2TVIv7Q> zs#Lhc8&o){#@p!3^s){2UZItz79Mmq$K6u*QA%YL{nQkpY-=Jd5E}v(P+Wde4WqUHZF}hr4#ctrsFo}@m zHp1>P$7$MT;Jaov>{}p0g@(V;nnn@mvz}%3ZUf)#_fedaOrOEk?EOZ&lH7Ss?*lp5 zbO|3+D1rQ%e&hm7(CEfu9CslLO#+5k-I`7eD=ng@tO!P~R04J_pXr>&cXgipOD7)} zg}L?raMM~*&UeFPIJ7eY)D(*Gy+$H-&DY1m&SvQRej3JqP$!Aeqr_m93c!+H+`2dy zc}E83rW`_-qgrq`^^ZVP$(c0{sit=Mh5~1!2=@7Z17vn@#nCg|a#2|MKky(D9OqV(e<<8R}@U8=s;~>nfHqi&&gR_~J zON_bgzn;;y3KhmF{Rr6=w;lDnUE!Eg5azlS;DL_uIKX@Vm&ov4IhQ54U1J^zD&rFI z_qIwrF>fKyVLS=D+gX95uo=$ro&;O-Zo$)i069h5QKaN89X`8=oG}VRwPT8GLfEKa z!nOwZB_9u0cie($r^Tj~veiSCy`jR5Kg)l)b4>i~&n0s3Y3um0gOS~WA=DDeyM^-y!9_Juw zS%9*&eK<5#j+3P3__FnUd8WG7KAssr{{sGr`3?H{ z{>)InKBHedj-L8t%A96-Ui+pd924rtjjS35Wg>*Ct${GAS_=c8t_m949>cOzgVg4L zBKPKFH_Takg!}s_9A}(6E~sbEqj8xH4i1@P_*z9K>f<|jzUL~Grkj%1DmUtN)|be5 zUV&8Cw|FD!0e!Hsmy}scy43XuXq?&w-394z;erO!l$ybge-S}< zY;}Z54%w_x_&c)gT_Jm^LK^Cu196L76wa{epa+bWanIX-;Zb7?u5Efe&RRYTR(q|XWuAA zvd{jEw>s}b!L|4-UR&`R_I$0N!QNZZ^?4`$x@AqWqL;#+F->H%P8=2rhUf*+>tv38 zBhlPm37_M)lwVY^=kM5!U~#yZ+CFn)Pbhk0Vxlu@)to`OrOo)GF&%e~H$j70S8)E! zDlpRW!+UF5plRSf{QC70b*jeGq8%rxgzrUqOWD)^>6-YUUHrO$lQoo6{n!I@ev#vm0|K;c%zJw z6Sw`qYDV5nm64S@4vv0Gn0I$N)G%d&&%DX8j*I zX5a>IJv-mT^PA5?@S+DmR(?Tt)P}3skb>8g?~$L+>WJ27BWBH}82IV=8UpfriHiGl z7;-p*rGlxP?AAau9_xq7S+}WM&~<8hE{m>h4yO)5gLLhzDmwX_E+)LR!+o%xEYGHb zf3l+R7j|LGnl##MSAu%-`Lv>L3a_{R6YM`BN=_L*$HnzO&`bCYDSmd1*uP(i;U`jI z`?Xi#y8J#!dv#I8G5akQa>c=9CC|n`umO*3`T+(0Qrv`5UQv_fcW`}O=zMpt;K{`x z{B%GZHL^3&dZP&HE$tHE^D&q|P7=n9UPCX=0p55&5qSPo;KTwo(Bp~)`Y2Yzd#wm; z;b(!`^`kJVbqo5!U2u+&0++l1p+{4j!x0mDc9R%r_ZU(m{TpCMzrf48$5HD`I6Cxh zBp(c$(Nk;(*Sz*0HZQ)*hFVMF*kx1r{NHpKcQz4kNfeVGYp?LW;9$_oGXw8A49fJ3 zXNY$h`1CIX?z=b1b`ZmaR0(DR&%zQrQwMvmmx0RYabDwA=Cswl@%R{kjm$>)2anOl zrUU~Y-GP-u;@BI~h=0E4^7p`M481&-Y+h$U=e^R#1+DMt#F2bFE%bxm#aUq5wu{s; zZ9Y~uo+WR;)zPm{7>t&Q!OB@RRHS|?_h`pYD)M<6GxVPwH&AFHsBF3e4i_>|)QQhG z?rUK^njWBx^%->f^|X9O)OPO1ItMa#(^|+_lSQfzRiTUAPuyy$PFMMTB*t}fxz6H0 zg7&9PsG)C)Gg3mKc8~-0ekn%l!b}n=l1i`dm4|q_8&sr70!^ZXpl)F<>3m292Q_A+ z+K&L3py!Wv&#Q5R@J&pa5e{Wfj9}-MB&yYA&iJ@#f!Bh?T(;>qxSXfOEWE4Fg<&23 zTBpSPdNoQ16%KIDUfm=$Srk^P9N@j4TM2I}K`V(NLFgx0FxBHZvE`dtuLc1X7 zycpjoU%{+B6jSZbf&QVh__W#;|1)oe{M~iLq)Ca(<#mAJZN`F6^%tS;>1B+mvt{;v zF(g(p+ZfgL!|a8$g59;(@DeByHk~GpTcYLj|w33=K`)+uK@;+ zd;l_aC0{dO%J=x(p`8gj3~gA>cfgK?ho7tPjCc!XPrJ&qYWDJ<%XaiX*nw)|3YZjp z5IRamQDsv+7|yT9EOBLAw9o-p2icH6om!B#Z!wWAH|2hwjzs_EZUQOmNSu4rgf^dF zfmcs;V@I1GO`W2J(>)ypw+$npk2r(nFt3?K-6dsCGl@O6@Lty4T$M=+NNsZlGik!i zK69L2-}#S(87^k(cikk@R5X|;{Qh-dG!|}cj|Y$MGida)8oFO1AFgeq(Csb<3)XBz zkGH?c)}Z~=;+Z)=jgKMbp8Pr}*K5wx89 z1(VzE(zNpj(KFqa%zL(-TNCkyrN`ZPUh_f>oa+ti3uDnl<9oS(=~lX0rju;BVGmFF zXRMi{&8?isdna}XbIo@;F!729F2AV2=VzY7`L&XK&-fH_dA|%tez2llOrc96$|5gYPm_$EICjV04Wmg+g!PPQ)t^S?$SO z`aVo8KF?%s%~8djeO{<*7mpzmH8~xTQTkM-5sZ`*Fm=sBY-A(gY4HoNSaJvKd&Iei z4bwq?MLKe&dRTQg0zakg!;ZhQsJM{d4>Nvj%SLsmgVj)O^@fy4+j3l$Ir+u+oW${5 zk}oO0;K|9k9G({DjI|pe*pb)P-lag=)orBLh3_KgO&pdzD$F{cbueN%P%iN#i173S zo@;!mTsA<6nor~T<0tI7;f9 zKH%wz^YPrEI2Y2n5g$vm(}HojoGtI|91L4WWH$dIx?=uleA^riZ!aJ3=tlLY zFQ=mCxwzqm5HzMtz>hD0@XQkm9?}V z!7EF{afO4y+>H)qf|09UP(I-#dg2lsr<={%g!7&;>G|lM|3wg=qkz+_H{+D-NmS~^ zC^bsEL5E(C`5!~)8HiOI#&MB7Dp4YoR5DU#o^xMMX&?W{XPWwF{`r3!bbIx<$*Y*GZexSH%Djo<=!B--h_~VKmTz!0xzO9?V zF4P=NwD$dk+yir9WxE6^d@~R17Rc~W9syQ&`H*MIYj`Gv3}F{3gU0a$I&bV{@=-$t zKhzz>!IjHlt-2iiw_-YMgcqCQ>LG8@z%jtmIv^Nn-?kn>B;^3`WCX!2GhfzSL1sxb$D~{Iv!J& z#>jak@a6GEHl{ESPMnT{YV}QmueYRx*YX1z)vTh)mF6zE&G*Z<-yVQ%3lPHJhy>9|LTL?8J;=+U=E9PJ2L(uzc0Vy;V%3V%@Nz8O2|0t9Ej_-$6 zPxuaOF{N|N8o*8>4T4QSlNX{tz;%KX&!3sV&7RUk*ZYm-7AnPKwE^#thBoZ%x8%H~ zj&Sx5J;pd47slYahkLv;L#7HE9nutZm}xNEf(=LA+SV5XmN@qp_${rX~!sdkW)i`a77q}*>WOWol*c9H}gBXSNy`UaYHCQRg9A<^dlkVQ$RK80@z;6 z1J%K?`23XtvH$1~bL17!tSOAl55LRU@!kIaj@V#9R5@90QI5hMMLcJbiV4Z-_`Zkt z?QFV><0SZZ0k?^FbAO_qLD}?k-~h%8r;<0}SE<7T3%2i*jquY=A7Qn+lW_SH2Y9X> z2!n@Cf!QNbykwyWB1MU$;BE})Ss#X9e~akVSuDgJ7Dz#0Iyyu#Bw-C9HsNvw!fyV?!^hP@{|~ycsmuv zcB!I&=K$4@il<{5bLpAq&)_JjfOqC=X?^V)xa9eVbZAt;HRs#JMJE}hO|(!oejR%8 zd7<=*?Id!^N}SApKfH!c(bsx+acjB`OJ4Nh>BTyD&VC<;^<754j#gYcg?B+lufdj! zktqFqGgZFkBwV!pBt~coacOuQgs1nR&i->aSgas43yemAeJ1T2T}(@Ny zl`rmwg1VLL`~@8l+o{T}`tcI)T~_6`6lrjZGI4lANfP9*M&W3FuN_#}%=ly(KpW30 zn7u2G%yW@JyWeWaice!BEa%W)tt0f`K6Q%&?o!~>tH$34Rsws+SlIVu2qQ}TN!a(5 zuqvzz7dxksT|ZNC-=Z}*-lZCPP0DcDhvW3J#0p|F+Z*CPWiauteL=j~iu+x95T8F* z2JOS#_L@`EZ_R37saVb>~r5^%zF*9!%?k*|ebb3)}E~ z99d``3N{;_5*LR=!QaDk(Isy(cV^u!v|4-&cePE!i}&~AbX#B_dw;?Ves6ozbS>~fwj*?*>wq=~4YyR0-`lHr*LsfpxE-fY}aDulwY zT37=@hQ!53|PJ*igXk& zCk>x7K;=IvILPxU)_aG+)1o>ya8L!tdwytitJmlJHhrQyD>^}1Sc1LDon(xA*nZ5KW+}!aC$NK_p%|D+Bwqu7e3%`-UXi$ zt;gt&eT*AkkK!Gs4UJVY7nn7*e=+^u5c{}K1?2_;xCP#_1 z&+&{0$@}jx0*|4=r*_gN-V1A@qH%Bn<)2eakVq|Oj5pmzW1hDJPM-vtU++VE%_W#; zBLY9dS3%^nYFKK*5ye&#!>_6KDb-9CR_cU>!Zw)WWuES>q{(TlBM4 zByEkg;i7C8GnZtY;pBonobYH4)peoJbMPqY{K=-X7f$5VjAOZ0o)4lR$vYgrIa6iA zv*-N+(Yxal7GBN2L`qoaKGaRKilRFvhC4_aXCbu;*G{tvY=6(4KX z6NeLZ=(p_!o$GO*+*lY1D+j94_K68s+8se6m$FcP`w}!2t;H@yH!f?pH1|FKJgD8y zg`KI}g$H-oGhzxA?7YRhnP2q_q2k(Ua4B+zzuOp|>$VS~H<%L9?9X)Z`fIRcOfW1h zk0ued6|iPPCZrk*aNTNvAM$;uWGx1A+G6m0poz$3iJM3ijc!4rMIwfZ`J%$xN!U7IkNf#N z?p>`S)Vvu2G8gzRa`By{9EXzmzvz>5G1PAKarWnv7<90DMp0@E zx4|u)pT)>y*s&%HL1`%LK0ZQ@{rX1U-!Pz^k6YoJ+<%aG@Hy#AOF*gET^MuLnJ8=J zV}O1MsbNg$;-xLvA-Ij=<~MQpq75#}vJx(7|9}HNA?Q#%5ms)Qi4Bp>c)2VR%6}X| zub}ZDvqMgpy>lN|(CG@ldX@_{I>k6{<$4(BK2f-WI}h`DZ(K%?oUlhF8>ZZ_fK%p0 zG(YbxY;Ry8x__4N#F?jbj-wStCd<&2^7 zOkNt?4#(#y2n{qEFvEl>3lj#%Vr1OM43xc*1))ZsBJs*8=8{HNM`Yrm=zy zybPfqE*8-(ZAFB=o{7UJ-(r%-b9l7bj(WYR0LgkOVeOpTc!P_ibN{V`uZKs0h}tko zTFEuOube1&q5_S-azE3s+iPKP+93T;mVXvzM^bsQ8cYgyrkPpMeD*Yt`(fBet`3OO z&)!El8<}=AG0Ugs1p?e@G(gAX7SbU9PcqUow3ZaKM^SQP9Gm`GeJ9> zG2G>$aGLwyDNML`iOOB(8FF!SCAhX7M^HybhW9diW10SW)=pXt zMx}ga-WP|ELp~h&H+3IO-+z!iwra-c7c0Rs{t(z}9>eVeDR`E5xD1Le!Ve>(sQmcF z)WxX^5Afe7|M0nBc}ENF!yd!Z^|N3oT!RzqUxoAK8_3A>Z6wcFpYv+1V_sRDf|}R? za>af+{?eQdO7nWLbooZ)&raZ2vYak>^cw!SC-WK9cUV9BF5S{U8YcM0gK)tRe@+NR z`|up-I8;Y}p3|WFen!Ag4=a9_que;wxdCpRI!4<^8t}GiIu6d3pudL!=elcgb+8D^_n#JSNgLNJ1#fsW$;+4L;L(-MX3rPbA_JRyRt|0_m}qV~O8oQgB5{ z*q?2M88@`x($le^Xn%n`xGDv&{z(e^-S%K7T!nz}M*KeFNG9r3z((E8=q~}#(NIm< zfHPS9avTH~S<}Uw9?bRZCXMZ%DVZa}GglR%QSS+<%sWC~yu66X|5eb#p%aK*w-md3 zdsAb$jw7}|K1EdXZ?K28Dv0#POx}yOn4BLg35UJ};=7{n)Mmpi+fR9LXreJ8wGa>N~s_Ok2P`-J2o!r&x+< zquWrg#|w1tT!*(#6S?nCT|sr{Zk!=ZA#;6%gZ;Y5g5NP);|J|pTC+l1ID7&ytG=I> z*p5f;xH>cMc_?bHc|aZ1#|UjTRk;V7&(ZY*b}(1W0~hT+gQ;5G^sn++%<8&MA3yA% zC(730z+oFME?0!;YMsMN`Xw~`Y6x+77KwGK~QkHsna- z#tadz+4l^tF33Wau@wCSgg9QP#@UBzL4IKoi8R*ah9j4OgX}f(&MFAu{CSxDT^kJy zwu5?BH8FIY!kL}i2Lr!Wz&U|2C-4Y`%$f>(5G#b%8TCZe-xGsM&ViECdF(&0%l#E^ zfXg@k5RW@@!ZmXug%LtU_VjHI48OJWE!AQ&RKG&FN^!B!%rm5+UgQeaPdJQ5He)$! zRenzq$-?WeS>)25Tx>kF5@q{k(XBcjkKW(P8E^^M7t4)zAO$!&K9E*H50!8z z!*aPs>{HdkC-uGL_}dDSzrUR9h-)GThUIYJS1plhyh^4&NrVlLQ+Z}XHEiXxE!sIv z=o%Ctd~m7;cWq0<@lyw2((Pqv-6!Ba9@G>b4;!-hoHvzo)4qsKE)!^ATre}Fy9gV5 z?WkH$D4y&PL4!zjl&*YAfKmKC=e9mAuKF_D58Qp8-f~7~z3fG2tx3 zQMjf42Xw8L#r=P*NNb8D2vP!R+O*rabbT7^yy8#&tU8IfMKB3poew!HuEIf&*Gy8w z4pe1yp*U&~Ld`#t&X;>I(D4&3G4*HOjLC(;qcgdqZ^~%*#3*vHXCd-*kL6C1AJF*nFBvNAODN&TAGQX=}8#m z%z$Am@2Fc)i(Bt^;b@5)j6J`j{wXz=!O!l2{`DLXo%0*3 z_c~BjwGF7c`yh8}q#BGrs&LDVx}aJ$9(*Qv;iGC3SRu27HW#l)qs0=OmhLp4wG}Q+zQ(?ZS&MN4{5fC?Pv6twbI-T)LG}TKRgGHkbOGPn->NAL zsq=)3NAzIiSP2n{3__nT0`xzBnHrevq_1z9l3V-Q1!sM(5#Qy0L_K93&k}e^lO`t; zPYY*^)!PH)x-vPP=#T4;$O)BN8JHz@21Cck(KUKk*!gFlW2LD+{y30~JC>fq9F0PJ zbt#IfiC8c_?K4rO{T@yo6GpSe_*`F&7WR45fZTP44e>{s{5 z_$NNt5UfB-x>w=Ei<@DC*#de@N}P zsF{Qj457#v2hcuS#oi3dhJ?Xs*m*pMG2?T; z>pnB&Qu7)J-4X;{M!KNl^qIVQVhk@T^XNkCqiJ==sNsAkW_R}nQvLWo-Z7jH1AgzI zS40LCJ8jS?A(jmc3MP_!jKFsMJZN~$@7UL7kT*9&aLFPMT(Ru|E>n(SGhce}9I(L# zT|dgqbR5Jk8#_F_FbBQI?Z$wgvFQEp6gv4XL^?VgU8~A4b3+_4sugEpFdQ4>@6+6| z$3bSAB>eg%4neO^V$|XXG;!t9{8N`g-ONrpsoa$rcP%#kc1bagoa&Fe82Rv*$1R=*ny29ex3p>!tI%j~8II(2cZ} zwV}(#l^}gplB->B!U=e$k?rO-u+MpgGWn*|)F}baZp|Tdtt+bidPa{5>gi-P9SmB$ zgm_g<;4V>TC>!rav#zVaXwy7c(cDir_bT%D+zWhe{{kDGk_|i36olfv%ZQ`wKiYhA zoN&^JJdWL1P7j|P4HtH1V#+#`#-)b0SzqNC=IC$?nNWTY@>-9;9Q#kimG4<*E~;k^ z_IqOR)IPez`!7At+VNeB2%Pvk68%<2;+3PtcqJzTmsJ{2tDadXIpr`O*qB8sZ;z$t zst@75;fdgoFj??v(JJO#fg;aBaU+`5OUc+*s?2Y1H&PK*3iDQ!vsvLi%xPu*SKPIxbrQ#>H0A;VURzUy~{(**?_)%lW~RHVS2YC61S`FCl_Dmvf8_6a5kOGAkaV_ z6dznb*{AL};c6Ia&y~Xu+iJ0GvJrx-G`Q5((oNrLjn;4KlqARXwH)0!x^6BRm?M#Q($Q7 zOUubZ6HT&N6r_?%~J06TSrFzWb}O zzw12CiswDyc$;bU(jw0%w2*I!L0CMkm0nOtC85e2>HKA*P_L8E4e(5J7wZGqdUpsV zGB}i5#d{{DlW~o;A4bN#!jx=D>T$G${GA#Ge{{dG+YY_P(ht)(Mu$Vm)r*Pe&T*W# z{uR=*Q4bcZ-UQVjJkjh%Gi})xL4V(J#L^@`vaR7NIbIfu5^uJHCHy6oY(LFu_u&1W z`miftJUJ=7k^Gq*MbpoWf+BGPc=7ckNqiHEQqpSlhHJRMpTslAx>n=Cy7kEVgs|xk zHHF2o&mk>K1^mXHy9id`V zG~oS?VhqdC!btUfbV=N3de-Ozt3Fu(u4mscmdSI`NYM}8J^oHT(xf41ULDCAd_`V9 z`hn|+A{V780WMLCc@~*Bep1*CHdg*b=iL?@8ce}leusB$dkvjEMx3(<2tj>uO=Bw=a@?pXE)Em;Nh+*LwjU6$hT=@M%6bSGK|7-O8dZR6QSc~rRU z1N!}=gvYlQ9TBB`T0oagnU}d5}?@D9;#c zkA}^`KbSrHgRopgh%YyNfI{6X^x9h;`m-v9sv4_d!uK6a`j>jtTtl#>IGCR^4$*5m zK~UCN#m{rcVrt7Pa_O7`&WKY2!>%#HQ;p?t;=4F%R2Q*CF&}KpIw_QUp!?$a=&}Da zg%{d5b-6#!An~Mo=Ul|L@`bp@zJde{r(u9j61Fb*1ao=}L2%Oq~W@>HoJ z9hW{T#lk5T7}6^u+`DHJSY0>lb&n{kyrXvI+o{dz zYMPQWla%ebz}D7(WgnRLGa=<#Fw*A-Ni&n-`^g1Z@hgT795_v4M@zyRq5~459_+C1 z2^4?yfo{?}Nj5+Bg)#kcM5AvCsgk-x@`4tV{0>#vkhFx{?_5N8__))nSr-J>B8RA_ znjU8nbd4hHAz9H<-11%yowG~H#Hph=qYD*$Uu6!g%4G3wOb!kkT%v8zjeDa{j7sl$t}Z#p?4%DLI%^xJna52fV4_UaB_Jy^yfCde|4##@%!3vlw>>wDUU~! zCmmDydbJ(&Y|EpI0^YKxMhn2=*AMtxJw+(GeKOADS$i$djD^C<>ZsAm?<>S9cr~R! zPpJSdPC9_+Q}~=!qBbx^$*k>JBS!D-Ep{s3WBYi`7Eh}<;$HYi3YVx8@qcY}Z;&Jj z7%M60zH|j{cn`C`=TD~N{iYzF93p#po@0&ZAF@-z5H=igYb^OtM%|wt!K6deV9Wgb za5^E1ipbi4*^bwOZ~Aqlp|A`No?x(N!&+f)WG8*KAQyVpl;UCiJFL6z8-dzZNf7ah z#mgra^8b&DaDw_~oOX8yQQ(^3fUY?z&16uihVKa%HG!Ia8)*NHho7Uqvjv9-X@vVa zSpO}YsBBsX+unR-K3<4}n%+UOCo_B9gSEqwxUJ|Pg8Mu@rgqPdzLhiQv%&wLWvOcJr-4?Q!XuT_- zKNQ1ZZqq49{Pe1E+1dGIx9()pRv3W`UjJmz+?|Gg53A@DK^qA;w2_!9Rx$=*lks2E z2(DMygmcZZP~EZ-ryP?aE%#-xHBW^r$a;lV4hy*h2~zkfc0C&Z(S{vKPq4})3XeuN z(Co5Syut6=FV&afu3jn5*L@oIYVsL8oI8Le{(rHi(;gqXKft9G3yEc`8+ora8W%K; zVf>aT2<3mhqHZeu{?|U8X0N^q;)dfP+xIbUx%!C*WJ}?HcVcmRL;*c#YD?tauLrrU zlkv})Z211<7~SKPLpR>OOE&Jc2d%mcYS8+H_I^GIiBYlWU!Vd~6$jbmM4qe9XZ+_X zXpk*r7U3tlFwNQ%uO88bRGy>ICS}9F=b}k1-|;hWQG}aEw($G9V_?1i2HPxbgi%-b z!=oJ)je86)z$l`OlU_%FuC6BTHezw<=^)}&aucV=gy11bJy`NI5jQV>%!-?hgJooEcYh}hPSZ$tdN$+29L5;GCDc0p7)f{cq{Ft~ z$awi}aKr0+qh~@XJLCEUka6GGn45B#6pt!}oWT$at==#qaClgl0 z$qA(nEXA3lZ;(;{(y;9L418OzBJ?_70v>lJV~0-^{3w@0HT?#t-%t&52W`RV?_J^= ztObShPe5N$B{Rl6iA=MSr?nEYAd&JCjz1fQd%RyVK)IS`n(W1?>=~xADxX-jbueP# z4Y*)+1enaeKpm#Nz-Nb&*a=bz{I0o%zRk;|Z{JPi_uhACq(c<_??fw&Uv-7u^y52t zE)56s&wLyw>>iV~NCM_=Yhxo+L{N9uB=~45fyaMnLzlZ1tuORrM2>2+*TY>g&q)$X zjp`wJc076C;tCGcQRGb8S#oE45BBFsa}P%LGrt4Q;ezo3t~H^Sd|qcI_;lhkfiH28 zKc<+GOFBW;eOJVTb5Br{;OBT_kqrIQ9gCtqq9F175b9aAG)ll`@O!x(QqCtg>c`F^ zE3t@d4;vuQm&P{k-nbZ+?QupGr+JMIxj@~7kLqrjax3cg6Kwfuym@X!#o3O zfwD5p8shWfOS51{)@XMA%~vFk4WqVpr_leZ7SbbDj9ykW3KjVd5#I~yUbBSE%Q*pZ z3Zd}s2Y^h~IHA1lIr8Mo7;f<|Kit3VC<%9}W!c=zw7PW{)*KuM@87zEf~EnG<^*uj zw}QvfVU1pbr@XUpG$hWE$EQ`!P<;3rX!&PCl8MPWGhS z)eROpia@2eEW9i{fOgMUk(y0ssPp(mcqZ(&V5w3YT|>{{9LF@0Sf>p(KP1YMKBb98KYxMac^1^&sCj+0hLiWt}hsuSo-29Jw#?y7AmL&hE2RH3gJzc+F?`=ZbUmm?%jlQ=p{sFZ_y5VIGQ#P@CpRp05)ES+|_HwDAjZ zrN>O+tbQY&ovY7@@2e%-MhcnC$km*p6VR$lN6FIv5H zz-=yf`=Ktd(<|_3%Wi!5pE!OELQ*m6Dpm~hyin0;+^Q54=5=x{IX9skwyDSpwH8zyBzQjKrCvlf5G^r4Yh8L29K$Nrx4i->QD5N=q0 z5mGjf0fnT|WW|pm80c*UuP0ibyH(E%=hAU|7g;;0c zfuCNy#D@l7adwd{9mzdJ+lw?{6ioqZ!wG=KVj!in9cQ>s!EeWFh-k4EsMw~{EdINo zo1%nwS1-Y>k}eRABh2K3S!7WnOPu`{u#0O4(bCzS1|<5BhuNFi2|U}}J1K=MtyJd* z?(gFc?^_5j{4L;jaUrpveos(+;2!gtC+LjehP@BM6{0R*eAJB-Pa8$_RT_;=`WagCBD_zbYR5BKaC3NX1|0is| z%>nw?ahRR_Wtge$%>d7$w%Msw5~g)Rsrq%I z9UexMDpje8c@tELj~BKtISfO8{()!iB~UUPEo9e(fo>z8E!+_a`O3E$BgwnWM`Lwr zlsXC1eUCw6Q3>kFaBMt%hhYb?hQmzzsZ2t zLk#ikrJJ0k=?R{vx2G|Z43S67rEUg}@XlAAT~o;y4{>4Dk?9b?_>fNl+ewAZL(Tsn9$iL~ov_I^JPFRyWs%g-2k zE9uX@8{^jzdT>sb5w+WsWZi-I7hUMbcf#s z=A8W!4d}BBf}pg8;1_QIY5x`As);<`xLuX?`YezA4+PMx@d>6b_h#~JR-xZgFO2oy z168dpG%EE3ei%GV|IA*7e-rX~X2nEQopKZ7J{FUGcZ~6!?+`5=u_v$c<-jjsChxU< zK-`7K^zWukXzcWxwTW8Zm>PHha=qq2L-lxcsyz)R^1M&fQInZ(JceAF|A1tjl>n6# zSJ*OY3|w123kLi}giF(ug>J8#U~3TX^$75QYu;+m*L(!UuI$6kTfZSBx*A_@{mCZC zU53x#&$WE%!4F1a!lnaX=+W@wL}ct1ynEk?-8n0s6a}Z#y?^fz`v(OeE4>sSlzn0H ziv*aEz8tjQ%mn=tL(tGlQ< z&oG{Ms~9_mO6cRg7C3nH4ILO*K&%Q5qRF>rYIJ%t87rPfBlk3s@L`@|J<$)A>BXbW z#tiUyzDJmJrV=(52xyI+4*objL&%mygHoC+7`LTkzE(Kd&3At_{hIOfW>M(Ve~G*9 zZKG>$n&6kQ4fx1fne+AJohJY0q9H%y%Prv>5Kfc1%ioTp#5M^ob$0>vEso-SVj1AT ze-<082Ke)Q9NpwOMQAG~E*!UM26|qksHmigyR7Y@_s&~995GCyp60^=_sdxRVm9Bo zdP_QF$AJ=&;F?+<1GVzOh?8ruQ=0Go2n7)6!9n}lH+&Xag*<5&kdB>=xb9{M7r9Z$ z{gR30qyr35hQC+NHI2ctft%FqQ7k*B{99vs_h@E+y$Ig?E*(U=g}7K=90PBcfPpyAfVle~ zc@-#v5ht4AI58pn4~^nl6?lJ@YAqOSlN1`%u7JzWDO8CaC7wpd(IZD6W4ms$OWi-Q zT+#woLua(mv?Cnsw$6c$xu3|H7eR1w-YCd?Sqra!=%aw&UF0NxgCgGq-cOjw9yN3& zoA$}VO;0(n)^ft#Ych%KuC+wt`3zWHpox8X65OuxG}y}DVRFy9;c>4@MyL5Iwch-d zl_(hkxs+_)U#$g}YtEx#wh4c}w1ju34$)8HvAAsTGG0{OfOFc%2w$mG!^FLii^kzc{oq#@2>G)uh2}huYyAE!p*go2KAbjyS?(pQCwC2A z_tZn+cTM5wmAsu*yBxRhnbBq!-r==m1HLGE4xKzB$-{3CGrWB~d1qb@vrbGyjU%Jz zCbdc`TOP>s=6o?Alb&@_N(`KRh zpK~oYTK!pg^Y&=`G!%fzA3fOgw>;zZ>sKHzpq69e;^M9xn7+Aunk7cm_{89Kp(+^H6_F7tUN_P2??7h;fM)DLHwU zYP4kXvtbX^T{#c`)sKZR!!OKvjl9M)lVo6Z%Q>^sbZ+-m zih)T;Ch%to|1MH#B#-VNzA{JpLQtsgftwFUG0Dp3Ve;8_xNm8Ui@W&uS6>nRQ`8Cp z>u&SB@iHnb7QxA;J5j~_IJQ-MCV3v;1*v>qU_!MU&F1FtY&=(}@bUz;!i6OI_#C=< zp&yD*$;KCf=Wx@Mad2HPg3(cbOk6BuEc%Y{XZhEmP~Y(s@+EcIq-qf^GFu0IZPwwD zNyZp6wiP?N5kFa+r3G2JRNp(6dKa`qoJ~s1v)&P zO81o+5&gn@jXG!Q(X96?&C}< zDSjKG=JoC1T-u4h&F?VvNB(2S=_{e@@-kvw@TRdScn6N$5reN!DbE}*CW~}4K;}gp zIQePOEt#9BGJn48Ej~mf3Qv;G{2H>VV@g{7mENtRL~EIsy^o!2@W zbLU&&3uVAVQgZx#CxLgW7($`fG8m;14bMa3u}RMzgJ%LRx{!(crJs;#^AsSe*9yy? zc+}s1+{+%fxW*cZhQPG&7zz#%uxm>Iu~rO*kdvwKW$91&SFZ;BZEhgz{Dq8csibCK zHo#E64LA;TK7MbhNj8|EBdip%NJJuD)zTQB`y_BG@B~FtMPcI5y=7q4Q zeXk2j@5(XDcdJqVA%=F{NhPXE#o$$8L$1c$r7sQo96qx>H=Z`OGrd zs_sFSKjl60?@H#CGxkh|wK~qO&!=%S0E3_3LY?(e+;oKyoRb*dcq2IyM1Kr`|HDu) z>(3`Eoo|vSgKl{D=>ZJBs}Jr*T{!u825}kF$4WSq;FHOB@ngm_I^p(PGH_)wdS4Mx z<9Q2VVvG-H&h`V5-k+@e>9t@Jy$NgdqS0{m6;gN8niG@CCyBexkj2wuaNyB$?j+Aw zd(}0bbBI}mS9o8S`PcEFpY#4vOK)}IZXeENC}oM@FMfKIK%fB zciECli_j;nt}*V^C48S0f)(*)WY&8Qg}!|5^wC*5nLn#9^R@#kMFIw8yXeUIV=%UZ z&(QC5L~BQF{Ao0VS{i(JV*f7?W^=H1vpCo;rDXr-15mam3z|NP(UptN0NT!EGh=g! zVp=h|Sn-r3<{M+|ND|-mF2eb}GvJ5pd0-U8NWk@6y6-wCu=|%xulSad&YdfnJ0Fsm zqY{mze^Dgeu>As){qHd-E?p*Em@6(^c8WhsO2wj`>OuT&#Q!E<9?fmyGm`(!8OyHt z8BSlW>!v3grNL-Q~CdN1s0to)Wsj$P1#sfz!Yv8#$v z-}gQ?{})IyCzMdD`NbqWxd!`cqaZEz3AwRiCU?d|k(1n|MO>a6aDOI`;{KUU$HYuA zZbR`O44@lRY}SIZ!cwz|t$GE3p&)&hLJSd??TSb}sQ0WJ7*{p|5( z=u_H4eR!uqzFh+G^;W?rYj$CLfFury$Z$cTPvJ=8D?0W4eKM2hlRKv9faC53_$53X ze$_4^*3)!(U*H*Z7wkO!eKaF7>s)BtzhMu1h8Kci&Kt{u(BJ+ z!1Q$~B;;-dSz$jy)~c@%R3G7UDnVDkOudLSIi7=MJ%yyEM1s?1SE0zsP~N}TiSIrY zVd|_;nBylj?utg*gKJEwo1S%CvOt9wU)Z%i*n~P z`TpnGXLQ4iaq!YZ0hWctVC4!QD(|Jo_|EFW!;{?MChJa%whl0Q4pCUIkU_t!zf3-p z2>SJu7QSKAh{)3_a$978X|OLNpBE%RZPRKrtZV`M&|&u8O)Dn;?o_CGGX>)Pb)m}E z8scwGf|(z7!nCS*n2;Y#XyprHKi`2wx1@tj#RgbVwS&4=Tp&k2`BTpkLhQpSkz0L- z8o3I|`oNu_da4SzpM{{kxg7^9-eRUf99sD-=Q`!9aLe>=EDIUS*-tFMH*=n2Eqjmu zPTJDubVodvBExNc-;1qWJSI$jL`+jgfkFK%YMUXz;iL=@IxocUYsEpjz?C*8T_GA; zn=sAU6W%@7#QeP1OvkTgxUyXa9>%!x8B`H?qG+Jl!)OB>ht_l1WZ>yqAa13Z zP*M?dkrbBM(bAzOs9h051G_eXvp(;jde+9u&8nhLyPr3P_!-d|;!_B#FAc4u$FU*_ zjZ8qp`i6zP$;IIE11gt$j3{5or-k?5_7D3zOujf37e)whu9 zon1f!-mhWbs$YR!xyQkjM-?@;Yr}>kG9X*2g(q&Fqx{+#d@D|(Y<)3od9jUt+AyDV z8;Zf!f=5KqcTnIj+6zrXH=t!~6zo{?A22=<{BM&MSzWjbt`2Sn-x53CWhD!T+>S&3 z5d(bxDunEnFycLN=jn;KP3*@#=c$O;D!g2L5USjA$dCI8WXyXh`l5xQS*IuB)vb5P zfu~})MO>T2ikPzxf6YhJ{SKJx?*}~=a;PNvlbM+q0SOKkG&(*LYsD&PuZ1tkzEB4*^(VpD#aroIr3qN} zVn5ySjG+OKOE6hZ2Y?k85>buzixnm?oMjw_P zQbDy3CK&R*k{og=#M>4%bVu47@@yJFmrOTAba_JEw?}m7RwxO|*#LC|lR&=XDl2+h zQdnPAji(~xaE$6RD*bmAYA?J+!_3N{xjF<#U9J&)?MP;Px^%g9{`Z-6k@tx9qEu9b$QVf|6{Xy>*NI9}Nzs5xNoW?yS1B1w zW+@6KnTJwIhO^g6D56<|LZL~N3W+A~dH(_T2lt+{_gc^M`P7RFN&gH0Cz}hT-*hb9 zvaXCQTv`Z85&>l8hM$7#?i010;7&ctcF;bXD`dkOdx(`In0j31TqQ6}lwqmF88F{Jnp@WjIJsBoZYcbtPQpBL%H}=jxZDOm z3T(+YVe!~BbPIDzM!}Ez6b$scjyA4GnBDU$g!tbrym|14X;-5xS6TTOKB+}9;#Z1^ z@s_(FrV~JpRLlUYC$(S@W{svt*Md%UC=GWzKqW(d5^aM^KvbGUes|OmcPK)f0Rf-P zxnTD6ImwTIFP!az0IpUMnV?!~cm4wH-f^xxXkY?q)MjDENF8=IISza3Jn^1l04csE z{3C}efN`U-sPU!|ZGJHxL#9{Lo61dO>u}q09g!2c@+zJCKBtB~=o7I|*7z3w@nUeQ?pKloqBIlJVCA!C|g08`zr!OIsbGup=9# zMM6fQaUZSGJq77YUJyMQ8NSQnEza5Un>@SE@U8WYSiF`aj{EA!)8B^#SKm(%Jn-0On?Yv%^przdM=xQr12G=Ah{R>iQD{!vaR#@#}8INJ`5B)mz_ z^mlko`Xn|vr&EdZ-PkO@4z>6i!5Js)wf5=Yf`nZV=O52xYX0W*N{pamR}YMhR)L_M z)#TsoFz{}TrHg|V!NWTd>;L6(6`zMVe*Gu9r^=liR^CPajA(-XeFWqitigNdI|$gR z1ck{CWYe<=q|P9ko{b&>yR;g>aj}0n?-Yf;F+mud(9g`?(axxjScdMm7Bb$J)u`67 ziJI1Z6uLQKxcqT34x2xVn3yNQ+>eTIa>sWXl!N?Pswv7<7HJQes{L2J^%)s!b8UAuA5e}#;^Z5`f9dQ2CwCa5BvOaFf03RO}NF!O(4cN32cnQ03UGNGbe5MleveKcxA!HF)Xb}s|2Fp zPITNSQ{;8nK6U}VYH$YErJL#ZE?1~A3gRcep2h!IIYje!1n}DHK4I|L*NE{V{>4L6 z{^`(cevQFxa>q89Ruw6-hawB$k+B%Na@7egT0xTiHDMl`b?*TDZEc|^UkK;^Ixm*@2&-{4e*Doj8n+}H9GM@ChkO|}7}eDMkG{>qncR(VK{A1kB7Hwe5z z>k7&W&bYlluHk_7Bl*P87lnmca6 zrNwjL-N~KcqI8m~= zl2>=RFJ)rvD1RTErsY8!dBX1bID^cW=0RUE1upJZBopICl;;M=W5JHo^mq0L(SI>b zB<#~edTwqd?)pT_zsct@`koi*=zKefbI2qT&Rel_Qy@wIEX(+>Pot|drsBzoEZMbY z1TPxjLJu7HfER8bM0@ru(Q_OJce|>g&2R;2b^Qh}gU--D!&2bO+i=dKHyr+4lfv5j zop``Ym*~;mm^%9xx(!_bxj-}6(VIxK_r2iy-#DVvwsOp0)XTKtY&uE13FRa@=v}CT zIg*{^$$4=;@Rk?-aLtA+*L3B21|7MX)30EkhdzJoMLry!RmU~YjiSN!`EX;)5%gPJ zgioI@0gG~hKmNgmS-W@ve5iF3XmlGc{&oo)6Z7cao_UzEXEtM)5CE9}Rd`ptg8DV< zK>Lv@l^JuA>O9Xy2DqsxP>9M(31}3QXlD=8C9+z>p|OJA%d)tz3~u7j5~g4R+ho@RCe2?k&-V z+0zs;VRAI7^*Kwb1Vz@|BZPj28Y-4t*Vyktz!__GY052yyaN=foM`ym>i*h8dWfZ+Q!C!P0 za_70ay!it!-ue4Y)cfxd^^KO}2QO=p?W%XFbDIp#c~%F1zI`Fe^Hm{2XCgntRgLd5 zDZr|MlQ{jS53ZcLi#GF??3hjS1poAU^zaWQv75AM*10`cr8@~nkI%%{--^rmmk3Xr zRbf(25sm$tMSPTR)9kDu`p}r8hg1Dv`0gYi4aey4<$_Z{$n>@)?7-;$cnhVc@rfngkZKgz9C6Wc-sx2EWYs2PF zvx6OVv!L`sG&90M6|Zb>B*!Q2AQK+P!I+9b=-9&JH?#A^);bZ6M7L2h@lcd1xI)%% znS_C-)M4?~1>~kSC7p)m7-w`}cOd;*|0fw8_jR zp=PuTiW#p$d%tpAld%lnd^jO6g9hO6oGDNrBe-FI+y-y+d8~!O2{JQa50u%aQ`53A zk=YV!x^rX=r@6kQ$TAxGm9Nu9$+_H3e>XBu>JF|rJQ^3>uc9^rCvBi_hA6(? z44+8);nk+sqRy}aEbJ8L98~0RS4;-%`lgQp$&mO~JQYQ^SqjhcC|IxK0>R32(R1x& zG%`QVwY|v1qW4Xl-q@#bA%6-yxoD3EgDw!4%m$$oHJ94UuY!d_PI=XgdwAYXC^F1& z#!<&Rk(=y}KAQ{hgliw{lgfmimQS3dLI#Ynd{BDosRaDfc@FL#Wn|^uUaAnRj(ZBj zaboo}RN6&xbB(}#_Fscn6x6^550U*wJFrB<7FSApqt~!BWaFHL-mt(E^?!{4Q%3SJ zFNJRVml^!a{liI=>R~))^^j&qEvCy)uO_)J_etK~M(*i<<3R0mgy|Na@i2Xd1=eQn zXR7bbf+K@!7~Ek_3ayWjh(X~@@+5@&WY#XN3>$@IDvg^aUOjI z_KoM;Q`q)nZV77N5EY_KZu|Xlwy>$$=?kb|9*Uw3@&Pts7 zw+NNbOoS{HGU1+g=|>Isvh>Xo{K#W2*ra_9W%j7@8M5Q}1J^!ce6|u_RxQoDcdx>M z)m3O)JDayO*oe|8#&GS@PSnX)Wk*X)VjmT1@k3QUPcY7_7{)mrx9%~-69HKJ)eh+YYv7- z$0B>A2qzxT#CcV(xtZ-xU^;`K_i-(84=W)b^4HUwXB)YNQG&~?cNZxzsey-okg}1H8zXrgt2#U-nceoGf&W=gF@#&K7*{g>VY=1hx39fi$>ln5_Vh% zFfMpJO#Yw?vkli1S$--=O1%Yk^$-pn8({iBHi1!v4jQz#V8<3!G<;V;8-837)jSaT z3UR6^o#0oVk!r&ob7%0U;J|PZxSJ01tKs=?378YtPyS8FB4WKhbpP6R=1o>Q9=-G2 z^mRoRV>9Un9mo^BFe(%I*<~q^d?yiPkL^HH^-?f7lLg;ABk3{5K*+|)qL`Q^mespJ zRF)L^wQ)E-mNO3CLrR^ndy9zxd?!+)QGk@NO~`(MN1=+O+$xHc5njuhh7KZ=gK5lOW>Q?b4+ z3m?vSf?v;=qnL6bZet(PmYTluWjmCakJsLa5;V8tZ9}0wv~dDXdNG`Mw1sm9f5x)w zJRXu`OE1IG8&^R#a2-szBL;sWHh|dpDWEetOkmRN#(QoScr0ox>HHgt0dFQ@Yr}i` zc}^Rhl<*XH*~a3gG8?MwAOreJ?eu$_3J~Y*7?@dzX@8r`(?7OT&HY>P{hITn>aI1+ zdh3RX&xe@F+NtCoZRcFwlStns6Vbwu#hm3EUFvyiG#M5yj(a+jXvfBd+>>QOuWW7} z2JH(ZmTzKFDf$CbS^klFteissj2H&XJx5W$r+dq-i=1)!`J-sNq?^2dd4xL6IYq%{ z44W`L8}DxOC#8u_blQPblsm43wn-Q1>=1eG@wXOu<@t_uy!%%E((w`$Hx80tRm%M4 zmH*MLo37EZ)|xOaEt7~}n+f-?T*qtwwqT4!0#r>}fQd`alCQ%)kn|5*aJ@qg*1n$y z)z>cIH`qXv=bSdV`+t*&)orPLmszbJ6j2GLl{Eakb%MQONaA+_QEq+9YEH z+g)?X9|;xeaK#q}KlsqB6{Cfod@}wP_SPB)1MrQ}Ij%1daBqGo{)vg819896w!j64 zvelrnshIl8D8i)iMa-G{do;4lfg9PGLhPAf@QdZhQy(`loLxwq%qrpRT@Og=jiKk& zGs&y+G&o51L-r^uP*g1um?s>@gTJ<~ONd{g}yLCHUz(_M-mm z`RMYw0S#r!>B)*mID39Ss>SMJUb_*3-AXzz&m=Ib51!5m)zgz-U5!jthO+94NtjSn8LmY3vWMD9ZAzw{$=*<(E)IvcQa}V#N zE>;srxV`W$S+Nx2(jLH--$6{|#zeRx>n`*MQ#rMXG5Er*kVZaI0CNp3fw^)CqZeIa zEdGvwm$9~3E?G>656JN*K|()5S{h}I3UJe+0Q|P90u3`gaQ}xhIH+of-}8UcxhF5; z`?bw9Qt28qOm#Q@5L7w|=y1ytJVrFm4&QU{w( z=YneUU7{i>Lm!R)2og#oVaW+`c>Fy8GTSRjY!09(a0TX@51@U8IwqdbBd+RGamyVh&YRt!jk&pwHkewfc;oe6v zRxA^?oCv|}DsyVpRYzB?R2A6gWwdZ*E;ld7h5jfIp<3Zec-g&)@qV=y#jb1Oy{a&{ z)^7?h-x=0;`at+wbBzA?uKZJB3hrXIVy~|hj!Et#Z&F9%`1iNyNbi?)mz+H|-Z4cw z(-XQ6Un@J=y#)r!WHJ7`6UO)DmNz{-N#i~WtgahXL@s3k41Z<@&lWC+bFZJF-k9xZ zZMh6;nKO8JPbsbYXG0cGZ-d2hb)aig0*VHCpxpEl{H8vq$$9oGyp`t~(|p1{~EXqI4y zl`Vz+Mw`hd{yUNGjbT>53qZL4hK`anBOS7jX}VT2Is3++Ngk8R_%9cMN7ikO%kaZh z3YJu1b~Db7ac6GNnS>S*I{ej-+fZ6jM&R;ar#EB+(8>2N{n5n`pPYQ`+qgw=E{})) zEESXq4#uC}JiWDJC-!9Z(z3TZaH7Ly3|hZN;O4L5)jEOa<)`y@auFo)`Wsr}l1vnQ z$3l#!8AQB@B1hKUBNis#i3zztX1k819?NHT|GIxC0c{YGGANFjBMnTXAMps#r%g{+6>cid;a(F8K zx)p-uN@a}7K>}KKud&QbPT;n?z|uTp9IF0I#kL8(WW9@U_2o0cC!|{561$xI$q&Yw z*{PgHy(Zq;ClKR?&f{m9Gcc#c6OSC1<~3u+uxYPeFdLXPbois&kQ1K;l}~lqq%AEt z;<6j+wlv_2n@hk>&lpD-$@6+uURb&145}9%#bP!E{tO?B`@XHf1F8+QJvTf(_w}wbj`ck<6rA9paN zMhdiD)nIOEHo1IrH|&}J24<(7hlN9{VNpssSNT;Jx-2x{O6xN`f5eQhcq}+WH~&KJ zMLl|CjpPGnY{a+I{BgL{aXjAJM%Ecn%AQXH?Kg7xQ(6NhnJt)P5sYG8Ex7S;TDjev zA9T*K_jHTrYVv5W#zv$uC%iwCpV`Y`Lbh=4D2l<4uUhea z$XH%QaW!%o+I&Kbz@g3Pp{Hlf<@bNK1J@l-r1BNGe{kt7hz^uBbGWh z(nW43z}ljk$c|n>K4w3FHQQzJ$MbHSS{DIJ{E|`;lNC|YPScJ;(Ng7^aBWr=n{4YJ0ZB|D`dkgHaD|UUoe61N&&f99j zwr6jtr|BXr4vXMIR}ZIt)xP9#QZW>F=#tBm{*p_>T|mZg9Xu@xf%DhxK*iRYmh`xi zVf8o5$8U(F&7)0dzLW_a&|89+!)8I4Q#u^3$c4)E4m$E^EMxy`CD}4i#T}a`a0Dvm z;|8lc%$G$=;QHMv=pNh382bg_$*M{!+xZo%PAA~Z9rM^jn+u3hoj>^g&VUsk9^uhp z4>0|vKi78j5_)ue!x-;TykpB{vfD`o-qt8%Z(lsjc=H--HOJ61e@F3

    oyFN{EBJ zEW2~CkUa1m!`_&z&hqYcWO-*AYDp$RM%^{2>HChN182y&c3(JPA%mM-Ie7X-*ty-5 z=EI$9(d6$tl6bKN!v(&pM0pYJ*YE;`P6f70c^K>VND-7|mUH7B2Z?s!RroabIn3Sn z9k|)$`00-Zc~Eo$H7i;m@vJ9xJAECMTI*5nVw>cXD;Pu4f`he3XR|$`vVsqe@nVYj(~21=lJrb z0dMiP9##BBSZqI^eU|Kq#$MIBHDeg2TxS4B;pMXU; zhyNDx7VEubd7s@Z^XrWz?pLZMi|QU>QAs%XSjEAL&W$u<&O)%?Gn|#}@q@c_&8U6+ z1IQb4BAd5}aMP_Lpge9Z33aS0RUKwa!n#X@F3eic6|&85e|~|s?oqhVU*Hy}7_gUK zC83vl2N_*8NG3%2U_-VU&iN_^&XJ>V=X^7W(mKFD^!-b=&-e(s(;2=Wx8cFWLR#Ia z4QbL|Lhxwxpa?VDW|<`1zr`N z>2-hp!|}Zv1y18=)KXZ1$6m<@9FF6}spJV0``VU!HUDk-?R7KA?V@2cc?l(2a~;w8 z;1K*6uK`7N32-iT1JTtt=5g~dUic(hzENK=E63n&x`tD_8jO#U!%dCzJn1199}>P% z62y0VW9k$)KH^Oz)Qk$oSwiRX=EI}dYPk!RTcwe=i!V{ltZBIAY(Cc6N21ZSAk5!z z7A;eXQ6|O(@4j-xlI8K7Yob1#cx64_-wOCoU?6@9pfvi-JZyICCIy+NIJKmDX0P5v z5-6NIdmPc`7RziCnExs>23OX#u@%ioI3&V{sHiRO;|~T0Pufgi7iea(R-KRZvH+T z>t8pMeH{<+r_=<&G5ku@HoHx<=EN4b^1TE8JQrb?{0->)%|rQUc_{u_hwCN(_rPA2=&Krf<)L5cm+O%8u@W>BX$e3_~$Ls zbvX|*{-!eXAFW3%`NJe!XFmiUtb`m-ITSnFO!dv@!FrVzx;{o9uDU9*S?!6Cw8xx2 zoz@8dow*IwrJZ!@3P-5YQ%4=0ML23>ae3Z-JNk0fX)CCnW!JU0(NAk)L5!N6uK zEScF2=Is;N$_8^gsjo77^qcFH`u(P8>gJ3t_8wieK!}Y?~mgbh3N3( zibMF%G>-fHV-~MxK98SpT8(wSBb-Bj1@IoitYO+&1vX-(7Tf7N$b9^rOG_%Ng-pjt za?9oldV8qx?(1?fVRQ#^iJgpXZXdXAOG<|V)%lfQb(pa?O}Lt6r|?XBAnDxA(GB7G zR9ih5hZ|K3nUz_%aIYzp%_<{}^*N$#&cUF+|1KnNHs#Iz%^|z=0yKnb@&-Gc;OzZh zOx~ja{94gMJ_X%|C6`9R+{|RSvj07lBrJ{F7WfQ%n!W<}w~Q z3nx}N^I22UY0R}UY6Fg_xI-U2OtNTsV;NOFa)d_x9L+nl9L5``#)G|?2Jt8{EcKNCR8D8hq1VN6t^4OqWRgqBARd zNw3jbP&(aD?lk3+Q^wQaqUT%Mt^SQX*|r(hFKZK}8UKP}eh_vJFfhvKFfqINNKhkW zk?E%uAb-y(=EvLzVD94qlf$>MEB(aSx%W73r`JhHI`9JGs*Ui!S=} zH@S;Z3+arYVsIEy4Yh8km~r1vg8zm*7%Q<5rxvZpr-^;A=*BOa9GgwvKM_Z*+n33y zi+#jOtQF3D)PkV(X%Kbv0`+7|$P@2}a9SmejNKaxua=Kzi=(c9;)2xjEC1PmVb2&a zT{Dl>O5MTA_EKmlxeaA`axnUD8hsvU2wSBECcnXEP}k0&Up2NsjCdjpsO}JUw0f}o zOBL0=z5#yN?1XWb_QH-cPNrXZC$KoGLe0&D?7q<^SS)o5X8v2pwYo|2*F(4AZ&r~% zuX+;Gs#W;LQzrZ;UkxZMKaH6?SMjRXbYR|r`!FhhH?63VfiJ7(@btV1ze|{HFQ28% zYl}O>yDCX?Y2h|L^t>#;StTY&D+;Qez!3gxkQHbE31b`3O2B9b2y2-V+OlRvp{F&%ktYF z(qQD%57cjdDSiD}g;o?Oa_(o<`BK3f5Z<%~u0}V&&dIkhq$`q(-Mt=fEZqTc#|K)b zEQK#OGU2g>HoLV^nw4(xCf4f;sDHv;ZeFk!4rm54oAp_cwyY&?nPIG7*9=zIT0}k$ z9meM}4di^f4t2fnO9!kXh{@L(kg{8Z+vDWQN$M7AZ+(-xE)J!N_NVFdL7`u=WhKe6 z@e-IMI?%WGA5-j{BC0wREieOHm;r?nu(y9Cbk2@I#(+9L8T5qQ<}dK(21oZ-9HI`g zyD>3Hi`UqV`29~LCR|J+OEfAiecKaJUaXz`3hX7xn~#CWMgoVgpGHDr+UPT>yC`!&jnh;qUhb^{+Y9|{{0V;e$q7ZXkjk=OxTZ`Dqdpyq-zkF_FiD0B*LGE8dS7* zkWTmjWV}NRItZMw$A!Of;qMXbl|OTE^%)hcl<|Q|^)8$+D+6y-AAx|(SuD2~$!isL zTKGqS-F*H4+#4;B@>4va&vi5(Q?&sqQx)L)0&x_jc~E<+We^uwhd<4Kp!wqns=o3T z8r*Q>R_vD*IO{4jeOm-RZjit`Y3^k1wApxJ&pn)SRFe1iGJ&p$N_uSbA#jxnBAhva zqRY+Z+dbEqAIfzX0!-4@W<-rSO=k!jR7Y z&`&K%6mv}i8yb1hH}`&~Ud{mCIoWYadrh#RvQgABxDr49QlyH9UC60SisEYPxasZs z^!kS;5_(0R{xr>EWH!H}dD~R!p)$eop>r1xt{zWw!+(-dPENR2=t2&t6u{wAgjB7! z!Do6oqSowwS|KVTgDvv3xMDBK?otE==@J^&_>md6;Wr)KvJF0552jt_U-8T>EzEa0 zj#1v*5=%vnv`K%lcNV|h~ z<5=!R@mr!@@&KNkaHdYHJMqETG)CdVaolWp0w2%4NtJv1iD6m~RDR`PhP)~N%4ZV4 z?)yi~lF>&4>3H&AR5ZD5aF&QWjpZ&!+Crn-1Rf<+sm84#GB?5x*N&G4jfKNt#J@6p zDVfi}zaYB9`5`fy)=jtg24m(N7OY>a1Pcp+VVRo*qdv*8X9w!w(b2_tcU2?$8owpJ zr8nXD{)xokNExUFoWP>#SIE`z&$-N(wRjodmTMqRxsCS`;*iTD4Ec_dnGD zbNZ>A#~AkFFkQHrr3k$3N03y%#x%{2U_2!M!mYe zr<@=uQX7iJ!tle9ccek#DRsMXgDf9uN|yKfqiA3)O08K6z42)%Hq)5ijEKg*ZACQt zD^E-7t#C^AZ1DG5h+NHh6MR^Qrc8tK)eNu2!%nGEdEXZ~yf}Gx80dc<9p?J49oUGSk;~PyNq(dB9 zKV5>$(d%KMWHvdsAPjC3S$r(&pt0}WAt@~lqK5=dpw?wbmbM0q`6cis%n+QOYqAc7 z&GhWqmyGU!BAvz0r0H@~m?tVZbc6d*u4>SPwCa4N0dx#McK&>nKK6qq)vNH|CgxJx z)EngEqp`e^#eM4eEF4yi>!$iUQ=l|^7CU&Q4m%3+Fjv=@_zUL;`{H8idFKa_6PMrv zc^jIMGLet>jllcwzHm2l0re||UGsKXx@7eWqGa(4Bjsc1oxe8JZ~F#;f7w93{8hqH zS{ns_z(ee94W#ET%!J`H&%viX=l(B>AwwGyx!yZ{Waw@e%szX9?hMo8e2ALqEgqT9-R1-4Zfj;nGJZrq{tK?#l9=_)$; zJ&l-pC7^EDHBs&eUDh-F8EpG@1nA%_{I6{kd|*}Z2Z^9cYpYSKNEfD^=wp&j4uiAt z572SCA-=UehWdV=xSrL3P6dkmm)^^;N6LxhbTy&hQGtmUmWC-?%;8s>CAr@dh^Kds zfgW2~yg9j^m<)D9=S)TZt$Yn;Y!LF_|2FVHs=f=J3O9JDt10Q_E=zf5VJ}p z$=m}W5D;mH50Z5SMsEf7X5`AG+yvcP(qpX2 zzSnRd`hCOLfW$UxEcjC_x3c7r!6o#sn1e~zO2}2IJ-BAOJ+L`%z;jqIWKbWX<@=l{ z&wC+vqj*9y&H!%ZL0hewrODRo^6=gTZsu*UC{P# z8vJz3CB;)763@6vRHYzSGu9)R+n#SpX?!e~7^lu=nBRa;4#sGiTtIeh9?jbK zIe}WRBKzaqJop`X2Yj0>S%Yb>L0jMjOmGNI(_3x!4f&T_k^wUpFPW?xNqr0LDU`~ zY3KuQ4L^BiZBhQgrDVpe58jYP@A)Hxa7|k&rMlbj_kqWBIALS}&Rj(BG?~;evk4L}( z$xBdFT>u-NzNL{WLxj%|W?M!Z@XrJx)7IBT?~xr~xc?ewcX%6B_trpfO%s?|-h*BX zyNR-n3_c3nfVXxGBYkfosLAB%`~uHMRK4N^9?R~a?&FB(}D?#q_3^=}OJ8v;_2fZHiip+6a!)K3_CtK8A;A_fCUhUZl7$^P~?rXGhE3=2V zJj*Up|KKzs51NIZ#a_m7ZX!AOJD-lUZPw2QLFU4aHL;*=p>vbca)JpW6- zst3|*QU27uj3Ki^GQiboAw0+*2HSF#*^|@6$zX^T{#y18<~H497u~deAJ;w!j z?=Grnqy}bbp|HBxfph;_4L^mh*(v{p#5U1`I-I`^vOAEn@=r;WWFTxmqX;usJ|jcT z`aE?hW}NnoW$$*_@bfChVAs-inEKrp!`d$3RlicWEu}=|fgVfotPxwuH;*$eXeDJ4vq*67E%DjGs;>Wgwquf?r!hmRBZcDr}r{9hdr zQxkfAzqVknP9Jghsx6;u+z2r`92i$P;w!5>tQ%_qtDhu8v&2@qm#riRmE~a|W;XN1 zV=#MVK~x{>*EUZ+#M(V1A$U z30&mMi5-w+WC>SoIqFy@1*Mmq;Y7*^CR`yN4hcEsQ^FlvirWqzpOsy99k!C|ddjy-^zKPwnNen+^ z3ipB5&!qK%9(B^Gqj{q>(8YH-@00AppEz`azFZ!KoNf{pe_BIk?42QU8g~GtzC0(2 zTYp05_8K_4S8&<>C(McKkHUp`Q%Dk6gIiu1GxM1=@YpBL$Ft|~M_L*6-z~#6FUbOL z7jaVGz7bdXkHF+*A7QEd2Yl#v8Fj>s$=<&&>GzUsnq45v`bI=^CS@a_-ZUP%FWU1b z#mjJ|mp1-rT+A#zA?P#LIm4z8S-@?0$cUX0=514x*xK~v>}`K{I2|C&TmnhQe&yqwH~T|SP}Pl{N?`Kze9eCEO2GYbeK9$o9~%2 z2A!6@Bw^_u#3d$>u5+4=yR;^OpK}JOes9i1<=;TvqCL>7J{&+@=zMw$9h11#*dAJq zf6}KSQ}-XNe(AtpiU>h>@)i`W^wFX)7^m5eWK#scr}>n>U?h(ud!q;U$i6~ zvm$SS%WFy$+)`o1VWGDeT0$qi-^GOF<)FfJH~!7cBzotU4{3_Cz!CpC=(;7xF#Aa? z{Nh`oDX|?#qL9nW4uTc-qj<&Xqp6lzI^+g!VZio|;Bk=?tvk2~``0C6T)+vs=es6s zSrJS+)|`ffLNl!WBZQXXTIh{Gp=3;hM!8PHZv2$uPTs!=6Yf`|p_UfVS|!9&s%GTZ zOGEzH#xAnhRs~I@FBAX!k@Um$P_%hoL__ivNzsEm>Rua+a$yFX(uzGe&^VtY)EJOu zI&HK`lt(fnrg8iIa+y)`#<r;L+=_wPTSG@uiXmcckrxk4HwH29M%ZbEGSEEGFgMZU8I7Gi41M+aW-167P3C7BqFb;7Vi*4B0H^ zm&hmK$-@uO{kxQBZtuHgoXPExDld-!Kl6yCeIn%}$Cir?-i zxXXpkJKfM_dc3xYTr&G$I{#l!`E@P`mrCv8{WLoNiNq&?mG#Ms<#H1D|_!I$NH^)&!?HnkcIhAV^ zUkA2V;_=?Lw`6z2YM7__7B1M|f&_Mes4f=HFE<26QJXVd6*Hof(GGo82g;Q)4@2*c zN}B%WAWAwIVgGd{ba|Wwp*{21B@RMHHA{jG5prvrl>^Xbp5O~OpMb_6cH_UjQBN1N|a&MN;%riO=A5#;e#8?~ZuJ#jV_f{m1ih z_Nwi$Y|cIWZ_@*aJYGtw$6m(xSrgdmM?0}OT8R&6Jqt}=ERfOYrm9cR(xgdAv@Mbzlg=sPYXb5?lA1WZoz1( z*K*0f6Y$6tZS?JLWiDJPC6iu?;q>iuL}4*Xm?C;j1w4-FQ*9R*QFjLX6I#iT(Ma~- z_cp2_%y*Bk{fI4NQ!!M6lFvkqedMtU-j|($;Q_X!_E-gd{is0j9jxImTO0DvqO+*G z=K(rHUL4;Q)YD@h-0--fW7)(4c@nxPTXbILGI_f(7TvqFQ2S#(=i)}G!?qu$EtSFC zZ_SCgX>AvlR?0$WmIFRNJq=Tj9s#uucQB2Whpd4;L?JPR+J0wQ!4A)^^Gc;}502&k zo}Y5UjPFg|S;FLS~Knd1gT|}Sz8khV0+s0Xp&%x@^yRkg9Psm+} zu@8a@L8ZnVE^D?@O*g>@xaK#>G5C+(U7ehi1| zqgk;BKI~lO@38XWJ8%mg4I$dn{Mfo|IF;DM`I>vt{s<+0UhF}>U@6Bf7-PV0TX7wN zrf&nAwot0$c?PDBNJG`ir5LmFA>vdaYqD$*Ym*AmKB1g+e~{(RR|*XCPYdw7Oc-BO zV9a~zoy6_=J9+spIt#IIz|Tt!|CyFIiKJAGeB|#b~it+PdMF8eu={ zJrOO^tHA@_1P7&8;pJopkbZgv+A?yXuJUK;4GlNk(K?2T1uHP!HL6&p89-jxpTgf| zJ#cM1;rFU8=g<8rAs1H{a48j5m|i>#r7a|Af$tA)$0Hxywl5BiUVCG*OdB;}He#)i zLw;scM{YW2VqK;zUl`Ru;!l);#QRLx9GL+9rcHF-sy%q*#b>%!WgXsXR7X&BqMMdZ zf!l?$6n7iqM_*ywQeq3~#U{wSZK5rAC=>eb7%JX6!r8o>2M-QUp;lvM`85#&3o*U} zJ{dm8TZhKb#g`%n0cT2Pg19{tzuMXyENO$3k2nIs3wH_b>ermk zSr-U!e2#5(&eVg`g1a7$a6rg3ejWFo9IBSYMJ96m1p|fM~fSWkG_Gu-oOv!;W%28-Obv3W#9L8JS z6XP%4mSBH-MnH4tZ^lPYov5sv1sY)qTXmfh&*oCP0O=d|}+ zmc$hl8|Eug_I^SKo5c9aCyv*eMx=?%z&{!C*nAZzs#q3_lbXv2k!E$;^giC zw`GFhWqE!RH}y6`$-qiHSg*kwS-r*u4R@fP&7eci7c;rrWqC&l8U9)JEchQqXW~xP z+l65=W}XrXkxBzeDeQNh3~3+=p-2>I(1=u0#*9gZGG;0vl|+U8t{oZ_QIaO9)K4X( zQW`XT`}+f2*Kr*0+3#Aa?wlCB)hNk1<_ow3`hW5AKp_Ma48y;l*GQgXA#s^KPS9oI08w@mATKQr z0yi3hp}ZXC{VGD|*it$oG6UQjpVFs6CW4CcZ}_T@=bJj;C%!Yy(Wb+K)?YA&nRojk zu;B(-CTO7_B~)<2cm;fRXD<$zB(sa1bIGF8a6Ife8$a2~0sZ9*nj_)ZJebbUCb-`(irY|=Q#KnFAr}0$6?p1 zE12xUzt&foaP@K?{SmVn|CpV|4X=xF(u{eW3IF`@V_hT_(YT0P45#3)r=OrcOcD&u zK7ps1E!ULqz{Ob(WB$tNoM2of$+TAI79TDEF~&eJxpFsjb-#iaMz0|PzF}X04w$Ug zz)72D;MEi2+ab6ovxz~ngRFe-sn_noe|2eS^t%8*eZ#37k-lE79wQfokpCN zN$_Y=0I6A|iYm{K^1I*FxWK@ZYD^nPviYu^e_k59Ve1kw_Gh6Ht>BE|2l8TA1S0ue zriW`F-cI3jb)kB&e`^r&(rRNI7DdcBF2*ZH9OJLApfzk{t3SK;h&eOi+!hL2v2qfe)7 z#5+@-pzFCyIBoJ%^oz(urNyea`O}ZOlz@}?cH20vWBE@Uu{8o&zJF2j<}%aO-~{cZ zqJr?v2jS7k3*5O>k(;ah2gTP(Ae2sro7}+!5H+?C$L$y6R;C$p!k?$o8`>+dUZ@-)rwCNcvvG37 zthzPcL0rHICGKzIdXDiZqGm4-fqirpZc%vxxCG@*RfNBZH*ljT4Oh z>&AO7CevTPMcF&18F+N^Ir?bo6KM8NrOx$EXv^m{>^D9oS&1t!!z~N_m%8CJ`LQU! z?KJFIy@+a+{h?+(^8^#O9HF|i-q9xI6tcTYl)HGh3liV%pi@=nP+i>sJlvS3i!>b?0As~7lQLKghmmXhkHskrBLDf@({Q7rwUPK>qXK!=|d_JlH|EGnL~ z|J(pS-w1>Kff=lFqZ%|m{zN8(A0P=4^<>iBZYKG%0dj}_(8iH=JSek>Iez9O`RFNx z8XGjB`|C`i5O*9mM&G3>#@6^_Sr0}J#=xYCP_QUVpyj@fuvJ=2Ff%!u^fXzZ%Xw9< zb=q6(VWq%*x+iUo@gteBo|s+IK_*^!gH@B-(RZFT=1&_T=_9{!-OdiIKVgD}F_PTP zrP^GSayiP}&cp*BZRobZUF5uE1IB&ah>~9pl9My_uzt@9oWwIh-`7iWMOV(zBf{rF zK2EWD?HwHKth z7p>z^VNWj&mh(bcmu2{8=O)yzEu9jR~1hme1NC)`p{zMRo=A|fVrjL=!lRxXJDnm&CK3xbc$H!wI&)JM#bQ(g# z^1#+X0w&K9gRAB~5VSb~PJPd%mv22I^KUuw4uu!|9$*GEm`;YlX{E4Yp(f1o_oe~U zCg3c^V>H;~W!;q6Q&f4Q8RQlmflyBioN1SchOXKe92J8n*MG*_J6LqtFGX)oyF_&6 zH_^4WQrzOjSII!)6O#6=1|=@UQt=5v)I2+i++zK+xOkJf@EXv^Qx-jD zd0?onD%Yi-1f|s(q(8C+`bzoTJMRNatI{V0k4s?JX$e&G9ffC4&B6NZbtX})8nXPh z!__tXgj|95Jr~Q+vJINVf#*&gA36*_m3D%6-#v2dcqp`%b`tGtXX(40S!9`!Jl|Wl zgln^3)2o-yu$qRFGwDJt~e zC7eHU9-FWJ#o|0i-h<-B9N%Mz^Y#@|yrf4iMh9=ZEze3PG*-PI?%B4r$<&LV_^`rubm0E&5mAWR>&Ik8c>2mUVnFF&xY6bbUWENSbn1m8F@|d=?mfEYc z?3w?fcu)EoOr4#>Wo8mfxqZ%4&&ap)6Rc&1GgkUQa~- z3BiKQSO_|33zDsBVB46??3CF-&*dJ*nSFde(^?g~qq4BDW;4!SD#V!t-DJn5&A}i4 z61k0ASL5NhOQ@wK$*oGWpf49JpbOKxsZ!Y?c3+<_yeg=LPCaw+GV;x9EQc^>|rR8Ol7bqOQSK-Zfv0*BuK;648U(xx%PAFojw?@q?HRmzm{t z@i0l`0#UDPBBNJ1@Mxce32#{PX;(4omrdiHYZ`)T*;Y37Qykp3@(_eg?87HPrleK$ z012IS8Xwgq&>08r;FkVwh%xB~-O8!3V%cJxqb$Hp5iaD?x>qRk?jrV^=HtuRkHJnp zl)f5eQS{w;l#-U_3Y+F}O<~2D{q-`sCSK;xP%ECbZ3Kn&V)W^pIou&>ACY>qo?%LaQR1R_?&&1c>Fxc8m@Mxa#4B+Z2aOJ(4!mUTGiY$ch$FbU4Z`M_QI z$@H|%HBi6UL4793fmP@x^fr)#1cTe==Th8>$zdb%WyPkgS=p&dod>Myp7q*KLMBW4n`CXv2%G3 zS2k(DcYBga{23j%EWHivw9~OQ;Rj~koPrvWQAAhoD5fUW@foC*=7%bJa5q1j+vL_s zZw!v1e$!L%(<2GAEYj!dzlfrks|mi{)xd-vi@|%%i^##B>9l3hDja#?!JMeHjOtayCP8#;5-hkEr3}Akh5SPe5uP+#GrkeNXVQq{g zjyK!}Yf490UE^o;@}?>@JekFuHA6b9;w-g1x)>~uXOWs^l5A_3I_H;Pjo)Ya@L2^D zoG{G_eOs!63`Gn0nv<|o3By?5|*&{j+{wLmBBU@TZ;O}P8((Ut5h7W zRRlHH`$*%VLAYGI0Co&naY@%IC~^7@aW?N@urrqa?OhI6WMsi`>kKH44&%?QdT3B} z0JmKhT($d0yzp2Siu0~u-)I-xZ?zj+f2zZ?Az?w^q5taE*AC(NGv7#5%|90SdvUit z->Xnj<3dhkW3@Nm9q+jSwp=G%zVFHXw;jPJ?GL=ZC@r`;`WcJ-Uy!!CGPN&}x=cH6YSeNrVB9bk_%x6?x4Xc1iYdM_okFl$7Io*>fLF_JqQ7G~ zu2Qf=!}SbRiLiv|-t{OEHbBImYd{Q-?>D95T<#bC4*Kmn9-0aGW?wSIoi*UjteMnEd}@T> zw%ek2{$y@D!!r@n!_ncy6i(q6KQG>=1!jJE7{YF+PA0{8aMv|+Tq?&U)GBikI=pwn z$DWH;dxS+YdE{uj0ggC!;7dtYs1kbvx6Pkm-Ck?BQ<5Z@UV4Y}5=Zjf_Y&{{eke^W z1CbjkP&KE9;_4D|dI{hq$isx|5kyY&80PUDFu}(~A6B)xgajt+fdfHl=%VwU424w@wS+*Z%dH`L4q4=#?lS7F zlED6oO~#%VuSsvQ5ZAdp6*raZa8A0@>P*hA!RKE2)PEY!@K8AnlVBZauY3er|4C4% zC6W;NH4`mDY?kU4O^Ir93_E<%Gq8`|HoZ_`F8ElT1a*qe*1ujt6kzN(sIECmwc4dw}%5Kv=Q8yzcpb*3`Dyn;LI@OiPxe(1Fc` zSgtvjRna*??Yh!%o}@Q6OLo->wZt=)FRtKtvl!fzQ$}6m!nk#^(cGWMqMYq)-b0@B z4V!&#(bloY=QdoI3ks>j_W4k&kL zK4+P~lnoZ!LcSehLD^`9;P$htuzvxOi5^Q%tu+f3>19r zWQFSEP^5VfH_w|)yH`!e%!1v>b<9WeYkj1Dh8N1;7VtTcH$>w4FL2zF!nRGB#Kv8i zg6~Tz=otxB)HF`QpoS>S3!Vlt?ZN^X#~QMyVI_5qWk_w5Cik`65VhZg@^dJTG5chX zb1qx~&mTrGuW|+7mtwGCpDp8+@{=fR(#PfUJFvZ9i!=NrPTyUYK{s1P!Ei5Pn`t%u zbEX>&>qlw2`8B%YUIrd~q7EBr5^dxAA-zidB>LqRs^jsHxpQX?Qr#%*ZrFo4L9;=6 zdn6Tw>-2_;tiXi0qR8ML6v+$1qx%=b%vbj@w6O$zX&k=t-cMuKrO@f4D!Bb$4n7-y z3)17j?;i;X#)g}4Yx!P(wR#9?{4E1si!vbD@HR~rK1nCL9fmc6qoiY3E@fm+ zv5~#a5SS{BlRqWlso*5KUd)t^;~fHXBQ)S}!7g^>b`>W6E{6oqxq|qDmOA+{d{;{F zAJytrfji{^IAv`Pp-Z*6eW4m$QR_VVS}dE++4q?}Gj<~U+BglD-HAb;yAqV#FC>*C z8e}-V4>u;qasQ->=>+2{G{_-1GI)4c| zY>r}+rngg}AQg1x5`lBw0=H+@P}_gbY=!w9(zR(0PCkBuQxaPx&@)yOcpb1o5%Wey zVb4)0UsKLiG%d!U!g^LDHx^A&^1ye0BELV9Clb7Y#Yp-y57;|L1)3I_v6}O% z=}6gjw(d?i-Z(rTR#@iY$fUQl{$My*%rA%GM|GsV*qpocIYS`#U0!fdA_Etk?}Wh! zpzAk(#l#9{ZjJjXc0-I3ceiaJGN(Ub?}haZEF2;&ulTr6WynBV#|j46uh$CpXOg{D7FV3IZK5FSyO;RvX5& zz@8rwoWA~CApBVq{I(I;Cu?xT<_$gkucEH)d#K=Ax)*ysHJ`Q#Z28XoIXK>Sj>zh# z*PS|b1A?DUq)nGcK>oh3z;fOm9G`L5Tyc*FQJ?2XlUK%r(wuHo?CPTj$E3h+Pl^i6 zdc30R%01!t@zT4KvFWou=R)K;u_S^&h#^jzlnCK>E|JA6k&;94>^HY*wEAu}{T^FI zePT|N`Mh8BP^T}>M;p3ysyix+n4s+FMRLV6hbXLdLWOHRc)cM3QalZjvy+6KUcgm5 zlw;q!v9Pqd1Q(}N;A8V;xLCstW}Xd%t^^&@UaZhPE%~_d_-khWbBE+Tr@gzC*j^S?2dj1k-+1Piq_qH%-+xx;j{@>v>%*{Rlo-tFwo12V|hN=Wyw!qFZUQW{E5fq zy~_ll9~=bNj=BiS3nF2bP#NjSpN7AuF6P$$Sxojhm~x%hirFen6D$fh!$W4f@WeXyc-RJr?22>QYHGUUY()arF^>`@N8EA1EWM zPP?Mmj3DZrv6NR?nBEvs@EA~_2Klk*!$0r-xa3PS!)D`{!2tYTIZW?Z ztK%2BQxL12O1@+{f=|mFI&$(MyRY^&UE`)rm12e9`A&PhFY%72>Lo!!vj%<+)ke9* zHKgrX?X4@$Kk!w;Z_ z3##UzNi5G_eYgN~T+g!oLD9H%UNd@kh~U51!e%}F)x^sT$#ugf=2N-`q)xp^a-vGG zqhK!8IxGQA=DS$lR8ORM?&Tq4V|>(nlbO@rM$TCr!t;p)@^{&jt-Ql=o7-s`e|HWs zKI1_LhX(16p=x&Us}qLpk6@06#1dueHJIfWPK#j;4 zQYaPHMIRrDK*hEwY&&U-CHIceS>t5!+eBq(5Gf|@3nOsahA=|D>_)$J+fYAa8V)Eu zrsg+gpz+Rp82i+3KN?Xac!DwW@nNP5%~z;XMVy4=@O;DWq5RM;evngxAzuY_wMv-$(s z*HT11-xx#b@I)G!P(}}bQljnmlF|OR7M?vd35R}fBpw-obP>idCyhdg0tPU;}#cWyC0R7f{gxD@~ME}bg$iD2P@hz(O zB65J)8}pKB8ks^&k4QsN^e)^UDvW3H;%U~M<)CJLg7ywY;#ZzK;WuYLz(~)E^I;>9U3=EGQ_f&fP2a8yH~66 z+t~dGzhv>#+XXms<&l~Bk2HYxLM)xzWFGz)z&<#KDD6)tsYDq5@x3CS&Io+9;5;dv zBuBHHc9IV_9l>CQBe;d#XO_sVBk?Xz=>D5J$hoA_*O{+s5BW&r`!+3VsWltjjWe+0 znj5-4zDMg%XkmWC1iElWJDPvhBV2hU>L>DZ#;s@Qr`M^tUN42*wwi)z7j0!{1#j*yFzw;P5_V5Au z;JpgxjtitAOIwL%t~L5i55S^TLnJpL1~%iuU0KBo{VhOsmD)6A(UDB2KD z!WXoW)J2y3yi*7-iu#ign>@P0^93W@DFW5Z_Q1}71WdpeDl?lVNm zsZzA2ZadCMaUv%@i)hq+0b!T!$LrQv=0oq)P~=zvz4AAWO;W8V8P{%nG+Uo zWV+2((gJg3h&N@~i_N#0u9rJ;ZCW`AZ41Vu3nWSDt!>oFcM{t8>Je3$RnG%`>|fR+MHPz2Ws>{Vo%ASCM~y9;iNk@dsClG- zw3!|-k9qQweRk(Mb;(bqc0I>Yh&7?xViah|W*yRBF^RNW@SittLpn8Vko`4P8nbpc zGqvC2@kzTSdiYe*YyUMxtl|9sUM1?H>PZYM9exu`~r$AuqU#dHBhS}krO{QE9Us|MtL+(L=tC}t<>2R#7tDu&QsmywW)@%GiHFu-VEW6i8n{~hFXeBruKtUX2k;#hRJx=>8?5JU`|f2{sBNdX_;{yZs4ik$pst z?S4RB%P)gx6?2L4U?TH#V>mv}%cdf{m?@yd(ER;%L+pR@f{yb0hGA`SyuNM|{*c{{ zCvx}DuhRRl+G{h}UGBvSf4@%NUQCDi@mcWG<1+7uo=j<1D%QTt#oZGY(B)f?;l`2| zbYxv5F57$ppMTB5cZ==F;P2n8(%~_jNrVeN(G=mV!{V@C0b zncErs#OG5K$|&Bfl@E!c=~=ojc6Z=)635f~-ghPPgB#Y+{0JkN3mtrZ3&e8Y6| z$!SjA{Y)cfhg=8KtLIFTRikjBjWK^e(<0YPz7dt?V3d#yq5Za+D19Iqe+A#bD~Fr; z{B$d8c~lg%texns5J$p_7}JMtH<BV!Eq?W9~(<$4rVb&@3 zvHIJm;uZk2o6Jo;BZRV-4eD3_v$Sf^~V;9vMoK^gvBexad^=!G(F;nv*e%Awi*Uqny!)Y zJ~p`Hzh|_zr-4p(tR`Y#O397$!Z2f!3`Dm_<1C)*7@=WNr^NH3>=vxX11pM3OT9iLRD@WpoUyC$=iUDY-;aT>rei=sb%chjp3Z-mvPi9K0{Ji75UnTV@rguTICfzs zjF+Np-TGr_J1ds&QWxO+;e~Y$b6(Nw*XH8>tqDX*#~)*E>f)eDFFi5u7c)9j6&-_A zh>6ux_I0@q)$H=2Z!0h3nl1mxqM8gk;r9c2VDA_5jaIRn`xxw4SIpK|h@lEUoAvNm zOYvX@nCSM>jeUk>R)-xa-YJIb<@GSeU_HBQt~+{1?gTe4O?cOk!i>%IqUy3D)WR{0 zmL<7^Tv{kEZC+FEE`4Km_@J`^if{^E{)l&jD2Pk>C9^0 zt@1gVI{);;vPm1zAnXAR>+r(nNgC)Vv=`e_E3o14XY)CUI+&xv@4%lc(S?&EnFG%) zcn6(0Jf3zGm)-;%Um}IXub;${8nU+YE2(lafX(V)zOQo=8dR)+B9~uva#nAsZks;M zvq?wq)CllSx!BvY7!=I zg#j!19Qh72#3du_FIPS%ZqHKdJ!gseu|aakC!XA!FUG#us)lac)Z7kCMB)}1%ou2o}){`{pT|-D^tm(EM;)%N@v~eKhsxLRy5tQo>WTB!sBgr zAY!KsvcC1q1XF*soYuyqgf7AJ!s7U0<^ZD|u$P*}YvOLLQd*y@L{^x8qFQ@3VTRl( zs+nbp!*-_ZDt85>y{U}zK@S#;GI5vhQgk?w4q^HOjCrA%`LBngbs_%N?E6_i+5Qiv z;PZAITyXrxvqfuID_Lpy8=DNhYF2cH+jwGJD1`Q%{PX@!Z_*&xOV5^-(N$;Km}QI> z{%t%;T9kb)DV8=Z?LMjM!A$)$Ap{yXvyv zpPgi2f?7P2|7~CqEWCQA=BtYpX1OYXvvCYn;LM2f)d;BiJs%uT6_CTZpV{Nb)p6?N zG2ngj1(DdgjzlSEGB)!FJruVZ^!Qx5e6bk2<kNKH0j~P72-9-(@sP%T+@7nAhFb&i{$69u4_OXb3#4dJjRjapA1Bs-){+I4 zzGQCjcK%L$ig^=pjNFP!s8g`lg|9l{uybITnm-qXK5(5OPyN5|hEFqgfx6>ks=IF@5xg8n(rza~ z)#zLD%cz?%BCWJ7+ZzSE$6Y9EFVQKGg`)*&_};h)!`1k`?XVFBJI}}ABO7tCNCXzn z?!sdu<8i)W8|j~r&iMRLCp0sgh{;Rizm0ck&(jiCU1cMP4dv4Hf-&@(ZaQ0bAO?dY zyU_WO96LC*lPOxIj&oi2;EBzaXs}!aT!&wgHKUDm;=&s=rS%Efuk()g8t`|VdS{H^ zE)LyxBIN8lZ&cf)N*j%&pj=Fh5!Fc{KZNp$ui`D*{!fl%e{_Ph*gBfTv!h=-ju#B9 z^7LvQQcl0fvK>)N{5Nxj8EjvRf?hyWAu4{@e|!Rj`V+FL=O4Ej)zZ4@EFzc3dM5 z-Yi8~s|4b8LmbvFTFD+YS%$ygJ)ko93Vj!c!mRgWVfRH-!bgZ%sg6gC=GlBKIw(oE zd5F;yGdO&5!p8imN+h{$wvV1xAA>a+u{8Ok1RgZhAV1FfVOF|3xoNPHXK~unPS>YY zzJDR)Y6gtcU$c4q-OBDa-%==eZn z-2_l3TLL?6cA?xr8Zp0Vh@GovGwHkw*0UrXooC%3KQ}xv^UK_Xq7%9ao2icBYtBr7i5Qx)Y%C;6 z3E^PVQZi-{A&Flfu@}>qv1>cSK(*+kxrWAjDw-Wm1&?*nHOB-yBHYkrTLe|pk%h2( zK)2nvYaV804x5f-(IhdR{cZG#UK8ymkqKXFpB?NVvp?6HyBwSh`Yx4Jh&-lhcYI;u ztxKe+{2p_1cn+o+95y#!FT}3S;@z)9Qrvo>i@5y~zk5s_!aFv+*PQIe%=1stuxAMC z#dRQkrv&v=E+YA#y4ho^Vrorg-62DG5>9L8dGv24QJpDI@%xr=+ER5BZ_nrN;Zt^^ zN$XfHWZ47U_~Rc9byVi+-86A@ZW%QUE+dx052#?17TBEoMUFYO)7$sD_&bp}+%2Dm z8b6FtOVbP&7s{J=tUN}q*rt)IaSvH9a}n(Fn+GdgH<3=>L-_t`H|uQ~hqF^2lKa|T z)HgGOK6E+CEN`8FODY>ka$_`(%zw$8e5hz%_9q4c^ms3PTp06yW**q3)Wd~NGhFbW z7%aYF1%Lgn(w{wql*~F!jbE;$!$smCweu=favKZTKW@;oA%B>WABMEgx&Jhi7?Ym5v?tHvddL%5?FB)o<2K`8JK^ zxfBImsWjQ9oQiA4(Wd;(~L|E5qzv9Kr)@m(&)xVqEb7ZcF;$0O!+`wa4`x0t$oxrmFusX+WeC8Rd`wA*tG zv`M;Btv_4QtwI?qgVI^y^>ay|=6H}%n#9%bIgY1RP~6!yoAdU4jcxhyw9yy1X*Q?1 z@0(4y>pPV>$Bmg-_OpWh=9dfVJ4`WfdpO(-{0MY<8%@s4MuiRk$X;#~ryT6XhliHp zJkgIlS2z>wO(qJ?k6DTRPH*W`y$rH^!bTS6r8F= zN8N79iM62en@$|OQi+e(Wnh>7Rr-AYYI5lV{~GVcFe;vBK*Bc|Z*S3t4MIL3y1E&M z&7;tBayS?_f2k9Q>2l+CPU8HU=W`vmv)ESgRq$;vjm8Fc5gZgD2LrV+Vv!kl zKA?#(ZQ-y;`30=W*JI8l@(ecJLh!#<2}g%t(?jRgL0-fKJ}|FI<)T(nD_lY2#vkJY zaNQ708TuxEA8DH30u5&i=m$$9m^*WXNod>(^+V!tb(JB#G}sDW4|_m!njHitq>!Lx z7s;!?)iA@ApM%Uk22KXL0Ulqu;Jf#tFUi?m{80*ILW7h&B z+{WimHcny~Bd=28>L^Br_&M$=rEYpW^bADpaVKg4!}yYC*lYAj;@kBV=(hO|N=(VX z%&u4X>B)J}x?)5-=J1{yvK*hBpNi|N`I%heFcb6526YQ|GwV;NvSIi0@Lf+GyWmMN z?pF%Ks%ZCSwgcx8E4@DhFWy*HEHxn(ZO|CdkG6~&0;5>4Edt%+mObm5YWDBhi)fsblt z2>gyjz?Ky*Wb@`|yk%fdJ)-r=>k0KJb6k{rV>6jevA@iXe$D5eXTQQ3qOM%I!&)vt zNt`pbb>ybnwUq3^o&>7|W#$WPCDqCQkc;};2|Ug8CFskxD?)3GUJdGQvk zpIuG0=A_e^S-a@rp)XAIg(PNI**&JV@iHSm(Gog!{?L+w1bk%>Kw|r>amwK`RJvjd zPXZ(aH`iNnBqN9JFpTF}B-UKpkP2e8a`7Kyh}gM@G31*?qCxv?^jAP-2>X;(od=EdwNt)iTk#;5Z$yBu$iAl?d@2C6*ESm=S&FnkvP(9 zD1jXs-`Mr445$xV6 ziVGaP@XWO)BDb&rl55U`wpa_r-?+lbSBZ7`_q8r}2#5|tnGg>4{rnb$kZXxGQ}M8D1xbln%hsLnX> zZVX3RIVBVvNW||kmDv3ZxQ>`}_^6Zx@evQ|>|G0!L@z?1p%dLC6^%13SJG{}w=%7! zQ@QTX0kEI%&TlNa0xuHxaXS+3;FCUnFaD|=(#o9#J7I|+Emj>fHyow9cfIKHuyLrZ zcZ*iZM-VY15j=1Egx*j*iF5un(fl%|CfMN;d45(w5K-|5bZ$y9qF?U9iAPF;!jKRs z|1Ae)dt5;JtTd)qHK37~wKa2jK2S9gNlC3^IwCLwfwyqS~Fku-igJu;*g}c6gP7$H@!O$9pWv zbq(GDejohHTMtRMXFW;WeZq?V z%Et{F`WX9t5&inN0{*DafXgzc$c)Kj1@0lO#HalNWF;npl2kRg%?*ch>0MYc&W(5P ze5D866NqScn7MjDB3cH%$DAY`E@0_m&SgXkpUAq<`78Qx&9E?@+VTQJc+OSa;Uav& z=X7U`4@1pYreGj#L0$Fu-EW8`tgQ$Fo#ASpL+=NEhQG<6Vlj0*Uqly;Y{P-w)?}Z_ zZTcT9!2Z=^u=?OEDy%dSn73o;&e#gP+|WY~Nhx5g!hE{uvlO1$?MEfoUB^HVp2epb z$T=_dhQm>Quu&w7+2US6&i5Iz9!0ZBdhIO|B`btC5A*!sKYCo{>J-%Cdy5rE8C0u| zM&ECv^yf@ZO!JK=v$krX*ZK%5Tbjw9tW|*+-qX24)*9FT_Z+DD6s!!k0-pmL1R{J_ zM%-e6k=s3ly6(a>U;GHxx9o!z_SeB*D<8)MjL?dNP)Mqo3&&iYG5ozOw0ChhWZH&5 zcCNwnn|`SOvmEdLF=iX%JW%5DF1GH!pD=iT4e8ilggWlCfd>MkNCQ8MzEnUQ2Uz+( ze>&K>Y{0m$AKACtksNnuW$3Z9`01u1PBmOe#%nHsLH;bYJ%5yb(BQjNCZ~yS@oB6T zzspRGIBdRbViIn+;R*U%?cmGfSG50OG)?dlLh*(Rs8Ki*?_OMpYD#Be^QJa<8Zs6= z9OMMiH;DX@|c_+umA^_C@>wjgRSokgO%&TaN_u@kQXM*^TFqXp3h~NsdSlb z-*y&^@+Q!A12=j0q$C-C^%a3!Neq8vimub9lUEaCNzl@_#MyWU=ihpb=YIdhy-|wX zLAlS=@sbGlsA@VLaS(xZ#csHKV-;SIQ|DAR&E(eS--NAlUtv%|jJa554xL3^Y?`nI zUJOYKAN+B)MP2ej*Ff0()}#)jnw0 zuL|Zbk7YZi`0c_)I$ZxX|#g$a%YINxJmcG46&^TB3RYCD zhZd)IbpZ$dN6~r5WA(mq+@@@@6(LGdR>irmr_w-$q@q2)sT3tGGb@rA4HB{nC6x7? z`#N^0R7%n?8d|i6w%_^v?XSn{dCs}->-v1&?{`3xgHc-Bh8X8JLu`2t@7uH@;a4Ou*4eQpW)Vs`{HA9RCMSskm~)RLjufv`xpO%OD{(YE87he?696bwai` zlBg_^M}L`koVIN$z8sXJI5`%xzYpWy#QF3`uNHN8>cqOQpK-oKDjaeTM)}-hINRES z_>N5l8M$eo-p&B(QJ8t*5bj)Mi7&?3;r6q+@Jy6I(2i!N^PCL*pdCT}DT?5mJGu1d z^8L)O*5&YWCJU!8G})DwmXP<86Y#`?8JJlZNQNa&vez$qK-mW;cKT;6_>dRP%sO=x z8t%$-s_*}@aq+eI!!nuc_u0VNZ{5LpZB3*vEe-JXb2nVR)Q0A(y@KFPi^!!d33$|h zlpr~8Exs7N7Ni(O=nMcTd@7!7Q0vz-dptQ06r?c zhJ6t#P%gTOa9j7HPHzZ=w-cC0bSPa;&{5TiwP_oL1>2F}hxcx2xwu6Ond zTnqE7_qjltdmJO8x>4xS&5%K(IaGFcHhZC98TReG!sJLjCu-x9B(Z{Yl?m(9tS<g?D3Xak{s>11aOflI?f(3z;lC5C20 z&B+sR^inv;+qeiNw#*lNFVPfas?O$0!%PH!!lnxN?hR__|0B6-=G>c)dZ-yM#)(-O zarx0YoaMDCG(f32mHBjTaCHA#!meHVi`R1{tf%~ zd4lu9Rl8Vv^Oc z3qKqhjosN1pphF!vOKbx?g3XEN-CnduczY<6>-e?z;96VSyapw;p9Iz3HJ`AQX{oc zXxU^YFu!}7u9%sJ@*OAamgQAJ(-nSZVVH|Y#m>W)MauNp^JXH&XY?&4@*wGzEO#%q zo4IvCnih)e6y|o6;(P8gdC&7~m#p{<=eF;InWKZr({~qvyK#&(S00Bs4!hA{%4O7L z&wy%z6L{_XMOI(FLf)<&CMdrRVkh5*j~BuqB6ltr{)t9l+sJnb85~LTz^ymZK%4KX z30I{+)_Wt2PgQ^f-j}_pbQM`H_+v-jFjRRz&+*|&vo@=c`s7(-ic~(NtTBaix2-^2 z?lb&osl&*Juff8&jrq2!4xB9apnkgoWy6i|Z{!qQbYLs>u`MJk=K0f!Teg$YyUx)W zJQs3JfiAaibSQTrQJwqS)`nT?R@|u`Gj7?tpBVXkH+rPb!KzbyrulC)J`YCh8c`;< za<@^>`>}lakD(%FhVXUA2L8T(4W2FePvE;qQJ`}A9g3{n2dc9S1p%#DP|BLZ@SRk+ z9xNxg=ibWhdpZHW9JGLjRWpI3;xz4N7}aUZ!sHwkfWt|syOu?-sP}Z#UVG+nMg>jX zH6M=LdBNXJ+o<cb;;s(vP@%@#8C{7fRweGW7&Sc35{-Z-F)?@{2da{L$`K*uky+ygS=IwCKEfNhR>QQNtK6C_xFp6Tgac}BZa6agU z&8l-j+o%{aWaR`Koz2)B-EtD`*oD3WgCvyiU-oY(p?uT;*B?w}=C+ojU3)zpTpop) z6P598(paKo*$>4}`=P>m5#6&t1I90#M3$GBaBdEg_&(!5Ow4v86PGNe22Ra%@w^`F z4>!a9;c`}?;S%Swu9W;Ye-_FMPE*+p=3w)+nA~moOn;c|p+WVXR95#=_5aUUD*kWj zgrQ9OmSCB}X`1E~g4$l4c9z0axVZBR z>;Lx*Nu7}a2HY?#JgN+Nic##q(QG=``4UqIi|K(Q^_cyvA5DghxIf{I=yJLemAVS) zPO&eT!S}|VYD?n<3q?VrV7XA%Qy+H>$qRNLIKaevG|?lnjVR6UO?^*YBL*8vNqCnc z(&AV)+lSxZJ2~QkbV)cir%Iq+{R>okM$r|n`|6o=0fXc;ugy+^$WQ9yAaqh~7n3Wl5w{aIbHGHER@+d8K zI)_aCe5~K^Ah=vTR^XrI4ZC@F%h4un4#{WgD?5lOzC*ZV)p=(9_+4DxD?3i@kTDc% z4bvS&59_~X!RLnp+|6CY?d>IWn@%Qp)Cn2S9TVWggihM?glDZqD`5`LWBKhY3!WD( z$QEWa>YkfKLQg)ymWj2P`QKHPpKL{MFK;04VuPub=~4Q#Faz$-OT&uPK=#bz7BqSw z%Qf-rjWe=iIO*5vGj0Y6sh@=;Cn1u^)bh?Zwat^U(8-y2@t&miYI}UO-xef-GGLaN z7~lQjXFg3c;q|Rb_T{xp_`E<2AHDg2b}G7p-XcBNALwFt;@54u{_J>=^*xGOf%bT_ zZGv5BRwUlvx{O+6zae2V!Cc!@SMGgnB4aYbXVf$*@uJoe>bxc$4Cy$*8aHi0ok%zo zuh0+}4qt(M_Z?_|Oc6!04H(yAFQOrChdZX1(>XWx6LFpeJJ>F;?{BsDgBnX@b>Z;{>^H0_3Dsd2B$K0IcGS202jZ~<_@f~b-}O z2X&ygcp@k@^;6~7+Vok7D_wZ>Zu1Fd%Y!Uz z<)0I8Zi(Z4r4%r?k;BQ$qA_TyI2WCN5+c_=r?o3bW5fK#Xz)mz#3(tCw)jZyzM48Q z3vpuK$8F-AW!stS)#vH*H?jilX`etV<0xC8PPj?ka@f9LEVTXSjUPh7d8WloGBG!f zIG5=`)Kmos@Q{X)0VE&wD`4@z2l%DyB?L58;n+Y)!MTT97`xm^2&wErA6q5fMH2!a z26a&U4Tlyl-;?s&?pVO@Cgzl=U_|sLu5y|lIo!30(OsH@-#$DcU;K6PzQ#c~xMUEi zjs*RkD#6Xp{f2ToI&po;NzCcFNCnXZ_Zw(%%^nlE4FRI`ylXJ=v|fZOt}*atToo=I zCnX4ebPV>}U&Tr1liA}@6VbSSJC;U%z~DIpWavZyZWp_bJ2*G=tvZdDZB`0)m&iiE zmOdOiFBji5XOZHiiO`-Gi5GMZ!u-v{Fnw}9(O>U~Gcz?g?Gvfosq2SPC3y!vuiMG( zcGToz_AZ7;qcZSIwko%4KZim!H_qzsF3z%T3U`}l0jzY)r-nv{;rFref}zOiFlozJ zZkeGD)wa3=;`AKNeUXAj!JasMK{FFtHx9MS`2FIe(cGy{-rt)zinBU(7PGe4BX*u9 zomQ$`nhAk>;_g`UNRr=6jpD{ur*P=a^Wz+|v3lzR>~HXfzw2f3h4)%eX*ohq@w^h7 z=|iyn$OIIQ%)_|_bJ60C2^SD|mfNLu56!l*uNq07CMn3C zQv^GWENH%{wxD6*3DM$OvIJ zRuSi#2tqyoz`)vU>Z_SSFDX&_?)WaMTU|h}B`1*`t|e$aD2Xa%W_a071*4|Tz$)WZ zJLND3C^y$(So^oExBY4mx%QcrL`U%8f3MZf+i-(@1qmA6foXgR-v0ChcF7k9e82P@ zx)>J|xs^dE41Q{7+Atl3F&{Bnxf*Reo|EanSHX=-(*QS$!b`mu?7FxX^w@U=v(s0D z*Lpe5>1QDdT|D{<{nA1Hn51JxhoCnL%J!yxy)MS%N0_Z$^{3Y5d;(1RilILgRa-u+O6t ze6%dc*|XyW7Y`H>?{zKoPu^O(s5Tj9s+ckN_K$+UlCt#G&~%)BV3=wC>Os4^wDAfw zk>t_pAQxi|f`^rMbiWVGbm4o9ZR6;x-LvT&CLh=Rm`i^J@LB3{NAb9UHBl6~MC=O> zgV*teI6itSl&c3AG+* z;&6>K?Hgl?p1YkeWZ?v`Jd;WP#X7^0arwl!8=?5$6SDou7)apHAkyE8*y@s-@M>Zm z+&Vv>Y1y#^v{S~wwXgE6S+n~3)FX4sy~XI(C*L3ya6pzV+| zEV(&>Ie9RSKVz(g?X8LepEZ-nIJZV}x_mM$j9vj-SD9gY3||SdPr;K*48ZwFKAYL# zOX_YFQm>s!q_ETpcU9UzQsF+LJm*bKh+_^lIeUuE2we*Ojywl-b_i9Nm{0oUJn8+e zvsC#}00e(XA$n5$uHiS&4OU%D#(Yv|*Xy2w_%TPJD9%>+=G7cJz0aCk_}w4H>?&Yu zxD_6g{z6R6OW;#nF2?G&((wNtu{yCP?CBXN=+r;m{5fen?icrjMGa{fIBFF&CE|j# zMmJ)R=#M{xmO$FlKEz918kE4z1aSH#txIz+_<- zJ%ZaEukv@MtBmY>p75&m8fCZpp~1i9bmx{TdO740{xW^V7&QP9l}trLu}P%2BAVD( z{-V+|x0xPo^L7>94m?h(yb73ZK1;f}Sr+?k8;HmW zX&f#`wC? z==F0C@0Gm;e+E6kX|+H=|12O{Q{3>a?{bp#q>fe&uO%yc+rZ0Z9OOd-)m-$Rl&srB zMUDXUD4!*v=3`JRRF5buYC%)8Ci>rNXS6!Eim5TGB$}fK$W9|qnDfAj?0lC=+7vF6 z;ij7;JSCj0x_J)WY_8*rB@gJjjRaFZt;BwN-XS762EQ%pq(8%qaeDW8-0(IGjeSny zsX9N~Ba?zqQRynG=%*vTxoOwtyB(*gS-|z#6=ddG9jq%@h+T(bSuw9_viRN&#`#<( zy>-`++GjnZp$_gerTZUk@+!p^R)8&H^7xDIn(fyU6D(CP1dpZKxc<}$I)jy=3oq6} zn#z6pHT@MaKWc;R%|`H>_tr?95Q7q{B``1k7jcyq(yrXEbkVVV@*qSNF2-x(0h<&i zVZvVAuwyEUT;X{&<#sf{gwJd8&J3v0MESsK_WQbCVo@1O>N_TZWBo=rrL_>PTc=a8 zb$dzw9}`CHMKqdR%)@pYIj&|<8k5vjaFqL4^s2cA8sAM}v(^h*VY`Sr+=|2R8_&`1 zZ|W#~X^)W#CG>2NGZZ}iOszLf!tp9bAg;a)mOt&Hk4D<)zIj*angDYgsCA`A|Mbc3 z%R*wn_eyrfpCf)9?QEH)1^KJOcbBJ@()me?;GUcr{r#hvF7;}q3{Jquxa^5Z0~HP;)-$Lbe8{Ly2QY-ab}PoFd9mh>0pn85f$N_ zaN*r7Vs52FB##`&UO}zh!Z|tgW2F?g%WEc{@zli+-;UyxMR`QQDhVbH9mIe;$MM6N zV!Pa^DJfW zrazS4n~%Pt&ly>bbeLIPL+U(x=~`(O%nrItO+$l-F+)^~?s8W~g>ypA)liM`d>J1}zSb$elf{~b)vTuG>;?J?Vc>IEZ zZn=?-sYyPh;Kn(s(>adZ`r%4t+=|F}<;`rA%yBY#k_gW$=q8R0I|XM#@|dj!5_~Sr zTCj}o)jXb^O`goS4W`qUL+Y##WYWSRqI3Ku)5hlk-Tk-W=t6J!FWnlZx;o$~$$Yx| z^+_Vpb%^9C4$)hh_h_5AG|dbBNORhb^A3!OMC+I>6MH9`y>2-l$f$TYqH+c1ZqWwm zl}|xq9S`#laR-NygJ`22fR0xl&}i=i_{@C;CWwv2DF%FpqJ9qszIbaV(k~_0y3q-q z_2$uY+lpw+yg(dh@QUax`GiHG5#;5%)9}*t7kwx8jp_H+1WSKLxM%M%ENL~ze)AJ_ z-Wp>(eqs(xbBV%0UwOQdRZfb3P+an5geZL$f~9W)zV10kbZm@au~`~r%)+Txp##~X z^ppLRzMgW0?quo%1-56F1Z}?BL{ts)g&VuGU`E7BvPaO0Z=@zOKTDP1laS|`$#VGc zv^NfE6~jbJ-eDBv0xq+y1%bQ|`V_y%zIEyqR352d)~x@n7;>=uKYZ0Ez_{?|^!dF6Ed6RuQjL?Tz{di&NM%hb?Dvv@izG7Dl1tUYs5XJN1(s;Tel@_p@ zNW_Ny5F5D*4v84j^UYDHZreh+Sqx+(jz_=z2Ku_Bnz%pQPkenu?TnVkGQqBvaP4j? zIVY{os5dfDXOPBD2uh*%bjLA45q3~CCLT_u@5TcQcSG6k7o=3$9hFKC(_@ofl1J;3 z$l)!gv0;KG9LO_)GtUjs*}V^+4i#glgB;GDkw;dEH^B4br$~3-UptRU=ZHbvJ*f4( zh4xdGa6wWs=$1%uA9uFVkvTuv(1SWSsKU=R%)is8U-(}2wf~5P)@;(6ScCZm=b7$% z7umTD=TQw_x@P0x2Ww3fx1$iF36VcTU9}Ss6rf)JS88uAY1;lnfg3V~72)FK%nZg#MB zK{0Un&jVV{9ieA$OVXVRCs96~s>tQIq(^?GE z$JxW&w@5=9HskrgOz?3&K?7zifv(V6_~YhJOiqSUcI}0lwV!Sf>&%H%pj}Ux?i{## zq8ykKMEMwBui4>HV^!{ug1oPE@6ZeOUr8ce&Lx2U zr9iA4T1^9P%q535XVGjSgE2avVf>Qmbm00S+qhySRBB72)yo1{t7aJ*nP)bLnT8 zJkgbOPhvDiA1w#>cRS&r$pf-g?E^C{@jJE5I)z7vL)c0DGNURW1^Yat8C5w=s0|y3 za^_>WC_bNMO^fVYeGj3U1n()kn^|+ewg5VV{J@mk$7D*621iL2Z@gx4WR@8y3eJP> z%028Gr#7^dmjZ6f30Qh&5>=??fibsmj+{94uXskV zXDk#-TA=o02|@bR8Fa;~Nth~r5mrU7Ln*zPs2j{e0Y49V)v%Bg)wP8!u9eK@X*W=< zS(jUWL6R$Kdx+z`7vjS@S*TMe#2cfMATw5hs1~SjGRsR*cUBS@7EQv*%xFQxjgxex z+jz)EZMyg04BS0G0}q?=yxR%As6TleH~I58&XVsYlwbeOJol>tEx+@uNSYuDt&E94 zRlvWypC-f9v2$R_CpmOdp9EgzGoex}5hiusqh)e)xn&oQlSNCfpn+aJ76qPRKYuJk z6W2ZD)a3v=O=}DUPF&1wy!8&4d(-go`v)i{Uk=&smobF?z_}~3ApN@(D}L$&?$}^~ zZ|zgD$WovCF*1fLJ5)gjDk%Ds1E`ok1()TXW2LWLr4b*k(EMQuI^2-PSIWomZbmP; zV-du6Wk=|yhW}71fx|2J3&`M8{%rG33I@7{P|mc9Ne-3cCO%zB4JNC?s@QF`rqCJO zj!2W&Pu0+O-BK{T`H9A)c+;_}_B>~3FYjF22dBr55qw@U#QXjh2-ajvQ_+zDVT4a2 zeA&(4qt5?e`V5k6tPW z&=@6nmt+jbE^EV8$5RmgqXlkN-Jw^04r5wnId);pB$zxZsTvx7V_i9&$Q@ zO}B3|&pmCiu`LR>wfv*S?nm(N>OOYJc`e+4OYqsW12IdZGz~iVTL^0NnO&Hl9L{#>G7H*Uyme%p2pK%c9U{QAm}wS2F6107UdP$)LK7U5?Rc3|cNr>N~enrDPWn zn#mCFg-@Bs0w2EHBntE0cjH-&a5!}L3GHvaNqQv-RF=yMLap;bAv_9lxL4@`CZNW}K;Bd32%6c`O`1R7N(+)?!lM(@`U zOn6mCZdpnQ<`}$yS3FZVDKs3H<=kXNayJok#tI^~-yk5Ji)ZDIqwcX>G}&njj`5F4 zt>%8Z(LRy&c@~2cqpj(c#vW3wSPIggli`@xIV7_r1ZkPqQ0|{BH@?_RkQlbkIF4nR2<2r~v)5Ua!C(!gMv#GAqC)OtaJnQXHf|A;&@Jq%X_^!+F-knnD zH>qGue1_>P-8^&(I|FZz^BIsZAxcN(ksmk5;Tahb+;QZlUE_QOtSk`Nebj9u3dfGn zcS2q2mi!8e+RV@|*^zUZ6~;T;HqcW&5ApQ2mqa7&AyGZ~g!&)d&gAp?>fYu5p>1gf z1dTn50*e&-xqUTF7`R6q4sGCh-sQOc+yJf5euVamn@CITBT~O(fQE#Lz~o!Y;J#!P z)aR@u9Uej&mf%io_tw(kEI;!3*DCTmCm8nfeVu>y$)K&!PR`F9BD3a&!D!q-Y&%^r z^Ybqn8BtC0OA9dXdOZE*5pGv&>A-n8&A`x_leF*m5LRg@kb8lCSh(XFc1p;?!h1VN zflU&IR^`weue%vFQ{Xx;MkBcsh08WXpv@zWNqoEk64P%$`n_Qy{22!UN)tdi%?O2t6Mj3Uk6KrhImg<0LSBzYL$XbA*`#aa-^yaFi;&<7yqs|K;4k_! zqZC7aMPr5X3HHQ6c`n%KBHstONnO^R5l%>wLSBaz8|4580nKz%F8@CPn-}-}5q&L>` z&-;W+^SL+sHq)u!rZX3Io#A)*OHoU*8b&Oaz+dhCcp%9 zVzp5!=mzMov=l`CnMfBIIAaQZhSivkof}QK#h+YhH=mX6xtPtIZMsk9j~yiTca7j* zi5Wfju$!H*)&XZs6DO{(@<@w81*$){#?fWp@y)Le9QDD3+E0|?u3MfUezqo9=CBb> z#oo}fb(Gm3HJg(zktSL%@1c5!1$UK>p}RhQp(n#vadqep{_(ZM;lEa_P&5>{cA9ZZ zRCCcytIM zS~}_&b{`P$B$0#?j=T-D1LX^Ipl+o*l)a3Cxr?RhWhk@kC2-+jtN?D^l@-aV~!U>PVw=)bUz{HDvDkLF(P6 zA=jcug6Ay;ttUmqFtQz#gEqsY7uguJ;}5C+*N4xgO}I<)Car zBbz_#gR*BX1fP0Lbj=iDiM1F<>yM*@S25n*XpIT8#&Aa_+@n)}90yCiIdJRm8)CBM zBRTJI0nhfIL%+cs9MpP93mT8$l?j*dQ^st(ST}-+2FLN*jZjiyG7j6q(n+3CEPFM% z8My*Ya^BC3B=yJO@?ZK~Z0`x$ZnhUJEp@mRp4s@;Ad05A_hQ_84{X-5M{Z~)-Q$;l zPko-yx#mmAtewNewk87f(j7=}sR6v`oDOy=f9dFZme@YyC0^DS(zL|S=%ysaX-)?2*#NF6wRa4aeG?7q4*G-2yOVUvsZ45T z`;;!<69X&8xj=sWOne_{OAQ+IAmvOZv_3mUHOv0P!*U*Eq_K@!z1>59kM^dLoex=q z55v$r!39*u+mfdtXKkqiOC80efyd~RM5U!5o0&^~YNRo})lIZcClPKsRnun&6e0V= z2PU~amom+s&?e@LnrgeK+q1>!XqO2tQaj<3Ya@-np#YaNkAO(WBC5Epf{eSZ3O_bH zfc9&(bYNj3D|c=N%-S`IN}D&5a-GqrF-jJiN_Fw@Nk`IsU?+Rt%7rX<)}?VecFdF~ z?Ih^v2R4%DQyW=qgsIhMKvYl!>sEY(_AA{G&3nFV%x=QEk|^-t=fN_+ok+hoG@afq(+ro!Dzaw=q)3x>Z8DZ}?cB}0ZJU-z$mfn@))-&on$MiCLKlCE5Qv8FaCh4rAwhH9N zW)a^9Z>jdT>0Hd^*TOFc7ej*PA6z3Z!KH`ty=8}q#8A{3mId+7bJ|Nsb!{RUv!7C{ z5LI?plrpLC<(wsSw7NS#=SPWCyeg_T>F4hDKXf~b7kh` zy+m(|TAl&yfrb_HaoTM|;n&}exbo8(YSC$oH4@Tzr-jeE#3qv2%k~Smu6u?vlYihP zuQXIEtHX@F5lo8iC{DP|fD3)|5wi$~^Hq9aOzu^9v$+x$Eh~oGhwEuw*?MxNcLEt# zbqF*RXF*}~MvUlm#=rv+>}ev7R($5TN_`Q}0p3WLU6Doqrhjbt@Q$aWR@aZPDmQ9y*@6b_`HZ+j_YrnY>PN-P9k_YFE@zcfj8|JPqPaKFv-WgS%ZLutrUZpFzIG;r+ic zc1J0;o-M%<`J=S3VE{Sv=Xh&+GtZIeL`9QNxL}qg7b>w3yUVP&*Nb?LGSAg6R(XUG zzmCuW;SE+Yr3_PJ(lP012zodd>XgXm_zLBq+h#3$Y*iSf`Q?CZs2MprYaZ_Ulu3K` zoM*}J2c)_`gjs8{kj*np=H2GCxM!O=SN3EHC-Wo{yE;GetnDfE+-w7kA7@56VKnCQP1C<`I&H@tF8R%BB;8*2)znZ@WQ;^=;M4D z(|(Vl6^Co^*)iwKRYe}k&C(rHX(A_i}HOVy_=hE{$~(bN|# z%zG_GALUrl*86wp({U@ocY_)T=JC7ca%q9|U>j6USAr1H5O~6O%IcDgT7Raz&0e{wbl9z=}xYc+az8|lNht}UCj}Coicif8t z+apd;w8sWs%)Lpq^uJLxzSA<{KsGH)O=0DIBJj%T8;t1qVDOxpNQCdkg52}t^kzgE zZOD#8bBhLS{aT6E%cgJ!n*1DMlo2j`oQjI>r|7}fX=vOWfsw6M%*&lF=$ON^*JHlZ zT~E5OvEPcmRWqj>TDF07{5*Uhu>tJ96SVy}9zSh5!Ujx`CC=4R+=VB=ZN0pWYd*e^ zyTZ2M#yO(ghm0Q7`@RT2mTH5~M~eC<9N_0*7%Yp~${C+gK+&;h?T+5ti{eK!LEi2g z1SGcO;C2yCIrI%~d-jHGs^`(xxCtWvtNs?HP6`K^H9BUt?HTC7zwFWBWCa z=jA&!@J`iqs9H1~7W|81Uqp8hv&mjydO4bT`KJnm4*xP5RWW-(fDlzs-(@O)@J{L@6HS{L0C<)~(!+ z*0r3!hCkPKFBCQEe~|Y+Qe5q(Bbffc6eS{WBJ;Hsf5nR-8}XFHo-81GM;9<1YPMh# zvK)RNv}C69oZ}Lr%l=rUfa`e9W1o^VnVx@`-QE*Snw?qZ zZS`r4++K|}RY!6BWhwTyQw;MV_&r|z(L>&06e@o*;9Rxi`QJ}3an`87Dgy@yyy*!N zD-OZo^Wpe-$6d_ZSk6qUevj>9mH6(*dI;s;eZ`Wi(N_KiP=2PV?>Ps~cYa6sT?BXk zs}R2WxQXK~sG!e@f4HI7o#Wn~#OrAXA%yQlWrYtChf`8)`hX)u4qDON)dh6p&$HMV zq{>x!x!~3VgCwM^6>Yke=#;HDiIU_QydXCp`>tkTzMnS)*zBXd8@H0+1qW!vsqrv+ zQ6M~fH=g$V>7owWVlZ*0Azp9&g&P)5#8LatlU|W(sxSQoC;fR25`XT%y2E#%#Zdv2 zR8}*ybym~06PjVn;S`vAavua+Z3Ok>kLii@SaLpFlv7``lUw}WlUvI-!X=YUrm5tlVvbs>O5Tkrki*i*Wjiv=)}=-a@;2{!k0@n z!A|Q$8kO3E#fzttpoLAOHTN>M2HeH8Q5(?w;7^PQzt7B>|C31OTk;&yYcNzaN}&CE zKUnS_3s%Y*;1eu?_PJen)e`akfAu8B;331A)WF&^;gH64L+F{qIG$(Ay!;+Xog98r zLt2YBriWAK;X7pazpMD?*K|l+(|yyUN*#M6Sn%}?ZQ%$y*Cl!uaBdn zq_3h+dIZIE{MxI)dDRJ*AMR0Qvi{(}n|C5+r{ zJ7gZ`GZQjPV1FS9jK6<^tJNY{kv&cD3yp;Gih(3#!gxW9!E5L_K1Oic;W0?oeSz~G za?rH237iwe1f@U41$!HRz_F7jiKBfb7M#q0;}wzk zbqqLm!N3zg2)ZSNcfJ!U@i}DsYwNG>o|$4&(k_2BXt@ z(DL&#orW@4cKsMWENr0$GvDI@(=gCOWfUF}k~we|tY1�y5mV2n`#%fvbxI7UM&3 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