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 / user-4696802

Zebrafish's questions

Martin Hope
Zebrafish
Asked: 2025-04-28 21:58:16 +0800 CST

Por que o Windows permite que sua GPU use apenas metade da sua RAM?

  • 5

A seguir está o que o visualizador de recursos do Vulkan mostra para meu computador:

MEMORY HEAP 0
    DEVICE SIZE 8321499136
    FLAGS
        DEVICE_LOCAL_BIT
        MULTI_INSTANCE_BIT

    MEMORY TYPE 0
        DEVICE_LOCAL_BIT
    MEMORY TYPE 1
        DEVICE_LOCAL_BIT

MEMORY HEAP 1
    DEVICE SIZE 16760438784
    FLAGS
    NONE

    MEMORY TYPE 0
        HOST_VISIBLE_BIT
        HOST_COHERENT_BIT
    MEMORY TYPE 0
        HOST_VISIBLE_BIT
        HOST_COHERENT_BIT

O heap 0 é o meu dispositivo de GPU, que tem 8 GB. O heap 1 deveria ser a RAM da minha CPU. Tenho 32 GB e é isso que aparece no meu gerenciador de tarefas no Windows, mas apenas metade disso (16 GB) aparece na descrição do heap de memória Vulkan com o Vulkan. Pesquisei o motivo disso e encontrei na página "Calculando Memória Gráfica" na página da Microsoft:

Antes que o VidMm possa reportar uma conta precisa aos clientes, ele precisa primeiro calcular a quantidade total de memória gráfica. O VidMm usa os seguintes tipos de memória e fórmulas para calcular os números de memória gráfica:

Memória total do sistema

This value is the total amount of system memory accessible to the operating system. Memory that the BIOS allocates doesn't appear in this number. For example, a computer with a 1 GB DIMM (1,024 MB) that has a BIOS that reserves 1 MB of memory appears to have 1,023 MB of system memory.

Memória total do sistema disponível para uso gráfico

This value is the total amount of system memory that is dedicated or shared to the GPU. This number is calculated as follows:
C++ 

TotalSystemMemoryAvailableForGraphics = MÁX.((TotalSystemMemory / 2), 64 MB)

O link está aqui .

Eu estava me perguntando por que isso acontece. Só metade da sua RAM está disponível para uso com Vulkan e DirectX, ou API gráfica? Aparentemente é isso que o VidMm informa. Não sei o que é o VidMm, mas o DirectX ou o Vulkan consultam isso para ver quanta memória está disponível, e sempre informam apenas metade da sua RAM?

No meu caso, tenho uma GPU dedicada com 8 GB, que é informada corretamente, e a RAM do sistema é informada como METADE do que eu realmente tenho, 32 GB dividido por 2. O que aconteceria se fosse uma iGPU? O dispositivo só conseguiria usar metade dessa memória do sistema? Ou seja, apenas metade da memória do dispositivo conseguiria ser usada? Isso só acontece no Windows e agora em outros sistemas operacionais?

windows
  • 1 respostas
  • 38 Views
Martin Hope
Zebrafish
Asked: 2025-04-27 06:23:28 +0800 CST

Ainda é uma condição de corrida se dois acessos estiverem separados por um período de tempo muito longo? [duplicado]

  • 5
Esta pergunta já tem respostas aqui :
Como resolver a condição de corrida? (3 respostas)
Fechado há 21 horas .

Os exemplos dados de por que condições de corrida ocorrem são que uma thread pode acessar memória que não é a versão mais recente porque outra thread pode tê-la modificado ou estar modificando-a ao mesmo tempo. Portanto, protegemos áreas de memória com primitivas de sincronização ou variáveis ​​atômicas. O que eu quero saber é se a seguinte afirmação é verdadeira:

Sempre que mais de um thread acessa o mesmo local de memória de um único processo, ele DEVE, em todas as circunstâncias, ser sincronizado explicitamente.

Por explicitamente, quero dizer coisas como um mutex ou uma variável atômica, uma barreira ou algo assim. É esse o caso? A razão pela qual pergunto isso é porque, quando são dados exemplos de por que precisamos de sincronização entre threads, sempre se trata de threads acessando uma área da memória em um curto período de tempo, e a explicação geralmente é algo como "não sabemos se a Thread 2 verá o valor escrito pela Thread 1". No entanto, considere o seguinte:

int some_global_var = 0; // INITIALIZED BEFORE STARTUP

Thread 1:

some_global_var = 1;

Thread 2:

sleep_for(/* 5 days */);
print("%d", some_global_var);

