OpenBLAS高性能计算库使用指南

OpenBLAS高性能计算库使用指南

OpenBLAS OpenBLAS 项目地址: https://gitcode.com/gh_mirrors/ope/OpenBLAS

内存管理问题解析与解决方案

当使用OpenBLAS时,可能会遇到"Program is Terminated. Because you tried to allocate too many memory regions"错误。这是由于OpenBLAS内部管理着一个内存缓冲区池,其数量由MAX_CPU_NUMBER×2决定。这个错误表明程序超出了缓冲区数量限制。

解决方案有以下几种:

  1. 编译时增加NUM_THREADS参数值,例如:

    make NUM_THREADS=32
    或
    make NUM_THREADS=64
    
  2. 值得注意的是,即使构建单线程版本,如果多线程程序调用SGEMM等函数,仍可能触发此问题。在这种情况下,程序可能会直接崩溃或抛出段错误而不显示警告信息。

多线程环境下的最佳实践

在已有多线程的应用程序中使用OpenBLAS时,需要注意线程冲突问题。以下是几种配置方案:

  1. 环境变量设置:

    export OPENBLAS_NUM_THREADS=1
    
  2. 运行时动态设置:

    openblas_set_num_threads(1);
    
  3. 编译单线程版本:

    make USE_THREAD=0
    
  4. 对于使用OpenMP并行化的应用程序,建议使用以下参数编译OpenBLAS:

    make USE_OPENMP=1
    

运行时目标架构选择

当使用DYNAMIC_ARCH编译时,可以通过环境变量手动选择内核:

export OPENBLAS_CORETYPE=Haswell

在程序中,可以使用以下函数获取当前使用的目标架构:

char* openblas_get_corename();

线程亲和性控制

OpenBLAS默认不设置处理器亲和性。如需禁用线程亲和性,有以下两种方式:

  1. 运行时禁用:

    export OPENBLAS_MAIN_FREE=1
    
  2. 编译时禁用: 在Makefile.rule中设置:

    NO_AFFINITY=1
    

库链接指南

动态链接

gcc -o test test.c -I /path/to/OpenBLAS/include/ -L/path/to/OpenBLAS/lib -lopenblas

注意事项:

  • 多线程版本需添加-lpthread
  • 包含LAPACK函数需添加-lgfortran或其他Fortran库

静态链接

gcc -o test test.c /path/to/libopenblas.a

完整静态链接示例:

gcc -static -I/opt/OpenBLAS/include -L/opt/OpenBLAS/lib -o my_program my_program.c -lopenblas -lpthread

常见错误解决: 若未添加-lpthread,可能出现undefined reference to pthread_mutex_lock等错误。

编程实例详解

CBLAS接口调用示例

#include <cblas.h>
#include <stdio.h>

void main()
{
  double A[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0};
  double B[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0};
  double C[9] = {.5,.5,.5,.5,.5,.5,.5,.5,.5};
  
  cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans,
              3,3,2,1,A,3,B,3,2,C,3);

  for(int i=0; i<9; i++)
    printf("%lf ", C[i]);
  printf("\n");
}

编译命令:

gcc -o test_cblas test_cblas_dgemm.c -I /path/to/OpenBLAS/include/ \
-L/path/to/OpenBLAS/lib -lopenblas -lpthread -lgfortran

BLAS Fortran接口调用示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>

extern void dgemm_(char*, char*, int*, int*, int*, 
                  double*, double*, int*, 
                  double*, int*, double*, 
                  double*, int*);

int main(int argc, char* argv[])
{
  if(argc<4){
    printf("Usage: %s <m> <n> <k>\n", argv[0]);
    return 1;
  }

  int m = atoi(argv[1]);
  int n = atoi(argv[2]);
  int k = atoi(argv[3]);
  
  // 矩阵初始化与计算逻辑...
  
  struct timeval start, finish;
  gettimeofday(&start, NULL);
  
  dgemm_(&ta, &tb, &m, &n, &k, &alpha, 
         A, &m, B, &k, &beta, C, &m);
         
  gettimeofday(&finish, NULL);
  
  // 性能计算与输出...
  
  return 0;
}

编译与运行:

gcc -o time_dgemm time_dgemm.c /path/to/libopenblas.a -lpthread
./time_dgemm 1024 1024 1024

常见问题排查

  1. 编译器版本要求:

    • GCC 4.6及以上版本支持Sandy Bridge AVX内核
    • Clang 3.1及以上版本才能正确生成AVX二进制代码
  2. 硬件限制:

    • 默认支持最多256个CPU核心
    • 在Linux x86_64上,使用BIGNUMA=1编译可支持最多1024个CPU核心和128个NUMA节点
  3. 处理器亲和性:

    • 默认不设置处理器亲和性
    • 如需启用,需在Makefile.rule中注释掉NO_AFFINITY=1

性能优化建议

  1. 对于大型矩阵运算,适当调整NUM_THREADS参数可获得最佳性能
  2. 在多NUMA系统上,考虑使用BIGNUMA=1编译选项
  3. 对于特定CPU架构,使用TARGET参数针对性地优化

学习资源

  1. BLAS函数参考:

    • Intel MKL参考手册
    • netlib.org上的BLAS文档
  2. OpenBLAS扩展功能文档

通过本指南,开发者可以全面了解OpenBLAS的使用方法、常见问题解决方案以及性能优化技巧,为科学计算和高性能应用开发提供有力支持。

OpenBLAS OpenBLAS 项目地址: https://gitcode.com/gh_mirrors/ope/OpenBLAS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秦俐冶Kirby

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值