[Question]: About the support for efficient Winograd convolution in SPU

Issue Type
Build/Install
Modules Involved
MPC protocol
Have you reproduced the bug with SPU HEAD?
Yes
Have you searched existing issues?
Yes
SPU Version
spu 0.9.0.dev20240311
OS Platform and Distribution
Ubuntu 18.04.6 LTS by WSL
Python Version
3.10
Compiler Version
GCC 11.3.0
Current Behavior?
Hi dear SPU team,
In recent weeks I have been working on using SPU to evaluate the private inference cost of Winograd-based ConvNets, which can reduce the number of multiplications and thus a lightweight comm cost.
BTW, using Winograd for more efficient PPML is gradually emerging and has been proven to be an efficient way to improve the comm efficiency, including:

Zeng W, Li M, Yang H, et al. Copriv: Network/protocol co-optimization for communication-efficient private inference[J]. Advances in Neural Information Processing Systems, 2023, 36: 78906-78925.
Zeng W, Xu T, Li M, et al. EQO: Exploring Ultra-Efficient Private Inference with Winograd-Based Protocol and Quantization Co-Optimization[J]. arXiv preprint arXiv:2404.09404, 2024.

But I found that the reduction of multiplications will NOT make the comm truly decreases in SPU. In general, the respective comms of a single conv layer are: the stand conv: 759296 byte, Winograd-EWMM (element-wise matmul) conv: 6291456 byte, Winograd-GEMM (general matmul) conv: 3964928 byte. Apparently, the Winograd algorithm increases the comm by 8.28x and 5.22x, respectively. And the increased comm mainly comes from the frequent invocation of truncations. For details please see here.
So if now I want to modify the C++ backend op for Winograd in SPU, could you tell me where should I start and which piece should i start looking at in SPU? Thanks! (If possible, I am willing to contribute the support for Winograd to the SPU community.)
Standalone code to reproduce the issue
N/A

Relevant log output
N/A

Hi @warpoons
To change conv implementation, please check here

Hi @anakinxc Thanks for your quick reponse!
Currently I have implemented the Wingrad conv class in Flax in the frontend of SPU but the comm improvement is far from expectation.
Should I directly re-implement the Winograd convolution in the libspu/kernel/hlo/convolution.cc you mentioned here?
If so, for the model definition such as ResNet18 in the frontend of SPU, should I retain the definition of conv layers as regular nn.conv or something else?
Thanks.

Should I directly re-implement the Winograd convolution in the libspu/kernel/hlo/convolution.cc you mentioned here?

yes

If so, for the model definition such as ResNet18 in the frontend of SPU, should I retain the definition of conv layers as regular nn.conv or something else?

regular conv should be fine

Hi @anakinxc. Thanks for your respones and keeping this issue active.
In recent days, I have been trying to implement the C++ backend op for Winograd in SPU.  But there are still some difficulties because of my unfamiliarity with C++. So I sincerely request your guidance and assistance. Thanks.
First of all, many apologies if these are trivial questions.
As previously pointed, I have re-implemented the convolution in libspu/kernel/hlo/convolution.cc by highly referencing the python/torch version here. And the modified convolution.cc is:
#include "libspu/kernel/hlo/convolution.h"
#include "libspu/core/value.h"
#include "libspu/kernel/hal/polymorphic.h"
#include "libspu/kernel/hal/shape_ops.h"
#include "libspu/kernel/hal/permute.h" // Newly added for Winograd transformation

namespace spu::kernel::hlo {

// This is an optimized conv2D with im2col
spu::Value Convolution2D(SPUContext *ctx, const spu::Value &input,
                         const spu::Value &kernel,
                         const ConvolutionConfig &config,
                         const Shape &result_shape) {
  SPU_ENFORCE(!input.isComplex() && !kernel.isComplex());
  // input  : (N, H, W, C)
  // kernel : (h, w, C, O)
  // output : (N, hh,ww,O), where hh=(H-h)/sh+1, ww=(W-w)/sw+1

  // Alias input dimensions.
  auto N = input.shape()[0];
  auto H = input.shape()[1];
  auto W = input.shape()[2];
  auto C = input.shape()[3];

  auto h = kernel.shape()[0];
  auto w = kernel.shape()[1];
  SPU_ENFORCE_EQ(kernel.shape()[2], C, "input/kernel channel mismatch");
  auto O = kernel.shape()[3];

  SPU_ENFORCE_EQ(result_shape[0], N, "result batch mismatch");
  auto hh = result_shape[1];
  auto ww = result_shape[2];
  SPU_ENFORCE_EQ(result_shape[3], O, "result filters mismatch");

  SPU_ENFORCE_EQ(config.window_strides.size(), 2U);
  int64_t sh = config.window_strides[0];
  int64_t sw = config.window_strides[1];

  SPU_ENFORCE_EQ(hh, (H - h) / sh + 1);
  SPU_ENFORCE_EQ(ww, (W - w) / sw + 1);

  // For 3x3 kernel size, use Winograd convolution
  if (h == 3 && w == 3) {
    // Parameters
    auto r = h;  // kernel size, which is fixed to 3 here
    auto m = 2; // output tile size, which is fixed to 2 here
    auto a = m + r -1; // input tile size, which is fixed to 4 here
    auto T = hal::ceil((H - r + 1) / m); // number of tiles along height/weight
    auto P = N * T * T; // total number of tiles
    auto tile_stride = a - r + 1; // stride for extracting input tiles

    // Define Winograd transformation matrices
    auto G = { {1.0, 0.0, 0.0},
             {0.5, 0.5, 0.5},
             {0.5, -0.5, 0.5},
             {0.0, 0.0, 1.0} };
    auto G_T = { {1.0, 0.5, 0.5, 0.0},
               {0.0, 0.5, -0.5, 0.0},
               {0.0, 0.5, 0.5, 1.0} };
    auto B = { {1, 0, 0, 0},
             {0, 1, -1, 1},
             {-1, 1, 1, 0},
             {0, 0, 0, -1} };
    auto B_T = { {1, 0, -1, 0},
               {0, 1, 1, 0},
               {0, -1, 1, 0},
               {0, 1, 0, -1} };
    auto A = { {1, 0},
             {1, 1},
             {1, -1},
             {0, -1}};
    auto A_T = { {1, 1, 1, 0},
               {0, 1, -1, -1}};
    // Transform kernel to Winograd domain
    auto U = hal::matmul(ctx, G, hal::matmul(ctx, kernel, G_T));
    // Transform input to Winograd domain
    Value expanded;
    {
      std::vector<spu::Value> tiled_input;
      // Separate the input into axa tiles
      for (int64_t x = 0; x <= H - a; x += tile_stride) {
        for (int64_t y = 0; y <= W - a; y += tile_stride) {
          auto tile = hal::slice(ctx, input, {0, x, y, 0}, {N, x + a, y + a, C}, {});
          tiled_input.emplace_back(hal::reshape(ctx, tile, {1, N, a, a, C}));
        }
      }
      auto stacked = hal::concatenate(ctx, tiled_input, 0);
      expanded = hal::reshape(ctx, stacked, {P, a, a, C});
    }
    auto V = hal::matmul(ctx, B_T, hal::matmul(ctx, expanded, B));

    // Transform Winograd input and kernel to GEMM format
    U = hal::permute(ctx, U, {0, 1, 3, 2}); // U (a, a, C, O) -> (a, a, O, C)
    V = hal::permute(ctx, V, {1, 2, 3, 0}); // V (P, a, a, C) -> (a, a, C, P)

    // Do GEMM
    auto M = hal::matmul(ctx, U, V); // M (a, a, O, P)
    M = hal::permute(ctx, M, {3, 0, 1, 2}); // M (a, a, O, P) -> (P, a, a, O)

    // Transform Winograd output to regular output
    auto output_tile = hal::matmul(ctx, A_T, hal::matmul(ctx, M, A)); // output_tile (P, 2, 2, O)
    auto out_size = H - r + 1;
    auto result = hal::reshape(ctx, hal::permute(ctx, hal::reshape(ctx, output_tile, {N, T, T, m, m, O}), {0, 1, 3, 2, 4, 5}), {N, out_size, out_size, O});

    return result;

  } else {
    // Fallback, use im2col + dot to implement convolution
    // expand the image according to the kernel size.
    // assumption:
    // - padding is erased by some compiler pass.
    // - input  : NxHxWxC
    // - kernel : hxwxCxO
    Value expanded;
    {
      std::vector<spu::Value> images;
      for (int64_t x = 0; x <= H - h; x += sh) {
        for (int64_t y = 0; y <= W - w; y += sw) {
          auto window =
              hal::slice(ctx, input, {0, x, y, 0}, {N, x + h, y + w, C}, {});
          images.emplace_back(hal::reshape(ctx, window, {N, 1, h, w, C}));
        }
      }
      auto stacked = hal::concatenate(ctx, images, 1);
      SPU_ENFORCE_EQ(stacked.shape()[1], hh * ww);
      expanded = hal::reshape(ctx, stacked, {N, hh * ww, h * w, C});
    }

    // TODO(jint): the below method is much slower then the code above, consider
    // to use slice+reshape+concat to rewrite expandWindow.
    //
    // std::vector<std::pair<int64_t, int64_t>> padding(4, {0, 0});
    // auto expanded = expandWindow(ctx, input,      // input
    //                                    {N, h, w, C},    // window_shape
    //                                    {1, sh, sw, 1},  // strides
    //                                    padding);

    // Now expanded shape is (N, hh*ww, h*w, C)
    SPU_ENFORCE_EQ(expanded.shape()[0], N);
    SPU_ENFORCE_EQ(expanded.shape()[1], hh * ww);
    SPU_ENFORCE_EQ(expanded.shape()[2], h * w);
    SPU_ENFORCE_EQ(expanded.shape()[3], C);

    // Reshape it to (N, hh, ww, h, w, C)
    expanded = hal::reshape(ctx, expanded, {N, hh, ww, h, w, C});

    // Contract on h, w, C
    // expanded:  (N, hh, ww, h, w, C)
    // kernel:               (h, w, C, O)
    // result:    (N, hh, ww,          O)
    auto result = hal::tensordot(ctx, expanded, kernel, {3, 4, 5}, {0, 1, 2});
    SPU_ENFORCE_EQ(result.shape()[0], N);
    SPU_ENFORCE_EQ(result.shape()[1], hh);
    SPU_ENFORCE_EQ(result.shape()[2], ww);
    SPU_ENFORCE_EQ(result.shape()[3], O);

    return result;
  }
}

}  // namespace spu::kernel::hlo

Please note that I only convert 3x3 convs into Winograd version and the others are retained as regular convs. The input/output tile size are fixed to 4/2 respectively.
This implemention is a peer-to-peer implemention as its torch version but it didn't work. I have some issues:

As I want to make as few changes as possible to the SPU backend, are the definitions of Winograd transformation matrices A, B, G with auto correct?
Winograd conv with GEMM requires the permute function (tensor.permute in torch) to transform Winograd input and kernel to GEMM format, I don't know if my use of permute function is correct?
I have noted that the original implemention in SPU uses hal::tensordot for conv, should I use hal::tensordot or hal::matmul for input/kernel transformation and GEMM?
There is an ordinary version of Winograd conv with EWMM (point-wise/Hadamard product), is there a point-wise matmul implemention available in SPU so as to compare the performance of EWMM/GEMM Winograd?

SPU is a grand and complex project, so it is quite difficult for me to fully understand it. If possible, could you please provide me with the modifications required for the above code as much detailed as possible. Thank you very much.

Winograd conv with GEMM requires the permute function (tensor.permute in torch) to transform Winograd input and kernel to GEMM format, I don't know if my use of permute function is correct?

