2011-01-30 34 views
5

Việc thực hiện (simd) của tôi mất nhiều thời gian, mặc dù nó được chạy cho đầu vào cố định. Thời gian chạy thay đổi giữa khoảng 100 triệu chu kỳ đồng hồ đến 120 triệu chu kỳ đồng hồ. Chương trình gọi một hàm khoảng 600 lần, và phần đắt nhất của hàm là bộ nhớ được truy cập ~ 2000 lần. Do đó, sự tham gia của bộ nhớ tổng thể khá cao trong chương trình của tôi.Thời gian chạy biến của chương trình C

Biến thể trong thời gian chạy do các mẫu truy cập bộ nhớ/nội dung bộ nhớ ban đầu?

Tôi đã sử dụng valgrind để phân tích hồ sơ chương trình của mình. Nó cho thấy mỗi truy cập bộ nhớ mất khoảng 8 hướng dẫn. Điều này có bình thường không?

Sau đây là đoạn mã (hàm) được gọi là 600 lần. Mulprev [32] [20] là mảng được truy cập nhiều lần nhất.

j = 15; 
u3v = _mm_set_epi64x (0xF, 0xF); 
while (j + 1) 
{ 

    l = j << 2; 
    for (i = 0; i < 20; i++) 
    { 
     val1v = _mm_load_si128 ((__m128i *) &elm1v[i]);  
     uv = _mm_and_si128 (_mm_srli_epi64 (val1v, l), u3v); 
     u1 = _mm_extract_epi16 (uv, 0); 
     u2 = _mm_extract_epi16 (uv, 4) + 16; 

     for (ival = i, ival1 = i + 1, k = 0; k < 20; k += 2, ival += 2, ival1 += 2) 
     { 
      temp11v = _mm_load_si128 ((__m128i *) &mulprev[u1][k]); 
      temp12v = _mm_load_si128 ((__m128i *) &mulprev[u2][k]); 

      val1v = _mm_load_si128 ((__m128i *) &res[ival]); 
      val2v = _mm_load_si128 ((__m128i *) &res[ival1]); 

      bv = _mm_xor_si128 (val1v, _mm_unpacklo_epi64 (temp11v, temp12v)); 
      av = _mm_xor_si128 (val2v, _mm_unpackhi_epi64 (temp11v, temp12v)); 

      _mm_store_si128 ((__m128i *) &res[ival], bv);         
      _mm_store_si128 ((__m128i *) &res[ival1], av); 
     } 
    } 

    if (j == 0) 
     break; 
    val0v = _mm_setzero_si128(); 

    for (i = 0; i < 40; i++) 
    { 
     testv = _mm_load_si128 ((__m128i *) &res[i]); 
     val1v = _mm_srli_epi64 (testv, 60); 
     val2v = _mm_xor_si128 (val0v, _mm_slli_epi64 (testv, 4)); 
     _mm_store_si128 (&res[i], val2v); 
     val0v = val1v; 
    } 
    j--; 
}  

Tôi muốn giảm thời gian tính toán của chương trình. Bất kỳ đề xuất?

+0

Bạn cần đăng mã thực tế nếu bạn muốn trợ giúp tối ưu hóa nó –

+0

Vui lòng xem câu hỏi đã chỉnh sửa .. – anup

Trả lời

3

Bạn đang thực hiện hầu như không có tính toán giữa tải và cửa hàng, do đó thời gian thực hiện của bạn rất có thể sẽ bị chi phối bởi chi phí I/O đến/từ bộ nhớ cache/bộ nhớ. Thậm chí tệ hơn, tập dữ liệu của bạn dường như tương đối nhỏ. Có lẽ cách duy nhất bạn có thể tối ưu hóa hơn nữa là cải thiện mẫu truy cập bộ nhớ (thực hiện truy cập tuần tự nếu có thể và đảm bảo rằng các dòng bộ nhớ cache không bị lãng phí, vv) và/hoặc kết hợp các hoạt động này với mã khác hoạt động trên cùng một tập dữ liệu trước/sau thói quen này (để chi phí tải/cửa hàng phân bổ phần nào).

