AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-7462275

Stef1611's questions

Martin Hope
Stef1611
Asked: 2025-04-19 19:48:58 +0800 CST

Fortran 派生类型数组上的“%”是否会在内存中创建副本?

  • 7

我想知道“%”如何在派生类型的数组上起作用。

我编写了以下程序,其中“+”运算符已被重载:

module my_mod

  implicit none

  type :: my_type
    real :: r1 , r2
    integer :: i1, i2
  end type my_type
  
  interface operator(+)
    module procedure add_my_type_vec, add_my_type
  end interface
  
contains
  function add_my_type_vec(a,b) result(res)
    type(my_type), dimension(:),intent(in) :: a, b
    type(my_type), dimension(size(a)) :: res

      res%r1 = a%r1 + b%r1
      res%r2 = a%r2 + b%r2
      res%i1 = a%i1 + b%i1
      res%i2 = a%i2 + b%i2
      
  end function add_my_type_vec
  
  function add_my_type(a,b) result(res)
    type(my_type), intent(in) :: a, b
    type(my_type) :: res

      res%r1 = a%r1 + b%r1
      res%r2 = a%r2 + b%r2
      res%i1 = a%i1 + b%i1
      res%i2 = a%i2 + b%i2
      
  end function add_my_type
  
end module my_mod

program my_pgm
    use my_mod
    implicit none
    
    type(my_type),allocatable, dimension(:) :: my_vec1, my_vec2, my_vec3
    
    write(*,*) "Sum on type : ", my_type(1.0, 2.0, 1, 2) + my_type(1.0, 2.0, 1, 2)

    allocate(my_vec1(1000), my_vec2(1000), my_vec3(1000))
    my_vec1 = my_type(1.0, 2.0, 1, 2)
    my_vec2 = my_type(1.0, 2.0, 1, 2)
    my_vec3 = my_vec1 + my_vec2
    
    write(*,*) "Sum on vec of type : ", my_vec3(123)
    

end program my_pgm

在函数中add_my_type_vec,它是如何%工作的?例如,在指令中res%r1 = a%r1 + b%r1,是否创建(即内存复制)两个仅包含a%r1和 的实数数组b%r1,然后对这些数组进行求和,最后对 进行赋值res%r1?我想这应该更复杂一些。

fortran
  • 2 个回答
  • 96 Views
Martin Hope
Stef1611
Asked: 2025-04-09 00:03:15 +0800 CST

在Fortran中使用可分配变量作为参数进行过程重载

  • 6

我正在学习 Fortran 的面向对象编程。我好奇,当编译时参数的类型未知时,重载类型绑定过程有什么意义。

让我一步一步解释我的问题(这些程序只是为了提高我的 Fortran 技能的例子)

第一个程序:类型绑定过程的重载

module my_mod

  implicit none
  
  type :: my_type_t
    character(len=128) :: my_text
  contains
    procedure :: integer_print, real_print
    generic :: my_print => integer_print, real_print
  end type my_type_t
  
  contains
  
  subroutine integer_print(this, my_int)
    class(my_type_t), intent(in) :: this
    integer, intent(in) :: my_int
    write (*,"(a,a,i0)") trim(this%my_text),' integer ', my_int
  end subroutine integer_print
  
  subroutine real_print(this, my_real)
    class(my_type_t), intent(in) :: this
    real, intent(in) :: my_real
    write (*,"(a,a,f0.3)") trim(this%my_text),' real ', my_real
  end subroutine real_print

end module my_mod

program my_pgm

  use my_mod
  implicit none
  
  type(my_type_t) :: my_var
  my_var%my_text = "Hello"
  
  call my_var%my_print(10)
  call my_var%my_print(9.9)

end program my_pgm

它给出了预期的结果。使用integer_print或real_print,取决于参数的类型my_print(整数或实数)。

第二个程序(或者应该写成步骤):使用了一个抽象类型,并且有两个派生类型:my_int_t和my_real_t。它与第一个例子非常相似。但是,使用了两种类型:一个用于整数,另一个用于实数。