Hi @warpoons
Nice work! Thanks

for A B G, you need to build a proper Value with constant api.
@tpppppub Can you check usage of permute
tensordot is a more general version of dot, which supports > 2D inputs. If you only need 2D dot, matmul is good enough
Hadamard product is just an element-wise multiply of two tensors right? Just use regular mul api should be good enough.

Hi @warpoons , SPU transpose does the same thing as torch.permute.

Hi @anakinxc. Thanks for your respones!

for A B G, you need to build a proper Value with constant api.

Could you please kindly provide a specific example just about the definition of one of the Winograd transformation matrices A, B, G. For example, the instence to define:
G = { {1.0, 0.0, 0.0},
       {0.5, 0.5, 0.5},
       {0.5, -0.5, 0.5},
       {0.0, 0.0, 1.0} };

Thanks!

tensordot is a more general version of dot, which supports > 2D inputs. If you only need 2D dot, matmul is good enough.

Does this mean that tensordot supports both matmul and higher dimensional multiplications. Can I entirely use tensordot instead of matmul to avoid potential incompatibilities?

SPU transpose does the same thing as torch.permute.

Hi @tpppppub. Thanks for your respones!
Do you mind take a look at if the following usage of transpose is correct? I had searched the entire spu library but did not find an instructive example of using transpose. Thanks!
 // Transform Winograd input and kernel to General Matmul format
    U = hal::transpose(ctx, U, {0, 1, 3, 2}); // U (a, a, C, O) -> (a, a, O, C)
    V = hal::transpose(ctx, V, {1, 2, 3, 0}); // V (P, a, a, C) -> (a, a, C, P)

Hi @anakinxc @tpppppub . Mind take a look at my doubts? Thanks! :)

Your understanding of transpose is correct. Besides, the following tips are for your consideration.

Most SPU APIs (hlo/hal) are consistent/similar with stablehlo. You can read the doc for reference.
There are some comments on API declarations for explanations.
You can also read the tests for references.
Run your code to verify your guess.

Hi @tpppppub. Thanks for your quick and detailed respone! I have modified the convolution.cc as follows:
#include "libspu/kernel/hlo/convolution.h"
#include "libspu/core/value.h"
#include "libspu/kernel/hal/polymorphic.h"
#include "libspu/kernel/hal/shape_ops.h"
#include "libspu/kernel/hal/constants.h"  // Newly added for building winograd transformation matrices

namespace spu::kernel::hlo {

// This is an optimized conv2D with im2col
spu::Value Convolution2D(SPUContext *ctx, const spu::Value &input,
                         const spu::Value &kernel,
                         const ConvolutionConfig &config,
                         const Shape &result_shape) {
  SPU_ENFORCE(!input.isComplex() && !kernel.isComplex());
  // input  : (N, H, W, C)
  // kernel : (h, w, C, O)
  // output : (N, hh,ww,O), where hh=(H-h)/sh+1, ww=(W-w)/sw+1

  // Alias input dimensions.
  auto N = input.shape()[0];
  auto H = input.shape()[1];
  auto W = input.shape()[2];
  auto C = input.shape()[3];

  auto h = kernel.shape()[0];
  auto w = kernel.shape()[1];
  SPU_ENFORCE_EQ(kernel.shape()[2], C, "input/kernel channel mismatch");
  auto O = kernel.shape()[3];

  SPU_ENFORCE_EQ(result_shape[0], N, "result batch mismatch");
  auto hh = result_shape[1];
  auto ww = result_shape[2];
  SPU_ENFORCE_EQ(result_shape[3], O, "result filters mismatch");

  SPU_ENFORCE_EQ(config.window_strides.size(), 2U);
  int64_t sh = config.window_strides[0];
  int64_t sw = config.window_strides[1];

  SPU_ENFORCE_EQ(hh, (H - h) / sh + 1);
  SPU_ENFORCE_EQ(ww, (W - w) / sw + 1);

  // For 3x3 kernel size, use Winograd convolution
  if (h == 3 && w == 3) {
    // Parameters
    auto r = h;  // kernel size, which is fixed to 3 here
    auto m = 2; // output tile size, which is fixed to 2 here
    auto a = m + r -1; // input tile size, which is fixed to 4 here
    auto T = hal::ceil(ctx, (H - r + 1) / m); // number of tiles along height/weight
    auto P = N * T * T; // total number of tiles
    auto tile_stride = a - r + 1; // stride for extracting input tiles

    // Define Winograd transformation matrices
    std::vector<float> G_coefficients = { 1.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.0, 0.0, 1.0 };
    std::vector<float> G_T_coefficients = { 1.0, 0.5, 0.5, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.5, 1.0 };
    std::vector<float> B_coefficients = { 1, 0, 0, 0, 0, 1, -1, 1, -1, 1, 1, 0, 0, 0, 0, -1 };
    std::vector<float> B_T_coefficients = { 1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, -1 };
    std::vector<float> A_coefficients = { 1, 0, 1, 1, 1, -1, 0, -1};
    std::vector<float> A_T_coefficients = { 1, 1, 1, 0, 0, 1, -1, -1};

    auto G = spu::kernel::hal::constant(ctx, G_coefficients, input.dtype(), {4, 3});
    auto G_T = spu::kernel::hal::constant(ctx, G_T_coefficients, input.dtype(), {3, 4});
    auto B = spu::kernel::hal::constant(ctx, B_coefficients, input.dtype(), {4, 4});
    auto B_T = spu::kernel::hal::constant(ctx, B_T_coefficients, input.dtype(), {4, 4});
    auto A = spu::kernel::hal::constant(ctx, A_coefficients, input.dtype(), {4, 2});
    auto A_T = spu::kernel::hal::constant(ctx, A_T_coefficients, input.dtype(), {2, 4});

    // Transform kernel to Winograd domain
    auto U = hal::matmul(ctx, G, hal::matmul(ctx, kernel, G_T));
    // Transform input to Winograd domain
    Value expanded;
    {
      std::vector<spu::Value> tiled_input;
      // Separate the input into axa tiles
      for (int64_t x = 0; x <= H - a; x += tile_stride) {
        for (int64_t y = 0; y <= W - a; y += tile_stride) {
          auto tile = hal::slice(ctx, input, {0, x, y, 0}, {N, x + a, y + a, C}, {});
          tiled_input.emplace_back(hal::reshape(ctx, tile, {1, N, a, a, C}));
        }
      }
      auto stacked = hal::concatenate(ctx, tiled_input, 0);
      expanded = hal::reshape(ctx, stacked, {P, a, a, C});
    }
    auto V = hal::matmul(ctx, B_T, hal::matmul(ctx, expanded, B));

    // Transform Winograd input and kernel to General Matmul format
    U = hal::transpose(ctx, U, {0, 1, 3, 2}); // U (a, a, C, O) -> (a, a, O, C)
    V = hal::transpose(ctx, V, {1, 2, 3, 0}); // V (P, a, a, C) -> (a, a, C, P)

    // Do General Matmul
    auto M = hal::matmul(ctx, U, V); // M (a, a, O, P)
    M = hal::transpose(ctx, M, {3, 0, 1, 2}); // M (a, a, O, P) -> (P, a, a, O)

    // Transform Winograd output to regular output
    auto output_tile = hal::matmul(ctx, A_T, hal::matmul(ctx, M, A)); // output_tile (P, 2, 2, O)
    auto out_size = H - r + 1;
    auto result = hal::reshape(ctx, hal::transpose(ctx, hal::reshape(ctx, output_tile, {N, T, T, m, m, O}), {0, 1, 3, 2, 4, 5}), {N, out_size, out_size, O});

    return result;

  } else {
    // Fallback, use im2col + dot to implement convolution
    // expand the image according to the kernel size.
    // assumption:
    // - padding is erased by some compiler pass.
    // - input  : NxHxWxC
    // - kernel : hxwxCxO
    Value expanded;
    {
      std::vector<spu::Value> images;
      for (int64_t x = 0; x <= H - h; x += sh) {
        for (int64_t y = 0; y <= W - w; y += sw) {
          auto window =
              hal::slice(ctx, input, {0, x, y, 0}, {N, x + h, y + w, C}, {});
          images.emplace_back(hal::reshape(ctx, window, {N, 1, h, w, C}));
        }
      }
      auto stacked = hal::concatenate(ctx, images, 1);
      SPU_ENFORCE_EQ(stacked.shape()[1], hh * ww);
      expanded = hal::reshape(ctx, stacked, {N, hh * ww, h * w, C});
    }

    // TODO(jint): the below method is much slower then the code above, consider
    // to use slice+reshape+concat to rewrite expandWindow.
    //
    // std::vector<std::pair<int64_t, int64_t>> padding(4, {0, 0});
    // auto expanded = expandWindow(ctx, input,      // input
    //                                    {N, h, w, C},    // window_shape
    //                                    {1, sh, sw, 1},  // strides
    //                                    padding);

    // Now expanded shape is (N, hh*ww, h*w, C)
    SPU_ENFORCE_EQ(expanded.shape()[0], N);
    SPU_ENFORCE_EQ(expanded.shape()[1], hh * ww);
    SPU_ENFORCE_EQ(expanded.shape()[2], h * w);
    SPU_ENFORCE_EQ(expanded.shape()[3], C);

    // Reshape it to (N, hh, ww, h, w, C)
    expanded = hal::reshape(ctx, expanded, {N, hh, ww, h, w, C});

    // Contract on h, w, C
    // expanded:  (N, hh, ww, h, w, C)
    // kernel:               (h, w, C, O)
    // result:    (N, hh, ww,          O)
    auto result = hal::tensordot(ctx, expanded, kernel, {3, 4, 5}, {0, 1, 2});
    SPU_ENFORCE_EQ(result.shape()[0], N);
    SPU_ENFORCE_EQ(result.shape()[1], hh);
    SPU_ENFORCE_EQ(result.shape()[2], ww);
    SPU_ENFORCE_EQ(result.shape()[3], O);

    return result;
  }
}

}  // namespace spu::kernel::hlo

