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 / Perguntas / 78090706
Accepted
Damir Tenishev
Damir Tenishev
Asked: 2024-03-02 06:11:10 +0800 CST2024-03-02 06:11:10 +0800 CST 2024-03-02 06:11:10 +0800 CST

Qual é a abordagem para lidar com membros de classe opcionais?

  • 772

Processando grandes quantidades de dados (gigabytes) uso índices para matrizes de dados. Como o acesso aos dados pode levar à ineficiência do cache, quero armazenar em cache alguns dados do array junto com o índice, o que proporciona uma aceleração drástica para operações por meio de índices.

A quantidade de dados armazenados em cache é uma escolha em tempo de compilação que deve incluir quantidade zero de dados em cache. Tenho uma grande quantidade de índices, então neste caso não quero pagar por elementos “vazios” extras como std::arrayacontece, por exemplo.

Então, fiz um template com especialização:

using index_t = unsigned int;
using lexem_t = unsigned int;

template <std::size_t t_arg_cache_line_size>
struct lexem_index_with_cache_t {
    index_t index;
    std::array<lexem_t, t_arg_cache_line_size> cache_line;

    constexpr std::size_t cache_line_size() const {
        return t_arg_cache_line_size;
    }
};

template<>
struct lexem_index_with_cache_t<0> {
    index_t index;
    static std::array<lexem_t, 0> cache_line;

    constexpr std::size_t cache_line_size() const {
        return 0;
    }
};

std::array<lexem_t, 0> lexem_index_with_cache_t<0>::cache_line;

O problema é esse “hack” que usei na especialização com tamanho zero que utiliza membro estático para dar acesso formal ao cache_linewhile está vazio e o acesso não é realmente necessário. Isso me permite evitar especializações em funções que utilizam este modelo, como aqui:

using lexem_index_with_cache = lexem_index_with_cache_t<0>;

template <typename T>
class seq_forward_comparator_cached
{
    const std::vector<T>& vec;
public:
    seq_forward_comparator_cached(const std::vector<T>& vec) : vec(vec) { }

    bool operator() (const lexem_index_with_cache& idx1, const lexem_index_with_cache& idx2)
    {
        if (idx1.index == idx2.index) {
            return false;
        }

        const auto it1_cache_line = idx1.cache_line;  // This code wouldn’t compile in absence of static “hack”
        const auto it2_cache_line = idx2.cache_line;  // This code wouldn’t compile in absence of static “hack”

        auto res = std::lexicographical_compare_three_way(
            it1_cache_line.begin(), it1_cache_line.end(),
            it2_cache_line.begin(), it2_cache_line.end());

        if (res == std::strong_ordering::equal) {
            auto range1 = std::ranges::subrange(vec.begin() + idx1.index + idx1.cache_line_size(), vec.end());
            auto range2 = std::ranges::subrange(vec.begin() + idx2.index + idx2.cache_line_size(), vec.end());

            return std::ranges::lexicographical_compare(range1, range2);
        }

        return res == std::strong_ordering::less;
    }
};

Claro, posso implementar outra especialização de modelo deste modelo para cache de tamanho zero, mas isso levará à duplicação de código e tenho muitas dessas funções, então não quero especializar todas elas.

staticPor outro lado, qual é a maneira adequada no C++ moderno de evitar esse hack e possível duplicação de código?

Não tenho certeza, talvez algum tipo de código condicional incluído dependendo do tipo possa ajudar.

Eu gostaria de evitar o acesso a cache_lineuma função, mas se esse for o único caso, dê uma pista sobre a abordagem.

O código compilável está aqui .

c++
  • 1 1 respostas
  • 51 Views

1 respostas

  • Voted
  1. Best Answer
    Aedoro
    2024-03-02T06:37:19+08:002024-03-02T06:37:19+08:00

    Adicionei um exemplo com um truque para usar o if constexpr(...)código que não é de modelo.

    Agora é impossível usar a at()função acidentalmente, ao contrário da solução de membro estático.

    #include <array>
    
    using data_type = int;
    
    template<size_t _data_size>
    class ExtendableIndex
    {
    public:
        constexpr static size_t data_size = _data_size;
    
        data_type& at(size_t idx) { return data[idx]; }
    
        size_t index;
        std::array<data_type, _data_size> data;
    };
    
    template<>
    class ExtendableIndex<0>
    {
    public:
        constexpr static size_t data_size = 0;
    
        data_type& at(size_t idx);
    
        size_t index;
    };
    
    using DefaultIndex = ExtendableIndex<0>;
    
    class DataUser
    {
    public:
    
        void process(DefaultIndex& index)
        {
            if constexpr (DefaultIndex::data_size > 0)
            {
                // auto value = index.data[0]; // -> this fails to compile
                auto value = index.at(0); // -> but this slight workaround solves the issue, `at()` is not implemented and thats OK.
            }
        }
    
        template<size_t _data_size>
        void process_template(ExtendableIndex<_data_size>& index)
        {
            if constexpr (DefaultIndex::data_size > 0)
            {
                auto value = index.data[0]; // -> this compiles even if index.data doesn't exist when 'process' is a template
            }
        }
    
    };
    
    int main()
    {
        DataUser r;
        ExtendableIndex<0> index_zero;
    
        r.process(index_zero);
        r.process_template(index_zero);
    
        ExtendableIndex<1> index_one;
        r.process_template(index_one);
    }
    
    • 1

relate perguntas

  • Por que os compiladores perdem a vetorização aqui?

  • Erro de compilação usando CMake com biblioteca [fechada]

  • Erro lançado toda vez que tento executar o premake

  • Como criar um tipo de octeto semelhante a std::byte em C++?

  • Somente operações bit a bit para std::byte em C++ 17?

Sidebar

Stats

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

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

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 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

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 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
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +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
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +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