Haskell笔记 (9)—— typeclass

Typeclass顾名思义:typeclass,类型的分类,同Java中的interface类似。参看下例:

> :t (==)
(==) :: Eq a => a -> a -> Bool

=>之前的Eq a表示:atypeEqtypeclassaEq的一个实例。

参考资料:
Typeclasses 101
Why sum x y is of type (Num a) => a -> a -> a in Haskell?
Explain Type Classes in Haskell

 

CPU,GPU和GPGPU的区别

下面摘自Why are we still using CPUs instead of GPUs?

GPUs have far more processor cores than CPUs, but because each GPU core runs significantly slower than a CPU core and do not have the features needed for modern operating systems, they are not appropriate for performing most of the processing in everyday computing. They are most suited to compute-intensive operations such as video processing and physics simulations.

GPU(Graphics Processing Unit)core数量比CPU的多,它是显卡(video card)的CPU。由于它的指令集不如CPU强大,但是core数量多,所以适合做一些相对简单的,计算密集性的运算:比如图像处理等等。GPGPU(General Purpose Graphics Processing Unit)则不仅仅只做图像处理的相关运算,也会做一些一般性的运算。

更新:计算机屏幕上的图像是如何显示出来的?这个帖子给了很好的解释:

The GPU has a series of registers that the BIOS maps. These permit the CPU to access the GPU’s memory and instruct the GPU to perform operations. The CPU plugs values into those registers to map some of the GPU’s memory so that the CPU can access it. Then it loads instructions into that memory. It then writes a value to a register that tells the GPU to execute the instructions the CPU loaded into its memory.

The information consists of the software that the GPU needs to run. This software is bundled with the driver and then the driver handles the responsibility split between the CPU and GPU (by running portions of its code on both devices).

The driver then manages a series of “windows” into GPU memory that the CPU can read from and write to. Generally, the access pattern involves the CPU writing instructions or information into mapped GPU memory and then instructing the GPU, through a register, to execute those instruction or process that information. The information includes shader logic, textures, and so on.

简单地讲,CPU会把要显示的图像和指令存到显卡(video card)的register中,然后通知GPU(显卡上的CPU)去执行画图命令。 此外,wiki百科上的这张图形象地描述了整个过程:

CUDA_processing_flow_(En)

参考资料:

 

Haskell笔记 (8)—— 类型变量(type variables)

参看下面程序:

> :t head
head :: [a] -> a

这里的a不是typeHaskell中的类型以大写字母开头),而是type variale,可以代表任一类型,有点类似于其它编程语言的generics。含有type variable的函数称之为polymorphic functions

现在可以知道为什么type名字必须以大写字母开头,这是为了与type variable名字区分开。type variable必须以小写字母开头。 

此外:

You can always tell a type variable from a normal variable by context, because the languages of types and functions are separate: type variables live in type signatures, and regular variables live in normal expressions.

type variable存在于type signature中,而regular variable则存在于正常的表达式中。

 

Mesos笔记 (7)—— 打印VLOG函数输出的log

默认情况下,Mesos不会输出VLOG函数的log信息。如果想输出的话,需要加上GLOG_v=m

$ sudo GLOG_v=3 ./bin/mesos-master.sh --ip=15.242.100.56 --work_dir=/var/lib/mesos
WARNING: Logging before InitGoogleLogging() is written to STDERR
I1229 22:42:38.818521 11830 process.cpp:2426] Spawned process __gc__@15.242.100.56:5050
I1229 22:42:38.818613 11846 process.cpp:2436] Resuming __gc__@15.242.100.56:5050 at 2015-12-30 03:42:38.818540032+00:00
I1229 22:42:38.818749 11847 process.cpp:2436] Resuming __gc__@15.242.100.56:5050 at 2015-12-30 03:42:38.818712832+00:00
I1229 22:42:38.818802 11844 process.cpp:2436] Resuming help@15.242.100.56:5050 at 2015-12-30 03:42:38.818746112+00:00
I1229 22:42:38.819092 11844 process.cpp:2393] Dropping event for process @0.0.0.0:0
I1229 22:42:38.819212 11830 process.cpp:2426] Spawned process help@15.242.100.56:5050
I1229 22:42:38.819373 11858 process.cpp:2436] Resuming __gc__@15.242.100.56:5050 at 2015-12-30 03:42:38.819341056+00:00
I1229 22:42:38.819762 11830 process.cpp:2426] Spawned process logging@15.242.100.56:5050
I1229 22:42:38.819864 11830 process.cpp:2426] Spawned process profiler@15.242.100.56:5050
I1229 22:42:38.819890 11854 process.cpp:2436] Resuming logging@15.242.100.56:5050 at 2015-12-30 03:42:38.819844096+00:00
I1229 22:42:38.819907 11849 process.cpp:2436] Resuming profiler@15.242.100.56:5050 at 2015-12-30 03:42:38.819878144+00:00
......

