Merge pull request #54 from LCTT/master

update
This commit is contained in:
MjSeven 2018-07-17 10:54:51 +08:00 committed by GitHub
commit fdfe0df165
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 2186 additions and 154 deletions

View File

@ -0,0 +1,147 @@
如何在绝大部分类型的机器上安装 NVIDIA 显卡驱动
======
![](https://fedoramagazine.org/wp-content/uploads/2018/06/nvidia-816x345.jpg)
无论是研究还是娱乐,安装一个最新的显卡驱动都能提升你的计算机性能,并且使你能全方位地实现新功能。本安装指南使用 Fedora 28 的新的第三方仓库来安装 NVIDIA 驱动。它将引导您完成硬件和软件两方面的安装,并且涵盖需要让你的 NVIDIA 显卡启动和运行起来的一切知识。这个流程适用于任何支持 UEFI 的计算机和任意新的 NVIDIA 显卡。
### 准备
本指南依赖于下面这些材料:
* 一台使用 [UEFI][1] 的计算机,如果你不确定你的电脑是否有这种固件,请运行 `sudo dmidecode -t 0`。如果输出中出现了 “UEFI is supported”你的安装过程就可以继续了。不然的话虽然可以在技术上更新某些电脑来支持 UEFI但是这个过程的要求很苛刻我们通常不建议你这么使用。
* 一个现代的、支持 UEFI 的 NVIDIA 的显卡
* 一个满足你的 NVIDIA 显卡的功率和接线要求的电源(有关详细信息,请参考“硬件和修改”的章节)
* 网络连接
* Fedora 28 系统
### 安装实例
这个安装示例使用的是:
* 一台 Optiplex 9010 的主机(一台相当老的机器)
* [NVIDIA GeForce GTX 1050 Ti XLR8 游戏超频版 4 GB GDDR5 PCI Express 3.0 显卡][2]
* 为了满足新显卡的电源要求,电源升级为 [EVGA 80 PLUS 600 W ATX 12V/EPS 12V][3]这个最新的电源PSU比推荐的最低要求高了 300 W但在大部分情况下满足推荐的最低要求就足够了。
* 然后当然的Fedora 28 也别忘了.
### 硬件和修改
#### 电源PSU
打开你的台式机的机箱,检查印刷在电源上的最大输出功率。然后,查看你的 NVIDIA 显卡的文档,确定推荐的最小电源功率要求(以瓦特为单位)。除此之外,检查你的显卡,看它是否需要额外的接线,例如 6 针连接器,大多数的入门级显卡只从主板获取电力,但是有一些显卡需要额外的电力,如果出现以下情况,你需要升级你的电源:
1. 你的电源的最大输出功率低于显卡建议的最小电源功率。注意:根据一些显卡厂家的说法,比起推荐的功率,预先构建的系统可能会需要更多或更少的功率,而这取决于系统的配置。如果你使用的是一个特别耗电或者特别节能的配置,请灵活决定你的电源需求。
2. 你的电源没有提供必须的接线口来为你的显卡供电。
电源的更换很容易,但是在你拆除你当前正在使用的电源之前,请务必注意你的接线布局。除此之外,请确保你选择的电源适合你的机箱。
#### CPU
虽然在大多数老机器上安装高性能的 NVIDIA 显卡是可能的,但是一个缓慢或受损的 CPU 会阻碍显卡性能的发挥,如果要计算在你的机器上瓶颈效果的影响,请点击[这里][4]。了解你的 CPU 性能来避免高性能的显卡和 CPU 无法保持匹配是很重要的。升级你的 CPU 是一个潜在的考虑因素。
#### 主板
在继续进行之前,请确认你的主板和你选择的显卡是兼容的。你的显卡应该插在最靠近散热器的 PCI-E x16 插槽中。确保你的设置为显卡预留了足够的空间。此外,请注意,现在大部分的显卡使用的都是 PCI-E 3.0 技术。虽然这些显卡如果插在 PCI-E 3.0 插槽上会运行地最好,但如果插在一个旧版的插槽上的话,性能也不会受到太大的影响。
### 安装
1、 首先,打开终端更新你的包管理器(如果没有更新的话):
```
sudo dnf update
```
2、 然后,使用这条简单的命令进行重启:
```
reboot
```
3、 在重启之后,安装 Fedora 28 的工作站的仓库:
```
sudo dnf install fedora-workstation-repositories
```
4、 接着,设置 NVIDIA 驱动的仓库:
```
sudo dnf config-manager --set-enabled rpmfusion-nonfree-nvidia-driver
```
5、 然后,再次重启。
6、 在这次重启之后,通过下面这条命令验证是否添加了仓库:
```
sudo dnf repository-packages rpmfusion-nonfree-nvidia-driver info
```
如果加载了多个 NVIDIA 工具和它们各自的 spec 文件,请继续进行下一步。如果没有,你可能在添加新仓库的时候遇到了一个错误。你应该再试一次。
7、 登录,连接到互联网,然后打开“软件”应用程序。点击“加载项>硬件驱动> NVIDIA Linux 图形驱动>安装”。
如果你使用更老的显卡或者想使用多个显卡,请进一步查看 [RPMFusion 指南][8]。最后,要确保启动成功,设置 `/etc/gdm/custom.conf` 中的 `WaylandEnable=false`,确认避免使用安全启动。
接着,再一次重启。
8、这个过程完成后关闭所有的应用并**关机**。拔下电源插头,然后按下电源按钮以释放余电,避免你被电击。如果你对电源有开关,关闭它。
9、 最后,安装显卡,拔掉老的显卡并将新的显卡插入到正确的 PCI-E x16 插槽中。成功安装新的显卡之后,关闭你的机箱,插入电源 ,然后打开计算机,它应该会成功启动。
**注意:** 要禁用此安装中使用的 NVIDIA 驱动仓库,或者要禁用所有的 Fedora 工作站仓库,请参考这个 [Fedora Wiki 页面][6]。
### 验证
1、 如果你新安装的 NVIDIA 显卡已连接到你的显示器并显示正确,则表明你的 NVIDIA 驱动程序已成功和显卡建立连接。
如果你想去查看你的设置,或者验证驱动是否在正常工作(这里,主板上安装了两块显卡),再次打开 “NVIDIA X 服务器设置应用程序”。这次,你应该不会得到错误信息提示,并且系统会给出有关 X 的设置文件和你的 NVIDIA 显卡的信息。(请参考下面的屏幕截图)
![NVIDIA X Server Settings][7]
通过这个应用程序,你可以根据你的需要需改 X 配置文件,并可以监控显卡的性能,时钟速度和温度信息。
2、 为确保新显卡以满功率运行显卡性能测试是非常必要的。GL Mark 2是一个提供后台处理、构建、照明、纹理等等有关信息的标准工具。它提供了一个优秀的解决方案。GL Mark 2 记录了各种各样的图形测试的帧速率,然后输出一个总体的性能评分(这被称为 glmark2 分数)。
**注意:** glxgears 只会测试你的屏幕或显示器的性能,不会测试显卡本身,请使用 GL Mark 2。
要运行 GLMark2
1. 打开终端并关闭其他所有的应用程序
2. 运行 `sudo dnf install glmark2` 命令
3. 运行 `glmark2` 命令
4. 允许运行完整的测试来得到最好的结果。检查帧速率是否符合你对这块显卡的预期。如果你想要额外的验证,你可以查阅网站来确认是否已有你这块显卡的 glmark2 测试评分被公布到网上,你可以比较这个分数来评估你这块显卡的性能。
5. 如果你的帧速率或者 glmark2 评分低于预期请思考潜在的因素。CPU 造成的瓶颈?其他问题导致?
如果诊断的结果很好,就开始享受你的新显卡吧。
### 参考链接
- [How to benchmark your GPU on Linux][9]
- [How to install a graphics card][10]
- [The Fedora Wiki Page][6]
- [The Bottlenecker][4]
- [What Is Unified Extensible Firmware Interface (UEFI)][1]
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/install-nvidia-gpu/
作者:[Justice del Castillo][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[hopefully2333](https://github.com/hopefully2333)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://fedoramagazine.org/author/justice/
[1]:https://whatis.techtarget.com/definition/Unified-Extensible-Firmware-Interface-UEFI
[2]:https://www.cnet.com/products/pny-geforce-gtx-xlr8-gaming-1050-ti-overclocked-edition-graphics-card-gf-gtx-1050-ti-4-gb/specs/
[3]:https://www.evga.com/products/product.aspx?pn=100-B1-0600-KR
[4]:http://thebottlenecker.com (Home: The Bottle Necker)
[5]:https://bytebucket.org/kenneym/fedora-28-nvidia-gpu-installation/raw/7bee7dc6effe191f1f54b0589fa818960a8fa18b/nvidia_xserver_error.jpg?token=c6a7effe35f1c592a155a4a46a068a19fd060a91 (NVIDIA X Sever Prompt)
[6]:https://fedoraproject.org/wiki/Workstation/Third_Party_Software_Repositories
[7]:https://bytebucket.org/kenneym/fedora-28-nvidia-gpu-installation/raw/7bee7dc6effe191f1f54b0589fa818960a8fa18b/NVIDIA_XCONFIG.png?token=64e1a7be21e5e9ba157f029b65e24e4eef54d88f (NVIDIA X Server Settings)
[8]:https://rpmfusion.org/Howto/NVIDIA?highlight=%28CategoryHowto%29
[9]: https://www.howtoforge.com/tutorial/linux-gpu-benchmark/
[10]: https://www.pcworld.com/article/2913370/components-graphics/how-to-install-a-graphics-card.html

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,614 @@
MjSeven is translating
Understanding Python DataclassesPart 1
============================================================
![](https://cdn-images-1.medium.com/max/900/1*7pr8EL8EDsP296pxL7Wz_g.png)
If youre reading this, then you are already aware of Python 3.7 and the new features that come packed with it. Personally, I am most excited about `Dataclasses`. I have been waiting for them to arrive for a while.
This is a two part post:
1\. Dataclass features overview in this post
2\. Dataclass `fields` overview in the [next post][1]
### Introduction
`Dataclasses` are python classes but are suited for storing data objects. What are data objects, you ask? Here is a non-exhaustive list of features that define data objects:
* They store data and represent a certain data type. Ex: A number. For people familiar with ORMs, a model instance is a data object. It represents a specific kind of entity. It holds attributes that define or represent the entity.
* They can be compared to other objects of the same type. Ex: A number can be `greater than`, `less than`, or `equal to` another number
There are certainly more features, but this list is sufficient to help you understand the crux.
To understand `Dataclasses`, we shall be implementing a simple class that holds a number, and allows us to perform the above mentioned operations.
First, we shall be using normal classes, and then we shall use `Dataclasses` to achieve the same result.
But before we begin, a word on the usage of `Dataclasses`
Python 3.7 provides a decorator [dataclass][2] that is used to convert a class into a dataclass.
All you have to do is wrap the class in the decorator:
```
from dataclasses import dataclass
```
```
@dataclass
class A:
```
Now, lets dive into the usage of how and what `dataclass` changes for us.
### Initialization
Usual
```
class Number:
```
```
__init__(self, val):
self.val = val
>>> one = Number(1)
>>> one.val
>>> 1
```
With `dataclass`
```
@dataclass
class Number:
val:int
>>> one = Number(1)
>>> one.val
>>> 1
```
Heres whats changed with the dataclass decorator:
1\. No need of defining `__init__`and then assigning values to `self`, `d` takes care of it
2\. We defined the member attributes in advance in a much more readable fashion, along with [type hinting][3]. We now know instantly that `val` is of type `int`. This is definitely more readable than the usual way of defining class members.
> Zen of Python: Readability counts
It is also possible to define default values:
```
@dataclass
class Number:
val:int = 0
```
### Representation
Object representation is a meaningful string representation of the object that is very useful in debugging.
Default python objects representation is not very meaningful:
```
class Number:
def __init__(self, val = 0):
self.val = val
>>> a = Number(1)
>>> a
>>> <__main__.Number object at 0x7ff395b2ccc0>
```
This gives us no insight as to the utility of the object, and will result in horrible a debugging experience.
A meaningful representation could be implemented by defining a `__repr__`method in the class definition.
```
def __repr__(self):
return self.val
```
Now we get a meaningful representation of the object:
```
>>> a = Number(1)
>>> a
>>> 1
```
`dataclass` automatically add a `__repr__ `function, so that we dont have to manually implement it.
```
@dataclass
class Number:
val: int = 0
```
```
>>> a = Number(1)
>>> a
>>> Number(val = 1)
```
### Data Comparison
Generally, data objects come with a need to be compared with each other.
Comparison between two objects `a` and `b` generally consists of the following operations:
* a < b
* a > b
* a == b
* a >= b
* a <= b
In python, it is possible to define [methods][4] in classes that can do the above operations. For the sake of simplicity and to not let this post run amuck, I shall be only demonstrating implementation of `==` and `<`.
Usual
```
class Number:
def __init__( self, val = 0):
self.val = val
def __eq__(self, other):
return self.val == other.val
def __lt__(self, other):
return self.val < other.val
```
With `dataclass`
```
@dataclass(order = True)
class Number:
val: int = 0
```
Yup, thats it.
We dont need to define the `__eq__`and `__lt__` methods, because `dataclass`decorator automatically adds them to the class definition for us when called with `order = True`
Well, how does it do that?
When you use `dataclass,` it adds a functions `__eq__` and `__lt__` to the class definition. We already know that. So, how do these functions know how to check equality and do comparison?
A dataclass generated `__eq__` function will compare a tuple of its attributes with a tuple of attributes of the other instance of the same class. In our case heres what the `automatically` generated `__eq__` function would be equivalent to:
```
def __eq__(self, other):
return (self.val,) == (other.val,)
```
Lets look at a more elaborate example:
We shall write a dataclass `Person `to hold their `name` and `age`.
```
@dataclass(order = True)
class Person:
name: str
age:int = 0
```
The automatically generated `__eq__` method will be equivalent of:
```
def __eq__(self, other):
return (self.name, self.age) == ( other.name, other.age)
```
Pay attention to the order of the attributes. They will always be generated in the order you defined them in the dataclass definition.
Similarly, the equivalent `__le__` function would be akin to:
```
def __le__(self, other):
return (self.name, self.age) <= (other.name, other.age)
```
A need for defining a function like `__le__` generally arises, when you have to sort a list of your data objects. Pythons built-in [sorted][5] function relies on comparing two objects.
```
>>> import random
```
```
>>> a = [Number(random.randint(1,10)) for _ in range(10)] #generate list of random numbers
```
```
>>> a
```
```
>>> [Number(val=2), Number(val=7), Number(val=6), Number(val=5), Number(val=10), Number(val=9), Number(val=1), Number(val=10), Number(val=1), Number(val=7)]
```
```
>>> sorted_a = sorted(a) #Sort Numbers in ascending order
```
```
>>> [Number(val=1), Number(val=1), Number(val=2), Number(val=5), Number(val=6), Number(val=7), Number(val=7), Number(val=9), Number(val=10), Number(val=10)]
```
```
>>> reverse_sorted_a = sorted(a, reverse = True) #Sort Numbers in descending order
```
```
>>> reverse_sorted_a
```
```
>>> [Number(val=10), Number(val=10), Number(val=9), Number(val=7), Number(val=7), Number(val=6), Number(val=5), Number(val=2), Number(val=1), Number(val=1)]
```
### `dataclass` as a callable decorator
It is not always desirable to have all the `dunder` methods defined. Your use case might only consist of storing the values and checking equality. Thus, you only need the `__init__` and `__eq__` methods defined. If we could tell the decorator to not generate the other methods, it would reduce some overhead and we shall have correct operations available on the data object.
Fortunately, this can be achieved by using `dataclass` decorator as a callable.
From the official [docs][6], the decorator can be used as a callable with the following arguments:
```
@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
class C:
```
1. `init` : By default an `__init__` method will be generated. If passed as `False`, the class will not have an `__init__` method.
2. `repr` : `__repr__` method is generated by default. If passed as `False`, the class will not have an `__repr__` method.
3. `eq`: By default the `__eq__` method will be generated. If passed as `False`, the `__eq__` method will not be added by `dataclass`, but will default to the `object.__eq__`.
4. `order` : By default `__gt__` , `__ge__`, `__lt__`, `__le__` methods will be generated. If passed as `False`, they are omitted.
We shall discuss `frozen` in a while. The `unsafe_hash` argument deserves a separate post because of its complicated use cases.
Now, back to our use case, heres what we need:
1. `__init__`
2. `__eq__`
These functions are generated by default, so what we need is to not have the other functions generated. How do we do that? Simply pass the relevant arguments as false to the generator.
```
@dataclass(repr = False) # order, unsafe_hash and frozen are False
class Number:
val: int = 0
```
```
>>> a = Number(1)
```
```
>>> a
```
```
>>> <__main__.Number object at 0x7ff395afe898>
```
```
>>> b = Number(2)
```
```
>>> c = Number(1)
```
```
>>> a == b
```
```
>>> False
```
```
>>> a < b
```
```
>>> Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: < not supported between instances of Number and Number
```
### Frozen Instances
Frozen Instances are objects whose attributes cannot be modified after the object has been initialized.
> It is not possible to create truly immutable Python objects
To create immutable attributes on an object in Python is an arduous task, and something that I wont dive into in this post.
Heres what we expect from an immutable object:
```
>>> a = Number(10) #Assuming Number class is immutable
```
```
>>> a.val = 10 # Raises Error
```
With Dataclasses it is possible to define a frozen object by using `dataclass`decorator as a callable with argument `frozen=True` .
When a frozen dataclass object is instantiated, any attempt to modify the attributes of the object raises `FrozenInstanceError`.
```
@dataclass(frozen = True)
class Number:
val: int = 0
```
```
>>> a = Number(1)
```
```
>>> a.val
```
```
>>> 1
```
```
>>> a.val = 2
```
```
>>> Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
File “<string>”, line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field val
```
So a frozen instance is a great way of storing
* constants
* settings
These generally do not change over the lifetime of the application and any attempt to modify them should generally be warded off.
### Post init processing
With Dataclasses the requirement of defining an `__init__` method to assign variables to `self` has been taken care of. But now we lose the flexibility of making function-calls/processing that might be required immediately after the variables have been assigned.
Let us discuss a use case where we define a class `Float` to contain float numbers, and we calculate the integer and decimal parts immediately after initialization.
Usual
```
import math
```
```
class Float:
def __init__(self, val = 0):
self.val = val
self.process()
def process(self):
self.decimal, self.integer = math.modf(self.val)
>>> a = Float( 2.2)
```
```
>>> a.decimal
```
```
>>> 0.2000
```
```
>>> a.integer
```
```
>>> 2.0
```
Fortunately, post initialization processing is already taken care of with [__post_init__][9] method.
The generated `__init__` method calls the `__post_init__` method before returning. So, any processing can be made in this functions.
```
import math
```
```
@dataclass
class FloatNumber:
val: float = 0.0
def __post_init__(self):
self.decimal, self.integer = math.modf(self.val)
>>> a = Number(2.2)
```
```
>>> a.val
```
```
>>> 2.2
```
```
>>> a.integer
```
```
>>> 2.0
```
```
>>> a.decimal
```
```
>>> 0.2
```
Neat!
### Inheritance
`Dataclasses` support inheritance like normal python classes.
So, the attributes defined in the parent class will be available in the child class.
```
@dataclass
class Person:
age: int = 0
name: str
```
```
@dataclass
class Student(Person):
grade: int
```
```
>>> s = Student(20, "John Doe", 12)
```
```
>>> s.age
```
```
>>> 20
```
```
>>> s.name
```
```
>>> "John Doe"
```
```
>>> s.grade
```
```
>>> 12
```
Pay attention to the fact that the arguments to `Student` are in the order of fields defined in the class definition.
What about the behavior of `__post_init__` during inheritance?
Since `__post_init__` is just another function, it has to be invoked in the conventional form:
```
@dataclass
class A:
a: int
def __post_init__(self):
print("A")
```
```
@dataclass
class B(A):
b: int
def __post_init__(self):
print("B")
```
```
>>> a = B(1,2)
```
```
>>> B
```
In the above example, only `B's` `__post_init__` is called. How do we invoke `A's` `__post_init__` ?
Since it is a function of the parent class, it can be invoked using `super.`
```
@dataclass
class B(A):
b: int
def __post_init__(self):
super().__post_init__() #Call post init of A
print("B")
```
```
>>> a = B(1,2)
```
```
>>> A
B
```
### Conclusion
So, above are a few ways in which Dataclasses make life easier for Python developers.
I have tried to be thorough and cover most of the use cases, yet, no man is perfect. Reach out if you find mistakes, or want me to pay attention to relevant use cases.
I shall cover [dataclasses.field][10] and `unsafe_hash` in different posts.
Follow me on [Github][11], [Twitter][12].
Update: Post for `dataclasses.field` can be found [here][13].
--------------------------------------------------------------------------------
via: https://medium.com/mindorks/understanding-python-dataclasses-part-1-c3ccd4355c34
作者:[Shikhar Chauhan][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://medium.com/@xsschauhan?source=post_header_lockup
[1]:https://medium.com/@xsschauhan/understanding-python-dataclasses-part-2-660ecc11c9b8
[2]:https://docs.python.org/3.7/library/dataclasses.html#dataclasses.dataclass
[3]:https://stackoverflow.com/q/32557920/4333721
[4]:https://docs.python.org/3/reference/datamodel.html#object.__lt__
[5]:https://docs.python.org/3.7/library/functions.html#sorted
[6]:https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass
[7]:http://twitter.com/dataclass
[8]:http://twitter.com/dataclass
[9]:https://docs.python.org/3/library/dataclasses.html#post-init-processing
[10]:https://docs.python.org/3/library/dataclasses.html#dataclasses.field
[11]:http://github.com/xssChauhan/
[12]:https://twitter.com/xssChauhan
[13]:https://medium.com/@xsschauhan/understanding-python-dataclasses-part-2-660ecc11c9b8

View File

@ -0,0 +1,394 @@
MjSeven is translating
Python Sets: What, Why and How
============================================================
posted on 07/10/2018 by [wilfredinni][5]
![Python Sets: What, Why and How](https://raw.githubusercontent.com/wilfredinni/pysheetComments/master/2018-july/python_sets/sets.png)
Python comes equipped with several built-in data types to help us organize our data. These structures include lists, dictionaries, tuples and sets.
From the Python 3 documentation:
> A set is an  _unordered collection_  with no  _duplicate elements_ . Basic uses include  _membership testing_  and  _eliminating duplicate entries_ . Set objects also support mathematical operations like  _union_ ,  _intersection_ ,  _difference_ , and  _symmetric difference_ .
In this article, we are going to review and see examples of every one of the elements listed in the above definition. Let's start right away and see how we can create them.
### Initializing a Set
There are two ways to create a set: one is to provide the built-in function `set()` with a list of elements, and the other is to use the curly braces `{}`.
Initializing a set using the `set()` built-in function:
```
>>> s1 = set([1, 2, 3])
>>> s1
{1, 2, 3}
>>> type(s1)
<class 'set'>
```
Initializing a set using curly braces `{}`
```
>>> s2 = {3, 4, 5}
>>> s2
{3, 4, 5}
>>> type(s2)
<class 'set'>
>>>
```
As you can see, both options are valid. The problem comes when what we want is an empty one:
```
>>> s = {}
>>> type(s)
<class 'dict'>
```
That's right, we will get a dictionary instead of a set if we use empty curly braces =)
It's a good moment to mention that for the sake of simplicity, all the examples provided in this article will use single digit integers, but sets can have all the [hashable][6] data types that Python support. In other words, integers, strings and tuples, but not  _mutable_  items like  _lists_  or  _dictionaries_ :
```
>>> s = {1, 'coffee', [4, 'python']}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
```
Now that you know how to create a set and what type of elements it can contain, let's continue and see  _why_  we should always have them in our toolkit.
### Why You Should Use Them
When writing code, you can do it in more than a single way. Some are considered to be pretty bad, and others,  _clear, concise and maintainable_ . Or " [_pythonic_][7] ".
From the [The Hitchhikers Guide to Python][8]:
> When a veteran Python developer (a Pythonista) calls portions of code not “Pythonic”, they usually mean that these lines of code do not follow the common guidelines and fail to express its intent in what is considered the best (hear: most readable) way.
Let's start exploring the way that Python sets can help us not just with readability, but also speeding up our programs execution time.
### Unordered Collection of Elements
First things first: you can't access a set element using indexes.
```
>>> s = {1, 2, 3}
>>> s[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support indexing
```
Or modify them with slices:
```
>>> s[0:2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'set' object is not subscriptable
```
BUT, if what we need is to remove duplicates, or do mathematical operations like combining lists (unions), we can, and  _SHOULD_  always use Sets.
I have to mention that when iterating over, sets are outperformed by lists, so prefer them if that is what you need. Why? well, this article does not intend to explain the inner workings of sets, but if you are interested, here are a couple of links where you can read about it:
* [TimeComplexity][1]
* [How is set() implemented?][2]
* [Python Sets vs Lists][3]
* [Is there any advantage or disadvantage to using sets over list comps to ensure a list of unique entries?][4]
### No Duplicate Items
While writing this I cannot stop thinking in all the times I used the  _for_  loop and the  _if_  statement to check and remove duplicate elements in a list. My face turns red remembering that, more than once, I wrote something like this:
```
>>> my_list = [1, 2, 3, 2, 3, 4]
>>> no_duplicate_list = []
>>> for item in my_list:
... if item not in no_duplicate_list:
... no_duplicate_list.append(item)
...
>>> no_duplicate_list
[1, 2, 3, 4]
```
Or used a list comprehension:
```
>>> my_list = [1, 2, 3, 2, 3, 4]
>>> no_duplicate_list = []
>>> [no_duplicate_list.append(item) for item in my_list if item not in no_duplicate_list]
[None, None, None, None]
>>> no_duplicate_list
[1, 2, 3, 4]
```
But it's ok, nothing of that matters anymore because we now have the sets in our arsenal:
```
>>> my_list = [1, 2, 3, 2, 3, 4]
>>> no_duplicate_list = list(set(my_list))
>>> no_duplicate_list
[1, 2, 3, 4]
>>>
```
Now let's use the  _timeit_  module and see the excecution time of lists and sets when removing duplicates:
```
>>> from timeit import timeit
>>> def no_duplicates(list):
... no_duplicate_list = []
... [no_duplicate_list.append(item) for item in list if item not in no_duplicate_list]
... return no_duplicate_list
...
>>> # first, let's see how the list perform:
>>> print(timeit('no_duplicates([1, 2, 3, 1, 7])', globals=globals(), number=1000))
0.0018683355819786227
```
```
>>> from timeit import timeit
>>> # and the set:
>>> print(timeit('list(set([1, 2, 3, 1, 2, 3, 4]))', number=1000))
0.0010220493243764395
>>> # faster and cleaner =)
```
Not only we write  _fewer lines_  with sets than with lists comprehensions, we also obtain more  _readable_  and  _performant_  code.
Note: remember that sets are unordered, so there is no guarantee that when converting them back to a list the order of the elements is going to be preserved.
From the [Zen of Python][9]:
> Beautiful is better than ugly. 
> Explicit is better than implicit.
> Simple is better than complex.
> Flat is better than nested.
Aren't sets just Beautiful, Explicit, Simple and Flat? =)
### Membership Tests
Every time we use an  _if_  statement to check if an element is, for example, in a list, you are doing a membership test:
```
my_list = [1, 2, 3]
>>> if 2 in my_list:
... print('Yes, this is a membership test!')
...
Yes, this is a membership test!
```
And sets are more performant than lists when doing them:
```
>>> from timeit import timeit
>>> def in_test(iterable):
... for i in range(1000):
... if i in iterable:
... pass
...
>>> timeit('in_test(iterable)',
... setup="from __main__ import in_test; iterable = list(range(1000))",
... number=1000)
12.459663048726043
```
```
>>> from timeit import timeit
>>> def in_test(iterable):
... for i in range(1000):
... if i in iterable:
... pass
...
>>> timeit('in_test(iterable)',
... setup="from __main__ import in_test; iterable = set(range(1000))",
... number=1000)
0.12354438152988223
>>>
```
Note: the above tests come from [this][10] StackOverflow thread.
So if you are doing comparisons like this in huge lists, it should speed you a good bit if you convert that list into a set.
### How to Use Them
Now that you know what a set is and why you should use them, let's do a quick tour and see how can we modify and operate with them.
### Adding Elements
Depending on the number of elements to add, we will have to choose between the `add()` and `update()` methods.
`add()` will add a single element:
```
>>> s = {1, 2, 3}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
```
And `update()` multiple ones:
```
>>> s = {1, 2, 3}
>>> s.update([2, 3, 4, 5, 6])
>>> s
{1, 2, 3, 4, 5, 6}
```
Remember, sets remove duplicates.
### Removing Elements
If you want to be alerted when your code tries to remove an element that is not in the set, use `remove()`. Otherwise, `discard()` provides a good alternative:
```
>>> s = {1, 2, 3}
>>> s.remove(3)
>>> s
{1, 2}
>>> s.remove(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 3
```
`discard()` won't raise any errors:
```
>>> s = {1, 2, 3}
>>> s.discard(3)
>>> s
{1, 2}
>>> s.discard(3)
>>> # nothing happens!
```
We can also use `pop()` to randomly discard an element:
```
>>> s = {1, 2, 3, 4, 5}
>>> s.pop() # removes an arbitrary element
1
>>> s
{2, 3, 4, 5}
```
Or `clear()` to remove all the values from a set:
```
>>> s = {1, 2, 3, 4, 5}
>>> s.clear() # discard all the items
>>> s
set()
```
### union()
`union()` or `|` will create a new set that contains all the elements from the sets we provide:
```
>>> s1 = {1, 2, 3}
>>> s2 = {3, 4, 5}
>>> s1.union(s2) # or 's1 | s2'
{1, 2, 3, 4, 5}
```
### intersection()
`intersection` or `&` will return a set containing only the elements that are common in all of them:
```
>>> s1 = {1, 2, 3}
>>> s2 = {2, 3, 4}
>>> s3 = {3, 4, 5}
>>> s1.intersection(s2, s3) # or 's1 & s2 & s3'
{3}
```
### difference()
Using `diference()` or `-`, creates a new set with the values that are in "s1" but not in "s2":
```
>>> s1 = {1, 2, 3}
>>> s2 = {2, 3, 4}
>>> s1.difference(s2) # or 's1 - s2'
{1}
```
### symmetric_diference()
`symetric_difference` or `^` will return all the values that are not common between the sets.
```
>>> s1 = {1, 2, 3}
>>> s2 = {2, 3, 4}
>>> s1.symmetric_difference(s2) # or 's1 ^ s2'
{1, 4}
```
### Conclusions
I hope that after reading this article you know what a set is, how to manipulate their elements and the operations they can perform. Knowing when to use a set will definitely help you write cleaner code and speed up your programs.
If you have any doubts, please leave a comment and I will gladly try to answer them. Also, don´t forget that if you already understand sets, they have their own [place][11] in the [Python Cheatsheet][12], where you can have a quick reference and refresh what you already know.
--------------------------------------------------------------------------------
via: https://www.pythoncheatsheet.org/blog/python-sets-what-why-how
作者:[wilfredinni][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.pythoncheatsheet.org/author/wilfredinni
[1]:https://wiki.python.org/moin/TimeComplexity
[2]:https://stackoverflow.com/questions/3949310/how-is-set-implemented
[3]:https://stackoverflow.com/questions/2831212/python-sets-vs-lists
[4]:https://mail.python.org/pipermail/python-list/2011-June/606738.html
[5]:https://www.pythoncheatsheet.org/author/wilfredinni
[6]:https://docs.python.org/3/glossary.html#term-hashable
[7]:http://docs.python-guide.org/en/latest/writing/style/
[8]:http://docs.python-guide.org/en/latest/
[9]:https://www.python.org/dev/peps/pep-0020/
[10]:https://stackoverflow.com/questions/2831212/python-sets-vs-lists
[11]:https://www.pythoncheatsheet.org/#sets
[12]:https://www.pythoncheatsheet.org/

View File

@ -1,154 +0,0 @@
在绝大部分类型的机器上安装 NVIDIA 显卡驱动
======
![](https://fedoramagazine.org/wp-content/uploads/2018/06/nvidia-816x345.jpg)
无论是研究还是娱乐,安装一个最新的显卡驱动都能提升你的计算机性能,并且使你能全方位地实现新功能。本安装指南使用 Fedora 28 的新的第三方仓库来安装 NVIDIA 驱动。它将引导您完成硬件和软件两方面的安装,并且涵盖你需要得到的 NVIDIA 显卡启动和运行的一切。这个流程适用于任何支持 UEFI 的计算机和任意新的 NVIDIA 显卡。
### 准备
本指南依赖于下面这些材料:
* 一台使用 UEFI 的计算机,如果你不确定你的电脑是否有这个这个固件,请运行 sudo dmidecode -t 0。如果输出中出现了“UEFI is supported”你的安装过程就可以继续了。不然的话虽然可以在技术上更新部分电脑来支持 UEFI但是这个过程的要求很苛刻我们通常不建议你这么使用。
* 一个现代的,支持 UEFI 的 NVIDIA 的显卡
* 一个满足你的 NVIDIA 显卡的功率和接线要求的电源(有关详细信息,请参考硬件和修改的章节)
* 网络连接
* Fedora 28 系统
### 安装实例
这个安装示例使用的是:
* 一台 Optiplex 9010 的主机(一台相当老的机器)
* NVIDIA GeForce GTX 1050 Ti XLR8 游戏超频版 4 GB GDDR5 PCI Express 3.0 显卡
* 为了满足新显卡的电源要求,电源升级为 EVGA 80 PLUS 600 W ATX 12V/EPS 12V这个最新的 PSU 比推荐的最低要求高了 300 W但在大部分情况下满足推荐的最低要求就足够了。
* 然后当然的Fedora 28 也别忘了.
### 硬件和修改
#### PSU
打开你的台式机的机箱,检查印刷在电源上的最大输出功率。然后,查看你的 NVIDIA 显卡的文档,确定推荐的最小电源功率要求(以瓦特为单位)。除此之外,检查你的显卡,看它是否需要额外的接线,例如 6 针口连接器,大多数的入门级显卡只从主板获取电力,但是有一些显卡需要额外的电力,如果出现以下情况,你需要升级的 PSU
1. 你的电源的最大输出功率低于显卡建议的最小电源功率。注意:根据一些显卡厂家的说法,比起推荐的功率,预先构建的系统可能会需要更多或更少的功率,而这取决于系统的配置。如果你使用的是一个特别耗电或者特别节能的配置,请灵活决定你的电源需求。
2. 你的电源没有提供必须的接线口来为你的显卡供电。
PSU 的更换很容易,但是在你拆除你当前正在使用的电源之前,请务必注意你的接线布局。除此之外,请确保你选择的 PSU 适合你的机箱。
#### CPU
虽然在大多数老机器上安装高性能的 NVIDIA 显卡是可能的,但是一个缓慢或受损的 CPU 会阻碍显卡性能的发挥,如果要计算在你的机器上瓶颈效果的影响,请点击这里。知道你的 CPU 性能来避免高性能的显卡和 CPU 无法保持匹配是很重要的。升级你的 CPU 是一个潜在的考虑因素。
#### 主板
在继续进行之前,请确认你的主板和你选择的显卡是兼容的。你的显卡应该插在最靠近散热器的 PCI-E x16 插槽中。确保你的设置为显卡预留了足够的空间。此外,请注意,现在大部分的显卡使用的都是 PCI-E 3.0 技术。虽然这些显卡如果插在 PCI-E 3.0 插槽上会运行地最好,但如果插在一个旧版的插槽上的话,性能也不会受到太大的影响。
### 安装
```
sudo dnf update
```
2\. 然后,使用这条简单的命令进行重启:
```
reboot
```
3\. 在重启之后,安装 Fedora 28 的工作站仓库:
```
sudo dnf install fedora-workstation-repositories
```
4\. 接着,设置 NVIDIA 驱动仓库:
```
sudo dnf config-manager --set-enabled rpmfusion-nonfree-nvidia-driver
```
5\. 然后,再次重启。
6\. 在这次重启之后,通过下面这条命令验证是否添加了仓库:
```
sudo dnf repository-packages rpmfusion-nonfree-nvidia-driver info
```
如果加载了多个 NVIDIA 工具和它们各自的参数,请继续进行下一步。如果没有,你可能在添加新仓库的时候遇到了一个错误。你应该再试一次。
7\. 登陆,连接到互联网,然后打开软件应用程序。点击加载项>硬件驱动> NVIDIA Linux 图形驱动>安装。
接着,再一次重启。
8\. 在重新启动后,转到侧栏上的‘显示应用程序’,然后打开新添加的 NVIDIA X 服务器设置应用程序。一个图形界面会被打开,然后出现一个对话框并包含以下信息:
![NVIDIA X Server Prompt][5]
请参考应用程序的建议,但是在这样做之前,请确保你的 NVIDIA 显卡就在手里,并且已准备好去安装。请注意在以 root 身份运行 nvidia xconfig 的时候,如果在没有立刻安装显卡的情况下关闭电源,这可能会造成严重损坏。这样做可能会导致你的电脑无法启动,并强制你通过重启屏幕来修复系统。重新安装 Fedora 会修复这些问题,但是效果会更加糟糕。
如果你已准备好继续,请输入下面这条命令:
```
sudo nvidia-xconfig
```
如果系统提示你完成任何地下载,请选择接收然后继续。
9\. 一旦这个过程完成,关闭所有的应用程序并关闭电脑,拔掉机器的电源。然后,按一下电源按钮来释放掉多有的剩余电量,以此来保护你自己不会被点击。如果你的 PSU 有电源开关,请将其关闭。
10\. 最后,安装显卡,拔掉老的显卡并将新的显卡插入到正确的 PCI-E x16 插槽中,风扇朝着下方。如果这个位置已经没有空间让风扇通风。那作为代替,如果可以的话就把显卡面朝上放置。成功安装新的显卡之后,关闭你的机箱,插入 PSU ,然后打开计算机,它应该会成功启动。
**注意:** 要禁用此安装中使用的 NVIDIA 驱动仓库,或者要禁用所有的 Fedora 工作站仓库,请参考这个 Fedora Wiki 页面。
### 验证
1\. 如果你新安装的显卡已连接到你的显示器并显示正确,则表明你的 NVIDIA 驱动程序已成功和显卡建立连接。
如果你想去查看你的设置,或者验证驱动是否在正常工作(如果机箱的主板里安装了两块显卡),再次打开 NVIDIA X 服务器设置应用程序。这次,你应该不会被提示一个错误信息,并且系统会给出有关 X 的设置文件和你的 NVIDIA 显卡的信息。(请参考下面的屏幕截图)
![NVIDIA X Server Settings][7]
通过这个应用程序,你可以根据你的需要需改 X 配置文件,并可以监控显卡的性能,时钟速度和温度信息。
2\. 为确保新显卡以满功率运行一次显卡性能测试是非常必要的。GL Mark 2是一个提供后台处理、构建、照明、纹理等等有关信息的标准工具。它提供了一个优秀的解决方案。GL Mark 2 记录了各种各样的图形测试的帧速率,然后输出一个总体的性能评分(这被称为 glmark2 分数)。
**注意:** glxgears 只会测试你的屏幕或显示器的性能,不会测试显卡本身,请使用 GL Mark 2。
要运行 GLMark2:
1. 打开终端并关闭其他所有的应用程序
2. 运行 sudo dnf install glmark2 命令
3. 运行 glmark2 命令
4. 允许运行完整的测试来得到最好的结果。检查帧速率是否符合你对这块显卡的预期。如果你想要额外的验证,你可以查阅网站来确认是否已有你这块显卡的 glmark2 测试评分被公布到网上,你可以比较这个分数来评估你这块显卡的性能。
5. 如果你的帧速率或者 glmark2 评分低于预期请思考潜在的因素。CPU 造成的瓶颈?其他问题导致?
如果诊断的结果很好,就开始享受你的新显卡吧。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/install-nvidia-gpu/
作者:[Justice del Castillo][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[hopefully2333](https://github.com/hopefully2333)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://fedoramagazine.org/author/justice/
[1]:https://whatis.techtarget.com/definition/Unified-Extensible-Firmware-Interface-UEFI
[2]:https://www.cnet.com/products/pny-geforce-gtx-xlr8-gaming-1050-ti-overclocked-edition-graphics-card-gf-gtx-1050-ti-4-gb/specs/
[3]:https://www.evga.com/products/product.aspx?pn=100-B1-0600-KR
[4]:http://thebottlenecker.com (Home: The Bottle Necker)
[5]:https://bytebucket.org/kenneym/fedora-28-nvidia-gpu-installation/raw/7bee7dc6effe191f1f54b0589fa818960a8fa18b/nvidia_xserver_error.jpg?token=c6a7effe35f1c592a155a4a46a068a19fd060a91 (NVIDIA X Sever Prompt)
[6]:https://fedoraproject.org/wiki/Workstation/Third_Party_Software_Repositories
[7]:https://bytebucket.org/kenneym/fedora-28-nvidia-gpu-installation/raw/7bee7dc6effe191f1f54b0589fa818960a8fa18b/NVIDIA_XCONFIG.png?token=64e1a7be21e5e9ba157f029b65e24e4eef54d88f (NVIDIA X Server Settings)