Tensorflow Tip01

问题:


在跑tensorflow程序时,出现这个问题:

Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA

大概意思是:你的CPU支持AVX扩展,但是你安装的TensorFlow版本无法编译使用

原因:


除了通常的算术和逻辑,现代CPU提供了许多低级指令,称为扩展,例如, SSE2,SSE4,AVX等来自维基百科:

高级矢量扩展(AVX)是英特尔在2008年3月提出的英特尔和AMD微处理器的x86指令集体系结构的扩展,英特尔首先通过Sandy Bridge处理器在2011年第一季度推出,随后由AMD推出Bulldozer处理器在2011年第三季度.AVX提供了新功能,新指令和新编码方案。
特别是,AVX引入了融合乘法累加(FMA)操作,加速了线性代数计算,即点积,矩阵乘法,卷积等。几乎所有机器学习训练都涉及大量这些操作,因此将会支持AVX和FMA的CPU(最高达300%)更快。该警告指出您的CPU确实支持AVX(hooray!)。

在此强调一下:

这只限于CPU。如果你有一个GPU,你不应该关心AVX的支持,因为大多数昂贵的操作将被分派到一个GPU设备上(除非明确地设置)。在这种情况下,您可以简单地忽略此警告。

那为什么会出现这种警告呢?

由于tensorflow默认分布是在没有CPU扩展的情况下构建的,例如SSE4.1,SSE4.2,AVX,AVX2,FMA等。默认版本(来自pip install tensorflow的版本)旨在与尽可能多的CPU兼容。另一个观点是,即使使用这些扩展名,CPU的速度也要比GPU慢很多,并且期望在GPU上执行中型和大型机器学习培训。

解决方法:

如果安装的是GPU版本
如果你有一个GPU,你不应该关心AVX的支持,因为大多数昂贵的操作将被分派到一个GPU设备上(除非明确地设置)。在这种情况下,您可以简单地忽略此警告:
import os
os.environ[‘TF_CPP_MIN_LOG_LEVEL’] = ‘2’

如果安装的是CPU版本(pip install tensorflow)
1.在代码中加入如下代码,忽略警告:
import os
os.environ[‘TF_CPP_MIN_LOG_LEVEL’] = ‘2’

2.编译TensorFlow源码
如果您没有GPU并且希望尽可能多地利用CPU,那么如果您的CPU支持AVX,AVX2和FMA,则应该从针对CPU优化的源构建tensorflow。在这个问题中已经讨论过这个问题,也是这个GitHub问题。 Tensorflow使用称为bazel的ad-hoc构建系统,构建它并不是那么简单,但肯定是可行的。在此之后,不仅警告消失,tensorflow性能也应该改善

感恩

感恩给你机会的人;

感恩给你智慧的人;

感恩一路上陪伴你的人;

保持一颗感恩的心,

您将无所不能 。

吉姆·罗杰斯在《给女儿的礼物》的16条建议

【分享著名投资家吉姆·罗杰斯在《给女儿的礼物》里写的给女儿的16条建议】

1、永远买高质量的商品,它们不但耐用,而且残存价值高。

2、去采购食品之前,记得要吃饱。如果你饿着肚子,将会买回一大堆超出所需的食物。

3、任何贴着“必看”、“必读”、“必须试试”标签的东西,都要避开,尤其是流行的,更要退避三舍。保持良好的教养,无论身处何方,无论对面是谁。这可以把你与他人永久区分开来。在任何社会,都要入乡问俗

4、永远不要问别人赚多少钱以及某样东西值多少钱。不要告诉别人你的东西多少钱买的。不要跟人谈论你赚多少钱以及有多少身家。这是咱们家族根深蒂固的传统,从我的爷爷那辈开始,大家就遵循,因为谈论这些事不但扎眼,而且缺乏教养,至少对我们家而言是这样。证明自己要靠行为,而不是谈钱。如今很多人喜欢谈钱,但我不希望你们这样。

5、如果你们借钱,一定要提前还,至少要按时还。好的信用至关重要,坏的信用记录会困扰你许多年。

6、等你们长大了,会跟男孩们打交道。我希望永远给你们建议和警告。与他们交往的基本原则是:记住他们对你们的需求远远大于你们对他们的需求。当他们狂热追你们的时候,他们会许下千万条诺言。实话告诉你们,这种漂亮话我能说得比他们好。直接忽略他们,对自己诚实。当听到荒谬的许诺、奉承、夸奖时,运用你们的常识。不要追随男孩们转学、迁徙、换工作。让他们来追随你。

7、等你们长大了,要知道你们单独去酒吧几乎没什么好处。吧台的少爷们知道的、经历的比你们多得多,他们会从你们这里讨便宜。

8、要警惕:许多看上去跟你爸爸或爷爷一样年纪的人,并不会把你们当成他的女儿或孙女。

9、在你们28岁之前不要结婚,只有到了这个年纪,你们才会对自身、对世界有所了解。

10、非常重要的一点:要分清好工作与生活的边界。下班后不要跟同事们去吃吃喝喝,你会发现,当老板的从来不会这么干,所以他们才是老板。永远没必要跟老板去喝酒,尤其是两人单独。永远不要在商务午餐时饮酒。最后,还有很重要的一点,避免发生办公室恋情。这件事总是以个人和职业的悲剧而结束。

11、在开长途车或在公共场合露面之前,记得要先去洗手间。

12、学会心算,虽然到处都有计算器,但心算会让你对数字更敏感,从而发现别人视而不见的机会。心算能让你们受益终生。

13、照顾好自己,一个人如果身体不好、休息不好,则很难成功。你们知道妈妈经常给你们擦防晒霜,她是对的。

14、当面临压力和混乱时,记得要冷静。这能让你做出清醒决定,也能让别人注意到你们的冷静沉着。我经常头脑发热,现在常常后悔。

15、与人有约,一定要早到。你这样做,不但能让自己保持高效,还能给人以好印象,因为大多数人都迟到,还有人每次都迟到。

16、一旦你对自己有了清醒的认识和理解,记住你是谁,并且保持住。我有时还会迷失,感情用事,或者做自己不擅长的事。当回首往昔,我真想踢自己,让自己对自己诚实。例如,我投资的时候,有时会跟着感觉走。我经常后悔,自己没有坚守住自己最擅长的领地,无论是投资,还是做别的。

Golang编码规范

package名字:

保持package的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,尽量和标准库不要冲突。包名应该为小写单词,不要使用下划线或者混合大小写

文件命名

  • 所以文件名应一律使用小写
  • 不同单词之间用下划线分词,不要使用驼峰式命名
  • 文件若具有平台特性,应以 文件名_平台.go 命名,比如 utils_ windows.go,utils_linux.go,可用的平台有:windows, unix, posix, plan9, darwin, bsd, linux, freebsd, nacl, netbsd, openbsd, solaris, dragonfly, bsd, notbsd, android,stubs
  • 一般情况下应用的主入口应为 main.go,或者以应用的全小写形式命名。比如MyBlog 的入口可以为 myblog.go
  • 如果是测试文件,可以以 _test.go 结尾

常量命名

目前在网络上可以看到主要有两种风格的写法:

  • 第一种是驼峰命名法,比如 appVersion
  • 第二种使用全大写且用下划线分词,比如 APP_VERSION

这两种风格,没有孰好孰弱,可自由选取,我个人更倾向于使用第二种,主要是能一眼与变量区分开来。

如果要定义多个变量,请使用 括号 来组织。

const (
    APP_VERSION = "0.1.0"
    CONF_PATH = "/etc/xx.conf"
)

变量命名

和常量不同,变量的命名,开发者们的喜好就比较一致了,统一使用 驼峰命名法

  • 在相对简单的环境(对象数量少、针对性强)中,可以将完整单词简写为单个字母,例如:user写为u
  • 若该变量为 bool 类型,则名称应以 HasIsCan 或 Allow 开头。例如:isExist ,hasConflict
  • 其他一般情况下首单词全小写,其后各单词首字母大写。例如:numShips 和 startDate
  • 若变量中有特有名词,且变量为私有,则首单词还是使用全小写,如 apiClient
  • 若变量中有特有名词,但变量不是私有,那首单词就要变成全大写。例如:APIClientURLString

函数命名

  • 函数名还是使用 驼峰命名法
  • 但是有一点需要注意,在 Golang 中是用大小写来控制函数的可见性,因此当你需要在包外访问,请使用 大写字母开头
  • 当你不需要在包外访问,请使用小写字母开头

另外,函数内部的参数的排列顺序也有几点原则

  • 参数的重要程度越高,应排在越前面
  • 简单的类型应优先复杂类型
  • 简单的类型应优先复杂类型

接口命名

使用驼峰命名法,可以用 type alias 来定义大写开头的 type 给包外访问:

type helloWorld interface {
    func Hello();
}

type SayHello helloWorld

当你的接口只有一个函数时,接口名通常会以 er 为后缀

type Reader interface {
    Read(p []byte) (n int, err error)
}

注释规范

包注释:

  • 位于 package 之前,如果一个包有多个文件,只需要在一个文件中编写即可
  • 如果你想在每个文件中的头部加上注释,需要在版权注释和 Package前面加一个空行,否则版权注释会作为Package的注释。

代码注释:

用于解释代码逻辑,可以有两种写法,单行注释使用 // ,多行注释使用 /* comment */

特别注释:

  • TODO:提醒维护人员此部分代码待完成
  • FIXME:提醒维护人员此处有BUG待修复
  • NOTE:维护人员要关注的一些问题说明

Golang学习笔记-2

Golang结构体初始化

Go 通过类型别名(alias types)和结构体的形式支持用户自定义类型。
结构体是复合类型,当需要定义类型,它由一系列属性组成,每个属性都有自己的类型和值的时候,就应该使用结构体,它把数据聚集在一起。

结构体也是值类型,因此可以通过 new 函数来创建

组成结构体类型的那些数据成为字段(fields)。每个字段都有一个类型和一个名字;在一个结构体中,字段名字必须是唯一的。

一,结构体定义

结构体定义的一般方式如下:

type identifier struct {
    field type1
    field type2
}

type T struct {a, b int} 也是合法的语法,它更适用于简单的结构体
结构体里的字段都有 名字,像 field1、field2 等,如果字段在代码中从来也不会被用到,那么可以命名它为 _。
结构体类型和字段的命名遵循可见性规则,所以可能存在一个结构体类型的某些字段是导出的,而另一些没有导出。
结构体的字段可以是任何类型,甚至是结构体本身,也可以是函数或者接口。可以声明结构体类型的一个变量,然后像下面这样给它的字段赋值:

var s T
s.a = 5
s.b = 8

数组也可以看作是一种结构体类型,不过它使用下标而不是具名的字段

二,初始化

方式一:通过 var 声明结构体

在 Go 语言中当一个变量被声明的时候,系统会自动初始化它的默认值,比如 int 被初始化为 0,指针为 nil。
var 声明同样也会为结构体类型的数据分配内存,所以我们才能像上一段代码中那样,在声明了 var s T 之后就能直接给他的字段进行赋值

方式二:使用 new

使用 new 函数给一个新的结构体变量分配内存,它返回指向已分配内存的指针:var t *T = new(T)。

type struct1 struct {
    i1 int
    f1 float32
    str string
}

func main() {
    ms := new(struct1)
    ms.i1 = 10
    ms.f1 = 15.5
    ms.str= "Chris"

    fmt.Printf("The int is: %d\n", ms.i1)
    fmt.Printf("The float is: %f\n", ms.f1)
    fmt.Printf("The string is: %s\n", ms.str)
    fmt.Println(ms)
}

与面向对象语言相同,使用点操作符可以给字段赋值:structname.fieldname = value
同样的,使用点操作符可以获取结构体字段的值:structname.fieldname

方式三:使用字面量

type Person struct {
    name string
    age int
    address string
}

func main() {
    var p1 Person
    p1 = Person{"lisi", 30, "shanghai"}   //方式A
    p2 := Person{address:"beijing", age:25, name:"wangwu"} //方式B
    p3 := Person{address:"NewYork"} //方式C
}

在(方式A)中,值必须以字段在结构体定义时的顺序给出。(方式B)是在值前面加上了字段名和冒号,这种方式下值的顺序不必一致,并且某些字段还可以被忽略掉,就想(方式C)那样。
除了上面这三种方式外,还有一种初始化结构体实体更简短和常用的方式,如下:

ms := &Person{"name", 20, "bj"}
ms2 := &Person{name:"zhangsan"}

&Person{a, b, c} 是一种简写,底层仍会调用 new(),这里值的顺序必须按照字段顺序来写,同样它也可以使用在值前面加上字段名和冒号的写法(见上文的方式B,C)。