module my_mod

  implicit none
  
  type, abstract :: my_abstract_t
  end type  my_abstract_t
  
  type, extends(my_abstract_t) :: my_int_t
    integer :: an_integer
  end type my_int_t
  
  type, extends(my_abstract_t) :: my_real_t
    real :: a_real
  end type my_real_t
  
  type :: my_type_t
    character(len=128) :: my_text
  contains
    procedure :: integer_print, real_print
    generic :: my_print => integer_print, real_print
  end type my_type_t
  
  contains
  
  subroutine integer_print(this, my_int)
    class(my_type_t), intent(in) :: this
    type(my_int_t), intent(in) :: my_int
    write (*,"(a,a,i0)") trim(this%my_text),' integer ', my_int%an_integer
  end subroutine integer_print
  
  subroutine real_print(this, my_real)
    class(my_type_t), intent(in) :: this
    type(my_real_t), intent(in) :: my_real
    write (*,"(a,a,f0.3)") trim(this%my_text),' real ', my_real%a_real
  end subroutine real_print

end module my_mod

program my_pgm

  use my_mod
  implicit none
  
  type(my_type_t) :: my_var
  type(my_int_t) :: my_int
  type(my_real_t) :: my_real
  
  my_var%my_text = "Hello"
  
  my_int%an_integer = 10
  my_real%a_real = 9.9
  
  call my_var%my_print(my_int)
  call my_var%my_print(my_real)

end program my_pgm

my_int和的类型my_real在编译类型时是已知的,因此输出是正确的。并且my_var%my_print(...)无论变量类型是什么(my_int_t或my_real_t),都会使用相同的调用,就像第一个示例中那样。

但是,现在这是我的问题。

program my_pgm

  use my_mod
  implicit none
  
  type(my_type_t) :: my_var
  class(my_abstract_t), allocatable :: my_number
  
  allocate(my_int_t::my_number)
  ! or allocate(my_real_t::my_number)
  
  my_var%my_text = "Hello"

  select type (my_number)
  type is (my_int_t)
      my_number%an_integer = 10
  type is (my_real_t)
      my_number%a_real = 9.9
  end select
  
  select type (my_number)
  type is (my_int_t)
      call my_var%my_print(my_number)
  type is (my_real_t)
      call my_var%my_print(my_number)
  end select

end program my_pgm

的类型my_number在编译时是未知的。因此,我必须使用一段我认为非常多余的代码:

  select type (my_number)
  type is (my_int_t)
      call my_var%my_print(my_number)
  type is (my_real_t)
      call my_var%my_print(my_number)
  end select

我本来希望只写一行 : ,call my_var%my_print(...)就像第一和第二个例子一样。我是不是应该得出结论,在第三个例子中,过程重载并不重要,最好直接在块中使用integer_printand ?还是有什么我没理解的地方?real_printselect type

编辑1

按照 Francescalus 的注释,如果我理解正确的话,我的确无法避免select type阻塞。因此,我按照以下方式修改了程序。

module my_mod

  implicit none
  
  type, abstract :: my_abstract_t
  end type  my_abstract_t
  
  type, extends(my_abstract_t) :: my_int_t
    integer :: an_integer
  end type my_int_t
  
  type, extends(my_abstract_t) :: my_real_t
    real :: a_real
  end type my_real_t
  
  type :: my_type_t
    character(len=128) :: my_text
  contains
    procedure, private :: real_print, integer_print
    procedure, public :: my_print
  end type my_type_t
  
  contains
  
  subroutine integer_print(this, my_int)
    class(my_type_t), intent(in) :: this
    type(my_int_t), intent(in) :: my_int
    write (*,"(a,a,i0)") trim(this%my_text),' integer ', my_int%an_integer
  end subroutine integer_print
  
  subroutine real_print(this, my_real)
    class(my_type_t), intent(in) :: this
    type(my_real_t), intent(in) :: my_real
    write (*,"(a,a,f0.3)") trim(this%my_text),' real ', my_real%a_real
  end subroutine real_print
  
  subroutine my_print(this,my_number)
    class(my_type_t), intent(in) :: this
    class(my_abstract_t), intent(in) :: my_number
    
    select type (my_number)
    type is (my_int_t)
        call this%integer_print(my_number)
    type is (my_real_t)
        call this%real_print(my_number)
    end select
    
  end subroutine my_print
    

end module my_mod

