【问题标题】:Multiply large numbers using multithreading使用多线程将大数相乘
【发布时间】:2020-02-15 00:08:34
【问题描述】:

我需要使用多线程将大数相乘。要相乘的两个数字最多可以有 10000 位。我使用单线程编写了乘法代码。但是当我将多个线程分配给不同的数字时,我不确定如何相乘。

例如,如果这两个数字是:254678 和 378929,并且有 3 个线程,我将这两个数字中的每一个分配给一个线程(2,5-Thread 1),(4,6->Thread 2) ,(7,8-> Thread 3) 并且每个数字都应该乘以第二个数字的数字-> 378929。

当线程并行运行时,当多个线程同时更新变量时,我不知道如何管理进位变量。

输入:数组包含两个数字
index: i1 包含第一个数字的最后一位
index: i2 包含第二个数字的最后一位

enter code here
for (int i=i1-1; i>=1; i--){ 
    int carry = 0; 
    int n1 = input[i]; 
    t2 = 0;
    for(int j=i2-1; j>i1-1; j--){                                               
        int n2 = input[j]; 
        int sum = n1*n2 + output[t1+t2] + carry;
        carry = sum/10;
        output[t1+t2] = sum % 10; 
        t2++; 
    }
    if(carry > 0)                                                                   
        output[t1 + t2] += carry; 
    t1++; 
}
int main() { 
    pthread_t threads[MAX_THREAD];
    for (int i = 0; i < MAX_THREAD; i++) 
        pthread_create(&threads[i], NULL, &multiply, (void*)NULL); 

    for (int i = 0; i < MAX_THREAD; i++) 
        pthread_join(threads[i], NULL); 
}

【问题讨论】:

  • 也许你用错了方法。为什么不让每个线程为您感兴趣的任何数字计算一整行乘法,并保留部分和。当所有线程都完成后,将所有部分和相加。
  • 我确实想过这样做,但由于线程数可以是 100,输出数组大小可以是 10^8(10^4*10^4),所以二维数组大小将是 10 ^2 * 10^8=10^10.
  • 不,如果你有 100 个线程,那么你只有 100 个累加器/部分和。

标签: c multithreading operating-system


【解决方案1】:

当线程并行运行时,当多个线程同时更新变量时,我不知道如何管理进位变量。

不允许多个线程同时更新任何内容。

具体来说(假设每个数字都是“base 1

my_accumulator = table_of_per_thread_accumulators[thread_number];
for (int src1_digit_number = startDigit; src1_digit_number >= 0; src1_digit_number -= NUM_THREADS ) {
    for (int src2_digit_number = src2_digits-1; src2_digit_number >= 0; src2_digit_number-- ) {
        int dest_digit_number = src1_digit_number  + src2_digit_number;

        uint32_t n1 = input1[src1_digit_number];
        uint32_t n2 = input2[src2_digit_number];
        uint64_t r = (uint64_t)n1 * n2;
        while(r != 0) {
            uint64_t temp = my_accumulator[dest_digit_number] + (r & 0xFFFFFFFFUL);
            my_accumulator[dest_digit_number++] = temp;
            temp >>= 32;
            r = (r >> 32) + temp;
        }
    }
}

然后,当所有线程都完成后(在一些“pthread_join()”调用之后?)您将添加每个线程的单独my_accumulator 中的数字以获得实际结果。

注1:理论上你可以做一些“累加器的二进制合并”,这样一个奇数线程等待下一个低编号线程完成并将该线程的累加器添加到它自己的;然后满足“my_thread_number % 4 == 3”的线程等待编号为“my_thread_number - 2”的线程完成并将其累加器添加到自己的;那么......这可能太复杂和太麻烦了。

注意 2:替代方案(如果您使用由多个线程修改的单个 output[])是使用互斥锁以确保只有一个线程可以同时修改 output[](或多个互斥锁以确保只有一个线程一次可以修改一条output[]);这会严重破坏性能,使用单线程会更快。

注 3:另一种选择是以某种方式使用原子,或使用内联汇编(例如“lock add [output+rdi],eax;”),这样就不需要互斥体。这仍然很糟糕,因为 CPU 将争夺对同一高速缓存行的独占访问权(如果 CPU 花费大部分时间试图获得对高速缓存行的独占访问权,您会破坏性能)。

【讨论】:

  • 非常感谢。我知道我应该如何进行。
猜你喜欢
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多