AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / 问题

All perguntas(coding)

Martin Hope
Ξένη Γήινος
Asked: 2025-04-25 21:46:58 +0800 CST

Por que usar uma roda maior não torna minha peneira primária de fatoração de roda mais rápida?

  • 5

Presumo que todos vocês saibam o que são números primos e o que é o Crivo de Eratóstenes, então não vou perder tempo explicando-os.

Agora, todos os números primos, exceto 2, são números ímpares, então precisamos verificar apenas os números ímpares. Isso é muito óbvio, mas vale a pena mencionar porque essa otimização simples reduziu pela metade os candidatos que precisamos verificar, e então precisamos marcar apenas os múltiplos ímpares de números primos diferentes de 2.

Outra otimização simples é verificar apenas números até a raiz quadrada do limite, e outra otimização simples é marcar como números compostos o início no quadrado do número primo. Como os motivos para isso devem ser óbvios, não explicarei o porquê, embora eu não consiga pensar em outras otimizações relacionadas à marcação de números compostos.

Mas podemos restringir ainda mais o espaço de busca: todos os números primos, exceto 2, 3 e 5, devem ser congruentes a [1, 7, 11, 13, 17, 19, 23, 29]30%. Isso é evidente pela natureza do módulo. Existem apenas 30 possibilidades; se o módulo for par, o número é múltiplo de 2, e as outras possibilidades significam que o número é múltiplo de 3, múltiplo de 5 ou ambos. Em outras palavras, todos os números primos devem ser coprimos a 30, exceto 2, 3 e 5.

Em Python, isso é:

wheel3 = [i for i in range(1, 30) if math.gcd(i, 30) == 1]
# [1, 7, 11, 13, 17, 19, 23, 29]

Agora calculamos a diferença entre pares consecutivos de elementos, começando em 7, e 1 vem imediatamente depois de 29 devido à natureza da operação de módulo, por exemplo, 31 % 30 == 1e então a diferença entre eles é 2.

Obtemos o seguinte: [4, 2, 4, 2, 4, 6, 2, 6].

Agora, de cada 30 números, precisamos verificar apenas 8, pulando 22. Isso representa uma melhoria significativa em relação à otimização anterior, que aplicava força bruta apenas aos números ímpares. Precisávamos processar 15 números de cada 30 números se processássemos todos os números ímpares. Agora, temos 7 números a menos, e o espaço de busca é reduzido para 4/15, que é 0,2666...

Podemos otimizar isso ainda mais usando uma roda maior, usando 2 * 3 * 5 * 7 = 210 como base, todos os números primos começando em 11 devem ser coprimos com 210.

wheel4 = [i for i in range(1, 210) if math.gcd(i, 210) == 1]
wheel4 == [
    1  , 11 , 13 , 17 , 19 , 23 ,
    29 , 31 , 37 , 41 , 43 , 47 ,
    53 , 59 , 61 , 67 , 71 , 73 ,
    79 , 83 , 89 , 97 , 101, 103,
    107, 109, 113, 121, 127, 131,
    137, 139, 143, 149, 151, 157,
    163, 167, 169, 173, 179, 181,
    187, 191, 193, 197, 199, 209
]

E a lista de alterações de índice é:

[
    2 , 4 , 2 , 4 , 6 , 2 ,
    6 , 4 , 2 , 4 , 6 , 6 ,
    2 , 6 , 4 , 2 , 6 , 4 ,
    6 , 8 , 4 , 2 , 4 , 2 ,
    4 , 8 , 6 , 4 , 6 , 2 ,
    4 , 6 , 2 , 6 , 6 , 4 ,
    2 , 4 , 6 , 2 , 6 , 4 ,
    2 , 4 , 2 , 10, 2 , 10
]

Agora, de cada 210 números, precisamos processar apenas 48 números, em comparação com os 56 números anteriores, precisamos processar 8 números a menos, reduzindo o espaço de busca para 8/35, que é 0,22857142857142857... e menos de um quarto.

Então, espero que a versão que usa a roda baseada em 210 leve apenas 6/7 ou 85,71% do tempo que a versão baseada em 30 leva para ser executada, mas não é isso que acontece.

import math
import numpy as np
import numba as nb


@nb.njit(cache=True)
def prime_wheel_sieve(n: int) -> np.ndarray:
    wheel = [4, 2, 4, 2, 4, 6, 2, 6]
    primes = np.ones(n + 1, dtype=np.uint8)
    primes[:2] = False
    for square, step in ((4, 2), (9, 6), (25, 10)):
        primes[square::step] = False

    k = 7
    lim = int(math.sqrt(n) + 0.5)
    i = 0
    while k <= lim:
        if primes[k]:
            primes[k**2 :: 2 * k] = False

        k += wheel[i]
        i = (i + 1) & 7

    return np.nonzero(primes)[0]