Esta ainda é uma condição de corrida e deve ser sincronizada, certo? Em outras palavras, a regra é simples: se for acessado por mais de uma thread em um processo, sem ifs, ands ou buts, você DEVE usar variável atômica ou mutex?

c++
  • 1 respostas
  • 143 Views
Martin Hope
Zebrafish
Asked: 2025-04-15 22:12:26 +0800 CST

Alguém pode explicar o que o ccache faz? [duplicado]

  • 1
Esta pergunta já tem respostas aqui :
quando é o caso de usar ccache? (3 respostas)
Fechado ontem .

É explicado como:

Ccache é um cache de compilador. Ele acelera a recompilação armazenando em cache compilações anteriores e detectando quando a mesma compilação está sendo executada novamente.

Não entendi. Quando uso um sistema de compilação como Ninja ou Makefiles e, por exemplo, altero um arquivo-fonte, o sistema de compilação já registra quais arquivos são dependências de quais unidades de tradução e evita recompilar essas unidades de tradução com base nessas informações, o que, até onde sei, eu descreveria como cache. Além disso, notei que, quando altero uma unidade de tradução, ele não apenas evita recompilar todas as unidades de tradução em arquivos-objeto novamente, mas também, de alguma forma (não sei como), evita vincular tudo novamente ao executável, de modo que, em um projeto muito grande, posso alterar o código em uma unidade de tradução, recompilar e tudo estará pronto para ser executado novamente em 2 segundos no meu rápido computador multi-core.

O que o ccache faz além disso, explique com exemplos concretos como "ele armazena em cache partes x, y, z do seu código".

c++
  • 2 respostas
  • 132 Views
Martin Hope
Zebrafish
Asked: 2025-04-11 17:12:01 +0800 CST

Se eu criar uma biblioteca estática que chama uma função que não está definida, preciso também compilar ou vincular outra biblioteca ou arquivo?

  • 5

Perguntei a um LLM online e ele disse:

Sim, com certeza. Você precisa vincular à biblioteca de dependências mesmo ao criar uma biblioteca estática que chama funções dentro dela.

Mas tentei construir uma biblioteca estática que chama outra função, e tudo o que fiz foi incluir o cabeçalho e, em seguida, chamar a função. Ela foi construída no Linux com GCC, sem nenhuma reclamação sobre referência indefinida ou algo do tipo.

Digamos:

MinhaBibliotecaEstática:

#include "MyExternalFunction.h"

void my_static_library_function()
{
     MyExternalFunction();
}

O compilado acima funciona bem, sem reclamações do compilador.

Então eu crio um executável, main:

void my_static_library_function();

int main()
{
    my_static_library_function();
    return 0;
}

Vinculei o executável principal à minha biblioteca estática (obviamente, porque chamo a função dela) e ENTÃO ele reclama que MyExternalFunction não está definido, então o EXECUTABLE precisa vincular essa função. Mas não a biblioteca estática. Portanto, a biblioteca estática não precisa vincular as funções que chama. E quanto a outros símbolos, como variáveis? É a mesma coisa? Uma biblioteca estática NUNCA PRECISA vincular nada, ela só precisa de declarações?

O que me levou a perguntar isso é que estou construindo uma biblioteca estática (libcurl) e estou me perguntando se essa biblioteca precisa apenas do diretório include para MBedTLS (o backend da biblioteca SSL) para ser compilada.

c++
  • 1 respostas
  • 100 Views
Martin Hope
Zebrafish
Asked: 2025-04-09 15:53:35 +0800 CST

Por que std::floor não é encontrado ao incluir <math.h> em C++23 no Android?

  • 8

Isso parece ser apenas uma pequena peculiaridade que eu poderia corrigir simplesmente incluindo <cmath>onde std::flooré usado, mas ainda assim é estranho e gostaria de saber se alguém sabe o que está acontecendo. Tenho um projeto que consigo compilar em MSVC, GCC e Clang em C++20 e C++23, sem problemas. No Android Studio, consigo compilar em C++20, mas se eu definir o padrão C++20 na minha configuração do CMake, recebo o erro:

erro: nenhum membro chamado 'floor' no namespace 'std'

No lugar onde preciso, incluo <math.h>, o que funcionou bem para todas as outras configurações de compilação. Acho que o math inclui <cmath>. De qualquer forma, posso fazer o erro desaparecer incluindo TAMBÉM <cmath>onde preciso, mas há algum motivo para isso acontecer na compilação do Android com C++23? Tipo, eu já tenho:

#include <math.h>

E com o C++23 no Android Studio eu literalmente tenho que incluir:

#include <cmath>