EDIT: lưu ý rằng tôi đã đưa ra câu trả lời rất giống nhau khi bạn hỏi nhiều câu hỏi tương tự cho phiên bản cũ hơn của quy trình này: How to make the following code faster - dường như bạn đã bỏ lỡ vấn đề về hiệu suất chính của bạn ở đây là truy cập bộ nhớ tính toán.

+1

Điều này. Rất nhiều điều này. –

1

Máy tính phức tạp. Có thể dễ dàng là quá trình nền can thiệp theo một cách nào đó. Thật khó để đề xuất cải tiến mà không có thông tin bổ sung. Nói chung, các tối ưu hóa tốt nhất là các mức cao nhất. Chọn thuật toán tốt hơn, giảm thiểu các hoạt động tốn kém. Nếu bạn không nghĩ rằng có nhiều chỗ để cải thiện ở đó, đừng mong đợi lợi ích quá cao. Bạn nói rằng truy cập bộ nhớ của bạn mất rất nhiều chu kỳ. Tôi có thể khuyên bạn nên sử dụng con trỏ bị hạn chế nếu có thể, nhưng thật khó để đưa ra lời khuyên chung về các vấn đề tối ưu hóa. Bạn phải tự mình thử những thứ đó.

+0

Tôi sẽ đề xuất điều tương tự (không đảm bảo quy trình nào sẽ chạy khi ở trong hệ điều hành đa nhiệm, nếu chúng có cùng ưu tiên), nhưng sau đó tôi đọc phần này: http://valgrind.org/docs/manual/cl-manual.html#cl-manual.cycles Rõ ràng, các chu kỳ trong valgrind không giống với chu kỳ xử lý (?) – esaj

+1

@esaj: Tôi có nghĩa là chu kỳ đồng hồ ... – anup

+1

@esaj liên kết đó mô tả chu kỳ đồ thị http://en.wikipedia.org/wiki/Cycle_(graph_theory) trong biểu đồ cuộc gọi của chương trình. –

0

8 chu kỳ truy cập bộ nhớ là khá lâu. Một quá trình khác có thể có tác động tiêu cực đến bộ đệm CPU khiến cho chương trình của bạn bị mất nhiều bộ nhớ cache hoặc nếu bộ nhớ của bạn được cấp phát động, bạn có thể thấy các hình phạt truy cập bộ nhớ không được ký hiệu.

Nó có thể là bất cứ điều gì.

+0

Bạn có thể cho tôi thời gian đọc bộ nhớ cache L1 điển hình với lần truy cập giả định không? Nếu dữ liệu nằm trong bộ nhớ cache, nó có đảm bảo rằng thời gian tìm nạp sẽ tương tự không phụ thuộc vào vị trí của nó trên bộ nhớ cache hay không. Bất kỳ tài liệu tham khảo? – anup

+0

8 chu kỳ là * KHÔNG * một thời gian dài để truy cập bộ nhớ.Trong trường hợp một bộ nhớ cache bỏ lỡ tất cả các cách để DRAM có thể mất 100 chu kỳ và nhiều hơn nữa trên một CPU hiện đại. –

+0

@anup, @Axel: Độ trễ cho lần truy cập L1 trên CPU hiện đại thường là ~ 4 chu kỳ (xem Hướng dẫn tối ưu hóa của Intel hoặc tài liệu dành riêng cho bộ vi xử lý để biết thêm chi tiết). Nó đáng chú ý là anup thực sự nói "[Valgrind] cho thấy mỗi truy cập bộ nhớ mất khoảng 8 hướng dẫn". Hướng dẫn không phải là chu kỳ; một CPU Intel hiện đại có khả năng có thể rút lui 4 hướng dẫn trên mỗi chu kỳ để "8 hướng dẫn" thực sự có nghĩa là chỉ một vài chu kỳ, phù hợp với lần truy cập L1. Tuy nhiên, tôi không quen thuộc với Valgrind, vì vậy tôi không biết nó thực sự đo lường như thế nào. –

Các vấn đề liên quan