After modifying the the convolution.cc file, I run the command bazel run -c opt //examples/python/utils:nodectl -- --config pwd/examples/python/ml/flax_resnet18/2pc.json up but unexpectedly got errors like:
ERROR: /home/warpoons/Desktop/spu-0.9.1b0/libspu/kernel/hlo/BUILD.bazel:152:15: Compiling libspu/kernel/hlo/convolution.cc failed: (Exit 1): gcc failed: error executing command (from target //libspu/kernel/hlo:convolution) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -g0 -O2 '-D_FORTIFY_SOURCE=1' -DNDEBUG -ffunction-sections ... (remaining 179 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
libspu/kernel/hlo/convolution.cc: In function 'spu::Value spu::kernel::hlo::Convolution2D(spu::SPUContext*, const spu::Value&, const spu::Value&, const spu::kernel::hlo::ConvolutionConfig&, const spu::Shape&)':
libspu/kernel/hlo/convolution.cc:62:41: error: invalid initialization of reference of type 'const spu::Value&' from expression of type 'long int'
   62 |     auto T = hal::ceil(ctx, (H - r + 1) / m); // number of tiles along height/weight
      |                             ~~~~~~~~~~~~^~~
In file included from libspu/kernel/hlo/convolution.cc:17:
./libspu/kernel/hal/polymorphic.h:88:42: note: in passing argument 2 of 'spu::Value spu::kernel::hal::ceil(spu::SPUContext*, const spu::Value&)'
   88 | Value ceil(SPUContext* ctx, const Value& in);
      |                             ~~~~~~~~~~~~~^~
libspu/kernel/hlo/convolution.cc:124:30: error: invalid initialization of reference of type 'const spu::Shape&' from expression of type '<brace-enclosed initializer list>'
  124 |       expanded = hal::reshape(ctx, stacked, {P, a, a, C});
      |                  ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from libspu/kernel/hlo/convolution.cc:18:
./libspu/kernel/hal/shape_ops.h:36:62: note: in passing argument 3 of 'spu::Value spu::kernel::hal::reshape(spu::SPUContext*, const spu::Value&, const spu::Shape&)'
   36 | Value reshape(SPUContext* ctx, const Value& in, const Shape& to_shape);
      |                                                 ~~~~~~~~~~~~~^~~~~~~~
libspu/kernel/hlo/convolution.cc:139:69: error: invalid initialization of reference of type 'const spu::Shape&' from expression of type '<brace-enclosed initializer list>'
  139 |     auto result = hal::reshape(ctx, hal::transpose(ctx, hal::reshape(ctx, output_tile, {N, T, T, m, m, O}), {0, 1, 3, 2, 4, 5}), {N, out_size, out_size, O});
      |                                                         ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from libspu/kernel/hlo/convolution.cc:18:
./libspu/kernel/hal/shape_ops.h:36:62: note: in passing argument 3 of 'spu::Value spu::kernel::hal::reshape(spu::SPUContext*, const spu::Value&, const spu::Shape&)'
   36 | Value reshape(SPUContext* ctx, const Value& in, const Shape& to_shape);
      |                                                 ~~~~~~~~~~~~~^~~~~~~~
Target //examples/python/utils:nodectl failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 116.662s, Critical Path: 47.96s
INFO: 418 processes: 15 internal, 403 linux-sandbox.
FAILED: Build did NOT complete successfully
ERROR: Build failed. Not running target

Would you mind take a look at what went wrong there and feasible solutions? Thanks! :)

libspu/kernel/hlo/convolution.cc:62:41: error: invalid initialization of reference of type 'const spu::Value&' from expression of type 'long int'
hal::ceil accepts the type spu::Value as argument, not builtin scalar types.

libspu/kernel/hlo/convolution.cc:62:41: error: invalid initialization of reference of type 'const spu::Value&' from expression of type 'long int'
hal::ceil accepts the type spu::Value as argument, not builtin scalar types.

Hi @tpppppub. Thanks for pointing out that! In the modified version, I have used auto T = input.shape()[1] / 2 - 1; without ceil and the SPU backend runtime can be successfully launched now, but when I tried to test the inference of ResNet18 with this new convolution.cc, the errors happened:

By running the flax_resnet_inference, I got:

INFO: Running command line: bazel-bin/examples/python/ml/flax_resnet18/flax_resnet_inference --config /home/warpoons/Desktop/spu-0.9.1b0/examples/python/ml/flax_resnet18/2pc.json
Run on SPU
------