program my_pgm

  use my_mod
  implicit none
  
  type(my_type_t) :: my_var
  class(my_abstract_t), allocatable :: my_number1, my_number2
  
  my_number1 = my_int_t(an_integer = 10)
  my_number2 = my_real_t(a_real = 9.9)
  
  my_var%my_text = "Hello"

  call my_var%my_print(my_number1)
  call my_var%my_print(my_number2)
  
end program my_pgm

任何评论都将受到欢迎。

oop
  • 1 个回答
  • 58 Views
Martin Hope
Stef1611
Asked: 2025-02-27 01:24:40 +0800 CST

如何在 Fortran 中对派生类型数组使用 openmp 归约?

  • 6

从 OpenMP 4.5 开始,可以使用指令减少数组。但是,当我尝试在派生类型的数组上使用它时,我遇到了一个问题,因为找不到此类型的 !$OMP DECLARE REDUCTION。我理解这个问题。经过多次尝试,我终于找到了一个似乎有效的程序。这是代码:

模块(module.f90):

module my_mod
    implicit none
    
    type :: my_type_t
        integer :: x
        integer :: y
    end type my_type_t
    
    interface operator(+)
    module procedure add_my_type_t_vec
    end interface
    
!$OMP DECLARE REDUCTION (+ : my_type_t : omp_out = omp_out + omp_in) INITIALIZER (omp_priv = omp_orig)
    
contains
    
    function add_my_type_t_vec(a,b) result(res)
        type(my_type_t), dimension(:),intent(in) :: a, b
        type(my_type_t), dimension(size(a)) :: res
        
        res(:)%x = a(:)%x + b(:)%x
        res(:)%y = a(:)%y + b(:)%y
    end function add_my_type_t_vec
    
end module my_mod

使用它的程序(pgm.f90):

program parallel
    use omp_lib
    use my_mod
    implicit none
    
    type(my_type_t), dimension(:), allocatable :: private_var, shared_var
    integer :: i
    
    allocate(private_var(5), shared_var(5))
    shared_var%x=0
    shared_var%y=0
    

!$OMP PARALLEL NUM_THREADS(4) PRIVATE(private_var,i) REDUCTION (+ : shared_var) 

    !$OMP DO
    
    do i=1,1000
        private_var%x = 1
        private_var%y = 2
        shared_var = shared_var + private_var
    end do
    
    !$OMP END DO

!$OMP END PARALLEL
    print *, "Total : ", shared_var

end program parallel

编译:gfortran -fopenmp module.f90 pgm.f90

为了找到此解决方案,我使用了以下答案https://stackoverflow.com/a/61148205/7462275。

它确实有效,但我不确定在某些情况下是否会出现未定义的行为。而且我不完全理解 DECLARE REDUCTION 和 INITIALIZER 指令的语法和机制。事实上,我复制/粘贴了上面提到的答案,但其中没有解释。感谢您的建议和解释。

arrays
  • 1 个回答
  • 55 Views
Martin Hope
Stef1611
Asked: 2024-11-05 20:55:05 +0800 CST

如何在 Matplotlib 中用颜色填充子图之间的空格?

  • 8

使用以下代码:

nb_vars=4

fig, axs = plt.subplots(4,4,figsize=(8,8), gridspec_kw = {'wspace':0.20, 'hspace':0.20}, dpi= 100)
for i_ax in axs:
    for ii_ax in i_ax:
        ii_ax.set_yticklabels([])
for i_ax in axs:
    for ii_ax in i_ax:
        ii_ax.set_xticklabels([])

子图之间的空间是白色的。如何给它们上色?用不同的颜色?例如,参见下图: 在此处输入图片描述

python
  • 1 个回答
  • 47 Views
Martin Hope
Stef1611
Asked: 2024-03-14 23:30:04 +0800 CST

如何在函数中初始化的复合文字中设置指向整数的指针?

  • 6

我尝试通过函数中的复合文字来初始化结构。在解决了我的部分问题之后(请参阅在函数内部使用复合文字来初始化 C 中的变量),我遇到了一个新问题,其中一个成员 ( ptr_mb) 必须是指向变量的指针。

这是代码:

typedef struct {
  int i_mb;
  int * ptr_mb;
} my_struct_t;

void init_struct(my_struct_t **my_struct, int * const ptr) {
  *my_struct=&(static my_struct_t) {.i_mb=3, .ptr_mb= ptr};
}

