C/C++使用指南
auto:for(auto& name : input){}
c++中name mingling较C更为复杂
创建静态链接库
gcc -fPIC -c a.c
gcc -fPIC -c b.c
gcc -shared -o libfoo.so a.o b.o
auto:for(auto& name : input){}
c++中name mingling较C更为复杂
创建静态链接库
gcc -fPIC -c a.c
gcc -fPIC -c b.c
gcc -shared -o libfoo.so a.o b.o
Kokkos 是 C++ library
hierarchy : device
, host-parallel
, host-serial
同步:Kokkos::fence()
两个问题:
DualView : 维护在 device memory 上的 Kokkos::View
和其在 host memory 上的 Kokkos::View
mirror,同时维护在两个不同 memory space 的 data
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()` 后调用
判断 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]);
RandomAccess
: Kokkos::MemoryTraits<Kokkos::RandomAccess>
,当在 Cuda
execution space 中执行时, 如果对于在 CudaSpace
或 CudaUVMSpace
中的 const View,Kokkos 会使用 texture fetch 访问
Unmanaged View
: Kokkos::MemoryTraits<Kokkos::Unmanaged>
, 对于一个 raw pointer, Kokkos 不进行 reference counting 和 deallocation
CPU 结构:
threads per core : 超线程
cores per socket : 每个 socket 核数
sockets
每个 mpi 进程有 affinity mask,长度为 CPU cores--bind-to core
: affinity mask 中只有对应 core 一位被 set--bind-to socket
: affinity mask 中 socket 对应 所有 core 被 set--bind-to none
--map-by node
--map-by socket
--map-by node:PE=8
: PE为每个进程分配的物理核数
hostfile :
i1 slots=2 max-slots=8
i2 slots=2 max-slots=8
`which mpirun` -np 2 --host i1:1,i2:1 hostname
`which mpirun` -np 4 --hostfile ./hostfile hostname
使用脚本时开头要加 #!/bin/bash
OMP_DISPLAY_ENV=true
输出 OMP 绑定情况OMP_PLACES=threads
, OMP_PLACES=cores
, OMP_PLACES=sockets
hyperthread cpu 分布:/sys/devices/system/cpu/cpu0/topology$ cat thread_siblings_list
#include <omp.h>
#include <sched.h>
#pragma omp parallel
{
int id = omp_get_thread_num();
int max_threads = omp_get_num_threads();
int cpuid = sched_getcpu();
printf("hello from cpu: %d thread: %d out of %d threads @ rank = %d\n", cpuid, id, max_threads, rank);
}
19 年时候学OOP(?)时候的post,更新一下记录一下遇到的新的设计模式:
用 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;
}
}
静态多态
template
struct base
{
void interface()
{
// ...
static_cast(this)->implementation();
// ...
}
};
struct derived : base
{
void implementation()
{
// ...
}
};
将数据与对数据的操作分离
//前向声明,访问者
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);
};
一些观察者观察一个数据,当数据被改动时通知所有观察者
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() ) );
}
}