0

我的 python 函数的一部分如下所示:

for i in range(0, len(longitude_aq)):
    center = Coordinates(latitude_aq[i], longitude_aq[i])
    currentAq = aq[i, :]
    for j in range(0, len(longitude_meo)):
        currentMeo = meo[j, :]
        grid_point = Coordinates(latitude_meo[j], longitude_meo[j])
        if is_in_circle(center, RADIUS, grid_point):
            if currentAq[TIME_AQ] == currentMeo[TIME_MEO]:
                humidity += currentMeo[HUMIDITY_MEO]
                pressure += currentMeo[PRESSURE_MEO]
                temperature += currentMeo[TEMPERATURE_MEO]
                wind_speed += currentMeo[WIND_SPEED_MEO]
                wind_direction += currentMeo[WIND_DIRECTION_MEO]
                count += 1.0

    if count != 0.0:
        final_tmp[i, HUMIDITY_FINAL] = humidity/count
        final_tmp[i, PRESSURE_FINAL] = pressure/count
        final_tmp[i, TEMPERATURE_FINAL] = temperature/count
        final_tmp[i, WIND_SPEED_FINAL] = wind_speed/count
        final_tmp[i, WIND_DIRECTION_FINAL] = wind_direction/count

    humidity, pressure, temperature, wind_speed, wind_direction, count = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

final.loc[:, :] = final_tmp[:, :]

问题: len(longitude_aq)大约。320klen(longitude_meo)是 700 万。这使该代码的迭代次数接近 21000 亿次……

我必须迭代一个文件(那个longitude_aq)然后计算一些平均值,迭代第二个文件(那个longitude_meo)给定从第一个文件中提取的一些特征。

看来我不能以任何不同的方式进行。

可能的解决方案:并行编程。我的大学允许我访问他们的 HPC。他们有几个节点 + 几个 GPU 可访问(此处列出GPU,此处列出CPU)

目标:没有使用 Python 进行 CUDA 编程的经验,我想知道将我的代码转换为 HPC 可运行的东西的最简单方法是什么,从而使计算时间急剧下降。

4

1 回答 1

-4

对不起,读起来可能很难读,但现实是残酷的,许多爱好者可能很容易man*months将“编码”努力破坏成一场先验失败的战争。最好仔细重新评估任何重新设计计划的所有先验已知的缺点/优点,然后再盲目地花费一个人*一天的时间进入一个主要错误的方向。

如果我没有接触到一个项目,我很可能不会在这里发布它,顶级院士已经花了几十个man*years,是的,一年多的时间与一个 12 岁以上的团队一起“生产”一个处理程序~ 26 [hr],其中如果使用适当的(硬件性能非破坏性)设计方法进行设计,则可在低于~ 15 [min](并且在 HPC/GPU 基础设施成本上更便宜)的情况下重现......

看来我不能以任何不同的方式进行。

好吧,实际上很难说,如果不是不可能的话:

您的帖子似乎假设了一些基本的事情,这些事情可能会避免从将上述草图转移到真正专业的 HPC / GPU 基础设施中获得任何真正的好处。

可能的解决方案:并行编程

比实际做起来更容易说/输入的方式。

A-wish-to-run-in-true-[PARALLEL]进程调度仍然只是一个愿望(相信我,或 Gene Amdahl,或其他 C/S 资深人士与否)确实需要重新设计艰难的进程,如果你的代码应该得到任何比纯[SERIAL]代码执行流程(如上面发布的)要好得多

1)一个纯粹[SERIAL]fileIO可以(几乎)杀死游戏:

关于纯文件访问的未发布部分(两个带有数据点的文件)......任何文件IO本质上都是最昂贵的资源,除了智能重新设计纯文件(充其量是一站式成本,但仍然)(重新)以顺序方式读取,所以不要指望在重新设计的代码中任何远离这个的地方有任何 Giant-Leap。这将始终是最慢且始终昂贵的阶段。[SERIAL] [SERIAL]

奖励:
虽然这似乎是或其他俚语接下来带来的任何东西的清单列表中最不性感的项目,但基本事实是,确实进行 HPC 计算快速且资源高效,输入(是的,静态文件)和计算策略通常都针对流处理进行了优化,并且如果要达到峰值性能,最好还可以享受不间断(避免冲突)的数据局部性. 这两个领域中的任何低效率不仅可以附加,而且实际上会影响计算费用(所以DIVIDE性能 ) 和差异可能很容易达到几个数量级 ( 从[ns] -> [us] -> [ms] -> [s] -> [min] -> [hr] -> [day] -> [week], 你 把 它们 都 命名 ...... )

2 ) 成本/收益可能会让您获得 PAY-WAY-MORE-THAN-YOU-GET

这部分确实是你最大的敌人:如果你的一次努力高于净收益的总和,GPU 根本不会增加任何附加值,或者不够,以支付你的附加成本。

为什么?

GPU 引擎是 SIMD 设备,非常适合在重复相同的 SMX 指令块的大面积区域上使用延迟屏蔽,需要一定的“权重”-of-“ nice ”-mathematics 在本地发生,如果它们要显示任何处理速度超过其他问题实施策略 - GPU 设备(不是游戏玩家的设备,而是 HPC 设备,并非同类中的所有卡都是,它们是吗?)对于确实很小的数据区域提供最好的 -局部性(微内核矩阵运算,截至 2018/Q2具有非常密集、最好非常小的 SMX 局部“ RAM”足迹)。<< ~ 100 [kB]

您的“计算”部分代码对从原始静态存储中(相当昂贵)获取的任何单个数据元素进行零重用,因此几乎所有的好处,GPU / SMX / SIMD 火炮已经根本不使用发明的,并且您尝试将此类代码加载到这样的异构(NUMA复杂)分布式计算中会获得负面的净收益(是的,每个GPU设备都相当“远”,“昂贵” (除非您的代码将利用它的 SMX 资源,直到几乎从 GPU 硅中冒出烟雾……)和“远程”异步操作的分布式计算节点,在您的全局计算策略中)系统。

GPU 代码的任何第一次分支都将在 SIMD 执行成本方面非常昂贵,因此您的大量if代码在语法上是公平的,但在性能方面几乎是游戏的杀手:

for i in range( 0,
                len( longitude_aq )
                ): #______________________________________ITERATOR #1 ( SEQ-of-I-s )
    currentAq =                        aq[i, :]           # .SET
    center    = Coordinates(  latitude_aq[i],             # .SET
                             longitude_aq[i]
                             ) #          |
    #                                     +-------------> # EASY2VECTORISE in [i]

    for j in range( 0,
                    len( longitude_meo )
                    ): #- - - - - - - - - - - - - - - - - ITERATOR #2 ( SEQ-of-J-s )
        currentMeo =                        meo[j, :]     # .SET
        grid_point = Coordinates(  latitude_meo[j],       # .SET
                                  longitude_meo[j]
                                  ) #           |
        #                                       +-------> # EASY2VECTORISE in [j]
        if is_in_circle( center,
                         RADIUS,
                         grid_point
                         ): # /\/\/\/\/\/\/\/\/\/\/\/\/\/ IF-ed SIMD-KILLER #1
            if (   currentAq[TIME_AQ]
               == currentMeo[TIME_MEO]
                  ): # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ IF-ed SIMD-KILLER #2
                humidity       += currentMeo[      HUMIDITY_MEO] # BEST PERF.
                pressure       += currentMeo[      PRESSURE_MEO] #   IF SMART
                temperature    += currentMeo[   TEMPERATURE_MEO] #   CURATED
                wind_speed     += currentMeo[    WIND_SPEED_MEO] #   AS NON
                wind_direction += currentMeo[WIND_DIRECTION_MEO] #   ATOMICS
                count          += 1.0

    if          count          != 0.0: # !!!!!!!!!!!!!!!!!! THIS NEVER HAPPENS
        # EXCEPT WHEN ZERO DATA-POINTS WERE AVAILABLE FOR THE i-TH ZONE,
        #        FILE DID NOT CONTAIN ANY SUCH,
        #        WHICH IS FAIR,
        #    BUT SUCH A BLOCK OUGHT NEVER HAVE STARTED ANY COMPUTING AT ALL
        #     IF ASPIRING FOR INDEED BEING LOADED
        #        ONTO AN HPC-GRADE COMPUTING INFRASTRUCTURE ( SPONSORED OR NOT )
        #
        final_tmp[i, HUMIDITY_FINAL]       = humidity       / count
        final_tmp[i, PRESSURE_FINAL]       = pressure       / count
        final_tmp[i, TEMPERATURE_FINAL]    = temperature    / count
        final_tmp[i, WIND_SPEED_FINAL]     = wind_speed     / count
        final_tmp[i, WIND_DIRECTION_FINAL] = wind_direction / count

