Mais

Como chamar módulos QGIS (qgis.core) do python idle, como posso chamar de arcpy

Como chamar módulos QGIS (qgis.core) do python idle, como posso chamar de arcpy


Eu estava tentando configurar o caminho para poder chamar os módulos qgis conforme definido em seu site Introdução e definir PYTHONPATH = c: qgispath python. Eu também tento seguir a sugestão do link abaixo

Como importar qgis.core para python IDLE?

No entanto, ainda recebo um erro de importação. Também recebo o erro ImportError: Falha ao carregar DLL: O módulo especificado não foi encontrado.

O outro erro que recebo é

Traceback (última chamada mais recente): Arquivo "", linha 1, em  import qgis.core Arquivo "C:  Arquivos de programas  QGIS Wien  apps  qgis  python  qgis  __ init__.py", linha 26, em  import sip ImportError: Nenhum módulo denominado sip

Eu quero ser capaz de chamar este módulo do Spider ou Python ocioso no arcgis. Alguém sabe como fazer isso ou tem documentação explicada mais detalhada? Eu posso chamar o arcpy do spider, mas não consegui fazer isso para o módulo qgis.core.


Depois de adicionar caminhos Python abaixo:

'C:  Arquivos de programas  QGIS Wien  apps  Python27  sip "C:  Arquivos de programas  QGIS Wien  apps  qgis  python" C:  Arquivos de programas  QGIS Wien  apps  Python27  Lib  site-packages'

O problema foi resolvido no PyScripter, porém no Spider, o erro agora é alterado para o seguinte:

from qgis._core import * ImportError: Falha ao carregar DLL: O procedimento especificado não foi encontrado.

Acho que vou usar o PyScripter em vez do Spider.


Testado e obteve um erro

Você fez algumas coisas erradas. Em primeiro lugar, executar sudo pip install python-qt5 fez o download do pip do Python2.7. No futuro, você pode evitar isso com py -3 -m pip install python-qt5. py é uma ferramenta muito útil quando você tem várias versões do Python.

A próxima coisa que você fez de errado foi copiar os módulos Python2.7 para sua lib Python3.x, a maioria dos módulos (especialmente os grandes e complexos como o PyQt, tem código específico de versão que não funciona. Nunca copie módulos de uma versão para outra, a menos que tenha certeza de que é independente de versão. Isso também se aplica entre lançamentos de subversões (como 2.6 e 2.7).

Finalmente, chegarei à solução. O que você não sabia, e é difícil descobrir, é que os binários do PyQt5 são do Windows apenas agora. No entanto, você mesmo pode compilar a partir do código-fonte, basta seguir este guia.

Essas instruções são para o Ubuntu 12.04, portanto, ignore a instalação do Qt, uma vez que você já o tem (Comece no passo 2). Ainda não tenho um Pi 2 (espero conseguir um!), Mas deve funcionar.


Gerenciadores de versão Python

A outra maneira é instalar direto de python.org. Isso irá instalar um python em / usr / local / bin. Acho que isso instala um executável python e python3. O problema com o Homebrew é que ele assume que as coisas em / usr / local são instaladas por ele e, portanto, o brew doctor relatará esses python.org python.org como problemas e, como esta questão mostra, também os frameworks em / Library serão problemáticos.

EDITAR 8/2018 *** Eu agora sugeriria o uso de conda miniconda ou anaconda. Este é outro gerenciador de pacotes, mas baseado e principalmente voltado para python, ele também dá o equivalente aos ambientes virtuais de python e pyenv (conforme outra resposta) e, portanto, cada projeto pode estar em um python diferente e em bibliotecas diferentes (Macports só muda a versão de python para todos os projetos)


& ldquoexcept (IOError, OSError), e: SyntaxError: sintaxe inválida & rdquo ao configurar python-lockfile

Estou tendo problemas para instalar novos pacotes no Ubuntu por causa do python.

Tentei sudo apt-get install python3 python3-dev, mas estou recebendo a seguinte saída:

Eu tentei quase tudo que posso encontrar no google. Estou usando o python 2.7.5. Eu fiz apt-get clean e apt-get autoclean e todas as variações desse tema.

Eu realmente quero poder instalar o python-dev. Como posso fazer isso acontecer? Neste ponto, estou disposto a considerar opções extremas, sejam elas quais forem, exceto a formatação do sistema.

Saída para sudo apt-get install --reinstall python-lockfile

Saída para apt-cache policy python-lockfile

Saída para -> sudo dpkg -C ---> http://goo.gl/ib3RqB (Desculpe, limite de palavras atingido, postando neste arquivo.)

Obrigado por sua paciência e ajuda.

Após as sugestões, continuo recebendo erros, meus resultados são:

Saída para sudo apt-get --reinstall install ubuntu-release-upgradeer-gtk


1 resposta 1

Certa vez, participei de um projeto Python no qual tivemos que empregar algumas etapas de processamento de dados muito longas e confusas. Para manter a modularidade mínima, desenvolvemos um sistema no qual os dados fluem de uma classe para outra por meio de uma cadeia muito longa. Cada elo da cadeia precisaria apenas conhecer a interface de chamada da "próxima" etapa da cadeia. Desta forma, poderíamos testar o processo geral testando as interações entre esses links adjacentes (classes e / ou módulos) e em cada "link" apenas a lógica de processamento necessária e específica. Observe que o "fluxo longo" era, na verdade, uma lógica / requisito do domínio.

Em nenhum momento essa estrutura levou a um código muito, muito insustentável. O problema era que a cadeia de fluxo era muito longa, tornando a lógica de processamento impossível de entender de uma perspectiva superior (ou seja, o quadro geral). Embora pudéssemos entender claramente as etapas de adjacência, não podíamos ver como os dados estavam sendo processados ​​/ modelados em toda a cadeia.

Decidimos então usar um diagrama de atividades, no qual tentamos mapear os diferentes fluxos de programa, decisões, chamadas de método, etc. Escolhemos um diagrama de atividades pelo fato de permitir que você vá do nível de detalhe no procedimento para o nível de classe ou níveis de comunicação / interação. Poderíamos abstrair quando necessário e mergulhar fundo na lógica do algoritmo quando necessário.

Usamos raias para representar classes / módulos e, dentro delas, descrevemos todos os detalhes necessários do que a classe realmente faria. As linhas fluindo de uma raia para outra nos permitiriam entender como as classes realmente se comunicam, e as linhas dentro da própria raia, como aquela classe específica faria seu próprio trabalho.

No final, não era o Diagrama de Atividades mais formal, mas na verdade era bom o suficiente para garantir que pudéssemos compreender o processo de uma perspectiva mais elevada. Isso nos permitiu compreender melhor como nosso sistema interagia e melhorá-lo, principalmente reduzindo o comprimento da corrente.

Depois de refatorar o código e limpar a estrutura da cadeia, tivemos que jogar fora o Diagrama, já que era completamente diferente e mantê-lo daria muito trabalho sem muitos benefícios. Preferimos construir um novo sempre que sentimos a necessidade, usamos diagramas como uma ferramenta de comunicação ao invés de documentação.

Se aquele desenho original em forma de corrente era adequado ou não, seria outra questão. De qualquer forma, depois dessa experiência, acho que os Diagramas de Atividades são um bom lugar para começar se você não quiser ter uma visão melhor do seu sistema / código para fins de "limpeza". A principal desvantagem é que é difícil realmente ter uma estrutura de programa (hierarquias, relações, etc.) de seu código.


Você pode obter isso usando um pandas rolling_max para encontrar o máximo anterior em uma janela para calcular a redução do dia atual, então use um rolling_min para determinar a redução máxima que foi experimentada.

Digamos que quiséssemos a redução máxima móvel de 1 ano (252 dias de negociação) experimentada por um determinado símbolo. O seguinte deve resolver o problema:

Que rende (o azul está executando diariamente a redução de 252 dias, o verde é a redução máxima experimentada de 252 dias no ano anterior):


Bom trabalho com sua calculadora. No geral, é bastante limpo e você tem um uso decente de funções para quebrar comportamentos. Mas, eu sou muito exigente e vou recomendar algumas refatorações realmente agressivas, então não leve nada para o lado pessoal :)

  • Olhe para o PEP8. Na verdade, você está bem perto disso, mas é a formatação padrão que a maioria dos pythoners usa. Existem ótimas ferramentas, como flake8, que reforçam o estilo para você.
    • Os comentários precisam de um espaço após o #
    • Existem alguns espaços obrigatórios entre as frases que estão faltando
    • Sem espaço após a impressão!
    • Quebrar linhas para 79 colunas
    • Aproveitando esse último ponto, você ainda deseja algum tipo de interface REPL se refatorar as coisas em uma função de cálculo. Você deve usar uma função main () para isso e usar o padrão se __name__ == '__main__': main ():
    • Você provavelmente quer erros melhores do que Sua formatação está errada de alguma forma
    • Em perform_operation, você usa float () (presumivelmente em números que você já chamou is_number on). Em Python, preferimos a abordagem "faça primeiro, desculpe-se depois" (ou seja, chame float e, se ocorrer um erro, seremos forçados a interromper a execução e tratá-lo). Normalmente não fazemos coisas como if foo_wont_raise (bar): foo (bar)
    • Eu vejo muito del. Para este aplicativo, eu recomendo evitar isso (e alterar essa lista em geral). A mutação da lista torna muito mais difícil para alguém tentar seguir seu código, porque então, em sua mente, eles têm que acompanhar o que você fez na lista (e eles não podem simplesmente pular para um ponto em seu código para ver o que está acontecendo, eles têm que rastrear todo o caminho até aquele ponto para ver se alguma mutação foi realizada na lista)
    • Realmente não há necessidade de Emergency_count. Seu código não é recursivo, então você não vai atingir o limite de pilha (e se você fizer isso, uma exceção é levantada)
    • Recentemente, passei a achar que você deveria digitar qualquer coisa não trivial em Python. Python é obviamente famoso por não ser tipado, mas mypy realmente progrediu muito e é suficiente para muitos casos de uso. Você verá por que abaixo eu acho que você quer digitar (isso tornará muito mais fácil garantir que sua calculadora esteja correta). Leia sobre isso: https://mypy.readthedocs.io/en/latest/getting_started.html

    Com comentários específicos sobre o seu código pronto. Vamos pensar de forma geral sobre calculadoras e falar sobre padrões úteis para construí-las (e compiladores para linguagens de programação, até certo ponto). O produto final aqui provavelmente será muito mais longo do que o código que você escreveu, mas será muito mais fácil raciocinar e ampliar! Como o resultado é longo e eu fico com fome, omitirei muitas partes desinteressantes (como exceções, que presumirei que existam).

    Você provavelmente não percebeu, mas seu código na verdade já está dividido nas partes certas! Você acabou de nomeá-los de maneira um pouco diferente (e eles não se comportam exatamente da maneira que os padrões os proíbem).

    Intrinsecamente, temos duas preocupações diferentes aqui:

    1. Queremos ser capazes de lidar com muitos espaçamentos arbitrários (ou seja, 1 + 1 é o mesmo que 1 + 1 é o mesmo que 1 + 1) e garantir que não haja caracteres inválidos (ou números inválidos como 123.456.789)
    2. Depois de remover os caracteres válidos e os espaços estranhos, queremos ter certeza de que a expressão está bem formada (os parênteses são balanceados e cada operador tem algo que pode ser avaliado como um número antes e depois) e, em seguida, avaliá-lo

    No projeto do compilador, esses dois são chamados de scanner e analisador, respectivamente (estou usando o analisador livremente aqui, pois em um compilador real um analisador produz um AST, mas no caso de uma calculadora é mais ergonômico apenas para fazer as contas em o analisador). Suas funções são:

    • Scanner: remova o espaçamento em excesso e certifique-se de que todos os caracteres sejam válidos c em '01234567890 + - * /. ()' E de cada caractere válido produza um "Token" (por exemplo, na expressão 2 * 20 + 2 os tokens são 2, ' * ', 20,' + ', 2)
    • Analisador: certifique-se de que uma lista de tokens está bem formada (os parênteses estão equilibrados e cada operador está rodeado por coisas que avaliam como números) e, em seguida, transforme-o em outra coisa (no nosso caso, avalie a matemática)

    Vamos lidar com o scanner primeiro. Ele tem três coisas principais que precisa fazer:

    1. Ignore os espaços em branco (embora isso tenha seus limites, provavelmente não queremos que 123 456 se torne 123456 - em vez disso, provavelmente queremos errar que não podemos ter dois números sequenciais, vamos deixar isso para o analisador, então por enquanto vamos digamos que o scanner emitirá apenas dois tokens para aquele 123 e 456)
    2. Transforme os símbolos em tokens únicos (ex c em '+ - / * ()')
    3. Números de análise (podem ter vários caracteres, podem estar mal formatados como em 123.456.789)

    Antes de realmente implementá-lo, Devo avisar que Python não é a melhor linguagem para expressar conceitos como este (pelo menos fora da caixa, existem bibliotecas que podem ajudar a tornar isso muito mais agradável). No final, algumas das minhas sugestões acima podem precisar ser dobradas ou quebradas. Esqueça, eu adoro Python: P Dito isso, eu ainda diria que não é a melhor linguagem para isso. (Se você está interessado na "melhor maneira" de fazer as coisas, pelo menos na minha opinião, espere alguns anos (não quero te confundir muito!) - dependendo do seu nível de habilidade - e então leia sobre combinadores de analisador e análise monádica)

    O scanner pode ser parecido com isto:

    Sem ficar muito preso a alguns dos padrões python mais avançados que usei, a ideia central está em (o único método público) scan (). É um gerador. Embora ainda tenhamos coisas na string de entrada para analisar, ela faz exatamente o que discutimos: (1) ignora o espaço em branco (2) retorna (rendimento no jargão do gerador, o que significa vagamente que pode retornar muitos) tokens para operadores matemáticos e então (3 ) produz um número se encontrar um.

    Caso você esteja interessado, anteriormente, quando disse que o Python não é adequado para isso, essas preocupações se manifestam no código acima:

    • A necessidade de self._done () (preferencialmente gostaríamos de uma das funções que usamos para lidar com isso para nós, mas infelizmente seus StopIteration s são consumidos quando obtemos deles)
    • O fato de que este loop infinito em personagens inesperados. Para lidar com isso em algum lugar nesse loop while, você precisa introduzir um _check_for_invalid_chars () que faz algo como self._take (lambda c: c not in '01234567890. + - / * ()') e então se não estiver vazio levanta uma exceção sobre um personagem inesperado. Vou deixar isso como um exercício para você.

    Agora, com sorte, você conseguiu descobrir o que _take () faz (é fornecido pelo BaseParser). Caso contrário, o resumo de alto nível é que ele produz caracteres da entrada, desde que eles satisfaçam o predicado (esse é o lambda que é passado). Para fins de integridade, aqui estão as classes utilitárias necessárias para fazer isso funcionar (separei-as porque nosso analisador também as usará!):

    Não vou entrar em detalhes sobre eles (os comentários do documento devem tornar seu comportamento óbvio), mas a necessidade deles é uma boa demonstração de por que o Python não é adequado para essa tarefa fora da caixa.

    Agora temos um scanner funcionando que podemos usar assim:

    Veja como nos dá uma lista de tokens de que precisamos? Agora, podemos passar para o analisador (sem ter que nos preocupar com coisas como espaços em branco inválidos ou números para os quais float gerará erros). É neste ponto que a digitação tornaria as coisas muito mais seguras (observe como nossa lista é de floats e strings - que acreditamos serem operadores), mas optei por omitir para não sobrecarregar.

    Agora, vamos falar sobre o analisador. A razão pela qual vamos reutilizar BaseParser é porque, na verdade, Scanner é um analisador que pega um iterável (especificamente uma string - um iterável de caracteres) e produz algo (tokens). Nosso analisador também pegará um iterável (os tokens produzidos pelo Scanner) e produzirá saída (para a calculadora, este é um único float - ou gerará uma exceção).

    Agora, antes de fazermos isso, precisamos entender um pouco sobre EBNFs. É uma boa maneira de representar linguagens regulares (a entrada para nossa calculadora é). Para sua calculadora, seria algo assim:

    Agora, o que tudo isso significa? As coisas do lado direito dos iguais são chamadas de produções. Por padrão, o primeiro é o "principal". O ("+" | "-") significa que precisamos de um + ou um - em seguida. O <> indica que tudo o que está dentro deles pode ocorrer zero ou mais vezes. Portanto, uma Expressão pode ser apenas um Termo, mas também pode ser um Termo "+" Termo "-" Termo "+" Termo.

    Se você tentar alguns exemplos como 1 * (2 - 3) + 4, verá como ele se divide nas produções na EBNF. Observe como a Expressão e o Fator agrupam as coisas para que a ordem das operações funcione (os mais profundos no aninhamento são * e /, que devem acontecer primeiro). Felizmente, você pode ver como, se pudéssemos transformar o fluxo de tokens nessa estrutura aninhada, poderíamos avaliá-la (por exemplo, avaliar uma expressão avaliando todos os seus termos e, em seguida, adicionando / subtraindo os resultados conforme apropriado, avalie um termo avaliando todos os seus Fator se, em seguida, multiplicando / dividindo os resultados conforme apropriado, e avalie um Fator retornando o número ou avaliando a expressão e retornando-o). Demora um pouco para entender, mas gaste algum tempo com isso e ficará mais claro: http://www.cs.utsa.edu/

    Com isso em mente, vamos escrever um analisador capaz de analisar essas produções. Como discutimos, analisar uma produção deve retornar o valor que ela avalia.

    Há muito o que desempacotar aqui! Primeiro, dê uma olhada no parse. Ele apenas analisa uma expressão e retorna o resultado de avaliá-la (lembra como a primeira produção na EBNF é a "principal"?). Para analisar uma Expressão, analisamos um termo, coletamos qualquer número de ("+" | "-") Termo que o segue e avaliamos essa matemática. Fazemos algo semelhante para Term. Para Factor, tentamos analisar um número (apenas um float) ou um "(" (subexpressão) e, se não conseguirmos encontrar, levantamos um erro.

    Observe como o trabalho real de fazer as contas é feito em evaluate e _evaluate_binary. Mas, criticamente, observe que o primeiro deve receber apenas listas de floats (já devem ser avaliados, o analisador lida com isso por meio de recursão) separados por operadores de mesma precedência. Isso significa que avaliar intencionalmente não pode lidar com [1, '+', 2, '*', 3]. O analisador lida com isso. Primeiro, ele analisaria um termo e chamaria a avaliação ([2, '*', 3]). Isso seria retornado e, em seguida, poderia terminar de analisar a Expressão e chamar a avaliação ([1, '+', 6]).

    Para um exemplo simples de calculadora, este código é decente. Mas você pode ver como as coisas rapidamente saem do controle para EBNFs mais complicados. Isso é o que eu estava aludindo antes.

    Este código precisa do seguinte auxiliar:

    Agora, tudo o que resta é conectar o scanner e o analisador como discutimos antes:

    Esperançosamente, isso deu a você uma visão geral de como os analisadores são projetados e como você pode usar padrões de analisador para tornar sua calculadora muito mais fácil de raciocinar. Devido a este design, você deve ser capaz de fazer o seguinte como um exercício com bastante facilidade:


    3 respostas 3

    Essa questão está mais relacionada à diferença entre um thread e um processo. Aqui está uma dica: Quando se trata de estruturas de agendamento do kernel, a única coisa que o kernel examina são os threads, não os processos.

    Um processo é mais fácil de entender como um grupo de threads. Todos os processos precisam ter pelo menos um thread, e é esse thread que está agendado no sistema operacional, não o processo.

    Portanto, com esse entendimento, em um sistema dual core com dois processos cada um contendo um thread cada, há dois threads no total que são agendados nos dois núcleos.

    Sim, vários processos podem ser executados simultaneamente (sem troca de contexto) em processadores multi-core.

    Se todos os processos forem de thread único conforme você pergunta, 2 processos podem ser executados simultaneamente em um processador dual core.

    O mesmo para processos multithread como você pede, 2 processos novamente, um para cada núcleo podem ser executados ao mesmo tempo.

    Você pode verificar o acima usando a linha de comando 'top' em sistemas Linux ou o 'Gerenciador de Tarefas' no Windows. Inicie dois processos de uso intensivo de CPU para um processador dual core e veja como eles chegam perto de 100% para cada núcleo de CPU e um terceiro processo atrapalha esses 100%. Para um quad core o mesmo ocorre com 4 processos e o quinto e assim por diante.

    Não confunda multi-core com suporte multi-thread. 1 núcleo pode ser capaz de executar apenas 1 ou mais encadeamentos (se for um núcleo de encadeamento único ou multi-encadeamento, respectivamente). Por exemplo, o AMD FX 8350 tem 8 núcleos, cada um capaz de executar um único thread de um processo, enquanto o Intel i7 3770K, por exemplo, tem 4 núcleos, cada um capaz de dois threads de um processo. Mas em algum lugar aqui estamos indo além do que você pediu, então espero que isto cubra tudo!


    Você precisa forçar a substituição dos arquivos que estão causando os erros:

    No seu caso, será:

    Você pode tentar o seguinte comando:

    Se você ainda terminar com o mesmo erro, tente:

    Mesmo que isso não funcione e você ainda receba o mesmo erro, verifique novamente e podemos resolver o problema.

    Pode ser um bug no pacote python-problem-report ou no pacote python-minimal ou uma cópia inválida do pacote.

    Vejo que este é um pacote de proposta precisa. Você pode querer deletar este repositório de sua lista de fontes de software e executar apt-get update de uma sessão de terminal (Ctrl - Alt - T) para recuperar.


    Por padrão, qualquer computador tentará usar todos os seus núcleos quando puder. No entanto, ele só pode conseguir isso quando um aplicativo é multi-threaded. Se não for (ou seja, um script Python que não usa o módulo de threading), ele só pode usar, no máximo, um núcleo. Isso equivale a 25% da CPU em uma CPU de quatro núcleos. Se desejar modificar seu script para usar vários núcleos, você pode dividir seu cálculo em várias partes e multithread como mostrado na documentação do Python.

    Como Anon respondeu, isso não funcionará sem funcionar com o GIL (Global Interpreter Lock) do Python. Isso permite que as tarefas operem (aparentemente) ao mesmo tempo, mas não permite que o código seja executado em vários núcleos. Se você estiver usando módulos escritos em C (por exemplo, numpy), eles podem permitir que você use vários núcleos para contornar essa limitação. Além disso, se isso não for uma opção, o Python oferece multiprocessamento, que permite que você execute qualquer tarefa em vários núcleos.

    Eu queria saber se existe uma maneira simples de "ligar" 100% da CPU para que eu possa executar processos mais rapidamente (como cálculos Python).

    Não no sentido que acho que você está sugerindo. Este não é um problema específico do pi, também, é uma restrição lógica.

    Sozinhos, os computadores atualmente não têm muita capacidade para determinar se um processo em execução como um único thread pode ser executado em paralelo. Observe que, no momento em que eles pudessem ter essa capacidade, não haveria necessidade de programadores de computador, porque um sistema de computador que pudesse fazer isso também poderia escrever seu próprio código 1..

    Considere a seguinte expressão matemática simples:

    Existe algum potencial para que isso seja calculado em paralelo, mas é logicamente limitado. Eu diria que não há sentido em mais de dois tópicos e, mesmo assim, na maioria das vezes, será apenas um:

    O thread # 2 contribuiu calculando 3 + 6 = 9, usado na etapa C pelo thread # 1, economizando uma etapa. Mas isso é até onde o paralelismo pode chegar aqui. Enquanto discussão # 2 poderia calcule 17/9 enquanto o nº 1 está fazendo 6 * 17, fazer isso seria inútil, porque agora você tem dois caminhos diferentes para o mesmo objetivo que não podem ser recombinados. Ou seja, o nº 2 pode continuar trabalhando:

    E acabam com o mesmo resultado do thread # 1 (11.333), mas eles não ajudaram um ao outro além da etapa A, portanto, ter dois deles perseguindo esse objetivo é uma perda de tempo.

    (Observe que este exemplo não é literal, ele pretende demonstrar um princípio lógico. A escala em que as tarefas são encadeadas no código do usuário é muito maior, mas você não precisa de uma lição real em programação multithread para entender a ideia aqui.)

    A exploração de vários processadores requer um código escrito para isso. Você não pode simplesmente pegar qualquer coisa e dizer, "oh, use todos os 4 núcleos e faça isso mais rápido!". Não é isso que aconteceria. Logicamente, muitos (... ou a maioria) problemas e tarefas envolvem etapas que não pode acontecer em paralelo, eles devem acontecer em sequência.

    1. Mas veja o comentário de Felix Dombek abaixo. Eu não sou um especialista em IA. Também pode ser importante notar que, de acordo com os comentários de Peter Corde, conjuntos de instruções e processadores contemporâneos podem ser explorados pelo sistema operacional para otimizar coisas muito granuladas de maneira paralela, e os pipelines de hardware também fazem isso, embora não entre núcleos (um único core tem mais de uma coisa acontecendo, operando no fluxo de instruções em vários pontos antes de sua execução final). Eu estava tentando me ater ao tópico de tópicos de usuários aqui, pois acho que é mais ou menos isso que você quer chegar.

    Outras pessoas estão sugerindo que você dê uma olhada em threading, que é uma resposta válida para a maioria das linguagens, mas eles não levaram em consideração que você está usando python.

    O python GIL não permite que você faça uso eficaz de múltiplos núcleos.

    O uso de múltiplos núcleos requer a exposição explícita do paralelismo em nível de thread para o sistema operacional, o que geralmente requer que o programador escreva um programa multi-thread. (Ou para executar um programa de thread único várias vezes em entradas diferentes, como compilar com make -j4)

    No entanto, compiladores para algumas linguagens suportam paralelização automática. Por exemplo, C ou C ++ com OpenMP pode compilar um loop for () comum em um programa que inicia vários threads.

    Mesmo assim, isso tem que acontecer quando você escreveu ou compilou o programa. Não há como o hardware e sistemas operacionais atuais usarem vários núcleos para acelerar um programa de thread único.

    Relacionado: Como um único thread é executado em vários núcleos ?: resposta: eles não funcionam. Mas existem outros tipos de paralelismo, como o paralelismo de nível de instrução que um único núcleo da CPU encontra e explora para executar um único thread mais rápido do que uma instrução por vez.

    Minha resposta a essa pergunta aborda alguns dos detalhes de como as CPUs modernas encontram e exploram o paralelismo refinado no nível de instrução. (Principalmente com foco em x86). Isso é apenas parte de como as CPUs normais funcionam, por ter várias instruções em andamento ao mesmo tempo, e não é algo que você precise habilitar especialmente. (Existem contadores de desempenho que permitem que você veja quantas instruções por relógio sua CPU conseguiu executar durante a execução de um programa, no entanto, ou outras medidas.)

    Observe que RPi3 usa núcleos de CPU ARM Cortex-A53 em ordem. Cada núcleo é superescalar de 2 largos (2 instruções por clock, conforme o ILP permite), mas não pode reordenar as instruções para encontrar mais paralelismo no nível de instrução e ocultar a latência.

    Ainda assim, a CPU é pipeline, de modo que o número total de instruções em andamento (da busca e decodificação até o estágio de write-back no final do pipeline) é significativo. Quando as dependências de dados não limitam as coisas, pode haver 2 instruções em cada estágio do pipeline em que a CPU está trabalhando, com uma taxa de transferência de 2 instruções por clock. (Isso é o que significa 2-wide.)

    Ele não pode executar instruções fora de ordem, mas com uma ordenação cuidadosa das instruções (geralmente por um compilador), ele ainda pode ocultar a latência de uma instrução que leva vários ciclos para que sua saída esteja pronta. (por exemplo, um carregamento mesmo que acerte no cache ou uma multiplicação levará vários ciclos, em comparação com um add estando pronto no próximo ciclo). O truque é ordenar as instruções asm de forma que haja várias instruções independentes entre aquela que produz um resultado e a que o usa.

    Ter um software (um compilador) programando instruções estaticamente é mais frágil do que ter um hardware que pode reordenar internamente enquanto preserva a ilusão de execução na ordem do programa. É muito difícil para os compiladores fazerem um trabalho tão bom quanto até mesmo uma pequena janela fora de ordem para reordenar instruções porque as falhas de cache são imprevisíveis e é difícil analisar cadeias de dependência entre chamadas de função em tempo de compilação. E o número de registros é limitado sem renomeação de registro de hardware.

    Tudo isso é um pequeno conforto quando seu código é executado mais lentamente do que você gostaria. Claro que há muitas coisas legais sob o capô em um Cortex-A53, mas há mais coisas legais sob o capô em um Cortex-A57 (como execução fora de ordem de até 3 instruções por relógio), e ainda mais em uma grande CPU x86 como Skylake (sem mencionar as diferenças de velocidade de clock).


    Assista o vídeo: Tutorial Qgis - Layout