使用线程改进一个简单的函数

Improving a simple function using threading

我用下面的代码编写了一个简单的函数来计算一维数组的最小值:

uint32_t get_minimum(const uint32_t* matrix) {
    int min = 0;
    min = matrix[0];


    for (ssize_t i = 0; i < g_elements; i++){
      if (min > matrix[i]){
        min = matrix[i];
      }
    }

    return min;
}    

但是,我想提高这个函数的性能,并被建议使用线程,所以我将其修改为以下内容:

struct minargument{
  const uint32_t* matrix;
  ssize_t tid;
  long long results;
};

static void *minworker(void *arg){
  struct minargument *argument = (struct minargument *)arg;

  const ssize_t start = argument -> tid * CHUNK;
  const ssize_t end = argument -> tid == THREADS - 1 ? g_elements :     (argument -> tid + 1) * CHUNK;

  long long result = argument -> matrix[0];

  for(ssize_t i = start; i < end; i++){
    for(ssize_t x = 0; x < g_elements; x++){
      if(result > argument->matrix[i]){
        result = argument->matrix[i];
      }    
    }
  }

  argument -> results = result;

  return NULL;


}


uint32_t get_minimum(const uint32_t* matrix) {

    struct minargument *args = malloc(sizeof(struct minargument) * THREADS);

    long long min = 0;


    for(ssize_t i = 0; i < THREADS; i++){
      args[i] = (struct minargument){
        .matrix = matrix,
        .tid = i,
        .results = min,
      };
    }

    pthread_t thread_ids[THREADS];

    for(ssize_t i =0; i < THREADS; i++){
      if(pthread_create(thread_ids + i, NULL, minworker, args + i) != 0){
        perror("pthread_create failed");
        return 1;
      }
    }

    for (ssize_t i = 0; i < THREADS; i++){
      if(pthread_join(thread_ids[i], NULL) != 0){
        perror("pthread_join failed");
        return 1;
      }
    }
    for(ssize_t i =0; i < THREADS; i++){
      min = args[i].results;
    }


    free(args);


    return min;
}

然而这似乎比第一个功能慢。 我使用线程使第一个函数 运行 更快是否正确?如果是这样,我该如何修改第二个函数,使其比第一个函数更快?

由于创建它们、调度它们并等待它们全部完成的开销,拥有比 运行 它们可用的内核更多的线程总是比单个线程慢。

您提供的示例不太可能从编译器将为您执行的优化之外的任何优化中受益,因为它是一个简短的操作。如果你在多核系统上做一些更复杂的事情,比如乘以两个巨大的矩阵,运行在高速实时数据上使用相关算法,那么多线程可能是解决方案。

另一个问题更抽象地回答了您的问题:您真的需要对其进行优化吗?除非您确实知道 存在 性能问题,否则 您的 时间最好花在为程序添加更多功能上,而不是解决问题并不存在。

编辑 - 比较

我只是 运行(代表版本)16 位 ARM 微控制器上的 OP 代码 运行 40 MHz 指令时钟。使用 GCC 编译的代码没有优化。

找到 20,000 个 32 位整数中的最小值用了 25 毫秒多一点。

页面大小为 40 kByte(用于保存 20,000 个 4 字节值数组的一半),线程 运行在主频为 2.67 GHz 的双 Intel 5150 处理器的不同内核上运行,需要将近 50 ms只是为了做上下文切换和分页操作!

就实时而言,一个简单的单线程微控制器实现所需的时间是多线程桌面实现的一半。