События и очереди команд OpenCL

Я работаю над переводом приложения CUDA (, если вы должны знать ]) в OpenCL. Исходное приложение использует CUDA API в стиле C с одним потоком, чтобы избежать автоматического ожидания занятости при чтении результатов.

Теперь я заметил, что очереди команд OpenCL очень похожи на потоки CUDA. Но в команда чтения устройства , а также в командах write и kernel execute также отмечают параметры для событий. У меня есть интерфейс, давайте назовем его IProtocol, который реализуется двумя отдельными классами. Мы смотрим более 600 строк кода здесь. Подавляющее большинство ...

У меня есть проблема дизайна, которую я хотел бы решить. У меня есть интерфейс, давайте назовем его IProtocol , который реализуется двумя отдельными классами. Мы смотрим более 600 строк кода здесь. Подавляющее большинство того, что они делают, - то же самое, за исключением для некоторых конкретных областей, таких как DiffStuff ();

Текущая структура выглядит примерно так:

public class Protocol1 : IProtocol
{
  MyInterfaceMethod1()
  {
     Same1();
     DiffStuff();
     Same2();
  }
}

И

 public Протокол класса 2: IProtocol
{
 MyInterfaceMethod1 ()
 {
 Same1 ();
 Same2 ();
 }
}

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

Я подумываю об изменении реализации Protocol1 для наследования от protocol2, например, так (Protocol2 в основном останется прежним, за исключением того, что мне придется обернуть Same1 () и Same2 () в частные методы.)

public class Protocol1 : Protocol2
{
  void Same1()
  {
     base.Same1();
  }

  void Same2()
  {
     base.Same2();
  }

  MyInterfaceMethod1()
  {
     Same1();
     DiffStuff();
     Same2();
  }
}  

Правильный ли это способ решения этой проблемы?

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

  • Жлоберу
  • Хансу Пассанту
  • Джеффу Стерну

7
задан Community 23 May 2017 в 10:33
поделиться

6 ответов

    /// <summary>
    /// IProtocol interface
    /// </summary>
    public interface IProtocol
    {
        void MyInterfaceMethod1();
        void Same1();
        void Same2();
    }

затем...

public abstract class ProtocolBase : IProtocol
{
    #region IProtocol Members

    public void MyInterfaceMethod1()
    {
        // Implementation elided...
    }

    public void Same1()
    {
        // Implementation elided...
    }

    public void Same2()
    {
        // Implementation elided...
    }

    public abstract void DiffStuff();

    #endregion
}

наконец...

public sealed class Protocol1 : ProtocolBase
{
    public override void DiffStuff()
    {
        // Implementation elided...
    }
}

public sealed class Protocol2 : ProtocolBase
{
    public override void DiffStuff()
    {
        // Implementation elided...
    }
}
7
ответ дан 6 December 2019 в 13:59
поделиться

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

Однако вам следует рассмотреть возможность использования композиции вместо наследования. Оба подхода имеют различные преимущества и недостатки, но композиция часто (обычно?) лучше*:

 public class Protocol {

      private ISpecialHandler specialHandler;

      public Protocol() {}

      public Protocol(ISpecialHandler specialHandler) {
          this.specialHandler = specialHandler;
      }

      void Same1() {}
      void Same2() {}

      public void DoStuff() {
          this.Same1();
          if (this.specialHandler != null) {
              this.specialHandler.DoStuff();
          }
          this.Same2();
      }
 }

Вызывающие стороны могут передавать экземпляры объектов (стратегии), которые обеспечивают специализированные алгоритмы для обработки любого случая:

 Protocol protocol1 = new Protocol(new DiffStuffHandler());
 protocol1.DoStuff();

*Подробное объяснение того, почему композиция обычно лучше наследования в вашем случае, смотрите в Patterns I Hate #2: Template Method.

4
ответ дан 6 December 2019 в 13:59
поделиться

Вы можете рассмотреть, работает ли этот тип паттерна:

public class ProtocolHelper
{
    public void Same1() {}
    public void Same2() {}
}

public class Protocol1 : IProtocol
{
    private readonly ProtocolHelper _helper = new ProtocolHelper();

    void MyInterfaceMethod1()
    {
        _helper.Same1();
        DiffStuff();
        _helper.Same2();
    }
}

Вы можете определить, имеет ли это смысл, посмотрев, сможете ли вы придумать хорошее имя для класса 'ProtocolHelper'. Если имя естественным образом вытекает из вашей логики, то это хороший способ разбить класс на части. Для того чтобы это работало, вам может понадобиться передать некоторые зависимости (например, приватные поля) в качестве параметров методов.

0
ответ дан 6 December 2019 в 13:59
поделиться

Я согласен с MathEpic. Я бы использовал Шаблонный метод шаблона.

-1
ответ дан 6 December 2019 в 13:59
поделиться

Не совсем. Нет смысла добавлять методы Same1 и Same2, вы наследуете их от ProtocolBase. А DiffStuff () должен быть виртуальным методом, чтобы вы могли его переопределить и придать ему другое поведение.

5
ответ дан 6 December 2019 в 13:59
поделиться

Я лучше проектирую (на мой взгляд)

public abstract class Protocol_common : IProtocol 
{ 
  MyInterfaceMethod1() 
  { 
     Same1(); 
     DiffStuff(); 
     Same2(); 
  } 

  abstract void DiffStuff();

}

public class Protocol1 : Protocol_common
{ 
  DiffStuff() 
  { 
      /// stuff here.
  } 
}

public class Protocol2 : Protocol_common
{ 
  DiffStuff() 
  { 
      /// nothing here.
  } 
}

(На самом деле это больше псевдокода, чем правильный C #, но я достиг лучших результатов)

0
ответ дан 6 December 2019 в 13:59
поделиться
Другие вопросы по тегам:

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