# fmt: off
WHEEL4 = np.array([
    2 , 4 , 2 , 4 , 6 , 2 ,
    6 , 4 , 2 , 4 , 6 , 6 ,
    2 , 6 , 4 , 2 , 6 , 4 ,
    6 , 8 , 4 , 2 , 4 , 2 ,
    4 , 8 , 6 , 4 , 6 , 2 ,
    4 , 6 , 2 , 6 , 6 , 4 ,
    2 , 4 , 6 , 2 , 6 , 4 ,
    2 , 4 , 2 , 10, 2 , 10
], dtype=np.uint8)
# fmt: on


@nb.njit(cache=True)
def prime_wheel_sieve4(n: int) -> np.ndarray:
    primes = np.ones(n + 1, dtype=np.uint8)
    primes[:2] = False
    for square, step in ((4, 2), (9, 6), (25, 10), (49, 14)):
        primes[square::step] = False

    k = 11
    lim = int(math.sqrt(n) + 0.5)
    i = 0
    while k <= lim:
        if primes[k]:
            primes[k**2 :: 2 * k] = False

        k += WHEEL4[i]
        i = (i + 1) % 48

    return np.nonzero(primes)[0]
In [549]: np.array_equal(prime_wheel_sieve(65536), prime_wheel_sieve4(65536))
Out[549]: True

In [550]: %timeit prime_wheel_sieve(65536)
161 μs ± 1.13 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

In [551]: %timeit prime_wheel_sieve4(65536)
163 μs ± 1.79 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

In [552]: %timeit prime_wheel_sieve4(131072)
330 μs ± 10.6 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [553]: %timeit prime_wheel_sieve(131072)
328 μs ± 7.4 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [554]: %timeit prime_wheel_sieve4(262144)
680 μs ± 14.3 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [555]: %timeit prime_wheel_sieve(262144)
669 μs ± 7.79 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [556]: %timeit prime_wheel_sieve(524288)
1.44 ms ± 16.2 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [557]: %timeit prime_wheel_sieve4(524288)
1.48 ms ± 13.4 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [558]: %timeit prime_wheel_sieve4(1048576)
3.25 ms ± 81.3 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [559]: %timeit prime_wheel_sieve(1048576)
3.23 ms ± 115 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [560]: %timeit prime_wheel_sieve(2097152)
7.08 ms ± 80.9 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [561]: %timeit prime_wheel_sieve4(2097152)
7.1 ms ± 85.9 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [562]: %timeit prime_wheel_sieve4(4194304)
14.8 ms ± 120 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [563]: %timeit prime_wheel_sieve(4194304)
14.2 ms ± 145 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [564]: %timeit prime_wheel_sieve(8388608)
39.4 ms ± 1.44 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [565]: %timeit prime_wheel_sieve4(8388608)
41.7 ms ± 2.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

De acordo com meus testes, usar uma roda maior torna o código mais lento, e não mais rápido. Por que isso acontece? Teoricamente, usar uma roda maior estreita o espaço de busca, então não deveria aumentar o tempo de execução. Por que usar uma roda maior torna o código mais lento?


Ok, usando o método científico, controlei as diferenças entre as duas funções de modo que a única diferença entre elas, a única quantidade que pode afetar o desempenho, é a roda usada.

Fiz a primeira função usar o operador módulo em vez do AND bit a bit, e fiz a segunda função usar uma lista local, assim como a primeira. Eu queria separar código e dados, mas tudo bem.

@nb.njit(cache=True)
def prime_wheel_sieve3(n: int) -> np.ndarray:
    wheel = [4, 2, 4, 2, 4, 6, 2, 6]
    primes = np.ones(n + 1, dtype=np.uint8)
    primes[:2] = False
    for square, step in ((4, 2), (9, 6), (25, 10)):
        primes[square::step] = False

    k = 7
    lim = int(math.sqrt(n) + 0.5)
    i = 0
    while k <= lim:
        if primes[k]:
            primes[k**2 :: 2 * k] = False

        k += wheel[i]
        i = (i + 1) % 8

    return np.nonzero(primes)[0]