int main() {
  int a;
  my_struct_t *my_struct;
  
  // my_struct = &(my_struct_t) {.i_mb=3, .ptr_mb=&a}; It is OK

  // Try to initialize it in a function
  init_struct(&my_struct, &a);
  
}

在 中main(),它有效(参见程序中的注释行)

发出编译错误。在函数 中init_struct,ptr 不是常量(行*my_struct=&(static my_struct_t) {.i_mb=3, .ptr_mb= ptr};:)。

a是在 中声明的变量main()。因此,它的地址是恒定的。我试着用、、、……来表现出矫揉造作的感觉。(int const *)有时(int * const)这(int const * const)是无稽之谈,但只是尝试却没有任何效果。

是否可以在函数中按照其工作方式进行此类初始化main()?

(使用了 Rq.。static我知道这是一个 C23 标准,并且该标准尚未发布;有关详细信息,请参阅此答案:Use ofcompoundliteral inside a function to init a variable in C。)

c
  • 2 个回答
  • 66 Views
Martin Hope
Stef1611
Asked: 2024-03-14 21:41:10 +0800 CST

为什么可以通过指向常量 int 的指针间接更改整数的值?

  • 8

我读了很多老问题,很多关于const声明中关键字的答案,以深入理解声明的语法。

我玩过const,现在我对这个例子有点困惑:

int i;
i=1;
int const *ptr_i;
ptr_i=&i;
printf("%d\n",*ptr_i);
i=2;
printf("%d\n",*ptr_i);

如果是指向常量整数的int const *指针,为什么允许?不是常整数。ptr_i=&i;i

此外,如果 的值i从 1 更改为 2(显然,这是可能的,因为i不是常整数),第二个printf显示 2。我并不感到惊讶,因为 的值i已更改并且ptr_i是指向 的指针i。

我还检查了 ptr_i 的值没有改变(printf("%p ",ptr_i))。

我的误会在哪里?

c
  • 2 个回答
  • 57 Views
Martin Hope
Stef1611
Asked: 2023-08-19 21:52:20 +0800 CST

如何解释两个处理器之间巨大的执行速度差异?

  • 7

我写了一个fortran程序来模拟分子系统。我在一台处理器为Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz. 之后,为了启动大规模模拟,我使用了处理器为 的计算刀片AMD Opteron(tm) Processor 6176 @ 2.3 GHz。我很惊讶,因为执行时间增加了大约 3 倍。

所以,我决定学习如何使用perf、、asm...来优化程序。经过一番努力,我终于写出了这个短程序,我的因子仍然是 3 左右。

program simple_pgm

    integer :: i, res
    
    res = 0
    do i=1,1000000000
        res = res + i
    enddo
    write(*,*) res

end program simple_pgm

编译命令:gfortran -g -Wall -O2 simple.f90 -o simple

当我查看annotate MAIN__时perf report -n,汇编代码或多或少是相同的。

在 i7 处理器上:

     │    res = 0
     │    do i=1,1000000000
     │      mov  $0x1,%eax
     │      xchg %ax,%ax
     │    res = res + i
1095 │10:   add  %eax,%edx
     │    do i=1,1000000000
 1   │      add  $0x1,%eax
     │      cmp  $0x3b9aca01,%eax
     │    ↑ jne  10
     │    enddo

在 Opteron 上:

     │    res = 0                                                                                                                                  
     │    do i=1,1000000000                                                                                                                         
     │      mov    $0x1,%eax                                                                                                                        
     │    program simple_pgm                                                                                                                        
     │      sub    $0x220,%rsp                                                                                                                      
     │      nop                                                                                                                                     
     │    res = res + i
1972 │10:   add    %eax,%edx                                          
     │    do i=1,1000000000
1524 │      add    $0x1,%eax                                          
     │      cmp    $0x3b9aca01,%eax                                                                                                                 
     │    ↑ jne    10                                                                                                                               
     │    enddo

我想知道为什么在sample专栏中,对于指令add $0x1,%eax,对于 Opteron 处理器来说值非常大(1524)。它可以解释大约执行速度的因素吗?

感谢您的回答。由于我正在学习 ASM、处理器和计算机体系结构、性能……(对于初学者来说有很多东西),任何意见、建议将不胜感激。我知道我可能走错路了。

performance
  • 1 个回答
  • 56 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve