分类 未分类 下的文章

ASSERT_* : fatal 错误,退出当前程序
EXPECT_* : nonfatal 错误,发生时不退出当前程序

test fixture

对于多个测试使用相同数据设置
继承 testing::Test, 以 protected: 开始。
使用 默认构造函数 或 SetUp() override 函数 为测试初始化
使用 析构函数 或 TearDown() 结束
在 fixture 中使用 TEST_F() 而非 TEST() 定义测试

不同 test 之间不会复用 fixture


::testing::StaticAssertTypeEq<T1, T2>(); assert 两个类型相同,不同时发生编译错误

あぁ! 夏を今もう一回
いまが最高!

时间追溯到几个月前,之前就一直想去一次ASL现场,没去上23年的觉得还是有点可惜的,所以就在想今年跑一趟。公布阵容的时候发现 day3 的阵容很想看:闹闹,TRUE老师,minori,ReoNa ,爱喵,asaka,还有南球和 fripside。所以拜托马哥帮忙搞票。后来又追加了北宇治和B小町,阵容就更加无敌了。

- 阅读剩余部分 -

Kokkos 是 C++ library

hierarchy :
device, host-parallel, host-serial

同步:
Kokkos::fence()

两个问题:

  1. memory space : device / host
  2. memory layout : LayoutLeft / LayoutRight

DualView : 维护在 device memory 上的 Kokkos::View 和其在 host memory 上的 Kokkos::View mirror,同时维护在两个不同 memory space 的 data

  • template argument:DataType, Layout, Device
  • using view_type = Kokkos::DualView<Scalar**, Kokkos::LayoutLeft, Device>

原子操作相关

scatter-add :两个粒子共享邻居,当两个粒子同时更新邻居时可能造成 race
使用 data replication V.S. 使用 atomic operation 解决 race 问题
ScatterView : 在编译时透明地选择处理原子操作方法,对于 CPU 使用 data replication,对于 GPU 使用 atomic operation

`Kokkos::Experimental::contribute(View &dest, Kokkos::Experimental::ScatterView
const &src) 将 ScatterView 的 reduction 结果放回到 dest,可能在 Kokkos::parallel_reduce()` 后调用

检查 Kokkos 属性

判断 layout :

  if (std::is_same<typename decltype(fpair->f)::traits::array_layout, Kokkos::LayoutLeft>::value) {
    printf("array fpair->f is LayoutLeft\n");
  }
  if (std::is_same<typename decltype(fpair->f)::traits::array_layout, Kokkos::LayoutRight>::value) {
    printf("array fpair->f is LayoutRight\n");
  }

获取 stride :

  int strides[2];
  (fpair->x).stride(strides);
  printf("array fpair->x stride : (%d, %d)\n", strides[0], strides[1]);

Access traits

RandomAccess : Kokkos::MemoryTraits<Kokkos::RandomAccess> ,当在 Cuda execution space 中执行时, 如果对于在 CudaSpaceCudaUVMSpace 中的 const View,Kokkos 会使用 texture fetch 访问

Unmanaged View : Kokkos::MemoryTraits<Kokkos::Unmanaged>, 对于一个 raw pointer, Kokkos 不进行 reference counting 和 deallocation

19 年时候学OOP(?)时候的post,更新一下记录一下遇到的新的设计模式:

std::enable_if

用 std::enable_if 增加一个新的函数参数
利用 SFINAE (Substitution Failure Is Not An Error)
模板替换失败不会报错,只会使对应模板不存在

template<int val>
void func(int x, typename std::enable_if<val, int>::type y) {
    printf("in func yes %d\n", x);
}

template<int val>
void func(int x, typename std::enable_if<!val, int>::type y) {
    printf("in func no %d\n", x);
}

int main() {
    func<0>(123, 123);
    
}

当 enable_if 为 false 时,std::enable_if<!val, int> 不存在 type 参数,模板替换错误,此时函数不存在

https://www.runoob.com/design-pattern/design-pattern-intro.html

委托模式


class I /*interface*/ {
public:
    virtual void f() = 0;
    virtual void g() = 0;
};

class A : public I {
public:
    void f(){std::cout << "A::f()" << std::endl;}
    void g(){std::cout << "A::g()" << std::endl;}
};

class B : public I {
public:
    void f(){std::cout << "B::f()" << std::endl;}
    void g(){std::cout << "B::g()" << std::endl;}
};


class C : public I {
public:
    C() { m_i = new A();/*delegation*/ }

    void f(){ m_i->f(); }
    void g(){ m_i->g(); }

    // normal attributes
    void toA(){ m_i = new A(); }
    void toB(){ m_i = new B(); }

private:
    I* m_i;
}

工厂模式

public class ShapeFactory {

   //使用 getShape 方法获取形状类型的对象
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

CRTP

静态多态



template 
struct base
{
    void interface()
    {
         // ...
         static_cast(this)->implementation();
         // ...
    }
};
 
struct derived : base
{
     void implementation()
     {
         // ...
     }
};

visitor模式

将数据与对数据的操作分离


//前向声明,访问者
class Visitor;

//被访问的抽象类,只有一个接口,用来接受访问者
class Object
{
public:
    virtual void accept(Visitor&v) = 0;
};

//具体的被访问的对象,学生。
class StudentA :public Object
{
    std::string name;
    int score;
public:
    StudentA(std::string name_);
    int getScore();
    std::string getName()
    {
        return name;
    }
    void setScore(int num);
    virtual void StudentA::accept(Visitor & v)
    {
        v.visit(this);
    }
};

//抽象访问者,只有一个接口,访问.
class Visitor
{
public:
    virtual void visit(Object* obj)=0;

};

//具体的访问者一,班主任,实现访问(学生并给学分)
class ClassLeader :public Visitor
{
public:
    virtual void visit(Object* obj);
};
//具体的访问者二,校长,实现访问(学生并批评不及格的学生)
class HeadMaster :public Visitor
{
public:
    virtual void visit(Object* obj);
};

observer模式

一些观察者观察一个数据,当数据被改动时通知所有观察者


public class Subject {
   
   private List observers 
      = new ArrayList();
   private int state;
 
   public int getState() {
      return state;
   }
 
   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }
 
   public void attach(Observer observer){
      observers.add(observer);      
   }
 
   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }  
}
public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}
public class BinaryObserver extends Observer{
 
   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Binary String: " 
      + Integer.toBinaryString( subject.getState() ) ); 
   }
}