@nb.njit(cache=True)
def prime_wheel_sieve4_1(n: int) -> np.ndarray:
    # fmt: off
    wheel = [
        2 , 4 , 2 , 4 , 6 , 2 ,
        6 , 4 , 2 , 4 , 6 , 6 ,
        2 , 6 , 4 , 2 , 6 , 4 ,
        6 , 8 , 4 , 2 , 4 , 2 ,
        4 , 8 , 6 , 4 , 6 , 2 ,
        4 , 6 , 2 , 6 , 6 , 4 ,
        2 , 4 , 6 , 2 , 6 , 4 ,
        2 , 4 , 2 , 10, 2 , 10
    ]
    # fmt: on
    primes = np.ones(n + 1, dtype=np.uint8)
    primes[:2] = False
    for square, step in ((4, 2), (9, 6), (25, 10), (49, 14)):
        primes[square::step] = False

    k = 11
    lim = int(math.sqrt(n) + 0.5)
    i = 0
    while k <= lim:
        if primes[k]:
            primes[k**2 :: 2 * k] = False

        k += wheel[i]
        i = (i + 1) % 48

    return np.nonzero(primes)[0]

Tive que adicionar comentários de formatação para evitar que o Black Formatter bagunçasse minha tabela formatada no VS Code e, claro, isso não afeta o desempenho em nada.

As únicas diferenças entre as funções são o valor inicial de k, os primos que tiveram que ser processados ​​antes de girar a roda propriamente dita e, claro, o tamanho da roda (e a própria roda). Estes tiveram que ser diferentes (porque usam rodas diferentes), mas todo o resto permanece inalterado.

In [679]: np.array_equal(prime_wheel_sieve3(65536), prime_wheel_sieve4_1(65536))
Out[679]: True

In [680]: %timeit prime_wheel_sieve3(65536)
162 μs ± 2.27 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

In [681]: %timeit prime_wheel_sieve4_1(65536)
158 μs ± 1.83 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

In [682]: %timeit prime_wheel_sieve3(131072)
326 μs ± 7.91 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [683]: %timeit prime_wheel_sieve4_1(131072)
322 μs ± 8.89 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [684]: %timeit prime_wheel_sieve3(262144)
659 μs ± 7.74 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [685]: %timeit prime_wheel_sieve4_1(262144)
655 μs ± 12.2 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [686]: %timeit prime_wheel_sieve3(524288)
1.45 ms ± 14.1 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [687]: %timeit prime_wheel_sieve4_1(524288)
1.42 ms ± 8.13 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [688]: %timeit prime_wheel_sieve3(1048576)
3.2 ms ± 68.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [689]: %timeit prime_wheel_sieve4_1(1048576)
3.2 ms ± 199 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Curiosamente, prime_wheel_sieve4_1o desempenho é um pouco mais rápido que prime_wheel_sieve3, mas é só um pouquinho. A aceleração é insignificante, mas sei que o tempo de execução do código é estocástico por natureza, então prime_wheel_sieve4_1um desempenho consistentemente mais rápido que , prime_wheel_sieve3um pouquinho, é estatisticamente significativo. Embora eu não tenha testado muito, isso não exclui a possibilidade de coincidência.

Mas, de acordo com minha teoria, eu deveria ver uma redução de 14,29% no tempo de execução, e não basicamente nenhuma melhoria. Meus testes fortaleceram meu argumento.

Então por que usar uma roda maior não acelera o código?

python
  • 1 respostas
  • 74 Views
Martin Hope
Giuseppe Festa
Asked: 2025-04-25 21:42:07 +0800 CST

Problemas de assinante no ESP32 executando Micro-ros

  • 5

Estou trabalhando em um projeto micro-ROS usando o ESP32 conectado a um PC via serial (USB) a 921.600 bauds. Embora a funcionalidade de publicador funcione bem, quando adiciono um assinante, o ESP32 entra em um loop de erros constantemente no momento em que inicio o agente micro-ROS.

Este é o arquivo de inicialização e comando atual, onde outro nó de teste é executado para verificar a publicação e a assinatura

ros2 launch robot_launcher robot_launcher.launch.py

from launch import LaunchDescription
from launch.actions import ExecuteProcess, SetEnvironmentVariable
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        SetEnvironmentVariable('ROS_DOMAIN_ID', '0'),
        Node(
            package='micro_ros_agent',
            executable='micro_ros_agent',
            name='micro_ros_agent',
            output='screen',
            arguments=[
                'serial',
                '--dev', '/dev/ttyACM0',
                '--baudrate', '921600',
            ],
        ),        
        Node(
            package='robot_launcher',
            executable='angle_listener',
            name='angle_listener',
            output='screen',
        ),
    ])


Configurar

  • Microcontrolador ESP32 (ambiente esp32 rebaixado para 2.0.2 para resolver problemas de compatibilidade com microros)
  • Agente micro-ROS em execução no PC (Ubuntu 22.04)
  • Nó Python ROS2 ( angle_listener.py) que assina dados do codificador e publica comandos de velocidade
  • Conexão serial via USB (UART0) a 921600 baud
  • A configuração é apenas um teste, então algumas das soluções (como as matrizes unidimensionais de tamanho 1 por causa de N_MOTORS) são para escalar o código até 6 motores posteriormente

