Eu sempre pensei que é a sabedoria geral que std::vector
é "implementada como uma matriz", blá blá blá. Hoje desci e testei, e parece não ser assim:
Aqui estão alguns resultados dos testes:
UseArray completed in 2.619 seconds
UseVector completed in 9.284 seconds
UseVectorPushBack completed in 14.669 seconds
The whole thing completed in 26.591 seconds
Isso é cerca de 3 a 4 vezes mais lento! Realmente não justifica os comentários " vector
pode ser mais lento para alguns nanossegundos".
E o código que eu usei:
#include <cstdlib>
#include <vector>
#include <iostream>
#include <string>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/microsec_time_clock.hpp>
class TestTimer
{
public:
TestTimer(const std::string & name) : name(name),
start(boost::date_time::microsec_clock<boost::posix_time::ptime>::local_time())
{
}
~TestTimer()
{
using namespace std;
using namespace boost;
posix_time::ptime now(date_time::microsec_clock<posix_time::ptime>::local_time());
posix_time::time_duration d = now - start;
cout << name << " completed in " << d.total_milliseconds() / 1000.0 <<
" seconds" << endl;
}
private:
std::string name;
boost::posix_time::ptime start;
};
struct Pixel
{
Pixel()
{
}
Pixel(unsigned char r, unsigned char g, unsigned char b) : r(r), g(g), b(b)
{
}
unsigned char r, g, b;
};
void UseVector()
{
TestTimer t("UseVector");
for(int i = 0; i < 1000; ++i)
{
int dimension = 999;
std::vector<Pixel> pixels;
pixels.resize(dimension * dimension);
for(int i = 0; i < dimension * dimension; ++i)
{
pixels[i].r = 255;
pixels[i].g = 0;
pixels[i].b = 0;
}
}
}
void UseVectorPushBack()
{
TestTimer t("UseVectorPushBack");
for(int i = 0; i < 1000; ++i)
{
int dimension = 999;
std::vector<Pixel> pixels;
pixels.reserve(dimension * dimension);
for(int i = 0; i < dimension * dimension; ++i)
pixels.push_back(Pixel(255, 0, 0));
}
}
void UseArray()
{
TestTimer t("UseArray");
for(int i = 0; i < 1000; ++i)
{
int dimension = 999;
Pixel * pixels = (Pixel *)malloc(sizeof(Pixel) * dimension * dimension);
for(int i = 0 ; i < dimension * dimension; ++i)
{
pixels[i].r = 255;
pixels[i].g = 0;
pixels[i].b = 0;
}
free(pixels);
}
}
int main()
{
TestTimer t1("The whole thing");
UseArray();
UseVector();
UseVectorPushBack();
return 0;
}
Estou fazendo errado ou algo assim? Ou acabei de quebrar esse mito da performance?
Estou usando o modo Release no Visual Studio 2005 .
No Visual C ++ , #define _SECURE_SCL 0
reduz UseVector
pela metade (diminuindo para 4 segundos). Isso é realmente enorme, IMO.
vector
é uma matriz redimensionável de uso geral. Parabéns. Como em todas as ferramentas de uso geral, é possível criar situações especializadas em que isso é subótimo. É por isso que a sabedoria convencional é começar comvector
ae considerar alternativas, se necessário.Respostas:
Usando o seguinte:
Portanto, o array é duas vezes mais rápido que o vetor.
Mas, depois de analisar o código com mais detalhes, isso é esperado; conforme você percorre o vetor duas vezes e a matriz apenas uma vez. Nota: quando você
resize()
vector, você não está apenas alocando a memória, mas também executando o vetor e chamando o construtor em cada membro.Reorganizando o código levemente para que o vetor inicialize apenas cada objeto uma vez:
Agora, fazendo o mesmo tempo novamente:
O vetor agora apresenta desempenho apenas ligeiramente pior que o da matriz. Na OMI, essa diferença é insignificante e pode ser causada por várias coisas não associadas ao teste.
Eu também consideraria que você não está inicializando / destruindo corretamente o objeto Pixel no
UseArrray()
método, pois nem o construtor / destruidor é chamado (isso pode não ser um problema para essa classe simples, mas algo um pouco mais complexo (por exemplo, com ponteiros ou membros com ponteiros) causará problemas.fonte
reserve()
vez deresize()
. Isso aloca espaço para os objetos (ou seja, altera a capacidade do vetor), mas não cria os objetos (ou seja, o tamanho do vetor permanece inalterado).resize()
porreserve()
, porque isso não ajusta a ideia interna do vetor de seu próprio tamanho; portanto, as gravações subsequentes em seus elementos são tecnicamente "gravadas além do fim" e produzirão UB. Embora, na prática, toda implementação de STL "se comporte" a esse respeito, como você ressincroniza o tamanho do vetor? Se você tentar chamarresize()
depois de preencher o vetor, ele provavelmente substituirá todos esses elementos com valores construídos por padrão!reserve
apenas altera a capacidade de um vetor, não seu tamanho./EHsc
de opções de compilação limpava isso eassign()
atualmente supera a matriz. Yay.Ótima pergunta. Eu vim aqui esperando encontrar alguma correção simples que agilizasse os testes de vetores. Isso não funcionou como eu esperava!
A otimização ajuda, mas não é suficiente. Com a otimização ativada, ainda vejo uma diferença de desempenho 2X entre o UseArray e o UseVector. Curiosamente, o UseVector foi significativamente mais lento que o UseVectorPushBack sem otimização.
Idéia # 1 - Use novo [] em vez de malloc
Tentei mudar
malloc()
paranew[]
no UseArray para que os objetos fossem construídos. E mudando da atribuição de campo individual para a atribuição de uma instância de Pixel. Ah, e renomear a variável de loop interno paraj
.Surpreendentemente (para mim), nenhuma dessas mudanças fez qualquer diferença. Nem mesmo a alteração na
new[]
qual o padrão será construído em todos os pixels. Parece que o gcc pode otimizar as chamadas de construtor padrão ao usarnew[]
, mas não ao usarvector
.Idéia # 2 - Remover chamadas repetidas do operador []
Também tentei me livrar da
operator[]
pesquisa tripla e armazenar em cache a referênciapixels[j]
. Isso realmente desacelerou o UseVector! OpaIdéia # 3 - Remover construtores
Que tal remover completamente os construtores? Talvez o gcc possa otimizar a construção de todos os objetos quando os vetores são criados. O que acontece se mudarmos Pixel para:
Resultado: cerca de 10% mais rápido. Ainda mais lento que um array. Hum.
Idéia # 4 - Use o iterador em vez do índice de loop
Que tal usar um
vector<Pixel>::iterator
índice em vez de um loop?Resultado:
Não, não é diferente. Pelo menos não é mais lento. Eu pensei que isso teria desempenho semelhante ao # 2, onde eu usei uma
Pixel&
referência.Conclusão
Mesmo que algum cookie inteligente descubra como fazer o loop de vetor tão rápido quanto o array, isso não fala bem do comportamento padrão de
std::vector
. O suficiente para o compilador ser inteligente o suficiente para otimizar todo o C ++ ness e tornar os contêineres STL tão rápidos quanto os arrays brutos.O ponto principal é que o compilador não pode otimizar as chamadas de construtor padrão no-op ao usar
std::vector
. Se você usar simples,new[]
ele os otimiza muito bem. Mas não comstd::vector
. Mesmo que você possa reescrever seu código para eliminar as chamadas do construtor que aparecem diante do mantra por aqui: "O compilador é mais inteligente que você. O STL é tão rápido quanto o normal C. Não se preocupe."fonte
vector<int>
.Esta é uma pergunta antiga, mas popular.
Neste ponto, muitos programadores estarão trabalhando no C ++ 11. E no C ++ 11, o código do OP, como escrito, é executado igualmente rápido para
UseArray
ouUseVector
.O problema fundamental era que, enquanto sua
Pixel
estrutura não foi inicializada, criastd::vector<T>::resize( size_t, T const&=T() )
um padrãoPixel
e o copia . O compilador não percebeu que estava sendo solicitado a copiar dados não inicializados e, portanto, executou a cópia.No C ++ 11,
std::vector<T>::resize
tem duas sobrecargas. O primeiro éstd::vector<T>::resize(size_t)
, o outro éstd::vector<T>::resize(size_t, T const&)
. Isso significa que quando você invocaresize
sem um segundo argumento, ele simplesmente constrói o padrão, e o compilador é inteligente o suficiente para perceber que a construção padrão não faz nada, portanto ignora a passagem sobre o buffer.(As duas sobrecargas foram adicionadas para lidar com tipos móveis, construtíveis e não copiáveis - a melhoria de desempenho ao trabalhar com dados não inicializados é um bônus).
A
push_back
solução também faz a verificação de vedação, o que a torna mais lenta, permanecendo mais lenta que amalloc
versão.exemplo ao vivo (também substituí o temporizador por
chrono::high_resolution_clock
).Observe que, se você possui uma estrutura que geralmente requer inicialização, mas deseja manipulá-la após aumentar seu buffer, pode fazer isso com um
std::vector
alocador personalizado . Se você quiser movê-lo para um estado mais normalstd::vector
, acredito que o uso cuidadosoallocator_traits
e a substituição de==
podem fazer isso, mas não tenho certeza.fonte
emplace_back
vs vspush_back
aqui.clang++ -std=c++11 -O3
temUseArray completed in 2.02e-07 seconds
eUseVector completed in 1.3026 seconds
. Eu também adicionei umaUseVectorEmplaceBack
versão que é de aprox. 2,5x mais rápido queUseVectorPushBack
.Para ser justo, você não pode comparar uma implementação C ++ com uma implementação C, como eu chamaria sua versão malloc. O malloc não cria objetos - apenas aloca memória não processada. O fato de você tratar essa memória como objetos sem chamar o construtor é um C ++ ruim (possivelmente inválido - deixarei isso para os advogados de linguagem).
Dito isso, simplesmente alterar o malloc para
new Pixel[dimensions*dimensions]
e free todelete [] pixels
não faz muita diferença com a implementação simples do Pixel que você possui. Aqui estão os resultados na minha caixa (E6600, 64 bits):Mas com uma ligeira mudança, as mesas viram:
Pixel.h
Pixel.cc
main.cc
Compilado desta maneira:
obtemos resultados muito diferentes:
Com um construtor não embutido para Pixel, std :: vector agora supera uma matriz bruta.
Parece que a complexidade da alocação por meio de std :: vector e std: alocador é demais para ser otimizada de maneira tão eficaz quanto simples
new Pixel[n]
. No entanto, podemos ver que o problema está simplesmente na alocação e não no acesso ao vetor, ajustando algumas das funções de teste para criar o vetor / matriz uma vez movendo-o para fora do loop:e
Agora obtemos esses resultados:
O que podemos aprender com isso é que std :: vector é comparável a uma matriz bruta de acesso, mas se você precisar criar e excluir o vetor / matriz muitas vezes, a criação de um objeto complexo consumirá mais tempo do que a criação de uma matriz simples quando o construtor do elemento não estiver embutido. Não acho que isso seja muito surpreendente.
fonte
Tente com isto:
Eu tenho quase exatamente o mesmo desempenho que com o array.
A questão
vector
é que é uma ferramenta muito mais geral do que uma matriz. E isso significa que você deve considerar como usá-lo. Ele pode ser usado de várias maneiras diferentes, fornecendo funcionalidades que nem mesmo uma matriz possui. E se você usá-lo "errado" para o seu objetivo, gera muita sobrecarga, mas se usá-lo corretamente, geralmente é basicamente uma estrutura de dados com zero sobrecarga. Nesse caso, o problema é que você inicializou o vetor separadamente (fazendo com que todos os elementos tivessem seu nome padrão chamado) e, em seguida, substituiu cada elemento individualmente com o valor correto. Isso é muito mais difícil para o compilador otimizar o processo do que quando você faz a mesma coisa com uma matriz. É por isso que o vetor fornece um construtor que permite fazer exatamente isso:N
X
.E quando você usa isso, o vetor é tão rápido quanto uma matriz.
Então não, você não quebrou o mito da performance. Mas você mostrou que isso só é verdade se você usar o vetor de maneira ideal, o que também é um bom argumento. :)
Pelo lado positivo, é realmente o uso mais simples que acaba sendo o mais rápido. Se você contrastar meu snippet de código (uma única linha) com a resposta de John Kugelman, contendo montes e montes de ajustes e otimizações, que ainda não eliminam completamente a diferença de desempenho, é bem claro que, apesar de tudo,
vector
é muito inteligente. Você não precisa pular aros para obter velocidade igual a uma matriz. Pelo contrário, você deve usar a solução mais simples possível.fonte
new[]
executa as mesmas construções padrão que ovector.resize()
faz, mas é muito mais rápido.new[]
+ loop interno deve ter a mesma velocidade quevector.resize()
+ loop interno, mas não é, é quase o dobro da velocidade.malloc
qual não inicializa ou constrói nada; portanto, é efetivamente um algoritmo de passagem única, como o meuvector
exemplo. Enew[]
a resposta é obviamente que ambas exigem duas passagens, mas, nonew[]
caso, o compilador é capaz de otimizar essa sobrecarga adicional, o que não ocorre novector
caso. Mas não vejo por que é interessante o que acontece em casos abaixo do ideal. Se você se preocupa com o desempenho, não escreve código assim.vector::resize()
para me fornecer um pedaço contingente de memória sem perder tempo chamando construtores inúteis.malloc
que não executa inicialização, mas que não funcionará em C ++ com tipos não POD. Portanto, no caso geral, uma matriz C ++ seria igualmente ruim. Talvez a questão seja: se você realizar esse cego com frequência, não reutilizará o mesmo vetor / matriz? E se você fizer isso, pagará apenas o custo dos "construtores inúteis" uma vez, logo no início. O blitting real é tão rápido, afinal.Não foi uma comparação justa quando olhei seu código pela primeira vez; Eu definitivamente pensei que você não estava comparando maçãs com maçãs. Então pensei: vamos chamar construtores e destruidores em todos os testes; e depois compare.
Meu pensamento era que, com essa configuração, eles deveriam ser exatamente os mesmos. Acontece que eu estava errado.
Então, por que essa perda de desempenho de 30% ocorreu? O STL possui tudo nos cabeçalhos, portanto, deveria ter sido possível para o compilador entender tudo o que era necessário.
Meu pensamento era que é como o loop inicializa todos os valores para o construtor padrão. Então eu fiz um teste:
Os resultados foram como eu suspeitava:
Essa é claramente a fonte da desaceleração, o fato de o vetor usar o construtor de cópia para inicializar os elementos de um objeto construído padrão.
Isso significa que a seguinte ordem de pseudo-operação está acontecendo durante a construção do vetor:
Que, devido ao construtor de cópia implícita feito pelo compilador, é expandido para o seguinte:
Assim, o padrão
Pixel
continua a ser inicializado-un, enquanto o resto são inicializados com o padrãoPixel
's inicializado-un valores.Em comparação com a situação alternativa com
New[]
/Delete[]
:Todos são deixados com seus valores não inicializados e sem a iteração dupla sobre a sequência.
Armado com esta informação, como podemos testá-la? Vamos tentar sobrescrever o construtor de cópias implícitas.
E os resultados?
Então, em resumo, se você estiver criando centenas de vetores com muita frequência: repense seu algoritmo .
Em qualquer caso, a implementação do STL não é mais lenta por algum motivo desconhecido, apenas faz exatamente o que você pede; esperando que você saiba melhor.
fonte
Tente desativar os iteradores verificados e criar no modo de liberação. Você não deve ver muita diferença de desempenho.
fonte
#define _SECURE_SCL 0
. Isso fezUseVector
algo em torno de 4 segundos (semelhante aogcc
abaixo), mas ainda é duas vezes mais lento.-O3
._HAS_ITERATOR_DEBUGGING
está desabilitado na versão: msdn.microsoft.com/en-us/library/aa985939(VS.80).aspxO STL do GNU (e outros), dado
vector<T>(n)
, o padrão constrói um objeto prototípicoT()
- o compilador otimizará o construtor vazio - mas, em seguida, uma cópia do lixo que estiver nos endereços de memória agora reservados para o objeto é obtida pelos STLs__uninitialized_fill_n_aux
, que loops que preenchem cópias desse objeto como os valores padrão no vetor. Portanto, "my" STL não está construindo um loop, mas construindo um loop / cópia. É contra-intuitivo, mas eu deveria ter lembrado quando comentei uma recente pergunta sobre o stackoverflow sobre esse ponto: a construção / cópia pode ser mais eficiente para objetos de referência contados etc.Assim:
ou
é - em muitas implementações de STL - algo como:
O problema é que a geração atual de otimizadores de compilador não parece funcionar com a percepção de que temp é um lixo não inicializado e falha ao otimizar as invocações de loop e construtor de cópia padrão. Você pode argumentar com credibilidade que os compiladores absolutamente não devem otimizar isso, pois um programador que escrever o acima tem uma expectativa razoável de que todos os objetos serão idênticos após o loop, mesmo que lixo (advertências comuns sobre 'idêntico' / operador == vs memcmp / operator = etc aplicável). Não se pode esperar que o compilador tenha uma visão extra do contexto maior de std :: vector <> ou o uso posterior dos dados que sugerem que essa otimização é segura.
Isso pode ser contrastado com a implementação direta mais óbvia:
O que podemos esperar que um compilador otimize.
Para ser um pouco mais explícito sobre a justificativa para esse aspecto do comportamento do vetor, considere:
Claramente, é uma grande diferença se criarmos 10000 objetos independentes versus 10000 fazendo referência aos mesmos dados. Há um argumento razoável de que a vantagem de proteger usuários casuais de C ++ de fazer algo acidentalmente supera o custo muito pequeno do mundo real da construção de cópias difíceis de otimizar.
RESPOSTA ORIGINAL (para referência / interpretação dos comentários): Sem chance. o vetor é tão rápido quanto uma matriz, pelo menos se você reservar espaço sensatamente. ...
fonte
A resposta de Martin York me incomoda porque parece uma tentativa de escovar o problema de inicialização debaixo do tapete. Mas ele tem razão em identificar a construção padrão redundante como a fonte de problemas de desempenho.
[EDIT: A resposta de Martin não sugere mais alterar o construtor padrão.]
Para o problema imediato em questão, você certamente poderia chamar a versão de 2 parâmetros do
vector<Pixel>
ctor:Isso funciona se você deseja inicializar com um valor constante, que é um caso comum. Mas o problema mais geral é: como você pode inicializar eficientemente com algo mais complicado que um valor constante?
Para isso, você pode usar a
back_insert_iterator
, que é um adaptador iterador. Aqui está um exemplo com um vetor deint
s, embora a ideia geral funcione igualmente bem paraPixel
s:Como alternativa, você pode usar
copy()
ou emtransform()
vez degenerate_n()
.A desvantagem é que a lógica para construir os valores iniciais precisa ser movida para uma classe separada, o que é menos conveniente do que tê-lo no lugar (embora as lambdas em C ++ 1x tornem isso muito melhor). Também espero que isso ainda não seja tão rápido quanto uma
malloc()
versão não-STL baseada em, mas espero que seja próxima, pois ele faz apenas uma construção para cada elemento.fonte
Os vetores também estão chamando construtores de Pixel.
Cada um deles está causando quase um milhão de execuções de ctor que você está cronometrando.
edit: então há o loop externo 1 ... 1000, então faça com que um bilhão de ctor ligue!
edit 2: seria interessante ver a desmontagem do caso UseArray. Um otimizador pode otimizar tudo, já que não tem outro efeito senão queimar a CPU.
fonte
Veja como o
push_back
método no vetor funciona:Depois de chamar os
push_back
itens X:Repetir. Se você não está no
reserving
espaço, definitivamente será mais lento. Mais do que isso, se for caro copiar o item, então 'push_back' assim o comerá vivo.Quanto à
vector
coisa versus matriz, vou ter que concordar com as outras pessoas. Execute a liberação, ative as otimizações e coloque mais algumas bandeiras para que as pessoas amigáveis da Microsoft não # #% $ ^ façam isso por você.Mais uma coisa, se você não precisar redimensionar, use o Boost.Array.
fonte
reserve
como deveria.push_back
amortizou o tempo constante. Parece que você está descrevendo um processo O (N). (As etapas 1 e 3 parecem completamente deslocadas.) O que tornapush_back
lento o OP é a verificação do intervalo para verificar se a realocação precisa ocorrer, atualizando os ponteiros, a verificação contra o NULL no posicionamento internonew
e outras pequenas coisas que normalmente são abafadas pelo o trabalho real do programa.reserve
ele ainda precisa fazer essa verificação (se é necessário realocar) em todospush_back
.vector
funcionalidade é redimensionada, é apenas "mágica". Aqui, deixe-me esclarecer um pouco mais.Alguns dados do criador de perfil (o pixel está alinhado a 32 bits):
Blah
Em
allocator
:vector
:matriz
A maior parte da sobrecarga está no construtor de cópias. Por exemplo,
Tem o mesmo desempenho que uma matriz.
fonte
pixels.size()
será quebrada.Meu laptop é o Lenova G770 (4 GB de RAM).
O sistema operacional é o Windows 7 de 64 bits (aquele com laptop)
O compilador é o MinGW 4.6.1.
O IDE é Code :: Blocks .
Eu testo os códigos-fonte do primeiro post.
Os resultados
Otimização de O2
UseArray concluído em 2,841 segundos
UseVector concluído em 2.548 segundos
UseVectorPushBack concluído em 11,95 segundos
A coisa toda concluída em 17,342 segundos
pausa no sistema
Otimização de O3
UseArray concluído em 1.452 segundos
UseVector concluído em 2.514 segundos
UseVectorPushBack concluído em 12,967 segundos
A coisa toda concluída em 16.937 segundos
Parece que o desempenho do vetor é pior na otimização do O3.
Se você alterar o loop para
A velocidade da matriz e do vetor sob O2 e O3 é quase a mesma.
fonte
Uma referência melhor (eu acho ...), o compilador devido às otimizações pode alterar o código, porque os resultados dos vetores / matrizes alocados não são usados em lugar algum. Resultados:
Compilador:
CPU:
E o código:
fonte
Eu fiz alguns testes extensivos que eu queria por um tempo agora. Pode muito bem compartilhar isso.
Esta é a minha máquina de inicialização dupla i7-3770, 16 GB de RAM, x86_64, no Windows 8.1 e no Ubuntu 16.04. Mais informações e conclusões, comentários abaixo. Testou o MSVS 2017 e o g ++ (no Windows e no Linux).
Programa de teste
Resultados
Notas
std::sort()
(você pode vê-lo comentado), mas os removi mais tarde porque não havia diferenças significativas.Minhas conclusões e observações
std::array
variações de tempo entre execuções consecutivas, enquanto outras, especialmente as estruturas std :: data, variaram bastante em comparaçãostd::array
matrizes no estilo c mais rapidamente no Windows sem otimizaçãoVeredito
Claro que isso é código para uma compilação otimizada. E já que a pergunta era sobre
std::vector
sim, é sim! matrizes mais lentas do que simples (otimizadas / não otimizadas). Mas quando você está fazendo um benchmark, naturalmente deseja produzir código otimizado.A estrela do show para mim foi
std::array
.fonte
Com as opções corretas, vetores e matrizes podem gerar asm idênticas . Nesses casos, é claro que eles têm a mesma velocidade, porque você obtém o mesmo arquivo executável de qualquer maneira.
fonte
A propósito, a desaceleração da visualização em classes usando vetor também ocorre com tipos padrão como int. Heres um código multithread:
O comportamento do código mostra que a instanciação do vetor é a parte mais longa do código. Depois de passar pelo gargalo da garrafa. O restante do código é executado extremamente rápido. Isso é verdade, não importa quantos threads você esteja executando.
A propósito, ignore o número absolutamente insano de inclusões. Eu tenho usado esse código para testar as coisas de um projeto, para que o número de inclusões continue crescendo.
fonte
Eu só quero mencionar que vetor (e smart_ptr) é apenas uma fina camada adicionada em cima de matrizes brutas (e ponteiros brutos). E, na verdade, o tempo de acesso de um vetor na memória contínua é mais rápido que o array. O código a seguir mostra o resultado da inicialização e acesso ao vetor e matriz.
A saída é:
Portanto, a velocidade será quase a mesma se você a usar corretamente. (como outros mencionados usando reserve () ou redimensionar ()).
fonte
Bem, porque vector :: resize () faz muito mais processamento do que alocação de memória simples (por malloc).
Tente colocar um ponto de interrupção no construtor de cópias (defina-o para que você possa interromper!) E o tempo de processamento adicional será gasto.
fonte
Devo dizer que não sou especialista em C ++. Mas, para adicionar alguns resultados de experimentos:
compile: gcc-6.2.0 / bin / g ++ -O3 -std = c ++ 14 vector.cpp
máquina:
OS:
Resultado:
Aqui, a única coisa que me parece estranha é o desempenho do "UseFillConstructor" em comparação com o "UseConstructor".
O código:
Portanto, o "valor" adicional fornecido diminui bastante o desempenho, o que eu acho que é devido à chamada múltipla para copiar o construtor. Mas...
Compilar:
Resultado:
Portanto, nesse caso, a otimização do gcc é muito importante, mas não pode ajudá-lo muito quando um valor é fornecido como padrão. Isso é contra a minha mensalidade, na verdade. Espero que ajude o novo programador a escolher qual formato de inicialização do vetor.
fonte
Parece depender dos sinalizadores do compilador. Aqui está um código de referência:
Diferentes sinalizadores de otimização fornecem respostas diferentes:
Seus resultados exatos variam, mas isso é bastante típico na minha máquina.
fonte
Na minha experiência, às vezes, apenas às vezes,
vector<int>
pode ser muitas vezes mais lento queint[]
. Uma coisa a ter em mente é que os vetores de vetores são muito diferentesint[][]
. Como os elementos provavelmente não são contíguos na memória. Isso significa que você pode redimensionar vetores diferentes dentro do principal, mas a CPU pode não ser capaz de armazenar em cache elementos, assim como no caso deint[][]
.fonte