Para std::floorser reconhecido, as funções estão comentadas. Parece estranho.

c++
  • 3 respostas
  • 166 Views
Martin Hope
Zebrafish
Asked: 2025-04-08 12:40:06 +0800 CST

Por que não tenho um config.toml padrão?

  • 5

Então, eu queria definir o número de tarefas que o compilador Rust usa, e ouvi dizer que deveria estar em config.toml. Além disso, config.toml deveria estar em:

$CARGO_HOME/config.toml cujo padrão é:

Windows: %USERPROFILE%\.cargo\config.toml
Unix: $HOME/.cargo/config.toml

O mais próximo que tenho são três nomes de arquivos como este:

/home/meunome/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-expr-0.15.8/.cargo/config.toml

Não é esse, certo? Pelo que entendi, o Cargo procura por um config.toml no diretório atual e, em seguida, recursivamente, uma pasta acima até chegar à raiz. Nem sei o que ele está usando, pois não vejo um arquivo chamado config.toml e, de qualquer forma, a busca em todo o sistema só mostrou o que colei acima. Onde está esse arquivo config.toml? Dois dos arquivos config.toml são bem pequenos e definem algumas flags, e o que está em cfg-expr-0.15.8/.cargo se parece com:

[target.'cfg(all())']
rustflags = [
    # BEGIN - Embark standard lints v6 for Rust 1.55+
    # do not change or add/remove here, but one can add exceptions after this section
    # for more info see: <https://github.com/EmbarkStudios/rust-ecosystem/issues/59>
    "-Dunsafe_code",
    "-Wclippy::all",
    "-Wclippy::await_holding_lock",
    "-Wclippy::char_lit_as_u8",
    "-Wclippy::checked_conversions",
    "-Wclippy::dbg_macro",
    "-Wclippy::debug_assert_with_mut_call",
    "-Wclippy::doc_markdown",
    "-Wclippy::empty_enum",
    "-Wclippy::enum_glob_use",
    "-Wclippy::exit",
    "-Wclippy::expl_impl_clone_on_copy",
    "-Wclippy::explicit_deref_methods",
    "-Wclippy::explicit_into_iter_loop",
    "-Wclippy::fallible_impl_from",
    "-Wclippy::filter_map_next",
    "-Wclippy::flat_map_option",
    "-Wclippy::float_cmp_const",
    "-Wclippy::fn_params_excessive_bools",
    "-Wclippy::from_iter_instead_of_collect",
    "-Wclippy::if_let_mutex",
    "-Wclippy::implicit_clone",
    "-Wclippy::imprecise_flops",
    "-Wclippy::inefficient_to_string",
    "-Wclippy::invalid_upcast_comparisons",
    "-Wclippy::large_digit_groups",
    "-Wclippy::large_stack_arrays",
    "-Wclippy::large_types_passed_by_value",
    "-Wclippy::let_unit_value",
    "-Wclippy::linkedlist",
    "-Wclippy::lossy_float_literal",
    "-Wclippy::macro_use_imports",
    "-Wclippy::manual_ok_or",
    "-Wclippy::map_err_ignore",
    "-Wclippy::map_flatten",
    "-Wclippy::map_unwrap_or",
    "-Wclippy::match_on_vec_items",
    "-Wclippy::match_same_arms",
    "-Wclippy::match_wild_err_arm",
    "-Wclippy::match_wildcard_for_single_variants",
    "-Wclippy::mem_forget",
    "-Wclippy::mismatched_target_os",
    "-Wclippy::missing_enforced_import_renames",
    "-Wclippy::mut_mut",
    "-Wclippy::mutex_integer",
    "-Wclippy::needless_borrow",
    "-Wclippy::needless_continue",
    "-Wclippy::needless_for_each",
    "-Wclippy::option_option",
    "-Wclippy::path_buf_push_overwrite",
    "-Wclippy::ptr_as_ptr",
    "-Wclippy::rc_mutex",
    "-Wclippy::ref_option_ref",
    "-Wclippy::rest_pat_in_fully_bound_structs",
    "-Wclippy::same_functions_in_if_condition",
    "-Wclippy::semicolon_if_nothing_returned",
    "-Wclippy::single_match_else",
    "-Wclippy::string_add_assign",
    "-Wclippy::string_add",
    "-Wclippy::string_lit_as_bytes",
    "-Wclippy::string_to_string",
    "-Wclippy::todo",
    "-Wclippy::trait_duplication_in_bounds",
    "-Wclippy::unimplemented",
    "-Wclippy::unnested_or_patterns",
    "-Wclippy::unused_self",
    "-Wclippy::useless_transmute",
    "-Wclippy::verbose_file_reads",
    "-Wclippy::zero_sized_map_values",
    "-Wfuture_incompatible",
    "-Wnonstandard_style",
    "-Wrust_2018_idioms",
    # END - Embark standard lints v6 for Rust 1.55+

Editar: OK, descobri que o Cargo também procura por arquivos chamados apenas "config" sem o ".toml". Bem, na minha pasta pessoal do Cargo não há nenhum arquivo de configuração, apenas um monte de "config.yml" e "config.rs", junto com os três "config.toml" que mencionei, mas não está na pasta pessoal do Cargo, está em algum caminho longo.

rust
  • 1 respostas
  • 39 Views
Martin Hope
Zebrafish
Asked: 2025-04-06 21:31:38 +0800 CST

Como os "tipos" têm ligação externa ou interna? Por que isso tem ligação interna?

  • 10

Eu sei que variáveis/objetos têm ligação interna e externa, mas não sabia que "tipos" têm ligação interna e externa. Quando compilo meu código com o GCC, recebo o aviso:

'ShaderModuleObject' tem um campo 'GFXAPIShaderModuleHandle ShaderModuleObject::handle' cujo tipo tem ligação interna [-Wsubobject-linkage]

Aqui está o código, e eu o colei no Godbolt , mas não vejo o mesmo aviso, ou mesmo se o Godbolt tem avisos habilitados:

#define GFX_API_NULL_HANDLE 0

template <typename T, void(*deleter)(T)>
struct MoveOnlyGFXAPIHandle
{
    MoveOnlyGFXAPIHandle() : handle(GFX_API_NULL_HANDLE) {}
    MoveOnlyGFXAPIHandle(T handle) : handle(handle) {}
    MoveOnlyGFXAPIHandle(const MoveOnlyGFXAPIHandle&) = delete;
    MoveOnlyGFXAPIHandle(MoveOnlyGFXAPIHandle&& other) : handle(other.handle) { other.handle = GFX_API_NULL_HANDLE; };
    MoveOnlyGFXAPIHandle& operator=(const MoveOnlyGFXAPIHandle&) = delete;
    MoveOnlyGFXAPIHandle& operator=(MoveOnlyGFXAPIHandle&& other)
    {
        this->reset();
        handle = other.handle;
        other.handle = GFX_API_NULL_HANDLE;

        return *this;
    }
    void reset() { 
        if (handle != GFX_API_NULL_HANDLE) 
        {
            deleter(this->handle); 
            handle = GFX_API_NULL_HANDLE; 
        }    
    }
    
    void assign(T handle) { reset(); this->handle = handle; }
    operator T() const { return handle; }

    T get() const { return handle; }
    ~MoveOnlyGFXAPIHandle() { 

        reset(); }
private:
    T handle;
};


using GFXAPIShaderModuleHandle = MoveOnlyGFXAPIHandle < int,
    +[](int handle) {

          //destroyShaderModule(handle);
    } > ;




struct ShaderModuleObject {

    GFXAPIShaderModuleHandle handle;
};


int main()
{

    ShaderModuleObject module_object;


    return 0;
}

O que são tipos com ligação interna e externa? E por que meu tipo tem ligação interna, e por que isso é algo ruim a ponto de o GCC me alertar sobre isso?

c++
  • 1 respostas
  • 127 Views
Martin Hope
Zebrafish
Asked: 2025-03-31 02:38:38 +0800 CST

Núcleos P e E ao fazer programação multithread

  • 5

Quando você divide um algoritmo/função/qualquer coisa para executar como threads separadas, digamos que eu lanço 8 threads, você não sabe que cada thread será executada em um dos meus 8 núcleos, pois é tarefa do planejador decidir quais threads serão dadas a quais núcleos. Ainda assim, se eu tiver 8 núcleos e dividir um trabalho em 8 threads, eu praticamente espero que isso aconteça, cada um dos meus 8 núcleos (aproximadamente) levará um oitavo da carga de trabalho. No caso de processadores Intel que têm núcleos P e E (núcleos de desempenho e eficiência), os núcleos P podem ter clock de 5,4 GHz e os núcleos E podem ter clock de 4,2 GHz. Esse tipo de processador com dois tipos diferentes de processadores torna a programação multithread mais imprevisível ou menos desejável? O sistema de duas camadas é comum em outros dispositivos, como smartphones e CPUs da Apple, e a mesma pergunta se aplica. Como programador, como você deve levar em conta o fato de que quando você executa algo em um thread diferente, digamos que você gera um novo thread ou outro thread está esperando em um pool de threads por um trabalho, ele pode ser executado em um núcleo de desempenho ou em um núcleo de eficiência? Você tem alguma escolha?

multithreading
  • 1 respostas
  • 45 Views
Martin Hope
Zebrafish
Asked: 2025-03-30 13:10:47 +0800 CST

O dispositivo não tem PIPELINE_EXTENSION_NAME, embora rayTracingPipeline seja compatível

  • 2

Quando dou ponteiros para estruturas de extensão a serem preenchidas quando chamo vkGetPhysicalDeviceFeatures, o sinalizador rayTracingPipeline é 1, o que significa que ele deve ser suportado, e praticamente todos os sinalizadores em VkPhysicalDeviceRayTracingPipelineFeaturesKHR são definidos como 1. No entanto, quando crio o dispositivo lógico, recebo o erro de validação:

pCreateInfo->pNext inclui um ponteiro para um VkPhysicalDeviceRayTracingPipelineFeaturesKHR, mas ao criar o VkDevice, a extensão pai (VK_KHR_ray_tracing_pipeline) não foi incluída em ppEnabledExtensionNames.

Então, justo, parece que eu tenho que habilitar o VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME na lista de extensões habilitadas ao criar o dispositivo lógico. Então eu faço isso, mas então eu recebo:

Retorno de chamada da camada de validação Vulkan: loader_validate_device_extensions: A extensão do dispositivo VK_KHR_ray_tracing_pipeline não é suportada pelo dispositivo físico selecionado ou pelas camadas habilitadas.

Retorno de chamada da camada de validação Vulkan: vkCreateDevice: Falha ao validar extensões na lista

Quando verifico o nome da extensão com vkEnumerateDeviceExtensionProperties, ele não está na lista. Estou usando uma Radeon RX570.

vulkan
  • 1 respostas
  • 48 Views
Martin Hope
Zebrafish
Asked: 2025-03-22 16:54:22 +0800 CST

Lendo de um cachimbo imediatamente após abri-lo

  • 7

Eu queria lançar um executável de um processo pai. Esperar até que o processo termine, então ler de volta o que ele escreveu no stdout. Acontece que você não pode esperar o programa terminar e então ler o fluxo FILE*, porque esperar que ele termine significa chamar pclose(FILE*) e nesse ponto o fluxo de arquivo é destruído. Na documentação do Windows, diz para fazer isso :

char psBuffer[128];
    FILE* pPipe;

    /* Run DIR so that it writes its output to a pipe. Open this
     * pipe with read text attribute so that we can read it
     * like a text file.
     */

    if ((pPipe = _popen("dir *.c /on /p", "rt")) == NULL)
    {
        exit(1);
    }

    /* Read pipe until end of file, or an error occurs. */

    while (fgets(psBuffer, 128, pPipe))
    {
        puts(psBuffer);
    }

    int endOfFileVal = feof(pPipe);
    int closeReturnVal = _pclose(pPipe);

    if (endOfFileVal)
    {
        printf("\nProcess returned %d\n", closeReturnVal);
    }
    else
    {
        printf("Error: Failed to read the pipe to the end.\n");
    }

Ele está abrindo o pipe e, em seguida, lendo imediatamente do fluxo. Não é o caso de que é provável que ele leia o fluxo e ele estará vazio ou no fim do arquivo, já que a leitura é executada imediatamente após iniciar o processo filho? Por que isso é válido?

c
  • 1 respostas
  • 69 Views
Martin Hope
Zebrafish
Asked: 2025-03-07 18:17:51 +0800 CST

Ao converter ponto flutuante para ponto fixo, por que vi alguns códigos fazendo BIT_WIDTH ^ 2 MENOS 1?

  • 4

Na minha mente intuitivamente, e mesmo depois de pensar um pouco, se eu quiser converter um valor float normalizado de volta para ponto fixo, eu o multiplicaria pelo valor máximo que pode ser mantido pelo formato de ponto fixo. Então multiplique por 255 ou 65535, ou o que for. No entanto, em alguns casos, vi algumas pessoas ou códigos insistirem que a maneira correta é multiplicar por 255 - 1, ou 65535 - 1. Não sei por que isso acontece ou por que deveria ser o caso. Isso é para lidar com estouro? Não vejo o que de ruim poderia acontecer se você multiplicasse 1,0f * 255. Mesmo que 1,0f não possa ser perfeitamente representado no IEEE 754 e a multiplicação produza 255,0001, então, ao converter isso para um inteiro, ainda termina como 255, sem estouro.

Editar: Desculpe, há dois erros na minha pergunta. Quero dizer 2 ^ bit_width - 1, não bit_width ^ 2 - 1. O que provavelmente está correto, então para um inteiro de 8 bits você multiplicaria por 255, e para um inteiro de 16 bits você multiplicaria por 65535. Minha pergunta é, tenho quase certeza de que já vi código que multiplica por 255 - 1, que é 254. Existe algum motivo para multiplicar por 254 em vez de 255?

graphics
  • 1 respostas
  • 40 Views
Martin Hope
Zebrafish
Asked: 2025-03-07 08:21:21 +0800 CST

É suposto haver interpolação ao usar um usampler2D?

  • 7

Estou amostrando uma imagem R16_UINT no shader com um usampler2D. Eu faço:

uvec4 upix_color = texture(usampler2D(utextures[nonuniformEXT(idx_of_height_map)], samplers[0]), result.uvs);

Mas parece que os valores não retornam filtrados/interpolados, como mostra esta imagem:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Sei que uma imagem em tons de cinza R16 também pode ser R16_UNORM, caso em que é lida como um ponto flutuante normalizado, e sei que números inteiros podem ser mais difíceis de interpolar, mas números inteiros no intervalo de 0 a 65.535 devem poder ser interpolados.

glsl
  • 1 respostas
  • 31 Views
Martin Hope
Zebrafish
Asked: 2025-02-11 09:18:04 +0800 CST

Como os compiladores C e C++ distinguem operadores unários?

  • 9

Se eu tiver o sinal de menos ao lado de uma variável como:

int a;
int b = -a; // UNARY OPERATOR
b = - a; // UNARY OPERATOR

O menos antes do 'a' é considerado um operador unário e o valor negativo de a é tomado. No entanto, neste:

int a, b;
a -b; // SUBTRACTION
a - b; // SUBTRACTION

Então, disso deduzo que:

  1. É irrelevante se o operador está ou não separado do operando por um espaço.
  2. A dedução de se é uma subtração ou um operador unário depende da presença de um operando anterior e é altamente contextual.

Alguém pode dar um resumo simples das regras de como o compilador decide isso?

c++
  • 3 respostas
  • 267 Views
Martin Hope
Zebrafish
Asked: 2024-11-14 05:17:29 +0800 CST

Cada biblioteca estática deve obter sua própria cópia de uma variável embutida?

  • 5

Supõe-se que, de acordo com as informações que ouvi, se você tiver uma variável como:

inline int a_var;

ou

struct Foo
{
     static inline int a_var;
};

Em um arquivo de cabeçalho e inclua esse cabeçalho em algum lugar em uma biblioteca estática, library2, e então inclua-o em uma biblioteca, Library2, então cada biblioteca terá sua própria cópia dessa variável.

Então eu testei isso. Eu fiz um executável e vinculei à Biblioteca estática 1 e à Biblioteca estática2.

Declaro uma variável em uma struct em um cabeçalho comum:

struct MyStruct
{
    static inline int static_var = 0;
};

E no meu executável/main() eu faço:

void library_one_function();
void library_two_function();

#include "common_header.h"
#include <iostream>

int main()
{
    MyStruct::static_var = 1;
    std::cout << "Value from executable = " << MyStruct::static_var << "\n"; // I GET 1
    library_one_func(); // LIBRARY ONE FUNCTION CHANGES IT TO 7
    std::cout << "Value from executable = " << MyStruct::static_var << "\n"; // I GET 7
    library_two_function(); // LIBRARY TWO FUNCTION CHANGES IT TO 100
    std::cout << "Value from executable = " << MyStruct::static_var << "\n"; // I GET 100

}

Toda vez que eu referencio essa variável, não há nenhuma indicação de que cada biblioteca tem sua própria cópia. É sempre a mesma coisa. Por que então as pessoas dizem que as variáveis ​​inline têm suas próprias cópias?

c++
  • 1 respostas
  • 97 Views
Martin Hope
Zebrafish
Asked: 2024-11-13 01:45:53 +0800 CST

Como posso usar tipos de chaves heterogêneos com boost::unordered_flat_map

  • 7

Boost unordered_flat_mapé muito bom, é bem mais rápido que std::unordered_map. Estou tentando usá-lo com tipos de chave heterogêneos:

boost::unordered::unordered_flat_map<std::string, int> my_map;
my_map.emplace(std::string("Hello"), 1);
my_map.find(std::string_view("Hello")); 
// no instance of overloaded function matches the argument list
            argument types are: (std::string_view)

Agora, como criei um mapa que tem o tipo de chave std::string, há uma função find que aceita um std::string, mas também há uma função find modelo que aceita um K, e normalmente essas coisas devem funcionar desde que o contêiner:

  1. Sabe como fazer hash do tipo heterogêneo e
  2. Conhece um operador de igualdade que considera o tipo heterogêneo como o lado direito.

Mesmo que eu faça:

auto equal_to = [](auto& lhs, auto& rhs) { return lhs == rhs; };

E passo essa classe de igualdade para o contêiner, ainda recebo o erro:

boost::unordered::unordered_flat_map<std::string, int, decltype(equal_to)> my_map;

Como faço para fazer isso funcionar?

c++
  • 2 respostas
  • 47 Views
Martin Hope
Zebrafish
Asked: 2024-10-30 16:17:23 +0800 CST

Esta é a maneira mais rápida de transferir uma imagem para a memória da GPU usando o Vulkan?

  • 5

Do jeito que estou fazendo agora, pelo que entendi, cada nova imagem tem que ser criada com LAYOUT_UNDEFINED. Então coloco uma barreira para fazer a transição para TRANSFER_DST_OPTIMAL. Agora posso transferir a imagem. A menos que você queira usar LINEAR TILING, é isso que você precisa fazer no mínimo.

Agora preciso transferir os dados para o buffer. No meu caso, a memória visível ao host não é local do dispositivo, então escrevo os dados da imagem em um buffer de preparação, então emito um buffer para cópia da imagem e transição de DST_SRC para READ_OPTIMAL. Esta é a maneira MAIS eficiente de fazer isso se a memória visível ao host não for local do dispositivo.

Agora considere que a memória visível do host também é local do dispositivo. Sinto que devo conseguir gravar no buffer local do dispositivo da GPU imediatamente, mas não sei como ou mesmo se é possível, porque acho que você sempre precisa de um buffer para copiar a imagem. Isso está certo?

graphics
  • 1 respostas
  • 15 Views
Martin Hope
Zebrafish
Asked: 2024-10-27 15:12:20 +0800 CST

Existe uma maneira de incluir condicionalmente um cabeçalho ou importar um módulo dependendo de um switch/flag?

  • 8

Eu tentei:

#ifdef USE_CPP20_MODULES
#define IMPORT_OR_INCLUDE(module_name, include_filepath) \
import module_name;
#else
#define IMPORT_OR_INCLUDE(module_name, include_filepath) \
#include include_filepath
#endif

Mas nenhum dos compiladores o compilou:

Barulho:

    Output of x86-64 clang 19.1.0 (Compiler #1)

<source>:6:2: error: '#' is not followed by a macro parameter
    6 | #include include_filepath
      |  ^

CCG:

<source>:5:56: error: '#' is not followed by a macro parameter
    5 | #define IMPORT_OR_INCLUDE(module_name, include_filepath) \

Não entendo por que o pré-processador falha.
Imagino que você não possa usar #includecomo definição/substituição de uma macro?

c++
  • 1 respostas
  • 58 Views
Martin Hope
Zebrafish
Asked: 2024-10-23 14:25:38 +0800 CST

Como evitar que threads de trabalho fiquem ociosos até a próxima notificação de variável de condição

  • 5

Digamos que eu tenha um monte de threads de trabalho esperando até que haja tarefas na fila.
Geralmente, você faz o produtor chamar a função de produção e, em seguida, notify_onepara que o thread de trabalho possa desbloquear e continuar.
No entanto, digamos que quando o produtor produziu, não há threads esperando no condition_variable. O produtor notificará, o que não fará nada. Então, um consumidor chega no condition_variablee waits, mas perdeu a notificação anterior.
Agora você tem uma tarefa em uma fila até que o produtor chame notificar NOVAMENTE, momento em que haverá duas tarefas na fila.

Minha pergunta é: como posso evitar que haja trabalhos na fila de espera quando há threads disponíveis?

Exemplo:

struct ThreadPool
{
    static inline std::mutex mutex;
    static inline std::condition_variable condition_var;

    static inline int number_of_things_to_consume = 0;

    static void consume()
    {
        std::unique_lock lock{ mutex };

        /* THE WORKER THREAD COULD BE WAITING HERE WITH SOMETHING IN THE QUEUE
        - BECAUSE THE PRODUCER CALLED NOTIFY ONE BUT NO THREAD WAS WAITING YET */
        condition_var.wait(lock, []() {return number_of_things_to_consume > 0; });

        /* CONSUME */
    }

    static void produce()
    {
        std::unique_lock lock{ mutex };
        ++number_of_things_to_consume;
        condition_var.notify_one();
    }
};
c++
  • 1 respostas
  • 65 Views
Martin Hope
Zebrafish
Asked: 2024-10-19 08:56:57 +0800 CST

Como posso colocar um typedef dentro de uma classe usando macros?

  • 5

Eu tenho um registro de componentes que registra componentes (classes/tipos). Eu consegui fazer com que o sistema não funcionasse se você tentasse usá-lo com uma classe que não foi registrada. No entanto, mesmo se ele foi registrado uma vez com um tipo de registro, ele funciona com todos eles porque há um:

template <typename T> static inline component_id;

Isso é colocado dentro da classe pela macro.

template <typename name>
struct ComponentRegistry
{
    using this_type = ComponentRegistry;

    template <typename component_t>
    static char register_new_component(const char* name)
    {
        static int counter = 0;
        component_t::template component_id<this_type> = counter++;
        /* REGISTER THE COMPONENT HERE*/
        
        return char(); /* ANYTHING. THE ONLY ONLY REASON THE DUMMY EXISTS IS TO TRIGGER THIS FUNCTION CALL ON PROGRAM INITIALIZATION */
    }
    template <typename component_t>
    int getComponentID()
    {
        /* IF THE COMPONENT WASN'T REGISTERED WITH ANY REGISTRY AT ALL, THEN THE template component_id DOESN'T EXIST AND SO IT WORKS
        - THE PROBLEM IS THAT EVEN IF IT WAS REGISTERED WITH ANOTHER REGISTRY THIS WILL STILL INSTANTIATE THE TEMPLATE
        - HOW DO I THROW A COMPILE ERROR? */
        return component_t::template component_id<this_type>; 
    }
};



#define REGISTER_COMPONENT_WITH_REGISTRY(comp_name, ecs_registry_type, comp_type) \
static inline char dummy_assignee_##ecs_registry_type = ecs_registry_type::register_new_component<comp_type>(comp_name); \
template <typename T> \
static inline int component_id;



struct ComponentRegistryName {}; // JUST USED TO DISTINGUISH. EACH TYPE CAN HAVE ITS OWN SET OF COMPONENTS

using ComponentRegistryType = ComponentRegistry<ComponentRegistryName>;

struct MyComponentType
{
    REGISTER_COMPONENT_WITH_REGISTRY("MyComponentTypeName", ComponentRegistryType, MyComponentType)

};

struct MyComponentType2
{
    /* NOT REGISTERED */
};

int main()
{
    ComponentRegistryType component_registry;

    component_registry.getComponentID<MyComponentType>(); // THIS SUCCEEDS BECAUSE IT WAS REGISTERED
    //component_registry.getComponentID<MyComponentType2>(); // THIS FAILS TO COMPILE BECAUSE THE COMPONENT WASN'T REGISTERED

}

Isso funciona bem para verificar se o componente foi registrado, porque se não foi:

Mas o problema é que se eu quiser registrar o componente em outro tipo de registro, não há mais verificação de restrição porque quando eu faço isso:

componente_t::modelo componente_id

Não existe de forma alguma. No entanto, mesmo se o getComponentID for chamado com um argumento de modelo de um componente que foi registrado em QUALQUER registro, ele terá sucesso. Eu esperava colocar um typedef na classe usando a macro que eu posso verificar como um membro, e se existir, então está bom.

c++
  • 1 respostas
  • 50 Views
Martin Hope
Zebrafish
Asked: 2024-10-12 01:20:06 +0800 CST

Existe alguma diferença entre adicionar um arquivo de origem e vincular a uma biblioteca estática?

  • 5

Eu sei que todos os arquivos de compilação (unidades de tradução) são compilados para arquivos de objeto, e então o vinculador resolve símbolos que o compilador não conseguiu encontrar no estágio de compilação, procurando nesses arquivos de objeto. Mas isso também acontece ao vincular a uma biblioteca estática. Então, quais são as diferenças entre vincular a uma biblioteca estática pré-compilada versus vincular a um arquivo de objeto? Eu tenho um arquivo c de aproximadamente 300 mil linhas (sqlite) e estou pensando se devo compilá-lo para uma biblioteca estática em vez de apenas passar o arquivo c para o compilador como uma unidade de compilação. Eu sei que em ambos os casos o compilador não "vê" o código naquele arquivo até o estágio de vinculação. Acho que uma vez, quando eu estava experimentando essas coisas, vi uma diferença no tamanho binário final, mas não consigo lembrar se eu tinha as configurações de otimização definidas corretamente (ou seja, vinculação de nível de função -ffunction-sections -fdata-sections).

c++
  • 1 respostas
  • 131 Views

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