Limitação de hardware

Minhas capacidades de depuração são limitadas porque a porta serial de hardware que estou usando para comunicação USB (UART0) é a única disponível na placa que estou usando. Isso significa que não posso adicionar instruções Serial.print para depuração.

Código

Trecho de código ESP32 (C++):

#include <Wire.h>
#include <AS5600.h>
#include <TMCStepper.h>


#include <micro_ros_arduino.h>
#include <AccelStepper.h>

#include <std_msgs/msg/float64.h>

#include <stdio.h>
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>

#include <std_msgs/msg/int32.h>

float a2s(float angular_velocity_rad_s);

#define RCCHECK(fn)                                                    \
  {                                                                    \
    rcl_ret_t rc = fn;                                                 \
    if (rc != RCL_RET_OK) {                                            \
      Serial.print(F("ERROR at "));                                    \
      Serial.print(F(#fn));                                            \
      Serial.print(F(": "));                                           \
      Serial.println(rcl_get_error_string().str);                      \
      error_loop();                                                    \
    }                                                                  \
  }
#define RCSOFTCHECK(fn) \
  { \
    rcl_ret_t temp_rc = fn; \
    if ((temp_rc != RCL_RET_OK)) {} \
  }

#define MICROSTEP 64
#define STEPS_PER_REV 200.0
#define LED_PIN 14
// Pin definitions
#define CLK_PIN 18
#define PDN_UART_PIN 16
#define SPREAD_PIN 17

#define DIR1_PIN 4
#define STEP1_PIN 13

#define DIR2_PIN 32
#define STEP2_PIN 25


#define N_MOTOR 1

#define SERIAL_PORT Serial2
#define UART_RX_PIN 16        // PDN_UART used as UART RX
#define UART_TX_PIN 17        // SPREAD used as UART TX (optional)
#define DRIVER_ADDRESS1 0b00  // Driver address (if multiple drivers on UART)
#define DRIVER_ADDRESS2 0b01

#define R_SENSE 0.11f
#define DRIVER_CURRENT 1000  // mA, adjust based on your motor



rcl_subscription_t subscriber;
std_msgs__msg__Float64 sub_msg;
float motor_velocities[N_MOTOR] = {0.0f};

AccelStepper motors[N_MOTOR] = {
  AccelStepper(AccelStepper::DRIVER, STEP1_PIN, DIR1_PIN),
  // … fino a 6
};


TMC2209Stepper drivers[N_MOTOR]={
  TMC2209Stepper(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS1)
};


void error_loop() {
  while (1) {
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));
    delay(100);
  }
}


rcl_publisher_t publisher;
std_msgs__msg__Int32 msg;
rclc_executor_t executor;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;
rcl_timer_t timer;

#define MULTIPLEXER_ADDR 0x70

#define ENCODER_PUBLISH_TIME 20  //ms
TwoWire &i2cBus = Wire;

// Classe per multiplexer PCA9548A
class PCA9548A {
public:
  PCA9548A(uint8_t address, TwoWire &wire = Wire)
    : _addr(address), _wire(wire) {}

  void begin() {
    _wire.begin();
  }

  void selectChannel(uint8_t channel) {
    if (channel > 7) return;
    _wire.beginTransmission(_addr);
    _wire.write(1 << channel);
    _wire.endTransmission();
  }

private:
  uint8_t _addr;
  TwoWire &_wire;
};

PCA9548A mux(MULTIPLEXER_ADDR, Wire);
AS5600 encoder(&i2cBus);