参考资料:
Re: How can mesos print logs from VLOG function?

 

Mesos笔记 (5)—— 资源

本文参考Building Applications on Mesos

Mesos Slave提供的通用资源包含:CPUsmemorydiskports。需要注意的是CPUs的值定义:

Capture

Slave提供资源的例子:

Capture Slave本身属性的定义:

Capture

Slave为不同的role预留资源有两种方式:
静态方式:在命令行指定不同的role获得不同的资源:

Capture

动态方式:从0.25版本开始,支持通过JSON配置文件和HTTP API方式动态预留资源。

获取资源的函数:

namespace mesos {
namespace internal {
namespace slave {

// TODO(idownes): Move this to the Containerizer interface to complete
// the delegation of containerization, i.e., external containerizers should be
// able to report the resources they can isolate.
Try<Resources> Containerizer::resources(const Flags& flags)
{
  Try<Resources> parsed = Resources::parse(
      flags.resources.getOrElse(""), flags.default_role);

  if (parsed.isError()) {
    return Error(parsed.error());
  }

  Resources resources = parsed.get();

  // NOTE: We need to check for the "cpus" string within the flag
  // because once Resources are parsed, we cannot distinguish between
  //  (1) "cpus:0", and
  //  (2) no cpus specified.
  // We only auto-detect cpus in case (2).
  // The same logic applies for the other resources!
  if (!strings::contains(flags.resources.getOrElse(""), "cpus")) {
    // No CPU specified so probe OS or resort to DEFAULT_CPUS.
    double cpus;
    Try<long> cpus_ = os::cpus();
    if (!cpus_.isSome()) {
      LOG(WARNING) << "Failed to auto-detect the number of cpus to use: '"
                   << cpus_.error()
                   << "'; defaulting to " << DEFAULT_CPUS;
      cpus = DEFAULT_CPUS;
    } else {
      cpus = cpus_.get();
    }

    resources += Resources::parse(
        "cpus",
        stringify(cpus),
        flags.default_role).get();
  }

  // Memory resource.
  ......
}

举个例子:启动Slave时参数为--resources=gpgpus:1,则Resources::parse函数会解析gpgpus资源;由于命令行没有提供CPUmemory之类的参数,需要调用os::cpus()等方法来获得。

 

Kubernetes笔记(7)—— 搭建”k8s on Mesos”注意事项

在本地搭建k8s on Mesos项目时,Mesos client脚本要以root身份运行。另外如果本地环境用到了proxy,一定要注意可能(不确定是否有例外,比如也许取决于你所使用的proxy或操作系统)需要把k8s或者MesosIP地址加入到no-proxy/NO_PROXY环境变量中。具体可参见下列issues
The kubernetes on Mesos can’t run successfully on the same machine
Why does “km controller-manager” think it is an invalid event?
The “km controller-manager” command doesn’t work successfully behind proxy.

 

Go语言的new函数

以下摘自The Go Programming Language

Each call to new returns a distinct variable with a unique address:
p := new(int)
q := new(int)
fmt.Println(p == q) // “false”
There is one exception to this rule: two variables whose type carries no information and is therefore of size zero, such as struct{} or [0]int, may, depending on the implementation, have the same address.
The new function is relatively rarely used because the most common unnamed variables are of struct types, for which the struct literal syntax is more flexible.

Since new is a predeclared function, not a keyword, it’s possible to redefine the name for something else within a function, for example:
func delta(old, new int) int { return new – old }
Of course, within delta, the built-in new function is unavailable.