表达式 new(Type) 和 &Type{} 是等价的。

三,几种初始化方式之间的区别

到目前为止,我们已经了解了三种初始化结构体的方式:

//第一种,在Go语言中,可以直接以 var 的方式声明结构体即可完成实例化
var t T
t.a = 1
t.b = 2

//第二种,使用 new() 实例化
t := new(T)

//第三种,使用字面量初始化
t := T{a, b}
t := &T{} //等效于 new(T)

使用 var t T 会给 t 分配内存,并零值化内存,但是这个时候的 t 的类型是 T
使用 new 关键字时 t := new(T),变量 t 则是一个指向 T 的指针
从内存布局上来看,我们就能看出这三种初始化方式的区别:
使用 var 声明:

使用 new 初始化:

使用结构体字面量初始化:


Golang学习笔记-1

Go 中的所有东西都是按值传递的。每次调用函数时,传入的数据都会被复制。对于具有值接收者的方法,在调用该方法时将复制该值。

因为所有的参数都是通过值传递的,这就可以解释为什么 *Cat 的方法不能被 Cat 类型的值调用了。任何一个 Cat 类型的值可能会有很多 *Cat 类型的指针指向它,如果我们尝试通过 Cat 类型的值来调用 *Cat 的方法,根本就不知道对应的是哪个指针。相反,如果 Dog 类型上有一个方法,通过 *Dog 来调用这个方法可以确切的找到该指针对应的 Gog 类型的值,从而调用上面的方法。运行时,Go 会自动帮我们做这些,所以我们不需要像 C语言中那样使用类似如下的语句 d->Speak() 。

解释一下导入包名前面的”_”作用:

import 下划线(如:import _ github/demo)的作用:当导入一个包时,该包下的文件里所有init()函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来,仅仅是是希望它执行init()函数而已。这个时候就可以使用 import _ 引用该包。

Golang的interface{}

golang的interface{}一个是可以代表设计模式中的接口,一个可以看做类似C中的void*

强类型语言为了保持动态语言的优势添加的。类似于java中的Object。golang的面向对象设计就是基于interface{}的。

interface和interface{}的区别,一个是go的语法机制用于数据抽象和解耦,一个是这个机制的具体实现。前者应该鼓励使用,而后者应该谨慎使用。

 Go 中的接口,记住下面这些结论:

  • 通过考虑数据类型之间的相同功能来创建抽象,而不是相同字段
  • interface{} 的值不是任意类型,而是 interface{} 类型
  • 接口包含两个字的大小,类似于 (type, value)
  • 函数可以接受 interface{} 作为参数,但最好不要返回 interface{}
  • 指针类型可以调用其所指向的值的方法,反过来不可以
  • 函数中的参数甚至接受者都是通过值传递
  • 一个接口的值就是就是接口而已,跟指针没什么关系
  • 如果你想在方法中修改指针所指向的值,使用 * 操作符

Go中的方法与接收器:

  • 接收器类型
    • 指针接收器:指针类型的接收器由一个结构体的指针组成,更接近于面向对象中的this,由于指针的特性,调用方法时,修改接收器指针的任意成员变量,在方法结束后,修改都是有效的。
    • 非指针接收器:Go语言会在代码运行时将接收器的值复制一份。在非指针接收器的方法中可以获取接收器的成员值,但修改后无效。
  • 如何选择
    • 在计算机中,小对象由于值复制时的速度比较快,所以适合使用非指针接收器。大对象因为复制性能低,适合使用指针接收器,在接收器和参数间传递时不进行复制,只传递指针。
    • 有修改成员变量的需求,用指针类型的接收器。

WordPress后台加载ajax.googleapi.com导致打开很慢的解决方案

打开wordpress后台,发现很卡,通过开发者工具看到是因为加载http://ajax.useso.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css这个元素导致的。

<link rel='stylesheet' id='jquery-ui-smoothness-css'  href='http://ajax.useso.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css' type='text/css' media='all' />

解决方案:

在functions.php里面添加如下代码:

function hc_cdn_callback($buffer) {
    return str_replace('googleapi.com', 'useso.com', $buffer);
}
function hc_buffer_start() {
    ob_start("hc_cdn_callback");
}
function izt_buffer_end() {
    ob_end_flush();
}
add_action('init', 'hc_buffer_start');
add_action('shutdown', 'hc_buffer_end');