void timer_callback(rcl_timer_t *timer, int64_t last_call_time) {
  RCLC_UNUSED(last_call_time);
  if (timer != NULL) {
    int32_t angle = encoder.readAngle();
    msg.data = angle;
    RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
  }
}
void velocity_callback(const void * msgin) {
  // Cast the incoming pointer to a Float64 message
  const auto *incoming = (const std_msgs__msg__Float64 *)msgin;
  float vel = incoming->data;                     // get the single float

  motor_velocities[0] = vel;                      // assuming N_MOTOR == 1
  motors[0].setSpeed(a2s(motor_velocities[0]));   // update stepper speed
}
void setup() {
  Serial.begin(921600);
  SERIAL_PORT.begin(115200, SERIAL_8N1, UART_RX_PIN, UART_TX_PIN);
  delay(500);

  for(int i=0; i<N_MOTOR;i++){
    drivers[i].begin();
    drivers[i].toff(5);
    drivers[i].rms_current(DRIVER_CURRENT);
    drivers[i].microsteps(MICROSTEP);
    drivers[i].en_spreadCycle(false);  // StealthChop

    motors[i].setMaxSpeed(a2s(100));
  }


  set_microros_transports();

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

  delay(100);

  allocator = rcl_get_default_allocator();

  //create init_options
  RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));

  // create node
  RCCHECK(rclc_node_init_default(&node, "ESP32_node", "", &support));

  // create publisher
  RCCHECK(rclc_publisher_init_default(
    &publisher,
    &node,
    ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
    "axis_1_encoder"));

  // create timer,
  RCCHECK(rclc_timer_init_default(
    &timer,
    &support,
    RCL_MS_TO_NS(ENCODER_PUBLISH_TIME),
    timer_callback));

   // ### 2. initialize subscriber message
  RCCHECK(std_msgs__msg__Float64__init(&sub_msg));

  // 3. create subscriber
  RCCHECK(rclc_subscription_init_default(
    &subscriber,
    &node,
    ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Float64),
    "motor_velocity_1"      // rename topic as you wish
  ));

  // create executor
  RCCHECK(rclc_executor_init(&executor, &support.context, 2, &allocator));

  RCCHECK(rclc_executor_add_timer(&executor, &timer));

    // 4. add subscription to executor
  RCCHECK(rclc_executor_add_subscription(
    &executor,
    &subscriber,
    &sub_msg,
    &velocity_callback,
    ON_NEW_DATA
  ));

  mux.begin();
  mux.selectChannel(0);

  encoder.begin();
}


void loop() {
  // Gestione micro-ROS
  rclc_executor_spin_some(&executor, RCL_MS_TO_NS(20));
  for (int i = 0; i < N_MOTOR; i++) {
    motors[i].runSpeed();
  }
}


float a2s(float angular_velocity_rad_s) {
  // steps_per_rev is typically 200 for 1.8°/step motors
  float rev_per_sec = angular_velocity_rad_s / (2.0f * M_PI);
  float steps_per_sec = rev_per_sec * STEPS_PER_REV * MICROSTEP;
  return steps_per_sec;
}


Nó Python:

import rclpy
from rclpy.node import Node
from std_msgs.msg import Int32, Float64  # use Float64 instead of Float64MultiArray

class Listener(Node):

    def __init__(self):
        super().__init__("angle_listener")

        # publisher for a single float64
        self.velocity_publisher = self.create_publisher(
            Float64, 
            "motor_velocity_1", 
            10
        )

        # subscriber as before
        self.subscriber = self.create_subscription(
            Int32, 
            "axis_1_encoder", 
            self.angle_callback, 
            10
        )
        self.get_logger().info("Subscribed to encoder topic")

    def angle_callback(self, message):
        # log incoming value
        self.get_logger().info(f"Received encoder: {message.data}")

        # build and publish single Float64 with value 2.0
        vel_msg = Float64()
        vel_msg.data = 2.0
        self.velocity_publisher.publish(vel_msg)
        self.get_logger().info("Published velocity: 2.0")

def main(args=None):
    rclpy.init(args=args)
    node = Listener()
    rclpy.spin(node)
    rclpy.shutdown()

if __name__ == "__main__":
    main()

Comportamento

  1. O ESP32 funciona corretamente apenas com o publicador (dados do codificador)
  2. Quando adiciono o código do assinante, o ESP32 entra imediatamente na função de loop de erro
  3. O loop de erro é acionado pela falha de uma das macros RCCHECK

O que eu tentei

  • Os nomes dos tópicos verificados correspondem entre o ESP32 e o nó Python
  • Verifiquei se os tópicos foram inicializados corretamente
  • Aumento do tempo de rotação no esp32 para garantir que o problema não esteja relacionado à CPU

O que pode estar fazendo com que o ESP32 entre no loop de erro ao adicionar um assinante? Qualquer ajuda seria muito apreciada!

python
  • 1 respostas
  • 20 Views
Martin Hope
Ralf_Reddings
Asked: 2025-04-25 21:20:04 +0800 CST

Impedir que a tecla de atalho <modificador> e <tecla> sejam disparadas se a <tecla> já estiver pressionada?

  • 5

Tenho um problema que não consegui resolver de forma elegante. Forneci o código abaixo como um exemplo reproduzível.

Se eu acionar shift+ f23, soltar shift, mas ainda mantendo pressionado f23; se eu pressionar control, control+ f23dispara. Não estou esperando esse comportamento e é indesejado. Não quero que control+ f23dispare se f23já estiver pressionado.

<^f23::
tooltip ctrl and f23 down
KeyWait, f23
tooltip ctrl and f23 up
return

<+f23::
tooltip shift and f23 down
KeyWait, f23
tooltip shift and f23 up
return

Tenho muitas teclas de atalho como as acima ( <^f1... <^f22,, etc etc), então estou procurando uma solução única para todos.

