【问题标题】:Multithreading array processing and then writing to result array for C-Python extension多线程数组处理,然后写入结果数组以进行 C-Python 扩展
【发布时间】:2019-07-12 17:54:36
【问题描述】:

下面的代码是一个 C-Python 扩展。此代码采用连续原始字节的输入 缓冲区(对于我的应用程序,原始字节的“块”,其中 1 个块 = 128 个字节),然后将这些字节处理为 2 个字节的“样本”,将结果项目。返回的结构只是处理成python整数的缓冲区。

以下是两个主要功能:

unpack_block(items, items_offset, buffer, buffer_offset, samples_per_block, sample_bits);

然后循环遍历 items 中的每个样本,然后将每个样本转换为 Python Int。

PyList_SET_ITEM(result, index, PyInt_FromLong( items[index] ));

    unsigned int num_blocks_per_thread, num_samples_per_thread, num_bytes_per_thread;
    unsigned int thread_id, p;
    unsigned int n_threads, start_index_bytes, start_index_blocks, start_index_samples;

    items = malloc(num_samples*sizeof(unsigned long));
    assert(items);

    #pragma omp parallel\
    default(none)\
    private(num_blocks_per_thread, num_samples_per_thread, num_bytes_per_thread, d, j, thread_id, n_threads, start_index_bytes, start_index_blocks, start_index_samples)\
    shared(samples_per_block, num_blocks, buffer, bytes_per_block, sample_bits, result, num_samples, items)
      {

        n_threads = omp_get_num_threads();
        num_blocks_per_thread = num_blocks/n_threads;
        num_samples_per_thread = num_samples/n_threads; 
        num_bytes_per_thread = num_blocks_per_thread*samples_per_block*2/n_threads;

        thread_id = omp_get_thread_num();
        start_index_bytes = num_bytes_per_thread*thread_id;
        start_index_blocks = num_blocks_per_thread*thread_id;  
        start_index_samples = num_samples_per_thread*thread_id;

        for (d=0; d<num_blocks_per_thread; d++) {
          unpack_block(items, start_index_samples+d*samples_per_block, buffer, start_index_blocks + d*bytes_per_block, samples_per_block, sample_bits);
        }

      }

     result = PyList_New(num_samples);
     assert(result);

     //*THIS WOULD ALSO SEEM RIPE FOR MULTITHREADING*
     for (p=0; p<num_samples; p++) {
        PyList_SET_ITEM(result, p, PyInt_FromLong( items[p] ));
      }

    free(items);
    free(buffer);

  return result;
}

速度非常糟糕,远远低于我对多线程的期望。我可能会遇到错误共享问题,线程写入 items 数组的不同块,即使每个线程只处理同一数组的互斥块。

对我来说一个基本问题是:如何正确地多线程处理单个数组的每个元素,然后将每个元素的结果输出到第二个“结果”数组中。我用我的两个函数执行了两次。

任何想法、解决方案或优化方法都会很棒。谢谢!

【问题讨论】:

    标签: python c multithreading openmp


    【解决方案1】:

    您已经提到虚假分享。为了避免这种情况,您必须相应地分配内存(使用 posix_memalign 或其他对齐的分配函数)并选择块大小,以便一个块的数据大小是缓存行大小的精确倍数。

    通常,使用 $N$ 个线程测量执行时间并计算加速比。你能和我们分享一下加速曲线吗?

    关于“这对于多线程来说似乎已经成熟”的评论:通常,期望太高(只是作为避免失望的警告词)。考虑您使用的每个线程有多少线程/元素以及每个线程的工作负载(即每个项目需要多少计算)。也许工作负载太小以至于 OpenMP 开销占主导地位。此外,每个内存加载操作需要多少条指令?通常,每个内存负载的许多指令都是并行化的合理候选者。比率低表示程序受内存限制。

    说到内存访问,您是否在具有不同 NUMA 域的多套接字系统上?如果是,您必须处理亲和力问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多