An NVIDIA GPU may be present on this machine, but a CUDA-enabled jaxlib is not installed. Falling back to cpu.
Traceback (most recent call last):
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/examples/python/ml/flax_resnet18/flax_resnet_inference.py", line 142, in <module>
    run_on_spu(inputs, params)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/examples/python/ml/flax_resnet18/flax_resnet_inference.py", line 118, in run_on_spu
    out = infer(params, inputs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 693, in __call__
    results = [future.result() for future in futures]
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 693, in <listcomp>
    results = [future.result() for future in futures]
  File "/home/warpoons/anaconda3/envs/spu_py310/lib/python3.10/concurrent/futures/_base.py", line 451, in result
    return self.__get_result()
  File "/home/warpoons/anaconda3/envs/spu_py310/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File "/home/warpoons/anaconda3/envs/spu_py310/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 247, in run
    return self._call(self._stub.Run, fn, *args, **kwargs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 240, in _call
    raise Exception("remote exception", result)
Exception: ('remote exception', Exception('Traceback (most recent call last):\n  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 326, in Run\n    ret_objs = fn(self, *args, **kwargs)\n  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 589, in builtin_spu_run\n    rt.run(spu_exec)\n  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/api.py", line 44, in run\n    return self._vm.Run(executable.SerializeToString())\nRuntimeError: what: \n\t[Enforce fail at libspu/kernel/hal/ring.cc:230] (lhs.ndim() > 0 && lhs.ndim() <= 2). \nStacktrace:\n#0 spu::kernel::hal::f_mmul()+0x735cd124b610\n#1 spu::kernel::hal::(anonymous namespace)::dtypeBinaryDispatch<>()+0x735cd122d2e2\n#2 spu::kernel::hal::matmul()+0x735cd122df4d\n#3 spu::kernel::hlo::Convolution2D()+0x735cd11d11ee\n#4 spu::device::pphlo::dispatchOp<>()+0x735cd0ae146e\n#5 spu::device::pphlo::dispatchOp<>()+0x735cd0ae24b3\n#6 spu::device::pphlo::dispatchOp<>()+0x735cd0ae424a\n#7 spu::device::pphlo::dispatchOp<>()+0x735cd0ae65f4\n#8 spu::device::runBlock()+0x735cd0c66a3d\n#9 spu::device::runRegion()+0x735cd0c68ae3\n#10 spu::device::executeImpl()+0x735cd059f0e7\n#11 spu::RuntimeWrapper::Run()+0x735ccf92f4cc\n#12 pybind11::cpp_function::initialize<>()::{lambda()#3}::_FUN()+0x735ccf90121d\n#13 pybind11::cpp_function::dispatcher()+0x735ccf8f6006\n#14 cfunction_call+0x4fdc87\n\nstacktrace: \n#0 spu::kernel::hal::f_mmul()+0x735cd124b610\n#1 spu::kernel::hal::(anonymous namespace)::dtypeBinaryDispatch<>()+0x735cd122d2e2\n#2 spu::kernel::hal::matmul()+0x735cd122df4d\n#3 spu::kernel::hlo::Convolution2D()+0x735cd11d11ee\n#4 spu::device::pphlo::dispatchOp<>()+0x735cd0ae146e\n#5 spu::device::pphlo::dispatchOp<>()+0x735cd0ae24b3\n#6 spu::device::pphlo::dispatchOp<>()+0x735cd0ae424a\n#7 spu::device::pphlo::dispatchOp<>()+0x735cd0ae65f4\n#8 spu::device::runBlock()+0x735cd0c66a3d\n#9 spu::device::runRegion()+0x735cd0c68ae3\n#10 spu::device::executeImpl()+0x735cd059f0e7\n#11 spu::RuntimeWrapper::Run()+0x735ccf92f4cc\n#12 pybind11::cpp_function::initialize<>()::{lambda()#3}::_FUN()+0x735ccf90121d\n#13 pybind11::cpp_function::dispatcher()+0x735ccf8f6006\n#14 cfunction_call+0x4fdc87\n\n\n'))

And the backend runtime reported something like:

[2024-07-16 17:19:27,187] [ForkServerProcess-1] Traceback (most recent call last):
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 326, in Run
    ret_objs = fn(self, *args, **kwargs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 589, in builtin_spu_run
    rt.run(spu_exec)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/api.py", line 44, in run
    return self._vm.Run(executable.SerializeToString())
RuntimeError: what:
        [Enforce fail at libspu/kernel/hal/ring.cc:230] (lhs.ndim() > 0 && lhs.ndim() <= 2).
Stacktrace:
#0 spu::kernel::hal::f_mmul()+0x735cd124b610
#1 spu::kernel::hal::(anonymous namespace)::dtypeBinaryDispatch<>()+0x735cd122d2e2
#2 spu::kernel::hal::matmul()+0x735cd122df4d
#3 spu::kernel::hlo::Convolution2D()+0x735cd11d11ee
#4 spu::device::pphlo::dispatchOp<>()+0x735cd0ae146e
#5 spu::device::pphlo::dispatchOp<>()+0x735cd0ae24b3
#6 spu::device::pphlo::dispatchOp<>()+0x735cd0ae424a
#7 spu::device::pphlo::dispatchOp<>()+0x735cd0ae65f4
#8 spu::device::runBlock()+0x735cd0c66a3d
#9 spu::device::runRegion()+0x735cd0c68ae3
#10 spu::device::executeImpl()+0x735cd059f0e7
#11 spu::RuntimeWrapper::Run()+0x735ccf92f4cc
#12 pybind11::cpp_function::initialize<>()::{lambda()#3}::_FUN()+0x735ccf90121d
#13 pybind11::cpp_function::dispatcher()+0x735ccf8f6006
#14 cfunction_call+0x4fdc87

Could you mind take a look at what were wrong here and feasible solutions? Sorry for taking your time. Thanks! :)

libspu/kernel/hlo/convolution.cc:62:41: error: invalid initialization of reference of type 'const spu::Value&' from expression of type 'long int'
hal::ceil accepts the type spu::Value as argument, not builtin scalar types.

Hi @tpppppub. Thanks for pointing out that! In the modified version, I have used auto T = input.shape()[1] / 2 - 1; without ceil and the SPU backend runtime can be successfully launched now, but when I tried to test the inference of ResNet18 with this new convolution.cc, the errors happened:

By running the flax_resnet_inference, I got:

INFO: Running command line: bazel-bin/examples/python/ml/flax_resnet18/flax_resnet_inference --config /home/warpoons/Desktop/spu-0.9.1b0/examples/python/ml/flax_resnet18/2pc.json
Run on SPU
------

An NVIDIA GPU may be present on this machine, but a CUDA-enabled jaxlib is not installed. Falling back to cpu.
Traceback (most recent call last):
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/examples/python/ml/flax_resnet18/flax_resnet_inference.py", line 142, in <module>
    run_on_spu(inputs, params)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/examples/python/ml/flax_resnet18/flax_resnet_inference.py", line 118, in run_on_spu
    out = infer(params, inputs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 693, in __call__
    results = [future.result() for future in futures]
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 693, in <listcomp>
    results = [future.result() for future in futures]
  File "/home/warpoons/anaconda3/envs/spu_py310/lib/python3.10/concurrent/futures/_base.py", line 451, in result
    return self.__get_result()
  File "/home/warpoons/anaconda3/envs/spu_py310/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File "/home/warpoons/anaconda3/envs/spu_py310/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 247, in run
    return self._call(self._stub.Run, fn, *args, **kwargs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/ml/flax_resnet18/flax_resnet_inference.runfiles/spulib/spu/utils/distributed_impl.py", line 240, in _call
    raise Exception("remote exception", result)
Exception: ('remote exception', Exception('Traceback (most recent call last):\n  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 326, in Run\n    ret_objs = fn(self, *args, **kwargs)\n  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 589, in builtin_spu_run\n    rt.run(spu_exec)\n  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/api.py", line 44, in run\n    return self._vm.Run(executable.SerializeToString())\nRuntimeError: what: \n\t[Enforce fail at libspu/kernel/hal/ring.cc:230] (lhs.ndim() > 0 && lhs.ndim() <= 2). \nStacktrace:\n#0 spu::kernel::hal::f_mmul()+0x735cd124b610\n#1 spu::kernel::hal::(anonymous namespace)::dtypeBinaryDispatch<>()+0x735cd122d2e2\n#2 spu::kernel::hal::matmul()+0x735cd122df4d\n#3 spu::kernel::hlo::Convolution2D()+0x735cd11d11ee\n#4 spu::device::pphlo::dispatchOp<>()+0x735cd0ae146e\n#5 spu::device::pphlo::dispatchOp<>()+0x735cd0ae24b3\n#6 spu::device::pphlo::dispatchOp<>()+0x735cd0ae424a\n#7 spu::device::pphlo::dispatchOp<>()+0x735cd0ae65f4\n#8 spu::device::runBlock()+0x735cd0c66a3d\n#9 spu::device::runRegion()+0x735cd0c68ae3\n#10 spu::device::executeImpl()+0x735cd059f0e7\n#11 spu::RuntimeWrapper::Run()+0x735ccf92f4cc\n#12 pybind11::cpp_function::initialize<>()::{lambda()#3}::_FUN()+0x735ccf90121d\n#13 pybind11::cpp_function::dispatcher()+0x735ccf8f6006\n#14 cfunction_call+0x4fdc87\n\nstacktrace: \n#0 spu::kernel::hal::f_mmul()+0x735cd124b610\n#1 spu::kernel::hal::(anonymous namespace)::dtypeBinaryDispatch<>()+0x735cd122d2e2\n#2 spu::kernel::hal::matmul()+0x735cd122df4d\n#3 spu::kernel::hlo::Convolution2D()+0x735cd11d11ee\n#4 spu::device::pphlo::dispatchOp<>()+0x735cd0ae146e\n#5 spu::device::pphlo::dispatchOp<>()+0x735cd0ae24b3\n#6 spu::device::pphlo::dispatchOp<>()+0x735cd0ae424a\n#7 spu::device::pphlo::dispatchOp<>()+0x735cd0ae65f4\n#8 spu::device::runBlock()+0x735cd0c66a3d\n#9 spu::device::runRegion()+0x735cd0c68ae3\n#10 spu::device::executeImpl()+0x735cd059f0e7\n#11 spu::RuntimeWrapper::Run()+0x735ccf92f4cc\n#12 pybind11::cpp_function::initialize<>()::{lambda()#3}::_FUN()+0x735ccf90121d\n#13 pybind11::cpp_function::dispatcher()+0x735ccf8f6006\n#14 cfunction_call+0x4fdc87\n\n\n'))

And the backend runtime reported something like:

[2024-07-16 17:19:27,187] [ForkServerProcess-1] Traceback (most recent call last):
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 326, in Run
    ret_objs = fn(self, *args, **kwargs)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/utils/distributed_impl.py", line 589, in builtin_spu_run
    rt.run(spu_exec)
  File "/home/warpoons/.cache/bazel/_bazel_warpoons/580f3d68baaaad498fe83c6c3b519d10/execroot/spulib/bazel-out/k8-opt/bin/examples/python/utils/nodectl.runfiles/spulib/spu/api.py", line 44, in run
    return self._vm.Run(executable.SerializeToString())
RuntimeError: what:
        [Enforce fail at libspu/kernel/hal/ring.cc:230] (lhs.ndim() > 0 && lhs.ndim() <= 2).
Stacktrace:
#0 spu::kernel::hal::f_mmul()+0x735cd124b610
#1 spu::kernel::hal::(anonymous namespace)::dtypeBinaryDispatch<>()+0x735cd122d2e2
#2 spu::kernel::hal::matmul()+0x735cd122df4d
#3 spu::kernel::hlo::Convolution2D()+0x735cd11d11ee
#4 spu::device::pphlo::dispatchOp<>()+0x735cd0ae146e
#5 spu::device::pphlo::dispatchOp<>()+0x735cd0ae24b3
#6 spu::device::pphlo::dispatchOp<>()+0x735cd0ae424a
#7 spu::device::pphlo::dispatchOp<>()+0x735cd0ae65f4
#8 spu::device::runBlock()+0x735cd0c66a3d
#9 spu::device::runRegion()+0x735cd0c68ae3
#10 spu::device::executeImpl()+0x735cd059f0e7
#11 spu::RuntimeWrapper::Run()+0x735ccf92f4cc
#12 pybind11::cpp_function::initialize<>()::{lambda()#3}::_FUN()+0x735ccf90121d
#13 pybind11::cpp_function::dispatcher()+0x735ccf8f6006
#14 cfunction_call+0x4fdc87

Could you mind take a look at what were wrong here and feasible solutions? Sorry for taking your time. Thanks! :)

matmul only supports < 2D dot. Seems you are doing 4D dot

Hi @anakinxc. Thanks for your reminder! I realized that tensordot should be used here instead of matmul.
Remember that for a fixed model with known weights, the kernel transformation can be done offline. Therefore, I replace the hal::tensordot in kernel transformation with constant all-ones mat to simulate this situation.  So confused!
Would you mind take a look at this and is there any suggestions? Thanks! :)

Hi @warpoons
Please try to benchmark with experimental_disable_mmul_split set to True.
Looks like your implementation requires 7 tensordot where the original implementation requires only 1.
Tensordot with non-integer inputs will introduce a truncation operation which is expensive and needs communication.
One thing you can try is reduce number of truncation, for example, trunc(dot(x, y) + trunc(dot(y, z)) can be simplified into trunc(dot(x,y) + dot(y,z))

Hi @warpoons
Please try to benchmark with experimental_disable_mmul_split set to True.
Looks like your implementation requires 7 tensordot where the original implementation requires only 1.
Tensordot with non-integer inputs will introduce a truncation operation which is expensive and needs communication.
One thing you can try is reduce number of truncation, for example, trunc(dot(x, y) + trunc(dot(y, z)) can be simplified into trunc(dot(x,y) + dot(y,z))

Hi @anakinx. Thanks for your suggestion! I have benchmarked with "experimental_disable_mmul_split": true in 2pc.json.
And for the number of tensordot, there are indeed 7 tensordot in a Winograd conv, where they specifically are:

For 6 fixed pre-defined 2D transformation matrices:
G = { {1.0, 0.0, 0.0},
{0.5, 0.5, 0.5},
{0.5, -0.5, 0.5},
{0.0, 0.0, 1.0} };
G_T = { {1.0, 0.5, 0.5, 0.0},
{0.0, 0.5, -0.5, 0.0},
{0.0, 0.5, 0.5, 1.0} };
B = { {1, 0, 0, 0},
{0, 1, -1, 1},
{-1, 1, 1, 0},
{0, 0, 0, -1} };
B_T = { {1, 0, -1, 0},
{0, 1, 1, 0},
{0, -1, 1, 0},
{0, 1, 0, -1} };
A = { {1, 0},
{1, 1},
{1, -1},
{0, -1}};
A_T = { {1, 1, 1, 0},
{0, 1, -1, -1}};
// Transform 4D (h, w, inCh, OutCh) kernel to Winograd domain
auto U = hal::tensordot(ctx, G, hal::tensordot(ctx, kernel, G_T, {1}, {0}), {1}, {0});  // 2 tensordot here
// Transform 4D (N, H, W, inCh) input to Winograd domain
auto V = hal::tensordot(ctx, B_T, hal::tensordot(ctx, expanded, B, {2}, {0}), {1}, {1});  // 2 tensordot here
// Do General Matmul
auto M = hal::tensordot(ctx, U, V, {1, 3}, {0, 2});  // 1 tensordot here
// Transform Winograd output back to regular output
auto output_tile = hal::tensordot(ctx, A_T, hal::tensordot(ctx, M, A, {2}, {0}), {1}, {1}); // 2 tensordot here

Therefore, there are total 2+2+1+2=7 tensordot for one Winograd conv. This might be the reason for high trunc and total comm.
I have also merged all the tensordot into one expression but the profile didn't change.
Are there any feasible optimizations? Thanks! :)

Hi @warpoons
Please try to benchmark with experimental_disable_mmul_split set to True.
Looks like your implementation requires 7 tensordot where the original implementation requires only 1.
Tensordot with non-integer inputs will introduce a truncation operation which is expensive and needs communication.
One thing you can try is reduce number of truncation, for example, trunc(dot(x, y) + trunc(dot(y, z)) can be simplified into trunc(dot(x,y) + dot(y,z))

Hi @AnakinX. Thanks for your suggestion! I have benchmarked with "experimental_disable_mmul_split": true in 2pc.json.
And for the number of tensordot, there are indeed 7 tensordot in a Winograd conv, where they specifically are:

For 6 fixed pre-defined 2D transformation matrices:
G = { {1.0, 0.0, 0.0},
{0.5, 0.5, 0.5},
{0.5, -0.5, 0.5},
{0.0, 0.0, 1.0} };
G_T = { {1.0, 0.5, 0.5, 0.0},
{0.0, 0.5, -0.5, 0.0},
{0.0, 0.5, 0.5, 1.0} };
B = { {1, 0, 0, 0},
{0, 1, -1, 1},
{-1, 1, 1, 0},
{0, 0, 0, -1} };
B_T = { {1, 0, -1, 0},
{0, 1, 1, 0},
{0, -1, 1, 0},
{0, 1, 0, -1} };
A = { {1, 0},
{1, 1},
{1, -1},
{0, -1}};
A_T = { {1, 1, 1, 0},
{0, 1, -1, -1}};
// Transform 4D (h, w, inCh, OutCh) kernel to Winograd domain
auto U = hal::tensordot(ctx, G, hal::tensordot(ctx, kernel, G_T, {1}, {0}), {1}, {0});  // 2 tensordot here
// Transform 4D (N, H, W, inCh) input to Winograd domain
auto V = hal::tensordot(ctx, B_T, hal::tensordot(ctx, expanded, B, {2}, {0}), {1}, {1});  // 2 tensordot here
// Do General Matmul
auto M = hal::tensordot(ctx, U, V, {1, 3}, {0, 2});  // 1 tensordot here
// Transform Winograd output back to regular output
auto output_tile = hal::tensordot(ctx, A_T, hal::tensordot(ctx, M, A, {2}, {0}), {1}, {1}); // 2 tensordot here

Therefore, there are total 2+2+1+2=7 tensordot for one Winograd conv. This might be the reason for high trunc and total comm.
I have also merged all the tensordot into one expression but the profile didn't change.
Are there any feasible optimizations? Thanks! :)

Merge into one expression does not reduce number of calls.
Try to figure out how many truncations you actually need might be a better idea.

Thank you @anakinxc. As you previously said, matmul is suitable for 2D dot while tensorsot supports >2D dot. An additional question is that does matmul also introduce 1 trunc just like tensorsot?

Thanks for the patient guidance and discussion. My problem has been solved. This issue can be closed as completed. Thansk for all!


UnboundLocalError: local variable 'keypoints' referenced before assignment

Traceback (most recent call last):
  File "inference.py", line 345, in <module>
    main()
  File "inference.py", line 82, in main
    lm = kp_extractor.extract_keypoint(frames_pil, './temp/'+base_name+'_landmarks.txt')
  File "D:\video-retalking\third_part\face3d\extract_kp_videos.py", line 29, in extract_keypoint
    current_kp = self.extract_keypoint(image)
  File "D:\video-retalking\third_part\face3d\extract_kp_videos.py", line 57, in extract_keypoint
    return keypoints
UnboundLocalError: local variable 'keypoints' referenced before assignment

OS: Windows 10

I am having the same issue.

same same

same here

If you check the error info again there's a good chance more error information above. The error message you posted is most likely caused by Line 41 of the same file.
I'm guessing it's caused by CUDA version conflict in PyTorch.


GH-33652: [C++][Parquet] Add interface total_compressed_bytes_written

Rationale for this change

What changes are included in this PR?

Talked in https://github.com/apache/arrow/issues/33652 . Main issue is that total_bytes_written is confusing, because it only tells the size of "uncompressed" bytes size written. For buffered page writer, the actually written size cannot be known until all column chunk is written and call sink_.Tell().
I'd like to:

[x] Add interface for PageWriter
[x] Add interface for ColumnWriter
[x] Add interface for RowGroupWriter
[ ] Testing them

Are these changes tested?

I'd like to test it later.
Are there any user-facing changes?
User can get excatly size written by: total_compressed_bytes_written() + total_compressed_bytes() for ColumnWriter before finish writing.

Closes: #33652

@pitrou @wjones127 I think the main code is already finished. If you think the interface and description is ok, I will add some simple tests here.

This looks good so far!

Well, by the way, I found a trickey issue. In RowGroupSerializer, it have both:
int64_t total_bytes_written() const override;

and member:
int64_t total_bytes_written_;

When RowGroupSerializer is closed, all bytes will accumulated to total_bytes_written_, and use it to finish metadata. But total_bytes_written() will always got 0. Should I add comment for this behavior? Or making it return total_bytes_written_ once closed?
@pitrou @wjones127 @wgtmac

Or making it return total_bytes_written_ once closed?

I think this is better. I would rather the behavior is not surprising than have to document special cases like that.

@wgtmac Some comment fixed.
By the way, after writing some comments, I thinks previous comment is really leaky... Maybe users have already misused these interface...

Yes, I think adding the comment should help understand. I wish these parts of the codebase were better documented.
Are you still planning on adding tests?

Yes, I think adding the comment should help understand. I wish these parts of the codebase were better documented.
Are you still planning on adding tests?

Yes, I will, but I'm a little busy this week, and adding tests for bytes_written is boring and troublesome, because we only know that I "would no less than xx bytes" or "should less than xx bytes", but actually don't know it's really length when writing...
I'll add it this weekend...

@wjones127 Test added, maybe I'm bad at organize testing, you can comment or edit it directly..

@westonpace Let me explain it detail here:
Parquet, which may contains multiple rowgroups, rowgroups may contain multiple columns, and columns may contain multiple pages.
For a ParquetFileWriter, use can use AppendBufferedRowGroup and AppendRowGroup to acquire a buffered and unbuffered rowgroup writer.
For buffered RowGroupWriter, it can:
for column in columns:
  columns[i] = file_writer->AppendBufferedRowGroup()

for value in value-batches:
  column_writer = columns[i]->column()
  typed_column_writer->Write()

For unbuffered RowGroupWriter, it can:
for column in columns:
  columns[i] = file_writer->AppendRowGroup()
  writeAllValues(columns[i])

Below are user-known api which you may familiar with. Now let's explain the interface of this patch, and why previous patch is trickey.
An active Column uses (Typed)ColumnWriter to write values, and ColumnWriter holds a PageWriter to write page to sink.  If no dict is enabled, it would be like:
Type1: non-buffered-non-dict:
Only Have One Active Column Writer
Column2: |  DataPage1 |   DataPage2 | Buffered-Values that didn't becoming a page |

For it, the output bytes are:

RowGroupWriter.total_compressed_bytes: 0
2.RowGroupWriter.total_bytes_written: It doesn't mean the Column1-Data-Bytes + Column2-DataPage1 + Column2-DataPage2. In fact, it means the uncompressed Column1-IO-Bytes + Column2-DataPage1 + Column2-DataPage2 if compression like zstd enabled
(New in this patch) RowGroupWriter.total_bytes_written: It means the Column1-Data-Bytes + Column2-DataPage1 + Column2-DataPage2. It will be a little less than really io-bytes, because page and column may write some metadata. But they will be close
ColumnWriter.total_compressed_bytes: 0
ColumnWriter.total_bytes_written: uncompressed Column2-DataPage1 + Column2-DataPage2
(New in this patch) ColumnWriter.total_compressed_bytes_written: It means the Column2-DataPage1 + Column2-DataPage2.

Type-2 non-buffered-dict:
Now, things would be a little different. ColumnWriter has a data_pages_ vector for pages.
Only Have One Active Column Writer
Column2:  | Buffered-Values that didn't becoming a page |
* Column2: buffers DataPage1  and  DataPage2
* Column2: Building Dictionary Page

Now, let's revisit the ColumnWriter's size:

ColumnWriter.total_compressed_bytes: compressed Column2-DataPage1 + Column2-DataPage2
ColumnWriter.total_bytes_written: 0
(New in this patch) ColumnWriter.total_compressed_bytes_written: 0

Type3: buffered-non-dict:
Have Two Active Column Writer
Column2: |  DataPage1 |  Buffered-Values that didn't becoming a page |
Column2: |  DataPage1 |   DataPage2 | Buffered-Values that didn't becoming a page |

ColumnWriter.total_compressed_bytes: Compressed c1.DataPage1 + c2.DataPage1 + c3.DataPage2
ColumnWriter.total_bytes_written: 0
(New in this patch) ColumnWriter.total_compressed_bytes_written: 0

And you may curious that what's the size didn't writen to a page, or holded by Dictionary. That's EstimatedDataEncodedSize().


Feature: Define Kafka connectors with terraform

hey, @Cliftonz .
Thanks for the issue. We will look into this.


Pull in new wording for maximum number question

Pulls in new wording for public display of opportunities.

👍


[10.x] Fix redis tag entries never becoming stale if cache ttl is past time

With the new redis tags implementation, setting a cache value with a TTL that is in the past resulted in tag entries getting a score of -1, thus never being considered stale.
This was because getSeconds() returns 0 when given a date in the past and tags->addEntry() assumed "forever" when it was passed a TTL of 0.
This PR fixes that issue for the add and put methods of RedisTaggedCache:

For add(), when the time is in the past, we simply return early with a false (same strategy as parent class)
For put(), we allow any existing entry to get updated, but the entry will have a score of the current timestamp so it will get cleaned up the next time flushStale() is called.

@taylorotwell  @jagers
This change makes the cache behave inconsistently. Is this the expected change?
For example:
Before:
        Cache::store('redis')->tags(['people', 'author'])->put('person-1', 'Sally', 100);
        Cache::store('redis')->tags(['people', 'author'])->put('person-1', 'Sally', 0);
        Cache::store('redis')->tags(['people', 'author'])->get('person-1');
        // null

After:
        Cache::store('redis')->tags(['people', 'author'])->put('person-1', 'Sally', 100);
        Cache::store('redis')->tags(['people', 'author'])->put('person-1', 'Sally', 0);
        Cache::store('redis')->tags(['people', 'author'])->get('person-1');
        // Sally

@kayw-geek you mean you cannot expire a cache items anymore with a 0 til?

@kayw-geek you mean you cannot expire a cache items anymore with a 0 ttl?

Yes, cause by following code
 if ($seconds <= 0) {
            return false;
        }


Bitbar crashes due to port leaks

I have a script running every second by the bitbar app and the Bitbar is leaking a port per execution.
Then bitbar crashes once it cannot get a port any more.
Following lines are crash log from console app:
Process:               BitBar [1149]
Path:                  /Applications/BitBar.app/Contents/MacOS/BitBar
Identifier:            com.matryer.BitBar
Version:               1.9.2 (1.9.2)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           BitBar [1149]
User ID:               501
Date/Time:             2020-01-10 13:03:31.874 -0800
OS Version:            Mac OS X 10.15.2 (19C57)
Report Version:        12
Anonymous UUID:        C6EA9A39-F85A-48C6-4820-6E0ABF22203C
Time Awake Since Boot: 320000 seconds
System Integrity Protection: enabled
Crashed Thread:        6  Dispatch queue: com.apple.root.default-qos
Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY
Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSRunLoop addPort:forMode:]: port argument cannot be nil'
abort() called
terminating with uncaught exception of type NSException
Application Specific Backtrace 1:
0   CoreFoundation                      0x00007fff309648ab __exceptionPreprocess + 250
1   libobjc.A.dylib                     0x00007fff66bd5805 objc_exception_throw + 48
2   Foundation                          0x00007fff32f79fce -[NSRunLoop(NSRunLoop) _addPort:forMode:] + 0
3   Foundation                          0x00007fff3303f7ed -[NSConcreteTask waitUntilExit] + 162
4   BitBar                              0x00000001065ec875 -[ExecutablePlugin refreshContentByExecutingCommand] + 546
5   BitBar                              0x00000001065ecca1 __27-[ExecutablePlugin refresh]_block_invoke + 45
6   libdispatch.dylib                   0x00007fff67ee9583 _dispatch_call_block_and_release + 12
7   libdispatch.dylib                   0x00007fff67eea50e _dispatch_client_callout + 8
8   libdispatch.dylib                   0x00007fff67eec358 _dispatch_queue_override_invoke + 763
9   libdispatch.dylib                   0x00007fff67ef87e2 _dispatch_root_queue_drain + 326
10  libdispatch.dylib                   0x00007fff67ef8f22 _dispatch_worker_thread2 + 92
11  libsystem_pthread.dylib             0x00007fff681446b6 _pthread_wqthread + 220
12  libsystem_pthread.dylib             0x00007fff68143827 start_wqthread + 15

Can you post your config?

Thank you for a quick reply.
However, I don't quite get how to obtain the config from bitbar. Could you please provide any instruction to obtain the config? In case, if you are talking about my script, I built a swift code to detect who prevents display sleep then rename it to


Go' bootstrap: Will the performance increase if C or assembly language is involved?

Please beat up C++ on performance so I can switch to Go as soon as possible.

Hi @beef9999 - We use the issue tracker only for specific bugs or proposals related to the Go programming language. Suggestions like these are best discussed in https://github.com/golang/go/wiki/Questions.
However, if you have some specific suggestions to improve, please do file specific issues on those. Thanks.

@beef9999 Go is already getting close to being as performant as C(++) for several types of program.
See, e.g. https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/go-gpp.html. And you can use the Go Assembler if you ever need a speed up for critical code.


Spread Operator isn't working correctly

So I'm having the following situation (code is also on flow.org/try):
I get some config variables (either from the config file or provided with data-attributes).
In the config file they're correct types (boolean or number), but when provided via data-attributes, they're strings.
type Language = 'de' | 'en' | 'fr' | 'nl';
type TemporaryConfig = {
  allowsac: boolean | string,
  allowssso: boolean | string,
  email: string,
  firstname: string,
  lang: Language,
  lastname: string,
  origin: string,
  processflow: number | string,
  requestpwd: boolean | string,
  showcloseplugin: boolean | string,
  token: string,
};

const tempConfig: TemporaryConfig = {
  allowsac: true,
  allowssso: 'true',
  email<EMAIL_ADDRESS>  firstname: 'John',
  lang: 'en',
  lastname: 'Doe',
  origin: 'http://origin.com',
  processflow: '1',
  requestpwd: true,
  showcloseplugin: 'false',
  token: 'test_token',
};

So I convert them to the correct types.
type Config = {
  allowsac: boolean,
  allowssso: boolean,
  email: string,
  firstname: string,
  lang: Language,
  lastname: string,
  origin: string,
  processflow: number,
  requestpwd: boolean,
  showcloseplugin: boolean,
  token: string,
};

const config: Config = convertConfigParams(tempConfig);

With the following conversion function:
const convertConfigParams = (configParams: TemporaryConfig): Config => {
  const {allowsac, allowssso, processflow, requestpwd, showcloseplugin}: TemporaryConfig = configParams;

  return {
    ...configParams,
    allowsac: convertParamToBoolean(allowsac),
    allowssso: convertParamToBoolean(allowssso),
    processflow: convertParamToNumber(processflow),
    requestpwd: convertParamToBoolean(requestpwd),
    showcloseplugin: convertParamToBoolean(showcloseplugin),
  };
};
const convertParamToBoolean = (param: boolean | string): boolean => {
    return `${String(param)}`.toLowerCase() === 'true';
};
const convertParamToNumber = (param: number | string): number => {
    return parseInt(param, 10);
};

One of the errors I get, is that allowsac isn't of type boolean:
36:   return {
             ^ object literal. This type is incompatible with the expected return type of
31: const convertConfigParams = (configParams: TemporaryConfig): Config => {
                                                                 ^ object type
Property `allowsac` is incompatible:
18:   allowsac: boolean | string,
                          ^ string. This type is incompatible with
4:   allowsac: boolean,
               ^ boolean

Which is because flow isn't counting in the overwritten value (which is a boolean).
I can solve this by setting all the other values explicitly in the return value and removing the spread operator, but that would be a bit cumbersome I think?
return {
  email,
  firstname,
  lang,
  lastname,
  origin,
  token,

  allowsac: convertParamToBoolean(allowsac),
  allowssso: convertParamToBoolean(allowssso),
  processflow: convertParamToNumber(processflow),
  requestpwd: convertParamToBoolean(requestpwd),
  showcloseplugin: convertParamToBoolean(showcloseplugin),
};

@MichaelDeBoey this one might be a mix of a bug in v58 and the Try not actually using older versions of Flow.
This works fine on my older flow and doesnt seem to work on v58 on my system.  It would seem that spread was broken completely in this version.  Still playing with this one a bit.

FYI this is still a problem: #7210

This should fix the issue: https://github.com/facebook/flow/pull/7298

This no longer errors on master


Origin whitelist fails on iOS for iframes

Hi,
i use react-native-webview 6.9.0 with react 59.5 to embed a page that contains an iframe with a standard google maps embed like this:
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1666.5345895801888!2d-111.841501241774!3d33.34314243590285!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x872ba9c40ac5d6f9%3A0x83f80f281a875961!2sReact+Defense!5e0!3m2!1sen!2sde!4v1565892032668!5m2!1sen!2sde" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe>
I have set originWhitelist to my website root.
With android, as expected you can navigate within my project and clicking external URLs will be handled by the OS.
With iOS (12.4) Safari gets opened immediately, loading the iframe src URL (the google embed page).
Is this a known problem for iframes?

hey @Niksac did you find any solution for this, bc I'm experimenting the same issue.

I solved the problem
In the node modules file we open the apple file inside the react-native-webwiew file and open RNCWebView.m
We need to make some additions here
if (_onShouldStartLoadWithRequest) {
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
[event addEntriesFromDictionary: @{
@"url": (request.URL).absoluteString,
@"mainDocumentURL": (request.mainDocumentURL).absoluteString,
@"navigationType": navigationTypes[@(navigationType)]
}];
if (![self.delegate webView:self
shouldStartLoadForRequest:event
withCallback:_onShouldStartLoadWithRequest]) {
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
such lines
if (_onShouldStartLoadWithRequest) {
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
[event addEntriesFromDictionary: @{
@"url": (request.URL).absoluteString,
@"mainDocumentURL": (request.mainDocumentURL).absoluteString,
@"navigationType": navigationTypes[@(navigationType)]
}];
if (!navigationAction.targetFrame.isMainFrame){
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
if (![self.delegate webView:self
shouldStartLoadForRequest:event
withCallback:_onShouldStartLoadWithRequest]) {
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
we have to change it this way

@Ibrahimkara92 would we need to reinstall pods after the change is done? I tried to directly add it on XCode to RNCWebView.m and it didn't seem to work for me.

it will not show if you make this change while the project is running. It is necessary to close the Metro control panel and run it again by saying npx react-native start @christianbermejo


Popup: zIndex is not applied in v2

Bug Report
Steps
Originally we have a Popup inside a Modal. On hover the Popup will not show up.
Expected Result
Should behave as in 1.3.1.
Actual Result
Popup is behind the Modal.
Version
2.0.0
Testcase => Reason
The  created as a popup container no longer has ANY classes, esp. not .ui.popup. Especially the z-index is not set.

The class is set one level below the outer div and the z-Index (1900) is no longer able to move the Popop contents above the modal.

@JMS-1 thanks for reporting this, this is a definitely valid issue. This change is a part of #3947:
https://github.com/Semantic-Org/Semantic-UI-React/blob/1fbeed912c80037b07201f37973f2d96fcd933b9/src/modules/Popup/Popup.js#L178-L182
It was done to avoid positioning issues with Popper.js as margins on containers are not handled anymore. As we don't control styles on our side we cannot simply remove margins (it also related to arrow positioning) 💥
Sorry for this unobvious change, I didn't take that it can affect apps... However, I tried different options before and I don't have a better solution there.

I will upgrade the migration guide and PR description to mention this issue.
I will added a shorthand prop (probably unstable_container) to allow customize classes and styles on that top level div:

<Popup unstable_container={{ className: 'foo', data-id: 'container', style: { zIndex: 10000 } }} />

Will it work for you?

Actually on first thought using Popup in Modal seems not be so rare - Modal for some Input Form, Popup for errors therein - so the solution seems to be a bit strange.
But indeed I think we have only few places and could live with it. I would have done something like this in CSS IF the container div hat at lease ANY class attached to ist but it hasn't. In F12 developer mode z-index: 1000 did the job.
So to summarize: yes, this will work for us. But it feels wrong (sorry) and personally I would prefer to have some class on the container IF this is possible (even data- would do) but as I understand this isn't.
Thanks
Jochen
PS: Thought by the side: why not putting an ADDITIONAL own div (absolute/0/0) around the container?

Any way to supply a class/style for parent will do. But don't give it a name of unstable as I'm not supposed to know about it's real nature.

The issue reproduces in many examples in my app which are not related to Modals.
Tooltip in a menu dropdown

Page inside a Pusher (part of SideBar component) which has z-index by default.
Looks like in previous popup version, the popup (it has a large z-index, 1900) class was the root of the popup portal, and not it is a child of some container.

I've patched locally my semantic-ui with
popperStyle = _extends({zIndex: 1900}, popperStyle);

In here: https://github.com/Semantic-Org/Semantic-UI-React/blob/1fbeed912c80037b07201f37973f2d96fcd933b9/src/modules/Popup/Popup.js#L177
And it solved the issue.

Do you think it's a good idea to have the z-Index in code? Wouldn't it be better to add some (new?) class and style the z-Index in?

It may be good enough to add .ui.popup to this div, it will definitely solve the problem

Do you think it's a good idea to have the z-Index in code? Wouldn't it be better to add some (new?) class and style the z-Index in?

The problem is that the this lib (React version of SUI) can't make changes in the CSS... it just relays on the original styles.

It may be good enough to add .ui.popup to this div, it will definitely solve the problem
I think that the comment here https://github.com/Semantic-Org/Semantic-UI-React/blob/1fbeed912c80037b07201f37973f2d96fcd933b9/src/modules/Popup/Popup.js#L178-L182 is the reason why this won't work.

Popup has properties popperDependencies and popperModifiers. Maybe there is some way to add popperStyle?

and popperClassName

Just to clarify, this change is a part of 2.0.0 and there is no any bugfixes or features that can force you to upgrade.

Why additional div is required?
Popper.js v2 requires to not have margins, but SUI defines them on .popup and they are also used to position a pointing beak:

I tried few options that came to my mind, but all of them were overcomplicated. Having an additional wrapping div is the most simple solution and it's used for positioning now.

Popup has properties popperDependencies and popperModifiers. Maybe there is some way to add popperStyle?

This will now scale as at some point it may be useful to add a data attribute, for example. Having a slot seems more reasonable for me and it's aligned with our API.
<Popup unstable_container={{ className: 'foo', data-id: 'container', style: { zIndex: 10000 } }} />
<Popup container={{ className: 'foo', data-id: 'container', style: { zIndex: 10000 } }} />
<Popup popper={{ className: 'foo', data-id: 'container', style: { zIndex: 10000 } }} />

@felixmosh I am thinking about syncing zIndex value between a container and .popup element:
componentDidMount() {
  this.syncZIndex()
}

componentDidUpdate() {
  this.syncZIndex()
}

syncZIndex() {
  // if it's defined in <Popup popper={{ style: {} }} /> there is no sense to override it
  if (_.isUndefined(this.props.popper.style.zIndex)) {
    this.popperRef.style.zIndex = window.getComputedStyle(this.popupRef).zIndex
  }
}

Since the value is hard coded in the css, there is no need to sync it.
Just add it to the proper styles as I suggested in my PR.

@felixmosh it can be the first iteration, however the issue that zIndex is not hardcoded, it's a variable in LESS so technically someone can have a different value:
z-index: @zIndex;

https://github.com/Semantic-Org/Semantic-UI/blob/master/src/definitions/modules/popup.less#L34
IMO, at least we should sync the initial value in componentDidMount().

Agree with syncing it in componentDidMount

Hello everyone. Have workaround?

Hello everyone. Have workaround?

https://github.com/Semantic-Org/Semantic-UI-React/issues/4083#issuecomment-703237102

@felixmosh Can we without fork?. Because i don't want to do fork

@sergeu90 I'm using patch-package in order to make a patch for the lib.
It allows you to modify the files in node_modules and save a patch file of this modification. At the end it will apply the patch each time you install dependency.

@felixmosh  Thanks. I see you created pull request.

Expanding upon @felixmosh's workaround, for people unfamiliar with patch-package here are some more detailed instructions:

Setup patch-package

Create a new file patches/semantic-ui-react+2.0.0.patch and add the following to the file:
diff --git a/node_modules/semantic-ui-react/dist/es/modules/Popup/Popup.js b/node_modules/semantic-ui-react/dist/es/modules/Popup/Popup.js
index 9d58fd4..6c1a42c 100644
--- a/node_modules/semantic-ui-react/dist/es/modules/Popup/Popup.js
+++ b/node_modules/semantic-ui-react/dist/es/modules/Popup/Popup.js
@@ -151,7 +151,7 @@ var Popup = /*#__PURE__*/function (_Component) {
         // defined by SUI CSS. It also means that this `div` will be positioned instead of `content`.
         React.createElement("div", {
           ref: popperRef,
-          style: popperStyle
+          style: _extends({zIndex: 1900}, popperStyle)
         }, /*#__PURE__*/React.createElement(ElementType, _extends({}, contentRestProps, {
           className: classes,
           style: styles

Run npx patch-package semantic-ui-react

Run git commit -m 'Fix popup z-index'

This worked for me in a meteor project.

@Blapi  It is cool decision. But we have many popup in the code and in each add this workaround not nice

actually I prefer the solution where the zIndex is not fixed in code - although up to now we never messed with the zIndex on semantic dialogs but you knows. So as long this isn't fixed we prefer a bit of a manual work-around which seems (only tested on one place) to work.
Step 1 is to provide a global method (TypeScript version)
export function semantic2PopupFix(elem: HTMLElement): void {     if (elem) {         elem.parentElement.parentElement.style.zIndex = getComputedStyle(elem.parentElement).zIndex     } }
Step 2 is to use it on every Popup.Content where it is necessary (in fact not all Popups come on as a problem and perhaps this is not applicable to the DateTimeInput problem - didn't check)
                        <Ref innerRef={semantic2PopupFix}>                             <Popup.Content>                                     ...                             </Popup.Content>                         </Ref>
In addition I still can't understand why it's so hard to "fix the fix" in suir itself - the outstanding PR uses a hardcoded 1900 and IMHO this is not an option. Ok, so in suir 2 you added an additional div for some good reasons. Why not simply propagate the zIndex from the inside to this new element when it's mounted - e.g. like the syncZIndex approach mentioned earlier?
Regards
Jochen

@Blapi It is cool decision. But we have many popup in the code and in each add this workaround not nice

@sergeu90 Indeed, this is why we took the decision to create a wrapper for the SUIR Popup
class PoppersPopup extends React.Component {
  static propTypes = {
    popperModifiers: PropTypes.arrayOf(PropTypes.object),
  }

  static defaultProps = {
    popperModifiers: [],
  }

  render() {
    const {popperModifiers, ...additionalProps} = this.props

    return (
      <Popup
        popperModifiers={[
          {
            name: 'zIndex',
            enabled: true,
            phase: 'write',
            fn: ({state}) => {
              state.styles.popper.zIndex = 42 // eslint-disable-line no-param-reassign
            },
          },
          ...popperModifiers,
        ]}
        {...additionalProps}
      />
    )
  }
}

And then replace each SUIR Popup in our codebase with a simple find & replace + a script to adding the imports (~60 files so it was not hectic)
And nothing was broken as we always used the content and trigger props, SUIR Popup was never wrapping anything in our codebase so this fix was, as I said, a - quick - workaround but it didn't take us much times to fix this issue in our app after finding out for popperModifiers while waiting for an official fix :)
But I can understand your point if you are not in my kind of situation, just want to point out that you can do this instead of adding this fix in every Popup that you have !

Folks please stop fixing this issue on your side, it will be fixed in SUIR on next week. If it creates issues for you just stay few days on 1.x until 2.0.1 will be released.

Thanks every for reporting and suggestions ❤
I fixed the issue in #4094 (visual tests were also added), BTW popperModifiers were the correct option as React lifecycle methods are executed in different frames. I expect that we will release it in 2.0.1 on Monday.

Released in<EMAIL_ADDRESS>🚢 Please check if everything works as expected.

@layershifter just in time for me, thx :)


Register Package

@JuliaRegistrator register()

Registration pull request created: JuliaRegistries/General/93232
After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.
This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:
git tag -a v0.1.0 -m "<description of version>" e8de851d8ebe3bc42b2ac20902fd38ece108b3bd
git push origin v0.1.0


feat(core): better SEO for images and package playground

Resolves #91, Fixes #89, Fixes #86.

Since (for the time I'm writing this) there's no known way to automatically guess the image aspect-ratio to prevent Cumulative Layout Shift (CLS), maybe it is a better choice to remove automatic width and height attributes from the Image component and let that job for the user. This means "no Lighthouse outta-the-box 100% performance score". 😭

I think the best choice, for now, is to reduce the scope for the Image component to perform the WebP replacement only. A possible future path is also deprecate the component in order to reduce the framework total size and MAYBE turn it into a separate module.

#89 seems to be fixed since version 1.0.10 of laravel-mix-simple-image-processing
Refer to this issue on the package repo: https://github.com/TristanMouchet/laravel-mix-simple-image-processing/issues/8


Test Content

Here is a bulleted list:

Bullet 1
Bullet 2
Bullet 3

Here is a hyperlink: hyperlink.
Here is italic text.
And here is a ## subheading (not working).

Comment.


[FEAT]: support similar multi-GPU selection

Description
should automatically switch to multi-GPU (the upper bound should be 8)
Additional Information
No response


Only depend on semigroups on old GHCs.

The conditional was already there for fail. It makes sense to only
incur the dependency on compatibility packages when needed, so let's
add semigroups to the conditional set, instead of depending on it unconditionally.

Looks good. Thanks.


[gui error report] Error: Initializing daemon...

👉 Please describe what you were doing when this error happened.
Specifications

OS: darwin 22.5.0
IPFS Desktop Version: 0.28.0
Electron Version: 19.1.9
Chrome Version: 102.0.5005.167

Error
Error: Initializing daemon...
Kubo version: 0.20.0
Repo version: 13
System version: amd64/darwin
Golang version: go1.19.8

Error: directory missing SHARDING file: /Users/utkarshchoudhary/.ipfs/blocks

    at errorTemplate (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/daemon/migration-prompt.js:78:49)
    at loadWindow (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/daemon/migration-prompt.js:129:26)
    at showMigrationPrompt (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/daemon/migration-prompt.js:134:3)
    at startIpfsWithLogs (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/daemon/daemon.js:193:9)
    at process.processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async startDaemon (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/daemon/daemon.js:216:27)
    at async startIpfs (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/daemon/index.js:48:17)
    at async setupDaemon (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/daemon/index.js:116:3)
    at async run (/Applications/IPFS Desktop.app/Contents/Resources/app.asar/src/index.js:85:5)

@whizzzkid Thanks for the response. I needed to install ipfs CLI.


Different url in swaggerUi and swaggerRouter when using them as sub-app

Problem
How to change url api path for swaggerUi where using express sub-app.
The goal is to build one app serving others API as sub-app. The sub-apps have common pattern and are served in root app.
sub-app/index.js
'use strict';

var app = require('express')();
var http = require('http');
var swaggerTools = require('swagger-tools');
var jsyaml = require('js-yaml');
var fs = require('fs');
var serverPort = 8081;

// swaggerRouter configuration
var options = {
  swaggerUi: __dirname + '/swagger.json',
  controllers: __dirname + '/controllers',
  useStubs: process.env.NODE_ENV === 'development' ? true : false // Conditionally turn on stubs (mock mode)
};

// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var spec = fs.readFileSync(__dirname + '/api/swagger.yaml', 'utf8');
var swaggerDoc = jsyaml.safeLoad(spec);
swaggerDoc.host = 'localhost:' + serverPort;

// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
  // Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
  app.use(middleware.swaggerMetadata());

  // Validate Swagger requests
  app.use(middleware.swaggerValidator());

  // Route validated requests to appropriate controller
  app.use(middleware.swaggerRouter(options));

  // Serve the Swagger documents and Swagger UI
  app.use(middleware.swaggerUi());

  // Start the server
  // http.createServer(app).listen(serverPort, function () {
  //   console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
  //   console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort);
  // });
});

module.exports = app;

swagger.yaml part
---
swagger: "2.0"
info:
  description: ""
  version: "v3"
  title: "Customer Management"
host: "localhost"
basePath: "/v3/customerManagement"
schemes:
- "http"
consumes:
- "application/json"
produces:
- "application/json"
paths:
  /customer:
    get:
(...)

root-app
const express = require('express');
const app = express();
const serverPort = 8081;

const customerManagement = require(__dirname + '/sub-app/index.js');
app.use(['/customerManagement'], customerManagement);

Problem details
The result is that swaggerUi is served under fallowing url:
http://localhost:8081/customerManagement/docs/

API is served under fallowing url:
http://localhost:8081/customerManagement/v3/customerManagement/customer

But when you are trying to use swaggerUi to test this API then the url is:
http://localhost:8081/v3/customerManagement/customer

How to change url path in swaggerUi?

swagger-ui uses the details from the spec, specifically info.host and info.basePath.  Are you sure this is a swagger-tools issue?

Yes, I know that it comes from the spec file. (To be clear and precise host and basePathare on the top level not in the info object). The problem is that I'm using Node.js express sub-app functionality. It means that finally host part of the url for the API will be different then oryginal spec but swagger-ui will still use the same url from file.
In my example host, basePath, schemes and path are:
host: "localhost"
basePath: "/v3/customerManagement"
schemes:
- "http"
paths:
  /customer:

So the API will be exposed under this url: http://localhost/v3/customerManagement/customer but when you use sub-app functionality the API will be exposed under this url: http://localhost/customerManagement/v3/customerManagement/customer but swagger-ui still will use oryginal specification: http://localhost/v3/customerManagement/customer.
The question is: How to set different url for swagger-ui or swagger-router?

If you are telling express to use a mountpoint or some other feature that prefixes the actual API paths, you need to make sure your basePath in the Swagger document corresponds.  That's the only way I know how to but I'm open to ideas.

If I change basePath adding the same prefix as mountpoint in express then this prefix will be added 2 times for API (1 from mountpoint 1 from basePath) and for swagger-ui only 1 (only from basePath). I was thinking about adding this prefix to host instead of basePath but the swagger file specification wan't be correct.

I'm not sure I understand what "added two times for API" means.  Does swagger-tools miss matching the API requests or is swagger-ui doing something wrong, or both?

Let's consider simple examples:
I'll put fallowing url to swagger file specification using schema, host and basePath: http://localhost:8080/basePath/resourcePart.
Examples:

Use prefix /foo' in express`.

API url will be: http://localhost:8080/foo/basePath/resourcePart
swagger-ui will use: http://localhost:8080/basePath/resourcePart

Use prefix /foo/bar in express.

API url will be: http://localhost:8080/foo/bar/basePath/resourcePart
swagger-ui will use: http://localhost:8080/basePath/resourcePart

I would like to do something like this:
(...)
app.use(swaggerMetadata(swaggerDoc));
app.use(swaggerValidator());
app.use(swaggerRouter({
  controllers: './controllers'
});
swaggerDoc.basePath = '/samePrefixAsInExpress' + swaggerDoc.basePath;
app.use(swaggerUi(swaggerDoc));
(...)

@andrzejzysko I have found and resolved a similar issue myself.
Internal and External paths
The problem is that you have internal and external views of the paths.  As far as swagger-tools is concerned, it doesn't know it is actually being served under /foo/bar. The swagger-router just uses the paths from the swagger yaml as-is; i.e. handling an internal path of /basePath/resourcePart. But because of the url prefix, the true external path to request that path has /foo/bar pre-pended to it giving a full path of /foo/bar/basePath/resourcePath as you state.
Critically, the swaggerUI is created directly from the same yaml file (by default), and still without knowledge of the path prefix of /foo/bar.  So it also shows the exact paths that are in the yaml, but these are the internal paths, not the full external paths as needed for the browser to call them.
Equally, you can't just change the paths in the yaml file to be the full external paths to make the swaggerUI correct, as that would make the router wrong (and you end up with it only responding to an external path of /foo/bar/foo/bar/basePath/...).
Solution
The solution I came up with was:

Define the basePath in the swagger yaml as the full external base path: /foo/bar/basePath.

This allows the file to be shared with external groups correctly, and needs no knowledge of the actual implementation to build clients.

After the yaml is loaded, make a clone of the document object (_.cloneDeep(), or JSON.parse(JSON.stringify(...)), or just load the file again etc.)

This gives us 2 independent copies of the swagger definition object.
It must be a clone because we are going to change the basePath of one of them, and if it's just another reference to the same object then both references will point to the same modified object.

Modify the basePath in the cloned document to remove the prefix used by your mount point e.g remove /foo/bar.

This converts the external paths in your document, to the internal paths required by the router under the mount point.

Pass the cloned & modified swagger document as the first parameter to initializeMiddleware(clonedAndModifiedSwaggerDoc, ...)

This initializes the middleware (and router) with the version with the internal paths

Pass the unmodified, original swagger document to the swagger-ui middleware as the first parameter: swaggerUi(originalSwaggerDoc, ...)

This initializes the swagger-ui using the external paths so that the browser calls the correct path.
Although the swaggerUI docs don't mention it, you can see that first parameter to this middleware is indeed the swagger document object by looking at the code.

This gives you a working swagger-router using the internal paths needed because they are running behind a mount point, and a working swagger-ui using the external paths needed so that the browser can call the full path.
Example code
We use JSON file format for the swagger doc and an Express Router for the sub-application, but the general code is essentially (from memory, so may not be exact!):
const router = expresss.Router();

// Load swagger doc (file defined with full external paths)
const originalSwaggerDocWithExternalPaths = require('path/to/swagger.json');

// Clone the doc to allow us to make a version with _internal_ paths for most of the middleware
const clonedSwaggerDocWithInternalPaths = _.cloneDeep(originalSwaggerDoc);

// Remove the the first 8 chars from `basePath` to remove "/foo/bar"
clonedSwaggerDocWithInternalPaths.basePath = basePath.slice(8);

// Initialize swaggerTools middleware with the _internal_ paths version
swaggerTools.initializeMiddleware(clonedSwaggerDocWithInternalPaths, , function (middleware) {
  router.use(middleware.swaggerMetadata());

  // ...etc...

  // Serve the Swagger documents and Swagger UI using the _external_ paths version
  router.use(middleware.swaggerUi(originalSwaggerDocWithExternalPaths));
}

// Mount the router under "/foo/bar" to run as a sub-application
app.use('/foo/bar', router);

Hope this helps!


Kubernetes error while running the deploy command

Problem encountered on https://dotnet.microsoft.com/learn/aspnet/deploy-microservice-tutorial/deploy
Operating System: macos
Provide details about the problem you're experiencing. Include your operating system version, exact error message, code sample, and anything else that is relevant.
I get an error when I try to run the deployment using this command:
$ kubectl apply -f deploy-myMicroservice.yaml
Error:
error: unable to recognize "deploy-myMicroservice.yaml": no matches for kind "Deployment" in version "apps/v1beta1"

with aks 1.16 v1Beta api is deprecated please use this code.
apiVersion: apps/v1
kind: Deployment
metadata:

We deployed a fix to that page. Let us know if you're still having issues.


Can't install onto Laravel 10

This is my composer.json file (partial):
    "require": {
        "php": "^8.1",
        "ext-pdo": "*",
        "darkaonline/l5-swagger": "^8.5",
        "guzzlehttp/guzzle": "^7.2",
        "laravel/framework": "^10.8",
        "laravel/sanctum": "^3.2",
        "laravel/tinker": "^2.8",
        "maatwebsite/excel": "^3.1",
        "santigarcor/laratrust": "^8.2",
        "sentry/sentry-laravel": "^3.4",
        "spatie/laravel-activitylog": "^4.7",
        "tinify/tinify": "^1.6",
        "yajra/laravel-datatables": "^10.0"
    },

And this is the error I'm getting when trying to install v1.14.0:
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - beyondcode/laravel-websockets 1.14.0 requires react/http ^1.1 -> satisfiable by react/http[v1.1.0, ..., v1.9.0].
    - beyondcode/laravel-websockets[1.0.0, ..., 1.3.0] require php ^7.1 -> your php version (8.1.12) does not satisfy that requirement.
    - beyondcode/laravel-websockets[1.4.0, ..., 1.10.0] require php ^7.2 -> your php version (8.1.12) does not satisfy that requirement.
    - beyondcode/laravel-websockets[1.11.0, ..., 1.13.0] require guzzlehttp/psr7 ^1.5 -> found guzzlehttp/psr7[1.5.0, ..., 1.9.1] but the package is fixed to 2.5.0 (lock file version) by a partial update and that version does not match. Make sure you list it as
an argument for the update command.
    - beyondcode/laravel-websockets[1.13.1, ..., 1.13.2] require illuminate/broadcasting ^6.0|^7.0|^8.0|^9.0 -> found illuminate/broadcasting[v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27, v9.0.0, ..., v9.52.15] but these were not loaded, li
kely because it conflicts with another require.
    - react/http[v1.1.0, ..., v1.9.0] require psr/http-message ^1.0 -> found psr/http-message[1.0, 1.0.1, 1.1] but the package is fixed to 2.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the u
pdate command.
    - Root composer.json requires beyondcode/laravel-websockets * -> satisfiable by beyondcode/laravel-websockets[1.0.0, ..., 1.14.0].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require beyondcode/laravel-websockets:*" to figure out if any version is installable, or "composer require beyondcode/laravel-websockets:^2.1" if you know which you
need.

When I try to install latest, v2.0.0-beta.37, I get this:
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires beyondcode/laravel-websockets 2.0.0-beta.37 -> satisfiable by beyondcode/laravel-websockets[2.0.0-beta.37].
    - beyondcode/laravel-websockets 2.0.0-beta.37 requires illuminate/broadcasting ^6.3|^7.0|^8.0|^9.0 -> found illuminate/broadcasting[v6.3.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27, v9.0.0, ..., v9.52.15] but these were not loaded, likely b
ecause it conflicts with another require.

I also tried installing the dev-master:
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires beyondcode/laravel-websockets dev-master -> satisfiable by beyondcode/laravel-websockets[dev-master].
    - beyondcode/laravel-websockets dev-master requires doctrine/dbal ^2.9 -> found doctrine/dbal[v2.9.0, ..., 2.13.9] but the package is fixed to 3.6.2 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument
 for the update command.

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

Same problem for new created app.
step:

composer create-project laravel/laravel example-app
cd example-app && composer require beyondcode/laravel-websockets

Got
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - react/http[v1.1.0, ..., v1.9.0] require psr/http-message ^1.0 -> found psr/http-message[1.0, 1.0.1, 1.1] but the package is fixed to 2.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
    - beyondcode/laravel-websockets 1.14.0 requires react/http ^1.1 -> satisfiable by react/http[v1.1.0, ..., v1.9.0].
    - Root composer.json requires beyondcode/laravel-websockets ^1.14 -> satisfiable by beyondcode/laravel-websockets[1.14.0].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require beyondcode/laravel-websockets:*" to figure out if any version is installable, or "composer require beyondcode/laravel-websockets:^2.1" if you know which you need.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

I have the same problem, has anyone solved it?

Laravel 10.x is not supported, this package has no changes since 2022

I've installed succesfully with -W parameter

Oh, it looks like this package does not support the latest version of laravel :(

I do not want to use -W parameter, since it sounds a bit scary. Updating any dependency? No, thanks.
I solved it by using paid service, Pusher. For now.

Soketi also is a good option

me to :(
` composer require beyondcode/laravel-websockets
./composer.json has been updated
Running composer update beyondcode/laravel-websockets
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- beyondcode/laravel-websockets[1.14.0, ..., 1.14.1] require react/http ^1.1 -> satisfiable by react/http[v1.1.0, ..., v1.9.0].
- beyondcode/laravel-websockets[1.0.0, ..., 1.3.0] require php ^7.1 -> your php version (8.2.4) does not satisfy that requirement.
- beyondcode/laravel-websockets[1.4.0, ..., 1.10.0] require php ^7.2 -> your php version (8.2.4) does not satisfy that requirement.
- beyondcode/laravel-websockets[1.11.0, ..., 1.13.0] require guzzlehttp/psr7 ^1.5 -> found guzzlehttp/psr7[1.5.0, ..., 1.9.1] but the package is fixed to 2.6.1 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- beyondcode/laravel-websockets[1.13.1, ..., 1.13.2] require illuminate/broadcasting ^6.0|^7.0|^8.0|^9.0 -> found illuminate/broadcasting[v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27, v9.0.0, ..., v9.52.15] but these were not loaded, likely because it conflicts with another require.
- react/http[v1.1.0, ..., v1.9.0] require psr/http-message ^1.0 -> found psr/http-message[1.0, 1.0.1, 1.1] but the package is fixed to 2.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- Root composer.json requires beyondcode/laravel-websockets * -> satisfiable by beyondcode/laravel-websockets[1.0.0, ..., 1.14.1].
Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require beyondcode/laravel-websockets:*" to figure out if any version is installable, or "composer require beyondcode/laravel-websockets:^2.1" if you know which you need.
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
`

I also encounter that problem too
composer require beyondcode/laravel-websockets
Your requirements could not be resolved to an installable set of packages.
Problem 1
- beyondcode/laravel-websockets[1.14.0, ..., 1.14.1] require react/http ^1.1 -> satisfiable by react/http[v1.1.0, ..., v1.9.0].
- beyondcode/laravel-websockets[1.0.0, ..., 1.3.0] require php ^7.1 -> your php version (8.2.4) does not satisfy that requirement.
- beyondcode/laravel-websockets[1.4.0, ..., 1.10.0] require php ^7.2 -> your php version (8.2.4) does not satisfy that requirement.
- beyondcode/laravel-websockets[1.11.0, ..., 1.13.0] require guzzlehttp/psr7 ^1.5 -> found guzzlehttp/psr7[1.5.0, ..., 1.9.1] but the package is fixed to 2.6.1 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- beyondcode/laravel-websockets[1.13.1, ..., 1.13.2] require illuminate/broadcasting ^6.0|^7.0|^8.0|^9.0 -> found illuminate/broadcasting[v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27, v9.0.0, ..., v9.52.15] but these were not loaded, likely because it conflicts with another require.
- react/http[v1.1.0, ..., v1.9.0] require psr/http-message ^1.0 -> found psr/http-message[1.0, 1.0.1, 1.1] but the package is fixed to 2.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- Root composer.json requires beyondcode/laravel-websockets * -> satisfiable by beyondcode/laravel-websockets[1.0.0, ..., 1.14.1].
Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require beyondcode/laravel-websockets:*" to figure out if any version is installable, or "composer require beyondcode/laravel-websockets:^2.1" if you know which you need.

Same. Any updates?

use version 1.14.1

use version 1.14.1

worked for laravel 10 :+1:

I'm facing the same problem!!! Any updates?

I'm facing the same problem!!! Any updates?

use version 1.14.1

@Kweku-Sammy  it's not working. I tried this command but the error persists composer require beyondcode/laravel-websockets:1.14.1

same problem here

sam problem any help?

am using laravel v10.10

same problem
beyondcode/laravel-websockets[1.0.0, ..., 1.3.0] require php ^7.1 -> your php version (8.2.14) does not satisfy that requirement.

i already run composer require beyondcode/laravel-websockets:1.14.1
Error:
Problem 1
    - react/http[v1.1.0, ..., v1.9.0] require psr/http-message ^1.0 -> found psr/http-message[1.0, 1.0.1, 1.1] but the package is fixed to 2.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
    - beyondcode/laravel-websockets 1.14.1 requires react/http ^1.1 -> satisfiable by react/http[v1.1.0, ..., v1.9.0].
    - Root composer.json requires beyondcode/laravel-websockets 1.14.1 -> satisfiable by beyondcode/laravel-websockets[1.14.1].

@Kweku-Sammy it's not working. I tried this command but the error persists composer require beyondcode/laravel-websockets:1.14.1

try composer require beyondcode/laravel-websockets -W

It seems like v2 of this package does not support Laravel 10. To use Laravel 10 you need to use v1 of this package. It makes absolutely zero sense. Furthermore, the package seems to be abandoned by Beyond Code.  I hardly feel like this package is "done right."


Integrate chai-enzyme

Would this task involve removing karma from the testing flow? I see there is a mocha-loader for webpack[-dev-server] which I am trying to integrate now.

I really don't have a problem with Karma, so I'd like to keep it if we could (having never used something like jsdom) but if you have any arguments for scrapping it I'd love to hear them.

I'm trying to help mxstbr/react-boilerplate migrate from mocha/jsdom to Karma, and they already have chai-enzyme set up.
I can't figure out how to integrate chai-enzyme and karma. I'm not very knowledgeable when it comes to how require works, ES modules, karma plugins, etc. so I'd be interested to see if you are able to figure it out.
If you're interested take a look at the issue here: https://github.com/mxstbr/react-boilerplate/issues/79#issuecomment-174238581


Rate control refine to fit MAX bitrate requirement

review at:
https://rbcommons.com/s/OpenH264/r/888/

Archiving from https://rbcommons.com/s/OpenH264/r/888/

@sijchen Do you have a copy of this link, it's dead too  : (


Loop on Win32 to satisfy large random byte requests (as is done on Linux)

This change resolves a crash on Windows when using SystemRandomNumberGenerator and requesting a very large number (> ULONG_MAX) of random bytes.
In practice, it's unlikely anyone will be requesting more than 4GB of random bytes, but we don't abort on other platforms and nothing about the API suggests that a large buffer size is unsupported or disallowed.
I have not written a unit test because it would be impractical to request such a large amount of random data during a test run in CI.

Resolves #62130.

@swift-ci please test


fix: add lock in case of rent same ip

resolve #135

Already fixed it, I re-pushed image tag v2.2.1, so you can set deployment kubevpn-traffic-manager imagePullPolicy to always and restart pod, it will pull latest image v2.2.1. just update pod image is ok, not needs to update kubevpn client