autohotkey
  • 1 respostas
  • 55 Views
Martin Hope
Markus-Hermann
Asked: 2025-04-25 20:34:41 +0800 CST

O tkinter.Listbox tem uma "seleção de sombra" ao lado da seleção adequada. Como sincronizar ambos?

  • 6

Criei e preenchi um tkinter.Listbox. Agora tenho eventos que selecionarão o item no índice index. Assim:

listbox.selection_clear(0, tk.END)
listbox.select_set(index)

E funciona porque a entrada com índice indexé de fato selecionada.

No entanto, ao usar as teclas "tab" para navegar até outros widgets que também têm o poder de selecionar itens naquela caixa de listagem e, em seguida, retornar à caixa de listagem, há uma seleção de sombra , que parece não ser a âncora (pelo menos, listbox.selection_anchor(index) não resolveu o problema para mim) na seleção que estava ativa quando deixei o foco nela pela última vez listbox. Usar as teclas "para cima" e "para baixo" assumirá o controle da seleção ativa. No entanto, elas não começarão na seleção correta ( 010_adfno exemplo abaixo), mas naquela sombra ( 007_adf) que só posso especificar mais detalhadamente fornecendo esta captura de tela:

insira a descrição da imagem aqui

Fig.: A "sombra" em questão está ao redor da entrada 007_adf. A seleção correta é 010.adf. Como sincronizar a sombra com a seleção correta?

python
  • 2 respostas
  • 49 Views
Martin Hope
Shiela
Asked: 2025-04-25 20:11:13 +0800 CST

Como obter o nome exato da equipe usando Application.VLookup

  • 5

Folha1

Folha 1 img

Erro durante a inicialização:

erro

O que deve ser corrigido no código abaixo para obter o nome exato da equipe preenchido no Me.cmbTeam.Value (combobox) se o membro da equipe estiver correspondendo na coluna 2.

Private Sub UserForm_Initialize()
    Me.cmbDev.Value = "Nory"

    Dim ws As Worksheet: Set ws = Worksheets("Sheet1")
    Dim i As Long
    Dim arr: arr = ws.Range("B1").CurrentRegion.Value
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim teamName As Variant

    For i = 2 To UBound(arr)
        dict(arr(i, 2)) = Empty
    Next
   ' ***
   
    If dict.exists(Me.cmbDev.Value) Then
        teamName = Application.VLookup(Me.cmbDev.Value, ws.Range("B1").CurrentRegion.Value, 1, False)
        Me.cmbTeam.Value = teamName 'should get a result of George
    Else
        Me.cmbDev.Value = ""
        Me.cmbTeam.Value = ""
    End If

End Sub
excel
  • 1 respostas
  • 67 Views
Martin Hope
KBriggs
Asked: 2025-04-25 19:51:20 +0800 CST

Evitando o cache desnecessário de dados ao usar o memmap numpy

  • 6

Tenho um programa que lê arquivos binários muito grandes (~100 GB-TB) em blocos usando numpy memmap. O programa faz uma única passagem pelos dados, então não há necessidade de armazenar nada em cache, já que nunca há necessidade de voltar e reler, mas, np.memmappor padrão, armazena os dados em cache. Como resultado, o uso de RAM satura rapidamente, mesmo sem haver necessidade real disso.

Existe alguma maneira de desativar o cache de dados ou, caso contrário, limpar o cache manualmente? Encontrei alguns outros tópicos sobre o assunto que sugerem que a única maneira é excluir todas as referências a flushele memmap, executar o coletor de lixo e recriar o arquivo memmapdo zero, o que funciona, mas obviamente não é o ideal. Posso fazer melhor?

Aqui está um MWE que demonstra o problema (observe que ele criará 2 GB de lixo aleatório no seu HDD se você executá-lo). Como você pode ver, o uso de RAM reflete a quantidade cumulativa de dados carregados, mesmo que seja chunk_sizepequena. Idealmente, o uso de RAM seria limitado à quantidade de dados contidos em um único bloco.

import numpy as np
import os
import psutil
import gc
import time

# Parameters
filename = 'test_memmap.bin'
file_size_gb = 2  # Change this if needed
dtype = np.float32
element_size = np.dtype(dtype).itemsize
num_elements = (file_size_gb * 1024**3) // element_size
chunk_size = 1_000_000  # Number of elements to read at once

# Step 1: Create a large binary file
if not os.path.exists(filename):
    print("Creating file...")
    with open(filename, 'wb') as f:
        f.write(np.random.rand(num_elements).astype(dtype).tobytes())

# Step 2: Process file using memmap in chunks
print("Processing with memmap...")
mm = np.memmap(filename, dtype=dtype, mode='r')
process = psutil.Process(os.getpid())

