Укажите процессор или графический процессор для нескольких моделей tenorflow java

Я использую Tensorflow java API (1.8.0), где загружаю несколько моделей (в разных сеансах). Эти модели загружаются из файлов .pb с использованием метода SavedModelBundle.load (...). Эти файлы .pb были получены путем сохранения моделей Кераса.

Допустим, я хочу загрузить 3 модели A, B, C. Для этого я реализовал класс java Модель:

public class Model implements Closeable {

private String inputName;
private String outputName;
private Session session;
private int inputSize;

public Model(String modelDir, String input_name, String output_name, int inputSize) {
    SavedModelBundle bundle = SavedModelBundle.load(modelDir, "serve");
    this.inputName = input_name;
    this.outputName = output_name;
    this.inputSize = inputSize;
    this.session = bundle.session();
}

public void close() {
    session.close();
}

public Tensor predict(Tensor t) {
    return session.runner().feed(inputName, t).fetch(outputName).run().get(0);
}
}

Затем я легко могу создать экземпляры 3 объектов Модель, соответствующих моим моделям A, B и C, с этим классом и сделать прогнозы с этими 3 моделями в той же программе Java. Я также заметил, что если у меня есть графический процессор, на него загружаются 3 модели.

Однако Я хотел бы, чтобы только модель A работала на графическом процессоре, а две другие - на CPU.

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

    public Model(String modelDir, String input_name, String output_name, int inputSize) {
      SavedModelBundle bundle = SavedModelBundle.load(modelDir, "serve");
      this.inputName = input_name;
      this.outputName = output_name;
      this.inputSize = inputSize;
      ConfigProto configProto = ConfigProto.newBuilder().setAllowSoftPlacement(false).setGpuOptions(GPUOptions.newBuilder().setVisibleDeviceList("").build()).build();
      this.session = new Session(bundle.graph(),configProto.toByteArray());
}

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

Спасибо за ваш ответ.

Я не знаком с Java API Tensorflow. Но я знаю, что с его API Python вы можете делать что-то вроде: with tf.device('/cpu:0'): # your graph или with tf.device('/gpu:0'): # your graph. Я думаю, что в Java должно быть что-то подобное. Итак, я поискал и нашел этот ответ на SO. Я думаю (особенно последний фрагмент кода) - это решение, которое вы ищете, но я не уверен. Пожалуйста, подтвердите это.

today 13.07.2018 21:21
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
10
1
860
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете установить конфигурацию device вашего графика тензорного потока. Вот соответствующий код: [источник].

...
byte[] config = ConfigProto.newBuilder()
                           .setLogDevicePlacement(true)
                           .setAllowSoftPlacement(true)
                           .build()
                           .toByteArray()

Session sessions[] = new Session[numModels];

// function to move the graph definition to a new device 
public static byte[] modifyGraphDef(byte[] graphDef, String device) throws Exception {
  GraphDef.Builder builder = GraphDef.parseFrom(graphDef).toBuilder();
  for (int i = 0; i < builder.getNodeCount(); ++i) {
    builder.getNodeBuilder(i).setDevice(device);
  }
  return builder.build().toByteArray();
} 

graphA.importGraphDef(modifyGraphDef(graphDef, "/gpu:0"));
graphB.importGraphDef(modifyGraphDef(graphDef, "/cpu:0"));

Это, вероятно, было бы чище, чем более очевидная установка переменной среды CUDA_VISIBLE_DEVICES на "" после загрузки первой модели.

@alex в качестве некоторой отладки, устанавливает CUDA_VISIBLE_DEVICES в пустую строку, предотвращает переход всех моделей на GPU (как и должно)

modesitt 17.07.2018 17:43

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

Alex 18.07.2018 14:30
Ответ принят как подходящий

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

Затем вы можете протестировать:

ConfigProto configProto = ConfigProto.newBuilder()
                .setAllowSoftPlacement(true) // allow less GPUs than configured
                .setGpuOptions(GPUOptions.newBuilder().setPerProcessGpuMemoryFraction(0.01).build())
                .build();
SavedModelBundle  bundle = SavedModelBundle.loader(modelDir).withTags("serve").withConfigProto(configProto.toByteArray()).load();

Приведенные выше ответы не помогли мне. Использование putDeviceCount ("GPU", 0) заставляет TF использовать CPU. Он работает в версии 1.15.0. Вы можете загружать одну и ту же модель как в процессор, так и в графический процессор, и если графический процессор выдает Resource is made: OOM при выделении тензора, используйте модель процессора для прогнозирования.

ConfigProto configProtoCpu = ConfigProto.newBuilder().setAllowSoftPlacement(true).putDeviceCount("GPU", 0)
                    .build();
SavedModelBundle modelCpu=SavedModelBundle.loader(modelPath).withTags("serve")
                    .withConfigProto(configProtoCpu.toByteArray()).load();

ConfigProto configProtoGpu = ConfigProto.newBuilder().setAllowSoftPlacement(true)
    .setGpuOptions(GPUOptions.newBuilder().setAllowGrowth(true).build()).build();
SavedModelBundle modelgpu = SavedModelBundle.loader(modelPath).withTags("serve")
                    .withConfigProto(configProtoGpu.toByteArray()).load();

Другие вопросы по теме