[i,j]如果我们省略 all- s 域和if-ed 交叉路口上的迭代器,则计算的实际“有用”部分只进行非常浅的数学运算——这项工作包含一些 SLOC-s,其中主要将独立值相加(最好避免任何添加操作的冲突,因此可以非常便宜地彼此独立操作(最好使用提前预取的常量)在少于几个[ns] 是的,您的计算有效负载不需要更多而不仅仅是几个单位[ns]来执行。

问题在于数据流的智能工程(我喜欢称其为DATA-HYDRAULICS(如何使数据的进一步不可压缩流进入{ CPU | GPU | APU | *** }-processor 寄存器,以便获得它们的进程))

其余的都很容易。HPC 级 DATA-HYDRAULICS 的智能解决方案通常不是。

没有语言,没有框架会自动帮助您。有些可以从您的“手动”工作中释放解决方案工程的某些部分,有些不能,有些甚至会破坏可能的计算性能,因为它们内部设计决策中的“廉价”捷径和做出的妥协,没有同样的好处您的目标 -性能


最好的下一步?

A )尝试更好地了解您希望用于广泛(但不是密集(是的,每个只有几个 SLOC [i,j])的计算基础设施的限制,HPC 主管不希望看到这些基础设施流入他们运营的昂贵的 HPC 资源) .

B)如果在重新设计自上而下的DATA-HYDRAULICS解决方案的时间 + 人数 + 财务资源方面遇到问题,最好重新分解您的代码,以便至少进入矢量化,numpy/ numba(并不总是numba比一个已经智能的numpy矢量化代码,但定量测试将告诉每个事件的事实,而不是一般)

C)如果您的计算问题预计会更频繁地重新运行,请务必从数据存储的早期预处理(处理中最慢的部分)评估重新设计的管道,其中基于流的预处理- 主要静态值的处理是可能的,这可能会最大程度地影响生成的DATA-HYDRAULICS流(性能)与预先计算 + 智能对齐的值。正如上面所报告的那样,沿着车道的几个ADD-s 的块不会得到改善[ns],但是如果重新安排成一个智能流,利用所有可用的资源,慢流可以更快地跳跃几个数量级,但“只是“ [CONCURRENT]--ly 操作资源(任何试图安排 True-[PARALLEL]调度在这里纯粹是胡说八道,因为任务主要不是[PARALLEL]调度问题,而是数据点的纯[SERIAL](重新)处理流,其中智能但“公正”[CONCURRENT]的处理重新安排可能会有所帮助缩小由此产生的过程持续时间)。

奖励:
如果对进入N -CPU 操作的计算图可实现的性能增益进行更深入的推理感兴趣,请随时了解有关重新制定的阿姆达尔定律和相关问题的更多信息,如在此处发布的更多详细信息。

于 2019-10-23T20:28:14.180 回答