for i in range(0, len(mm), chunk_size):
    chunk = mm[i:i+chunk_size]
    # Simulate processing
    chunk.sum()
    
    # Monitor RAM usage
    mem = process.memory_info().rss / (1024 ** 2)  # in MB
    print(f"Step {i // chunk_size + 1}, RAM usage: {mem:.2f} MB")
del mm
gc.collect()
time.sleep(5) #os takes a second to catch up
mem = process.memory_info().rss / (1024 ** 2)  # in MB
print(f"Final RAM usage after deleting memmap: {mem:.2f} MB")
python-3.x
  • 1 respostas
  • 38 Views
Martin Hope
Stephen Clark
Asked: 2025-04-25 19:41:12 +0800 CST

Alterar a cor do texto que rotula um bloco no ggplot2

  • 6

Esta pergunta é uma continuação desta ( Mensagem de aviso: 2 linhas contendo valores ausentes foram removidas (`geom_tile()`) ). Alguns dias são fins de semana e gostaria de comunicar isso no gráfico. No momento, codifiquei os valores de fim de semana com um número negativo e alterei a escala para que aparecessem em azul. Não tenho certeza se é isso que eu quero. O ideal seria que os fins de semana tivessem o mesmo valor positivo, mas talvez um texto com uma cor diferente (branco em vez de preto) e/ou uma borda ao redor do bloco. Tenho uma coluna booleana que me informa se são fins de semana. Talvez haja uma visualização melhor que possa identificar os dias de fim de semana?

hours <- c(16, 17, 0, 1, 2, 21, 22, 9, 19, 20)
days <- c(0, 0, 3, 3, 3, 6, 6, 11, 21, 21)
value <- c(3, 60, -18, -60, -23, 51, 48, 49, 47, 40)
weekend<- c(FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE)

df <- data.frame(hours, days, value, weekend)

h<-1
w<-1

ggplot(df, aes(days, hours)) +
  geom_tile(aes(fill = value, width = w, height = h)) +
  geom_text(aes(label = value), size = 3) +
  scale_fill_continuous(limits=c(-60,60),breaks=seq(-60,60,20),low = "blue", high = "red") +
  xlab("Day") +
  ylab("Hour") +
  scale_x_continuous(
    breaks = seq(0, 41, by = 7),
    expand = c(0.05, 0.05)
  ) +
  scale_y_continuous(
    breaks = seq(0, 23, by = 3),
    expand = c(0.05, 0.05)
  ) +
  coord_cartesian(xlim=c(0,41),ylim=c(0,23))

Responder:

hours <- c(16, 17, 0, 1, 2, 21, 22, 9, 19, 20)
days <- c(0, 0, 3, 3, 3, 6, 6, 11, 21, 21)
value <- c(3, 60, 18, 60, 23, 51, 48, 49, 47, 40)
weekend<- c("black","black","white","white","white","black","black","black","black","black")

df <- data.frame(hours, days, value, weekend)

h<-1
w<-1

ggplot(df, aes(days, hours)) +
    geom_tile(aes(fill = value, width = w, height = h)) +
    geom_text(aes(label = value), size = 4, colour=weekend) +
    scale_fill_continuous(limits=c(0,60),breaks=seq(-0,60,10),low = "white", high = "red") +
    xlab("Day") +
    ylab("Hour") +
    scale_x_continuous(
        breaks = seq(0, 41, by = 7),
        expand = c(0.05, 0.05)
    ) +
    scale_y_continuous(
       breaks = seq(0, 23, by = 3),
       expand = c(0.05, 0.05)
    ) +
    coord_cartesian(xlim=c(0,41),ylim=c(0,23))
  • 1 respostas
  • 37 Views
Martin Hope
Shehara Nayanananda
Asked: 2025-04-25 19:12:48 +0800 CST

A navegação Typesafe trava com IllegalStateException: você deve chamar setGraph() antes de chamar getGraph()

  • 7

Este é meu primeiro aplicativo para Android. Atualmente, estou trabalhando na parte de navegação. O problema é que, sempre que clico IconButtonpara navegar para a tela Adicionar Notas, o aplicativo trava com esta exceção:

java.lang.IllegalStateException: You must call setGraph() before calling getGraph()

Na minha MainActivity, tenho este código:

val navController = rememberNavController()

NavHost(
    navController = navController,
    startDestination = Home,
) {
    composable<Home> {
        TopBar()
    }
    composable<AddNote> {
        // add Notes here
    }
}

E estes são os destinos de navegação que eu uso:

@Serializable
object Home

@Serializable
object AddNote

Esta é uma versão condensada da minha TopBar para onde desejo navegar AddNotequando o botão for clicado:

@Composable
fun TopBar() {
    //navigate through screens
    val navController = rememberNavController()

    // IconButton to handle the add note action
    IconButton(onClick = { navController.navigate(AddNote) }) {
        Icon(
            imageVector = Icons.Rounded.Add,
            contentDescription = "Add Note",
        )
    }
}
  • 2 respostas
  • 58 Views
Martin Hope
Martin Brown
Asked: 2025-04-25 19:01:52 +0800 CST

Falha no gráfico de dispersão XY do Excel

  • 5

Às vezes, o Excel se recusa terminantemente a criar gráficos de dispersão XY corretamente. Adota um formato padrão que plota linhas como linhas com legendas "série 1", "série 2" e "série 3", apesar de identificar os cabeçalhos das colunas, que ele cola no eixo X! A ideia era ser um gráfico de dispersão XY com pontos unidos por retas (foi o que foi selecionado), mas não foi entregue.

O problema que vejo intermitentemente parece estar possivelmente relacionado a este tópico anterior sobre gráficos de dispersão XY, onde o eixo X é, na verdade, um formato de tempo em tempo . Mas não vejo razão para que isso se aplique aqui. Os dados são todos claramente números inteiros.

Sei que se títulos ou dados estiverem malformados (contiverem NANs, INFS ou espaços em branco), isso acontecerá (justo). Mas às vezes, o erro ocorre sem motivo aparente quando são fornecidos dados numéricos perfeitamente válidos. Este é um exemplo particularmente pequeno que encontrei hoje, reduzido a um MRE que ainda falha. Normalmente, há muito mais colunas e linhas. Apresentado abaixo como um arquivo CSV:

log2N,N,valid,solutions
3,8,35,10
4,16,1365,119
5,32,31465,852

Se você copiar e colar este conjunto de dados aparentemente inocente no Excel e selecioná-lo, tente plotar o gráfico XY de N, soluções válidas e versus Log2N, e ele fará aquele gráfico insano e inútil. Na verdade, ele só fará um gráfico de dispersão XY adequado se você selecionar as colunas A e B para Log2Ne N. Uma vez que o formato correto do gráfico XY seja estabelecido, ele permitirá que o intervalo de dados seja expandido. Selecione os dados do gráfico e edite "=Sheet1!$A$1:$B$4"para, "=Sheet1!$A$1:$D$4"e o formato permanece como XY, mas isso é um PITA.

insira a descrição da imagem aqui

Estou usando o Excel 2021 MS Office Pro. Ele se identifica como: Microsoft® Excel® 2021 MSO (Versão 2503 Build 16.0.18623.20178) 64 bits

Tenho observado esse comportamento em todas as versões recentes do Excel desde 2007. Esta é apenas a primeira vez que encontro um pequeno MRE em que o comportamento se manifesta tão claramente. Acredito que seja um bug nas suposições do Excel sobre dados acionados pela faixa dinâmica, mas ficaria muito grato se alguém pudesse encontrar uma maneira de contornar esse problema para que a criação de gráficos de dispersão XY funcionasse corretamente em qualquer seleção de dados numéricos válidos, tratando a primeira coluna como o eixo X e a primeira linha como legendas para as linhas do gráfico.

Ou se for reproduzível e for um bug, como reportá-lo à MS para que seja corrigido.

Embora eu tenha uma solução alternativa, prefiro uma solução permanente. Se houver algo sutilmente incorreto nos meus dados que eu não tenha percebido, por favor, aponte. Obrigado.

excel
  • 1 respostas
  • 44 Views
Martin Hope
Daniel
Asked: 2025-04-25 19:00:15 +0800 CST

Compilador React 19 e funções inline em jsx

  • 5

Atualmente, estou atualizando meu código-base para o React 19 e usando o compilador. Tradicionalmente, as funções de seta inline no React no JSX eram consideradas práticas ruins por questões de desempenho. No entanto, estou tentando encontrar confirmação se o compilador do React lidará com esse caso de uso agora e se posso usar funções inline com segurança.

por exemplo, anteriormente eu poderia ter feito algo assim:

const testFunction = useCallback(() => {
    doSomething(id)
  }, [id])

  <Button onClick={testFunction} />

mas isso pode agora ser simplificado para:

<Button onClick={() => doSomething(id)} />

sem afetar o desempenho.

Alguém sabe se o compilador agora suporta funções de seta inline? Gostaria especialmente de saber se alguém que tenha trabalhado no compilador pode confirmar.

Fiz algumas pesquisas no Google e li os documentos, mas não encontrei nenhuma confirmação explícita sobre isso.

javascript
  • 1 respostas
  • 54 Views
Prev
Próximo

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve