Я читаю массив параллельно, используя openmp. Ниже приведен минимальный воспроизводимый пример:
#include <cstdint>
#include <cstdlib>
#include <immintrin.h>
#include <iostream>
#include <memory>
#include <omp.h>
int main(int argc, char* argv[]){
// align to cache line, which is 512 bits or 64 bytes
size_t actualSize = 2048;
uint8_t* array = static_cast<uint8_t *>(aligned_alloc(64, actualSize));
for(size_t i = 0; i < actualSize; i++){
// initialize values
array[i] = rand() % 256;
}
__m256i sum_v = _mm256_setzero_si256 ();
#pragma omp parallel for
for (size_t i = 0; i < actualSize; i+=32){
__m256i v1 = _mm256_load_si256((const __m256i *) array+i);
// i understand that there is a race condition here, but I'm just
// concerned with the memory leaks
sum_v = _mm256_add_epi8 (sum_v, v1);
}
// just to keep compiler from optimizing out sum_v
uint8_t result = _mm256_extract_epi8 (sum_v, 0);
std::cout << "result: " << result << std::endl;
free(array);
return 0;
}
Это попытка измерить пропускную способность памяти на моем компьютере, в конечном итоге я рассчитываю это для разных фактических размеров.
Я скомпилирую это с g++ -Wall -g -std=c++1y -march=native -mtune=native -fopenmp -O3 -g minimal-memleaks.cpp
,Когда я запускаю эту программу, используя valgrind ./a.out
, я получаю утечку памяти, часть которой копируется ниже
==7688== Thread 8:
==7688== Invalid read of size 32
==7688== at 0x108D30: _mm256_add_epi8 (avx2intrin.h:107)
==7688== by 0x108D30: main._omp_fn.0 (minimal-memleaks.cpp:25)
==7688== by 0x51DB95D: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==7688== by 0x5FA66DA: start_thread (pthread_create.c:463)
==7688== by 0x551588E: clone (clone.S:95)
==7688== Address 0x61e1980 is 29,280 bytes inside an unallocated block of size 4,077,760 in arena "client"
полный вывод доступен здесь: https://pastebin.com/qr0W9FGD
Я могуКажется, не понимаю, почему. Сначала я думал, что цикл проходит за 2048 байтов, которые я выделил, но моя математика говорит, что это не должно. Я прочитал в блоках 32, и добавление 32 к i в конечном итоге будет равно 2048, когда цикл должен остановиться. Я также подумал, что, возможно, основной поток закрывался до дочерних потоков, но мои исследования показывают, что основной поток не будет закрываться, пока не будут созданы потоки, созданные в цикле #pragma omp parallel for
. Это неправильно?
Спасибо за любую помощь, которую вы можете предоставить.