arrays - 在 Fortran 中的特定索引处将数组添加到更长数组的巧妙方法?
问题描述
我有两个(1d)数组,一个长数组A
(大小 m)和一个短数组B
(大小 n)。我想通过在特定索引处添加短数组的每个元素来更新长数组。
示意性地,数组的结构是这样的,
A = [a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 ... am]
B = [ b1 b2 b3 b4 b5 b6 b7 b8 b9 ... bn ]
我想A
通过添加B
.
最直接的方法是有一些索引数组indarray
(与 相同的大小B
)告诉我们A
对应的索引B(i)
:
选项1
do i = 1, size(B)
A(indarray(i)) = A(indarray(i)) + B(i)
end do
但是,有一个组织可以解决这个问题,我觉得应该允许一些更好的性能:
以矢量化方式执行此操作应该没有障碍。即每个更新
i
都是独立的,可以按任何顺序进行。无需在数组中来回跳转
A
。机器应该知道只在数组中循环一次,只A
在必要时更新。应该不需要任何临时数组。
在 Fortran 中执行此操作的最佳方法是什么?
选项 2
一种方法可能是使用PACK
,UNPACK
和一个布尔掩码M
(与 相同的大小A
),其用途与 相同indarray
:
A = [a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 ... am]
B = [ b1 b2 b3 b4 b5 b6 b7 b8 b9 ... bn ]
M = [. T T T . T T . . T . T T T T . ]
(其中T
代表.true.
和.
是.false.
)。
代码就是
A = UNPACK(PACK(A, M) + B, M, A)
这非常简洁,可能满足(1)和(2)排序(似乎通过数组进行两个循环而不是一个)。但我担心机器会在这个过程中创建一些临时数组,这似乎是不必要的。
选项 3
使用where
with怎么样UNPACK
?
where (M)
A =A + UNPACK(B, M, 0.0d0)
end where
这似乎与选项 2 大致相同(两个循环,可能会创建临时数组)。它还必须M=.false.
用 's 填充 UNPACK 数组的元素,0
这似乎完全是浪费。
选项 4
在我的情况下.true.
,掩码的元素通常是连续的块(即连续几个真,然后是一堆假,然后是另一个真块,等等)。也许这可能会导致类似于选项 1 的结果。假设有K
这些.true.
块。我需要一个数组indstart
(大小K
)给出A
每个真实块开始的索引,以及一个具有真实块长度的索引blocksize
(大小K
)。
j = 1
do i = 1, size(indstart)
i0 = indstart(i)
i1 = i0 + blocksize(i) - 1
A(i0:i1) = A(i0:i1) + B(j:j+blocksize(i)-1)
j = j + blocksize(i)
end do
至少这只会循环一次。这段代码似乎更明确地说明了数组内没有来回跳转的事实。但我认为编译器无法解决这个问题(blocksize
例如可能有负值)。所以这个选项可能不会产生矢量化的结果。
--
关于这样做的好方法有什么想法吗?在我的情况下,数组indarray
、M
、indstart
和blocksize
将被创建一次,但添加操作必须针对不同的数组A
和B
(尽管这些数组将具有恒定大小)进行多次。该where
声明似乎可能是相关的。
解决方案
推荐阅读
- javascript - 如何转义 Javascript 模板字符串的属性?
- express - 如何用 jest 指定运行规范文件的顺序?例如:首先运行 spec.fille1.js 然后 spec.file2.js 等
- python - Pandas:如何在保持空值的同时删除越界时间戳?
- android - 活动结束
- android - Flutter Spotify API 身份验证
- spring - 如何在 JPA 和 JPQL 中使用 @Query 查询多个接受的值?
- r - 如何在 csv 中保存特殊字符,同时为 excel 保留它们?
- authentication - Infinispan 服务器 CLI 身份验证
- sharepoint - Microsoft Sharepoint 部署问题
- react-native - React Navigation:当从 redux react navigation V5.0 更新页面数据时更新屏幕标题