sc = SparkContext(master="local[16]")
t0 = time()
rdd = sc.parallelize([1,2]*10000000)
rdd1 = rdd.reduce(lambda x,y:x+y)
print(time()-t0)
我想了解程序员方法而不是嵌入式系统设计人员方法的解释。
我知道我们将PINSEL寄存器设置为0 但是在编译器的那一行中到底发生了什么呢?
答案 0 :(得分:2)
LPC_PINCON
是指向结构的指针(可能是语法上的并集,但在这种情况下更有可能使用结构)。结构只是数据布局。它包含几个不同类型的成员。指针的值是一个内存地址。
LPC_PINCON->
表示要访问结构的成员。实际上,它是*
和.
这两个操作的组合,如(*LPC_PINCON).
所示,其中*
表示引用指针地址和{ {1}}表示要引用该结构中的成员。
.
通过指定要引用的成员来完成此操作。为此,计算机将获取指针LPC_PINCON->PINSEL1
的值,并向其添加LPC_PINCON
的偏移量,即它将从结构开始处将字节数添加到地址中。给成员PINSEL1
。 (至少,从概念上讲,它是这样做的。由于优化和编译的其他复杂性,实际操作可能会有所不同,但会产生同等的效果。)
然后PINSEL1
将零分配给LPC_PINCON->PINSEL1=0x00
成员。名义上,这里发生的是生成了一条存储指令。实际发生的情况取决于PINSEL1
的类型(未显示)。可能它只是指向普通对象的指针,在这种情况下,编译器仅需要“概念上”为LPC_PINCON
分配零-它可以通过各种方式优化该操作,例如将其与其他存储区组合到结构中甚至完全删除它(如果它可以确定它对程序的“可观察到的行为”没有影响)。但是,在这种情况下,PINSEL1
并非指向LPC_PINCON
对象或包含volatile
成员的结构的指针。为了分配给volatile
对象,(根据C标准)要求编译器生成存储指令(或任何实现定义为对实际对象的写操作)。因此,生成的代码将有效地类似于(因硬件架构和其他一些情况而异):
volatile
的值。LPC_PINCON
的偏移量。我们可能还要注意,PINSEL1
可能已经被设置为一个特定的地址,设备寄存器被映射为显示在内存中,而不是普通的内存地址。 LPC_PINCON
也可以是普通变量(标识符和对象),也可以是由表达式替换的某些宏。 (例如,它可能是LPC_PINCON
,它以旨在用作内存地址的数字开头并将其转换为指针。)如果是这样的宏,则编译器可能会计算{{1 }}加上编译时((volatile struct foo *) 0x1234000)
的偏移量,因此生成的汇编代码将只包含准备零的指令和存储到固定地址的指令。
答案 1 :(得分:1)
它取消引用指针LPC_PINCON
到变量PINSEL1
,然后为变量赋值零(实际上,十六进制表示为零的事实无关紧要)。