Почему MPI считают более твердой, чем общая память и Erlang, который рассматривают легче, когда они - оба передача сообщений?

Статический метод определяется не в контексте объекта, а в контексте класса. Вы можете быть смущены присутствием this в статическом методе Groovy. Тем не менее, это только синтаксический сахар, который в конечном итоге заменяет this.name на Animal.class.name.

Если вы скомпилируете класс Animal из вашего примера с включенной статической компиляцией, вы увидите, что он компилируется в следующий эквивалент Java (результат после декомпиляции файла .class ):

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;

public class Animal implements GroovyObject {
    public Animal() {
        MetaClass var1 = this.$getStaticMetaClass();
        this.metaClass = var1;
    }

    public static Object echo() {
        DefaultGroovyMethods.println(Animal.class, Animal.class.getName());
        return null;
    }
}

Вы можете видеть, что следующая строка в методе echo:

DefaultGroovyMethods.println(Animal.class, Animal.class.getName());

работает непосредственно с именем класса Animal. Таким образом, с точки зрения метода echo, не имеет значения, сколько классов его расширяют. Пока эти классы вызывают метод echo, определенный в классе Animal, вы всегда будете видеть Animal напечатанным в результате.

1144 И даже больше. Если вы используете следующий скрипт конфигурации компилятора:

config.groovy

withConfig(configuration) {
    ast(groovy.transform.CompileStatic)
    ast(groovy.transform.TypeChecked)
}

и затем скомпилируете скрипт (назовем его script.groovy ]) используя эту опцию конфигурации с помощью следующей команды:

groovyc --configscript=config.groovy script.groovy

, после декомпиляции файла .class вы увидите нечто подобное:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import groovy.lang.Binding;
import org.codehaus.groovy.runtime.InvokerHelper;

public class script extends groovy.lang.Script {
    public script() {
    }

    public script(Binding context) {
        super(context);
    }

    public static void main(String... args) {
        InvokerHelper.runScript(script.class, args);
    }

    public Object run() {
        Animal.echo();
        return Animal.echo();
    }
}

Вы Можно видеть, что даже если вы вызвали Dog.echo() и Cat.echo() в своем скрипте Groovy, компилятор заменил эти вызовы двойным вызовом Animal.echo(). Это произошло потому, что вызов этого статического метода в любом другом подклассе не имеет никакого значения.

Возможное решение: применение двойной диспетчеризации

Есть один способ получить ожидаемый результат - переопределить статический метод echo в классах Dog и Cat. Я могу предположить, что ваш реальный метод может делать что-то большее, чем примерный метод echo, который вы показали выше, поэтому вам может потребоваться вызвать метод super echo из родительского класса. Но ... есть две проблемы: (1) вы не можете использовать super.echo() в статическом контексте, и (2) это не решает проблему, потому что родительский метод все еще работает в контексте класса Animal. '

Чтобы решить проблему такого рода, вам может понадобиться имитировать технику, называемую double dispatch . Вкратце - когда у нас нет информации о вызывающем объекте в вызываемом методе, давайте разрешим вызывающему передать эту информацию с помощью вызова метода. Рассмотрим следующий пример:

import groovy.transform.CompileStatic

@CompileStatic
class Animal {
    // This is a replacement for the previous echo() method - this one knows the animal type from a parameter
    protected static void echo(Class clazz) {
        println clazz.name
    }

    static void echo() {
        echo(Animal)
    }
}

@CompileStatic
class Dog extends Animal {
    static void echo() {
        echo(Dog)
    }
}

@CompileStatic
class Cat extends Animal {
    static void echo() {
        echo(Cat)
    }
}

Animal.echo()
Dog.echo()
Cat.echo()

Это может звучать как шаблонное решение - для этого требуется реализация метода echo в каждом подклассе. Тем не менее, он инкапсулирует логику echo в методе, который требует параметра Class, поэтому мы можем позволить каждому подклассу вводить свой конкретный подтип. Конечно, это не идеальное решение. Это требует реализации метода echo в каждом подклассе, но другого альтернативного пути нет. Другая проблема заключается в том, что это не мешает вам звонить по телефону Dog.echo(Animal), что вызовет тот же эффект, что и вызов по телефону Animal.echo(). Этот подход с двойной диспетчеризацией больше похож на введение сокращенной версии метода echo, в которой для простоты используется общая реализация статического метода echo.

Я не знаю, решит ли такой подход вашу проблему, но, возможно, он поможет вам найти окончательное решение.

31
задан Lorin Hochstein 9 October 2008 в 00:10
поделиться

4 ответа

Я соглашаюсь со всеми предыдущими ответами, но я думаю ключевое мнение, которое не высказано полностью ясное, то, что одной причиной, что MPI можно было бы считать твердым и легкий Erlang, является соответствие модели к домену.

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

MPI основан на локальной памяти и передаче сообщений, и предназначается для проблем, где перемещение данных является ключевой ролью домена. Высокоэффективные вычисления очень о взятии набора данных для проблемы, и разделение его среди хоста вычисляет ресурсы. И это - довольно тяжелая работа в системе передачи сообщений, поскольку данные должны быть явно распределены с балансировкой в памяти. По существу MPI может быть просмотрен как сдержанная проводимость, которую не масштабирует общая память. И это предназначается для высокоэффективного распространения вычисления через 100k процессоры или больше.

Erlang не пытается достигнуть максимально возможной производительности, скорее разложить естественно параллельную проблему на ее естественные потоки. Это было разработано с полностью другим типом программирования задач в памяти по сравнению с MPI.

, Таким образом, Erlang является лучшим по сравнению с pthreads и другими довольно локальными неоднородными решениями для потока, а не MPI, который действительно нацелен на совсем другое (и в некоторой степени по сути тяжелее) проблемный набор.

37
ответ дан 27 November 2019 в 21:56
поделиться

Параллелизм в Erlang все еще довольно трудно для реализации. Этим я подразумеваю, что все еще необходимо выяснить, как разделить проблему, но существует несколько незначительных вещей, которые упрощают эту трудность по сравнению с некоторой библиотекой MPI в C или C++.

Первый, так как передача сообщений Erlang является первоклассной функцией языка, синтаксический сахар заставляет ее чувствовать себя легче.

кроме того, библиотеки Erlang все создаются вокруг передачи сообщений Erlang. Эта опорная конструкция помогает стимулировать Вас в параллельную-processling землю. Смотрите на компоненты OTP как gen_server, gen_fsm, gen_event. Это очень простые в использовании структуры, которые могут помочь Вашей программе стать параллельной.

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

12
ответ дан 27 November 2019 в 21:56
поделиться

Относительно MPI по сравнению с OpenMP/UPC: MPI вынуждает Вас нарезать проблему в маленьких частях и взять на себя ответственность за перемещение данных. С OpenMP/UPC, "все данные там", просто необходимо разыменовать указатель. Преимущество MPI состоит в том, что 32-512 кластеров ЦП являются намного более дешевыми, чем ЦП 32-512 единственные машины. Кроме того, с MPI расход оплачиваем авансом при разработке алгоритма. OpenMP/UPC может скрыть задержки, что Вы достигнете время выполнения, если Ваша система будет использовать NUMA (и все большие системы делают) - то Ваша программа не масштабируется, и это будет требовать времени к фигуре почему.

0
ответ дан 27 November 2019 в 21:56
поделиться

Я думаю, что это имеет некоторое отношение к мышлению, когда Вы программируете с MPI и когда Вы программируете с Erlang. Например, MPI не создается - на язык, тогда как Erlang имеет встроенную поддержку передачи сообщений. Другая возможная причина является разъединением между простой отправкой/получением сообщений и разделением решений в параллельные единицы выполнения.

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

С MPI, с другой стороны, Вы вынуждены думать просто о фактической передаче сообщений, но не действительно разложении работы. Этот кадр взглядов требует своего рода контекстного переключения между записью решения и обменивающейся сообщениями инфраструктурой в Вашем коде.

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

8
ответ дан 27 November 2019 в 21:56
поделиться
Другие вопросы по тегам:

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