Функциональное программирование позволяет лучшую оптимизацию компилятора во время выполнения?

Можно использовать модуль pygame surfarray. Этот модуль имеет 3-й метод возврата пиксельной матрицы, названный pixels3d (поверхность). Я показал использование ниже:

from pygame import surfarray, image, display
import pygame
import numpy #important to import

pygame.init()
image = image.load("myimagefile.jpg") #surface to render
resolution = (image.get_width(),image.get_height())
screen = display.set_mode(resolution) #create space for display
screen.blit(image, (0,0)) #superpose image on screen
display.flip()
surfarray.use_arraytype("numpy") #important!
screenpix = surfarray.pixels3d(image) #pixels in 3d array:
#[x][y][rgb]
for y in range(resolution[1]):
    for x in range(resolution[0]):
        for color in range(3):
            screenpix[x][y][color] += 128
            #reverting colors
screen.blit(surfarray.make_surface(screenpix), (0,0)) #superpose on screen
display.flip() #update display
while 1:
    print finished

я надеюсь полезный. Последнее слово: экран заблокирован в течение времени жизни screenpix.

22
задан 2 revs, 2 users 93% 10 December 2009 в 20:08
поделиться

9 ответов

Have you seen this "good math, bad math" blog post?

I program in C, assembly and OCaml. I sometimes look at the assembly generated by the C compiler. It is dreafully inefficient. Often I notice that a global variable is re-loaded again and again, when it's clear (to someone aware of the logic of the program) that it doesn't change during the execution of the function, but because the function manipulates pointers, the compiler cannot assume that the variable isn't touched. One simple way to fix this when you notice it is to copy the contents of the global into a local at the beginning of the function, this way you keep the portability of C but get assembly-like performance...

But you shouldn't have to do this, and indeed, with a higher-level language, you don't have too, because there are less pointer, casts and other low-level constructs that let you get close to the hardware when you want to but actually get in the way of automatic optimization.

14
ответ дан 29 November 2019 в 04:26
поделиться

Чтобы прояснить, только потому, что компилятор для функционального языка может оптимизировать лучше, не означает, что это действительно так . Любая безумная оптимизация по определению приводит к неожиданному поведению во время выполнения, что почти наверняка приводит к ошибкам. Итак, чтобы развеять большое заблуждение: теоретически программы на Haskell могут быть распараллелены компилятором «бесплатно», но на самом деле это не так и не должно быть.

Я думаю, что дни, когда оптимизация компилятора была королем, закончились . Когда тактовая частота была основным узким местом для оптимизации производительности, например, развертывание цикла было необходимо. Однако для подавляющего большинства приложений проблема заключается не в чистой скорости ЦП, а в других факторах, таких как пропускная способность сети, дисковый ввод-вывод и / или скорость используемого вами алгоритма.

Насколько мне известно, не существует оптимизации компилятора для повторной реализации вашего кода, например, для использования параллельного шаблона проектирования. Другими словами, если вы используете пузырьковую сортировку с каждой оптимизацией компилятора, о которой вы можете подумать, я использую быструю сортировку. В большинстве ситуаций разумные деньги заключаются в реализации Quick Sort.

Функциональное программирование имеет большую ценность, но «потому что они работают быстрее» не следует принимать во внимание.

9
ответ дан 29 November 2019 в 04:26
поделиться

нет побочных эффектов и значений не мутировать, это облегчает компилятор, чтобы увеличить время выполнения оптимизации

В некотором смысле да - пока вы не поймете, что побочные эффекты и изменяемые значения сами по себе являются оптимизацией.

9
ответ дан 29 November 2019 в 04:26
поделиться

Check out the Haskell vs C comparison here:

http://www.haskell.org/haskellwiki/Introduction#Quicksort_in_Haskell

You will note that the Haskell verison is much shorter. However, the page goes on to say that while the c version is arguably more complex, it also sorts in place, while the Haskell version must allocate much more memory to work.

So, by definition, if you want the ability to get extreme fine-tuning of the performance, the c algorithm is the better approach.

5
ответ дан 29 November 2019 в 04:26
поделиться

As a general rule, compiler optimization makes a difference in code that:

  1. It actually compiles. If most of the time the bottom of the call stack is inside code that the compiler never sees, it can optimize all it wants, but will have no effect.

  2. That consumes a significant fraction (like 10% or more) of run-time when the user or others are actually waiting for the program. If nobody's waiting for if, the optimization will never be noticed.

  3. That contains no function calls. If the code being compiled contains function calls, the program counter is almost always elsewhere.

So you'll never notice unless you write heavy crunching algorithms working on lots of data without calling out to code you don't compile. Like the minute you put string-compare into a sort algorithm, optimization is academic.

0
ответ дан 29 November 2019 в 04:26
поделиться

I think you should be talking about language models rather than compiler optimizations. imperative procedural/functional both have their own area where they shine. I will give you two examples:

Imperative - procedural

Erlang ( a functional language). Took the approach of shared state with their built in Mnesia database -- it is inherently non-functional as a update transaction locks a database resource gets a value, changes it, and writes it back. They did this for performance because they recognize that speed is important in this area and if they didn't do this Erlang would be useless for the problems they were trying to solve (can you imagine writing an entire database file out each time you make a change ? ) =D.

Pure Functional

Functional vs. non-function in terms of performance allowed by the model is a funny subject area. Taking the functional viewpoint; Erlang can saturate the core's the machine is running when problems are inherently concurrency oriented. Some tests showed the YAWS web-server handling 100k connections where Apache fell over at 4k :D Ejabberd can also handle MUCH more load than traditional message switches. What I am trying to say is that pure functional language can have a runtime engine which can massively parallelize the application across large amounts of cores. You can't easily do this with imperative procedural code.

Different models are suitable for different problems. I personally think you can optimize procedural code much better than functional code, functional code still executes as procedural code, and it is interpreted :P I have studied compiler theory, and I honestly can't think of mind-blowing code-transformations I would apply to functional code before I executed it. You have tail-recursion and lazy-evaluation, but surely those are features of the programming model.

4
ответ дан 29 November 2019 в 04:26
поделиться

Когда дело доходит до C или C ++, требуется много оптимизации компилятора, и компилятор может решить отказаться от любой из хороших маленьких идей, поскольку он может гораздо лучше определить, какая оптимизация для использования в определенном месте (например, встраивания) и учитывает такие вещи, как конвейеры команд и т. д. Архитектура оборудования стала слишком сложной для людей, чтобы напрямую программировать оборудование. в настоящее время даже простые компиляторы используют значительные объемы оптимизации. использование фанковых приемов менее читаемо и труднее для компилятора оптимизировать, потому что ручная оптимизация снижает семантику. поэтому, даже если вы пишете C или C ++, ваш выбор - либо выстрелить себе в ногу, либо позволить компилятору сделать оптимизацию для этого. Об этом и говорится в большинстве из 9 513 227 строк кода в GCC.

я думаю, очень важно, чтобы программное обеспечение было проверяемым, надежным, поддерживаемым, гибким и многоразовым / расширяемым. чем выразительнее и лаконичнее язык, тем легче разработчикам соответствовать этим критериям.

есть последний, но важный критерий для программного обеспечения: эффективность. Важный вопрос в том, как вы измеряете эффективность. Я бы измерил это чистой скоростью и масштабируемостью. эти два понятия не исключают друг друга, однако, используя язык, который тесно связан с концепциями параллельных / распределенных вычислений и имеет особенности проектирования языковых конструкций, разрабатывать такие алгоритмы гораздо проще. конечно, это работало бы быстрее, если бы вы выполняли всю диспетчеризацию самостоятельно, но это чревато ошибками и требует много времени.

вам также следует учитывать, что оптимизация компилятора имеет линейный эффект. Если ваши алгоритмы или дизайн вашей системы плохо масштабируются, это не решит проблему за вас. если он хорошо масштабируется, вы можете решить проблемы с производительностью, добавив больше оборудования, что всегда дешевле, чем время разработки.

В конце концов, выбор, который вы делаете,

1
ответ дан 29 November 2019 в 04:26
поделиться

Вот пример в Clojure - итерация по списку вещей с использованием некоторой функции.

(map some-fn big-list)

Что круто, так это то, что вы можете распараллелить его (несколько ядер, а не нескольких машин) одним символом:

(pmap some-fn big-list)

Язык / компилятор, обеспечивающий работу pmap , был бы невозможен без чистых функций и неизменяемых структур данных.

Это все еще экспериментальная функция. Но функциональное программирование без побочных эффектов значительно упрощает выполнение многоядерных программ.

3
ответ дан 29 November 2019 в 04:26
поделиться

Это просто анекдотический вклад:

Я обучил себя (некоторым) Clojure, используя математические задачи из Project Euler . Я решил некоторые проблемы, используя ленивые последовательности.

Я обнаружил, что, когда я применял подсказки типов, производительность для длинных вычислений (где запуск не имеет значения) обычно была сопоставима с вручную настроенной Java.

Это почти должно быть ожидалось: Clojure заранее компилирует байт-код JVM, и он работает с той же оптимизационной средой выполнения, что и код Java.

На какое-то время меня поразило то, что некоторые вычисления занимали несколько ядер, хотя я этого не делал (сознательно ) запрограммирован при любом распараллеливании. Кажется, что среда выполнения может воспользоваться возможностью распараллелить генерацию и потребление ленивых последовательностей.

Мой вывод:

1
ответ дан 29 November 2019 в 04:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: